diff --git a/.editorconfig b/.editorconfig index 4ddeb73842d..75c4b4d016c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -46,10 +46,6 @@ indent_size = 2 [*.sh] indent_size = 2 -# YAML files -[*.{yml,yaml}] -indent_size = 2 - ############################### # Override Visual Studio # ############################### diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 4d41aec96ba..6585461ebde 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -35,22 +35,6 @@ _Please choose one of the keywords above to refer to the issue this PR solves fo _Optional. Remove if not applicable._ -## Documentation - -#### Requires documentation update - -- [ ] Yes -- [ ] No - -_If yes, link the PR to the docs update or the issue with the details labeled `docs`. Remove if not applicable._ - -#### Requires explanation in Release Notes - -- [ ] Yes -- [ ] No - -_If yes, fill in the details here. Remove if not applicable._ - ## Remarks _Optional. Remove if not applicable._ diff --git a/.github/workflows/build-nethermind-docker-images.yml b/.github/workflows/build-nethermind-docker-images.yml new file mode 100644 index 00000000000..dee902c580a --- /dev/null +++ b/.github/workflows/build-nethermind-docker-images.yml @@ -0,0 +1,55 @@ +name: '[BUILD] Docker images and publish' + +on: + workflow_dispatch: + inputs: + repo: + description: 'Docker Hub org and repo name' + required: false + default: 'nethermindeth/nethermind' + tag: + description: 'Image tag' + required: false + default: '' + dockerfile: + description: 'Dockerfile to use' + required: false + default: 'Dockerfile' + +jobs: + build-dockers: + if: github.repository_owner == 'NethermindEth' + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v3 + - name: Unshallow fetching + run: git fetch --unshallow + - name: Configure settings + id: settings + run: | + echo "BUILD_TIMESTAMP=$(date '+%s')" >> $GITHUB_OUTPUT + echo "COMMIT_HASH=$(git describe --always --exclude=* --abbrev=40)" >> $GITHUB_OUTPUT + echo "TAG_FROM_REPO=$(git describe --tags --always | cut -d- -f1)" >> $GITHUB_OUTPUT + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v2 + - name: Log in to Docker Hub + if: success() + run: | + echo "${{ secrets.DOCKER_ACCESS_TOKEN }}" | docker login --username "${{ secrets.DOCKER_USERNAME }}" --password-stdin + - name: Build and pushing image to Docker registry (major) / trigger DAppNode build + if: github.event.inputs.tag == steps.settings.outputs.TAG_FROM_REPO + run: | + docker buildx build --platform=linux/amd64,linux/arm64 -t "${{ github.event.inputs.repo }}:latest" -t "${{ github.event.inputs.repo }}:${{ github.event.inputs.tag }}" -f ${{ github.event.inputs.dockerfile }} --build-arg COMMIT_HASH=${{ steps.settings.outputs.COMMIT_HASH }} --build-arg BUILD_TIMESTAMP=${{ steps.settings.outputs.BUILD_TIMESTAMP}} . --push + curl -s -X POST -u "${{ secrets.REPOSITORY_DISPATCH_TOKEN }}" -H "Accept: application/vnd.github.everest-preview+json" -H "Content-Type: application/json" -d '{"event_type":"dappnode","client_payload":{"tag":"${{ github.event.inputs.tag }}"}}' https://api.github.com/repos/$GITHUB_REPOSITORY/dispatches + - name: Build and push image to Docker registry (patch) + if: github.event.inputs.tag != steps.settings.outputs.TAG_FROM_REPO + run: | + docker buildx build --platform=linux/amd64,linux/arm64 -t "${{ github.event.inputs.repo }}:${{ github.event.inputs.tag }}" -f ${{ github.event.inputs.dockerfile }} --build-arg COMMIT_HASH=${{ steps.settings.outputs.COMMIT_HASH }} --build-arg BUILD_TIMESTAMP=${{ steps.settings.outputs.BUILD_TIMESTAMP}} . --push + - name: Clear Docker cache + if: always() + run: | + rm -f $HOME/.docker/config.json diff --git a/.github/workflows/build-nethermind-packages.yml b/.github/workflows/build-nethermind-packages.yml index e1d9da93b43..bd1db5b0c83 100644 --- a/.github/workflows/build-nethermind-packages.yml +++ b/.github/workflows/build-nethermind-packages.yml @@ -46,14 +46,14 @@ jobs: scripts/deployment/build-runner.sh $GITHUB_SHA $build_timestamp - name: Build Nethermind.Cli run: nethermind/scripts/deployment/build-cli.sh $GITHUB_SHA ${{ steps.build-runner.outputs.build-timestamp }} - - name: Build Nethermind launcher + - name: Build Nethermind.Launcher run: nethermind/scripts/deployment/build-launcher.sh - - name: Build Nethermind launcher for Linux arm64 + - name: Build Nethermind.Launcher for Linux arm64 run: | cd nethermind docker buildx build --platform=linux/arm64 -t tmp-launcher -f Dockerfile.launcher . --load - docker run --platform=linux/arm64 -v $PWD:/opt/mount --rm tmp-launcher bash -c "cp /nethermind/nethermind-launcher /opt/mount/" - mv nethermind-launcher $GITHUB_WORKSPACE/$PUB_DIR/linux-arm64/nethermind-launcher + docker run --platform=linux/arm64 -v $PWD:/opt/mount --rm tmp-launcher bash -c "cp /nethermind/Nethermind.Launcher /opt/mount/" + mv Nethermind.Launcher $GITHUB_WORKSPACE/$PUB_DIR/linux-arm64/Nethermind.Launcher - name: Archive packages env: PACKAGE_PREFIX: nethermind-preview-${{ steps.build-runner.outputs.commit-hash }} diff --git a/.github/workflows/build-nethtest-hive-docker-images.yml b/.github/workflows/build-nethtest-hive-docker-images.yml new file mode 100644 index 00000000000..f8ff35f6e87 --- /dev/null +++ b/.github/workflows/build-nethtest-hive-docker-images.yml @@ -0,0 +1,38 @@ +name: '[BUILD] Nethtest/Hive images and publisg them to Docker Hub' + +on: + push: + branches: + - master + +jobs: + build-secondary-dockers: + if: github.repository_owner == 'NethermindEth' + runs-on: ubuntu-latest + steps: + - name: Checking out repository + uses: actions/checkout@v3 + - name: Unshallow fetching + run: git fetch --unshallow + - name: Settings + id: settings + run: | + echo "BUILD_TIMESTAMP=$(date '+%s')" >> $GITHUB_OUTPUT + echo "COMMIT_HASH=$(git describe --always --exclude=* --abbrev=40)" >> $GITHUB_OUTPUT + - name: Setting up QEMU + uses: docker/setup-qemu-action@v2 + - name: Setting up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v2 + - name: Logging to Docker Hub + if: success() + run: | + echo "${{ secrets.DOCKER_ACCESS_TOKEN }}" | docker login --username "${{ secrets.DOCKER_USERNAME }}" --password-stdin + - name: Building & Pushing image to docker registry + run: | + docker buildx build --platform=linux/amd64 -t nethermindeth/nethtest -f Dockerfile.stateRunner . --push + docker buildx build --platform=linux/amd64 -t nethermindeth/hive:latest -f Dockerfile --build-arg COMMIT_HASH=${{ steps.settings.outputs.COMMIT_HASH }} --build-arg BUILD_TIMESTAMP=${{ steps.settings.outputs.BUILD_TIMESTAMP}} . --push + - name: Clearing + if: always() + run: | + rm -f $HOME/.docker/config.json diff --git a/.github/workflows/build-solutions.yml b/.github/workflows/build-solutions.yml index b6c2e60e6c2..20ce78e73b8 100644 --- a/.github/workflows/build-solutions.yml +++ b/.github/workflows/build-solutions.yml @@ -14,8 +14,6 @@ env: BUILD_CONFIG: release DOTNET_VERSION: 7 DOTNET_INSTALL_DIR: '~/.dotnet' - DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION: "1" - TERM: xterm jobs: build: diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index 766c67725cd..09b5c2aae79 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -8,8 +8,6 @@ env: BUILD_CONFIG: release DOTNET_VERSION: 7 DOTNET_INSTALL_DIR: '~/.dotnet' - DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION: "1" - TERM: xterm jobs: spacing-check: diff --git a/.github/workflows/hive-tests.yml b/.github/workflows/hive-tests.yml index 836595f906d..9380770a2e7 100644 --- a/.github/workflows/hive-tests.yml +++ b/.github/workflows/hive-tests.yml @@ -3,7 +3,7 @@ name: Hive tests on: push: tags: ['*'] - branches: [master] + workflow_dispatch: inputs: test-suite: diff --git a/.github/workflows/nethermind-tests.yml b/.github/workflows/nethermind-tests.yml index 667686d7f35..d20fa3beed9 100644 --- a/.github/workflows/nethermind-tests.yml +++ b/.github/workflows/nethermind-tests.yml @@ -20,8 +20,6 @@ env: COLLECT_COVERAGE: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' || github.event.inputs.coverage }} DOTNET_VERSION: 7 RETENTION: 1 - DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION: "1" - TERM: xterm jobs: nethermind-tests: @@ -77,6 +75,8 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v3 + with: + submodules: true - name: Set up .NET uses: actions/setup-dotnet@v3 with: diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml deleted file mode 100644 index d3a65d65acd..00000000000 --- a/.github/workflows/publish-docker.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: Publish Docker image - -on: - push: - branches: [master] - paths: - - 'src/Nethermind/**' - - workflow_dispatch: - inputs: - tag: - description: Image tag - required: true - dockerfile: - description: Dockerfile - required: true - default: Dockerfile - build-config: - description: Build configuration - required: true - default: release - type: choice - options: - - release - - debug - -jobs: - publish-docker: - name: Publish to Docker Hub - runs-on: ubuntu-latest - steps: - - name: Check out repository - uses: actions/checkout@v3 - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - name: Log in to Docker Hub - if: success() - run: echo "${{ secrets.DOCKER_ACCESS_TOKEN }}" | docker login --username "${{ secrets.DOCKER_USERNAME }}" --password-stdin - - name: Build and push image to Docker Hub (staging) - run: | - build_timestamp=$(date '+%s') - docker buildx build --platform=linux/amd64,linux/arm64 \ - -f ${{ github.event.inputs.dockerfile || 'Dockerfile' }} \ - -t "nethermindeth/nethermind:${{ github.event.inputs.tag || 'master' }}" \ - --build-arg BUILD_CONFIG=${{ github.event.inputs.build-config || 'release' }} \ - --build-arg BUILD_TIMESTAMP=$build_timestamp \ - --build-arg COMMIT_HASH=$GITHUB_SHA . --push - - name: Clear Docker cache - if: always() - run: rm -f $HOME/.docker/config.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2e627679013..9e5a99546e9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -61,14 +61,14 @@ jobs: $SCRIPTS_PATH/build-runner.sh $GITHUB_SHA $build_timestamp - name: Build Nethermind.Cli run: $SCRIPTS_PATH/build-cli.sh $GITHUB_SHA ${{ steps.build-runner.outputs.build-timestamp }} - - name: Build Nethermind launcher + - name: Build Nethermind.Launcher run: $SCRIPTS_PATH/build-launcher.sh - - name: Build Nethermind launcher for Linux arm64 + - name: Build Nethermind.Launcher for Linux arm64 working-directory: nethermind run: | docker buildx build --platform=linux/arm64 -t tmp-launcher -f Dockerfile.launcher . --load - docker run --platform=linux/arm64 -v $PWD:/opt/mount --rm tmp-launcher bash -c "cp /nethermind/nethermind-launcher /opt/mount/" - mv nethermind-launcher $GITHUB_WORKSPACE/$PUB_DIR/linux-arm64/nethermind-launcher + docker run --platform=linux/arm64 -v $PWD:/opt/mount --rm tmp-launcher bash -c "cp /nethermind/Nethermind.Launcher /opt/mount/" + mv Nethermind.Launcher $GITHUB_WORKSPACE/$PUB_DIR/linux-arm64/Nethermind.Launcher - name: Archive packages id: archive env: diff --git a/.github/workflows/run-a-single-node-from-branch.yml b/.github/workflows/run-a-single-node-from-branch.yml index f627a245802..e29d04b58de 100644 --- a/.github/workflows/run-a-single-node-from-branch.yml +++ b/.github/workflows/run-a-single-node-from-branch.yml @@ -44,6 +44,14 @@ on: description: "If checked, node will be started in NonValidator mode (OldBodies and oldReceipts will not be synced)" default: true type: boolean + timeout: + description: "Timeout in hours before triggering the deletion of smoke test instances. Maximum time of node lifetime can be 72 hours." + default: "24" + required: true + volume: + description: "In case custom volume size needs to be applied, put value in GB here)" + required: false + default: "" additional_nethermind_flags: description: "Provide any additional flags to the Nethermind in space-separated format. Example: \"JsonRpc.Enabled=false Sync.SnapSync=false\"." default: "" @@ -52,9 +60,10 @@ on: description: "Provide any additional flags to the CL client in space-separated format. Example: \"clflag1=1 clflag2=2\"." default: "" required: false - additional_options: - description: "A Json property which allows to customize node even more" - default: '{"timeout":"24", "default_dockerfile":"Dockerfile", "default_dockerfile_build_type":"release", "ssh_keys":"", "allowed_ips":""}' + ssh_keys: + description: "SSH Keys to be installed in the smoke test nodes (separated by commas without space in-between commas) for example: key1,key2,key3" + default: "" + required: false jobs: create_docker_image: @@ -79,54 +88,35 @@ jobs: run: | BASE_TAG="${GITHUB_USERNAME:0:1}$(shuf -i 1000-9999 -n 1)" echo "BASE_TAG=$BASE_TAG" >> $GITHUB_ENV - echo "base_tag=$BASE_TAG" >> $GITHUB_OUTPUT + echo "::set-output name=base_tag::$BASE_TAG" - name: Creating a node with NodeName="DevNode-${{ github.actor }}-${{ env.BASE_TAG }}-${{ env.CLEAN_REF }}-${{ inputs.network }}-${{ inputs.cl_client }}" run: echo "NodeName='DevNode-${{ github.actor }}-${{ env.BASE_TAG }}-${{ env.CLEAN_REF }}-${{ inputs.network }}-${{ inputs.cl_client }}'" - - - name: Extract dockerfile from additional_options - id: extract_dockerfile - run: | - echo "dockerfile=$(echo '${{ inputs.additional_options }}' | jq -r .default_dockerfile)" >> $GITHUB_OUTPUT - echo "build-config=$(echo '${{ inputs.additional_options }}' | jq -r .default_dockerfile_build_type | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT - - - name: Set Repo and Org Variables - run: | - echo "ORG_NAME=${{ github.repository_owner }}" >> $GITHUB_ENV - echo "REPO_NAME=${{ github.event.repository.name }}" >> $GITHUB_ENV - - - name: Check if master branch and default additional_options - id: check_conditions + + - name: Set Repo Variable run: | - if - [[ "${{ github.ref }}" == "refs/heads/master" ]] && - [[ "${{ steps.extract_dockerfile.outputs.dockerfile }}" == "Dockerfile" ]] && - [[ "${{ steps.extract_dockerfile.outputs.build-config }}" == "release" ]]; then - echo "skip_docker_build=true" >> $GITHUB_OUTPUT - else - echo "skip_docker_build=false" >> $GITHUB_OUTPUT - fi - + echo "REPO=$(echo $GITHUB_REPOSITORY | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV + - name: Trigger Docker Build Action with Cleaned Ref - if: steps.check_conditions.outputs.skip_docker_build != 'true' uses: benc-uk/workflow-dispatch@v1 - env: - ADDITIONAL_OPTIONS: ${{ inputs.additional_options }} with: - workflow: publish-docker.yml + workflow: build-nethermind-docker-images.yml ref: "${{ github.ref }}" token: "${{ secrets.REPOSITORY_DISPATCH_TOKEN }}" inputs: '{ + "repo": "${{ env.REPO }}", "tag": "${{ env.CLEAN_REF }}", - "dockerfile": "${{ steps.extract_dockerfile.outputs.dockerfile }}", - "build-config": "${{ steps.extract_dockerfile.outputs.build-config }}" + "dockerfile": "Dockerfile" }' - + + - name: Set Repo and Org Variables + run: | + echo "ORG_NAME=$(echo $GITHUB_REPOSITORY | cut -d / -f 1)" >> $GITHUB_ENV + echo "REPO_NAME=$(echo $GITHUB_REPOSITORY | cut -d / -f 2)" >> $GITHUB_ENV - name: Wait for Docker Build Action to complete - if: steps.check_conditions.outputs.skip_docker_build != 'true' env: GITHUB_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_TOKEN }} - WORKFLOW_ID: 'publish-docker.yml' + WORKFLOW_ID: 'build-nethermind-docker-images.yml' MAX_WAIT_MINUTES: '5' INTERVAL: '5' TIMEOUT: '10' @@ -153,13 +143,9 @@ jobs: echo "CLEAN_REF=$CLEAN_REF" >> $GITHUB_ENV - - name: Extract Variables - id: extract_variables + - name: Use BASE_TAG run: | echo "BASE_TAG=${{ needs.create_docker_image.outputs.base_tag }}" >> $GITHUB_ENV - echo "timeout=$(echo ${{ inputs.additional_options }} | jq -r .timeout)" >> $GITHUB_OUTPUT - echo "ssh_keys=$(echo ${{ inputs.additional_options }} | jq -r .ssh_keys)" >> $GITHUB_OUTPUT - echo "allowed_ips=$(echo ${{ inputs.additional_options }} | jq -r .allowed_ips)" >> $GITHUB_OUTPUT - name: Trigger Node creation Repo Action uses: benc-uk/workflow-dispatch@v1 @@ -175,7 +161,7 @@ jobs: "nethermind_branch": "${{ env.CLEAN_REF }}", "network": "${{ inputs.network }}", "cl_client": "${{ inputs.cl_client }}", - "additional_options": "{\"cl_custom_image\":\"${{ inputs.cl_custom_image }}\", \"timeout\":\"${{ steps.extract_variables.outputs.timeout }}\", \"non_validator_mode\":${{ inputs.non_validator_mode }}, \"additional_nethermind_flags\":\"${{ inputs.additional_nethermind_flags }}\", \"additional_cl_flags\":\"${{ inputs.additional_cl_flags }}\", \"ssh_keys\":\"${{ steps.extract_variables.outputs.ssh_keys }}\", \"allowed_ips\":\"${{ steps.extract_variables.outputs.allowed_ips }}\"}" + "additional_options": "{\"cl_custom_image\":\"${{ inputs.cl_custom_image }}\", \"timeout\":\"${{ inputs.timeout }}\", \"non_validator_mode\":${{ inputs.non_validator_mode }}, \"volume_size\":\"${{ inputs.volume }}\", \"additional_nethermind_flags\":\"${{ inputs.additional_nethermind_flags }}\", \"additional_cl_flags\":\"${{ inputs.additional_cl_flags }}\", \"ssh_keys\":\"${{ inputs.ssh_keys }}\"}" }' - name: Wait for creation of node @@ -190,19 +176,5 @@ jobs: REF: 'main' run: | chmod +x scripts/wait-for-workflow-completed.sh - ./scripts/wait-for-workflow-completed.sh | tee script-output.txt - run_id=$(grep -oP 'Run ID: \K\d+' script-output.txt) - echo "Run ID extracted is: $run_id" - echo "RUN_ID=$run_id" >> $GITHUB_ENV + ./scripts/wait-for-workflow-completed.sh working-directory: ${{ github.workspace }} - - - name: Download machine specs artifact - run: | - ARTIFACT_ID=$(curl -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ secrets.REPOSITORY_DISPATCH_TOKEN }}" https://api.github.com/repos/NethermindEth/post-merge-smoke-tests/actions/runs/${{ env.RUN_ID }}/artifacts | jq '.artifacts[0].id') - curl -L -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ secrets.REPOSITORY_DISPATCH_TOKEN }}" -o artifact.zip https://api.github.com/repos/NethermindEth/post-merge-smoke-tests/actions/artifacts/$ARTIFACT_ID/zip - unzip artifact.zip -d ./downloaded-artifacts/ - - - name: Display machine specs content - run: | - FILE=$(ls downloaded-artifacts/machine-details | head -n 1) - cat "downloaded-artifacts/machine-details/$FILE" diff --git a/.github/workflows/sync-testnets.yml b/.github/workflows/sync-testnets.yml index f4d1d12dfd6..2eae82def23 100644 --- a/.github/workflows/sync-testnets.yml +++ b/.github/workflows/sync-testnets.yml @@ -2,38 +2,23 @@ name: Sync Testnets on: push: - branches: [master] + branches: ["master"] workflow_dispatch: -env: - DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION: "1" - TERM: xterm - jobs: - testnet-sync: - strategy: - matrix: - include: - - network: "chiado" - checkpoint-sync-url: "http://139.144.26.89:4000/" - cl-client: "lighthouse" - el-client: "nethermind:current_branch_image" - - network: "sepolia" - checkpoint-sync-url: "https://beaconstate-sepolia.chainsafe.io" - cl-client: "lighthouse" - el-client: "nethermind:current_branch_image" - name: "Run sync of ${{ matrix.network }} testnet" + chiado: + name: "Run sync of chiado testnet" runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v3 - + - name: Configure settings id: settings run: | echo "BUILD_TIMESTAMP=$(date '+%s')" >> $GITHUB_OUTPUT echo "COMMIT_HASH=$(git describe --always --exclude=* --abbrev=40)" >> $GITHUB_OUTPUT - + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 @@ -58,51 +43,51 @@ jobs: echo 'Generating sedge docker...' ./build/sedge deps install ./build/sedge generate --logging none -p $GITHUB_WORKSPACE/sedge \ - full-node --map-all --no-mev-boost --no-validator --network ${{ matrix.network }} \ - -c ${{ matrix.cl-client }} -e ${{ matrix.el-client }} \ + full-node --map-all --no-mev-boost --no-validator --network chiado \ + -c lighthouse:sigp/lighthouse:latest -e nethermind:current_branch_image \ --el-extra-flag Sync.NonValidatorNode=true --el-extra-flag Sync.DownloadBodiesInFastSync=false \ --el-extra-flag Sync.DownloadReceiptsInFastSync=false \ --el-extra-flag JsonRpc.EnabledModules=[Eth,Subscribe,Trace,TxPool,Web3,Personal,Proof,Net,Parity,Health,Rpc,Debug] \ - --checkpoint-sync-url=${{ matrix.checkpoint-sync-url }} + --cl-extra-flag checkpoint-sync-url=http://139.144.26.89:4000/ echo 'Running sedge...' docker compose up -d - - name: Wait for ${{ matrix.network }} to sync + - name: Wait for Chiado to sync id: wait timeout-minutes: 90 run: | set +e - + declare -A bad_logs bad_logs["Invalid"]=1 bad_logs["Exception"]=1 bad_logs["Corrupted"]=1 - + declare -A good_logs - good_logs["Synced chain Head"]=0 - good_logs["Processed"]=0 - + good_logs["Valid. Result of a new payload:"]=0 + good_logs["FCU - block"]=0 + declare -A required_count - required_count["Synced chain Head"]=20 - required_count["Processed"]=20 - + required_count["Valid. Result of a new payload:"]=20 + required_count["FCU - block"]=20 + echo "Starting Docker logs monitoring..." docker logs -f sedge-execution-client | while read -r line; do echo "$line" - + for bad_log in "${!bad_logs[@]}"; do if [[ "$line" == *"$bad_log"* ]]; then echo "Error: $bad_log found in Docker logs." exit 1 fi done - + for good_log in "${!good_logs[@]}"; do if [[ "$line" == *"$good_log"* ]]; then ((good_logs["$good_log"]++)) fi done - + # Check if all good logs have reached the required count all_reached_required_count=true for good_log in "${!good_logs[@]}"; do @@ -111,11 +96,110 @@ jobs: break fi done - + if $all_reached_required_count; then echo "All required logs found." break fi done + + echo "Node is synced." + + sepolia: + name: "Run sync of sepolia testnet" + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Configure settings + id: settings + run: | + echo "BUILD_TIMESTAMP=$(date '+%s')" >> $GITHUB_OUTPUT + echo "COMMIT_HASH=$(git describe --always --exclude=* --abbrev=40)" >> $GITHUB_OUTPUT + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Build docker image + run: docker buildx build --platform=linux/amd64 -t current_branch_image -f Dockerfile --build-arg COMMIT_HASH=${{ steps.settings.outputs.COMMIT_HASH }} --build-arg BUILD_TIMESTAMP=${{ steps.settings.outputs.BUILD_TIMESTAMP}} --load . + - name: Setup Go environment + uses: actions/setup-go@v4.0.0 + + - name: Install Sedge environment + run: | + echo "Downloading sedge sources..." + git clone https://github.com/NethermindEth/sedge.git sedge --branch main --single-branch + echo "Sources downloaded." + cd sedge + echo "Building sedge..." + make compile + + - name: Run Sedge + working-directory: sedge + run: | + echo 'Generating sedge docker...' + ./build/sedge deps install + ./build/sedge generate --logging none -p $GITHUB_WORKSPACE/sedge \ + full-node --map-all --no-mev-boost --no-validator --network sepolia \ + -c lighthouse:sigp/lighthouse:latest -e nethermind:current_branch_image \ + --el-extra-flag Sync.NonValidatorNode=true --el-extra-flag Sync.DownloadBodiesInFastSync=false \ + --el-extra-flag Sync.DownloadReceiptsInFastSync=false \ + --el-extra-flag JsonRpc.EnabledModules=[Eth,Subscribe,Trace,TxPool,Web3,Personal,Proof,Net,Parity,Health,Rpc,Debug] \ + --cl-extra-flag checkpoint-sync-url=https://beaconstate-sepolia.chainsafe.io + echo 'Running sedge...' + docker compose up -d + + - name: Wait for Sepolia to sync + id: wait + timeout-minutes: 90 + run: | + set +e + + declare -A bad_logs + bad_logs["Invalid"]=1 + bad_logs["Exception"]=1 + bad_logs["Corrupted"]=1 + + declare -A good_logs + good_logs["Valid. Result of a new payload:"]=0 + good_logs["FCU - block"]=0 + + declare -A required_count + required_count["Valid. Result of a new payload:"]=20 + required_count["FCU - block"]=20 + + echo "Starting Docker logs monitoring..." + docker logs -f sedge-execution-client | while read -r line; do + echo "$line" + + for bad_log in "${!bad_logs[@]}"; do + if [[ "$line" == *"$bad_log"* ]]; then + echo "Error: $bad_log found in Docker logs." + exit 1 + fi + done + + for good_log in "${!good_logs[@]}"; do + if [[ "$line" == *"$good_log"* ]]; then + ((good_logs["$good_log"]++)) + fi + done + + # Check if all good logs have reached the required count + all_reached_required_count=true + for good_log in "${!good_logs[@]}"; do + if [[ ${good_logs[$good_log]} -lt ${required_count[$good_log]} ]]; then + all_reached_required_count=false + break + fi + done + + if $all_reached_required_count; then + echo "All required logs found." + break + fi + done + echo "Node is synced." diff --git a/.github/workflows/update-config-files.yml b/.github/workflows/update-config-files.yml index 17bc5855194..11df08d99d2 100644 --- a/.github/workflows/update-config-files.yml +++ b/.github/workflows/update-config-files.yml @@ -36,6 +36,7 @@ jobs: - mainnet.cfg - goerli.cfg - rinkeby.cfg + - ropsten.cfg - sepolia.cfg Properties refreshed: diff --git a/Dockerfile b/Dockerfile index d59cee390c6..c24abab54c3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,22 +7,18 @@ ARG TARGETPLATFORM ARG TARGETOS ARG TARGETARCH ARG BUILDPLATFORM -ARG BUILD_CONFIG=release ARG BUILD_TIMESTAMP ARG COMMIT_HASH COPY . . RUN if [ "$TARGETARCH" = "amd64" ]; \ - then dotnet publish src/Nethermind/Nethermind.Runner -c $BUILD_CONFIG -r $TARGETOS-x64 -o out --sc false \ + then dotnet publish src/Nethermind/Nethermind.Runner -c release -r $TARGETOS-x64 -o out \ -p:BuildTimestamp=$BUILD_TIMESTAMP -p:Commit=$COMMIT_HASH -p:Deterministic=true ; \ - else dotnet publish src/Nethermind/Nethermind.Runner -c $BUILD_CONFIG -r $TARGETOS-$TARGETARCH -o out --sc false \ + else dotnet publish src/Nethermind/Nethermind.Runner -c release -r $TARGETOS-$TARGETARCH -o out \ -p:BuildTimestamp=$BUILD_TIMESTAMP -p:Commit=$COMMIT_HASH -p:Deterministic=true ; \ fi -# A temporary symlink to support the old executable name -RUN ln -s -r out/nethermind out/Nethermind.Runner - FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/aspnet:7.0-jammy ARG TARGETPLATFORM @@ -30,7 +26,7 @@ ARG TARGETOS ARG TARGETARCH ARG BUILDPLATFORM -RUN apt-get update && apt-get -y install libsnappy-dev +RUN apt-get update && apt-get -y install libsnappy-dev libc6-dev libc6 WORKDIR /nethermind @@ -44,4 +40,4 @@ VOLUME /nethermind/nethermind_db VOLUME /nethermind/logs VOLUME /nethermind/keystore -ENTRYPOINT ["./nethermind"] +ENTRYPOINT ["./Nethermind.Runner"] diff --git a/Dockerfile.dev b/Dockerfile.dev index f5cd99004ab..f5ca72a4a36 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -7,7 +7,6 @@ ARG TARGETPLATFORM ARG TARGETOS ARG TARGETARCH ARG BUILDPLATFORM -ARG BUILD_CONFIG=release ARG BUILD_TIMESTAMP ARG COMMIT_HASH @@ -18,26 +17,23 @@ RUN if [ "$TARGETARCH" = "amd64" ]; \ dotnet tool install JetBrains.dotTrace.GlobalTools --version 2022.3.3 --tool-path /tmp/ && \ dotnet add src/Nethermind/Nethermind.Runner package JetBrains.dotMemory.Console.$TARGETOS-x64 \ --version 2022.3.3 --package-directory /tmp/ && \ - dotnet publish src/Nethermind/Nethermind.Runner -c $BUILD_CONFIG -r $TARGETOS-x64 -o out --sc false \ + dotnet publish src/Nethermind/Nethermind.Runner -c release -r $TARGETOS-x64 -o out \ -p:BuildTimestamp=$BUILD_TIMESTAMP -p:Commit=$COMMIT_HASH ; \ else \ dotnet tool install JetBrains.dotTrace.GlobalTools --version 2022.3.3 --tool-path /tmp/ && \ dotnet add src/Nethermind/Nethermind.Runner package JetBrains.dotMemory.Console.$TARGETOS-$TARGETARCH \ --version 2022.3.3 --package-directory /tmp/ && \ - dotnet publish src/Nethermind/Nethermind.Runner -c $BUILD_CONFIG -r $TARGETOS-$TARGETARCH -o out --sc false \ + dotnet publish src/Nethermind/Nethermind.Runner -c release -r $TARGETOS-$TARGETARCH -o out \ -p:BuildTimestamp=$BUILD_TIMESTAMP -p:Commit=$COMMIT_HASH ; \ fi -# A temporary symlink to support the old executable name -RUN ln -s -r out/nethermind out/Nethermind.Runner - RUN dotnet tool install --tool-path /dotnetcore-tools dotnet-trace && \ dotnet tool install --tool-path /dotnetcore-tools dotnet-dump && \ dotnet tool install --tool-path /dotnetcore-tools dotnet-gcdump FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/aspnet:7.0 -RUN apt-get update && apt-get -y install libsnappy-dev procps && \ +RUN apt-get update && apt-get -y install libsnappy-dev libc6-dev libc6 procps && \ rm -rf /var/lib/apt/lists/* WORKDIR /nethermind @@ -58,4 +54,4 @@ VOLUME /nethermind/nethermind_db VOLUME /nethermind/logs VOLUME /nethermind/keystore -ENTRYPOINT ["./nethermind"] +ENTRYPOINT ["./Nethermind.Runner"] diff --git a/Dockerfile.launcher b/Dockerfile.launcher index 28e45133000..61f27af5986 100644 --- a/Dockerfile.launcher +++ b/Dockerfile.launcher @@ -9,9 +9,9 @@ RUN npm i pkg @vercel/ncc -g && \ git clone https://github.com/NethermindEth/nethermind.launcher.git && \ cd nethermind.launcher && \ npm install && \ - pkg index.js -t latest-linux-arm64 -o nethermind-launcher + pkg index.js -t latest-linux-arm64 -o Nethermind.Launcher FROM arm64v8/node AS launcher WORKDIR /nethermind -COPY --from=build /source/nethermind.launcher/nethermind-launcher . +COPY --from=build /source/nethermind.launcher/Nethermind.Launcher . diff --git a/README.md b/README.md index 03068c709ec..545caf5ee26 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@

- - - Nethermind + + + Nethermind

@@ -22,7 +22,7 @@ Nethermind documentation is available at [docs.nethermind.io](https://docs.nethe ### Supported networks -**`Mainnet`** **`Goerli`** **`Sepolia`** **`Holesky`** **`Gnosis (xDai)`** **`Chiado`** **`Energy Web`** **`Volta`** +**`Mainnet`** **`Goerli`** **`Sepolia`** **`Gnosis (xDai)`** **`Energy Web`** **`Volta`** ## Download and run @@ -65,8 +65,8 @@ winget install Microsoft.VCRedist.2015+.x64 #### Install using Windows Package Manager 1. `winget install nethermind` -2. To run directly: `nethermind.exe -c mainnet` \ - or with the assistant: `nethermind-launcher.exe` +2. To run directly: `nethermind.runner.exe -c mainnet` \ + or with the assistant: `nethermind.launcher.exe` ### On macOS @@ -106,7 +106,7 @@ Install [.NET SDK](https://dotnet.microsoft.com/en-us/download) ### Clone the repository ```sh -git clone --recursive https://github.com/nethermindeth/nethermind.git +git clone https://github.com/nethermindeth/nethermind --recursive ``` ### Build and run diff --git a/scripts/deployment/archive-packages.sh b/scripts/deployment/archive-packages.sh index 77d91775abe..2321847e8b7 100755 --- a/scripts/deployment/archive-packages.sh +++ b/scripts/deployment/archive-packages.sh @@ -10,11 +10,11 @@ cd $GITHUB_WORKSPACE mkdir $PACKAGE_DIR cd $PUB_DIR -cd linux-x64 && zip -r -y $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-linux-x64.zip . && cd .. -cd linux-arm64 && zip -r -y $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-linux-arm64.zip . && cd .. +cd linux-x64 && zip -r $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-linux-x64.zip . && cd .. +cd linux-arm64 && zip -r $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-linux-arm64.zip . && cd .. cd win-x64 && zip -r $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-windows-x64.zip . && cd .. -cd osx-x64 && zip -r -y $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-macos-x64.zip . && cd .. -cd osx-arm64 && zip -r -y $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-macos-arm64.zip . && cd .. +cd osx-x64 && zip -r $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-macos-x64.zip . && cd .. +cd osx-arm64 && zip -r $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-macos-arm64.zip . && cd .. cd ref && zip -r $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-ref-assemblies.zip . && cd .. echo "Archiving completed" diff --git a/scripts/deployment/build-launcher.sh b/scripts/deployment/build-launcher.sh index 72b4342fa3b..54ce9ffa885 100755 --- a/scripts/deployment/build-launcher.sh +++ b/scripts/deployment/build-launcher.sh @@ -4,7 +4,7 @@ set -e -app_name=nethermind-launcher +app_name=Nethermind.Launcher output_path=$GITHUB_WORKSPACE/$PUB_DIR echo "Building Nethermind Launcher" diff --git a/scripts/deployment/build-runner.sh b/scripts/deployment/build-runner.sh index d20d7a485ce..7e9016b8459 100755 --- a/scripts/deployment/build-runner.sh +++ b/scripts/deployment/build-runner.sh @@ -24,10 +24,6 @@ do cp -r configs $output_path/$rid mkdir $output_path/$rid/keystore - - # A temporary symlink for Linux and macOS to support existing scripts if any - # To be removed after a few months - [[ $rid != win* ]] && ln -s -r $output_path/$rid/nethermind $output_path/$rid/Nethermind.Runner done cd .. diff --git a/scripts/deployment/debian/control b/scripts/deployment/debian/control index 715bcab204e..a5fd41dd8f9 100644 --- a/scripts/deployment/debian/control +++ b/scripts/deployment/debian/control @@ -7,7 +7,7 @@ Standards-Version: 4.5.0 Homepage: https://nethermind.io Package: nethermind -Architecture: amd64 arm64 +Architecture: amd64 Multi-Arch: foreign Depends: libsnappy-dev, libc6-dev, libc6, unzip, jq, curl, wget Description: An Ethereum client built on .NET diff --git a/scripts/deployment/debian/postinst b/scripts/deployment/debian/postinst index 2a279274886..303c1b7d234 100644 --- a/scripts/deployment/debian/postinst +++ b/scripts/deployment/debian/postinst @@ -1,14 +1,12 @@ #!/bin/bash arch=$(uname -m) -json=$(curl -sSL https://api.github.com/repos/NethermindEth/nethermind/releases/latest) -tag_name=$(echo $json | jq -r '.tag_name') if [[ $arch == x86_64* ]]; then - echo $json | jq -r '.assets[].browser_download_url | select(contains("linux-x64"))' | xargs -I % curl -sSL % -o nethermind.zip + curl -s https://api.github.com/repos/NethermindEth/nethermind/releases/latest | jq -r ".assets[] | select(.name) | .browser_download_url" | grep linux-x64 | xargs wget -O nethermind.zip -q ln -s /usr/lib/x86_64-linux-gnu/libdl.so.2 /usr/lib/x86_64-linux-gnu/libdl.so > /dev/null 2>&1 -elif [[ $arch == arm* ]] || [[ $arch = aarch64 ]]; then - echo $json | jq -r '.assets[].browser_download_url | select(contains("linux-arm64"))' | xargs -I % curl -sSL % -o nethermind.zip +elif [[ $arch == arm* ]] || [[ $arch = aarch64 ]]; then + curl -s https://api.github.com/repos/NethermindEth/nethermind/releases/latest | jq -r ".assets[] | select(.name) | .browser_download_url" | grep linux-arm64 | xargs wget -O nethermind.zip -q ln -s /usr/lib/aarch64-linux-gnu/libdl.so.2 /usr/lib/aarch64-linux-gnu/libdl.so > /dev/null 2>&1 apt update > /dev/null 2>&1 && apt install libgflags-dev -y > /dev/null 2>&1 fi @@ -19,5 +17,5 @@ mkdir -p /usr/share/nethermind cp -r nethermind/* /usr/share/nethermind rm -rf nethermind -curl -sSL https://raw.githubusercontent.com/NethermindEth/nethermind/release/$tag_name/scripts/execution.sh -o /usr/bin/nethermind +wget https://raw.githubusercontent.com/NethermindEth/nethermind/master/scripts/execution.sh -O /usr/bin/nethermind chmod +x /usr/bin/nethermind diff --git a/scripts/deployment/publish-github.sh b/scripts/deployment/publish-github.sh index 2c6eb72fa00..cc97dedddd4 100755 --- a/scripts/deployment/publish-github.sh +++ b/scripts/deployment/publish-github.sh @@ -5,6 +5,7 @@ set -e echo "Publishing packages to GitHub" +echo "Drafting release $GIT_TAG" release_id=$(curl https://api.github.com/repos/$GITHUB_REPOSITORY/releases \ -X GET \ @@ -13,8 +14,6 @@ release_id=$(curl https://api.github.com/repos/$GITHUB_REPOSITORY/releases \ if [ "$release_id" == "" ] then - echo "Drafting release $GIT_TAG" - body=$(printf \ '{"tag_name": "%s", "target_commitish": "%s", "name": "v%s", "body": "## Release notes\\n\\n", "draft": true, "prerelease": %s}' \ $GIT_TAG $GITHUB_SHA $GIT_TAG $PRERELEASE) @@ -26,13 +25,9 @@ then -H "Authorization: Bearer $GITHUB_TOKEN" \ -d "$body" | jq -r '.id') else - echo "Publishing release $GIT_TAG" - - make_latest=$([ $PRERELEASE = 'true' ] && echo "false" || echo "true") - body=$(printf \ - '{"target_commitish": "%s", "name": "v%s", "draft": false, "make_latest": "%s", "prerelease": %s}' \ - $GITHUB_SHA $GIT_TAG $make_latest $PRERELEASE) + '{"target_commitish": "%s", "name": "v%s", "draft": false, "prerelease": %s}' \ + $GITHUB_SHA $GIT_TAG $PRERELEASE) curl https://api.github.com/repos/$GITHUB_REPOSITORY/releases/$release_id \ -X PATCH \ diff --git a/scripts/execution.sh b/scripts/execution.sh index ebb8c54f2fe..20e333b64f1 100644 --- a/scripts/execution.sh +++ b/scripts/execution.sh @@ -6,10 +6,10 @@ sudo chown -R $(whoami) /usr/share/nethermind opts=$@ if [ ${#opts} -gt 0 ] then - echo 'Executing Nethermind' - sudo /usr/share/nethermind/nethermind $@ + echo 'Executing Nethermind Runner' + sudo /usr/share/nethermind/Nethermind.Runner $@ else - echo 'Executing Nethermind launcher' + echo 'Executing Nethermind Launcher' cd /usr/share/nethermind - sudo /usr/share/nethermind/nethermind-launcher + sudo /usr/share/nethermind/Nethermind.Launcher fi diff --git a/scripts/infra.sh b/scripts/infra.sh index aad2014ac36..29267d00f31 100644 --- a/scripts/infra.sh +++ b/scripts/infra.sh @@ -18,4 +18,4 @@ cp ~/$CONFIG.key ~/nethermind_$CONFIG/keystore/node.key.plain DB_PATH="/root/db/$CONFIG" echo "DB PATH: " $DB_PATH cat ~/$CONFIG.cfg | jq '.Init.BaseDbPath = "'$DB_PATH'"' | sponge ~/$CONFIG.cfg -dotnet nethermind.dll -c ../$CONFIG.cfg +dotnet Nethermind.Runner.dll --config ../$CONFIG.cfg diff --git a/scripts/nethermind.service b/scripts/nethermind.service index c51eda62f2d..d073cb81ff5 100644 --- a/scripts/nethermind.service +++ b/scripts/nethermind.service @@ -11,7 +11,7 @@ User=nethermind Group=nethermind EnvironmentFile=/home/nethermind/.env WorkingDirectory=/home/nethermind -ExecStart=/home/nethermind/build/nethermind -dd /home/nethermind/data +ExecStart=/home/nethermind/build/Nethermind.Runner --datadir /home/nethermind/data Restart=on-failure LimitNOFILE=1000000 diff --git a/scripts/syncSettings.py b/scripts/syncSettings.py index 106f05b2f4f..83821bc0263 100644 --- a/scripts/syncSettings.py +++ b/scripts/syncSettings.py @@ -34,6 +34,11 @@ "blockReduced": 8192, "multiplierRequirement": 10000 }, + "xdai": { + "url": "https://rpc.gnosischain.com", + "blockReduced": 8192, + "multiplierRequirement": 10000 + }, "chiado": { "url": "https://rpc.chiadochain.net", "blockReduced": 8192, diff --git a/src/Nethermind/Chains/eip4844_local.json b/src/Nethermind/Chains/eip4844_local.json new file mode 100644 index 00000000000..5c4844d4f6f --- /dev/null +++ b/src/Nethermind/Chains/eip4844_local.json @@ -0,0 +1,70 @@ +{ + "name": "Eip4844Local", + "dataDir": "eip4844_local", + "engine": { + "clique": { + "params": { + "period": 5, + "epoch": 30000 + } + } + }, + "params": { + "terminalTotalDifficulty": "2", + "terminalPowBlockNumber": 1, + "chainID": "1", + "networkID": "69", + "maximumExtraDataSize": "1000000", + "eip140Transition": "0x0", + "eip145Transition": "0x0", + "eip150Transition": "0x0", + "eip155Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0", + "eip1014Transition": "0x0", + "eip1052Transition": "0x0", + "eip1283Transition": "0x0", + "eip1283DisableTransition": "0x0", + "eip152Transition": "0x0", + "eip1108Transition": "0x0", + "eip1344Transition": "0x0", + "eip1884Transition": "0x0", + "eip2028Transition": "0x0", + "eip2200Transition": "0x0", + "eip2565Transition": "0x0", + "eip2929Transition": "0x0", + "eip2930Transition": "0x0", + "maxCodeSizeTransition": "0x0", + "eip1559Transition": "0x0", + "eip4895TransitionTimestamp": "0x0", + "eip4844TransitionTimestamp": "0x0" + }, + "genesis": { + "author": "0x0000000000000000000000000000000000000000", + "difficulty": "0x0", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1C9C380", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "seal": { + "ethereum": { + "nonce": "0x42", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "timestamp": 0, + "baseFeePerGas": "0x7" + }, + "accounts": { + "0x8A04d14125D0FDCDc742F4A05C051De07232EDa4": { + "code": "0x60806040526004361061003f5760003560e01c806301ffc9a714610044578063228951181461008c578063621fd130146101a2578063c5f2892f1461022c575b600080fd5b34801561005057600080fd5b506100786004803603602081101561006757600080fd5b50356001600160e01b031916610253565b604080519115158252519081900360200190f35b6101a0600480360360808110156100a257600080fd5b8101906020810181356401000000008111156100bd57600080fd5b8201836020820111156100cf57600080fd5b803590602001918460018302840111640100000000831117156100f157600080fd5b91939092909160208101903564010000000081111561010f57600080fd5b82018360208201111561012157600080fd5b8035906020019184600183028401116401000000008311171561014357600080fd5b91939092909160208101903564010000000081111561016157600080fd5b82018360208201111561017357600080fd5b8035906020019184600183028401116401000000008311171561019557600080fd5b91935091503561028a565b005b3480156101ae57600080fd5b506101b7610ce6565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f15781810151838201526020016101d9565b50505050905090810190601f16801561021e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023857600080fd5b50610241610cf8565b60408051918252519081900360200190f35b60006001600160e01b031982166301ffc9a760e01b148061028457506001600160e01b03198216638564090760e01b145b92915050565b603086146102c95760405162461bcd60e51b81526004018080602001828103825260268152602001806112516026913960400191505060405180910390fd5b602084146103085760405162461bcd60e51b81526004018080602001828103825260368152602001806111e86036913960400191505060405180910390fd5b606082146103475760405162461bcd60e51b81526004018080602001828103825260298152602001806112c46029913960400191505060405180910390fd5b670de0b6b3a764000034101561038e5760405162461bcd60e51b815260040180806020018281038252602681526020018061129e6026913960400191505060405180910390fd5b633b9aca003406156103d15760405162461bcd60e51b815260040180806020018281038252603381526020018061121e6033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff81111561041f5760405162461bcd60e51b81526004018080602001828103825260278152602001806112776027913960400191505060405180910390fd5b606061042a82610fc6565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a61045f602054610fc6565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f01601f191690910187810386528c815260200190508c8c808284376000838201819052601f909101601f191690920188810386528c5181528c51602091820193918e019250908190849084905b838110156104f65781810151838201526020016104de565b50505050905090810190601f1680156105235780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f909101601f19169092018881038452895181528951602091820193918b019250908190849084905b8381101561057f578181015183820152602001610567565b50505050905090810190601f1680156105ac5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284376fffffffffffffffffffffffffffffffff199094169190930190815260408051600f19818403018152601090920190819052815191955093508392506020850191508083835b602083106106415780518252601f199092019160209182019101610622565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610680573d6000803e3d6000fd5b5050506040513d602081101561069557600080fd5b5051905060006002806106ab6040848a8c61114a565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106107015780518252601f1990920191602091820191016106e2565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610740573d6000803e3d6000fd5b5050506040513d602081101561075557600080fd5b50516002610766896040818d61114a565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106107c15780518252601f1990920191602091820191016107a2565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610800573d6000803e3d6000fd5b5050506040513d602081101561081557600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b6020831061086b5780518252601f19909201916020918201910161084c565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa1580156108aa573d6000803e3d6000fd5b5050506040513d60208110156108bf57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b6020831061092e5780518252601f19909201916020918201910161090f565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa15801561096d573d6000803e3d6000fd5b5050506040513d602081101561098257600080fd5b50516040518651600291889160009188916020918201918291908601908083835b602083106109c25780518252601f1990920191602091820191016109a3565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610a495780518252601f199092019160209182019101610a2a565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610a88573d6000803e3d6000fd5b5050506040513d6020811015610a9d57600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610af35780518252601f199092019160209182019101610ad4565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610b32573d6000803e3d6000fd5b5050506040513d6020811015610b4757600080fd5b50519050858114610b895760405162461bcd60e51b81526004018080602001828103825260548152602001806111946054913960600191505060405180910390fd5b60205463ffffffff11610bcd5760405162461bcd60e51b81526004018080602001828103825260218152602001806111736021913960400191505060405180910390fd5b602080546001019081905560005b6020811015610cda578160011660011415610c0d578260008260208110610bfe57fe5b015550610cdd95505050505050565b600260008260208110610c1c57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610c745780518252601f199092019160209182019101610c55565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610cb3573d6000803e3d6000fd5b5050506040513d6020811015610cc857600080fd5b50519250600282049150600101610bdb565b50fe5b50505050505050565b6060610cf3602054610fc6565b905090565b6020546000908190815b6020811015610ea9578160011660011415610ddb57600260008260208110610d2657fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610d7e5780518252601f199092019160209182019101610d5f565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610dbd573d6000803e3d6000fd5b5050506040513d6020811015610dd257600080fd5b50519250610e9b565b60028360218360208110610deb57fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610e425780518252601f199092019160209182019101610e23565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610e81573d6000803e3d6000fd5b5050506040513d6020811015610e9657600080fd5b505192505b600282049150600101610d02565b50600282610eb8602054610fc6565b600060401b6040516020018084815260200183805190602001908083835b60208310610ef55780518252601f199092019160209182019101610ed6565b51815160209384036101000a600019018019909216911617905267ffffffffffffffff199590951692019182525060408051808303600719018152601890920190819052815191955093508392850191508083835b60208310610f695780518252601f199092019160209182019101610f4a565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015610fa8573d6000803e3d6000fd5b5050506040513d6020811015610fbd57600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b8260008151811061100057fe5b60200101906001600160f81b031916908160001a9053508060061a60f81b8260018151811061102b57fe5b60200101906001600160f81b031916908160001a9053508060051a60f81b8260028151811061105657fe5b60200101906001600160f81b031916908160001a9053508060041a60f81b8260038151811061108157fe5b60200101906001600160f81b031916908160001a9053508060031a60f81b826004815181106110ac57fe5b60200101906001600160f81b031916908160001a9053508060021a60f81b826005815181106110d757fe5b60200101906001600160f81b031916908160001a9053508060011a60f81b8260068151811061110257fe5b60200101906001600160f81b031916908160001a9053508060001a60f81b8260078151811061112d57fe5b60200101906001600160f81b031916908160001a90535050919050565b60008085851115611159578182fd5b83861115611165578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a164736f6c634300060b000a", + "balance": "0x0" + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0x6d6172697573766477000000" + } + } +} diff --git a/src/Nethermind/Chains/gnosis.json b/src/Nethermind/Chains/gnosis.json index fdd63e2b508..53f90180591 100644 --- a/src/Nethermind/Chains/gnosis.json +++ b/src/Nethermind/Chains/gnosis.json @@ -41,12 +41,10 @@ } }, "params": { - "networkID": "100", "gasLimitBoundDivisor": "0x400", "maximumExtraDataSize": "0x20", - "maxCodeSize": "0x6000", - "maxCodeSizeTransitionTimestamp": "0x64c8edbc", "minGasLimit": "0x1388", + "networkID": "100", "eip140Transition": "0x0", "eip211Transition": "0x0", "eip214Transition": "0x0", @@ -70,10 +68,6 @@ "eip3529Transition": 19040000, "eip3541Transition": 19040000, "eip1559Transition": 19040000, - "eip3651TransitionTimestamp": "0x64c8edbc", - "eip3855TransitionTimestamp": "0x64c8edbc", - "eip3860TransitionTimestamp": "0x64c8edbc", - "eip4895TransitionTimestamp": "0x64c8edbc", "eip1559BaseFeeMaxChangeDenominator": "0x8", "eip1559ElasticityMultiplier": "0x2", "eip1559BaseFeeInitialValue": "0x3b9aca00", @@ -95,19 +89,14 @@ "gasLimit": "0x989680" }, "nodes": [ - "enode://6765fff89db92aa8d923e28c438af626c8ae95a43093cdccbd6f550a7b6ce6ab5d1a3dc60dd79af3e6d2c2e6731bae629f0e54446a0d9da408c4eca7ebcd8485@3.75.159.31:30303", - "enode://9a7c98e8ee8cdd3199db68092b48868847d4743a471b26afc2ff878bafaa829ed43ee405f9aff58ae13fce53b898f7c2e3c30cb80af8eb111682c3c13f686dbb@18.198.130.54:30303", - "enode://2c4307831914c237801993eac4f9596d8b2f78e1e76830419b64cb23f0933e52cb1e2bb3009cb4af76454bb5bc296135b36869fd6c13e2c2e536a0780e60fe82@3.64.242.196:30303", - "enode://074f68e1a7df5b0859314ff721d55b59d9690e93249c941660609a29b302f02864df4f93ee48884f7ede57dc7f7646379d017a43c9745e34baff049749896b50@3.126.169.151:30303", - "enode://d239697375d7586c7ea1de790401c310b0b1d389326849fa3b7c7005833c7a6b9020e49dfb3b61abfa39135237ffc4ff219cb84ca7653069e8548497527aa432@107.22.4.120:30303", - "enode://d5852bf415d89b756faa809f4ff3f8beb661dc7d60cfb4a5542f9a5fcdf41e1ed0708a210db64b8c7ca32426e04ef0a50da58974124fdf562a8510314d11e28c@3.26.206.142:30303", - "enode://01d372392bb22dd8a91f8b10b6bbb8d80d2dbe98d695801e0df9e4bd4825781df84bba88361f24d1b6580a61313f64e6cec82e8d842ad5f1b3d7cf8d6d132da7@15.152.45.82:30303", - "enode://aee88e803b8e54925081957965b2527961cd90f4d6d14664884580b429da44729678a1258a8b49a42d1582c9c7c5ded05733622f7ab442ad9c6f655545a5ecdd@54.207.220.169:30303", - "enode://fb14d72321ee823fcf21e163091849ee42e0f6ac0cddc737d79e324b0a734c4fc51823ef0a96b749c954483c25e8d2e534d1d5fc2619ea22d58671aff96f5188@65.109.103.148:30303", - "enode://40f40acd78004650cce57aa302de9acbf54becf91b609da93596a18979bb203ba79fcbee5c2e637407b91be23ce72f0cc13dfa38d13e657005ce842eafb6b172@65.109.103.149:30303", - "enode://9e50857aa48a7a31bc7b46957e8ced0ef69a7165d3199bea924cb6d02b81f1f35bd8e29d21a54f4a331316bf09bb92716772ea76d3ef75ce027699eccfa14fad@141.94.97.22:30303", - "enode://96dc133ce3aeb5d9430f1dce1d77a36418c8789b443ae0445f06f73c6b363f5b35c019086700a098c3e6e54974d64f37e97d72a5c711d1eae34dc06e3e00eed5@141.94.97.74:30303", - "enode://516cbfbe9bbf26b6395ed68b24e383401fc33e7fe96b9d235ebca86c9f812fde8d33a7dbebc0fb5595459d2c5cc6381595d96507af89e6b48b5bdd0ebf8af0c0@141.94.97.84:30303" +"enode://6765fff89db92aa8d923e28c438af626c8ae95a43093cdccbd6f550a7b6ce6ab5d1a3dc60dd79af3e6d2c2e6731bae629f0e54446a0d9da408c4eca7ebcd8485@3.75.159.31:30303", +"enode://9a7c98e8ee8cdd3199db68092b48868847d4743a471b26afc2ff878bafaa829ed43ee405f9aff58ae13fce53b898f7c2e3c30cb80af8eb111682c3c13f686dbb@18.198.130.54:30303", +"enode://2c4307831914c237801993eac4f9596d8b2f78e1e76830419b64cb23f0933e52cb1e2bb3009cb4af76454bb5bc296135b36869fd6c13e2c2e536a0780e60fe82@3.64.242.196:30303", +"enode://074f68e1a7df5b0859314ff721d55b59d9690e93249c941660609a29b302f02864df4f93ee48884f7ede57dc7f7646379d017a43c9745e34baff049749896b50@3.126.169.151:30303", +"enode://d239697375d7586c7ea1de790401c310b0b1d389326849fa3b7c7005833c7a6b9020e49dfb3b61abfa39135237ffc4ff219cb84ca7653069e8548497527aa432@107.22.4.120:30303", +"enode://d5852bf415d89b756faa809f4ff3f8beb661dc7d60cfb4a5542f9a5fcdf41e1ed0708a210db64b8c7ca32426e04ef0a50da58974124fdf562a8510314d11e28c@3.26.206.142:30303", +"enode://01d372392bb22dd8a91f8b10b6bbb8d80d2dbe98d695801e0df9e4bd4825781df84bba88361f24d1b6580a61313f64e6cec82e8d842ad5f1b3d7cf8d6d132da7@15.152.45.82:30303", +"enode://aee88e803b8e54925081957965b2527961cd90f4d6d14664884580b429da44729678a1258a8b49a42d1582c9c7c5ded05733622f7ab442ad9c6f655545a5ecdd@54.207.220.169:30303" ], "accounts": { "0x0000000000000000000000000000000000000005": { diff --git a/src/Nethermind/Chains/holesky.json b/src/Nethermind/Chains/holesky.json deleted file mode 100644 index a06501a813c..00000000000 --- a/src/Nethermind/Chains/holesky.json +++ /dev/null @@ -1,1056 +0,0 @@ -{ - "name": "Holesky Testnet", - "dataDir": "holesky", - "engine": { - "Ethash": {} - }, - "params": { - "accountStartNonce": "0x0", - "chainID": "0x4268", - "networkID": "0x4268", - "eip140Transition": "0x0", - "eip145Transition": "0x0", - "eip150Transition": "0x0", - "eip155Transition": "0x0", - "eip160Transition": "0x0", - "eip161abcTransition": "0x0", - "eip161dTransition": "0x0", - "eip211Transition": "0x0", - "eip214Transition": "0x0", - "eip658Transition": "0x0", - "eip1014Transition": "0x0", - "eip1052Transition": "0x0", - "eip1283Transition": "0x0", - "eip1283DisableTransition": "0x0", - "eip152Transition": "0x0", - "eip1108Transition": "0x0", - "eip1344Transition": "0x0", - "eip1884Transition": "0x0", - "eip2028Transition": "0x0", - "eip2200Transition": "0x0", - "eip2565Transition": "0x0", - "eip2929Transition": "0x0", - "eip2930Transition": "0x0", - "eip1559Transition": "0x0", - "eip3198Transition": "0x0", - "eip3529Transition": "0x0", - "eip3541Transition": "0x0", - "eip3651TransitionTimestamp": "0x6516eac0", - "eip3855TransitionTimestamp": "0x6516eac0", - "eip3860TransitionTimestamp": "0x6516eac0", - "eip4895TransitionTimestamp": "0x6516eac0", - "terminalTotalDifficulty": "0x0", - "gasLimitBoundDivisor": "0x400", - "maxCodeSize": "0x6000", - "maxCodeSizeTransition": "0x0", - "maximumExtraDataSize": "0xffff", - "minGasLimit": "0x1388", - "registrar": "0x0000000000000000000000000000000000000000", - "MergeForkIdTransition": "0x0" - }, - "genesis": { - "seal": { - "ethereum": { - "nonce": "0x1234", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "difficulty": "0x01", - "author": "0x0000000000000000000000000000000000000000", - "extraData": "", - "gasLimit": "0x17D7840", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp": "0x65156994" - }, - "nodes": [ - "enode://ac906289e4b7f12df423d654c5a962b6ebe5b3a74cc9e06292a85221f9a64a6f1cfdd6b714ed6dacef51578f92b34c60ee91e9ede9c7f8fadc4d347326d95e2b@146.190.13.128:30303", - "enode://a3435a0155a3e837c02f5e7f5662a2f1fbc25b48e4dc232016e1c51b544cb5b4510ef633ea3278c0e970fa8ad8141e2d4d0f9f95456c537ff05fdf9b31c15072@178.128.136.233:30303" - ], - "accounts": { - "0x0000000000000000000000000000000000000000": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000001": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000002": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000003": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000004": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000005": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000006": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000007": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000008": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000009": { - "balance": "1" - }, - "0x000000000000000000000000000000000000000a": { - "balance": "1" - }, - "0x000000000000000000000000000000000000000b": { - "balance": "1" - }, - "0x000000000000000000000000000000000000000c": { - "balance": "1" - }, - "0x000000000000000000000000000000000000000d": { - "balance": "1" - }, - "0x000000000000000000000000000000000000000e": { - "balance": "1" - }, - "0x000000000000000000000000000000000000000f": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000010": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000011": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000012": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000013": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000014": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000015": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000016": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000017": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000018": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000019": { - "balance": "1" - }, - "0x000000000000000000000000000000000000001a": { - "balance": "1" - }, - "0x000000000000000000000000000000000000001b": { - "balance": "1" - }, - "0x000000000000000000000000000000000000001c": { - "balance": "1" - }, - "0x000000000000000000000000000000000000001d": { - "balance": "1" - }, - "0x000000000000000000000000000000000000001e": { - "balance": "1" - }, - "0x000000000000000000000000000000000000001f": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000020": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000021": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000022": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000023": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000024": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000025": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000026": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000027": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000028": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000029": { - "balance": "1" - }, - "0x000000000000000000000000000000000000002a": { - "balance": "1" - }, - "0x000000000000000000000000000000000000002b": { - "balance": "1" - }, - "0x000000000000000000000000000000000000002c": { - "balance": "1" - }, - "0x000000000000000000000000000000000000002d": { - "balance": "1" - }, - "0x000000000000000000000000000000000000002e": { - "balance": "1" - }, - "0x000000000000000000000000000000000000002f": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000030": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000031": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000032": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000033": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000034": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000035": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000036": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000037": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000038": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000039": { - "balance": "1" - }, - "0x000000000000000000000000000000000000003a": { - "balance": "1" - }, - "0x000000000000000000000000000000000000003b": { - "balance": "1" - }, - "0x000000000000000000000000000000000000003c": { - "balance": "1" - }, - "0x000000000000000000000000000000000000003d": { - "balance": "1" - }, - "0x000000000000000000000000000000000000003e": { - "balance": "1" - }, - "0x000000000000000000000000000000000000003f": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000040": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000041": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000042": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000043": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000044": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000045": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000046": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000047": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000048": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000049": { - "balance": "1" - }, - "0x000000000000000000000000000000000000004a": { - "balance": "1" - }, - "0x000000000000000000000000000000000000004b": { - "balance": "1" - }, - "0x000000000000000000000000000000000000004c": { - "balance": "1" - }, - "0x000000000000000000000000000000000000004d": { - "balance": "1" - }, - "0x000000000000000000000000000000000000004e": { - "balance": "1" - }, - "0x000000000000000000000000000000000000004f": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000050": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000051": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000052": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000053": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000054": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000055": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000056": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000057": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000058": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000059": { - "balance": "1" - }, - "0x000000000000000000000000000000000000005a": { - "balance": "1" - }, - "0x000000000000000000000000000000000000005b": { - "balance": "1" - }, - "0x000000000000000000000000000000000000005c": { - "balance": "1" - }, - "0x000000000000000000000000000000000000005d": { - "balance": "1" - }, - "0x000000000000000000000000000000000000005e": { - "balance": "1" - }, - "0x000000000000000000000000000000000000005f": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000060": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000061": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000062": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000063": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000064": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000065": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000066": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000067": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000068": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000069": { - "balance": "1" - }, - "0x000000000000000000000000000000000000006a": { - "balance": "1" - }, - "0x000000000000000000000000000000000000006b": { - "balance": "1" - }, - "0x000000000000000000000000000000000000006c": { - "balance": "1" - }, - "0x000000000000000000000000000000000000006d": { - "balance": "1" - }, - "0x000000000000000000000000000000000000006e": { - "balance": "1" - }, - "0x000000000000000000000000000000000000006f": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000070": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000071": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000072": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000073": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000074": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000075": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000076": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000077": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000078": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000079": { - "balance": "1" - }, - "0x000000000000000000000000000000000000007a": { - "balance": "1" - }, - "0x000000000000000000000000000000000000007b": { - "balance": "1" - }, - "0x000000000000000000000000000000000000007c": { - "balance": "1" - }, - "0x000000000000000000000000000000000000007d": { - "balance": "1" - }, - "0x000000000000000000000000000000000000007e": { - "balance": "1" - }, - "0x000000000000000000000000000000000000007f": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000080": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000081": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000082": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000083": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000084": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000085": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000086": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000087": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000088": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000089": { - "balance": "1" - }, - "0x000000000000000000000000000000000000008a": { - "balance": "1" - }, - "0x000000000000000000000000000000000000008b": { - "balance": "1" - }, - "0x000000000000000000000000000000000000008c": { - "balance": "1" - }, - "0x000000000000000000000000000000000000008d": { - "balance": "1" - }, - "0x000000000000000000000000000000000000008e": { - "balance": "1" - }, - "0x000000000000000000000000000000000000008f": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000090": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000091": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000092": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000093": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000094": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000095": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000096": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000097": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000098": { - "balance": "1" - }, - "0x0000000000000000000000000000000000000099": { - "balance": "1" - }, - "0x000000000000000000000000000000000000009a": { - "balance": "1" - }, - "0x000000000000000000000000000000000000009b": { - "balance": "1" - }, - "0x000000000000000000000000000000000000009c": { - "balance": "1" - }, - "0x000000000000000000000000000000000000009d": { - "balance": "1" - }, - "0x000000000000000000000000000000000000009e": { - "balance": "1" - }, - "0x000000000000000000000000000000000000009f": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000a0": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000a1": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000a2": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000a3": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000a4": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000a5": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000a6": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000a7": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000a8": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000a9": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000aa": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000ab": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000ac": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000ad": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000ae": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000af": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000b0": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000b1": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000b2": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000b3": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000b4": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000b5": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000b6": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000b7": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000b8": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000b9": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000ba": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000bb": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000bc": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000bd": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000be": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000bf": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000c0": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000c1": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000c2": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000c3": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000c4": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000c5": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000c6": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000c7": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000c8": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000c9": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000ca": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000cb": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000cc": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000cd": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000ce": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000cf": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000d0": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000d1": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000d2": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000d3": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000d4": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000d5": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000d6": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000d7": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000d8": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000d9": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000da": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000db": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000dc": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000dd": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000de": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000df": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000e0": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000e1": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000e2": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000e3": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000e4": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000e5": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000e6": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000e7": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000e8": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000e9": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000ea": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000eb": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000ec": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000ed": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000ee": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000ef": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000f0": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000f1": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000f2": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000f3": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000f4": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000f5": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000f6": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000f7": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000f8": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000f9": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000fa": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000fb": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000fc": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000fd": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000fe": { - "balance": "1" - }, - "0x00000000000000000000000000000000000000ff": { - "balance": "1" - }, - "0x4242424242424242424242424242424242424242": { - "balance": "0", - "code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a26469706673582212201dd26f37a621703009abf16e77e69c93dc50c79db7f6cc37543e3e0e3decdc9764736f6c634300060b0033", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000022": "0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b", - "0x0000000000000000000000000000000000000000000000000000000000000023": "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", - "0x0000000000000000000000000000000000000000000000000000000000000024": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", - "0x0000000000000000000000000000000000000000000000000000000000000025": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", - "0x0000000000000000000000000000000000000000000000000000000000000026": "0x9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30", - "0x0000000000000000000000000000000000000000000000000000000000000027": "0xd88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1", - "0x0000000000000000000000000000000000000000000000000000000000000028": "0x87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c", - "0x0000000000000000000000000000000000000000000000000000000000000029": "0x26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193", - "0x000000000000000000000000000000000000000000000000000000000000002a": "0x506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1", - "0x000000000000000000000000000000000000000000000000000000000000002b": "0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b", - "0x000000000000000000000000000000000000000000000000000000000000002c": "0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220", - "0x000000000000000000000000000000000000000000000000000000000000002d": "0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f", - "0x000000000000000000000000000000000000000000000000000000000000002e": "0xdf6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e", - "0x000000000000000000000000000000000000000000000000000000000000002f": "0xb58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784", - "0x0000000000000000000000000000000000000000000000000000000000000030": "0xd49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb", - "0x0000000000000000000000000000000000000000000000000000000000000031": "0x8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb", - "0x0000000000000000000000000000000000000000000000000000000000000032": "0x8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab", - "0x0000000000000000000000000000000000000000000000000000000000000033": "0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4", - "0x0000000000000000000000000000000000000000000000000000000000000034": "0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f", - "0x0000000000000000000000000000000000000000000000000000000000000035": "0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa", - "0x0000000000000000000000000000000000000000000000000000000000000036": "0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c", - "0x0000000000000000000000000000000000000000000000000000000000000037": "0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167", - "0x0000000000000000000000000000000000000000000000000000000000000038": "0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7", - "0x0000000000000000000000000000000000000000000000000000000000000039": "0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0", - "0x000000000000000000000000000000000000000000000000000000000000003a": "0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544", - "0x000000000000000000000000000000000000000000000000000000000000003b": "0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765", - "0x000000000000000000000000000000000000000000000000000000000000003c": "0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4", - "0x000000000000000000000000000000000000000000000000000000000000003d": "0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1", - "0x000000000000000000000000000000000000000000000000000000000000003e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636", - "0x000000000000000000000000000000000000000000000000000000000000003f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c", - "0x0000000000000000000000000000000000000000000000000000000000000040": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7" - } - }, - "0x0000006916a87b82333f4245046623b23794C65C": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x0be949928Ff199c9EBA9E110db210AA5C94EFAd0": { - "balance": "0x7c13bc4b2c133c56000000" - }, - "0x0C100000006d7b5e23a1eAEE637f28cA32Cd5b31": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x0C35317B7a96C454E2CB3d1A255D775Ab112cCc8": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x0d731cfabC5574329823F26d488416451d2ea376": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x0e79065B5F11b5BD1e62B935A600976ffF3754B9": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x105083929bF9bb22C26cB1777Ec92661170D4285": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x10F5d45854e038071485AC9e402308cF80D2d2fE": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x1268AD189526AC0b386faF06eFfC46779c340eE6": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x12Cba59f5A74DB81a12ff63C349Bd82CBF6007C2": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x1446D7f6dF00380F246d8211dE7f0FaBC4Fd248C": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x164e38a375247A784A81d420201AA8fe4E513921": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x1B7aA44088a0eA95bdc65fef6E5071E946Bf7d8f": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x222222222222cF64a76AE3d36859958c864fDA2c": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x2f14582947E292a2eCd20C430B46f2d27CFE213c": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x2f2c75B5Dd5D246194812b00eEb3B09c2c66e2eE": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x341c40b94bf2afbfa42573cb78f16ee15a056238": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x34f845773D4364999f2fbC7AA26ABDeE902cBb46": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x3C75594181e03E8ECD8468A0037F058a9dAfad79": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x462396E69dBfa455F405f4DD82F3014Af8003B72": { - "balance": "0xa56fa5b99019a5c8000000" - }, - "0x49Df3CCa2670eB0D591146B16359fe336e476F29": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x4D0b04b405c6b62C7cFC3aE54759747e2C0b4662": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x4D496CcC28058B1D74B7a19541663E21154f9c84": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x509a7667aC8D0320e36172c192506a6188aA84f6": { - "balance": "0x7c13bc4b2c133c56000000" - }, - "0x5180db0237291A6449DdA9ed33aD90a38787621c": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x52730f347dEf6BA09adfF62EaC60D5fEe8205BC4": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x5EAC0fBd3dfef8aE3efa3c5dc1aa193bc6033dFd": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x6a7aA9b882d50Bb7bc5Da1a244719C99f12F06a3": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x6Cc9397c3B38739daCbfaA68EaD5F5D77Ba5F455": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x762cA62ca2549ad806763B3Aa1eA317c429bDBDa": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x778F5F13C4Be78A3a4d7141BCB26999702f407CF": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x875D25Ee4bC604C71BaF6236a8488F22399BED4b": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x8dF7878d3571BEF5e5a744F96287C8D20386d75A": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0x9E415A096fF77650dc925dEA546585B4adB322B6": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xA0766B65A4f7B1da79a1AF79aC695456eFa28644": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xA29B144A449E414A472c60C7AAf1aaFfE329021D": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xa55395566b0b54395B3246f96A0bDc4b8a483df9": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xAC9ba72fb61aA7c31A95df0A8b6ebA6f41EF875e": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xB0498C15879db2eE5471d4926c5fAA25C9a09683": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xB19Fb4c1f280327e60Ed37b1Dc6EE77533539314": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0xC21cB9C99C316d1863142F7dD86dd5496D81A8D6": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xc473d412dc52e349862209924c8981b2ee420768": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xC48E23C5F6e1eA0BaEf6530734edC3968f79Af2e": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0xc6e2459991BfE27cca6d86722F35da23A1E4Cb97": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0xD3994e4d3202dD23c8497d7F75bF1647d1DA1bb1": { - "balance": "0x19D971E4FE8401E74000000" - }, - "0xDCA6e9B48Ea86AeBFDf9929949124042296b6e34": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xe0a2Bd4258D2768837BAa26A28fE71Dc079f84c7": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0xEA28d002042fd9898D0Db016be9758eeAFE35C1E": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xEfA7454f1116807975A4750B46695E967850de5D": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xFBFd6Fa9F73Ac6A058E01259034C28001BEf8247": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0xe0991E844041bE6F11B99da5b114b6bCf84EBd57": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x15E719b6AcAf1E4411Bf0f9576CB1D0dB161DdFc": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x346D827a75F98F0A7a324Ff80b7C3F90252E8baC": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x73b2e0E54510239E22cC936F0b4a6dE1acf0AbdE": { - "balance": "0x52b7d2dcc80cd2e4000000" - }, - "0xBb977B2EE8a111D788B3477D242078d0B837E72b": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x834Dbf5A03e29c25bc55459cCe9c021EeBE676Ad": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xD1F77E4C1C45186e8653C489F90e008a73597296": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xb04aeF2a3d2D86B01006cCD4339A2e943d9c6480": { - "balance": "0xd3c21bcecceda1000000" - }, - "0xC9CA2bA9A27De1Db589d8c33Ab8EDFa2111b31fb": { - "balance": "0xd3c21bcecceda1000000" - }, - "0x4BC656B34De23896fa6069C9862F355b740401aF": { - "balance": "0x084595161401484a000000" - } - } -} diff --git a/src/Nethermind/Chains/ropsten.json b/src/Nethermind/Chains/ropsten.json new file mode 100644 index 00000000000..82363a43fdc --- /dev/null +++ b/src/Nethermind/Chains/ropsten.json @@ -0,0 +1,3535 @@ +{ + "name": "Ropsten Testnet", + "dataDir": "ropsten", + "engine": { + "Ethash": { + "params": { + "minimumDifficulty": "0x20000", + "difficultyBoundDivisor": "0x800", + "durationLimit": "0xd", + "blockReward": { + "0x0": "0x4563918244F40000", + "0x19f0a0": "0x29A2241AF62C0000", + "0x408b70": "0x1BC16D674EC80000" + }, + "homesteadTransition": "0x0", + "eip100bTransition": "0x19f0a0", + "difficultyBombDelays": { + "0x19f0a0": "0x2dc6c0", + "0x408b70": "0x1e8480", + "0x6C993D": "0x3D0900", + "0xA03549": "0xAAE60" + } + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x400", + "registrar": "0x81a4b044831c4f12ba601adb9274516939e9b8a2", + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID": "0x3", + "forkBlock": "0x40E80F", + "forkCanonHash": "0x3e12d5c0f8d63fbc5831cc7f7273bd824fa4d0a9a4102d65d99a7ea5604abc00", + "maxCodeSize": "0x6000", + "maxCodeSizeTransition": "0xa", + "eip150Transition": "0x0", + "eip160Transition": "0xa", + "eip161abcTransition": "0xa", + "eip161dTransition": "0xa", + "eip155Transition": "0xa", + "eip140Transition": "0x19f0a0", + "eip211Transition": "0x19f0a0", + "eip214Transition": "0x19f0a0", + "eip658Transition": "0x19f0a0", + "eip145Transition": "0x408b70", + "eip1014Transition": "0x408b70", + "eip1052Transition": "0x408b70", + "eip1283Transition": "0x408b70", + "eip1283DisableTransition": "0x4b5e82", + "eip152Transition": "0x62F756", + "eip1108Transition": "0x62F756", + "eip1344Transition": "0x62F756", + "eip1884Transition": "0x62F756", + "eip2028Transition": "0x62F756", + "eip2200Transition": "0x62F756", + "eip2565Transition": "0x95B8DD", + "eip2929Transition": "0x95B8DD", + "eip2930Transition": "0x95B8DD", + "eip1559Transition": "0xA03549", + "eip3198Transition": "0xA03549", + "eip3529Transition": "0xA03549", + "eip3541Transition": "0xA03549", + "terminalTotalDifficulty": "B1A2BC2EC50000" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x100000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x3535353535353535353535353535353535353535353535353535353535353535", + "gasLimit": "0x1000000" + }, + "hardcodedSync": { + "header": "f9021aa0a8da98b6ef1e12b6c49e85b0e965f1ed1688f5e3605f06bb3c6ce4f857aa0bc6a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794635b4764d1939dfacd3a8014726159abc277becca0d03c319fe68a91e22fb3b945a8dfc73b817976e29cf57e6c8425e6a02e9bf034a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000849fe1546f8350d001837a121d80845c9d55f29fde8302020b8f5061726974792d457468657265756d86312e33322e30826c69a04bf72e97bcf64717bfd655e2bca9ed1a5253cce5373268729161b1786ca4710488db3c50627f9321c4", + "totalDifficulty": "18787961645682286", + "CHTs": [ + "0x614648fc0a459451850bdfe353a932b5ff824e1b568478394f78b3ed5427e37a", + "0x1eae561c582dbb7f4e041998e084e165d0332c915d3a6da367638a8d24f3fafc", + "0x6fdc50234f74fd6eb5b8bb28378583da28963d26c7226e1254e04b676951c4b4", + "0x0d40b71e8f08c4d93a0f62d93eaee4c6ba92ee1ff6e46dab57dc64c992873245", + "0x7f129d232456d600332b59fb30434e4c71aa95b0e3a4f9328c74ec5b97102ecc", + "0x0aff522a9d28bb1a32af4524d049ce9b3e66149e8d2644efbad5736c9fa044ba", + "0xf9adf08eb7bca9237babc37df559297c6e1b54b585867867a2aed7c10cd191b9", + "0x5b90ca8fa35cad63ad662e3696f41c4159fa871e5f77637e018595a626282150", + "0xf33aa648935eb7dd99906d0855c71893b4c0d0c9b32ab8c8b7ae316e503ba35f", + "0x79946d20c81f7aae18f427d991f21888169c96424813461d04a61758bbe9f214", + "0x80950805fc209691ddaea24e8afecd0096e84e3c465940508131f41f569d559e", + "0xd58de59cb3b7f0323ff3edaf9e3af56843258c457f490346cf25a73a35163ed1", + "0xcf52cf0f195caa769e2d5857231f31bf17efed369c358e7ade257f6278b1df0b", + "0xce570fce622e9f3bd03942c63537417f96250bb3605d2182e5a567e961739e46", + "0xe6add695b25d4b06bfa08a80e9e9295c84948fc34202cf24b42c1cc325075d04", + "0x4699a5f1df0d7b2dab8ba282b6e83af0d0b31b604443e13ccf097fd46f346bcb", + "0x1a16f27083787c5dc1dd8f0be868338c78ce147d0cc043b299870f568de20a3b", + "0x2dc5c4538c1812e892e0a53c112e8e4c3fd9f6f60d1e8531a9df5419df86d013", + "0x40de720fa5ec3b58b3be838f189ae59bc4f21bc8d8f406e569339ff054f93459", + "0xc7274c13bc7462d09cbe60044ea6c9e92622204c41dfddfe864d388f830ab35e", + "0xfb6b099472c5457a813698944d4901b766b4bb8a177c4d357897f1974ba6c431", + "0x9e6104a79f7bbf96d117607ec87be8604417d80af11f558ef1e74067168dff0d", + "0xb8deb38b0b58be7b3eb89a5a3ca1eedc5726ab14186baba17ac520a592f68827", + "0x59a58beef1250fb3315291f0b84480b947672deb331980cda261c94ba544e22f", + "0x0fa4b28513f4a3639b427b5abb87902273fdc4077cc0a51361c3dddc264871f5", + "0xf9e1e92a1de2346fbd8b54987960f08a8b21cb0a8a6c561edcccd6cdfacb46b0", + "0x89f4a9590d0865e126622cc47ce2a1ba50aad880161335e8c88c8a24af709fd9", + "0x5f014ca414e0663c92fcbda0c7250153445a04808c7d062859d000c970003834", + "0xbdfc2347806fb9641788978b5d0a6bccc81b11203cd751dfae45a8dfd3bde7ea", + "0x41420d311b7b527ec68770306d97ce3352d7fee50fdba3b05bb54e70c7250459", + "0x3ad7001f1b2b2635266141327ed45b017f334fc3a5f410e3e99624492c489def", + "0x2beb717939cc0404dc173e50dfbe1477ff32c1ccb59f40d7900c2337021e2d6e", + "0x558b53c5eda0866f7515f113ea3254cb85424b739a5dd6ad48bd4d9221006985", + "0x294c62ce078bf950361111adbca5ebc963d5f12c7014b04e3d86d3cc95c6faba", + "0xec18a7c338bbebfdfbd03f1896d726dbb1d21a29e32e92fd9949478078bb19d9", + "0x6e61bb0641c13be0e0858bc3da3a0b06f6a8ac462301a33fab7425e99d6ae14e", + "0x7a4378c70cb339cb4e3805d013f6ecd66ebcfed3dd1df972c8124bd7b888c8e3", + "0x5911bdce0868655abb581c9ce87a51b85b449101d6d52350c05ff1db30deb900", + "0x081f65d017c48967f02efec9781ac4bc124f42a31ad20104cf4ac6553fe788e4", + "0x89a055c33ecf13f71637fc1dd818c6c26e86f4751c2e09c5b8970195b39ddcfe", + "0x83d33e35f31824d849e27d2cd1d4d02812cb84c8508bbb391ba563264ba2a429", + "0x144d66cd98cbac72f3dd9af9b2656529a00fe7fda8f70e02d0ee025fdf2de9d1", + "0x35d44c6849d379e58398189d06b149eee34a267e94230ae5e24a0c58ba3b7d30", + "0xe4d67e58b9be3711015ac016983bcbfeaf2ec71ee85bc08fc2e53e6d173ff348", + "0x67f7bfc9457f1a1566d9acd3700c399a2fbeb2e1071b3f5c908eb56f2bbb9716", + "0x2546b96a4a88411aa7b3aaffd71a0e22484cf526a099d58f1dd330b3209e4aca", + "0x91f9c4aa8357a4835ae2fc913ff21eb4790b711d2a813e94b38fbf52ced0c4f6", + "0xb4623b136bd01bbf2dfe3ccdcda850cdbc6da79b69324a582d3e1c29703a70ac", + "0x68649bddb9b142d43905ef85df986ccc35c5b0796d860b367c21085c9f1d0220", + "0xa007ebec8e3242c209a178e01eb7aac3666fe09370dc1064bfbc46651c5c4e01", + "0x614125ba7478c7ba2ecd062eb8014ad3b50f4d9a7ba546c932e3f0a3c43c13c9", + "0xfa579127b6d13731bddb5c27cff6bea2d0ec13bb6d17679d4d9e1ffce8d7dc2e", + "0xdb11e78fced06b1bd768da0d345f19c023d5708e7b57bf09c37009887e0bcde8", + "0xda9a47b636cebceb2f378d9149a4a5bdeb6841746e7f677942c26629d3d1d4ba", + "0xeaf7cf3816297b48236ea2cf3f60ece988ca7cc97f5c8efaac1433d23c3a5ae2", + "0x1b7746aeeeb0651a867a3f1d34eb0662660aa667847c04d6761507f043d0eb71", + "0x4e6a1631fc6702fef39cc0e383f4fb5608e8a1f0c721b1622c8f25ea14aa86ce", + "0x9e96f3b348c2170685fbaa99c968fadb4bd9dd621f6e913784851ab1bcad60a2", + "0x65df62cc768c87ec256f7308d9f199040aafc24c03d5c6d527bdaef9da365e4e", + "0xdf067410f903d878471fc3b53d020bce9d0b672ebd51df16ad65f4a3468be124", + "0x358cecbaca6506567a60b08d00c888c7b1dd66ccc292ba7c4c9aa3e37b018391", + "0x5102782ac246337226e6527ce651294bb5c3787cc68219208d6dfe6ce398f0b5", + "0xe6a48cff6189dc26c3d7242eacaf1e34c81503327b18087840a755c322665ca7", + "0xbf599651ec19034ca45bec20673f41813b43387ebbc596a57384a813eb6a21b2", + "0xa5a5242eb4e6fecf1b497a62de8138401cae35cad4a9c136d9efdfc12fd53d60", + "0x05eddef47694a7dfc61e79f78b65bcf9c5e0e65513cfadd2957ac3a324f54b55", + "0xa4b5589bca8121c6bc00a846ec459faa99441d0ffa4b577a45984c32d63128ac", + "0xc8a2f9d7974a1aa77b35188d9dbb3fd56d5a2f6c796d2a665360374886c5a386", + "0xe9d430f782c0275eab831108f934ea3bd589c6c72f9da930e9fd392de833e486", + "0x71e85321e2d1a4b0eb48d8493a97ee3634fe153f30a85d1dd55fb0f5f8c82b91", + "0xfed03a8dffe6cb8043a11ccad791096151f0803b020e4dcf33adc4b180551fa1", + "0xaf1beb7795169537916bf4c9b1515effd365cc0e3988cd3e296fa075831fb63d", + "0x06ffb84050198793b580803a41e78d4a6fbcaaba0901a6f938a5ac5f9982f1e2", + "0xb416bb6b94d5076df719edfd2e2bb9237eb2171b9ebbcdb082e1bb1016244371", + "0x60d6170c0fe77eada1dd85af74079ea0387a167341df0ee8ae110d0047c00fef", + "0x15f03d5f617db0bbf963d2daa06816a768b21794d05873131deb677bc3ff2a07", + "0x0b9fa1e7fb11e3c0b33cc609a87dba8c1acca7476a15da2116518d72ea019e0e", + "0x9bba5ba8b88b76613a52504bdde96ccc1064f3e868881cfb4b155d24d237e093", + "0xa8a77eb3fa43914feb609274d1ed96d51ae29028fa59e7f0d174b085d106fd27", + "0x142d2e126b1faaa6997553835ce1933083a5c2cfc9818ae71d559c8571757fab", + "0xe9241f795bd887173fa93f9e72bd7f07ee58d69dede512fc31f9faf0ddea8e29", + "0x526d5379c00d1a318409ea42ceeb7fa9d33a4bdb71793c940e0d1b42cc848d36", + "0x2045cd5b32670fc4c36fd32e45437db69f468aab51e10e32da423ad28bdf85b1", + "0xf0d0bdc64abd76e66be96239efbd0f25ae30bcad096a4cf28b8b5bd9658c8c3c", + "0xfa5cf979a921b2c5ba8fddc330cf1df7a445936f7bc990553c578dc3ca45de49", + "0xdf2ccce3cf15b30d7bef7ca83b45875e96f02e41c6aee9a1a97025f0dc75585a", + "0xb61fe42d47707d473a2ba8483dbd4b9a40c1e7b79c2bff15ff52aec560d505a6", + "0x068ce2cc3d65a152aa574be6f0617ff7e2f688db97b020d8ba84e81ae9037f57", + "0xef3c631c846ef30f6dfdaa901d8d1424cd100710335805e14226976e719cc2b2", + "0xd582c2e6adb0d112786bdf27dbf1c77fc7bd002511e53d0a10f4dbe780156478", + "0x8a028e29f728e414cf7e3d403bce9de7766feae6090ae0f7f787944569f2b001", + "0xafa8f78b22031dfb0b06004d32b6699421586ae779624fdb7153854d1ea5bd4a", + "0x7ff5e562415a97c4f731c7f8a6b82e401705e34a78751a6e8039b0930eb0dc59", + "0x4cff7c84dfe821e917e48089d3a25a88a84983fa5836d7a78fe050915ea86374", + "0x2ba7416bb329d81424f9fb12b43a285eb3077799e71cd21f0095845d2d165c87", + "0x613ca539b0ec3a5819424d8df2f4ee08e03e5e95a2607503bfaa8574270d163d", + "0x3f6ce1315b8feca300da0bd990b582c647b4440d4a218fb4bb6c841a789da37e", + "0xba8b0c45d55e44cec801c724ad6b6b699fa78505d87a5f356f6ef054628f0e0f", + "0xed1069e471b099408ceb19fdca42cb57bca2389dec54b8fd283db0a53ebe2c30", + "0xcbb375230e9aa4f7aa8536f42f4df3a6bd7572f603c03e716a934b0d3bbe475e", + "0xa8954ae2e84ed2c0f45db6e41731a09ebffec9b064cbd12e020e66b7575d2c9a", + "0x9229f2300310a0675f281f76c695b06214960621aaa4592e3bba558c23b5bad3", + "0xe821e771c08bd42b6d926bc1ecef87dd846110693f59d71cc79a55d7bdec4cf4", + "0xa7e54537a3a01524894a0f602bf010043a52c8c7ac7f6cba10a6ebf86ca11820", + "0x3ef166570a593e608afe6b848ab8543957963e63448b7a1d0febb8127003b527", + "0x1308ea66fbc0fdf84680f227d6425e63dd850286de1783300b64ce77deb696ce", + "0x14676109d2f68c5cee4f58c27f40579cc04663dcd01017963402aa2f06fd315b", + "0xfb9434241629e83ec929e1f3feeb1943945e8ce87590eb69a9ae44e3fdbdcb4e", + "0xb695c39514548fe5240723355a6a2eb2d233a48018485435b2d9a63a1097ef55", + "0x9caf7a3660201b0118736033e479b74e488f64a07a79e33f4782048af424840d", + "0x82f188de672c6e1826d70aa5f7d54f499aac011139ecde9d4d05360cd8b9aed7", + "0xdf7367edfa34b79be80c06aab16a54e7d1f74eb9f813a080a8c4af916e3a61c5", + "0xbd7cf6ed130f745c853777d762706e9050c2a45d01839b124d517e3e73206c6f", + "0x474b7557c158d93d732fa0b8829b40c2d9e593206c3c36d7743b6eadb0067689", + "0x1ff6d56aa85903b2a9710b56ad4760825edc5343cab855bc966cad9bd11aef7b", + "0x52c4c3990413706a86714b1dcac8d9c4e55a36eddd176dc55066cc39e308175c", + "0x7a63b6427abc9780a14a4826c45a313fa2d020ea33ae91d48e4cea28ebda51a5", + "0xfa7ec58ce730e3d66c79b2616e14f11b87077c5d911db6bd89cf7c69f9fb2559", + "0x58f1b88f3ae0b76dbaae0ac58673ab38118f5253b07ee2a309cffa1c3f9f3a30", + "0xca98407f9cbb2911422f5a0716c325e1c2ef053355796e47eb619094790da45f", + "0xad072d0b4fcb8ab2662e3d27f6c6baa2f914bedcb91d178a9ab02b9646e6203a", + "0xd8319f885666fd19a5a9801005530e4a490fe29765f9d60c38b60c5b9ea92d5e", + "0xe95daec9ea36ec00b4f9f7478ae136c1453bbbc3530f839e93483fdef4a61cc9", + "0x6eeb1a044cf3cddaa87f70dbca704fe9cad675e82659380fb733153ad452761d", + "0x89c53801a896ebb9cb6c3a881269a93f610122fe9c3132ec19d64a6f22e9f7bf", + "0x81e57e25ce8817d0cf3ca17d099ec20e75f11d32464c2480d2f63a53a22dbe47", + "0x42ddde6c79ae71e64ab091b24e3db68c0c3b560669aeda58107d07f61d9bd39d", + "0x6936a2002771717810dacc23da43097c7c1bf5c2619975f55132b5f450c03047", + "0x0dbc448620312bdf04e118caad4ce1fc5058d0c14b1bf655b650677a2d1eaaa6", + "0x108dc62f87065752fb77f6a3f00e9141e1fd170b9c0538124739bc75d5632b4b", + "0x9b555f75bbc6b9fa5ab1b63b5e7a4f6efc7e9c659a8829a69ec591b968133478", + "0x3f31b6d6e18c7afa96a95ba0855b52a2b0e3158d338ce3a20f14c14078abbeff", + "0x78940ccb7637be74bf6f1735c615054e632ce53410b77e9b1d9f256699a54861", + "0x71b5505cf3b75c328113ffdc94e8ef89b673838a26bee4bd7ce582049592e54a", + "0x68ecd3b26c50447e6483aa0adfd4187a4f99bd1b8517772a9b90f939b322687e", + "0x6c291cfad552325bb806ce314f066f3a7af0ccb5950fede839023b8140b3d06a", + "0xa32f442c4134ff4559c3411aafc87649ba6776f54e0148469b7538c243c19787", + "0x06ab81f6da34fadcc2d1b52982cfc69e20d9451801da18672dbbabe4abfb6983", + "0x8ad902710d008f2b7bf8dc50b66a11045c7e10f80be12f6c5e622c05ad48f2dc", + "0xb85a2abe729f4f7bfebc6a7eddf085c99992d6af700f487a9a2a64164dd14abe", + "0x11039611b2f406125519fa4d3f1cc7f4a89a284be02f0d23971b2990883b4b1b", + "0x69e21960b1ed6da34778848a92b200c8275ec8ae1763e07b8edab481cbd5c1cb", + "0xab4a7ffbe54a07e8b1af0eccdd1fda88d72a25d61bf6b12c9f5022afae936fc1", + "0x8d8fef9f7b0df3e2cbe6cd99ae3ec231c3bf7a583028c0f6accc38d2ac294019", + "0xf8c75352c289c74a797e8673193c505600611433730e415ed877087cad99d3fd", + "0x28b756fe2c8e5c6cfb5df29e8c4f3a9ae149c9d7408efc31c57e5164e9333da1", + "0x3912bfa54cdcb8e6eb1900d7b8d464fab0aa97593b9795802d8a084d66d82288", + "0x0db191d64e9a75039a2fe0817308692f3a163bcd1cd6b476fb5e04cdc8af7808", + "0x7df00cf34abc055979b1dd70e38b364f0b1f9b6ca8a2cdaa8e72dc1c30bf5471", + "0xc4ebe3625665babdf6b8862da0ab84be8fd7b5c1e4849e9c0c2277df99c1ce4e", + "0xd6b86c60afd43553bced67a5e202b5dfdd62e668359eb25e29c4768328136fb8", + "0x46be2d0335c8157496ce74edc96bba09b3873acbe46c285c54e6985615519fb7", + "0x876940ef8cbf54dfda6ffe0d469ac0fc9adb375fdfeaafe3da8345a9db0c964d", + "0xde7c02533643f05dcefdefa9c7cce1f0583a655fa2a9b4a5040ba6a7489c650e", + "0xdfb9bea572e6a60edf6406a5e87ef3fe60f5e5884ff2fdbd9ab5ccc7f0bc602b", + "0x56b30ee04caa1d1e8367f58855c361b43c2c17361e5b242e3b6dc1e53778df5e", + "0x5da53224eafabe23f1a5637ae74cac54adffca2f18fb4a2f506a617370f06378", + "0xe1f7ba27cc89f68862c9cdefcebd4b63419d01e6cc49122f7e6187912f3298df", + "0x67d0b1d84379e0f67466a6ea295a94cd55ed67392e51a6012994218be921d805", + "0x9db5e16e54e0f9310e578d5dc943a5e45ef5b3f5e66bf758d99eb8a7528d2013", + "0x4e0b154a0b06d6544950634de6bbdf511735226649bd694b4194c43aa7e89bc6", + "0x8146ae0e77da83a036ed8b78046f204defbc771ae61bff4016cda3ccb6597cc2", + "0x00cd2da8855d464a368ccbd92907baef0fd0fe2aa8c24e48e4bb6854a011d746", + "0x261fe32ea2985be3ac260b68aea223c4b8e4db240e5fb182490407a062acea5d", + "0x65eee7ac2b1b90a0f5a4e0950b2a0f3a9b32e0928aad7f4243d4bea2f056641a", + "0x7d9e7db3a97919ff2204736eb3920587d8fdbdc97d91f14049f1d41a1eeb78d7", + "0x9c2edb4a5bb85fe484094b0e033cd7d31408a2e2d4b801a001f6f886b92e73ef", + "0x1e191b4674a3a80e09b68efe4c4dd4f38d344ac0b42a1fa152aa1242a5b53e1d", + "0xf498295a3d4e3b72ae1a11fc1d1f031cdcb68aed705be3fd698b5b92bcdc8cf3", + "0xcc89f9c163149bc17d5b0a1d79bf5538a86c4aaa3374e202a7b41cd4a562c6e1", + "0x11b5219b9b2daa6832f206bba106c64a2b9c3aba39f7dbad1feaefd788c9ee42", + "0xd936254f54f45c34c79c8a1ded63133c9437e82c99a26a8bf3efb95ad9b5cf54", + "0x8e8b502743a0ea7075c89a88bd149b8f97846dd915918ab8cb21c7b7b710a4da", + "0xdf0e67381564465619d90165d5677c19a396674d832530c18cef2a348f9671bf", + "0x6481f7abc12e1a5655b0c88a693ecbbe5ab2685c776eb5a9a3485167eeaf95c2", + "0xe9ebad32fa87a2a77c82a6d276a18b0efd6f615361f0d6e72c0a037b35bb396a", + "0x3e052b0aed9cee87f4d70626837c1a49ec169b2e8e03c37fc5616bb0573fe35a", + "0x15245833a84147b5df07f999c6baf27655bda682a5a4db93879f41a2ea023f31", + "0x4820d25f27aec110817a81bea0d7b9bedeeb8d9af55ace79de81380093a02176", + "0x4e156aedc00095dfff29092326b02fe2863a6aba3ebf8add79485096f20267ff", + "0x3b63cf9b1decf710ac331a5db829a5fd2eb0a7da6724c0a90b9525334092d6e9", + "0xb54145d2b41dd0142f5d2487b0db7fa96f42621c08d63edc036dee4b072eda08", + "0x8084c6690651740db4e67dbb0623b5d1342cec0ce95b6349058d7051fbf186c9", + "0x9c6b1c3b15784111ae80cdf7398e1283f4d68a9c2a6a2cd95b8594e0acee752d", + "0x71322541265c9b5d5404e9f089e505ef1814fcad641a81ba3e1bec009abcb920", + "0x1e028666b6fe44f8c8b2c9f3fa8c8ae5f062a7e117d79d661446fcb8a72b5db7", + "0x3a6cd5395b4be2aa1ee4f7d24d1d1433f46db1307c7ae823803ca1df7843ac6c", + "0x64b8b040c6c0cc2ebb2f011039dcb091d4c8f4d338b82fc1a68235c6eeb8c8a1", + "0x89f98b1f7e78b539f83d45c5ce8cb455e8ad7686f42d39f9c195d37ee9cf5fe4", + "0x14abc82071dae6f563f272da9e1ba7f9ac6f0547544cf9cdec088ac6283eb464", + "0x6aa6490aa64733dab57d954b9907f421c6c571ab2b2cebbd833d59d74ba19be3", + "0x62e4524b07b9b8d8a53cd29e457a58dd9f940141797f847b889023c22330db0d", + "0x534a4c4ffd28cc8c3f9823826644138c9207255958f3dac5d0a5f279d57508d5", + "0x3e7f74f25707ae6686334c585603253a21764cc1adc730353c02a56f6b7f3e81", + "0x59cc225b1c9cee2ece86b3093a8bf6ad3ae0260ee760384f1299b5af75eaa1ff", + "0x15ee9a6c566674f1f7742d1e07015fcd66e22d7648ba25be50428006efccd026", + "0xc0668ec3f88e6a9f1097050e999f0082e9a39ba43fccb194790e51a41602e704", + "0x03b0cdd4ca4ca3d8b1270eb9b73dd28f22ce5681c3e0dd5d11107719d2614de5", + "0xffad54056c851b02f83948e7d665980f623643ef40aebe91936c3bf0d24a3a2e", + "0xdd587650149a81f7a5e92739c18af1216bf32ff2cd7b1c908a6d3100c052b0b0", + "0x1fb346da4fa3c0b7d1acf87e4e8b9c0b05cf41d21794d9db58b14e321f9b6bbb", + "0xc15a230b3105e4c549291228b28a3ded073e7061f56bd31a8bbe4570e2e11910", + "0x9c01dbeda0dd9cfb4e70e8b63551c590edf5be26c879d319781154c44520aba9", + "0x8b418cd11db8823868c9495d213b9e5c5e0d8b25d5f7c262f21b3d2b9f591ea2", + "0xff7cbadcb60f8e9574e1a1ca57c0cf1b5b26725a7683a870b581734ce906df73", + "0x0efe88c68a8404cf9e1cee6d4b863c48ba502c5b5f504dd8a6f251122138e651", + "0x87994dbe88b7749a347e438c76273ba5a7b8835449d32ba75bbc877979e5a3b8", + "0x366779f7f70fc10da80427ba5f0f6af0e1b5d60c37c0c7e524e408a1e2f261eb", + "0x616c1a9eeb13a026372b099a101eece0cf0d1715dddf192147d401c722b6a6f8", + "0xb35494e9758f3bd7bb23fdd9c86f60a8bc73e3422cc9be80c7f592fbcef26b9e", + "0xbfcf52fcbd301f4b5d32e62f284f95d01bc545e16f806ab64038d11be74f8638", + "0x3f155939a40b556e30ccc4b32273a3586fd5aa89c4209337da1ecf145416c6f6", + "0xc23227be04320beca30ce9ee2b9f74bc8802414ee78754d7af1bc887e1e260f0", + "0xbc45e7b6bab510e72479ed0a675a05217244a9879be26d24780a39537c233f10", + "0xf651ff7ae3c7570a95245216c9461fbf90293a3962f8883d502a92277f0e4ecc", + "0x92b1b6ba3f6bb8a949225e51a480dd63152147e98d96ff5aca2ddc81eadac6c5", + "0x368b2b21a1411fd2d651c12cba2f2c3d4d9dee020e98a63aeea861e4b6837e12", + "0xe52565a7d159275cbe9e024130faeec3ddc3c3e27507d35d92565c8a56e13c64", + "0x3252703f9e4b7ba715810126ba57d87bf585fbec8e5928aa598c577f11daf792", + "0x6283fbe3a436d7860c0b564f2c7a32814c189093c775a8d800ae24160dd3e72e", + "0xe76378b3adf8f756728c553a5d822afa016d8117cb04a24b1c2a1eadd62421a3", + "0xc0a2504fcbb69d1adce70da836a73fe8e8fd74aa7aa4cb7d22bf844e7b91aa89", + "0x4d3e70bd5f122962b3cf64de57c69d85194126d71e79c964fc4397afe252da25", + "0x7efda1eb1564ba1d295eb6d403d9900b3336f081f2bb6de2c375889883f64097", + "0x6bdce19bc957c2bfc7e49f91d436367374847fdc6daae2e621f00aa024f78094", + "0xf42d152632eb0a55173ce7ce4cca3a91c7d7971a7456eb6ffe88dea54c3182df", + "0xa6a2353ab4a3bda46687cfd3ec8e349f2ed61e449875b9d1580d9a2370ccd54d", + "0x3aa4b80ff21dc79fac0b4f913d46687c4f991e5005fa6af731c9b2d10dad9c81", + "0x7d1022dc5a7fad9c0291448c56eb99283e1e64c37f6a55431843644102959d6b", + "0xa918366830e62330c423ce2f03f99206f6f3c1bf7660e01fafdddc40c8a0b650", + "0xace8ee8ad7fb40d481f20b165ac8012f3ff69f0bd8fd3ee290d894236549d065", + "0xb03858a13f584d7128989a47ae71d945dd67a3c2f54ecb3368ab76371d944c6d", + "0x56c78acc4c4dab9994018a969c3d3451300f8229d018f6af2de91fa4da6d4230", + "0xfb4313d83488e1003d38869fd8e8788d7e74c124542774ad7fa75971bdc61131", + "0x1decf505cb4473ffb91dc428710d2a2188d57bbcca71b7b5e277eaba0c7252cd", + "0x9db499b44cf0bd96713ec99cc769c8454fba3729014d87b67c18b55f0b4b9fc0", + "0x3cc717a489465b21a09c3fa19453d2a8cddb914b7d2789c21db6c311386e0f80", + "0xce4868287d923f8b22aca7a1df1ee11685d7c50c6384994ded2e99fcd2c01906", + "0x06b502cc70d1ae3c79e44a421b6ffb9a1a6f0bc647b4421cb375ab5d8474c713", + "0x4803b5e78af29ff140e37b23bd2f3de9fa6cda3a1bea2361e838061490708d0f", + "0x874051f592d34ea3684460f094a78d0e1be3bcf49586b1467be0386f1f9e3d94", + "0x8b66caf3a57d9998e2d88b0e4ff296825b6dbafbded01e384fd87bf4a92c5bbb", + "0x61f6244709692f492cf345586212374f4b209f1d2f92d3ba0e4000ad0634bda2", + "0xc58788c015dda34717586db2395a654f49ef0bfb4642459cc0ac5a5d74a2fb67", + "0x5161b49a84d5c614d72bb3e220878afa94d9acd30cdeef78873dcd91233de390", + "0x5e358365657197bab7481eab0dfbf8a6d66eec8dc62aa345c5364f75c07b8675", + "0xb358c9e7d218bdbb42f91752d03365945a474d49e84dbb15982e368def01cffc", + "0x908bf24327cfa0001d13fb5a0a73b536132e7ecf66d47f2c77215b03bb5b1693", + "0xb041e9e1a1087afbf41d87aa9e56195cc548527c81023d43416720c025b896ef", + "0x48ff5fcf252fa38a00aaf887e108928755932f45d7cef5a8fa0b72d711789f66", + "0x16f99b5d528b9ea7a92e5f7ac59e60d4305b71c9b20485c7911f84e3ddd1802a", + "0xeadc395d16b240b8412e14d5065a33847fcf8ae122d22f24438d7f79d8cfc40f", + "0x560faaf4e0471cfe39aafa10c9660d61c8489d2c5d49eff2a8e62ab31b7ec08d", + "0xf1c8bac46e0764d0faf89556b0080cc7b16433070e1e945e83f1ae36595da7fe", + "0xcb7409cbd3d3104a4b5d856887fe6d390643b4c433de855644f2184218631662", + "0x6eec345c4baf4e699f0ea48bdf54b2e74f98020395759e275e7cda0138424ab0", + "0x48a8bb061ad00561541b4e19009d3e8c2e2b9064337ef431fde45fb2988136c3", + "0x458b21c6ca362ec731487499486c4c0ea69905c8f36617810009edac608b9e20", + "0xb338584ad517b679ea52ea9abfc8d786ce1eb55cd3f221782de658f75b23ed47", + "0xdfe64bd8632a87d995972376311f78a0fd390fd2635e002e3dcd7838a3b28516", + "0x49d9ca4420847c21e2969911b7b5f321fbdac5037d0d8644d6f357444f91238f", + "0xd654571d72fc11d7a86ed2408cd1f78e8009dcd117323c8970614ed8731d66d4", + "0x2133c8e084efa57df6e1b4f1af5515a4662809d722ec002676eaa99987a2607d", + "0x5bc530b5fae32bc84127fbe7feb7eb07432313915e2d579a668f46fdbe46bd1d", + "0x8070890263bff747db0122240249361f5aa66cf121c3b6c4ac40deff6e42af5a", + "0xecd7aef2e4b4419539fa40570a61a967a0f296f524c25de9cdbb012b03d8d837", + "0x4376d56fa5e09c64156c6d1371151a33f7ac1e46635afb37823ed75287083bf1", + "0x50d32b39873466597d5fd29a2bc3596f54051d064559c46510f643f2c24e6319", + "0xc44c4284e5cb873846761cd012e0d221763c972242c0c4a161f3fe0e2da74026", + "0x141d2894e4cebe94df908cf463d5aa6a95e22624f5183d03cb60011c0677eaab", + "0x1bb68700d0f6e052ca64c983352731ccb0c3947ec73d67ecbbcb72c5ae3791e5", + "0x73095bc9acdbad7044390e72ae6c471c8636dc0116e2ec322198bc080af7fb11", + "0x66bbec6ab32528486c3ad89c36fe750d9c6e5bec862ea683988ba578302db503", + "0x979820d20c32a076297e3a940ef4b9f3ef02c9ed551996fa106b6db778852e52", + "0x4da1d4babd26763bb29976f0f2c439d3cdc06089951d0eeab7df2da59c128454", + "0x4c70dd6d755e7fe3da5f94dd2af53d037bda9d7b1eabb68bdb75111ecd190e04", + "0x87ff13d01ebf46a5a45f5b29e7026117e8b41d135829457d80918dc00a325f0b", + "0x78d573b16ad8a3c3b0a704a01fa79915907fbddeaca6c7e189c5c586855ea882", + "0x95b9c87ed9b7365b1ac15b02a388d47f75ae8036bf658850ebbd8b829ded9186", + "0x812fb8d5c2d962725245a182d0d267fbf97358d5c236cfece3fb398fe641f78b", + "0x31db1fe9db91df6684660f1eed0928bbdac477bd1bd376399e27a53ce760ffd8", + "0x4bb0cc2765ae336b21fd1f983f21464e907c6fa4831b047386f64e021550b2e7", + "0x7f6317d849a40784edf0d2c7b32f57569e561efcb4fb3c5f857b30319a93e2e6", + "0x5921a9e8ccdb11e574a012cafcb05a6dcf86ff8006595837fce805675202b8df", + "0x5357bc6834cde24334aa697f050c51c0456f7b03f938819baaf8c5be1dc10df5", + "0x8fb8b01b64eab496c9496179016adac0dae5ff6793970b3c307202fb17a93af1", + "0xd4ad4478bee0d5bb0852461107c3bef946f147f66a478789b39f7efb517b3bea", + "0x630bd6a0422ab626b28f205ec9bca83c499462556cd8116556bb40ad0cdf0e66", + "0xb2d07716e5e20312f314cde99480110794d3cf70ccc786828fa25ebf97ffdcad", + "0x87fc5c3371e3ed8f9201f61768fb2683bdadf8c3f6a3039c3504107b07b508d0", + "0x9e67bf7118e42faff0aaf8aae3118867c692b27c35efcbfd057d562e8d4390d9", + "0xd96833f813ac20074274531949bce0637e06636b6ee8b875b4811f09cbc8c116", + "0x4e9f29f98bee2fdb5c5692d94bad8f87b6b2904258549a937603da0ab5d36b65", + "0x77c3b0bee822bab79529cbe96d6847649d9528399a488ba9e94484f7059c46c4", + "0x948d3eca01db52a52679fbc33ca30aceb7e3ff6449463a2748fad0982b75313b", + "0xb3084fdf4a2ea5228c35adb20017039f4ef01e97d99aae08d4adf591b96330c0", + "0x5bfb4369df41aa75c957c1fffd6b498be3e7ae858cd53f67c1c688b9c78afc4e", + "0x6a2092f54cfb6c26b0d5c8f559e5e9995c79873db7631a8f6397ef5ef815352c", + "0xb286ce1787331698f1f860e1232f6766a658d27390b7623d460136a6be90a444", + "0xf84ba9ae60fe7bae5d3eb5be6c6b85aa564f8d0a7ffc479d4b0d1c8bd69a2adf", + "0x467550339dad58cba021e3fe967bd5d81be04e6670488adfcfeeb0dab07d6b2f", + "0x5150476eb3075df5b6ab3fb54ded34ce76e06660ee401951652e484e9a3fbd62", + "0x80845f54e9c21ee96f4aebacad6d199416a6b30fd741d6e6c9966f58c54f1364", + "0x8264045a020782a7dfc047efdfaa103bc186e88c920f2c25a016911fcf33fa2c", + "0x52399e942b721929b9875c274ec6b5034c26f7749f6d26eddd99972370dad3ca", + "0xf03d8bd2bdb8ea0b6ae2e7bb55703520cff714143501f291a3e7199be5d466a8", + "0x40eed1aa25f1a87c849f5e02f846c991e7473af9fa0985e3d61bdee01cf0a5b8", + "0x3d18c888cc8729f63ee415348121e10b5d990c8f091fccce7e2d8f5c0132a20a", + "0x2e72d969de06d28196506263e6dba8310b6854b5069fdf94317a6d3e90752560", + "0x2bf249dd628dec9d4cb267a9013e050f0710daa2915e468a623748dde1a036e1", + "0x91c578ed45a55d0108656d1533d209de851f77d9abdb58265bf867d7aeeac5e9", + "0x88dabe83eea11db59d67db99a159c623498cbc648c79d829a317719b836540bf", + "0x5fac0c3efa49004a1af631263097978f16f7e6710ee7a1557432aa727e44e09d", + "0xa8506487d3c54e70b3d6e83eb72af7858f583527ba6f6a6aee6a3eb33750e538", + "0x62641830df38adc76a043baad1fbbdd8e49356c11b6565ae0b04429743011b08", + "0xf053195e1bc2db0d0451ab69471520d0a03370a8f27a4f62a1885702a36d583d", + "0x7197d7a7897505dde22c7a518054d9df7f3368fcbd109cb596872d92f6a86fcf", + "0xa5092fedfd64b4985e70ffbcd7b4522eb45f9bcabe4c478b1f1452b063d6d551", + "0x027251c22748451514c27aed0f091e7589600bdfe816ffb0a5ba99d55265b65e", + "0x590271f52852c220ae38b56cca9960a1fb94d5343a0090bfeca5e8b5bf82b2c5", + "0xf8df310ab62fd52c452122deb0f2e79bfb85bbcd0bcba7e6aa5a99a541233431", + "0x5d313f0071f2d885da1b1b5d104b8d78ae49842ff9a636ad2613ad9e90b4ea52", + "0x2672988155e5c27a3af3ae26e74d164d9f52b4c71b74905ae90466113e991692", + "0x330c8cb081da0372f6dded08c0036199e11aa8ab51f6f9869995cecd3eb16f24", + "0xd65721d9678bf4667c6688af76d2dba106fc51e8396b0af78bcc80bf4149629a", + "0xf5019f4da39e5ca6102679e5a0388a3850eae7bcd91c632d26515caef12c472f", + "0xe9c747dfd6af4dc29b5836495be42673a20bb2475264a2f9bed00eb8250fea7f", + "0x2486ab886ced7bbdd774371aa0ed1c177d6d187bda235a4a8fa390b704eeee8e", + "0xa91824527f5a40050aafe359817594b43cfddbe3977113207a7d5868507caa19", + "0xd44591357b62e80b8f5606eebd4cac5052efddfc3e6a8c5689660d6617f93b33", + "0xfe5628e6d9dc75f413cb12ee1004e1514769ad7085b5434f762e93db9115b78e", + "0xd0393986e30a8961e01ede613787fd2e6fab42db329d0e57bfd16b42cacc4045", + "0xbe40cc6ffd2d51f7658f48359d4b726c64a354a9d1becf189ed83775f8fb4086", + "0x1d06de0ea61fd233ed701c9520f18012143277ca9b379d39db62fcd0a4e7681c", + "0x463ffe1d54544945f4abd7e35cb7c90a4a809c25e1919215207b7d2a8d3b4fe9", + "0xdf128c4d6c4048d4fb0f7db6db091ce4de10d509c45736f5521ebc4ac93a7ddc", + "0x5ed827eae4b7e95cac552d60b60fa209157f1a8c6e3611c1a5f6f7a49e8a6a92", + "0xd7fd28964beb50a410de115f290a0140fbc78d0d4c47ba02afe9f47d80df5e53", + "0x1996f9b8f7efa3d860233141774f46c00b63f207219c2eac5e61318a9464d7a7", + "0x4cfccfc8a9623fc9b5ab38c991999f8a52c6537d984ecbb0c490ff37559cc51b", + "0x4aeec05c7d47781008273281bd01b36c5ce21916cf7fc9dbf79aa2c477923c1f", + "0x96cb38c2449f97c92c81f5f4317b15267c9c2f4ab62240885280ced5f54bbc53", + "0xab5e6b9e4c4a27aa725183699ae30a6f8bc8148bfe85d1e4d0bb8565502e6e73", + "0x23fcdee9cd75706e640aa55c4e8acccd7ba9591e724bf351a7070104cdc698bf", + "0x5f3433fb2aff1e3843785b2f2cba22811cac84061803a2c5fd045b1983c8ba81", + "0x5613366fa3c323b091a44d10ffdfb1f485160fb45094cbd52707484f820cdae5", + "0xfc43bffcd36963706e2bac564dea4d593c35c5156de02eb747bc557988d628cb", + "0x4f23fab93388bc79a879f85c3efe0f15606828e6034cdc6b66810a90cdacb793", + "0x62ebc41d0592d1569001358ff3f1641c0a6ad89e66b0fd1e784f060c9101dee3", + "0x12bc43cf16c8965f106f3749bb6b5d9ff3936a205d2ef5719ee637308f81ea24", + "0xe991829e5d9c26cd365f6907de1fe2f2153cd88a7d7e8e56224c9dacce442fa8", + "0x55679ce947be929966abf9953031fd172480b7da8be0b34344512406d93764ac", + "0xae1f80cf386c6cbdd1ee0a1241e738c245eb12665f2fd1a614391ba54c741847", + "0xad12a941df30e25584f19f5aa65069d919a2e0dcbcce73de8724f975abdceef9", + "0xb3478980a68ed409b58d35759d4648ce21ed97758a1eaa0d0f1ce6b059b6da41", + "0xbec5fc3e9184d2e46bf0ae39c408a7cc243a41b69a923fb2d1224638153b3ce0", + "0xec95c1df965aef7e6061a770e0c82b6dab0027dccca5ea3791ed207b868098ed", + "0x2bd64bac83283cbb0bb5f7c1d461261a089a40904574e2daaee97110425092cd", + "0xeed53a58f04a07af388b098bb8c1e49abab852736c84d69bcbb78b945f23b86e", + "0x2c2c81b8a0c362105ccd0251119ddb406b65562611b2c3b3fb9825dba0cf6ac7", + "0x91c93ff5548a0462f1cc7cdf0a5c57dfc1f21932dee38e25759c9e5719036fbe", + "0xbb1c1bea058893b30e38cf0ea2f53b943fd6bcafb86b0eb647ccd152aa42dad8", + "0x079da567e28f61687250a49aa9fca4c465245cb0ce02ff075b500b203c459605", + "0x691de81b04aab67b3276168be7dc43e220114005a4d66a1ce9ef2665cd2bc867", + "0x3deccfb1fdf3e57aa2d63d0692cb37f375aa457da52d88cc9cf277c32021bf45", + "0x6cd1a84bb6976f2599898aa46fc67627663738cdeeb815ef1f45762cbb14dae5", + "0x29c96ea5d11a5a761ff7c64b24a0892daeed506b8f7ab33e93d6eb6023b9b37c", + "0x0bd8890f06cc6187a1d1a029cb319df75018b067bf796591b0b0a07a2c33c008", + "0x6a3d0b949241a493d2eab974adb173daee1e3c791c2dce6bfe59b127f8557ba8", + "0xd102ccc0476081c8d399083930dfa59486a51f83d33096ce77897b9b0fe41b1b", + "0xf9ddd66ee324bc7f06544cd53f792dba6697c1ecfd4c40a44733944f7e7ebc91", + "0xc14b245a2f2d02ecb944acb218d76e311659cfabcf72f9eb49db59541550b6d9", + "0x190781209df0cb64a4ed6ceb15428699e6b67f3cff28b7a987988a8e29829171", + "0x46605aba1cbee0bfdf90b57e320823ad4607d9ea1d6698005820021128c472b0", + "0xfac04645717514b9ec56f85cf0e6cae5aab46e25e69e3cd010513d9598d56609", + "0xfd0c9f959513a72149bfa23b32c5006ea766ba2e41edd47f450090568d44cef6", + "0xf0560a14936e66cced54d4002599808b127f9e56260f04f144fe9da412577c61", + "0xc9448c9e8a3b09fd51ee93b77feecb8a8ba03e1781a3f5bccc93b4d1815232fd", + "0x3c41d49f2aa53e90f5fed6f372c620fff5a80f442894c71bd7b6c2f55ed76f47", + "0x0d9517fddbd945294c72ed49bf6bcbd88d84c9b3b2e257c05f64bb69c4d7815f", + "0x1a67fe64cb906429f47250e1a30858366e0204c3f39b7d4b3f121a46a51566a4", + "0x9833e385110465d72ab133f02348cb33433f38454f6e985b022720a9836e5015", + "0x89f653efbe7bdc469e2896aedb2a22ce5982b919a7c6dd14046db4eee3950b6d", + "0xe92427a7878630f65cd4f38dcee4c5d87ea0dc3d0ba1720c0d9f53cd84411b7f", + "0x1f692c127e4d0e37f55f24f5c20516c804dad968b5dfcfa000595b4682aabab6", + "0xa3557041302da75734accb2e95db335abb208626e1b9d20a54ec0e0d23a5e003", + "0x96bfe30b54d1f39b5693272ec7cea523e0531cb7fb805e69a820888ea747b3ba", + "0xca8f5d8fdd17be423ad5bf84d7f591466137a54388b65f5d853aa83ef25e9b42", + "0xafd729d01c437b299b29da02e34eef0b8a762a24447b96c0499231a17a84fe7b", + "0xf95f528a8abcdc0eeb66250fc3d1df11d0831a08b30d11f0f6f0f96b02f7ef82", + "0x483de90f340fd0035676305359fb8c83b709374676796c86c4d4b615ac779b5e", + "0x433f6ce08d28351388ef6310847d7949f4e92ec99d585c3cbb5fd7152baa507f", + "0x77dc56a6b802ffae812c3e4d8768fc3d80bf96b95a55b1b9736a9073ed0093ab", + "0x5c3c2bfb8cda1218a08084c4645e2a84fde3aad03ce00c3310b3ae5d80e25be2", + "0x3321f6475c8ed111a1373bdeb68609f52c4740f22e4f13952e8a6d98fbfae542", + "0x7a0c172b717acba8a7b874e6c88257cfe68d41855506ee909d84d23b028a7ffb", + "0x7ae3757e9cb71b9063d79db76109af96ff1a5e6aa1183b1b70150757243a94e1", + "0x4ce794f4c0c9273c14e6faa680e8837247c6a0ab503a82432f69529d4f5530b0", + "0x8a0ff3d87111ac19f2d95d813e384a96dae3cb15caf12e50b99816393db3a374", + "0x35adc4577b9532f5e821d6a39029cb898886ec9a8b938bde92ccb1df67d2dc2c", + "0x84976050b7ccc3c953976162a6406d125edae798bc1bf850b8867b3242076a30", + "0xa64d9c9681b1192185c9570a6512d8b21483534bf0ca7f457acc96f91070358d", + "0xb27f0ed2428dde6c5506770651e3cab0fc62b71be0f245a8f6a84c326ebdf327", + "0x4f71b19b200ccaf3d359eee3ad5d7c155616b86495a43e2a7c18d0740304aa2a", + "0xf22988f8c5443f4400af9895f655a84b31e871a68e74a396ea5334297c0fa190", + "0x37dbed2e2f7408ce439ab0ab09af040972021ecd606f517af45c195a80e3f3f6", + "0x5165c41b008baa5fdd010a9a17f0c2fae2a0f16b4d230c21bdcfc737e9279c23", + "0x96ebfdbfbc02fbf12acdf622ad7ffb8dc10299ee66c4ca956eacebc6073fad75", + "0x47ff8c523b69bd123ebc4ee8a81240f2bc1c4e8dafcf9b9cb5db5b7a8f4c884c", + "0xcc3a09c1108d216199d7b3412f86d73d4fa7585c393dd3ed95ef0320f0f9bba6", + "0xa79133fa77c790f4f12a9bebaf21531c831c72db93e4a36a8f2ea672260d74a6", + "0xfaaa6544245fbf22f3016befbd4acf93135e64f69a7aeab07599af3a52f6323a", + "0xf489992872d1dddbba3c6b2fee1eed0f604f02e7350d747398944bcf4fac3171", + "0xb49c4387382e339ed00cba9469275920e116ea556bbefeecfc9c154d2f1c1f77", + "0xfff493a58d86d6160d9bdaf60504b07d6f33412fee522af09c1a7de8ec9fcb05", + "0x584d1e0a2569cff0fc1b71c850eee0c1f680037cbb678bbaff035c49ea5a6275", + "0x91682c3606944042c10a5fed5e6b5662c39cf980471b8bc603042cf0d455842c", + "0xb979f301dc2bed6c7e60bafb112b92b22b5f173f1d9e8fd665415bace1a580e0", + "0x71d439075aede2a781f1a872dcb8c89846056f5317be5df5dbf47904d106938b", + "0x9c2353de49861c4d10309f99457e6f6d9e5b7a57360837aaf0a1942c0440fe9a", + "0xc2c08c3e2d8741a4b4bb180fee1b1d0cb54f87f2739aa3881d534a9c73fd2d1d", + "0xcd75923a659ed6e79c9a1e22201374bada6bb2e030e3664763dda54552bddb15", + "0x60749dd09da7517a03cf6baa9b4623198f4209f1274c00bfb234c61d467da12d", + "0x11b1893d89913c9c57f32ab875ed403fd9802475e3c861472dab770d4882192c", + "0x26ddfbfde82876e17d6872f31aca7f233f790b3ec0618d6b5c51871c9700039f", + "0x8c9ceba1e4cc81ee6103acda0bceebf5b0413023966dd5c3c5641453c96c29b4", + "0xf30e9e6f8456fb427f96f356eac399fbee64dee3ec4a2806701c3484608c0edb", + "0x7773f80e3cadcae69cabda956228cac8cf774bfa84e2ce92ab2872ed19946858", + "0x4d510670cd4036f534fda9c7b4ddc14aba28ac985b90a0bc831483621d44996b", + "0x4e7d6a0fef6ac54f4f0336961561398600d0c6a04862f613ed6eb648d45bd348", + "0x55c0bb04ee6e1aa15ae55e1de229ab5a4b553864c43cf527f2ee42d441bb0bd6", + "0x92a9c4000171a6534d7546749d7392a9a18974be969bd773b4ff3f5c39c91a17", + "0x892daebee1b6c833ad425d5606ac7562c135688ba8e83178c0f8438679e84e7f", + "0xfb1438e6e00a88a26dc46bdb1ff1696cfac94bebd02f16891c08b52de7accd84", + "0x46404590a94fdd59cdd4ce607c1ba016a78be8bfd8dac361b8cccf6191aa0bdb", + "0xc1a63495f12681da588396c2d30096cdc8c52fafbc0bb0d6f11de5ee2c5a7c51", + "0x86ce595e0805026d106024d9d13e0fca7b208155901b67cb0011138b31bd947d", + "0x7bd81277da5da97359e67e2d5c12cb238daa009f4220166e13ba1f067125888e", + "0x2dbf4b23c2178c8dea6066d43b5f1285894d9e74a8b1056d0ee02091b84dee50", + "0xe983e1211c5b12ccb547dffe850e4adff01eadbb6717adb150248900332482ae", + "0x2f42bd119e06fde6cf7e95c59caeb189afcec85ee9968196f7a15917f98962c9", + "0x1e54e7e17e28b7c2de1c8391684a938e1adc2011fdf8f4a6da900f3664f2f25a", + "0x657e31fe41599356929abc24f7d751e49aa769ef9a4b9d5b37e6bf019dd567a7", + "0x33de4f2776dcd8b17b846816e02c4dd1694891b6827f87a80b31ed37ac0c6048", + "0x2b3b692269fd869b7797c78de9a521705aa223d78652dfbb32c1b8b612bc4351", + "0xa57d205b64565acb103e962a83d300a302efdcd96a13f4c79e80e2733341a70c", + "0xbcdcd2d22c7e21d24e48d28c43d09186a15568feaa24f44f126e5bb96ffbde99", + "0x3a6de68513eb363878604d054f46224e8567f2654cbcc0d9f81fd37fda804a65", + "0xb762285a5d8172a6df584ed15e954f432ddd8f41ca342db7d1d14c54af21e420", + "0x97702988d087056b85f9046bb8d3e37365f4e5811507c1e2daf544af76f1825b", + "0x8d1dbce8efa6eeb4269e22b45c2a9e7c53f7ecafb83e8219b14d43f66b6fa68b", + "0x54a2b87cc430e350eba1271a9161fd08157e196a4d4a7ea29a7461dfab6370a1", + "0x253d68032f383891fbf9c1898fe7d41c6362ebf759b3e3216bc14bad63250181", + "0x175102f1ccd3712675505c3d74609f2c46053c2501998a91b69b2eac9e1e476b", + "0xb07dfe916a1c61b07571327de80a478aeccd3f6f26aa4ecd7081a5f16556e946", + "0x0c87d079935642a1d3673d9b41ed2d3da33ef124acc081e236b23c50d78ac968", + "0x0f3718936f3be6ac78445fe56dc92e4806032d67e014cbe0a92e3193999c8acf", + "0x88bc8add9c916ec21c2f83e398bee626533eb038900c787eed34cdc1ef273a2c", + "0xccd4eebce003d0415c0ecf2d40916651b5f336e5ac64652b69a2ef653d777995", + "0xb9bbc12a4b92aad64875c00d7536c7dee7d62b87813b99a9a77bdc066c169a89", + "0x9ec43027a7229ab550391eb6dfd0cd5cc9b3b103eeb0b79dc9d2f4d8ce3c0aa3", + "0xb4e8c06e7424fdeee2f241365828d9a407f117a0811cced5ac35dbe9abe70a81", + "0xa5a9149f1002457f7c9c3dc2a4aebf7d5453f20c1d7e3a3a732ae92b04b8c00a", + "0x28d20d654b1e7a024956a6c8f53bd1c097d1df3a6de91036092c88c8070474f4", + "0xa11eebe47ce50f4076209307fd58c75b0ff725469ea0875c658119f7abc644de", + "0xfff2020661ecfbb50cd6263686f903127b9d1e5f43dd8bd2d5ecb09eccf6090c", + "0x253576932466ee619cbd3f012915380f1e7a79972864fa0e98a755f902f1199c", + "0x554258855ef348fa770e3af434da722350e998e930f234b5b8c33d3d2f806595", + "0xad11b76ad542ca1e825b251a6cf410b6f86c8c4b42b3c8690a2871e7cfb27882", + "0x3c3d7cddca90448af6119481e08b388df75389ac3c7dcc26ac532680b23ce2a3", + "0x94c4ede45ad5b27c5a6b051fca3b055d548e4c29d2541a9cb4c37bcfff4f19a2", + "0xabf8f7c1b9828d61e3aa72ded1ceeafd6ad539b79b5d56c5eb93c3327b9d83ee", + "0x6e2aa49e5942f19f19181ae911e7951534aec1a7fe295bbf921d8f28a4b7c0aa", + "0x0f49df5c80ca4ff33623bcab40e9ded6159d3f167f7754c3dfaa2eea0ccc368f", + "0x070b14922cfbdf78ead68019e520a08b987ad203db005f4085cd25e6ab587016", + "0x8501cdc568d6c64cef9b87e639d5a0e3f5a4b7d77e8510df07bf0fc50d89d020", + "0xacb70d4cd2010d149f382dbc0f7fc1b74f0fa6bfb5e770017fad960aeb7c80e8", + "0xf49878d3473b21f4ff2c331fe48074ba47ff78198f839dfc7d1d69abab81e499", + "0x9a11ca4ae2a7a68bfdbf54d7f0978150176aa4012ccb8d1781c10b58e01b851c", + "0x58729c03b10b2ec8b4abd91b876ab57a2c0bf05ff02218bae9765a90037562b3", + "0x3b5b033d76798ad041842b9ecbe223dbcfc2d5babdbe864480126dd932d29fa5", + "0xe08ce9149dae8cbc8968dbabbd97624f917148f26f45b858e49c2c389bb22f20", + "0x6b532db41ccc7cdd970d5cb0166dee2272346f23e0acfd8d751491d0c3ecaec0", + "0x99fbdf39928b3f855b2390bb845a96478221330b7c350e83e7b4dbf7a35e2685", + "0xd2a2a108c0a4dfe5ba0d0488da0de7f6d15994f6c14b511712dff4af33bbcf8d", + "0x75ddbc2ad15fc25c2ae71750f1d5bde5e825b40d29d631a27d8801590d5e1321", + "0x226995d806f5d03722266554109395921f63ba1f66f5ed1ece7341bd860a635f", + "0xf78d4178efcc128e86b2e1df767e59c76a4bc9db0ea294bec79b08448133568c", + "0x160e1fa8fde835d6e91187a3da5caee245d4d0b9ee30894170617b680d275166", + "0x361d71c972953283f8ddbab4a45a01b39f30290dc1dbf1b6b744af5afb2e70d0", + "0xb8394cc0d42a0b60ec40984f753b8eb5b9175022bc2ca7f80d64d26106ce86b5", + "0xa0f6ff5ee727a3106e045468b5ed9ee8ef387eb9a0355f2249a71441819b7bd8", + "0xf441bc00d94f06485368e043f933ec9f8e181b11ab0212d728d83e2d039edfb6", + "0x1da12d2213cd65f5fce71c06e44b40a487d5e676558e6f617372244f8e98d549", + "0x7d988011d5c7da97b37c6a6936aa499a70aee8b38f8ed60959f576c108c54d1a", + "0x3d5ff693e4ec163fecbfffc95024cdddc4d2c561297124bb69c8d6aad4ae85b9", + "0xf7db67de101d00409e1ce3430445fe3d38a073e1c81e1453d63f4228a51615ce", + "0x335a94506606e70ca259348ae7157066b55faf09a4ac11bcc34a0b865f4a8057", + "0x137d0de6cfa1e475f6d94248c1e30bc10c17b98d40829974ed4ccfd7de0ffec4", + "0x1d63a7c1c54bc740875f3b5d8750aa6bc85d1c10e3caa4c9d67b4b010a83c29a", + "0x04e0208220bd1218b6180dcdfada95b3a8391bb380b0b0ad5a1a8a02f1a3687b", + "0x02a3dbb2d221bb8e8be58e12982445246928b9965caee73383e54edadc017315", + "0x549dfa1efb8c32071dac220aa4c76ccc038cde6ec9a39e2745a2d55e92bc0890", + "0x1f9bec0a6b3415194528a23443c9904f578d57d7024ceb964ab09a9e8e3d9c03", + "0xbfb25a68c40fcc0dd996e992b18dc73a48525a323995a0eee03a0a04c572b68f", + "0x7244057fe32846105479bf704b871bd1a081acefc57b37aea76116442805a70d", + "0xe6a48159dc041cc9a0d8eb124aebcffad394a400724410e956f8f46e1d89e8b7", + "0x812d9147b6661f54af0c39c1f4de79588ad9cb62b25befd4334ef5f3ebbc2cff", + "0xf9aa945fe2eb3d1e2a01db68d4502a4f33afcfa967fc06944e035c582dbf383f", + "0x63a437b920c6b916eed44003b8d35872acbd0d1859b6596b4f45e39d04057e0c", + "0xffbaa46c582530498f30e51d18deb6973824b850d09bf4a4535699890a548eca", + "0x6ab7423011299d3a82d2037cfac752bc0e88a82696f6aead69ae940bf202792a", + "0x2fc6f5dbcccf16340f2b3a5e341e364c3cb1dbb3e899c7acd6e50e7ab333f45a", + "0xd354b48b2d3cf13487ac8138caca0740408b42613b50f056ea595741ba275d7c", + "0x8e1cbf4bb7a83b1e47f69c08f3fbb133bd36d8fbce923db79a248c21e9657f8e", + "0x414c7f4d86ecf78c3988723ab584ff735633a37267b1f5986d0c2e6375f878b8", + "0xe0b0dc519fccf20ef45b2b185d791575d88f93011bcf5205f4880f7ed755a54d", + "0x528a7ac7c6a17775d207a983b76ff54f8fbb84b8ceb3f6fbb60a80d9f306c497", + "0x458bfe441e32d15fd95a33de1665a94ff4f2a4c357f4fdef5c9e7c82013f59be", + "0xd478a55408477b3559d50bcc4b5c4cc2713e0666f40d87c5faa7328c5b7db489", + "0x9977a36db4a48e7e1f4029efc494a341b8eb2e40c73fa9ed3be2f16065df8900", + "0xe2cb22eaad423da374bbe1cfb8f4f353eab0f9874084aac4f42578525e26586c", + "0x0225069114efef02e188a1a35320d6522c115706c7b87b3b54805aeeb9e60db7", + "0xf82e17b405c2e19957b63706c0d7405e09be93b129ecf850e1941d62f1c309eb", + "0xe26f6f439b0d33f00a973b12f5d3c619bc4cae8662ba25173fa3398b8fa19d02", + "0xeec38666a51fc161736b7b48c8befc98cf9683975abb8432cf735edb907b05d7", + "0x8d8c5ec1f83108372f361b0679a65bc72f1b5055a3b9a12f01855a61437c9ebf", + "0xb53f85551f811c60b17b48df2125648aacef9a74af403cbd877c1e539c045ede", + "0x498d608f0ebf85809b9f5a9270e481d03f4e26cfa38600e50347b968cc05b13c", + "0x8e6d9c2693bb876101c2c0ced0976fe71db31b0a725fcccc88cf9a69b47cc9bd", + "0x5ac71d4859c028d90da98406f2c739ce6280cc227529ef8f1be3d3547ef84da0", + "0x5e72e33c2d66fb9b31bfd4d423aa1ae7d4aa88a30758e29610eaaee778ad75ef", + "0x97345508a573bf5036243f384e1584dea6a723ae342a876b572526cf992f956e", + "0xccb2773ad04c605e9b4a6dede3cc41d69f43439f19e4cd97f54de3a28052d0e6", + "0x0d48cd6317b72fcdd315a6f912646831ed52257ebeb03fa70576a918282e43ae", + "0x688754d57dc88205d6223c88e802461852c5f930252bf74e08b73a79e4f0ebd9", + "0x2860c5f26b4eb0896b4ce041582a8d38b1c8aa21b6c163784277df2658d7e191", + "0x35257fb9aa6c9e8ac16068786fda9c06ece1cb2219106da3216ef4648d28be29", + "0x1b81179c25932e14098aad725e59bcb8da8867dc4a5d145e90103beff868f2ca", + "0x60309b91add03a291fce9fc3f8804eeb993508d7cd5ec4c13a41d31b71d09997", + "0x04d2e5e78c8d8c0059d829c16ea7397834cff5914a5c0618e5904a9037338deb", + "0xd6d345d35827336d086eeb801e331fe77491d47f0df668234e05c3755e413e13", + "0x7f29ddcbfc971fa8ec8e73ed1e77301310e99f677c17320a62fa32ca225e3e97", + "0x036d5fdecca68a54be820fd086e1185312bc9d434b332db547d65d9fd0adc5d8", + "0x07d7ebf143ec977f4134d782bbb3da778b1add224fc3617987d9b21c7bf7d09c", + "0xf27fcee747ad3f1acfee97988403537b85f51ac1157aba723ace11945bcb5115", + "0x5cb6c6cf872823930abb5798d4f1db9d0ae200d21ca3716445fcfe675432cb68", + "0x8226cce1ff6639ac646ec09fd71a0de3d6ffd323df6ea24446dbae7eba66a69c", + "0x6e07367cd7df8d5e756e9e4c535f0933df76941640a7bee501f8af8b653543b0", + "0xa60f86078624b3c727784d4a95bd6dee72210c801e7cd0a4fb01a2ef5f7e24e5", + "0xe3ff30fa3e754fec8605305377cf6a3842d2cb323950db58e5bf02794135bb2a", + "0x74203c76eba1b90e3e76fd493f66fe46130e13359547ce4c94919e9c8909ddec", + "0x4ad657902a564df2f15d7fcad6e4171c96c65798d8b49d3976c7d77869c06ab9", + "0x043cf965b0b5b2dae096d8c73190ad9b834b665097e6b77212359c5029fe8f1a", + "0xb370bc64167f8c6be57238f35a56b840688138e860b08c2c8694401ca32d22ad", + "0x1c242203268f4d543b7087b0b4506f4b5e5e6fa4f4b495c6bd15f94c7ccad31b", + "0x1250c4ef1fd54888a4e377127c9f27889fc5bae3455010733e8f48d7aef65c99", + "0x83bd5c6109c0937f109307dfae9b347fe7da69fceac9444da2d6394d26911956", + "0xbc25fde0522d9ded3c69f9ce8233145b5b15242a8f5d6d6feb2b7aaf0aec5cc8", + "0x0b7fd860e34f21a54293ba2dbd61b28fe5ea3399a29ff7af4f577e681ed579c5", + "0xb2d96f1f4fd0f26e226386aa94e306d8a4a2a3be2860951e0c2e39c77dc31bb8", + "0x4b9794e3a3fa08b8a71f55afd71f2c5ba34fc9d773c32242246c721c87e4b14d", + "0x01d6ab151bd597e2681e9c67a0c3f445c85bfca4f8cd73e3d088f49dd669ed2c", + "0x686280902ed294c99c49b8c2366686af45b9c6ad0e7bfdb1c52f1c901a6be2b6", + "0xe0a05a29c78f04794b3957ccb343be88cf11b00f5d2454a6003e2b363f88d5aa", + "0x798aead8eccab3a4d4dc1283cda04057038bbf80944a87c9e796fa7565e34ad8", + "0x866ba6664beb3b953f5b5524190685eacdd1830248bcb5b0cdcf686101be0ab0", + "0xf31b7929f0cd73d652d1ded75d5ac19d95720b386fdc660e0829d122e66a576f", + "0x20fb041619114e9beb6d70ed0a488a1ed8aa149ab506e7bf62244934441fe0a2", + "0x91f9dfc54ea16eea1700cf1d729e77408d037f43238545136f6cd9c72bb2d260", + "0x7f633029a0d96a3e4232ca3b02189b59b10e6edeafa9756f8db1e8844e9cba44", + "0x0b4f8a2e3547fb13fb7ee5555281ee325d068a76a67ddb1dcef60a6ae4b41597", + "0x35b3e9e377449e7b1a023573123f5d132b50a829091183d279590edc73df67a3", + "0x8ac0d74f10c0f6a60d2e5729d150ffef0467934f8c3e0b37eb7112eaff246a60", + "0xa8f65245b7fea166560a0d775db32688a0249ae3df937a42847f4f0f358af085", + "0x6d5812337f22e0e436ee2dee8bd3a45b237df7e045a4bee1458c55a1a269cfbb", + "0x6f79965282b544af683f2cd74cb056c092d5aeadea1d16e34382cd97113f4436", + "0xf91f555495a762ed98f946487f9aac89b4485c71fde9d700cf562164773b119f", + "0x92397cb86fcd4bdfd448fce9e3fd6fcda60586482217ab74884182d91f3a33e2", + "0x3f694bc4515ce3389bb57feb21ffeb3078e67c3a13bb53a345f7d837d92e91d4", + "0x81694d138eb5afbb7137ed7de9e4fd7010528da30014d06feded8cb2db307994", + "0x56d59ea9f640664f6a1ea3d92860f15ac38ec313d520b24b0ff4e365dff53b4b", + "0x5056000d0e11cf10bf36c57b44eff8fe9560e261264ba2b29e97323c3fdda5b6", + "0x427230af29e403291fed2784ea8852a68d4bb0c07a514dba4797644c8150ddad", + "0x21d5f70bde1ffe09c38545103cb9e6a349e62c1316f1e7e78c2f93e577a6dad1", + "0x385df64391152fe6e1f574efc1be371bf46606ba571420c601877dacfc3d1458", + "0x4076eeac8e1b22684b6fd996a11db49ef6b52539e481c1dbee3f1ad3f59d4872", + "0xa8239c7d2d32a3ef6f887799bef8b470dc52d0c82af8de31bf3a8e4a6bdf3535", + "0x52a6ab7c89019f8fed6761845f9071bed1748aa461b87b0a587b7f59489b2dbd", + "0xbf80c8df3c0202192d1b888f80668c5ebb9d4f8c7d168570afc54276af4de578", + "0xddb5784df235570dcbb1a08fd293d58f63b7afac494b1f8f947677f2dd36a87d", + "0xa741791df39f377bec8cede1f1c491eae35a710de095b5ca5c56d77f4431e87b", + "0xb119d39b47e1cdffe5a4f912d7bb19c6e7776803a386ef62226f08ac1fa0f4ad", + "0xf71e68699da769cf06d77c0432ecff635cedbed284256336c682d542e33c96ac", + "0xb600381fb3bbfa7f7c3b555c51999446b148a1507bd6279752e7059e2e0052a9", + "0xa596f51a92c38e63a7172461962834dd700bc847b1e29c03e27b8e49cca19b4a", + "0xee28f2ef5162f0dedb5de1c4b38a1049e98c82a34570b8bfa19735e915909579", + "0x1672d010862647d074aeddc4189a5bc3a128b8084eba6d011046b11ad23f445b", + "0xc99102d4079edccd947367846ae35e2b40ab3f0e1aae8d68885b1753c2c64177", + "0xcd1003ed721269cc94a0736f70714394c191e7a663191268e2daadeeae2790f9", + "0xd33a0f2338d2d95eff701d0bd287e70e0093c6954455bbc63be7de7c39f6d9c1", + "0x97fb57fab06fee889ca8db09d5dad12007024c3dc59f867170d65540d64808e5", + "0xc4a6963627634d4baf5697343904c4c803b2f875f05260602d9ecd45e0e34d4b", + "0xdf3bafd9380eda31fa5f606fa915253ee8b9a41cdbc0ad12e2dc1cbdb76ccf88", + "0x141dc873ceca100df1127451dbd96e117ffefd054076327b68b1c76a4651cb92", + "0xebcfc5da5a1e1882637b9714fd899d59fb957dc9e4afdaac199264e8d29fe5a3", + "0x087504ed686f8e598560ba1f70dbfc72eeefb7cbee9559927a98bbb31b7bb9fd", + "0x767d65e905169fc44546a7c7828c2f1b76898d93df663291db08a0a6f0fd8610", + "0x0ce5170b5c9ec6377c3ef465d986159f12e65c32ad577d8005fba498fc6e5d9f", + "0x76a78e8c3799f93f1359313a6b42f3a4bf92a9c52c7b495b8d82946d471ca965", + "0x1b5006aceffd1d61936cb327b7420f3a88ecc4ed8808db9f245cabdcf3da6fe0", + "0x5588ef96fb1e960284211b143bb5b5a1e431a015b5ae8aad1a86ba1b49fad459", + "0xce5cf0c647eadd6de376cfa52e4a3008bdc0ea3e09beef3be5e2369978bdadf2", + "0x2e55c31e3dec040cbf0f2bd0816bcf6d41ea29376b9958a40bd799c7c788d8d5", + "0x871c62991b05eaece3ac9fd843c62f6a635230d885b075df28f3421c64fafa55", + "0x36004f4df1cd2809aa89c4edfe3ce3df7a70c1cea1b99d906a64491f002b0374", + "0x91ce82776a39a4a32979f0df16d17c4ca0544e7086c90562c66868b588058106", + "0x23d8c25e9c94779c445bc7aa84ed86189617463e3a9e62dd974a23a29eada969", + "0x249e41cd4fd36f6bd6860286bd29945bb98cf66c0348f73b26bb4a28c3103a52", + "0xf158ef6bbe5a54a85f11c58e5c569dc927089ebb641c9d0f6a4641770e551cca", + "0x4e30a215bc185573c02cddf66c40a1c829b86dc639c2eca7e6a4026fd8a27933", + "0x15f0ad2cf92788cf0905aa6f8d092b1350e3f1530f1b06e07ffd8f37d9d867ee", + "0xe7d081057d6d3f5d85be6e28cff22e4f4e2c842d31599885f4e3f1c96049c101", + "0x342f966910c67104f934395a34ffddb97260920bd9043e2f1aace5062520ceee", + "0xd09b337b1ec7e7a3188b2a8981d14dfb89bed807807a6fc40a21ce82a3814b63", + "0x5bfcb62ce51ed31f94636e5e55a4fbbb8d63342818814d9167d690f96ebd9153", + "0x9f46f879a2b469812d61674250053eb01ff91b3d61b66ccffcf8b0566bb0ab0a", + "0x9e7c1698af64e08be4d5d2bc9262a7e0d2ddbab9b5c9499b505245869a1e791e", + "0xddc3dde6d397fdc437fc95bdc98b1bac052a1b4fb1bd81b90d18d63093bc0efc", + "0xb8180ff01aa196209573375a70c590e9ca8fb5eb94c921436c534fa57b93c802", + "0x795c03cb817afda30f993770ee0718774aaec6d0c9c01cb91ab2061539ab7349", + "0x45cbd728f2329f5bca7f7d188e64b9b307eabbd816365d0352e2ea661d923511", + "0xbc1e8acc0b620fe7c44f4d661950981e8388e3f8bbd58546157a1dc716d43414", + "0x4e796ee801061efacf4d84372f6daab14a98c3e91b569a0d580217442e1b821f", + "0xda432dc7a649547983d6ccba6ad31b7cf97ba3c7eebb5eab05f34561759e6090", + "0xd51b0632c736b3403bcc07399e9be4e40e04928ee4e63e87710002b066e462ff", + "0xa3076a6242b4e2e450f227294940d5aaef5b62ad68d63affc390f874958c0c0a", + "0xeed1d4e115039d92f2d82401aa631248a9c5b8de06bcf784adb918ff28d70bd2", + "0x6267b83c5d6acf41cbe965d1bbb8871228a060e46435a29c6a7ade18e44f3ce7", + "0xbe79880b453639b576dfc891353dcabbff3d16479ceb74ad2184a1dc89daadeb", + "0xd5356e5ff86c455718ddc8527750b69b3658c9746c0e47ac93291b039bc2db8a", + "0x079545539cfb2ab2b1d5341de50c6c71b8725cbf3a6ef168869d392c2e6f6ad5", + "0x0e3aaea1d36e3945580c3cd8e26456260a19ec0630476dc3ed444c517baaf5dd", + "0x28d6d2c1e9e4080e0bfdfa907f6d7c9f533cc477a729eb83ffd0f96f6d6f5018", + "0xebb8535debdfb417acf2c13e3ce6107d7e286cc573ec1c06ea28ef4cf3729c8c", + "0x96440ac46648fcf69de403e4c146dd1a37eecea957370f223753ec93f32298e3", + "0xca28ae763d5602c91d437349aebdb5cf9dbc89e6cfc53c124370b67e31fe8f9f", + "0xe27ba10642ff994e47ab1fc5a29ce071d80b82d6f584eaa56ac1a62a771eb21a", + "0x34e7db6c5ad2d646e6791b58ec4d429b8bfd69f76b1d9bf71f860b1faa4911ad", + "0x0b83663dee1daa173203e106ee4996ef147a9940f2318b912364bcfefcb07271", + "0xb164c1d879ad665dafe81929e0db557cf2c573f188cd86fe35ef24271cfd9b26", + "0x6587efc2bfa2ebd6da9816538e3abc5f03c75b5bc425f7e5e9c676f97b1449ff", + "0x668316bbac3e4cfd0c4fee48957d9c8fda962bc556c5ca35246b88b6c43fe291", + "0x264917f66c2d927b7f632744f9dd7b844514af80bf3729f30832b222410a08aa", + "0x38b162eecc129bb2e1c82e65d785e84b5a4a9822bf1e6506492a25b082309bf6", + "0xeaa3ee39cfaed2aca6c1560608bc1a2ae32805812d792471c9c6a9ebc80aabe2", + "0xd7738ea58e4319f98250874c16bc4ba12f2362a8f09a7158ca4e2ecacd954d99", + "0xd26d6e2dd1b62f7086673cf153c3249b15c652a7bd43a4ef7b796dcc2bc44a96", + "0x11a9a4f1f8d10712e79a219eac2fc81b3360c60aaa9bf179e720ec04d69956ec", + "0x6ea3422e40bbd52abd6660d9ee8ff351ccc61d997082e470197a474509ae1383", + "0x1ab854452eb96365cc3ab33c6c45b296864ee61b3a477716dd9eb715529787b6", + "0xeecb8949e3be53db9ab660c71d1bf702d8e919ae6487812181858992e7668c8b", + "0x2a2ee4c33009656e5e38e44a7314c40254639bd46e32cb09eb1b9643d92f9ffb", + "0xa14c5b1993fb968f7e1dfe4ad24716e8d9a5be662cb0af13f43e174e0bc2c5b6", + "0xd5603250b1933ef1cd1b27932627f27599f81ca29c9f02e3627eb621f613c935", + "0xcca950815341af147085a53b4108ce368db1a634f204ad75f3c687b5b7ea3985", + "0xe14e1ce237fe627e8047d5d8f8153157ff1ff3d2650e0e2ba870ece940421470", + "0xfe2bd09d81d1525b996c67fb8407636e06723b4327803a106c19ee60a4a960ce", + "0x995cd4b1f16450b64098fda2e678b14833a3b382f76e14cea71a0d297ade2080", + "0xefbf5dfa769a1e6132741600fa9459b8a1d11b11c3b2563b22c79cddb34b2ff3", + "0x1618c918d173a9af0daf3af314d576a6419456636a46e2c6b8126f2365d627ec", + "0x3b9a773b1c0e16037a429ab42fa3883803f320beb9a34c8e36c80b2b7b814331", + "0xbe3b816b72cc63cdb63e2897064965c1b4e9cbca1ae26c770a20508be1d9695a", + "0xc57f2c5ff8087d6cc2039910f00323a90a0bdc3d2164e0f52bbfa920d62a15a0", + "0x0f11a1d5bf509afb2694bc08584718bb93288355a7bf0f801e478eeb9ef52da2", + "0x829bcd6a2392c957300253f7e9abcba7513908d3013a74387e918dc57053c035", + "0xae4d9d51eabed53e9ba4dcfecfc449bc165b3bd40d87830fe044811f4056580d", + "0x2a8a21d59547009a533695b5808d928992547937478ff9a61fa4388e9afc1147", + "0xcca2ff6985f20f7d1633c35447f45a5b27fd5a93802688e2afe494a2c350917f", + "0x2b8a2080fdcdafddc5d94292ab4fde01d91e7ad2c1b5b5a2f04dca9a729c3778", + "0x211074e33dcaf13183115f89252435b4efd8e1f01c38ed484ca69c14bac72eaf", + "0x5de84a9ddb48a4e2134be8cdd5c274471055234d428daaa1039ae2500e59ebd3", + "0x3f71bb8768f5c8d0db2ec8360278279f4382f3a50a939842d80be98685c536df", + "0xd26b7cf7c6f987f4975010eb9e77becf7c0c93ace9eb53d289beab868ab5c93b", + "0x889d8c294f942cc322a197b4f746c688a15e1692cad0d2d9fa9a125f4998a6d8", + "0x7a0c807c41e209d12128445df83dc1931d5a24923b38d259a7bb9e8e4459db43", + "0x564e904caabec0630b52e056ef9ac08a2fd276ec99d81644bf38dc0b09eaf820", + "0xd5804d2547786f7d26282726d3f9f22e53e0ee2390ff0de8b97c33a4e4237535", + "0x5999f87486f0c721b038c659831c836980a2f7ee9c887c759710d62691588670", + "0x9fa08ce53c180bb53d5352dbb2312603a0c3a5087cb32f81bcff368c457a498b", + "0xb1279296a8cef2e6b80117a48db7291169ad35b39140debe3ee71465b2a93f85", + "0xd3ca8ebe2a6ce6db208b4bf1853b8625e8b12f7792df1ece14f696d1694addbc", + "0x7fea211ff413b60098ababd9e3077f58325ec14d9fe23bbb1cea0025d95896dc", + "0x270f61667793c26f67cbae50931919b8370c0b395704640837d66aba90a393b3", + "0xe81214151eae79a310d5bd8fbee6358a3d897b2b9ed1282337b71a653db17384", + "0x5f2928cf34dc3da9a559ab89d7496510b3c2b5d00d8de730b6df083d03103abd", + "0x619e0c1627f0802d660f1b06bb55c39c0b570514e71c69d5de41232fc6bca961", + "0xc8384233eaacb714f29163a0a9b507b9c9d0ad537dd64c25bce91cec6fa6c2c9", + "0x54c2e035312faaff2fd08fea36df91f2add2ce39298a1987f4286f3592405e8d", + "0x32bd9a7d486a43926319510505b5018b9ae951f4ff0837f8b9058e93bc303876", + "0x6df5062af0c06aed44dc45026fd74a287e15f5a60f122e49343e5a1d10e5f371", + "0x6b3ffbe23bec6a576dcac6756375e6420123ef1eb39750aa6fdce9d874ab790b", + "0xcdd08aecaa642133a9b93ef888c5a808cb2c84c48943e7ffb6d531dfc1c6c205", + "0x563f9e429bcfdaca1ec2ee7007f286b1b3e4358b76d12d94015d9989dd50b2da", + "0xd3a709568bc87059c1a11909396d655c2f107c999bd75ff5104449f53d590f99", + "0xaadf85b25fd426d50f3a22404616141211dbe541eb116b71c6ad960fa453e172", + "0xc411d65a0dd44d5725a401d4a479f9b5aec10334938bbec7ec216572bddd84fb", + "0x4ba49c0fcf4dc7858eb6b77c942b528a349ad39859a2a1f8995593f04ae8cb2e", + "0x17f327906a7bcee96532e912374523b88f474beca4e40661113121ea626a209f", + "0xb0fce9690ee2a2cd55a0e088c0e96fa0e922b4119df230d4b903c4b18cd6da7d", + "0xf7070d16a82595a5782717429dc6d00b1f8abf6778db1836a23954cf66bcdac9", + "0xceae3600d842c5d03611dcdfd0a0231e469c65b151e247b2205cba2916324707", + "0x6d1e0d4ef9387d070ccfb68f0866937d44ffe7d9c4059a21bbb4b0c87b7a6461", + "0xa7c125405cda699de778318152df327cfe79cfbd999c5cc45db15bfed216b146", + "0x5d90e851ff50eff60b8c92d63274c9f9b5efec6efec3c2a412b003693ff014c6", + "0x03efe16b91c66ac58204c952a9cd24818ca61fc6b1ce4d81a31263a7c045aabb", + "0xfe9324d99b23bd0502d6c1020564a850c932a0d010593e1894ae21641ac5c248", + "0x969138be8e3cf0bf9bd0963d2cc6467d8690fc40797bb2c2950de0df1a8329bd", + "0xdefc0e0c25782165aeca15723fb74d95d96d1ed7420be7f3c85ce7cf7440322e", + "0x0bf69f52b595f75df550078e4293602593e3bc2d7ac528b7be44f556435d9e42", + "0x142f2883383cb22f5aa8e863756bcdd154ff3ed8a02d5cde8fc1572db65003bf", + "0x0fc8980e2ce7498656aa9012eff375b6b32216a3142fb974c357a553bc9b248d", + "0x2714b77d484d7639adb40e1158734058dc02dc761c7349c4f3818c70347b348d", + "0xaac5d4ca615ede62571ea4150e4c01cf31dc410b06d5b443267117197e60478a", + "0xcf9f45357d06955730a934d2de24b859d39ac0ac40c8b29430ffe061e3bbe4e7", + "0x52330a846f5d2fbfc26c48a5a95c9d2e3c88a654ee8f5fcb7f9eeed39b2eeb17", + "0x807c2b8bbeec7e6d43bb781f2d7405f9389cef647751c1fd30fccde0f004aaaa", + "0x8cceb13ddcdb1b080075083091120c394a94d6f8f00a2eb4c4498a3b1a7d2f5e", + "0xef770e4d62f2912430987ad5ea59974aae40a81771295fa1380e417b3df88562", + "0x92cefcd22fbf95dbfa766e7c49a4e211596cc6d997976b04efd818ba8ab49bd9", + "0x809d91cdc51f42438312ae27ea1fa94fea4bcb2c9341c274ea18513ba20ec931", + "0x10538534fabee44df110346114f62797a31cf363d4979f881b721043b2250e82", + "0xe252558398e892e85351274a5064fff650f0323f38b0a4456b14a435c9a40d82", + "0x7d313335d362826f589dae0164a04ea681cfcd54f10d8e339ad1978ee63d7045", + "0x713414b22fd3719c42775449895089e6122064b90258a1b495704fbc4677d92c", + "0x748b6883462e9706a8fcab3b0c71272fb0bedac622144d5d81fe710562b8dedd", + "0x2945d4809258eba164089c2a5605a7c9e72759bf615bdce0aacf96ceb7d6ec12", + "0xfd89a991d0e20bc05d484b9cab61d27a0406fa741e0be6c8c1c2655d1310cdf6", + "0xaa296f6295ade70466ed9c185480e186596f2183947f65bd04fb5644dec93d33", + "0x5286efb4ae287693b85bb3eb47ac0b697ceb72ed6331aaaa521d58ad7dcd7974", + "0x6b3a5802ba251becdf8ba2508a6fb1d3db0b5b99646465b12844b8bc23f062fe", + "0xfbeff1e7cea22e0563407d57d9b16518a0355b676c48605adfb13945d7bb2f60", + "0x7c0764932e56518167f4ee45d912c1a7c78f30271b41ee16038f358d9865258b", + "0xfcb998af040eb99c3393b165dbc904a197341fb7dec2d8430346b7772935dfd0", + "0xe46aec72c95d0accef6ebf564e9264de932458fc1143570ddc28eef3801430c0", + "0x08f97afe124dfb2a18c6c624d9d1bac4cdb5dd102da6bec9c676e7fa000a43fb", + "0x50a62c4cd65e3591651f8fa56831ddb37ff966cba87c12d83708aba72591a060", + "0x1abe248da61411aa6b6801dc188e3f834c3fc4600ccef36ad9d7bc517441a61d", + "0x07e38e7dee4062c20f4b3f221df72590c0838619617e051243087250defd0028", + "0xbab90921cb56563d69347a4197b869a8c8bc34d01d753b509eeb5895e77eac81", + "0x620404dca85a89624483cdd7e2b143b12a38b737c0eb783f5e4b378fa1d578e9", + "0xd70f44dbb657c8fcdb90bcc24a47485fdc99c35ce746d8eb2302d529be43bdf0", + "0x425c47cba9cde3b337c451eb7828b0789a76bdbe1f86757292e7c3768cc51b6f", + "0x11b521b56aecb173dff0358678298ac7f55015dd8b217d81dfe52129d03b54b7", + "0x98ef31c7277a68ba0a2a2809f8e7b4099c0e50cd47ab030f5e1c3ea38b92d39e", + "0x82ae5ef4f71c43cc296f1f6279eddc71766102997b0534ca737c0c1a63b0b3cf", + "0x44e2f38922e64f0aaf27607673724e5c91ed5a8176899e935c73c0fc09826355", + "0xa0361b8e3d7709c4a68ff24623856c54d16ead1762578eb562c295f86f453b14", + "0x91726ead73260dcf30eb478615968be91e4e2b6aee522ff6d814bae4aa595c64", + "0x8afe8954bd7cf7a6c40e3903015830f516ecb1a98c1b028b6799e1605892b49c", + "0x142bfadd2c9e988cb07d36bab795231b9582fe424a62de129a24fac85fc47b88", + "0xe369b5c6a44aa592c1d2c55a6fb9e2a0ec3274be74fea84d2e05451db7ff9b8c", + "0x10030041949c30aed18afceb0b6ba1b9bf58c338e275ae6ed9f2dead02a1b6d1", + "0x993fb9325d7be082347cf9361f665efd4d38466de4234233f272b1c09854657a", + "0xe2cdddac0a6984c0ed9d4232d8b58bc2c61e404c3e60b58b90b5876640e8e19d", + "0x4adb2f59c6704b8be33a046a07d2585328465dc1b45a41bf30fba1ebf6b2f7a4", + "0x2c47e906f61c60bbe994a54e3d0a68ba8dfb519928cf350b6cf8421e5c1779f2", + "0x4b712c7fc97f4784b2f562ffad648d29884ce68c505644e2eb4195fc43c00d9a", + "0xcc0fd5276fae744a1ebf274df70eeefbf301ca7e3d1bdd6cbaf425fe0d400758", + "0x0d3e81f37d9d96efad22ded24f6cb7174606c3b2d294259f37e4f754b28fa2e1", + "0xf80aae34aff371a9911fefdcae1289c126c5876b3e4d2477784196a4ed6dc156", + "0x916469d84a13c2971d02ceb166dbe0c9cdaa88c23e57772cd3c260db7d2f9ea0", + "0x37a5b98e5934c2bf16b048f76c06b4ab17945c1f549a20b76ecbf99ac99c3698", + "0x1dcff6c4816141355ac06f9e31a73f31e4b1cd947de42a078eb60ae828d5cf58", + "0x099bbbaa5915dcbc3f975ef1ee1e5da2bf248e96e87856323151a08dee9b5e7d", + "0xd0f2f3478ed51f2454d21cb838b89a3569b3b2704af4d702526af646b42dfbfb", + "0xd906aac9b70f76522bdaff3840df5d9714d352c8a632f44e52370786ab631167", + "0x7f99f6d3add64e2381d7ddbdee1306e6f6749ce116642f993bc4c06970295663", + "0x58988b3a6a1437814e0057b08ce6e86f58cef845f8df78a6ec563d056592b81f", + "0x7476333d9709b4295a63b55e1d5eeb7c23a752c4211bc8696016b70a4c13dadf", + "0xcbe4bdbaa8e34a22b883371b21d5e7cd474368ef0df5ccfeea3edcb377e071ac", + "0xffc358eec58c4c6cc0031562809154edc13b9aa091674e473304682dcc4c2c1e", + "0x9dadda32c544767bd65dce5804a695b8e5c35d2f96c203c350001e5be78c044a", + "0xce2a6bb7c0bceedce3111d97294b8672d0f6ae8eb537ea785398fdf06d6ca2a8", + "0x5ed79a31acc649619c09c9b5df4d595c806a02e93e92c4fdbe882899832f3cff", + "0xb3e94be6cf733ad114b1c1fe76565c448faa9f14131b30aa79aa36a0edc615c8", + "0xeb33e3a43cc5068b611f7a95fef45d5a83d0219906515a9ff02e31c0f1aa4e39", + "0x63a2f545af614f075469aa9f8d4e49fcac12336722936def26c0a4cd01a31b6c", + "0xa6d5ba412c63ff5903e2f30bdf2d1e93118514a8c82b532fda0259b5c3c21986", + "0xd170edc5d55910ee2671397a9b04890faf8b4a3aed0e98852d5732af897989d5", + "0x508e7b9e80ea2fee221ee8a527ded1d480d6bda70d7fcc2d8d521e35c184deec", + "0xeb07494e1b639b09c49b145d51ecb9c2f8b98ea596779d1a14a71e2eed22975d", + "0x50b37a16f4233ba9287fcda52030e2a7d92db254746bc42f7358c9fa0d4e3116", + "0x447b12ecbd02d12bc80c990d632cc2032b72a441b418b74dcbcf3a76ad8d69a0", + "0xdfa6b21b930c94454ae6845041fb6f4e345a11440077c905b4f3386bf4824ecf", + "0x7eab803353df60fa522a5c1c7d155939e1059ce4d6c83d7e4e3ca756bd0fd9d0", + "0x25a35bba3fb585339e9c9df30a10246774a72f47e99fc329d64d36c67df4fa59", + "0x17ca37df7ec4f94f41dfa272553fd5dd3d641a986fa5a9dbb262fc395dac8ea2", + "0x766bb71133abdf384d8c24aac3f663f858bc8283817ec2dc082bb008739eeb37", + "0x5748e015a55f336461f5b1c4bfc80e5d76dcd9bb3c72d583cb7e585c35d67111", + "0x39909825449948d25a7f9346dd07d83f087e50c82e9fe9b9d474c10eb7bab0ea", + "0x441bf9c03a11ecb3b0472fcbed6aff62ce1c44b237c3357a4c3f5e8ca190dba7", + "0xa0456b6f725f0c4cd0917cc463ad42e8d7ac9496cb0c34f067b691d89dc1f2dd", + "0x6571a9b298c2180c91a8436c7ed81da8a69cde6c1a20c78f8327e9cb7bf9d929", + "0x152f3642af6d21630770d739d3f86b5a0a8b8ae5806be4e1b568499349d36882", + "0xa7dad74a9ed1bde34b6cb0baa940b7d565afb8dd6c4e2bb7fabcc30673f255b5", + "0xaa829dc659ea777c2d84851ca7eeaf8fa1e1409df8ec151ff9d9a87bbc8cd848", + "0xf70ff1f39678b75cd7e9c7cf7de35bab6d54997cce23b769ae452cbaf13db690", + "0x2ebfa2e52ab6f68c8b7f2a8d656c1fd997df4cb680ab4106cacbc50c4f1beec7", + "0xdcc2ac91b7ba5294b3de1eb7db158cfa53db057a4956d403732be9aee6899fbb", + "0x65dd99a245b52befb5099b69afa332a9a529bdb5c3b57dedb3fee52bc11ec426", + "0x83f08c95ecaee8710f687b9ef06fdae143fb7581ff1498bce187acdcc1af566e", + "0xffd22fe4049110b55b117b38f5ea4c268737db4fe92b9b5fe691630b39092dfc", + "0x7b4dbfce2925a674b0de23746b226bd901b7aa49140e400af6209e9877d11617", + "0x8c8d8762e05effacf2e70742f9c563458065f7a0abcf9cb6d6f605450aef08bd", + "0xb97df188cf546690574e316b144c8db55c7fee2d241ebfdba1424739b96a4197", + "0x83cb74821c0295a9d11e4be54cb7f2fd4fdcdeecf9a61a3cf7d168338194342e", + "0xc05d2a626a448cd6b89824fc6ceca1b2295361d7e94ce86005f7d527a0bbf10c", + "0xd0fb8122dfe38416a100bbf00ec04cfb14526296e746da85dc4487f2c7597efd", + "0xdef0c26f8ac9f6704a016635dc46386a95e014a8637733f054cbe87e59e0089b", + "0x084e741565cde3ad7fb2c60e0cb1244b1f8f6b87b210993abf2959fd380127c5", + "0x7986d8c793b5bcf0977260c761f5ab4af1d0bdec8a5dc49230f63258f6a0f403", + "0x584a5726cfe9772deb22093a30ff2b9b30ebc018cf861b8aa0fb28bed97ee0ed", + "0xf046b4649898fbdce79870896dbc2752050b5f654faeff320ed2184c7bab659e", + "0x744c1495610301a14d82e49dafbfce8c70f7f78bc0679f2c6fb964a476fcbecf", + "0x4edf5a73306621d2c4966d4aa6cb2935cd9484f1f0ba709ed5d5b91160a5de2c", + "0xb5faa128c00d7f97a3e5204995065e99aebc76706e2e96ccf4b37d7641690045", + "0x729bbb468965401fbb0f2ad1ba0b8ffc7072f9b18ef63e95f47cd98285b89854", + "0x0550d90dc0f6e8d2017e14324d404ec8a200c45ab4a17ac24cb17ca9b68881c2", + "0xdbc02a7ebd9bf74121fa2b4b05c1abf4bdf00a973b43e27faefd095d6cf80390", + "0xabd6ef9629eaafe2d8170d511a39ea29c30d9ca0f071d5ea0b80fcbaffbebabd", + "0xa9dad7abbf1bdbc32d229a67dac65cb5a14cb0e25e8dc57ef7538122471909fb", + "0xd1e063a59f032a9e0ccd9b926bcd6639e197fce15e28dc6b1bb1a4aae5862e75", + "0xe3187db1ce4e4faf95ae3b2136c34ec2ecf028e4054995fa59aacb94d0e16d75", + "0x4aaff2417ccb6bb6be1e3bb759f745053a3d45ce144db0fb627edd9900000276", + "0x3b108aeee36e6fef8d74ec08c937143facb90cfa5616ab7af6d37c00b3a4f1b1", + "0x1ad317c91fcc12235526ed9d6a45c3854f2fd421ce36a2d475fdf92d8afcb524", + "0xe39f66c3ab33ddb0d1fb51b969bacda7ce0f0f53af7012dcd4530435666b7dae", + "0xe071c158a9c418c34270cf27035afb0896251616ebbc57e7e5a2fbd503cb30c2", + "0x41dae0f056d18719bb5568f0893fae512f623e16effae772d35398da2bd8931f", + "0x426b1e3b67fb576cca9a180523ef9979aaf4d14649637f69347ad3876bdb6fee", + "0x2678a16324ded3abcc20b8545ad9a4155184e63b12d1d3a1959fc9d08dda781c", + "0x3f18f5def267a73abf0543135da57d752c57e4344ea941199055a38a46758ae3", + "0x031b50935a859999c1de5b772eb4363615388dbb9d12bfa6ca72111a069052a2", + "0x57bfecf554524f9dee811f59e9ddb287b04338323e4932c44b208913611533ea", + "0x870b1bf5feb1bb5297f34a80b058c81db9c97cb79609c537641f02753f665b68", + "0x3bcadf9d3dba81c74a178f533c75f1e77c64baa6ae274bd25a0cee762da43a26", + "0x38cb775e5437c113ad72ee04f0721390b7b8fdec2efd0eeae24d22cfd3f0abb0", + "0xc6b545762e567ad0fb73b49e3af783035e77e252f5f26fb56c39f2ba280e4937", + "0x922ba1cbae3ae6beb2e01ce1ac2b3a73383aeda9cd3825cdc6206d04fa04cbf4", + "0x9e5899be114b856b51e0de7a25cc1c5c6247fd2c06f0381d5cedb2c26c2081e4", + "0xc7c57fa4cfd2f5d2df0bbca134f48d152d8e284f1c0d946fcab4fdfde9235b22", + "0xf35e4daf46b5b181b6c6adb53f5d2f93acc93b76b422ad82ad996fcf95d5a942", + "0x0cf08cbe8ab573727328f5e5809baba6b8620536053d023dddbb9cc310df3246", + "0x6ab0f99c1cb99bd763af36647d29d6caafafa4aa119ec34527999f992de25104", + "0xa8aabd97d98e4a657980b581b26abbc9280a288301c33c45961f5e35303c31fd", + "0x3c92814886acb8f2af1342904d0b2688be4f269a24849507ffc0a7fd0d67584d", + "0x582781b1bfd4cd4d619ee98db64eed9a11c0562565fedb6613accc03670dc376", + "0x832c0574c81bc58cadbedff928fd08fcf1b4c80d7b323670bf67a29e312f4151", + "0x932b7bd4b919fdd18acaad39228563d65d19da6c7e8737f9c34fa3d58a57c7fe", + "0x153059b97cc89de7bdf0171150670085b850a63125d3e51525bba6765be313b0", + "0xba341526b613c0f3927d604bac37232dcd5ac104bf256720c62ed14ab05370a4", + "0x2b015d7a5486e2023aa93a00261be3ab97d38a1e7e1b14d8878e6c109d28ba51", + "0x554e29e53bd94dfe253d703050d8f54c703a009b412232847fe01e1b138f64db", + "0xfc603400b18e2570276dd994aa168b7ebf2fa9c8a3d7f4edcc8bd6bf5c008109", + "0x66e1cb6677eb595cad35fd028a36aa416f698b6366c73d179b8bd451b0dc3ce2", + "0x9219571b2c2860cfd4bf49b92439dd76304c2b5b2542f036392566b2b431db86", + "0x84c510b2dcbadb5562a66a1312b6016a4d6fdba205b5ee698978f2570fa191a7", + "0x483e7d9599fe6da557b4f5e35bc66b9d4bbaee82e2bcf29aa245c4aa679918e8", + "0x84dddf3ab9a135de68eb188476c23d1460c45c377e9a62c14015b2fcae515d94", + "0xe03b4b8470073abefcb0d4db364624116a046e85be9a28a52bd6fa5b4d2264a9", + "0x342a467e79121dae9c3d203615f772383d1e700fb05ff8ccb5a48961b423ec9e", + "0x025c53fc663b8cb0bae6a439bc0d4f3996618926337bd80797510b67000c6f94", + "0x0ebcae3ede50801c88b517af406fec7a3922b4876f28b3096425d4dec3f2ec1c", + "0xff78e7b509fbac13400ebbb8955bfadc0f35a4b568549dae44b55d15bdcf2a9f", + "0xe19e3bb2648377f25d4a190fc44b14e80b3e2c8dd17427fdcf50451af8b5a8b9", + "0x50ad2c5b2732b7f2c34fc0e2e103884effb23f7672a5290c7a3ee7f7c4609fd7", + "0xe5a000a849f39efb9bfa550d959e86d2d0d92b6f4034a3e75a84a4bcd34b647a", + "0x56fe17466ab440baaa576898ffb22735f4fb680db4ccb9a7dc6f19a060fe81e0", + "0x1ba71ed6a71d823c35464cafd2f4b35a047de73666f0bddc272398d1758b4aa0", + "0x801ac73a07eb37ee08ec538f723dcf2c41ba8f0f0e553c740a73c1b486b29567", + "0x732703b2b96778d10970cd6f90634e8e383d41f3b863c424a71aacdf3d567ef0", + "0x5295a9cea073059a0c806b5d84e95dd449bd15e081ec1543f04709737e12665a", + "0x25aa778a07dfa614a7554d7b00ed9c5360e1bda16df694279d45fb4c0a4ce11f", + "0x3a9e9b5dcda51fd92f8dbd18caa817f53f096f3b66f953a1f731adf41577eef9", + "0x554d4c03a8f7f4b16bee2ecc809a4a03b3e6bec0b0dfeffb45acbeac698241cf", + "0x567f2220013d4694394b054b9f93fd33f9b24d165ec92eb86eb216f2658a35a6", + "0xfec8e9f64cbf08d5dd3e19ecf7e685ac89e8430221f05166f84eed16e6e42935", + "0x1398f794bb66f9bb26eb2a17b32bcff6c6c8796df52e7a5f8c2b58a94e2d8912", + "0xd32d51d30aa51d571b89bea7eadbb3d32792c5971832880053e6da18a6644f77", + "0x753244cb3d3813f9a59b396fff82253ecafa836b37dd4f4572d2ae033142436c", + "0x74077018c89bbebdba21b096ddeb988a40943985fd479a4a95b172d6d89b3f12", + "0x20ca619770c23b5522ee50b629697763767a61f17652ae06f3f30bef7f300605", + "0xbe0de8f6eef387c01546944519c3bd9761c69bce0e9620d9995dfd4dc66e10ec", + "0x101bc2c69d14c170de6b3ecab9208f68b7b1b8ff0001a400f7373b77454113a7", + "0x8cf7437d2474278b2646a71baf196c21994f640e9baf0be059d820f57e0c66cc", + "0xc5751a0d6f9f5b859382b9840127d837a015a7b33d0a775e935ac2f2e57b1488", + "0xbabcfa88c03ae1d413a6165c7dfbf204d5511999a4fc74ea33a694aabb55e054", + "0x66b70f7c56c40e818fb1cb842a13be3e44d864d9ac5f1a4336dd00330685cb80", + "0x790a401845ed04ea517fe4721da3cda115adba8cbd28775e8fdc9bbe7a5bc670", + "0x2696bb11d905914f93ed07d71b99a6a4f2e90aa7bd5eca5e32275bd4870ac95d", + "0x5aea5a8a2b8586491f85ba8a387e6a6cfe8970c5f47a77f517afafef9a009fc1", + "0x7ccf035e2483a2dfdf068c0cbba769d25e21347dbb40302dd2a5c396cc082237", + "0xc7cfd5568e4d9769465645a1726b4889656c99befb7aa02a5b8ef8daaa8b03b4", + "0x5d5436654bf6c9b428c8ad12645ea5d5fe95aeb5e639ec46d4324dd54b0e7e8f", + "0x82f4a8a018dffaa850312b375503a6325562e75786393810a383498e71dc2c6c", + "0xcb82be0f881fb2794314fc3e2cfdd57ea5e12fa7105a824ed033615c4ae22f34", + "0xefe0e3f97c4e6b5be518d58f398ded35421d54c33e0c93e3ca0b527ca50e927b", + "0xe6ebb787f18f2d0d042eec05f2886020262ac20f3c14e8c03885e04136028823", + "0x1e41e40d2da6017775457223d1cdfb06bf41762b8bf47040357592315f627dea", + "0xada6d7bcc5013069b5d0676df3b067110db631d07020104a556b61423a26d3b3", + "0x8e0840f9e38908e49fd12635be7735c7293833c65929d5aeb5035d45942301d0", + "0xb01ea85a249d3c640f5e2ae43b340a5f0455350719b13cc8bf1a50c8941a8ad3", + "0x4e5524cca029a2729d27a3d2a712979f35e07cf9d436ca7dfc8c414eaf5d5a52", + "0x72208f2a837b1fe9e7445a72f7d57e414db9e0bd87f7e5daa8de14752a2a87c2", + "0xfcf05de95385cee5449c1ffc63cff009b585ea5896b2ad96d43e747bed4aec71", + "0xb9ba0e212f4dc38e5a0c2b62bd0c1bda73459e72233ea38cae8f4a91f0a6d764", + "0xa8946ec7aef9ee1402442e7cfb4363df529b915c96698110ec1e3c15d445299d", + "0x07349344fc0ac74be9acd9f616a08b3d1bcfbb08c2f95d079c235f52a0322fcc", + "0x223fbcf9b3a552057f728cc0e4dd283176735668beabba942f62006a902249b3", + "0x0e28903b5f5db741536eaff97cca54fb98357ffa69b84bbe365312d77374e47e", + "0x6588620c06642d029a1f8dc0b95a14c198b7af2648acdf1c8d73c80d87cdfda6", + "0x021f66c28e1fc7678af4f05726d8670bd88a143e749a96edcf7cf8239607e9f3", + "0x339ca9feebab8de1672036fe85ef63bb591f5466da074793436a07919a7740d5", + "0xee504bd35830555e345301e108b4ee3698c9a0739a8d4210ac975f1aebdfb944", + "0x61a020081cf4fd487b0e9b694465b94016d461897d4e18990e2d34a26e6a6541", + "0x539ed46b92da9b97e94f0bb089b034af3e6c85b9812f5ac18b64026906ef4f33", + "0xd244eaa108e905c9160cba9f75b3d4f46e428749c0a2de7b165e95992e63caf5", + "0xd88315191813c72230222f636d5de64bf5ed7bbeefd574b1d0c2fa61e16d5919", + "0xd428f280ca6b4ba0ff8bdc58a1b5c8ca5991f9d2dcb8522b17b3c09647a9c8a4", + "0x0744cac8522e0366aa470de75f1dc92e307f82e2e300fac1f8adb359e7f5d9ef", + "0x6e504ac6d3e63679f9db61c3e37bc9416d687156354d1fe82f7f434c4e43708a", + "0x34a5c50161a9b06229234a23f210458cf64fbb5531298735826599bc46179e87", + "0x03a94978bc793490395c9cbbae9fba0f7a725f5de2737e65f7e4f55763631585", + "0x183f981a62d19c3a4edc055aba9d04e642f89f203381a4e63ed7496ba7a1074c", + "0xae5492ed7758112e7fd6c21582df31dfe0b1d6b3fcece4d2e8bcb7d5bf56a00d", + "0x8f5062a00e823791785fac6c0eb7c1aa732a70cb1fdd23d4336b2323a99d9f5e", + "0x74584b0ad5236526dc1a4dce8f4e65f87ba3d529749a702217f46ac9a6acef7d", + "0x06f7debcf4fa4511a1182d992fb0ee265714e70354a08fd496f2550a9e268b70", + "0x8a6b101b16aefa233c158e0392f0897efea6b4144a98ab3050551f8f530ffc94", + "0xc65d3267fb49c21636e1cee8d39c515b9028058e8b9e0ec5c2d6e7adc9293e45", + "0xb9286dcd79def251104af4f3b68de8b9e5717ad5275665b6c079f49afab7770d", + "0xfa735c22373482f2017aea5547def3bbe6f0b8f08b7054b775dcd04c3a3b8597", + "0xe3d360213b5720573864c6a1d9204151491bad4235e56c35b340b22e8c29f5c4", + "0x87ee0e69a5db0bf2dcf753e2e1dccb92725f9d1d597aae378743038121071b9b", + "0xda446379789bac65f03bc0d2bddf4da37867069743ddbc4f2e846c90db8ab568", + "0x553465cc2c0ab7fca15424c8507d216d95f53a25e053657fd8eaad58efd45346", + "0xd3eda9aac5e84aa9cb845cbbaa180854868f497fb79c5053becd16f6d9ff13a2", + "0xf8bff7af9e6fc79a875bd7cc4c1a0a347572c5f83c8a6864313e5f182a8bcd96", + "0x3d49c1fc6ca0f9eef57064a5c125c24464d1ae6f29989f2e7f4942c50128f31c", + "0xfa78f4fff3ce4c2b34935ec5692b9bb0f326a65ec6b14299f990e697ceb89a34", + "0xd7de5c5c86a0ada9f328e8b67393f4002714c5d5f0d1ff68129c68b882d5c6d3", + "0x89f2fb3dc33363365ce597c0e5c4d14c0f66b60a8c6ae3f6d45d72af301cef4b", + "0x218c78843492895ae5ab088ed80e82eed320cb6f98595a211340b19428d94985", + "0x5380a88382839684d7d9fc7047eca486ec0383966b262e5e46b9aa0859ec1547", + "0x19cc514f0518b3cedbe31529f8506fe60c93122cc7da49ac6f855abdbb729e9d", + "0x93e2d29e5c272ba8dd20f621132c60ddeea7779309a4d14fde6e6d58b0643f98", + "0x3158d8140bea277184329a7f2f2bd7e956725dc80573ccb169c40bfdcf3f2c70", + "0x7505475407491f5a4619a25b97b1d5cc1e1ba38764be61b694b6c1d3ca51c216", + "0x40c556618336fdf46e581183b7e57a2f6e2665d8adf0d44b39d9a5150a56a13c", + "0xe8d0da5275d1280e0906d62421bd64a3397b5fade799a701e0a37111d13602f9", + "0x28fc4cfdd74093fc78d100681b770d7aead4d57552c9366d56bee6e7776653ce", + "0x81eb57db158fe3ae4e62785ab8a5c4fa07bf5a7815f1dcbe25bb997b89392691", + "0x361a76dda932befd901f101507a238fe1dd43ab563d09e5e3c6ca43e6de48f19", + "0x9931f8e7444209b91572ff581bee13380706e6d6de933ad96f185f71eeb1ca9f", + "0xf9b544a3c3090c494eda2657a527288e48b5f4c9032ed26eba3dcc6558508d79", + "0x16936de0caabfbe2e395583091c3b90305cd1fa734a5ecacc8db0ba8c40fa89b", + "0x998492ec7efc0178ad691288e36758800b139a26aa493bef28f2e96c460be402", + "0x626f93a0163fffb94c1cf227e6a0ef125f7930f3a21971dd3a9d443162a0b176", + "0x64a7ed78b519d1f04b5b3b46c6804c0647889475d4fe991c8a7e405a4a2334f8", + "0x4aedeb8f7470b9c97c2fec75b4c44252a855d36b73c6a4550d15368dbee9d0c2", + "0x17095f0fb67a7d24910c086ad4cac72e493bd7276afef463d05e26fec1f39381", + "0x05b5fc483f428f6c854403b365ad11f4cb170a2229ec66ba671b94ed50686858", + "0x76bd14300b8f845500b2991e8a78df8dca3054016ef6b5069b77ef05b806caab", + "0x718aafdcb0223d7010c9b6c012c38aaf82e02c8737488bace9a7f8db15c60047", + "0xeedb09efda45baaa9034a18259f1aae1275a86fc81a218d9982e0b17f8d743fe", + "0x2608c1d2f2f8513ff1ac6e33d21659624c16e00218f984ce971eb9bee4825101", + "0xa5331637e8221d95d318cd4f32d5d37698731f569c4879c151086974e2cd4e95", + "0x2f9faaf3d219ae56a94fb4ab12f940d63a1d86776aef6541d40ed63d03d44682", + "0xd91d881ed4fd4b6197d77713d2c42758d9e550343ab67fd761c7c3e7a3724fe5", + "0x2404c00a40e6d67254ded0ff5a5413776351b8587ab1fdc4cde74c316435a9df", + "0x8591c719906e31c2150ff3183382f665f756c9a324ed470d0916deaddc240edf", + "0x8d670ef59f2237573019bb60cceb14f7198698773b572f6acfe3d3bad6c33d3a", + "0x3631004b8ebaff324494cc7320bb3c0deca53480a21d2d7fdd516271af7c97ab", + "0x4dc37b8650d5e49ab1a87a9e88912a98a60099cdcfc33a5c21627f0bb05ff124", + "0x95a8b189f6335a7d1523c470aedd2fd41f66043019da9a1ea46b379372ad4d6b", + "0x7219f1318a197b919a83dd51417803c752c24dc3a005cd08c091b0339634e806", + "0x81d850ed79388dd32265463d5283b02b11f012e08eddddfe389d55790cd1ff52", + "0xe170a7511431b18ed7330446569a253047f4fd0653915e107104380ac40affb3", + "0x9c38e78c1851edfe159971a455a70e1d61b1ae71ea0cf828ef40d4166741fad4", + "0x1ee49fd6dc9fc4f6e8bdee61a3e010a0eb9d06597c256200538ec73580c42bec", + "0xc0e415e7a108c241fe301e6ac22c81738470b499aa65317fb9344d59ed763a09", + "0x4fd8e4224aa6f2863ec655c10e829e113882646230a3dc753d80c111093ba167", + "0xcd7f4ab1b3900488068618eca688f2fbf85e58b265ec0dc4c0ea55f8892be5a4", + "0xddcfaa6613a08b4d0a5f4259abae86cbe95fd5ec5ec77fad9ff2c5662efd4025", + "0xf8bc573cc98ace8805ea12e49c664d8d9cccd650038a4c6ad559780d1d2392cc", + "0x65d8dda84a5666f872d4a744a7c98b6dac5e1082e06625d49d32212a37bb1291", + "0xffc19cd76943cd82bd7aeb8d25d6dc4bb71f834cafe50a5ca2ae257d76a93db2", + "0x3efd8f977e31b77007ae5f290a63c22cb417b52d9bb36899baf826049d169785", + "0x9e225513beea6034be1edc5c51a3f12718713578a2a69bafe7af00bdfc477d02", + "0xebd0e1994eb8dc81f7ed767aa664ee7fc0514caf96fa5080c1ea120bc9803ce0", + "0x340d016d76c6f0db1853ef43ac32c2ebcca11a936c19f0f6814d64aff8d63ee7", + "0x57ba48a6bee7cc99a609f5ec1c9dc2aa1ad26589b292d0e913bbb7e6700895f4", + "0xb0b3f638edd6161784754f858844e77f9dc13a52943120680171deba7272e9d4", + "0x901ab47b6f412b57c0b09020defa44b5375c4e80749199c084f6ce0ecb89ab0c", + "0xb8c7e255dffdbe496fa3d949ed552e36ebdd6d14acc4049491ec6a033c086616", + "0x2f1780d8df1d77937e6dc3ec8483d39e3722eee9b102d84cb412b6765e1de74e", + "0x88712075a1174fbe444b715cad257d16547968ac267142ef293897332feac87f", + "0x6287016bcf8d4d4b67412f0b94b080d6b09b35d2a969d333fec03a114f49852e", + "0x7bae2942ac4d0c98a53feae67f5486415b9a59305b6adb3c7fdbf78642004eb7", + "0xe2dcb80caabe834c0897449540154ba5102f7c7a534c40f05dad77d42e26c571", + "0xc1856ba8c970c81104603472986449d9a6ad17f56cf67dd243c707c689e2faf0", + "0x3dc698054a61289b4b39f89c7f09dfdcf72c4a5a54276e508b095374cbbdf69a", + "0x0b27594e85ee0393ee4b16ac44751b9a1d8a9e7d704f42cc7c46bc1cb30dda54", + "0xfd47f64c6b87363b36d1de4950c72a7ae7fc61d941d6d046f89eec5bd63d863d", + "0xa420ed29af2c8a076098250c29704638476fd014558fdc68524d7a1c9b4043cc", + "0x20e516a19060c4f95559484dcff148812ba875407c1e0548714b630439985f65", + "0x779971f5b6aeb2717e6e336f91b3babc6b96621fd93352f0444b96043c34c1f0", + "0xa57891c1f318ee62a989a151b1be70176b8a86466e3f1669a87b3131b3f7190f", + "0xb09340884952e9fce0a543bd8e98617caacc63d4c87485da51cdb906aefd479f", + "0xff2c2dc309fb4c05b90a80a3fc715427f540be0788b33525a5ea00f0376ecf8a", + "0xaff098da407d643f4d60ce864184a0cd2001301833da3f379659ea4462da737d", + "0x0650daa5593e4d835532cb1cc353bd2e93fbae818e1f334491539ef4d363c2c0", + "0x1d6e8666bf720b0cc1fab78d8ea982ecd2b44305dac8edb2f5b9b9881722399a", + "0x673a6337982d71675566e7e6acf703f9c5b18718856bfae59edac11f4cf2ad3a", + "0x6f68da412db64aea7ea33dd930e145f45b36cce9d285ccb878d33594bceafdb7", + "0xbcc221ad6460fb4066d8c630720a519557064183fd3ff3feffce36b0d80b8da3", + "0xe671736f8a72834e5944c296f64a0d35743edaf75becef65203409bd369615d0", + "0xe4b50f9724453eef07bb00e56c32f6e056bddf38fed0cc80d3d9d2f86258810e", + "0xfa0594818b10ecd7be1deba272ee23b3cce007382e6974645a505df7d289ca39", + "0x35cfa0772e326b9325a613ac39ec350241a62d9f51cc0a1b0de4875d2ce48059", + "0xb6575e9d2cdfe08b13fce3badd0a991f5d331cff4444821932973767677ca13a", + "0xd4821ae28196784c066b254b2fb3b6230d5f4a0e769d8b85fc7ba453d3e93f1a", + "0xfd9f762aa42f1eb43e75c3c00d292f9afe393a14e272037d072872f820e710a8", + "0x9f78b0168eddb9acecaeb07fea85080fb638aca8874a9ff15d3bca7e3e4f9e73", + "0x8c2f0986e10039e96cc6695884401991d714adf5c445e9bb0f90a14cb4a12477", + "0xb7059b47417c4a06bcb11c6ab78221835279d130f52f5cfc316e80f87977b87a", + "0x56fcf49a8a7a69d4f8604190d79eae7e2957a1d129cfd813c9447249ace909fa", + "0x9401c3ee1a458253b3da8820c1e9b8945710839a826582f3a86e8a482dbca0f2", + "0xff3f9e5724cfbba1f837a10f3844cd437c0f1b5e31ddf61c4e56ec504fafac55", + "0x8787e48bce6ac94e62c13b82c544c2265b42ec08d959c18722c3f722cc8ff2d4", + "0x18cfd60669f16555f0b0a429a6b98bb64e936863d5524e23c3d263dce8177866", + "0x33a19dfb8f79494cd2b1b5983884992f637099735e67b2197ff48b00fa28ed0a", + "0xcd2d1272d5982579a63f951c3678c5ec440dcbdc2a5fe4ee8c765fd16ff07353", + "0xa7bd53be4ffe9029d5bf0c15051158d4fa1d9857861d9b3fa63dd0d5052ac98f", + "0x6e039f06324bfe8b9604711719bee4c840526f8c3ce9bc5c3c5584315362f0e8", + "0xafd6c666917c47aeae4d44703d891a3498211054535295178903665328d24291", + "0xc0f0dcd1102ae4eb932e3ee71f1417dc852f3f1ba6a8f2b12cfd8b86ceb3c335", + "0x6845dbf33355716e4161cd3e03ad296a4bec741255d91bcdb6e36950c7010c75", + "0x832d9dfedc39989c97066d465f256ceb8922f99e01c730865f62bba3a0aa786b", + "0xdf99981c644b3dd68728aa9801d5ae41579cc499a534d5213797b3fc35bb64d6", + "0x0115b4118eaf40a9f0fc1cdb8f26ed41e88de8c99e572f72d79dffad9a776e20", + "0x8b09da2fa7f9bd66158c3d469cd22d3f8ade9d86d0cfbc49ccb48335eac53df1", + "0x1edaf123ca42fef6c94b334ab5584c2837949abf3b3ad0b05de4e1da16a5fdeb", + "0xa7bf42422c1beb01742120f78b46ac1eae595f442b0f246f53a919343b4b3b37", + "0xcf72cd32a99afad5a5d9db18819131219a92c1404b57f64215a9e9e891c9428c", + "0xb0d4dc75898e16ff0c4b8bb317669eaba1e54f8d1a1cced03e6565ef3063fde2", + "0xde58a7597969ab3d35a4269d0623ba77254fa140ee0dc00f85e1d256f515c26c", + "0xc0c52dbd3d1febd3e5b4a59d9a6c1a4023d612160bccc5733f2006738baeb149", + "0x42759b763eef5c70b4fbb982cd247c29b0570dcfcba9649084622bc93bf0440b", + "0x02b44944241f25120667fd0c83797915239018c4b370378719be93a809d0fe31", + "0x176572271efc8297d8472120996569abdc26e0b2695cc1c69f72d8e27fd927d6", + "0x2c2f7eb653428b3a5329b339094caeeb4924d322b4362546ade060f8ce89ba65", + "0x3b548a06156cb3ce3ee222cd68a95ecd69bce5914a699b020f0890719a5f97fe", + "0xe74cc69a92f69d63c16a4baae5cb692e57f2e2efde17e0c46fc4cb338eadf215", + "0x9b2a05590bcfc56c432ddda8607b7902c1195ac72fae25c7f18e547a20fc1654", + "0x52f4d9509d31fa6100c7fa8d644dbfe2122581e8a277c6fe80b68aec78035ce6", + "0x380c3d4f876907fed243d11a8caf436445ac5ec55bfb3596091791bfd80ab8d3", + "0x386a91979bb6c8e42d282132f6903e517204fb9ce1379fe5f2a90b66b1f708c2", + "0x333d6dcba02dc8418059d95d43e22b9bc33539bda31f424c762c5b62676b04b1", + "0x50b91f399926865ca64ef68dfa540257f660759ced1276da1033bba6c2500da1", + "0x78266d3dde661a3b10f43d31375993ff002a7b49717a075c6367259baaa58fb1", + "0xb5066418dc050952f056082ef0f6d6b47fb423e9e5458176296aaa6edb7e7af0", + "0x3b8320734691ac54f2a231b296b889c9c8511843984a9ad80f3c43b8fdfb2391", + "0xf85d88e47f6b7ec5f5107785f80fd8b51ad6d5488be9b147e03b5697567ec932", + "0xc352f5af398bf837c89b42eeb48c322ac8eafdbf57af5c1c33ab0880623c7599", + "0x450a16022ae364a4f3ffd5e554aa9a324ebf8b9e6e635e753f4872ed6f63051f", + "0x0438e9c7d357912b1527a7fa5d6e30ec428e472a617d30e33946e47a1f648dac", + "0x4cea137040ab131bca9c9cdd41760c181244c736ca1d9d19370012935de0de6f", + "0x757728e69874bcea324af5348e76db22c3eaf8348843f61b82271570a5a96a93", + "0xf45bd1383b1d53e95dd4d0515f20035cecfb0707442c525c0f06b55e7ff52a61", + "0x156d898c3abc5a55d9860d679d97c36b2e48f833c1342bbf455b13874743b1bd", + "0xb3e80e0fe51cd1ab5d8ef201a011bf6a0a5878d070eabfdb4a6d7c77d06dfbe2", + "0xf7302c6bf2d04fff65957a18c8b988bf0e3dd7f3933229a6f1700e6447560d5f", + "0x73ad7c6627035301b9815d82626fe958ec0ddae62060f0c7f431865dc1b9f6b5", + "0xf10b5b53d915c1bb2eb9979dabd2e917dfbcfff17f1d09cb616b2a5179014ce8", + "0x93570e1d259272e6b825a5ed34a103fffcd27f792fb5b09a2442cc83a3bd172a", + "0x8c5538b8ff9ce17625018bc309af258e4f5acbf9c7c2d4e948cee8b30b336f92", + "0xe9a6cf047c81e965dd32c57edb680c2aaffe2e367976eaf49da5dfc957fac2f4", + "0x7b972cd72e31473b463ae197e30b121afdda7878b9bf0e1961d3813734663435", + "0x9690c83cc3a1b1b8649a89a9bb1e1fed606e4c949d46ab8f66f16c8320ff5127", + "0x8326afe249d762313e5e089474f174825821099a5e9136a7783c3eca7a160d05", + "0x240410eba6ddc5b60a0bdc83fca59d615d95c64b0afaed0a7f17b96ea65684b4", + "0xc48969c8f72df638ef2e8b98f0d67dc6d9eae1d5bfba2b02e584ac2dab51f3e9", + "0xc4fa4b201243c20d35df1ba466a4c40139471ec86bb55f872d54f6404d4bb05b", + "0xfd085495f4ebfd30f7ee4ad9f122ff3da3932fb87ee9aeaa7c8103602671b96d", + "0x17ef24bb8c605d6a27b3b44744353bfcd127488be96ac77a3d8c706015889040", + "0xfc2fa0f9a8aabf5fe515cb5b4a4ec6047f08e6140e81bab8624b02dbb3f99d71", + "0x3ea5269fd6cc38f8a2167cb1619d643ec9de3deb9ece6c19542626f7284b7b0d", + "0xd6ae9f4d8afee0374c662a86b489c603b4e16fb82dee3f57ddfa971e68531fbc", + "0xcdc97e7c7aba5cc5939382dc37142c9d59683d3188d642009edb492ccba1ed77", + "0x847886244064d2edd6791561638b63acd09336b4c88eecdb09493e8ee5324dc6", + "0xc3695209de581e3e3ee849b3dfd93d8102c9e047edc1596aa332d8137d0bc3e4", + "0xdf1399b24c2588519cbf19e2e7218d0fdd793cae1eeec52f9fda7c729a0d4e02", + "0x9718b2e289feaf4a2acff80f5d1c61400e917200fe97b5b9b6200d4c48e7a526", + "0x6fbd4948fdbf124fd0a9c958953abf372854bb6e29adfe9190b0101b97a342f9", + "0xb54aabb1fcf4c8b701734624fb68c842b500f5e71c39dd04083f8a3eaf7d7c51", + "0xc3710e6042dce5652464ec6891ec5b9f436208c12afeda5fd3f454edd8b5d79b", + "0xb6e3d629f78477b79bb9368f1611b62d717b3214675c64f1eb737dfa17b03b04", + "0x6fa6a372c4f33ec50d56a4039c0eb7d6652fb934b24ca468c1fa8f034aa043f5", + "0x51ae789b75938201ca463bd4e7c36152aeafc4b63544293e689e15ec80ed94a2", + "0x4fbb4816f1ea23ea83a425969223be5b9cbcd69113ff43e622ba9753a3a25901", + "0xb2df755c413220d7b684b063f81a800072f2f552e37fc057f555b252f70e858d", + "0xb5d01c218c65539914a8b01c40bcf629c83bbb4ef0c6289c127f583b133aa4ca", + "0x1489588ee88b1922296b2ba27abdd0d393a774009941f4779a63d3ccc015c34f", + "0x093c64995cd670084f2a908be6d6a508f490641474bfc722eb8605e0600d246e", + "0x9addbfaec75c7de95a89691ac3c23ac7c557c278155ba6026aa73258870847f4", + "0xedc09711042a5e3e94a1fff57e7d00e0193f1fb292e3625c6c230c66bfadf1e5", + "0x99a935be3a0aeeef44a096fc8b18ed302bf7224b6b7abcf5e897ad7fd44ad9b5", + "0x00d804cff32284e41ec123482da2a86019ad97d8b36c0b743873438e0cc7438d", + "0x669eabe8771c02c109a7d46ec07b346be0901078f5cd4419b05f3f62442f0b1d", + "0xbf26eeacefd0dfe498f7672aab4a5262d75af5a7e8f5a5dbf0a3e9cce3573b1e", + "0x9b43c92edad88c5825f99c8490b627b68602701a8358baa22103d2b11ced2d77", + "0x8e8988d54263d7e2d9692ad884d44575d3fcb7bfc37333a814ad19328df3c690", + "0x208d671c12795da6d89847247d9707cade2dad378a840d281a637e2af57d137e", + "0xfe83e593e005e58c47571fa00075d440286e02674394eb46956a25ac2e2d3622", + "0x41a61f08717bcb479edd0ed1fc9d8bcc13b9ca3ddede35dee6e0d0fc347c4c45", + "0xe9fa1018977dcb1a2dd82ef24105dcd827bf815985fa97afc0d294711997f686", + "0x7deebf65689aefa15a6d15f7b6e4818547f56b01f622f94fbc42ef968762ebf4", + "0xa8fad9841e2c5d7c1131c16145c57829f22b62566b5a7366d6653157dbddbc83", + "0xe0614431ceb7f622aa4f43c03fae28318aa726dc1ce0f95d69aae011eb62a017", + "0xc731b4b0341ff915979233c76f3562e8a28f268b5d3e531d8d4f3c927837f123", + "0xef265f9c899303b2afcf6cf2418cfc8f9c71d4254321aed87827c0c749f51546", + "0x40edf9f2122834fdbfa84483c376a6bd8b67eac8b8bf454258dc7810f8e849e9", + "0x63093778c25926c58ca06014bd1b668b4d89e641acbb94bcb13c9ca0519fdcc6", + "0xd8b930be700bbc53228755ecb5074d16308f8dd3187cd3a0efe0c2414001458e", + "0x75b0cc9e892313d9c1ecfef4bf4b3f5976f1c830a7283a82fc331277a4a97eb8", + "0x4f102fe9ed705a74524f2598ee6f22adfc1d4186e2ebcc7331bb48e900795cdd", + "0x48a257229a0e91207cc31ef82f00532ec12cb605abaeabf1235676dc57306357", + "0x9ed64622acf60a2bc6fdb2bb738517aae8dad9cffa738ed4f95b02d3be04176d", + "0xd23a29871a1fe22d8bb7e7749aadf6d77c0140fd383cab55b099714af617a371", + "0x79c92002b2077df1c7127a4c49575d7caea872ca1175011d47e019ff14ed8535", + "0x9a9434b2d09c181c7d9f8ce3e10fafd8c3b1e27b807243d74075e747570fb391", + "0xd3c946d1ed5a76e6e17a599d06bbae3319dedfa047e8443f9df3c4b09aca3b88", + "0x4f3ef090e35ccddb78598a581800ea6f2709c691e3024c2f5d13635d3fdba27a", + "0xf958691aa9a520e8e399e466e390679ce3781b82f1d0dfc62bb53d0b3f640176", + "0x4a7faaf47a5031e0a798dc00ab8248aae16866cf74935ac0703d3f1730617d79", + "0x6d350d1568d7db6c029f32d7c8fe47cfbe99984d5d24a9470800f4b70207f653", + "0x6553729bf5616496d7d3ff3e120ddf1c4e64857c53303003e4c9c2546f8458c2", + "0x05491ee727fefe4ef46b9922856a5282c4ba27a90150b967a04e62d85cb3dce4", + "0x61e8d5b5143c0c532adc9f466dde430afc1d1755775dd39095a51a5aa2d4422a", + "0x2b5a26a051940c5f804db637ca77a835ab50f6c62648adb5da7ea05b39b04b38", + "0xbc391789c853b9ed06fa0d2533f1f56b55937a49061f1cd1a102fbe88657a764", + "0x4206d3b075128ba118dd06bc273999ab5ec097f1690c2abfdab351efcfddaca8", + "0x78075f3f0420f490386d419fe2b187d8c6a3b0bbb2158e0f9bf04071ad235bb2", + "0x0cf1b70db8922a59f11eb3a40ee22264a231905cabcb270dc3df11d22c8cb780", + "0x093ca9659cfc716634b38ccc97cb8193baabdb6569f4b33e56e3d8ec1157dbbb", + "0xfb17fcc35e7609264b5dde51f3847f98f555808c693fc345e6b4da55dec4fb9e", + "0x7b6ff07aa7bd0decf690c24d510a2d08ec07fa78276311205004b521f15a161f", + "0x2323e4a69094bff2e821a49caf30ccd91717bfd9eef8609331621071d4fcca2d", + "0x9f05738aa053bd67194099d8bf7baf3166c4cc18b76aaf7cc1a197d4af911765", + "0xb46c0513fd784d2ef4029eb3352e4423d627861431c160988bdc901c01957114", + "0xe1b5c3328267a91718980d369530a7ce76c6f7e404030e880c5dd57508abb03e", + "0x66d908a91b10d229bd478a9ae64021757a22edebf9d41e4a58e2168e8445d137", + "0x9de8289dc95f5b61cdea4a32c7064750adaf034123380c68251df2b816790893", + "0xf9de4b4229f1d152bf4d00864d8d5c37e8cf38264b2fe304931392f848fbe8ec", + "0x356654f74408077036e642d6ae98d7d3893190f6169110c682bbeffad006e33c", + "0xe5a731364889cf98c6136de7365fc53b3f8cd622ae7480fc35a9aca8f4e615fc", + "0xecb8b7af4e850d0854aacb48f034d96a74a81e588f900e1acf0f421e8ea2e59a", + "0xd3d25554bfe2217268be1364b9f74ece500ba8e49260218f22bdb86558edeea2", + "0xee9e40ade104510e4d04b9141864d3d14ddf947f7dd8d05ca29fb3b4d4efce7c", + "0x440556c74bba8c2d89d9eae72f713529f0694a72a741951d5144f7f977ba745a", + "0xfb63981c40b30bc7675280cec8063e7f64f44eb60d983b462cbfbd923a18c46f", + "0x666810ed3d8a8cb87b9d3d908285b7428380cbffeaa2ac9f50b9acfe3727a334", + "0xf87e07add78b9ff8c8b8c4e81b1086ae1fc9f97903a0b8d5e30442781abf5747", + "0x7919d5dac99d403b646b4785205c3ec2635023816e534eef9f14aefe01a0c8e5", + "0x99e1935acf142897bcc10ca07285849b08e5d8f0f8ab73bfb5b6f79cc65f4919", + "0x182a38b8286b5a6ecc93b431a20356a178cba89ac025327e28b7bab5e815ae1c", + "0x666d49f7785b6d3db5ad92f1403e2e447743351bfd31f1b3b61665a79037a1ea", + "0x898f91e453cb2349f6a222f23aa848bf01426fb40fc7c00fea3015847da37edd", + "0x6919143735b6f85a9d0e37bc4b81a92d664b5ef75e40be58fd1b269f5627fdc1", + "0xb854a51fa1ac7182b6f92d48cd90d8a576e75f769147916565acfbeeead664e7", + "0x3924e051c439c6a49a7af5d5a07d3b9b193eb1a6c1511ef406aee6f8e94b2f94", + "0xc6a2b425de2dd99bfa1c0970d29df185045a56cfd3b4021a3eaf630d4e87c6b4", + "0xe66104bd368ce9ce40920c6a0a1dace7be55bdd5ec594cb9169e42cf07282168", + "0x876d3a55345136b3079c260cdb312f8c708f9ae8afd3a6a90f8c018ba58be19b", + "0x5c0849ab35f38121bfceec816cdcc2525e88530ad874086bfa4056c8dedb1e77", + "0x3028fba2e7ff0c70acf12e33e744a881b94865d6f373a50d5d5eef23202568f5", + "0x9ac128a61197f07dd4b0fbac847b864a6496f1047a085e9a26f1618e9ae83406", + "0x55c9428bc7a5017957e025f046231005d4199c8e92627074923280cc3f6e3cc1", + "0x474004a4237145fc86484ae385c21523250746c662e791d5c366441c3b9d2189", + "0xa53ff4b977a2417289f9b532a20b758a2b0bbaa84e71c82e783c7ef045f16eec", + "0x0418a7320d961c5dede728027a0be6f4979211ec600b564edd408a1e9377d5b9", + "0xc8ed8d992f2b75be024eafc15ff7d7c5c0b0599cdd6b603437b4e737a60993e8", + "0x3f5e222d8b28b38a8c7b190448286d4a14afd1b0cb2697fd9356158f5215a0e8", + "0xcfc961c5ff3b8615089248635d900fbea9ae9f7b4d86ebee3703453567a67485", + "0xcb88b820997d440812da7192f44c6debd27da3a41f04b595f515e65cf8a80d50", + "0xce6f3fa44aa7a177ea56d97f00ba344852f614951e665e3742429a6aaf698c37", + "0x21bee516e3366f5770dc4f6af36f799a5c967eaf398f2b70c3a8ca694096a9d5", + "0xe5a99d3fddf70f8e732f7f4a14fe81de8cf1ffc945a47d9eaa7a28c5eaf6ef84", + "0x0d9e3847d768c28783981c6313bc9b0e60ef4c2a8693cc25d399e9db50f393da", + "0x728f54d10e7b531b464ec7e86f3320a4e853967c14061e727f58ee3c115cf65b", + "0xe1a0b9237f50b5e47c98190589842f0b72be2acb3b6a57c075b0c9933ee23100", + "0xe42d8bd36eb740ad018367109ad59f8a74ab017eee893be54a4d1b04b7cf37f7", + "0x72bd0949deab66aed968e725b4434158741c70007855105dd17ab9cec2cb1a91", + "0x450177933434050053831a4c162399286a92c18f9899c413d1c579ef95379fad", + "0x8c950374baef552acae9affd2238ce1b0a1c27e463a03e518b99f23f269f805c", + "0x7a09cddc74127b837571d245fc039489cd0be46ef3618460013de17c2bbf7933", + "0x6ad520bcc098e50d371d504a1e4f4e37b63484066606556debb14c1341880f9d", + "0xca0232939f26cf17430ab3299f1970c334f8dc132724c6e6b01a2467f4dbc149", + "0x9edc115c3af74d77a3267df2b87a77d82b825d07993b74fc31668a09915ae070", + "0x0147d798bf772842ca2e33c28b65fc6934e41e8775b5cfd566dd2f60641da26a", + "0xca005d851a4c27070a0706bfb3b95303b7d79008f49a681f052700c1b4275c57", + "0xc365df99690cb05b89c7efc60a7af3bb4e01c22e5f6d51c9631cf737717965c6", + "0x80aac988930e5f1de8d1db964645abb114e145f301db96925bb02cae2f6bbdc2", + "0x7c67c1aa7d047bbb20131ba231a55d0b596394b06b89c574d23b8aee7231b65d", + "0xd2e03510fc847b2890ea18eba3ed90ebdaaed83b55bf9cb5eb37b9fac10517bf", + "0x4047b15bafa722bf1f5ed69691e671a64c54eda20f11d25143ac7e5dd4e9ccad", + "0x746ab5985f0ef9bc18cf60d1216c69d1fd40df2c1bec2262bae7438acdcd42b2", + "0x7fdfec7be4c42f0d16b66818334e49c97d7b06ea6a2befa361a4aba3c511cb7f", + "0xaedb8c3201c978069b5b2b562252cf617e2a0b0cdae62dabef3a04badce1a084", + "0x24dc7b367353aa7ac0c386f4f5768ef1212fa2cb0de8317300ee54b6b8e420fc", + "0x6bf5c551d97c93ed425eefb8f2998b5fb3735f96bd71b1384799a3330347074b", + "0x9d0be98f9e31ad94e6badd0bbaeb85dc69322649b825f8c41dccc8f9a8d0b4a0", + "0x0d1e4ef567e933a591dd361bb254c080f91351b04ded52e022ed296c2c06580f", + "0xb80d22650285ec257007fb6ff1de2c209cc6be02303b3e2bac43c6a57c0d7004", + "0xe2cd2f349288db25e7315e3c8b4257367f082a377ba4384275a506e814940caa", + "0xf56100200b9fee76191568e49bbfa0eba66887f24cbd6cfc0145db6f31da07b9", + "0x13beb775c7a572d1c54631405b45f3e96938af0d5c740c4762d5ebe5f7ceb1b6", + "0xb5b20d1527a14d733fdb3a94f178dcbecfc9f4312e2c3c0dbfe57996e143682b", + "0x5153bf8c2d061de36ebbc21a31c3755f96296936e79584d03ea169d7450700f7", + "0x8d59bf8350b7eb84d5cceecbf735db04270e4d76b66eb9961243af61317a30e3", + "0x90e0af4b3a2806ea91799ee9d973fe9a2a3c7c07574acb7c72665af11a515bc2", + "0x171fc19c2c2e6fa95af7789a01078a34a628f998ed882884e6f514d45642cd6e", + "0x5f73cd024051e26bf239f11b35b757e896dffc144a2cfabb50aee58e2b4c8afd", + "0xdb7401010dd1db0e8af735200f9bfea39f868425afa01bcc404e5136db7cafad", + "0x809dfd2cc6df05328ef813bc5ab86b6ae90bfadf37107dade647e5a49fbda950", + "0xc731c27a9d048ff7ac2f08d1d68d46fa57e61e620e044b929dcd7d076d157eb6", + "0x1d443d7c2a3974ce9d3211aa39efb84d779dde08e132628c77d72cf092ece1ec", + "0x71410564b523d40ccd091e3e19deaad26d74d97963a171cd6e2f739abfacf63e", + "0xab33110fe291f5cc2f469cec31c7d21409345545446ac33c0f49e1e004542f6d", + "0xa775e97c8fb2b70449066c1d33efbc44a10ed6c931b7d4a193e649b853f23794", + "0xf07dd49b627af4aa3253f0403aeef8a3bb452dc2c69a1227325a1c88731ada5b", + "0xfc648f6b75782491734b7d24fde9c7b4bd939d0b338a74a0b36daab26ca3555e", + "0xaa88a296c0cd44bbaaf8148c005f180d7a2757b4ddcc623a43a88a43deeee936", + "0x1ee2fb788d4dc943f726b8455957bc175ebac3e4b8427177a053d7f299a3598b", + "0x13e7c4da8f8982f0ad250a425a24ea8f8b8574abe033e236dfbf596fe2efac0e", + "0x8acdcc6356fc748e03c06ff4878d0fa96f18e4f03272ce01f02ad29d8211f611", + "0x230d99e6323448f1ebcf7e6792e2978a5d74ef654234be97ebaec5c56a684457", + "0xad35598f4bcf7bfa1852a9265a59d0f9914b3b6289a7aa3015e3d808d504aca6", + "0x4d9956ec8c5887e8cce4bab5b6819cc13a8703cb527f14a5e9db99cbfd83b665", + "0x99a277612b78515fd153c88e0060c274b1ab4a60202b575a9b9892420ae657a3", + "0x656acdfdfdf9b76d499176bc3a259aa9722b31c7f3f4ae5c2da8bc3833c12d66", + "0xd06448c98e529a17170aae72cf359a1e2808ff529ca9f37df3360b92790f925e", + "0x9afd24c01afe4856a47db81a6818899d93a5096853b395a24cb9edd693bd24e0", + "0x03b7a5d8eb6ae24ebe158e411df31514229a2f302108984597317196f6226ccf", + "0x6f97a76567724eecec6c55e811085e7a83cd5f6551924f6f8de590b16cd255cc", + "0x5fa0d567d50e49df1d24f243a2ff97feecaacacb6a5d7e34620a9f7e18cb3f84", + "0x727b25a1d44fa0eaea544ac593fd8bbde356a71a48162160feace5596251f1e9", + "0x3d8340ffdc8e124785dcbf85d3b12a65808c49d91a77ed7a1ef54e404acb56cf", + "0x9057ce97cd01e362ac771d04ecdc45b10cfd45d0c3a1070e2c0fbbc81fcdcbd4", + "0x016b166a2ff70c7beec4ecf9a408a8fa4c556e0e4382911057a984454fd9ab45", + "0x9c2a27134a95f9f28d9f313ed2ff1dba33d5a080cd2d00626b8b6efab87d6957", + "0x66f3583ab4095411135af58756f72480d888a24aeda166136e18e25f42d56e39", + "0xf2cbde4bb5fef74ce2342be3f2178a7ec92ec819721456687705025708a2ddcb", + "0x5ce0fddd2a1a63fbe9bb28c01ba7d1c120f2eab2eacb0dc6200fea8c170e5d2d", + "0xeee2051e5b3a37bed40c32e05f141ea33283556a20e42cac05e5efded1b046a4", + "0x0a38951aeda2ad0227d5db28597901dd2f15fb8a53027241941f705f84f3462d", + "0xd532a9afec12700d8a6976dd148621347df54aa5f78fd64581835027a88ef6f1", + "0x2e328120b2bdbe717d673b04c9fe2c66d9320f668798b9fa11c257a5719c12ca", + "0x46a2cc57ba5798731135b891a9cb9af4b1f780a168d91a9d745f5eb39bdf72f8", + "0xe350043ef30f36168e8f68da553667cccd2eaaa4a1ef85c187163b9e5ab243a0", + "0x183ba0d0cdc68e3ac433eae5822bf39e1e351bac9faa4ec279fe9d3304bc6dd7", + "0xdbbfda6ab37d6b32188cbfa975f513f6024e84364bd6c59d513357598c92f80f", + "0xa44361a80cd53311a9e2de8e244013ea6a926cbd5854920ae3e162bd25d8ea21", + "0xd832af8bb66b36e85828711a95a77a2b6f4b42a5865bebbca59209e6585e8c9b", + "0xc7f64dc286ba1f7b6ddb15638662314813113bf058c7a9065597aaa4452c752a", + "0x178b152e9820020d4245e8a997deb02767796841a0220ac22544aa1250f84296", + "0xa182cbcf24b7d477c0efb568a8b120ca341c4b82ff0fd0d6d0b856a65dcf1083", + "0xb1f0f8c06b2743e1f8149ce4dc215f5dfb89f8f1da9718f3f312e500ef06aacb", + "0x5027caa12ed653330800d4de4014e24fe9251ddbcafea58e2c27012dac58c371", + "0x35a7801cd57644a1df91656b0566c62265159106b963368cdaf429472913c189", + "0xe80e4e8f12abcd5a79aeca6efc64bafe1893075bbec001338f625642fc047bee", + "0x994fb4f27b15427028aba87c42b08eb0919e12870a05405e0ef8f2458cc2b279", + "0x67cc00cc4591d984d9c2270fbdadb8c0d4ec9b40c6879aad8176f9cc7131e31b", + "0xd73e02e0c536cabfda569a8da06c99a28f3314d2761e7c0271aa5480dfad3246", + "0x8d709e7a8435b1d5507859d0e4406589b03d1b3ca646f9f26ec3004c6b2d973a", + "0xd5b64c36bc4614f9ee9bdfadab6c095ad183a8cdfa87a9e6858c4b12d9067aac", + "0x9d1d6d5c1eedbffcfcfc2af6aa9a6df958897cd81cac630dcb998f41a6b14638", + "0x39a3945ad321e02ffda18c8072e74f0dae525a57c7197dfeb86453ad208ecd98", + "0x878708a865debc222b72daa2611b7cb8368313c05f7f41e7f8fbbf33f602a582", + "0x305cf1edcfb804a104d777371850939c7c028f50d45f2fc4791524e24b6adfa7", + "0x6f5dac19867a9f14de66769c9a8f0813d7ac7fc4590eb3a862cd14ef63381491", + "0xdd7d64e12a1391437a07fa88b6ea7184676cacfc7cc8db544ab1808dfae8c87e", + "0x1e97a0e1992b75202522362a4edd8004a430f99c024a6503105cc55bcc7b843a", + "0xcc78f11a9f6996cf742875333c8274c68800658fd5a7465bdbf9c13cf2cf72f1", + "0x1fcfc22ea13dc96c9f8f3546f3f1b8f458bf7d1d46445c92deadd848bfee0c09", + "0xaa5d6969d152ebbb075a97c4a051195db68d90a75c37c104321131c073fdd843", + "0xf4f6e0c5bd269c7de9d1473c5074b3bd4d42b207742b918ab1481c633d05a38a", + "0xbba5eb96150613be2e45e1ea8ecad915415cb1e091a85b6858a7d1d5a8a005f4", + "0x1cdd61d797c519d6295196df06cffd0c9819ce0d9315c66e5309f14eacab63ce", + "0xb49771b39eefe9791d25ff5a1c94f0dc7d560a90cd9ca9c997625c05c0299783", + "0x5232fc02627cf406984a2f4f2e3813ad6260c1b07da797c2d1b7218d7eb05ad3", + "0xecc5ee2ea8e3956d964bed681f61323f608bbfe52397b5b28ef26f660e3c214b", + "0x49ce943abece2026b0c51a5ad5bd35613c92f480027bc47954eb9bc7cca5bb0b", + "0x27f731e278a0221daf21ab225b0297276db74ab79edc4806aa6a794e730f615e", + "0x55a9b21ac8387ad6aff87660d889be69d8b506a5de230043fe5937d0bfa53771", + "0xdd2ba4ff24bd512d48b553d031130799e46f3812c4b782c9423235ccebd7e655", + "0xffff9cc54e4484d4e70a6b3770d11fb9e13e583522ab4bc376cd6c7498021d65", + "0xb4bfa3c62b210ad81177faf4f6a170dd801713e5f9e3e4bcb7301c81cf60d083", + "0x5c3f5d4c0836dc02a32d7059c9598bfe46a813684f3576ec24aa8215a5de6270", + "0xd6d8e57c79dc17f19eebdce62de1adc0940d881d61c4a1099d51e6cf0b1009b4", + "0x2d3b6873546a1e6d026249e0cc45ad822fbdbb2ebcbb13832b7862ba9bc09982", + "0xd0d2b37a28cd798dd9d1a1e0892e86d90ebd54e6be912ff122402f6d923becb1", + "0x0345ca4471a47d8d12421bb39b0b0f7e8475d04181abfaa9050b95cde9aa4a8e", + "0x78a603e3f62c47845e657de355bc40d877612062b2f42b63c50645f3c12c4b15", + "0x1e973f2f79722999a5caa72528d1920917d7e7eb6839976ca19165c3a8bd26fb", + "0x3f5242f783e2336e5cf0cfee1427fbb15a833930b22187b3659367563a529039", + "0x181667e480e8017caf91681eb04cfaf0560254028a903b620485cb9771cc26d1", + "0xeaf92b93fcc996d886bca5fec1f6a7dcdb58cd7acd8033637a8fd9d4bda169b0", + "0xe5164f795fac046d3106dd707c4628d731bb73a3fed8d15ecf915de5b2f0a48a", + "0x556f9c42a01e441bf0e74c4a89323bdea6ce402dbbc1f500d5b00146be5439fa", + "0xe59b25cc5415f5b84b41ab7085b854f64f6d839085e85e6b2a30c41e6f689494", + "0x9e2c804effa40cd7a92ac8901798c03a5e66f47496cd89fd3b8314e7973f3d06", + "0xad4eec2bac36a3ea837c95bef538000dbc75374a4c4f8ffa7d2705ba300aebd9", + "0x12212ae8872a77a5d57a4f5fd91797c2fbf64ac2fa5af09aa55742b3950d8e88", + "0xd987ccc0c413e4390b5b5b69370f54b5d35f79c9cf4c1c534598a7e383399ebb", + "0x8d30d2dc8afe7f50e160fb4d3cfc5c54a962f31ae5b4f65c2362ceb7b8cc4733", + "0x617cb9b3cab2b8c43b11bc3412cab6f889197ba608c068dba2eaf1fa051b0f26", + "0x75bf3d53043c8375f1e51194be0942f3ec73ffbd61926d33910fdd00dddf5b87", + "0x72bd67478fa033abe7905125b728485f401aaa31694bf9ae7eb1184adff2db12", + "0x23d7a73706b970688eac1e8affa5524f0f563228aa7601fe7d790f844c186bbf", + "0xea350aacae57df34a533519b3448435879faf637e3f4a7cd3bbc891489d31caa", + "0xbff826ed9cc685de15275d59a299f5272cfab31750d39141e5ceb8f5d3645741", + "0x020ecefd03dde3543cea261d265a265898f6804230e95f044360d4aedfe031a6", + "0x71645432ccbc0826c83dfdf044ad7e3b2df4bc979e68513ca382ff93e24d1d77", + "0xfcd3731fa2259ace8cce5eb1a3fd74c723f997cfd8d4192105c41f2874d22d55", + "0xf13985444c5a6873217da182e9784fa87576829b9e841dc209a2592f0f5522ad", + "0x0e065da66efc90bd88217d6e9a5721280c4037de294d9e6ee8c1207b664217af", + "0xc6f893863ef60cf57991974de8edfa93c28c55c3af96f94cef9360be9a3a05b8", + "0xae2bfbe04bfe046166f0d6871d689a809fe443c9a6cdebdd5b2e32a36d7fa67c", + "0x733fbd82f21056a2e402ab050e32cc83aae96a67dfd3fa9c50732a3fd576e7d5", + "0xf4e29375a5f989dfebdbc9101d411f062c1090a9869058f6b87fe19b3a259489", + "0x95f902f47c21700bb030841890c47d759dbeca59983f1f2d5353674a4f45088f", + "0xb02a6050eaa94106ee9d4577b10f6adbfe7705a3ef9c3019412c4f60ee8d0e1a", + "0x20d64b55c9e4c2eb51e5af544ed068ce9d323c194c5b18bebea4bb0182344ea2", + "0xb6e40dd521e524b30139719580bd7441a35a1bc304c338c426b706673e179320", + "0xc54752027833b57236b5f043fed133b2461f199b75d52da8578c6e98dc2fc5da", + "0xfd3f9c65d1b05ccbf980a35cd433da01443ff8fc7be680892ea3185914d86727", + "0x7175b164364820f36d10f9e079707a40b21004d0687f90bab1b132c9c34ee2a9", + "0xe4c4df954bf0d3d0eff516775d60cfd29d0e780da4f07589ece3f11ba8925b2f", + "0xa927f17776d750c0b6996f1d8d0db22547fffdb006c0cff367d0a0edc41ddb01", + "0x27050f4807ec856a205518e9d13821b2cda0231cd8959f47ee34832181eaf8fa", + "0x4ebe3a5760406a59770cce09a0a44225dd5a2fade1d877b219558029e30ac4e1", + "0x290c328e60c366b0d18e55c5578b9b3bd83bf1b0600faf0822a1f6f1ae85edb5", + "0xd7bab11bbd83da583e3fcceb0f84bb551cda363c33c67f93e02800176c29bcee", + "0x3cdcfb49d11cfa3ba1809271869fdd9071017e5498f8acb01c595dedcd3ff109", + "0xc75582264ee66717ee40ff52a6689d03121ce0f1abb2c354cff6d92e532a81e5", + "0xe7004c5a4d09fc89e8737a5535221b552e67c3a0fb5851021e9f9a0de4672ab1", + "0xd6b8f94deccddb6d4f8b066c0302faa4b562f7a04e3a092b7d87b3a08485d933", + "0x2e726cd7212cdfd26cf0d928932b05ac8258003254e6558c87eca8a82cf6bb02", + "0x6c8786a64069e3f422dc5000e6a614adf14215ebce0aa8ab8e22c5f239a3714d", + "0x2f736729adc62370324b478cacfc6256fa0cb9119219a2a000d2c34c3293f6c8", + "0x8afc8743b959ab340dc86c6ddd9ca1726cf4bbd13054616b3d1d64bf656e0827", + "0x661832363afb109885055ee90663ea7514059a2c6d69144f8892138e89ed037f", + "0x2279ecda37192639297242d97723c6b635456cb2c98266493552e618067fc5ea", + "0xec7b510975a50daf40effbc94c977f508c84a9712cdb28d60c80b30adb3fd24c", + "0xcaea827e123419fe48b7f72dd67eb8c3965a4504f13e4ad7443bc8e87bd7c832", + "0xff012579799171dada6dc819977c222836b9cbb4f521142e74e9ef0762f73131", + "0x70ec4b383c92a8bb37f733825d60e76e75469a71b1d5361a84e37b38e3b8a34b", + "0x4dc584e8bce8efed0a55021d334b87dc5973de45effbc43e84acbfc03592532a", + "0x0fdabd0093aaf388fdc53d49570d3304c8c583415eadabc98635dc472f366b90", + "0x1b29d10d1443bb37e47668c9b6a124a1964a3f12075ab9be1620891579d8db31", + "0x3d350137648ba1e593182918a4ddb6b5983001356d6e406bcb88753449ea55f6", + "0xfc3911c59399e8c329db2dadcb5f7a58855f19401f513b9f6bdeca01e73edbcd", + "0x89a4277d6bf214c50fc0a7219ae59bdb719b71094d6a02c4ef5e07b50501e74e", + "0x7158b6d3debe3b6ef5dc0d40616691c804581d5614714f2284e63df42b5ea578", + "0x46d73cd458ee5a26724a68b2f8186930104aa9674fe4d94ce75215c61d0ede81", + "0x100c71337ae5379ca5d43f2177f2f6e6e57c628bbae4bfb70abdd1f23279787c", + "0x3c9e2e0161341c82207498608091846726ee4dba0fe1fe69c07a92a0ff7675c2", + "0x5c4885fe3f85ee61e50378943a48732843d47184619f40954daf24a165f2ba9b", + "0xce300dbdbc2c8eb91c75f7e0e8e91dc03ba8894478a9e65529241ff462abf713", + "0xebcc160dcb2f38f4607cfd3ae74a15286eb0aae05c8fc4f87abb751ca88a699a", + "0x91aa4f2af47471ac51160d0d1c81137c7c6a22ada295356668427a45d21c6a07", + "0xf30c1a0842faa5df4ef896e192d5902445ed7b01cfc83dc287492b1896126310", + "0x0e069a0772dd736ea68fbbef47302ed6e802868d0847518ea5ea2eb34a79705a", + "0xb49c6e624b584d49ba226f31611a0c4f3ff0033a746b370890533b209da2ac3f", + "0xf2a4cb9c4877795e0ee2964e5aec8828941bef07777ff4db07423b4a2eae5a31", + "0x2e9cee7389233b6b4937f5997be0a6f37a8c347c58886b75e3013060c10c4a82", + "0xd2318412b7dd0eb4f6b3da69c2c3cb7d8a6b7028ea8f0a39bc3bd513ec7c6d3c", + "0x74c00a1f66bbe517e7166993e18a1564d43877110c54be28053321721e619e86", + "0x37de40b83aff733b4792e27dd6211687ad891f8d95e397e3a3e07d481a5c44a7", + "0xb607adc39f83da6b0a7da38893a95cf33582d836c967496ea7636e61c6cb7191", + "0x518708d6d86b3a15dfd50d0003c340998be42ff59d533703be30763aa080c547", + "0xc9cc7282488774cbdb9d6511ebae8f6eb9947cc5360585d75197532e37e9c7ae", + "0x9c73d1c1a937f888d29da748772785d1a8269282003e7cbab2af4140039312ed", + "0xadc5c8b549e56222f6634a308348eda613afa171b5991ede1b127f241d25c570", + "0x0bcab0832ec43772bb1aa95f8ba9eac83b4b47bfa776876276b47722aaf5c3c5", + "0x8b37849d079adedcba7ed2be598a6d84464ccdd807ccdef2d711e5ef7bdc003b", + "0x8e2e677e5f20a78caa0ab3726528209bca791551d0d33346144c5e7b1c8c6bf7", + "0xda0666298d3184c66e54af103e988fa0c9a80a12e32921e5bea0233a8638e23a", + "0x1ffb4873b85e71b067e3ac99bb26e7f5ee5e036bba4835989f1477ac8b03466f", + "0xfc89d4900e3e7a475b8923bad15bf68f4cb967cb50fae648c2efb3d90cde84f9", + "0xb62eb8ea8e54ed6358a752943acd7a2a1fef9553533b56ca17f3cfc0ba719ec8", + "0x795e2eecc65f357e0b7a9c97d2c028b7503524809adc6e783f05eb0423362980", + "0xdb06a90870bce8df7a88118d485eb691a0043c695ceb64af565ed62d37770c98", + "0xa28bb65d12c4875edd64e643da53c1b65a154d9e40a4cd37c6f770940235740f", + "0x136902f6e7104043a9d828a027df5f23c61a7d085e49907042c55d99d72c16d7", + "0x058424a9554f7a52bb6516ee51653aee32ea09d96247fce31dd8b31af52a07aa", + "0xcce2dbdca699f427d620870ae23b96b38da3414c57e71990ba8af36a58e6b936", + "0xd1feadaa1927f77eae9bb7260fe84ada5d524bdf1239a6e688080da9f7b71af0", + "0xebe906165c9808c0b368392dd2cd950b55e1f95394d28255d7cb9848bd4f3839", + "0x639198f58b4712fde6064dc49f73b3db52726e76ab9bdc00f6ef9a0487fd6d5b", + "0xe9e2f1d0afa3d3b0883fc7269618ca1a50ea5aa828ea07f92fae48b2b2fc54fd", + "0x811ee53510a20a012a10ed6a02407dcaf98099823a35e54849b381d4a6e5b5e8", + "0x221c81c3c384717eabd545830b62427d11fc62bd1df260921a8e121456d719e0", + "0xdc62196c03031dfd983ad4a211a514e25c4c97c9cd9ca62ac18b44cc0da4e0ea", + "0x3f60edc7443b2ae2a4ede7f52c2c4de9d58f90d6be2f0fb25772b51c352aee17", + "0xb5cdbf0eda83613a613ea26b14401361a2de1be89412367f39d4ab01449a87f5", + "0x10d0156c9a828e9b8d61e615079beebbaa525a07f32d792e5a67d4f03846bf4c", + "0x4be38f1cac74f26e2e5bed0d2b416482a74aa425564ccfd3e0ef10b5f57a7d59", + "0x814aa2e560adae5e7192ada4ee11567bfebf3ff8a2a93aa8dd432df30c77f44f", + "0x187c004ce45887043188c222842da10e062a9be8a3db326d3ebdf860209e723e", + "0x60036829b2cce1932f2d4198b5207d70a2e0634c929a63df122ea38f620f89eb", + "0xc323959ae94b9d4e5246a35ccb887b8fcdd2b5de43ab581e53fd3090b4dc88b8", + "0x37a114fb8c7c973708d5dba9c37df501db5e0d074c757954e52ef716299239ec", + "0x8cb29fadf7071a43d8208036d986abe64a1974786c4ab573f4dcca88f8db83a9", + "0xfc4485a7b2ddece8cefbc0f45c949920b9412a47b3e21efa9aa381e0cba0ee72", + "0xfdd52d72e5f42cc1cf1bdcbdc97b15f623b78d78425c338fe588e890be995597", + "0x92e26312a466aff28597bf3444b0bd298b12872f099885ab10949c0d263446a5", + "0x420d6f0581dc5c914b0da7339fb69bb5c9094ea8715c778e9dccd922317c36da", + "0xdd8641edece5a0ab2b024b4ceefdc3f524cb0cc9549c200528962eb0fa341310", + "0x740c0963ec5c29ca9fa48445ddc604bec138df538edb18844182556924d09fa6", + "0xe66653af6368613260ba344cc051d6086a2e08331e8bc5ddc2d25ab06ead9eec", + "0x86e1aa0ab7a4e47828216a25073d6c355e2f4ac4773cf1d2d859f62fd8fb8a24", + "0x3be2cdbd947172907f5605beb7863e2edc5f176e0960904550358ed6c2670704", + "0xc7d4869adae5a7593dbea4f802ab068044dab40fe0063d5b7c7727a3bf288525", + "0x620611d92e256bf7cc471c8883801be5d64fc8b77c1f39682bf840031e0dcd3e", + "0xd89f0456b5a3d041d5309ef623e259003383277f7f509096ae5dd02d312543d6", + "0x7d91689ff4e212d6f2c7d62cdef0593686ba04aaf455c576535d097120f1353d", + "0x568a6763698a23b4b2289b851b46907ec5777284741d3a7304d7df297fa4129e", + "0xb9dec1f84c9b71d5939f40982fe5c88d15f868e265d4fd9fa0560c2b64191998", + "0x6620f3e9e7fae45ca0178116a9e478f95bc0a69fab3a8341dca673453741bb6d", + "0xbb418a7f8415e5378cca2ee7056c6c78641b085e30bb9f9da033ea193bbfc77f", + "0x002fe11d761d3135edbb3dcb50533a1b143593145f7b4cd914d84494b1df652e", + "0x5f76ba2c72c3e4d93d98668455def3d335b03f517648c6cfde1d0a37178a0ec1", + "0xda49060ebc8b7963a9ff4095c9777d902075967d75c47ee3e9f86f03031b0a3e", + "0xde325b667d85828b7416d437a91c19a14b0217323650dd5880a8a40ea85f451c", + "0x9c14e5953fe56c60599dea8284b0948603334fc7aa795cae80308eff4cbd67da", + "0xa9e82869a1be8247c665d86f52900784005853c5249393fadabe37d08752ac9b", + "0x3feff38ddc1917cd5cace417b4e86762126997a5420ac2cb32abafa769f91ac5", + "0x01144f9a6fa0b4396560cdee8bc6e873bdf3ec5c3ab3f7409e59884e6d2dbd05", + "0x96778169c9f2b805e67cf18324c292c8b67c57db72aeebfe5369d91aca0983b3", + "0x373f81dd55fb3bdc9de4c42028a5bdc970cfda825723b6f0f7804b50a1754bda", + "0x3af64226f4eb3ea6bd6d0dae027bce6b361b30c50b4a65a4e1661577268953d0", + "0x35b96aa54e1c50049a0c91281c75d3d06c4b609a2d3d92cb22d1328369adcdc6", + "0xb02c9650fc610b3f5a0b547e8bc505b4a840e1dea123b4cb2c8af6232ae1359f", + "0xae53d65eebce31c14b787f1df5b021334312e8d5b8302b84f6a56b6608e25d97", + "0x4901a419abac1937602d98c21e937a03db8a48d088e56895788da845829225cd", + "0xf5636fb8f3a381476267e6713f10763cef51071b6d981a8f661a24ff6d368e71", + "0x059e8319866374d8eb8372e71998cc9277c5f5e5968c126a81d87d0d7a6fe8fa", + "0xd5fbcd3d7a4387000e014e67ef61d4a7ce09a70374ad4fcdb6ca0b6b50b13ea5", + "0xc37ef88d74d307090a0dd49b69d5705c8e65ad606548b0880eef33b8346c2af8", + "0xa316c8a8ac949af5957fc905ba39c247a477224cd9c4cbabccd0671dbc1e17e7", + "0xdb313f10f0dfb56b8684e6ded5e89c4d5a3cd958a99b1773680db8682645b9f4", + "0x0c81ab956b95426f5c327c6ac6db2fbbaa8fd0f41cc9f58971d5089a0f3c52c5", + "0xb09827a7c1bfba1fb7e5c7acee1da5d8fda1c10da19046151f55ef7fefb784b9", + "0x4332b07750799b436dc5b8521feb0927d7e59b25832ac83876da4eb9df333aec", + "0xdf6895278968d74b85e4bb2c53d70772a6176322200f864b004ed914bcc3cf2c", + "0x9a4a6427c038efbb77e255b8e74df6f897590f734328e5be0ab6b16a6ca58e46", + "0xcf683bc5fd50f6c444a84a5524b3e6ba381fe62c39828650f8c70d9b5b6e8d47", + "0x3282bab4eea18b9a8147d6dbf26073882e7f859b498b2d17608cc96548f5ba7f", + "0x04684c3e47911134ccfa142c85d283f26ed315b5818a523a79e9be31c17b4dcc", + "0xa8efff633914b0ed52a2eb3b75d6efbe1efb0f640136807db13d8809289e40a4", + "0x4502554b0b48e3230e24efafc4f8eef7ff50347cea1a27a15ba46187ed0fb2a9", + "0xe0d6508774e4d8772bfed391286d5f13b986518dfe49d6cc9fd55c415e2382f8", + "0xeefb070835b6cacf8237566bfbc77b177ad0e3e6293587d76904f5cf56cfe62d", + "0x06162414a2b278bf48122286cfd04e83ab148c91ff45d5b90bb3a55d374debb1", + "0xf87fcab4bf30f560c5359ee594e263859f1160f3ddd4186918093275e271d520", + "0xf3ea8332782f88dfa789e42eebba3ec9672589d090c557e36e05c7eda9c7372c", + "0xf05f9c5ec95884e6da30f95d56ad58a025dd696215ff57683d6946ebce25d497", + "0x6738c17f58a1e7d41a634984b98a5efa47e910640da0fcd80d2ad0603c0ec9f9", + "0x8c2029217e14a9bd4dd88eefbe6ddf886d30c56df42035464a5acfe567406dcd", + "0x5d0434b926b112a81e7276b96d1dcff0391e782dd68003173a5d11701a8fc190", + "0x4d9a5c9209364544eddbc545822bea83af527fa1f7b24dbedbdda61b69e18250", + "0x3e5800a59c58a56bd2cb7659db0705f45b6b8e827cf06eb0fe98586abfc83368", + "0xbc3f4d3a46d5fe6df5ded66fc47b5b73baa878c9b8fc3798e87a17995614c515", + "0xf715cbf347c5308a4d50c99eeb4882c6244a03ca77349d126337ed3861e454a0", + "0xe831c5b327832f9440cfc795e7f703cae82648704d05f7bd41b2acd4e07b2c1f", + "0x46c6926581d617ac8384583726ec7088f1e0df60bb075a1b43ab51fbdaa108b7", + "0x236eb9d731c98bc8407bcb9954e3297c51ed6a116f90f6d1ccdd8f4c89bf5dd0", + "0x6ea6994bc6b93be59e0e8f48e32f2afbbcc653d4c1b845625b8a5e280db809bd", + "0x3af35cfbcdd184c7579a273a73361271ae9e1a97ef89fb1f0e6dfe89a776c237", + "0x7553093da896b06cda700a41c0233274a089e633dcb5fd8d81ff0393491db2c6", + "0xc555ae61e8f86c775768be4a07045042a8d5898ca6dac14687327b89303d9ad2", + "0x4fc388b57b8d35c704e8c03be70f1c9ba03e638ffac704791c0aeec6d3dd8e2c", + "0xfd0ec61b6a525012d03781c254697a98ac0d4b1e55f46e3aa1ab819e7a90436f", + "0x1d7e68aa18a225ddede2856f421613f88872e89a7024919590930c43326a5bf4", + "0x37865c43f2db20bbfd51a1440e7cf95923c6b980ac6b7e3173d3f867d60d9b32", + "0x44de3419b85216c1d2ab63cf3a002c28835dd084c2e3ee0eb4ba92dc49d5a1b5", + "0xd5fd4d94d504e021eb7865b8aff7ed53c6afa96970fbacd678c2b78fd8c5badf", + "0x479043958f7b84ee3c20a9503fb10b3ecbb895b2b4eb4f69b3ea0b5243f881c8", + "0x683669e82fd55e4162c00a97b2af897395e3a1d3dc51c7f12f4e01e4e3cc3ef6", + "0x9dfc309c9a3382fad72a40825cf621e1dfe095aa77e3b00bd5a0f0c5445d6a34", + "0x63def4af1a927f696cf1abaeba3c172de583cdff6278d8db46e23ac8063ac042", + "0x682e98b0482b1282c896bc2920ce48328246d8d3301b5059988325950f19e0ae", + "0x929abbe6a8ebc0ac32f5ec6a8c1f728d733284e81c02477f606163521d86f642", + "0xd3deb41a543048541beb8b96a1f5b029da6ddb513327d025a5176e95dd4ab1ed", + "0x886432bd185ec9c30a459182ac4467aa9c0f590de8825712c8fe3d9cf7bef9eb", + "0xcc9f64743d0672261a614e9e5c09e9f8416d754f9c536e456a08ef885569a39d", + "0x55bd4b7d2d2ffe8ffd7054d1c8f912119ae793a23dd2d9a10f0ba94ee4b8ac9c", + "0x00a86e2d5dcaec027c9c49853eba467e910f39b4cae50bee85c40b48d34313c6", + "0x89ebc269c4a123f9622e89fd221d22776def13c4a9637a7f69176504ed48ac2e", + "0x808d7a4793aa0afd91d35a6a46eb4f3ed522c77716fbd27765ad2104d2638d75", + "0x5766e58d79181a27639e4e2b1c141de7825e6abe3996d3d06a518bc87044abb0", + "0x53e304b2ae212fac8b059d283f8f97553cb16fb3332e8833305a32db18abb5fa", + "0xae7cbb3a3c753f730905201d09056662cbdd85c288fe94265aec6f1791ecea09", + "0xf6521ebf26b89ec9e3f437a8e3f60aee8063a821aa8e2e0694a90835b782b2df", + "0xb1e372bf9048f7e44d08b12c45b0a17028571fa84238954760da69bf7565cfa5", + "0xfce7f2160459a7e6aae2c85d9d48b5005179c05d703ce890a74b21d993fdb05e", + "0xc630b644d1083d77a698f658819ff7440c3e688aa89e18480167e651f8d1ec67", + "0x15ce3af581eaafaf4456af97352c4feb66b25aa20d3bd711221bdf8532639406", + "0x84600535f9a3338270d3055cb823c2d5a3e7e8a0ad2cc8be198557ea69d15c01", + "0x970435f2511428138573c6f1d67c860703ba5504cefcd675c0a77c37b17640f5", + "0xa6c0ac36032f2848a2ca230a5773760f2ea3afbd1294c0c8c8734d24f9a2c6ac", + "0x3cc9fcbd313d84afa7277112910029782b3b083500080ff34e10507b8b85c249", + "0x84cb76db3547f6ae1c91b7cf3196f8db451c020353776199f44b8b529c810ae4", + "0xff50e061106f378ccee04ddeaacb2aaf2af4ee90b1504f13a88ee325de268eb7", + "0xfc0d53a97fcc0a95f8681674e2f174f789becf7301c0742405c6cd28749acf3a", + "0xc0853233a2d93a9fcd5c67da4c233a248df9bd424d3765546c1ed39c42a437e5", + "0x8fdfabd694bd2266c71796cf19e8d4967ab9a42dc0d6aaac495c47ed4da9373c", + "0x2a8dc4cb7db4cf55beb0eb8662747d464e2907a3dfd0d58ce1067c85de2be0e8", + "0xf082d07fdff2f3665019d0fceece5b202c79f8c3b13d4f533f2eab2a83925f23", + "0xc155e24d5513d109af50284b49b723cdb1f812ded6d65eb1336cbc2d95b91f0b", + "0x435a39e77aa40920f0e7a67fa4547f67e2f099775f3f8a3db3dd1e48b0b2c376", + "0xc9a68f80733f9b39794101dc6750747cb6550b7858773de7e323140b1248839d", + "0x482140091ed9921f8774a0a1acc3644d2ec7b7019a5d50a0e8f42d9cc729e94e", + "0x88e75515699bc267d85f9410411ffa8ea0a852d7ee2fd2826e1260ca0218d497", + "0xee78dc1b01b7938dab9691b3a44d10497684fdecbfa4b175c3c688b22c9f563c", + "0xf7982d19a9779ea1077bf9cf6392057aa68b834ea3f8b301530484c0b9bbd567", + "0x125ef0450026699707ec50bee796181e783efddbf4141f3cdaa000ceada9b77a", + "0x3091b7728400f191e3764d5e9ecb8b4887e5e99fdc36b67d1a6f006c16e75ff1", + "0x169d3504fb8dd8fe74afef89d5eecaba66adc07f119f1fdc03b4b22419d6c586", + "0x6fe28b55a792cb900d1b830a047653e15d12374408a4b5d261e6b0daaa6a654f", + "0xe4adf68e5daeb9bedcb6329924c76eb6ff1770e93a7b3ad77d456bfb414c0b94", + "0x2ca7094ccb9beb1654ef7aac79af810e31f48e0063525e96ea4cc7548283b120", + "0xf087f8821c63865ada8f912bd4da2f6590d00a8a8e530c50d09600be91ea879d", + "0xbc106c39ae71e3d8d9c0b8869c63d21a2833cd09104a7fe13c988a1bc115dcfd", + "0x8310fa11f25180a7eaec83ad49e58f8344bc1b7b48f15ec12c16afb4399d4b28", + "0x5d9902bf98d0edfdf77a8605f15dc36c0d9fbe8fc16330099d8491450ed97819", + "0xe1715793831ca9e851f293dca235f53d1985ade89ec0dd08d8478ffac8837fac", + "0x86bd483291ed25a967f742e4eabd3f77e178be0fe9af43ce61595fd26e4089a5", + "0x3c01d8d2282c6406878471d453f97bc4247ba285ce0bd1fe7bafd21f617fa760", + "0xbfc1bfa277a866dc1b1a6739648202e15a90718c67db76af083ea57229e9ea03", + "0x1ab9c0778dfb859bc6e13cf425f29c796de5889593130ed9b591e1f854de51f9", + "0x235936c148f7a6c4875dfbf30b9a4101cbf329e3d682ec3bd2a6c79473efcd61", + "0x70c8282991bed0d69a19adf4c95312dc44f24822f59b915c8aa93a2e8bc322f3", + "0xeb2111dc14eec6dc250a382b529af8314a7d8a25bb7672c35685a53d0a6eaf2e", + "0x98242a2cef0a5d9258fde45048730a73321b46af2d218203bfd3da274bc3ecea", + "0x41de7ce88b052390dedb6dae965ef4b3254dfdb91ef0cff77ed0f990e6d53d1d", + "0xb307a83fb32e43ce73d5be05b8dec5791b55ea97abfa2916c3a118540cd8cf14", + "0x19c74a02ae96e9581017b8d1845344c0c20f7cb8b8f1cc0e298608e25429ba40", + "0x8fd7b83114f3294d9ef1994f96cc5dc3309b80feb86d7384c4797bd88914b4eb", + "0x6cbe4c1f28f393db37851436a41d739bc6d64e32553bc3b74a6d390390e29c9b", + "0xaff1d11010b3a90a863334bc65678fd1b719a424271c6a384321eaced720521c", + "0xb30947d573b684f02f2bdaf32241f9984e0fe1ccd2398013d7f55d0de0e8db7b", + "0x2777c4133201edad3b7478cf06b4418573bbb0b35a94956489f2c207a8ce07d1", + "0x852612bd283bec671358a009c4c02f57d7b150c466a673ffb7094ab8167e195b", + "0xb9b88021540165e714518c5ea97152e7a57214c2bb30143d0aeecd650b69c011", + "0xfa3a3d52ffe85f56b28a7d3613c50ab16a98dd0e5b14690676a0917b0d9821a6", + "0x1b4251f32144ee3ff35ec96c13739bf11940a7b7c0ad7819fb14508e37318179", + "0xb47b35b1a9efb47e5267e75bdd43cca5730b1dfe7c74fe70c854c26bc67eac20", + "0xcfcb740a8d76d44484ac862bc7bdf6b932a76a1128c77f4543e3310ad408416f", + "0x3c01a05b0ca98646fdcc76b2a95ff1ff958f61aa6f7ff199bdda9e354a7de21b", + "0x337c18196aa613d56cd098d128126403cb03b5172175f9b0cb3599c76499c358", + "0xe1773100b144b6612c5a811e80b6c4ce002ca6c0afedf9e2c82228c0d499586a", + "0x7f10533e666fe853571ed79da196262e8a69c2cb99222d26e0165808ab6d7582", + "0x2532a4dca10fcdb5d33c84c0b295dc6bddaec6f29030f4a74585a7718aa04bd7", + "0x1f6c65ac839c5e76c955848ef97b3aa1a095b9b77faa155278f793996cb8d438", + "0xc80d98e457a316951cb28828744885346b14e545dee625ce24c062ae30fb7867", + "0xb12c58437021718ad76e64e66259186a53421366acf78f871d53ecceab7bfaf3", + "0x4fced8fe6a8c19e32144376daaf080b4d6c8a77ab8e7f91d099881fbbfc091fc", + "0x1c2afc3229797fcaeb2df0293259564f45b4cf1fba17c2e5e266747fd24472d1", + "0x087e44d23f6cbc2233738ab793cf30306c222445e2404e1346c1609ccafae040", + "0x75e290747c7001e7e2fd8d26ea54c3b733e697a6dc5832e9c518041d58810a31", + "0xe7e457e551cd6797d18ce084d19d4d87ed31d07cde475f2e25f5ed1b750c2c64", + "0xde5c26097beb3a1d3212c9aa0de1970f599a16ecd9197abee5b3a3b281e57cfc", + "0x45a1df846c4b8b4e2ff8d674d7133bac3e98098ca6b594714007d2e5f211950e", + "0x6617fad5c634c52d5fa9118e6cf0a53d5f13eec7c1ac9220f15ef53746c82aa8", + "0xd34a1393ebb316793e8fce4212a9853a4f44710fc9a9838caa605518b4fca573", + "0x3e8a846225e07e62bc18df6e31929b830aba74aa96fe661d5cc0b100fd999b17", + "0x3193c7cfbe7d2ecca6d37e6385d69463362d4b12e6f9e4d2f6ee996e6413afdc", + "0x2ce3aaebfe489553bca7435ae95401731f4cdfa2256a570f64abfb407f7063ed", + "0x3173dd10922eb73900cf8e32f91dac0ad05d347c9068905b549f743a8f16a751", + "0x62fd37c8031ef4693dc0de52dbe06c293249ce2ce4b3be0b7a02c607bfded1c4", + "0xc2580dae73e6b96af85676116914b8a247ab8b368ebb1d2d38640b8a726fe0fd", + "0x8025d1c443ce28c8d35974af5e31d934bb3b08cd10a24c95bbd1efc78bc7eb10", + "0x7a05e4e6aee417c062142c03a47a8be9674d57b445ec0f8629936dc9f5bfd52f", + "0xac55c7dc4cd5f7a90bfd9a386d598e95501b8aad159cdd0d8ddab691eba76049", + "0x3296a64eb4b70230366b27a448b42177c5cee1fa7913938d4767696a6570b4f8", + "0x478ecfbe71160700d04a9052cbb91d62920db80489534887c382be5399776faf", + "0x4530a0a6e3fe3fee4e79c60bd0599c76dc82e841523ef667885d4b1cd02ddd4f", + "0x25d4fa59ecec69d0ff70e70fcba3c7fa6ca5b0689048ce038141293775a8dcd0", + "0x03020dc01c0785c3e3fed74535db3aa3546916d25cd49876839632a929e51268", + "0xeb9ba2f7ea0d80cf7a563ce5e7edbc4ef638962a5a4c16f74ba8feca76668a0d", + "0x6a7a46ffefc8ff2edaffb608a0b7f57ff514398e54f4dc10a1d4cf218b20c7a9", + "0x5bc4c7f447e2821b1b4c94e2eaf754e9478c50d2488d246243b524e8addd18d3", + "0xd3eed3c14d29c81ec39a8ff6f75bbea5a8eae9f713e2e2e54bb6b824ed05028c", + "0x39429d962be1e6aa0b47cef6fb92c3433c54775718d865d5cf7110463613b7ae", + "0x51f19c8404e99f31c464e2cdbc5e44ed0d9486cd0efeea7894c740fae39ea641", + "0xc3695934786b04d41b3c5da84445a06e1fbb5a20e344146c1065845acc9abcd1", + "0xf177f104e6bb76e81e553ed80eb7064d3e6b74b2617c96a446ab9742e2d62002", + "0xe827aacb085e41a63526fa9809b3044f2a5186a04ef4e257dff1621c9052cb32", + "0x9fdd2ae7875a3129242552756462870f1bb831077f48b436608fbc9c11a0d629", + "0xacc8c222a52ca74e17aafa6f0f1d962107c0ab9ce4445a429ad955692d7c7aac", + "0xfea8015b875507e5621ad868954241c2b6de02545a2acaeb2f9109fa30384215", + "0x869cfeeb4898e17ab4850bd5e3797bc141f4814e5409df02725d345b57c64ad3", + "0x38b6c1377ada6abc07a7e7f3a92779907ce2f1064abd0b9be038d6ae51a4b276", + "0xf54091e4e9e9a758fdd8b00b9a78b4c91e17c01ce305041b4bf69d21c743fc45", + "0xd230e2b5c01fbb2ae97c27d70a8a1264c003e815809fb4240f7b500c63bfe82e", + "0xc126f31bd32f9aecb8012f206c64e6c05b60f863af3a9225c8971903290990ad", + "0xf6cdbf25100cc3839c4944180eb9f3f1beec798737a3f6f6074e612520d3de30", + "0xea3098d0600c35c4c62b440181092fd61676c207bddf3482c31bcd19fb352c87", + "0xc0c9da7c976544e331c40b34830f208b9638670fff5103d0c800542ee3f81b9f", + "0x5fa65f0d1c70d8340feb251a52e955a10151b0cb8200c00514b4a8df1995ca8e", + "0xeb44462413e46dcd9f49c3d5cb556eccc8e881861459fa35d83e256e7e007dac", + "0x3e44a1713f55e1f6f9130b8846dce91f710c1fb8c77298de2d09425c725c04e7", + "0x66fd8f8922d09de2f4e9dbd8d45c04a9461bdb5d88c5df9e897acf165f7634f5", + "0x6ad50a6f3f0db27728a9e948bd18db4d8ad025878bc1401fe8f9786446163bc2", + "0xe93822a027e88efdf7089adc382857f2fdc960c906314284759b6b5b6d3d4181", + "0x883772056f1957b772374333addcd927ca88de3f750ef89cf8dd4ba9f6f212dc", + "0x588861a7f2b707bdc3c85168ae2116c9775321b2d8c6f877309fb02e17a42c84", + "0xc8a88e9261c63b7a96b2345b7ce9d3a9b94d99469b68a400d73d808d84c5b0e0", + "0x1d7e0b13963d58e279ef24c9ce3d67d010dea519afc4bfad84e518a719f73755", + "0x057ab7682cc73ccdde80b76f64ceaf1702da7010953691e1d2d305daaa0e2770", + "0xb3e06d340bedc968190ec1aa0f7c2798472bce88eb07e016ab81033037b7ca96", + "0x6c4a17d4fbfd0ee8ced914ba9c2c83e394527fa36e2027e1b22cfcc49f069de7", + "0x9c66d88937ac802e5fd961fd0da8f5e493de32f6ff63bb8d2ab785e8f87192f5", + "0x3fdb9093f1a679d472e4ea81dacaaec8b3a060f71422ce815e3318ba212fad97", + "0x17792f6c2d5c2be0666702249fcb36904fe029bb7f6b1dca95af32182295f3e1", + "0xe6aafe170dac781c3e576d7616bf963dbfd5d1d27738e0cd6fdd759e6174700a", + "0x6321683aa65da9013794d27333fd3b7d570c4e100156d44e999a930a634a3cdd", + "0x8aa56c35f7c70629a4b9272b1391e13c080c97c03b3ed675bd46737119f341b8", + "0x0f8384a649c8dfc242484c669ac4a798bb19b89f85d4d245b8415aa4dad0711d", + "0x041669c526354ff960ef721d72306b3a9d5e5a59501d565aaf1036f8d6d1aa0d", + "0x0af7915a53ade49d28eaefc8f43f24500a5a12acd06f23c80b8ab675220ade3e", + "0x5aeee4a33bacd934feac2c3e6a46cae5d00cac6ff8fa57167100d66e5ee73456", + "0x44aa02ff76be04a0ac59b4491ae9a6ae8cd475fb058dbd4c94220d26d554126a", + "0xed5b8883a073d192663e45eaaa55eaa840155bb9a201065cc61eefe2917c6ed2", + "0x4d856173cdfb61fb83d755b1957e39609a915c45f3b29950acb4cffd012cc3ad", + "0x50af3f28ce9ce9e95f664d2fa59afa461e88e949a0584407a92c113828248844", + "0x2ab900c46ed0980623eaa1cb61df89ff92d949bfdccc568ccb2183f83ef622a1", + "0xf2765636da2615454790b314148be63ad8008d0f6880dfc7767d36b88b753c31", + "0xc5df53c2589fbb388cae91b2efd03c1c707615e05e12f3e681def70e0d913697", + "0xa386bbfb9634a6f910e7052e188a81c9a6a1a318d340703c8e29dcee4b57eea6", + "0xad19889349d7d41230cb039ed46289e7e9ea0fb76ef2ee427d5a05892fe680ef", + "0xda6802024bf8ce4c2152fd2f1c166868159a2c4c70df00b28ede48644ee731cc", + "0xa563da16e6fa8a65b523d67399fdb3b5492508901037ad76f5f41aaa174a780d", + "0x9ee367b021d6ac2e516f16f48961de800b89f9b7115ae616b52d746b7ba8ef0b", + "0x37aeefeb48b2613b4afac289022e1707da0c596d6d8b85e59505ec5a3f47b7f5", + "0xbd0a3c7cb0d4c60411db3290cd2d0cda5c21cf22d9e36b8dc77fb7f572c806b7", + "0xe5d875bca8c6da0c24c0b7ee191168e22af7c99d3b7d58246eb1675bd3c090f4", + "0x9365c55d9be42230ba376054ca9df4346803e63ea4cb683261de4c497f92b329", + "0x0b8024d771e5f167db261b3da6f16e745198fb5ff550c51e689c3387fafc3efd", + "0x9cb78e33aed15fa5b6094e978883d147e8329ccd7371518cbf6da96b97dc9f70", + "0x6f6dcaf8f0ae184c7c065e322e390f27e27f3c4c554158bee433430aa5319108", + "0x0c729da3730254b379cc130776a9ea79575e7cd88071423a0635aa18f4aed0d5", + "0x0f918fff241f4492e630717a91c58af660b02201a64bd14d3a577b1c9390f5bc", + "0x6a33af88b454aeb3fcddcfa5043af313158de701d5227915e2d835bd8f2eb7db", + "0x7344a8e8ceafb36aee8bc1e3a1ca73168f583ecc7959e72b8a223fe252ad60dc", + "0xf457f0572ddee6c71e79f5f8d0643e4b59abd1798ac9dc5f158ea75efaff389d", + "0x0cbe584ca5e7a45b7fabdda306eb5c0f9b015cfe6f30ca451065bb38541b2bfd", + "0x91f35848c79274053eb0294be8395082ce4e5c08b5e6560fb9f3758609066ccc", + "0x4999f6428a7e0077f71eb127218270468f57561da1799470cfd736992013e074", + "0x042f9db538d5b8344279fadd5d3c8da5b4b9b455ee1d94aac1606272d052eca3", + "0xfb28b022f556e4344360b479d809cdad7ba7ee86a5e4943928f1dcf3f57a133d", + "0x687178fcd4ced35dc148a0e142276524d03240f750fe5cfa3d034e3fb9fcb4eb", + "0x441172f8e8b24698a50668aa6136b489bc85b7b21648e29f8ed1683399e7c56a", + "0x5f8c54d03b4fd64a2e5b526058bad1a27ba26f0feafc914fd6fb01b7fd31eb57", + "0x112af02bf0fafb42cc9e7b2b3985c5be78c3320550768d8bd271d62743a3a04c", + "0xf84b6ecc88fdd759a1c2263a0a4226a753b62a10df3fd7f094a1c9df7ea5918e", + "0x54ae04f6da0a8351f4ee4a2e36e1832329d5b6dd22452374abe1335914b36baa", + "0x52ab4533e536b7649979822857b1369df6cb0299f0f4ab32da6b8a7d2cff864c", + "0x8fc44fa1f6fe9e0b96b1f72da8b9936419a10a49ea5c02ba543a22b9f32e0618", + "0x95ee4eeba33f81a8d5eda57de81c3617fe03f785e7d9e90c085b91fe23a57a1c", + "0xadbc77bb5afc1c93a42d799fdff05e15998a17aa17d477611d9ba1d68b4abaa0", + "0x80ef051da1139c8f714f152629ca8b4607e82abc097d5f67bf66e26e3ec4b83b", + "0x6dad58c6230b60017db9536548b99c725644168f55d4cb2a1a0353a5e948b0de", + "0x8baa0703e1a050c40f85dc850fe477881f432c951b1cc1b2b71ffb68ab7fe0d7", + "0x14ca94dfd343548e32ef5659c043d6e28f0e577fd38da1ee12f11c08e281d775", + "0xef25357970c76a8b72a6e52f49bc30651f711c7df70444d4667e80febc0e3b2a", + "0x41b8b4ebd5919dad3bc609ded524b97403d88f019367f0f4f622561131644ffb", + "0xb29a8ad1157621d0120aedbd8dfeb4b318979bd43a5b018bf7b9ce33d85da312", + "0x9ddf78b5d67ef40454867ed33de83a01cbd8c18fe09da3d9f991a196811dfccd", + "0x3604121f9cfbb5cf552cf8bfc9a7958332eb97131158e4f40f4eda481e553991", + "0xf1778830f694720a6f990f9d476b0f365e8a74880253b55ee16f5cbd6c8082a4", + "0x89831626d154fbe84a4c62c3e2638cd00e42b3844c7c7b98cfad113abdbc5347", + "0x650573f5ef274b2aeb40642e25fbd661cb0eff66245d7cc8f6fb9e9daa80fc12", + "0x479f6c652173efe94abaa850bffe1557847b26f286467013a4d72973e05e8e54", + "0x7096619d5716c34592ac2d9907ac28a74c6f6b1ebb1962a0217df82bf3e714d4", + "0xb7c7edbd8ae7eed58e973dc0750adfd04042ed56baabf372b111fce3e4b4469a", + "0x25529b597bd15317e55767b3fbfecad0657aaeda99f098186b41b70811f7af2a", + "0xd790747b09f925fd155b7bbdb5ccd89d873277163e4fe7054bbf71c0b26b8072", + "0x3aa0b221d1c4743a06692f645f38a8128d55f1c07cfa6e9711b0d2e0f2e0e738", + "0x26fb5017218cbe4250d2ceae751e99b9a34d7befa162dc248ac008c5d1221e71", + "0x0e4ada59854027601f8f81fbdceb95228db667eb65fed97cefbb35dba21d3b52", + "0xd3be75ae2da3e271dd85cd8226d789aa12d108a4b0d2681462f6539637572e50", + "0x6f041891c8219b508138f67c95a1765d08c5ec06b9ce585f52f837806fce0609", + "0x9e106515d0e80b41397b2e8e98adbb7333e76265917339a62063a07d9a7ed311", + "0x25f47483ecc5ec32f94b3dbcb4d42a4cdbf5c279e93567e14afc742a4619d3e0", + "0x5d81afc54f6b68bd820dcc629ff7e9d8397da56ffedef9addab0eec620de0757", + "0x36e192130485f248925d4b0d2fd98745a76099eb13f53093621d216d0aff0d6c", + "0xb906e5e33b63f6cc355c13b8461a260ee25376ee96909fad2c6ac121ad831496", + "0xd68e7e0d136e30f67ccb7c21e4dc43b0ad5536584e4b77c9da8d903a04e9d212", + "0x5aa7847a4bddda7fbffa62325da920a21a11524ac1b691bc3b55e4d1790f24bc", + "0x331f95f062ed1d38dd02b5ab6a95dd238ef97c5ee9777c938697340c902b4b5d", + "0x8c6a580c8b07567f747bf20946023c3b581c51075cce5cd5d47b0d81d8922135", + "0x8b89483810a49626f90846a0b49ad3e2172657dfa3003d58fa2a43d12c8f4090", + "0x944f9a5754800a33d903c8a464d602fc9da6af8ff3990c3eb669ac9cd17891f9", + "0xc75c82a2c1ecd875d16f343a58835d756740902c246d3b1deae97e49aa19f98b", + "0x1d2e0f2f87ff2b08514b18855c343966d42e0f1a048ddd3d316dca6e06292db9", + "0xa6508507463e53b3a840dd55ed9be57c8a56e1533c9001276750bdf19796f8ea", + "0x01eb6b636b1852e8f9066c12d4e6b7b06b90a325be4d97e08f7f560bab4796a1", + "0x8a0d77fb41f50808ff0a46dc9f3831a2b5093f55ec2e94a3d2e92373ff3b5695", + "0xea3383ba1d30891d1e236db2b31373541f51a9e5c4b4d017cc4960480dd20311", + "0x01129e8d7eff516a225cc0db090e4e38362d9eb2d0571ce00f4417836de2e375", + "0x92feaefb7f9466814a0220e536fe5ee73560507d071e059827d406329e609f87", + "0xac149150c11b3bdc660320a0e955f154fa3137549a73951207659e2b903c145b", + "0xcb68cdb224f9b3b0b0f3ca0056e70817146c9ebc75876dd952e6ca8ea896f2ac", + "0x157565282a12d790452e343c9762c2124456039729f3a8f97a2cee60d85628fa", + "0x42eadc181d59d8d8b26b37e0e9c9052e45bde72090d330bf9cf21d9d3c7d9048", + "0x1ea0ec8879b200e259a3a2a0f2a7aa292301784fa422f7c32ed5d945183948b2", + "0x06aeb2956be9d74ae4ff0b8a6c1874ed8ba46a186616356dc060bea1cbe5c628", + "0x814b0382b52a155a4e35639aeb3d8c859afc4fe5d151de3b0f1bac646e40f2eb", + "0xb30bf3e85be41a2a9e53321ee9f03c7078516c72c7e2d8e7e3134de709b61c36", + "0x1f97f5d334b5e6ebc72f5b846f24c7911f4fd1653f89b3477ce4b8108342810f", + "0x84c6fd181c28ad159ff18d203d14f966668468c9ef0a5d6dbd863886a7e0af1e", + "0x4b2e6947d55ea504bf205bae9dfc0e5402efd33757eea4da00a8ed2a6a3838ae", + "0x85f31d45128bb91cd3490b58a0a641ef77246ea9c83de30fa89b621307fd96f3", + "0xd362f5e6f8cbb216e66eaf49e4df25e01504ac729da86c530871a34e11d302f6", + "0xb7860983b043bc13ce5a27135eea12ffaeff71879404b18af3079b98da156bf2", + "0xf2ff82a679b2b90cb9f4a3bb903eb7ab36ee1c47cbe40024d8d570f5e16bbf4e", + "0x7e34a7e6673146b6bb7f78593b6093ef15b8e9fd1271b33dc5f7d17876b31871", + "0x725c97f83b4cf213296ef353e1c8d64854ef08983fd61320088b8d9e2ab33849", + "0x18085800d10fc7845148835d0ef0ac980a82eeafc44e12bfa296f9c38fc6e19d", + "0xc6c3cf95310cfd0254f0f8e93a3c25bad2b17df04f9c51a25927b80d02e06b69", + "0x822213c1b03cf68ecadc0b7572d37266207d5fe4efd5e56a924b0a1aab8a8e84", + "0x1ff46ffd2dd880cca76244f6af1fd8bddbb4b9ec58f86639821a16f2ff08f3a8", + "0xe9d00df19d716dc859922f2e6c907263191c8e531498ea557869ea1115317c95", + "0x6d3f1edebd562e9d1a236ed7a1d9104fd8f5a086cd78d35c7a65f27c269d98ca", + "0xfea701ced5bca0d5043512700598d3eafa0b89dc02f3c157cd1d52bcf4d84d9b", + "0x556c1cd8ff3ebc2ccd4eee9f1ad3837e346ecda961da17c0ee9cd4d084a47653", + "0x5606be2fba065424af76c94d4156ea82f77d9872ddac7a4c2517957a169e58f9", + "0x8d0223425b48487db1b371c966c7688435f4b9fcda75b088f0aac203d6657cb1", + "0xfceb55d8f3048a3f2255562e0a9ee342439253abcd048fac151ef4b910048e22", + "0x360f76e4f2ef49632e3bf8cfc3afeccff6917e98a48d3568148c3bb13f9d2d7e", + "0xd87bbf8397204cc2af883362646b0ae95392303935ec1997ab052c194e0ef117", + "0x9f1dad9dfecaaf117ab5277caf672b70540578e703c2024d3f23bb7cf8d6410b", + "0x5e130ccb23b7b66dd2fbdd912d6006d2820071dafe2890f593f952028aaa19c0", + "0xccd2f182107992fb9b002b87cdf7990cb2810b202b2ae5d6ef5e0b3bd69632e2", + "0x4b40cd83205f8b946ca9f11fc3306872650e658e631511fd4080bc8ca749d913", + "0x652acc59b71ca20bb65ca195d1a4b3e177f6a3985bdcd6120e1a45b7d4a0c7ca", + "0x49a5e2580ceb329665244e489592aea27d54da8189a665d9435e037ea70c46a5", + "0x379801356beb3a8e5fa7311792c69c7ac1f675a9c08c837f9f0e9f53c243d6a7", + "0xfeff4543c70356b7d9767c26b228cac8452c95bc4875e92a60d7e6fc50468667", + "0x82eb18827313399cb3b0d3c975eb9a9480c3aa5587ce72d321bedccaaab56115", + "0xa644c582a751a6d8cbf30e59d6e770a6f441c017b486cdb23e6b9c48c614967d", + "0x75e6f4d4185515a3c58dea60b55d5e50af053bb261db2d3de00f812a4072ee2c", + "0x9018506876afe91cd2cded037f41c5ee8503fede2a59c47dfe7ea1b36c460f73", + "0x0b8bc06bf211f715291846c6c34b805b6aee91ef4e8c63cf3d15ec79b44ddae8", + "0x150e43fee00d798b8611d4e03838072d8b9c8ee3771e840ee2c161a541d6b643", + "0xe98c938110bd4227c660a9bdccba3b5ce5b8414d909514502e8f354f96abce69", + "0x0fdc3bd666d74a99e623f6d4957bcbfb17395bbdacb52b18ecf7aa5d2e4ad2ce", + "0x2c72d738e803c0522b5f424731ad6327548ef08ded4caf4ae0466b2cf171ac4b", + "0xa7709a082f8a2ed01e2e88c4a2d18930f510fe5b831d2a1bbb1a85a858f19e54", + "0x8ccb960803f6b6e87515ec20a36734128da0dd6e65845013d89996070d3cbc69", + "0x4ab2e49286c8505f32ca54314d1b5c3b2952578d191c69d1cc7ba78a000a01d4", + "0x6bb792b52949c952f20b9d11274c8a05edb44c4070d949bdfddcb0eef2464454", + "0xf61eccaeddac91487b2f5d7b3ec57d1ccbdd0e1307d2f624319fff525149941f", + "0x2dcf01b0d9ce31c13c20959618f2e5e0c7f8c48521f00c12c99d28bfcf202f57", + "0xb1e83745e6013706904b7322350c8b453aaaba0a61ba89f35eef8f19759ceeb4", + "0x8a2cd4944bee70696aa216b453774f4d915dee4bb78c8f7ff55410cddec318fe", + "0x49a78ff97bd4938cd030df23e5ff4d84ace59ef3fdc0099941d8ad7f82235894", + "0x61e2096919419c8856a5473f135f4f9febb102f80eecc90ad60baaed77a99d29", + "0xb95709562a26564e57cafa00d0969305ffdd0aea7e523ba90957a6cbad6ceb70", + "0xb7a6438f176aed77a9c6470e28ab8cf19dad8f77dd3313cfbbbc9276761f454b", + "0xc85a1c37b5a4e1e8ae67df31b369f0b44cdcf66418b42206e5b4a738a0a0bae7", + "0xf034b0d125eb1bd1bbde1fe413aef80fdc136339eed062b97cb9da2f4bc94ba5", + "0xcddbaba3e9e1680a2d1586a1e9e2268afb51b4894f2b41fb2eac5f667b6cb655", + "0x971b2fbd25a97bc710c30b6b98efc90428a7e423c09fe772622e7ea37d18e49c", + "0x8571bcf05c836a59a5d3216634ed1f691edb7bcddc7b5412bc513ae9e1fc0423", + "0x0543d8abe5e1bd541a5bc994b0c7ea5a556575d2e9302d1dc36348ebb7ab9e82", + "0xebd8f9095619980043f234bf4f7682534ae6a15b4584e9d1ae524138471467c3", + "0xd0699a768c873ca5bd615ab5b0fd9c7c6c649c4245b58cb622210ac2bfcf3111", + "0x35bd5a50b11033878751d985459657bd4c0206584cd1def98a355d7ffb0539f4", + "0xd476d2b8b62b720520ba0990137629f83db9c6896f1e788fa5bf08614af1f2bb", + "0x2a8034765c582c07580c0da45c4216bb513171d073a99cbca2fa2adc0c05dbf8", + "0x084b45a575706daccfbbbcc321a9546b0c911861f2639d81f210b77680f60fb7", + "0x499bfc54ba17718aa8f74ceb412dd9b6b6c7d1cbde4d8ad2385a5d5d77e98915", + "0x8638684b06607afb53385f477f0f295453f14e36161da6dc7728336475303a9d", + "0xa686ad8ccc3507627712d203f7ff3be65c289da67269388d0ad8949ad3a5a589", + "0x6d262ff8babed3a603f400501cd77344585fff92e5bab5f5848873042ab87cb0", + "0xb5755234055b3534fceeafcc84d0d77dac220d3466e1dbbbe7d7d44c345e1eec", + "0x92a54b989a1aafd36f979ff0f1fc73f9b1508628f054430234f4460cd9f3959d", + "0x1a48d9bb57e9a70b03c066c97ff9520c177b8361f2b3c343ac71fd8cbdbadba5", + "0xc9e103919e8b6827a1fd57a3e99155a24810f524fb69a7e3fbf486707b2da690", + "0x22a5ba2899ce696fe691a2c545b98ddecb7c0a844cff2375e50e0a0f0f9cf9b3", + "0x154890ebebe7f014aa88f8da52c9713e2b0cc8b9b6c7d29b354afa000c2eb429", + "0xf9a72e3ce36943a442d0dbc7a869a6344003d6a7ee4d344c1899ab8b96746a6b", + "0x270fe45a526aa3bcc8e4a5be075610ae9b15d6fe48b04c6ff0c82a1c7f56e0d8", + "0x9eacbdd695faa85bdbff10bcefcd5edfcc489c3380cb1c73ab5ca6cba2492995", + "0xca15124d292e0465c7e50276cfd374c82391bb668d68a3b19c67fbb9e68b0bba", + "0x9a8cfd3f1b8ad178c982feed1fc306dc996da3d928e99a6f8ad240e55f52cc3e", + "0xc173b14778977c5d6dcb1079023c493406911c6d6791ad08104f847323aff7cf", + "0x82b3e9b9a407ff0596aa7eabdeba10dded85fbf3258d12949ed4f46484e0f649", + "0xb8a009c28a2328b7c95531bc64e072388d797130652ea0a84159c801af562a5f", + "0x80e45ff8b60d28dbb45530b7b56e049e605d28087df7133766de0e151dfbd01c", + "0x7667e9cd22c5427e6f37f215b1d9cd90b2659d5db0bb499daa382e09fcfd58e3", + "0x825014f354bee6aa4cf5283f86e8293c0ea6faf07862abe2cfa12740a0d846d3", + "0xbe9116073311dc303fa29f7a226ff79fd39ec2ffbd2d2270652b972a701aef54", + "0xb3fd19eb6b0163156a350156b15e660853f68a903ea6ed758bf80b2fbc5a655b", + "0x3c5a408909bf485e8c3d8e683d8ae4e7b7149d1f01874807428a3f88e1293d4f", + "0xc759f51aceddb90e6e4273fb9439908592dea649f5202f530d15d455c5c8c7c8", + "0x1fc97f79d1b1d72da309bf2027ae193f0594ecb77c07a472421baadda577a24c", + "0x09c4fd284e5c0672ad031629e58fb2776d1e772c6041c91433f287304dfdcd1a", + "0x8c6b40f8700a0638ca5b7bb003c2de6b54e731881a072988cb78ba89557db1d6", + "0xcbc701507f4f970d8dbf15306d6ac5bdd46b6f58bfd2dd07db4ee01c65aab5f7", + "0x6b911e52f43696cab429c0e511fc40011846af92a2631f4d3f2cd040567f021f", + "0x4fa5373f6eeacba61818052da8a9787c4ed86be0bffe0672c0aea792cc3d2d49", + "0x518ceeb36cf1a406b89040ab0c60e380068f5f6571d042d3bd9a9d7af1b12204", + "0x82039214db7d3beae631682e9249b06f98e16153f864c2026a6edcb0727a6532", + "0x9a9e534af83084007e54dadbce2a0224008a8c42356c2ea650606e8e72d2ad8d", + "0xc4dc0b662ac8d4d987b8c2c65cd27fb8992f65d598bbc25f017c45b7032451f9", + "0xa921f124b5275f07b2c064d477d5779963096632f03c54ac9c87917bc4aa6e52", + "0xb4fe786c84a19c8db63117c421ce53244436d0c04384c62d508a88589f4e5c83", + "0xd57ea382802130e3ee8e7671be2b40a1392ebc6528e2e10d9d51f2899ac7ea54", + "0x224523fcd11abd078840803bbde2c3d1d359a0c2cfdd6f9110a93ac4d3c49845", + "0x5da21f79c0f1030e2a5dbfa283becced75e7ff223ef14a6cb5527434503ac71a", + "0x3e315746e89fd3e662f4dfe28245457c3b8a4ea6d9450b93639424a6d8ef7d41", + "0xe142bd09a6967021c4c5a5c7491b0df3b1bcf13564ac934a2668e1b2252e4723", + "0x2e9ab88b366cba155d1f6093e4edbbafd80032b07a192a35942aeea1bf0f1074", + "0xbcbd1b446853135abae9f330d63a06119a93fb53b63c621941f5a74324c384a1", + "0x7816de8933a433aa2719c99db24e692e6ac6551416b08f803302c7751fcfa3ee", + "0x52c53032dd84842dff6580013ab1edca7c251598ba5fc8b903c40e3d9e537095", + "0x771222b46cdcbeba729436ef39f81732aaf4893da720c1e7b59ebb3fd38ab9d6", + "0xfc440de1896e1b2848f2cc5c7d62c0a6b0019008de8aab41df5395586d340d4c", + "0x0df9b803307465e54cc77ee60dd6988e3d713d496ac0209509c5312ad0f19888", + "0x88179429086844e69122c70b6af8b689abea11e13ba0809743532663e3047c3e", + "0x503898d86c4038eb76124e18459e0d57ec25b177fc79bb87eeccce3fa75f0037", + "0xf46efd490382e4e4a3ac0e10926b46ec56e833769acfe3879acffb13030cfe9d", + "0x6efde5293a9d22e688165f2a51bb83e3b53584f9ef5bacc0bd1d99f5c7df18d4", + "0xc03dc313d9be55674000d061851c139f4c57c6fb46106b98c3442832a51c5f3a", + "0x8ec2accb7c89019d0fe2a31ddada0b8251ebe88a439de9d68be73c0994a6523a", + "0x36ec73d7e8c0181f6335c668ad7713f8eed607e0c302b43413f904b26160bdc1", + "0xa53e90d88a751a78397adc6d2fb4f93ad2b38f0ebd00b32932c4b2a39a276d9f", + "0xea2a25111ca37a53c8fade1ef65097f0cb85e00881b1ff201d36c9151a8e1a0f", + "0x8c1a24ac75821a4b0570c22b682c6030c678244b059ffd4b21e4d3cd05afb585", + "0xd230d46b14f9586f7b1947add191a69ed381cb6fdaa9b28c28869da8c6724dc6", + "0x4e8c717de6c94b4be274f052d9df627c945afe18df35c58a90a035759dce6b48", + "0xdefefe94ca6d93b78ef9f92911eec4c2ae0c10148691755f1624f86445a3b2b2", + "0xfa6c031ec69c7dac9f9b6524054806e2fa524c3200fdeac030d3bf7029ab776b", + "0x9204683278cad559a3f9ed2ec1f6539f34efb17957830d0aaa92b73cd0994732", + "0x2bb26a0cc5eb7424033e8bf552c7964573a0954e5b6aae32a51d95d951fc044b", + "0xf6e3827687af53fc532ba163d7ebd5ce18ffa6384157982b6dfdb1f4be82faf5", + "0x627bda246bf499f4498e8c512c8f601e36a1dcd778f21a598736f83b5b33fbd8", + "0x5816773273e4ef45fbacbe920dc3420602d8134fffe302459891cd6e65627f6f", + "0x7cd637fa8a5bb32dfd7c076c34e0e536d7c6710f1888f5ec18d64191a9930744", + "0xfe016a6e9ffd59237b349a817ba8c36f7775fef6513c4d430fbfc20ce72fcb1d", + "0x7c466b30cf23cb7115a3855d9d9c537c29f380ecfd7aaa0a6e59d9680bc43971", + "0xc49551e5eb138d28f5557ea8e8a8bbc7c058084ba0edf8f6bf64471928ecde43", + "0x7366cd68072f52c5644dc9fbe2e72339705dddd2b03690dd748265723944e754", + "0xbfb7c3bed071283cc18cca4192e2bdc1f97aee9b7185d493a29f20ed4d52ae3d", + "0x40c9fbfde126c8c92cf6d15a18be4b5a4da39ff60ce45cf5e9a2c1782244947a", + "0x1358333dd1b82e7c805dced5dcc2edd5d5784fe8104b64eabc598096c26d05ed", + "0x0a9777f7711b6d9f6cc6ad4a78b716199b57f026d1f30f04ded5d2cd8286322c", + "0x7a848ef083a03e4112c75bef258633779cc495df4ac5529e12c8eadc484baad7", + "0x17025c4c255f509163d11df3cac35c1de823e5ec71cfd66693393882d81fddb8", + "0xed0a2fe0dfe85c7d606d0d1b355518a48220e91202ec1c1178c8b37c86e1c9cb", + "0x4674e5e97dc0c615b03c34c702ceb07aec48cd7e8edc953a188d194a8cab35c1", + "0xa004c31b7a6f6511d7eeda4c400c5ede847ce2ea4339641b6c419f688cc4e574", + "0x1bb6c124e94df05e091f6aea45e7658351fd21318e91105274a15be4f7a7a632", + "0xc365b8bab2d6b902508d075195a1e23b04c97e40217c4ffa49fe16bb13e5b575", + "0x93c1383e2ab52ded5fc86e1b6f6e292c0d0977e8756e1fcbf87b099682060e25", + "0x2921b874e3855d9afca966d5088e9b1cfe59f37db54bf0c1e8bc5c5a97e7ef6c", + "0xfee916dad70495cb45c6ac632241a73869f0f553bf7172cc4e63fa382a5e1077", + "0xc63d63b401941d11edf755d7b6564b4fcba1f84ed99cd08f1580faf2c224478c", + "0x8069f00ca36baba06b310e28f6873e78b3ded25b456d95dad7eef4c517e7d096", + "0x48dc0968af32e91a8a3f252bc0082d7c22f8dd9797e4fa774d5b5365386a4602", + "0x861ffb24def147c4577aaa332aa2b5d3165542c4fd1e1882a9050e5de10f1f57", + "0x9fdfb7305249e7a38068f8099b74c5584a2f2df3f0514371f20042a6c0d2c85e", + "0x90212f15c5d6b686810e1895a139bbc26141181c3c472ee28ef9904553a2faed", + "0xdf967dfde0b63153142628dae7522307afb35b24146d9fc1d35874914244eec8", + "0xfb17a9d9e9a5ab6d742f55c0e8d80c5e5d722e9411e84bc47b1d2fe5fc33dd71", + "0x56b2c30b802088f9ebf0918c7ce44b50a96a0eac98f89e1711f53452006259c2", + "0x4c38b33bd4089a48a65369955540219b44af520000b8f8c346bdc96d47dc2479", + "0x7d3487d3823204a94e557b7a942d7c657c1b49d9f40f2d739a9099d4438695b3", + "0x2f82f94eb74aa2c0fb91bdb38ba0b416ce7e033c7e2a74aea113d201b225e24d", + "0xce8ac4b2f0f74601280bc3df0f5955d033e5c511372d812b36dffbca4b2e4736", + "0xb6ea6c89e91ecca1fbd723188a77370e9d23c3df8aac282cbcbe000b13d31b57", + "0xb8b8b7cb900482562227a0a1256ddbe822cdcf134a196e29b1aa6fd92423a4ed", + "0x0f47ab9f4985c3175e0a30a237d4f7c42db4a58f95344a86a818e459296610fe", + "0xc26a55a23eb390fc83fbdc9f07ee3ce09e8a2b28bc09386323ffc0844e13be24", + "0x1d5e97a7fdf5f34192e9b6dd255c41b63e24e1b4ef4ea43ae510fd1f50abb022", + "0x58b6120c4f0a1004e51703e77decb1c85bdd40bc83654d3f8ce5f7e3b4b6ca25", + "0xa2f4b27f5641d9294ee0411bcabc574f94b294ed8c50c9ae0c3d58caea7d6ba9", + "0xc4d6d3a8b4debec7ec7f3e2a6e1c64de46ec1187ed6e87fa2d87412c9874a3a6", + "0xfb59d9b66471893988d0fed17898fe2b7873d85aed217c20b6f438ed70fc340b", + "0x850df664737f288ae16d701878ad04f399b367fccaa2ddbf975d77868bea7cf5", + "0x4dfe47362c005896f82ac2d02a12ee9418693cd2f5d1bcfdc321980897171993", + "0xb652952de1bf9e1174e5f6a37b069b437792672a37a9e0159c4f36b6e64306b4", + "0xb72dd6cb5df1b00dbbd84e097e2da79af2ce60559697ab4c93b0a8b85b2ee406", + "0xb96fd4a94ac30c10f757691f7f06f25a4900fe424f4eb7ccf322e2f95249b914", + "0x99fd442599036f161ccef1ae8088c5ef694c1819f5b76d9d2fa8f979935f69f8", + "0x3e53574f6ae31a45ef928f9c37bea6c61e6d728a5ade9851567d3167f5ca3314", + "0xd7e3d08c5b71a7ad8338e8b51ec54cb11ad4d643d129a371af07376f8c47c1d4", + "0x1033c8aed4ec46377f75cc9a6b3297e1da0a7d1e74df20bae9fdf6d037afdc28", + "0x924d621544f3301f9e212fbb95872fce9eb4a4172a11693674de733bfc2b0018", + "0x7f61884149ea4def1444a70c022da1c23f31ecc51bb175905b492236a57c7fde", + "0x40c50785bc0665ab4eb3cec95405e17510c571570a5859ead804530dbcbd1387", + "0xf806491cf778f4796c0f73428e6eaf237da8488af99e9b61d72c56fa03e7051c", + "0x7a9670842dcb12c66f11e357a84849cee227ea5a7351e7c6c9370e9ef2560129", + "0x1c974da4e1073157c10deac8b256c8ced77a030e0500b2b8a90b6ca1d32ab4fa", + "0x97ebcc81ba9c1e04865ee4617daa967dec39f65501be21fbbe929db869d57dd8", + "0xa36e4506065d8b9c662697b18ffe50ed2f6ccfe6d07a065bdad048778cc53668", + "0xb9d5566eb0d40bbb03114d333d1d1dc85b0e780ec63229f3b93b2c84af5f9509", + "0xcd16693573724880c3c83834d516be65c35a861b76b43878e28aa7fcbc961361", + "0x4f60ecd7811acc087fc4557fdfaa1a0b522fe30da1cbae5e7740eec3cff04c00", + "0x9e58573b152bf5008e0ea3fc0d64573211916521a62fb08ba0f1b44c5da12e7d", + "0x2c6693cfd7e5bf9a3d8cef9e186b3da25d07af983564ced6238f9191b020f105", + "0x8cc6149caeafef85ec7b2456f33530459c52b30a5365a2a0022b1c308357f7b4", + "0x6f66863bd9909f687523128569cd0894c4cf41e2eddd5cd9c20d30c446b1711b", + "0x402317752053e7b6d7e2d5512d6397112d80ace0873f5f9d32c023a402ec03b3", + "0x2fcd50a79495057908bd34875e3531e6298488f0d06d043fb6fb0b140895d379", + "0x533ba9669dcee2c6e35713c7eca3bca168a326a36b0e39fcde76cbd35ab3d99d", + "0xdc2e86503e8066bc5fac91fe63544e33568a3c744967b9360458101c3d9df096", + "0xf994b38ba312d8bfb00d428b13a088738d93965b525eae81b45b9be344f99fd2", + "0x0721f3f772958d6a58dba638453b8d004e0c76dc8b4cf6d595b712edddcf002f", + "0x3c650c2c7ebbe7879a15882c3157552e8ae1adebea8f0c65a2dda272cc4ed838", + "0x649fe38e87546703245a7adf5925e8c7a07942750e14d39553a56ca3fcbd8c65", + "0xad204bf42d2a444faa864df8e9d023483a6b6daaa8001e00bb5373a45ed064a3", + "0x2c5cdc73d8ddef2e5c0d47358ac180043e7e246e590a7e8ad2b0a3f9b4e9375d", + "0xf38f6c364bbbbe626e849ca9bb9324c54cf0ba8dfc0b2741a3ff87ce7734adbc", + "0x317efc1cea774849d6219d31c8464a15956da4f3810bf15d4353443f79d98e75", + "0xb6796dccdf4d3cab16b5ec9567237cb988ee94131f3262c2a581180b775e76de", + "0x1fde3fdf2303d080d400c43345a424f50f6551a6a06ad50c6e277d49e8034df3", + "0x4d7bc44a3b56f5e69fd3e5e8c0cd8f5f839a775c4ee381b4b1d0a36656cf91cc", + "0x6051b60fdced0c51aa6a1cab2418c8f21c5d174109d514a4c6de758b2056611b", + "0x3c2f7be830078af3c2c6d1557b3da74d1d5bbfd8094f98886a959aa71ce70b15", + "0x8f296b90a0ece0a3dbec19a801072497c5840f9c0491062cd402db00c2b69f2a", + "0x6c14c4697f8291dbdfdbfea5522798e3f8b17204f80d8370e6d379e6ee659e77", + "0x4e98f63afaa50f8a30b0d352eb5fcb5403c635cf54b41545aa8b48465d23fb1d", + "0xad3059433e981ff12cd0d7dbc11a8d92a65cb39c6e936e9c7db5934d45806492", + "0x1cbb21f28ad2d191d6850c97487e5a733306f2f6ba370723fd5ed37cf6c880a0", + "0x82a0010a1b20d383bff0e5d7ba3751bc0d9161a4817554432558c5c2825babb3", + "0x33e54e93443e87c003d582dc51d0b9981ddcaeac4df0993877739651cbf52a58", + "0x1de8bc150f4142cd45b5d0784e5952abd8de7cba9654af959498c0fd0bcac404", + "0x3ee852f48a1a930d671e53c9c8d8c3c38353ee1737c093960c3f841e6c682e94", + "0xa9c6e05ec91e2a2f2f003419063fe033e37e5353c6e233706e29c08693e35eb8", + "0x649f7328064c55c03249d527dadaedcdbb4cb0e939d94c866844192d99469e05", + "0x3a407d00efcd5fe7bb765347b1a3f231b744349269b3aeb44099f4bdd068eb9e", + "0xa1a20af2f7e61082810ce7e7afe6118bc0ad95e9641e6129027f46af28048107", + "0x0d68fc5e58cacb2d16d99a0e9e612d674754ea51cbee2c68a21f4b0aa926688c", + "0x9b3e58144c014343271c9dc90daa8d2f642954b3eda223d64bbb0ac41380e512", + "0xd3de08b676d4f06bbf4322ed4340caab76e6ab7144c97af91c2bc9c749e65b38", + "0x21d626c9c38087aac6262b64f09398be6e4cbf246100d8c2416cab57e9ac1b68", + "0x563a450e35f40279f5946641a823f596ef3ad22a45b8ec280128546aeb0faf14", + "0xadd9c7128e14e670c7d21d6dfa5c09a11dfd237e90709b087e3329d3cd89b5fd", + "0x258cc0f845d8e7438a707f590f55203c6c51302cef4cfbf788b1c7054688da14", + "0x4309676aa14fa8244e0a089c7013b89c9adf57fa952295b8ddb23fc6545c9870", + "0x5db769765dfb41aefc0f40f06f3d005b30ce1f14f04f653e0c5500f651cd61cb", + "0xbef131c9f19572b05d295d7122fd1a09fe4a8afd4e20c5a0f3cd2785b7eb9882", + "0x3f235228ea537332a041ec75cc6cb5663edaa1c2ed1c1700273af73a5d49bf1c", + "0xc081811bb077c6ebe224b560eb6b81f3f813b26789cb06d96110071ffc25fcb4", + "0x912444c19a5e458b79c89969ed5336f2873267baf2fe729b6f218b74d269b797", + "0x5846fc726eb9627e9d070041b92d76191c4b32e315d33ad18121b8acd01634fd", + "0xc899f45494660034d343670856c13a32b230d047434a4d54a772132ddfe3e182", + "0x11a699c18b04e8cdcd96a43b7465f7bd81f8f64d7ebe79dcaf9201cc897f2746", + "0x8e09b134dc8a1735c060175e9688fd001974bf2e3baa5a8e88dc4c87365e0e07", + "0xa086797ebca0a1d446a9289b7eda920b926e1b595c288a9dea31ad225e6de86f", + "0x0cc04369b6036dff78a9856a5173bb2dde380359a8dbe0126e06d6e763a01c36", + "0x4b5efcac86e03d1f67774769b8bcc5d131c181cd4fa297eaa6cea5ec0cdfaa6f", + "0x47272a21a07ad5e14e3f97b237dab7e33344da4db5b2d31bc7cd0cc2d2c9f1db", + "0x9540755fd321d125b73cb6f1884c2f0b2a821d29362194f5029a5e7ba2d3ed44", + "0x229b88922fe52a78090673775f264cd665fe222002d6add2ed29b7ffd98de717", + "0x8fa2d755d5cc0efb01d9fd6f5ae1f7864404ae111d8ba17e23686ea9b6566336", + "0x33a8f2e0775fd19b1302b985bd6c29d4ab5fc63060bcf3df2c3685ab1b19ce67", + "0xf6d6bebb541ef9b84d779c62adb76774bb38a8eba3823e74e0790dc7401bebbc", + "0xa1f421108d49ed23996e55012613fc05e0f86e00f17251b1ff1e0824d35befc7", + "0x2cc572ed83dc6c604bb455ab050c550184a923f4b13815f06d10ef19dffb3c7a", + "0x28220e7d1a9583d68656f03ef4d6fa3e249c71d1b42698f87ba1fc582493e194", + "0xe8aa37b3214abb1bc167fdb6f10119a4019541f31c76b3b3f8c363bb138bd09e", + "0x825189c2c836dda454b457a03ff83d422bf78df1f368434768690fa7f51c57e0", + "0x5dad65d275e69478c81ecaec5b872660205735d9649ac020f65f5ea6ae972dda", + "0x84a1184d8f94fab280e0593479179348f9184d6fe5a2b2ea9697894c42574473", + "0xbef5a05bc7e1fb94465570144499672d95f31fa241b4c510011f6677e2bf72fb", + "0xd08235ebe6d79a8549bcd3d2414cd8afd2a3e2ca22ced226c60aacad1361ff89", + "0xbab5204ad45ec52860023e7474579e7c95397f3c4ac01db7e446e92c19dceef0", + "0x6c81acf2ff161d423a904c457166ff454ef41571d01e73d56bf9ab892790248d", + "0xaf4a603b808e3ddece42e3e123ea02defb9f8ef2546a95c5a617b6ecdb89c306", + "0xeecdbda25b04eb764e322d9a1e5eefad399c9ced8c77b1e4ecfbefcc90bb403d", + "0x9463f4677a2039ca372b61b16d5bcb7c043b26af04aea4d3f0dcdec7bd222070", + "0x27bfd92799b4cf9699d2bfcb158f6727bb986fc0dee780fc1052366ebc4e6364", + "0x63c3faa1a8fc0d531261cd241b1299d4fc13629abb4cd357eeb130505fbddf94", + "0x9a4535b07ff68862f3396b14b88fa07cff7abdd5744775aeeec6868606eb4712", + "0xae59e7c3e0a1df32f6e027da2983d3c55b4ba4d99e85329361561bd7f13ac629", + "0xcc5dc26b9be8fd8432537d967afe12fc668949e4fcf72d97a40f9214975fa57a", + "0x8f11634c83c7a43be8b98335ba617a64c6379f5f92664055c5e1620791134ddb", + "0x14ce2a69d844e6a46aa244c5aca9fb74c127f2151c7c16f4611ca030df365d8b", + "0xb06f220566a5e62570b9e9e49a8b9d5663501ba145b12260fbf9d4a18a4b19e3", + "0x6274f3cf553c45e6ba7ef644d75bf208e08a8c6325e336aefd35dda9cca3c4d2", + "0xd0d685497c2f2b923d0b9f1590a748da8c684a915a470db58c3105c83d8304e7", + "0xf37fab515f96e655f182f0b6e6aa3602f2cd74773329094772151e8c33d1f9a4", + "0xf6efd731481e8553f1d18b5735166499e787009b484b0dfbe4d35e7930f0d837", + "0xc96132b510863e553e08c54e98b5e9c0067f26e421980a6a3bfd4f07480c4396", + "0xdca9d8182c573871b6d6a184cb9819256398080bcb7fd765e6c69cd972a28d8d", + "0xd632ca6f5d45646726ecd2977ffea5c71a867890633f571b359657c0d096f840", + "0xfe3884dbca6bd3b0087466b04e6a5857ad59d7a25021e1d994d059d20005185b", + "0x7f40eb6fb94b05bb43873a98e9d4eb5f7ac90fb8913240bc0909c6be42922b30", + "0x5113a0808666815cfc52b8ed63c649d96f35c365def36ae623f536241b163c3f", + "0x8e6dbacfb5c593d7d7c2650d3d0115c3702cbb55f73011823a202e69ca33cc70", + "0x8f069ac7caa48bce09fe93f4aaef6784d8a6f7a3a09edb82c7512ec18acc3ab9", + "0xa5525e51fd789c59d3b208efffe09abca47cfd6981d36ab44084b86706c69888", + "0xcb4a7e60d5e8b9d22887ef1e8ce339cfcea0ae1fcbfa9adb766ad05d84182de7", + "0x0a14f23f9066ebdb67df31e66f6b8ab1c089025c0ba56ea56d15f73749f47cb7", + "0x0963e3eba12e41d21af7625b8dc487b637b1789a6ac05fb23062e0166942df68", + "0xcb7ec271b2f42cae0027d22b688b19b9288f2b5d9c43bc5b1ea23b35f5542828", + "0x9b97e6f4b2eeee29ecccf9584dc020c8caa3cae51c82f5b58d279eaf0c6ab4e3", + "0xad7f1963ce9993e6172c2ae90c6e1d4d3d3c52e14284fcc1b1e9a56776afb97e", + "0x52ef2ad7bc2921742dcbac9772f13d5c31be938eb1ad6aceb2fa8a163389cefa", + "0x369ead6d900e64ae0b5028df8574e59b67c61dca418c87ce6461eb4c8535fd30", + "0x7e1a18f6199f05f21f9eb5463e9ffd87637d2fd24a23047fe095895c533cb6a5", + "0xe1b8813a95e511aaec9b358d515e624fbc20e551c56328f843ae90b3c895d3a2", + "0xc2ea59f3d1e7bbe115390a4c210142fe9f9dcb1959764450f5b5292ad90e0fcf", + "0x97d235c3f18e6819c08dab4efe66d0f11f0d06f8ffc9686e3f28400e057e6f4a", + "0xea64f817770252b77b08ca2f579b440ec02e833fc88af7c9c96a8e1e07b2cb2c", + "0x185f5fd1f7001b533dc01783c83b7ab0828a4e2f188cc4e26768c515b4c421f6", + "0x0c9de9844e856a1e4340bf54dcaf9dc66b489304765b5c3c6ca20284f5a0dca6", + "0x4dd1d52da1d260d1f0f63bafc4c816b30cea8ec3434e7d4b63a0eff86997254c", + "0x0b3eb94aa246f7c8c871535ae2d3abe5c1b951e76b77510140ef52d5ea2457ee", + "0x27102708eea5d715799642f213049d8ac9abc3b12c76d147ce443dab28af96d8", + "0x81fb3c4e8dc6c658af2901b7aebf7467b9ae045dd0f58fe8d77f8770ac517fb6", + "0xf68dba4eee635d7494bae6fb9f0c44e739b3121d4bc6f6f21b495a716af3cf52", + "0xcf87b723dc473d313bf9ddfa233056036c5658777e831796f1f56647cd040c8d", + "0x49927c2100039ac496d9c16dd12f0a05c9441b8616c69c726fd2e79ae65e130c", + "0x088195c7251f6b9fa2105e77df5620211b8ca783a77f1a98de6752fc442c26c7", + "0x604de480bcb88e908b90451c4142b99b9cbb479167473befca7bea9b4ca427a3", + "0x642fdaf6bc1abbf261a9480fcf9bb48cf03fb80bdd434c6ab63401856c74fa39", + "0xe6b596393fce7a3023a316ac34a1fac18e18779ca5983791866f857f257592e1", + "0x40384a52564fae5df8c3e41827cdf584e38f3f555a54ca749b7b516619071d85", + "0xe52f7c17a4106594563ae7b724e5613e87d8442177f39a36b946b0e335be0e5b", + "0x7726202a7c255a9d7be47af6f3b44c1e379cda61237866554396fb6ec043482c", + "0x665da353f296cde80e3cbcb9c7f93b107d5676e5cd694b0bd33334d74789beb9", + "0xa1157fb181aaa945793b029d3915b37103d050f1f695862d9cda90df4755c189", + "0x449c9daae1c38b3d3f6861b63dc611f147b8a29029927f85c32b5e549df8ee9d", + "0x5739fcf908f960416e5227ff6f95aeb00696f8eb7192968239458a0aebf42533", + "0xfaa6017362d6e64f9ae1b6d11764ddba77cd980261acb5bdbb17b7cdee2d3024", + "0x97fee586909cf8b3cfb2f2dd4e251cb642eb551f1e5d9fa557a21dcb66f430c0", + "0x9934d90e0b4ec5900107784116323b0f76d1d71491cf9c619520478b6eb97ded", + "0x8f5afe4fefb0de810442e27b2bce63e3a424f9e339a0e1f46f6ed26617a4a404", + "0xcd12ed1b75e624f93d9e4fe7dc65407b6d7963196e4082fb459ce354977355a1", + "0x6858ff0c07de87aa2a88498ae948efe6cffade00f3f21086f0a71b8364090846", + "0xaca944e99122e4fe41c62b88e67940332483c8aae2a3a615508f848ceb1c044e", + "0xa8bd3a6b9197bec8849737e6771f563d14d7415707776ce4bed9460588c55c9a", + "0x20e5f18e795844cfcf2326f52ab1e56f4a53a1ce405fd355e0d37de5f6d552ee", + "0x038821cd156d2d9e2aff1ce3525726c42f581ca3e9e2cc75df524a3dbdfe0feb", + "0xb79bd23e10d1e6c7ae749cecaa732966ce3c2e2ea8b640d43638f14d7b78a21c", + "0x2c4d3bcae4a76ffe6924555b320847211367ee37899b187d8fd4358d91264c2e", + "0x0896db7657d2aa8d02166bd4ceba7515b24147fcf0aa34223590fb80db64f848", + "0x95f3b077d9cff92709d46185a7dc5d723f257fb77641e436b0f1bf07947844a1", + "0x6fdd931a93229698b92e6419074bc308a372e0923b35321b725916c1c151cae0", + "0x8c337c36c2027d0f2fb96405f76d3190cdd01237f6a602e07976e09c4a2339e4", + "0x8091a859cf86c1e2c22c870ebc10334f50e05bac2a41153102bf3f698bf5156b", + "0x382435cc836bf1873e489cb4d42d1c1673c5d1b452ba2d16dbd1ca77b7b87a8c", + "0xac5a288b16ed708b00cbe956a14e2a64b321f40851ea25ab1aded7b096822ec6", + "0xee95229b736827a21e0b7154873da3da59e38a1ba3e3b1770de2ed973495ce23", + "0x5168b6e3b5274054fec17b94a82931bc229d0270e5e4c9aeb61539fe8ba4f4a3", + "0x588c6144dfbb33922873946a44f03092bd65d2f89a01b3973002ed38f48917bc", + "0x6c51a964953dc036043b6e8c7fba4a3f6e83295306767bcc3562d9a8cdb04497", + "0x2cfdde11cc2669c5b504c4a82c31ff03e3f0b3aff044519b44bc39405bbf3c9b", + "0xd93200e550400a7179ac7afc394b22b7c710192eadbf429389450e7167191fdb", + "0x5e32f497c606c01c9be8ce1cca5f3cf475f62cf38b2195244a7c93df7d064dde", + "0xb0b74e34fd3983aef31a0584b6a7483ee936622b5fffbdce1411a9db6171c685", + "0x69d0a96a2eca8d6a5c32e700d3f910330930a3348e98e5b276013fcf70c0fe5f", + "0xf49cbb26f2463d38fde553e483de2d4bc6dd85efe2d0e56a2a79810df6af6db9", + "0xe58aa167a26eadf11257f1fcb5da7eef50f9985b590320cc6c015176965ea58e", + "0x582f08d14023a661a9d9dfd1db8324be88fc631cb9136e92f379ad7703584414", + "0xb9c5e584f5e231c2c41b41799a945d60b7ec22487e587ef55e2d9710489c3c00", + "0xd8b70c6657a5bf1fa4b67c4fc046c1eda284d677c610dbacaf0d2d84e4d782dd", + "0x1e29fb536e468abf66b59dd6f48d177a5100a192f1807afc12bb5c97368b8c95", + "0x595ac042acdb51370bf6bfd2b2058dda4781dd7ec330474defb2d5dd00e7f50e", + "0x3d00887c6509b148c5fadde21014aae94924fef363fd5723d80d6a2028df1de5", + "0x9632d419c9fdc7e676b130806cb9c86631aade0adc6a129d3769908ff97e7ef3", + "0x2f91c7ce1158228c8264a6147c6ca396b0d536cdde997a922cde2772b786743f", + "0xf4c731ac2e2612b7e7afcf3ba5911a58a03ef075133923218f54a736b25acb81", + "0x6748a5143ad25f0a461257a47eeab8f057782a438274ced580ca2bd3725d6be3", + "0x05a113b04baf81b6396dd32d59a53908d07a374ebdf17314ec334b3330a16697", + "0xb1bafaef874da14b8a9f883f89a896ec37d9af1b0958f5a3867780278bfe940d", + "0xd93c67d29befe531330c37dfa8b64db7339c8ac35b8cb674d741a414d90d77ef", + "0xb4319281a05f00968367a349e626ec63227412193c30aaface14ac6f7a480024", + "0xf6dce891724a49024535047bee44f889d5228066a931a8f40c18c7efed60f31b", + "0xccdeb308e3402c7dc72588871c23fb4f6fdc60e2a63230f628c5a2951878535b", + "0x90958033b917eea42ffb8bf077ccab8b19c2448113e8a128815ab3441846404b", + "0xed3436553039948094f33cffaff91a7e2b1eab86b638de5c8eb09538c8df0a8e", + "0x0910ba3093e37abaf70ffc0ef6a3b9b82e8c5f7ae497eec14b753f23d0a25343", + "0xdc78d9fceec3add33b92e1a0ee402b80cd87946e0def46f284d26eac46be6bcd", + "0x1d71a82b8d4b89f73747d8073a36acf8496757d35bb452e9cfd74d758774f492", + "0x5399612937722b6fbcb90c1768a92bb35acd4da6168814c1d9deb6156cf35134", + "0xc7156ee3591ab91824b2d4868d28baf11855a63a801b3793f99fdde7867eac7f", + "0xd25b288f3333ea8e33b33f42edf7b64976281e4840599aa49b07da39f895073a", + "0xc6596a87c544e84cfaa2baaa4fb0a93f3fa9d1e6938426ea05a418568a1589b0", + "0xdbf30aa7f1cb3a6d7661934d7ea2ec0665843ea1ec9b05fddd77fdb33fa7d834", + "0xfac2628cb5d70c177e8defbf62b0448297ecb13962638b9a26c5d05203cb2937", + "0xe8c5a65edee74d59e7b9e2fb4779485958d95303fff95bfebc0c1f4bf24ef9bf", + "0x67d21b95f40ca7c991f37981393dcec3218e70d5402d82ecbfcb21ae532872bb", + "0xba19c10601ed47bffb755f791325c50af9229d5c25294f315116fdb3640ca35a", + "0xf4c026f65e31d4606541c4e679d30d7336cfeeb81e9893465eb08c310792c061", + "0x5425ff602e06947bda22cfb687ace85c10896b5d48de144149cba26bac9a35ae", + "0xe11f82e350c209213da7d977e2de5199559ad3793a24a226cb4be367c0aa3c4a", + "0x13fb0194f473a4af296184d3293005dffcd28f1cf4b986bdaacede4a0a096fa6", + "0x3dab80c9fc23caf409e38791f07e107da3b5d0d9d4a64f87164e6d455660591b", + "0x5901803b234ef0445acfcd884baf0777970d3b600b80ab137dc1015a5b790885", + "0x3735e2d0ac017cd2c0570830615ed9eb642183fee5b2c2155e5fefc1d4de2561", + "0xea9030afc249a1e4f6c86f4b19660ea63783824e8d1c3de30e38802f1aea9d12", + "0x9def3e76927de026a1a76f39c242263ffbf94b3ef42fb6e98626b67ec3d8a308", + "0x504886149f29d5eb02412202f04b45f23cc97a82206bdf237c433e83c52e386b", + "0xc84d3b9e84727c2d9279dfebcdf8104762e3b101dd9f39c9482a456f87bcf976", + "0xf4737cd864b198c8049ece5a4f18eea18b48a649997c42504b560188adfb6f2b", + "0x410894a208ff99bd3ec5f925aa7ff6932c4404390df9e337601fa7b7251d09ff", + "0xe6e7e7e2b54bcbe37eb7066b9a3c9b01b632d228c8ed5ef8f1871d9b7235a55b", + "0x8af02fe4657f956a9ede1a9b0a83d67367b43a8f5efdf6bd753d09f428b58960", + "0xdd056794fcb6f5b694934b17ef35577dbec8d04159fe447e0eba02e4ff4e9d96", + "0xef94a3289e9e197b04c17886373adbe66a451efe052fb419846006b5f659b91a", + "0x5558e5612dc3c222d76e7190409fc5d38479e08f6fdf4b7df299e6da968c2811", + "0x5f38cc5046a503d424c4b63cb060956babe0c1de050517d0067eccfa23cb664d", + "0x4c6a04827f46e51378e9ff3b811c878dead62da3ae20ef7d392c57512a09a719", + "0x68fd9806bea1d937063778b245a6788cd992e4fc614d5bce1ffe06e125f67701", + "0x0751a79f86c4220e81bbf6b4692976ed4c315f9b62937b23083f4db2370f04eb", + "0x5651840a2065a3468d97bf824e78455eb5e22b82b45fde7bb69b297c4c40e853", + "0x959d277feeb492ed3393fcd5774f1dde27c6018b07cc4fc93b937ee266ae12ea", + "0xa145f2ed353350a89de97e83433188adbd14107c16c654c131203442c34f2899", + "0xf888fc918eab6f88a5f6c6545d47a32dd558f10d00e86a9949cb3f144b7264e2", + "0x2fef7f5f1c149c87602cbe38766631abc992efaee26dd5b59e5bc361f6901cf4", + "0x5e0735a9be3eb97e790a93502a6f138a8863b0f0c20905bee0ac14d5aff4206a", + "0x9c40cbdab8e769c2c6f9de57c23621c5d8a25adaedd1ba9df17fa1680cd4e63f", + "0x995e6a00f5bc63f0a5d837a6671260771f12995b82da19c72a9546ae7b93f38f", + "0x10f647c754615b475543fca5ed9a4491503867fae619513dad966af63cb7ed2b", + "0x7e45b18bd06e946d20bc3807aa926aa5c0a10555b9dc18f9574136969b8f48d5", + "0x8a419fcb515eef5a139a37241872c095818fd276f77e6388c74b82ae49e6386f", + "0x2cb2d82e278d8ba47830ed3dbd6edf69d2e49721182488ffe0a01698071e7d40", + "0x1e9e5cb7a68e7a2decef900bd250bd31c1f024ddd240799327263c72940c7e59", + "0x3904821c4388b16e9851e3a7318f4177102da38525cd3e5e5708430a243470a1", + "0x7785b9d9ff6dfa45d945aaa393270bf8b62bbde46e941aa068606c173963e518", + "0xbff782fbbadfc752f5c2a239e49ab13200fc35cfba29a5332fe936a0367d336c", + "0x294a3fd73f102c7017c9208857dfb91ec7c323916dd1bb3c9f1fac2c7d952b4b", + "0x3a9fe3685814b6cff7a918e514a9d5375a1fc8268a48d5b78da93dfda115332f", + "0xc033a1836983d485e28e5a0825c953a76d4c7f4a8ec5f7eb0b11baf5ae2beb79", + "0xb088df91127cad5d72f8db96d7ea86dfdef55374bf982222a45df7d2b631ceb6", + "0x1b949204d4713d568d40effb39002052a6d3a568bc81aeeea6d1253d198f1be8", + "0x12a2ca58e35fba0e6807cd6342ec56b3694a463f49804926349f4539be68d438", + "0x100b99dedfaec985e782b9b35858100eea3912b9aaf55fe7a8a767c93898546d", + "0x13d52bcec2eb86e2362570e1660726c03ab838fd5a00e75db7708941b4eb7f78", + "0x593965331b69f02f8ff23ff0530448376ea605ea05cfc28cf39e9db21b412521", + "0x0253f2a3b472affd04d8da76383653ad987d0cb533fd4bdde32a346ce441d74d", + "0xb43ab0c15315108cfcebbbb139eac536205a8fbde0b92e32937ef799d664127c", + "0xc4cb2191f244ba3720fbafe44d13c0d1a3a2e32f80a98363ef748731f54f180d", + "0xb28508b83729ac435202a034701f560fb4fc26e95b4a359da21309c66c082e7c", + "0x4826172b9fc3571e8b6193668e47ae6fd0c44a6a0cef1135333ac0213241f0d8", + "0xb5447c4fd18da34ffec6774325b3b486b625890aa5a383dd5f5ab4e4dc455523", + "0x92d2150387bc841a0a335417e3abe535a1fb00389ca22c22c68f82c8d4e78d7b", + "0x46a6298ee531dd085c8744359fa14217337e9dab9c28a22272185031198feb90", + "0x70cc7e64749cd76006b7553a3bd6a6d3da7840bb5544a27bf281563a82ad1d7c", + "0x727ca0fbafc16b0d88921b72ede2ba344988eb34339e0beb319906e94b99a50d", + "0x83f40d526191f18869fa9a3b4110f402d2304e4061cf90ef807ffdda90569bae", + "0x4267c3eda8a33a7de851bd9793c7ad5287b16204939a367f6139fcc63ed906e1", + "0xda06431a6cde3975a8d2279a1397714d898550e8e40506fa2b14cad7446745e3", + "0x841648c4d39e19e486d139799bdc0cf70976cdb455d581623c7a78dd3a681f82", + "0x88cf67a8dc5788f2c2423f9ba1a183114e58d51abc359f43a14691b14a49b35d", + "0x52caae2977f3bb88aeb21c8ed26821b69409d9de0356ecb042b39863df018dd3", + "0x2c993df9d2e2d312481f8e2fa518e1e49fbc01e70b1b82aaf3c7450d66b4b6b7", + "0x7fc40087df9f67f334d5b38845bd9a38d28e63f7ecd8ce72bbcf5e40954cfbfb", + "0x7ddcc5b059d9740b3692bdfc5734c024c54657bc0fcb06995455b72821e203c5", + "0x136ea4817f923a3f67706f0c2cfa69ef3dce06fd133206281e8eeca484c349d0", + "0xab84a618b9fd1f69deeb2fdccb86cf43be4d2e207e70928b29cd9c25d219c931", + "0x02408b3f518474db68ee4c1bf09d6f03e96df2628631b1bbc0614652851077d9", + "0x03d20cdf5fc553b833b5a09bc0c1aaef7de687815db28bc72ba0245ec266f818", + "0x6ef4844c3615faa2e9116e1a3413205c0100df07510b94ff889ae00ad7a6b735", + "0xce3ec8047d2051701d0adfbecb07eb72a95b37f7b87f01f8900391b543be9a5a", + "0xf461948fe25cfb681d9be95c34980f19e529ae0e2d958bfbf5034ca3626e6cd8", + "0x9cb75fef2a2f75204c125438c1841af419e92f0b490c7c6fccffe5e89f3f97b1", + "0x7132ee9c9db9faed4ade82b126b3b32ebc755114203a6eac2584fd720f9f86d9", + "0xaf1d9e8cf0734fda38af74ba1425fdf2121c3c597be9f3dd39e22d80e301e52e", + "0xc0ac3a2304310466215b8ac6c423719ef4da871d71fb774e180dd8712be96101", + "0x5fb5fbd3db4e37f637286e9cb2f07e5b878d482569d763549d4954c43215db32", + "0x34de5161e1b351e4e125a0235b7b9844f74b51a467f36e89641381f6fce5a7e4", + "0x606782a845f84ac4107a51b9c24209841173aa3f8e9cc2e51c57bfe72e332633", + "0x058d394d8a87c1e70b4ea57fce960eda9ace177d321b52fc90944ade4407022b", + "0xcf8f4925c630c8021aa1e00a1a001a05642f2adc2465dd52bb7a9a80991e84d2", + "0x0dae85d04c42da27288bdae0c6c8e564ec13f23e85da729cdc510bdc04934f55", + "0xc5b9dd7e2d0e55074e96b8b63159126a9c8ab43d42f56af3e5a326f042786b2c", + "0x9c1989e9163d7cb4710d82a708eb1d46b9cb7a9dcbaf1816f71e37090e94f836", + "0xe8d5dc22434014023f70461aa1c011c880a0f846255575353106b52df595509d", + "0x760d3fdc3d34548004d1aecedd84fb248467975572eb87f782009dc7c7c2d277", + "0x6b93dce72d74101a95b6b00d084972f4e35abce76ee4a58b6c260835f9a28c01", + "0xb6e8237d3d8a290f379f08e38f82f18be7e2d480ddc4f44df3e5f3f6c971cc81", + "0x77ebbde0737b668b3d16d764d055d29ccfac7ece19ba2e8d861f937f54df328e", + "0xa8c044ed1d2d77991561677ad8f9e58c07f2dd2caf110717bbd4cdba4cb60b84", + "0x86dd579810c664218ec61784006191f8511374db0078bc8782f52cc618ee4669", + "0x823fc59a1257302917fb1b53ac9dcb4056958ba764c2811b27db4691538d1a0d", + "0x5cc49ee5c1999eb52922e4be082eee8919bdee082d797a50c1ffa29b6ae4edc8", + "0x4a2e06ce47577ed442cbc35c5b232877793372091fc6efd6d60b77ab26bfb985", + "0x30b8c3227529b8da9c3e9ca74d67b62a594743b0fed7c2d66a9a04c9c2e05847", + "0x3c698f90a3cb7c32c3d909df5e2a6f3bc733ee415b95cc40edc52eab95345239", + "0x1210c6ae4167486def5fd9cf2b7042c7b35066e633145b4ba01413329d80095f", + "0xd5baa536453f7d6062dffb1dd1ee1eb1eaa8449e4a8091351a69d6222022b694", + "0x914297de69e782a4292254de92b5e754a1de92a841da73401eacd62404ef4fd8", + "0x0f052f1b2f73c32c032cd52589c08dd365503f2602bc41afbe143790ba86d89c", + "0x7f492b234cfe8681cf41cde74b479fbe8aa81dd47499cc27b07d9a06007af152", + "0x88bb5da748c6f96f3743edba77c172d061489ec2d8da82bc7f858660ae32c319", + "0x9d5db583ead51d5ed207f9b4aa7c0dc45b64517dc14906b9de0b01adea464bbf", + "0x92b9d0d7883b433d65cf3e2ef5af4c817216692816e1f8a3b27a079b622e251b", + "0x6bde93b8499664d61aedd67898071d1711e565f0565db89df8c2dfc2c7f1c08c", + "0x8bc8bbd4e865d6c446c4840ddbde800f3de2725fdeab0cce5e6e0e1acc23eb09", + "0x66e1fe40cbfede3b8791913b327c391f6a5d81137c5da5367cfeeaea5e6e1a8d", + "0xf2f87039b7beb30d4358b651b8566d509caca0fa4f50148b80b44cace72bd058", + "0x25dedfa2522ec37b9b607ccc7f8a260c5d8fe34b12771028524507bde815f004", + "0xf5808873db2b2b21c719ffa31382d0017ba9c4cc408148bd39ef161ab87307b2", + "0xb979dc5a24b39e9c4272c69d858bc1ee8ec49ae5259cb600b146ad8f27756397", + "0x60c3fa777a9c5d91775a173e137a79ca785989c5c3d71fd163bdda852ddc0cc8", + "0xb5ced19b8f2025e69f79511988f634c2ab0abb37dbce6dbd1e3df5cc58063a62", + "0xcc9d411691a188855b529bd49bf00b08689099b31fbb16e6420282c54167d3ac", + "0xc3d8398954555c2e1c7aff2f5908170892769035889ed3c64bcc842c87ba7499", + "0x8ed00b0d107969f06692868cf8d5bee85be943d417198b44e7c95962a1ddd7a4", + "0xf38a2c1e2179a3739fe8b53812d1ddef8acca6df5389050113992a10652f471f", + "0xf32225385feb683115b88285204d56922bdf59e0f58e332949d0f93aeaace4b5", + "0xc4559a00cd9b5b801c21278ed7a2b2a8e4884fd6baaad9fc986ce8cf85019edb", + "0x328bc1a550b6a9a9732e39ef04917f11a5c88f99a9b1f36009d339313159b0a3", + "0x322ce0bfe3aa6729e20ad2548aaed69e54ea1b94ee99dd7c2ef200677e5198ca", + "0x5b758330b7fc118ca6b36ab6b3dee1cae8dc315cdcebb3cd757d25be9718e2c1", + "0x3969413a5efff28ed9f4187ae712dbafe74ae712d801c15644a3961824e5fa2e", + "0xfcd6eb558bd44c5073aaf04f8c1d2a937a338ae6b75cc6d59d35b40dc707f151", + "0x27e43e27370c02660c742c83b6e8976358cc5e01ed04ec82ae087b5519345f86", + "0xf47ec3250d2cbd2f82e5ad70f93630e17d14ff43c791ddaf1c86715e03ebd5c6", + "0x308aa120dff142e89c16ffe5fd7d2204993ff3657b6ab0aa0dbb0d83d14b2afc", + "0x98fe524716333ba24337ca9d6d913a0cfba21362ea50b6e7285bd71956faa75d", + "0x938cd945ef8deed0eb2703d9875ce64712de9a78900578b85a0de6995323e3c9", + "0xbc31b5581f994b3017d6552a6934ca9c52553a4d42a8100af941edbdb2e91a9d", + "0x7327f0976fe152ac14e7d7d3fe9cc2a6a75b968a265e7e0172c0f350d3e152eb", + "0x6c2479beead9c745fe1060956af733766cc80da7188d2988bdc1340d6cd284d0", + "0x5fed2cf969c6cb9028a4e9bc7648022cc4a4f87522a553af1ab21928cdc55daf", + "0x7e8edab36495ede01b8705c5fdcaf89463371ebe10f57173ea857a9fa2192937", + "0xfb58d0ccbeaaacb3b4519c805255fb590596b54e4fc4430a6ec6c5c7fc9766ce", + "0x937a1898488e374bee45ca21d771793526f6a52b30199040760da726247f7cc3", + "0x6e85be1630192947170547f83f5f5278812841c1097decb2cdd7e7438643053f", + "0x12b0b60b027afc8a39e6c32b65aa828e12a7f9df6c8c1e970f08e18fca430513", + "0xf7037c53bc45bc06d8670e846f84824d109578068eec905054f666ee5510fc2b", + "0xc047b653ccbdd24a41214add8b7076bef8916bb040d47d5345e54d7b8438a099", + "0xee03d8ffcf729e8a46f817143763bdb98d646b9945eb573ee52997622e08bdc7", + "0x1adbbab8b4d4df3914a0dbbe70b6815a8c773f7000fef03b55665939d29a2d4f", + "0x475f1fbb7642240b7abff801b13dd369733c45f3103c836106e99cdd43c0caa8", + "0x2aaad3b7050cd04da0f9e613cadf75862c7e8250ed59163ae113e77d63818992", + "0xcbe88d935e66909bd168057b1601b1abfdd68db2a0c0e4ca61fdcf1dc0408774", + "0x576d6f60f196a7736d9197bca8bf9c82fafa9c934cf8988446e5c86859d89f43", + "0x5ec11602479ff16704b3413fcaf368cd8a6a87ff9f5a3a075ceadea2badeab05", + "0x6be482890a8e1b9de9d3d5d93a75fb3fec750c1b8440f7c9ab072c699ea35351", + "0x621797956f53edc280890b015baf2d0b73db85d3b186498e7e9f40fa3408a1d7", + "0xa622bc30127840cc1c1b83bfcba8410bde851070517b39f73fa0753e39f818ba", + "0x8f2c09f74bfbadbfd75ffa2af29e8ad6f6a67d3891ef8ae8d4d785e99af75757", + "0x2fea6a50503eaa6dff3275ec99f56e67e6125307697e4bdc2c489a3cb69029bf", + "0xe5bf069d84493e9f8fe20682f6241a99dfbce8e0580d26014245b28a15b63a51", + "0x5ccc1e2e1cc064acea0ee9299bf1c9469199bd2bd0c6769dd764a065e1d911ff", + "0xb912bad85e4c8b295e3ba2d68c8c5e0d45ba25d756ab24b0626257de8225ab49", + "0x7477d10d6c663d64dd03ad5051f7482fd5a6e5d320e9740041b13cf555e6a227", + "0xe7e04c26dedb78211e39660347214cf4751f19eedb86bb59f4b56855cbd0d2bf", + "0x61e04f4540f1db5e6acbda2b6b20fa5931a1f19607fa4717239acd737490e7d1", + "0x172a7fdf55b224b2bcd76c248216cea3e45a25f1783ac02150759495288297e5", + "0x304a01bca8244bc1ac8568fac49ebe00c83ac93df08362d3fd80f86dadbb779d", + "0xd495196cb5d83bdb3f962d3222d010e95949e2192f914ca256f25755e36b5bc8", + "0x5f4036ef1381adbdc0ae7a0647ca9051d21d5705a8c5c4753aacced054a86796", + "0xb6b2823ac77073022924ef5eccce0fafbf20cda23ba8ca9cca3972c6adcf772b", + "0xb3b34c3b6f3f3e96b4aa487a2bbfb5cf2b906bf3ab9ec411b6a1ebe19bc38364", + "0xc0c9826164bfacbe623f858bb51fefe867511023a8250c187d3520792d4972a2", + "0x1537fdcf26b6705f4585fe555151a59a557c672b91f39567762076d22de0d9bc", + "0x593d8b50367c9d3daafc403a38950e9c13ee3d3e38367f8ee6f0298cf41d8d5a", + "0xfa22314c812f3f8cf6d91c16a81fdbf93aa8606cf7010dd4711099ae87a3b81f", + "0x6ba7db726fc78312ab135893a5691db6efba59fc92efb206405ca863f289d721", + "0x8a13d09d91065c4d13fa532b0eafe3311ecc8a35b18092b042d7bd4df77b7e72", + "0x7d0afb3306161abe2a76e966d8ed01816930633c11d9caad92e7f45d195f0dd3", + "0xc8ed07d535b55af4ccaeb9c78a330fd051efb34b3d70f81a96f8221ea500efc5", + "0x4b1a35a1d95c3a6a2694938b071810412e6bdaa3681ef263efed5d1f4c93b55a", + "0x457cee6b8d1778eb00415c76c239966559e04b86b0ac597daf918f269b41b082", + "0x27177d9985954a57f90b6ca8b4592e285fec13196c3e2e01407fd3e123b6b516", + "0xdea7e638ca66b09790d12fb6fc8f6d6177aca1a209e090de296b9ecb3e0213d7", + "0x98e7e5327a7d2543822260ea2ed427d4f332dfa691d4547b4acef272010e90a8", + "0xc86428edf6c0b39db083970f80a7c2b04954cd572c49336772aaf27dd87b9849", + "0x17db87fad8a68694ca810bc2e5cefdf7c0f695004e4450d0cede7dbb2f7cf753", + "0xcc2face264b38e98ccb2bfb504675f599091617ac7430d25bbc5fc9481abc8b3", + "0x0495d951e99119e7e66f2372007269a6d76341cc0670acc196fa59df089c0af7", + "0x1a105f9a0ceb3b4ee2205b5626ff63335a9ad16f9abd16bc77b7a782f6769c77", + "0x685745060da6f81b54f0d74dbff6169e00a4fa4e28357d18745246e39c9e6220", + "0x3b5cc9eed80730746770c803eda7737854f0bc15a5adad1eaf4dc1e079613aae", + "0x050bc98e087c86272a5ab2eae1b81a37969c9762a36fb069a5751ff2fa1a1a5d", + "0xfc6f6cee79d69ed119a23bd2111ebe1bf9eb984b6d42440a31e2e9331cb3cb1e", + "0x24fe575b0aeaec871d13bfec4c00e3b48b023008e3c29e193e33c3fa267e6efd", + "0x1764cae60df974607c2da7058b73edf4071603722f32676e7c6d577995d6b37f", + "0xd9aa22b7c733a78ba533536250bb0e5837fc9a38fa73fd7f888b8ce0da88c954", + "0xf3e78ee05410dcd0f991c3ab1bf4a3637e61c54648c3d04cb594965f3463f645", + "0x21c2b2f3635984f79a1798d5705301736928c705bac8627045d4dbca46270e5c", + "0x6869195743c986a275e717728f0b35f5badddadcd4723864f2ccb7752edccf2d", + "0x41d7d273d54fb5bc454c69e8328130064472e89408a313befedcbd0dd5e1fb6c", + "0xf0fba130c22ca0753ee1e4424e767bc6d3fd2bbfa68ba85b195979def650bd88", + "0x1d4da114f9132fbe49907afe713a80866710ca533ff5c4a993ee598b2a17bac3", + "0x172165a85ca4100bcad3fe3082c59fdf3aaf0bed23a938b4b326694f64f7e349", + "0x12cf00d3b11cbfaf2038ca1e9de63e4dff65a3352da5824043978ba8fe7e08cf", + "0xd64011bda551b01b0b33e1065b0069fd1fe103e2e68c50fc5bdf1f99b4ab5e0f", + "0x3e3bef8f3d76d1f410327cfd8f4453e0fb9ed392da173e26ffaaed662411f7af", + "0x435816db536c536e0470a3fbfa32fcd6adab877831ffa66417e19bfaa2c9c62b", + "0x19d27119d0c702eb7735d70b30c26567d6ae4c5d204870a036f2273f027a80a9", + "0xd48c41e8365e9872d953b89e2b3dd0fa762b3360958ec9928124f54c79df5f19", + "0x7da805659d8b9e3f6b14aab3a5bd8d25e9d2d960076b4baf6c394a02fc763d12", + "0x5491cc6940517e3a790bf6e32437537e0241c9fcb3302a3bf94133ceb65b8862", + "0x0568a4d9b4e91fd1046fda2cb8a718ba57ba1526610013f465be7777e94356c1", + "0x0831b1ce49717503b49502ffe6b854ab2eb2c4db30f5ea5033c011f5e5e3d309", + "0xabd50d7ea56144421474763563ecdb591ec1df8645ccba4e28990d8b9b8ed16e", + "0xfe4ceb9425449bde581ef04b46c1fc7bdbd8f422c43d64b2d1bbbe3ff4dd7a26", + "0x489137c52ef8c71e620220d8e9e842c2a5befa812b70b0a709ab4603a729047d", + "0x8fa480e08230c6b9d964bca0bc5d5a246e4eac6c8d45c75a4cfac8c4601f455d", + "0xe5cde020c71c0ad3e7f9a789247e5518bc1b824b4c6297e12d09a42e265e4bef", + "0xd4c0b9e39b70ef4f229884817c317f20f53386969f8c1e2ddc69cfa57b1014f9", + "0x75b91e206eb0a2fa7752da4d6421fc294a4cd7d6d06dbdeb7b7df50e157ae99e", + "0xa650044c8fb1c0d98b1e671d576f389b0b7be37e946b7623ff6203ca72c574aa", + "0xe6dd07898de5688be966dbc612764a9956ef1105a7a02695ea269b6e40ccb077", + "0xd1c7d40ae3558d4b42cbf6bce332e718ed8f9b7026b81195beea713ea9fe81da", + "0xdfd6c816adcdd1a588db0bbb4c09050527a107bcc47d76be91c7e309a54dec92", + "0xa67e60d39fad4b6389908ced2c0b6fc4d0b1ae78379de0452963589cde410618", + "0x88a629bbfd9f5ec014580d47210562cc0ba162fc2e7f609dcc34babef9d2f89a", + "0x685dcd734516a666b7e9018a420cc1ed6f1cd13d13f54dc782d3d2529bafd375", + "0x00adf1bec319f440e54009e1ffc45d58f38a120644a111239aef09d1f91c20ed", + "0x0ec349f19c0374334a6f9463b349e97c6a6696984c7779cf29bf048a6317224e", + "0x0f190a67c3804e6aa618106b554578687d0f3983c8350709362fb7e4728adace", + "0x7af75c91424ed2a01f0b796ea4772780395cf77d4051c91552fcb962a384a04c", + "0xa43e2914fa364effea580b8d8ae6d7c5480acf7b9330b226438c12fb5e478ea2", + "0x38deda38720cb7918d43b4b7296fa0168d77ffefee1217bbe198b382fefade22", + "0x40e97169e2871117267eedd1095f76d97719f6e9dec56b3423a9258bb09815d7", + "0x3368d112a868cabf7d21ea1c5c851fe0a37551c03d72cfd6b235e3a904eb5889", + "0xaa25f4d9f97ca1cdbda79c61f1ab84883a037eed60d9ec2301cdd5c404c9805b", + "0x21132089753a085a0a982388817137c591a9a34d2cd9e6651c57c76a8b80b716", + "0xdf0c2df6ca5680424ac369b411ce78031614632c5fe44e2d8af1ddac30cd729a", + "0x4f55598eecadc5136e90d15fcb9f87e1eec65ce18121127b49cd159c69c94098", + "0x8a6b7276e3def38187b0cf9156aec251bab76637505f97583dc4d426ec86be50", + "0xe8a516509c5bcb7e81372ce88f7d51982e092ea93f895e5dc666ddaea58edd54", + "0x3edb18c971bd2f867ab6dbb3d63228aa94ed0d0eb9f603af71ebfb201095b836", + "0x0e7de89c28113289c1f84ed91c289328b9cac13495b289ce11cd1c5942be1188", + "0x2610da85e8fb400db625442fecb8cbe20435e8736fedf3bbf715501697ae6be0", + "0x5668c3a61683c91b17467e48b2f27c7e377010eaee64c69d53ecb1ab89dee1e1", + "0x58bb1cf79609e7223f1883dcc6d80538e278e514b1e11c6c2871db55dcdd9914", + "0xfd8faec518007958057845c7b9f204c8dd473db5dc19ad5f2460802b1fae2693", + "0x304b287a3513bf02a35fa61a8cb6aeb214d453d9d53213f458c207d2e15a537e", + "0x7b8f9c4775a775637d9e3274068df7c5330096a52750d604e6f3818c4a7f0b15", + "0xaac892295bff6dc1d99e51a4114857a5fffbc3c8b2b24bd057156c91a5e3bf7a", + "0x34266cdb180c5227ebae64b8ddbecec44a6144214b9412d723924a92fb4a93c4", + "0x1ed56966b89b57904056fcec5d2a23ca5a5d809a7f5c889c5123e3994d660398", + "0xb44dde8ad3b29068b5d3b3551bef7082d8f09366ac622e57f6b494bd594c7a03", + "0xabebaf98aa2e70020b83e45d5ab56164dcc58a4493264cdd6dfff3e921b395aa", + "0xdf26e98e5499f58665912d987eaebe8234eec92c9cb4e788b274b9e9cc8b527d", + "0xdb1f809c70c5633bac0f1642ad929984ff56154b16e0d81b8fa6b10706336c3e", + "0xecc6cfaadef8dab02149f15d1f39932e53b3fcf25fdb1d0379ef9b933222c018", + "0x17351e250078e53f17a144aad0933172ddc648a8f2fc530f0d4468623328b43a", + "0xb832ca94746ea0be489afd60548e74d654278b8a08bffdda83f87e58459769c8", + "0xbe1d486c25ec6042a110acb68d2fb9daeafb830f1d739506213b5a0de51887b5", + "0x560e8231a58aa914a6b82977734a8ce364d970af688f014e8957933ca3026d66", + "0x76b6b1959f5e0579fef78f6549b171028811c2fd64265bafd701e0a2de9d64b4", + "0xba8ee49b308ea0c0475cd30b90252f4909063b86119e4d1cd53dcf6b4671b0bb", + "0x168bfb6c2fd68fd7194561d6b0f6f76e733dfa092d550de243a2a7c0e6b14fa0", + "0x8d5dbd6b82c31c1237d84256a837ff86e005033d83622531bb00de243da0e5f4", + "0xd12f68a021b6f806c9d75468486f2c4fbad295ec51c0f507c445fc535a0caa81", + "0xdbe40f0f8ee88a80512e2f9162776abf02218c6dfb61a36042ba973ab55aad3a", + "0x6cf853351f1371aacafc02da272b304b246176c2867377185b349c5f5880257f", + "0x3f37a65caa18187a3552e300aab18b27d4a2b2a25c049f29e5d8d7a2c57af78f", + "0xad59d1d4be0ce243a38e94ffee6b21fe073b28b0bee9b0249f560219e9bf604d", + "0xe28ca7ade73017341acecc09a647c6c0e638f6ebdf1566b534dd27d5e9ad67ce", + "0xe3577a39c6d3670d2fcee9f36bfb4e79bcbea5695013ae037a7a7b4c5302979a", + "0x56a8566c6bb04d61331e9950a97248e152742d6f0408a77258c102efde79a0bd", + "0xf199dbb8b24df16441c45f5db31af6597172dcff5bcb84306a3f8ee9e7ebdea1", + "0x85a9e253bae3c1c5064f320911e7f964c7315602e83374f5df7ba532cd2acefc", + "0x80ce75ad1b2de3054cc12adc1774ef8e37f3123387d06daeb545953b7a2bb044", + "0xb26d9c8ece65562068826bc872a6fd93e76634b8b7b598769d3df142ed5d17d2", + "0xa43a1662961c4bd1bfa93fdf911067aca94460c733f5a9e296f9e47740b6f8a2", + "0xf84716d76638301b784430585722e4c112375a69329ac03fb8e98882fbbd2fb3", + "0xbdb1551fc7d0e24f2096586ea482b83b8603db1642ba6aa12d8369214af5e4c4", + "0x8f8f8de670e0dc95346e2b14b82bf8a63d9a2a4eca385b1fafc19964cf98f710", + "0x6d3f91249ce7f7f852a4ffab23b7e949117df088f2e2aa3db0fb386755a16c92", + "0xeb9c005485707baed2b7ab034e68597bb8be65bd6f8283b690cd338bf7d1826b", + "0xcaa884959fbea1f5110d7cc4360c24b2ede43d32f8cba522d28946ffd2d900fa", + "0xa561dbe805f8ba3cb6d3d1524c4b3bcbc95ac330e6d71d33642412f8f0a1a2a3", + "0xf158b9329dbbb90083c88982656840cb134713ba122e7e39b287bca4b0605dd4", + "0xee3ce79371c0f0a1ac399a3a722a1c7515f6b02d2e03118e3fb6d521e245ab6e", + "0x1083d6dba68c10cb19935b627e5576b5bc4e7904c8ff59657ced1c8397468017", + "0xa893338e4a49166bd36f4361799c7cccaaee211b512e0c8821136cdb823e8ac8", + "0x1327e2948ee57993f1b721e9fedc8f7d2e91f041b3e01340375bcbbdead83bfc", + "0x6bc88c663e475911e9fbdfb9a33931c34bcfff5e533e82059d33cd69ee414d94", + "0x81d95020affda45f536e01b1a4b840eb72afe2e82633d81de11acdeada45d93b", + "0x91e59cb7e3729c776c4dd441c3377659b37fd881760b9e70c73d5288e99bfa0a", + "0xbf69325ef2072cd5e3d2e93b8e6e2abbaa03434212e1ba4d36459a0f064a64ba", + "0x11f4a2d21c3145af81ba0edb80a9c27cf1e2d53b1a43a42b58b49d4340ce4fa2", + "0x8c366dac642346ca05e2fc047999f9adcab3b8166482854b06c77c2439e0655d", + "0xdcae4952619f997d791aa6a973f1c8c1d3a0c21859b0c37bec64533a6f7c0630", + "0x5300c16e42bf43e34c9e59fc5748c3e05d38437943956eb80ae91cebb4e33d87", + "0x40ec29594f14d9d9a76b13342face2565914b050cc5e5eb96299c51ec92a529d", + "0xa7da6ccf5a72ad5b8cfb6d00aed5f9f7e2bd70670c57873735ce976249fdd5d9", + "0x177a1ca473ae2fb06ed39e180567da24fd14faffa062edbdcb0cffe4520045b9", + "0xea7c63d98ea30c23e0f4df53566214eda57c96f9449aab5a02c165ddb8e61bd7", + "0x6bf4bac02febf1f9459a433d08b373143f44c0beabd3f7bce4218259e8d91311", + "0x6883559d2ed97c78d0aea12c0d14f0dbc911db36a3bd9e3f8a7142e1083e118f", + "0x999416083ffc7371c9b95b6d1bea32da9c2b00827e1f0e1f615354dfe76dd5aa", + "0x82873c88efa3041aae1d36c2a787e592a7af56c3d86f321b1dc619b974c88ff6", + "0x6bfb4371b0a7b9eb9e3fb1f6987854d6e4210286b98bf8dfe6f71f12014ffe59", + "0x5502ec7d23c5559afca6ac2d6178c1f2c778e4dca22a6bc8b16619082cafdc00", + "0x97307b650b949382bc80b6ea446b629c0fbd37bb65a36ac1b33b1e4ac310c056", + "0xe33b1569d06b2b5d05065c11a0dc4f22d214a7a4e4003c1888f7469094330a8d", + "0x691870ffdeabba194cbc10492332d51702d75c40681662fcbd5489753bd5fcaf", + "0xd9676a94b8e3eeac02389ca8c0a6d730e2718c0cfc3a5bab3110aa170d64bbf5", + "0xf558d9d27beca0657bd8ca7e82d1788b1777dbe06b474b7598acdfd46e8030cf", + "0x381d766d66669a50d13a141535c441887cad897984d7b2bd52e9bf33c385669c", + "0xacbc99a6cf54ca6fcc9ad8f844f8bbd7639791b663956cda2ac59fed34027024", + "0x04e5b5dfedaa9369bed72fe0ce827e3c16e7a07a274661d76ec92347baa8deda", + "0x2a905b1aa12a30fb04f56b2d9a26a38ce10cc2e9dc910f213ec3c6b368b15bf0", + "0x0f40416a8bc6d699c404972d27c9b69093b387a78f22295cb0a6001cd437a4fa", + "0x05a52a1501ff0d2c044f0c1932e5eb217aa734cabd527d865796fdd120fd8856", + "0x36c70cc55f4b571882ecab711522e4bffd3ae8f6873d940a0e4626ade7797612", + "0x4a7af1b12b32d3bb38ec4aa0cda6535cd96043466a56f0641253c7b21abe9205", + "0xf637f992df45cd4b58d2db4d5c8360a65cf05a11f14dba70638e50b5bf70bff4", + "0x5b271fd0d5a0adaa16218fab9f75e0599d85c093233761a76c03ba060d5b7948", + "0x8e3554617c506afbd2eed41a4c8e2ecc1bf619b163843a983411c884e5b07320", + "0x96c35e763be9f9a95f76c81fbe1659d22715f5cdc0cb36c168c67a1062818914", + "0x1d1235e2789d0d283a3d4c06e391a1e38869c788255facbaca7e23c4e76e5ba4", + "0x25246df476679b7364020ebe600ff596b6eb17b23c68ab05885a02616bd2e5f5", + "0x0a516b13c9e864bcaabf531c43ed3ca725d4521c9d34ee08280fd13500cdcfb5", + "0x15b0defb12ba7d05f4c5b387efbcf5eb41e325ece9a0b83619a5b7e19283b677", + "0x5000d5c4cad2ef87de73eb2f10d6733a840d069200cb30d4221031381e8c8f36", + "0x15e98f25d14ef227fbca0b760e2d436e291d3668498f486611a6a3118f5a8556", + "0xdc0d786b90d673f30f84706d29643bf0c392464f30ea66052b153ec28ee4b7cb", + "0xe4da2a6b7a254b85df06dbe8f2bf24b4ca3ef6d5c3b0fc8c17e0ebd32d5d69ac", + "0xe2e6fe80f327eded1c263684cbc525e27839bc816b237588b902c66623c38eb7", + "0x1b8c963829103769fab68bdf45dfe4d6130abc9560590871665f23b190e959e6", + "0x5d2e7cb7a42acaadbc832fb8974756f9473b18263ea50aa281fbcfe217a15762", + "0xcf46e1381d84a33aa488d4674b3ac43a1b6afb102c7a425fcc1447769ef5e6f9", + "0x00532839fe3e0691e406d230c8d384b6bc562923048ea0d89f1be054252eee58", + "0xa68d5545328145a3dabe1b143a57a13057d14866c6b9c9da8b4781f4efed4945", + "0x5223699aa191c964875eb16507aacefde636e88c0f0093d92bc38be221fb3792", + "0xa9b807ba38a8434b3befcc91f6b93427dc81f365354f62d5ee69730e319ce5d9", + "0xfd0dd9977372d780c38981010a339dd6552e8f81fc7654362590e7c6b9fd1f6f", + "0xca3900d2a87a6e0b04d679bb87dc81bd1ac11e79e4f0355e314c7e41d76de4e3", + "0x78ee224a33ce3b2629f7640392846f17c228288b89d6c2d9db42726cf64225cb", + "0x48a4acdd0758838c9ce2b322bc77459c1cc0fdca3d588d60697c8a5aa3035273", + "0x6eb8aeeda5a4b26e73ac2bd7f838c974b5bc45de138d14ba58b51bfb6d51cf93", + "0xd6895877c885791db924b0ab1a1d666c06a10e6d210e02cf9c2f29726d3c565b", + "0xcffa80c70e6246e7b17173c071384a7b46dfdd5ab4b4b524c88871ca02c7e658", + "0xbf64411370653f8e08373438b03ccff7fc6ae1d70385cd26a7e73b57da07dd75", + "0xd9a39f3b774d208608c7d1d9d1fcdacf0c0ff6e8cb7915bca57e8056a8b914c9", + "0xd6a1f8fae6440d4ba8b2e392dbd07f6dd6290651a221b3749cd2dd6b0f39ba0c", + "0xa1ad925960651423f598ab111a0f2bcc5d3fc7f62fc72eb2753815277183a4ac", + "0xf3f6feaa55dcb3eb9c572404a0da1cf7dbb53983a98873b3f0398aad91773b69", + "0xdb902ac0d33bba7b0bcfbbe3b5533b970d07381fb00a973b4dd92c8f7af7bcb8", + "0x5f97ac6dd3f55bbf179eafc50c64042f2daccfcb3bae9c4305045b709cf19ae2", + "0x7061adfb4514170759ff4ddf3922b10f2c85c1a65c361936e504ec77df84b703", + "0x07ae6b39e66142978d35c4c2a517c55c23ec47ae341557e8cbe8a0d001df0f6f", + "0x0e6b9fc3fec4e75d812128fbbae0946dc48b511b198a5301833992e763423da3", + "0x7e1da14382f9908299fe46dedaf1878a6d01e9070554f1436514d320e0a4ebc8", + "0xdb6cdc7239c51386bb9eb371765cccb84e4e4de38acc5ad7e5503bd0f60a31a4", + "0xcd0069c9fb9ba8d136a2020580827799eac95f613f7b75bce8322fe67ecdc2e0", + "0x06932b0dc851ffb7ce68ed9083cecb5ba074716f188c5bb4df94de8e7e057046", + "0x3a2e83e02240263c4e416898f9d54bd0b579ddb0076537b58c47c3a17df15208", + "0x61b166d6dee81bdf6d101f23bf8ca40b74c2eb3f47561b4ef024d30f410f88a7", + "0x7a9e85a9000cb7308a5c57c7b1421b22f63e64f48630a79e449e7a207cf586a1", + "0xd573fcbaafb3882fdb1985c1b939961d35dd7bcbd5865be82276d0cea1afc7a8", + "0x697152abd7502169e0d801346a41c815d8bd8e75e55845d4a4b251def64a9583", + "0x77e5cfae8dc5913c4bbd4f4d84a797bf8919a0c21a4eab4f5dfb42fe8c5019d3", + "0x6e7af8bd163f679b81489d3ec3cc4948cc57ccb3e0c8cbc80e387783bb87641d", + "0x4bd5ece25cfda291179b8977a84369ab1590c9d4d5b45a24865ca010e5ffa676", + "0x6331f61c715be1fe8e0c90740cb89c0a7cee24524be2258ad49542959f845477", + "0x0af729bb18715399a1b07ffe2e0d562f71c27ee2bc01921c25327d421165bef7", + "0x98ee97e5bbeaa0715143a39f38ac56736f54fe5b971584b4061c58721c051a3f", + "0xd06e19176339b1fb5cf469b1f0ee4350a416d20aaa9c1be50bdd26687b2424bc", + "0x2385cde28be71e40f64ba5db5bd1a8e5f4b767a9a17c21a96fd2642ead428394", + "0x3d2ef2f0e4bae5c2ca6fb9fcfa1a9ffc435471a7a533b3b7df2b28402d335f58", + "0x2ecc6ed70661e692248c80735650c253dfe6b3c2213bfc259ebc70c898ee8e6e", + "0x8a68b3eb663796ca2189e49b9fe5902e36615d03d28ac34c01f63a135b930f0b", + "0x563d7efb4175fc12dab431175b5097186c2379a5aca1901e39d641d02865d426", + "0x1a55cf9842f9008e0730ae9fc6af9f288edba323803d0ae787fc0fdda99be8c9", + "0xccdf47cee7142cad27bbf224f0afd1a6e5178345cab510f2f8ee27115ab27ff7", + "0xc5b3582937ad993c5c234d059e6cd3b98f2fa4e3fe4ad591ecb6ae710b51fee9", + "0xd651ab199355d61c49e63259e6a20d17bf72b27891271e5175a24c23fb2dc29c", + "0x800e1e33b0cd48afc6f8f7c69b85902ad93e94bb290b35a862cbad67706a2f3d", + "0x57c7349a6b630cb52c3c1205165df428ed51e25cc167c08739f86bfa46c69e48", + "0xb393d362daff182dafcce65eda9038fc0c8908b3cb1ec1a1218570211c34e142", + "0xb2f49f7a836cd0db9e4743158ff80dd97d23de7a39a0438d19c79c355339c43c", + "0x3f46776ec25b5c67468c32c1b2ca02910a7f46b4b62b5dc5d0cc6b9d3381b958", + "0x754c4ea722e501668aa48d6151ff423263b8a4e2f33b9e44e189ee4e78462741", + "0x12e79ee2724763a8a7f9196bf4d0e855e0ae3f75f5a697d90a263bf562acc5a3", + "0x407b168fea70128a8090ca86274b0b8e7965f16d54ea2b3bbabb378485b22a02", + "0x0d1557ad0cb1466965e6ee86c5ce887eedf462dbec2e719c5f396f8ed95edf08", + "0x29c3a0db9f83698e6ae703174dbeec06f3d2055eb933799e4ae3bf73f4570dde", + "0x8ade20e56fcacb40f54259696bea1aa04d839b88c503d6775d7b4491e0f9e7fa", + "0x327ef0f173632c5049988b312b1f49e9948b02125f70e117ea127088191c32d5", + "0x2989c11c234b7fc5901e168d7adfa655ff6165098eb94d244b623ba43c6abbd6", + "0x10b56dc8f023de6a8f97696dfe2993b56156a9b35f671438fee5830f52b633b5", + "0x46cd37fffe94a01297f2dcef322ae72f58bbf9f58bc9f930cbf56e73f8d5ce13", + "0x2240214683eafc37396f3078446b43ae96bc576e45db650b953ff87a895ee7d7", + "0x0db4d500e5755cba5b962f6b83942e72fd1504cf52531916084852179669a08d", + "0xafc686a8325a30966db0f54b64a4e7235ea54e300d280a4d2a502651a53424b5", + "0x59d46f6fb8eadcf18e31c9fd0da6844d63a2dc19eeeaf9ad5b80113aca5bc42a", + "0x153ae496364bf7c34c8c967e044cef69e401f0e4aff27b04808e2c299dcf15a8", + "0xc85b8d3156729c7f8ff1989f320464144f4918140d608cf03e7dfd5b51ec2acf", + "0x78fd0613f6f5291d4131152225fbded5464841a119d854a7550a1f178a8cdfc7", + "0x763dc1a000b949a45f792515fed6af70047641fa3d7beeb50b141c27b4f8cd33", + "0x42567a1e6caadaa10a13feff343ae1e2a903564affacc48aebc14f257db58ee1", + "0x62c208337234d101cc95cb6be54c17631e26c956758493f5bb7978faf0ace984", + "0x7977aec997a3029025ef789d3492755c80c2d028046aae8c4b926f247e1981d9", + "0xf927505a0c29231ed187a884af15a82dbc48a1cb002f6d91496f6569c673682d", + "0xefd2c54f6d2483a3dd7b994d8afa5441cfffa956d7da6e81bbd1691e07ac7519", + "0x7bcf94d8927a39dd00558763cdd2edaf40d55728d720dccfa0f5e1e827079cc0", + "0x19c7e5115ec25b14bd85e3d368e15d2bbe60451ed9a02f03770a3e845521b77c", + "0x60e32d48de6979c70dcb3e3f068fc3632aba5844703d50851a34975338b3a837", + "0x6722f01dc1d6dd1f0678e5b527155beb0616e33887697a56ef4cc1bac642f394", + "0x59bf17368d69e0379f0f20ec1b1b856298b8d6b4c36354ee765c8a894e58ab9b", + "0xe2559e7b67a15a3ddfbf1ddc597a1309d1fd780fe26da28aace16ad31754883c", + "0xbf687ac704bf02a3877e72f738691bf5027c21f64c68a50235876a8d015ae682", + "0xde01838df621b7368adf4fda268c827dfaa6753a39d51956c0445a2244585ec1", + "0x4ba14d3860d1dee44904719e45a5bfe54dd1e4c9bdafd0a41279e432a021f2e6", + "0xa2380cb32538cc80e07fda5575ecd7b35e0c12932687bd8002da652ad8c16dc2", + "0x82d0f5c8421d6803e52e3d6a37eea0cd978686792a2f6d175d77e9c75fb4ad86", + "0x23701b29d07c64c998ee4bf8199d5ac0f3d9724af2544cc29665a1d92a6dadce", + "0x8bbd490220c823506e111c668f923d18addf5a23d9b5244103cc135c4335f23d", + "0x190506f2d9decb8f9423662f406e61c99606abdcb369e25a1a89c2bdc44c6158", + "0xb9504b090b276cbbf86349bc4dbb66b46a42ce6ae8d44d5cd7f39773fdf6112a", + "0x38fc273344dc7230790963dfb3dedfabe142c18886d6542d77ace8ed6d117c4f", + "0xc76929e9a3a984f6ab6395c4811f007eb6d73a86fe62f8a1c02e860769f2bcde", + "0xc4fc2465f71d06102d232858cfd9737e6e82311a45b1cb2ac203de80c881a2f4", + "0x34427ee5534de01e7f0510b87e6f45aac6210897472978aee3c051c39776c561", + "0xec4f3c6349dac1e7e43b0541b1132b3d0cc8bd422436f31832184d1aa6f9c822", + "0x024a848067a1156852c78495581392774b00f22e32021ca531afeab1aafb683e", + "0x9bdf793e30326a181d3d8fb3f27818475b755e3d1fea200d8c514cf17024979a", + "0x55a1d92354a31354b4b1d9366e98b27c0467b01a108d67dab7feeeda23f981d9", + "0x74614ac3de92173d07434dd80d83aad5c1d551127896298808ad7fba96051e06", + "0x7bdb77183ca1e7f50d292e50ef701ad3bfff3e6e28d36629c5325da03cb8d013", + "0x3a35dc3d12de1053d204410a577b9e5c36d32fbda761f797aee248c27f7dbb02", + "0x430aaeb1dc02bb792375d1702999cda7c384dde1c6f46ef26f1e26e5a55dfd87", + "0xe12805d1713ba730fec6aae824bdcd0a896c6d5e12b9bfa5b6e0a2c2be251c17", + "0x5a297bd3be2352e56136db83a76c7041ef825128152366b2d8f032abb1d6656f", + "0x111782d82f50ea25d684af38689cea53319f1a88557d82c57e46ee5e75f99c05", + "0xe12520cda10064d74fdefba22b5ff4c5eb95508f77fd7c8c3fe82fb89e165bf6", + "0x6af12e8f4db19aee3865c3d681073e7433d902832bc651b8fc3f5fd038c8bca6", + "0x82a4a2ce19ca3fd99007279d62dadba547b6818607800e963b3bc53c5541298a", + "0xbf3a444d1b15d01a29ea22d05e71021ee3581338ecc9e770ee23ab6549a19d55", + "0x745ff92172b5c83cdd69265b919028b350ef95a01c84810366d630162fd9b07f", + "0x6128cd2ff1be9e56396a676362a2049f3e670c70ad2a77be724c090fd4085f0b", + "0x8ffc6bf8165e52ecf30ec955d4be1bb093e6074c92a527382a8892ffa3d3e7f7", + "0xd65bc11ef24c0fa476640d9effdc57030a86f547b7aa79b209954a6abf4072c4", + "0xcd5b5e184a5c0d1c5bdd12f80736ed1a4530210b4ef5f35dacd3feba722a334a", + "0xa80657ecf79ef03fb919bf312e02d94ab528c1b5c3858332d9bf82f807b1c232", + "0xc67dfe4aca5001e97ba6f401f15b72be85ae45972ba98b965a6dd4954d5c2386", + "0x59201e892aeab9e40aef69945585b81b47a7444ed61ba6c6e23e006103ed7edd", + "0xf535c920c5316f12f0bfedc298fbad028dd84161927414b14243c4c5ddd4f4f1", + "0x66c6e42c8137c043eb49528c718b10e5dbad9164bd3ffcc6b55b4b0501dc507b", + "0xa60b9485cb54818e0b0bfe4faeca923915f85bbac0525d09d96f375d0b2b9f81", + "0x8f9377dddacb6ed605c8ed8ed2bc6e2323a4e5d0c9b29bccdfbd27f57a9ec315", + "0xc48a1940c424c2df4803ba8d5573066ce4bbf0e0fbdaa87abcb2d2f51b0a4602", + "0xc7bce918e9f897aeb1351d2c9cbc2fbc8fd674017cb25c49846b05d609f00ed9", + "0xcdaa86e0c026c91954c6305cb7ce6010560f691a2667baf0e95bc18cd3e067df", + "0xf131e0910a8088fc5b0b1d2e93e31632eec67fa88f75bc4f9c3c1b0a317e1d54", + "0xb4f8d72a85c4c2261c7b00f43b96d7d749d0e53359993f52517da36de4c9559b", + "0x73f84bb4774a81b39b3a10d18c7a2404d21f3efd26301dbb7c8136e96304281e", + "0x5559435a987f1444e4ec78b8530009e49c52431b37c7e9f80ce2e056d44e876a", + "0x070664d11ee10c4e0475a7ece219eb0e606e055ee0fa1266b669e593b5ba1d87", + "0xfdfafeba7b5551d1e2d6f179be5ddfdbd0350bd2e9dfea40e272fb608549e8c2", + "0x50a1356bab9b56d8ed46a3e8f55b8a16af42df6b15fcc68aa548216de484c7eb", + "0x681161a307552ff12175074601005bae0c6f7b38cfa6dcb87975a1df205e28d5", + "0x2b39456efc2e8863197c95a4d6eef5069612cc2aa6414f0991393ffa672a1a15", + "0x571b916a82371fafcb456524655758bd42b4f7b768e13807a1a995e642ec205c", + "0xb2821504201eea0e6040a131a709547fc9afb44ba7bfa6a188201735753ba3b7", + "0xb16a8af1bfdde1fae0e28f29c6db0b361840df4b55e73bddffbc1cc11bcc5584", + "0x1df38b594f536cee38acad293a818bf83fc67830fc71bc19790d7733a2caab60", + "0xebb3e8f76f3b6a95285154dc11d4bd94ac4c3a150383ed69f5373499b1983dc3", + "0xb0919ed300acac5f912f01611a428861db27ffb8129a80495f735f0ac608ab35", + "0x2ee321d9d805b78a97210df2977ab62b352705e308773b90e0f4e923adec377c", + "0xee00cb02e9b86978ae10b119924bbe6c38f730c1d1b621d32c9d697e11105871" + ] + }, + "nodes": [ + "enode://6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f@52.232.243.152:30303", + "enode://94c15d1b9e2fe7ce56e458b9a3b672ef11894ddedd0c6f247e0f1d3487f52b66208fb4aeb8179fce6e3a749ea93ed147c37976d67af557508d199d9594c35f09@192.81.208.223:30303", + "enode://30b7ab30a01c124a6cceca36863ece12c4f5fa68e3ba9b0b51407ccc002eeed3b3102d20a88f1c1d3c3154e2449317b8ef95090e77b312d5cc39354f86d5d606@52.176.7.10:30303", + "enode://865a63255b3bb68023b6bffd5095118fcc13e79dcf014fe4e47e065c350c7cc72af2e53eff895f11ba1bbb6a2b33271c1116ee870f266618eadfc2e78aa7349c@52.176.100.77:30303", + "enode://691907d5a7dee24884b791e799183e5db01f4fe0b6e9b795ffaf5cf85a3023a637f2abadc82fc0da168405092df869126377c5f190794cd2d1c067245ae2b1ce@13.125.237.43:30303" + ], + "accounts": { + "0x0000000000000000000000000000000000000000": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000001": { + "balance": "0x1", + "nonce": "0x0", + "builtin": { + "name": "ecrecover", + "pricing": { + "linear": { + "base": 3000, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000002": { + "balance": "0x1", + "nonce": "0x0", + "builtin": { + "name": "sha256", + "pricing": { + "linear": { + "base": 60, + "word": 12 + } + } + } + }, + "0x0000000000000000000000000000000000000003": { + "balance": "0x1", + "nonce": "0x0", + "builtin": { + "name": "ripemd160", + "pricing": { + "linear": { + "base": 600, + "word": 120 + } + } + } + }, + "0x0000000000000000000000000000000000000004": { + "balance": "0x1", + "nonce": "0x0", + "builtin": { + "name": "identity", + "pricing": { + "linear": { + "base": 15, + "word": 3 + } + } + } + }, + "0x0000000000000000000000000000000000000005": { + "balance": "0x1", + "nonce": "0x0", + "builtin": { + "name": "modexp", + "activate_at": "0x19f0a0", + "pricing": { + "modexp": { + "divisor": 20 + } + } + } + }, + "0x0000000000000000000000000000000000000006": { + "balance": "0x1", + "nonce": "0x0", + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x19f0a0", + "pricing": { + "linear": { + "base": 500, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000007": { + "balance": "0x1", + "nonce": "0x0", + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x19f0a0", + "pricing": { + "linear": { + "base": 40000, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000008": { + "balance": "0x1", + "nonce": "0x0", + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x19f0a0", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000 + } + } + } + }, + "0x0000000000000000000000000000000000000009": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000a": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000000b": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000000c": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000000d": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000000e": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000000f": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000010": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000011": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000012": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000013": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000014": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000015": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000016": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000017": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000018": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000019": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000001a": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000001b": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000001c": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000001d": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000001e": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000001f": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000020": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000021": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000022": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000023": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000024": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000025": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000026": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000027": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000028": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000029": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000002a": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000002b": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000002c": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000002d": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000002e": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000002f": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000030": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000031": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000032": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000033": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000034": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000035": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000036": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000037": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000038": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000039": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000003a": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000003b": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000003c": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000003d": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000003e": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000003f": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000040": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000041": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000042": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000043": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000044": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000045": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000046": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000047": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000048": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000049": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000004a": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000004b": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000004c": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000004d": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000004e": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000004f": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000050": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000051": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000052": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000053": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000054": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000055": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000056": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000057": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000058": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000059": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000005a": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000005b": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000005c": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000005d": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000005e": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000005f": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000060": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000061": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000062": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000063": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000064": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000065": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000066": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000067": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000068": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000069": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000006a": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000006b": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000006c": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000006d": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000006e": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000006f": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000070": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000071": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000072": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000073": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000074": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000075": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000076": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000077": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000078": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000079": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000007a": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000007b": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000007c": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000007d": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000007e": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000007f": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000080": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000081": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000082": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000083": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000084": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000085": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000086": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000087": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000088": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000089": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000008a": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000008b": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000008c": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000008d": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000008e": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000008f": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000090": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000091": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000092": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000093": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000094": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000095": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000096": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000097": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000098": { + "balance": "0x0" + }, + "0x0000000000000000000000000000000000000099": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000009a": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000009b": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000009c": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000009d": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000009e": { + "balance": "0x0" + }, + "0x000000000000000000000000000000000000009f": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000a0": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000a1": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000a2": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000a3": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000a4": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000a5": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000a6": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000a7": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000a8": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000a9": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000aa": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000ab": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000ac": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000ad": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000ae": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000af": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000b0": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000b1": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000b2": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000b3": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000b4": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000b5": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000b6": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000b7": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000b8": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000b9": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000ba": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000bb": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000bc": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000bd": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000be": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000bf": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000c0": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000c1": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000c2": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000c3": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000c4": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000c5": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000c6": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000c7": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000c8": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000c9": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000ca": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000cb": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000cc": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000cd": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000ce": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000cf": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000d0": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000d1": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000d2": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000d3": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000d4": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000d5": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000d6": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000d7": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000d8": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000d9": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000da": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000db": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000dc": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000dd": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000de": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000df": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000e0": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000e1": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000e2": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000e3": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000e4": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000e5": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000e6": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000e7": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000e8": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000e9": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000ea": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000eb": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000ec": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000ed": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000ee": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000ef": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000f0": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000f1": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000f2": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000f3": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000f4": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000f5": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000f6": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000f7": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000f8": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000f9": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000fa": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000fb": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000fc": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000fd": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000fe": { + "balance": "0x0" + }, + "0x00000000000000000000000000000000000000ff": { + "balance": "0x0" + }, + "0x874b54a8bd152966d63f706bae1ffeb0411921e5": { + "balance": "0xc9f2c9cd04674edea40000000" + } + } +} \ No newline at end of file diff --git a/src/Nethermind/Chains/wit.json b/src/Nethermind/Chains/wit.json new file mode 100644 index 00000000000..975d8f927d0 --- /dev/null +++ b/src/Nethermind/Chains/wit.json @@ -0,0 +1,173 @@ +{ + "name": "CliqueTrinity", + "dataDir": "clique_trinity", + "engine": { + "clique": { + "params": { + "period": 15, + "epoch": 30000 + } + } + }, + "params": { + "accountStartNonce": "0x0", + "chainID": "0x5", + "eip140Transition": "0x0", + "eip145Transition": "0x0", + "eip150Transition": "0x0", + "eip155Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0", + "eip1014Transition": "0x0", + "eip1052Transition": "0x0", + "eip1283Transition": "0x0", + "eip1283DisableTransition": "0x0", + "eip152Transition": "0x17D433", + "eip1108Transition": "0x17D433", + "eip1344Transition": "0x17D433", + "eip1884Transition": "0x17D433", + "eip2028Transition": "0x17D433", + "eip2200Transition": "0x17D433", + "gasLimitBoundDivisor": "0x400", + "maxCodeSize": "0x6000", + "maxCodeSizeTransition": "0x0", + "maximumExtraDataSize": "0xffff", + "minGasLimit": "0x1388", + "networkID": "0x44" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "author": "0x0000000000000000000000000000000000000000", + "difficulty": "0x1", + "extraData": "0x22466c6578692069732061207468696e6722202d204166726900000000000000ff7c66068fb536b0a463ad82436b8baf741617290000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0xa00000", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp": "0x5bdda800" + }, + "nodes": [ + "enode://cedb232376896fd6753f4ed4c805cd5492aaadc484aa53626ac481e80b65cedea635c5ac9b2cd9db6e724d9fe40f2cdf86639591bf6dbc931e08dfd70276537d@94.237.80.80:31505" + ], + "accounts": { + "0x0000000000000000000000000000000000000000": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000001": { + "balance": "0x1", + "builtin": { + "name": "ecrecover", + "pricing": { + "linear": { + "base": 3000, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000002": { + "balance": "0x1", + "builtin": { + "name": "sha256", + "pricing": { + "linear": { + "base": 60, + "word": 12 + } + } + } + }, + "0x0000000000000000000000000000000000000003": { + "balance": "0x1", + "builtin": { + "name": "ripemd160", + "pricing": { + "linear": { + "base": 600, + "word": 120 + } + } + } + }, + "0x0000000000000000000000000000000000000004": { + "balance": "0x1", + "builtin": { + "name": "identity", + "pricing": { + "linear": { + "base": 15, + "word": 3 + } + } + } + }, + "0x0000000000000000000000000000000000000005": { + "balance": "0x1", + "builtin": { + "name": "modexp", + "activate_at": "0x0", + "pricing": { + "modexp": { + "divisor": 20 + } + } + } + }, + "0x0000000000000000000000000000000000000006": { + "balance": "0x1", + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x0", + "pricing": { + "linear": { + "base": 500, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000007": { + "balance": "0x1", + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x0", + "pricing": { + "linear": { + "base": 40000, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000008": { + "balance": "0x1", + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x0", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000 + } + } + } + }, + "7e5f4552091a69125d5dfcb7b8c2659029395bdf": { "balance": "100000000000000000000" }, + "2b5ad5c4795c026514f8317c7a215e218dccd6cf": { "balance": "100000000000000000000" }, + "6813eb9362372eef6200f3b1dbc3f819671cba69": { "balance": "100000000000000000000" }, + "1eff47bc3a10a45d4b230b5d10e37751fe6aa718": { "balance": "100000000000000000000" }, + "e1ab8145f7e55dc933d51a18c793f901a3a0b276": { "balance": "100000000000000000000" }, + "e57bfe9f44b819898f47bf37e5af72a0783e1141": { "balance": "100000000000000000000" }, + "d41c057fd1c78805aac12b0a94a405c0461a6fbb": { "balance": "100000000000000000000" }, + "f1f6619b38a98d6de0800f1defc0a6399eb6d30c": { "balance": "100000000000000000000" }, + "f7edc8fa1ecc32967f827c9043fcae6ba73afa5c": { "balance": "100000000000000000000" }, + "ff7c66068fb536b0a463ad82436b8baf74161729": { "balance": "100000000000000000000" } + } +} diff --git a/src/Nethermind/Chains/xdai.json b/src/Nethermind/Chains/xdai.json new file mode 100644 index 00000000000..5325171ad48 --- /dev/null +++ b/src/Nethermind/Chains/xdai.json @@ -0,0 +1,263 @@ +{ + "name": "GnosisChain", + "engine": { + "authorityRound": { + "params": { + "stepDuration": 5, + "blockReward": "0x0", + "maximumUncleCountTransition": 0, + "maximumUncleCount": 0, + "validators": { + "multi": { + "0": { + "list": [ + "0xcace5b3c29211740e595850e80478416ee77ca21" + ] + }, + "1300": { + "safeContract": "0x22e1229a2c5b95a60983b5577f745a603284f535" + }, + "9186425": { + "contract": "0xB87BE9f7196F2AE084Ca1DE6af5264292976e013" + } + } + }, + "blockRewardContractAddress": "0x867305d19606aadba405ce534e303d0e225f9556", + "blockRewardContractTransition": 1310, + "blockRewardContractTransitions": { + "9186425": "0x481c034c6d9441db23Ea48De68BCAe812C5d39bA" + }, + "randomnessContractAddress": { + "9186425": "0x5870b0527DeDB1cFBD9534343Feda1a41Ce47766" + }, + "posdaoTransition": 9186425, + "rewriteBytecode": { + "21735000": { + "0xf8D1677c8a0c961938bf2f9aDc3F3CFDA759A9d9": "0x6080604052600436106101b35763ffffffff60e060020a60003504166305d2035b81146101b857806306fdde03146101e1578063095ea7b31461026b5780630b26cf661461028f57806318160ddd146102b257806323b872dd146102d957806330adf81f14610303578063313ce567146103185780633644e5151461034357806339509351146103585780634000aea01461037c57806340c10f19146103ad57806342966c68146103d157806354fd4d50146103e957806366188463146103fe57806369ffa08a1461042257806370a0823114610449578063715018a61461046a578063726600ce1461047f5780637d64bcb4146104a05780637ecebe00146104b5578063859ba28c146104d65780638da5cb5b146105175780638fcbaf0c1461054857806395d89b4114610586578063a457c2d71461059b578063a9059cbb146105bf578063b753a98c146105e3578063bb35783b14610607578063c6a1dedf14610631578063cd59658314610646578063d505accf1461065b578063d73dd62314610694578063dd62ed3e146106b8578063f2d5d56b146106df578063f2fde38b14610703578063ff9e884d14610724575b600080fd5b3480156101c457600080fd5b506101cd61074b565b604080519115158252519081900360200190f35b3480156101ed57600080fd5b506101f661076c565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610230578181015183820152602001610218565b50505050905090810190601f16801561025d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561027757600080fd5b506101cd600160a060020a03600435166024356107fa565b34801561029b57600080fd5b506102b0600160a060020a0360043516610810565b005b3480156102be57600080fd5b506102c761086a565b60408051918252519081900360200190f35b3480156102e557600080fd5b506101cd600160a060020a0360043581169060243516604435610870565b34801561030f57600080fd5b506102c7610a38565b34801561032457600080fd5b5061032d610a5c565b6040805160ff9092168252519081900360200190f35b34801561034f57600080fd5b506102c7610a65565b34801561036457600080fd5b506101cd600160a060020a0360043516602435610a6b565b34801561038857600080fd5b506101cd60048035600160a060020a0316906024803591604435918201910135610aac565b3480156103b957600080fd5b506101cd600160a060020a0360043516602435610bbd565b3480156103dd57600080fd5b506102b0600435610cc8565b3480156103f557600080fd5b506101f6610cd5565b34801561040a57600080fd5b506101cd600160a060020a0360043516602435610d0c565b34801561042e57600080fd5b506102b0600160a060020a0360043581169060243516610de9565b34801561045557600080fd5b506102c7600160a060020a0360043516610e0e565b34801561047657600080fd5b506102b0610e29565b34801561048b57600080fd5b506101cd600160a060020a0360043516610e40565b3480156104ac57600080fd5b506101cd610e54565b3480156104c157600080fd5b506102c7600160a060020a0360043516610e5b565b3480156104e257600080fd5b506104eb610e6d565b6040805167ffffffffffffffff9485168152928416602084015292168183015290519081900360600190f35b34801561052357600080fd5b5061052c610e78565b60408051600160a060020a039092168252519081900360200190f35b34801561055457600080fd5b506102b0600160a060020a0360043581169060243516604435606435608435151560ff60a4351660c43560e435610e87565b34801561059257600080fd5b506101f6610fc5565b3480156105a757600080fd5b506101cd600160a060020a036004351660243561101f565b3480156105cb57600080fd5b506101cd600160a060020a0360043516602435611032565b3480156105ef57600080fd5b506102b0600160a060020a0360043516602435611054565b34801561061357600080fd5b506102b0600160a060020a0360043581169060243516604435611064565b34801561063d57600080fd5b506102c7611075565b34801561065257600080fd5b5061052c611099565b34801561066757600080fd5b506102b0600160a060020a036004358116906024351660443560643560ff6084351660a43560c4356110a8565b3480156106a057600080fd5b506101cd600160a060020a0360043516602435611184565b3480156106c457600080fd5b506102c7600160a060020a036004358116906024351661120b565b3480156106eb57600080fd5b506102b0600160a060020a0360043516602435611236565b34801561070f57600080fd5b506102b0600160a060020a0360043516611241565b34801561073057600080fd5b506102c7600160a060020a0360043581169060243516611261565b60065474010000000000000000000000000000000000000000900460ff1681565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107f25780601f106107c7576101008083540402835291602001916107f2565b820191906000526020600020905b8154815290600101906020018083116107d557829003601f168201915b505050505081565b600061080733848461127e565b50600192915050565b600654600160a060020a0316331461082757600080fd5b610830816112c0565b151561083b57600080fd5b6007805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60045490565b600080600160a060020a038516151561088857600080fd5b600160a060020a038416151561089d57600080fd5b600160a060020a0385166000908152600360205260409020546108c6908463ffffffff6112c816565b600160a060020a0380871660009081526003602052604080822093909355908616815220546108fb908463ffffffff6112da16565b600160a060020a038086166000818152600360209081526040918290209490945580518781529051919392891692600080516020611d7283398151915292918290030190a3600160a060020a0385163314610a225761095a853361120b565b905060001981146109c457610975818463ffffffff6112c816565b600160a060020a038616600081815260056020908152604080832033808552908352928190208590558051948552519193600080516020611d92833981519152929081900390910190a3610a22565b600160a060020a0385166000908152600a602090815260408083203384529091529020541580610a175750600160a060020a0385166000908152600a602090815260408083203384529091529020544211155b1515610a2257600080fd5b610a2d8585856112ed565b506001949350505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60025460ff1681565b60085481565b336000818152600560209081526040808320600160a060020a03871684529091528120549091610807918590610aa7908663ffffffff6112da16565b61127e565b600084600160a060020a03811615801590610ad05750600160a060020a0381163014155b1515610adb57600080fd5b610ae58686611324565b1515610af057600080fd5b85600160a060020a031633600160a060020a03167fe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c16878787604051808481526020018060200182810382528484828181526020019250808284376040519201829003965090945050505050a3610b65866112c0565b15610bb157610ba633878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843750611330945050505050565b1515610bb157600080fd5b50600195945050505050565b600654600090600160a060020a03163314610bd757600080fd5b60065474010000000000000000000000000000000000000000900460ff1615610bff57600080fd5b600454610c12908363ffffffff6112da16565b600455600160a060020a038316600090815260036020526040902054610c3e908363ffffffff6112da16565b600160a060020a038416600081815260036020908152604091829020939093558051858152905191927f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688592918290030190a2604080518381529051600160a060020a03851691600091600080516020611d728339815191529181900360200190a350600192915050565b610cd233826114ad565b50565b60408051808201909152600181527f3100000000000000000000000000000000000000000000000000000000000000602082015281565b336000908152600560209081526040808320600160a060020a0386168452909152812054808310610d6057336000908152600560209081526040808320600160a060020a0388168452909152812055610d95565b610d70818463ffffffff6112c816565b336000908152600560209081526040808320600160a060020a03891684529091529020555b336000818152600560209081526040808320600160a060020a038916808552908352928190205481519081529051929392600080516020611d92833981519152929181900390910190a35060019392505050565b600654600160a060020a03163314610e0057600080fd5b610e0a828261159c565b5050565b600160a060020a031660009081526003602052604090205490565b600654600160a060020a031633146101b357600080fd5b600754600160a060020a0390811691161490565b6000806000fd5b60096020526000908152604090205481565b600260056000909192565b600654600160a060020a031681565b600080861580610e975750864211155b1515610ea257600080fd5b604080517fea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb6020820152600160a060020a03808d16828401528b166060820152608081018a905260a0810189905287151560c0808301919091528251808303909101815260e0909101909152610f17906115da565b9150610f25828686866116e1565b600160a060020a038b8116911614610f3c57600080fd5b600160a060020a038a1660009081526009602052604090208054600181019091558814610f6857600080fd5b85610f74576000610f78565b6000195b905085610f86576000610f88565b865b600160a060020a03808c166000908152600a60209081526040808320938e1683529290522055610fb98a8a836118e3565b50505050505050505050565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107f25780601f106107c7576101008083540402835291602001916107f2565b600061102b8383610d0c565b9392505050565b600061103e8383611324565b151561104957600080fd5b6108073384846112ed565b61105f338383610870565b505050565b61106f838383610870565b50505050565b7fea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb81565b600754600160a060020a031690565b600080428610156110b857600080fd5b600160a060020a03808a1660008181526009602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c99281019290925281830193909352928b166060840152608083018a905260a0830182905260c08084018a90528151808503909101815260e090930190529250611149906115da565b9050611157818686866116e1565b600160a060020a038a811691161461116e57600080fd5b61117989898961127e565b505050505050505050565b336000908152600560209081526040808320600160a060020a03861684529091528120546111b8908363ffffffff6112da16565b336000818152600560209081526040808320600160a060020a038916808552908352928190208590558051948552519193600080516020611d92833981519152929081900390910190a350600192915050565b600160a060020a03918216600090815260056020908152604080832093909416825291909152205490565b61105f823383610870565b600654600160a060020a0316331461125857600080fd5b610cd281611a3e565b600a60209081526000928352604080842090915290825290205481565b6112898383836118e3565b60001981141561105f57600160a060020a038084166000908152600a60209081526040808320938616835292905290812055505050565b6000903b1190565b6000828211156112d457fe5b50900390565b818101828110156112e757fe5b92915050565b6112f682610e40565b1561105f5760408051600081526020810190915261131990849084908490611330565b151561105f57600080fd5b600061102b8383611abc565b600083600160a060020a031663a4c0ed3660e060020a028685856040516024018084600160a060020a0316600160a060020a0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156113a8578181015183820152602001611390565b50505050905090810190601f1680156113d55780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909916989098178852518151919790965086955093509150819050838360005b8381101561146357818101518382015260200161144b565b50505050905090810190601f1680156114905780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af1979650505050505050565b600160a060020a0382166000908152600360205260409020548111156114d257600080fd5b600160a060020a0382166000908152600360205260409020546114fb908263ffffffff6112c816565b600160a060020a038316600090815260036020526040902055600454611527908263ffffffff6112c816565b600455604080518281529051600160a060020a038416917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a2604080518281529051600091600160a060020a03851691600080516020611d728339815191529181900360200190a35050565b80600160a060020a03811615156115b257600080fd5b600160a060020a03831615156115d0576115cb82611b8b565b61105f565b61105f8383611b97565b6000600854826040518082805190602001908083835b6020831061160f5780518252601f1990920191602091820191016115f0565b51815160209384036101000a6000190180199092169116179052604080519290940182900382207f190100000000000000000000000000000000000000000000000000000000000083830152602283019790975260428083019790975283518083039097018752606290910192839052855192945084935085019190508083835b602083106116af5780518252601f199092019160209182019101611690565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912095945050505050565b6000808460ff16601b14806116f957508460ff16601c145b1515611775576040805160e560020a62461bcd02815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f7565000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611813576040805160e560020a62461bcd02815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f7565000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b60408051600080825260208083018085528a905260ff8916838501526060830188905260808301879052925160019360a0808501949193601f19840193928390039091019190865af115801561186d573d6000803e3d6000fd5b5050604051601f190151915050600160a060020a03811615156118da576040805160e560020a62461bcd02815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b600160a060020a0383161515611968576040805160e560020a62461bcd028152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a03821615156119ee576040805160e560020a62461bcd02815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a0380841660008181526005602090815260408083209487168084529482529182902085905581518581529151600080516020611d928339815191529281900390910190a3505050565b600160a060020a0381161515611a5357600080fd5b600654604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36006805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b33600090815260036020526040812054821115611ad857600080fd5b600160a060020a0383161515611aed57600080fd5b33600090815260036020526040902054611b0d908363ffffffff6112c816565b3360009081526003602052604080822092909255600160a060020a03851681522054611b3f908363ffffffff6112da16565b600160a060020a038416600081815260036020908152604091829020939093558051858152905191923392600080516020611d728339815191529281900390910190a350600192915050565b3031610e0a8282611c44565b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290518391600091600160a060020a038416916370a0823191602480830192602092919082900301818787803b158015611bfc57600080fd5b505af1158015611c10573d6000803e3d6000fd5b505050506040513d6020811015611c2657600080fd5b5051905061106f600160a060020a038516848363ffffffff611cac16565b604051600160a060020a0383169082156108fc029083906000818181858888f193505050501515610e0a578082611c79611d41565b600160a060020a039091168152604051908190036020019082f080158015611ca5573d6000803e3d6000fd5b5050505050565b82600160a060020a031663a9059cbb83836040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b158015611d0f57600080fd5b505af1158015611d23573d6000803e3d6000fd5b505050503d1561105f5760206000803e600051151561105f57600080fd5b604051602180611d51833901905600608060405260405160208060218339810160405251600160a060020a038116ff00ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a165627a7a72305820b96bb0733a3e45fdddafa592f51114d0cf16cad047ad60b9b91ae91eb772c6940029" + } + } + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x400", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID": "100", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0", + "eip145Transition": 1604400, + "eip1014Transition": 1604400, + "eip1052Transition": 1604400, + "eip1283Transition": 1604400, + "eip1283DisableTransition": 2508800, + "eip152Transition": 7298030, + "eip1108Transition": 7298030, + "eip1283ReenableTransition": 7298030, + "eip1344Transition": 7298030, + "eip1706Transition": 7298030, + "eip1884Transition": 7298030, + "eip2028Transition": 7298030, + "eip2565Transition": 16101500, + "eip2929Transition": 16101500, + "eip2930Transition": 16101500, + "eip3198Transition": 19040000, + "eip3529Transition": 19040000, + "eip3541Transition": 19040000, + "eip1559Transition": 19040000, + "eip1559BaseFeeMaxChangeDenominator": "0x8", + "eip1559ElasticityMultiplier": "0x2", + "eip1559BaseFeeInitialValue": "0x3b9aca00", + "eip1559FeeCollector": "0x6BBe78ee9e474842Dbd4AB4987b3CeFE88426A92", + "eip1559FeeCollectorTransition": 19040000, + "registrar": "0x6B53721D4f2Fb9514B85f5C49b197D857e36Cf03", + "transactionPermissionContract": "0x7Dd7032AA75A37ea0b150f57F899119C7379A78b", + "transactionPermissionContractTransition": 9186425, + "terminalTotalDifficulty": "8626000000000000000000058750000000000000000000" + }, + "genesis": { + "seal": { + "authorityRound": { + "step": "0x0", + "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x20000", + "gasLimit": "0x989680" + }, + "nodes": [ +"enode://6765fff89db92aa8d923e28c438af626c8ae95a43093cdccbd6f550a7b6ce6ab5d1a3dc60dd79af3e6d2c2e6731bae629f0e54446a0d9da408c4eca7ebcd8485@3.75.159.31:30303", +"enode://9a7c98e8ee8cdd3199db68092b48868847d4743a471b26afc2ff878bafaa829ed43ee405f9aff58ae13fce53b898f7c2e3c30cb80af8eb111682c3c13f686dbb@18.198.130.54:30303", +"enode://2c4307831914c237801993eac4f9596d8b2f78e1e76830419b64cb23f0933e52cb1e2bb3009cb4af76454bb5bc296135b36869fd6c13e2c2e536a0780e60fe82@3.64.242.196:30303", +"enode://074f68e1a7df5b0859314ff721d55b59d9690e93249c941660609a29b302f02864df4f93ee48884f7ede57dc7f7646379d017a43c9745e34baff049749896b50@3.126.169.151:30303", +"enode://d239697375d7586c7ea1de790401c310b0b1d389326849fa3b7c7005833c7a6b9020e49dfb3b61abfa39135237ffc4ff219cb84ca7653069e8548497527aa432@107.22.4.120:30303", +"enode://d5852bf415d89b756faa809f4ff3f8beb661dc7d60cfb4a5542f9a5fcdf41e1ed0708a210db64b8c7ca32426e04ef0a50da58974124fdf562a8510314d11e28c@3.26.206.142:30303", +"enode://01d372392bb22dd8a91f8b10b6bbb8d80d2dbe98d695801e0df9e4bd4825781df84bba88361f24d1b6580a61313f64e6cec82e8d842ad5f1b3d7cf8d6d132da7@15.152.45.82:30303", +"enode://aee88e803b8e54925081957965b2527961cd90f4d6d14664884580b429da44729678a1258a8b49a42d1582c9c7c5ded05733622f7ab442ad9c6f655545a5ecdd@54.207.220.169:30303" + ], + "accounts": { + "0x0000000000000000000000000000000000000005": { + "builtin": { + "name": "modexp", + "pricing": { + "0": { + "price": { + "modexp": { + "divisor": 20 + } + } + } + } + } + }, + "0x0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "pricing": { + "0": { + "price": { + "alt_bn128_const_operations": { + "price": 500 + } + } + }, + "7298030": { + "info": "Istanbul HF", + "price": { + "alt_bn128_const_operations": { + "price": 150 + } + } + } + } + } + }, + "0x0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "pricing": { + "0": { + "price": { + "alt_bn128_const_operations": { + "price": 40000 + } + } + }, + "7298030": { + "info": "Istanbul HF", + "price": { + "alt_bn128_const_operations": { + "price": 6000 + } + } + } + } + } + }, + "0x0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "pricing": { + "0": { + "price": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000 + } + } + }, + "7298030": { + "info": "Istanbul HF", + "price": { + "alt_bn128_pairing": { + "base": 45000, + "pair": 34000 + } + } + } + } + } + }, + "0x0000000000000000000000000000000000000009": { + "builtin": { + "name": "blake2_f", + "pricing": { + "7298030": { + "info": "Istanbul HF", + "price": { + "blake2_f": { + "gas_per_round": 1 + } + } + } + } + } + }, + "0x0000000000000000000000000000000000000001": { + "balance": "1", + "builtin": { + "name": "ecrecover", + "pricing": { + "0": { + "price": { + "linear": { + "base": 3000, + "word": 0 + } + } + } + } + } + }, + "0x0000000000000000000000000000000000000002": { + "balance": "1", + "builtin": { + "name": "sha256", + "pricing": { + "0": { + "price": { + "linear": { + "base": 60, + "word": 12 + } + } + } + } + } + }, + "0x0000000000000000000000000000000000000003": { + "balance": "1", + "builtin": { + "name": "ripemd160", + "pricing": { + "0": { + "price": { + "linear": { + "base": 600, + "word": 120 + } + } + } + } + } + }, + "0x0000000000000000000000000000000000000004": { + "balance": "1", + "builtin": { + "name": "identity", + "pricing": { + "0": { + "price": { + "linear": { + "base": 15, + "word": 3 + } + } + } + } + } + } + } +} diff --git a/src/Nethermind/Directory.Build.props b/src/Nethermind/Directory.Build.props index 671224eecec..74b3b515a84 100644 --- a/src/Nethermind/Directory.Build.props +++ b/src/Nethermind/Directory.Build.props @@ -9,8 +9,8 @@ Demerzel Solutions Limited Nethermind $(Commit.Substring(0, 8)) - 1.21.0 - unstable + 1.20.0-unstable + @@ -23,5 +23,5 @@ <_Parameter2>$(Commit) - + diff --git a/src/Nethermind/Directory.Packages.props b/src/Nethermind/Directory.Packages.props index e6e44f4b492..8088eacfd02 100644 --- a/src/Nethermind/Directory.Packages.props +++ b/src/Nethermind/Directory.Packages.props @@ -3,83 +3,81 @@ true - + - + - - + + - + - - + + - + - - - + + + - + - - - + + + - - - + + + - + - - + + - + - + - - - + + - + - - + + - + - - - - + + + - \ No newline at end of file + diff --git a/src/Nethermind/Ethereum.Blockchain.Block.Test/Eip6780Tests.cs b/src/Nethermind/Ethereum.Blockchain.Block.Test/Eip6780Tests.cs deleted file mode 100644 index e13da99b474..00000000000 --- a/src/Nethermind/Ethereum.Blockchain.Block.Test/Eip6780Tests.cs +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using Ethereum.Test.Base; -using NUnit.Framework; - -namespace Ethereum.Blockchain.Block.Test; - -[TestFixture] -[Parallelizable(ParallelScope.All)] -public class Eip6780Tests : BlockchainTestBase -{ - //[TestCaseSource(nameof(LoadTests))] - //public async Task Test(BlockchainTest test) - //{ - // await RunTest(test); - //} - - public static IEnumerable LoadTests() - { - var loader = new TestsSourceLoader(new LoadBlockchainTestsStrategy(), "bcEIP6780"); - return (IEnumerable)loader.LoadTests(); - } -} diff --git a/src/Nethermind/Ethereum.Blockchain.Test/Eip1153Tests.cs b/src/Nethermind/Ethereum.Blockchain.Test/Eip1153Tests.cs deleted file mode 100644 index 056d80d94f0..00000000000 --- a/src/Nethermind/Ethereum.Blockchain.Test/Eip1153Tests.cs +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using Ethereum.Test.Base; -using NUnit.Framework; - -namespace Ethereum.Blockchain.Test; - -[TestFixture] -[Parallelizable(ParallelScope.All)] -public class EIP1153transientStorageTests : GeneralStateTestBase -{ - [TestCaseSource(nameof(LoadTests))] - public void Test(GeneralStateTest test) - { - Assert.True(RunTest(test).Pass); - } - - public static IEnumerable LoadTests() - { - var loader = new TestsSourceLoader(new LoadEipTestsStrategy(), "stEIP1153-transientStorage"); - return (IEnumerable)loader.LoadTests(); - } -} diff --git a/src/Nethermind/Ethereum.Blockchain.Test/Eip4844Tests.cs b/src/Nethermind/Ethereum.Blockchain.Test/Eip4844Tests.cs deleted file mode 100644 index 89cbdba8b61..00000000000 --- a/src/Nethermind/Ethereum.Blockchain.Test/Eip4844Tests.cs +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using Ethereum.Test.Base; -using NUnit.Framework; - -namespace Ethereum.Blockchain.Test; - -[TestFixture] -[Parallelizable(ParallelScope.All)] -public class EIP4844blobtransactionsTests : GeneralStateTestBase -{ - // Uncomment when stEIP4844 tests are merged - - // [TestCaseSource(nameof(LoadTests))] - // public void Test(GeneralStateTest test) - // { - // Assert.True(RunTest(test).Pass); - // } - - public static IEnumerable LoadTests() - { - var loader = new TestsSourceLoader(new LoadEipTestsStrategy(), "stEIP4844-blobtransactions"); - return (IEnumerable)loader.LoadTests(); - } -} diff --git a/src/Nethermind/Ethereum.Blockchain.Test/Eip5656Tests.cs b/src/Nethermind/Ethereum.Blockchain.Test/Eip5656Tests.cs deleted file mode 100644 index 1a48e321290..00000000000 --- a/src/Nethermind/Ethereum.Blockchain.Test/Eip5656Tests.cs +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using Ethereum.Test.Base; -using NUnit.Framework; - -namespace Ethereum.Blockchain.Test; - -[TestFixture] -[Parallelizable(ParallelScope.All)] -public class EIP5656MCOPYTests : GeneralStateTestBase -{ - [TestCaseSource(nameof(LoadTests))] - public void Test(GeneralStateTest test) - { - Assert.True(RunTest(test).Pass); - } - - public static IEnumerable LoadTests() - { - var loader = new TestsSourceLoader(new LoadEipTestsStrategy(), "stEIP5656-MCOPY"); - return (IEnumerable)loader.LoadTests(); - } -} diff --git a/src/Nethermind/Ethereum.Blockchain.Test/EofTests.cs b/src/Nethermind/Ethereum.Blockchain.Test/EofTests.cs deleted file mode 100644 index f4fad766299..00000000000 --- a/src/Nethermind/Ethereum.Blockchain.Test/EofTests.cs +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using Ethereum.Test.Base; -using NUnit.Framework; - -namespace Ethereum.Blockchain.Test; - -[TestFixture] -[Parallelizable(ParallelScope.All)] -public class EOFTests : GeneralStateTestBase -{ - // Uncomment when EOF tests are merged - - // [TestCaseSource(nameof(LoadTests))] - // public void Test(GeneralStateTest test) - // { - // Assert.True(RunTest(test).Pass); - // } - - public static IEnumerable LoadTests() - { - var loader = new TestsSourceLoader(new LoadEipTestsStrategy(), "stEOF"); - return (IEnumerable)loader.LoadTests(); - } -} diff --git a/src/Nethermind/Ethereum.Blockchain.Test/Ethereum.Blockchain.Test.csproj b/src/Nethermind/Ethereum.Blockchain.Test/Ethereum.Blockchain.Test.csproj index 6b3b7fdfc72..246ef27c0b6 100644 --- a/src/Nethermind/Ethereum.Blockchain.Test/Ethereum.Blockchain.Test.csproj +++ b/src/Nethermind/Ethereum.Blockchain.Test/Ethereum.Blockchain.Test.csproj @@ -39,10 +39,6 @@ %(RecursiveDir)%(FileName)%(Extension) PreserveNewest - - %(RecursiveDir)%(FileName)%(Extension) - PreserveNewest - diff --git a/src/Nethermind/Ethereum.Blockchain.Test/RevertTests.cs b/src/Nethermind/Ethereum.Blockchain.Test/RevertTests.cs index 33588d24396..f3c6ac0a29b 100644 --- a/src/Nethermind/Ethereum.Blockchain.Test/RevertTests.cs +++ b/src/Nethermind/Ethereum.Blockchain.Test/RevertTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using System.Linq; using Ethereum.Test.Base; using NUnit.Framework; diff --git a/src/Nethermind/Ethereum.Blockchain.Test/SpecialTests.cs b/src/Nethermind/Ethereum.Blockchain.Test/SpecialTests.cs index d931e0b88c4..bf80448f7a5 100644 --- a/src/Nethermind/Ethereum.Blockchain.Test/SpecialTests.cs +++ b/src/Nethermind/Ethereum.Blockchain.Test/SpecialTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Ethereum.Test.Base; +using Nethermind.Core.Attributes; using NUnit.Framework; namespace Ethereum.Blockchain.Test diff --git a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyByzantiumTests.cs b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyByzantiumTests.cs index 88d65b7e599..33da4a946fc 100644 --- a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyByzantiumTests.cs +++ b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyByzantiumTests.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using Nethermind.Specs; +using Nethermind.Specs.Forks; using NUnit.Framework; namespace Ethereum.Difficulty.Test diff --git a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyConstantinopleTests.cs b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyConstantinopleTests.cs index 50f856ab4d0..15078b819f3 100644 --- a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyConstantinopleTests.cs +++ b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyConstantinopleTests.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; +using Nethermind.Specs; +using Nethermind.Specs.Forks; using NUnit.Framework; namespace Ethereum.Difficulty.Test diff --git a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyCustomHomesteadTests.cs b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyCustomHomesteadTests.cs index f050f6b1110..6de83f84249 100644 --- a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyCustomHomesteadTests.cs +++ b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyCustomHomesteadTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using Nethermind.Core; using Nethermind.Specs; using Nethermind.Specs.Forks; using NUnit.Framework; diff --git a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyEIP2384RandomTests.cs b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyEIP2384RandomTests.cs index b4d8d85fe8d..1c672c6399d 100644 --- a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyEIP2384RandomTests.cs +++ b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyEIP2384RandomTests.cs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using Nethermind.Specs; +using Nethermind.Specs.Forks; using NUnit.Framework; namespace Ethereum.Difficulty.Test diff --git a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyEIP2384RandomTo20MTests.cs b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyEIP2384RandomTo20MTests.cs index d1b7c51436e..4bc205c5c99 100644 --- a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyEIP2384RandomTo20MTests.cs +++ b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyEIP2384RandomTo20MTests.cs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using Nethermind.Specs; +using Nethermind.Specs.Forks; using NUnit.Framework; namespace Ethereum.Difficulty.Test diff --git a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyEIP2384Tests.cs b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyEIP2384Tests.cs index 09fde801b76..e58a0b8bff5 100644 --- a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyEIP2384Tests.cs +++ b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyEIP2384Tests.cs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using Nethermind.Specs; +using Nethermind.Specs.Forks; using NUnit.Framework; namespace Ethereum.Difficulty.Test diff --git a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyFrontierTests.cs b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyFrontierTests.cs index d5ef09b19b5..db6e74cb755 100644 --- a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyFrontierTests.cs +++ b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyFrontierTests.cs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using Nethermind.Specs; +using Nethermind.Specs.Forks; using NUnit.Framework; namespace Ethereum.Difficulty.Test diff --git a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyHomesteadTests.cs b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyHomesteadTests.cs index d317a40beff..122d1a44ae6 100644 --- a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyHomesteadTests.cs +++ b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyHomesteadTests.cs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using Nethermind.Specs; +using Nethermind.Specs.Forks; using NUnit.Framework; namespace Ethereum.Difficulty.Test diff --git a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyMordenTests.cs b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyMordenTests.cs index aa0c3979fa2..a21d300f708 100644 --- a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyMordenTests.cs +++ b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyMordenTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using Nethermind.Specs; using NUnit.Framework; namespace Ethereum.Difficulty.Test diff --git a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyOlimpicTests.cs b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyOlimpicTests.cs index 478be5ef5b3..701da0d546a 100644 --- a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyOlimpicTests.cs +++ b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyOlimpicTests.cs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using Nethermind.Specs; +using Nethermind.Specs.Forks; using NUnit.Framework; namespace Ethereum.Difficulty.Test diff --git a/src/Nethermind/Ethereum.Difficulty.Test/DifficultyRopstenTests.cs b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyRopstenTests.cs new file mode 100644 index 00000000000..11894e0c8cd --- /dev/null +++ b/src/Nethermind/Ethereum.Difficulty.Test/DifficultyRopstenTests.cs @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Collections.Generic; +using Nethermind.Specs; +using NUnit.Framework; + +namespace Ethereum.Difficulty.Test +{ + [Parallelizable(ParallelScope.All)] + public class DifficultyRopstenTests : TestsBase + { + public static IEnumerable LoadRopstenTests() + { + return LoadHex("difficultyRopsten.json"); + } + + [TestCaseSource(nameof(LoadRopstenTests))] + public void Test(DifficultyTests test) + { + RunTest(test, RopstenSpecProvider.Instance); + } + } +} diff --git a/src/Nethermind/Ethereum.Difficulty.Test/MetaTests.cs b/src/Nethermind/Ethereum.Difficulty.Test/MetaTests.cs index 3c886565562..49f8d5de059 100644 --- a/src/Nethermind/Ethereum.Difficulty.Test/MetaTests.cs +++ b/src/Nethermind/Ethereum.Difficulty.Test/MetaTests.cs @@ -35,7 +35,7 @@ public void All_categories_are_tested() Console.WriteLine($"{missing} category is missing"); } - Assert.That(missingCategories.Where(x => x != "difficultyRopsten").Count, Is.EqualTo(0)); + Assert.That(missingCategories.Count, Is.EqualTo(0)); } private static string ExpectedTypeName(string directory) diff --git a/src/Nethermind/Ethereum.Difficulty.Test/TestsBase.cs b/src/Nethermind/Ethereum.Difficulty.Test/TestsBase.cs index c6c76bcfecb..6fe45991904 100644 --- a/src/Nethermind/Ethereum.Difficulty.Test/TestsBase.cs +++ b/src/Nethermind/Ethereum.Difficulty.Test/TestsBase.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Numerics; using Ethereum.Test.Base; +using Nethermind.Consensus; using Nethermind.Consensus.Ethash; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; diff --git a/src/Nethermind/Ethereum.KeyAddress.Test/KeyAddressTests.cs b/src/Nethermind/Ethereum.KeyAddress.Test/KeyAddressTests.cs index cc25a50d7e6..7881bf48506 100644 --- a/src/Nethermind/Ethereum.KeyAddress.Test/KeyAddressTests.cs +++ b/src/Nethermind/Ethereum.KeyAddress.Test/KeyAddressTests.cs @@ -75,7 +75,7 @@ public void Signature_as_expected(KeyAddressTest test) string expectedSigHex = expectedSig.ToString(); Address expectedAddress = new Address(test.Address); - Assert.That(actualAddress, Is.EqualTo(expectedAddress), "address vs address from private key"); + Assert.That(actualAddress, Is.EqualTo(expectedAddress), "address vs adress from private key"); Address recoveredActualAddress = _ecdsa.RecoverAddress(actualSig, Keccak.OfAnEmptyString); Assert.That(recoveredActualAddress, Is.EqualTo(actualAddress)); diff --git a/src/Nethermind/Ethereum.KeyStore.Test/Ethereum.KeyStore.Test.csproj b/src/Nethermind/Ethereum.KeyStore.Test/Ethereum.KeyStore.Test.csproj deleted file mode 100644 index 5f2ee66e959..00000000000 --- a/src/Nethermind/Ethereum.KeyStore.Test/Ethereum.KeyStore.Test.csproj +++ /dev/null @@ -1,35 +0,0 @@ - - - net7.0 - false - latest - - - false - - - - true - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - Always - - - \ No newline at end of file diff --git a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs index 1e744eb6f8e..6a3d0d0fd77 100644 --- a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs +++ b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs @@ -35,11 +35,6 @@ private static IReleaseSpec ParseSpec(string network) network = network.Replace("Merge+3540+3670", "Shanghai"); network = network.Replace("Shanghai+3855", "Shanghai"); network = network.Replace("Shanghai+3860", "Shanghai"); - network = network.Replace("GrayGlacier+1153", "Cancun"); - network = network.Replace("Merge+1153", "Cancun"); - network = network.Replace("Shanghai+6780", "Cancun"); - network = network.Replace("GrayGlacier+1153", "Cancun"); - network = network.Replace("Merge+1153", "Cancun"); return network switch { "Frontier" => Frontier.Instance, @@ -136,13 +131,13 @@ public static Transaction Convert(PostStateJson postStateJson, TransactionJson t transaction.Signature = new Signature(1, 1, 27); transaction.Hash = transaction.CalculateHash(); - AccessList.Builder builder = new(); + AccessListBuilder builder = new(); ProcessAccessList(transactionJson.AccessLists is not null ? transactionJson.AccessLists[postStateJson.Indexes.Data] : transactionJson.AccessList, builder); - transaction.AccessList = builder.Build(); + transaction.AccessList = builder.ToAccessList(); - if (transaction.AccessList.AsEnumerable().Count() != 0) + if (transaction.AccessList.Data.Count != 0) transaction.Type = TxType.AccessList; else transaction.AccessList = null; @@ -153,7 +148,7 @@ public static Transaction Convert(PostStateJson postStateJson, TransactionJson t return transaction; } - private static void ProcessAccessList(AccessListItemJson[]? accessList, AccessList.Builder builder) + private static void ProcessAccessList(AccessListItemJson[]? accessList, AccessListBuilder builder) { foreach (AccessListItemJson accessListItemJson in accessList ?? Array.Empty()) { diff --git a/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs deleted file mode 100644 index 82b5f344d2c..00000000000 --- a/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using System.IO; -using Ethereum.Test.Base.Interfaces; - -namespace Ethereum.Test.Base -{ - public class LoadEipTestsStrategy : ITestLoadStrategy - { - public IEnumerable Load(string testsDirectoryName, string wildcard = null) - { - IEnumerable testDirs; - if (!Path.IsPathRooted(testsDirectoryName)) - { - string testsDirectory = GetGeneralStateTestsDirectory(); - - - testDirs = Directory.EnumerateDirectories(testsDirectory, testsDirectoryName, new EnumerationOptions { RecurseSubdirectories = true }); - } - else - { - testDirs = new[] { testsDirectoryName }; - } - - List testJsons = new(); - foreach (string testDir in testDirs) - { - testJsons.AddRange(LoadTestsFromDirectory(testDir, wildcard)); - } - - return testJsons; - } - - private string GetGeneralStateTestsDirectory() - { - char pathSeparator = Path.AltDirectorySeparatorChar; - string currentDirectory = AppDomain.CurrentDomain.BaseDirectory; - - return currentDirectory.Remove(currentDirectory.LastIndexOf("src")) + $"src{pathSeparator}tests{pathSeparator}EIPTests{pathSeparator}StateTests"; - } - - private IEnumerable LoadTestsFromDirectory(string testDir, string wildcard) - { - List testsByName = new(); - IEnumerable testFiles = Directory.EnumerateFiles(testDir); - - foreach (string testFile in testFiles) - { - FileTestsSource fileTestsSource = new(testFile, wildcard); - try - { - var tests = fileTestsSource.LoadGeneralStateTests(); - foreach (GeneralStateTest blockchainTest in tests) - { - blockchainTest.Category = testDir; - } - - testsByName.AddRange(tests); - } - catch (Exception e) - { - testsByName.Add(new GeneralStateTest { Name = testFile, LoadFailure = $"Failed to load: {e}" }); - } - } - - return testsByName; - } - } -} diff --git a/src/Nethermind/Ethereum.Trie.Test/TrieTests.cs b/src/Nethermind/Ethereum.Trie.Test/TrieTests.cs index 5f9b1856d9b..400d04ca299 100644 --- a/src/Nethermind/Ethereum.Trie.Test/TrieTests.cs +++ b/src/Nethermind/Ethereum.Trie.Test/TrieTests.cs @@ -10,6 +10,7 @@ using Nethermind.Core.Extensions; using Nethermind.Db; using Nethermind.Logging; +using Nethermind.State; using Nethermind.Trie; using NUnit.Framework; diff --git a/src/Nethermind/EthereumTests.sln b/src/Nethermind/EthereumTests.sln index 75b1eb7492b..615018fa241 100644 --- a/src/Nethermind/EthereumTests.sln +++ b/src/Nethermind/EthereumTests.sln @@ -1,5 +1,4 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 +Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.2.32630.192 MinimumVisualStudioVersion = 10.0.40219.1 @@ -93,8 +92,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nethermind.Network.Discover EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nethermind.Network.Stats", "Nethermind.Network.Stats\Nethermind.Network.Stats.csproj", "{A586EBA6-9922-4359-BC8C-D90A6A9CBBDE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ethereum.KeyStore.Test", "Ethereum.KeyStore.Test\Ethereum.KeyStore.Test.csproj", "{320846D9-D733-4A58-A85D-638D36A08272}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -277,10 +274,6 @@ Global {A586EBA6-9922-4359-BC8C-D90A6A9CBBDE}.Debug|Any CPU.Build.0 = Debug|Any CPU {A586EBA6-9922-4359-BC8C-D90A6A9CBBDE}.Release|Any CPU.ActiveCfg = Release|Any CPU {A586EBA6-9922-4359-BC8C-D90A6A9CBBDE}.Release|Any CPU.Build.0 = Release|Any CPU - {320846D9-D733-4A58-A85D-638D36A08272}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {320846D9-D733-4A58-A85D-638D36A08272}.Debug|Any CPU.Build.0 = Debug|Any CPU - {320846D9-D733-4A58-A85D-638D36A08272}.Release|Any CPU.ActiveCfg = Release|Any CPU - {320846D9-D733-4A58-A85D-638D36A08272}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Nethermind/Nethermind.Abi.Test/Json/AbiDefinitionParserTests.cs b/src/Nethermind/Nethermind.Abi.Test/Json/AbiDefinitionParserTests.cs index 933838bfccd..d6826a31594 100644 --- a/src/Nethermind/Nethermind.Abi.Test/Json/AbiDefinitionParserTests.cs +++ b/src/Nethermind/Nethermind.Abi.Test/Json/AbiDefinitionParserTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using FluentAssertions; using FluentAssertions.Json; using Nethermind.Blockchain.Contracts.Json; using Nethermind.Consensus.AuRa.Contracts; diff --git a/src/Nethermind/Nethermind.Abi/AbiEncoder.cs b/src/Nethermind/Nethermind.Abi/AbiEncoder.cs index b02282cd020..53c6f4f9d1c 100644 --- a/src/Nethermind/Nethermind.Abi/AbiEncoder.cs +++ b/src/Nethermind/Nethermind.Abi/AbiEncoder.cs @@ -2,7 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; +using System.Numerics; using Nethermind.Core.Extensions; +using Nethermind.Int256; namespace Nethermind.Abi { diff --git a/src/Nethermind/Nethermind.Abi/AbiFixedLengthArray.cs b/src/Nethermind/Nethermind.Abi/AbiFixedLengthArray.cs index fb8719e94b1..987bf69ec08 100644 --- a/src/Nethermind/Nethermind.Abi/AbiFixedLengthArray.cs +++ b/src/Nethermind/Nethermind.Abi/AbiFixedLengthArray.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; using Nethermind.Core.Extensions; namespace Nethermind.Abi diff --git a/src/Nethermind/Nethermind.Abi/AbiInt.cs b/src/Nethermind/Nethermind.Abi/AbiInt.cs index 3ff214b8a99..8d4f91d6ec7 100644 --- a/src/Nethermind/Nethermind.Abi/AbiInt.cs +++ b/src/Nethermind/Nethermind.Abi/AbiInt.cs @@ -4,6 +4,7 @@ using System; using System.Numerics; using Nethermind.Core.Extensions; +using Nethermind.Int256; namespace Nethermind.Abi { diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionPeerManagerTests.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionPeerManagerTests.cs index 417be0263c8..361e787a6a0 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionPeerManagerTests.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionPeerManagerTests.cs @@ -2,13 +2,21 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Antlr4.Runtime.Misc; +using FluentAssertions; using Nethermind.AccountAbstraction.Broadcaster; using Nethermind.AccountAbstraction.Data; using Nethermind.AccountAbstraction.Executor; using Nethermind.AccountAbstraction.Network; using Nethermind.AccountAbstraction.Source; using Nethermind.Blockchain; +using Nethermind.Blockchain.Filters; +using Nethermind.Blockchain.Filters.Topics; using Nethermind.Blockchain.Find; +using Nethermind.Blockchain.Receipts; using Nethermind.Consensus; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -18,7 +26,9 @@ using Nethermind.State; using NSubstitute; using NUnit.Framework; +using Nethermind.Core.Test.Builders; using Nethermind.Crypto; +using Nethermind.Int256; using Nethermind.JsonRpc; namespace Nethermind.AccountAbstraction.Test diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs index 9e23adb567f..44f0aef692c 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs @@ -21,6 +21,7 @@ using Nethermind.Consensus.Test; using Nethermind.Consensus.Transactions; using Nethermind.Consensus.Validators; +using Nethermind.Consensus.Withdrawals; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; @@ -251,7 +252,7 @@ protected override BlockProcessor CreateBlockProcessor() } protected override async Task Build(ISpecProvider? specProvider = null, - UInt256? initialValues = null, bool addBlockOnStart = true) + UInt256? initialValues = null) { TestBlockchain chain = await base.Build(specProvider, initialValues); IList
entryPointContractAddresses = new List
(); @@ -288,25 +289,29 @@ private IBlockValidator CreateBlockValidator() public void SendUserOperation(Address entryPoint, UserOperation userOperation) { ResultWrapper resultOfUserOperation = UserOperationPool[entryPoint].AddUserOperation(userOperation); - resultOfUserOperation.Result.Should().Be(Result.Success, resultOfUserOperation.Result.Error); - resultOfUserOperation.Data.Should().Be(userOperation.RequestId!); + resultOfUserOperation.GetResult().ResultType.Should().NotBe(ResultType.Failure, resultOfUserOperation.Result.Error); + resultOfUserOperation.GetData().Should().Be(userOperation.RequestId!); } public void SupportedEntryPoints() { ResultWrapper resultOfEntryPoints = AccountAbstractionRpcModule.eth_supportedEntryPoints(); - resultOfEntryPoints.Result.Should().Be(Result.Success, resultOfEntryPoints.Result.Error); + resultOfEntryPoints.GetResult().ResultType.Should() + .NotBe(ResultType.Failure, resultOfEntryPoints.Result.Error); IList
entryPointContractAddresses = new List
(); - IList entryPointContractAddressesString = _accountAbstractionConfig.GetEntryPointAddresses().ToList(); - foreach (string addressString in entryPointContractAddressesString) + IList _entryPointContractAddressesString = + _accountAbstractionConfig.GetEntryPointAddresses().ToList(); + foreach (string _addressString in _entryPointContractAddressesString) { - Address.TryParse(addressString, out Address? entryPointContractAddress); + bool parsed = Address.TryParse( + _addressString, + out Address? entryPointContractAddress); entryPointContractAddresses.Add(entryPointContractAddress!); } Address[] eps = entryPointContractAddresses.ToArray(); - Address[] receivedEps = resultOfEntryPoints.Data; - Assert.That(receivedEps, Is.EqualTo(eps)); + Address[] recieved_eps = (Address[])(resultOfEntryPoints.GetData()!); + Assert.That(recieved_eps, Is.EqualTo(eps)); } } } diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.cs index ba3e746fad0..e6cbd2bb705 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.cs @@ -3,25 +3,32 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using DotNetty.Common.Utilities; using FluentAssertions; using Nethermind.Abi; using Nethermind.AccountAbstraction.Contracts; using Nethermind.AccountAbstraction.Data; using Nethermind.AccountAbstraction.Test.TestContracts; +using Nethermind.Blockchain.Contracts; using Nethermind.Blockchain.Contracts.Json; using Nethermind.Consensus; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Eip2930; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Int256; +using Nethermind.JsonRpc; using Nethermind.JsonRpc.Data; using Nethermind.JsonRpc.Test.Modules; using Nethermind.Logging; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using NUnit.Framework; namespace Nethermind.AccountAbstraction.Test diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/MevBundlerTest.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/MevBundlerTest.cs index f33d39cb625..778d87072e2 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/MevBundlerTest.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/MevBundlerTest.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Linq; using System.Collections.Generic; using Nethermind.AccountAbstraction.Bundler; diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/Network/AaProtocolHandlerTests.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/Network/AaProtocolHandlerTests.cs index 446fb00ca1a..9ab2c075a87 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/Network/AaProtocolHandlerTests.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/Network/AaProtocolHandlerTests.cs @@ -6,8 +6,10 @@ using System.Net; using DotNetty.Buffers; using FluentAssertions; +using Nethermind.AccountAbstraction.Data; using Nethermind.AccountAbstraction.Network; using Nethermind.AccountAbstraction.Source; +using Nethermind.AccountAbstraction.Broadcaster; using Nethermind.Core; using Nethermind.Core.Test.Builders; using Nethermind.Core.Timers; diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/Network/UserOperationsMessageSerializerTests.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/Network/UserOperationsMessageSerializerTests.cs index 0efdf1434c6..c308c7fe052 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/Network/UserOperationsMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/Network/UserOperationsMessageSerializerTests.cs @@ -6,7 +6,9 @@ using Nethermind.AccountAbstraction.Data; using Nethermind.AccountAbstraction.Network; using Nethermind.Core; +using Nethermind.Network; using Nethermind.Network.Test.P2P; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using Nethermind.Serialization.Rlp; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/PaymasterThrottlerTests.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/PaymasterThrottlerTests.cs index cee09548090..bc1a156e897 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/PaymasterThrottlerTests.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/PaymasterThrottlerTests.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Threading; using FluentAssertions; +using Nethermind.AccountAbstraction.Source; using Nethermind.Core; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/TestPaymasterThrottler.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/TestPaymasterThrottler.cs index a97ee22aa04..a9183eb7e4f 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/TestPaymasterThrottler.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/TestPaymasterThrottler.cs @@ -3,6 +3,7 @@ using System; using Nethermind.AccountAbstraction.Source; +using Nethermind.Core; namespace Nethermind.AccountAbstraction.Test { diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationBuilder.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationBuilder.cs index 2736abc6cca..1d2ca57342e 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationBuilder.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationBuilder.cs @@ -1,8 +1,10 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using Nethermind.AccountAbstraction.Data; using Nethermind.Core; +using Nethermind.Core.Eip2930; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationPoolTests.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationPoolTests.cs index a172babed8a..b6bae30af9f 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationPoolTests.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationPoolTests.cs @@ -2,16 +2,20 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Antlr4.Runtime.Misc; using FluentAssertions; +using Nethermind.AccountAbstraction.Broadcaster; using Nethermind.AccountAbstraction.Data; using Nethermind.AccountAbstraction.Executor; using Nethermind.AccountAbstraction.Source; using Nethermind.Blockchain; using Nethermind.Blockchain.Filters; +using Nethermind.Blockchain.Filters.Topics; using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus; @@ -24,9 +28,11 @@ using NSubstitute; using NUnit.Framework; using Nethermind.Core.Test.Builders; +using Nethermind.Crypto; using Nethermind.Facade.Filters; using Nethermind.Int256; using Nethermind.JsonRpc; +using Org.BouncyCastle.Asn1.Cms; namespace Nethermind.AccountAbstraction.Test { diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationSubscribeTests.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationSubscribeTests.cs index b032c9d28b6..f8b4fd7bb48 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationSubscribeTests.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationSubscribeTests.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Threading; -using System.Threading.Tasks; using FluentAssertions; using Nethermind.AccountAbstraction.Data; using Nethermind.AccountAbstraction.Source; @@ -156,17 +155,17 @@ private JsonRpcResult GetNewReceivedUserOpsResult( } [Test] - public async Task NewPendingUserOperationsSubscription_creating_result() + public void NewPendingUserOperationsSubscription_creating_result() { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newPendingUserOperations"); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newPendingUserOperations"); string expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", serialized.Substring(serialized.Length - 44, 34), "\",\"id\":67}"); expectedResult.Should().Be(serialized); } [Test] - public async Task NewPendingUserOperationsSubscription_creating_result_with_custom_entryPoints() + public void NewPendingUserOperationsSubscription_creating_result_with_custom_entryPoints() { - string serialized = await RpcTest.TestSerializedRequest( + string serialized = RpcTest.TestSerializedRequest( _subscribeRpcModule, "eth_subscribe", "newPendingUserOperations", @@ -176,9 +175,9 @@ public async Task NewPendingUserOperationsSubscription_creating_result_with_cust } [Test] - public async Task NewPendingUserOperationsSubscription_creating_result_with_wrong_entryPoints() + public void NewPendingUserOperationsSubscription_creating_result_with_wrong_entryPoints() { - string serialized = await RpcTest.TestSerializedRequest( + string serialized = RpcTest.TestSerializedRequest( _subscribeRpcModule, "eth_subscribe", "newPendingUserOperations", "{\"entryPoints\":[\"" + _entryPointAddress + "\", \"" + "0x123" + "\"]}"); @@ -218,17 +217,17 @@ public void NewPendingUserOperationsSubscription_on_NewPending_event_without_ful } [Test] - public async Task NewReceivedUserOperationsSubscription_creating_result() + public void NewReceivedUserOperationsSubscription_creating_result() { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newReceivedUserOperations"); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newReceivedUserOperations"); var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", serialized.Substring(serialized.Length - 44, 34), "\",\"id\":67}"); expectedResult.Should().Be(serialized); } [Test] - public async Task NewReceivedUserOperationsSubscription_creating_result_with_custom_entryPoints() + public void NewReceivedUserOperationsSubscription_creating_result_with_custom_entryPoints() { - string serialized = await RpcTest.TestSerializedRequest( + string serialized = RpcTest.TestSerializedRequest( _subscribeRpcModule, "eth_subscribe", "newReceivedUserOperations", @@ -238,9 +237,9 @@ public async Task NewReceivedUserOperationsSubscription_creating_result_with_cus } [Test] - public async Task NewReceivedUserOperationsSubscription_creating_result_with_wrong_entryPoints() + public void NewReceivedUserOperationsSubscription_creating_result_with_wrong_entryPoints() { - string serialized = await RpcTest.TestSerializedRequest( + string serialized = RpcTest.TestSerializedRequest( _subscribeRpcModule, "eth_subscribe", "newPendingUserOperations", "{\"entryPoints\":[\"" + _entryPointAddress + "\", \"" + "0x123" + "\"]}"); @@ -279,30 +278,30 @@ public void NewReceivedUserOperationsSubscription_on_NewPending_event_without_fu } [Test] - public async Task Eth_unsubscribe_success() + public void Eth_unsubscribe_success() { - string serializedSub = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newPendingUserOperations"); + string serializedSub = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newPendingUserOperations"); string subscriptionId = serializedSub.Substring(serializedSub.Length - 44, 34); string expectedSub = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", subscriptionId, "\",\"id\":67}"); expectedSub.Should().Be(serializedSub); - string serializedUnsub = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_unsubscribe", subscriptionId); + string serializedUnsub = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_unsubscribe", subscriptionId); string expectedUnsub = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}"; expectedUnsub.Should().Be(serializedUnsub); } [Test] - public async Task Subscriptions_remove_after_closing_websockets_client() + public void Subscriptions_remove_after_closing_websockets_client() { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newPendingUserOperations"); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newPendingUserOperations"); string subscriptionId = serialized.Substring(serialized.Length - 44, 34); string expectedId = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", subscriptionId, "\",\"id\":67}"); expectedId.Should().Be(serialized); _jsonRpcDuplexClient.Closed += Raise.Event(); - string serializedLogsUnsub = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_unsubscribe", subscriptionId); + string serializedLogsUnsub = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_unsubscribe", subscriptionId); string expectedLogsUnsub = string.Concat("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32603,\"message\":\"Failed to unsubscribe: ", subscriptionId, ".\",\"data\":false},\"id\":67}"); diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationTracerTests.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationTracerTests.cs index 595d76753fd..7e3288e2060 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationTracerTests.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationTracerTests.cs @@ -1,6 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using AutoMapper.Mappers; using FluentAssertions; using Nethermind.AccountAbstraction.Executor; using Nethermind.Core; @@ -9,8 +12,10 @@ using Nethermind.Core.Test.Builders; using Nethermind.Evm; using Nethermind.Evm.Test; +using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Specs; +using Nethermind.Specs.Forks; using NUnit.Framework; namespace Nethermind.AccountAbstraction.Test @@ -235,8 +240,8 @@ public void Should_allow_gas_only_if_followed_by_call(Instruction instruction, b private (UserOperationTxTracer trace, Block block, Transaction transaction) ExecuteAndTraceAccessCall(SenderRecipientAndMiner addresses, byte[] code, bool paymasterWhitelisted = false, bool firstSimulation = true) { (Block block, Transaction transaction) = PrepareTx(BlockNumber, 100000, code, addresses, 0); - UserOperationTxTracer tracer = new(paymasterWhitelisted, firstSimulation, TestItem.AddressA, TestItem.AddressB, TestItem.AddressD, NullLogger.Instance); - _processor.Execute(transaction, new BlockExecutionContext(block.Header), tracer); + UserOperationTxTracer tracer = new(transaction, paymasterWhitelisted, firstSimulation, TestItem.AddressA, TestItem.AddressB, TestItem.AddressD, NullLogger.Instance); + _processor.Execute(transaction, block.Header, tracer); return (tracer, block, transaction); } diff --git a/src/Nethermind/Nethermind.AccountAbstraction/AccountAbstractionPlugin.cs b/src/Nethermind/Nethermind.AccountAbstraction/AccountAbstractionPlugin.cs index df23fac7e6b..1e8c3ef1418 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction/AccountAbstractionPlugin.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction/AccountAbstractionPlugin.cs @@ -34,260 +34,325 @@ using Nethermind.Config; using Nethermind.Network.Contract.P2P; -namespace Nethermind.AccountAbstraction; - -public class AccountAbstractionPlugin : IConsensusWrapperPlugin +namespace Nethermind.AccountAbstraction { - private IAccountAbstractionConfig _accountAbstractionConfig = null!; - private AbiDefinition _entryPointContractAbi = null!; - private ILogger _logger = null!; - - private INethermindApi _nethermindApi = null!; - private readonly IList
_entryPointContractAddresses = new List
(); - private readonly IList
_whitelistedPaymasters = new List
(); - private readonly IDictionary _userOperationPools = new Dictionary(); // EntryPoint Address -> Pool - private readonly IDictionary _userOperationSimulators = new Dictionary(); - private readonly IDictionary _userOperationTxBuilders = new Dictionary(); - private UserOperationTxSource? _userOperationTxSource; - private IUserOperationBroadcaster? _userOperationBroadcaster; - - private IBundler? _bundler; - - private MevPlugin MevPlugin => _nethermindApi - .GetConsensusWrapperPlugins() - .OfType() - .Single(); - - private UserOperationTxBuilder UserOperationTxBuilder(Address entryPoint) + public class AccountAbstractionPlugin : IConsensusWrapperPlugin { - if (_userOperationTxBuilders.TryGetValue(entryPoint, out UserOperationTxBuilder? userOperationTxBuilder)) + private IAccountAbstractionConfig _accountAbstractionConfig = null!; + private AbiDefinition _entryPointContractAbi = null!; + private ILogger _logger = null!; + + private INethermindApi _nethermindApi = null!; + private readonly IList
_entryPointContractAddresses = new List
(); + private readonly IList
_whitelistedPaymasters = new List
(); + private readonly IDictionary _userOperationPools = new Dictionary(); // EntryPoint Address -> Pool + private readonly IDictionary _userOperationSimulators = new Dictionary(); + private readonly IDictionary _userOperationTxBuilders = new Dictionary(); + private UserOperationTxSource? _userOperationTxSource; + private IUserOperationBroadcaster? _userOperationBroadcaster; + + private IBundler? _bundler; + + private MevPlugin MevPlugin => _nethermindApi + .GetConsensusWrapperPlugins() + .OfType() + .Single(); + + private UserOperationTxBuilder UserOperationTxBuilder(Address entryPoint) { + if (_userOperationTxBuilders.TryGetValue(entryPoint, out UserOperationTxBuilder? userOperationTxBuilder)) + { - return userOperationTxBuilder; - } + return userOperationTxBuilder; + } - var (getFromApi, _) = _nethermindApi!.ForProducer; + var (getFromApi, _) = _nethermindApi!.ForProducer; - _userOperationTxBuilders[entryPoint] = new UserOperationTxBuilder( - _entryPointContractAbi, - getFromApi.EngineSigner!, - entryPoint, - getFromApi.SpecProvider!); + _userOperationTxBuilders[entryPoint] = new UserOperationTxBuilder( + _entryPointContractAbi, + getFromApi.EngineSigner!, + entryPoint, + getFromApi.SpecProvider!); - return _userOperationTxBuilders[entryPoint]; - } + return _userOperationTxBuilders[entryPoint]; + } - private IUserOperationPool UserOperationPool(Address entryPoint) - { - if (_userOperationPools.TryGetValue(entryPoint, out IUserOperationPool? userOperationPool)) + private IUserOperationPool UserOperationPool(Address entryPoint) { - return userOperationPool; - } + if (_userOperationPools.TryGetValue(entryPoint, out IUserOperationPool? userOperationPool)) + { + return userOperationPool; + } - var (getFromApi, _) = _nethermindApi!.ForProducer; - - UserOperationSortedPool userOperationSortedPool = new UserOperationSortedPool( - _accountAbstractionConfig.UserOperationPoolSize, - CompareUserOperationsByDecreasingGasPrice.Default, - getFromApi.LogManager, - _accountAbstractionConfig.MaximumUserOperationPerSender); - - _userOperationPools[entryPoint] = new UserOperationPool( - _accountAbstractionConfig, - _nethermindApi.BlockTree!, - entryPoint, - _logger, - new PaymasterThrottler(BundleMiningEnabled), - _nethermindApi.LogFinder!, - _nethermindApi.EngineSigner!, - _nethermindApi.ChainHeadStateProvider!, - _nethermindApi.SpecProvider!, - _nethermindApi.Timestamper, - UserOperationSimulator(entryPoint), - userOperationSortedPool, - UserOperationBroadcaster, - _nethermindApi.SpecProvider!.ChainId); - - return _userOperationPools[entryPoint]; - } + var (getFromApi, _) = _nethermindApi!.ForProducer; + + UserOperationSortedPool userOperationSortedPool = new UserOperationSortedPool( + _accountAbstractionConfig.UserOperationPoolSize, + CompareUserOperationsByDecreasingGasPrice.Default, + getFromApi.LogManager, + _accountAbstractionConfig.MaximumUserOperationPerSender); + + _userOperationPools[entryPoint] = new UserOperationPool( + _accountAbstractionConfig, + _nethermindApi.BlockTree!, + entryPoint, + _logger, + new PaymasterThrottler(BundleMiningEnabled), + _nethermindApi.LogFinder!, + _nethermindApi.EngineSigner!, + _nethermindApi.ChainHeadStateProvider!, + _nethermindApi.SpecProvider!, + _nethermindApi.Timestamper, + UserOperationSimulator(entryPoint), + userOperationSortedPool, + UserOperationBroadcaster, + _nethermindApi.SpecProvider!.ChainId); - private UserOperationSimulator UserOperationSimulator(Address entryPoint) - { - if (_userOperationSimulators.TryGetValue(entryPoint, out UserOperationSimulator? userOperationSimulator)) - { - return userOperationSimulator; + return _userOperationPools[entryPoint]; } - var (getFromApi, _) = _nethermindApi!.ForProducer; - - ReadOnlyTxProcessingEnvFactory readOnlyTxProcessingEnvFactory = new( - getFromApi.DbProvider, - getFromApi.ReadOnlyTrieStore, - getFromApi.BlockTree, - getFromApi.SpecProvider, - getFromApi.LogManager); - - _userOperationSimulators[entryPoint] = new UserOperationSimulator( - UserOperationTxBuilder(entryPoint), - getFromApi.ChainHeadStateProvider!, - readOnlyTxProcessingEnvFactory, - _entryPointContractAbi, - entryPoint, - _whitelistedPaymasters.ToArray(), - getFromApi.SpecProvider!, - getFromApi.Timestamper, - getFromApi.LogManager, - getFromApi.Config()); - - return _userOperationSimulators[entryPoint]; - } - - private UserOperationTxSource UserOperationTxSource - { - get + private UserOperationSimulator UserOperationSimulator(Address entryPoint) { - _userOperationTxSource ??= new UserOperationTxSource - ( - _userOperationTxBuilders, - _userOperationPools, - _userOperationSimulators, - _nethermindApi.SpecProvider!, - _nethermindApi.ChainHeadStateProvider!, - _nethermindApi.EngineSigner!, - _logger - ); + if (_userOperationSimulators.TryGetValue(entryPoint, out UserOperationSimulator? userOperationSimulator)) + { + return userOperationSimulator; + } - return _userOperationTxSource; + var (getFromApi, _) = _nethermindApi!.ForProducer; + + ReadOnlyTxProcessingEnvFactory readOnlyTxProcessingEnvFactory = new( + getFromApi.DbProvider, + getFromApi.ReadOnlyTrieStore, + getFromApi.BlockTree, + getFromApi.SpecProvider, + getFromApi.LogManager); + + _userOperationSimulators[entryPoint] = new UserOperationSimulator( + UserOperationTxBuilder(entryPoint), + getFromApi.ChainHeadStateProvider!, + readOnlyTxProcessingEnvFactory, + _entryPointContractAbi, + entryPoint, + _whitelistedPaymasters.ToArray(), + getFromApi.SpecProvider!, + getFromApi.Timestamper, + getFromApi.LogManager, + getFromApi.Config()); + + return _userOperationSimulators[entryPoint]; } - } - private IUserOperationBroadcaster UserOperationBroadcaster - { - get + private UserOperationTxSource UserOperationTxSource { - _userOperationBroadcaster ??= new UserOperationBroadcaster(_logger); - - return _userOperationBroadcaster; + get + { + _userOperationTxSource ??= new UserOperationTxSource + ( + _userOperationTxBuilders, + _userOperationPools, + _userOperationSimulators, + _nethermindApi.SpecProvider!, + _nethermindApi.ChainHeadStateProvider!, + _nethermindApi.EngineSigner!, + _logger + ); + + return _userOperationTxSource; + } } - } - public string Name => "Account Abstraction"; + private IUserOperationBroadcaster UserOperationBroadcaster + { + get + { + _userOperationBroadcaster ??= new UserOperationBroadcaster(_logger); + + return _userOperationBroadcaster; + } + } - public string Description => "Implements account abstraction via alternative mempool (ERC-4337)"; + public string Name => "Account Abstraction"; - public string Author => "Nethermind"; + public string Description => "Implements account abstraction via alternative mempool (ERC-4337)"; - public Task Init(INethermindApi nethermindApi) - { - _nethermindApi = nethermindApi ?? throw new ArgumentNullException(nameof(nethermindApi)); - _accountAbstractionConfig = _nethermindApi.Config(); - _logger = _nethermindApi.LogManager.GetClassLogger(); + public string Author => "Nethermind"; - if (_accountAbstractionConfig.Enabled) + public Task Init(INethermindApi nethermindApi) { - // Increasing number of priority peers in network config by AaPriorityPeersMaxCount. - // Be careful if there is another plugin with priority peers - they won't be distinguished in SyncPeerPool. - _nethermindApi.Config().PriorityPeersMaxCount += _accountAbstractionConfig.AaPriorityPeersMaxCount; - IList entryPointContractAddressesString = _accountAbstractionConfig.GetEntryPointAddresses().ToList(); - foreach (string addressString in entryPointContractAddressesString) + _nethermindApi = nethermindApi ?? throw new ArgumentNullException(nameof(nethermindApi)); + _accountAbstractionConfig = _nethermindApi.Config(); + _logger = _nethermindApi.LogManager.GetClassLogger(); + + if (_accountAbstractionConfig.Enabled) { - bool parsed = Address.TryParse( - addressString, - out Address? entryPointContractAddress); - if (!parsed) + // Increasing number of priority peers in network config by AaPriorityPeersMaxCount. + // Be careful if there is another plugin with priority peers - they won't be distinguished in SyncPeerPool. + _nethermindApi.Config().PriorityPeersMaxCount += _accountAbstractionConfig.AaPriorityPeersMaxCount; + IList entryPointContractAddressesString = _accountAbstractionConfig.GetEntryPointAddresses().ToList(); + foreach (string addressString in entryPointContractAddressesString) { - if (_logger.IsError) _logger.Error("Account Abstraction Plugin: EntryPoint contract address could not be parsed"); + bool parsed = Address.TryParse( + addressString, + out Address? entryPointContractAddress); + if (!parsed) + { + if (_logger.IsError) _logger.Error("Account Abstraction Plugin: EntryPoint contract address could not be parsed"); + } + else + { + if (_logger.IsInfo) _logger.Info($"Parsed EntryPoint address: {entryPointContractAddress}"); + _entryPointContractAddresses.Add(entryPointContractAddress!); + } } - else + + IList whitelistedPaymastersString = _accountAbstractionConfig.GetWhitelistedPaymasters().ToList(); + foreach (string addressString in whitelistedPaymastersString) { - if (_logger.IsInfo) _logger.Info($"Parsed EntryPoint address: {entryPointContractAddress}"); - _entryPointContractAddresses.Add(entryPointContractAddress!); + bool parsed = Address.TryParse( + addressString, + out Address? whitelistedPaymaster); + if (!parsed) + { + if (_logger.IsError) _logger.Error("Account Abstraction Plugin: Whitelisted Paymaster address could not be parsed"); + } + else + { + if (_logger.IsInfo) _logger.Info($"Parsed Whitelisted Paymaster address: {whitelistedPaymaster}"); + _whitelistedPaymasters.Add(whitelistedPaymaster!); + } } + + _entryPointContractAbi = LoadEntryPointContract(); } - IList whitelistedPaymastersString = _accountAbstractionConfig.GetWhitelistedPaymasters().ToList(); - foreach (string addressString in whitelistedPaymastersString) + if (Enabled) { - bool parsed = Address.TryParse( - addressString, - out Address? whitelistedPaymaster); - if (!parsed) - { - if (_logger.IsError) _logger.Error("Account Abstraction Plugin: Whitelisted Paymaster address could not be parsed"); - } - else - { - if (_logger.IsInfo) _logger.Info($"Parsed Whitelisted Paymaster address: {whitelistedPaymaster}"); - _whitelistedPaymasters.Add(whitelistedPaymaster!); - } + if (_logger.IsInfo) _logger.Info(" Account Abstraction Plugin: User Operation Mining Enabled"); + } + else + { + if (_logger.IsInfo) _logger.Info(" Account Abstraction Plugin: User Operation Mining Disabled"); } - _entryPointContractAbi = LoadEntryPointContract(); + return Task.CompletedTask; } - if (Enabled) + public Task InitNetworkProtocol() { - if (_logger.IsInfo) _logger.Info(" Account Abstraction Plugin: User Operation Mining Enabled"); - } - else - { - if (_logger.IsInfo) _logger.Info(" Account Abstraction Plugin: User Operation Mining Disabled"); - } + if (_accountAbstractionConfig.Enabled) + { + if (_nethermindApi is null) throw new ArgumentNullException(nameof(_nethermindApi)); - return Task.CompletedTask; - } + // init all relevant objects if not already initialized + foreach (Address entryPoint in _entryPointContractAddresses) + { + UserOperationPool(entryPoint); + UserOperationSimulator(entryPoint); + UserOperationTxBuilder(entryPoint); + } - public Task InitNetworkProtocol() - { - if (_accountAbstractionConfig.Enabled) - { - if (_nethermindApi is null) throw new ArgumentNullException(nameof(_nethermindApi)); + if (_userOperationPools.Count == 0) throw new ArgumentNullException(nameof(UserOperationPool)); - // init all relevant objects if not already initialized - foreach (Address entryPoint in _entryPointContractAddresses) + IProtocolsManager protocolsManager = _nethermindApi.ProtocolsManager ?? + throw new ArgumentNullException( + nameof(_nethermindApi.ProtocolsManager)); + IMessageSerializationService serializer = _nethermindApi.MessageSerializationService ?? + throw new ArgumentNullException( + nameof(_nethermindApi.MessageSerializationService)); + INodeStatsManager stats = _nethermindApi.NodeStatsManager ?? + throw new ArgumentNullException(nameof(_nethermindApi.NodeStatsManager)); + ILogManager logManager = _nethermindApi.LogManager ?? + throw new ArgumentNullException(nameof(_nethermindApi.LogManager)); + + AccountAbstractionPeerManager peerManager = new(_userOperationPools, UserOperationBroadcaster, _accountAbstractionConfig.AaPriorityPeersMaxCount, _logger); + + serializer.Register(new UserOperationsMessageSerializer()); + protocolsManager.AddProtocol(Protocol.AA, + session => new AaProtocolHandler(session, serializer, stats, _userOperationPools, peerManager, logManager)); + protocolsManager.AddSupportedCapability(new Capability(Protocol.AA, 0)); + + if (_logger.IsInfo) _logger.Info("Initialized Account Abstraction network protocol"); + } + else { - UserOperationPool(entryPoint); - UserOperationSimulator(entryPoint); - UserOperationTxBuilder(entryPoint); + if (_logger.IsInfo) _logger.Info("Skipping Account Abstraction network protocol"); } - if (_userOperationPools.Count == 0) throw new ArgumentNullException(nameof(UserOperationPool)); + return Task.CompletedTask; + } - IProtocolsManager protocolsManager = _nethermindApi.ProtocolsManager ?? - throw new ArgumentNullException( - nameof(_nethermindApi.ProtocolsManager)); - IMessageSerializationService serializer = _nethermindApi.MessageSerializationService ?? - throw new ArgumentNullException( - nameof(_nethermindApi.MessageSerializationService)); - INodeStatsManager stats = _nethermindApi.NodeStatsManager ?? - throw new ArgumentNullException(nameof(_nethermindApi.NodeStatsManager)); - ILogManager logManager = _nethermindApi.LogManager ?? - throw new ArgumentNullException(nameof(_nethermindApi.LogManager)); + public Task InitRpcModules() + { + if (_accountAbstractionConfig.Enabled) + { + (IApiWithNetwork getFromApi, _) = _nethermindApi.ForRpc; - AccountAbstractionPeerManager peerManager = new(_userOperationPools, UserOperationBroadcaster, _accountAbstractionConfig.AaPriorityPeersMaxCount, _logger); + // init all relevant objects if not already initialized + foreach (Address entryPoint in _entryPointContractAddresses) + { + UserOperationPool(entryPoint); + UserOperationSimulator(entryPoint); + UserOperationTxBuilder(entryPoint); + } - serializer.Register(new UserOperationsMessageSerializer()); - protocolsManager.AddProtocol(Protocol.AA, - session => new AaProtocolHandler(session, serializer, stats, _userOperationPools, peerManager, logManager)); - protocolsManager.AddSupportedCapability(new Capability(Protocol.AA, 0)); + IJsonRpcConfig rpcConfig = getFromApi.Config(); + rpcConfig.EnableModules(ModuleType.AccountAbstraction); + + AccountAbstractionModuleFactory accountAbstractionModuleFactory = new(_userOperationPools, _entryPointContractAddresses.ToArray()); + ILogManager logManager = _nethermindApi.LogManager ?? + throw new ArgumentNullException(nameof(_nethermindApi.LogManager)); + getFromApi.RpcModuleProvider!.RegisterBoundedByCpuCount(accountAbstractionModuleFactory, rpcConfig.Timeout); + + ISubscriptionFactory? subscriptionFactory = _nethermindApi.SubscriptionFactory; + //Register custom UserOperation websocket subscription types in the SubscriptionFactory. + subscriptionFactory?.RegisterSubscriptionType( + "newPendingUserOperations", + (jsonRpcDuplexClient, param) => new NewPendingUserOpsSubscription( + jsonRpcDuplexClient, + _userOperationPools, + logManager, + param) + ); + subscriptionFactory?.RegisterSubscriptionType( + "newReceivedUserOperations", + (jsonRpcDuplexClient, param) => new NewReceivedUserOpsSubscription( + jsonRpcDuplexClient, + _userOperationPools, + logManager, + param) + ); - if (_logger.IsInfo) _logger.Info("Initialized Account Abstraction network protocol"); + if (BundleMiningEnabled && MevPluginEnabled) + { + if (_logger!.IsInfo) _logger.Info("Both AA and MEV Plugins enabled, sending user operations to mev bundle pool instead"); + _bundler = new MevBundler( + new OnNewBlockBundleTrigger(_nethermindApi.BlockTree!, _logger), + UserOperationTxSource, MevPlugin.BundlePool, + _logger + ); + } + + + if (_logger!.IsInfo) _logger.Info("Account Abstraction RPC plugin enabled"); + } + else + { + if (_logger!.IsWarn) _logger.Info("Skipping Account Abstraction RPC plugin"); + } + + return Task.CompletedTask; } - else + + public ValueTask DisposeAsync() { - if (_logger.IsInfo) _logger.Info("Skipping Account Abstraction network protocol"); + return ValueTask.CompletedTask; } - return Task.CompletedTask; - } - - public Task InitRpcModules() - { - if (_accountAbstractionConfig.Enabled) + public Task InitBlockProducer(IConsensusPlugin consensusPlugin) { - (IApiWithNetwork getFromApi, _) = _nethermindApi.ForRpc; + if (!Enabled) throw new InvalidOperationException("Account Abstraction plugin is disabled"); - // init all relevant objects if not already initialized + // init all relevant objects if not already initted foreach (Address entryPoint in _entryPointContractAddresses) { UserOperationPool(entryPoint); @@ -295,103 +360,39 @@ public Task InitRpcModules() UserOperationTxBuilder(entryPoint); } - IJsonRpcConfig rpcConfig = getFromApi.Config(); - rpcConfig.EnableModules(ModuleType.AccountAbstraction); - - AccountAbstractionModuleFactory accountAbstractionModuleFactory = new(_userOperationPools, _entryPointContractAddresses.ToArray()); - ILogManager logManager = _nethermindApi.LogManager ?? - throw new ArgumentNullException(nameof(_nethermindApi.LogManager)); - getFromApi.RpcModuleProvider!.RegisterBoundedByCpuCount(accountAbstractionModuleFactory, rpcConfig.Timeout); - - ISubscriptionFactory? subscriptionFactory = _nethermindApi.SubscriptionFactory; - //Register custom UserOperation websocket subscription types in the SubscriptionFactory. - subscriptionFactory?.RegisterSubscriptionType( - "newPendingUserOperations", - (jsonRpcDuplexClient, param) => new NewPendingUserOpsSubscription( - jsonRpcDuplexClient, - _userOperationPools, - logManager, - param) - ); - subscriptionFactory?.RegisterSubscriptionType( - "newReceivedUserOperations", - (jsonRpcDuplexClient, param) => new NewReceivedUserOpsSubscription( - jsonRpcDuplexClient, - _userOperationPools, - logManager, - param) - ); - - if (BundleMiningEnabled && MevPluginEnabled) - { - if (_logger!.IsInfo) _logger.Info("Both AA and MEV Plugins enabled, sending user operations to mev bundle pool instead"); - _bundler = new MevBundler( - new OnNewBlockBundleTrigger(_nethermindApi.BlockTree!, _logger), - UserOperationTxSource, MevPlugin.BundlePool, - _logger - ); - } - + _nethermindApi.BlockProducerEnvFactory!.TransactionsExecutorFactory = + new AABlockProducerTransactionsExecutorFactory( + _nethermindApi.SpecProvider!, + _nethermindApi.LogManager!, + _nethermindApi.EngineSigner!, + _entryPointContractAddresses.ToArray()); - if (_logger!.IsInfo) _logger.Info("Account Abstraction RPC plugin enabled"); - } - else - { - if (_logger!.IsWarn) _logger.Info("Skipping Account Abstraction RPC plugin"); - } + UInt256 minerBalance = _nethermindApi.ChainHeadStateProvider!.GetBalance(_nethermindApi.EngineSigner!.Address); + if (minerBalance < 1.Ether()) + if (_logger.IsWarn) _logger.Warn( + $"Account Abstraction Plugin: Miner ({_nethermindApi.EngineSigner!.Address}) Ether balance low - {minerBalance / 1.Ether()} Ether < 1 Ether. Increasing balance is recommended"); + else + { + if (_logger.IsInfo) + _logger.Info( + $"Account Abstraction Plugin: Miner ({_nethermindApi.EngineSigner!.Address}) Ether balance adequate - {minerBalance / 1.Ether()} Ether"); + } - return Task.CompletedTask; - } + IManualBlockProductionTrigger trigger = new BuildBlocksWhenRequested(); - public ValueTask DisposeAsync() - { - return ValueTask.CompletedTask; - } + return consensusPlugin.InitBlockProducer(trigger, UserOperationTxSource); + } - public Task InitBlockProducer(IConsensusPlugin consensusPlugin) - { - if (!Enabled) throw new InvalidOperationException("Account Abstraction plugin is disabled"); + public bool MevPluginEnabled => _nethermindApi.Config().Enabled; + public bool BundleMiningEnabled => _accountAbstractionConfig.Enabled && (_nethermindApi.Config().IsMining || _nethermindApi.Config().Enabled); + public bool Enabled => BundleMiningEnabled && !MevPluginEnabled; // IConsensusWrapperPlugin.Enabled - // init all relevant objects if not already initted - foreach (Address entryPoint in _entryPointContractAddresses) + private AbiDefinition LoadEntryPointContract() { - UserOperationPool(entryPoint); - UserOperationSimulator(entryPoint); - UserOperationTxBuilder(entryPoint); + AbiDefinitionParser parser = new(); + parser.RegisterAbiTypeFactory(new AbiTuple()); + string json = parser.LoadContract(typeof(EntryPoint)); + return parser.Parse(json); } - - _nethermindApi.BlockProducerEnvFactory!.TransactionsExecutorFactory = - new AABlockProducerTransactionsExecutorFactory( - _nethermindApi.SpecProvider!, - _nethermindApi.LogManager!, - _nethermindApi.EngineSigner!, - _entryPointContractAddresses.ToArray()); - - UInt256 minerBalance = _nethermindApi.ChainHeadStateProvider!.GetBalance(_nethermindApi.EngineSigner!.Address); - if (minerBalance < 1.Ether()) - if (_logger.IsWarn) _logger.Warn( - $"Account Abstraction Plugin: Miner ({_nethermindApi.EngineSigner!.Address}) Ether balance low - {minerBalance / 1.Ether()} Ether < 1 Ether. Increasing balance is recommended"); - else - { - if (_logger.IsInfo) - _logger.Info( - $"Account Abstraction Plugin: Miner ({_nethermindApi.EngineSigner!.Address}) Ether balance adequate - {minerBalance / 1.Ether()} Ether"); - } - - IManualBlockProductionTrigger trigger = new BuildBlocksWhenRequested(); - - return consensusPlugin.InitBlockProducer(trigger, UserOperationTxSource); - } - - public bool MevPluginEnabled => _nethermindApi.Config().Enabled; - public bool BundleMiningEnabled => _accountAbstractionConfig.Enabled && (_nethermindApi.Config().IsMining || _nethermindApi.Config().Enabled); - public bool Enabled => BundleMiningEnabled && !MevPluginEnabled; // IConsensusWrapperPlugin.Enabled - - private AbiDefinition LoadEntryPointContract() - { - AbiDefinitionParser parser = new(); - parser.RegisterAbiTypeFactory(new AbiTuple()); - string json = parser.LoadContract(typeof(EntryPoint)); - return parser.Parse(json); } } diff --git a/src/Nethermind/Nethermind.AccountAbstraction/Executor/AABlockProducerTransactionsExecutor.cs b/src/Nethermind/Nethermind.AccountAbstraction/Executor/AABlockProducerTransactionsExecutor.cs index e3791db4b03..a9bdcb0f1c0 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction/Executor/AABlockProducerTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction/Executor/AABlockProducerTransactionsExecutor.cs @@ -8,7 +8,6 @@ using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Core.Specs; -using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; @@ -51,17 +50,16 @@ public override TxReceipt[] ProcessTransactions( int i = 0; LinkedHashSet transactionsInBlock = new(ByHashTxComparer.Instance); - BlockExecutionContext blkCtx = new(block.Header); foreach (Transaction transaction in transactions) { if (IsAccountAbstractionTransaction(transaction)) { - BlockProcessor.TxAction action = ProcessAccountAbstractionTransaction(block, blkCtx, transaction, i++, receiptsTracer, processingOptions, transactionsInBlock); + BlockProcessor.TxAction action = ProcessAccountAbstractionTransaction(block, transaction, i++, receiptsTracer, processingOptions, transactionsInBlock); if (action == BlockProcessor.TxAction.Stop) break; } else { - BlockProcessor.TxAction action = ProcessTransaction(block, blkCtx, transaction, i++, receiptsTracer, processingOptions, transactionsInBlock); + BlockProcessor.TxAction action = ProcessTransaction(block, transaction, i++, receiptsTracer, processingOptions, transactionsInBlock); if (action == BlockProcessor.TxAction.Stop) break; } } @@ -81,7 +79,6 @@ private bool IsAccountAbstractionTransaction(Transaction transaction) private BlockProcessor.TxAction ProcessAccountAbstractionTransaction( Block block, - BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, @@ -90,7 +87,7 @@ private BlockProcessor.TxAction ProcessAccountAbstractionTransaction( { int snapshot = receiptsTracer.TakeSnapshot(); - BlockProcessor.TxAction action = ProcessTransaction(block, blkCtx, currentTx, index, receiptsTracer, processingOptions, transactionsInBlock, false); + BlockProcessor.TxAction action = ProcessTransaction(block, currentTx, index, receiptsTracer, processingOptions, transactionsInBlock, false); if (action != BlockProcessor.TxAction.Add) { return action; diff --git a/src/Nethermind/Nethermind.AccountAbstraction/Executor/UserOperationSimulator.cs b/src/Nethermind/Nethermind.AccountAbstraction/Executor/UserOperationSimulator.cs index a0e47c6b01b..60ce68bfcea 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction/Executor/UserOperationSimulator.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction/Executor/UserOperationSimulator.cs @@ -3,10 +3,12 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using Nethermind.Abi; using Nethermind.AccountAbstraction.Data; +using Nethermind.Blockchain; using Nethermind.Config; using Nethermind.Consensus.Processing; using Nethermind.Core; @@ -15,7 +17,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Crypto; -using Nethermind.Evm; +using Nethermind.Db; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Facade; @@ -23,6 +25,7 @@ using Nethermind.JsonRpc; using Nethermind.Logging; using Nethermind.State; +using Nethermind.Trie.Pruning; namespace Nethermind.AccountAbstraction.Executor { @@ -121,14 +124,16 @@ private UserOperationSimulationResult SimulateValidation( ITransactionProcessor transactionProcessor) { bool paymasterWhitelisted = _whitelistedPaymasters.Contains(userOperation.Paymaster); - UserOperationTxTracer txTracer = new(paymasterWhitelisted, + UserOperationTxTracer txTracer = new( + transaction, + paymasterWhitelisted, userOperation.InitCode != Bytes.Empty, userOperation.Sender, userOperation.Paymaster, _entryPointContractAddress, _logger ); - transactionProcessor.Trace(transaction, new BlockExecutionContext(parent), txTracer); + transactionProcessor.Trace(transaction, parent, txTracer); FailedOp? failedOp = _userOperationTxBuilder.DecodeEntryPointOutputError(txTracer.Output); @@ -200,7 +205,7 @@ public BlockchainBridge.CallOutput EstimateGas(BlockHeader header, Transaction t estimateGasTracer.WithCancellation(cancellationToken)); GasEstimator gasEstimator = new(transactionProcessor, _stateProvider, _specProvider, _blocksConfig); - long estimate = gasEstimator.Estimate(tx, header, estimateGasTracer, cancellationToken); + long estimate = gasEstimator.Estimate(tx, header, estimateGasTracer); return new BlockchainBridge.CallOutput { @@ -259,7 +264,7 @@ private void CallAndRestore( : blockHeader.BaseFeePerGas; transaction.Hash = transaction.CalculateHash(); - transactionProcessor.CallAndRestore(transaction, new BlockExecutionContext(callHeader), tracer); + transactionProcessor.CallAndRestore(transaction, callHeader, tracer); } } } diff --git a/src/Nethermind/Nethermind.AccountAbstraction/Executor/UserOperationTracer.cs b/src/Nethermind/Nethermind.AccountAbstraction/Executor/UserOperationTracer.cs index 0b64db5b9d7..fcc73300e1a 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction/Executor/UserOperationTracer.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction/Executor/UserOperationTracer.cs @@ -15,7 +15,7 @@ namespace Nethermind.AccountAbstraction.Executor { - public class UserOperationTxTracer : TxTracer + public class UserOperationTxTracer : ITxTracer { private static readonly Instruction[] _bannedOpcodes = { @@ -37,6 +37,7 @@ public class UserOperationTxTracer : TxTracer private bool _nextOpcodeMustBeCall; // GAS is allowed only if it followed immediately by a CALL, DELEGATECALL, STATICCALL, or CALLCODE public UserOperationTxTracer( + Transaction? transaction, bool paymasterWhitelisted, bool hasInitCode, Address sender, @@ -62,20 +63,28 @@ public UserOperationTxTracer( public string? Error { get; private set; } public byte[] Output { get; private set; } - public override bool IsTracingReceipt => true; - public override bool IsTracingActions => true; - public override bool IsTracingOpLevelStorage => true; - public override bool IsTracingInstructions => true; - public override bool IsTracingState => true; - public override bool IsTracingAccess => true; + public bool IsTracingReceipt => true; + public bool IsTracingActions => true; + public bool IsTracingOpLevelStorage => true; + public bool IsTracingMemory => false; + public bool IsTracingInstructions => true; + public bool IsTracingRefunds => false; + public bool IsTracingCode => false; + public bool IsTracingStack => false; + public bool IsTracingState => true; + public bool IsTracingStorage => false; + public bool IsTracingBlockHash => false; + public bool IsTracingAccess => true; + public bool IsTracingFees => false; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; - public override void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) { Output = output; } - public override void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) { Success = false; @@ -83,7 +92,33 @@ public override void MarkAsFailed(Address recipient, long gasSpent, byte[] outpu Output = output; } - public override void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) + { + } + + public void ReportCodeChange(Address address, byte[]? before, byte[]? after) + { + } + + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) + { + } + + public void ReportAccountRead(Address address) + { + } + + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) + { + throw new NotImplementedException(); + } + + public void ReportStorageRead(in StorageCell storageCell) + { + throw new NotImplementedException(); + } + + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) { if (_nextOpcodeMustBeCall) { @@ -151,13 +186,48 @@ public override void StartOperation(int depth, long gas, Instruction opcode, int } } - public override void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, + public void ReportOperationError(EvmExceptionType error) + { + } + + public void ReportOperationRemainingGas(long gas) + { + } + + public void SetOperationStack(List stackTrace) + { + throw new NotImplementedException(); + } + + public void ReportStackPush(in ReadOnlySpan stackItem) + { + } + + public void SetOperationMemory(List memoryTrace) + { + throw new NotImplementedException(); + } + + public void SetOperationMemorySize(ulong newSize) + { + throw new NotImplementedException(); + } + + public void ReportMemoryChange(long offset, in ReadOnlySpan data) + { + } + + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) + { + } + + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) { HandleStorageAccess(address, storageIndex); } - public override void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) { HandleStorageAccess(address, storageIndex); } @@ -186,7 +256,12 @@ private void HandleStorageAccess(Address address, UInt256 storageIndex) } } - public override void ReportAction(long gas, UInt256 value, Address from, Address to, ReadOnlyMemory input, + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) + { + //TODO: would this ever be allowed? + } + + public void ReportAction(long gas, UInt256 value, Address from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) { @@ -198,7 +273,11 @@ public override void ReportAction(long gas, UInt256 value, Address from, Address Error ??= $"simulation failed: balance write allowed only from sender to entrypoint, instead found from: {from} to: {_entryPointAddress} with value {value}"; } - public override void ReportActionError(EvmExceptionType evmExceptionType) + public void ReportActionEnd(long gas, ReadOnlyMemory output) + { + } + + public void ReportActionError(EvmExceptionType evmExceptionType) { if (evmExceptionType == EvmExceptionType.OutOfGas) { @@ -207,7 +286,35 @@ public override void ReportActionError(EvmExceptionType evmExceptionType) } } - public override void ReportAccess(IReadOnlySet
accessedAddresses, + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) + { + } + + public void ReportBlockHash(Keccak blockHash) + { + throw new NotImplementedException(); + } + + public void ReportByteCode(byte[] byteCode) + { + throw new NotImplementedException(); + } + + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) + { + } + + public void ReportRefund(long refund) + { + throw new NotImplementedException(); + } + + public void ReportExtraGasPressure(long extraGasPressure) + { + throw new NotImplementedException(); + } + + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) { AccessedAddresses = accessedAddresses; @@ -223,5 +330,10 @@ private void AddToAccessedStorage(Address address, UInt256 index) AccessedStorage.Add(address, new HashSet { index }); } + + public void ReportFees(UInt256 fees, UInt256 burntFees) + { + throw new NotImplementedException(); + } } } diff --git a/src/Nethermind/Nethermind.AccountAbstraction/Network/UserOperationsMessageSerializer.cs b/src/Nethermind/Nethermind.AccountAbstraction/Network/UserOperationsMessageSerializer.cs index 510fb503852..f6253e8793e 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction/Network/UserOperationsMessageSerializer.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction/Network/UserOperationsMessageSerializer.cs @@ -4,6 +4,7 @@ using DotNetty.Buffers; using Nethermind.AccountAbstraction.Data; using Nethermind.Network; +using Nethermind.Network.P2P; using Nethermind.Serialization.Rlp; namespace Nethermind.AccountAbstraction.Network diff --git a/src/Nethermind/Nethermind.AccountAbstraction/Subscribe/NewReceivedUserOpsSubscription.cs b/src/Nethermind/Nethermind.AccountAbstraction/Subscribe/NewReceivedUserOpsSubscription.cs index b0a0ec7cb7e..b72b9952615 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction/Subscribe/NewReceivedUserOpsSubscription.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction/Subscribe/NewReceivedUserOpsSubscription.cs @@ -8,6 +8,7 @@ using Nethermind.AccountAbstraction.Source; using Nethermind.Core; using Nethermind.JsonRpc; +using Nethermind.JsonRpc.Modules.Eth; using Nethermind.JsonRpc.Modules.Subscribe; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Analytics/RewardsVerifier.cs b/src/Nethermind/Nethermind.Analytics/RewardsVerifier.cs index 62d44c3993c..a7edd83e994 100644 --- a/src/Nethermind/Nethermind.Analytics/RewardsVerifier.cs +++ b/src/Nethermind/Nethermind.Analytics/RewardsVerifier.cs @@ -7,6 +7,7 @@ using Nethermind.Consensus.Rewards; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Specs; using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Specs; diff --git a/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs b/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs index c99111c9db6..10612330c41 100644 --- a/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs +++ b/src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs @@ -68,7 +68,6 @@ public interface IApiWithBlockchain : IApiWithStores, IBlockchainBridgeFactory INonceManager? NonceManager { get; set; } ITxPool? TxPool { get; set; } ITxPoolInfoProvider? TxPoolInfoProvider { get; set; } - CompositeTxGossipPolicy TxGossipPolicy { get; } IWitnessCollector? WitnessCollector { get; set; } IWitnessRepository? WitnessRepository { get; set; } IHealthHintService? HealthHintService { get; set; } diff --git a/src/Nethermind/Nethermind.Api/IBasicApi.cs b/src/Nethermind/Nethermind.Api/IBasicApi.cs index 9677d0a67b1..cb6131a87e1 100644 --- a/src/Nethermind/Nethermind.Api/IBasicApi.cs +++ b/src/Nethermind/Nethermind.Api/IBasicApi.cs @@ -7,6 +7,7 @@ using Nethermind.Abi; using Nethermind.Api.Extensions; using Nethermind.Config; +using Nethermind.Consensus; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Core.Timers; diff --git a/src/Nethermind/Nethermind.Api/IInitConfig.cs b/src/Nethermind/Nethermind.Api/IInitConfig.cs index 4653e101a14..33fad6328dd 100644 --- a/src/Nethermind/Nethermind.Api/IInitConfig.cs +++ b/src/Nethermind/Nethermind.Api/IInitConfig.cs @@ -73,9 +73,6 @@ public interface IInitConfig : IConfig [ConfigItem(Description = "A hint for the max memory that will allow us to configure the DB and Netty memory allocations.", DefaultValue = "null")] long? MemoryHint { get; set; } - - [ConfigItem(Description = "[TECHNICAL] Disable setting malloc options. Set to true if using different memory allocator or manually setting malloc opts.", DefaultValue = "false", HiddenFromDocs = true)] - bool DisableMallocOpts { get; set; } } public enum DiagnosticMode diff --git a/src/Nethermind/Nethermind.Api/INethermindApi.cs b/src/Nethermind/Nethermind.Api/INethermindApi.cs index 8d864b2e9f8..28b4443461c 100644 --- a/src/Nethermind/Nethermind.Api/INethermindApi.cs +++ b/src/Nethermind/Nethermind.Api/INethermindApi.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only #nullable enable +using Nethermind.Blockchain; using Nethermind.Config; namespace Nethermind.Api diff --git a/src/Nethermind/Nethermind.Api/InitConfig.cs b/src/Nethermind/Nethermind.Api/InitConfig.cs index 6ad3c91ff0f..c123d39c432 100644 --- a/src/Nethermind/Nethermind.Api/InitConfig.cs +++ b/src/Nethermind/Nethermind.Api/InitConfig.cs @@ -31,7 +31,6 @@ public class InitConfig : IInitConfig public string RpcDbUrl { get; set; } = String.Empty; public long? MemoryHint { get; set; } - public bool DisableMallocOpts { get; set; } = false; [Obsolete("Use DiagnosticMode with MemDb instead")] public bool UseMemDb diff --git a/src/Nethermind/Nethermind.Api/NethermindApi.cs b/src/Nethermind/Nethermind.Api/NethermindApi.cs index c94205abf91..fe323844e39 100644 --- a/src/Nethermind/Nethermind.Api/NethermindApi.cs +++ b/src/Nethermind/Nethermind.Api/NethermindApi.cs @@ -232,6 +232,5 @@ public ISealEngine SealEngine public CompositePruningTrigger PruningTrigger { get; } = new(); public ISnapProvider? SnapProvider { get; set; } public IProcessExitSource? ProcessExit { get; set; } - public CompositeTxGossipPolicy TxGossipPolicy { get; } = new(); } } diff --git a/src/Nethermind/Nethermind.AuRa.Test/AuRaAdditionalBlockProcessorFactoryTests.cs b/src/Nethermind/Nethermind.AuRa.Test/AuRaAdditionalBlockProcessorFactoryTests.cs index 182f156e09c..8d4fcfd3768 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/AuRaAdditionalBlockProcessorFactoryTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/AuRaAdditionalBlockProcessorFactoryTests.cs @@ -13,6 +13,7 @@ using Nethermind.Consensus.AuRa.Validators; using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Db; using Nethermind.Specs.ChainSpecStyle; using Nethermind.Evm.TransactionProcessing; using Nethermind.JsonRpc.Modules.Eth.GasPrice; diff --git a/src/Nethermind/Nethermind.AuRa.Test/AuRaBlockFinalizationManagerTests.cs b/src/Nethermind/Nethermind.AuRa.Test/AuRaBlockFinalizationManagerTests.cs index 6cf360b3918..a17f1653ffe 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/AuRaBlockFinalizationManagerTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/AuRaBlockFinalizationManagerTests.cs @@ -12,8 +12,10 @@ using Nethermind.Consensus.Processing; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Logging; +using Nethermind.Serialization.Rlp; using Nethermind.State.Repositories; using NSubstitute; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.AuRa.Test/AuRaBlockProducerTests.cs b/src/Nethermind/Nethermind.AuRa.Test/AuRaBlockProducerTests.cs index 7fce1955f2b..a974955fd7a 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/AuRaBlockProducerTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/AuRaBlockProducerTests.cs @@ -2,10 +2,13 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Castle.DynamicProxy.Generators.Emitters.SimpleAST; using Nethermind.Blockchain; +using Nethermind.Blockchain.Synchronization; using Nethermind.Config; using Nethermind.Consensus; using Nethermind.Consensus.AuRa; @@ -19,8 +22,10 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Evm.Tracing; +using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Specs; +using Nethermind.Specs.Forks; using Nethermind.State; using NSubstitute; using NSubstitute.ReceivedExtensions; diff --git a/src/Nethermind/Nethermind.AuRa.Test/AuRaContractGasLimitOverrideTests.cs b/src/Nethermind/Nethermind.AuRa.Test/AuRaContractGasLimitOverrideTests.cs index 9f9fee3620b..2b8eb90b88b 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/AuRaContractGasLimitOverrideTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/AuRaContractGasLimitOverrideTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using FluentAssertions; using Nethermind.Abi; diff --git a/src/Nethermind/Nethermind.AuRa.Test/AuRaHealthHintServiceTests.cs b/src/Nethermind/Nethermind.AuRa.Test/AuRaHealthHintServiceTests.cs index 1f456018852..1679cc67162 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/AuRaHealthHintServiceTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/AuRaHealthHintServiceTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Nethermind.Blockchain; using Nethermind.Blockchain.Services; using Nethermind.Consensus.AuRa; using Nethermind.Consensus.AuRa.Services; diff --git a/src/Nethermind/Nethermind.AuRa.Test/AuRaSealValidatorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/AuRaSealValidatorTests.cs index dbbd7df1bf2..8fc0e894408 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/AuRaSealValidatorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/AuRaSealValidatorTests.cs @@ -5,11 +5,14 @@ using System.Collections; using System.Collections.Generic; using System.Net; +using System.Security; +using FluentAssertions; using Nethermind.Blockchain; using Nethermind.Consensus.AuRa; using Nethermind.Consensus.AuRa.Validators; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Specs.ChainSpecStyle; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; diff --git a/src/Nethermind/Nethermind.AuRa.Test/AuRaSealerTests.cs b/src/Nethermind/Nethermind.AuRa.Test/AuRaSealerTests.cs index 3386d8b8b32..679dfaf87ea 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/AuRaSealerTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/AuRaSealerTests.cs @@ -2,8 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections; using NUnit.Framework; using System.Collections.Generic; +using System.Net; using System.Threading; using System.Threading.Tasks; using FluentAssertions; @@ -13,10 +15,13 @@ using Nethermind.Consensus.AuRa.Validators; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Logging; using Nethermind.Serialization.Rlp; +using Nethermind.Specs; +using Nethermind.Wallet; using NSubstitute; namespace Nethermind.AuRa.Test diff --git a/src/Nethermind/Nethermind.AuRa.Test/AuRaStepCalculatorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/AuRaStepCalculatorTests.cs index 07c8d332c0f..8e8fcc3870a 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/AuRaStepCalculatorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/AuRaStepCalculatorTests.cs @@ -5,11 +5,15 @@ using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using FluentAssertions; using Nethermind.Consensus.AuRa; using Nethermind.Core; +using Nethermind.Core.Extensions; +using Nethermind.Crypto; using Nethermind.Logging; using NUnit.Framework; +using Org.BouncyCastle.Asn1.Cms; namespace Nethermind.AuRa.Test { diff --git a/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs index 5798002af55..60033b7820c 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs @@ -17,6 +17,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Db; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreTests.cs index 679c145f6c3..a12ccbbe736 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreTests.cs @@ -13,6 +13,7 @@ using Nethermind.Consensus.AuRa.Contracts; using Nethermind.Consensus.AuRa.Contracts.DataStore; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Logging; @@ -20,256 +21,257 @@ using NSubstitute.ExceptionExtensions; using NUnit.Framework; -namespace Nethermind.AuRa.Test.Contract; - -public class ContractDataStoreTests +namespace Nethermind.AuRa.Test.Contract { - [Test] - public void returns_data_from_getAll_on_init() - { - TestCase
testCase = BuildTestCase
(); - BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).TestObject; - Address[] expected = { TestItem.AddressA }; - testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(expected); - testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader).Should().BeEquivalentTo(expected.Cast()); - } - - [Test] - public void returns_cached_data_from_on_consecutive_calls() - { - TestCase
testCase = BuildTestCase
(); - BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).TestObject; - Address[] expected = { TestItem.AddressA }; - testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(expected); - - testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader).Should().BeEquivalentTo(testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader)); - testCase.DataContract.Received(1).GetAllItemsFromBlock(blockHeader); - } - - [Test] - public void returns_data_from_getAll_on_non_consecutive_call() + public class ContractDataStoreTests { - TestCase
testCase = BuildTestCase
(); - BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; - testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(new[] { TestItem.AddressA }); - BlockHeader secondBlockHeader = Build.A.BlockHeader.WithNumber(3).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakC).TestObject; - Address[] expected = { TestItem.AddressB }; - testCase.DataContract.GetAllItemsFromBlock(secondBlockHeader).Returns(expected); - - testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); - testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlockHeader).Should().BeEquivalentTo(expected.Cast()); - } - - [Test] - public void returns_data_from_previous_block_on_error() - { - TestCase
testCase = BuildTestCase
(); - BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; - Address[] expected = { TestItem.AddressA }; - testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(expected); - BlockHeader secondBlockHeader = Build.A.BlockHeader.WithNumber(3).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakC).TestObject; - testCase.DataContract.GetAllItemsFromBlock(secondBlockHeader).Throws(new AbiException(string.Empty)); - - testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); - testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlockHeader).Should().BeEquivalentTo(expected.Cast()); - } + [Test] + public void returns_data_from_getAll_on_init() + { + TestCase
testCase = BuildTestCase
(); + BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).TestObject; + Address[] expected = { TestItem.AddressA }; + testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(expected); + testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader).Should().BeEquivalentTo(expected.Cast()); + } + + [Test] + public void returns_cached_data_from_on_consecutive_calls() + { + TestCase
testCase = BuildTestCase
(); + BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).TestObject; + Address[] expected = { TestItem.AddressA }; + testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(expected); - [Test] - public void returns_data_from_getAll_on_non_consecutive_receipts_with_incremental_changes() - { - TestCase
testCase = BuildTestCase
(); - BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; - testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(new[] { TestItem.AddressA }); - Block secondBlock = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(3).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakC).TestObject).TestObject; - Address[] expected = { TestItem.AddressB }; - testCase.DataContract.GetAllItemsFromBlock(secondBlock.Header).Returns(expected); + testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader).Should().BeEquivalentTo(testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader)); + testCase.DataContract.Received(1).GetAllItemsFromBlock(blockHeader); + } - testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); - testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); + [Test] + public void returns_data_from_getAll_on_non_consecutive_call() + { + TestCase
testCase = BuildTestCase
(); + BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; + testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(new[] { TestItem.AddressA }); + BlockHeader secondBlockHeader = Build.A.BlockHeader.WithNumber(3).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakC).TestObject; + Address[] expected = { TestItem.AddressB }; + testCase.DataContract.GetAllItemsFromBlock(secondBlockHeader).Returns(expected); + + testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); + testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlockHeader).Should().BeEquivalentTo(expected.Cast()); + } + + [Test] + public void returns_data_from_previous_block_on_error() + { + TestCase
testCase = BuildTestCase
(); + BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; + Address[] expected = { TestItem.AddressA }; + testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(expected); + BlockHeader secondBlockHeader = Build.A.BlockHeader.WithNumber(3).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakC).TestObject; + testCase.DataContract.GetAllItemsFromBlock(secondBlockHeader).Throws(new AbiException(string.Empty)); + + testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); + testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlockHeader).Should().BeEquivalentTo(expected.Cast()); + } + + [Test] + public void returns_data_from_getAll_on_non_consecutive_receipts_with_incremental_changes() + { + TestCase
testCase = BuildTestCase
(); + BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; + testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(new[] { TestItem.AddressA }); + Block secondBlock = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(3).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakC).TestObject).TestObject; + Address[] expected = { TestItem.AddressB }; + testCase.DataContract.GetAllItemsFromBlock(secondBlock.Header).Returns(expected); - testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Should().BeEquivalentTo(expected.Cast()); - } + testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); + testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); - [Test] - public async Task returns_data_from_receipts_on_non_consecutive_with_not_incremental_changes() - { - TestCase
testCase = BuildTestCase
(); - testCase.DataContract.IncrementalChanges.Returns(false); - BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; - testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(new[] { TestItem.AddressA }); - Block secondBlock = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(3).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakC).TestObject).TestObject; - Address[] expected = { TestItem.AddressB }; - testCase.DataContract.TryGetItemsChangedFromBlock(secondBlock.Header, Array.Empty(), out Arg.Any>()) - .Returns(x => - { - x[2] = expected; - return true; - }); + testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Should().BeEquivalentTo(expected.Cast()); + } - testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); - testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); + [Test] + public async Task returns_data_from_receipts_on_non_consecutive_with_not_incremental_changes() + { + TestCase
testCase = BuildTestCase
(); + testCase.DataContract.IncrementalChanges.Returns(false); + BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; + testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(new[] { TestItem.AddressA }); + Block secondBlock = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(3).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakC).TestObject).TestObject; + Address[] expected = { TestItem.AddressB }; + testCase.DataContract.TryGetItemsChangedFromBlock(secondBlock.Header, Array.Empty(), out Arg.Any>()) + .Returns(x => + { + x[2] = expected; + return true; + }); - await Task.Delay(10); // delay for refresh from contract as its async + testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); + testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); - testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Should().BeEquivalentTo(expected.Cast()); - } + await Task.Delay(10); // delay for refresh from contract as its async - [Test] - public void returns_data_from_getAll_on_non_consecutive_with_not_incremental_changes_if_genesis() - { - TestCase
testCase = BuildTestCase
(); - testCase.DataContract.IncrementalChanges.Returns(false); - Block block = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(0).TestObject).TestObject; - Address[] expected = { TestItem.AddressB }; - testCase.DataContract.GetAllItemsFromBlock(block.Header).Returns(expected); - testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(block)); - testCase.ContractDataStore.GetItemsFromContractAtBlock(block.Header).Should().BeEquivalentTo(expected.Cast()); - } + testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Should().BeEquivalentTo(expected.Cast()); + } - [Test] - public async Task returns_data_from_receipts_on_consecutive_with_not_incremental_changes() - { - TestCase
testCase = BuildTestCase
(); - testCase.DataContract.IncrementalChanges.Returns(false); - BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; - testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(new[] { TestItem.AddressA }); - Block secondBlock = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(2).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakA).TestObject).TestObject; - Address[] expected = { TestItem.AddressB }; - testCase.DataContract.TryGetItemsChangedFromBlock(secondBlock.Header, Array.Empty(), out Arg.Any>()) - .Returns(x => - { - x[2] = expected; - return true; - }); + [Test] + public void returns_data_from_getAll_on_non_consecutive_with_not_incremental_changes_if_genesis() + { + TestCase
testCase = BuildTestCase
(); + testCase.DataContract.IncrementalChanges.Returns(false); + Block block = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(0).TestObject).TestObject; + Address[] expected = { TestItem.AddressB }; + testCase.DataContract.GetAllItemsFromBlock(block.Header).Returns(expected); + testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(block)); + testCase.ContractDataStore.GetItemsFromContractAtBlock(block.Header).Should().BeEquivalentTo(expected.Cast()); + } + + [Test] + public async Task returns_data_from_receipts_on_consecutive_with_not_incremental_changes() + { + TestCase
testCase = BuildTestCase
(); + testCase.DataContract.IncrementalChanges.Returns(false); + BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; + testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(new[] { TestItem.AddressA }); + Block secondBlock = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(2).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakA).TestObject).TestObject; + Address[] expected = { TestItem.AddressB }; + testCase.DataContract.TryGetItemsChangedFromBlock(secondBlock.Header, Array.Empty(), out Arg.Any>()) + .Returns(x => + { + x[2] = expected; + return true; + }); - testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); - testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); + testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); + testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); - await Task.Delay(10); // delay for refresh from contract as its async + await Task.Delay(10); // delay for refresh from contract as its async - testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Should().BeEquivalentTo(expected.Cast()); - } + testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Should().BeEquivalentTo(expected.Cast()); + } - [Test] - public async Task returns_data_from_receipts_on_consecutive_with_incremental_changes() - { - TestCase
testCase = BuildTestCase
(); - BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; - testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(new[] { TestItem.AddressA }); - Block secondBlock = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(2).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakA).TestObject).TestObject; - testCase.DataContract.TryGetItemsChangedFromBlock(secondBlock.Header, Array.Empty(), out Arg.Any>()) - .Returns(x => - { - x[2] = new[] { TestItem.AddressB }; - return true; - }); + [Test] + public async Task returns_data_from_receipts_on_consecutive_with_incremental_changes() + { + TestCase
testCase = BuildTestCase
(); + BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; + testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(new[] { TestItem.AddressA }); + Block secondBlock = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(2).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakA).TestObject).TestObject; + testCase.DataContract.TryGetItemsChangedFromBlock(secondBlock.Header, Array.Empty(), out Arg.Any>()) + .Returns(x => + { + x[2] = new[] { TestItem.AddressB }; + return true; + }); - testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); - testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); + testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); + testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); - await Task.Delay(50); // delay for refresh from contract as its async + await Task.Delay(10); // delay for refresh from contract as its async - Assert.That( - () => testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).ToList(), - Is.EquivalentTo(new ArrayList() { TestItem.AddressA, TestItem.AddressB }).After(1000, 100) - ); - } + Assert.That( + () => testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).ToList(), + Is.EquivalentTo(new ArrayList() { TestItem.AddressA, TestItem.AddressB }).After(1000, 100) + ); + } - [Test] - public async Task returns_unmodified_data_from_empty_receipts_on_consecutive_with_incremental_changes() - { - TestCase
testCase = BuildTestCase
(); - BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; - testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(new[] { TestItem.AddressA, TestItem.AddressC }); - Block secondBlock = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(2).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakA).TestObject).TestObject; - testCase.DataContract.TryGetItemsChangedFromBlock(secondBlock.Header, Array.Empty(), out Arg.Any>()) - .Returns(x => - { - x[2] = Array.Empty
(); - return false; - }); + [Test] + public async Task returns_unmodified_data_from_empty_receipts_on_consecutive_with_incremental_changes() + { + TestCase
testCase = BuildTestCase
(); + BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; + testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns(new[] { TestItem.AddressA, TestItem.AddressC }); + Block secondBlock = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(2).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakA).TestObject).TestObject; + testCase.DataContract.TryGetItemsChangedFromBlock(secondBlock.Header, Array.Empty(), out Arg.Any>()) + .Returns(x => + { + x[2] = Array.Empty
(); + return false; + }); - testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); - testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); + testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); + testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); - await Task.Delay(10); // delay for refresh from contract as its async + await Task.Delay(10); // delay for refresh from contract as its async - testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Should().BeEquivalentTo(TestItem.AddressA, TestItem.AddressC); - } + testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Should().BeEquivalentTo(TestItem.AddressA, TestItem.AddressC); + } - [Test] - public async Task returns_data_from_receipts_on_consecutive_with_incremental_changes_with_identity() - { - TestCase testCase = BuildTestCase( - TxPriorityContract.DistinctDestinationMethodComparer.Instance, - TxPriorityContract.ValueDestinationMethodComparer.Instance); - BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; - testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns( - new[] - { - new TxPriorityContract.Destination(TestItem.AddressB, new byte[] {0, 1, 2, 3}, 2), - new TxPriorityContract.Destination(TestItem.AddressA, new byte[] {0, 1, 2, 3}, 1), - }); - - Block secondBlock = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(2).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakA).TestObject).TestObject; - testCase.DataContract.TryGetItemsChangedFromBlock(secondBlock.Header, Array.Empty() - , out Arg.Any>()) - .Returns(x => - { - x[2] = new[] + [Test] + public async Task returns_data_from_receipts_on_consecutive_with_incremental_changes_with_identity() + { + TestCase testCase = BuildTestCase( + TxPriorityContract.DistinctDestinationMethodComparer.Instance, + TxPriorityContract.ValueDestinationMethodComparer.Instance); + BlockHeader blockHeader = Build.A.BlockHeader.WithNumber(1).WithHash(TestItem.KeccakA).TestObject; + testCase.DataContract.GetAllItemsFromBlock(blockHeader).Returns( + new[] { - new TxPriorityContract.Destination(TestItem.AddressB, new byte[] {0, 1, 2, 5}, 4), - new TxPriorityContract.Destination(TestItem.AddressB, new byte[] {0, 1, 2, 3}, 6) - }; - return true; - }); - - testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); - testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); - - await Task.Delay(10); // delay for refresh from contract as its async + new TxPriorityContract.Destination(TestItem.AddressB, new byte[] {0, 1, 2, 3}, 2), + new TxPriorityContract.Destination(TestItem.AddressA, new byte[] {0, 1, 2, 3}, 1), + }); + + Block secondBlock = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(2).WithHash(TestItem.KeccakB).WithParentHash(TestItem.KeccakA).TestObject).TestObject; + testCase.DataContract.TryGetItemsChangedFromBlock(secondBlock.Header, Array.Empty() + , out Arg.Any>()) + .Returns(x => + { + x[2] = new[] + { + new TxPriorityContract.Destination(TestItem.AddressB, new byte[] {0, 1, 2, 5}, 4), + new TxPriorityContract.Destination(TestItem.AddressB, new byte[] {0, 1, 2, 3}, 6) + }; + return true; + }); + + testCase.ContractDataStore.GetItemsFromContractAtBlock(blockHeader); + testCase.BlockTree.NewHeadBlock += Raise.EventWith(new BlockEventArgs(secondBlock)); + + await Task.Delay(10); // delay for refresh from contract as its async + + Assert.That( + () => testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Count(), + Is.EqualTo(3).After(1000, 100) + ); - Assert.That( - () => testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Count(), - Is.EqualTo(3).After(1000, 100) - ); + testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Should().BeEquivalentTo(new[] + { + new TxPriorityContract.Destination(TestItem.AddressB, new byte[] {0, 1, 2, 3}, 6), + new TxPriorityContract.Destination(TestItem.AddressB, new byte[] {0, 1, 2, 5}, 4), + new TxPriorityContract.Destination(TestItem.AddressA, new byte[] {0, 1, 2, 3}, 1) + }, o => o.ComparingByMembers()); + } - testCase.ContractDataStore.GetItemsFromContractAtBlock(secondBlock.Header).Should().BeEquivalentTo(new[] + protected virtual TestCase BuildTestCase(IComparer keyComparer = null, IComparer valueComparer = null) { - new TxPriorityContract.Destination(TestItem.AddressB, new byte[] {0, 1, 2, 3}, 6), - new TxPriorityContract.Destination(TestItem.AddressB, new byte[] {0, 1, 2, 5}, 4), - new TxPriorityContract.Destination(TestItem.AddressA, new byte[] {0, 1, 2, 3}, 1) - }, o => o.ComparingByMembers()); - } - - protected virtual TestCase BuildTestCase(IComparer keyComparer = null, IComparer valueComparer = null) - { - IDataContract dataContract = Substitute.For>(); - dataContract.IncrementalChanges.Returns(true); + IDataContract dataContract = Substitute.For>(); + dataContract.IncrementalChanges.Returns(true); - IBlockTree blockTree = Substitute.For(); - IReceiptFinder receiptsFinder = Substitute.For(); - receiptsFinder.Get(Arg.Any()).Returns(Array.Empty()); + IBlockTree blockTree = Substitute.For(); + IReceiptFinder receiptsFinder = Substitute.For(); + receiptsFinder.Get(Arg.Any()).Returns(Array.Empty()); - return new TestCase() + return new TestCase() + { + DataContract = dataContract, + BlockTree = blockTree, + ReceiptFinder = receiptsFinder, + ContractDataStore = keyComparer is null + ? new ContractDataStore(new HashSetContractDataStoreCollection(), dataContract, blockTree, receiptsFinder, LimboLogs.Instance) + : new DictionaryContractDataStore(new SortedListContractDataStoreCollection(keyComparer, valueComparer), dataContract, blockTree, receiptsFinder, LimboLogs.Instance) + }; + } + + public class TestCase { - DataContract = dataContract, - BlockTree = blockTree, - ReceiptFinder = receiptsFinder, - ContractDataStore = keyComparer is null - ? new ContractDataStore(new HashSetContractDataStoreCollection(), dataContract, blockTree, receiptsFinder, LimboLogs.Instance) - : new DictionaryContractDataStore(new SortedListContractDataStoreCollection(keyComparer, valueComparer), dataContract, blockTree, receiptsFinder, LimboLogs.Instance) - }; - } - - public class TestCase - { - public IContractDataStore ContractDataStore { get; set; } + public IContractDataStore ContractDataStore { get; set; } - public IBlockTree BlockTree { get; set; } + public IBlockTree BlockTree { get; set; } - public IReceiptFinder ReceiptFinder { get; set; } + public IReceiptFinder ReceiptFinder { get; set; } - public IDataContract DataContract { get; set; } + public IDataContract DataContract { get; set; } + } } } diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreWithLocalDataTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreWithLocalDataTests.cs index b9d633d3520..692fbd346e0 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreWithLocalDataTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/ContractDataStoreWithLocalDataTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using FluentAssertions; using Nethermind.Blockchain; diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/TestContractBlockchain.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/TestContractBlockchain.cs index c74e85bf67d..8da766372d6 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/TestContractBlockchain.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/TestContractBlockchain.cs @@ -3,6 +3,7 @@ using System.IO; using System.Threading.Tasks; +using Castle.Core.Internal; using Nethermind.Blockchain; using Nethermind.Core; using Nethermind.Core.Specs; diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/TxPriorityContractTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/TxPriorityContractTests.cs index 3e0fc34aa08..4851ea4cd03 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/TxPriorityContractTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/TxPriorityContractTests.cs @@ -11,11 +11,17 @@ using FluentAssertions; using Nethermind.Abi; using Nethermind.Blockchain.Data; +using Nethermind.Consensus; +using Nethermind.Consensus.AuRa; using Nethermind.Consensus.AuRa.Contracts; using Nethermind.Consensus.AuRa.Contracts.DataStore; +using Nethermind.Consensus.AuRa.Transactions; +using Nethermind.Consensus.AuRa.Validators; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Producers; +using Nethermind.Consensus.Transactions; using Nethermind.Core; +using Nethermind.Core.Attributes; using Nethermind.Core.Specs; using Nethermind.Core.Test.Blockchain; using Nethermind.Core.Test.Builders; @@ -24,7 +30,10 @@ using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Serialization.Json; +using Nethermind.Specs.ChainSpecStyle; using Nethermind.Trie.Pruning; +using Nethermind.TxPool; +using NSubstitute; using NUnit.Framework; namespace Nethermind.AuRa.Test.Contract @@ -324,9 +333,9 @@ private Transaction[] SignTransactions(IEthereumEcdsa ecdsa, PrivateKey key, UIn for (int index = 0; index < transactions.Length; index++) { Transaction transaction = transactions[index]; - transaction.Nonce = (UInt256)index + baseNonce; ecdsa.Sign(key, transaction, true); transaction.SenderAddress = key.Address; + transaction.Nonce = (UInt256)index + baseNonce; transaction.Hash = transaction.CalculateHash(); } @@ -354,7 +363,7 @@ protected override ILocalDataSource> GetWhitelistLocalDataS protected override ILocalDataSource> GetMinGasPricesLocalDataStore() => LocalDataSource.GetMinGasPricesLocalDataSource(); - protected override Task Build(ISpecProvider specProvider = null, UInt256? initialValues = null, bool addBlockOnStart = true) + protected override Task Build(ISpecProvider specProvider = null, UInt256? initialValues = null) { TempFile = TempPath.GetTempFile(); LocalDataSource = new TxPriorityContract.LocalDataSource(TempFile.Path, new EthereumJsonSerializer(), new FileSystem(), LimboLogs.Instance, Interval); diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs index acf6647aecb..d6df3491e65 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs @@ -82,7 +82,7 @@ public void finalize_change_should_call_correct_transaction() contract.FinalizeChange(_block.Header); _transactionProcessor.Received().Execute( - Arg.Is(t => IsEquivalentTo(expectation, t)), Arg.Is(blkCtx => blkCtx.Header.Equals(_block.Header)), Arg.Any()); + Arg.Is(t => IsEquivalentTo(expectation, t)), _block.Header, Arg.Any()); } private static bool IsEquivalentTo(Transaction expected, Transaction item) diff --git a/src/Nethermind/Nethermind.AuRa.Test/ListExtensionsTests.cs b/src/Nethermind/Nethermind.AuRa.Test/ListExtensionsTests.cs index 467b645b5d9..8d59ada84bf 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/ListExtensionsTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/ListExtensionsTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using FluentAssertions; +using Nethermind.Consensus.AuRa; using Nethermind.Core.Collections; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.AuRa.Test/Reward/AuRaRewardCalculatorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Reward/AuRaRewardCalculatorTests.cs index 417955c1ffe..7717e75d0e6 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Reward/AuRaRewardCalculatorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Reward/AuRaRewardCalculatorTests.cs @@ -14,12 +14,12 @@ using Nethermind.Core.Test; using Nethermind.Specs.ChainSpecStyle; using Nethermind.Core.Test.Builders; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; using NSubstitute; using NUnit.Framework; -using Nethermind.Evm; namespace Nethermind.AuRa.Test.Reward { @@ -198,7 +198,7 @@ private void SetupBlockRewards(IDictionary rewards) { _transactionProcessor.When(x => x.Execute( Arg.Is(t => CheckTransaction(t, rewards.Keys, _rewardData)), - Arg.Is(blkCtx => blkCtx.Header.Equals(_block.Header)), + _block.Header, Arg.Is(t => t is CallOutputTracer))) .Do(args => { diff --git a/src/Nethermind/Nethermind.AuRa.Test/Transactions/GeneratedTxSourceSealerTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Transactions/GeneratedTxSourceSealerTests.cs index 76447cde3f3..3e2ebd669ff 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Transactions/GeneratedTxSourceSealerTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Transactions/GeneratedTxSourceSealerTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Linq; using FluentAssertions; using Nethermind.Consensus; @@ -13,6 +14,7 @@ using Nethermind.Logging; using Nethermind.State; using Nethermind.TxPool; +using Nethermind.Wallet; using NSubstitute; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.AuRa.Test/Transactions/GeneratedTxSourceTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Transactions/GeneratedTxSourceTests.cs index 85e6731ce29..a10bbe84c31 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Transactions/GeneratedTxSourceTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Transactions/GeneratedTxSourceTests.cs @@ -1,11 +1,13 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Linq; using Nethermind.Consensus.AuRa.Transactions; using Nethermind.Consensus.Transactions; using Nethermind.Core; using Nethermind.Core.Test.Builders; +using Nethermind.Int256; using Nethermind.Logging; using Nethermind.State; using Nethermind.TxPool; diff --git a/src/Nethermind/Nethermind.AuRa.Test/Transactions/MinGasPriceContractTxFilterTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Transactions/MinGasPriceContractTxFilterTests.cs index b1a69be308e..2602fadc6a7 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Transactions/MinGasPriceContractTxFilterTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Transactions/MinGasPriceContractTxFilterTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections; +using System.Collections.Generic; using Nethermind.Config; using Nethermind.Consensus.AuRa.Contracts; using Nethermind.Consensus.AuRa.Contracts.DataStore; @@ -12,6 +13,7 @@ using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Int256; +using Nethermind.TxPool; using NSubstitute; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.AuRa.Test/Transactions/PermissionTxComparerTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Transactions/PermissionTxComparerTests.cs index 9fee91bac4b..32d7c5fd5f0 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Transactions/PermissionTxComparerTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Transactions/PermissionTxComparerTests.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.ComponentModel.Design; using System.Diagnostics.CodeAnalysis; using System.Linq; using FluentAssertions; @@ -19,6 +20,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Int256; using Nethermind.Specs; +using Nethermind.TxPool; using Nethermind.TxPool.Collections; using NSubstitute; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs index 4fdef5729d7..cd20ec0da8a 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs @@ -20,6 +20,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Db; using Nethermind.Int256; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; @@ -29,7 +30,7 @@ using NSubstitute; using NUnit.Framework; using BlockTree = Nethermind.Blockchain.BlockTree; -using Nethermind.Evm; +using Nethermind.Core.Specs; namespace Nethermind.AuRa.Test.Validators { @@ -176,13 +177,13 @@ public void loads_initial_validators_from_contract(long blockNumber) _transactionProcessor.Received() .CallAndRestore( Arg.Is(t => CheckTransaction(t, _getValidatorsData)), - Arg.Is(blkCtx => blkCtx.Header.Equals(_parentHeader)), + _parentHeader, Arg.Is(t => t is CallOutputTracer)); // finalizeChange should be called _transactionProcessor.Received(finalizeChangeCalled ? 1 : 0) .Execute(Arg.Is(t => CheckTransaction(t, _finalizeChangeData)), - Arg.Is(blkCtx => blkCtx.Header.Equals(block.Header)), + block.Header, Arg.Is(t => t is CallOutputTracer)); // initial validator should be true @@ -550,7 +551,7 @@ IEnumerable GetAllBlocks(BlockTree bt) Address validators = TestItem.Addresses[initialValidatorsIndex * 10]; InMemoryReceiptStorage inMemoryReceiptStorage = new(); - BlockTreeBuilder blockTreeBuilder = Build.A.BlockTree(MainnetSpecProvider.Instance) + BlockTreeBuilder blockTreeBuilder = Build.A.BlockTree(RopstenSpecProvider.Instance) .WithTransactions(inMemoryReceiptStorage, delegate (Block block, Transaction transaction) { byte i = 0; @@ -595,7 +596,7 @@ private void ValidateFinalizationForChain(ConsecutiveInitiateChangeTestParameter // finalizeChange should be called or not based on test spec _transactionProcessor.Received(chain.ExpectedFinalizationCount) .Execute(Arg.Is(t => CheckTransaction(t, _finalizeChangeData)), - Arg.Is(blkCtx => blkCtx.Header.Equals(_block.Header)), + _block.Header, Arg.Is(t => t is CallOutputTracer)); _transactionProcessor.ClearReceivedCalls(); @@ -626,7 +627,7 @@ private void SetupInitialValidators(BlockHeader header, BlockHeader parentHeader _transactionProcessor.When(x => x.CallAndRestore( Arg.Is(t => CheckTransaction(t, _getValidatorsData)), - Arg.Any(), + Arg.Any(), Arg.Is(t => t is CallOutputTracer))) .Do(args => args.Arg().MarkAsSuccess( diff --git a/src/Nethermind/Nethermind.AuRa.Test/Validators/ListValidatorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Validators/ListValidatorTests.cs index 79d8dbde6b8..b822a0b666b 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Validators/ListValidatorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Validators/ListValidatorTests.cs @@ -3,14 +3,19 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Linq; +using System.Numerics; +using System.Runtime.Serialization.Formatters; using FluentAssertions; using Nethermind.Consensus.AuRa.Validators; using Nethermind.Core; +using Nethermind.Core.Extensions; using Nethermind.Specs.ChainSpecStyle; using Nethermind.Core.Test.Builders; using Nethermind.Logging; using NSubstitute; +using NSubstitute.ExceptionExtensions; using NUnit.Framework; namespace Nethermind.AuRa.Test.Validators diff --git a/src/Nethermind/Nethermind.AuRa.Test/Validators/ValidatorStoreTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Validators/ValidatorStoreTests.cs index 4a64670c401..0ae03ea1b5d 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Validators/ValidatorStoreTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Validators/ValidatorStoreTests.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.IO; using System.Linq; using FluentAssertions; using Nethermind.Consensus.AuRa.Validators; @@ -13,6 +14,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Db; using Nethermind.Serialization.Rlp; +using Nethermind.Db.Blooms; using NUnit.Framework; namespace Nethermind.AuRa.Test.Validators diff --git a/src/Nethermind/Nethermind.Benchmark/Core/ByteArrayToHexBenchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Core/ByteArrayToHexBenchmarks.cs index aa4ab3250b8..774eb120e51 100644 --- a/src/Nethermind/Nethermind.Benchmark/Core/ByteArrayToHexBenchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Core/ByteArrayToHexBenchmarks.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using HexMate; using Nethermind.Core.Extensions; diff --git a/src/Nethermind/Nethermind.Benchmark/Core/BytesCompareBenchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Core/BytesCompareBenchmarks.cs index 168bd64ec19..75d070b6755 100644 --- a/src/Nethermind/Nethermind.Benchmark/Core/BytesCompareBenchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Core/BytesCompareBenchmarks.cs @@ -1,7 +1,10 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; +using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; diff --git a/src/Nethermind/Nethermind.Benchmark/Core/BytesIsZeroBenchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Core/BytesIsZeroBenchmarks.cs index 953e6937c55..70714e76454 100644 --- a/src/Nethermind/Nethermind.Benchmark/Core/BytesIsZeroBenchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Core/BytesIsZeroBenchmarks.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; diff --git a/src/Nethermind/Nethermind.Benchmark/Core/BytesPadBenchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Core/BytesPadBenchmarks.cs index 473b28fe2cd..bb2cb75aa5a 100644 --- a/src/Nethermind/Nethermind.Benchmark/Core/BytesPadBenchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Core/BytesPadBenchmarks.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; diff --git a/src/Nethermind/Nethermind.Benchmark/Core/FromHexBenchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Core/FromHexBenchmarks.cs index 8ba06a463c0..199f36557b8 100644 --- a/src/Nethermind/Nethermind.Benchmark/Core/FromHexBenchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Core/FromHexBenchmarks.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core.Extensions; namespace Nethermind.Benchmarks.Core diff --git a/src/Nethermind/Nethermind.Benchmark/Core/LruCacheBenchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Core/LruCacheBenchmarks.cs index f658bba33b2..3010e553fbf 100644 --- a/src/Nethermind/Nethermind.Benchmark/Core/LruCacheBenchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Core/LruCacheBenchmarks.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using BenchmarkDotNet.Attributes; using Nethermind.Core.Caching; diff --git a/src/Nethermind/Nethermind.Benchmark/Core/ToHexBenchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Core/ToHexBenchmarks.cs index 1fe91f6b8fc..b36e1b2cedf 100644 --- a/src/Nethermind/Nethermind.Benchmark/Core/ToHexBenchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Core/ToHexBenchmarks.cs @@ -3,6 +3,7 @@ using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; diff --git a/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseAndBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseAndBenchmark.cs index b89833f126d..d336dfc0997 100644 --- a/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseAndBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseAndBenchmark.cs @@ -1,10 +1,12 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; namespace Nethermind.Benchmarks.Evm { diff --git a/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseNotBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseNotBenchmark.cs index ce721090a60..394fb7516bf 100644 --- a/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseNotBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseNotBenchmark.cs @@ -5,6 +5,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; namespace Nethermind.Benchmarks.Evm { diff --git a/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseOrBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseOrBenchmark.cs index 8c69398724e..dd9e7d596e2 100644 --- a/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseOrBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseOrBenchmark.cs @@ -5,6 +5,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; namespace Nethermind.Benchmarks.Evm { diff --git a/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseXorBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseXorBenchmark.cs index 99e780f69b0..4cd05359b21 100644 --- a/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseXorBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Evm/BitwiseXorBenchmark.cs @@ -5,6 +5,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; namespace Nethermind.Benchmarks.Evm { diff --git a/src/Nethermind/Nethermind.Benchmark/Evm/Blake2Benchmark.cs b/src/Nethermind/Nethermind.Benchmark/Evm/Blake2Benchmark.cs index 2bbfe76480c..ad50bf4f0c6 100644 --- a/src/Nethermind/Nethermind.Benchmark/Evm/Blake2Benchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Evm/Blake2Benchmark.cs @@ -3,7 +3,10 @@ using System; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using BenchmarkDotNet.Running; +using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Crypto.Blake2; diff --git a/src/Nethermind/Nethermind.Benchmark/Evm/EcRecoverBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Evm/EcRecoverBenchmark.cs index cd755ba409e..0460c3a8b87 100644 --- a/src/Nethermind/Nethermind.Benchmark/Evm/EcRecoverBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Evm/EcRecoverBenchmark.cs @@ -3,6 +3,7 @@ using System; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; namespace Nethermind.Benchmarks.Evm { diff --git a/src/Nethermind/Nethermind.Benchmark/Evm/JumpDestinationsBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Evm/JumpDestinationsBenchmark.cs index b77cc017fa4..ed28fabb456 100644 --- a/src/Nethermind/Nethermind.Benchmark/Evm/JumpDestinationsBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Evm/JumpDestinationsBenchmark.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core.Extensions; +using Nethermind.Evm; using Nethermind.Evm.CodeAnalysis; namespace Nethermind.Benchmarks.Evm diff --git a/src/Nethermind/Nethermind.Benchmark/Evm/MemoryCostBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Evm/MemoryCostBenchmark.cs index a2f6ac7b7fe..f97b7cd9573 100644 --- a/src/Nethermind/Nethermind.Benchmark/Evm/MemoryCostBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Evm/MemoryCostBenchmark.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Evm; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Benchmark/Evm/SignExtendBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Evm/SignExtendBenchmark.cs index a4325a738f8..0c53d78683b 100644 --- a/src/Nethermind/Nethermind.Benchmark/Evm/SignExtendBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Evm/SignExtendBenchmark.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core.Extensions; namespace Nethermind.Benchmarks.Evm diff --git a/src/Nethermind/Nethermind.Benchmark/Mining/EthashHashimotoBenchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Mining/EthashHashimotoBenchmarks.cs index 3da24f13426..ee1f166eac2 100644 --- a/src/Nethermind/Nethermind.Benchmark/Mining/EthashHashimotoBenchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Mining/EthashHashimotoBenchmarks.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Consensus.Ethash; using Nethermind.Core; using Nethermind.Core.Crypto; diff --git a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeAccountBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeAccountBenchmark.cs index 037ca56de70..b88d4cec44d 100644 --- a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeAccountBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeAccountBenchmark.cs @@ -3,6 +3,7 @@ using System.Globalization; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core; using Nethermind.Core.Test.Builders; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeBlockBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeBlockBenchmark.cs index e5f923d7fc8..e855a2f3b2b 100644 --- a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeBlockBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeBlockBenchmark.cs @@ -2,12 +2,14 @@ // SPDX-License-Identifier: LGPL-3.0-only using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Int256; using Nethermind.Logging; +using Nethermind.Specs.Forks; namespace Nethermind.Benchmarks.Rlp { diff --git a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeIntBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeIntBenchmark.cs index 10ee404ee57..39a3043e9be 100644 --- a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeIntBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeIntBenchmark.cs @@ -3,6 +3,7 @@ using System; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Serialization.Rlp; namespace Nethermind.Benchmarks.Rlp diff --git a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeKeccakBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeKeccakBenchmark.cs index 7584a20b909..4242844e14a 100644 --- a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeKeccakBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeKeccakBenchmark.cs @@ -1,10 +1,14 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Serialization.Rlp; +using NUnit.Framework; namespace Nethermind.Benchmarks.Rlp { diff --git a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeLongBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeLongBenchmark.cs index af934413f0f..f0fe66576ec 100644 --- a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeLongBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpDecodeLongBenchmark.cs @@ -3,6 +3,7 @@ using System; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Serialization.Rlp; namespace Nethermind.Benchmarks.Rlp diff --git a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeAccountBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeAccountBenchmark.cs index d873523677a..6155f69f159 100644 --- a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeAccountBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeAccountBenchmark.cs @@ -3,6 +3,7 @@ using System.Globalization; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core; using Nethermind.Core.Test.Builders; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeBlockBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeBlockBenchmark.cs index c055004e014..5e555a063f6 100644 --- a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeBlockBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeBlockBenchmark.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; @@ -12,6 +13,7 @@ using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Serialization.Rlp; +using Nethermind.Specs.Forks; namespace Nethermind.Benchmarks.Rlp { diff --git a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeHeaderBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeHeaderBenchmark.cs index a572eb1424b..e28286f05bb 100644 --- a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeHeaderBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeHeaderBenchmark.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; diff --git a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeLongBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeLongBenchmark.cs index 8fd13561638..bef1cf627cb 100644 --- a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeLongBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeLongBenchmark.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core.Extensions; namespace Nethermind.Benchmarks.Rlp diff --git a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeTransactionBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeTransactionBenchmark.cs index 5fa30720434..11747fa9eb5 100644 --- a/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeTransactionBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Rlp/RlpEncodeTransactionBenchmark.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; diff --git a/src/Nethermind/Nethermind.Benchmark/State/StorageCellBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/State/StorageCellBenchmark.cs index 33e8639a995..eb74cff4830 100644 --- a/src/Nethermind/Nethermind.Benchmark/State/StorageCellBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/State/StorageCellBenchmark.cs @@ -6,6 +6,7 @@ using BenchmarkDotNet.Attributes; using Nethermind.Core; using Nethermind.Int256; +using Nethermind.State; using Nethermind.State.Tracing; namespace Nethermind.Benchmarks.State diff --git a/src/Nethermind/Nethermind.Benchmark/State/StorageTreeBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/State/StorageTreeBenchmark.cs index 4e0071ca704..eaa280269f3 100644 --- a/src/Nethermind/Nethermind.Benchmark/State/StorageTreeBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/State/StorageTreeBenchmark.cs @@ -1,10 +1,15 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using BenchmarkDotNet.Attributes; +using Microsoft.Diagnostics.Tracing.Parsers.MicrosoftAntimalwareEngine; +using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Int256; using Nethermind.Logging; using Nethermind.State; +using Nethermind.Trie; using Nethermind.Trie.Pruning; namespace Nethermind.Benchmarks.State diff --git a/src/Nethermind/Nethermind.Benchmark/Store/BloomStorageBenchmark.cs b/src/Nethermind/Nethermind.Benchmark/Store/BloomStorageBenchmark.cs index 8b49592e1fb..770af849eb9 100644 --- a/src/Nethermind/Nethermind.Benchmark/Store/BloomStorageBenchmark.cs +++ b/src/Nethermind/Nethermind.Benchmark/Store/BloomStorageBenchmark.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; using BenchmarkDotNet.Attributes; +using FluentAssertions; using Nethermind.Core; using Nethermind.Db; using Nethermind.Db.Blooms; diff --git a/src/Nethermind/Nethermind.Benchmark/Store/HexPrefixFromBytesBenchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Store/HexPrefixFromBytesBenchmarks.cs index e544921b005..fd5ae7a6b30 100644 --- a/src/Nethermind/Nethermind.Benchmark/Store/HexPrefixFromBytesBenchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Store/HexPrefixFromBytesBenchmarks.cs @@ -2,8 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; +using Nethermind.Db.Blooms; using Nethermind.Trie; namespace Nethermind.Benchmarks.Store diff --git a/src/Nethermind/Nethermind.Benchmark/Store/PatriciaTreeBenchmarks.cs b/src/Nethermind/Nethermind.Benchmark/Store/PatriciaTreeBenchmarks.cs index c1205be173e..f3f844157bd 100644 --- a/src/Nethermind/Nethermind.Benchmark/Store/PatriciaTreeBenchmarks.cs +++ b/src/Nethermind/Nethermind.Benchmark/Store/PatriciaTreeBenchmarks.cs @@ -3,10 +3,12 @@ using System; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.State; +using Nethermind.Db.Blooms; namespace Nethermind.Benchmarks.Store { diff --git a/src/Nethermind/Nethermind.Blockchain.Test.Runner/BlockchainTestsBugHunter.cs b/src/Nethermind/Nethermind.Blockchain.Test.Runner/BlockchainTestsBugHunter.cs index e3a38660ba0..716abb3b5e3 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test.Runner/BlockchainTestsBugHunter.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test.Runner/BlockchainTestsBugHunter.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Ethereum.Test.Base; using Ethereum.Test.Base.Interfaces; +using Nethermind.Logging; using Nethermind.Logging.NLog; namespace Nethermind.Blockchain.Test.Runner diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockFinderExtensionsTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockFinderExtensionsTests.cs index dfd7ef2182a..05412dd27c4 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockFinderExtensionsTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockFinderExtensionsTests.cs @@ -23,11 +23,11 @@ public void Can_upgrade_maybe_parent() parent.TotalDifficulty.Should().BeNull(); // just to avoid the testing rig change without this test being updated IBlockFinder blockFinder = Substitute.For(); - blockFinder.FindHeader(child.ParentHash!, BlockTreeLookupOptions.TotalDifficultyNotNeeded).Returns(parent); - blockFinder.FindHeader(child.ParentHash!, BlockTreeLookupOptions.None).Returns(parentWithTotalDiff); + blockFinder.FindHeader(child.ParentHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded).Returns(parent); + blockFinder.FindHeader(child.ParentHash, BlockTreeLookupOptions.None).Returns(parentWithTotalDiff); blockFinder.FindParentHeader(child, BlockTreeLookupOptions.TotalDifficultyNotNeeded).Should().Be(parent); - blockFinder.FindParentHeader(child, BlockTreeLookupOptions.None)!.TotalDifficulty.Should().Be((UInt256?)UInt256.One); + blockFinder.FindParentHeader(child, BlockTreeLookupOptions.None).TotalDifficulty.Should().Be((UInt256?)UInt256.One); } } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs index a56d98e68d2..58c6fb51a53 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs @@ -10,6 +10,7 @@ using Nethermind.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Db; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Logging; using Nethermind.Specs.Forks; @@ -25,6 +26,7 @@ using FluentAssertions; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Rewards; +using Nethermind.Consensus.Withdrawals; using Nethermind.Core.Test.Blockchain; using Nethermind.Evm.TransactionProcessing; @@ -67,7 +69,7 @@ public void Can_store_a_witness() { IDb stateDb = new MemDb(); IDb codeDb = new MemDb(); - TrieStore trieStore = new TrieStore(stateDb, LimboLogs.Instance); + var trieStore = new TrieStore(stateDb, LimboLogs.Instance); IWorldState stateProvider = new WorldState(trieStore, codeDb, LimboLogs.Instance); ITransactionProcessor transactionProcessor = Substitute.For(); @@ -90,7 +92,7 @@ public void Can_store_a_witness() ProcessingOptions.None, NullBlockTracer.Instance); - witnessCollector.Received(1).Persist(block.Hash!); + witnessCollector.Received(1).Persist(block.Hash); } [Test, Timeout(Timeout.MaxTestTime)] @@ -139,20 +141,20 @@ public void Recovers_state_on_cancel() [TestCase(2000)] public async Task Process_long_running_branch(int blocksAmount) { - Address address = TestItem.Addresses[0]; - TestSingleReleaseSpecProvider spec = new TestSingleReleaseSpecProvider(ConstantinopleFix.Instance); - TestRpcBlockchain testRpc = await TestRpcBlockchain.ForTest(SealEngineType.NethDev) + var address = TestItem.Addresses[0]; + var spec = new TestSingleReleaseSpecProvider(ConstantinopleFix.Instance); + var testRpc = await TestRpcBlockchain.ForTest(SealEngineType.NethDev) .Build(spec); testRpc.TestWallet.UnlockAccount(address, new SecureString()); await testRpc.AddFunds(address, 1.Ether()); await testRpc.AddBlock(); - SemaphoreSlim suggestedBlockResetEvent = new SemaphoreSlim(0); - testRpc.BlockTree.NewHeadBlock += (_, _) => + var suggestedBlockResetEvent = new SemaphoreSlim(0); + testRpc.BlockTree.NewHeadBlock += (s, e) => { suggestedBlockResetEvent.Release(1); }; - int branchLength = blocksAmount + (int)testRpc.BlockTree.BestKnownNumber + 1; + var branchLength = blocksAmount + (int)testRpc.BlockTree.BestKnownNumber + 1; ((BlockTree)testRpc.BlockTree).AddBranch(branchLength, (int)testRpc.BlockTree.BestKnownNumber); (await suggestedBlockResetEvent.WaitAsync(TestBlockchain.DefaultTimeout * 10)).Should().BeTrue(); Assert.That((int)testRpc.BlockTree.BestKnownNumber, Is.EqualTo(branchLength - 1)); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs index 07119be768f..ed6be277ba6 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs @@ -33,9 +33,9 @@ namespace Nethermind.Blockchain.Test [TestFixture] public class BlockTreeTests { - private TestMemDb _blocksInfosDb = null!; - private TestMemDb _headersDb = null!; - private TestMemDb _blocksDb = null!; + private TestMemDb _blocksInfosDb; + private TestMemDb _headersDb; + private TestMemDb _blocksDb; private BlockTree BuildBlockTree() { @@ -57,10 +57,10 @@ public void Add_genesis_shall_notify() { bool hasNotified = false; BlockTree blockTree = BuildBlockTree(); - blockTree.NewHeadBlock += (_, _) => { hasNotified = true; }; + blockTree.NewHeadBlock += (sender, args) => { hasNotified = true; }; bool hasNotifiedNewSuggested = false; - blockTree.NewSuggestedBlock += (_, _) => { hasNotifiedNewSuggested = true; }; + blockTree.NewSuggestedBlock += (sender, args) => { hasNotifiedNewSuggested = true; }; Block block = Build.A.Block.WithNumber(0).TestObject; AddBlockResult result = blockTree.SuggestBlock(block); @@ -76,10 +76,10 @@ public void Add_genesis_shall_work_even_with_0_difficulty() { bool hasNotified = false; BlockTree blockTree = BuildBlockTree(); - blockTree.NewBestSuggestedBlock += (_, _) => { hasNotified = true; }; + blockTree.NewBestSuggestedBlock += (sender, args) => { hasNotified = true; }; bool hasNotifiedNewSuggested = false; - blockTree.NewSuggestedBlock += (_, _) => { hasNotifiedNewSuggested = true; }; + blockTree.NewSuggestedBlock += (sender, args) => { hasNotifiedNewSuggested = true; }; Block block = Build.A.Block.WithNumber(0).WithDifficulty(0).TestObject; AddBlockResult result = blockTree.SuggestBlock(block); @@ -107,10 +107,10 @@ public void Shall_notify_on_new_head_block_after_genesis() Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; Block block1 = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject; blockTree.SuggestBlock(block0); - blockTree.NewHeadBlock += (_, _) => { hasNotified = true; }; + blockTree.NewHeadBlock += (sender, args) => { hasNotified = true; }; bool hasNotifiedNewSuggested = false; - blockTree.NewSuggestedBlock += (_, _) => { hasNotifiedNewSuggested = true; }; + blockTree.NewSuggestedBlock += (sender, args) => { hasNotifiedNewSuggested = true; }; AddBlockResult result = blockTree.SuggestBlock(block1); blockTree.UpdateMainChain(block1); @@ -133,13 +133,13 @@ public void Shall_notify_new_head_block_once_and_block_added_to_main_multiple_ti Block block3 = Build.A.Block.WithNumber(3).WithDifficulty(0).WithParent(block2).TestObject; blockTree.SuggestBlock(block0); - blockTree.NewHeadBlock += (_, _) => { newHeadBlockNotifications++; }; - blockTree.BlockAddedToMain += (_, _) => { blockAddedToMainNotifications++; }; + blockTree.NewHeadBlock += (sender, args) => { newHeadBlockNotifications++; }; + blockTree.BlockAddedToMain += (sender, args) => { blockAddedToMainNotifications++; }; blockTree.SuggestBlock(block1); blockTree.SuggestBlock(block2); blockTree.SuggestBlock(block3); - blockTree.UpdateMainChain(new[] { block1, block2, block3 }, true); + blockTree.UpdateMainChain(new Block[] { block1, block2, block3 }, true); newHeadBlockNotifications.Should().Be(1, "new head block"); blockAddedToMainNotifications.Should().Be(3, "block added to main"); @@ -153,10 +153,10 @@ public void Shall_notify_on_new_suggested_block_after_genesis() Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; Block block1 = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject; blockTree.SuggestBlock(block0); - blockTree.NewBestSuggestedBlock += (_, _) => { hasNotified = true; }; + blockTree.NewBestSuggestedBlock += (sender, args) => { hasNotified = true; }; bool hasNotifiedNewSuggested = false; - blockTree.NewSuggestedBlock += (_, _) => { hasNotifiedNewSuggested = true; }; + blockTree.NewSuggestedBlock += (sender, args) => { hasNotifiedNewSuggested = true; }; AddBlockResult result = blockTree.SuggestBlock(block1); @@ -176,11 +176,11 @@ public void Shall_not_notify_but_add_on_lower_difficulty() Block block2 = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject; blockTree.SuggestBlock(block0); blockTree.SuggestBlock(block1); - blockTree.NewHeadBlock += (_, _) => { hasNotifiedHead = true; }; - blockTree.NewBestSuggestedBlock += (_, _) => { hasNotifiedBest = true; }; + blockTree.NewHeadBlock += (sender, args) => { hasNotifiedHead = true; }; + blockTree.NewBestSuggestedBlock += (sender, args) => { hasNotifiedBest = true; }; bool hasNotifiedNewSuggested = false; - blockTree.NewSuggestedBlock += (_, _) => { hasNotifiedNewSuggested = true; }; + blockTree.NewSuggestedBlock += (sender, args) => { hasNotifiedNewSuggested = true; }; AddBlockResult result = blockTree.SuggestBlock(block2); @@ -230,16 +230,16 @@ public void Cleans_invalid_blocks_before_starting() tree.SuggestBlock(block2); tree.SuggestBlock(block3); - blockInfosDb.Set(BlockTree.DeletePointerAddressInDb, block1.Hash!.Bytes); + blockInfosDb.Set(BlockTree.DeletePointerAddressInDb, block1.Hash.Bytes); BlockTree tree2 = new(blocksDb, headersDb, blockInfosDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); Assert.That(tree2.BestKnownNumber, Is.EqualTo(0L), "best known"); Assert.That(tree2.Head, Is.EqualTo(null), "head"); - Assert.That(tree2.BestSuggestedHeader!.Number, Is.EqualTo(0L), "suggested"); + Assert.That(tree2.BestSuggestedHeader.Number, Is.EqualTo(0L), "suggested"); - Assert.IsNull(blocksDb.Get(block2.Hash!), "block 1"); - Assert.IsNull(blocksDb.Get(block2.Hash!), "block 2"); - Assert.IsNull(blocksDb.Get(block3.Hash!), "block 3"); + Assert.IsNull(blocksDb.Get(block2.Hash), "block 1"); + Assert.IsNull(blocksDb.Get(block2.Hash), "block 2"); + Assert.IsNull(blocksDb.Get(block3.Hash), "block 3"); Assert.IsNull(blockInfosDb.Get(2), "level 1"); Assert.IsNull(blockInfosDb.Get(2), "level 2"); @@ -271,16 +271,16 @@ public void When_cleaning_descendants_of_invalid_does_not_touch_other_branches() tree.SuggestBlock(block2B); tree.SuggestBlock(block3B); - blockInfosDb.Set(BlockTree.DeletePointerAddressInDb, block1.Hash!.Bytes); + blockInfosDb.Set(BlockTree.DeletePointerAddressInDb, block1.Hash.Bytes); BlockTree tree2 = new(blocksDb, headersDb, blockInfosDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); Assert.That(tree2.BestKnownNumber, Is.EqualTo(3L), "best known"); Assert.That(tree2.Head, Is.EqualTo(null), "head"); - Assert.That(tree2.BestSuggestedHeader!.Hash, Is.EqualTo(block3B.Hash), "suggested"); + Assert.That(tree2.BestSuggestedHeader.Hash, Is.EqualTo(block3B.Hash), "suggested"); - blocksDb.Get(block1.Hash!).Should().BeNull("block 1"); - blocksDb.Get(block2.Hash!).Should().BeNull("block 2"); - blocksDb.Get(block3.Hash!).Should().BeNull("block 3"); + blocksDb.Get(block1.Hash).Should().BeNull("block 1"); + blocksDb.Get(block2.Hash).Should().BeNull("block 2"); + blocksDb.Get(block3.Hash).Should().BeNull("block 3"); Assert.NotNull(blockInfosDb.Get(1), "level 1"); Assert.NotNull(blockInfosDb.Get(2), "level 2"); @@ -302,7 +302,7 @@ public void Can_load_best_known_up_to_256million() return chainLevel.Bytes; } - return null!; + return null; }; BlockTree blockTree = new(_blocksDb, _headersDb, blocksInfosDb, new ChainLevelInfoRepository(blocksInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); @@ -336,7 +336,7 @@ public void Add_on_branch_move_find_via_block_finder_interface() BlockTree blockTree = BuildBlockTree(); Block block = Build.A.Block.TestObject; AddToMain(blockTree, block); - Block? found = ((IBlockFinder)blockTree).FindBlock(new BlockParameter(block.Hash!, true)); + Block? found = ((IBlockFinder)blockTree).FindBlock(new BlockParameter(block.Hash, true)); Assert.That(found?.Header.CalculateHash(), Is.EqualTo(block.Hash)); } @@ -356,7 +356,7 @@ public void Add_on_branch_and_not_find_on_main_via_block_finder_interface() BlockTree blockTree = BuildBlockTree(); Block block = Build.A.Block.TestObject; blockTree.SuggestBlock(block); - Block? found = ((IBlockFinder)blockTree).FindBlock(new BlockParameter(block.Hash!, true)); + Block? found = ((IBlockFinder)blockTree).FindBlock(new BlockParameter(block.Hash, true)); Assert.IsNull(found); } @@ -675,7 +675,7 @@ public void Total_difficulty_is_calculated_when_exists_parent_with_total_difficu Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; blockTree.SuggestBlock(block0); - Block block1 = Build.A.Block.WithNumber(1).WithParentHash(block0.Hash!).WithDifficulty(2).TestObject; + Block block1 = Build.A.Block.WithNumber(1).WithParentHash(block0.Hash).WithDifficulty(2).TestObject; blockTree.SuggestBlock(block1); block1.TotalDifficulty.Should().NotBeNull(); Assert.That((int)block1.TotalDifficulty!, Is.EqualTo(3)); @@ -703,7 +703,7 @@ public void Head_block_gets_updated() AddToMain(blockTree, block0); AddToMain(blockTree, block1); - Assert.That(blockTree.Head!.CalculateHash(), Is.EqualTo(block1.Hash)); + Assert.That(blockTree.Head.CalculateHash(), Is.EqualTo(block1.Hash)); } [Test, Timeout(Timeout.MaxTestTime)] @@ -715,8 +715,8 @@ public void Best_suggested_block_gets_updated() AddToMain(blockTree, block0); blockTree.SuggestBlock(block1); - Assert.That(blockTree.Head!.CalculateHash(), Is.EqualTo(block0.Hash), "head block"); - Assert.That(blockTree.BestSuggestedHeader!.CalculateHash(), Is.EqualTo(block1.Hash), "best suggested"); + Assert.That(blockTree.Head.CalculateHash(), Is.EqualTo(block0.Hash), "head block"); + Assert.That(blockTree.BestSuggestedHeader.CalculateHash(), Is.EqualTo(block1.Hash), "best suggested"); } [Test, Timeout(Timeout.MaxTestTime)] @@ -726,7 +726,7 @@ public void Sets_genesis_block() Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; AddToMain(blockTree, block0); - Assert.That(blockTree.Genesis!.CalculateHash(), Is.EqualTo(block0.Hash)); + Assert.That(blockTree.Genesis.CalculateHash(), Is.EqualTo(block0.Hash)); } [Test, Timeout(Timeout.MaxTestTime)] @@ -764,12 +764,12 @@ public void Can_init_head_block_from_db_by_hash() MemDb blocksDb = new(); MemDb headersDb = new(); - blocksDb.Set(genesisBlock.Hash!, Rlp.Encode(genesisBlock).Bytes); - headersDb.Set(genesisBlock.Hash!, Rlp.Encode(genesisBlock.Header).Bytes); + blocksDb.Set(genesisBlock.Hash, Rlp.Encode(genesisBlock).Bytes); + headersDb.Set(genesisBlock.Hash, Rlp.Encode(genesisBlock.Header).Bytes); MemDb blockInfosDb = new(); - blockInfosDb.Set(Keccak.Zero, genesisBlock.Hash!.Bytes); - ChainLevelInfo level = new(true, new BlockInfo(headBlock.Hash!, headBlock.Difficulty)); + blockInfosDb.Set(Keccak.Zero, genesisBlock.Hash.Bytes); + ChainLevelInfo level = new(true, new BlockInfo(headBlock.Hash, headBlock.Difficulty)); level.BlockInfos[0].WasProcessed = true; blockInfosDb.Set(0, Rlp.Encode(level).Bytes); @@ -801,7 +801,7 @@ public void Sets_head_block_hash_in_db_on_new_head_block() AddToMain(blockTree, block0); AddToMain(blockTree, block1); - Keccak dec = new Keccak(blockInfosDb.Get(Keccak.Zero)!); + Keccak dec = new Keccak(blockInfosDb.Get(Keccak.Zero)); Assert.That(dec, Is.EqualTo(block1.Hash)); } @@ -814,9 +814,9 @@ public void Can_check_if_block_was_processed() BlockTree blockTree = BuildBlockTree(); blockTree.SuggestBlock(block0); blockTree.SuggestBlock(block1); - Assert.False(blockTree.WasProcessed(block1.Number, block1.Hash!), "before"); + Assert.False(blockTree.WasProcessed(block1.Number, block1.Hash), "before"); blockTree.UpdateMainChain(new[] { block0, block1 }, true); - Assert.True(blockTree.WasProcessed(block1.Number, block1.Hash!), "after"); + Assert.True(blockTree.WasProcessed(block1.Number, block1.Hash), "after"); } [Test, Timeout(Timeout.MaxTestTime)] @@ -840,7 +840,7 @@ public void Is_main_chain_returns_false_when_on_branch() BlockTree blockTree = BuildBlockTree(); blockTree.SuggestBlock(block0); blockTree.SuggestBlock(block1); - Assert.False(blockTree.IsMainChain(block1.Hash!)); + Assert.False(blockTree.IsMainChain(block1.Hash)); } [Test, Timeout(Timeout.MaxTestTime)] @@ -853,7 +853,7 @@ public void Is_main_chain_returns_true_when_on_main() blockTree.SuggestBlock(block0); blockTree.SuggestBlock(block1); blockTree.UpdateMainChain(block1); - Assert.True(blockTree.IsMainChain(block1.Hash!)); + Assert.True(blockTree.IsMainChain(block1.Hash)); } [Test, Timeout(Timeout.MaxTestTime)] @@ -1104,18 +1104,15 @@ public void When_deleting_invalid_block_does_not_delete_blocks_that_are_not_its_ [Test, Timeout(Timeout.MaxTestTime), TestCaseSource(nameof(SourceOfBSearchTestCases))] public void Loads_lowest_inserted_header_correctly(long beginIndex, long insertedBlocks) { - long? expectedResult = insertedBlocks == 0L ? null : beginIndex - insertedBlocks + 1L; + long? expectedResult = insertedBlocks == 0L ? (long?)null : beginIndex - insertedBlocks + 1L; MemDb blocksDb = new(); MemDb blockInfosDb = new(); MemDb headersDb = new(); MemDb metadataDb = new(); - SyncConfig syncConfig = new() - { - FastSync = true, - PivotNumber = beginIndex.ToString(), - }; + SyncConfig syncConfig = new() { FastSync = true }; + syncConfig.PivotNumber = beginIndex.ToString(); BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); tree.SuggestBlock(Build.A.Block.Genesis.TestObject); @@ -1144,10 +1141,8 @@ public void Loads_lowest_inserted_body_correctly(long beginIndex, long insertedB blocksDb.Set(0, Rlp.Encode(1L).Bytes); - SyncConfig syncConfig = new() - { - PivotNumber = beginIndex.ToString(), - }; + SyncConfig syncConfig = new(); + syncConfig.PivotNumber = beginIndex.ToString(); ChainLevelInfoRepository repo = new ChainLevelInfoRepository(blockInfosDb); BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, repo, MainnetSpecProvider.Instance, NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); @@ -1194,7 +1189,7 @@ public void Loads_lowest_inserted_body_correctly(long beginIndex, long insertedB new object[] {7280000L, 1L} }; - private ChainLevelInfoRepository _chainLevelInfoRepository = null!; + private ChainLevelInfoRepository _chainLevelInfoRepository; [Test, Timeout(Timeout.MaxTestTime), TestCaseSource(nameof(SourceOfBSearchTestCases))] public void Loads_best_known_correctly_on_inserts(long beginIndex, long insertedBlocks) @@ -1206,11 +1201,9 @@ public void Loads_best_known_correctly_on_inserts(long beginIndex, long inserted MemDb headersDb = new(); MemDb metadataDb = new(); - SyncConfig syncConfig = new() - { - PivotNumber = beginIndex.ToString(), - FastSync = true, - }; + SyncConfig syncConfig = new(); + syncConfig.PivotNumber = beginIndex.ToString(); + syncConfig.FastSync = true; BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); tree.SuggestBlock(Build.A.Block.Genesis.TestObject); @@ -1237,64 +1230,6 @@ public void Loads_best_known_correctly_on_inserts(long beginIndex, long inserted Assert.That(loadedTree.BestKnownNumber, Is.EqualTo(expectedResult), "loaded tree"); } - [Test] - public void Loads_best_head_up_to_best_persisted_state() - { - MemDb blocksDb = new(); - MemDb blockInfosDb = new(); - MemDb headersDb = new(); - MemDb metadataDb = new(); - - metadataDb.Set(MetadataDbKeys.BeaconSyncPivotNumber, Rlp.Encode(51).Bytes); - - SyncConfig syncConfig = new() - { - PivotNumber = "0", - FastSync = true, - }; - - BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); - Block genesis = Build.A.Block.Genesis.TestObject; - tree.SuggestBlock(genesis); - Block parent = genesis; - - List blocks = new() { genesis }; - - for (long i = 1; i < 100; i++) - { - Block block = Build.A.Block - .WithNumber(i) - .WithParent(parent) - .WithTotalDifficulty(i).TestObject; - blocks.Add(block); - parent = block; - if (i <= 50) - { - // tree.Insert(block.Header); - tree.SuggestBlock(block); - } - else - { - tree.Insert(block, BlockTreeInsertBlockOptions.SaveHeader, BlockTreeInsertHeaderOptions.BeaconBodyMetadata); - } - } - tree.UpdateMainChain(blocks.ToArray(), true); - tree.BestPersistedState = 50; - - BlockTree loadedTree = new( - blocksDb, - headersDb, - blockInfosDb, - metadataDb, - new ChainLevelInfoRepository(blockInfosDb), - MainnetSpecProvider.Instance, - NullBloomStorage.Instance, - syncConfig, - LimboLogs.Instance); - - Assert.That(loadedTree.Head?.Number, Is.EqualTo(50)); - } - [Timeout(Timeout.MaxTestTime)] [TestCase(1L)] [TestCase(2L)] @@ -1306,15 +1241,13 @@ public void Loads_best_known_correctly_on_inserts_followed_by_suggests(long pivo MemDb headersDb = new(); MemDb metadataDb = new(); - SyncConfig syncConfig = new() - { - PivotNumber = pivotNumber.ToString(), - }; + SyncConfig syncConfig = new(); + syncConfig.PivotNumber = pivotNumber.ToString(); BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); tree.SuggestBlock(Build.A.Block.Genesis.TestObject); - Block? pivotBlock = null; + Block pivotBlock = null!; for (long i = pivotNumber; i > 0; i--) { Block block = Build.A.Block.WithNumber(i).WithTotalDifficulty(i).TestObject; @@ -1337,10 +1270,7 @@ public void Loads_best_known_correctly_when_head_before_pivot() { int pivotNumber = 1000; int head = 10; - SyncConfig syncConfig = new() - { - PivotNumber = pivotNumber.ToString() - }; + SyncConfig syncConfig = new() { PivotNumber = pivotNumber.ToString() }; BlockTreeBuilder treeBuilder = Build.A.BlockTree().OfChainLength(head + 1); @@ -1368,10 +1298,8 @@ public void Cannot_insert_genesis() long pivotNumber = 0L; - SyncConfig syncConfig = new() - { - PivotNumber = pivotNumber.ToString(), - }; + SyncConfig syncConfig = new(); + syncConfig.PivotNumber = pivotNumber.ToString(); BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); Block genesis = Build.A.Block.Genesis.TestObject; @@ -1390,10 +1318,8 @@ public void Should_set_zero_total_difficulty() long pivotNumber = 0L; - SyncConfig syncConfig = new() - { - PivotNumber = pivotNumber.ToString(), - }; + SyncConfig syncConfig = new(); + syncConfig.PivotNumber = pivotNumber.ToString(); CustomSpecProvider specProvider = new(((ForkActivation)0, London.Instance)); specProvider.UpdateMergeTransitionInfo(null, 0); @@ -1420,10 +1346,8 @@ public void Inserts_blooms() long pivotNumber = 5L; - SyncConfig syncConfig = new() - { - PivotNumber = pivotNumber.ToString(), - }; + SyncConfig syncConfig = new(); + syncConfig.PivotNumber = pivotNumber.ToString(); IBloomStorage bloomStorage = Substitute.For(); IChainLevelInfoRepository chainLevelInfoRepository = Substitute.For(); @@ -1450,10 +1374,8 @@ public void Block_loading_is_lazy() MemDb headersDb = new(); MemDb metadataDb = new(); - SyncConfig syncConfig = new() - { - PivotNumber = 0L.ToString(), - }; + SyncConfig syncConfig = new(); + syncConfig.PivotNumber = 0L.ToString(); Block genesis = Build.A.Block.Genesis.TestObject; BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); @@ -1687,7 +1609,7 @@ public void Recovers_total_difficulty(int chainLength, bool deleteAllLevels, ulo ChainLevelInfo? level = blockTreeBuilder.ChainLevelInfoRepository.LoadLevel(i); level.Should().NotBeNull(); - level!.BlockInfos.Should().HaveCount(1); + level.BlockInfos.Should().HaveCount(1); } } @@ -1771,11 +1693,11 @@ public static IEnumerable InvalidBlockTestCases foreach (BlockTreeLookupOptions blockTreeLookupOptions in valueCombinations) { bool allowInvalid = (blockTreeLookupOptions & BlockTreeLookupOptions.AllowInvalid) == BlockTreeLookupOptions.AllowInvalid; - yield return new TestCaseData((Func)FindHeader, blockTreeLookupOptions, allowInvalid) + yield return new TestCaseData(FindHeader, blockTreeLookupOptions, allowInvalid) { TestName = $"InvalidBlock_{nameof(FindHeader)}_({blockTreeLookupOptions})_{(allowInvalid ? "found" : "not_found")}" }; - yield return new TestCaseData((Func)FindBlock, blockTreeLookupOptions, allowInvalid) + yield return new TestCaseData(FindBlock, blockTreeLookupOptions, allowInvalid) { TestName = $"InvalidBlock_{nameof(FindBlock)}_({blockTreeLookupOptions})_{(allowInvalid ? "found" : "not_found")}" }; @@ -1803,9 +1725,9 @@ public TestBlockTreeVisitor(ManualResetEvent manualResetEvent) _manualResetEvent = manualResetEvent; } - public bool PreventsAcceptingNewBlocks => true; - public long StartLevelInclusive => 0; - public long EndLevelExclusive => 3; + public bool PreventsAcceptingNewBlocks { get; } = true; + public long StartLevelInclusive { get; } = 0; + public long EndLevelExclusive { get; } = 3; public async Task VisitLevelStart(ChainLevelInfo chainLevelInfo, long levelNumber, CancellationToken cancellationToken) { if (_wait) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs index 66e32c4f0c1..e9c59963b6a 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics.Metrics; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -108,18 +109,18 @@ public Block[] Process(Keccak newBranchStateRoot, List suggestedBlocks, P } else { - _rootProcessed.Add(suggestedBlocks.Last().StateRoot!); + _rootProcessed.Add(suggestedBlocks.Last().StateRoot); BlockProcessed?.Invoke(this, new BlockProcessedEventArgs(suggestedBlocks.Last(), Array.Empty())); return suggestedBlocks.ToArray(); } } } - public event EventHandler? BlocksProcessing; + public event EventHandler BlocksProcessing; - public event EventHandler? BlockProcessed; + public event EventHandler BlockProcessed; - public event EventHandler? TransactionProcessed + public event EventHandler TransactionProcessed { add { } remove { } @@ -128,9 +129,11 @@ public event EventHandler? TransactionProcessed private class RecoveryStepMock : IBlockPreprocessorStep { - private readonly ILogger _logger; - private readonly ConcurrentDictionary _allowed = new(); - private readonly ConcurrentDictionary _allowedToFail = new(); + private ILogger _logger; + + private ConcurrentDictionary _allowed = new(); + + private ConcurrentDictionary _allowedToFail = new(); public RecoveryStepMock(ILogManager logManager) { @@ -143,6 +146,12 @@ public void Allow(Keccak hash) _allowed[hash] = new object(); } + public void AllowToFail(Keccak hash) + { + _logger.Info($"Allowing {hash} to fail recover"); + _allowedToFail[hash] = new object(); + } + public void RecoverData(Block block) { _logger.Info($"Recovering data for {block.ToString(Block.Format.Short)}"); @@ -154,12 +163,11 @@ public void RecoverData(Block block) while (true) { - Keccak blockHash = block.Hash!; - if (!_allowed.ContainsKey(blockHash)) + if (!_allowed.ContainsKey(block.Hash)) { - if (_allowedToFail.ContainsKey(blockHash)) + if (_allowedToFail.ContainsKey(block.Hash)) { - _allowedToFail.Remove(blockHash, out _); + _allowedToFail.Remove(block.Hash, out _); throw new Exception(); } @@ -168,23 +176,22 @@ public void RecoverData(Block block) } block.Header.Author = Address.Zero; - _allowed.Remove(blockHash, out _); + _allowed.Remove(block.Hash, out _); return; } } } - private readonly BlockTree _blockTree; - private readonly AutoResetEvent _resetEvent; - private readonly AutoResetEvent _queueEmptyResetEvent; - private readonly BlockProcessorMock _blockProcessor; - private readonly RecoveryStepMock _recoveryStep; - private readonly BlockchainProcessor _processor; - private readonly ILogger _logger; - - private Keccak? _headBefore; + private BlockTree _blockTree; + private AutoResetEvent _resetEvent; + private AutoResetEvent _queueEmptyResetEvent; + private BlockProcessorMock _blockProcessor; + private RecoveryStepMock _recoveryStep; + private BlockchainProcessor _processor; + private ILogger _logger; + private Keccak _headBefore; private int _processingQueueEmptyFired; - private const int ProcessingWait = 2000; + public const int ProcessingWait = 2000; public ProcessingTestContext(bool startProcessor) { @@ -208,7 +215,7 @@ public ProcessingTestContext(bool startProcessor) _queueEmptyResetEvent.Set(); }; - _blockTree.NewHeadBlock += (_, args) => + _blockTree.NewHeadBlock += (sender, args) => { _logger.Info($"Finished waiting for {args.Block.ToString(Block.Format.Short)} as block became the new head block"); _resetEvent.Set(); @@ -236,7 +243,7 @@ public AfterBlock Processed(Block block) _headBefore = _blockTree.Head?.Hash; ManualResetEvent processedEvent = new(false); bool wasProcessed = false; - _blockProcessor.BlockProcessed += (_, args) => + _blockProcessor.BlockProcessed += (sender, args) => { if (args.Block.Hash == block.Hash) { @@ -246,7 +253,7 @@ public AfterBlock Processed(Block block) }; _logger.Info($"Waiting for {block.ToString(Block.Format.Short)} to process"); - _blockProcessor.Allow(block.Hash!); + _blockProcessor.Allow(block.Hash); processedEvent.WaitOne(ProcessingWait); Assert.True(wasProcessed, $"Expected this block to get processed but it was not: {block.ToString(Block.Format.Short)}"); @@ -257,7 +264,7 @@ public AfterBlock ProcessedSkipped(Block block) { _headBefore = _blockTree.Head?.Hash; _logger.Info($"Waiting for {block.ToString(Block.Format.Short)} to be skipped"); - _blockProcessor.Allow(block.Hash!); + _blockProcessor.Allow(block.Hash); return new AfterBlock(_logManager, this, block); } @@ -266,7 +273,7 @@ public AfterBlock ProcessedFail(Block block) _headBefore = _blockTree.Head?.Hash; ManualResetEvent processedEvent = new(false); bool wasProcessed = false; - _blockProcessor.BlockProcessed += (_, args) => + _blockProcessor.BlockProcessed += (sender, args) => { if (args.Block.Hash == block.Hash) { @@ -276,7 +283,7 @@ public AfterBlock ProcessedFail(Block block) }; _logger.Info($"Waiting for {block.ToString(Block.Format.Short)} to fail processing"); - _blockProcessor.AllowToFail(block.Hash!); + _blockProcessor.AllowToFail(block.Hash); processedEvent.WaitOne(ProcessingWait); Assert.True(wasProcessed, $"Block was never processed {block.ToString(Block.Format.Short)}"); Assert.That(_blockTree.Head?.Hash, Is.EqualTo(_headBefore), $"Processing did not fail - {block.ToString(Block.Format.Short)} became a new head block"); @@ -305,8 +312,15 @@ public ProcessingTestContext SuggestedWithoutProcessingAndMoveToMain(Block block } _blockTree.UpdateMainChain(new[] { block }, false); - _blockProcessor.Allow(block.Hash!); - _recoveryStep.Allow(block.Hash!); + _blockProcessor.Allow(block.Hash); + _recoveryStep.Allow(block.Hash); + + return this; + } + + public ProcessingTestContext StartProcessor() + { + _processor.Start(); return this; } @@ -325,7 +339,7 @@ public ProcessingTestContext Suggested(BlockHeader block) public ProcessingTestContext Recovered(Block block) { - _recoveryStep.Allow(block.Hash!); + _recoveryStep.Allow(block.Hash); return this; } @@ -336,6 +350,12 @@ public ProcessingTestContext CountIs(int expectedCount) return this; } + public ProcessingTestContext ThenRecoveredFail(Block block) + { + _recoveryStep.AllowToFail(block.Hash); + return this; + } + public AfterBlock FullyProcessed(Block block) { return Suggested(block) @@ -366,10 +386,10 @@ public ProcessingTestContext QueueIsEmpty(int count) public class AfterBlock { + private ILogger _logger; public const int IgnoreWait = 200; - - private readonly ILogger _logger; private readonly Block _block; + private readonly ProcessingTestContext _processingTestContext; public AfterBlock(ILogManager logManager, ProcessingTestContext processingTestContext, Block block) @@ -383,7 +403,7 @@ public ProcessingTestContext BecomesGenesis() { _logger.Info($"Waiting for {_block.ToString(Block.Format.Short)} to become genesis block"); _processingTestContext._resetEvent.WaitOne(ProcessingWait); - Assert.That(_processingTestContext._blockTree.Genesis!.Hash, Is.EqualTo(_block.Header.Hash), "genesis"); + Assert.That(_processingTestContext._blockTree.Genesis.Hash, Is.EqualTo(_block.Header.Hash), "genesis"); return _processingTestContext; } @@ -391,7 +411,7 @@ public ProcessingTestContext BecomesNewHead() { _logger.Info($"Waiting for {_block.ToString(Block.Format.Short)} to become the new head block"); _processingTestContext._resetEvent.WaitOne(ProcessingWait); - Assert.That(() => _processingTestContext._blockTree.Head!.Hash, Is.EqualTo(_block.Header.Hash).After(1000, 100)); + Assert.That(() => _processingTestContext._blockTree.Head.Hash, Is.EqualTo(_block.Header.Hash).After(1000, 100)); return _processingTestContext; } @@ -399,7 +419,7 @@ public ProcessingTestContext IsKeptOnBranch() { _logger.Info($"Waiting for {_block.ToString(Block.Format.Short)} to be ignored"); _processingTestContext._resetEvent.WaitOne(IgnoreWait); - Assert.That(_processingTestContext._blockTree.Head!.Hash, Is.EqualTo(_processingTestContext._headBefore), "head"); + Assert.That(_processingTestContext._blockTree.Head.Hash, Is.EqualTo(_processingTestContext._headBefore), "head"); _logger.Info($"Finished waiting for {_block.ToString(Block.Format.Short)} to be ignored"); return _processingTestContext; } @@ -408,7 +428,7 @@ public ProcessingTestContext IsDeletedAsInvalid() { _logger.Info($"Waiting for {_block.ToString(Block.Format.Short)} to be deleted"); _processingTestContext._resetEvent.WaitOne(IgnoreWait); - Assert.That(_processingTestContext._blockTree.Head!.Hash, Is.EqualTo(_processingTestContext._headBefore), "head"); + Assert.That(_processingTestContext._blockTree.Head.Hash, Is.EqualTo(_processingTestContext._headBefore), "head"); _logger.Info($"Finished waiting for {_block.ToString(Block.Format.Short)} to be deleted"); Assert.Null(_processingTestContext._blockTree.FindBlock(_block.Hash, BlockTreeLookupOptions.None)); return _processingTestContext; @@ -429,17 +449,17 @@ private static class When public static ProcessingTestContext ProcessorIsNotStarted => new(false); } - private static readonly Block _block0 = Build.A.Block.WithNumber(0).WithNonce(0).WithDifficulty(0).TestObject; - private static readonly Block _block1D2 = Build.A.Block.WithNumber(1).WithNonce(1).WithParent(_block0).WithDifficulty(2).TestObject; - private static readonly Block _block2D4 = Build.A.Block.WithNumber(2).WithNonce(2).WithParent(_block1D2).WithDifficulty(2).TestObject; - private static readonly Block _block3D6 = Build.A.Block.WithNumber(3).WithNonce(3).WithParent(_block2D4).WithDifficulty(2).TestObject; - private static readonly Block _block4D8 = Build.A.Block.WithNumber(4).WithNonce(4).WithParent(_block3D6).WithDifficulty(2).TestObject; - private static readonly Block _block5D10 = Build.A.Block.WithNumber(5).WithNonce(5).WithParent(_block4D8).WithDifficulty(2).TestObject; - private static readonly Block _blockB2D4 = Build.A.Block.WithNumber(2).WithNonce(6).WithParent(_block1D2).WithDifficulty(2).TestObject; - private static readonly Block _blockB3D8 = Build.A.Block.WithNumber(3).WithNonce(7).WithParent(_blockB2D4).WithDifficulty(4).TestObject; - private static readonly Block _blockC2D100 = Build.A.Block.WithNumber(3).WithNonce(8).WithParent(_block1D2).WithDifficulty(98).TestObject; - private static readonly Block _blockD2D200 = Build.A.Block.WithNumber(3).WithNonce(8).WithParent(_block1D2).WithDifficulty(198).TestObject; - private static readonly Block _blockE2D300 = Build.A.Block.WithNumber(3).WithNonce(8).WithParent(_block1D2).WithDifficulty(298).TestObject; + private static Block _block0 = Build.A.Block.WithNumber(0).WithNonce(0).WithDifficulty(0).TestObject; + private static Block _block1D2 = Build.A.Block.WithNumber(1).WithNonce(1).WithParent(_block0).WithDifficulty(2).TestObject; + private static Block _block2D4 = Build.A.Block.WithNumber(2).WithNonce(2).WithParent(_block1D2).WithDifficulty(2).TestObject; + private static Block _block3D6 = Build.A.Block.WithNumber(3).WithNonce(3).WithParent(_block2D4).WithDifficulty(2).TestObject; + private static Block _block4D8 = Build.A.Block.WithNumber(4).WithNonce(4).WithParent(_block3D6).WithDifficulty(2).TestObject; + private static Block _block5D10 = Build.A.Block.WithNumber(5).WithNonce(5).WithParent(_block4D8).WithDifficulty(2).TestObject; + private static Block _blockB2D4 = Build.A.Block.WithNumber(2).WithNonce(6).WithParent(_block1D2).WithDifficulty(2).TestObject; + private static Block _blockB3D8 = Build.A.Block.WithNumber(3).WithNonce(7).WithParent(_blockB2D4).WithDifficulty(4).TestObject; + private static Block _blockC2D100 = Build.A.Block.WithNumber(3).WithNonce(8).WithParent(_block1D2).WithDifficulty(98).TestObject; + private static Block _blockD2D200 = Build.A.Block.WithNumber(3).WithNonce(8).WithParent(_block1D2).WithDifficulty(198).TestObject; + private static Block _blockE2D300 = Build.A.Block.WithNumber(3).WithNonce(8).WithParent(_block1D2).WithDifficulty(298).TestObject; [Test, Timeout(Timeout.MaxTestTime)] public void Can_ignore_lower_difficulty() @@ -505,12 +525,12 @@ public async Task Can_process_fast_sync() await testBlockchain.BuildSomeBlocks(5); When.ProcessingBlocks - .FullyProcessed(testBlockchain.BlockTree.FindBlock(0)!).BecomesGenesis() - .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(1)!) - .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(2)!) - .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(3)!) - .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(4)!) - .FullyProcessed(testBlockchain.BlockTree.FindBlock(5)!).BecomesNewHead(); + .FullyProcessed(testBlockchain.BlockTree.FindBlock(0)).BecomesGenesis() + .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(1)) + .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(2)) + .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(3)) + .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(4)) + .FullyProcessed(testBlockchain.BlockTree.FindBlock(5)).BecomesNewHead(); } [Test, Timeout(Timeout.MaxTestTime)] diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockhashProviderTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockhashProviderTests.cs index dd3b8feee26..89008b2e606 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockhashProviderTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockhashProviderTests.cs @@ -37,10 +37,10 @@ public void Can_lookup_up_to_256_before_with_headers_only() BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(chainLength).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); - BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None)!; + BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None); Block current = Build.A.Block.WithParent(head).TestObject; Keccak result = provider.GetBlockhash(current.Header, chainLength - 256); - Assert.That(result, Is.EqualTo(tree.FindHeader(256, BlockTreeLookupOptions.None)!.Hash)); + Assert.That(result, Is.EqualTo(tree.FindHeader(256, BlockTreeLookupOptions.None).Hash)); } [Test, Timeout(Timeout.MaxTestTime)] @@ -49,7 +49,7 @@ public void Can_lookup_up_to_256_before_with_headers_only_and_competing_branches const int chainLength = 512; Block genesis = Build.A.Block.Genesis.TestObject; - BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block _, chainLength, 1).TestObject; + BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block alternativeHeadBlock, chainLength, 1).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); Block current = Build.A.Block.WithParent(headBlock).TestObject; @@ -64,7 +64,7 @@ public void Can_lookup_up_to_256_before_soon_after_fast_sync() const int chainLength = 512; Block genesis = Build.A.Block.Genesis.TestObject; - BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block _, chainLength, 1).TestObject; + BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block alternativeHeadBlock, chainLength, 1).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); Block current = Build.A.Block.WithParent(headBlock).TestObject; @@ -81,7 +81,7 @@ public void Can_lookup_up_to_256_before_some_blocks_after_fast_sync() const int chainLength = 512; Block genesis = Build.A.Block.Genesis.TestObject; - BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block _, chainLength, 1).TestObject; + BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block alternativeHeadBlock, chainLength, 1).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); @@ -104,7 +104,7 @@ public void Can_handle_non_main_chain_in_fast_sync() const int chainLength = 512; Block genesis = Build.A.Block.Genesis.TestObject; - BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block _, chainLength, 1).TestObject; + BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block alternativeHeadBlock, chainLength, 1).TestObject; Block current = Build.A.Block.WithParent(headBlock).TestObject; for (int i = 0; i < 6; i++) { @@ -129,7 +129,7 @@ public void Can_get_parent_hash() BlockTree tree = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); - BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None)!; + BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None); Block current = Build.A.Block.WithParent(head).TestObject; Keccak result = provider.GetBlockhash(current.Header, chainLength - 1); Assert.That(result, Is.EqualTo(head.Hash)); @@ -144,7 +144,7 @@ public void Cannot_ask_for_self() BlockTree tree = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); - BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None)!; + BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None); Block current = Build.A.Block.WithParent(head).TestObject; Keccak result = provider.GetBlockhash(current.Header, chainLength); Assert.Null(result); @@ -159,7 +159,7 @@ public void Cannot_ask_about_future() BlockTree tree = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); - BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None)!; + BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None); Block current = Build.A.Block.WithParent(head).TestObject; Keccak result = provider.GetBlockhash(current.Header, chainLength + 1); Assert.Null(result); @@ -174,10 +174,10 @@ public void Can_lookup_up_to_256_before() BlockTree tree = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); - BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None)!; + BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None); Block current = Build.A.Block.WithParent(head).TestObject; Keccak result = provider.GetBlockhash(current.Header, chainLength - 256); - Assert.That(result, Is.EqualTo(tree.FindHeader(256, BlockTreeLookupOptions.None)!.Hash)); + Assert.That(result, Is.EqualTo(tree.FindHeader(256, BlockTreeLookupOptions.None).Hash)); } [Test, Timeout(Timeout.MaxTestTime)] @@ -189,7 +189,7 @@ public void No_lookup_more_than_256_before() BlockTree tree = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); - BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None)!; + BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None); Block current = Build.A.Block.WithParent(head).TestObject; Keccak result = provider.GetBlockhash(current.Header, chainLength - 257); Assert.Null(result); @@ -204,7 +204,7 @@ public void UInt_256_overflow() BlockTree tree = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); - BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None)!; + BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None); Block current = Build.A.Block.WithParent(head).TestObject; Keccak result = provider.GetBlockhash(current.Header, 127); Assert.That(result, Is.EqualTo(head.Hash)); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Blocks/BlockStoreTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Blocks/BlockStoreTests.cs index 0a6f19373d9..a4bd92bf46c 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Blocks/BlockStoreTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Blocks/BlockStoreTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Runtime.InteropServices.JavaScript; using FluentAssertions; using Nethermind.Blockchain.Blocks; using Nethermind.Core; @@ -25,12 +26,12 @@ public void Test_can_insert_get_and_remove_blocks(bool cached) Block block = Build.A.Block.WithNumber(1).TestObject; store.Insert(block); - Block? retrieved = store.Get(block.Hash!, cached); + Block? retrieved = store.Get(block.Hash, cached); retrieved.Should().BeEquivalentTo(block); - store.Delete(block.Hash!); + store.Delete(block.Hash); - store.Get(block.Hash!, cached).Should().BeNull(); + store.Get(block.Hash, cached).Should().BeNull(); } [Test] @@ -55,12 +56,12 @@ public void Test_when_cached_does_not_touch_db_on_next_get() Block block = Build.A.Block.WithNumber(1).TestObject; store.Insert(block); - Block? retrieved = store.Get(block.Hash!, true); + Block? retrieved = store.Get(block.Hash, true); retrieved.Should().BeEquivalentTo(block); db.Clear(); - retrieved = store.Get(block.Hash!, true); + retrieved = store.Get(block.Hash, true); retrieved.Should().BeEquivalentTo(block); } @@ -76,7 +77,8 @@ public void Test_getReceiptRecoveryBlock_produce_same_transaction_as_normal_get( store.Insert(block); - ReceiptRecoveryBlock retrieved = store.GetReceiptRecoveryBlock(block.Hash!)!.Value; + ReceiptRecoveryBlock retrieved = store.GetReceiptRecoveryBlock(block.Hash).Value; + retrieved.Should().NotBeNull(); retrieved.Header.Should().BeEquivalentTo(block.Header); retrieved.TransactionCount.Should().Be(block.Transactions.Length); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Bloom/BloomStorageTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Bloom/BloomStorageTests.cs index 44dfb98417d..9bee49a8549 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Bloom/BloomStorageTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Bloom/BloomStorageTests.cs @@ -11,6 +11,7 @@ using Nethermind.Core.Extensions; using Nethermind.Db; using Nethermind.Db.Blooms; +using NSubstitute; using NUnit.Framework; namespace Nethermind.Blockchain.Test.Bloom diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs b/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs index 71270f9b4ca..dee1a500774 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs @@ -14,7 +14,7 @@ public class FilterBuilder private static int _id; private BlockParameter _fromBlock = new(BlockParameterType.Latest); private BlockParameter _toBlock = new(BlockParameterType.Latest); - private AddressFilter _address = AddressFilter.AnyAddress; + private AddressFilter _address = new((Address)null); private SequenceTopicsFilter _topicsFilter = new(); private FilterBuilder() @@ -109,13 +109,6 @@ public FilterBuilder ToPendingBlock() return this; } - public FilterBuilder WithAnyAddress() - { - _address = AddressFilter.AnyAddress; - - return this; - } - public FilterBuilder WithAddress(Address address) { _address = new AddressFilter(address); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/NullSignerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/NullSignerTests.cs index 2befce006bb..299dab8411f 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/NullSignerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/NullSignerTests.cs @@ -26,8 +26,8 @@ public void Test() public async Task Test_signing() { NullSigner signer = NullSigner.Instance; - await signer.Sign((Transaction)null!); - signer.Sign((Keccak)null!).Bytes.Should().HaveCount(64); + await signer.Sign((Transaction)null); + signer.Sign((Keccak)null).Bytes.Should().HaveCount(64); } } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/OneByOneTxSourceTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/OneByOneTxSourceTests.cs index 1ba45176618..c5506cf3f6f 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/OneByOneTxSourceTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/OneByOneTxSourceTests.cs @@ -17,11 +17,10 @@ public class OneByOneTxSourceTests public void Can_serve_one_by_one() { ITxSource source = Substitute.For(); - BlockHeader blockHeader = new(); - source.GetTransactions(blockHeader, 0).Returns(new Transaction[5]); + source.GetTransactions(null, 0).Returns(new Transaction[5]); ITxSource oneByOne = source.ServeTxsOneByOne(); - oneByOne.GetTransactions(blockHeader, 0).Count().Should().Be(1); + oneByOne.GetTransactions(null, 0).Count().Should().Be(1); } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SignerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SignerTests.cs index 43c3e511ace..24f262985ca 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SignerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SignerTests.cs @@ -18,19 +18,26 @@ namespace Nethermind.Blockchain.Test.Consensus [TestFixture] public class SignerTests { + [Test, Timeout(Timeout.MaxTestTime)] + public void Throws_when_null_log_manager_in_constructor() + { + Assert.Throws(() => new Signer(1, (PrivateKey)null, null)); + Assert.Throws(() => new Signer(1, (ProtectedPrivateKey)null, null)); + } + [Test, Timeout(Timeout.MaxTestTime)] public void Address_is_zero_when_key_is_null() { // not a great fan of using Address.Zero like a null value but let us show in test // what it does - Signer signer = new(1, (PrivateKey?)null, LimboLogs.Instance); + Signer signer = new(1, (PrivateKey)null, LimboLogs.Instance); signer.Address.Should().Be(Address.Zero); } [Test, Timeout(Timeout.MaxTestTime)] public void Cannot_sign_when_null_key() { - Signer signer = new(1, (PrivateKey?)null, LimboLogs.Instance); + Signer signer = new(1, (PrivateKey)null, LimboLogs.Instance); signer.CanSign.Should().BeFalse(); } @@ -39,7 +46,7 @@ public void Can_set_signer_to_null() { Signer signer = new(1, TestItem.PrivateKeyA, LimboLogs.Instance); signer.CanSign.Should().BeTrue(); - signer.SetSigner((PrivateKey?)null); + signer.SetSigner((PrivateKey)null); signer.CanSign.Should().BeFalse(); } @@ -48,14 +55,14 @@ public void Can_set_signer_to_protected_null() { Signer signer = new(1, TestItem.PrivateKeyA, LimboLogs.Instance); signer.CanSign.Should().BeTrue(); - signer.SetSigner((ProtectedPrivateKey?)null); + signer.SetSigner((ProtectedPrivateKey)null); signer.CanSign.Should().BeFalse(); } [Test, Timeout(Timeout.MaxTestTime)] public void Throws_when_trying_to_sign_with_a_null_key() { - Signer signer = new(1, (PrivateKey?)null, LimboLogs.Instance); + Signer signer = new(1, (PrivateKey)null, LimboLogs.Instance); Assert.Throws(() => signer.Sign(Keccak.Zero)); } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SinglePendingTxSelectorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SinglePendingTxSelectorTests.cs index f8d509b7e5d..2e626579bd4 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SinglePendingTxSelectorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SinglePendingTxSelectorTests.cs @@ -7,6 +7,7 @@ using Nethermind.Consensus.Transactions; using Nethermind.Core; using Nethermind.Core.Test.Builders; +using Nethermind.Int256; using NSubstitute; using NUnit.Framework; @@ -24,6 +25,12 @@ public void To_string_does_not_throw() _ = selector.ToString(); } + [Test, Timeout(Timeout.MaxTestTime)] + public void Throws_on_null_argument() + { + Assert.Throws(() => new SinglePendingTxSelector(null)); + } + [Test, Timeout(Timeout.MaxTestTime)] public void When_no_transactions_returns_empty_list() { diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Data/FileLocalDataSourceTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Data/FileLocalDataSourceTests.cs index 2114a7fb98e..891b1ff4d5e 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Data/FileLocalDataSourceTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Data/FileLocalDataSourceTests.cs @@ -12,6 +12,8 @@ using Nethermind.Core.Test.IO; using Nethermind.Logging; using Nethermind.Serialization.Json; +using NSubstitute; +using NSubstitute.ExceptionExtensions; using NUnit.Framework; namespace Nethermind.Blockchain.Test.Data diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs deleted file mode 100644 index b65612e7320..00000000000 --- a/src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs +++ /dev/null @@ -1,274 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using FluentAssertions; -using Nethermind.Blockchain.Filters; -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Core.Test.Builders; -using NUnit.Framework; - -namespace Nethermind.Blockchain.Test.Filters; - -[TestFixture] -public class AddressFilterTests -{ - [Test] - public void Accepts_a_specific_address() - { - AddressFilter filter = new AddressFilter(TestItem.AddressA); - - filter.Accepts(TestItem.AddressA).Should().BeTrue(); - } - - [Test] - public void Accepts_a_specific_address_by_ref() - { - AddressFilter filter = new AddressFilter(TestItem.AddressA); - - AddressStructRef @ref = TestItem.AddressA.ToStructRef(); - filter.Accepts(ref @ref).Should().BeTrue(); - } - - [Test] - public void Rejects_different_address() - { - AddressFilter filter = new AddressFilter(TestItem.AddressA); - - filter.Accepts(TestItem.AddressB).Should().BeFalse(); - } - - [Test] - public void Rejects_different_address_by_ref() - { - AddressFilter filter = new AddressFilter(TestItem.AddressA); - - AddressStructRef addressBRef = TestItem.AddressB.ToStructRef(); - filter.Accepts(ref addressBRef).Should().BeFalse(); - } - - [Test] - public void Accepts_any_address() - { - AddressFilter filter = AddressFilter.AnyAddress; - - filter.Accepts(TestItem.AddressA).Should().BeTrue(); - filter.Accepts(TestItem.AddressB).Should().BeTrue(); - filter.Accepts(TestItem.AddressC).Should().BeTrue(); - } - - [Test] - public void Accepts_any_address_by_ref() - { - AddressFilter filter = AddressFilter.AnyAddress; - - AddressStructRef addressARef = TestItem.AddressA.ToStructRef(); - AddressStructRef addressBRef = TestItem.AddressB.ToStructRef(); - AddressStructRef addressCRef = TestItem.AddressC.ToStructRef(); - filter.Accepts(ref addressARef).Should().BeTrue(); - filter.Accepts(ref addressBRef).Should().BeTrue(); - filter.Accepts(ref addressCRef).Should().BeTrue(); - } - - [Test] - public void Accepts_any_address_when_set_is_empty() - { - HashSet
addresses = new(); - AddressFilter filter = new AddressFilter(addresses); - - filter.Accepts(TestItem.AddressA).Should().BeTrue(); - filter.Accepts(TestItem.AddressB).Should().BeTrue(); - filter.Accepts(TestItem.AddressC).Should().BeTrue(); - } - - [Test] - public void Accepts_any_address_when_set_is_empty_by_ref() - { - HashSet
addresses = new(); - AddressFilter filter = new AddressFilter(addresses); - - AddressStructRef addressARef = TestItem.AddressA.ToStructRef(); - AddressStructRef addressBRef = TestItem.AddressB.ToStructRef(); - AddressStructRef addressCRef = TestItem.AddressC.ToStructRef(); - filter.Accepts(ref addressARef).Should().BeTrue(); - filter.Accepts(ref addressBRef).Should().BeTrue(); - filter.Accepts(ref addressCRef).Should().BeTrue(); - } - - [Test] - public void Accepts_only_addresses_in_a_set() - { - HashSet
addresses = new() - { - TestItem.AddressA, TestItem.AddressC - }; - AddressFilter filter = new AddressFilter(addresses); - - filter.Accepts(TestItem.AddressA).Should().BeTrue(); - filter.Accepts(TestItem.AddressB).Should().BeFalse(); - filter.Accepts(TestItem.AddressC).Should().BeTrue(); - } - - [Test] - public void Accepts_only_addresses_in_a_set_by_ref() - { - HashSet
addresses = new() - { - TestItem.AddressA, TestItem.AddressC - }; - AddressFilter filter = new AddressFilter(addresses); - - AddressStructRef addressARef = TestItem.AddressA.ToStructRef(); - AddressStructRef addressBRef = TestItem.AddressB.ToStructRef(); - AddressStructRef addressCRef = TestItem.AddressC.ToStructRef(); - filter.Accepts(ref addressARef).Should().BeTrue(); - filter.Accepts(ref addressBRef).Should().BeFalse(); - filter.Accepts(ref addressCRef).Should().BeTrue(); - } - - [Test] - public void Matches_bloom_using_specific_address() - { - AddressFilter filter = new AddressFilter(TestItem.AddressA); - Core.Bloom bloom = BloomFromAddress(TestItem.AddressA); - - filter.Matches(bloom).Should().BeTrue(); - } - - [Test] - public void Matches_bloom_using_specific_address_by_ref() - { - AddressFilter filter = new AddressFilter(TestItem.AddressA); - BloomStructRef bloomRef = BloomFromAddress(TestItem.AddressA).ToStructRef(); - - filter.Matches(ref bloomRef).Should().BeTrue(); - } - - [Test] - public void Does_not_match_bloom_using_different_address() - { - AddressFilter filter = new AddressFilter(TestItem.AddressA); - - filter.Matches(BloomFromAddress(TestItem.AddressB)).Should().BeFalse(); - } - - [Test] - public void Does_not_match_bloom_using_different_address_by_ref() - { - AddressFilter filter = new AddressFilter(TestItem.AddressA); - BloomStructRef bloomRef = BloomFromAddress(TestItem.AddressB).ToStructRef(); - - filter.Matches(ref bloomRef).Should().BeFalse(); - } - - [Test] - public void Matches_bloom_using_any_address() - { - AddressFilter filter = AddressFilter.AnyAddress; - - filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue(); - filter.Matches(BloomFromAddress(TestItem.AddressB)).Should().BeTrue(); - filter.Matches(BloomFromAddress(TestItem.AddressC)).Should().BeTrue(); - } - - [Test] - public void Matches_bloom_using_any_address_by_ref() - { - AddressFilter filter = AddressFilter.AnyAddress; - - BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef(); - BloomStructRef bloomBRef = BloomFromAddress(TestItem.AddressB).ToStructRef(); - BloomStructRef bloomCRef = BloomFromAddress(TestItem.AddressC).ToStructRef(); - filter.Matches(ref bloomARef).Should().BeTrue(); - filter.Matches(ref bloomBRef).Should().BeTrue(); - filter.Matches(ref bloomCRef).Should().BeTrue(); - } - - [Test] - public void Matches_any_bloom_when_set_is_empty() - { - HashSet
addresses = new(); - AddressFilter filter = new AddressFilter(addresses); - - filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue(); - filter.Matches(BloomFromAddress(TestItem.AddressB)).Should().BeTrue(); - filter.Matches(BloomFromAddress(TestItem.AddressC)).Should().BeTrue(); - } - - [Test] - public void Matches_any_bloom_when_set_is_empty_by_ref() - { - HashSet
addresses = new(); - AddressFilter filter = new AddressFilter(addresses); - - BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef(); - BloomStructRef bloomBRef = BloomFromAddress(TestItem.AddressB).ToStructRef(); - BloomStructRef bloomCRef = BloomFromAddress(TestItem.AddressC).ToStructRef(); - filter.Matches(ref bloomARef).Should().BeTrue(); - filter.Matches(ref bloomBRef).Should().BeTrue(); - filter.Matches(ref bloomCRef).Should().BeTrue(); - } - - [Test] - public void Matches_any_bloom_when_set_is_forced_null() - { - AddressFilter filter = new AddressFilter(addresses: null!); - - filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue(); - filter.Matches(BloomFromAddress(TestItem.AddressB)).Should().BeTrue(); - filter.Matches(BloomFromAddress(TestItem.AddressC)).Should().BeTrue(); - } - - [Test] - public void Matches_any_bloom_when_set_is_forced_null_by_ref() - { - AddressFilter filter = new AddressFilter(addresses: null!); - - BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef(); - BloomStructRef bloomBRef = BloomFromAddress(TestItem.AddressB).ToStructRef(); - BloomStructRef bloomCRef = BloomFromAddress(TestItem.AddressC).ToStructRef(); - filter.Matches(ref bloomARef).Should().BeTrue(); - filter.Matches(ref bloomBRef).Should().BeTrue(); - filter.Matches(ref bloomCRef).Should().BeTrue(); - } - - [Test] - public void Matches_any_bloom_using_addresses_set() - { - HashSet
addresses = new() - { - TestItem.AddressA, TestItem.AddressC - }; - AddressFilter filter = new AddressFilter(addresses); - - filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue(); - filter.Matches(BloomFromAddress(TestItem.AddressB)).Should().BeFalse(); - filter.Matches(BloomFromAddress(TestItem.AddressC)).Should().BeTrue(); - } - - [Test] - public void Matches_any_bloom_using_addresses_set_by_ref() - { - HashSet
addresses = new() - { - TestItem.AddressA, TestItem.AddressC - }; - AddressFilter filter = new AddressFilter(addresses); - - BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef(); - BloomStructRef bloomBRef = BloomFromAddress(TestItem.AddressB).ToStructRef(); - BloomStructRef bloomCRef = BloomFromAddress(TestItem.AddressC).ToStructRef(); - filter.Matches(ref bloomARef).Should().BeTrue(); - filter.Matches(ref bloomBRef).Should().BeFalse(); - filter.Matches(ref bloomCRef).Should().BeTrue(); - } - - private static Core.Bloom BloomFromAddress(Address address) - { - LogEntry entry = new LogEntry(address, new byte[] { }, new Keccak[] { }); - Core.Bloom bloom = new Core.Bloom(new[] { entry }); - - return bloom; - } -} diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterManagerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterManagerTests.cs index d4b8342142d..59f85aa73fa 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterManagerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterManagerTests.cs @@ -9,7 +9,6 @@ using Nethermind.Blockchain.Test.Builders; using Nethermind.Consensus.Processing; using Nethermind.Core; -using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Facade.Filters; using Nethermind.Logging; @@ -21,12 +20,11 @@ namespace Nethermind.Blockchain.Test.Filters { public class FilterManagerTests { - private IFilterStore _filterStore = null!; - private IBlockProcessor _blockProcessor = null!; - private ITxPool _txPool = null!; - private ILogManager _logManager = null!; - private FilterManager _filterManager = null!; - + private IFilterStore _filterStore; + private IBlockProcessor _blockProcessor; + private ITxPool _txPool; + private ILogManager _logManager; + private FilterManager _filterManager; private int _currentFilterId; [SetUp] @@ -41,36 +39,36 @@ public void Setup() [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_default_filter_parameters() - => LogsShouldNotBeEmpty(_ => { }, _ => { }); + => LogsShouldNotBeEmpty(filter => { }, receipt => { }); [Test, Timeout(Timeout.MaxTestTime)] public void many_logs_should_not_be_empty_for_default_filters_parameters() - => LogsShouldNotBeEmpty(new Action[] { _ => { }, _ => { }, _ => { } }, - new Action[] { _ => { }, _ => { }, _ => { } }); + => LogsShouldNotBeEmpty(new Action[] { filter => { }, filter => { }, filter => { } }, + new Action[] { receipt => { }, receipt => { }, receipt => { } }); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_from_block_earliest_type() - => LogsShouldNotBeEmpty(filter => filter.FromEarliestBlock(), _ => { }); + => LogsShouldNotBeEmpty(filter => filter.FromEarliestBlock(), receipt => { }); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_from_block_pending_type() - => LogsShouldNotBeEmpty(filter => filter.FromPendingBlock(), _ => { }); + => LogsShouldNotBeEmpty(filter => filter.FromPendingBlock(), receipt => { }); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_from_block_latest_type() - => LogsShouldNotBeEmpty(filter => filter.FromLatestBlock(), _ => { }); + => LogsShouldNotBeEmpty(filter => filter.FromLatestBlock(), receipt => { }); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_to_block_earliest_type() - => LogsShouldNotBeEmpty(filter => filter.ToEarliestBlock(), _ => { }); + => LogsShouldNotBeEmpty(filter => filter.ToEarliestBlock(), receipt => { }); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_to_block_pending_type() - => LogsShouldNotBeEmpty(filter => filter.ToPendingBlock(), _ => { }); + => LogsShouldNotBeEmpty(filter => filter.ToPendingBlock(), receipt => { }); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_to_block_latest_type() - => LogsShouldNotBeEmpty(filter => filter.ToLatestBlock(), _ => { }); + => LogsShouldNotBeEmpty(filter => filter.ToLatestBlock(), receipt => { }); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_from_block_number_in_range() @@ -147,60 +145,73 @@ public void logs_should_be_empty_for_from_block_number_not_in_range_and_to_block [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_existing_address() => LogsShouldNotBeEmpty(filter => filter.WithAddress(TestItem.AddressA), - receipt => receipt.WithLogs(Build.A.LogEntry.WithAddress(TestItem.AddressA).TestObject)); + receipt => receipt.WithLogs(new[] { Build.A.LogEntry.WithAddress(TestItem.AddressA).TestObject })); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_be_empty_for_non_existing_address() => LogsShouldBeEmpty(filter => filter.WithAddress(TestItem.AddressA), receipt => receipt - .WithLogs(Build.A.LogEntry.WithAddress(TestItem.AddressB).TestObject)); + .WithLogs(new[] { Build.A.LogEntry.WithAddress(TestItem.AddressB).TestObject })); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_existing_addresses() - => LogsShouldNotBeEmpty(filter => filter.WithAddresses(TestItem.AddressA, TestItem.AddressB), + => LogsShouldNotBeEmpty(filter => filter.WithAddresses(new[] { TestItem.AddressA, TestItem.AddressB }), receipt => receipt - .WithLogs(Build.A.LogEntry.WithAddress(TestItem.AddressB).TestObject)); + .WithLogs(new[] { Build.A.LogEntry.WithAddress(TestItem.AddressB).TestObject })); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_be_empty_for_non_existing_addresses() - => LogsShouldBeEmpty(filter => filter.WithAddresses(TestItem.AddressA, TestItem.AddressB), + => LogsShouldBeEmpty(filter => filter.WithAddresses(new[] { TestItem.AddressA, TestItem.AddressB }), receipt => receipt - .WithLogs(Build.A.LogEntry.WithAddress(TestItem.AddressC).TestObject)); + .WithLogs(new[] { Build.A.LogEntry.WithAddress(TestItem.AddressC).TestObject })); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_existing_specific_topic() => LogsShouldNotBeEmpty(filter => filter .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA)), receipt => receipt - .WithLogs(Build.A.LogEntry.WithTopics(TestItem.KeccakA, TestItem.KeccakB).TestObject)); + .WithLogs(new[] + {Build.A.LogEntry.WithTopics(new[] {TestItem.KeccakA, TestItem.KeccakB}).TestObject})); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_be_empty_for_non_existing_specific_topic() => LogsShouldBeEmpty(filter => filter .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA)), receipt => receipt - .WithLogs(Build.A.LogEntry.WithTopics(TestItem.KeccakB, TestItem.KeccakC).TestObject)); + .WithLogs(new[] + {Build.A.LogEntry.WithTopics(new[] {TestItem.KeccakB, TestItem.KeccakC}).TestObject})); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_existing_any_topic() => LogsShouldNotBeEmpty(filter => filter .WithTopicExpressions(TestTopicExpressions.Any), receipt => receipt - .WithLogs(Build.A.LogEntry.WithTopics(TestItem.KeccakA, TestItem.KeccakB).TestObject)); + .WithLogs(new[] + {Build.A.LogEntry.WithTopics(new[] {TestItem.KeccakA, TestItem.KeccakB}).TestObject})); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_existing_or_topic() => LogsShouldNotBeEmpty(filter => filter - .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakD))), + .WithTopicExpressions(TestTopicExpressions.Or(new[] + { + TestTopicExpressions.Specific(TestItem.KeccakB), + TestTopicExpressions.Specific(TestItem.KeccakD) + })), receipt => receipt - .WithLogs(Build.A.LogEntry.WithTopics(TestItem.KeccakB, TestItem.KeccakC).TestObject)); + .WithLogs(new[] + {Build.A.LogEntry.WithTopics(new[] {TestItem.KeccakB, TestItem.KeccakC}).TestObject})); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_be_empty_for_non_existing_or_topic() => LogsShouldBeEmpty(filter => filter - .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Specific(TestItem.KeccakD))), + .WithTopicExpressions(TestTopicExpressions.Or(new[] + { + TestTopicExpressions.Specific(TestItem.KeccakA), + TestTopicExpressions.Specific(TestItem.KeccakD) + })), receipt => receipt - .WithLogs(Build.A.LogEntry.WithTopics(TestItem.KeccakB, TestItem.KeccakC).TestObject)); + .WithLogs(new[] + {Build.A.LogEntry.WithTopics(new[] {TestItem.KeccakB, TestItem.KeccakC}).TestObject})); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_existing_block_and_address_and_topics() @@ -208,35 +219,56 @@ public void logs_should_not_be_empty_for_existing_block_and_address_and_topics() .FromBlock(1L) .ToBlock(10L) .WithAddress(TestItem.AddressA) - .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakD))), + .WithTopicExpressions(TestTopicExpressions.Or(new[] + { + TestTopicExpressions.Specific(TestItem.KeccakB), + TestTopicExpressions.Specific(TestItem.KeccakD) + })), receipt => receipt .WithBlockNumber(6L) - .WithLogs(Build.A.LogEntry.WithAddress(TestItem.AddressA) - .WithTopics(TestItem.KeccakB, TestItem.KeccakC).TestObject)); + .WithLogs(new[] + { + Build.A.LogEntry.WithAddress(TestItem.AddressA) + .WithTopics(new[] {TestItem.KeccakB, TestItem.KeccakC}).TestObject + })); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_existing_block_and_addresses_and_topics() => LogsShouldNotBeEmpty(filter => filter .FromBlock(1L) .ToBlock(10L) - .WithAddresses(TestItem.AddressA, TestItem.AddressB) - .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakD))), + .WithAddresses(new[] { TestItem.AddressA, TestItem.AddressB }) + .WithTopicExpressions(TestTopicExpressions.Or(new[] + { + TestTopicExpressions.Specific(TestItem.KeccakB), + TestTopicExpressions.Specific(TestItem.KeccakD) + })), receipt => receipt .WithBlockNumber(6L) - .WithLogs(Build.A.LogEntry.WithAddress(TestItem.AddressA) - .WithTopics(TestItem.KeccakB, TestItem.KeccakC).TestObject)); + .WithLogs(new[] + { + Build.A.LogEntry.WithAddress(TestItem.AddressA) + .WithTopics(new[] {TestItem.KeccakB, TestItem.KeccakC}).TestObject + })); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_be_empty_for_existing_block_and_addresses_and_non_existing_topic() => LogsShouldBeEmpty(filter => filter .FromBlock(1L) .ToBlock(10L) - .WithAddresses(TestItem.AddressA, TestItem.AddressB) - .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakC), TestTopicExpressions.Specific(TestItem.KeccakD))), + .WithAddresses(new[] { TestItem.AddressA, TestItem.AddressB }) + .WithTopicExpressions(TestTopicExpressions.Or(new[] + { + TestTopicExpressions.Specific(TestItem.KeccakC), + TestTopicExpressions.Specific(TestItem.KeccakD) + })), receipt => receipt .WithBlockNumber(6L) - .WithLogs(Build.A.LogEntry.WithAddress(TestItem.AddressA) - .WithTopics(TestItem.KeccakB, TestItem.KeccakC).TestObject)); + .WithLogs(new[] + { + Build.A.LogEntry.WithAddress(TestItem.AddressA) + .WithTopics(new[] {TestItem.KeccakB, TestItem.KeccakC}).TestObject + })); private void LogsShouldNotBeEmpty(Action filterBuilder, @@ -259,14 +291,14 @@ private void Assert(IEnumerable> filterBuilders, IEnumerable> receiptBuilders, Action> logsAssertion) { - List filters = new List(); - List receipts = new List(); - foreach (Action filterBuilder in filterBuilders) + var filters = new List(); + var receipts = new List(); + foreach (var filterBuilder in filterBuilders) { filters.Add(BuildFilter(filterBuilder)); } - foreach (Action receiptBuilder in receiptBuilders) + foreach (var receiptBuilder in receiptBuilders) { receipts.Add(BuildReceipt(receiptBuilder)); } @@ -282,8 +314,8 @@ private void Assert(IEnumerable> filterBuilders, _blockProcessor.BlockProcessed += Raise.EventWith(_blockProcessor, new BlockProcessedEventArgs(block, Array.Empty())); - int index = 1; - foreach (TxReceipt receipt in receipts) + var index = 1; + foreach (var receipt in receipts) { _blockProcessor.TransactionProcessed += Raise.EventWith(_blockProcessor, new TxProcessedEventArgs(index, Build.A.Transaction.TestObject, receipt)); @@ -292,20 +324,20 @@ private void Assert(IEnumerable> filterBuilders, NUnit.Framework.Assert.Multiple(() => { - foreach (LogFilter filter in filters.OfType()) + foreach (var filter in filters.OfType()) { - FilterLog[] logs = _filterManager.GetLogs(filter.Id); + var logs = _filterManager.GetLogs(filter.Id); logsAssertion(logs); } - Keccak[] hashes = _filterManager.GetBlocksHashes(blockFilter.Id); + var hashes = _filterManager.GetBlocksHashes(blockFilter.Id); NUnit.Framework.Assert.That(hashes.Length, Is.EqualTo(1)); }); } private LogFilter BuildFilter(Action builder) { - FilterBuilder builderInstance = FilterBuilder.New(ref _currentFilterId); + var builderInstance = FilterBuilder.New(ref _currentFilterId); builder(builderInstance); return builderInstance.Build(); @@ -313,7 +345,7 @@ private LogFilter BuildFilter(Action builder) private static TxReceipt BuildReceipt(Action builder) { - ReceiptBuilder builderInstance = new(); + var builderInstance = new ReceiptBuilder(); builder(builderInstance); return builderInstance.TestObject; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Filters/LogFilterTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Filters/LogFilterTests.cs index d8248aed918..8d016bf3f44 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Filters/LogFilterTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Filters/LogFilterTests.cs @@ -3,7 +3,6 @@ using System; using FluentAssertions; -using Nethermind.Blockchain.Filters; using Nethermind.Blockchain.Test.Builders; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -19,8 +18,8 @@ public class LogFilterTests [Test, Timeout(Timeout.MaxTestTime)] public void any_address_filter_matches_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) - .WithAnyAddress() + var filter = FilterBuilder.New(ref _filterCounter) + .WithAddress(null) .Build(); filter.Matches(Core.Bloom.Empty).Should().BeTrue(); @@ -29,11 +28,11 @@ public void any_address_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void address_filter_matches_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithAddress(TestItem.AddressA) .Build(); - Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressA)); + var bloom = GetBloom(GetLogEntry(TestItem.AddressA)); filter.Matches(bloom).Should().BeTrue(); } @@ -41,11 +40,11 @@ public void address_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void addresses_filter_matches_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithAddresses(TestItem.AddressA, TestItem.AddressB, TestItem.AddressC) .Build(); - Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressB)); + var bloom = GetBloom(GetLogEntry(TestItem.AddressB)); filter.Matches(bloom).Should().BeTrue(); } @@ -53,7 +52,7 @@ public void addresses_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void any_topics_filter_matches_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Any) .Build(); @@ -63,11 +62,11 @@ public void any_topics_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void specific_topics_filter_matches_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA)) .Build(); - Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakA, TestItem.KeccakB)); + var bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakA, TestItem.KeccakB)); filter.Matches(bloom).Should().BeTrue(); } @@ -75,11 +74,11 @@ public void specific_topics_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void multiple_specific_topics_filter_matches_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Specific(TestItem.KeccakB)) .Build(); - Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakA, TestItem.KeccakB)); + var bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakA, TestItem.KeccakB)); filter.Matches(bloom).Should().BeTrue(); } @@ -87,11 +86,11 @@ public void multiple_specific_topics_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void or_topics_filter_matches_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakA))) .Build(); - Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakB)); + var bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakB)); filter.Matches(bloom).Should().BeTrue(); } @@ -99,11 +98,11 @@ public void or_topics_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void complex_topics_filter_matches_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakA))) .Build(); - Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakA)); + var bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakA)); filter.Matches(bloom).Should().BeTrue(); } @@ -111,12 +110,12 @@ public void complex_topics_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void complex_filter_matches_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakC))) .WithAddress(TestItem.AddressD) .Build(); - Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressD, TestItem.KeccakA, TestItem.KeccakC)); + var bloom = GetBloom(GetLogEntry(TestItem.AddressD, TestItem.KeccakA, TestItem.KeccakC)); filter.Matches(bloom).Should().BeTrue(); } @@ -124,11 +123,11 @@ public void complex_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void address_filter_doesnt_match_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithAddress(TestItem.AddressA) .Build(); - Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressD), GetLogEntry(TestItem.AddressC)); + var bloom = GetBloom(GetLogEntry(TestItem.AddressD), GetLogEntry(TestItem.AddressC)); filter.Matches(bloom).Should().BeFalse(); } @@ -136,11 +135,11 @@ public void address_filter_doesnt_match_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void addresses_filter_doesnt_match_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithAddresses(TestItem.AddressA, TestItem.AddressB, TestItem.AddressC) .Build(); - Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressD)); + var bloom = GetBloom(GetLogEntry(TestItem.AddressD)); filter.Matches(bloom).Should().BeFalse(); } @@ -148,11 +147,11 @@ public void addresses_filter_doesnt_match_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void specific_topics_filter_doesnt_match_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Specific(TestItem.KeccakC)) .Build(); - Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakA, TestItem.KeccakB)); + var bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakA, TestItem.KeccakB)); filter.Matches(bloom).Should().BeFalse(); } @@ -160,11 +159,11 @@ public void specific_topics_filter_doesnt_match_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void multiple_specific_topics_filter_doesnt_match_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Specific(TestItem.KeccakB)) .Build(); - Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakC)); + var bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakC)); filter.Matches(bloom).Should().BeFalse(); } @@ -172,11 +171,11 @@ public void multiple_specific_topics_filter_doesnt_match_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void or_topics_filter_doesnt_match_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakA))) .Build(); - Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakC)); + var bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakC)); filter.Matches(bloom).Should().BeFalse(); } @@ -184,11 +183,11 @@ public void or_topics_filter_doesnt_match_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void complex_topics_filter_doesnt_match_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakA))) .Build(); - Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakC)); + var bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakC)); filter.Matches(bloom).Should().BeFalse(); } @@ -196,19 +195,19 @@ public void complex_topics_filter_doesnt_match_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void complex_filter_doesnt_match_bloom() { - LogFilter filter = FilterBuilder.New(ref _filterCounter) + var filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakC))) .WithAddress(TestItem.AddressD) .Build(); - Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakA, TestItem.KeccakD)); + var bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakA, TestItem.KeccakD)); filter.Matches(bloom).Should().BeFalse(); } private Core.Bloom GetBloom(params LogEntry[] logEntries) { - Core.Bloom bloom = new Core.Bloom(); + var bloom = new Core.Bloom(); bloom.Add(logEntries); return bloom; } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Find/LogFinderTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Find/LogFinderTests.cs index 76edfd90ec5..d559d77c2f1 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Find/LogFinderTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Find/LogFinderTests.cs @@ -14,6 +14,7 @@ using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Test.Builders; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Db; @@ -344,9 +345,9 @@ private void StoreTreeBlooms(bool withBloomDb) { if (withBloomDb) { - for (int i = 0; i <= _blockTree.Head!.Number; i++) + for (int i = 0; i <= _blockTree.Head.Number; i++) { - _bloomStorage.Store(i, _blockTree.FindHeader(i)!.Bloom!); + _bloomStorage.Store(i, _blockTree.FindHeader(i).Bloom); } } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/CopyTreeVisitorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/CopyTreeVisitorTests.cs index 7150f0fbabb..233dcb34040 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/CopyTreeVisitorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/CopyTreeVisitorTests.cs @@ -41,7 +41,7 @@ public void copies_state_between_dbs(int fullPruningMemoryBudgetMb, int maxDegre }; IPruningContext ctx = StartPruning(trieDb, clonedDb); - CopyDb(ctx, trieDb, visitingOptions, writeFlags: WriteFlags.LowPriority); + CopyDb(ctx, trieDb, clonedDb, visitingOptions, writeFlags: WriteFlags.LowPriority); List keys = trieDb.Keys.ToList(); List values = trieDb.Values.ToList(); @@ -61,16 +61,16 @@ public async Task cancel_coping_state_between_dbs() MemDb trieDb = new(); MemDb clonedDb = new(); IPruningContext pruningContext = StartPruning(trieDb, clonedDb); - Task task = Task.Run(() => CopyDb(pruningContext, trieDb)); + Task task = Task.Run(() => CopyDb(pruningContext, trieDb, clonedDb)); - pruningContext.CancellationTokenSource.Cancel(); + pruningContext?.CancellationTokenSource.Cancel(); await task; clonedDb.Count.Should().BeLessThan(trieDb.Count); } - private static IPruningContext CopyDb(IPruningContext pruningContext, MemDb trieDb, VisitingOptions? visitingOptions = null, WriteFlags writeFlags = WriteFlags.None) + private static IPruningContext CopyDb(IPruningContext pruningContext, MemDb trieDb, MemDb clonedDb, VisitingOptions visitingOptions = null, WriteFlags writeFlags = WriteFlags.None) { LimboLogs logManager = LimboLogs.Instance; PatriciaTree trie = Build.A.Trie(trieDb).WithAccountsByIndex(0, 100).TestObject; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/DiskFreeSpacePruningTriggerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/DiskFreeSpacePruningTriggerTests.cs index 9f7ea261aa7..d9234b6488a 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/DiskFreeSpacePruningTriggerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/DiskFreeSpacePruningTriggerTests.cs @@ -3,6 +3,8 @@ using System; using System.IO.Abstractions; +using FluentAssertions; +using MathGmp.Native; using Nethermind.Blockchain.FullPruning; using Nethermind.Core.Timers; using NSubstitute; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs index 999a0c9030f..c5af5c5c360 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using FluentAssertions; +using FluentAssertions.Extensions; using Nethermind.Blockchain.FullPruning; using Nethermind.Config; using Nethermind.Core; @@ -33,10 +34,10 @@ public class FullPruningDiskTest { public class PruningTestBlockchain : TestBlockchain { - public IFullPruningDb PruningDb { get; private set; } = null!; + public IFullPruningDb PruningDb { get; private set; } public TempPath TempDirectory { get; } public IPruningTrigger PruningTrigger { get; } = Substitute.For(); - public FullTestPruner FullPruner { get; private set; } = null!; + public FullTestPruner FullPruner { get; private set; } public IPruningConfig PruningConfig { get; set; } = new PruningConfig(); public IDriveInfo DriveInfo { get; set; } = Substitute.For(); public IChainEstimations _chainEstimations = Substitute.For(); @@ -47,9 +48,9 @@ public PruningTestBlockchain() TempDirectory = TempPath.GetTempDirectory(); } - protected override async Task Build(ISpecProvider? specProvider = null, UInt256? initialValues = null, bool addBlockOnStart = true) + protected override async Task Build(ISpecProvider? specProvider = null, UInt256? initialValues = null) { - TestBlockchain chain = await base.Build(specProvider, initialValues, addBlockOnStart); + TestBlockchain chain = await base.Build(specProvider, initialValues); PruningDb = (IFullPruningDb)DbProvider.StateDb; DriveInfo.AvailableFreeSpace.Returns(long.MaxValue); _chainEstimations.StateSize.Returns((long?)null); @@ -74,7 +75,7 @@ public override void Dispose() protected override Task AddBlocksOnStart() => Task.CompletedTask; - public static async Task Create(IPruningConfig? pruningConfig = null) + public static async Task Create(IPruningConfig pruningConfig = null) { PruningTestBlockchain chain = new() { PruningConfig = pruningConfig ?? new PruningConfig() }; await chain.Build(); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/GenesisLoaderTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/GenesisLoaderTests.cs index cc21249528e..ba0a26b1d87 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/GenesisLoaderTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/GenesisLoaderTests.cs @@ -3,6 +3,7 @@ using System.IO; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Db; using Nethermind.Evm.TransactionProcessing; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/KnownChainSizesTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/KnownChainSizesTests.cs index 980713cdae0..9e353b8c63b 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/KnownChainSizesTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/KnownChainSizesTests.cs @@ -14,9 +14,9 @@ public class KnownChainSizesTests public void Update_known_chain_sizes() { // Pruning size have to be updated frequently - ChainSizes.CreateChainSizeInfo(BlockchainIds.Mainnet).PruningSize.Should().BeLessThan(210.GB()); - ChainSizes.CreateChainSizeInfo(BlockchainIds.Goerli).PruningSize.Should().BeLessThan(90.GB()); - ChainSizes.CreateChainSizeInfo(BlockchainIds.Sepolia).PruningSize.Should().BeLessThan(11.GB()); + ChainSizes.CreateChainSizeInfo(BlockchainIds.Mainnet).PruningSize.Should().BeLessThan(200.GB()); + ChainSizes.CreateChainSizeInfo(BlockchainIds.Goerli).PruningSize.Should().BeLessThan(55.GB()); + ChainSizes.CreateChainSizeInfo(BlockchainIds.Sepolia).PruningSize.Should().BeLessThan(8.GB()); ChainSizes.CreateChainSizeInfo(BlockchainIds.Chiado).PruningSize.Should().Be(null); ChainSizes.CreateChainSizeInfo(BlockchainIds.Gnosis).PruningSize.Should().Be(null); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Nethermind.Blockchain.Test.csproj b/src/Nethermind/Nethermind.Blockchain.Test/Nethermind.Blockchain.Test.csproj index 71c02ad2856..e9b719ed235 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Nethermind.Blockchain.Test.csproj +++ b/src/Nethermind/Nethermind.Blockchain.Test/Nethermind.Blockchain.Test.csproj @@ -4,7 +4,9 @@ false latest enable - true + + + diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs index 4e66e5bd708..530b5c3b15d 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs @@ -6,11 +6,14 @@ using System.Threading.Tasks; using Nethermind.Abi; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Evm; using Nethermind.Int256; using Nethermind.JsonRpc.Test.Modules; +using Nethermind.Logging; using Nethermind.Specs; using Nethermind.TxPool; using NUnit.Framework; @@ -21,22 +24,20 @@ public partial class BlockProducerBaseTests { public static class BadContract { - public static AbiSignature Divide { get; } = new("divide"); // divide + public static readonly AbiSignature Divide = new("divide"); // divide } public static partial class BaseFeeTestScenario { public partial class ScenarioBuilder { - private readonly Address _address = TestItem.Addresses[0]; - private readonly IAbiEncoder _abiEncoder = new AbiEncoder(); - - private Address _contractAddress = null!; - private TestRpcBlockchain _testRpcBlockchain = null!; - + private Address _address = TestItem.Addresses[0]; + private Address _contractAddress; + private IAbiEncoder _abiEncoder = new AbiEncoder(); private long _eip1559TransitionBlock; private bool _eip1559Enabled; - private Task? _antecedent; + private TestRpcBlockchain _testRpcBlockchain; + private Task _antecedent; private UInt256 _currentNonce = 1; public ScenarioBuilder WithEip1559TransitionBlock(long transitionBlock) @@ -83,14 +84,12 @@ private async Task DeployContractAsync() await ExecuteAntecedentIfNeeded(); _contractAddress = ContractAddress.From(_address, 0L); byte[] bytecode = await GetContractBytecode("BadContract"); - Transaction tx = new() - { - Value = 0, - Data = bytecode, - GasLimit = 1000000, - GasPrice = 20.GWei(), - SenderAddress = _address, - }; + Transaction tx = new(); + tx.Value = 0; + tx.Data = bytecode; + tx.GasLimit = 1000000; + tx.GasPrice = 20.GWei(); + tx.SenderAddress = _address; await _testRpcBlockchain.TxSender.SendTransaction(tx, TxHandlingOptions.ManagedNonce | TxHandlingOptions.PersistentBroadcast); return this; } @@ -158,13 +157,13 @@ private async Task BlocksBeforeTransitionShouldHaveZeroBaseFeeA { await ExecuteAntecedentIfNeeded(); IBlockTree blockTree = _testRpcBlockchain.BlockTree; - Block startingBlock = blockTree.Head!; - Assert.That(startingBlock.Header.BaseFeePerGas, Is.EqualTo(UInt256.Zero)); + Block startingBlock = blockTree.Head; + Assert.That(startingBlock!.Header.BaseFeePerGas, Is.EqualTo(UInt256.Zero)); for (long i = startingBlock.Number; i < _eip1559TransitionBlock - 1; ++i) { await _testRpcBlockchain.AddBlock(); - Block currentBlock = blockTree.Head!; - Assert.That(currentBlock.Header.BaseFeePerGas, Is.EqualTo(UInt256.Zero)); + Block currentBlock = blockTree.Head; + Assert.That(currentBlock!.Header.BaseFeePerGas, Is.EqualTo(UInt256.Zero)); } return this; @@ -176,8 +175,8 @@ private async Task AssertNewBlockAsync(UInt256 expectedBaseFee, await ExecuteAntecedentIfNeeded(); await _testRpcBlockchain.AddBlock(transactions); IBlockTree blockTree = _testRpcBlockchain.BlockTree; - Block headBlock = blockTree.Head!; - Assert.That(headBlock.Header.BaseFeePerGas, Is.EqualTo(expectedBaseFee)); + Block headBlock = blockTree.Head; + Assert.That(headBlock!.Header.BaseFeePerGas, Is.EqualTo(expectedBaseFee)); return this; } @@ -187,10 +186,10 @@ private async Task AssertNewBlockWithDecreasedBaseFeeAsync() await ExecuteAntecedentIfNeeded(); IBlockTree blockTree = _testRpcBlockchain.BlockTree; - Block startingBlock = blockTree.Head!; + Block startingBlock = blockTree.Head; await _testRpcBlockchain.AddBlock(); - Block newBlock = blockTree.Head!; - Assert.Less(newBlock.Header.BaseFeePerGas, startingBlock.Header.BaseFeePerGas); + Block newBlock = blockTree.Head; + Assert.Less(newBlock!.Header.BaseFeePerGas, startingBlock!.Header.BaseFeePerGas); return this; } @@ -200,10 +199,10 @@ private async Task AssertNewBlockWithIncreasedBaseFeeAsync() await ExecuteAntecedentIfNeeded(); IBlockTree blockTree = _testRpcBlockchain.BlockTree; - Block startingBlock = blockTree.Head!; + Block startingBlock = blockTree.Head; await _testRpcBlockchain.AddBlock(); - Block newBlock = blockTree.Head!; - Assert.Less(startingBlock.Header.BaseFeePerGas, newBlock.Header.BaseFeePerGas); + Block newBlock = blockTree.Head; + Assert.Less(startingBlock!.Header.BaseFeePerGas, newBlock!.Header.BaseFeePerGas); return this; } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.FeeCollector.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.FeeCollector.cs index acd93014c43..742d3644a36 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.FeeCollector.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.FeeCollector.cs @@ -17,7 +17,7 @@ public static partial class BaseFeeTestScenario { public partial class ScenarioBuilder { - private Address _eip1559FeeCollector = null!; + private Address _eip1559FeeCollector; public ScenarioBuilder WithEip1559FeeCollector(Address address) { @@ -34,6 +34,10 @@ public ScenarioBuilder AssertNewBlockFeeCollected(UInt256 expectedFeeCollected, private async Task AssertNewBlockFeeCollectedAsync(UInt256 expectedFeeCollected, params Transaction[] transactions) { await ExecuteAntecedentIfNeeded(); + if (_eip1559FeeCollector is null) + { + Assert.Fail($"{nameof(IReleaseSpec.Eip1559FeeCollector)} not set"); + } UInt256 balanceBefore = _testRpcBlockchain.State.GetBalance(_eip1559FeeCollector); await _testRpcBlockchain.AddBlock(transactions); UInt256 balanceAfter = _testRpcBlockchain.State.GetBalance(_eip1559FeeCollector); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.IsProducingBlocks.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.IsProducingBlocks.cs index 49e67f7c50b..bf98d79c258 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.IsProducingBlocks.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.IsProducingBlocks.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Security; using System.Threading; using System.Threading.Tasks; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlockRegularlyTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlockRegularlyTests.cs index cde66f555c0..76e38d26e03 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlockRegularlyTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlockRegularlyTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Threading; using System.Threading.Tasks; using FluentAssertions; using Nethermind.Consensus.Producers; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlocksOnlyWhenNotProcessingTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlocksOnlyWhenNotProcessingTests.cs index a3574121765..eb6707f5f68 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlocksOnlyWhenNotProcessingTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlocksOnlyWhenNotProcessingTests.cs @@ -23,7 +23,7 @@ public async Task should_trigger_block_production_on_empty_queue() { Context context = new(); context.BlockProcessingQueue.IsEmpty.Returns(true); - Block block = (await context.MainBlockProductionTrigger.BuildBlock())!; + Block block = await context.MainBlockProductionTrigger.BuildBlock(); block.Should().Be(context.DefaultBlock); context.TriggeredCount.Should().Be(1); } @@ -50,7 +50,7 @@ public async Task should_cancel_triggering_block_production() Context context = new(); context.BlockProcessingQueue.IsEmpty.Returns(false); using CancellationTokenSource cancellationTokenSource = new(); - Task buildTask = context.MainBlockProductionTrigger.BuildBlock(cancellationToken: cancellationTokenSource.Token); + Task buildTask = context.MainBlockProductionTrigger.BuildBlock(cancellationToken: cancellationTokenSource.Token); await Task.Delay(BuildBlocksOnlyWhenNotProcessing.ChainNotYetProcessedMillisecondsDelay * 2); buildTask.IsCanceled.Should().BeFalse(); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlocksWhenRequestedTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlocksWhenRequestedTests.cs index 86d96c4271e..df95537b464 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlocksWhenRequestedTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlocksWhenRequestedTests.cs @@ -3,6 +3,7 @@ using FluentAssertions; using Nethermind.Consensus.Producers; +using Nethermind.Core.Test.Builders; using NUnit.Framework; namespace Nethermind.Blockchain.Test.Producers diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/CompositeBlockProductionTriggerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/CompositeBlockProductionTriggerTests.cs index 969708c8f6a..efc0c4db6dd 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/CompositeBlockProductionTriggerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/CompositeBlockProductionTriggerTests.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Threading; using FluentAssertions; using Nethermind.Consensus.Producers; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs index d4167162e52..c8de8362917 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs @@ -10,6 +10,7 @@ using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Transactions; using Nethermind.Consensus.Validators; +using Nethermind.Consensus.Withdrawals; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; @@ -98,18 +99,18 @@ public void Test() blockchainProcessor.Start(); devBlockProducer.Start(); - ProducedBlockSuggester _ = new ProducedBlockSuggester(blockTree, devBlockProducer); + ProducedBlockSuggester suggester = new ProducedBlockSuggester(blockTree, devBlockProducer); AutoResetEvent autoResetEvent = new(false); - blockTree.NewHeadBlock += (_, _) => autoResetEvent.Set(); + blockTree.NewHeadBlock += (s, e) => autoResetEvent.Set(); blockTree.SuggestBlock(Build.A.Block.Genesis.TestObject); autoResetEvent.WaitOne(1000).Should().BeTrue("genesis"); trigger.BuildBlock(); autoResetEvent.WaitOne(1000).Should().BeTrue("1"); - blockTree.Head!.Number.Should().Be(1); + blockTree.Head.Number.Should().Be(1); } } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/IfPoolIsNotEmptyTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/IfPoolIsNotEmptyTests.cs index 1b01f73280b..7f39e272b18 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/IfPoolIsNotEmptyTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/IfPoolIsNotEmptyTests.cs @@ -3,6 +3,7 @@ using FluentAssertions; using Nethermind.Consensus.Producers; +using Nethermind.Core; using Nethermind.TxPool; using NSubstitute; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Proofs/ReceiptTrieTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Proofs/ReceiptTrieTests.cs index d43496eb342..ec52da837d3 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Proofs/ReceiptTrieTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Proofs/ReceiptTrieTests.cs @@ -11,8 +11,6 @@ using Nethermind.Specs; using Nethermind.State.Proofs; using Nethermind.Trie; -using Nethermind.Trie.Pruning; -using NSubstitute; using NUnit.Framework; namespace Nethermind.Blockchain.Test.Proofs @@ -23,16 +21,16 @@ public class ReceiptTrieTests public void Can_calculate_root_no_eip_658() { TxReceipt receipt = Build.A.Receipt.WithAllFieldsFilled.TestObject; - Keccak rootHash = ReceiptTrie.CalculateRoot(MainnetSpecProvider.Instance.GetSpec((1, null)), new[] { receipt }); - Assert.That(rootHash.ToString(), Is.EqualTo("0xe51a2d9f986d68628990c9d65e45c36128ec7bb697bd426b0bb4d18a3f3321be")); + ReceiptTrie receiptTrie = new(MainnetSpecProvider.Instance.GetSpec((1, null)), new[] { receipt }); + Assert.That(receiptTrie.RootHash.ToString(), Is.EqualTo("0xe51a2d9f986d68628990c9d65e45c36128ec7bb697bd426b0bb4d18a3f3321be")); } [Test, Timeout(Timeout.MaxTestTime)] public void Can_calculate_root() { TxReceipt receipt = Build.A.Receipt.WithAllFieldsFilled.TestObject; - Keccak rootHash = ReceiptTrie.CalculateRoot(MainnetSpecProvider.Instance.GetSpec((MainnetSpecProvider.MuirGlacierBlockNumber, null)), new[] { receipt }); - Assert.That(rootHash.ToString(), Is.EqualTo("0x2e6d89c5b539e72409f2e587730643986c2ef33db5e817a4223aa1bb996476d5")); + ReceiptTrie receiptTrie = new(MainnetSpecProvider.Instance.GetSpec((MainnetSpecProvider.MuirGlacierBlockNumber, null)), new[] { receipt }); + Assert.That(receiptTrie.RootHash.ToString(), Is.EqualTo("0x2e6d89c5b539e72409f2e587730643986c2ef33db5e817a4223aa1bb996476d5")); } [Test, Timeout(Timeout.MaxTestTime)] @@ -51,7 +49,7 @@ public void Can_collect_proof_with_branch() private static void VerifyProof(byte[][] proof, Keccak receiptRoot) { TrieNode node = new(NodeType.Unknown, proof.Last()); - node.ResolveNode(Substitute.For()); + node.ResolveNode(null); TxReceipt receipt = new ReceiptMessageDecoder().Decode(node.Value.AsRlpStream()); Assert.NotNull(receipt.Bloom); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Proofs/TxTrieTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Proofs/TxTrieTests.cs index 25b0788b6a5..fe25d8075ef 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Proofs/TxTrieTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Proofs/TxTrieTests.cs @@ -29,15 +29,15 @@ public TxTrieTests(bool useEip2718) public void Can_calculate_root() { Block block = Build.A.Block.WithTransactions(Build.A.Transaction.TestObject).TestObject; - Keccak rootHash = TxTrie.CalculateRoot(block.Transactions); + TxTrie txTrie = new(block.Transactions); if (_releaseSpec == Berlin.Instance) { - Assert.That(rootHash.ToString(), Is.EqualTo("0x29cc403075ed3d1d6af940d577125cc378ee5a26f7746cbaf87f1cf4a38258b5")); + Assert.That(txTrie.RootHash.ToString(), Is.EqualTo("0x29cc403075ed3d1d6af940d577125cc378ee5a26f7746cbaf87f1cf4a38258b5")); } else { - Assert.That(rootHash.ToString(), Is.EqualTo("0x29cc403075ed3d1d6af940d577125cc378ee5a26f7746cbaf87f1cf4a38258b5")); + Assert.That(txTrie.RootHash.ToString(), Is.EqualTo("0x29cc403075ed3d1d6af940d577125cc378ee5a26f7746cbaf87f1cf4a38258b5")); } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/ReadOnlyBlockTreeTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/ReadOnlyBlockTreeTests.cs index 11188208105..8a537419d0e 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/ReadOnlyBlockTreeTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/ReadOnlyBlockTreeTests.cs @@ -11,8 +11,8 @@ namespace Nethermind.Blockchain.Test { public class ReadOnlyBlockTreeTests { - private IBlockTree _innerBlockTree = null!; - private ReadOnlyBlockTree _blockTree = null!; + private IBlockTree _innerBlockTree; + private ReadOnlyBlockTree _blockTree; [SetUp] public void SetUp() diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs index 991a0f577dc..998784411b6 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using System.Linq; using System.Threading; using FluentAssertions; @@ -19,7 +18,6 @@ using Nethermind.Serialization.Rlp; using Nethermind.Specs; using NSubstitute; -using NSubstitute.Core; using NUnit.Framework; namespace Nethermind.Blockchain.Test.Receipts @@ -30,13 +28,13 @@ namespace Nethermind.Blockchain.Test.Receipts public class PersistentReceiptStorageTests { private TestMemColumnsDb _receiptsDb = null!; - private ReceiptsRecovery _receiptsRecovery = null!; - private IBlockTree _blockTree = null!; - private IBlockStore _blockStore = null!; + private ReceiptsRecovery _receiptsRecovery; + private IBlockTree _blockTree; + private IBlockStore _blockStore; private readonly bool _useCompactReceipts; - private ReceiptConfig _receiptConfig = null!; - private PersistentReceiptStorage _storage = null!; - private ReceiptArrayStorageDecoder _decoder = null!; + private ReceiptConfig _receiptConfig; + private PersistentReceiptStorage _storage; + private ReceiptArrayStorageDecoder _decoder; public PersistentReceiptStorageTests(bool useCompactReceipts) { @@ -46,7 +44,7 @@ public PersistentReceiptStorageTests(bool useCompactReceipts) [SetUp] public void SetUp() { - MainnetSpecProvider specProvider = MainnetSpecProvider.Instance; + RopstenSpecProvider specProvider = RopstenSpecProvider.Instance; EthereumEcdsa ethereumEcdsa = new(specProvider.ChainId, LimboLogs.Instance); _receiptConfig = new ReceiptConfig(); _receiptsRecovery = new(ethereumEcdsa, specProvider); @@ -82,7 +80,7 @@ public void Returns_null_for_missing_tx() [Test, Timeout(Timeout.MaxTestTime)] public void ReceiptsIterator_doesnt_throw_on_empty_span() { - _storage.TryGetReceiptsIterator(1, Keccak.Zero, out ReceiptsIterator iterator); + _storage.TryGetReceiptsIterator(1, Keccak.Zero, out var iterator); iterator.TryGetNext(out _).Should().BeFalse(); } @@ -90,7 +88,7 @@ public void ReceiptsIterator_doesnt_throw_on_empty_span() public void ReceiptsIterator_doesnt_throw_on_null() { _receiptsDb.GetColumnDb(ReceiptsColumns.Blocks).Set(Keccak.Zero, null!); - _storage.TryGetReceiptsIterator(1, Keccak.Zero, out ReceiptsIterator iterator); + _storage.TryGetReceiptsIterator(1, Keccak.Zero, out var iterator); iterator.TryGetNext(out _).Should().BeFalse(); } @@ -113,7 +111,7 @@ public void Adds_and_retrieves_receipts_for_block() [Test] public void Adds_should_prefix_key_with_blockNumber() { - (Block block, _) = InsertBlock(); + var (block, receipts) = InsertBlock(); Span blockNumPrefixed = stackalloc byte[40]; block.Number.ToBigEndianByteArray().CopyTo(blockNumPrefixed); // TODO: We don't need to create an array here... @@ -125,10 +123,10 @@ public void Adds_should_prefix_key_with_blockNumber() [Test] public void Adds_should_attempt_hash_key_first_if_inserted_with_hashkey() { - (Block block, TxReceipt[] receipts) = PrepareBlock(); + var (block, receipts) = PrepareBlock(); using NettyRlpStream rlpStream = _decoder.EncodeToNewNettyStream(receipts, RlpBehaviors.Storage); - _receiptsDb.GetColumnDb(ReceiptsColumns.Blocks)[block.Hash!.Bytes] = rlpStream.AsSpan().ToArray(); + _receiptsDb.GetColumnDb(ReceiptsColumns.Blocks)[block.Hash.Bytes] = rlpStream.AsSpan().ToArray(); CreateStorage(); _storage.Get(block); @@ -138,14 +136,14 @@ public void Adds_should_attempt_hash_key_first_if_inserted_with_hashkey() block.Hash!.Bytes.CopyTo(blockNumPrefixed[8..]); TestMemDb blocksDb = (TestMemDb)_receiptsDb.GetColumnDb(ReceiptsColumns.Blocks); - blocksDb.KeyWasRead(blockNumPrefixed.ToArray(), times: 0); - blocksDb.KeyWasRead(block.Hash.BytesToArray(), times: 1); + blocksDb.KeyWasRead(blockNumPrefixed.ToArray(), 0); + blocksDb.KeyWasRead(block.Hash.BytesToArray(), 1); } [Test] public void Should_be_able_to_get_block_with_hash_address() { - (Block block, TxReceipt[] receipts) = PrepareBlock(); + var (block, receipts) = PrepareBlock(); Span blockNumPrefixed = stackalloc byte[40]; block.Number.ToBigEndianByteArray().CopyTo(blockNumPrefixed); // TODO: We don't need to create an array here... @@ -160,16 +158,16 @@ public void Should_be_able_to_get_block_with_hash_address() [Test, Timeout(Timeout.MaxTestTime)] public void Should_not_cache_empty_non_processed_blocks() { - Block block = Build.A.Block + var block = Build.A.Block .WithTransactions(Build.A.Transaction.SignedAndResolved().TestObject) .WithReceiptsRoot(TestItem.KeccakA) .TestObject; - TxReceipt[] emptyReceipts = Array.Empty(); + var emptyReceipts = Array.Empty(); _storage.Get(block).Should().BeEquivalentTo(emptyReceipts); // can be from cache: _storage.Get(block).Should().BeEquivalentTo(emptyReceipts); - (_, TxReceipt[] receipts) = InsertBlock(block); + var (_, receipts) = InsertBlock(block); // before should not be cached _storage.Get(block).Should().BeEquivalentTo(receipts); } @@ -180,7 +178,7 @@ public void Adds_and_retrieves_receipts_for_block_with_iterator_from_cache_after var (block, receipts) = InsertBlock(); _storage.TryGetReceiptsIterator(0, block.Hash!, out ReceiptsIterator iterator).Should().BeTrue(); - iterator.TryGetNext(out TxReceiptStructRef receiptStructRef).Should().BeTrue(); + iterator.TryGetNext(out var receiptStructRef).Should().BeTrue(); receiptStructRef.LogsRlp.ToArray().Should().BeEmpty(); receiptStructRef.Logs.Should().BeEquivalentTo(receipts.First().Logs); iterator.TryGetNext(out receiptStructRef).Should().BeFalse(); @@ -264,17 +262,16 @@ public void EnsureCanonical_should_change_tx_blockhash( } [Test] - public void EnsureCanonical_should_use_blockNumber_if_finalized() + public void EnsureCanonical_should_use_blocknumber_if_finalized() { (Block block, TxReceipt[] receipts) = InsertBlock(isFinalized: true); - Span txHashBytes = receipts[0].TxHash!.Bytes; if (_receiptConfig.CompactTxIndex) { - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[txHashBytes].Should().BeEquivalentTo(Rlp.Encode(block.Number).Bytes); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().BeEquivalentTo(Rlp.Encode(block.Number).Bytes); } else { - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[txHashBytes].Should().NotBeNull(); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().NotBeNull(); } } @@ -286,10 +283,11 @@ public void When_TxLookupLimitIs_NegativeOne_DoNotIndexTxHash() (Block block, TxReceipt[] receipts) = InsertBlock(isFinalized: true); _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(block)); Thread.Sleep(100); - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes].Should().BeNull(); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().BeNull(); } [Test] + [Ignore("Needs to be fixed, details https://github.com/NethermindEth/nethermind/pull/5621")] public void Should_not_index_tx_hash_if_blockNumber_is_negative() { _receiptConfig.TxLookupLimit = 10; @@ -297,7 +295,7 @@ public void Should_not_index_tx_hash_if_blockNumber_is_negative() _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(Build.A.Block.WithNumber(1).TestObject)); Thread.Sleep(100); - IEnumerable calls = _blockTree.ReceivedCalls() + var calls = _blockTree.ReceivedCalls() .Where(call => !call.GetMethodInfo().Name.EndsWith(nameof(_blockTree.BlockAddedToMain))); calls.Should().BeEmpty(); } @@ -310,7 +308,7 @@ public void When_HeadBlockIsFarAhead_DoNotIndexTxHash() (Block block, TxReceipt[] receipts) = InsertBlock(isFinalized: true, headNumber: 1001); _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(block)); Thread.Sleep(100); - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes].Should().BeNull(); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().BeNull(); } [Test] @@ -321,11 +319,11 @@ public void When_NewHeadBlock_Remove_TxIndex_OfRemovedBlock() if (_receiptConfig.CompactTxIndex) { - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes].Should().BeEquivalentTo(Rlp.Encode(block.Number).Bytes); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().BeEquivalentTo(Rlp.Encode(block.Number).Bytes); } else { - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes].Should().NotBeNull(); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().NotBeNull(); } Block newHead = Build.A.Block.WithNumber(1).TestObject; @@ -333,7 +331,7 @@ public void When_NewHeadBlock_Remove_TxIndex_OfRemovedBlock() _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(newHead, block)); Assert.That( - () => _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes], + () => _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes], Is.Null.After(1000, 100) ); } @@ -345,14 +343,13 @@ public void When_NewHeadBlock_ClearOldTxIndex() CreateStorage(); (Block block, TxReceipt[] receipts) = InsertBlock(); - Span txHashBytes = receipts[0].TxHash!.Bytes; if (_receiptConfig.CompactTxIndex) { - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[txHashBytes].Should().BeEquivalentTo(Rlp.Encode(block.Number).Bytes); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().BeEquivalentTo(Rlp.Encode(block.Number).Bytes); } else { - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[txHashBytes].Should().NotBeNull(); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().NotBeNull(); } Block newHead = Build.A.Block.WithNumber(_receiptConfig.TxLookupLimit.Value + 1).TestObject; @@ -360,7 +357,7 @@ public void When_NewHeadBlock_ClearOldTxIndex() _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(newHead)); Assert.That( - () => _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes], + () => _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes], Is.Null.After(1000, 100) ); } @@ -373,7 +370,7 @@ public void When_NewHeadBlock_ClearOldTxIndex() .WithReceiptsRoot(TestItem.KeccakA) .TestObject; - _blockTree.FindBlock(block.Hash!).Returns(block); + _blockTree.FindBlock(block.Hash).Returns(block); _blockTree.FindBlock(block.Number).Returns(block); _blockTree.FindHeader(block.Number).Returns(block.Header); _blockTree.FindBlockHash(block.Number).Returns(block.Hash); @@ -392,7 +389,7 @@ public void When_NewHeadBlock_ClearOldTxIndex() .TestObject; _blockTree.FindBestSuggestedHeader().Returns(farHead); } - TxReceipt[] receipts = { Build.A.Receipt.WithCalculatedBloom().TestObject }; + var receipts = new[] { Build.A.Receipt.WithCalculatedBloom().TestObject }; return (block, receipts); } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsIteratorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsIteratorTests.cs index 6201e017336..1c30fb07ee7 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsIteratorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsIteratorTests.cs @@ -38,15 +38,15 @@ public void SmokeTestWithRecovery() iterator.TryGetNext(out TxReceiptStructRef receipt).Should().BeTrue(); iterator.RecoverIfNeeded(ref receipt); receipt.Sender.Bytes.ToArray().Should().BeEquivalentTo(TestItem.AddressA.Bytes); - receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[0].Hash!.BytesToArray()); + receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[0].Hash.BytesToArray()); iterator.TryGetNext(out receipt).Should().BeTrue(); iterator.RecoverIfNeeded(ref receipt); receipt.Sender.Bytes.ToArray().Should().BeEquivalentTo(TestItem.AddressB.Bytes); - receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[1].Hash!.BytesToArray()); + receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[1].Hash.BytesToArray()); iterator.TryGetNext(out receipt).Should().BeTrue(); iterator.RecoverIfNeeded(ref receipt); receipt.Sender.Bytes.ToArray().Should().BeEquivalentTo(TestItem.AddressC.Bytes); - receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[1].Hash!.BytesToArray()); + receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[1].Hash.BytesToArray()); } [Test] @@ -56,7 +56,7 @@ public void SmokeTestWithDelayedRecovery() .Block .WithTransactions(3, MainnetSpecProvider.Instance) .TestObject; - TxReceipt[] receipts = + TxReceipt[] receipts = new[] { Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressA).TestObject, Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressB).TestObject, @@ -74,7 +74,7 @@ public void SmokeTestWithDelayedRecovery() iterator.TryGetNext(out receipt).Should().BeTrue(); iterator.RecoverIfNeeded(ref receipt); receipt.Sender.Bytes.ToArray().Should().BeEquivalentTo(TestItem.AddressC.Bytes); - receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[1].Hash!.BytesToArray()); + receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[1].Hash.BytesToArray()); } [Test] @@ -84,7 +84,7 @@ public void SmokeTest() .Block .WithTransactions(3, MainnetSpecProvider.Instance) .TestObject; - TxReceipt[] receipts = + TxReceipt[] receipts = new[] { Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressA).TestObject, Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressB).TestObject, diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsRecoveryTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsRecoveryTests.cs index fbf4bf4cde7..a178d702653 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsRecoveryTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsRecoveryTests.cs @@ -14,12 +14,12 @@ namespace Nethermind.Blockchain.Test.Receipts; public class ReceiptsRecoveryTests { - private IReceiptsRecovery _receiptsRecovery = null!; + private IReceiptsRecovery _receiptsRecovery; [SetUp] public void Setup() { - MainnetSpecProvider specProvider = MainnetSpecProvider.Instance; + RopstenSpecProvider specProvider = RopstenSpecProvider.Instance; EthereumEcdsa ethereumEcdsa = new(specProvider.ChainId, LimboLogs.Instance); _receiptsRecovery = new ReceiptsRecovery(ethereumEcdsa, specProvider); @@ -51,20 +51,4 @@ public void TryRecover_should_return_correct_receipts_recovery_result(int blockT _receiptsRecovery.TryRecover(block, receipts, forceRecoverSender).Should().Be(expected); } - - [Test] - public void TryRecover_should_recover_contract_address() - { - Transaction tx = Build.A.Transaction.WithSenderAddress(null).WithTo(null).Signed().TestObject; - Block block = Build.A.Block.WithTransactions(tx).TestObject; - TxReceipt receipt = Build.A.Receipt.WithBlockHash(block.Hash!).TestObject; - - tx.SenderAddress.Should().BeNull(); - receipt.ContractAddress.Should().BeNull(); - - ReceiptsRecoveryResult result = _receiptsRecovery.TryRecover(block, new[] { receipt }); - - result.Should().Be(ReceiptsRecoveryResult.NeedReinsert); - receipt.ContractAddress.Should().Be(new Address("0x3a6e7897affdf344781bb9098a605e9839ac131b")); - } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsRootTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsRootTests.cs index 16476bda031..68724b00c0c 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsRootTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsRootTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections; +using System.Collections.Generic; using Nethermind.Blockchain.Receipts; using Nethermind.Core; using Nethermind.Core.Crypto; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs index fc8005305ee..8795add9d9c 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs @@ -2,13 +2,16 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using System.Threading; using FluentAssertions; using Nethermind.Blockchain.Receipts; +using Nethermind.Blockchain.Spec; using Nethermind.Blockchain.Synchronization; using Nethermind.Consensus.Comparers; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; +using Nethermind.Consensus.Withdrawals; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; @@ -16,6 +19,7 @@ using Nethermind.Db; using Nethermind.Db.Blooms; using Nethermind.Evm; +using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; using Nethermind.Specs; @@ -24,6 +28,7 @@ using Nethermind.State.Witnesses; using Nethermind.Trie.Pruning; using Nethermind.TxPool; +using NSubstitute; using NUnit.Framework; namespace Nethermind.Blockchain.Test @@ -31,8 +36,8 @@ namespace Nethermind.Blockchain.Test [TestFixture] public class ReorgTests { - private BlockchainProcessor _blockchainProcessor = null!; - private BlockTree _blockTree = null!; + private BlockchainProcessor _blockchainProcessor; + private BlockTree _blockTree; [SetUp] public void Setup() @@ -123,8 +128,8 @@ public void Test() Assert.That(() => _blockTree.Head, Is.EqualTo(block2B).After(10000, 500)); events.Should().HaveCount(6); - events[4].Hash.Should().Be(block1B.Hash!); - events[5].Hash.Should().Be(block2B.Hash!); + events[4].Hash.Should().Be(block1B.Hash); + events[5].Hash.Should().Be(block2B.Hash); } } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Rewards/RewardCalculatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Rewards/RewardCalculatorTests.cs index 041676676af..a1a2db6ad87 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Rewards/RewardCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Rewards/RewardCalculatorTests.cs @@ -3,6 +3,7 @@ using Nethermind.Consensus.Rewards; using Nethermind.Core; +using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Specs; using NUnit.Framework; @@ -18,7 +19,7 @@ public void Two_uncles_from_the_same_coinbase() Block uncle2 = Build.A.Block.WithNumber(1).TestObject; Block block = Build.A.Block.WithNumber(3).WithUncles(uncle, uncle2).TestObject; - RewardCalculator calculator = new(MainnetSpecProvider.Instance); + RewardCalculator calculator = new(RopstenSpecProvider.Instance); BlockReward[] rewards = calculator.CalculateRewards(block); Assert.That(rewards.Length, Is.EqualTo(3)); @@ -33,7 +34,7 @@ public void One_uncle() Block uncle = Build.A.Block.WithNumber(1).TestObject; Block block = Build.A.Block.WithNumber(3).WithUncles(uncle).TestObject; - RewardCalculator calculator = new(MainnetSpecProvider.Instance); + RewardCalculator calculator = new(RopstenSpecProvider.Instance); BlockReward[] rewards = calculator.CalculateRewards(block); Assert.That(rewards.Length, Is.EqualTo(2)); @@ -46,7 +47,7 @@ public void No_uncles() { Block block = Build.A.Block.WithNumber(3).TestObject; - RewardCalculator calculator = new(MainnetSpecProvider.Instance); + RewardCalculator calculator = new(RopstenSpecProvider.Instance); BlockReward[] rewards = calculator.CalculateRewards(block); Assert.That(rewards.Length, Is.EqualTo(1)); @@ -56,12 +57,12 @@ public void No_uncles() [Test, Timeout(Timeout.MaxTestTime)] public void Byzantium_reward_two_uncles() { - long blockNumber = MainnetSpecProvider.ByzantiumBlockNumber; + long blockNumber = RopstenSpecProvider.ByzantiumBlockNumber; Block uncle = Build.A.Block.WithNumber(blockNumber - 2).TestObject; Block uncle2 = Build.A.Block.WithNumber(blockNumber - 2).TestObject; Block block = Build.A.Block.WithNumber(blockNumber).WithUncles(uncle, uncle2).TestObject; - RewardCalculator calculator = new(MainnetSpecProvider.Instance); + RewardCalculator calculator = new(RopstenSpecProvider.Instance); BlockReward[] rewards = calculator.CalculateRewards(block); Assert.That(rewards.Length, Is.EqualTo(3)); @@ -73,12 +74,12 @@ public void Byzantium_reward_two_uncles() [Test, Timeout(Timeout.MaxTestTime)] public void Constantinople_reward_two_uncles() { - long blockNumber = MainnetSpecProvider.ConstantinopleFixBlockNumber; + long blockNumber = RopstenSpecProvider.ConstantinopleBlockNumber; Block uncle = Build.A.Block.WithNumber(blockNumber - 2).TestObject; Block uncle2 = Build.A.Block.WithNumber(blockNumber - 2).TestObject; Block block = Build.A.Block.WithNumber(blockNumber).WithUncles(uncle, uncle2).TestObject; - RewardCalculator calculator = new(MainnetSpecProvider.Instance); + RewardCalculator calculator = new(RopstenSpecProvider.Instance); BlockReward[] rewards = calculator.CalculateRewards(block); Assert.That(rewards.Length, Is.EqualTo(3)); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Services/HealthHintServiceTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Services/HealthHintServiceTests.cs index e9c3ecc2280..4099cb06d41 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Services/HealthHintServiceTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Services/HealthHintServiceTests.cs @@ -25,9 +25,11 @@ public void GetBlockProcessorAndProducerIntervalHint_returns_expected_result( public class BlockProcessorIntervalHint { - public required ChainSpec ChainSpec { get; init; } - public ulong? ExpectedProcessingHint { get; init; } - public ulong? ExpectedProducingHint { get => null; } + public ChainSpec ChainSpec { get; set; } + + public ulong? ExpectedProcessingHint { get; set; } + + public ulong? ExpectedProducingHint { get; set; } public override string ToString() => $"SealEngineType: {ChainSpec.SealEngineType}, ExpectedProcessingHint: {ExpectedProcessingHint}, ExpectedProducingHint: {ExpectedProducingHint}"; @@ -37,22 +39,22 @@ public static IEnumerable BlockProcessorIntervalHint { get { - yield return new BlockProcessorIntervalHint + yield return new BlockProcessorIntervalHint() { - ChainSpec = new ChainSpec { SealEngineType = SealEngineType.NethDev, } + ChainSpec = new ChainSpec() { SealEngineType = SealEngineType.NethDev, } }; - yield return new BlockProcessorIntervalHint + yield return new BlockProcessorIntervalHint() { - ChainSpec = new ChainSpec { SealEngineType = SealEngineType.Ethash }, + ChainSpec = new ChainSpec() { SealEngineType = SealEngineType.Ethash }, ExpectedProcessingHint = 180 }; - yield return new BlockProcessorIntervalHint + yield return new BlockProcessorIntervalHint() { - ChainSpec = new ChainSpec { SealEngineType = "Interval" } + ChainSpec = new ChainSpec() { SealEngineType = "Interval" } }; - yield return new BlockProcessorIntervalHint + yield return new BlockProcessorIntervalHint() { - ChainSpec = new ChainSpec { SealEngineType = SealEngineType.None } + ChainSpec = new ChainSpec() { SealEngineType = SealEngineType.None } }; } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionGasPriceComparisonTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionGasPriceComparisonTests.cs index 60e373f4445..2df0346d299 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionGasPriceComparisonTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionGasPriceComparisonTests.cs @@ -9,6 +9,7 @@ using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Int256; +using Nethermind.Logging; using Nethermind.Specs; using NSubstitute; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs index 5281b0a37ce..a734d5ca1bb 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs @@ -23,6 +23,7 @@ using NSubstitute; using NUnit.Framework; using Nethermind.Config; +using Nethermind.Core.Crypto; namespace Nethermind.Blockchain.Test { @@ -150,37 +151,29 @@ public static IEnumerable EnoughShardBlobTransactionsSelectedTestCases { get { - ProperTransactionsSelectedTestCase maxTransactionsSelected = ProperTransactionsSelectedTestCase.Eip1559Default; - maxTransactionsSelected.ReleaseSpec = Cancun.Instance; - maxTransactionsSelected.BaseFee = 1; + ProperTransactionsSelectedTestCase maxTransactionsSelected = ProperTransactionsSelectedTestCase.Default; maxTransactionsSelected.Transactions.ForEach(tx => { tx.Type = TxType.Blob; tx.BlobVersionedHashes = new byte[1][]; - tx.MaxFeePerBlobGas = 1; }); maxTransactionsSelected.Transactions[1].BlobVersionedHashes = - new byte[Eip4844Constants.MaxBlobGasPerTransaction / Eip4844Constants.BlobGasPerBlob - 1][]; + new byte[Eip4844Constants.MaxDataGasPerTransaction / Eip4844Constants.DataGasPerBlob - 1][]; maxTransactionsSelected.ExpectedSelectedTransactions.AddRange( maxTransactionsSelected.Transactions.OrderBy(t => t.Nonce).Take(2)); yield return new TestCaseData(maxTransactionsSelected).SetName("Enough transactions selected"); ProperTransactionsSelectedTestCase enoughTransactionsSelected = - ProperTransactionsSelectedTestCase.Eip1559Default; - enoughTransactionsSelected.ReleaseSpec = Cancun.Instance; - enoughTransactionsSelected.BaseFee = 1; - + ProperTransactionsSelectedTestCase.Default; Transaction[] expectedSelectedTransactions = enoughTransactionsSelected.Transactions.OrderBy(t => t.Nonce).ToArray(); expectedSelectedTransactions[0].Type = TxType.Blob; expectedSelectedTransactions[0].BlobVersionedHashes = - new byte[Eip4844Constants.MaxBlobGasPerTransaction / Eip4844Constants.BlobGasPerBlob][]; - expectedSelectedTransactions[0].MaxFeePerBlobGas = 1; + new byte[Eip4844Constants.MaxDataGasPerTransaction / Eip4844Constants.DataGasPerBlob][]; expectedSelectedTransactions[1].Type = TxType.Blob; expectedSelectedTransactions[1].BlobVersionedHashes = new byte[1][]; - expectedSelectedTransactions[1].MaxFeePerBlobGas = 1; enoughTransactionsSelected.ExpectedSelectedTransactions.AddRange( - expectedSelectedTransactions.Where((_, index) => index != 1)); + expectedSelectedTransactions.Where((tx, index) => index != 1)); yield return new TestCaseData(enoughTransactionsSelected).SetName( "Enough shard blob transactions and others selected"); } @@ -196,7 +189,8 @@ public void Proper_transactions_selected(ProperTransactionsSelectedTestCase test MemDb codeDb = new(); TrieStore trieStore = new(stateDb, LimboLogs.Instance); WorldState stateProvider = new(trieStore, codeDb, LimboLogs.Instance); - StateReader _ = new(new TrieStore(stateDb, LimboLogs.Instance), codeDb, LimboLogs.Instance); + StateReader stateReader = + new(new TrieStore(stateDb, LimboLogs.Instance), codeDb, LimboLogs.Instance); ISpecProvider specProvider = Substitute.For(); void SetAccountStates(IEnumerable
missingAddresses) @@ -230,7 +224,7 @@ void SetAccountStates(IEnumerable
missingAddresses) IComparer defaultComparer = transactionComparerProvider.GetDefaultComparer(); IComparer comparer = CompareTxByNonce.Instance.ThenBy(defaultComparer); Dictionary transactions = testCase.Transactions - .Where(t => t.SenderAddress is not null) + .Where(t => t?.SenderAddress is not null) .GroupBy(t => t.SenderAddress) .ToDictionary( g => g.Key!, @@ -247,13 +241,9 @@ void SetAccountStates(IEnumerable
missingAddresses) TxPoolTxSource poolTxSource = new(transactionPool, specProvider, transactionComparerProvider, LimboLogs.Instance, txFilterPipeline); - BlockHeaderBuilder parentHeader = Build.A.BlockHeader.WithStateRoot(stateProvider.StateRoot).WithBaseFee(testCase.BaseFee); - if (spec.IsEip4844Enabled) - { - parentHeader = parentHeader.WithExcessBlobGas(0); - } + IEnumerable selectedTransactions = - poolTxSource.GetTransactions(parentHeader.TestObject, + poolTxSource.GetTransactions(Build.A.BlockHeader.WithStateRoot(stateProvider.StateRoot).WithBaseFee(testCase.BaseFee).TestObject, testCase.GasLimit); selectedTransactions.Should() .BeEquivalentTo(testCase.ExpectedSelectedTransactions, o => o.WithStrictOrdering()); @@ -269,7 +259,7 @@ public class ProperTransactionsSelectedTestCase public List ExpectedSelectedTransactions { get; } = new(); public UInt256 MinGasPriceForMining { get; set; } = 1; - public required IReleaseSpec ReleaseSpec { get; set; } + public IReleaseSpec ReleaseSpec { get; set; } public UInt256 BaseFee { get; set; } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionsExecutorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionsExecutorTests.cs index f43d92ead95..65c6d055cca 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionsExecutorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionsExecutorTests.cs @@ -4,7 +4,9 @@ using System.Collections; using System.Collections.Generic; using System.Linq; +using Castle.Components.DictionaryAdapter; using FluentAssertions; +using Nethermind.Config; using Nethermind.Consensus.Comparers; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Producers; @@ -19,6 +21,7 @@ using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; using Nethermind.Logging; +using Nethermind.Specs; using Nethermind.Specs.Forks; using Nethermind.State; using Nethermind.Trie.Pruning; @@ -271,7 +274,7 @@ public void Proper_transactions_selected(TransactionSelectorTests.ProperTransact specProvider.GetSpec(Arg.Any()).Returns(spec); ITransactionProcessor transactionProcessor = Substitute.For(); - transactionProcessor.When(t => t.BuildUp(Arg.Any(), Arg.Any(), Arg.Any())) + transactionProcessor.When(t => t.BuildUp(Arg.Any(), Arg.Any(), Arg.Any())) .Do(info => { Transaction tx = info.Arg(); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/HeaderValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/HeaderValidatorTests.cs index 8021996cf6b..6ea033cfdc6 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/HeaderValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/HeaderValidatorTests.cs @@ -16,6 +16,7 @@ using Nethermind.Db.Blooms; using Nethermind.Int256; using Nethermind.Logging; +using Nethermind.Merge.Plugin; using Nethermind.Specs; using Nethermind.Specs.Forks; using Nethermind.Specs.Test; @@ -28,13 +29,13 @@ namespace Nethermind.Blockchain.Test.Validators [TestFixture] public class HeaderValidatorTests { - private IHeaderValidator _validator = null!; - private ISealValidator _ethash = null!; - private TestLogger _testLogger = null!; - private Block _parentBlock = null!; - private Block _block = null!; - private IBlockTree _blockTree = null!; - private ISpecProvider _specProvider = null!; + private IHeaderValidator _validator; + private ISealValidator _ethash; + private TestLogger _testLogger; + private Block _parentBlock; + private Block _block; + private IBlockTree _blockTree; + private ISpecProvider _specProvider; [SetUp] public void Setup() diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs index 815f1aa0413..ad361daadea 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using Nethermind.Blockchain.Find; using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Specs; @@ -17,15 +18,15 @@ namespace Nethermind.Blockchain.Test.Validators; public class ShardBlobBlockValidatorTests { - [TestCaseSource(nameof(BlobGasFieldsPerForkTestCases))] - public static bool Blob_gas_fields_should_be_set(IReleaseSpec spec, ulong? blobGasUsed, ulong? excessBlobGas) + [TestCaseSource(nameof(DataGasFieldsPerForkTestCases))] + public static bool Data_gas_fields_should_be_set(IReleaseSpec spec, ulong? dataGasUsed, ulong? excessDataGas) { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, spec)); HeaderValidator headerValidator = new(Substitute.For(), Always.Valid, specProvider, TestLogManager.Instance); BlockValidator blockValidator = new(Always.Valid, headerValidator, Always.Valid, specProvider, TestLogManager.Instance); return blockValidator.ValidateSuggestedBlock(Build.A.Block - .WithBlobGasUsed(blobGasUsed) - .WithExcessBlobGas(excessBlobGas) + .WithDataGasUsed(dataGasUsed) + .WithExcessDataGas(excessDataGas) .WithWithdrawalsRoot(TestItem.KeccakA) .WithWithdrawals(TestItem.WithdrawalA_1Eth) .WithParent(Build.A.BlockHeader.TestObject) @@ -33,10 +34,10 @@ public static bool Blob_gas_fields_should_be_set(IReleaseSpec spec, ulong? blobG } [TestCase(0ul, ExpectedResult = true)] - [TestCase(Eip4844Constants.MaxBlobGasPerBlock - Eip4844Constants.BlobGasPerBlob, ExpectedResult = true)] - [TestCase(Eip4844Constants.MaxBlobGasPerBlock, ExpectedResult = true)] - [TestCase(Eip4844Constants.MaxBlobGasPerBlock + Eip4844Constants.BlobGasPerBlob, ExpectedResult = false)] - public bool Blobs_per_block_count_is_valid(ulong blobGasUsed) + [TestCase(Eip4844Constants.MaxDataGasPerBlock - Eip4844Constants.DataGasPerBlob, ExpectedResult = true)] + [TestCase(Eip4844Constants.MaxDataGasPerBlock, ExpectedResult = true)] + [TestCase(Eip4844Constants.MaxDataGasPerBlock + Eip4844Constants.DataGasPerBlob, ExpectedResult = false)] + public bool Blobs_per_block_count_is_valid(ulong dataGasUsed) { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Cancun.Instance)); BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, TestLogManager.Instance); @@ -44,59 +45,59 @@ public bool Blobs_per_block_count_is_valid(ulong blobGasUsed) Build.A.Block .WithWithdrawalsRoot(TestItem.KeccakA) .WithWithdrawals(TestItem.WithdrawalA_1Eth) - .WithBlobGasUsed(blobGasUsed) - .WithExcessBlobGas(0) - .WithTransactions(Enumerable.Range(0, (int)(blobGasUsed / Eip4844Constants.BlobGasPerBlob)) + .WithDataGasUsed(dataGasUsed) + .WithExcessDataGas(0) + .WithTransactions(Enumerable.Range(0, (int)(dataGasUsed / Eip4844Constants.DataGasPerBlob)) .Select(i => Build.A.Transaction.WithType(TxType.Blob) - .WithMaxFeePerBlobGas(ulong.MaxValue) + .WithMaxFeePerDataGas(ulong.MaxValue) .WithBlobVersionedHashes(1).TestObject).ToArray()) .TestObject); } - public static IEnumerable BlobGasFieldsPerForkTestCases + public static IEnumerable DataGasFieldsPerForkTestCases { get { yield return new TestCaseData(Shanghai.Instance, null, null) { - TestName = "Blob gas fields are not set pre-Cancun", + TestName = "Data gas fields are not set pre-Cancun", ExpectedResult = true }; yield return new TestCaseData(Shanghai.Instance, 0ul, null) { - TestName = "BlobGasUsed is set pre-Cancun", + TestName = "DataGasUsed is set pre-Cancun", ExpectedResult = false }; yield return new TestCaseData(Shanghai.Instance, null, 0ul) { - TestName = "ExcessBlobGas is set pre-Cancun", + TestName = "ExcessDataGas is set pre-Cancun", ExpectedResult = false }; yield return new TestCaseData(Shanghai.Instance, 0ul, 0ul) { - TestName = "Blob gas fields are set pre-Cancun", + TestName = "Data gas fields are set pre-Cancun", ExpectedResult = false }; yield return new TestCaseData(Cancun.Instance, null, null) { - TestName = "Blob gas fields are not set post-Cancun", + TestName = "Data gas fields are not set post-Cancun", ExpectedResult = false }; yield return new TestCaseData(Cancun.Instance, 0ul, null) { - TestName = "Just BlobGasUsed is set post-Cancun", + TestName = "Just DataGasUsed is set post-Cancun", ExpectedResult = false }; yield return new TestCaseData(Cancun.Instance, null, 0ul) { - TestName = "Just ExcessBlobGas is set post-Cancun", + TestName = "Just ExcessDataGas is set post-Cancun", ExpectedResult = false }; yield return new TestCaseData(Cancun.Instance, 0ul, 0ul) { - TestName = "Blob gas fields are set post-Cancun", + TestName = "Data gas fields are set post-Cancun", ExpectedResult = true }; } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TestBlockValidator.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TestBlockValidator.cs index 6edc6277341..11b632192f7 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TestBlockValidator.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TestBlockValidator.cs @@ -55,10 +55,4 @@ public bool ValidateWithdrawals(Block block, out string? error) return _alwaysSameResultForSuggested ?? _suggestedValidationResults.Dequeue(); } - - public bool ValidateOrphanedBlock(Block block, out string? error) - { - error = null; - return _alwaysSameResultForSuggested ?? _suggestedValidationResults.Dequeue(); - } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TestSealValidator.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TestSealValidator.cs new file mode 100644 index 00000000000..77f496bafef --- /dev/null +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TestSealValidator.cs @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Generic; +using Nethermind.Consensus; +using Nethermind.Consensus.Validators; +using Nethermind.Core; + +namespace Nethermind.Blockchain.Test.Validators +{ + // ReSharper disable once ClassNeverInstantiated.Global + public class TestSealValidator : ISealValidator + { + public static ISealValidator AlwaysValid = Always.Valid; + public static ISealValidator NeverValid = Always.Invalid; + + private readonly Queue _processedValidationResults; + private readonly Queue _suggestedValidationResults; + private bool? _alwaysSameResultForSeal; + private bool? _alwaysSameResultForParams; + + public TestSealValidator(bool validateParamsResult, bool validateSealResult) + { + _alwaysSameResultForParams = validateParamsResult; + _alwaysSameResultForSeal = validateSealResult; + } + + public TestSealValidator(Queue suggestedValidationResults, Queue processedValidationResults) + { + _suggestedValidationResults = suggestedValidationResults ?? throw new ArgumentNullException(nameof(suggestedValidationResults)); + _processedValidationResults = processedValidationResults ?? throw new ArgumentNullException(nameof(processedValidationResults)); + } + + public bool ValidateParams(BlockHeader parent, BlockHeader header, bool isUncle) + { + return _alwaysSameResultForParams ?? _suggestedValidationResults.Dequeue(); + } + + public bool ValidateSeal(BlockHeader header, bool force) + { + return _alwaysSameResultForSeal ?? _processedValidationResults.Dequeue(); + } + } +} diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs index e952d079701..59dca3b99a3 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs @@ -154,7 +154,7 @@ public bool Before_eip_2930_has_to_be_legacy_tx(TxType txType, bool eip2930) .WithType(txType > TxType.AccessList ? TxType.Legacy : txType) .WithChainId(TestBlockchainIds.ChainId) .WithAccessList(txType == TxType.AccessList - ? AccessList.Empty() + ? new AccessList(new Dictionary>()) : null) .WithSignature(signature).TestObject; @@ -185,7 +185,7 @@ public bool Before_eip_1559_has_to_be_legacy_or_access_list_tx(TxType txType, bo .WithMaxPriorityFeePerGas(txType == TxType.EIP1559 ? 10.GWei() : 5.GWei()) .WithMaxFeePerGas(txType == TxType.EIP1559 ? 10.GWei() : 5.GWei()) .WithAccessList(txType == TxType.AccessList || txType == TxType.EIP1559 - ? AccessList.Empty() + ? new AccessList(new Dictionary>()) : null) .WithSignature(signature).TestObject; @@ -210,7 +210,7 @@ public bool Chain_Id_required_for_non_legacy_transactions_after_Berlin(TxType tx Transaction tx = Build.A.Transaction .WithType(txType > TxType.AccessList ? TxType.Legacy : txType) .WithAccessList(txType == TxType.AccessList - ? AccessList.Empty() + ? new AccessList(new Dictionary>()) : null) .WithSignature(signature).TestObject; @@ -240,7 +240,7 @@ public bool MaxFeePerGas_is_required_to_be_greater_than_MaxPriorityFeePerGas(TxT .WithMaxPriorityFeePerGas((UInt256)maxPriorityFeePerGas) .WithMaxFeePerGas((UInt256)maxFeePerGas) .WithAccessList(txType == TxType.AccessList - ? AccessList.Empty() + ? new AccessList(new Dictionary>()) : null) .WithChainId(TestBlockchainIds.ChainId) .WithSignature(signature).TestObject; @@ -331,7 +331,7 @@ public void ShardBlobTransactions_should_have_destination_set() .WithTimestamp(ulong.MaxValue) .WithTo(null) .WithMaxFeePerGas(1) - .WithMaxFeePerBlobGas(1) + .WithMaxFeePerDataGas(1) .WithBlobVersionedHashes(1) .WithChainId(TestBlockchainIds.ChainId) .SignedAndResolved().TestObject; @@ -341,7 +341,7 @@ public void ShardBlobTransactions_should_have_destination_set() .WithTimestamp(ulong.MaxValue) .WithTo(TestItem.AddressA) .WithMaxFeePerGas(1) - .WithMaxFeePerBlobGas(1) + .WithMaxFeePerDataGas(1) .WithBlobVersionedHashes(1) .WithChainId(TestBlockchainIds.ChainId) .SignedAndResolved().TestObject; @@ -354,13 +354,13 @@ public void ShardBlobTransactions_should_have_destination_set() [TestCase(TxType.EIP1559, false, ExpectedResult = true)] [TestCase(TxType.EIP1559, true, ExpectedResult = false)] [TestCase(TxType.Blob, true, ExpectedResult = true)] - public bool MaxFeePerBlobGas_should_be_set_for_blob_tx_only(TxType txType, bool isMaxFeePerBlobGasSet) + public bool MaxFeePerDataGas_should_be_set_for_blob_tx_only(TxType txType, bool isMaxFeePerDataGasSet) { TransactionBuilder txBuilder = Build.A.Transaction .WithType(txType) .WithTimestamp(ulong.MaxValue) .WithMaxFeePerGas(1) - .WithMaxFeePerBlobGas(isMaxFeePerBlobGasSet ? 1 : null) + .WithMaxFeePerDataGas(isMaxFeePerDataGasSet ? 1 : null) .WithBlobVersionedHashes(txType == TxType.Blob ? Eip4844Constants.MinBlobsPerTransaction : null) .WithChainId(TestBlockchainIds.ChainId) .SignedAndResolved(); @@ -379,7 +379,7 @@ public bool BlobVersionedHash_should_be_correct(byte[] hash) .WithType(TxType.Blob) .WithTimestamp(ulong.MaxValue) .WithMaxFeePerGas(1) - .WithMaxFeePerBlobGas(1) + .WithMaxFeePerDataGas(1) .WithBlobVersionedHashes(new[] { hash }) .WithChainId(TestBlockchainIds.ChainId) .SignedAndResolved().TestObject; @@ -465,7 +465,7 @@ static TransactionBuilder MakeTestObject(int blobCount = 1) => Buil .WithChainId(TestBlockchainIds.ChainId) .WithTimestamp(ulong.MaxValue) .WithMaxFeePerGas(1) - .WithMaxFeePerBlobGas(1) + .WithMaxFeePerDataGas(1) .WithShardBlobTxTypeAndFields(blobCount); yield return new TestCaseData(MakeTestObject().SignedAndResolved().TestObject) @@ -498,19 +498,19 @@ static TransactionBuilder MakeTestObject(int blobCount = 1) => Buil TestName = "More than minimum BlobVersionedHashes", ExpectedResult = true }; - yield return new TestCaseData(MakeTestObject((int)(Eip4844Constants.MaxBlobGasPerBlock / Eip4844Constants.BlobGasPerBlob - 1)) + yield return new TestCaseData(MakeTestObject((int)(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob - 1)) .SignedAndResolved().TestObject) { TestName = "Less than maximum BlobVersionedHashes", ExpectedResult = true }; - yield return new TestCaseData(MakeTestObject((int)(Eip4844Constants.MaxBlobGasPerBlock / Eip4844Constants.BlobGasPerBlob)) + yield return new TestCaseData(MakeTestObject((int)(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob)) .SignedAndResolved().TestObject) { TestName = "Maximum BlobVersionedHashes", ExpectedResult = true }; - yield return new TestCaseData(MakeTestObject((int)(Eip4844Constants.MaxBlobGasPerBlock / Eip4844Constants.BlobGasPerBlob + 1)) + yield return new TestCaseData(MakeTestObject((int)(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob + 1)) .SignedAndResolved().TestObject) { TestName = "Too many BlobVersionedHashes", diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/UnclesValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/UnclesValidatorTests.cs index f0d01c68da3..31cfc7108e7 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/UnclesValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/UnclesValidatorTests.cs @@ -19,7 +19,7 @@ public class UnclesValidatorTests private readonly Block _parent; private readonly Block _block; private readonly IBlockTree _blockTree; - private IHeaderValidator _headerValidator = null!; + private IHeaderValidator _headerValidator; private readonly Block _duplicateUncle; @@ -33,7 +33,7 @@ public void Setup() public UnclesValidatorTests() { _blockTree = Build.A.BlockTree().OfChainLength(1).TestObject; - _grandgrandparent = _blockTree.FindBlock(0, BlockTreeLookupOptions.None)!; + _grandgrandparent = _blockTree.FindBlock(0, BlockTreeLookupOptions.None); _grandparent = Build.A.Block.WithParent(_grandgrandparent).TestObject; _duplicateUncle = Build.A.Block.WithParent(_grandgrandparent).TestObject; _parent = Build.A.Block.WithParent(_grandparent).WithUncles(_duplicateUncle).TestObject; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Visitors/DbBlocksLoaderTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Visitors/DbBlocksLoaderTests.cs index d627c93e130..7d81fbe97f8 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Visitors/DbBlocksLoaderTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Visitors/DbBlocksLoaderTests.cs @@ -14,6 +14,8 @@ using Nethermind.Specs; using Nethermind.State.Repositories; using Nethermind.Db.Blooms; +using Nethermind.TxPool; +using NSubstitute; using NUnit.Framework; namespace Nethermind.Blockchain.Test.Visitors @@ -21,7 +23,7 @@ namespace Nethermind.Blockchain.Test.Visitors [TestFixture] public class DbBlocksLoaderTests { - private readonly int _dbLoadTimeout = 5000; + private int _dbLoadTimeout = 5000; [Test, Timeout(Timeout.MaxTestTime)] public async Task Can_load_blocks_from_db() @@ -35,23 +37,23 @@ public async Task Can_load_blocks_from_db() MemDb headersDb = new(); BlockTree testTree = Build.A.BlockTree(genesisBlock).OfChainLength(chainLength).TestObject; - for (int i = 0; i < testTree.Head!.Number + 1; i++) + for (int i = 0; i < testTree.Head.Number + 1; i++) { - Block ithBlock = testTree.FindBlock(i, BlockTreeLookupOptions.None)!; - blocksDb.Set(ithBlock.Hash!, Rlp.Encode(ithBlock).Bytes); + Block ithBlock = testTree.FindBlock(i, BlockTreeLookupOptions.None); + blocksDb.Set(ithBlock.Hash, Rlp.Encode(ithBlock).Bytes); - headersDb.Set(ithBlock.Hash!, Rlp.Encode(ithBlock.Header).Bytes); + headersDb.Set(ithBlock.Hash, Rlp.Encode(ithBlock.Header).Bytes); ChainLevelInfo ithLevel = new( true, - blockInfos: new[] + new BlockInfo[] { - new BlockInfo(ithBlock.Hash!, ithBlock.TotalDifficulty!.Value) {WasProcessed = true} + new(ithBlock.Hash, ithBlock.TotalDifficulty.Value) {WasProcessed = true} }); blockInfosDb.Set(i, Rlp.Encode(ithLevel).Bytes); } - blockInfosDb.Set(Keccak.Zero, genesisBlock.Header.Hash!.Bytes); + blockInfosDb.Set(Keccak.Zero, genesisBlock.Header.Hash.Bytes); headersDb.Set(genesisBlock.Header.Hash, Rlp.Encode(genesisBlock.Header).Bytes); BlockTree blockTree = new( @@ -66,7 +68,7 @@ public async Task Can_load_blocks_from_db() DbBlocksLoader loader = new(blockTree, LimboNoErrorLogger.Instance); await blockTree.Accept(loader, CancellationToken.None); - Assert.That(blockTree.BestSuggestedHeader!.Hash, Is.EqualTo(testTree.Head.Hash), $"head {chainLength}"); + Assert.That(blockTree.BestSuggestedHeader.Hash, Is.EqualTo(testTree.Head.Hash), $"head {chainLength}"); } } @@ -82,22 +84,22 @@ public async Task Can_load_blocks_from_db_odd() MemDb headersDb = new(); BlockTree testTree = Build.A.BlockTree(genesisBlock).OfChainLength(chainLength).TestObject; - for (int i = 0; i < testTree.Head!.Number + 1; i++) + for (int i = 0; i < testTree.Head.Number + 1; i++) { - Block ithBlock = testTree.FindBlock(i, BlockTreeLookupOptions.None)!; - blocksDb.Set(ithBlock.Hash!, Rlp.Encode(ithBlock).Bytes); + Block ithBlock = testTree.FindBlock(i, BlockTreeLookupOptions.None); + blocksDb.Set(ithBlock.Hash, Rlp.Encode(ithBlock).Bytes); - headersDb.Set(ithBlock.Hash!, Rlp.Encode(ithBlock.Header).Bytes); + headersDb.Set(ithBlock.Hash, Rlp.Encode(ithBlock.Header).Bytes); - ChainLevelInfo ithLevel = new(true, blockInfos: new[] + ChainLevelInfo ithLevel = new(true, new BlockInfo[1] { - new BlockInfo(ithBlock.Hash!, ithBlock.TotalDifficulty!.Value) + new(ithBlock.Hash, ithBlock.TotalDifficulty.Value) }); blockInfosDb.Set(i, Rlp.Encode(ithLevel).Bytes); } - blockInfosDb.Set(Keccak.Zero, genesisBlock.Header.Hash!.Bytes); + blockInfosDb.Set(Keccak.Zero, genesisBlock.Header.Hash.Bytes); headersDb.Set(genesisBlock.Header.Hash, Rlp.Encode(genesisBlock.Header).Bytes); BlockTree blockTree = new( @@ -112,7 +114,7 @@ public async Task Can_load_blocks_from_db_odd() DbBlocksLoader loader = new(blockTree, LimboNoErrorLogger.Instance); await blockTree.Accept(loader, CancellationToken.None); - Assert.That(blockTree.BestSuggestedHeader!.Hash, Is.EqualTo(testTree.Head.Hash), $"head {chainLength}"); + Assert.That(blockTree.BestSuggestedHeader.Hash, Is.EqualTo(testTree.Head.Hash), $"head {chainLength}"); } } @@ -162,9 +164,11 @@ public async Task Can_load_from_DB_when_there_is_an_invalid_block_in_DB_and_a_va LimboLogs.Instance); CancellationTokenSource tokenSource = new(); - tokenSource.CancelAfter(_dbLoadTimeout); +#pragma warning disable 4014 + Task.Delay(_dbLoadTimeout).ContinueWith(t => tokenSource.Cancel()); +#pragma warning restore 4014 - tree2.NewBestSuggestedBlock += (_, args) => + tree2.NewBestSuggestedBlock += (sender, args) => { if (args.Block.Hash == block1.Hash) { @@ -180,12 +184,12 @@ public async Task Can_load_from_DB_when_there_is_an_invalid_block_in_DB_and_a_va await tree2.Accept(loader, tokenSource.Token); Assert.That(tree2.BestKnownNumber, Is.EqualTo(3L), "best known"); - tree2.Head!.Header.Should().BeEquivalentTo(block3B.Header, options => { return options.Excluding(t => t.MaybeParent); }); + tree2.Head.Header.Should().BeEquivalentTo(block3B.Header, options => { return options.Excluding(t => t.MaybeParent); }); tree2.BestSuggestedHeader.Should().BeEquivalentTo(block3B.Header, options => { return options.Excluding(t => t.MaybeParent); }); - Assert.IsNull(blocksDb.Get(block1.Hash!), "block 1"); - Assert.IsNull(blocksDb.Get(block2.Hash!), "block 2"); - Assert.IsNull(blocksDb.Get(block3.Hash!), "block 3"); + Assert.IsNull(blocksDb.Get(block1.Hash), "block 1"); + Assert.IsNull(blocksDb.Get(block2.Hash), "block 2"); + Assert.IsNull(blocksDb.Get(block3.Hash), "block 3"); Assert.NotNull(blockInfosDb.Get(1), "level 1"); Assert.NotNull(blockInfosDb.Get(2), "level 2"); @@ -230,9 +234,11 @@ public async Task Can_load_from_DB_when_there_is_only_an_invalid_chain_in_DB() LimboLogs.Instance); CancellationTokenSource tokenSource = new(); - tokenSource.CancelAfter(_dbLoadTimeout); +#pragma warning disable 4014 + Task.Delay(_dbLoadTimeout).ContinueWith(t => tokenSource.Cancel()); +#pragma warning restore 4014 - tree2.NewBestSuggestedBlock += (_, args) => + tree2.NewBestSuggestedBlock += (sender, args) => { if (args.Block.Hash == block1.Hash) { @@ -250,12 +256,12 @@ public async Task Can_load_from_DB_when_there_is_only_an_invalid_chain_in_DB() /* note the block tree historically loads one less block than it could */ Assert.That(tree2.BestKnownNumber, Is.EqualTo(0L), "best known"); - Assert.That(tree2.Head!.Hash, Is.EqualTo(block0.Hash), "head"); - Assert.That(tree2.BestSuggestedHeader!.Hash, Is.EqualTo(block0.Hash), "suggested"); + Assert.That(tree2.Head.Hash, Is.EqualTo(block0.Hash), "head"); + Assert.That(tree2.BestSuggestedHeader.Hash, Is.EqualTo(block0.Hash), "suggested"); - Assert.IsNull(blocksDb.Get(block1.Hash!), "block 1"); - Assert.IsNull(blocksDb.Get(block2.Hash!), "block 2"); - Assert.IsNull(blocksDb.Get(block3.Hash!), "block 3"); + Assert.IsNull(blocksDb.Get(block1.Hash), "block 1"); + Assert.IsNull(blocksDb.Get(block2.Hash), "block 2"); + Assert.IsNull(blocksDb.Get(block3.Hash), "block 3"); Assert.IsNull(blockInfosDb.Get(1), "level 1"); Assert.IsNull(blockInfosDb.Get(2), "level 2"); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Visitors/StartupTreeFixerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Visitors/StartupTreeFixerTests.cs index 08032d394f6..86731c49e89 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Visitors/StartupTreeFixerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Visitors/StartupTreeFixerTests.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using FluentAssertions; +using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; using Nethermind.Blockchain.Visitors; using Nethermind.Consensus.Processing; @@ -14,8 +15,14 @@ using Nethermind.Specs; using Nethermind.State.Repositories; using Nethermind.Db.Blooms; +using Nethermind.Evm; using Nethermind.JsonRpc.Test.Modules; +using Nethermind.Serialization.Rlp; +using Nethermind.State; +using Nethermind.Trie.Pruning; +using Nethermind.TxPool; using NUnit.Framework; +using System.Runtime.CompilerServices; namespace Nethermind.Blockchain.Test.Visitors { @@ -74,7 +81,7 @@ public async Task Deletes_everything_after_the_missing_level() Assert.Null(blockInfosDb.Get(4), "level 4"); Assert.Null(blockInfosDb.Get(5), "level 5"); - tree.Head!.Header.Should().BeEquivalentTo(block2.Header, options => options.Excluding(t => t.MaybeParent)); + tree.Head.Header.Should().BeEquivalentTo(block2.Header, options => options.Excluding(t => t.MaybeParent)); tree.BestSuggestedHeader.Should().BeEquivalentTo(block2.Header, options => options.Excluding(t => t.MaybeParent)); tree.BestSuggestedBody?.Body.Should().BeEquivalentTo(block2.Body); tree.BestKnownNumber.Should().Be(2); @@ -162,18 +169,18 @@ public async Task Fixer_should_not_suggest_block_with_null_block() testRpc.BlockchainProcessor = newBlockchainProcessor; IBlockTreeVisitor fixer = new StartupBlockTreeFixer(new SyncConfig(), tree, testRpc.DbProvider.StateDb, LimboNoErrorLogger.Instance, 5); - BlockVisitOutcome result = await fixer.VisitBlock(null!, CancellationToken.None); + BlockVisitOutcome result = await fixer.VisitBlock(null, CancellationToken.None); Assert.That(result, Is.EqualTo(BlockVisitOutcome.None)); } private static void SuggestNumberOfBlocks(IBlockTree blockTree, int blockAmount) { - Block newParent = blockTree.Head!; + Block newParent = blockTree.Head; for (int i = 0; i < blockAmount; ++i) { Block newBlock = Build.A.Block - .WithNumber(newParent.Number + 1) + .WithNumber(newParent!.Number + 1) .WithDifficulty(newParent.Difficulty + 1) .WithParent(newParent) .WithStateRoot(newParent.StateRoot!).TestObject; @@ -182,6 +189,7 @@ private static void SuggestNumberOfBlocks(IBlockTree blockTree, int blockAmount) } } + [Ignore("It is causing some trouble now. Disabling it while the restarts logic is under review")] [Test, Timeout(Timeout.MaxTestTime)] public async Task When_head_block_is_followed_by_a_block_bodies_gap_it_should_delete_all_levels_after_the_gap_start() { @@ -214,7 +222,7 @@ public async Task When_head_block_is_followed_by_a_block_bodies_gap_it_should_de Assert.That(tree.BestKnownNumber, Is.EqualTo(2L), "best known"); Assert.That(tree.Head?.Header, Is.EqualTo(block2.Header), "head"); - Assert.That(tree.BestSuggestedHeader!.Hash, Is.EqualTo(block2.Hash), "suggested"); + Assert.That(tree.BestSuggestedHeader.Hash, Is.EqualTo(block2.Hash), "suggested"); } } } diff --git a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs b/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs deleted file mode 100644 index 925530833b6..00000000000 --- a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core.Specs; -using Nethermind.Core; -using Nethermind.Int256; -using Nethermind.State; -using Nethermind.Core.Crypto; -using Nethermind.Core.Extensions; - -namespace Nethermind.Consensus.BeaconBlockRoot; -public class BeaconBlockRootHandler : IBeaconBlockRootHandler -{ - public static UInt256 HISTORICAL_ROOTS_LENGTH = 8191; - private static readonly Address DefaultPbbrContractAddress = new Address("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02"); - - public void ApplyContractStateChanges(Block block, IReleaseSpec spec, IWorldState stateProvider) - { - if (!spec.IsBeaconBlockRootAvailable || - block.IsGenesis || - block.Header.ParentBeaconBlockRoot is null) return; - - UInt256 timestamp = (UInt256)block.Timestamp; - Keccak parentBeaconBlockRoot = block.ParentBeaconBlockRoot; - - UInt256.Mod(timestamp, HISTORICAL_ROOTS_LENGTH, out UInt256 timestampReduced); - UInt256 rootIndex = timestampReduced + HISTORICAL_ROOTS_LENGTH; - - StorageCell tsStorageCell = new(spec.Eip4788ContractAddress ?? DefaultPbbrContractAddress, timestampReduced); - StorageCell brStorageCell = new(spec.Eip4788ContractAddress ?? DefaultPbbrContractAddress, rootIndex); - - stateProvider.Set(tsStorageCell, Bytes.WithoutLeadingZeros(timestamp.ToBigEndian()).ToArray()); - stateProvider.Set(brStorageCell, Bytes.WithoutLeadingZeros(parentBeaconBlockRoot.Bytes).ToArray()); - } -} diff --git a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/IBeaconBlockRootHandler.cs b/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/IBeaconBlockRootHandler.cs deleted file mode 100644 index d30074fc4cc..00000000000 --- a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/IBeaconBlockRootHandler.cs +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core.Specs; -using Nethermind.Core; -using Nethermind.State; - -namespace Nethermind.Consensus.BeaconBlockRoot; -public interface IBeaconBlockRootHandler -{ - void ApplyContractStateChanges(Block block, IReleaseSpec spec, IWorldState state); -} diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs deleted file mode 100644 index cc6b0403a62..00000000000 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.Initializer.cs +++ /dev/null @@ -1,382 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.IO; -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Db; -using Nethermind.Serialization.Rlp; - -namespace Nethermind.Blockchain; - -public partial class BlockTree -{ - private bool _tryToRecoverFromHeaderBelowBodyCorruption = false; - - public void RecalculateTreeLevels() - { - LoadLowestInsertedBodyNumber(); - LoadLowestInsertedHeader(); - LoadLowestInsertedBeaconHeader(); - LoadBestKnown(); - LoadBeaconBestKnown(); - } - - private void AttemptToFixCorruptionByMovingHeadBackwards() - { - if (_tryToRecoverFromHeaderBelowBodyCorruption && BestSuggestedHeader is not null) - { - long blockNumber = BestPersistedState ?? BestSuggestedHeader.Number; - ChainLevelInfo chainLevelInfo = LoadLevel(blockNumber); - BlockInfo? canonicalBlock = chainLevelInfo?.MainChainBlock; - if (canonicalBlock is not null && canonicalBlock.WasProcessed) - { - SetHeadBlock(canonicalBlock.BlockHash!); - } - else - { - _logger.Error("Failed attempt to fix 'header < body' corruption caused by an unexpected shutdown."); - } - } - } - - private bool LevelExists(long blockNumber, bool findBeacon = false) - { - ChainLevelInfo? level = LoadLevel(blockNumber); - if (findBeacon) - { - return level is not null && level.HasBeaconBlocks; - } - - return level is not null && level.HasNonBeaconBlocks; - } - - private bool HeaderExists(long blockNumber, bool findBeacon = false) - { - ChainLevelInfo level = LoadLevel(blockNumber); - if (level is null) - { - return false; - } - - foreach (BlockInfo blockInfo in level.BlockInfos) - { - BlockHeader? header = FindHeader(blockInfo.BlockHash, BlockTreeLookupOptions.None); - if (header is not null) - { - if (findBeacon && blockInfo.IsBeaconHeader) - { - return true; - } - - if (!findBeacon && !blockInfo.IsBeaconHeader) - { - return true; - } - } - } - - return false; - } - - private bool BodyExists(long blockNumber, bool findBeacon = false) - { - ChainLevelInfo level = LoadLevel(blockNumber); - if (level is null) - { - return false; - } - - foreach (BlockInfo blockInfo in level.BlockInfos) - { - Block? block = FindBlock(blockInfo.BlockHash, BlockTreeLookupOptions.None); - if (block is not null) - { - if (findBeacon && blockInfo.IsBeaconBody) - { - return true; - } - - if (!findBeacon && !blockInfo.IsBeaconBody) - { - return true; - } - } - } - - return false; - } - - private void LoadLowestInsertedBodyNumber() - { - LowestInsertedBodyNumber = - _blockStore.GetMetadata(LowestInsertedBodyNumberDbEntryAddress)? - .AsRlpValueContext().DecodeLong(); - } - - private void LoadLowestInsertedBeaconHeader() - { - if (_metadataDb.KeyExists(MetadataDbKeys.LowestInsertedBeaconHeaderHash)) - { - Keccak? lowestBeaconHeaderHash = _metadataDb.Get(MetadataDbKeys.LowestInsertedBeaconHeaderHash)? - .AsRlpStream().DecodeKeccak(); - _lowestInsertedBeaconHeader = FindHeader(lowestBeaconHeaderHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded); - } - } - - private void LoadLowestInsertedHeader() - { - long left = 1L; - long right = _syncConfig.PivotNumberParsed; - - LowestInsertedHeader = BinarySearchBlockHeader(left, right, LevelExists, BinarySearchDirection.Down); - } - - private void LoadBestKnown() - { - long left = (Head?.Number ?? 0) == 0 - ? Math.Max(_syncConfig.PivotNumberParsed, LowestInsertedHeader?.Number ?? 0) - 1 - : Head.Number; - - long right = Math.Max(0, left) + BestKnownSearchLimit; - - long bestKnownNumberFound = - BinarySearchBlockNumber(1, left, LevelExists) ?? 0; - long bestKnownNumberAlternative = - BinarySearchBlockNumber(left, right, LevelExists) ?? 0; - - long bestSuggestedHeaderNumber = - BinarySearchBlockNumber(1, left, HeaderExists) ?? 0; - long bestSuggestedHeaderNumberAlternative - = BinarySearchBlockNumber(left, right, HeaderExists) ?? 0; - - long bestSuggestedBodyNumber - = BinarySearchBlockNumber(1, left, BodyExists) ?? 0; - long bestSuggestedBodyNumberAlternative - = BinarySearchBlockNumber(left, right, BodyExists) ?? 0; - - if (_logger.IsInfo) - _logger.Info("Numbers resolved, " + - $"level = Max({bestKnownNumberFound}, {bestKnownNumberAlternative}), " + - $"header = Max({bestSuggestedHeaderNumber}, {bestSuggestedHeaderNumberAlternative}), " + - $"body = Max({bestSuggestedBodyNumber}, {bestSuggestedBodyNumberAlternative})"); - - bestKnownNumberFound = Math.Max(bestKnownNumberFound, bestKnownNumberAlternative); - bestSuggestedHeaderNumber = Math.Max(bestSuggestedHeaderNumber, bestSuggestedHeaderNumberAlternative); - bestSuggestedBodyNumber = Math.Max(bestSuggestedBodyNumber, bestSuggestedBodyNumberAlternative); - - if (bestKnownNumberFound < 0 || - bestSuggestedHeaderNumber < 0 || - bestSuggestedBodyNumber < 0 || - bestSuggestedHeaderNumber < bestSuggestedBodyNumber) - { - if (_logger.IsWarn) - _logger.Warn( - $"Detected corrupted block tree data ({bestSuggestedHeaderNumber} < {bestSuggestedBodyNumber}) (possibly due to an unexpected shutdown). Attempting to fix by moving head backwards. This may fail and you may need to resync the node."); - if (bestSuggestedHeaderNumber < bestSuggestedBodyNumber) - { - bestSuggestedBodyNumber = bestSuggestedHeaderNumber; - _tryToRecoverFromHeaderBelowBodyCorruption = true; - } - else - { - throw new InvalidDataException("Invalid initial block tree state loaded - " + - $"best known: {bestKnownNumberFound}|" + - $"best header: {bestSuggestedHeaderNumber}|" + - $"best body: {bestSuggestedBodyNumber}|"); - } - } - - BestKnownNumber = Math.Max(bestKnownNumberFound, bestKnownNumberAlternative); - BestSuggestedHeader = FindHeader(bestSuggestedHeaderNumber, BlockTreeLookupOptions.None); - BlockHeader? bestSuggestedBodyHeader = FindHeader(bestSuggestedBodyNumber, BlockTreeLookupOptions.None); - BestSuggestedBody = bestSuggestedBodyHeader is null - ? null - : FindBlock(bestSuggestedBodyHeader.Hash, BlockTreeLookupOptions.None); - } - - - private void LoadBeaconBestKnown() - { - long left = Math.Max(Head?.Number ?? 0, LowestInsertedBeaconHeader?.Number ?? 0) - 1; - long right = Math.Max(0, left) + BestKnownSearchLimit; - long bestKnownNumberFound = BinarySearchBlockNumber(left, right, LevelExists, findBeacon: true) ?? 0; - - left = Math.Max( - Math.Max( - Head?.Number ?? 0, - LowestInsertedBeaconHeader?.Number ?? 0), - BestSuggestedHeader?.Number ?? 0 - ) - 1; - - right = Math.Max(0, left) + BestKnownSearchLimit; - long bestBeaconHeaderNumber = BinarySearchBlockNumber(left, right, HeaderExists, findBeacon: true) ?? 0; - - long? beaconPivotNumber = _metadataDb.Get(MetadataDbKeys.BeaconSyncPivotNumber)?.AsRlpValueContext().DecodeLong(); - left = Math.Max(Head?.Number ?? 0, beaconPivotNumber ?? 0) - 1; - right = Math.Max(0, left) + BestKnownSearchLimit; - long bestBeaconBodyNumber = BinarySearchBlockNumber(left, right, BodyExists, findBeacon: true) ?? 0; - - if (_logger.IsInfo) - _logger.Info("Beacon Numbers resolved, " + - $"level = {bestKnownNumberFound}, " + - $"header = {bestBeaconHeaderNumber}, " + - $"body = {bestBeaconBodyNumber}"); - - if (bestKnownNumberFound < 0 || - bestBeaconHeaderNumber < 0 || - bestBeaconBodyNumber < 0 || - bestBeaconHeaderNumber < bestBeaconBodyNumber) - { - if (_logger.IsWarn) - _logger.Warn( - $"Detected corrupted block tree data ({bestBeaconHeaderNumber} < {bestBeaconBodyNumber}) (possibly due to an unexpected shutdown). Attempting to fix by moving head backwards. This may fail and you may need to resync the node."); - if (bestBeaconHeaderNumber < bestBeaconBodyNumber) - { - bestBeaconBodyNumber = bestBeaconHeaderNumber; - _tryToRecoverFromHeaderBelowBodyCorruption = true; - } - else - { - throw new InvalidDataException("Invalid initial block tree state loaded - " + - $"best known: {bestKnownNumberFound}|" + - $"best header: {bestBeaconHeaderNumber}|" + - $"best body: {bestBeaconBodyNumber}|"); - } - } - - BestKnownBeaconNumber = bestKnownNumberFound; - BestSuggestedBeaconHeader = FindHeader(bestBeaconHeaderNumber, BlockTreeLookupOptions.TotalDifficultyNotNeeded); - BlockHeader? bestBeaconBodyHeader = FindHeader(bestBeaconBodyNumber, BlockTreeLookupOptions.TotalDifficultyNotNeeded); - BestSuggestedBeaconBody = bestBeaconBodyHeader is null - ? null - : FindBlock(bestBeaconBodyHeader.Hash, BlockTreeLookupOptions.TotalDifficultyNotNeeded); - } - - private enum BinarySearchDirection - { - Up, - Down - } - - private BlockHeader? BinarySearchBlockHeader(long left, long right, Func isBlockFound, - BinarySearchDirection direction = BinarySearchDirection.Up) - { - long? blockNumber = BinarySearchBlockNumber(left, right, isBlockFound, direction); - if (blockNumber.HasValue) - { - ChainLevelInfo? level = LoadLevel(blockNumber.Value); - if (level is null) - { - throw new InvalidDataException( - $"Missing chain level at number {blockNumber.Value}"); - } - - BlockInfo blockInfo = level.BlockInfos[0]; - return FindHeader(blockInfo.BlockHash, BlockTreeLookupOptions.None); - } - - return null; - } - - private static long? BinarySearchBlockNumber(long left, long right, Func isBlockFound, - BinarySearchDirection direction = BinarySearchDirection.Up, bool findBeacon = false) - { - if (left > right) - { - return null; - } - - long? result = null; - while (left != right) - { - long index = direction == BinarySearchDirection.Up - ? left + (right - left) / 2 - : right - (right - left) / 2; - if (isBlockFound(index, findBeacon)) - { - result = index; - if (direction == BinarySearchDirection.Up) - { - left = index + 1; - } - else - { - right = index - 1; - } - } - else - { - if (direction == BinarySearchDirection.Up) - { - right = index; - } - else - { - left = index; - } - } - } - - if (isBlockFound(left, findBeacon)) - { - result = direction == BinarySearchDirection.Up ? left : right; - } - - return result; - } - - private void LoadStartBlock() - { - Block? startBlock = null; - byte[] persistedNumberData = _blockInfoDb.Get(StateHeadHashDbEntryAddress); - BestPersistedState = persistedNumberData is null ? null : new RlpStream(persistedNumberData).DecodeLong(); - long? persistedNumber = BestPersistedState; - if (persistedNumber is not null) - { - startBlock = FindBlock(persistedNumber.Value, BlockTreeLookupOptions.None); - if (_logger.IsInfo) _logger.Info( - $"Start block loaded from reorg boundary - {persistedNumber} - {startBlock?.ToString(Block.Format.Short)}"); - } - else - { - byte[] data = _blockInfoDb.Get(HeadAddressInDb); - if (data is not null) - { - startBlock = FindBlock(new Keccak(data), BlockTreeLookupOptions.None); - if (_logger.IsInfo) _logger.Info($"Start block loaded from HEAD - {startBlock?.ToString(Block.Format.Short)}"); - } - } - - if (startBlock is not null) - { - if (startBlock.Hash is null) - { - throw new InvalidDataException("The start block hash is null."); - } - - SetHeadBlock(startBlock.Hash); - } - } - - private void SetHeadBlock(Keccak headHash) - { - Block? headBlock = FindBlock(headHash, BlockTreeLookupOptions.None); - if (headBlock is null) - { - throw new InvalidOperationException( - "An attempt to set a head block that has not been stored in the DB."); - } - - ChainLevelInfo? level = LoadLevel(headBlock.Number); - int? index = level?.FindIndex(headHash); - if (!index.HasValue) - { - throw new InvalidDataException("Head block data missing from chain info"); - } - - headBlock.Header.TotalDifficulty = level.BlockInfos[index.Value].TotalDifficulty; - Head = headBlock; - } -} diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs index 8ef3b90d8f0..e18069d1d65 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs @@ -59,6 +59,7 @@ public partial class BlockTree : IBlockTree private readonly IBloomStorage _bloomStorage; private readonly ISyncConfig _syncConfig; private readonly IChainLevelInfoRepository _chainLevelInfoRepository; + private bool _tryToRecoverFromHeaderBelowBodyCorruption = false; public BlockHeader? Genesis { get; private set; } public Block? Head { get; private set; } @@ -233,6 +234,317 @@ public BlockTree( } } + private void AttemptToFixCorruptionByMovingHeadBackwards() + { + if (_tryToRecoverFromHeaderBelowBodyCorruption && BestSuggestedHeader is not null) + { + ChainLevelInfo chainLevelInfo = LoadLevel(BestSuggestedHeader.Number); + BlockInfo? canonicalBlock = chainLevelInfo?.MainChainBlock; + if (canonicalBlock is not null && canonicalBlock.WasProcessed) + { + SetHeadBlock(canonicalBlock.BlockHash!); + } + else + { + _logger.Error("Failed attempt to fix 'header < body' corruption caused by an unexpected shutdown."); + } + } + } + + public void RecalculateTreeLevels() + { + LoadLowestInsertedBodyNumber(); + LoadLowestInsertedHeader(); + LoadLowestInsertedBeaconHeader(); + LoadBestKnown(); + LoadBeaconBestKnown(); + } + + private void LoadLowestInsertedBodyNumber() + { + LowestInsertedBodyNumber = + _blockStore.GetMetadata(LowestInsertedBodyNumberDbEntryAddress)? + .AsRlpValueContext().DecodeLong(); + } + + public void LoadLowestInsertedBeaconHeader() + { + if (_metadataDb.KeyExists(MetadataDbKeys.LowestInsertedBeaconHeaderHash)) + { + Keccak? lowestBeaconHeaderHash = _metadataDb.Get(MetadataDbKeys.LowestInsertedBeaconHeaderHash)? + .AsRlpStream().DecodeKeccak(); + _lowestInsertedBeaconHeader = FindHeader(lowestBeaconHeaderHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded); + } + } + + private void LoadLowestInsertedHeader() + { + long left = 1L; + long right = _syncConfig.PivotNumberParsed; + + LowestInsertedHeader = BinarySearchBlockHeader(left, right, LevelExists, BinarySearchDirection.Down); + } + + private bool LevelExists(long blockNumber, bool findBeacon = false) + { + ChainLevelInfo? level = LoadLevel(blockNumber); + if (findBeacon) + { + return level is not null && level.HasBeaconBlocks; + } + + return level is not null && level.HasNonBeaconBlocks; + } + + private bool HeaderExists(long blockNumber, bool findBeacon = false) + { + ChainLevelInfo level = LoadLevel(blockNumber); + if (level is null) + { + return false; + } + + foreach (BlockInfo blockInfo in level.BlockInfos) + { + BlockHeader? header = FindHeader(blockInfo.BlockHash, BlockTreeLookupOptions.None); + if (header is not null) + { + if (findBeacon && blockInfo.IsBeaconHeader) + { + return true; + } + + if (!findBeacon && !blockInfo.IsBeaconHeader) + { + return true; + } + } + } + + return false; + } + + private bool BodyExists(long blockNumber, bool findBeacon = false) + { + ChainLevelInfo level = LoadLevel(blockNumber); + if (level is null) + { + return false; + } + + foreach (BlockInfo blockInfo in level.BlockInfos) + { + Block? block = FindBlock(blockInfo.BlockHash, BlockTreeLookupOptions.None); + if (block is not null) + { + if (findBeacon && blockInfo.IsBeaconBody) + { + return true; + } + + if (!findBeacon && !blockInfo.IsBeaconBody) + { + return true; + } + } + } + + return false; + } + + private void LoadBestKnown() + { + long left = (Head?.Number ?? 0) == 0 + ? Math.Max(_syncConfig.PivotNumberParsed, LowestInsertedHeader?.Number ?? 0) - 1 + : Head.Number; + + long right = Math.Max(0, left) + BestKnownSearchLimit; + + long bestKnownNumberFound = + BinarySearchBlockNumber(1, left, LevelExists) ?? 0; + long bestKnownNumberAlternative = + BinarySearchBlockNumber(left, right, LevelExists) ?? 0; + + long bestSuggestedHeaderNumber = + BinarySearchBlockNumber(1, left, HeaderExists) ?? 0; + long bestSuggestedHeaderNumberAlternative + = BinarySearchBlockNumber(left, right, HeaderExists) ?? 0; + + long bestSuggestedBodyNumber + = BinarySearchBlockNumber(1, left, BodyExists) ?? 0; + long bestSuggestedBodyNumberAlternative + = BinarySearchBlockNumber(left, right, BodyExists) ?? 0; + + if (_logger.IsInfo) + _logger.Info("Numbers resolved, " + + $"level = Max({bestKnownNumberFound}, {bestKnownNumberAlternative}), " + + $"header = Max({bestSuggestedHeaderNumber}, {bestSuggestedHeaderNumberAlternative}), " + + $"body = Max({bestSuggestedBodyNumber}, {bestSuggestedBodyNumberAlternative})"); + + bestKnownNumberFound = Math.Max(bestKnownNumberFound, bestKnownNumberAlternative); + bestSuggestedHeaderNumber = Math.Max(bestSuggestedHeaderNumber, bestSuggestedHeaderNumberAlternative); + bestSuggestedBodyNumber = Math.Max(bestSuggestedBodyNumber, bestSuggestedBodyNumberAlternative); + + if (bestKnownNumberFound < 0 || + bestSuggestedHeaderNumber < 0 || + bestSuggestedBodyNumber < 0 || + bestSuggestedHeaderNumber < bestSuggestedBodyNumber) + { + if (_logger.IsWarn) + _logger.Warn( + $"Detected corrupted block tree data ({bestSuggestedHeaderNumber} < {bestSuggestedBodyNumber}) (possibly due to an unexpected shutdown). Attempting to fix by moving head backwards. This may fail and you may need to resync the node."); + if (bestSuggestedHeaderNumber < bestSuggestedBodyNumber) + { + bestSuggestedBodyNumber = bestSuggestedHeaderNumber; + _tryToRecoverFromHeaderBelowBodyCorruption = true; + } + else + { + throw new InvalidDataException("Invalid initial block tree state loaded - " + + $"best known: {bestKnownNumberFound}|" + + $"best header: {bestSuggestedHeaderNumber}|" + + $"best body: {bestSuggestedBodyNumber}|"); + } + } + + BestKnownNumber = Math.Max(bestKnownNumberFound, bestKnownNumberAlternative); + BestSuggestedHeader = FindHeader(bestSuggestedHeaderNumber, BlockTreeLookupOptions.None); + BlockHeader? bestSuggestedBodyHeader = FindHeader(bestSuggestedBodyNumber, BlockTreeLookupOptions.None); + BestSuggestedBody = bestSuggestedBodyHeader is null + ? null + : FindBlock(bestSuggestedBodyHeader.Hash, BlockTreeLookupOptions.None); + } + + private void LoadBeaconBestKnown() + { + long left = Math.Max(Head?.Number ?? 0, LowestInsertedBeaconHeader?.Number ?? 0) - 1; + long right = Math.Max(0, left) + BestKnownSearchLimit; + long bestKnownNumberFound = BinarySearchBlockNumber(left, right, LevelExists, findBeacon: true) ?? 0; + + left = Math.Max( + Math.Max( + Head?.Number ?? 0, + LowestInsertedBeaconHeader?.Number ?? 0), + BestSuggestedHeader?.Number ?? 0 + ) - 1; + + right = Math.Max(0, left) + BestKnownSearchLimit; + long bestBeaconHeaderNumber = BinarySearchBlockNumber(left, right, HeaderExists, findBeacon: true) ?? 0; + + long? beaconPivotNumber = _metadataDb.Get(MetadataDbKeys.BeaconSyncPivotNumber)?.AsRlpValueContext().DecodeLong(); + left = Math.Max(Head?.Number ?? 0, beaconPivotNumber ?? 0) - 1; + right = Math.Max(0, left) + BestKnownSearchLimit; + long bestBeaconBodyNumber = BinarySearchBlockNumber(left, right, BodyExists, findBeacon: true) ?? 0; + + if (_logger.IsInfo) + _logger.Info("Beacon Numbers resolved, " + + $"level = {bestKnownNumberFound}, " + + $"header = {bestBeaconHeaderNumber}, " + + $"body = {bestBeaconBodyNumber}"); + + if (bestKnownNumberFound < 0 || + bestBeaconHeaderNumber < 0 || + bestBeaconBodyNumber < 0 || + bestBeaconHeaderNumber < bestBeaconBodyNumber) + { + if (_logger.IsWarn) + _logger.Warn( + $"Detected corrupted block tree data ({bestBeaconHeaderNumber} < {bestBeaconBodyNumber}) (possibly due to an unexpected shutdown). Attempting to fix by moving head backwards. This may fail and you may need to resync the node."); + if (bestBeaconHeaderNumber < bestBeaconBodyNumber) + { + bestBeaconBodyNumber = bestBeaconHeaderNumber; + _tryToRecoverFromHeaderBelowBodyCorruption = true; + } + else + { + throw new InvalidDataException("Invalid initial block tree state loaded - " + + $"best known: {bestKnownNumberFound}|" + + $"best header: {bestBeaconHeaderNumber}|" + + $"best body: {bestBeaconBodyNumber}|"); + } + } + + BestKnownBeaconNumber = bestKnownNumberFound; + BestSuggestedBeaconHeader = FindHeader(bestBeaconHeaderNumber, BlockTreeLookupOptions.TotalDifficultyNotNeeded); + BlockHeader? bestBeaconBodyHeader = FindHeader(bestBeaconBodyNumber, BlockTreeLookupOptions.TotalDifficultyNotNeeded); + BestSuggestedBeaconBody = bestBeaconBodyHeader is null + ? null + : FindBlock(bestBeaconBodyHeader.Hash, BlockTreeLookupOptions.TotalDifficultyNotNeeded); + } + + private enum BinarySearchDirection + { + Up, + Down + } + + private BlockHeader? BinarySearchBlockHeader(long left, long right, Func isBlockFound, + BinarySearchDirection direction = BinarySearchDirection.Up) + { + long? blockNumber = BinarySearchBlockNumber(left, right, isBlockFound, direction); + if (blockNumber.HasValue) + { + ChainLevelInfo? level = LoadLevel(blockNumber.Value); + if (level is null) + { + throw new InvalidDataException( + $"Missing chain level at number {blockNumber.Value}"); + } + + BlockInfo blockInfo = level.BlockInfos[0]; + return FindHeader(blockInfo.BlockHash, BlockTreeLookupOptions.None); + } + + return null; + } + + private static long? BinarySearchBlockNumber(long left, long right, Func isBlockFound, + BinarySearchDirection direction = BinarySearchDirection.Up, bool findBeacon = false) + { + if (left > right) + { + return null; + } + + long? result = null; + while (left != right) + { + long index = direction == BinarySearchDirection.Up + ? left + (right - left) / 2 + : right - (right - left) / 2; + if (isBlockFound(index, findBeacon)) + { + result = index; + if (direction == BinarySearchDirection.Up) + { + left = index + 1; + } + else + { + right = index - 1; + } + } + else + { + if (direction == BinarySearchDirection.Up) + { + right = index; + } + else + { + left = index; + } + } + } + + if (isBlockFound(left, findBeacon)) + { + result = direction == BinarySearchDirection.Up ? left : right; + } + + return result; + } + public AddBlockResult Insert(BlockHeader header, BlockTreeInsertHeaderOptions headerOptions = BlockTreeInsertHeaderOptions.None) { if (!CanAcceptNewBlocks) @@ -1199,6 +1511,59 @@ private bool BestSuggestedImprovementRequirementsSatisfied(BlockHeader header) return preMergeImprovementRequirementSatisfied || terminalBlockRequirementSatisfied || postMergeImprovementRequirementSatisfied; } + private void LoadStartBlock() + { + Block? startBlock = null; + byte[] persistedNumberData = _blockInfoDb.Get(StateHeadHashDbEntryAddress); + BestPersistedState = persistedNumberData is null ? null : new RlpStream(persistedNumberData).DecodeLong(); + long? persistedNumber = BestPersistedState; + if (persistedNumber is not null) + { + startBlock = FindBlock(persistedNumber.Value, BlockTreeLookupOptions.None); + if (_logger.IsInfo) _logger.Info( + $"Start block loaded from reorg boundary - {persistedNumber} - {startBlock?.ToString(Block.Format.Short)}"); + } + else + { + byte[] data = _blockInfoDb.Get(HeadAddressInDb); + if (data is not null) + { + startBlock = FindBlock(new Keccak(data), BlockTreeLookupOptions.None); + if (_logger.IsInfo) _logger.Info($"Start block loaded from HEAD - {startBlock?.ToString(Block.Format.Short)}"); + } + } + + if (startBlock is not null) + { + if (startBlock.Hash is null) + { + throw new InvalidDataException("The start block hash is null."); + } + + SetHeadBlock(startBlock.Hash); + } + } + + private void SetHeadBlock(Keccak headHash) + { + Block? headBlock = FindBlock(headHash, BlockTreeLookupOptions.None); + if (headBlock is null) + { + throw new InvalidOperationException( + "An attempt to set a head block that has not been stored in the DB."); + } + + ChainLevelInfo? level = LoadLevel(headBlock.Number); + int? index = level?.FindIndex(headHash); + if (!index.HasValue) + { + throw new InvalidDataException("Head block data missing from chain info"); + } + + headBlock.Header.TotalDifficulty = level.BlockInfos[index.Value].TotalDifficulty; + Head = headBlock; + } + public bool IsKnownBlock(long number, Keccak blockHash) { if (number > BestKnownNumber) diff --git a/src/Nethermind/Nethermind.Blockchain/Blocks/BlockStore.cs b/src/Nethermind/Nethermind.Blockchain/Blocks/BlockStore.cs index 8c558048abe..150543e6843 100644 --- a/src/Nethermind/Nethermind.Blockchain/Blocks/BlockStore.cs +++ b/src/Nethermind/Nethermind.Blockchain/Blocks/BlockStore.cs @@ -3,6 +3,7 @@ using System; using System.Buffers; +using System.Runtime.InteropServices; using Nethermind.Core; using Nethermind.Core.Caching; using Nethermind.Core.Crypto; diff --git a/src/Nethermind/Nethermind.Blockchain/Contracts/CallableContract.cs b/src/Nethermind/Nethermind.Blockchain/Contracts/CallableContract.cs index 5d3964f7204..41dff35a7c9 100644 --- a/src/Nethermind/Nethermind.Blockchain/Contracts/CallableContract.cs +++ b/src/Nethermind/Nethermind.Blockchain/Contracts/CallableContract.cs @@ -66,7 +66,7 @@ private bool TryCall(BlockHeader header, Transaction transaction, out byte[] res try { - _transactionProcessor.Execute(transaction, new BlockExecutionContext(header), tracer); + _transactionProcessor.Execute(transaction, header, tracer); result = tracer.ReturnValue; return tracer.StatusCode == StatusCode.Success; } diff --git a/src/Nethermind/Nethermind.Blockchain/Contracts/Contract.cs b/src/Nethermind/Nethermind.Blockchain/Contracts/Contract.cs index efb89e16a7f..dfa733b619e 100644 --- a/src/Nethermind/Nethermind.Blockchain/Contracts/Contract.cs +++ b/src/Nethermind/Nethermind.Blockchain/Contracts/Contract.cs @@ -178,11 +178,11 @@ protected byte[] CallCore(ITransactionProcessor transactionProcessor, BlockHeade { if (callAndRestore) { - transactionProcessor.CallAndRestore(transaction, new BlockExecutionContext(header), tracer); + transactionProcessor.CallAndRestore(transaction, header, tracer); } else { - transactionProcessor.Execute(transaction, new BlockExecutionContext(header), tracer); + transactionProcessor.Execute(transaction, header, tracer); } failure = tracer.StatusCode != StatusCode.Success; diff --git a/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs b/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs index 1fcd84181f6..283e2f4304a 100644 --- a/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs +++ b/src/Nethermind/Nethermind.Blockchain/Find/BlockParameter.cs @@ -61,9 +61,5 @@ public override bool Equals(object? obj) } public override int GetHashCode() => HashCode.Combine(Type, BlockNumber, BlockHash, RequireCanonical); - - public static bool operator ==(BlockParameter? left, BlockParameter? right) => Equals(left, right); - - public static bool operator !=(BlockParameter? left, BlockParameter? right) => !Equals(left, right); } } diff --git a/src/Nethermind/Nethermind.Blockchain/Find/ResourceNotFoundException.cs b/src/Nethermind/Nethermind.Blockchain/Find/ResourceNotFoundException.cs index 8334e06e52a..24c4c3f81a7 100644 --- a/src/Nethermind/Nethermind.Blockchain/Find/ResourceNotFoundException.cs +++ b/src/Nethermind/Nethermind.Blockchain/Find/ResourceNotFoundException.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Transactions; namespace Nethermind.Blockchain.Find; diff --git a/src/Nethermind/Nethermind.Blockchain/FullPruning/CompositePruningTrigger.cs b/src/Nethermind/Nethermind.Blockchain/FullPruning/CompositePruningTrigger.cs index 49f20bb7e2e..3e0aab8bfe4 100644 --- a/src/Nethermind/Nethermind.Blockchain/FullPruning/CompositePruningTrigger.cs +++ b/src/Nethermind/Nethermind.Blockchain/FullPruning/CompositePruningTrigger.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; namespace Nethermind.Blockchain.FullPruning; diff --git a/src/Nethermind/Nethermind.Blockchain/FullPruning/CopyTreeVisitor.cs b/src/Nethermind/Nethermind.Blockchain/FullPruning/CopyTreeVisitor.cs index 6a80ba86ffa..3e929ff2ea8 100644 --- a/src/Nethermind/Nethermind.Blockchain/FullPruning/CopyTreeVisitor.cs +++ b/src/Nethermind/Nethermind.Blockchain/FullPruning/CopyTreeVisitor.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using System.Threading; using Nethermind.Core; -using Nethermind.Core.Buffers; using Nethermind.Core.Crypto; using Nethermind.Db.FullPruning; using Nethermind.Logging; @@ -75,7 +74,7 @@ private void PersistNode(TrieNode node) if (node.Keccak is not null) { // simple copy of nodes RLP - _pruningContext.Set(node.Keccak.Bytes, node.FullRlp.ToArray(), _writeFlags); + _pruningContext.Set(node.Keccak.Bytes, node.FullRlp, _writeFlags); Interlocked.Increment(ref _persistedNodes); // log message every 1 mln nodes diff --git a/src/Nethermind/Nethermind.Blockchain/FullPruning/FullPruner.cs b/src/Nethermind/Nethermind.Blockchain/FullPruning/FullPruner.cs index e318c0dff6c..fb27c76f176 100755 --- a/src/Nethermind/Nethermind.Blockchain/FullPruning/FullPruner.cs +++ b/src/Nethermind/Nethermind.Blockchain/FullPruning/FullPruner.cs @@ -30,7 +30,7 @@ public class FullPruner : IDisposable private readonly IProcessExitSource _processExitSource; private readonly ILogManager _logManager; private readonly IChainEstimations _chainEstimations; - private readonly IDriveInfo? _driveInfo; + private readonly IDriveInfo _driveInfo; private IPruningContext? _currentPruning; private int _waitingForBlockProcessed = 0; private int _waitingForStateReady = 0; @@ -48,7 +48,7 @@ public FullPruner( IStateReader stateReader, IProcessExitSource processExitSource, IChainEstimations chainEstimations, - IDriveInfo? driveInfo, + IDriveInfo driveInfo, ILogManager logManager) { _fullPruningDb = fullPruningDb; @@ -138,7 +138,7 @@ private void OnUpdateMainChain(object? sender, OnUpdateMainChainArgs e) BlockHeader? header = _blockTree.FindHeader(_stateToCopy); if (header is not null && Interlocked.CompareExchange(ref _waitingForStateReady, 0, 1) == 1) { - if (_logger.IsInfo) _logger.Info($"Full Pruning Ready to start: pruning garbage before state {_stateToCopy} with root {header.StateRoot}"); + if (_logger.IsInfo) _logger.Info($"Full Pruning Ready to start: pruning garbage before state {_stateToCopy} with root {header.StateRoot}."); Task.Run(() => RunPruning(_currentPruning, header.StateRoot!)); _blockTree.OnUpdateMainChain -= OnUpdateMainChain; } @@ -181,13 +181,12 @@ private bool HaveEnoughDiskSpaceToRun() return true; } - long available = _driveInfo?.AvailableFreeSpace ?? 0; - long required = currentChainSize.Value * ChainSizeThresholdFactor / 100; - if (available < required) + long available = _driveInfo.AvailableFreeSpace; + if (available < currentChainSize.Value * ChainSizeThresholdFactor / 100) { if (_logger.IsWarn) _logger.Warn( - $"Not enough disk space to run full pruning. Required {required / 1.GB()} GB. Have {available / 1.GB()} GB"); + $"Not enough disk space to run full pruning. Required {(currentChainSize * ChainSizeThresholdFactor) / 1.GB()} GB. Have {available / 1.GB()} GB"); return false; } return true; @@ -223,7 +222,6 @@ protected virtual void RunPruning(IPruningContext pruning, Keccak statRoot) MaxDegreeOfParallelism = _pruningConfig.FullPruningMaxDegreeOfParallelism, FullScanMemoryBudget = ((long)_pruningConfig.FullPruningMemoryBudgetMb).MiB(), }; - if (_logger.IsInfo) _logger.Info($"Full pruning started with MaxDegreeOfParallelism: {visitingOptions.MaxDegreeOfParallelism} and FullScanMemoryBudget: {visitingOptions.FullScanMemoryBudget}"); _stateReader.RunTreeVisitor(copyTreeVisitor, statRoot, visitingOptions); if (!pruning.CancellationTokenSource.IsCancellationRequested) diff --git a/src/Nethermind/Nethermind.Blockchain/FullPruning/PathSizePruningTrigger.cs b/src/Nethermind/Nethermind.Blockchain/FullPruning/PathSizePruningTrigger.cs index c3c453153d4..a1586323a1d 100644 --- a/src/Nethermind/Nethermind.Blockchain/FullPruning/PathSizePruningTrigger.cs +++ b/src/Nethermind/Nethermind.Blockchain/FullPruning/PathSizePruningTrigger.cs @@ -3,8 +3,10 @@ using System; using System.Collections.Generic; +using System.IO; using System.IO.Abstractions; using System.Linq; +using System.Threading; using Nethermind.Core.Timers; namespace Nethermind.Blockchain.FullPruning diff --git a/src/Nethermind/Nethermind.Blockchain/GenesisLoader.cs b/src/Nethermind/Nethermind.Blockchain/GenesisLoader.cs index b135a4a04ae..8cac17f0ed3 100644 --- a/src/Nethermind/Nethermind.Blockchain/GenesisLoader.cs +++ b/src/Nethermind/Nethermind.Blockchain/GenesisLoader.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Crypto; @@ -14,7 +15,6 @@ using Nethermind.Evm.TransactionProcessing; using Nethermind.Specs.ChainSpecStyle; using Nethermind.State; -using Nethermind.Consensus.BeaconBlockRoot; namespace Nethermind.Blockchain { @@ -24,7 +24,6 @@ public class GenesisLoader private readonly ISpecProvider _specProvider; private readonly IWorldState _stateProvider; private readonly ITransactionProcessor _transactionProcessor; - private readonly BeaconBlockRootHandler _beaconBlockRootHandler; public GenesisLoader( ChainSpec chainSpec, @@ -36,7 +35,6 @@ public GenesisLoader( _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); _stateProvider = stateProvider ?? throw new ArgumentNullException(nameof(stateProvider)); _transactionProcessor = transactionProcessor ?? throw new ArgumentNullException(nameof(transactionProcessor)); - _beaconBlockRootHandler = new BeaconBlockRootHandler(); } public Block Load() @@ -87,7 +85,7 @@ private void Preallocate(Block genesis) }; CallOutputTracer outputTracer = new(); - _transactionProcessor.Execute(constructorTransaction, new BlockExecutionContext(genesis.Header), outputTracer); + _transactionProcessor.Execute(constructorTransaction, genesis.Header, outputTracer); if (outputTracer.StatusCode != StatusCode.Success) { diff --git a/src/Nethermind/Nethermind.Blockchain/IBlockTree.cs b/src/Nethermind/Nethermind.Blockchain/IBlockTree.cs index 9e052632cf2..ac680bc9b5f 100644 --- a/src/Nethermind/Nethermind.Blockchain/IBlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/IBlockTree.cs @@ -9,6 +9,7 @@ using Nethermind.Blockchain.Visitors; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Int256; namespace Nethermind.Blockchain { @@ -158,6 +159,8 @@ AddBlockResult Insert(Block block, BlockTreeInsertBlockOptions insertBlockOption void ForkChoiceUpdated(Keccak? finalizedBlockHash, Keccak? safeBlockBlockHash); + void LoadLowestInsertedBeaconHeader(); + event EventHandler NewBestSuggestedBlock; event EventHandler NewSuggestedBlock; diff --git a/src/Nethermind/Nethermind.Blockchain/KnownChainSizes.cs b/src/Nethermind/Nethermind.Blockchain/KnownChainSizes.cs index 28724697b02..3b25442fb62 100644 --- a/src/Nethermind/Nethermind.Blockchain/KnownChainSizes.cs +++ b/src/Nethermind/Nethermind.Blockchain/KnownChainSizes.cs @@ -69,15 +69,15 @@ public static IChainEstimations CreateChainSizeInfo(ulong chainId) return chainId switch { BlockchainIds.Goerli => new ChainEstimations( - new LinearExtrapolation(50.GB(), 15.MB(), new DateTime(2023, 07, 14)), + new LinearExtrapolation(8490.MB(), 15.MB(), new DateTime(2021, 12, 7)), new LinearExtrapolation( 49311060515, new(2023, 05, 20, 1, 31, 00), 52341479114, new(2023, 06, 07, 20, 12, 00))), BlockchainIds.Mainnet => new ChainEstimations( - new LinearExtrapolation(167.GB(), 70.MB(), new DateTime(2023, 07, 14)), + new LinearExtrapolation(90000.MB(), 70.MB(), new DateTime(2022, 04, 7)), new LinearExtrapolation( - 177439054863, new DateTime(2023, 06, 8, 02, 36, 0), - 188742060333, new DateTime(2023, 09, 26, 19, 32, 0))), + 172553555637, new DateTime(2023, 05, 18, 18, 12, 0), + 177439054863, new DateTime(2023, 06, 8, 02, 36, 0))), BlockchainIds.Gnosis => new ChainEstimations( new LinearExtrapolation(18000.MB(), 48.MB(), new DateTime(2021, 12, 7))), BlockchainIds.EnergyWeb => new ChainEstimations( diff --git a/src/Nethermind/Nethermind.Blockchain/LogTraceDumper.cs b/src/Nethermind/Nethermind.Blockchain/LogTraceDumper.cs index 2164563bf1a..8a3029eb1cf 100644 --- a/src/Nethermind/Nethermind.Blockchain/LogTraceDumper.cs +++ b/src/Nethermind/Nethermind.Blockchain/LogTraceDumper.cs @@ -13,71 +13,72 @@ using Nethermind.Serialization.Json; using Newtonsoft.Json; -namespace Nethermind.Blockchain; - -public static class BlockTraceDumper +namespace Nethermind.Blockchain { - public static List Converters { get; } = new List(); - - public static void LogDiagnosticTrace( - IBlockTracer blockTracer, - Keccak blockHash, - ILogger logger) + public static class BlockTraceDumper { - static FileStream GetFileStream(string name) => - new( - Path.Combine(Path.GetTempPath(), name), - FileMode.Create, - FileAccess.Write); + public static List Converters { get; } = new List(); - string fileName = string.Empty; - - try + public static void LogDiagnosticTrace( + IBlockTracer blockTracer, + Keccak blockHash, + ILogger logger) { - IJsonSerializer serializer = new EthereumJsonSerializer(); - serializer.RegisterConverters(Converters); + static FileStream GetFileStream(string name) => + new( + Path.Combine(Path.GetTempPath(), name), + FileMode.Create, + FileAccess.Write); + + string fileName = string.Empty; - if (blockTracer is BlockReceiptsTracer receiptsTracer) + try { - fileName = $"receipts_{blockHash}.txt"; - using FileStream diagnosticFile = GetFileStream(fileName); - IReadOnlyList receipts = receiptsTracer.TxReceipts; - serializer.Serialize(diagnosticFile, receipts, true); - if (logger.IsInfo) - logger.Info($"Created a Receipts trace of block {blockHash} in file {diagnosticFile.Name}"); + IJsonSerializer serializer = new EthereumJsonSerializer(); + serializer.RegisterConverters(Converters); - } + if (blockTracer is BlockReceiptsTracer receiptsTracer) + { + fileName = $"receipts_{blockHash}.txt"; + using FileStream diagnosticFile = GetFileStream(fileName); + IReadOnlyList receipts = receiptsTracer.TxReceipts; + serializer.Serialize(diagnosticFile, receipts, true); + if (logger.IsInfo) + logger.Info($"Created a Receipts trace of block {blockHash} in file {diagnosticFile.Name}"); - if (blockTracer is GethLikeBlockMemoryTracer gethTracer) - { - fileName = $"gethStyle_{blockHash}.txt"; - using FileStream diagnosticFile = GetFileStream(fileName); - IReadOnlyCollection trace = gethTracer.BuildResult(); - serializer.Serialize(diagnosticFile, trace, true); - if (logger.IsInfo) - logger.Info($"Created a Geth-style trace of block {blockHash} in file {diagnosticFile.Name}"); - } + } - if (blockTracer is ParityLikeBlockTracer parityTracer) + if (blockTracer is GethLikeBlockTracer gethTracer) + { + fileName = $"gethStyle_{blockHash}.txt"; + using FileStream diagnosticFile = GetFileStream(fileName); + IReadOnlyCollection trace = gethTracer.BuildResult(); + serializer.Serialize(diagnosticFile, trace, true); + if (logger.IsInfo) + logger.Info($"Created a Geth-style trace of block {blockHash} in file {diagnosticFile.Name}"); + } + + if (blockTracer is ParityLikeBlockTracer parityTracer) + { + fileName = $"parityStyle_{blockHash}.txt"; + using FileStream diagnosticFile = GetFileStream(fileName); + IReadOnlyCollection trace = parityTracer.BuildResult(); + serializer.Serialize(diagnosticFile, trace, true); + if (logger.IsInfo) + logger.Info($"Created a Parity-style trace of block {blockHash} in file {diagnosticFile.Name}"); + } + } + catch (IOException e) { - fileName = $"parityStyle_{blockHash}.txt"; - using FileStream diagnosticFile = GetFileStream(fileName); - IReadOnlyCollection trace = parityTracer.BuildResult(); - serializer.Serialize(diagnosticFile, trace, true); - if (logger.IsInfo) - logger.Info($"Created a Parity-style trace of block {blockHash} in file {diagnosticFile.Name}"); + if (logger.IsError) + logger.Error($"Cannot save trace of block {blockHash} in file {fileName}", e); } } - catch (IOException e) + + public static void LogTraceFailure(IBlockTracer blockTracer, Keccak blockHash, Exception exception, ILogger logger) { if (logger.IsError) - logger.Error($"Cannot save trace of block {blockHash} in file {fileName}", e); + logger.Error($"Cannot create trace of blocks starting from {blockHash} of type {blockTracer.GetType().Name}", exception); } } - - public static void LogTraceFailure(IBlockTracer blockTracer, Keccak blockHash, Exception exception, ILogger logger) - { - if (logger.IsError) - logger.Error($"Cannot create trace of blocks starting from {blockHash} of type {blockTracer.GetType().Name}", exception); - } } diff --git a/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs b/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs index d222198e183..09a5478791a 100644 --- a/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs @@ -122,6 +122,8 @@ public void UpdateHeadBlock(Keccak blockHash) public bool WasProcessed(long number, Keccak blockHash) => _wrapped.WasProcessed(number, blockHash); + public void LoadLowestInsertedBeaconHeader() => _wrapped.LoadLowestInsertedBeaconHeader(); + public event EventHandler NewBestSuggestedBlock { add { } diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptConfig.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptConfig.cs index aae9dfbaf5a..43df1c23317 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptConfig.cs @@ -13,12 +13,6 @@ public interface IReceiptConfig : IConfig [ConfigItem(Description = "If set to 'true' then receipts db will be migrated to new schema.", DefaultValue = "false")] bool ReceiptsMigration { get; set; } - [ConfigItem(Description = "[TECHNICAL] Specify degree of parallelism during receipt migration.", DefaultValue = "0", HiddenFromDocs = true)] - int ReceiptsMigrationDegreeOfParallelism { get; set; } - - [ConfigItem(Description = "Force receipt recovery if its not able to detect it.", DefaultValue = "false", HiddenFromDocs = true)] - bool ForceReceiptsMigration { get; set; } - [ConfigItem(Description = "If set to 'true' then reduce receipt db size at expense of rpc performance.", DefaultValue = "true")] bool CompactReceiptStore { get; set; } diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptStorage.cs index 30688d73b6d..e2ce64e5785 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptStorage.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Core; using Nethermind.Core.Crypto; diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs index a16c552c6f6..da8b503dd32 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs @@ -3,8 +3,12 @@ using System; using System.Collections.Concurrent; +using System.Linq; +using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Db; +using Nethermind.Serialization.Rlp; namespace Nethermind.Blockchain.Receipts { diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs index 24425624ead..cc3b57ee6d5 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs @@ -80,7 +80,6 @@ private void BlockTreeOnBlockAddedToMain(object? sender, BlockReplacementEventAr // Dont block main loop Task.Run(() => { - Block newMain = e.Block; // Delete old tx index @@ -89,12 +88,20 @@ private void BlockTreeOnBlockAddedToMain(object? sender, BlockReplacementEventAr Block newOldTx = _blockTree.FindBlock(newMain.Number - _receiptConfig.TxLookupLimit.Value); if (newOldTx != null) { - RemoveBlockTx(newOldTx); + ClearTxIndexForBlock(newOldTx); } } }); } + private void ClearTxIndexForBlock(Block block) + { + foreach (Transaction transaction in block.Transactions) + { + _transactionDb[transaction.Hash.Bytes] = null; + } + } + public Keccak FindBlockHash(Keccak txHash) { var blockHashData = _transactionDb.Get(txHash); diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptConfig.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptConfig.cs index fe7c36fa121..b392d4f8c48 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptConfig.cs @@ -7,8 +7,6 @@ public class ReceiptConfig : IReceiptConfig { public bool StoreReceipts { get; set; } = true; public bool ReceiptsMigration { get; set; } = false; - public int ReceiptsMigrationDegreeOfParallelism { get; set; } = 0; - public bool ForceReceiptsMigration { get; set; } = false; public bool CompactReceiptStore { get; set; } = true; public bool CompactTxIndex { get; set; } = true; public long? TxLookupLimit { get; set; } = 2350000; diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptsExtensions.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptsExtensions.cs index 17ea3273b95..d1be4df28e7 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptsExtensions.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptsExtensions.cs @@ -6,7 +6,6 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.State.Proofs; -using Nethermind.Trie; namespace Nethermind.Blockchain.Receipts { @@ -30,7 +29,7 @@ Keccak SkipStateAndStatusReceiptsRoot() txReceipts.SetSkipStateAndStatusInRlp(true); try { - return ReceiptTrie.CalculateRoot(receiptSpec, txReceipts); + return new ReceiptTrie(receiptSpec, txReceipts).RootHash; } finally { @@ -38,7 +37,7 @@ Keccak SkipStateAndStatusReceiptsRoot() } } - Keccak receiptsRoot = ReceiptTrie.CalculateRoot(receiptSpec, txReceipts); + Keccak receiptsRoot = new ReceiptTrie(receiptSpec, txReceipts).RootHash; if (!receiptSpec.ValidateReceipts && receiptsRoot != suggestedRoot) { var skipStateAndStatusReceiptsRoot = SkipStateAndStatusReceiptsRoot(); diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptsIterator.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptsIterator.cs index b7efc6b0891..b95f2b1af5a 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptsIterator.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptsIterator.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Db; diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptsRecovery.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptsRecovery.cs index e0257f41eb6..69f9a5f37d8 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptsRecovery.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/ReceiptsRecovery.cs @@ -3,6 +3,7 @@ using System; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Crypto; using Nethermind.Evm; @@ -66,7 +67,6 @@ public bool NeedRecover(TxReceipt[] receipts, bool forceRecoverSender = true, bo if (receipts is null || receipts.Length == 0) return false; if (recoverSenderOnly) return (forceRecoverSender && receipts[0].Sender is null); - return (receipts[0].BlockHash is null || (forceRecoverSender && receipts[0].Sender is null)); } @@ -97,17 +97,12 @@ public void RecoverReceiptData(TxReceipt receipt) Transaction transaction = _block.GetNextTransaction(); - if (transaction.SenderAddress is null && _forceRecoverSender) - { - transaction.SenderAddress = _ecdsa.RecoverAddress(transaction, !_releaseSpec.ValidateChainId); - } - receipt.TxType = transaction.Type; receipt.BlockHash = _block.Hash; receipt.BlockNumber = _block.Number; receipt.TxHash = transaction.Hash; receipt.Index = _transactionIndex; - receipt.Sender ??= transaction.SenderAddress; + receipt.Sender ??= transaction.SenderAddress ?? (_forceRecoverSender ? _ecdsa.RecoverAddress(transaction, !_releaseSpec.ValidateChainId) : null); receipt.Recipient = transaction.IsContractCreation ? null : transaction.To; // how would it be in CREATE2? diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISnapSyncPeer.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISnapSyncPeer.cs index f9ddf91b4f8..e1cb0a090d0 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISnapSyncPeer.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISnapSyncPeer.cs @@ -1,7 +1,10 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; +using System.Linq; +using System.Text; using System.Threading; using System.Threading.Tasks; using Nethermind.Core.Crypto; diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs index 7b62189c959..4610dad14e4 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs @@ -61,7 +61,7 @@ public interface ISyncConfig : IConfig [ConfigItem(DisabledForCli = true, HiddenFromDocs = true)] Keccak? PivotHashParsed => PivotHash is null ? null : new Keccak(Bytes.FromHexString(PivotHash)); - [ConfigItem(Description = "Max number of attempts (seconds) to update pivot block basing on Forkchoice message from Consensus Layer. Only for PoS chains. Infinite by default.", DefaultValue = "2147483647")] + [ConfigItem(Description = "Max number of attempts (seconds) to update pivot block basing on Forkchoice message from Consensus Layer. Only for PoS chains.", DefaultValue = "900")] int MaxAttemptsToUpdatePivot { get; set; } [ConfigItem(Description = "[EXPERIMENTAL] Defines the earliest body downloaded in fast sync when DownloadBodiesInFastSync is enabled. Actual values used will be Math.Max(1, Math.Min(PivotNumber, AncientBodiesBarrier))", DefaultValue = "0")] @@ -104,7 +104,7 @@ public interface ISyncConfig : IConfig [ConfigItem(Description = "[EXPERIMENTAL] Only for non validator nodes! If set to true, DownloadReceiptsInFastSync and/or DownloadBodiesInFastSync can be set to false.", DefaultValue = "false")] public bool NonValidatorNode { get; set; } - [ConfigItem(Description = "[EXPERIMENTAL] Optimize db for write during sync. Significantly reduce total writes written and some sync time if you are not network limited.", DefaultValue = "HeavyWrite")] + [ConfigItem(Description = "[EXPERIMENTAL] Optimize db for write during sync. Significantly reduce total writes written and some sync time if you are not network limited.", DefaultValue = "Default")] public ITunableDb.TuneType TuneDbMode { get; set; } [ConfigItem(Description = "[EXPERIMENTAL] Optimize db for write during sync just for blocks db. Useful for turning on blobs file.", DefaultValue = "EnableBlobFiles")] @@ -112,17 +112,5 @@ public interface ISyncConfig : IConfig [ConfigItem(Description = "[TECHNICAL] Specify max num of thread used for processing. Default is same as logical core count.", DefaultValue = "0")] public int MaxProcessingThreads { get; set; } - - [ConfigItem(Description = "Enables healing trie from network when state is corrupted.", DefaultValue = "true", HiddenFromDocs = true)] - public bool TrieHealing { get; set; } - - [ConfigItem(Description = "Exit Nethermind once sync is finished", DefaultValue = "false")] - public bool ExitOnSynced { get; set; } - - [ConfigItem(Description = "Specify wait time after sync finished.", DefaultValue = "60")] - public int ExitOnSyncedWaitTimeSec { get; set; } - - [ConfigItem(Description = "[TECHNICAL] specify interval between malloc_trim during sync", DefaultValue = "300", HiddenFromDocs = true)] - public int MallocTrimIntervalSec { get; set; } } } diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncPeer.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncPeer.cs index 3b3403e81a2..379ef3b84b7 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncPeer.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncPeer.cs @@ -21,7 +21,6 @@ public interface ISyncPeer : ITxPoolPeer, IPeerWithSatelliteProtocol { Node Node { get; } - string Name { get; } string ClientId => Node?.ClientId; NodeClientType ClientType => Node?.ClientType ?? NodeClientType.Unknown; Keccak HeadHash { get; set; } @@ -31,8 +30,8 @@ public interface ISyncPeer : ITxPoolPeer, IPeerWithSatelliteProtocol bool IsPriority { get; set; } byte ProtocolVersion { get; } string ProtocolCode { get; } - void Disconnect(DisconnectReason reason, string details); - Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token); + void Disconnect(InitiateDisconnectReason reason, string details); + Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token); Task GetBlockHeaders(long number, int maxBlocks, int skip, CancellationToken token); Task GetBlockHeaders(Keccak startHash, int maxBlocks, int skip, CancellationToken token); Task GetHeadBlockHeader(Keccak? hash, CancellationToken token); diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs index 97608552ae9..8734473a792 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs @@ -49,7 +49,7 @@ public string? PivotHash get => FastSync || SnapSync ? _pivotHash : null; set => _pivotHash = value; } - public int MaxAttemptsToUpdatePivot { get; set; } = int.MaxValue; + public int MaxAttemptsToUpdatePivot { get; set; } = 900; public bool WitnessProtocolEnabled { get; set; } = false; public bool SnapSync { get; set; } = false; public int SnapSyncAccountRangePartitionCount { get; set; } = 8; @@ -60,13 +60,9 @@ public string? PivotHash public bool StrictMode { get; set; } = false; public bool BlockGossipEnabled { get; set; } = true; public bool NonValidatorNode { get; set; } = false; - public ITunableDb.TuneType TuneDbMode { get; set; } = ITunableDb.TuneType.HeavyWrite; + public ITunableDb.TuneType TuneDbMode { get; set; } = ITunableDb.TuneType.Default; public ITunableDb.TuneType BlocksDbTuneDbMode { get; set; } = ITunableDb.TuneType.EnableBlobFiles; public int MaxProcessingThreads { get; set; } - public bool ExitOnSynced { get; set; } = false; - public int ExitOnSyncedWaitTimeSec { get; set; } = 60; - public int MallocTrimIntervalSec { get; set; } = 300; - public bool TrieHealing { get; set; } = true; public override string ToString() { diff --git a/src/Nethermind/Nethermind.Cli/Console/CliConsole.cs b/src/Nethermind/Nethermind.Cli/Console/CliConsole.cs index 274d5ed0284..140427a3271 100644 --- a/src/Nethermind/Nethermind.Cli/Console/CliConsole.cs +++ b/src/Nethermind/Nethermind.Cli/Console/CliConsole.cs @@ -25,19 +25,19 @@ public CliConsole() { _terminal = PrepareConsoleForTerminal(); - System.Console.WriteLine("**********************************************"); - System.Console.WriteLine(); - System.Console.WriteLine("Nethermind CLI {0}", ProductInfo.Version); - System.Console.WriteLine(" https://github.com/NethermindEth/nethermind"); - System.Console.WriteLine(" https://nethermind.readthedocs.io/en/latest/"); - System.Console.WriteLine(); - System.Console.WriteLine("powered by:"); - System.Console.WriteLine(" https://github.com/sebastienros/jint"); - System.Console.WriteLine(" https://github.com/tomakita/Colorful.Console"); - System.Console.WriteLine(" https://github.com/tonerdo/readline"); - System.Console.WriteLine(); - System.Console.WriteLine("**********************************************"); - System.Console.WriteLine(); + //System.Console.WriteLine("**********************************************"); + //System.Console.WriteLine(); + //System.Console.WriteLine("Nethermind CLI {0}", ProductInfo.Version); + //System.Console.WriteLine(" https://github.com/NethermindEth/nethermind"); + //System.Console.WriteLine(" https://nethermind.readthedocs.io/en/latest/"); + //System.Console.WriteLine(); + //System.Console.WriteLine("powered by:"); + //System.Console.WriteLine(" https://github.com/sebastienros/jint"); + //System.Console.WriteLine(" https://github.com/tomakita/Colorful.Console"); + //System.Console.WriteLine(" https://github.com/tonerdo/readline"); + //System.Console.WriteLine(); + //System.Console.WriteLine("**********************************************"); + //System.Console.WriteLine(); } protected Terminal GetTerminal() diff --git a/src/Nethermind/Nethermind.Cli/Modules/PersonalCliModule.cs b/src/Nethermind/Nethermind.Cli/Modules/PersonalCliModule.cs index cbde29764a9..9cedd3bb401 100644 --- a/src/Nethermind/Nethermind.Cli/Modules/PersonalCliModule.cs +++ b/src/Nethermind/Nethermind.Cli/Modules/PersonalCliModule.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using Jint.Native; +using Nethermind.JsonRpc.Data; namespace Nethermind.Cli.Modules { diff --git a/src/Nethermind/Nethermind.Cli/Nethermind.Cli.csproj b/src/Nethermind/Nethermind.Cli/Nethermind.Cli.csproj index f0a2b11c5bc..fca16b9b62c 100644 --- a/src/Nethermind/Nethermind.Cli/Nethermind.Cli.csproj +++ b/src/Nethermind/Nethermind.Cli/Nethermind.Cli.csproj @@ -4,7 +4,6 @@ net7.0 true Exe - nethermind-cli Nethermind CLI Nethermind 1.0.0 @@ -15,7 +14,7 @@ - + diff --git a/src/Nethermind/Nethermind.Cli/NodeManager.cs b/src/Nethermind/Nethermind.Cli/NodeManager.cs index e326dd637c1..817c7255278 100644 --- a/src/Nethermind/Nethermind.Cli/NodeManager.cs +++ b/src/Nethermind/Nethermind.Cli/NodeManager.cs @@ -63,7 +63,7 @@ public async Task PostJint(string method, params object[] parameters) { if (_currentClient is null) { - _cliConsole.WriteErrorLine("[INTERNAL ERROR] JSON RPC client not set."); + //_cliConsole.WriteErrorLine("[INTERNAL ERROR] JSON RPC client not set."); } else { @@ -115,7 +115,7 @@ public async Task PostJint(string method, params object[] parameters) { if (_currentClient is null) { - _cliConsole.WriteErrorLine("[INTERNAL ERROR] JSON RPC client not set."); + //_cliConsole.WriteErrorLine("[INTERNAL ERROR] JSON RPC client not set."); } else { diff --git a/src/Nethermind/Nethermind.Clique.Test/CliqueHealthHintServiceTests.cs b/src/Nethermind/Nethermind.Clique.Test/CliqueHealthHintServiceTests.cs index fb16d67607c..edeed4bf053 100644 --- a/src/Nethermind/Nethermind.Clique.Test/CliqueHealthHintServiceTests.cs +++ b/src/Nethermind/Nethermind.Clique.Test/CliqueHealthHintServiceTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using Nethermind.Blockchain; using Nethermind.Blockchain.Services; using Nethermind.Consensus.Clique; using Nethermind.Core; diff --git a/src/Nethermind/Nethermind.Clique.Test/CliqueRpcModuleTests.cs b/src/Nethermind/Nethermind.Clique.Test/CliqueRpcModuleTests.cs index 5a335a07e2a..fd2c0ee9ba4 100644 --- a/src/Nethermind/Nethermind.Clique.Test/CliqueRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.Clique.Test/CliqueRpcModuleTests.cs @@ -31,7 +31,7 @@ public void Sets_clique_block_producer_properly() { CliqueConfig cliqueConfig = new(); IBlockTree blockTree = Substitute.For(); - Signer signer = new(BlockchainIds.Sepolia, TestItem.PrivateKeyA, LimboLogs.Instance); + Signer signer = new(BlockchainIds.Ropsten, TestItem.PrivateKeyA, LimboLogs.Instance); CliqueBlockProducer producer = new( Substitute.For(), Substitute.For(), diff --git a/src/Nethermind/Nethermind.Clique.Test/CliqueSealEngineTests.cs b/src/Nethermind/Nethermind.Clique.Test/CliqueSealEngineTests.cs index 5308cd223ac..0181777e096 100644 --- a/src/Nethermind/Nethermind.Clique.Test/CliqueSealEngineTests.cs +++ b/src/Nethermind/Nethermind.Clique.Test/CliqueSealEngineTests.cs @@ -12,13 +12,16 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Db; using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Serialization.Rlp; +using Nethermind.Db.Blooms; using Nethermind.Trie; +using Nethermind.Wallet; using NUnit.Framework; using BlockTree = Nethermind.Blockchain.BlockTree; diff --git a/src/Nethermind/Nethermind.Clique.Test/CliqueTests.cs b/src/Nethermind/Nethermind.Clique.Test/CliqueTests.cs index 7963389c9c2..dd08fcfea29 100644 --- a/src/Nethermind/Nethermind.Clique.Test/CliqueTests.cs +++ b/src/Nethermind/Nethermind.Clique.Test/CliqueTests.cs @@ -7,12 +7,15 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Db; using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Serialization.Rlp; +using Nethermind.Db.Blooms; +using Nethermind.Wallet; using NUnit.Framework; using BlockTree = Nethermind.Blockchain.BlockTree; diff --git a/src/Nethermind/Nethermind.Clique.Test/SnapshotDecoderTests.cs b/src/Nethermind/Nethermind.Clique.Test/SnapshotDecoderTests.cs index 091c4efe674..8334491fc08 100644 --- a/src/Nethermind/Nethermind.Clique.Test/SnapshotDecoderTests.cs +++ b/src/Nethermind/Nethermind.Clique.Test/SnapshotDecoderTests.cs @@ -2,10 +2,16 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using Nethermind.Blockchain; using Nethermind.Consensus.Clique; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; +using Nethermind.Specs; +using Nethermind.Core.Test.Builders; +using Nethermind.Int256; using Nethermind.Serialization.Rlp; +using Nethermind.Db.Blooms; using NUnit.Framework; namespace Nethermind.Clique.Test diff --git a/src/Nethermind/Nethermind.Clique.Test/SnapshotManagerTests.cs b/src/Nethermind/Nethermind.Clique.Test/SnapshotManagerTests.cs index ea60a07ea83..ad43dadc44f 100644 --- a/src/Nethermind/Nethermind.Clique.Test/SnapshotManagerTests.cs +++ b/src/Nethermind/Nethermind.Clique.Test/SnapshotManagerTests.cs @@ -1,10 +1,12 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Blockchain; using Nethermind.Consensus.Clique; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Db; diff --git a/src/Nethermind/Nethermind.Config.Test/ConfigFileTestsBase.cs b/src/Nethermind/Nethermind.Config.Test/ConfigFileTestsBase.cs index 3635cb0aa9a..2d62788fd22 100644 --- a/src/Nethermind/Nethermind.Config.Test/ConfigFileTestsBase.cs +++ b/src/Nethermind/Nethermind.Config.Test/ConfigFileTestsBase.cs @@ -15,218 +15,236 @@ using Nethermind.Core.Extensions; using NUnit.Framework; -namespace Nethermind.Config.Test; - -[Parallelizable(ParallelScope.All)] -public abstract class ConfigFileTestsBase +namespace Nethermind.Config.Test { - private readonly IDictionary _cachedProviders = new ConcurrentDictionary(); - private readonly Dictionary> _configGroups = new(); - - [OneTimeSetUp] - public void Setup() + [Parallelizable(ParallelScope.All)] + public abstract class ConfigFileTestsBase { - // by pre-caching configs we make the tests do lot less work + private readonly IDictionary _cachedProviders = new ConcurrentDictionary(); + private readonly Dictionary> _configGroups = new(); - IEnumerable configTypes = TypeDiscovery.FindNethermindBasedTypes(typeof(IConfig)).Where(t => t.IsInterface).ToArray(); - - Parallel.ForEach(Resolve("*"), configFile => + [OneTimeSetUp] + public void Setup() { - TestConfigProvider configProvider = GetConfigProviderFromFile(configFile); - foreach (Type configType in configTypes) + // by pre-caching configs we make the tests do lot less work + + IEnumerable configTypes = TypeDiscovery.FindNethermindTypes(typeof(IConfig)).Where(t => t.IsInterface).ToArray(); + + Parallel.ForEach(Resolve("*"), configFile => { - configProvider.GetConfig(configType); - } + TestConfigProvider configProvider = GetConfigProviderFromFile(configFile); + foreach (Type configType in configTypes) + { + configProvider.GetConfig(configType); + } - _cachedProviders.Add(configFile, configProvider); - }); - } + _cachedProviders.Add(configFile, configProvider); + }); + } - [ConfigFileGroup("*")] - protected abstract IEnumerable Configs { get; } + [ConfigFileGroup("*")] + protected abstract IEnumerable Configs { get; } - [ConfigFileGroup("fast")] - protected IEnumerable FastSyncConfigs - => Configs.Where(config => !config.Contains("_") && !config.Contains("spaceneth")); + [ConfigFileGroup("fast")] + protected IEnumerable FastSyncConfigs + => Configs.Where(config => !config.Contains("_") && !config.Contains("spaceneth")); - [ConfigFileGroup("archive")] - protected IEnumerable ArchiveConfigs - => Configs.Where(config => config.Contains("_archive")); + [ConfigFileGroup("archive")] + protected IEnumerable ArchiveConfigs + => Configs.Where(config => config.Contains("_archive")); - [ConfigFileGroup("poacore")] - protected IEnumerable PoaCoreConfigs - => Configs.Where(config => config.Contains("poacore")); + [ConfigFileGroup("ropsten")] + protected IEnumerable RopstenConfigs + => Configs.Where(config => config.Contains("ropsten")); - [ConfigFileGroup("volta")] - protected IEnumerable VoltaConfigs - => Configs.Where(config => config.Contains("volta")); + [ConfigFileGroup("poacore")] + protected IEnumerable PoaCoreConfigs + => Configs.Where(config => config.Contains("poacore")); - [ConfigFileGroup("energy")] - protected IEnumerable EnergyConfigs - => Configs.Where(config => config.Contains("energy")); + [ConfigFileGroup("volta")] + protected IEnumerable VoltaConfigs + => Configs.Where(config => config.Contains("volta")); - [ConfigFileGroup("gnosis")] - protected IEnumerable GnosisConfigs - => Configs.Where(config => config.Contains("gnosis")); + [ConfigFileGroup("energy")] + protected IEnumerable EnergyConfigs + => Configs.Where(config => config.Contains("energy")); - [ConfigFileGroup("sepolia")] - protected IEnumerable SepoliaConfigs - => Configs.Where(config => config.Contains("sepolia")); + [ConfigFileGroup("xdai")] + protected IEnumerable XDaiConfigs + => Configs.Where(config => config.Contains("xdai")); - [ConfigFileGroup("chiado")] - protected IEnumerable ChiadoConfigs - => Configs.Where(config => config.Contains("chiado")); + [ConfigFileGroup("gnosis")] + protected IEnumerable GnosisConfigs + => Configs.Where(config => config.Contains("gnosis")); - [ConfigFileGroup("goerli")] - protected IEnumerable GoerliConfigs - => Configs.Where(config => config.Contains("goerli")); + [ConfigFileGroup("sepolia")] + protected IEnumerable SepoliaConfigs + => Configs.Where(config => config.Contains("sepolia")); - [ConfigFileGroup("rinkeby")] - protected IEnumerable RinkebyConfigs - => Configs.Where(config => config.Contains("rinkeby")); + [ConfigFileGroup("chiado")] + protected IEnumerable ChiadoConfigs + => Configs.Where(config => config.Contains("chiado")); - [ConfigFileGroup("kovan")] - protected IEnumerable KovanConfigs - => Configs.Where(config => config.Contains("kovan")); + [ConfigFileGroup("goerli")] + protected IEnumerable GoerliConfigs + => Configs.Where(config => config.Contains("goerli")); - [ConfigFileGroup("spaceneth")] - protected IEnumerable SpacenethConfigs - => Configs.Where(config => config.Contains("spaceneth")); + [ConfigFileGroup("rinkeby")] + protected IEnumerable RinkebyConfigs + => Configs.Where(config => config.Contains("rinkeby")); - [ConfigFileGroup("mainnet")] - protected IEnumerable MainnetConfigs - => Configs.Where(config => config.Contains("mainnet")); + [ConfigFileGroup("kovan")] + protected IEnumerable KovanConfigs + => Configs.Where(config => config.Contains("kovan")); - [ConfigFileGroup("validators")] - protected IEnumerable ValidatorConfigs - => Configs.Where(config => config.Contains("validator")); + [ConfigFileGroup("spaceneth")] + protected IEnumerable SpacenethConfigs + => Configs.Where(config => config.Contains("spaceneth")); - [ConfigFileGroup("aura")] - protected IEnumerable AuraConfigs - => PoaCoreConfigs - .Union(GnosisConfigs) - .Union(ChiadoConfigs) - .Union(VoltaConfigs) - .Union(EnergyConfigs) - .Union(KovanConfigs); + [ConfigFileGroup("mainnet")] + protected IEnumerable MainnetConfigs + => Configs.Where(config => config.Contains("mainnet")); - [ConfigFileGroup("aura_non_validating")] - protected IEnumerable AuraNonValidatingConfigs - => AuraConfigs.Where(c => !c.Contains("validator")); + [ConfigFileGroup("validators")] + protected IEnumerable ValidatorConfigs + => Configs.Where(config => config.Contains("validator")); - [ConfigFileGroup("clique")] - protected IEnumerable CliqueConfigs - => RinkebyConfigs.Union(GoerliConfigs); + [ConfigFileGroup("ndm")] + protected IEnumerable NdmConfigs + => Configs.Where(config => config.Contains("ndm")); - protected IEnumerable Resolve(string configWildcard) - { - Dictionary> groups = BuildConfigGroups(); - string[] configWildcards = configWildcard.Split(" "); + [ConfigFileGroup("aura")] + protected IEnumerable AuraConfigs + => PoaCoreConfigs + .Union(XDaiConfigs) + .Union(GnosisConfigs) + .Union(ChiadoConfigs) + .Union(VoltaConfigs) + .Union(EnergyConfigs) + .Union(KovanConfigs); + + [ConfigFileGroup("aura_non_validating")] + protected IEnumerable AuraNonValidatingConfigs + => AuraConfigs.Where(c => !c.Contains("validator")); - List> toIntersect = new(); - foreach (string singleWildcard in configWildcards) + [ConfigFileGroup("clique")] + protected IEnumerable CliqueConfigs + => RinkebyConfigs.Union(GoerliConfigs); + + [ConfigFileGroup("ethhash")] + protected IEnumerable EthashConfigs + => MainnetConfigs.Union(RopstenConfigs); + + protected IEnumerable Resolve(string configWildcard) { - string singleWildcardBase = singleWildcard.Replace("^", string.Empty); - IEnumerable result = groups.TryGetValue(singleWildcardBase, out IEnumerable? value) ? value : Enumerable.Repeat(singleWildcardBase, 1); + Dictionary> groups = BuildConfigGroups(); + string[] configWildcards = configWildcard.Split(" "); - if (singleWildcard.StartsWith("^")) + List> toIntersect = new(); + foreach (string singleWildcard in configWildcards) { - result = Configs.Except(result); - } + string singleWildcardBase = singleWildcard.Replace("^", string.Empty); + IEnumerable result = groups.TryGetValue(singleWildcardBase, out IEnumerable? value) ? value : Enumerable.Repeat(singleWildcardBase, 1); - toIntersect.Add(result); - } + if (singleWildcard.StartsWith("^")) + { + result = Configs.Except(result); + } - IEnumerable intersection = toIntersect.First(); - foreach (IEnumerable next in toIntersect.Skip(1)) - { - intersection = intersection.Intersect(next); - } + toIntersect.Add(result); + } - return intersection; - } + IEnumerable intersection = toIntersect.First(); + foreach (IEnumerable next in toIntersect.Skip(1)) + { + intersection = intersection.Intersect(next); + } - protected void Test(string configWildcard, Expression> getter, TProperty expectedValue) where T : IConfig - { - Test(configWildcard, getter, (s, propertyValue) => propertyValue.Should().Be(expectedValue, s + ": " + typeof(T).Name + "." + getter.GetName())); - } + return intersection; + } - protected void Test(string configWildcard, Expression> getter, Action expectedValue) where T : IConfig - { - foreach (TestConfigProvider configProvider in GetConfigProviders(configWildcard)) + protected void Test(string configWildcard, Expression> getter, TProperty expectedValue) where T : IConfig { - T config = configProvider.GetConfig(); - expectedValue(configProvider.FileName, getter.Compile()(config)); + Test(configWildcard, getter, (s, propertyValue) => propertyValue.Should().Be(expectedValue, s + ": " + typeof(T).Name + "." + getter.GetName())); } - } - protected IEnumerable GetConfigProviders(string configWildcard) - { - foreach (string configFile in Resolve(configWildcard)) + protected void Test(string configWildcard, Expression> getter, Action expectedValue) where T : IConfig { - if (!_cachedProviders.TryGetValue(configFile, out TestConfigProvider? configProvider)) + foreach (TestConfigProvider configProvider in GetConfigProviders(configWildcard)) { - configProvider = GetConfigProviderFromFile(configFile); + T config = configProvider.GetConfig(); + expectedValue(configProvider.FileName, getter.Compile()(config)); } - - yield return configProvider; } - } - - protected class TestConfigProvider : ConfigProvider - { - public string FileName { get; } - public TestConfigProvider(string fileName) + protected IEnumerable GetConfigProviders(string configWildcard) { - FileName = fileName; + foreach (string configFile in Resolve(configWildcard)) + { + if (!_cachedProviders.TryGetValue(configFile, out TestConfigProvider? configProvider)) + { + configProvider = GetConfigProviderFromFile(configFile); + } + + yield return configProvider; + } } - } - private static TestConfigProvider GetConfigProviderFromFile(string configFile) - { - try + protected class TestConfigProvider : ConfigProvider { - TestConfigProvider configProvider = new(configFile); - string configPath = Path.Combine(TestContext.CurrentContext.TestDirectory, "configs", configFile); - configProvider.AddSource(new JsonConfigSource(configPath)); - return configProvider; + public string FileName { get; } + + public TestConfigProvider(string fileName) + { + FileName = fileName; + } } - catch (Exception e) + + private static TestConfigProvider GetConfigProviderFromFile(string configFile) { - throw new ConfigurationErrorsException($"Cannot load config file {configFile}", e); + try + { + TestConfigProvider configProvider = new(configFile); + string configPath = Path.Combine(TestContext.CurrentContext.TestDirectory, "configs", configFile); + configProvider.AddSource(new JsonConfigSource(configPath)); + return configProvider; + } + catch (Exception e) + { + throw new ConfigurationErrorsException($"Cannot load config file {configFile}", e); + } } - } - private Dictionary> BuildConfigGroups() - { - lock (_configGroups) + private Dictionary> BuildConfigGroups() { - if (_configGroups.Count == 0) + lock (_configGroups) { - PropertyInfo[] propertyInfos = GetType() - .GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); - foreach (PropertyInfo propertyInfo in propertyInfos) + if (_configGroups.Count == 0) { - ConfigFileGroup? groupAttribute = propertyInfo.GetCustomAttribute(); - if (groupAttribute is not null) + PropertyInfo[] propertyInfos = GetType() + .GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); + foreach (PropertyInfo propertyInfo in propertyInfos) { - _configGroups.Add(groupAttribute.Name, (IEnumerable)propertyInfo.GetValue(this)!); + ConfigFileGroup? groupAttribute = propertyInfo.GetCustomAttribute(); + if (groupAttribute is not null) + { + _configGroups.Add(groupAttribute.Name, (IEnumerable)propertyInfo.GetValue(this)!); + } } } - } - return _configGroups; + return _configGroups; + } } - } - protected class ConfigFileGroup : Attribute - { - public ConfigFileGroup(string name) + protected class ConfigFileGroup : Attribute { - Name = name; - } + public ConfigFileGroup(string name) + { + Name = name; + } - public string Name { get; } + public string Name { get; } + } } } diff --git a/src/Nethermind/Nethermind.Config/ConfigExtensions.cs b/src/Nethermind/Nethermind.Config/ConfigExtensions.cs index f061fbfe37c..fcc73a046d1 100644 --- a/src/Nethermind/Nethermind.Config/ConfigExtensions.cs +++ b/src/Nethermind/Nethermind.Config/ConfigExtensions.cs @@ -2,8 +2,12 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.ComponentModel; +using System.Linq; using System.Reflection; +using System.Text; +using System.Threading.Tasks; namespace Nethermind.Config; public static class ConfigExtensions diff --git a/src/Nethermind/Nethermind.Config/ConfigProvider.cs b/src/Nethermind/Nethermind.Config/ConfigProvider.cs index ae2e3c41e04..035c92e4fa6 100644 --- a/src/Nethermind/Nethermind.Config/ConfigProvider.cs +++ b/src/Nethermind/Nethermind.Config/ConfigProvider.cs @@ -9,156 +9,157 @@ using Nethermind.Core; using Nethermind.Core.Extensions; -namespace Nethermind.Config; - -public class ConfigProvider : IConfigProvider +namespace Nethermind.Config { - private readonly ConcurrentDictionary _instances = new(); + public class ConfigProvider : IConfigProvider + { + private readonly ConcurrentDictionary _instances = new(); - private readonly List _configSource = new(); - private Dictionary Categories { get; set; } = new(StringComparer.InvariantCultureIgnoreCase); + private readonly List _configSource = new(); + private Dictionary Categories { get; set; } = new(StringComparer.InvariantCultureIgnoreCase); - private readonly Dictionary _implementations = new(); + private readonly Dictionary _implementations = new(); - public T GetConfig() where T : IConfig - { - return (T)GetConfig(typeof(T)); - } - - public object GetConfig(Type configType) - { - if (!typeof(IConfig).IsAssignableFrom(configType)) throw new ArgumentException($"Type {configType} is not {typeof(IConfig)}"); + public T GetConfig() where T : IConfig + { + return (T)GetConfig(typeof(T)); + } - if (!_instances.ContainsKey(configType)) + public object GetConfig(Type configType) { - if (!_implementations.ContainsKey(configType)) + if (!typeof(IConfig).IsAssignableFrom(configType)) throw new ArgumentException($"Type {configType} is not {typeof(IConfig)}"); + + if (!_instances.ContainsKey(configType)) { - Initialize(); + if (!_implementations.ContainsKey(configType)) + { + Initialize(); + } } - } - return _instances[configType]; - } + return _instances[configType]; + } - public object GetRawValue(string category, string name) - { - for (int i = 0; i < _configSource.Count; i++) + public object GetRawValue(string category, string name) { - (bool isSet, string str) = _configSource[i].GetRawValue(category, name); - if (isSet) + for (int i = 0; i < _configSource.Count; i++) { - return str; + (bool isSet, string str) = _configSource[i].GetRawValue(category, name); + if (isSet) + { + return str; + } } - } - - return Categories.TryGetValue(category, out object value) ? value.GetType() - .GetProperties(BindingFlags.Instance | BindingFlags.Public) - .SingleOrDefault(p => string.Equals(p.Name, name, StringComparison.InvariantCultureIgnoreCase)) - ?.GetValue(value) : null; - } - public void AddSource(IConfigSource configSource) - { - _configSource.Add(configSource); - } + return Categories.TryGetValue(category, out object value) ? value.GetType() + .GetProperties(BindingFlags.Instance | BindingFlags.Public) + .SingleOrDefault(p => string.Equals(p.Name, name, StringComparison.InvariantCultureIgnoreCase)) + ?.GetValue(value) : null; + } - public void Initialize() - { - Type type = typeof(IConfig); - IEnumerable interfaces = TypeDiscovery.FindNethermindBasedTypes(type).Where(x => x.IsInterface); + public void AddSource(IConfigSource configSource) + { + _configSource.Add(configSource); + } - foreach (Type @interface in interfaces) + public void Initialize() { - Type directImplementation = @interface.GetDirectInterfaceImplementation(); + Type type = typeof(IConfig); + IEnumerable interfaces = TypeDiscovery.FindNethermindTypes(type).Where(x => x.IsInterface); - if (directImplementation is not null) + foreach (Type @interface in interfaces) { - Categories.Add(@interface.Name[1..], - Activator.CreateInstance(directImplementation)); + Type directImplementation = @interface.GetDirectInterfaceImplementation(); + + if (directImplementation is not null) + { + Categories.Add(@interface.Name[1..], + Activator.CreateInstance(directImplementation)); - _implementations[@interface] = directImplementation; + _implementations[@interface] = directImplementation; - object config = Activator.CreateInstance(_implementations[@interface]); - _instances[@interface] = config!; + object config = Activator.CreateInstance(_implementations[@interface]); + _instances[@interface] = config!; - foreach (PropertyInfo propertyInfo in config.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) - { - for (int i = 0; i < _configSource.Count; i++) + foreach (PropertyInfo propertyInfo in config.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { - string category = @interface.IsAssignableFrom(typeof(INoCategoryConfig)) ? null : config.GetType().Name; - string name = propertyInfo.Name; - (bool isSet, object value) = _configSource[i].GetValue(propertyInfo.PropertyType, category, name); - if (isSet) + for (int i = 0; i < _configSource.Count; i++) { - try - { - propertyInfo.SetValue(config, value); - } - catch (Exception e) + string category = @interface.IsAssignableFrom(typeof(INoCategoryConfig)) ? null : config.GetType().Name; + string name = propertyInfo.Name; + (bool isSet, object value) = _configSource[i].GetValue(propertyInfo.PropertyType, category, name); + if (isSet) { - throw new InvalidOperationException($"Cannot set value of {category}.{name}", e); + try + { + propertyInfo.SetValue(config, value); + } + catch (Exception e) + { + throw new InvalidOperationException($"Cannot set value of {category}.{name}", e); + } + + break; } - - break; } } } } } - } - public (string ErrorMsg, IList<(IConfigSource Source, string Category, string Name)> Errors) FindIncorrectSettings() - { - if (_instances.IsEmpty) + public (string ErrorMsg, IList<(IConfigSource Source, string Category, string Name)> Errors) FindIncorrectSettings() { - Initialize(); - } - - HashSet propertySet = _instances.Values - .SelectMany(i => i.GetType() - .GetProperties() - .Select(p => GetKey(i.GetType().Name, p.Name))) - .ToHashSet(StringComparer.OrdinalIgnoreCase); + if (_instances.IsEmpty) + { + Initialize(); + } - List<(IConfigSource Source, string Category, string Name)> incorrectSettings = new(); + HashSet propertySet = _instances.Values + .SelectMany(i => i.GetType() + .GetProperties() + .Select(p => GetKey(i.GetType().Name, p.Name))) + .ToHashSet(StringComparer.OrdinalIgnoreCase); - foreach (var source in _configSource) - { - var configs = source.GetConfigKeys(); + List<(IConfigSource Source, string Category, string Name)> incorrectSettings = new(); - foreach (var conf in configs) + foreach (var source in _configSource) { - if (!propertySet.Contains(GetKey(conf.Category, conf.Name))) + var configs = source.GetConfigKeys(); + + foreach (var conf in configs) { - incorrectSettings.Add((source, conf.Category, conf.Name)); + if (!propertySet.Contains(GetKey(conf.Category, conf.Name))) + { + incorrectSettings.Add((source, conf.Category, conf.Name)); + } } } - } - var msg = string.Join(Environment.NewLine, incorrectSettings.Select(s => $"ConfigType:{GetConfigSourceName(s.Source)}|Category:{s.Category}|Name:{s.Name}")); + var msg = string.Join(Environment.NewLine, incorrectSettings.Select(s => $"ConfigType:{GetConfigSourceName(s.Source)}|Category:{s.Category}|Name:{s.Name}")); - return (msg, incorrectSettings); + return (msg, incorrectSettings); - static string GetConfigSourceName(IConfigSource source) => source switch - { - ArgsConfigSource => "RuntimeOption", - EnvConfigSource => "EnvironmentVariable(NETHERMIND_*)", - JsonConfigSource => "JsonConfigFile", - _ => source.ToString() - }; - - static string GetKey(string category, string name) - { - if (string.IsNullOrEmpty(category)) + static string GetConfigSourceName(IConfigSource source) => source switch { - category = nameof(NoCategoryConfig); - } - else if (!category.EndsWith("config", StringComparison.OrdinalIgnoreCase)) + ArgsConfigSource => "RuntimeOption", + EnvConfigSource => "EnvironmentVariable(NETHERMIND_*)", + JsonConfigSource => "JsonConfigFile", + _ => source.ToString() + }; + + static string GetKey(string category, string name) { - category += "Config"; - } + if (string.IsNullOrEmpty(category)) + { + category = nameof(NoCategoryConfig); + } + else if (!category.EndsWith("config", StringComparison.OrdinalIgnoreCase)) + { + category += "Config"; + } - return category + '.' + name; + return category + '.' + name; + } } } } diff --git a/src/Nethermind/Nethermind.Config/ConfigSourceHelper.cs b/src/Nethermind/Nethermind.Config/ConfigSourceHelper.cs index 39c91339c65..7f402e56f30 100644 --- a/src/Nethermind/Nethermind.Config/ConfigSourceHelper.cs +++ b/src/Nethermind/Nethermind.Config/ConfigSourceHelper.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.IO; using System.Linq; using Nethermind.Int256; using Newtonsoft.Json; diff --git a/src/Nethermind/Nethermind.Config/INoCategoryConfig.cs b/src/Nethermind/Nethermind.Config/INoCategoryConfig.cs index e7f2041d494..d7ad4814efa 100644 --- a/src/Nethermind/Nethermind.Config/INoCategoryConfig.cs +++ b/src/Nethermind/Nethermind.Config/INoCategoryConfig.cs @@ -1,6 +1,12 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + namespace Nethermind.Config { public interface INoCategoryConfig : IConfig diff --git a/src/Nethermind/Nethermind.Config/IProcessExitSource.cs b/src/Nethermind/Nethermind.Config/IProcessExitSource.cs index 6e7c20977ea..74a48b5bdcd 100644 --- a/src/Nethermind/Nethermind.Config/IProcessExitSource.cs +++ b/src/Nethermind/Nethermind.Config/IProcessExitSource.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; -using System.Threading.Tasks; using Nethermind.Core.Extensions; namespace Nethermind.Config; @@ -17,10 +16,6 @@ public class ProcessExitSource : IProcessExitSource private CancellationTokenSource _cancellationTokenSource = new(); public int ExitCode { get; set; } = ExitCodes.Ok; - private readonly TaskCompletionSource _exitResult = new(); - - public Task ExitTask => _exitResult.Task; - public CancellationToken Token => _cancellationTokenSource!.Token; public void Exit(int exitCode) @@ -28,7 +23,6 @@ public void Exit(int exitCode) if (CancellationTokenExtensions.CancelDisposeAndClear(ref _cancellationTokenSource)) { ExitCode = exitCode; - _exitResult.SetResult(); } } } diff --git a/src/Nethermind/Nethermind.Config/NoCategoryConfig.cs b/src/Nethermind/Nethermind.Config/NoCategoryConfig.cs index 56a73d77ac4..a812b01463a 100644 --- a/src/Nethermind/Nethermind.Config/NoCategoryConfig.cs +++ b/src/Nethermind/Nethermind.Config/NoCategoryConfig.cs @@ -1,6 +1,12 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + namespace Nethermind.Config { public class NoCategoryConfig : INoCategoryConfig diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBetterPeerStrategy.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBetterPeerStrategy.cs index d71df7d1d72..4c309b15879 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBetterPeerStrategy.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBetterPeerStrategy.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Blockchain.Synchronization; +using Nethermind.Core; using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Synchronization; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs index 1c4c5b44b22..52dc575fab0 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs @@ -14,6 +14,8 @@ using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Crypto; +using Nethermind.Db; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Logging; using Nethermind.State; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProducer.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProducer.cs index 3db92361804..6a9b4207fe8 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProducer.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProducer.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain; @@ -14,6 +15,7 @@ using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Evm.Tracing; +using Nethermind.Int256; using Nethermind.Logging; using Nethermind.State; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaSealer.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaSealer.cs index dd627eaf9de..db57d468b4d 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaSealer.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaSealer.cs @@ -11,6 +11,7 @@ using Nethermind.Crypto; using Nethermind.Logging; using Nethermind.Serialization.Rlp; +using Nethermind.Wallet; namespace Nethermind.Consensus.AuRa { diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaValidatorFactory.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaValidatorFactory.cs index 00db5435a80..d140e9cb835 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaValidatorFactory.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaValidatorFactory.cs @@ -12,6 +12,7 @@ using Nethermind.Logging; using Nethermind.Specs.ChainSpecStyle; using Nethermind.State; +using Nethermind.Db.Blooms; using Nethermind.Evm.TransactionProcessing; using Nethermind.JsonRpc.Modules.Eth.GasPrice; using Nethermind.TxPool; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/BeaconBlockRoot/NullBeaconBlockRootHandler.cs b/src/Nethermind/Nethermind.Consensus.AuRa/BeaconBlockRoot/NullBeaconBlockRootHandler.cs deleted file mode 100644 index 96138999814..00000000000 --- a/src/Nethermind/Nethermind.Consensus.AuRa/BeaconBlockRoot/NullBeaconBlockRootHandler.cs +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Consensus.BeaconBlockRoot; -using Nethermind.Core; -using Nethermind.Core.Specs; -using Nethermind.State; - -namespace Nethermind.Consensus.AuRa.BeaconBlockRoot; -internal class NullBeaconBlockRootHandler : IBeaconBlockRootHandler -{ - public void ApplyContractStateChanges(Block block, IReleaseSpec spec, IWorldState state) - { - } - - public static IBeaconBlockRootHandler Instance { get; } = new NullBeaconBlockRootHandler(); -} diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Config/AuRaConfig.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Config/AuRaConfig.cs index c93d6bf495f..a8a9f55e842 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Config/AuRaConfig.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Config/AuRaConfig.cs @@ -1,6 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Config; +using Nethermind.Core; + namespace Nethermind.Consensus.AuRa.Config { public class AuRaConfig : IAuraConfig diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Config/IAuraConfig.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Config/IAuraConfig.cs index cf749aa04f5..157ffcf049e 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Config/IAuraConfig.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Config/IAuraConfig.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Config; +using Nethermind.Core; namespace Nethermind.Consensus.AuRa.Config { diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/ContractRewriter.cs b/src/Nethermind/Nethermind.Consensus.AuRa/ContractRewriter.cs index 12ec5bc9b7d..cd8c60a5263 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/ContractRewriter.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/ContractRewriter.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.State; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/BlockGasLimitContract.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/BlockGasLimitContract.cs index 37954b6ca9a..e2a9a558c65 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/BlockGasLimitContract.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/BlockGasLimitContract.cs @@ -4,8 +4,10 @@ using System; using Nethermind.Abi; using Nethermind.Blockchain.Contracts; +using Nethermind.Blockchain.Contracts.Json; using Nethermind.Core; using Nethermind.Int256; +using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Consensus.AuRa.Contracts diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/CertifierContract.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/CertifierContract.cs index a5aa60a0c6c..fc431dbb788 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/CertifierContract.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/CertifierContract.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Abi; +using Nethermind.Blockchain.Contracts; using Nethermind.Core; +using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Consensus.AuRa.Contracts diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/DataStore/ContractDataStore.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/DataStore/ContractDataStore.cs index 567fff61423..3c3b6037f58 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/DataStore/ContractDataStore.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/DataStore/ContractDataStore.cs @@ -4,9 +4,11 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Threading.Tasks; using Nethermind.Abi; using Nethermind.Blockchain; +using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Core; using Nethermind.Core.Crypto; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/DataStore/IContractDataStore.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/DataStore/IContractDataStore.cs index 4394262f7ec..5726efd5313 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/DataStore/IContractDataStore.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/DataStore/IContractDataStore.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using Nethermind.Core; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RandomContract.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RandomContract.cs index ac2f624e29a..d6deb29c180 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RandomContract.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RandomContract.cs @@ -2,10 +2,14 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Numerics; using Nethermind.Abi; +using Nethermind.Blockchain.Contracts.Json; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Int256; +using Nethermind.Evm; +using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Consensus.AuRa.Contracts diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RegisterBasedContract.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RegisterBasedContract.cs index 1dad455c056..ceb8a3d779f 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RegisterBasedContract.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RegisterBasedContract.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Abi; using Nethermind.Blockchain.Contracts; using Nethermind.Core; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RegisterContract.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RegisterContract.cs index a81bbc521c9..349babeae43 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RegisterContract.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RegisterContract.cs @@ -6,6 +6,7 @@ using Nethermind.Blockchain.Contracts; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Consensus.AuRa.Contracts diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/ReportingValidatorContract.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/ReportingValidatorContract.cs index 75041e9b453..9a75b5377d7 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/ReportingValidatorContract.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/ReportingValidatorContract.cs @@ -4,8 +4,11 @@ using System; using Nethermind.Abi; using Nethermind.Blockchain.Contracts; +using Nethermind.Blockchain.Contracts.Json; using Nethermind.Core; using Nethermind.Int256; +using Nethermind.Evm; +using Nethermind.State; namespace Nethermind.Consensus.AuRa.Contracts { diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RewardContract.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RewardContract.cs index e78314f8d97..a18967fdfc8 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RewardContract.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/RewardContract.cs @@ -2,10 +2,15 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Diagnostics.CodeAnalysis; +using System.Numerics; using Nethermind.Abi; using Nethermind.Blockchain.Contracts; +using Nethermind.Blockchain.Contracts.Json; using Nethermind.Core; using Nethermind.Int256; +using Nethermind.Evm; +using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Consensus.AuRa.Contracts diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContract.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContract.cs index 8efb2163ab2..1874bc81acc 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContract.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContract.cs @@ -2,10 +2,12 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using Nethermind.Abi; using Nethermind.Blockchain.Contracts; using Nethermind.Core; using Nethermind.Int256; +using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Consensus.AuRa.Contracts diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV1.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV1.cs index 7509c8a2f6b..149621c1cc9 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV1.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV1.cs @@ -3,8 +3,10 @@ using System; using Nethermind.Abi; +using Nethermind.Blockchain.Contracts.Json; using Nethermind.Core; using Nethermind.Int256; +using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Consensus.AuRa.Contracts diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV2.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV2.cs index d5bbfa9299a..1c5673bc980 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV2.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV2.cs @@ -3,8 +3,10 @@ using System; using Nethermind.Abi; +using Nethermind.Blockchain.Contracts.Json; using Nethermind.Core; using Nethermind.Int256; +using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Consensus.AuRa.Contracts diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV3.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV3.cs index dd9afdcb38a..99c955616fa 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV3.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV3.cs @@ -3,10 +3,12 @@ using System; using Nethermind.Abi; +using Nethermind.Blockchain.Contracts.Json; using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Int256; +using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Consensus.AuRa.Contracts diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV4.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV4.cs index 77ba9466d3d..33561997d60 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV4.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TransactionPermissionContractV4.cs @@ -7,6 +7,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Int256; +using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Consensus.AuRa.Contracts diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TxPriorityContract.LocalData.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TxPriorityContract.LocalData.cs index df16f4a5015..a1cfea575b3 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TxPriorityContract.LocalData.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TxPriorityContract.LocalData.cs @@ -7,6 +7,7 @@ using System.Linq; using Nethermind.Blockchain.Data; using Nethermind.Core; +using Nethermind.Evm; using Nethermind.Logging; using Nethermind.Serialization.Json; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TxPriorityContract.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TxPriorityContract.cs index 40d31e2d346..274533148a5 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TxPriorityContract.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/TxPriorityContract.cs @@ -6,7 +6,10 @@ using System.Linq; using Nethermind.Abi; using Nethermind.Blockchain.Contracts; +using Nethermind.Blockchain.Find; using Nethermind.Core; +using Nethermind.Core.Extensions; +using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; using Nethermind.Facade; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/ValidatorContract.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/ValidatorContract.cs index 7483dc283db..4f909a8442a 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/ValidatorContract.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/ValidatorContract.cs @@ -2,10 +2,15 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using Nethermind.Abi; using Nethermind.Blockchain.Contracts; +using Nethermind.Blockchain.Contracts.Json; using Nethermind.Core; +using Nethermind.Int256; +using Nethermind.Evm; using Nethermind.State; +using Nethermind.Blockchain.Find; using Nethermind.Evm.TransactionProcessing; using Nethermind.Facade; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/VersionedContract.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/VersionedContract.cs index d5b574843a5..f21d9bb7d69 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/VersionedContract.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/VersionedContract.cs @@ -4,7 +4,9 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Versioning; using Nethermind.Abi; +using Nethermind.Blockchain.Contracts; using Nethermind.Core; using Nethermind.Core.Caching; using Nethermind.Core.Crypto; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/VersionedTransactionPermissionContract.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/VersionedTransactionPermissionContract.cs index 2d8ff94cc51..8f779eb4894 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/VersionedTransactionPermissionContract.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Contracts/VersionedTransactionPermissionContract.cs @@ -2,12 +2,14 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using System.Linq; using Nethermind.Abi; using Nethermind.Core; using Nethermind.Core.Caching; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Int256; +using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/IActivatedAt.cs b/src/Nethermind/Nethermind.Consensus.AuRa/IActivatedAt.cs index bc2675e619d..796e66926c0 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/IActivatedAt.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/IActivatedAt.cs @@ -2,6 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; +using System.Linq; +using Nethermind.Consensus.AuRa.Contracts; using Nethermind.Core; namespace Nethermind.Consensus.AuRa diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs index 650a82b5dd6..4c9227a9331 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs @@ -144,8 +144,7 @@ private IAuRaValidator CreateAuRaValidator(IBlockProcessor processor, IReadOnlyT _api.EngineSigner, _api.SpecProvider, _api.GasPriceOracle, - _api.ReportingContractValidatorCache, - chainSpecAuRa.PosdaoTransition) + _api.ReportingContractValidatorCache, chainSpecAuRa.PosdaoTransition, false) .CreateValidatorProcessor(chainSpecAuRa.Validators, _api.BlockTree.Head?.Header); if (validator is IDisposable disposableValidator) @@ -279,7 +278,6 @@ protected override TxPool.TxPool CreateTxPool() _api.TxValidator, _api.LogManager, CreateTxPoolTxComparer(txPriorityContract, localDataSource), - _api.TxGossipPolicy, new TxFilterAdapter(_api.BlockTree, txPoolFilter, _api.LogManager), txPriorityContract is not null || localDataSource is not null); } diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Rewards/AuRaRewardCalculator.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Rewards/AuRaRewardCalculator.cs index 17ba98510f5..141ae51fdcb 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Rewards/AuRaRewardCalculator.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Rewards/AuRaRewardCalculator.cs @@ -8,6 +8,9 @@ using Nethermind.Consensus.AuRa.Contracts; using Nethermind.Consensus.Rewards; using Nethermind.Core; +using Nethermind.Core.Extensions; +using Nethermind.Evm; +using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Specs.ChainSpecStyle; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Services/AuRaHealthHintService.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Services/AuRaHealthHintService.cs index e620fe33bea..9cbf93868aa 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Services/AuRaHealthHintService.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Services/AuRaHealthHintService.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Blockchain; using Nethermind.Blockchain.Services; using Nethermind.Consensus.AuRa.Validators; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityBase.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityBase.cs index 4c13b9fe61c..42e1153a2a3 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityBase.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityBase.cs @@ -3,12 +3,14 @@ using System; using System.Collections.Generic; +using System.Linq; using Nethermind.Consensus.AuRa.Contracts; using Nethermind.Consensus.AuRa.Contracts.DataStore; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Int256; +using Nethermind.TxPool; namespace Nethermind.Consensus.AuRa.Transactions { diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityOnHead.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityOnHead.cs index 8e8ca0a332d..368572e8bc6 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityOnHead.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityOnHead.cs @@ -2,10 +2,13 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Linq; +using System.Threading; using Nethermind.Blockchain; using Nethermind.Consensus.AuRa.Contracts; using Nethermind.Consensus.AuRa.Contracts.DataStore; using Nethermind.Core; +using Nethermind.Int256; namespace Nethermind.Consensus.AuRa.Transactions { diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityOnSpecifiedBlock.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityOnSpecifiedBlock.cs index ad726bca204..2707a9f3ea9 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityOnSpecifiedBlock.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/CompareTxByPriorityOnSpecifiedBlock.cs @@ -1,9 +1,12 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Consensus.AuRa.Contracts; using Nethermind.Consensus.AuRa.Contracts.DataStore; using Nethermind.Core; +using Nethermind.Core.Extensions; +using Nethermind.Int256; namespace Nethermind.Consensus.AuRa.Transactions { diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/LocalTxFilter.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/LocalTxFilter.cs index f00bafe5d62..ef42c44fd3a 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/LocalTxFilter.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/LocalTxFilter.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Consensus.Transactions; using Nethermind.Core; using Nethermind.TxPool; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/RandomContractTxSource.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/RandomContractTxSource.cs index 668448bdee1..a578cd96ccd 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/RandomContractTxSource.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/RandomContractTxSource.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using Nethermind.Abi; using Nethermind.Consensus.AuRa.Contracts; using Nethermind.Consensus.Transactions; @@ -12,7 +13,9 @@ using Nethermind.Core.Extensions; using Nethermind.Crypto; using Nethermind.Int256; +using Nethermind.Evm; using Nethermind.Logging; +using Nethermind.State; using Org.BouncyCastle.Crypto; namespace Nethermind.Consensus.AuRa.Transactions diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/ServiceTxFilter.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/ServiceTxFilter.cs index 7f61cc5330f..fd2a0643cd4 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/ServiceTxFilter.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/ServiceTxFilter.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Consensus.Transactions; using Nethermind.Core; using Nethermind.Core.Specs; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxCertifierFilter.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxCertifierFilter.cs index a50775deb9f..b3f5de11cf6 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxCertifierFilter.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxCertifierFilter.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using Nethermind.Abi; using Nethermind.Consensus.AuRa.Contracts; using Nethermind.Consensus.Transactions; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPermissionFilter.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPermissionFilter.cs index bac9362b8a3..fcd9b2bfc7f 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPermissionFilter.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPermissionFilter.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Diagnostics; using Nethermind.Abi; using Nethermind.Consensus.AuRa.Contracts; using Nethermind.Consensus.Transactions; @@ -9,6 +10,7 @@ using Nethermind.Core.Caching; using Nethermind.Core.Crypto; using Nethermind.Logging; +using Nethermind.State; using Nethermind.TxPool; namespace Nethermind.Consensus.AuRa.Transactions diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPriorityTxSource.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPriorityTxSource.cs index 133e1b0e9f9..12a7d4ca0f2 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPriorityTxSource.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Transactions/TxPriorityTxSource.cs @@ -10,7 +10,9 @@ using Nethermind.Consensus.Producers; using Nethermind.Consensus.Transactions; using Nethermind.Core; +using Nethermind.Core.Extensions; using Nethermind.Core.Specs; +using Nethermind.Int256; using Nethermind.Logging; using Nethermind.State; using Nethermind.TxPool; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Validators/AuRaValidatorBase.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Validators/AuRaValidatorBase.cs index d673c1c5f33..1ea99b83068 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Validators/AuRaValidatorBase.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Validators/AuRaValidatorBase.cs @@ -6,6 +6,7 @@ using Nethermind.Consensus.Processing; using Nethermind.Core; using Nethermind.Logging; +using Nethermind.Specs.ChainSpecStyle; namespace Nethermind.Consensus.AuRa.Validators { diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ContractBasedValidator.Posdao.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ContractBasedValidator.Posdao.cs index 097fc56af45..19218cf39d5 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ContractBasedValidator.Posdao.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ContractBasedValidator.Posdao.cs @@ -5,6 +5,7 @@ using Nethermind.Abi; using Nethermind.Consensus.Transactions; using Nethermind.Core; +using Nethermind.Int256; namespace Nethermind.Consensus.AuRa.Validators { diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ListBasedValidator.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ListBasedValidator.cs index b875b2552fb..30310beba0d 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ListBasedValidator.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ListBasedValidator.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Blockchain; using Nethermind.Logging; using Nethermind.Specs.ChainSpecStyle; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Validators/MultiValidator.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Validators/MultiValidator.cs index 9f469916d91..7c022c4bd3e 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Validators/MultiValidator.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Validators/MultiValidator.cs @@ -9,6 +9,7 @@ using Nethermind.Consensus.Processing; using Nethermind.Consensus.Transactions; using Nethermind.Core; +using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Specs.ChainSpecStyle; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ReportingContractBasedValidator.Cache.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ReportingContractBasedValidator.Cache.cs index e37f4236e77..fc87b3cbd81 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ReportingContractBasedValidator.Cache.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ReportingContractBasedValidator.Cache.cs @@ -1,7 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Concurrent; using System.Collections.Generic; +using System.Threading; using Nethermind.Core; using Nethermind.Core.Caching; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ReportingContractBasedValidator.PersistentReports.cs b/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ReportingContractBasedValidator.PersistentReports.cs index 3debf91ac47..5242999196a 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ReportingContractBasedValidator.PersistentReports.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/Validators/ReportingContractBasedValidator.PersistentReports.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Linq; using Nethermind.Abi; +using Nethermind.Blockchain; using Nethermind.Consensus.Transactions; using Nethermind.Core; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Consensus.Clique/CliqueHealthHintService.cs b/src/Nethermind/Nethermind.Consensus.Clique/CliqueHealthHintService.cs index 6ba4fbd2044..e9994061db7 100644 --- a/src/Nethermind/Nethermind.Consensus.Clique/CliqueHealthHintService.cs +++ b/src/Nethermind/Nethermind.Consensus.Clique/CliqueHealthHintService.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Blockchain; using Nethermind.Blockchain.Services; using Nethermind.Specs.ChainSpecStyle; diff --git a/src/Nethermind/Nethermind.Consensus.Clique/CliqueSealer.cs b/src/Nethermind/Nethermind.Consensus.Clique/CliqueSealer.cs index 1c2708c85a6..8cd7f3d8024 100644 --- a/src/Nethermind/Nethermind.Consensus.Clique/CliqueSealer.cs +++ b/src/Nethermind/Nethermind.Consensus.Clique/CliqueSealer.cs @@ -9,6 +9,7 @@ using Nethermind.Core.Crypto; using Nethermind.Crypto; using Nethermind.Logging; +using Nethermind.Wallet; [assembly: InternalsVisibleTo("Nethermind.Clique.Test")] diff --git a/src/Nethermind/Nethermind.Consensus.Clique/SnapshotDecoder.cs b/src/Nethermind/Nethermind.Consensus.Clique/SnapshotDecoder.cs index bf5e9485464..4ed5e0377b4 100644 --- a/src/Nethermind/Nethermind.Consensus.Clique/SnapshotDecoder.cs +++ b/src/Nethermind/Nethermind.Consensus.Clique/SnapshotDecoder.cs @@ -1,7 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; +using System.IO; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Consensus.Ethash/EthashPlugin.cs b/src/Nethermind/Nethermind.Consensus.Ethash/EthashPlugin.cs index 89207009a90..0047956814f 100644 --- a/src/Nethermind/Nethermind.Consensus.Ethash/EthashPlugin.cs +++ b/src/Nethermind/Nethermind.Consensus.Ethash/EthashPlugin.cs @@ -7,6 +7,7 @@ using Nethermind.Consensus.Producers; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Transactions; +using Nethermind.Core; namespace Nethermind.Consensus.Ethash { diff --git a/src/Nethermind/Nethermind.Consensus.Ethash/MinedBlockProducer.cs b/src/Nethermind/Nethermind.Consensus.Ethash/MinedBlockProducer.cs index 80b111c77ad..b927e2b85c8 100644 --- a/src/Nethermind/Nethermind.Consensus.Ethash/MinedBlockProducer.cs +++ b/src/Nethermind/Nethermind.Consensus.Ethash/MinedBlockProducer.cs @@ -1,13 +1,19 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; using Nethermind.Blockchain; using Nethermind.Config; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Producers; using Nethermind.Consensus.Transactions; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Int256; using Nethermind.Logging; using Nethermind.State; diff --git a/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs b/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs index 60fa34be699..4db8a7d0aa6 100644 --- a/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs +++ b/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs @@ -12,6 +12,7 @@ using Nethermind.Consensus.Producers; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Transactions; +using Nethermind.Consensus.Withdrawals; using Nethermind.Db; using Nethermind.Logging; using Nethermind.State; diff --git a/src/Nethermind/Nethermind.Consensus.Test/ManualGasLimitCalculator.cs b/src/Nethermind/Nethermind.Consensus.Test/ManualGasLimitCalculator.cs index c5ef4bc8e31..ccd109b8f93 100644 --- a/src/Nethermind/Nethermind.Consensus.Test/ManualGasLimitCalculator.cs +++ b/src/Nethermind/Nethermind.Consensus.Test/ManualGasLimitCalculator.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Consensus; using Nethermind.Core; namespace Nethermind.Consensus.Test diff --git a/src/Nethermind/Nethermind.Consensus/EngineApiVersions.cs b/src/Nethermind/Nethermind.Consensus/EngineApiVersions.cs deleted file mode 100644 index 598c8784907..00000000000 --- a/src/Nethermind/Nethermind.Consensus/EngineApiVersions.cs +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Consensus; - -public static class EngineApiVersions -{ - public const int Paris = 1; - public const int Shanghai = 2; - public const int Cancun = 3; -} diff --git a/src/Nethermind/Nethermind.Consensus/NethDevSealEngine.cs b/src/Nethermind/Nethermind.Consensus/NethDevSealEngine.cs index 082e096f413..b28161da23d 100644 --- a/src/Nethermind/Nethermind.Consensus/NethDevSealEngine.cs +++ b/src/Nethermind/Nethermind.Consensus/NethDevSealEngine.cs @@ -11,7 +11,7 @@ namespace Nethermind.Consensus { public class NethDevSealEngine : ISealer, ISealValidator { - public NethDevSealEngine(Address? address = null) + public NethDevSealEngine(Address address = null) { Address = address ?? Address.Zero; } @@ -30,12 +30,12 @@ public bool CanSeal(long blockNumber, Keccak parentHash) public Address Address { get; } - public bool ValidateParams(BlockHeader? parent, BlockHeader? header, bool isUncle = false) + public bool ValidateParams(BlockHeader parent, BlockHeader header, bool isUncle = false) { return true; } - public bool ValidateSeal(BlockHeader? header, bool force) + public bool ValidateSeal(BlockHeader header, bool force) { return true; } diff --git a/src/Nethermind/Nethermind.Consensus/NullSealEngine.cs b/src/Nethermind/Nethermind.Consensus/NullSealEngine.cs index ac599278d0d..e743b9fb857 100644 --- a/src/Nethermind/Nethermind.Consensus/NullSealEngine.cs +++ b/src/Nethermind/Nethermind.Consensus/NullSealEngine.cs @@ -18,22 +18,22 @@ private NullSealEngine() public Address Address => Address.Zero; - public Task SealBlock(Block? block, CancellationToken cancellationToken) + public Task SealBlock(Block block, CancellationToken cancellationToken) { return Task.FromResult(block); } - public bool CanSeal(long blockNumber, Keccak? parentHash) + public bool CanSeal(long blockNumber, Keccak parentHash) { return true; } - public bool ValidateParams(BlockHeader? parent, BlockHeader? header, bool isUncle = false) + public bool ValidateParams(BlockHeader parent, BlockHeader header, bool isUncle = false) { return true; } - public bool ValidateSeal(BlockHeader? header, bool force) + public bool ValidateSeal(BlockHeader header, bool force) { return true; } diff --git a/src/Nethermind/Nethermind.Consensus/NullSigner.cs b/src/Nethermind/Nethermind.Consensus/NullSigner.cs index ce587807924..c0ec72c2d4c 100644 --- a/src/Nethermind/Nethermind.Consensus/NullSigner.cs +++ b/src/Nethermind/Nethermind.Consensus/NullSigner.cs @@ -10,9 +10,9 @@ namespace Nethermind.Consensus { public class NullSigner : ISigner, ISignerStore { - public static NullSigner Instance { get; } = new(); + public static readonly NullSigner Instance = new(); - public Address Address { get; } = Address.Zero; // TODO: why zero address + public Address Address { get; } = Address.Zero; // TODO: why zero address public ValueTask Sign(Transaction tx) => default; @@ -20,7 +20,7 @@ public class NullSigner : ISigner, ISignerStore public bool CanSign { get; } = true; // TODO: why true? - public PrivateKey? Key { get; } = null; + public PrivateKey Key { get; } public void SetSigner(PrivateKey key) { } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionPicker.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionPicker.cs index 983a4da83f3..f5a2e6bc030 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionPicker.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionPicker.cs @@ -7,6 +7,8 @@ using Nethermind.Core.Specs; using Nethermind.Evm; using Nethermind.Int256; +using Nethermind.Logging; +using Nethermind.Specs; using Nethermind.State; namespace Nethermind.Consensus.Processing @@ -90,24 +92,12 @@ private bool HasEnoughFounds(Transaction transaction, in UInt256 senderBalance, return false; } - if (!transaction.IsServiceTransaction && eip1559Enabled) + if (eip1559Enabled && !transaction.IsServiceTransaction && senderBalance < (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + transaction.Value) { - UInt256 maxFee = (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + transaction.Value; - - if (senderBalance < maxFee) - { - e.Set(TxAction.Skip, $"{maxFee} is higher than sender balance ({senderBalance}), MaxFeePerGas: ({transaction.MaxFeePerGas}), GasLimit {transaction.GasLimit}"); - return false; - } - - if (transaction.SupportsBlobs && ( - !BlobGasCalculator.TryCalculateBlobGasPrice(block.Header, transaction, out UInt256 blobGasPrice) || - senderBalance < (maxFee += blobGasPrice))) - { - e.Set(TxAction.Skip, $"{maxFee} is higher than sender balance ({senderBalance}), MaxFeePerGas: ({transaction.MaxFeePerGas}), GasLimit {transaction.GasLimit}, BlobGasPrice: {blobGasPrice}"); - return false; - } + e.Set(TxAction.Skip, $"MaxFeePerGas ({transaction.MaxFeePerGas}) times GasLimit {transaction.GasLimit} is higher than sender balance ({senderBalance})"); + return false; } + return true; } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs index 44c6cdc58f0..05b11f9d7b7 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs @@ -7,7 +7,6 @@ using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Core.Specs; -using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; @@ -68,10 +67,9 @@ public virtual TxReceipt[] ProcessTransactions(Block block, ProcessingOptions pr int i = 0; LinkedHashSet transactionsInBlock = new(ByHashTxComparer.Instance); - BlockExecutionContext blkCtx = new(block.Header); foreach (Transaction currentTx in transactions) { - TxAction action = ProcessTransaction(block, blkCtx, currentTx, i++, receiptsTracer, processingOptions, transactionsInBlock); + TxAction action = ProcessTransaction(block, currentTx, i++, receiptsTracer, processingOptions, transactionsInBlock); if (action == TxAction.Stop) break; } @@ -83,7 +81,6 @@ public virtual TxReceipt[] ProcessTransactions(Block block, ProcessingOptions pr protected TxAction ProcessTransaction( Block block, - BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, @@ -99,7 +96,7 @@ protected TxAction ProcessTransaction( } else { - _transactionProcessor.ProcessTransaction(blkCtx, currentTx, receiptsTracer, processingOptions, _stateProvider); + _transactionProcessor.ProcessTransaction(block, currentTx, receiptsTracer, processingOptions, _stateProvider); if (addToBlock) { diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs index 116ba87a90c..4489c88109d 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs @@ -5,7 +5,6 @@ using System.Linq; using Nethermind.Core; using Nethermind.Core.Specs; -using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.State; @@ -34,19 +33,17 @@ public BlockValidationTransactionsExecutor(ITransactionProcessorAdapter transact public TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processingOptions, BlockReceiptsTracer receiptsTracer, IReleaseSpec spec) { - Evm.Metrics.ResetBlockStats(); - BlockExecutionContext blkCtx = new(block.Header); for (int i = 0; i < block.Transactions.Length; i++) { Transaction currentTx = block.Transactions[i]; - ProcessTransaction(blkCtx, currentTx, i, receiptsTracer, processingOptions); + ProcessTransaction(block, currentTx, i, receiptsTracer, processingOptions); } return receiptsTracer.TxReceipts.ToArray(); } - private void ProcessTransaction(BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions) + private void ProcessTransaction(Block block, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions) { - _transactionProcessor.ProcessTransaction(blkCtx, currentTx, receiptsTracer, processingOptions, _stateProvider); + _transactionProcessor.ProcessTransaction(block, currentTx, receiptsTracer, processingOptions, _stateProvider); TransactionProcessed?.Invoke(this, new TxProcessedEventArgs(index, currentTx, receiptsTracer.TxReceipts[index])); } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index 82ee3b1d655..d1eb8b3ae03 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Numerics; using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; -using Nethermind.Consensus.BeaconBlockRoot; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; using Nethermind.Consensus.Withdrawals; @@ -32,7 +32,6 @@ public partial class BlockProcessor : IBlockProcessor private readonly IReceiptStorage _receiptStorage; private readonly IWitnessCollector _witnessCollector; private readonly IWithdrawalProcessor _withdrawalProcessor; - private readonly IBeaconBlockRootHandler _beaconBlockRootHandler; private readonly IBlockValidator _blockValidator; private readonly IRewardCalculator _rewardCalculator; private readonly IBlockProcessor.IBlockTransactionsExecutor _blockTransactionsExecutor; @@ -65,7 +64,7 @@ public BlockProcessor( _withdrawalProcessor = withdrawalProcessor ?? new WithdrawalProcessor(stateProvider, logManager); _rewardCalculator = rewardCalculator ?? throw new ArgumentNullException(nameof(rewardCalculator)); _blockTransactionsExecutor = blockTransactionsExecutor ?? throw new ArgumentNullException(nameof(blockTransactionsExecutor)); - _beaconBlockRootHandler = new BeaconBlockRootHandler(); + _receiptsTracer = new BlockReceiptsTracer(); } @@ -226,14 +225,12 @@ protected virtual TxReceipt[] ProcessBlock( _receiptsTracer.SetOtherTracer(blockTracer); _receiptsTracer.StartNewBlockTrace(block); - _beaconBlockRootHandler.ApplyContractStateChanges(block, spec, _stateProvider); - _stateProvider.Commit(spec); - TxReceipt[] receipts = _blockTransactionsExecutor.ProcessTransactions(block, options, _receiptsTracer, spec); if (spec.IsEip4844Enabled) { - block.Header.BlobGasUsed = BlobGasCalculator.CalculateBlobGas(block.Transactions); + block.Header.DataGasUsed = DataGasCalculator.CalculateDataGas( + block.Transactions.Sum(tx => tx.BlobVersionedHashes?.Length ?? 0)); } block.Header.ReceiptsRoot = receipts.GetReceiptsRoot(spec, block.ReceiptsRoot); @@ -271,8 +268,8 @@ private Block PrepareBlockForProcessing(Block suggestedBlock) bh.GasLimit, bh.Timestamp, bh.ExtraData, - bh.BlobGasUsed, - bh.ExcessBlobGas) + bh.DataGasUsed, + bh.ExcessDataGas) { Bloom = Bloom.Empty, Author = bh.Author, @@ -287,7 +284,6 @@ private Block PrepareBlockForProcessing(Block suggestedBlock) BaseFeePerGas = bh.BaseFeePerGas, WithdrawalsRoot = bh.WithdrawalsRoot, IsPostMerge = bh.IsPostMerge, - ParentBeaconBlockRoot = bh.ParentBeaconBlockRoot, }; return suggestedBlock.CreateCopy(headerForProcessing); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs index ff4a6a945d9..ef4bdaf71ca 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockchainProcessor.cs @@ -21,751 +21,745 @@ using Nethermind.State; using Metrics = Nethermind.Blockchain.Metrics; -namespace Nethermind.Consensus.Processing; - -public class BlockchainProcessor : IBlockchainProcessor, IBlockProcessingQueue +namespace Nethermind.Consensus.Processing { - public int SoftMaxRecoveryQueueSizeInTx = 10000; // adjust based on tx or gas - public const int MaxProcessingQueueSize = 2000; // adjust based on tx or gas - - [ThreadStatic] - private static bool _isMainProcessingThread; - public static bool IsMainProcessingThread => _isMainProcessingThread; - public bool IsMainProcessor { get; init; } - - public ITracerBag Tracers => _compositeBlockTracer; - - private readonly IBlockProcessor _blockProcessor; - private readonly IBlockPreprocessorStep _recoveryStep; - private readonly IStateReader _stateReader; - private readonly Options _options; - private readonly IBlockTree _blockTree; - private readonly ILogger _logger; - - private readonly BlockingCollection _recoveryQueue = new(new ConcurrentQueue()); - - private readonly BlockingCollection _blockQueue = new(new ConcurrentQueue(), - MaxProcessingQueueSize); - - private int _queueCount; - - private readonly ProcessingStats _stats; - - private CancellationTokenSource? _loopCancellationSource; - private Task? _recoveryTask; - private Task? _processorTask; - private DateTime _lastProcessedBlock; - - private int _currentRecoveryQueueSize; - private const int MaxBlocksDuringFastSyncTransition = 8192; - private readonly CompositeBlockTracer _compositeBlockTracer = new(); - private readonly Stopwatch _stopwatch = new(); - - public event EventHandler? InvalidBlock; - - /// - /// - /// - /// - /// - /// - /// - /// - /// - public BlockchainProcessor( - IBlockTree? blockTree, - IBlockProcessor? blockProcessor, - IBlockPreprocessorStep? recoveryStep, - IStateReader stateReader, - ILogManager? logManager, - Options options) + public class BlockchainProcessor : IBlockchainProcessor, IBlockProcessingQueue { - _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); - _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); - _blockProcessor = blockProcessor ?? throw new ArgumentNullException(nameof(blockProcessor)); - _recoveryStep = recoveryStep ?? throw new ArgumentNullException(nameof(recoveryStep)); - _stateReader = stateReader ?? throw new ArgumentNullException(nameof(stateReader)); - _options = options; + public int SoftMaxRecoveryQueueSizeInTx = 10000; // adjust based on tx or gas + public const int MaxProcessingQueueSize = 2000; // adjust based on tx or gas - _blockTree.NewBestSuggestedBlock += OnNewBestBlock; - _blockTree.NewHeadBlock += OnNewHeadBlock; + public ITracerBag Tracers => _compositeBlockTracer; - _stats = new ProcessingStats(_logger); - } + private readonly IBlockProcessor _blockProcessor; + private readonly IBlockPreprocessorStep _recoveryStep; + private readonly IStateReader _stateReader; + private readonly Options _options; + private readonly IBlockTree _blockTree; + private readonly ILogger _logger; - private void OnNewHeadBlock(object? sender, BlockEventArgs e) - { - _lastProcessedBlock = DateTime.UtcNow; - } + private readonly BlockingCollection _recoveryQueue = new(new ConcurrentQueue()); - private void OnNewBestBlock(object sender, BlockEventArgs blockEventArgs) - { - ProcessingOptions options = ProcessingOptions.None; - if (_options.StoreReceiptsByDefault) + private readonly BlockingCollection _blockQueue = new(new ConcurrentQueue(), + MaxProcessingQueueSize); + + private int _queueCount; + + private readonly ProcessingStats _stats; + + private CancellationTokenSource? _loopCancellationSource; + private Task? _recoveryTask; + private Task? _processorTask; + private DateTime _lastProcessedBlock; + + private int _currentRecoveryQueueSize; + private const int MaxBlocksDuringFastSyncTransition = 8192; + private readonly CompositeBlockTracer _compositeBlockTracer = new(); + private readonly Stopwatch _stopwatch = new(); + + public event EventHandler InvalidBlock; + + /// + /// + /// + /// + /// + /// + /// + /// + /// + public BlockchainProcessor( + IBlockTree? blockTree, + IBlockProcessor? blockProcessor, + IBlockPreprocessorStep? recoveryStep, + IStateReader stateReader, + ILogManager? logManager, + Options options) { - options |= ProcessingOptions.StoreReceipts; + _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); + _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); + _blockProcessor = blockProcessor ?? throw new ArgumentNullException(nameof(blockProcessor)); + _recoveryStep = recoveryStep ?? throw new ArgumentNullException(nameof(recoveryStep)); + _stateReader = stateReader ?? throw new ArgumentNullException(nameof(stateReader)); + _options = options; + + _blockTree.NewBestSuggestedBlock += OnNewBestBlock; + _blockTree.NewHeadBlock += OnNewHeadBlock; + + _stats = new ProcessingStats(_logger); } - if (blockEventArgs.Block is not null) + private void OnNewHeadBlock(object? sender, BlockEventArgs e) { - Enqueue(blockEventArgs.Block, options); + _lastProcessedBlock = DateTime.UtcNow; } - } - - public void Enqueue(Block block, ProcessingOptions processingOptions) - { - if (_logger.IsTrace) _logger.Trace($"Enqueuing a new block {block.ToString(Block.Format.Short)} for processing."); - - int currentRecoveryQueueSize = Interlocked.Add(ref _currentRecoveryQueueSize, block.Transactions.Length); - Keccak? blockHash = block.Hash!; - BlockRef blockRef = currentRecoveryQueueSize >= SoftMaxRecoveryQueueSizeInTx - ? new BlockRef(blockHash, processingOptions) - : new BlockRef(block, processingOptions); - if (!_recoveryQueue.IsAddingCompleted) + private void OnNewBestBlock(object sender, BlockEventArgs blockEventArgs) { - Interlocked.Increment(ref _queueCount); - try + ProcessingOptions options = ProcessingOptions.None; + if (_options.StoreReceiptsByDefault) { - _recoveryQueue.Add(blockRef); - if (_logger.IsTrace) _logger.Trace($"A new block {block.ToString(Block.Format.Short)} enqueued for processing."); + options |= ProcessingOptions.StoreReceipts; } - catch (Exception e) + + if (blockEventArgs.Block is not null) { - Interlocked.Decrement(ref _queueCount); - BlockRemoved?.Invoke(this, new BlockHashEventArgs(blockHash, ProcessingResult.QueueException, e)); - if (e is not InvalidOperationException || !_recoveryQueue.IsAddingCompleted) - { - throw; - } + Enqueue(blockEventArgs.Block, options); } } - } - - public void Start() - { - _loopCancellationSource = new CancellationTokenSource(); - _recoveryTask = RunRecovery(); - _processorTask = RunProcessing(); - } - public async Task StopAsync(bool processRemainingBlocks = false) - { - if (processRemainingBlocks) + public void Enqueue(Block block, ProcessingOptions processingOptions) { - _recoveryQueue.CompleteAdding(); - await (_recoveryTask ?? Task.CompletedTask); - _blockQueue.CompleteAdding(); + if (_logger.IsTrace) _logger.Trace($"Enqueuing a new block {block.ToString(Block.Format.Short)} for processing."); + + int currentRecoveryQueueSize = Interlocked.Add(ref _currentRecoveryQueueSize, block.Transactions.Length); + Keccak? blockHash = block.Hash!; + BlockRef blockRef = currentRecoveryQueueSize >= SoftMaxRecoveryQueueSizeInTx + ? new BlockRef(blockHash, processingOptions) + : new BlockRef(block, processingOptions); + + if (!_recoveryQueue.IsAddingCompleted) + { + Interlocked.Increment(ref _queueCount); + try + { + _recoveryQueue.Add(blockRef); + if (_logger.IsTrace) _logger.Trace($"A new block {block.ToString(Block.Format.Short)} enqueued for processing."); + } + catch (Exception e) + { + Interlocked.Decrement(ref _queueCount); + BlockRemoved?.Invoke(this, new BlockHashEventArgs(blockHash, ProcessingResult.QueueException, e)); + if (e is not InvalidOperationException || !_recoveryQueue.IsAddingCompleted) + { + throw; + } + } + } } - else + + public void Start() { - _loopCancellationSource?.Cancel(); - _recoveryQueue.CompleteAdding(); - _blockQueue.CompleteAdding(); + _loopCancellationSource = new CancellationTokenSource(); + _recoveryTask = RunRecovery(); + _processorTask = RunProcessing(); } - await Task.WhenAll((_recoveryTask ?? Task.CompletedTask), (_processorTask ?? Task.CompletedTask)); - if (_logger.IsInfo) _logger.Info("Blockchain Processor shutdown complete.. please wait for all components to close"); - } - - private Task RunRecovery() - { - TaskCompletionSource tcs = new(); - - Thread thread = new(() => + public async Task StopAsync(bool processRemainingBlocks = false) { - try + if (processRemainingBlocks) { - RunRecoveryLoop(); - if (_logger.IsDebug) _logger.Debug("Sender address recovery complete."); + _recoveryQueue.CompleteAdding(); + await (_recoveryTask ?? Task.CompletedTask); + _blockQueue.CompleteAdding(); } - catch (OperationCanceledException) + else { - if (_logger.IsDebug) _logger.Debug("Sender address recovery stopped."); + _loopCancellationSource?.Cancel(); + _recoveryQueue.CompleteAdding(); + _blockQueue.CompleteAdding(); } - catch (Exception ex) + + await Task.WhenAll((_recoveryTask ?? Task.CompletedTask), (_processorTask ?? Task.CompletedTask)); + if (_logger.IsInfo) _logger.Info("Blockchain Processor shutdown complete.. please wait for all components to close"); + } + + private Task RunRecovery() + { + TaskCompletionSource tcs = new(); + + Thread thread = new(() => { - if (_logger.IsError) _logger.Error("Sender address recovery encountered an exception.", ex); - } - finally + try + { + RunRecoveryLoop(); + if (_logger.IsDebug) _logger.Debug("Sender address recovery complete."); + } + catch (OperationCanceledException) + { + if (_logger.IsDebug) _logger.Debug("Sender address recovery stopped."); + } + catch (Exception ex) + { + if (_logger.IsError) _logger.Error("Sender address recovery encountered an exception.", ex); + } + finally + { + tcs.SetResult(); + } + }) { - tcs.SetResult(); - } - }) - { - IsBackground = true, - Name = "Block Recovery", - // Boost priority to make sure we process blocks as fast as possible - Priority = ThreadPriority.AboveNormal, - }; - thread.Start(); - - return tcs.Task; - } + IsBackground = true, + Name = "Block Recovery", + // Boost priority to make sure we process blocks as fast as possible + Priority = ThreadPriority.AboveNormal, + }; + thread.Start(); - private void RunRecoveryLoop() - { - void DecrementQueue(Keccak blockHash, ProcessingResult processingResult, Exception? exception = null) - { - Interlocked.Decrement(ref _queueCount); - BlockRemoved?.Invoke(this, new BlockHashEventArgs(blockHash, processingResult, exception)); - FireProcessingQueueEmpty(); + return tcs.Task; } - if (_logger.IsDebug) _logger.Debug($"Starting recovery loop - {_blockQueue.Count} blocks waiting in the queue."); - _lastProcessedBlock = DateTime.UtcNow; - foreach (BlockRef blockRef in _recoveryQueue.GetConsumingEnumerable(_loopCancellationSource.Token)) + private void RunRecoveryLoop() { - try + void DecrementQueue(Keccak blockHash, ProcessingResult processingResult, Exception? exception = null) { - if (blockRef.Resolve(_blockTree)) - { - Interlocked.Add(ref _currentRecoveryQueueSize, -blockRef.Block!.Transactions.Length); - if (_logger.IsTrace) _logger.Trace($"Recovering addresses for block {blockRef.BlockHash}."); - _recoveryStep.RecoverData(blockRef.Block); + Interlocked.Decrement(ref _queueCount); + BlockRemoved?.Invoke(this, new BlockHashEventArgs(blockHash, processingResult, exception)); + FireProcessingQueueEmpty(); + } - try - { - _blockQueue.Add(blockRef); - } - catch (Exception e) + if (_logger.IsDebug) _logger.Debug($"Starting recovery loop - {_blockQueue.Count} blocks waiting in the queue."); + _lastProcessedBlock = DateTime.UtcNow; + foreach (BlockRef blockRef in _recoveryQueue.GetConsumingEnumerable(_loopCancellationSource.Token)) + { + try + { + if (blockRef.Resolve(_blockTree)) { - DecrementQueue(blockRef.BlockHash, ProcessingResult.QueueException, e); + Interlocked.Add(ref _currentRecoveryQueueSize, -blockRef.Block!.Transactions.Length); + if (_logger.IsTrace) _logger.Trace($"Recovering addresses for block {blockRef.BlockHash}."); + _recoveryStep.RecoverData(blockRef.Block); - if (e is InvalidOperationException) + try { - if (_logger.IsDebug) _logger.Debug($"Recovery loop stopping."); - return; + _blockQueue.Add(blockRef); } + catch (Exception e) + { + DecrementQueue(blockRef.BlockHash, ProcessingResult.QueueException, e); - throw; + if (e is InvalidOperationException) + { + if (_logger.IsDebug) _logger.Debug($"Recovery loop stopping."); + return; + } + + throw; + } + } + else + { + DecrementQueue(blockRef.BlockHash, ProcessingResult.MissingBlock); + if (_logger.IsTrace) _logger.Trace("Block was removed from the DB and cannot be recovered (it belonged to an invalid branch). Skipping."); } } - else + catch (Exception e) { - DecrementQueue(blockRef.BlockHash, ProcessingResult.MissingBlock); - if (_logger.IsTrace) _logger.Trace("Block was removed from the DB and cannot be recovered (it belonged to an invalid branch). Skipping."); + DecrementQueue(blockRef.BlockHash, ProcessingResult.Exception, e); + throw; } } - catch (Exception e) - { - DecrementQueue(blockRef.BlockHash, ProcessingResult.Exception, e); - throw; - } } - } - - private Task RunProcessing() - { - TaskCompletionSource tcs = new(); - Thread thread = new(() => + private Task RunProcessing() { - _isMainProcessingThread = IsMainProcessor; + TaskCompletionSource tcs = new(); - try - { - RunProcessingLoop(); - if (_logger.IsDebug) _logger.Debug($"{nameof(BlockchainProcessor)} complete."); - } - catch (OperationCanceledException) - { - if (_logger.IsDebug) _logger.Debug($"{nameof(BlockchainProcessor)} stopped."); - } - catch (Exception ex) + Thread thread = new(() => { - if (_logger.IsError) _logger.Error($"{nameof(BlockchainProcessor)} encountered an exception.", ex); - } - finally + try + { + RunProcessingLoop(); + if (_logger.IsDebug) _logger.Debug($"{nameof(BlockchainProcessor)} complete."); + } + catch (OperationCanceledException) + { + if (_logger.IsDebug) _logger.Debug($"{nameof(BlockchainProcessor)} stopped."); + } + catch (Exception ex) + { + if (_logger.IsError) _logger.Error($"{nameof(BlockchainProcessor)} encountered an exception.", ex); + } + finally + { + tcs.SetResult(); + } + }) { - tcs.SetResult(); - } - }) - { - IsBackground = true, - Name = "Block Processor", - // Boost priority to make sure we process blocks as fast as possible - Priority = ThreadPriority.Highest, - }; - thread.Start(); - - return tcs.Task; - } - - private void RunProcessingLoop() - { - if (_logger.IsDebug) _logger.Debug($"Starting block processor - {_blockQueue.Count} blocks waiting in the queue."); + IsBackground = true, + Name = "Block Processor", + // Boost priority to make sure we process blocks as fast as possible + Priority = ThreadPriority.Highest, + }; + thread.Start(); - FireProcessingQueueEmpty(); + return tcs.Task; + } - foreach (BlockRef blockRef in _blockQueue.GetConsumingEnumerable(_loopCancellationSource.Token)) + private void RunProcessingLoop() { - try + if (_logger.IsDebug) _logger.Debug($"Starting block processor - {_blockQueue.Count} blocks waiting in the queue."); + + FireProcessingQueueEmpty(); + + foreach (BlockRef blockRef in _blockQueue.GetConsumingEnumerable(_loopCancellationSource.Token)) { - if (blockRef.IsInDb || blockRef.Block is null) + try { - BlockRemoved?.Invoke(this, new BlockHashEventArgs(blockRef.BlockHash, ProcessingResult.MissingBlock)); - throw new InvalidOperationException("Processing loop expects only resolved blocks"); - } + if (blockRef.IsInDb || blockRef.Block is null) + { + BlockRemoved?.Invoke(this, new BlockHashEventArgs(blockRef.BlockHash, ProcessingResult.MissingBlock)); + throw new InvalidOperationException("Processing loop expects only resolved blocks"); + } - Block block = blockRef.Block; + Block block = blockRef.Block; - if (_logger.IsTrace) _logger.Trace($"Processing block {block.ToString(Block.Format.Short)})."); - _stats.Start(); + if (_logger.IsTrace) _logger.Trace($"Processing block {block.ToString(Block.Format.Short)})."); + _stats.Start(); - Block processedBlock = Process(block, blockRef.ProcessingOptions, _compositeBlockTracer.GetTracer()); + Block processedBlock = Process(block, blockRef.ProcessingOptions, _compositeBlockTracer.GetTracer()); - if (processedBlock is null) + if (processedBlock is null) + { + if (_logger.IsTrace) _logger.Trace($"Failed / skipped processing {block.ToString(Block.Format.Full)}"); + BlockRemoved?.Invoke(this, new BlockHashEventArgs(blockRef.BlockHash, ProcessingResult.ProcessingError)); + } + else + { + if (_logger.IsTrace) _logger.Trace($"Processed block {block.ToString(Block.Format.Full)}"); + BlockRemoved?.Invoke(this, new BlockHashEventArgs(blockRef.BlockHash, ProcessingResult.Success)); + } + } + catch (Exception exception) { - if (_logger.IsTrace) _logger.Trace($"Failed / skipped processing {block.ToString(Block.Format.Full)}"); - BlockRemoved?.Invoke(this, new BlockHashEventArgs(blockRef.BlockHash, ProcessingResult.ProcessingError)); + if (_logger.IsWarn) _logger.Warn($"Processing loop threw an exception. Block: {blockRef}, Exception: {exception}"); + BlockRemoved?.Invoke(this, new BlockHashEventArgs(blockRef.BlockHash, ProcessingResult.Exception, exception)); } - else + finally { - if (_logger.IsTrace) _logger.Trace($"Processed block {block.ToString(Block.Format.Full)}"); - BlockRemoved?.Invoke(this, new BlockHashEventArgs(blockRef.BlockHash, ProcessingResult.Success)); + Interlocked.Decrement(ref _queueCount); } - } - catch (Exception exception) - { - if (_logger.IsWarn) _logger.Warn($"Processing loop threw an exception. Block: {blockRef}, Exception: {exception}"); - BlockRemoved?.Invoke(this, new BlockHashEventArgs(blockRef.BlockHash, ProcessingResult.Exception, exception)); - } - finally - { - Interlocked.Decrement(ref _queueCount); + + if (_logger.IsTrace) _logger.Trace($"Now {_blockQueue.Count} blocks waiting in the queue."); + FireProcessingQueueEmpty(); } - if (_logger.IsTrace) _logger.Trace($"Now {_blockQueue.Count} blocks waiting in the queue."); - FireProcessingQueueEmpty(); + if (_logger.IsInfo) _logger.Info("Block processor queue stopped."); } - if (_logger.IsInfo) _logger.Info("Block processor queue stopped."); - } - - private void FireProcessingQueueEmpty() - { - if (((IBlockProcessingQueue)this).IsEmpty) + private void FireProcessingQueueEmpty() { - ProcessingQueueEmpty?.Invoke(this, EventArgs.Empty); + if (((IBlockProcessingQueue)this).IsEmpty) + { + ProcessingQueueEmpty?.Invoke(this, EventArgs.Empty); + } } - } - public event EventHandler? ProcessingQueueEmpty; - public event EventHandler? BlockRemoved; + public event EventHandler? ProcessingQueueEmpty; + public event EventHandler? BlockRemoved; - int IBlockProcessingQueue.Count => _queueCount; + int IBlockProcessingQueue.Count => _queueCount; - public Block? Process(Block suggestedBlock, ProcessingOptions options, IBlockTracer tracer) - { - if (!RunSimpleChecksAheadOfProcessing(suggestedBlock, options)) + public Block? Process(Block suggestedBlock, ProcessingOptions options, IBlockTracer tracer) { - return null; - } + if (!RunSimpleChecksAheadOfProcessing(suggestedBlock, options)) + { + return null; + } - UInt256 totalDifficulty = suggestedBlock.TotalDifficulty ?? 0; - if (_logger.IsTrace) _logger.Trace($"Total difficulty of block {suggestedBlock.ToString(Block.Format.Short)} is {totalDifficulty}"); + UInt256 totalDifficulty = suggestedBlock.TotalDifficulty ?? 0; + if (_logger.IsTrace) _logger.Trace($"Total difficulty of block {suggestedBlock.ToString(Block.Format.Short)} is {totalDifficulty}"); - bool shouldProcess = - suggestedBlock.IsGenesis - || _blockTree.IsBetterThanHead(suggestedBlock.Header) - || options.ContainsFlag(ProcessingOptions.ForceProcessing); + bool shouldProcess = + suggestedBlock.IsGenesis + || _blockTree.IsBetterThanHead(suggestedBlock.Header) + || options.ContainsFlag(ProcessingOptions.ForceProcessing); - if (!shouldProcess) - { - if (_logger.IsDebug) - _logger.Debug( - $"Skipped processing of {suggestedBlock.ToString(Block.Format.FullHashAndNumber)}, Head = {_blockTree.Head?.Header?.ToString(BlockHeader.Format.Short)}, total diff = {totalDifficulty}, head total diff = {_blockTree.Head?.TotalDifficulty}"); - return null; - } + if (!shouldProcess) + { + if (_logger.IsDebug) + _logger.Debug( + $"Skipped processing of {suggestedBlock.ToString(Block.Format.FullHashAndNumber)}, Head = {_blockTree.Head?.Header?.ToString(BlockHeader.Format.Short)}, total diff = {totalDifficulty}, head total diff = {_blockTree.Head?.TotalDifficulty}"); + return null; + } - ProcessingBranch processingBranch = PrepareProcessingBranch(suggestedBlock, options); - PrepareBlocksToProcess(suggestedBlock, options, processingBranch); + ProcessingBranch processingBranch = PrepareProcessingBranch(suggestedBlock, options); + PrepareBlocksToProcess(suggestedBlock, options, processingBranch); - _stopwatch.Restart(); - Block[]? processedBlocks = ProcessBranch(processingBranch, options, tracer); - if (processedBlocks is null) - { - return null; - } + _stopwatch.Restart(); + Block[]? processedBlocks = ProcessBranch(processingBranch, options, tracer); + if (processedBlocks is null) + { + return null; + } - Block? lastProcessed = null; - if (processedBlocks.Length > 0) - { - lastProcessed = processedBlocks[^1]; - if (_logger.IsTrace) _logger.Trace($"Setting total on last processed to {lastProcessed.ToString(Block.Format.Short)}"); - lastProcessed.Header.TotalDifficulty = suggestedBlock.TotalDifficulty; - } - else - { - if (_logger.IsDebug) _logger.Debug($"Skipped processing of {suggestedBlock.ToString(Block.Format.FullHashAndNumber)}, last processed is null: {true}, processedBlocks.Length: {processedBlocks.Length}"); - } + Block? lastProcessed = null; + if (processedBlocks.Length > 0) + { + lastProcessed = processedBlocks[^1]; + if (_logger.IsTrace) _logger.Trace($"Setting total on last processed to {lastProcessed.ToString(Block.Format.Short)}"); + lastProcessed.Header.TotalDifficulty = suggestedBlock.TotalDifficulty; + } + else + { + if (_logger.IsDebug) _logger.Debug($"Skipped processing of {suggestedBlock.ToString(Block.Format.FullHashAndNumber)}, last processed is null: {true}, processedBlocks.Length: {processedBlocks.Length}"); + } - bool updateHead = !options.ContainsFlag(ProcessingOptions.DoNotUpdateHead); - if (updateHead) - { - if (_logger.IsTrace) _logger.Trace($"Updating main chain: {lastProcessed}, blocks count: {processedBlocks.Length}"); - _blockTree.UpdateMainChain(processingBranch.Blocks, true); - } + bool updateHead = !options.ContainsFlag(ProcessingOptions.DoNotUpdateHead); + if (updateHead) + { + if (_logger.IsTrace) _logger.Trace($"Updating main chain: {lastProcessed}, blocks count: {processedBlocks.Length}"); + _blockTree.UpdateMainChain(processingBranch.Blocks, true); + } - bool readonlyChain = options.ContainsFlag(ProcessingOptions.ReadOnlyChain); - long blockProcessingTimeInMs = _stopwatch.ElapsedMilliseconds; - if (!readonlyChain) - { - Metrics.LastBlockProcessingTimeInMs = blockProcessingTimeInMs; + bool readonlyChain = options.ContainsFlag(ProcessingOptions.ReadOnlyChain); + long blockProcessingTimeInMs = _stopwatch.ElapsedMilliseconds; + if (!readonlyChain) + { + Metrics.LastBlockProcessingTimeInMs = blockProcessingTimeInMs; + } + + if ((options & ProcessingOptions.MarkAsProcessed) == ProcessingOptions.MarkAsProcessed) + { + if (_logger.IsTrace) _logger.Trace($"Marked blocks as processed {lastProcessed}, blocks count: {processedBlocks.Length}"); + _blockTree.MarkChainAsProcessed(processingBranch.Blocks); + + Metrics.LastBlockProcessingTimeInMs = blockProcessingTimeInMs; + } + + if (!readonlyChain) + { + _stats.UpdateStats(lastProcessed, _blockTree, _recoveryQueue.Count, _blockQueue.Count, _stopwatch.ElapsedMicroseconds()); + } + + return lastProcessed; } - if ((options & ProcessingOptions.MarkAsProcessed) == ProcessingOptions.MarkAsProcessed) + public bool IsProcessingBlocks(ulong? maxProcessingInterval) { - if (_logger.IsTrace) _logger.Trace($"Marked blocks as processed {lastProcessed}, blocks count: {processedBlocks.Length}"); - _blockTree.MarkChainAsProcessed(processingBranch.Blocks); + if (_processorTask is null || _recoveryTask is null || _processorTask.IsCompleted || _recoveryTask.IsCompleted) + return false; - Metrics.LastBlockProcessingTimeInMs = blockProcessingTimeInMs; + // user does not setup interval and we cannot set interval time based on chainspec + return maxProcessingInterval is null || _lastProcessedBlock.AddSeconds(maxProcessingInterval.Value) > DateTime.UtcNow; } - if (!readonlyChain) + private void TraceFailingBranch(ProcessingBranch processingBranch, ProcessingOptions options, IBlockTracer blockTracer, DumpOptions dumpType) { - _stats.UpdateStats(lastProcessed, _blockTree, _recoveryQueue.Count, _blockQueue.Count, _stopwatch.ElapsedMicroseconds()); + if ((_options.DumpOptions & dumpType) != 0) + { + try + { + _blockProcessor.Process( + processingBranch.Root, + processingBranch.BlocksToProcess, + options, + blockTracer); + } + catch (InvalidBlockException ex) + { + BlockTraceDumper.LogDiagnosticTrace(blockTracer, ex.InvalidBlock.Hash!, _logger); + } + catch (Exception ex) + { + BlockTraceDumper.LogTraceFailure(blockTracer, processingBranch.Root, ex, _logger); + } + } } - return lastProcessed; - } - - public bool IsProcessingBlocks(ulong? maxProcessingInterval) - { - if (_processorTask is null || _recoveryTask is null || _processorTask.IsCompleted || _recoveryTask.IsCompleted) - return false; - - // user does not setup interval and we cannot set interval time based on chainspec - return maxProcessingInterval is null || _lastProcessedBlock.AddSeconds(maxProcessingInterval.Value) > DateTime.UtcNow; - } - - private void TraceFailingBranch(in ProcessingBranch processingBranch, ProcessingOptions options, IBlockTracer blockTracer, DumpOptions dumpType) - { - if ((_options.DumpOptions & dumpType) != 0) + private Block[]? ProcessBranch(ProcessingBranch processingBranch, ProcessingOptions options, IBlockTracer tracer) { + void DeleteInvalidBlocks(Keccak invalidBlockHash) + { + for (int i = 0; i < processingBranch.BlocksToProcess.Count; i++) + { + if (processingBranch.BlocksToProcess[i].Hash == invalidBlockHash) + { + _blockTree.DeleteInvalidBlock(processingBranch.BlocksToProcess[i]); + if (_logger.IsDebug) _logger.Debug($"Skipped processing of {processingBranch.BlocksToProcess[^1].ToString(Block.Format.FullHashAndNumber)} because of {processingBranch.BlocksToProcess[i].ToString(Block.Format.FullHashAndNumber)} is invalid"); + } + } + } + + Keccak? invalidBlockHash = null; + Block[]? processedBlocks; try { - _blockProcessor.Process( + processedBlocks = _blockProcessor.Process( processingBranch.Root, processingBranch.BlocksToProcess, options, - blockTracer); + tracer); } catch (InvalidBlockException ex) { - BlockTraceDumper.LogDiagnosticTrace(blockTracer, ex.InvalidBlock.Hash!, _logger); - } - catch (Exception ex) - { - BlockTraceDumper.LogTraceFailure(blockTracer, processingBranch.Root, ex, _logger); + InvalidBlock?.Invoke(this, new IBlockchainProcessor.InvalidBlockEventArgs + { + InvalidBlock = ex.InvalidBlock, + }); + + invalidBlockHash = ex.InvalidBlock.Hash; + TraceFailingBranch( + processingBranch, + options, + new BlockReceiptsTracer(), + DumpOptions.Receipts); + + TraceFailingBranch( + processingBranch, + options, + new ParityLikeBlockTracer(ParityTraceTypes.StateDiff | ParityTraceTypes.Trace), + DumpOptions.Parity); + + TraceFailingBranch( + processingBranch, + options, + new GethLikeBlockTracer(GethTraceOptions.Default), + DumpOptions.Geth); + + processedBlocks = null; } - } - } - private Block[]? ProcessBranch(in ProcessingBranch processingBranch, ProcessingOptions options, IBlockTracer tracer) - { - void DeleteInvalidBlocks(in ProcessingBranch processingBranch, Keccak invalidBlockHash) - { - for (int i = 0; i < processingBranch.BlocksToProcess.Count; i++) + finally { - if (processingBranch.BlocksToProcess[i].Hash == invalidBlockHash) + if (invalidBlockHash is not null && !options.ContainsFlag(ProcessingOptions.ReadOnlyChain)) { - _blockTree.DeleteInvalidBlock(processingBranch.BlocksToProcess[i]); - if (_logger.IsDebug) _logger.Debug($"Skipped processing of {processingBranch.BlocksToProcess[^1].ToString(Block.Format.FullHashAndNumber)} because of {processingBranch.BlocksToProcess[i].ToString(Block.Format.FullHashAndNumber)} is invalid"); + DeleteInvalidBlocks(invalidBlockHash); } } - } - Keccak? invalidBlockHash = null; - Block[]? processedBlocks; - try - { - processedBlocks = _blockProcessor.Process( - processingBranch.Root, - processingBranch.BlocksToProcess, - options, - tracer); - } - catch (InvalidBlockException ex) - { - InvalidBlock?.Invoke(this, new IBlockchainProcessor.InvalidBlockEventArgs - { - InvalidBlock = ex.InvalidBlock, - }); - - invalidBlockHash = ex.InvalidBlock.Hash; - TraceFailingBranch( - processingBranch, - options, - new BlockReceiptsTracer(), - DumpOptions.Receipts); - - TraceFailingBranch( - processingBranch, - options, - new ParityLikeBlockTracer(ParityTraceTypes.StateDiff | ParityTraceTypes.Trace), - DumpOptions.Parity); - - TraceFailingBranch( - processingBranch, - options, - new GethLikeBlockMemoryTracer(GethTraceOptions.Default), - DumpOptions.Geth); - - processedBlocks = null; + return processedBlocks; } - finally + private void PrepareBlocksToProcess(Block suggestedBlock, ProcessingOptions options, + ProcessingBranch processingBranch) { - if (invalidBlockHash is not null && !options.ContainsFlag(ProcessingOptions.ReadOnlyChain)) + List blocksToProcess = processingBranch.BlocksToProcess; + if (options.ContainsFlag(ProcessingOptions.ForceProcessing)) { - DeleteInvalidBlocks(in processingBranch, invalidBlockHash); + processingBranch.Blocks.Clear(); // TODO: investigate why if we clear it all we need to collect and iterate on all the blocks in PrepareProcessingBranch? + blocksToProcess.Add(suggestedBlock); } - } + else + { + foreach (Block block in processingBranch.Blocks) + { + _loopCancellationSource?.Token.ThrowIfCancellationRequested(); - return processedBlocks; - } + if (block.Hash is not null && _blockTree.WasProcessed(block.Number, block.Hash)) + { + if (_logger.IsInfo) + _logger.Info( + $"Rerunning block after reorg or pruning: {block.ToString(Block.Format.FullHashAndNumber)}"); + } - private void PrepareBlocksToProcess(Block suggestedBlock, ProcessingOptions options, - ProcessingBranch processingBranch) - { - List blocksToProcess = processingBranch.BlocksToProcess; - if (options.ContainsFlag(ProcessingOptions.ForceProcessing)) - { - processingBranch.Blocks.Clear(); // TODO: investigate why if we clear it all we need to collect and iterate on all the blocks in PrepareProcessingBranch? - blocksToProcess.Add(suggestedBlock); - } - else - { - foreach (Block block in processingBranch.Blocks) - { - _loopCancellationSource?.Token.ThrowIfCancellationRequested(); + blocksToProcess.Add(block); + } - if (block.Hash is not null && _blockTree.WasProcessed(block.Number, block.Hash)) + if (!blocksToProcess[0].IsGenesis) { - if (_logger.IsInfo) - _logger.Info( - $"Rerunning block after reorg or pruning: {block.ToString(Block.Format.Short)}"); + BlockHeader? parentOfFirstBlock = _blockTree.FindHeader(blocksToProcess[0].ParentHash!, BlockTreeLookupOptions.None); + if (parentOfFirstBlock == null) + { + throw new InvalidOperationException("Attempted to process a disconnected blockchain"); + } + + if (!_stateReader.HasStateForBlock(parentOfFirstBlock)) + { + throw new InvalidOperationException("Attempted to process a blockchain without having starting state"); + } } + } - blocksToProcess.Add(block); + if (_logger.IsTrace) + _logger.Trace($"Processing {blocksToProcess.Count} blocks from state root {processingBranch.Root}"); + for (int i = 0; i < blocksToProcess.Count; i++) + { + /* this can happen if the block was loaded as an ancestor and did not go through the recovery queue */ + _recoveryStep.RecoverData(blocksToProcess[i]); } + } - if (!blocksToProcess[0].IsGenesis) + private ProcessingBranch PrepareProcessingBranch(Block suggestedBlock, ProcessingOptions options) + { + BlockHeader branchingPoint = null; + List blocksToBeAddedToMain = new(); + + bool preMergeFinishBranchingCondition; + bool suggestedBlockIsPostMerge = suggestedBlock.IsPostMerge; + + Block toBeProcessed = suggestedBlock; + long iterations = 0; + do { - BlockHeader? parentOfFirstBlock = _blockTree.FindHeader(blocksToProcess[0].ParentHash!, BlockTreeLookupOptions.None); - if (parentOfFirstBlock == null) + iterations++; + if (!options.ContainsFlag(ProcessingOptions.Trace)) { - throw new InvalidOperationException("Attempted to process a disconnected blockchain"); + blocksToBeAddedToMain.Add(toBeProcessed); } - if (!_stateReader.HasStateForBlock(parentOfFirstBlock)) + if (_logger.IsTrace) + _logger.Trace( + $"To be processed (of {suggestedBlock.ToString(Block.Format.Short)}) is {toBeProcessed?.ToString(Block.Format.Short)}"); + if (toBeProcessed.IsGenesis) { - throw new InvalidOperationException("Attempted to process a blockchain without having starting state"); + break; } - } - } - if (_logger.IsTrace) - _logger.Trace($"Processing {blocksToProcess.Count} blocks from state root {processingBranch.Root}"); - for (int i = 0; i < blocksToProcess.Count; i++) - { - /* this can happen if the block was loaded as an ancestor and did not go through the recovery queue */ - _recoveryStep.RecoverData(blocksToProcess[i]); - } - } + branchingPoint = _blockTree.FindParentHeader(toBeProcessed.Header, + BlockTreeLookupOptions.TotalDifficultyNotNeeded); + if (branchingPoint is null) + { + // genesis block + break; + } - private ProcessingBranch PrepareProcessingBranch(Block suggestedBlock, ProcessingOptions options) - { - BlockHeader branchingPoint = null; - List blocksToBeAddedToMain = new(); + // !!! + // for beam sync we do not expect previous blocks to necessarily be there and we + // do not need them since we can requests state from outside + // TODO: remove this and verify the current usage scenarios - seems wrong + // !!! + if (options.ContainsFlag(ProcessingOptions.IgnoreParentNotOnMainChain)) + { + break; + } - bool preMergeFinishBranchingCondition; - bool suggestedBlockIsPostMerge = suggestedBlock.IsPostMerge; + bool headIsGenesis = _blockTree.Head?.IsGenesis ?? false; + bool toBeProcessedIsNotBlockOne = toBeProcessed.Number > 1; + if (_logger.IsTrace) + _logger.Trace($"Finding parent of {toBeProcessed.ToString(Block.Format.Short)}"); + toBeProcessed = _blockTree.FindParent(toBeProcessed.Header, BlockTreeLookupOptions.None); + if (_logger.IsTrace) _logger.Trace($"Found parent {toBeProcessed?.ToString(Block.Format.Short)}"); + bool isFastSyncTransition = headIsGenesis && toBeProcessedIsNotBlockOne; + if (toBeProcessed is null) + { + if (_logger.IsDebug) + _logger.Debug( + $"Treating this as fast sync transition for {suggestedBlock.ToString(Block.Format.Short)}"); + break; + } - Block toBeProcessed = suggestedBlock; - long iterations = 0; - do - { - iterations++; - if (!options.ContainsFlag(ProcessingOptions.Trace)) - { - blocksToBeAddedToMain.Add(toBeProcessed); - } + if (isFastSyncTransition) + { + // If we hit this condition, it means that something is wrong in MultiSyncModeSelector. + // MultiSyncModeSelector switched to full sync when it shouldn't + // In this case, it is better to stop searching for more blocks and failed during the processing than trying to build a branch up to the genesis point + if (iterations > MaxBlocksDuringFastSyncTransition) + { + if (_logger.IsWarn) _logger.Warn($"Too long branch to be processed during fast sync transition. Current block to be processed {toBeProcessed}, StateRoot: {toBeProcessed?.StateRoot}"); + break; + } - if (_logger.IsTrace) - _logger.Trace( - $"To be processed (of {suggestedBlock.ToString(Block.Format.Short)}) is {toBeProcessed?.ToString(Block.Format.Short)}"); - if (toBeProcessed.IsGenesis) + // if we have parent state it means that we don't need to go deeper + if (toBeProcessed?.StateRoot is null || _stateReader.HasStateForBlock(toBeProcessed.Header)) + { + if (_logger.IsInfo) _logger.Info($"Found state for parent: {toBeProcessed}, StateRoot: {toBeProcessed?.StateRoot}"); + break; + } + else + { + if (_logger.IsDebug) _logger.Debug($"A new block {toBeProcessed} in fast sync transition branch - state not found"); + } + } + + // TODO: there is no test for the second condition + // generally if we finish fast sync at block, e.g. 8 and then have 6 blocks processed and close Neth + // then on restart we would find 14 as the branch head (since 14 is on the main chain) + // we need to dig deeper to go all the way to the false (reorg boundary) head + // otherwise some nodes would be missing + bool notFoundTheBranchingPointYet = !_blockTree.IsMainChain(branchingPoint.Hash!); + bool notReachedTheReorgBoundary = branchingPoint.Number > (_blockTree.Head?.Header.Number ?? 0); + preMergeFinishBranchingCondition = (notFoundTheBranchingPointYet || notReachedTheReorgBoundary); + if (_logger.IsTrace) + _logger.Trace( + $" Current branching point: {branchingPoint.Number}, {branchingPoint.Hash} TD: {branchingPoint.TotalDifficulty} Processing conditions notFoundTheBranchingPointYet {notFoundTheBranchingPointYet}, notReachedTheReorgBoundary: {notReachedTheReorgBoundary}, suggestedBlockIsPostMerge {suggestedBlockIsPostMerge}"); + + } while (preMergeFinishBranchingCondition); + + if (branchingPoint is not null && branchingPoint.Hash != _blockTree.Head?.Hash) { - break; + if (_logger.IsTrace) + _logger.Trace($"Head block was: {_blockTree.Head?.Header?.ToString(BlockHeader.Format.Short)}"); + if (_logger.IsTrace) + _logger.Trace($"Branching from: {branchingPoint.ToString(BlockHeader.Format.Short)}"); } - - branchingPoint = _blockTree.FindParentHeader(toBeProcessed.Header, - BlockTreeLookupOptions.TotalDifficultyNotNeeded); - if (branchingPoint is null) + else { - // genesis block - break; + if (_logger.IsTrace) + _logger.Trace(branchingPoint is null + ? "Setting as genesis block" + : $"Adding on top of {branchingPoint.ToString(BlockHeader.Format.Short)}"); } - // !!! - // for beam sync we do not expect previous blocks to necessarily be there and we - // do not need them since we can requests state from outside - // TODO: remove this and verify the current usage scenarios - seems wrong - // !!! - if (options.ContainsFlag(ProcessingOptions.IgnoreParentNotOnMainChain)) + Keccak stateRoot = branchingPoint?.StateRoot; + if (_logger.IsTrace) _logger.Trace($"State root lookup: {stateRoot}"); + blocksToBeAddedToMain.Reverse(); + return new ProcessingBranch(stateRoot, blocksToBeAddedToMain); + } + + [Todo(Improve.Refactor, "This probably can be made conditional (in DEBUG only)")] + private bool RunSimpleChecksAheadOfProcessing(Block suggestedBlock, ProcessingOptions options) + { + /* a bit hacky way to get the invalid branch out of the processing loop */ + if (suggestedBlock.Number != 0 && + !_blockTree.IsKnownBlock(suggestedBlock.Number - 1, suggestedBlock.ParentHash)) { - break; + if (_logger.IsDebug) + _logger.Debug( + $"Skipping processing block {suggestedBlock.ToString(Block.Format.FullHashAndNumber)} with unknown parent"); + return false; } - bool headIsGenesis = _blockTree.Head?.IsGenesis ?? false; - bool toBeProcessedIsNotBlockOne = toBeProcessed.Number > 1; - if (_logger.IsTrace) - _logger.Trace($"Finding parent of {toBeProcessed.ToString(Block.Format.Short)}"); - toBeProcessed = _blockTree.FindParent(toBeProcessed.Header, BlockTreeLookupOptions.None); - if (_logger.IsTrace) _logger.Trace($"Found parent {toBeProcessed?.ToString(Block.Format.Short)}"); - bool isFastSyncTransition = headIsGenesis && toBeProcessedIsNotBlockOne; - if (toBeProcessed is null) + if (suggestedBlock.Header.TotalDifficulty is null) { if (_logger.IsDebug) _logger.Debug( - $"Treating this as fast sync transition for {suggestedBlock.ToString(Block.Format.Short)}"); - break; + $"Skipping processing block {suggestedBlock.ToString(Block.Format.FullHashAndNumber)} without total difficulty"); + throw new InvalidOperationException( + "Block without total difficulty calculated was suggested for processing"); } - if (isFastSyncTransition) + if (!options.ContainsFlag(ProcessingOptions.NoValidation) && suggestedBlock.Hash is null) { - // If we hit this condition, it means that something is wrong in MultiSyncModeSelector. - // MultiSyncModeSelector switched to full sync when it shouldn't - // In this case, it is better to stop searching for more blocks and failed during the processing than trying to build a branch up to the genesis point - if (iterations > MaxBlocksDuringFastSyncTransition) - { - if (_logger.IsWarn) _logger.Warn($"Too long branch to be processed during fast sync transition. Current block to be processed {toBeProcessed}, StateRoot: {toBeProcessed?.StateRoot}"); - break; - } + if (_logger.IsDebug) _logger.Debug($"Skipping processing block {suggestedBlock.ToString(Block.Format.FullHashAndNumber)} without calculated hash"); + throw new InvalidOperationException("Block hash should be known at this stage if running in a validating mode"); + } - // if we have parent state it means that we don't need to go deeper - if (toBeProcessed?.StateRoot is null || _stateReader.HasStateForBlock(toBeProcessed.Header)) - { - if (_logger.IsInfo) _logger.Info($"Found state for parent: {toBeProcessed}, StateRoot: {toBeProcessed?.StateRoot}"); - break; - } - else + for (int i = 0; i < suggestedBlock.Uncles.Length; i++) + { + if (suggestedBlock.Uncles[i].Hash is null) { - if (_logger.IsDebug) _logger.Debug($"A new block {toBeProcessed} in fast sync transition branch - state not found"); + if (_logger.IsDebug) _logger.Debug($"Skipping processing block {suggestedBlock.ToString(Block.Format.FullHashAndNumber)} with null uncle hash ar {i}"); + throw new InvalidOperationException($"Uncle's {i} hash is null when processing block"); } } - // TODO: there is no test for the second condition - // generally if we finish fast sync at block, e.g. 8 and then have 6 blocks processed and close Neth - // then on restart we would find 14 as the branch head (since 14 is on the main chain) - // we need to dig deeper to go all the way to the false (reorg boundary) head - // otherwise some nodes would be missing - bool notFoundTheBranchingPointYet = !_blockTree.IsMainChain(branchingPoint.Hash!); - bool notReachedTheReorgBoundary = branchingPoint.Number > (_blockTree.Head?.Header.Number ?? 0); - preMergeFinishBranchingCondition = (notFoundTheBranchingPointYet || notReachedTheReorgBoundary); - if (_logger.IsTrace) - _logger.Trace( - $" Current branching point: {branchingPoint.Number}, {branchingPoint.Hash} TD: {branchingPoint.TotalDifficulty} Processing conditions notFoundTheBranchingPointYet {notFoundTheBranchingPointYet}, notReachedTheReorgBoundary: {notReachedTheReorgBoundary}, suggestedBlockIsPostMerge {suggestedBlockIsPostMerge}"); - - } while (preMergeFinishBranchingCondition); - - if (branchingPoint is not null && branchingPoint.Hash != _blockTree.Head?.Hash) - { - if (_logger.IsTrace) - _logger.Trace($"Head block was: {_blockTree.Head?.Header?.ToString(BlockHeader.Format.Short)}"); - if (_logger.IsTrace) - _logger.Trace($"Branching from: {branchingPoint.ToString(BlockHeader.Format.Short)}"); - } - else - { - if (_logger.IsTrace) - _logger.Trace(branchingPoint is null - ? "Setting as genesis block" - : $"Adding on top of {branchingPoint.ToString(BlockHeader.Format.Short)}"); - } - - Keccak stateRoot = branchingPoint?.StateRoot; - if (_logger.IsTrace) _logger.Trace($"State root lookup: {stateRoot}"); - blocksToBeAddedToMain.Reverse(); - return new ProcessingBranch(stateRoot, blocksToBeAddedToMain); - } - - [Todo(Improve.Refactor, "This probably can be made conditional (in DEBUG only)")] - private bool RunSimpleChecksAheadOfProcessing(Block suggestedBlock, ProcessingOptions options) - { - /* a bit hacky way to get the invalid branch out of the processing loop */ - if (suggestedBlock.Number != 0 && - !_blockTree.IsKnownBlock(suggestedBlock.Number - 1, suggestedBlock.ParentHash)) - { - if (_logger.IsDebug) - _logger.Debug( - $"Skipping processing block {suggestedBlock.ToString(Block.Format.FullHashAndNumber)} with unknown parent"); - return false; - } - - if (suggestedBlock.Header.TotalDifficulty is null) - { - if (_logger.IsDebug) - _logger.Debug( - $"Skipping processing block {suggestedBlock.ToString(Block.Format.FullHashAndNumber)} without total difficulty"); - throw new InvalidOperationException( - "Block without total difficulty calculated was suggested for processing"); + return true; } - if (!options.ContainsFlag(ProcessingOptions.NoValidation) && suggestedBlock.Hash is null) + public void Dispose() { - if (_logger.IsDebug) _logger.Debug($"Skipping processing block {suggestedBlock.ToString(Block.Format.FullHashAndNumber)} without calculated hash"); - throw new InvalidOperationException("Block hash should be known at this stage if running in a validating mode"); + _recoveryQueue.Dispose(); + _blockQueue.Dispose(); + _loopCancellationSource?.Dispose(); + _recoveryTask?.Dispose(); + _processorTask?.Dispose(); + _blockTree.NewBestSuggestedBlock -= OnNewBestBlock; + _blockTree.NewHeadBlock -= OnNewHeadBlock; } - for (int i = 0; i < suggestedBlock.Uncles.Length; i++) + [DebuggerDisplay("Root: {Root}, Length: {BlocksToProcess.Count}")] + private readonly struct ProcessingBranch { - if (suggestedBlock.Uncles[i].Hash is null) + public ProcessingBranch(Keccak root, List blocks) { - if (_logger.IsDebug) _logger.Debug($"Skipping processing block {suggestedBlock.ToString(Block.Format.FullHashAndNumber)} with null uncle hash ar {i}"); - throw new InvalidOperationException($"Uncle's {i} hash is null when processing block"); + Root = root; + Blocks = blocks; + BlocksToProcess = new List(); } - } - return true; - } - - public void Dispose() - { - _recoveryQueue.Dispose(); - _blockQueue.Dispose(); - _loopCancellationSource?.Dispose(); - _recoveryTask?.Dispose(); - _processorTask?.Dispose(); - _blockTree.NewBestSuggestedBlock -= OnNewBestBlock; - _blockTree.NewHeadBlock -= OnNewHeadBlock; - } - - [DebuggerDisplay("Root: {Root}, Length: {BlocksToProcess.Count}")] - private readonly struct ProcessingBranch - { - public ProcessingBranch(Keccak root, List blocks) - { - Root = root; - Blocks = blocks; - BlocksToProcess = new List(); + public Keccak Root { get; } + public List Blocks { get; } + public List BlocksToProcess { get; } } - public Keccak Root { get; } - public List Blocks { get; } - public List BlocksToProcess { get; } - } - - public class Options - { - public static Options NoReceipts = new() { StoreReceiptsByDefault = true }; - public static Options Default = new(); + public class Options + { + public static Options NoReceipts = new() { StoreReceiptsByDefault = true }; + public static Options Default = new(); - public bool StoreReceiptsByDefault { get; set; } = true; + public bool StoreReceiptsByDefault { get; set; } = true; - public DumpOptions DumpOptions { get; set; } = DumpOptions.None; + public DumpOptions DumpOptions { get; set; } = DumpOptions.None; + } } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs index b3703b653f8..0a0ba644782 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/IBlockchainProcessor.cs @@ -3,7 +3,9 @@ using System; using System.Threading.Tasks; +using Nethermind.Blockchain; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Evm.Tracing; namespace Nethermind.Consensus.Processing diff --git a/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs index dba8eecce74..668319e3b0a 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/OneTimeProcessor.cs @@ -3,6 +3,7 @@ using System; using System.Threading.Tasks; +using Nethermind.Blockchain; using Nethermind.Core; using Nethermind.Db; using Nethermind.Evm.Tracing; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs index 5d36900eb83..0181b2cef05 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs @@ -5,26 +5,22 @@ using System.Diagnostics; using Nethermind.Blockchain; using Nethermind.Core; -using Nethermind.Core.Extensions; using Nethermind.Int256; using Nethermind.Logging; namespace Nethermind.Consensus.Processing { - //TODO Consult on disabling of such metrics from configuration + //TODO Consult on disabeling of such metrics from configuration internal class ProcessingStats { private readonly ILogger _logger; private readonly Stopwatch _processingStopwatch = new(); private readonly Stopwatch _runStopwatch = new(); private long _lastBlockNumber; - private long _lastElapsedRunningMicroseconds; + private long _lastElapsedProcessingTicks; + private long _lastElapsedRunningTicks; private decimal _lastTotalMGas; private long _lastTotalTx; - private long _lastTotalCalls; - private long _lastTotalEmptyCalls; - private long _lastTotalSLoad; - private long _lastTotalSStore; private long _lastStateDbReads; private long _lastStateDbWrites; private long _lastGen0; @@ -36,9 +32,7 @@ internal class ProcessingStats private long _maxMemory; private long _totalBlocks; private bool _isDebugMode = false; - private decimal _processingMicroseconds; - private long _lastTotalCreates; - private long _lastReportMs; + private decimal _processingTimeInMicros; public ProcessingStats(ILogger logger) { @@ -51,17 +45,8 @@ public ProcessingStats(ILogger logger) #endif } - public void UpdateStats(Block? block, IBlockTree blockTreeCtx, int recoveryQueueSize, int blockQueueSize, long blockProcessingTimeInMicros) + public void UpdateStats(Block? block, IBlockTree blockTreeCtx, int recoveryQueueSize, int blockQueueSize, long lastBlockProcessingTimeInMicros) { - const string resetColor = "\u001b[37m"; - const string whiteText = "\u001b[97m"; - const string yellowText = "\u001b[93m"; - const string orangeText = "\u001b[38;5;208m"; - const string redText = "\u001b[38;5;196m"; - const string greenText = "\u001b[92m"; - const string darkGreenText = "\u001b[32m"; - const string darkGreyText = resetColor; // "\u001b[90m"; - if (block is null) { return; @@ -74,7 +59,7 @@ public void UpdateStats(Block? block, IBlockTree blockTreeCtx, int recoveryQueue _lastBlockNumber = block.Number; } - _processingMicroseconds += blockProcessingTimeInMicros; + _processingTimeInMicros += lastBlockProcessingTimeInMicros; Metrics.Mgas += block.GasUsed / 1_000_000m; Metrics.Transactions += block.Transactions.Length; @@ -89,143 +74,64 @@ public void UpdateStats(Block? block, IBlockTree blockTreeCtx, int recoveryQueue Metrics.BlockchainHeight = block.Header.Number; Metrics.BestKnownBlockNumber = blockTreeCtx.BestKnownNumber; - long processingMicroseconds = _processingStopwatch.ElapsedMicroseconds(); - long runningMicroseconds = _runStopwatch.ElapsedMicroseconds(); - decimal runMicroseconds = (runningMicroseconds - _lastElapsedRunningMicroseconds); + long currentTicks = _processingStopwatch.ElapsedTicks; + long runningTicks = _runStopwatch.ElapsedTicks; + decimal runMicroseconds = (runningTicks - _lastElapsedRunningTicks) * (1_000_000m / Stopwatch.Frequency); - long reportMs = Environment.TickCount64; - if (reportMs - _lastReportMs > 1000) + if (runMicroseconds > 1 * 1000 * 1000) { + decimal chunkMicroseconds = _processingTimeInMicros; + decimal totalMicroseconds = currentTicks * (1_000_000m / Stopwatch.Frequency); long currentStateDbReads = Db.Metrics.StateDbReads; long currentStateDbWrites = Db.Metrics.StateDbWrites; long currentTreeNodeRlp = Trie.Metrics.TreeNodeRlpEncodings + Trie.Metrics.TreeNodeRlpDecodings; long evmExceptions = Evm.Metrics.EvmExceptions; long currentSelfDestructs = Evm.Metrics.SelfDestructs; - + long chunkTx = Metrics.Transactions - _lastTotalTx; long chunkBlocks = Metrics.Blocks - _lastBlockNumber; + decimal chunkMGas = Metrics.Mgas - _lastTotalMGas; + _totalBlocks += chunkBlocks; - if (_logger.IsInfo) - { - decimal chunkMicroseconds = _processingMicroseconds; - decimal totalMicroseconds = processingMicroseconds; - long chunkTx = Metrics.Transactions - _lastTotalTx; - long chunkCalls = Evm.Metrics.Calls - _lastTotalCalls; - long chunkEmptyCalls = Evm.Metrics.EmptyCalls - _lastTotalEmptyCalls; - long chunkCreates = Evm.Metrics.Creates - _lastTotalCreates; - long chunkSload = Evm.Metrics.SloadOpcode - _lastTotalSLoad; - long chunkSstore = Evm.Metrics.SstoreOpcode - _lastTotalSStore; - decimal chunkMGas = Metrics.Mgas - _lastTotalMGas; - decimal mgasPerSecond = chunkMicroseconds == 0 ? -1 : chunkMGas / chunkMicroseconds * 1000 * 1000; - decimal totalMgasPerSecond = totalMicroseconds == 0 ? -1 : Metrics.Mgas / totalMicroseconds * 1000 * 1000; - decimal totalTxPerSecond = totalMicroseconds == 0 ? -1 : Metrics.Transactions / totalMicroseconds * 1000 * 1000; - decimal totalBlocksPerSecond = totalMicroseconds == 0 ? -1 : _totalBlocks / totalMicroseconds * 1000 * 1000; - decimal txps = chunkMicroseconds == 0 ? -1 : chunkTx / chunkMicroseconds * 1000 * 1000; - decimal bps = chunkMicroseconds == 0 ? -1 : chunkBlocks / chunkMicroseconds * 1000 * 1000; - decimal chunkMs = (chunkMicroseconds == 0 ? -1 : chunkMicroseconds / 1000); - decimal runMs = (runMicroseconds == 0 ? -1 : runMicroseconds / 1000); - string blockGas = Evm.Metrics.BlockMinGasPrice != decimal.MaxValue ? $" Gas gwei: {Evm.Metrics.BlockMinGasPrice:N2} .. {whiteText}{Math.Max(Evm.Metrics.BlockMinGasPrice, Evm.Metrics.BlockEstMedianGasPrice):N2}{resetColor} ({Evm.Metrics.BlockAveGasPrice:N2}) .. {Evm.Metrics.BlockMaxGasPrice:N2}" : ""; - if (chunkBlocks > 1) - { - _logger.Info($"Processed {block.Number - chunkBlocks + 1,9}...{block.Number,9} | {chunkMs,9:N2} ms | slot {runMs,7:N0} ms |{blockGas}"); - } - else - { - var chunkColor = chunkMs switch - { - < 200 => greenText, - < 300 => darkGreenText, - < 500 => whiteText, - < 1000 => yellowText, - < 2000 => orangeText, - _ => redText - }; - _logger.Info($"Processed {block.Number,9} | {chunkColor}{chunkMs,9:N2}{resetColor} ms | slot {runMs,7:N0} ms |{blockGas}"); - } - - var mgasColor = chunkMGas switch - { - > 28 => greenText, - > 25 => darkGreenText, - > 15 => whiteText, - _ => resetColor - }; - var sstoreColor = chunkBlocks > 1 ? "" : chunkSstore switch - { - > 3500 => redText, - > 2500 => orangeText, - > 2000 => yellowText, - > 1500 => whiteText, - > 900 when chunkCalls > 900 => whiteText, - _ => "" - }; - var callsColor = chunkBlocks > 1 ? "" : chunkCalls switch - { - > 3500 => redText, - > 2500 => orangeText, - > 2000 => yellowText, - > 1500 => whiteText, - > 900 when chunkSstore > 900 => whiteText, - _ => "" - }; - var createsColor = chunkBlocks > 1 ? "" : chunkCreates switch - { - > 300 => redText, - > 200 => orangeText, - > 150 => yellowText, - > 75 => whiteText, - _ => "" - }; - _logger.Info($"- Block{(chunkBlocks > 1 ? $"s {chunkBlocks,-9:N0}" : " ")}{(chunkBlocks == 1 ? mgasColor : "")} {chunkMGas,7:F2}{resetColor} MGas | {chunkTx,6:N0} txs | calls {callsColor}{chunkCalls,6:N0}{resetColor} {darkGreyText}({chunkEmptyCalls,3:N0}){resetColor} | sload {chunkSload,7:N0} | sstore {sstoreColor}{chunkSstore,6:N0}{resetColor} | create {createsColor}{chunkCreates,3:N0}{resetColor}{(currentSelfDestructs - _lastSelfDestructs > 0 ? $"{darkGreyText}({-(currentSelfDestructs - _lastSelfDestructs),3:N0}){resetColor}" : "")}"); - _logger.Info($"- Block throughput {mgasPerSecond,7:F2} MGas/s | {txps,9:F2} t/s | {bps,7:F2} Blk/s | recv {recoveryQueueSize,7:N0} | proc {blockQueueSize,6:N0}"); - // Only output the total throughput in debug mode - if (_logger.IsDebug) - { - _logger.Debug($"- Total throughput {totalMgasPerSecond,7:F2} MGas/s | {totalTxPerSecond,9:F2} t/s | {totalBlocksPerSecond,7:F2} Blk/s | Gas gwei: {Evm.Metrics.MinGasPrice:N2} .. {Math.Max(Evm.Metrics.MinGasPrice, Evm.Metrics.EstMedianGasPrice):N2} ({Evm.Metrics.AveGasPrice:N2}) .. {Evm.Metrics.MaxGasPrice:N2}"); - } - - if (_logger.IsTrace) - { - long currentGen0 = GC.CollectionCount(0); - long currentGen1 = GC.CollectionCount(1); - long currentGen2 = GC.CollectionCount(2); - long currentMemory = GC.GetTotalMemory(false); - _maxMemory = Math.Max(_maxMemory, currentMemory); - _logger.Trace($"Gen0 {currentGen0 - _lastGen0,6}, Gen1 {currentGen1 - _lastGen1,6}, Gen2 {currentGen2 - _lastGen2,6}, maxmem {_maxMemory / 1000000,5}, mem {currentMemory / 1000000,5}, reads {currentStateDbReads - _lastStateDbReads,9}, writes {currentStateDbWrites - _lastStateDbWrites,9}, rlp {currentTreeNodeRlp - _lastTreeNodeRlp,9}, exceptions {evmExceptions - _lastEvmExceptions}, selfdstrcs {currentSelfDestructs - _lastSelfDestructs}"); - _lastGen0 = currentGen0; - _lastGen1 = currentGen1; - _lastGen2 = currentGen2; - } + decimal mgasPerSecond = chunkMicroseconds == 0 ? -1 : chunkMGas / chunkMicroseconds * 1000 * 1000; + decimal totalMgasPerSecond = totalMicroseconds == 0 ? -1 : Metrics.Mgas / totalMicroseconds * 1000 * 1000; + decimal totalTxPerSecond = totalMicroseconds == 0 ? -1 : Metrics.Transactions / totalMicroseconds * 1000 * 1000; + decimal totalBlocksPerSecond = totalMicroseconds == 0 ? -1 : _totalBlocks / totalMicroseconds * 1000 * 1000; + decimal txps = chunkMicroseconds == 0 ? -1 : chunkTx / chunkMicroseconds * 1000 * 1000; + decimal bps = chunkMicroseconds == 0 ? -1 : chunkBlocks / chunkMicroseconds * 1000 * 1000; + if (_logger.IsInfo) _logger.Info($"Processed {block.Number,9} | {(chunkMicroseconds == 0 ? -1 : chunkMicroseconds / 1000),7:N0}ms of {(runMicroseconds == 0 ? -1 : runMicroseconds / 1000),7:N0}ms, mgasps {mgasPerSecond,7:F2} total {totalMgasPerSecond,7:F2}, tps {txps,7:F2} total {totalTxPerSecond,7:F2}, bps {bps,7:F2} total {totalBlocksPerSecond,7:F2}, recv queue {recoveryQueueSize}, proc queue {blockQueueSize}"); + if (_logger.IsTrace) + { + long currentGen0 = GC.CollectionCount(0); + long currentGen1 = GC.CollectionCount(1); + long currentGen2 = GC.CollectionCount(2); + long currentMemory = GC.GetTotalMemory(false); + _maxMemory = Math.Max(_maxMemory, currentMemory); + _logger.Trace($"Gen0 {currentGen0 - _lastGen0,6}, Gen1 {currentGen1 - _lastGen1,6}, Gen2 {currentGen2 - _lastGen2,6}, maxmem {_maxMemory / 1000000,5}, mem {currentMemory / 1000000,5}, reads {currentStateDbReads - _lastStateDbReads,9}, writes {currentStateDbWrites - _lastStateDbWrites,9}, rlp {currentTreeNodeRlp - _lastTreeNodeRlp,9}, exceptions {evmExceptions - _lastEvmExceptions}, selfdstrcs {currentSelfDestructs - _lastSelfDestructs}"); + _lastGen0 = currentGen0; + _lastGen1 = currentGen1; + _lastGen2 = currentGen2; } - _lastReportMs = reportMs; _lastBlockNumber = Metrics.Blocks; _lastTotalMGas = Metrics.Mgas; - _lastElapsedRunningMicroseconds = runningMicroseconds; + _lastElapsedProcessingTicks = currentTicks; + _lastElapsedRunningTicks = runningTicks; _lastTotalTx = Metrics.Transactions; - _lastTotalCalls = Evm.Metrics.Calls; - _lastTotalEmptyCalls = Evm.Metrics.EmptyCalls; - _lastTotalCreates = Evm.Metrics.Creates; - _lastTotalSLoad = Evm.Metrics.SloadOpcode; - _lastTotalSStore = Evm.Metrics.SstoreOpcode; _lastStateDbReads = currentStateDbReads; _lastStateDbWrites = currentStateDbWrites; _lastTreeNodeRlp = currentTreeNodeRlp; _lastEvmExceptions = evmExceptions; _lastSelfDestructs = currentSelfDestructs; - _processingMicroseconds = 0; + _processingTimeInMicros = 0; } } public void Start() { _processingStopwatch.Start(); - if (!_runStopwatch.IsRunning) - { - _lastReportMs = Environment.TickCount64; - _runStopwatch.Start(); - } + _runStopwatch.Start(); } } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs index 65baaa7ea3e..da38938699c 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs @@ -5,6 +5,7 @@ using Nethermind.Blockchain.Receipts; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; +using Nethermind.Consensus.Withdrawals; using Nethermind.Core.Specs; using Nethermind.Db; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs index 1f6a60de2d4..f99c5f01b12 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs @@ -3,6 +3,7 @@ using System; using Nethermind.Blockchain; +using Nethermind.Consensus.Withdrawals; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Db; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs b/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs index b8f6ae446f4..d00b2b4fdf2 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs @@ -2,29 +2,29 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Core; -using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.State; -namespace Nethermind.Consensus.Processing; - -internal static class TransactionProcessorAdapterExtensions +namespace Nethermind.Consensus.Processing { - public static void ProcessTransaction(this ITransactionProcessorAdapter transactionProcessor, - BlockExecutionContext blkCtx, - Transaction currentTx, - BlockReceiptsTracer receiptsTracer, - ProcessingOptions processingOptions, - IWorldState stateProvider) + internal static class TransactionProcessorAdapterExtensions { - if (processingOptions.ContainsFlag(ProcessingOptions.DoNotVerifyNonce)) + public static void ProcessTransaction(this ITransactionProcessorAdapter transactionProcessor, + Block block, + Transaction currentTx, + BlockReceiptsTracer receiptsTracer, + ProcessingOptions processingOptions, + IWorldState stateProvider) { - currentTx.Nonce = stateProvider.GetNonce(currentTx.SenderAddress); - } + if (processingOptions.ContainsFlag(ProcessingOptions.DoNotVerifyNonce)) + { + currentTx.Nonce = stateProvider.GetNonce(currentTx.SenderAddress); + } - receiptsTracer.StartNewTxTrace(currentTx); - transactionProcessor.Execute(currentTx, blkCtx, receiptsTracer); - receiptsTracer.EndTxTrace(); + receiptsTracer.StartNewTxTrace(currentTx); + transactionProcessor.Execute(currentTx, block.Header, receiptsTracer); + receiptsTracer.EndTxTrace(); + } } } diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs index 961bac4cd6c..6899d80e8ab 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs @@ -12,6 +12,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Int256; using Nethermind.Logging; @@ -291,7 +292,6 @@ protected virtual BlockHeader PrepareBlockHeader(BlockHeader parent, { Author = blockAuthor, MixHash = payloadAttributes?.PrevRandao, - ParentBeaconBlockRoot = payloadAttributes?.ParentBeaconBlockRoot }; UInt256 difficulty = _difficultyCalculator.Calculate(header, parent); @@ -300,6 +300,7 @@ protected virtual BlockHeader PrepareBlockHeader(BlockHeader parent, if (Logger.IsDebug) Logger.Debug($"Setting total difficulty to {parent.TotalDifficulty} + {difficulty}."); + IReleaseSpec spec = _specProvider.GetSpec(header); header.BaseFeePerGas = BaseFeeCalculator.Calculate(parent, _specProvider.GetSpec(header)); return header; diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProductionEventArgs.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProductionEventArgs.cs index 089a12cfcf6..1e31cf40d8a 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProductionEventArgs.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProductionEventArgs.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Nethermind.Core; using Nethermind.Evm.Tracing; +using Nethermind.Int256; namespace Nethermind.Consensus.Producers { diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockToProduce.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockToProduce.cs index 7a23c516027..ab7bb2ffa9a 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockToProduce.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockToProduce.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Runtime.CompilerServices; using Nethermind.Core; diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BuildBlocksWhenRequested.cs b/src/Nethermind/Nethermind.Consensus/Producers/BuildBlocksWhenRequested.cs index 90e4d26acd9..1d2a7755319 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BuildBlocksWhenRequested.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BuildBlocksWhenRequested.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Nethermind.Core; using Nethermind.Evm.Tracing; +using Nethermind.Int256; namespace Nethermind.Consensus.Producers { diff --git a/src/Nethermind/Nethermind.Consensus/Producers/IManualBlockProductionTrigger.cs b/src/Nethermind/Nethermind.Consensus/Producers/IManualBlockProductionTrigger.cs index 5938b5d70f5..1c9b20fbc25 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/IManualBlockProductionTrigger.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/IManualBlockProductionTrigger.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Nethermind.Core; using Nethermind.Evm.Tracing; +using Nethermind.Int256; namespace Nethermind.Consensus.Producers { diff --git a/src/Nethermind/Nethermind.Consensus/Producers/PayloadAttributes.cs b/src/Nethermind/Nethermind.Consensus/Producers/PayloadAttributes.cs index 4f2a7f8bd3e..a2e78b2a2fd 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/PayloadAttributes.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/PayloadAttributes.cs @@ -25,7 +25,6 @@ public class PayloadAttributes public IList? Withdrawals { get; set; } - public Keccak? ParentBeaconBlockRoot { get; set; } /// Gets or sets the gas limit. /// Used for MEV-Boost only. public long? GasLimit { get; set; } @@ -44,33 +43,23 @@ public string ToString(string indentation) sb.Append($", {nameof(Withdrawals)} count: {Withdrawals.Count}"); } - if (ParentBeaconBlockRoot is not null) - { - sb.Append($", {nameof(ParentBeaconBlockRoot)} : {ParentBeaconBlockRoot}"); - } - sb.Append('}'); return sb.ToString(); } } -public enum PayloadAttributesValidationResult : byte { Success, InvalidParams, UnsupportedFork }; - public static class PayloadAttributesExtensions { public static string ComputePayloadId(this PayloadAttributes payloadAttributes, BlockHeader parentHeader) { bool hasWithdrawals = payloadAttributes.Withdrawals is not null; - bool hasParentBeaconBlockRoot = payloadAttributes.ParentBeaconBlockRoot is not null; - - const int preambleLength = Keccak.Size + Keccak.Size + Keccak.Size + Address.ByteLength; - Span inputSpan = stackalloc byte[preambleLength + (hasWithdrawals ? Keccak.Size : 0) + (hasParentBeaconBlockRoot ? Keccak.Size : 0)]; + Span inputSpan = stackalloc byte[32 + 32 + 32 + 20 + (hasWithdrawals ? 32 : 0)]; - parentHeader.Hash!.Bytes.CopyTo(inputSpan[..Keccak.Size]); - BinaryPrimitives.WriteUInt64BigEndian(inputSpan.Slice(56, sizeof(UInt64)), payloadAttributes.Timestamp); - payloadAttributes.PrevRandao.Bytes.CopyTo(inputSpan.Slice(64, Keccak.Size)); - payloadAttributes.SuggestedFeeRecipient.Bytes.CopyTo(inputSpan.Slice(96, Address.ByteLength)); + parentHeader.Hash!.Bytes.CopyTo(inputSpan[..32]); + BinaryPrimitives.WriteUInt64BigEndian(inputSpan.Slice(56, 8), payloadAttributes.Timestamp); + payloadAttributes.PrevRandao.Bytes.CopyTo(inputSpan.Slice(64, 32)); + payloadAttributes.SuggestedFeeRecipient.Bytes.CopyTo(inputSpan.Slice(96, 20)); if (hasWithdrawals) { @@ -78,12 +67,7 @@ public static string ComputePayloadId(this PayloadAttributes payloadAttributes, ? PatriciaTree.EmptyTreeHash : new WithdrawalTrie(payloadAttributes.Withdrawals).RootHash; - withdrawalsRootHash.Bytes.CopyTo(inputSpan[preambleLength..]); - } - - if (hasParentBeaconBlockRoot) - { - payloadAttributes.ParentBeaconBlockRoot.Bytes.CopyTo(inputSpan[(preambleLength + (hasWithdrawals ? Keccak.Size : 0))..]); + withdrawalsRootHash.Bytes.CopyTo(inputSpan[116..]); } ValueKeccak inputHash = ValueKeccak.Compute(inputSpan); @@ -92,79 +76,32 @@ public static string ComputePayloadId(this PayloadAttributes payloadAttributes, } public static int GetVersion(this PayloadAttributes executionPayload) => - executionPayload switch - { - { ParentBeaconBlockRoot: not null, Withdrawals: not null } => EngineApiVersions.Cancun, - { Withdrawals: not null } => EngineApiVersions.Shanghai, - _ => EngineApiVersions.Paris - }; + executionPayload.Withdrawals is null ? 1 : 2; - public static int ExpectedEngineSpecVersion(this IReleaseSpec spec) => - spec switch - { - { IsEip4844Enabled: true } => EngineApiVersions.Cancun, - { WithdrawalsEnabled: true } => EngineApiVersions.Shanghai, - _ => EngineApiVersions.Paris - }; - - public static PayloadAttributesValidationResult Validate( - this PayloadAttributes payloadAttributes, - ISpecProvider specProvider, - int apiVersion, - [NotNullWhen(false)] out string? error) => - Validate( - apiVersion: apiVersion, - actualVersion: payloadAttributes.GetVersion(), - expectedVersion: specProvider.GetSpec(ForkActivation.TimestampOnly(payloadAttributes.Timestamp)) - .ExpectedEngineSpecVersion(), - "PayloadAttributesV", - out error); - - public static PayloadAttributesValidationResult Validate( - int apiVersion, - int actualVersion, - int expectedVersion, - string methodName, + public static bool Validate( + this PayloadAttributes payloadAttributes, + IReleaseSpec spec, + int version, [NotNullWhen(false)] out string? error) { - if (apiVersion >= EngineApiVersions.Cancun) - { - if (actualVersion == apiVersion && expectedVersion != apiVersion) - { - error = $"{methodName}{expectedVersion} expected"; - return PayloadAttributesValidationResult.UnsupportedFork; - } - } - else if (apiVersion == EngineApiVersions.Shanghai) - { - if (actualVersion == apiVersion && expectedVersion >= EngineApiVersions.Cancun) - { - error = $"{methodName}{expectedVersion} expected"; - return PayloadAttributesValidationResult.UnsupportedFork; - } - } + int actualVersion = payloadAttributes.GetVersion(); - if (actualVersion == expectedVersion) + error = actualVersion switch { - if (apiVersion >= EngineApiVersions.Cancun) - { - if (actualVersion == apiVersion) - { - error = null; - return PayloadAttributesValidationResult.Success; - } - } - else - { - if (apiVersion >= actualVersion) - { - error = null; - return PayloadAttributesValidationResult.Success; - } - } - } + 1 when spec.WithdrawalsEnabled => "PayloadAttributesV2 expected", + > 1 when !spec.WithdrawalsEnabled => "PayloadAttributesV1 expected", + _ => actualVersion > version ? $"PayloadAttributesV{version} expected" : null + }; - error = $"{methodName}{expectedVersion} expected"; - return PayloadAttributesValidationResult.InvalidParams; + return error is null; } + + public static bool Validate(this PayloadAttributes payloadAttributes, + ISpecProvider specProvider, + int version, + [NotNullWhen(false)] out string? error) => + payloadAttributes.Validate( + specProvider.GetSpec(ForkActivation.TimestampOnly(payloadAttributes.Timestamp)), + version, + out error); } diff --git a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs index 558ce50f7d7..d26c9390ad4 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs @@ -61,7 +61,7 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi // TODO: removing transactions from TX pool here seems to be a bad practice since they will // not come back if the block is ignored? int blobsCounter = 0; - UInt256 blobGasPrice = UInt256.Zero; + UInt256? dataGasPrice = null; foreach (Transaction tx in transactions) { @@ -79,31 +79,19 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi if (tx.SupportsBlobs) { - if (blobGasPrice.IsZero) - { - ulong? excessBlobGas = BlobGasCalculator.CalculateExcessBlobGas(parent, _specProvider.GetSpec(parent)); - if (excessBlobGas is null) - { - if (_logger.IsTrace) _logger.Trace($"Declining {tx.ToShortString()}, the specification is not configured to handle shard blob transactions."); - continue; - } - if (!BlobGasCalculator.TryCalculateBlobGasPricePerUnit(excessBlobGas.Value, out blobGasPrice)) - { - if (_logger.IsTrace) _logger.Trace($"Declining {tx.ToShortString()}, failed to calculate blob gas price."); - continue; - } - } + dataGasPrice ??= DataGasCalculator.CalculateDataGasPricePerUnit( + DataGasCalculator.CalculateExcessDataGas(parent, _specProvider.GetFinalSpec()) ?? 0); int txAmountOfBlobs = tx.BlobVersionedHashes?.Length ?? 0; - if (blobGasPrice > tx.MaxFeePerBlobGas) + if (dataGasPrice > tx.MaxFeePerDataGas) { - if (_logger.IsTrace) _logger.Trace($"Declining {tx.ToShortString()}, blob gas fee is too low."); + if (_logger.IsTrace) _logger.Trace($"Declining {tx.ToShortString()}, data gas fee is too low."); continue; } - if (BlobGasCalculator.CalculateBlobGas(blobsCounter + txAmountOfBlobs) > - Eip4844Constants.MaxBlobGasPerBlock) + if (DataGasCalculator.CalculateDataGas(blobsCounter + txAmountOfBlobs) > + Eip4844Constants.MaxDataGasPerBlock) { if (_logger.IsTrace) _logger.Trace($"Declining {tx.ToShortString()}, no more blob space."); continue; diff --git a/src/Nethermind/Nethermind.Consensus/Signer.cs b/src/Nethermind/Nethermind.Consensus/Signer.cs index 8b36bcf08ef..25c79743c49 100644 --- a/src/Nethermind/Nethermind.Consensus/Signer.cs +++ b/src/Nethermind/Nethermind.Consensus/Signer.cs @@ -21,10 +21,10 @@ public class Signer : ISigner, ISignerStore public bool CanSign => _key is not null; - public Signer(ulong chainId, PrivateKey? key, ILogManager logManager) + public Signer(ulong chainId, PrivateKey key, ILogManager logManager) { _chainId = chainId; - _logger = logManager.GetClassLogger(); + _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); SetSigner(key); } diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs index 5149db22cc2..9313bd03d5d 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs @@ -2,8 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; -using System.IO.Abstractions; using System.Linq; using System.Threading; using Nethermind.Blockchain; @@ -18,175 +16,149 @@ using Nethermind.Evm.TransactionProcessing; using Nethermind.Serialization.Rlp; -namespace Nethermind.Consensus.Tracing; - -public class GethStyleTracer : IGethStyleTracer +namespace Nethermind.Consensus.Tracing { - private readonly IBlockTree _blockTree; - private readonly ChangeableTransactionProcessorAdapter _transactionProcessorAdapter; - private readonly IBlockchainProcessor _processor; - private readonly IReceiptStorage _receiptStorage; - private readonly IFileSystem _fileSystem; - - public GethStyleTracer( - IBlockchainProcessor processor, - IReceiptStorage receiptStorage, - IBlockTree blockTree, - ChangeableTransactionProcessorAdapter transactionProcessorAdapter, - IFileSystem fileSystem) - { - _processor = processor ?? throw new ArgumentNullException(nameof(processor)); - _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage)); - _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); - _transactionProcessorAdapter = transactionProcessorAdapter; - _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); - } - - public GethLikeTxTrace Trace(Keccak blockHash, int txIndex, GethTraceOptions options, CancellationToken cancellationToken) - { - Block block = _blockTree.FindBlock(blockHash, BlockTreeLookupOptions.None); - if (block is null) throw new InvalidOperationException("Only historical blocks"); - - if (txIndex > block.Transactions.Length - 1) throw new InvalidOperationException($"Block {blockHash} has only {block.Transactions.Length} transactions and the requested tx index was {txIndex}"); - - return Trace(block, block.Transactions[txIndex].Hash, cancellationToken, options); - } - - public GethLikeTxTrace? Trace(Rlp block, Keccak txHash, GethTraceOptions options, CancellationToken cancellationToken) - { - return TraceBlock(GetBlockToTrace(block), options with { TxHash = txHash }, cancellationToken).FirstOrDefault(); - } - - public GethLikeTxTrace? Trace(BlockParameter blockParameter, Transaction tx, GethTraceOptions options, CancellationToken cancellationToken) + public class GethStyleTracer : IGethStyleTracer { - Block block = _blockTree.FindBlock(blockParameter); - if (block is null) throw new InvalidOperationException($"Cannot find block {blockParameter}"); - tx.Hash ??= tx.CalculateHash(); - block = block.WithReplacedBodyCloned(BlockBody.WithOneTransactionOnly(tx)); - ITransactionProcessorAdapter currentAdapter = _transactionProcessorAdapter.CurrentAdapter; - _transactionProcessorAdapter.CurrentAdapter = new TraceTransactionProcessorAdapter(_transactionProcessorAdapter.TransactionProcessor); - - try + private readonly IBlockTree _blockTree; + private readonly ChangeableTransactionProcessorAdapter _transactionProcessorAdapter; + private readonly IBlockchainProcessor _processor; + private readonly IReceiptStorage _receiptStorage; + + public GethStyleTracer( + IBlockchainProcessor processor, + IReceiptStorage receiptStorage, + IBlockTree blockTree, + ChangeableTransactionProcessorAdapter transactionProcessorAdapter) { - return Trace(block, tx.Hash, cancellationToken, options); + _processor = processor ?? throw new ArgumentNullException(nameof(processor)); + _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage)); + _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); + _transactionProcessorAdapter = transactionProcessorAdapter; } - finally + + public GethLikeTxTrace Trace(Keccak blockHash, int txIndex, GethTraceOptions options, CancellationToken cancellationToken) { - _transactionProcessorAdapter.CurrentAdapter = currentAdapter; + Block block = _blockTree.FindBlock(blockHash, BlockTreeLookupOptions.None); + if (block is null) throw new InvalidOperationException("Only historical blocks"); + + if (txIndex > block.Transactions.Length - 1) throw new InvalidOperationException($"Block {blockHash} has only {block.Transactions.Length} transactions and the requested tx index was {txIndex}"); + + return Trace(block, block.Transactions[txIndex].Hash, cancellationToken, options); } - } - public GethLikeTxTrace? Trace(Keccak txHash, GethTraceOptions traceOptions, CancellationToken cancellationToken) - { - Keccak? blockHash = _receiptStorage.FindBlockHash(txHash); - if (blockHash is null) + public GethLikeTxTrace? Trace(Rlp block, Keccak txHash, GethTraceOptions options, CancellationToken cancellationToken) { - return null; + return TraceBlock(GetBlockToTrace(block), options, cancellationToken, txHash).FirstOrDefault(); } - Block block = _blockTree.FindBlock(blockHash, BlockTreeLookupOptions.RequireCanonical); - if (block is null) + public GethLikeTxTrace? Trace(BlockParameter blockParameter, Transaction tx, GethTraceOptions options, CancellationToken cancellationToken) { - return null; + Block block = _blockTree.FindBlock(blockParameter); + if (block is null) throw new InvalidOperationException($"Cannot find block {blockParameter}"); + tx.Hash ??= tx.CalculateHash(); + block = block.WithReplacedBodyCloned(BlockBody.WithOneTransactionOnly(tx)); + ITransactionProcessorAdapter currentAdapter = _transactionProcessorAdapter.CurrentAdapter; + _transactionProcessorAdapter.CurrentAdapter = new TraceTransactionProcessorAdapter(_transactionProcessorAdapter.TransactionProcessor); + + try + { + return Trace(block, tx.Hash, cancellationToken, options); + } + finally + { + _transactionProcessorAdapter.CurrentAdapter = currentAdapter; + } } - return Trace(block, txHash, cancellationToken, traceOptions); - } - - public GethLikeTxTrace? Trace(long blockNumber, int txIndex, GethTraceOptions options, CancellationToken cancellationToken) - { - Block block = _blockTree.FindBlock(blockNumber, BlockTreeLookupOptions.RequireCanonical); - if (block is null) throw new InvalidOperationException("Only historical blocks"); - - if (txIndex > block.Transactions.Length - 1) throw new InvalidOperationException($"Block {blockNumber} has only {block.Transactions.Length} transactions and the requested tx index was {txIndex}"); - - return Trace(block, block.Transactions[txIndex].Hash, cancellationToken, options); - } + public GethLikeTxTrace? Trace(Keccak txHash, GethTraceOptions traceOptions, CancellationToken cancellationToken) + { + Keccak? blockHash = _receiptStorage.FindBlockHash(txHash); + if (blockHash is null) + { + return null; + } - public GethLikeTxTrace? Trace(long blockNumber, Transaction tx, GethTraceOptions options, CancellationToken cancellationToken) - { - Block block = _blockTree.FindBlock(blockNumber, BlockTreeLookupOptions.RequireCanonical); - if (block is null) throw new InvalidOperationException("Only historical blocks"); - if (tx.Hash is null) throw new InvalidOperationException("Cannot trace transactions without tx hash set."); - - block = block.WithReplacedBodyCloned(BlockBody.WithOneTransactionOnly(tx)); - GethLikeBlockMemoryTracer blockTracer = new(options with { TxHash = tx.Hash }); - _processor.Process(block, ProcessingOptions.Trace, blockTracer.WithCancellation(cancellationToken)); - return blockTracer.BuildResult().SingleOrDefault(); - } - public GethLikeTxTrace[] TraceBlock(BlockParameter blockParameter, GethTraceOptions options, CancellationToken cancellationToken) - { - var block = _blockTree.FindBlock(blockParameter); + Block block = _blockTree.FindBlock(blockHash, BlockTreeLookupOptions.RequireCanonical); + if (block is null) + { + return null; + } - return TraceBlock(block, options, cancellationToken); - } + return Trace(block, txHash, cancellationToken, traceOptions); + } - public GethLikeTxTrace[] TraceBlock(Rlp blockRlp, GethTraceOptions options, CancellationToken cancellationToken) - { - return TraceBlock(GetBlockToTrace(blockRlp), options, cancellationToken); - } + public GethLikeTxTrace? Trace(long blockNumber, int txIndex, GethTraceOptions options, CancellationToken cancellationToken) + { + Block block = _blockTree.FindBlock(blockNumber, BlockTreeLookupOptions.RequireCanonical); + if (block is null) throw new InvalidOperationException("Only historical blocks"); - public IEnumerable TraceBlockToFile(Keccak blockHash, GethTraceOptions options, CancellationToken cancellationToken) - { - ArgumentNullException.ThrowIfNull(blockHash); - ArgumentNullException.ThrowIfNull(options); + if (txIndex > block.Transactions.Length - 1) throw new InvalidOperationException($"Block {blockNumber} has only {block.Transactions.Length} transactions and the requested tx index was {txIndex}"); - var block = _blockTree.FindBlock(blockHash) ?? throw new InvalidOperationException("Only historical blocks"); + return Trace(block, block.Transactions[txIndex].Hash, cancellationToken, options); + } - if (!block.IsGenesis) + public GethLikeTxTrace? Trace(long blockNumber, Transaction tx, GethTraceOptions options, CancellationToken cancellationToken) { - var parent = _blockTree.FindParentHeader(block.Header, BlockTreeLookupOptions.None); - - if (parent?.Hash is null) - throw new InvalidOperationException("Cannot trace blocks with invalid parents"); + Block block = _blockTree.FindBlock(blockNumber, BlockTreeLookupOptions.RequireCanonical); + if (block is null) throw new InvalidOperationException("Only historical blocks"); + if (tx.Hash is null) throw new InvalidOperationException("Cannot trace transactions without tx hash set."); + + block = block.WithReplacedBodyCloned(BlockBody.WithOneTransactionOnly(tx)); + GethLikeBlockTracer blockTracer = new(tx.Hash, options); + _processor.Process(block, ProcessingOptions.Trace, blockTracer.WithCancellation(cancellationToken)); + return blockTracer.BuildResult().SingleOrDefault(); } + public GethLikeTxTrace[] TraceBlock(BlockParameter blockParameter, GethTraceOptions options, CancellationToken cancellationToken) + { + var block = _blockTree.FindBlock(blockParameter); - var tracer = new GethLikeBlockFileTracer(block, options, _fileSystem); + return TraceBlock(block, options, cancellationToken); + } - _processor.Process(block, ProcessingOptions.Trace, tracer.WithCancellation(cancellationToken)); + public GethLikeTxTrace[] TraceBlock(Rlp blockRlp, GethTraceOptions options, CancellationToken cancellationToken) + { + return TraceBlock(GetBlockToTrace(blockRlp), options, cancellationToken); + } - return tracer.FileNames; - } + private GethLikeTxTrace? Trace(Block block, Keccak? txHash, CancellationToken cancellationToken, GethTraceOptions options) + { + if (txHash is null) throw new InvalidOperationException("Cannot trace transactions without tx hash set."); - private GethLikeTxTrace? Trace(Block block, Keccak? txHash, CancellationToken cancellationToken, GethTraceOptions options) - { - ArgumentNullException.ThrowIfNull(txHash); + GethLikeBlockTracer listener = new(txHash, options); + _processor.Process(block, ProcessingOptions.Trace, listener.WithCancellation(cancellationToken)); + return listener.BuildResult().SingleOrDefault(); + } - var tracer = new GethLikeBlockMemoryTracer(options with { TxHash = txHash }); + private GethLikeTxTrace[] TraceBlock(Block? block, GethTraceOptions options, CancellationToken cancellationToken, Keccak? txHash = null) + { + if (block is null) throw new InvalidOperationException("Only canonical, historical blocks supported"); - _processor.Process(block, ProcessingOptions.Trace, tracer.WithCancellation(cancellationToken)); + if (!block.IsGenesis) + { + BlockHeader? parent = _blockTree.FindParentHeader(block.Header, BlockTreeLookupOptions.None); + if (parent?.Hash is null) + { + throw new InvalidOperationException("Cannot trace blocks with invalid parents"); + } - return tracer.BuildResult().SingleOrDefault(); - } + if (!_blockTree.IsMainChain(parent.Hash)) throw new InvalidOperationException("Cannot trace orphaned blocks"); + } - private GethLikeTxTrace[] TraceBlock(Block? block, GethTraceOptions options, CancellationToken cancellationToken) - { - ArgumentNullException.ThrowIfNull(block); + GethLikeBlockTracer listener = txHash is null ? new GethLikeBlockTracer(options) : new GethLikeBlockTracer(txHash, options); + _processor.Process(block, ProcessingOptions.Trace, listener.WithCancellation(cancellationToken)); + return listener.BuildResult().ToArray(); + } - if (!block.IsGenesis) + private static Block GetBlockToTrace(Rlp blockRlp) { - BlockHeader? parent = _blockTree.FindParentHeader(block.Header, BlockTreeLookupOptions.None); - if (parent?.Hash is null) + Block block = Rlp.Decode(blockRlp); + if (block.TotalDifficulty is null) { - throw new InvalidOperationException("Cannot trace blocks with invalid parents"); + block.Header.TotalDifficulty = 1; } - if (!_blockTree.IsMainChain(parent.Hash)) throw new InvalidOperationException("Cannot trace orphaned blocks"); - } - - GethLikeBlockMemoryTracer tracer = new(options); - _processor.Process(block, ProcessingOptions.Trace, tracer.WithCancellation(cancellationToken)); - return tracer.BuildResult().ToArray(); - } - - private static Block GetBlockToTrace(Rlp blockRlp) - { - Block block = Rlp.Decode(blockRlp); - if (block.TotalDifficulty is null) - { - block.Header.TotalDifficulty = 1; + return block; } - - return block; } } diff --git a/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs b/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs index d3bd1c787a3..268f92bd719 100644 --- a/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs +++ b/src/Nethermind/Nethermind.Consensus/Tracing/IGethStyleTracer.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; using System.Threading; using Nethermind.Blockchain.Find; using Nethermind.Core; @@ -9,17 +8,17 @@ using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Serialization.Rlp; -namespace Nethermind.Consensus.Tracing; - -public interface IGethStyleTracer +namespace Nethermind.Consensus.Tracing { - GethLikeTxTrace Trace(Keccak txHash, GethTraceOptions options, CancellationToken cancellationToken); - GethLikeTxTrace Trace(long blockNumber, Transaction transaction, GethTraceOptions options, CancellationToken cancellationToken); - GethLikeTxTrace Trace(long blockNumber, int txIndex, GethTraceOptions options, CancellationToken cancellationToken); - GethLikeTxTrace Trace(Keccak blockHash, int txIndex, GethTraceOptions options, CancellationToken cancellationToken); - GethLikeTxTrace Trace(Rlp blockRlp, Keccak txHash, GethTraceOptions options, CancellationToken cancellationToken); - GethLikeTxTrace? Trace(BlockParameter blockParameter, Transaction tx, GethTraceOptions options, CancellationToken cancellationToken); - GethLikeTxTrace[] TraceBlock(BlockParameter blockParameter, GethTraceOptions options, CancellationToken cancellationToken); - GethLikeTxTrace[] TraceBlock(Rlp blockRlp, GethTraceOptions options, CancellationToken cancellationToken); - IEnumerable TraceBlockToFile(Keccak blockHash, GethTraceOptions options, CancellationToken cancellationToken); + public interface IGethStyleTracer + { + GethLikeTxTrace Trace(Keccak txHash, GethTraceOptions options, CancellationToken cancellationToken); + GethLikeTxTrace Trace(long blockNumber, Transaction transaction, GethTraceOptions options, CancellationToken cancellationToken); + GethLikeTxTrace Trace(long blockNumber, int txIndex, GethTraceOptions options, CancellationToken cancellationToken); + GethLikeTxTrace Trace(Keccak blockHash, int txIndex, GethTraceOptions options, CancellationToken cancellationToken); + GethLikeTxTrace Trace(Rlp blockRlp, Keccak txHash, GethTraceOptions options, CancellationToken cancellationToken); + GethLikeTxTrace? Trace(BlockParameter blockParameter, Transaction tx, GethTraceOptions options, CancellationToken cancellationToken); + GethLikeTxTrace[] TraceBlock(BlockParameter blockParameter, GethTraceOptions options, CancellationToken cancellationToken); + GethLikeTxTrace[] TraceBlock(Rlp blockRlp, GethTraceOptions options, CancellationToken cancellationToken); + } } diff --git a/src/Nethermind/Nethermind.Consensus/Transactions/SinglePendingTxSelector.cs b/src/Nethermind/Nethermind.Consensus/Transactions/SinglePendingTxSelector.cs index 7c24771203f..17aae85d7f2 100644 --- a/src/Nethermind/Nethermind.Consensus/Transactions/SinglePendingTxSelector.cs +++ b/src/Nethermind/Nethermind.Consensus/Transactions/SinglePendingTxSelector.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.Linq; using Nethermind.Core; @@ -13,7 +14,7 @@ public class SinglePendingTxSelector : ITxSource public SinglePendingTxSelector(ITxSource innerSource) { - _innerSource = innerSource; + _innerSource = innerSource ?? throw new ArgumentNullException(nameof(innerSource)); } public IEnumerable GetTransactions(BlockHeader parent, long gasLimit) => diff --git a/src/Nethermind/Nethermind.Consensus/Transactions/TxFilterPipeline.cs b/src/Nethermind/Nethermind.Consensus/Transactions/TxFilterPipeline.cs index 1df4d38fcc8..cde9ed6d3c6 100644 --- a/src/Nethermind/Nethermind.Consensus/Transactions/TxFilterPipeline.cs +++ b/src/Nethermind/Nethermind.Consensus/Transactions/TxFilterPipeline.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Nethermind.Core; using Nethermind.Logging; using Nethermind.TxPool; diff --git a/src/Nethermind/Nethermind.Consensus/Transactions/TxFilterPipelineBuilder.cs b/src/Nethermind/Nethermind.Consensus/Transactions/TxFilterPipelineBuilder.cs index 318ad9dd4ac..e1d615bea52 100644 --- a/src/Nethermind/Nethermind.Consensus/Transactions/TxFilterPipelineBuilder.cs +++ b/src/Nethermind/Nethermind.Consensus/Transactions/TxFilterPipelineBuilder.cs @@ -4,6 +4,7 @@ using System; using Nethermind.Config; using Nethermind.Core.Specs; +using Nethermind.Int256; using Nethermind.Logging; namespace Nethermind.Consensus.Transactions diff --git a/src/Nethermind/Nethermind.Consensus/Validators/AlwaysValid.cs b/src/Nethermind/Nethermind.Consensus/Validators/AlwaysValid.cs index be60c6375dc..0dc77b6e60a 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/AlwaysValid.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/AlwaysValid.cs @@ -80,10 +80,4 @@ public bool ValidateWithdrawals(Block block, out string? error) return _result; } - - public bool ValidateOrphanedBlock(Block block, out string? error) - { - error = null; - return _result; - } } diff --git a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs index 575393308d3..55ea2a3cd88 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Linq; using Nethermind.Blockchain; +using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; @@ -46,24 +48,6 @@ public bool Validate(BlockHeader header, bool isUncle) return _headerValidator.Validate(header, isUncle); } - /// - /// Applies to blocks without parent - /// - /// A block to validate - /// Error description in case of failed validation - /// Validation result - /// - /// Parent may be absent during BeaconSync - /// - public bool ValidateOrphanedBlock(Block block, out string? error) - { - if (!ValidateEip4844Fields(block, _specProvider.GetSpec(block.Header), out error)) - return false; - - error = null; - return true; - } - /// /// Suggested block validation runs basic checks that can be executed before going through the expensive EVM processing. /// @@ -73,29 +57,33 @@ public bool ValidateOrphanedBlock(Block block, out string? error) /// public bool ValidateSuggestedBlock(Block block) { + Transaction[] txs = block.Transactions; IReleaseSpec spec = _specProvider.GetSpec(block.Header); - if (!ValidateTransactions(block, spec)) - return false; - - if (!ValidateEip4844Fields(block, spec, out _)) - return false; + for (int i = 0; i < txs.Length; i++) + { + if (!_txValidator.IsWellFormed(txs[i], spec)) + { + if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} Invalid transaction {txs[i].Hash}"); + return false; + } + } if (spec.MaximumUncleCount < block.Uncles.Length) { - if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} Uncle count of {block.Uncles.Length} exceeds the max limit of {spec.MaximumUncleCount}"); + _logger.Debug($"{Invalid(block)} Uncle count of {block.Uncles.Length} exceeds the max limit of {spec.MaximumUncleCount}"); return false; } - if (!ValidateUnclesHashMatches(block, out Keccak unclesHash)) + if (!ValidateUnclesHashMatches(block, out var unclesHash)) { - if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} Uncles hash mismatch: expected {block.Header.UnclesHash}, got {unclesHash}"); + _logger.Debug($"{Invalid(block)} Uncles hash mismatch: expected {block.Header.UnclesHash}, got {unclesHash}"); return false; } if (!_unclesValidator.Validate(block.Header, block.Uncles)) { - if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} Invalid uncles"); + _logger.Debug($"{Invalid(block)} Invalid uncles"); return false; } @@ -115,6 +103,9 @@ public bool ValidateSuggestedBlock(Block block) if (!ValidateWithdrawals(block, spec, out _)) return false; + if (!ValidateTransactionsDataGas(block, spec, out _)) + return false; + return true; } @@ -154,19 +145,14 @@ public bool ValidateProcessedBlock(Block processedBlock, TxReceipt[] receipts, B if (_logger.IsError) _logger.Error($"- state root: expected {suggestedBlock.Header.StateRoot}, got {processedBlock.Header.StateRoot}"); } - if (processedBlock.Header.BlobGasUsed != suggestedBlock.Header.BlobGasUsed) - { - if (_logger.IsError) _logger.Error($"- blob gas used: expected {suggestedBlock.Header.BlobGasUsed}, got {processedBlock.Header.BlobGasUsed}"); - } - - if (processedBlock.Header.ExcessBlobGas != suggestedBlock.Header.ExcessBlobGas) + if (processedBlock.Header.DataGasUsed != suggestedBlock.Header.DataGasUsed) { - if (_logger.IsError) _logger.Error($"- excess blob gas: expected {suggestedBlock.Header.ExcessBlobGas}, got {processedBlock.Header.ExcessBlobGas}"); + if (_logger.IsError) _logger.Error($"- data gas used: expected {suggestedBlock.Header.DataGasUsed}, got {processedBlock.Header.DataGasUsed}"); } - if (processedBlock.Header.ParentBeaconBlockRoot != suggestedBlock.Header.ParentBeaconBlockRoot) + if (processedBlock.Header.ExcessDataGas != suggestedBlock.Header.ExcessDataGas) { - if (_logger.IsError) _logger.Error($"- parent beacon block root : expected {suggestedBlock.Header.ParentBeaconBlockRoot}, got {processedBlock.Header.ParentBeaconBlockRoot}"); + if (_logger.IsError) _logger.Error($"- excess data gas: expected {suggestedBlock.Header.ExcessDataGas}, got {processedBlock.Header.ExcessDataGas}"); } for (int i = 0; i < processedBlock.Transactions.Length; i++) @@ -220,25 +206,7 @@ private bool ValidateWithdrawals(Block block, IReleaseSpec spec, out string? err return true; } - private bool ValidateTransactions(Block block, IReleaseSpec spec) - { - Transaction[] transactions = block.Transactions; - - for (int txIndex = 0; txIndex < transactions.Length; txIndex++) - { - Transaction transaction = transactions[txIndex]; - - if (!_txValidator.IsWellFormed(transaction, spec)) - { - if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} Invalid transaction {transaction.Hash}"); - return false; - } - } - - return true; - } - - private bool ValidateEip4844Fields(Block block, IReleaseSpec spec, out string? error) + private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out string? error) { if (!spec.IsEip4844Enabled) { @@ -247,51 +215,37 @@ private bool ValidateEip4844Fields(Block block, IReleaseSpec spec, out string? e } int blobsInBlock = 0; - UInt256 blobGasPrice = UInt256.Zero; - Transaction[] transactions = block.Transactions; - - for (int txIndex = 0; txIndex < transactions.Length; txIndex++) + UInt256? dataGasPrice = null; + for (int txIndex = 0; txIndex < block.Transactions.Length; txIndex++) { - Transaction transaction = transactions[txIndex]; - + Transaction transaction = block.Transactions[txIndex]; if (!transaction.SupportsBlobs) { continue; } - if (blobGasPrice.IsZero) + if (transaction.MaxFeePerDataGas < (dataGasPrice ??= DataGasCalculator.CalculateDataGasPricePerUnit(block.Header))) { - if (!BlobGasCalculator.TryCalculateBlobGasPricePerUnit(block.Header, out blobGasPrice)) - { - error = "{nameof(blobGasPrice)} overflow"; - if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} {error}."); - return false; - } - } - - if (transaction.MaxFeePerBlobGas < blobGasPrice) - { - error = $"A transaction has unsufficient {nameof(transaction.MaxFeePerBlobGas)} to cover current blob gas fee: {transaction.MaxFeePerBlobGas} < {blobGasPrice}"; - if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} {error}."); + error = $"A transaction has unsufficient MaxFeePerDataGas {transaction.MaxFeePerDataGas} < {dataGasPrice}."; + if (_logger.IsWarn) _logger.Warn(error); return false; } blobsInBlock += transaction.BlobVersionedHashes!.Length; } - ulong blobGasUsed = BlobGasCalculator.CalculateBlobGas(blobsInBlock); - - if (blobGasUsed > Eip4844Constants.MaxBlobGasPerBlock) + ulong dataGasUsed = DataGasCalculator.CalculateDataGas(blobsInBlock); + if (dataGasUsed > Eip4844Constants.MaxDataGasPerBlock) { - error = $"A block cannot have more than {Eip4844Constants.MaxBlobGasPerBlock} blob gas."; - if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} {error}."); + error = $"A block cannot have more than {Eip4844Constants.MaxDataGasPerBlock} data gas."; + if (_logger.IsWarn) _logger.Warn(error); return false; } - if (blobGasUsed != block.Header.BlobGasUsed) + if (dataGasUsed != block.Header.DataGasUsed) { - error = $"{Invalid(block)} {nameof(BlockHeader.BlobGasUsed)} declared in the block header does not match actual blob gas used: {block.Header.BlobGasUsed} != {blobGasUsed}."; - if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} {error}."); + error = $"DataGasUsed does not match actual data gas used: {block.Header.DataGasUsed} != {dataGasUsed}."; + if (_logger.IsWarn) _logger.Warn(error); return false; } diff --git a/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs index 9f8d37e127f..66d77ad4694 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs @@ -121,7 +121,7 @@ public virtual bool Validate(BlockHeader header, BlockHeader? parent, bool isUnc } } - bool eip4844Valid = ValidateBlobGasFields(header, parent, spec); + bool eip4844Valid = ValidateDataGasFields(header, parent, spec); return totalDifficultyCorrect && @@ -279,42 +279,42 @@ header.Bloom is not null && header.ExtraData.Length <= _specProvider.GenesisSpec.MaximumExtraDataSize; } - private bool ValidateBlobGasFields(BlockHeader header, BlockHeader parentHeader, IReleaseSpec spec) + private bool ValidateDataGasFields(BlockHeader header, BlockHeader parentHeader, IReleaseSpec spec) { if (!spec.IsEip4844Enabled) { - if (header.BlobGasUsed is not null) + if (header.DataGasUsed is not null) { - if (_logger.IsWarn) _logger.Warn($"BlobGasUsed field should not have value."); + if (_logger.IsWarn) _logger.Warn($"DataGasUsed field should not have value."); return false; } - if (header.ExcessBlobGas is not null) + if (header.ExcessDataGas is not null) { - if (_logger.IsWarn) _logger.Warn($"ExcessBlobGas field should not have value."); + if (_logger.IsWarn) _logger.Warn($"ExcessDataGas field should not have value."); return false; } return true; } - if (header.BlobGasUsed is null) + if (header.DataGasUsed is null) { - if (_logger.IsWarn) _logger.Warn($"BlobGasUsed field is not set."); + if (_logger.IsWarn) _logger.Warn($"DataGasUsed field is not set."); return false; } - if (header.ExcessBlobGas is null) + if (header.ExcessDataGas is null) { - if (_logger.IsWarn) _logger.Warn($"ExcessBlobGas field is not set."); + if (_logger.IsWarn) _logger.Warn($"ExcessDataGas field is not set."); return false; } - UInt256? expectedExcessBlobGas = BlobGasCalculator.CalculateExcessBlobGas(parentHeader, spec); + UInt256? expectedExcessDataGas = DataGasCalculator.CalculateExcessDataGas(parentHeader, spec); - if (header.ExcessBlobGas != expectedExcessBlobGas) + if (header.ExcessDataGas != expectedExcessDataGas) { - if (_logger.IsWarn) _logger.Warn($"ExcessBlobGas field is incorrect: {header.ExcessBlobGas}, should be {expectedExcessBlobGas}."); + if (_logger.IsWarn) _logger.Warn($"ExcessDataGas field is incorrect: {header.ExcessDataGas}, should be {expectedExcessDataGas}."); return false; } return true; diff --git a/src/Nethermind/Nethermind.Consensus/Validators/IBlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/IBlockValidator.cs index 43f99b149c1..3aea6301417 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/IBlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/IBlockValidator.cs @@ -7,10 +7,7 @@ namespace Nethermind.Consensus.Validators; public interface IBlockValidator : IHeaderValidator, IWithdrawalValidator { - bool ValidateOrphanedBlock(Block block, out string? error); - bool ValidateSuggestedBlock(Block block); bool ValidateProcessedBlock(Block processedBlock, TxReceipt[] receipts, Block suggestedBlock); - } diff --git a/src/Nethermind/Nethermind.Consensus/Validators/NeverValidBlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/NeverValidBlockValidator.cs index d70f10eacd9..649c8f7885b 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/NeverValidBlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/NeverValidBlockValidator.cs @@ -35,12 +35,7 @@ public bool ValidateProcessedBlock(Block processedBlock, TxReceipt[] receipts, B public bool ValidateWithdrawals(Block block, out string? error) { error = null; - return false; - } - public bool ValidateOrphanedBlock(Block block, out string? error) - { - error = null; return false; } } diff --git a/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs index 65c44357101..21fd0dcc1c0 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs @@ -111,15 +111,15 @@ private static bool Validate4844Fields(Transaction transaction) // Execution-payload version verification if (!transaction.SupportsBlobs) { - return transaction.MaxFeePerBlobGas is null && + return transaction.MaxFeePerDataGas is null && transaction.BlobVersionedHashes is null && transaction is not { NetworkWrapper: ShardBlobNetworkWrapper }; } if (transaction.To is null || - transaction.MaxFeePerBlobGas is null || + transaction.MaxFeePerDataGas is null || transaction.BlobVersionedHashes is null || - BlobGasCalculator.CalculateBlobGas(transaction.BlobVersionedHashes!.Length) > Eip4844Constants.MaxBlobGasPerTransaction || + DataGasCalculator.CalculateDataGas(transaction.BlobVersionedHashes!.Length) > Eip4844Constants.MaxDataGasPerTransaction || transaction.BlobVersionedHashes!.Length < Eip4844Constants.MinBlobsPerTransaction) { return false; diff --git a/src/Nethermind/Nethermind.Consensus/Withdrawals/WithdrawalProcessor.cs b/src/Nethermind/Nethermind.Consensus/Withdrawals/WithdrawalProcessor.cs index 41f161d528a..907519834fc 100644 --- a/src/Nethermind/Nethermind.Consensus/Withdrawals/WithdrawalProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Withdrawals/WithdrawalProcessor.cs @@ -2,8 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Numerics; using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Int256; using Nethermind.Logging; using Nethermind.State; diff --git a/src/Nethermind/Nethermind.Core.Test/AddressTests.cs b/src/Nethermind/Nethermind.Core.Test/AddressTests.cs index b3a847049d2..1e8304289e3 100644 --- a/src/Nethermind/Nethermind.Core.Test/AddressTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/AddressTests.cs @@ -91,10 +91,9 @@ public void Equals_operator_works() Assert.False(addressA == addressB); Assert.False(addressA is null); Assert.False(null == addressA); - { - Address? address = null; - Assert.True(address is null); - } +#pragma warning disable CS8520 + Assert.True((Address?)null is null); +#pragma warning restore CS8520 } [Test] @@ -111,10 +110,9 @@ public void Not_equals_operator_works() Assert.True(addressA != addressB); Assert.True(addressA is not null); Assert.True(null != addressA); - { - Address? address = null; - Assert.False(address is not null); - } +#pragma warning disable CS8519 + Assert.False((Address?)null is not null); +#pragma warning restore CS8519 } [Test] @@ -181,7 +179,7 @@ public void Of_contract(long nonce, string expectedAddress) [TestCaseSource(nameof(PointEvaluationPrecompileTestCases))] public bool Is_PointEvaluationPrecompile_properly_activated(IReleaseSpec spec) => - Address.FromNumber(0x0a).IsPrecompile(spec); + Address.FromNumber(0x14).IsPrecompile(spec); public static IEnumerable PointEvaluationPrecompileTestCases { diff --git a/src/Nethermind/Nethermind.Core.Test/AssertionsSetup.cs b/src/Nethermind/Nethermind.Core.Test/AssertionsSetup.cs index 0788de7a9be..76352241512 100644 --- a/src/Nethermind/Nethermind.Core.Test/AssertionsSetup.cs +++ b/src/Nethermind/Nethermind.Core.Test/AssertionsSetup.cs @@ -3,6 +3,7 @@ using System; using NUnit.Framework; +using NUnit.Framework.Internal; using FluentAssertions; using Nethermind.Core.Extensions; diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockProducer.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockProducer.cs index bb4676e4d03..78e03de4f2e 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockProducer.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockProducer.cs @@ -1,9 +1,11 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain; +using Nethermind.Blockchain.Synchronization; using Nethermind.Config; using Nethermind.Consensus; using Nethermind.Consensus.Processing; @@ -11,7 +13,9 @@ using Nethermind.Consensus.Transactions; using Nethermind.Core.Specs; using Nethermind.Evm.Tracing; +using Nethermind.Int256; using Nethermind.Logging; +using Nethermind.Specs; using Nethermind.State; namespace Nethermind.Core.Test.Blockchain diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index f0c11ba233d..59ab6390e1e 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -10,7 +10,6 @@ using Nethermind.Blockchain.Receipts; using Nethermind.Config; using Nethermind.Consensus; -using Nethermind.Consensus.BeaconBlockRoot; using Nethermind.Consensus.Comparers; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Producers; @@ -50,7 +49,6 @@ public class TestBlockchain : IDisposable public ITxPool TxPool { get; set; } = null!; public IDb CodeDb => DbProvider.CodeDb; public IBlockProcessor BlockProcessor { get; set; } = null!; - public IBeaconBlockRootHandler BeaconBlockRootHandler { get; set; } = null!; public IBlockchainProcessor BlockchainProcessor { get; set; } = null!; public IBlockPreprocessorStep BlockPreprocessorStep { get; set; } = null!; @@ -109,7 +107,7 @@ protected TestBlockchain() public static TransactionBuilder BuildSimpleTransaction => Builders.Build.A.Transaction.SignedAndResolved(TestItem.PrivateKeyA).To(AccountB); - protected virtual async Task Build(ISpecProvider? specProvider = null, UInt256? initialValues = null, bool addBlockOnStart = true) + protected virtual async Task Build(ISpecProvider? specProvider = null, UInt256? initialValues = null) { Timestamper = new ManualTimestamper(new DateTime(2020, 2, 15, 12, 50, 30, DateTimeKind.Utc)); JsonSerializer = new EthereumJsonSerializer(); @@ -118,13 +116,6 @@ protected virtual async Task Build(ISpecProvider? specProvider = DbProvider = await CreateDbProvider(); TrieStore = new TrieStore(StateDb, LogManager); State = new WorldState(TrieStore, DbProvider.CodeDb, LogManager); - - // Eip4788 precompile state account - if (specProvider?.GenesisSpec?.IsBeaconBlockRootAvailable ?? false) - { - State.CreateAccount(SpecProvider.GenesisSpec.Eip4788ContractAddress, 1); - } - State.CreateAccount(TestItem.AddressA, (initialValues ?? InitialValue)); State.CreateAccount(TestItem.AddressB, (initialValues ?? InitialValue)); State.CreateAccount(TestItem.AddressC, (initialValues ?? InitialValue)); @@ -178,7 +169,6 @@ protected virtual async Task Build(ISpecProvider? specProvider = BloomStorage bloomStorage = new(new BloomConfig(), new MemDb(), new InMemoryDictionaryFileStoreFactory()); ReceiptsRecovery receiptsRecovery = new(new EthereumEcdsa(SpecProvider.ChainId, LimboLogs.Instance), SpecProvider); LogFinder = new LogFinder(BlockTree, ReceiptStorage, ReceiptStorage, bloomStorage, LimboLogs.Instance, receiptsRecovery); - BeaconBlockRootHandler = new BeaconBlockRootHandler(); BlockProcessor = CreateBlockProcessor(); BlockchainProcessor chainProcessor = new(BlockTree, BlockProcessor, BlockPreprocessorStep, StateReader, LogManager, Consensus.Processing.BlockchainProcessor.Options.Default); @@ -204,10 +194,7 @@ protected virtual async Task Build(ISpecProvider? specProvider = BlockTree.SuggestBlock(genesis); await WaitAsync(_resetEvent, "Failed to process genesis in time."); - - if (addBlockOnStart) - await AddBlocksOnStart(); - + await AddBlocksOnStart(); return this; } @@ -305,6 +292,7 @@ protected virtual Block GetGenesisBlock() genesisBlockBuilder = GenesisBlockBuilder; } + genesisBlockBuilder.WithStateRoot(State.StateRoot); if (SealEngineType == Core.SealEngineType.AuRa) { genesisBlockBuilder.WithAura(0, new byte[65]); @@ -312,17 +300,10 @@ protected virtual Block GetGenesisBlock() if (SpecProvider.GenesisSpec.IsEip4844Enabled) { - genesisBlockBuilder.WithBlobGasUsed(0); - genesisBlockBuilder.WithExcessBlobGas(0); - } - - - if (SpecProvider.GenesisSpec.IsBeaconBlockRootAvailable) - { - genesisBlockBuilder.WithParentBeaconBlockRoot(Keccak.Zero); + genesisBlockBuilder.WithDataGasUsed(0); + genesisBlockBuilder.WithExcessDataGas(0); } - genesisBlockBuilder.WithStateRoot(State.StateRoot); return genesisBlockBuilder.TestObject; } diff --git a/src/Nethermind/Nethermind.Core.Test/Buffers/CappedArrayTests.cs b/src/Nethermind/Nethermind.Core.Test/Buffers/CappedArrayTests.cs deleted file mode 100644 index 41aec9761e8..00000000000 --- a/src/Nethermind/Nethermind.Core.Test/Buffers/CappedArrayTests.cs +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Linq; -using FluentAssertions; -using Nethermind.Core.Buffers; -using NUnit.Framework; - -namespace Nethermind.Core.Test.Buffers; - -public class CappedArrayTests -{ - [Test] - public void WhenGivenNullArray_IsNull_ShouldReturnTrue() - { - CappedArray array = new(null); - array.IsNull.Should().BeTrue(); - } - - [Test] - public void WhenGivenNullArray_AsSpan_ShouldReturnEmpty() - { - CappedArray array = new(null); - array.AsSpan().IsEmpty.Should().BeTrue(); - array.AsSpan().Length.Should().Be(0); - array.Length.Should().Be(0); - } - - [Test] - public void WhenGivenArray_AndLengthIsSame_ToArray_ShouldReturnSameArray() - { - int[] baseArray = Enumerable.Range(0, 10).ToArray(); - CappedArray array = new(baseArray); - array.IsUncapped.Should().BeTrue(); - array.IsNull.Should().BeFalse(); - array.IsNotNull.Should().BeTrue(); - array.Length.Should().Be(10); - array.ToArray().Should().BeSameAs(baseArray); - } - - [Test] - public void WhenGivenArray_AndLengthIsLess_ToArray_ShouldBeCapped() - { - int[] baseArray = Enumerable.Range(0, 10).ToArray(); - CappedArray array = new(baseArray, 5); - array.IsUncapped.Should().BeFalse(); - array.IsNull.Should().BeFalse(); - array.IsNotNull.Should().BeTrue(); - array.Length.Should().Be(5); - array.ToArray().Should().BeEquivalentTo(baseArray[..5]); - array.AsSpan().Length.Should().Be(5); - array.AsSpan().ToArray().Should().BeEquivalentTo(baseArray[..5]); - } -} diff --git a/src/Nethermind/Nethermind.Core.Test/Buffers/NettyBufferMemoryOwnerTests.cs b/src/Nethermind/Nethermind.Core.Test/Buffers/NettyBufferMemoryOwnerTests.cs deleted file mode 100644 index 99af30e0d5c..00000000000 --- a/src/Nethermind/Nethermind.Core.Test/Buffers/NettyBufferMemoryOwnerTests.cs +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Linq; -using DotNetty.Buffers; -using FluentAssertions; -using Nethermind.Core.Buffers; -using Nethermind.Serialization.Rlp; -using NUnit.Framework; - -namespace Nethermind.Core.Test.Buffers; - -public class NettyBufferMemoryOwnerTests -{ - [Test] - public void Should_ExposeBufferMemory() - { - IByteBuffer buffer = Unpooled.Buffer(10); - buffer.SetWriterIndex(buffer.WriterIndex + 10); - buffer.AsSpan().Fill(0); - NettyBufferMemoryOwner memoryOwner = new NettyBufferMemoryOwner(buffer); - memoryOwner.Memory.Length.Should().Be(10); - memoryOwner.Memory.Span.Fill(1); - - buffer.AsSpan().ToArray().Should().BeEquivalentTo(Enumerable.Repeat((byte)1, 10).ToArray()); - } - - [Test] - public void When_Dispose_ShouldReduceBufferRefCounter() - { - IByteBuffer buffer = Unpooled.Buffer(10); - buffer.SetWriterIndex(buffer.WriterIndex + 10); - buffer.ReferenceCount.Should().Be(1); - - NettyBufferMemoryOwner memoryOwner = new NettyBufferMemoryOwner(buffer); - memoryOwner.Memory.Length.Should().Be(10); - buffer.ReferenceCount.Should().Be(2); - - memoryOwner.Dispose(); - buffer.ReferenceCount.Should().Be(1); - } -} diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/AccessListBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/AccessListBuilder.cs index 2076ff7d95d..1bfc8b34b9c 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/AccessListBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/AccessListBuilder.cs @@ -9,12 +9,12 @@ public class TestAccessListBuilder : BuilderBase { public TestAccessListBuilder() { - AccessList.Builder accessListBuilder = new(); + AccessListBuilder accessListBuilder = new(); foreach (Address address in TestItem.Addresses.Take(5)) { accessListBuilder.AddAddress(address); } - TestObjectInternal = accessListBuilder.Build(); + TestObjectInternal = accessListBuilder.ToAccessList(); } } diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs index da42cf5a6c5..c26ac138b54 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Linq; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; @@ -56,15 +57,15 @@ public BlockBuilder WithTimestamp(ulong timestamp) return this; } - public BlockBuilder WithBlobGasUsed(ulong? blobGasUsed) + public BlockBuilder WithDataGasUsed(ulong? dataGasUsed) { - TestObjectInternal.Header.BlobGasUsed = blobGasUsed; + TestObjectInternal.Header.DataGasUsed = dataGasUsed; return this; } - public BlockBuilder WithExcessBlobGas(ulong? excessBlobGas) + public BlockBuilder WithExcessDataGas(ulong? excessDataGas) { - TestObjectInternal.Header.ExcessBlobGas = excessBlobGas; + TestObjectInternal.Header.ExcessDataGas = excessDataGas; return this; } @@ -276,11 +277,5 @@ public BlockBuilder WithWithdrawals(params Withdrawal[]? withdrawals) return this; } - - public BlockBuilder WithParentBeaconBlockRoot(Keccak? parentBeaconBlockRoot) - { - TestObjectInternal.Header.ParentBeaconBlockRoot = parentBeaconBlockRoot; - return this; - } } } diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/BlockHeaderBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/BlockHeaderBuilder.cs index e20cc4f61f3..dfc12b82659 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/BlockHeaderBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/BlockHeaderBuilder.cs @@ -178,21 +178,15 @@ public BlockHeaderBuilder WithWithdrawalsRoot(Keccak? root) return this; } - public BlockHeaderBuilder WithBlobGasUsed(ulong? blobGasUsed) + public BlockHeaderBuilder WithDataGasUsed(ulong? dataGasUsed) { - TestObjectInternal.BlobGasUsed = blobGasUsed; + TestObjectInternal.DataGasUsed = dataGasUsed; return this; } - public BlockHeaderBuilder WithExcessBlobGas(ulong? excessBlobGas) + public BlockHeaderBuilder WithExcessDataGas(ulong? excessDataGas) { - TestObjectInternal.ExcessBlobGas = excessBlobGas; - return this; - } - - public BlockHeaderBuilder WithParentBeaconBlockRoot(Keccak? parentBeaconBlockRoot) - { - TestObjectInternal.ParentBeaconBlockRoot = parentBeaconBlockRoot; + TestObjectInternal.ExcessDataGas = excessDataGas; return this; } } diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/BlockTreeBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/BlockTreeBuilder.cs index a16bb56e06f..61f6843162b 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/BlockTreeBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/BlockTreeBuilder.cs @@ -11,6 +11,7 @@ using Nethermind.Core.Specs; using Nethermind.Crypto; using Nethermind.Db; +using Nethermind.Specs; using Nethermind.Logging; using Nethermind.Serialization.Rlp; using Nethermind.State.Proofs; @@ -18,6 +19,7 @@ using Nethermind.Db.Blooms; using NSubstitute; using NUnit.Framework; +using Nethermind.Core.Extensions; namespace Nethermind.Core.Test.Builders { diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/BlockTreeExtensions.cs b/src/Nethermind/Nethermind.Core.Test/Builders/BlockTreeExtensions.cs index ca015aabb06..ebc12630130 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/BlockTreeExtensions.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/BlockTreeExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Nethermind.Blockchain; +using Nethermind.Core.Crypto; using Nethermind.Crypto; namespace Nethermind.Core.Test.Builders diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/Build.Transaction.cs b/src/Nethermind/Nethermind.Core.Test/Builders/Build.Transaction.cs index cd33bbf886e..3df93e7f9ac 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/Build.Transaction.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/Build.Transaction.cs @@ -1,6 +1,14 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; +using System.Linq; +using Nethermind.Core.Eip2930; +using Nethermind.Core.Extensions; +using Nethermind.Crypto; +using Nethermind.Int256; +using Nethermind.Logging; + namespace Nethermind.Core.Test.Builders; public partial class Build diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/ReceiptBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/ReceiptBuilder.cs index c20dd7a5990..a52516901f6 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/ReceiptBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/ReceiptBuilder.cs @@ -3,6 +3,7 @@ using System; using Nethermind.Core.Crypto; +using Nethermind.Int256; namespace Nethermind.Core.Test.Builders { @@ -48,7 +49,7 @@ public ReceiptBuilder WithTxType(TxType txType) return this; } - public ReceiptBuilder WithTransactionHash(Keccak? hash) + public ReceiptBuilder WithTransactionHash(Keccak hash) { TestObject.TxHash = hash; return this; @@ -60,7 +61,7 @@ public ReceiptBuilder WithBlockNumber(long number) return this; } - public ReceiptBuilder WithBlockHash(Keccak? hash) + public ReceiptBuilder WithBlockHash(Keccak hash) { TestObject.BlockHash = hash; return this; @@ -84,7 +85,7 @@ public ReceiptBuilder WithBloom(Bloom bloom) return this; } - public ReceiptBuilder WithError(string? error) + public ReceiptBuilder WithError(string error) { TestObjectInternal.Error = error; return this; @@ -102,13 +103,13 @@ public ReceiptBuilder WithSender(Address sender) return this; } - public ReceiptBuilder WithContractAddress(Address? contractAddress) + public ReceiptBuilder WithContractAddress(Address contractAddress) { TestObjectInternal.ContractAddress = contractAddress; return this; } - public ReceiptBuilder WithRecipient(Address? recipient) + public ReceiptBuilder WithRecipient(Address recipient) { TestObjectInternal.Recipient = recipient; return this; diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/TestItem.Tree.cs b/src/Nethermind/Nethermind.Core.Test/Builders/TestItem.Tree.cs index c6609215f53..ba34d21ceb5 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/TestItem.Tree.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/TestItem.Tree.cs @@ -2,9 +2,13 @@ // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Net; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Crypto; using Nethermind.Db; +using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Serialization.Rlp; using Nethermind.State; diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/TestItem.cs b/src/Nethermind/Nethermind.Core.Test/Builders/TestItem.cs index 54fc80fb766..bc17bd97963 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/TestItem.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/TestItem.cs @@ -6,6 +6,7 @@ using System.Net; using System.Text.Json; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Crypto; using Nethermind.Int256; using Nethermind.Serialization.Rlp; diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/TransactionBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/TransactionBuilder.cs index 654d004eaca..76517b69aff 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/TransactionBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/TransactionBuilder.cs @@ -121,7 +121,7 @@ public TransactionBuilder WithValue(int value) return this; } - public TransactionBuilder WithAccessList(AccessList? accessList) + public TransactionBuilder WithAccessList(AccessList accessList) { TestObjectInternal.AccessList = accessList; TestObjectInternal.ChainId = TestObjectInternal.Signature?.ChainId ?? TestObjectInternal.ChainId; @@ -134,9 +134,9 @@ public TransactionBuilder WithSenderAddress(Address? address) return this; } - public TransactionBuilder WithMaxFeePerBlobGas(UInt256? maxFeePerBlobGas) + public TransactionBuilder WithMaxFeePerDataGas(UInt256? maxFeePerDataGas) { - TestObjectInternal.MaxFeePerBlobGas = maxFeePerBlobGas; + TestObjectInternal.MaxFeePerDataGas = maxFeePerDataGas; return this; } @@ -153,7 +153,7 @@ public TransactionBuilder WithBlobVersionedHashes(int? count) return this; } - TestObjectInternal.BlobVersionedHashes = Enumerable.Range(0, count.Value).Select(_ => + TestObjectInternal.BlobVersionedHashes = Enumerable.Range(0, count.Value).Select(x => { byte[] bvh = new byte[32]; bvh[0] = KzgPolynomialCommitments.KzgBlobHashVersionV1; @@ -173,7 +173,7 @@ public TransactionBuilder WithShardBlobTxTypeAndFields(int blobCount = 1, boo } TestObjectInternal.Type = TxType.Blob; - TestObjectInternal.MaxFeePerBlobGas ??= 1; + TestObjectInternal.MaxFeePerDataGas ??= 1; if (isMempoolTx) { @@ -236,14 +236,6 @@ public TransactionBuilder Signed(IEthereumEcdsa ecdsa, PrivateKey privateKey, return this; } - public TransactionBuilder Signed(PrivateKey? privateKey = null) - { - privateKey ??= TestItem.IgnoredPrivateKey; - EthereumEcdsa ecdsa = new(TestObjectInternal.ChainId ?? TestBlockchainIds.ChainId, LimboLogs.Instance); - - return Signed(ecdsa, privateKey, isEip155Enabled: true); - } - // TODO: auto create ecdsa here public TransactionBuilder SignedAndResolved(IEthereumEcdsa ecdsa, PrivateKey privateKey, bool isEip155Enabled = true) { diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/TrieBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/TrieBuilder.cs index 33de3023b11..585537a8f03 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/TrieBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/TrieBuilder.cs @@ -6,6 +6,7 @@ using Nethermind.Logging; using Nethermind.Serialization.Rlp; using Nethermind.Trie; +using Nethermind.Trie.Pruning; namespace Nethermind.Core.Test.Builders { diff --git a/src/Nethermind/Nethermind.Core.Test/Collections/ClampedReadOnlyListTests.cs b/src/Nethermind/Nethermind.Core.Test/Collections/ClampedReadOnlyListTests.cs deleted file mode 100644 index 279754f2b1a..00000000000 --- a/src/Nethermind/Nethermind.Core.Test/Collections/ClampedReadOnlyListTests.cs +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using System.Linq; -using FluentAssertions; -using NUnit.Framework; - -namespace Nethermind.Core.Test.Collections; - -public class ClampedReadOnlyListTests -{ - [Test] - public void When_ListIsSmallerThanClamp_ReturnTheSameObject() - { - int[] baseList = Enumerable.Repeat(0, 100).ToArray(); - IReadOnlyList clamped = baseList.Clamp(1000); - clamped.Should().BeSameAs(baseList); - } - - [Test] - public void When_Clamped_ReturnOnlyPrefixOfOriginalArray() - { - int[] baseList = Enumerable.Range(0, 100).ToArray(); - IReadOnlyList clamped = baseList.Clamp(10); - - clamped.Should().BeEquivalentTo(Enumerable.Range(0, 10).ToArray()); - } - - [Test] - public void When_Clamped_AttemptToIndexAboveRange_WillThrow() - { - int[] baseList = Enumerable.Range(0, 100).ToArray(); - IReadOnlyList clamped = baseList.Clamp(10); - - clamped.Count.Should().Be(10); - - Action act = () => - { - int _ = clamped[11]; - }; - - act.Should().Throw(); - } -} diff --git a/src/Nethermind/Nethermind.Core.Test/Collections/LockableConcurrentDictionaryTests.cs b/src/Nethermind/Nethermind.Core.Test/Collections/LockableConcurrentDictionaryTests.cs index 3ac80bec60f..79d707293a6 100644 --- a/src/Nethermind/Nethermind.Core.Test/Collections/LockableConcurrentDictionaryTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Collections/LockableConcurrentDictionaryTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading.Tasks; diff --git a/src/Nethermind/Nethermind.Core.Test/Crypto/EthereumEcdsaTests.cs b/src/Nethermind/Nethermind.Core.Test/Crypto/EthereumEcdsaTests.cs index 07728abe408..09366c21253 100644 --- a/src/Nethermind/Nethermind.Core.Test/Crypto/EthereumEcdsaTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Crypto/EthereumEcdsaTests.cs @@ -1,10 +1,14 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections; using System.Collections.Generic; +using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Logging; +using Nethermind.Serialization.Rlp; using NUnit.Framework; namespace Nethermind.Core.Test.Crypto @@ -21,16 +25,16 @@ public class EthereumEcdsaTests [TestCaseSource(nameof(TestCaseSources))] public void Signature_verify_test((string Name, Transaction Tx) testCase) { - EthereumEcdsa ecdsa = new(BlockchainIds.Sepolia, LimboLogs.Instance); + EthereumEcdsa ecdsa = new(BlockchainIds.Ropsten, LimboLogs.Instance); ecdsa.Verify(testCase.Tx.SenderAddress!, testCase.Tx); } [TestCase(true)] [TestCase(false)] - public void Signature_test_sepolia(bool eip155) + public void Signature_test_ropsten(bool eip155) { - EthereumEcdsa ecdsa = new(BlockchainIds.Sepolia, LimboLogs.Instance); + EthereumEcdsa ecdsa = new(BlockchainIds.Ropsten, LimboLogs.Instance); PrivateKey key = Build.A.PrivateKey.TestObject; Transaction tx = Build.A.Transaction.TestObject; ecdsa.Sign(key, tx, eip155); @@ -38,6 +42,17 @@ public void Signature_test_sepolia(bool eip155) Assert.That(address, Is.EqualTo(key.Address)); } + [Test] + public void Test_eip155_for_the_first_ropsten_transaction() + { + Transaction tx = Rlp.Decode(new Rlp(Bytes.FromHexString("0xf85f808082520894353535353535353535353535353535353535353580801ca08d24b906be2d91a0bf2168862726991cc408cddf94cb087b392ce992573be891a077964b4e55a5c8ec7b85087d619c641c06def33ab052331337ca9efcd6b82aef"))); + + Assert.That(tx.Hash, Is.EqualTo(new Keccak("0x5fd225549ed5c587c843e04578bdd4240fc0d7ab61f8e9faa37e84ec8dc8766d")), "hash"); + EthereumEcdsa ecdsa = new(BlockchainIds.Ropsten, LimboLogs.Instance); + Address? from = ecdsa.RecoverAddress(tx); + Assert.That(from, Is.EqualTo(new Address("0x874b54a8bd152966d63f706bae1ffeb0411921e5")), "from"); + } + [TestCase(true)] [TestCase(false)] public void Signature_test_olympic(bool isEip155Enabled) diff --git a/src/Nethermind/Nethermind.Core.Test/Eip2930/AccessListTests.cs b/src/Nethermind/Nethermind.Core.Test/Eip2930/AccessListTests.cs deleted file mode 100644 index c6978eda415..00000000000 --- a/src/Nethermind/Nethermind.Core.Test/Eip2930/AccessListTests.cs +++ /dev/null @@ -1,200 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using FluentAssertions; -using Nethermind.Core.Eip2930; -using Nethermind.Core.Test.Builders; -using Nethermind.Int256; -using NUnit.Framework; - -namespace Nethermind.Core.Test.Eip2930; - -public class AccessListTests -{ - [Test] - public void Single_address_with_multiple_storage_keys() - { - Address address = TestItem.AddressA; - UInt256 storageKey1 = (UInt256)1; - UInt256 storageKey2 = (UInt256)2; - UInt256 storageKey3 = (UInt256)3; - - AccessList accessList = new AccessList.Builder() - .AddAddress(address) - .AddStorage(storageKey1) - .AddStorage(storageKey2) - .AddStorage(storageKey3) - .Build(); - - IEnumerable<(Address, IEnumerable)> expected = new List<(Address, IEnumerable)> - { - (address, new[] { storageKey1, storageKey2, storageKey3 }) - }; - - accessList.Should().BeEquivalentTo(expected); - } - - [Test] - public void Single_address_with_duplicated_storage_keys() - { - Address address = TestItem.AddressA; - UInt256 storageKey1 = (UInt256)1; - UInt256 storageKey2 = (UInt256)2; - UInt256 storageKey3 = (UInt256)3; - - AccessList accessList = new AccessList.Builder() - .AddAddress(address) - .AddStorage(storageKey1) - .AddStorage(storageKey2) - .AddStorage(storageKey3) - .AddStorage(storageKey1) - .Build(); - - IEnumerable<(Address, IEnumerable)> expected = new List<(Address, IEnumerable)> - { - (address, new[] { storageKey1, storageKey2, storageKey3, storageKey1 }) - }; - - accessList.Should().BeEquivalentTo(expected); - } - - [Test] - public void Duplicated_address_with_multiple_storage_keys() - { - Address address = TestItem.AddressA; - UInt256 storageKey1 = (UInt256)1; - UInt256 storageKey2 = (UInt256)2; - UInt256 storageKey3 = (UInt256)3; - - AccessList accessList = new AccessList.Builder() - .AddAddress(address) - .AddStorage(storageKey1) - .AddStorage(storageKey2) - .AddAddress(address) - .AddStorage(storageKey3) - .Build(); - - IEnumerable<(Address, IEnumerable)> expected = new List<(Address, IEnumerable)> - { - (address, new[] { storageKey1, storageKey2 }), - (address, new[] { storageKey3 }) - }; - - accessList.Should().BeEquivalentTo(expected); - } - - [Test] - public void Duplicated_address_with_duplicated_storage_keys() - { - Address address = TestItem.AddressA; - UInt256 storageKey1 = (UInt256)1; - UInt256 storageKey2 = (UInt256)2; - UInt256 storageKey3 = (UInt256)3; - - AccessList accessList = new AccessList.Builder() - .AddAddress(address) - .AddStorage(storageKey1) - .AddStorage(storageKey2) - .AddAddress(address) - .AddStorage(storageKey1) - .AddStorage(storageKey3) - .Build(); - - IEnumerable<(Address, IEnumerable)> expected = new List<(Address, IEnumerable)> - { - (address, new[] { storageKey1, storageKey2 }), - (address, new[] { storageKey1, storageKey3 }) - }; - - accessList.Should().BeEquivalentTo(expected); - } - - [Test] - public void Multiple_addresses_no_storage() - { - Address address1 = TestItem.AddressA; - Address address2 = TestItem.AddressB; - - AccessList accessList = new AccessList.Builder() - .AddAddress(address1) - .AddAddress(address2) - .Build(); - - IEnumerable<(Address, IEnumerable)> expected = new List<(Address, IEnumerable)> - { - (address1, new UInt256[] { }), - (address2, new UInt256[] { }) - }; - - accessList.Should().BeEquivalentTo(expected); - } - - [Test] - public void Multiple_addresses_with_storage() - { - Address address1 = TestItem.AddressA; - Address address2 = TestItem.AddressB; - UInt256 storageKey1 = (UInt256)1; - UInt256 storageKey2 = (UInt256)2; - UInt256 storageKey3 = (UInt256)3; - - AccessList accessList = new AccessList.Builder() - .AddAddress(address1) - .AddStorage(storageKey1) - .AddStorage(storageKey2) - .AddAddress(address2) - .AddStorage(storageKey3) - .Build(); - - IEnumerable<(Address, IEnumerable)> expected = new List<(Address, IEnumerable)> - { - (address1, new[] { storageKey1, storageKey2 }), - (address2, new[] { storageKey3 }) - }; - - accessList.Should().BeEquivalentTo(expected); - } - - [Test] - public void Multiple_duplicated_addresses_with_storage() - { - Address address1 = TestItem.AddressA; - Address address2 = TestItem.AddressB; - UInt256 storageKey1 = (UInt256)1; - UInt256 storageKey2 = (UInt256)2; - UInt256 storageKey3 = (UInt256)3; - - AccessList accessList = new AccessList.Builder() - .AddAddress(address1) - .AddStorage(storageKey1) - .AddStorage(storageKey2) - .AddAddress(address2) - .AddStorage(storageKey3) - .AddAddress(address1) - .AddStorage(storageKey1) - .AddAddress(address2) - .Build(); - - IEnumerable<(Address, IEnumerable)> expected = new List<(Address, IEnumerable)> - { - (address1, new[] { storageKey1, storageKey2 }), - (address2, new[] { storageKey3 }), - (address1, new[] { storageKey1 }), - (address2, new UInt256[] { }), - }; - - accessList.Should().BeEquivalentTo(expected); - } - - [Test] - public void Invalid_storage_when_no_previous_address() - { - Assert.Throws(() => - { - AccessList.Builder _ = new AccessList.Builder() - .AddStorage(UInt256.Zero); - }); - } -} diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/AccessListDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/AccessListDecoderTests.cs index 76579f93489..5cd844d9733 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/AccessListDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/AccessListDecoderTests.cs @@ -5,6 +5,7 @@ using FluentAssertions; using Nethermind.Core.Eip2930; using Nethermind.Core.Test.Builders; +using Nethermind.Int256; using Nethermind.Serialization.Rlp; using Nethermind.Serialization.Rlp.Eip2930; using NUnit.Framework; @@ -16,77 +17,71 @@ public class AccessListDecoderTests { private readonly AccessListDecoder _decoder = new(); - public static IEnumerable<(string, AccessList?)> TestCaseSource() + public static IEnumerable<(string, AccessList)> TestCaseSource() { - yield return ( - "null", - null); + yield return ("null", null!); - // yield return ("empty", AccessList.Empty()); <-- null and empty are equivalent here + HashSet indexes = new(); + Dictionary> data = new(); + // yield return ("empty", new AccessList(data)); <-- null and empty are equivalent here + // + indexes = new HashSet(); + data = new Dictionary>(); + data.Add(TestItem.AddressA, indexes); + yield return ("no storage", new AccessList(data)); - yield return ( - "no storage", - new AccessList.Builder() - .AddAddress(TestItem.AddressA) - .Build()); + indexes = new HashSet(); + data = new Dictionary>(); + data.Add(TestItem.AddressA, indexes); + data.Add(TestItem.AddressB, indexes); + yield return ("no storage 2", new AccessList(data)); - yield return ( - "no storage 2", - new AccessList.Builder() - .AddAddress(TestItem.AddressA) - .AddAddress(TestItem.AddressB) - .Build()); + indexes = new HashSet(); + data = new Dictionary>(); + data.Add(TestItem.AddressA, indexes); + indexes.Add(1); + yield return ("1-1", new AccessList(data)); - yield return ( - "1-1", - new AccessList.Builder() - .AddAddress(TestItem.AddressA) - .AddStorage(1) - .Build()); + indexes = new HashSet(); + data = new Dictionary>(); + data.Add(TestItem.AddressA, indexes); + indexes.Add(1); + indexes.Add(2); + yield return ("1-2", new AccessList(data)); - yield return ( - "1-2", - new AccessList.Builder() - .AddAddress(TestItem.AddressA) - .AddStorage(1) - .AddStorage(2) - .Build()); + indexes = new HashSet(); + data = new Dictionary>(); + indexes.Add(1); + indexes.Add(2); + data.Add(TestItem.AddressA, indexes); + data.Add(TestItem.AddressB, indexes); + yield return ("2-2", new AccessList(data)); - yield return ( - "2-1", - new AccessList.Builder() - .AddAddress(TestItem.AddressA) - .AddStorage(1) - .AddAddress(TestItem.AddressB) - .AddStorage(2) - .Build()); + indexes = new HashSet(); + var indexes2 = new HashSet(); + data = new Dictionary>(); + indexes.Add(1); + indexes2.Add(2); + data.Add(TestItem.AddressA, indexes); + data.Add(TestItem.AddressB, indexes2); + AccessList accessList = new(data, + new Queue(new List { TestItem.AddressA, (UInt256)1, TestItem.AddressB, (UInt256)2 })); + yield return ("with order queue", accessList); - yield return ( - "2-2", - new AccessList.Builder() - .AddAddress(TestItem.AddressA) - .AddStorage(1) - .AddStorage(2) - .AddAddress(TestItem.AddressB) - .AddStorage(1) - .AddStorage(2) - .Build()); - - yield return ( - "with duplicates", - new AccessList.Builder() - .AddAddress(TestItem.AddressA) - .AddStorage(1) - .AddStorage(1) - .AddAddress(TestItem.AddressB) - .AddStorage(2) - .AddAddress(TestItem.AddressB) - .AddStorage(2) - .Build()); + indexes = new HashSet(); + indexes2 = new HashSet(); + data = new Dictionary>(); + indexes.Add(1); + indexes2.Add(2); + data.Add(TestItem.AddressA, indexes); + data.Add(TestItem.AddressB, indexes2); + accessList = new AccessList(data, + new Queue(new List { TestItem.AddressA, (UInt256)1, (UInt256)1, TestItem.AddressB, (UInt256)2, TestItem.AddressB, (UInt256)2 })); + yield return ("with order queue and duplicates", accessList); } [TestCaseSource(nameof(TestCaseSource))] - public void Roundtrip((string TestName, AccessList? AccessList) testCase) + public void Roundtrip((string TestName, AccessList AccessList) testCase) { RlpStream rlpStream = new(10000); _decoder.Encode(rlpStream, testCase.AccessList); @@ -98,12 +93,12 @@ public void Roundtrip((string TestName, AccessList? AccessList) testCase) } else { - decoded.Should().BeEquivalentTo(testCase.AccessList, testCase.TestName); + decoded!.Data.Should().BeEquivalentTo(testCase.AccessList.Data, testCase.TestName); } } [TestCaseSource(nameof(TestCaseSource))] - public void Roundtrip_value((string TestName, AccessList? AccessList) testCase) + public void Roundtrip_value((string TestName, AccessList AccessList) testCase) { RlpStream rlpStream = new(10000); _decoder.Encode(rlpStream, testCase.AccessList); @@ -116,7 +111,7 @@ public void Roundtrip_value((string TestName, AccessList? AccessList) testCase) } else { - decoded.Should().BeEquivalentTo(testCase.AccessList, testCase.TestName); + decoded!.Data.Should().BeEquivalentTo(testCase.AccessList.Data, testCase.TestName); } } diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs index 1de97dd9f91..20ac09f5235 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs @@ -63,8 +63,8 @@ public BlockDecoderTests() .WithTransactions(transactions) .WithUncles(uncles) .WithWithdrawals(8) - .WithBlobGasUsed(0) - .WithExcessBlobGas(0) + .WithDataGasUsed(0) + .WithExcessDataGas(0) .WithMixHash(Keccak.EmptyTreeHash) .TestObject, Build.A.Block @@ -73,8 +73,8 @@ public BlockDecoderTests() .WithTransactions(transactions) .WithUncles(uncles) .WithWithdrawals(8) - .WithBlobGasUsed(0xff) - .WithExcessBlobGas(0xff) + .WithDataGasUsed(0xff) + .WithExcessDataGas(0xff) .WithMixHash(Keccak.EmptyTreeHash) .TestObject, Build.A.Block @@ -83,8 +83,8 @@ public BlockDecoderTests() .WithTransactions(transactions) .WithUncles(uncles) .WithWithdrawals(8) - .WithBlobGasUsed(ulong.MaxValue) - .WithExcessBlobGas(ulong.MaxValue) + .WithDataGasUsed(ulong.MaxValue) + .WithExcessDataGas(ulong.MaxValue) .WithMixHash(Keccak.EmptyTreeHash) .TestObject }; diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/BlockInfoDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/BlockInfoDecoderTests.cs index 7b339aa1d0e..f719f591021 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/BlockInfoDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/BlockInfoDecoderTests.cs @@ -102,7 +102,7 @@ public static Rlp BlockInfoEncodeDeprecated(BlockInfo? item, bool chainWithFinal stream.Encode(item.IsFinalized); } - return new Rlp(stream.Data!); + return new Rlp(stream.Data); } } } diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/CompactReceiptStorageDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/CompactReceiptStorageDecoderTests.cs index 28bd91ec217..708ff94bfc9 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/CompactReceiptStorageDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/CompactReceiptStorageDecoderTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using DotNetty.Common.Utilities; using FluentAssertions; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs index 577d21b456e..eb6b1be1130 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs @@ -162,30 +162,29 @@ public void Can_encode_decode_with_negative_long_when_using_span(long negativeLo blockHeader.GasLimit.Should().Be(negativeLong); } - [TestCaseSource(nameof(CancunFieldsSource))] - public void Can_encode_decode_with_cancun_fields(ulong? blobGasUsed, ulong? excessBlobGas, Keccak? parentBeaconBlockRoot) + [TestCaseSource(nameof(ExcessDataGasCaseSource))] + public void Can_encode_decode_with_excessDataGas(ulong? dataGasUsed, ulong? excessDataGas) { BlockHeader header = Build.A.BlockHeader .WithTimestamp(ulong.MaxValue) .WithBaseFee(1) .WithWithdrawalsRoot(Keccak.Zero) - .WithBlobGasUsed(blobGasUsed) - .WithExcessBlobGas(excessBlobGas) - .WithParentBeaconBlockRoot(parentBeaconBlockRoot).TestObject; + .WithDataGasUsed(dataGasUsed) + .WithExcessDataGas(excessDataGas).TestObject; Rlp rlp = Rlp.Encode(header); BlockHeader blockHeader = Rlp.Decode(rlp.Bytes.AsSpan()); - blockHeader.BlobGasUsed.Should().Be(blobGasUsed); - blockHeader.ExcessBlobGas.Should().Be(excessBlobGas); + blockHeader.DataGasUsed.Should().Be(dataGasUsed); + blockHeader.ExcessDataGas.Should().Be(excessDataGas); } - public static IEnumerable CancunFieldsSource() + public static IEnumerable ExcessDataGasCaseSource() { - yield return new object?[] { null, null, null }; - yield return new object?[] { 0ul, 0ul, TestItem.KeccakA }; - yield return new object?[] { 1ul, 2ul, TestItem.KeccakB }; - yield return new object?[] { ulong.MaxValue / 2, ulong.MaxValue, null }; - yield return new object?[] { ulong.MaxValue, ulong.MaxValue / 2, null }; + yield return new object?[] { null, null }; + yield return new object?[] { 0ul, 0ul }; + yield return new object?[] { 1ul, 2ul }; + yield return new object?[] { ulong.MaxValue / 2, ulong.MaxValue }; + yield return new object?[] { ulong.MaxValue, ulong.MaxValue / 2 }; } } diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/OwnedBlockBodiesTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/OwnedBlockBodiesTests.cs deleted file mode 100644 index 550bb8a26bb..00000000000 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/OwnedBlockBodiesTests.cs +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Buffers; -using FluentAssertions; -using Nethermind.Core.Test.Builders; -using Nethermind.Specs; -using NSubstitute; -using NUnit.Framework; - -namespace Nethermind.Core.Test.Encoding; - -public class OwnedBlockBodiesTests -{ - [Test] - public void Should_dispose_memory_owner() - { - IMemoryOwner memoryOwner = Substitute.For>(); - BlockBody[] blockBodies = { Build.A.Block.WithTransactions(2, MainnetSpecProvider.Instance).TestObject.Body }; - OwnedBlockBodies ownedBlockBodies = new(blockBodies, memoryOwner); - ownedBlockBodies.Dispose(); - memoryOwner.Received().Dispose(); - } - - [Test] - public void Should_copy_data_when_disowned() - { - IMemoryOwner actualMemoryOwner = MemoryPool.Shared.Rent(100); - IMemoryOwner memoryOwner = Substitute.For>(); - BlockBody[] blockBodies = { Build.A.Block.WithTransactions(1, MainnetSpecProvider.Instance).TestObject.Body }; - blockBodies[0].Transactions[0].Data = actualMemoryOwner.Memory; - actualMemoryOwner.Memory.Span.Fill(1); - blockBodies[0].Transactions[0].Data.Should().BeEquivalentTo(actualMemoryOwner.Memory); - - OwnedBlockBodies ownedBlockBodies = new(blockBodies, memoryOwner); - ownedBlockBodies.Disown(); - actualMemoryOwner.Memory.Span.Fill(0); - blockBodies[0].Transactions[0].Data.Should().NotBeEquivalentTo(actualMemoryOwner.Memory); - } -} diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/ReceiptArrayDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/ReceiptArrayDecoderTests.cs index ea38b82da26..0dd8543bb07 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/ReceiptArrayDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/ReceiptArrayDecoderTests.cs @@ -1,7 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using FluentAssertions; +using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Serialization.Rlp; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/ShardBlobTxDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/ShardBlobTxDecoderTests.cs index de21439c924..0240c4b1c59 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/ShardBlobTxDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/ShardBlobTxDecoderTests.cs @@ -33,7 +33,7 @@ public partial class ShardBlobTxDecoderTests [TestCaseSource(nameof(TestCaseSource))] public void Roundtrip_ExecutionPayloadForm_for_shard_blobs((Transaction Tx, string Description) testCase) { - RlpStream rlpStream = new RlpStream(_txDecoder.GetLength(testCase.Tx, RlpBehaviors.None)); + RlpStream rlpStream = new RlpStream(_txDecoder.GetLength(testCase.Tx)); _txDecoder.Encode(rlpStream, testCase.Tx); rlpStream.Position = 0; Transaction? decoded = _txDecoder.Decode(rlpStream); diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/TxDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/TxDecoderTests.cs index 09f7395c85c..08764c24ef5 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/TxDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/TxDecoderTests.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; using System.Threading.Tasks; using FluentAssertions; using FluentAssertions.Numeric; @@ -33,10 +34,11 @@ public class TxDecoderTests .WithType(TxType.AccessList) .WithChainId(TestBlockchainIds.ChainId) .WithAccessList( - new AccessList.Builder() - .AddAddress(Address.Zero) - .AddStorage(1) - .Build()) + new AccessList( + new Dictionary> + { + { Address.Zero, new HashSet { (UInt256)1 } } + }, new Queue(new List { Address.Zero, (UInt256)1 }))) .SignedAndResolved(), "access list"); yield return (Build.A.Transaction .WithData(new byte[] { 1, 2, 3 }) @@ -44,10 +46,11 @@ public class TxDecoderTests .WithMaxFeePerGas(30) .WithChainId(TestBlockchainIds.ChainId) .WithAccessList( - new AccessList.Builder() - .AddAddress(Address.Zero) - .AddStorage(1) - .Build()) + new AccessList( + new Dictionary> + { + { Address.Zero, new HashSet { (UInt256)1 } } + }, new Queue(new List { Address.Zero, (UInt256)1 }))) .SignedAndResolved(), "EIP1559 - access list"); yield return (Build.A.Transaction .WithType(TxType.EIP1559) @@ -77,7 +80,7 @@ public void CanCorrectlyCalculateTxHash_when_called_concurrently((Transaction Tx Keccak expectedHash = Keccak.Compute(rlp.Bytes); - Transaction decodedTx = decoder.Decode(new RlpStream(rlp.Bytes))!; + Transaction decodedTx = decoder.Decode(new RlpStream(rlp.Bytes)); decodedTx.SetPreHash(rlp.Bytes); @@ -120,47 +123,13 @@ public void Roundtrip_ValueDecoderContext((Transaction Tx, string Description) t decoded.EqualToTransaction(testCase.Tx); } - [TestCaseSource(nameof(TestCaseSource))] - public void Roundtrip_ValueDecoderContext_WithMemorySlice((Transaction Tx, string Description) testCase) - { - RlpStream rlpStream = new(10000); - _txDecoder.Encode(rlpStream, testCase.Tx); - - Rlp.ValueDecoderContext decoderContext = new(rlpStream.Data, true); - rlpStream.Position = 0; - Transaction? decoded = _txDecoder.Decode(ref decoderContext); - decoded!.SenderAddress = - new EthereumEcdsa(TestBlockchainIds.ChainId, LimboLogs.Instance).RecoverAddress(decoded); - decoded.Hash = decoded.CalculateHash(); - decoded.EqualToTransaction(testCase.Tx); - } - - [TestCaseSource(nameof(TestCaseSource))] - public void ValueDecoderContext_DecodeWithMemorySlice_ShouldUseSameBuffer((Transaction Tx, string Description) testCase) - { - if (!testCase.Tx.Data.HasValue || testCase.Tx.Data.Value.Length == 0) return; - - RlpStream rlpStream = new(10000); - _txDecoder.Encode(rlpStream, testCase.Tx); - - Rlp.ValueDecoderContext decoderContext = new(rlpStream.Data, true); - rlpStream.Position = 0; - Transaction? decoded = _txDecoder.Decode(ref decoderContext); - - byte[] data1 = decoded!.Data!.Value.ToArray(); - data1.AsSpan().Fill(1); - rlpStream.Data.AsSpan().Fill(1); - - decoded.Data.Value.ToArray().Should().BeEquivalentTo(data1); - } - [TestCaseSource(nameof(YoloV3TestCases))] public void Roundtrip_yolo_v3((string IncomingRlpHex, Keccak Hash) testCase) { TestContext.Out.WriteLine($"Testing {testCase.Hash}"); RlpStream incomingTxRlp = Bytes.FromHexString(testCase.IncomingRlpHex).AsRlpStream(); - Transaction decoded = _txDecoder.Decode(incomingTxRlp)!; + Transaction decoded = _txDecoder.Decode(incomingTxRlp); decoded.CalculateHash().Should().Be(testCase.Hash); RlpStream ourRlpOutput = new(incomingTxRlp.Length * 2); @@ -176,10 +145,10 @@ public void CalculateHash_and_tx_hash_after_decoding_return_the_same_value( { TestContext.Out.WriteLine($"Testing {testCase.Hash}"); RlpStream incomingTxRlp = Bytes.FromHexString(testCase.IncomingRlpHex).AsRlpStream(); - Transaction decoded = _txDecoder.Decode(incomingTxRlp)!; + Transaction decoded = _txDecoder.Decode(incomingTxRlp); Rlp encodedForTreeRoot = _txDecoder.Encode(decoded, RlpBehaviors.SkipTypedWrapping); - decoded.CalculateHash().Should().Be(decoded.Hash!); + decoded.CalculateHash().Should().Be(decoded.Hash); decoded.Hash.Should().Be(Keccak.Compute(encodedForTreeRoot.Bytes)); } @@ -188,7 +157,7 @@ public void Hash_calculation_do_not_change_after_roundtrip((string IncomingRlpHe { TestContext.Out.WriteLine($"Testing {testCase.Hash}"); RlpStream incomingTxRlp = Bytes.FromHexString(testCase.IncomingRlpHex).AsRlpStream(); - Transaction decoded = _txDecoder.Decode(incomingTxRlp)!; + Transaction decoded = _txDecoder.Decode(incomingTxRlp); Rlp encodedForTreeRoot = _txDecoder.Encode(decoded, RlpBehaviors.SkipTypedWrapping); decoded.Hash.Should().Be(Keccak.Compute(encodedForTreeRoot.Bytes)); } @@ -198,7 +167,7 @@ public void Hash_calculation_do_not_change_after_roundtrip2((string IncomingRlpH { TestContext.Out.WriteLine($"Testing {testCase.Hash}"); RlpStream incomingTxRlp = Bytes.FromHexString(testCase.IncomingRlpHex).AsRlpStream(); - Transaction decoded = _txDecoder.Decode(incomingTxRlp)!; + Transaction decoded = _txDecoder.Decode(incomingTxRlp); Rlp encodedForTreeRoot = _txDecoder.Encode(decoded, RlpBehaviors.SkipTypedWrapping); decoded.Hash.Should().Be(Keccak.Compute(encodedForTreeRoot.Bytes)); } @@ -224,12 +193,14 @@ private void ValueDecoderContext_return_the_same_transaction_as_rlp_stream( RlpStream incomingTxRlp = Bytes.FromHexString(testCase.IncomingRlpHex).AsRlpStream(); Span spanIncomingTxRlp = Bytes.FromHexString(testCase.IncomingRlpHex).AsSpan(); Rlp.ValueDecoderContext decoderContext = new(spanIncomingTxRlp); - Transaction decodedByValueDecoderContext = _txDecoder.Decode(ref decoderContext, wrapping ? RlpBehaviors.SkipTypedWrapping : RlpBehaviors.None)!; - Transaction decoded = _txDecoder.Decode(incomingTxRlp, wrapping ? RlpBehaviors.SkipTypedWrapping : RlpBehaviors.None)!; - Rlp encoded = _txDecoder.Encode(decoded); - Rlp encodedWithDecodedByValueDecoderContext = _txDecoder.Encode(decodedByValueDecoderContext); - decoded.Hash.Should().Be(testCase.Hash); - decoded.Hash.Should().Be(decodedByValueDecoderContext.Hash!); + Transaction decodedByValueDecoderContext = _txDecoder.Decode(ref decoderContext, + wrapping ? RlpBehaviors.SkipTypedWrapping : RlpBehaviors.None); + Transaction decoded = _txDecoder.Decode(incomingTxRlp, + wrapping ? RlpBehaviors.SkipTypedWrapping : RlpBehaviors.None); + Rlp encoded = _txDecoder.Encode(decoded!); + Rlp encodedWithDecodedByValueDecoderContext = _txDecoder.Encode(decodedByValueDecoderContext!); + decoded!.Hash.Should().Be(testCase.Hash); + decoded!.Hash.Should().Be(decodedByValueDecoderContext!.Hash); Assert.That(encodedWithDecodedByValueDecoderContext.Bytes, Is.EqualTo(encoded.Bytes)); } @@ -242,35 +213,6 @@ public void Rlp_encode_should_return_the_same_as_rlp_stream_encoding( Assert.That(rlpStreamResult.Bytes, Is.EqualTo(rlpResult.Bytes)); } - [Test] - public void Duplicate_storage_keys_result_in_different_hashes() - { - Transaction noDuplicates = Build.A.Transaction - .WithType(TxType.EIP1559) - .WithChainId(TestBlockchainIds.ChainId) - .WithAccessList( - new AccessList.Builder() - .AddAddress(Address.Zero) - .AddStorage(1) - .Build()) - .SignedAndResolved() - .TestObject; - - Transaction duplicates = Build.A.Transaction - .WithType(TxType.EIP1559) - .WithChainId(TestBlockchainIds.ChainId) - .WithAccessList( - new AccessList.Builder() - .AddAddress(Address.Zero) - .AddStorage(1) - .AddStorage(1) - .Build()) - .SignedAndResolved() - .TestObject; - - duplicates.CalculateHash().Should().NotBe(noDuplicates.CalculateHash()); - } - public static IEnumerable<(string, Keccak)> SkipTypedWrappingTestCases() { yield return diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/WithdrawalDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/WithdrawalDecoderTests.cs index 7408c193bd5..56be1dc3da2 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/WithdrawalDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/WithdrawalDecoderTests.cs @@ -4,6 +4,7 @@ using System; using FluentAssertions; using Nethermind.Core.Extensions; +using Nethermind.Int256; using Nethermind.Serialization.Rlp; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Core.Test/MeasuredProgressTests.cs b/src/Nethermind/Nethermind.Core.Test/MeasuredProgressTests.cs index 770dc4f7b1e..04359bb71f2 100644 --- a/src/Nethermind/Nethermind.Core.Test/MeasuredProgressTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/MeasuredProgressTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Threading.Tasks; using NUnit.Framework; namespace Nethermind.Core.Test diff --git a/src/Nethermind/Nethermind.Core.Test/Memory/MallocHelperTests.cs b/src/Nethermind/Nethermind.Core.Test/Memory/MallocHelperTests.cs deleted file mode 100644 index fecc70483a0..00000000000 --- a/src/Nethermind/Nethermind.Core.Test/Memory/MallocHelperTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using FluentAssertions; -using Nethermind.Core.Extensions; -using Nethermind.Core.Memory; -using NUnit.Framework; - -namespace Nethermind.Core.Test.Memory; - -public class MallocHelperTests -{ - [Test] - public void TestMallOpts() - { - MallocHelper.Instance.MallOpt(MallocHelper.Option.M_MMAP_THRESHOLD, (int)128.KiB()).Should().BeTrue(); - } - - [Test] - public void TestMallocTrim() - { - MallocHelper.Instance.MallocTrim(0).Should().BeTrue(); - } -} diff --git a/src/Nethermind/Nethermind.Core.Test/Nethermind.Core.Test.csproj b/src/Nethermind/Nethermind.Core.Test/Nethermind.Core.Test.csproj index 3dcb93f2ff2..82355dc82b7 100644 --- a/src/Nethermind/Nethermind.Core.Test/Nethermind.Core.Test.csproj +++ b/src/Nethermind/Nethermind.Core.Test/Nethermind.Core.Test.csproj @@ -5,7 +5,6 @@ latest true enable - true diff --git a/src/Nethermind/Nethermind.Core.Test/RateLimiterTests.cs b/src/Nethermind/Nethermind.Core.Test/RateLimiterTests.cs deleted file mode 100644 index 0e6e358564d..00000000000 --- a/src/Nethermind/Nethermind.Core.Test/RateLimiterTests.cs +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using FluentAssertions; -using NUnit.Framework; - -namespace Nethermind.Core.Test; - -[Parallelizable(ParallelScope.Self)] -public class RateLimiterTests -{ - [TestCase(100, 1, 1000)] - [TestCase(100, 1, 100)] - [TestCase(1000, 1, 100)] - [TestCase(100, 4, 1000)] - [TestCase(100, 4, 100)] - [TestCase(1000, 4, 100)] - public async Task RateLimiter_should_delay_wait_to_rate_limit(int eventPerSec, int concurrency, int durationMs) - { - RateLimiter rateLimiter = new(eventPerSec); - - TimeSpan duration = TimeSpan.FromMilliseconds(durationMs); - DateTimeOffset startTime = DateTimeOffset.Now; - DateTimeOffset deadline = startTime + duration; - long counter = 0; - - Task[] tasks = Enumerable.Range(0, concurrency).Select(async (_) => - { - while (DateTimeOffset.Now < deadline) - { - Interlocked.Increment(ref counter); - await rateLimiter.WaitAsync(CancellationToken.None); - } - }).ToArray(); - - await Task.WhenAll(tasks); - - int effectivePerSec = (int)(counter / (DateTimeOffset.Now - startTime).TotalSeconds); - effectivePerSec.Should().BeInRange((int)(eventPerSec * 0.5), (int)(eventPerSec * 1.1)); - } - - [Test] - public async Task RateLimiter_should_throw_when_cancelled() - { - RateLimiter rateLimiter = new(1); - await rateLimiter.WaitAsync(CancellationToken.None); - CancellationTokenSource cts = new(); - ValueTask waitTask = rateLimiter.WaitAsync(cts.Token); - cts.Cancel(); - - Func act = async () => await waitTask; - await act.Should().ThrowAsync(); - } - - [Test] - public async Task RateLimiter_should_return_true_on_is_throttled_if_throttled() - { - RateLimiter rateLimiter = new(1); - await rateLimiter.WaitAsync(CancellationToken.None); - rateLimiter.IsThrottled().Should().BeTrue(); - } -} diff --git a/src/Nethermind/Nethermind.Core.Test/RequestSizer/AdaptiveRequestSizerTests.cs b/src/Nethermind/Nethermind.Core.Test/RequestSizer/AdaptiveRequestSizerTests.cs deleted file mode 100644 index 37687d77c1c..00000000000 --- a/src/Nethermind/Nethermind.Core.Test/RequestSizer/AdaptiveRequestSizerTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Threading.Tasks; -using FluentAssertions; -using NUnit.Framework; - -namespace Nethermind.Core.Test.RequestSizer; - -public class AdaptiveRequestSizerTests -{ - [TestCase(1, 100, 20, AdaptiveRequestSizer.Direction.Increase, 30)] - [TestCase(1, 100, 20, AdaptiveRequestSizer.Direction.Decrease, 13)] - [TestCase(1, 100, 20, AdaptiveRequestSizer.Direction.Stay, 20)] - [TestCase(1, 100, 1, AdaptiveRequestSizer.Direction.Increase, 2)] - [TestCase(1, 100, 1, AdaptiveRequestSizer.Direction.Decrease, 1)] - [TestCase(1, 100, 1, AdaptiveRequestSizer.Direction.Stay, 1)] - [TestCase(1, 100, 100, AdaptiveRequestSizer.Direction.Increase, 100)] - [TestCase(1, 100, 100, AdaptiveRequestSizer.Direction.Decrease, 66)] - [TestCase(1, 100, 100, AdaptiveRequestSizer.Direction.Stay, 100)] - public async Task Test_Threshold(int minSize, int maxSize, int startingSize, AdaptiveRequestSizer.Direction direction, int afterRequestSize) - { - AdaptiveRequestSizer sizer = new(minSize, maxSize, startingSize); - - await sizer.Run((requestSize => Task.FromResult((requestSize, direction)))); - - sizer.RequestSize.Should().Be(afterRequestSize); - } -} diff --git a/src/Nethermind/Nethermind.Core.Test/RequestSizer/LatencyAndMessageSizeBasedRequestSizerTests.cs b/src/Nethermind/Nethermind.Core.Test/RequestSizer/LatencyAndMessageSizeBasedRequestSizerTests.cs deleted file mode 100644 index 64ff92fce94..00000000000 --- a/src/Nethermind/Nethermind.Core.Test/RequestSizer/LatencyAndMessageSizeBasedRequestSizerTests.cs +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Linq; -using System.Threading.Tasks; -using FluentAssertions; -using NUnit.Framework; - -namespace Nethermind.Core.Test.RequestSizer; - -public class LatencyAndMessageSizeBasedRequestSizerTests -{ - private static readonly int[] _sampleRequest = Enumerable.Range(0, 10).ToArray(); - - [TestCase(0, 0, 3)] - [TestCase(0, 10000, 1)] - [TestCase(20, 0, 2)] - [TestCase(20, 10000, 1)] - [TestCase(100, 0, 1)] - public async Task TestChangeInRequestSize(int waitTimeMs, long responseSize, int afterRequestSize) - { - LatencyAndMessageSizeBasedRequestSizer sizer = new( - 1, 4, - TimeSpan.FromMilliseconds(10), - TimeSpan.FromMilliseconds(50), - 1000, - 2 - ); - - await sizer.Run(_sampleRequest, async _ => - { - await Task.Delay(waitTimeMs); - return (0, responseSize); - }); - - int modifiedRequestSize = await sizer.Run(_sampleRequest, (cappedRequest) => Task.FromResult((cappedRequest.Count, (long)0))); - - modifiedRequestSize.Should().Be(afterRequestSize); - } -} diff --git a/src/Nethermind/Nethermind.Core.Test/RequestSizer/LatencyBasedRequestSizerTests.cs b/src/Nethermind/Nethermind.Core.Test/RequestSizer/LatencyBasedRequestSizerTests.cs deleted file mode 100644 index ac11c52f51e..00000000000 --- a/src/Nethermind/Nethermind.Core.Test/RequestSizer/LatencyBasedRequestSizerTests.cs +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Threading.Tasks; -using FluentAssertions; -using NUnit.Framework; - -namespace Nethermind.Core.Test.RequestSizer; - -public class LatencyBasedRequestSizerTests -{ - [TestCase(0, 3)] - [TestCase(20, 2)] - [TestCase(100, 1)] - public async Task TestWait(int waitTimeMs, int afterRequestSize) - { - LatencyBasedRequestSizer sizer = new( - 1, 4, - TimeSpan.FromMilliseconds(10), - TimeSpan.FromMilliseconds(50)); - - await sizer.MeasureLatency((_ => Task.FromResult(0))); - await sizer.MeasureLatency((async _ => - { - await Task.Delay(waitTimeMs); - return Task.FromResult(0); - })); - - int modifiedRequestSize = await sizer.MeasureLatency((Task.FromResult)); - - modifiedRequestSize.Should().Be(afterRequestSize); - } -} diff --git a/src/Nethermind/Nethermind.Core.Test/RlpTests.cs b/src/Nethermind/Nethermind.Core.Test/RlpTests.cs index 502e8e3dae4..9810b2cfcf1 100644 --- a/src/Nethermind/Nethermind.Core.Test/RlpTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/RlpTests.cs @@ -41,7 +41,7 @@ public void Serializing_sequence_with_one_int_regression() [Explicit("That was a regression test but now it is failing again and cannot find the reason we needed this behaviour in the first place. Sync works all fine. Leaving it here as it may resurface - make sure to add more explanation to it in such case.")] public void Serializing_object_int_regression() { - Rlp output = Rlp.Encode(new[] { Rlp.Encode(1) }); + Rlp output = Rlp.Encode(new Rlp[] { Rlp.Encode(1) }); Assert.That(output.Bytes, Is.EqualTo(new byte[] { 1 })); } @@ -64,7 +64,7 @@ public void Length_of_uint() public void Long_negative() { Rlp output = Rlp.Encode(-1L); - RlpStream context = new RlpStream(output.Bytes); + var context = new RlpStream(output.Bytes); long value = context.DecodeLong(); Assert.That(value, Is.EqualTo(-1L)); @@ -73,7 +73,7 @@ public void Long_negative() [Test] public void Empty_byte_array() { - byte[] bytes = Array.Empty(); + byte[] bytes = new byte[0]; Rlp rlp = Rlp.Encode(bytes); Rlp rlpSpan = Rlp.Encode(bytes.AsSpan()); Rlp expectedResult = new(new byte[] { 128 }); @@ -241,7 +241,7 @@ public void RlpContextWithSliceMemory_shouldNotCopyUnderlyingData(bool sliceValu { Memory? slice = context.DecodeByteArrayMemory(); slice.Should().NotBeNull(); - MemoryMarshal.TryGetArray(slice!.Value, out ArraySegment segment); + MemoryMarshal.TryGetArray(slice.Value, out ArraySegment segment); bool isACopy = (segment.Offset == 0 && segment.Count == slice.Value.Length); isACopy.Should().NotBe(sliceValue); diff --git a/src/Nethermind/Nethermind.Core.Test/SizeExtensionsTests.cs b/src/Nethermind/Nethermind.Core.Test/SizeExtensionsTests.cs index ea7939ef720..53aad12d4ee 100644 --- a/src/Nethermind/Nethermind.Core.Test/SizeExtensionsTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/SizeExtensionsTests.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using FluentAssertions; using Nethermind.Core.Extensions; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Core.Test/TestMemDb.cs b/src/Nethermind/Nethermind.Core.Test/TestMemDb.cs index e82cd21c024..5dc1e8ba9f8 100644 --- a/src/Nethermind/Nethermind.Core.Test/TestMemDb.cs +++ b/src/Nethermind/Nethermind.Core.Test/TestMemDb.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; using FluentAssertions; using Nethermind.Db; using Bytes = Nethermind.Core.Extensions.Bytes; @@ -17,16 +16,13 @@ namespace Nethermind.Core.Test; public class TestMemDb : MemDb, ITunableDb { private List<(byte[], ReadFlags)> _readKeys = new(); - private List<((byte[], byte[]?), WriteFlags)> _writes = new(); + private List<(byte[], WriteFlags)> _writeKeys = new(); private List _removedKeys = new(); private List _tuneTypes = new(); public Func? ReadFunc { get; set; } public Action? RemoveFunc { get; set; } - public bool WasFlushed { get; set; } - - [MethodImpl(MethodImplOptions.Synchronized)] public override byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) { _readKeys.Add((key.ToArray(), flags)); @@ -35,10 +31,9 @@ public class TestMemDb : MemDb, ITunableDb return base.Get(key, flags); } - [MethodImpl(MethodImplOptions.Synchronized)] public override void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteFlags.None) { - _writes.Add(((key.ToArray(), value), flags)); + _writeKeys.Add((key.ToArray(), flags)); base.Set(key, value, flags); } @@ -47,7 +42,6 @@ public override Span GetSpan(ReadOnlySpan key) return Get(key); } - [MethodImpl(MethodImplOptions.Synchronized)] public override void Remove(ReadOnlySpan key) { _removedKeys.Add(key.ToArray()); @@ -82,17 +76,12 @@ public void KeyWasReadWithFlags(byte[] key, ReadFlags flags, int times = 1) public void KeyWasWritten(byte[] key, int times = 1) { - _writes.Count(it => Bytes.AreEqual(it.Item1.Item1, key)).Should().Be(times); - } - - public void KeyWasWritten(Func<(byte[], byte[]?), bool> cond, int times = 1) - { - _writes.Count(it => cond.Invoke(it.Item1)).Should().Be(times); + _writeKeys.Count(it => Bytes.AreEqual(it.Item1, key)).Should().Be(times); } public void KeyWasWrittenWithFlags(byte[] key, WriteFlags flags, int times = 1) { - _writes.Count(it => Bytes.AreEqual(it.Item1.Item1, key) && it.Item2 == flags).Should().Be(times); + _writeKeys.Count(it => Bytes.AreEqual(it.Item1, key) && it.Item2 == flags).Should().Be(times); } public void KeyWasRemoved(Func cond, int times = 1) @@ -104,9 +93,4 @@ public override IBatch StartBatch() { return new InMemoryBatch(this); } - - public override void Flush() - { - WasFlushed = true; - } } diff --git a/src/Nethermind/Nethermind.Core.Test/TransactionTests.cs b/src/Nethermind/Nethermind.Core.Test/TransactionTests.cs index 9d371f038cd..11edde35601 100644 --- a/src/Nethermind/Nethermind.Core.Test/TransactionTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/TransactionTests.cs @@ -48,7 +48,7 @@ public static void EqualToTransaction(this Transaction subject, Transaction expe subject.Should().BeEquivalentTo( expectation, o => o - .ComparingByMembers() + .ComparingByMembers() .Using>(ctx => ctx.Subject.AsArray().Should().BeEquivalentTo(ctx.Expectation.AsArray())) .WhenTypeIs>() ); diff --git a/src/Nethermind/Nethermind.Core/AccountStateProviderExtensions.cs b/src/Nethermind/Nethermind.Core/AccountStateProviderExtensions.cs index ca0df131ec1..b162773145d 100644 --- a/src/Nethermind/Nethermind.Core/AccountStateProviderExtensions.cs +++ b/src/Nethermind/Nethermind.Core/AccountStateProviderExtensions.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core.Crypto; using Nethermind.Core.Specs; namespace Nethermind.Core diff --git a/src/Nethermind/Nethermind.Core/Attributes/Metrics.cs b/src/Nethermind/Nethermind.Core/Attributes/Metrics.cs index b762e495e7b..392e71c824a 100644 --- a/src/Nethermind/Nethermind.Core/Attributes/Metrics.cs +++ b/src/Nethermind/Nethermind.Core/Attributes/Metrics.cs @@ -16,17 +16,3 @@ public sealed class CounterMetricAttribute : Attribute { } /// [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] public sealed class GaugeMetricAttribute : Attribute { } - -/// -/// Mark that the attribute is a dictionary whose key is used as a label of name LabelName. -/// -[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] -public sealed class KeyIsLabelAttribute : Attribute -{ - public string LabelName { get; } - - public KeyIsLabelAttribute(string labelName) - { - LabelName = labelName; - } -} diff --git a/src/Nethermind/Nethermind.Core/Authentication/JwtAuthentication.cs b/src/Nethermind/Nethermind.Core/Authentication/JwtAuthentication.cs index 5a5f59379e6..7329353d246 100644 --- a/src/Nethermind/Nethermind.Core/Authentication/JwtAuthentication.cs +++ b/src/Nethermind/Nethermind.Core/Authentication/JwtAuthentication.cs @@ -4,6 +4,7 @@ using System; using System.IdentityModel.Tokens.Jwt; using System.IO; +using System.Linq; using System.Security.Cryptography; using System.Text.RegularExpressions; using Microsoft.IdentityModel.Tokens; diff --git a/src/Nethermind/Nethermind.Core/BaseFeeCalculator.cs b/src/Nethermind/Nethermind.Core/BaseFeeCalculator.cs index 70b72473a73..344d608e6c9 100644 --- a/src/Nethermind/Nethermind.Core/BaseFeeCalculator.cs +++ b/src/Nethermind/Nethermind.Core/BaseFeeCalculator.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Core.Specs; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Core/Block.cs b/src/Nethermind/Nethermind.Core/Block.cs index b1b3e1b03da..59e9ed916bb 100644 --- a/src/Nethermind/Nethermind.Core/Block.cs +++ b/src/Nethermind/Nethermind.Core/Block.cs @@ -98,16 +98,15 @@ public Transaction[] Transactions public UInt256 BaseFeePerGas => Header.BaseFeePerGas; // do not add setter here - public ulong? BlobGasUsed => Header.BlobGasUsed; // do not add setter here + public ulong? DataGasUsed => Header.DataGasUsed; // do not add setter here - public ulong? ExcessBlobGas => Header.ExcessBlobGas; // do not add setter here + public ulong? ExcessDataGas => Header.ExcessDataGas; // do not add setter here public bool IsPostMerge => Header.IsPostMerge; // do not add setter here public bool IsBodyMissing => Header.HasBody && Body.IsEmpty; public Keccak? WithdrawalsRoot => Header.WithdrawalsRoot; // do not add setter here - public Keccak? ParentBeaconBlockRoot => Header.ParentBeaconBlockRoot; // do not add setter here public override string ToString() => ToString(Format.Short); diff --git a/src/Nethermind/Nethermind.Core/BlockHeader.cs b/src/Nethermind/Nethermind.Core/BlockHeader.cs index c47e73c02d3..d9fd16d2183 100644 --- a/src/Nethermind/Nethermind.Core/BlockHeader.cs +++ b/src/Nethermind/Nethermind.Core/BlockHeader.cs @@ -25,9 +25,8 @@ public BlockHeader( long gasLimit, ulong timestamp, byte[] extraData, - ulong? blobGasUsed = null, - ulong? excessBlobGas = null, - Keccak? parentBeaconBlockRoot = null) + ulong? dataGasUsed = null, + ulong? excessDataGas = null) { ParentHash = parentHash; UnclesHash = unclesHash; @@ -37,9 +36,8 @@ public BlockHeader( GasLimit = gasLimit; Timestamp = timestamp; ExtraData = extraData; - ParentBeaconBlockRoot = parentBeaconBlockRoot; - BlobGasUsed = blobGasUsed; - ExcessBlobGas = excessBlobGas; + DataGasUsed = dataGasUsed; + ExcessDataGas = excessDataGas; } public WeakReference? MaybeParent { get; set; } @@ -69,9 +67,8 @@ public BlockHeader( public long? AuRaStep { get; set; } public UInt256 BaseFeePerGas { get; set; } public Keccak? WithdrawalsRoot { get; set; } - public Keccak? ParentBeaconBlockRoot { get; set; } - public ulong? BlobGasUsed { get; set; } - public ulong? ExcessBlobGas { get; set; } + public ulong? DataGasUsed { get; set; } + public ulong? ExcessDataGas { get; set; } public bool HasBody => (TxRoot is not null && TxRoot != Keccak.EmptyTreeHash) || (UnclesHash is not null && UnclesHash != Keccak.OfAnEmptySequenceRlp) || (WithdrawalsRoot is not null && WithdrawalsRoot != Keccak.EmptyTreeHash); @@ -104,14 +101,10 @@ public string ToString(string indent) { builder.AppendLine($"{indent}WithdrawalsRoot: {WithdrawalsRoot}"); } - if (ParentBeaconBlockRoot is not null) + if (DataGasUsed is not null || ExcessDataGas is not null) { - builder.AppendLine($"{indent}ParentBeaconBlockRoot: {ParentBeaconBlockRoot}"); - } - if (BlobGasUsed is not null || ExcessBlobGas is not null) - { - builder.AppendLine($"{indent}BlobGasUsed: {BlobGasUsed}"); - builder.AppendLine($"{indent}ExcessBlobGas: {ExcessBlobGas}"); + builder.AppendLine($"{indent}DataGasUsed: {DataGasUsed}"); + builder.AppendLine($"{indent}ExcessDataGas: {ExcessDataGas}"); } builder.AppendLine($"{indent}IsPostMerge: {IsPostMerge}"); builder.AppendLine($"{indent}TotalDifficulty: {TotalDifficulty}"); diff --git a/src/Nethermind/Nethermind.Core/BlockchainIds.cs b/src/Nethermind/Nethermind.Core/BlockchainIds.cs index c054fc02e22..59d76c7d6a1 100644 --- a/src/Nethermind/Nethermind.Core/BlockchainIds.cs +++ b/src/Nethermind/Nethermind.Core/BlockchainIds.cs @@ -8,6 +8,7 @@ namespace Nethermind.Core /// 0: Olympic, Ethereum public pre-release PoW testnet /// 1: Expanse, an alternative Ethereum implementation, chain ID 2 /// 2: Morden Classic, the public Ethereum Classic PoW testnet + /// 3: Ropsten, the public cross-client Ethereum PoS testnet /// 4: Rinkeby, the public Geth-only PoA testnet /// 5: Goerli, the public cross-client PoA testnet /// 42: Kovan, the public Parity-only PoA testnet @@ -23,6 +24,7 @@ public static class BlockchainIds public const int Olympic = 0; public const int Mainnet = 1; public const int Morden = 2; + public const int Ropsten = 3; public const int Rinkeby = 4; public const int Goerli = 5; public const int RootstockMainnet = 30; @@ -37,7 +39,6 @@ public static class BlockchainIds public const int Chiado = 10200; public const int Volta = 73799; public const int Sepolia = 11155111; - public const int Holesky = 17000; public static string GetBlockchainName(ulong networkId) { @@ -46,6 +47,7 @@ public static string GetBlockchainName(ulong networkId) Olympic => nameof(Olympic), Mainnet => nameof(Mainnet), Morden => nameof(Morden), + Ropsten => nameof(Ropsten), Rinkeby => nameof(Rinkeby), Goerli => nameof(Goerli), RootstockMainnet => nameof(RootstockMainnet), diff --git a/src/Nethermind/Nethermind.Core/Buffers/CappedArray.cs b/src/Nethermind/Nethermind.Core/Buffers/CappedArray.cs deleted file mode 100644 index ae665b44c9a..00000000000 --- a/src/Nethermind/Nethermind.Core/Buffers/CappedArray.cs +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using Nethermind.Core.Crypto; -using Nethermind.Core.Extensions; - -namespace Nethermind.Core.Buffers; - -/// -/// Basically like ArraySegment, but only contain length, which reduces it size from 16byte to 12byte. Useful for -/// polling memory where memory pool usually can't return exactly the same size of data. To conserve space, The -/// underlying array can be null and this struct is meant to be non nullable, checking the `IsNull` property to check -/// if it represent null. -/// -public struct CappedArray -{ - private T[]? _array = null; - private int _length = 0; - - public CappedArray(T[]? array, int length) - { - _array = array; - _length = length; - } - - public CappedArray(T[]? array) - { - if (array != null) - { - _array = array; - _length = array.Length; - } - } - - public static implicit operator ReadOnlySpan(CappedArray array) - { - return array.AsSpan(); - } - - public static implicit operator CappedArray(T[]? array) - { - if (array == null) return new CappedArray(null); - return new CappedArray(array); - } - - public int Length - { - get => _length; - set => _length = value; - } - - public T[]? Array => _array; - public bool IsUncapped => _length == _array?.Length; - public bool IsNull => _array is null; - public bool IsNotNull => _array is not null; - - public Span AsSpan() - { - return _array.AsSpan()[..Length]; - } - - public T[]? ToArray() - { - if (_array is null) return null; - if (_length == _array?.Length) return _array; - return AsSpan().ToArray(); - } -} diff --git a/src/Nethermind/Nethermind.Core/Buffers/ICappedArrayPool.cs b/src/Nethermind/Nethermind.Core/Buffers/ICappedArrayPool.cs deleted file mode 100644 index 7a238b65699..00000000000 --- a/src/Nethermind/Nethermind.Core/Buffers/ICappedArrayPool.cs +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Core.Buffers; - -public interface ICappedArrayPool -{ - CappedArray Rent(int size); - - void Return(CappedArray buffer); -} - -public static class BufferPoolExtensions -{ - public static CappedArray SafeRentBuffer(this ICappedArrayPool? pool, int size) - { - if (pool == null) return new CappedArray(new byte[size]); - return pool.Rent(size); - } - - public static void SafeReturnBuffer(this ICappedArrayPool? pool, CappedArray buffer) - { - pool?.Return(buffer); - } -} diff --git a/src/Nethermind/Nethermind.Core/Buffers/LargerArrayPool.cs b/src/Nethermind/Nethermind.Core/Buffers/LargerArrayPool.cs index 09ee3adb9eb..fcd975d99be 100644 --- a/src/Nethermind/Nethermind.Core/Buffers/LargerArrayPool.cs +++ b/src/Nethermind/Nethermind.Core/Buffers/LargerArrayPool.cs @@ -11,7 +11,7 @@ public sealed class LargerArrayPool : ArrayPool { static readonly LargerArrayPool s_instance = new(); - public static new LargerArrayPool Shared => s_instance; + public static new ArrayPool Shared => s_instance; public const int LargeBufferSize = 8 * 1024 * 1024; const int ArrayPoolLimit = 1024 * 1024; @@ -44,7 +44,7 @@ byte[] RentLarge() } } - return GC.AllocateUninitializedArray(_largeBufferSize); + return new byte[_largeBufferSize]; } void ReturnLarge(byte[] array, bool clearArray) @@ -78,7 +78,7 @@ public override byte[] Rent(int minimumLength) } // too big to pool, just allocate - return GC.AllocateUninitializedArray(minimumLength); + return new byte[minimumLength]; } public override void Return(byte[] array, bool clearArray = false) diff --git a/src/Nethermind/Nethermind.Core/Caching/LinkedListNode.cs b/src/Nethermind/Nethermind.Core/Caching/LinkedListNode.cs index 93011a77bb6..fdf04ee183d 100644 --- a/src/Nethermind/Nethermind.Core/Caching/LinkedListNode.cs +++ b/src/Nethermind/Nethermind.Core/Caching/LinkedListNode.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; diff --git a/src/Nethermind/Nethermind.Core/Caching/LruCache.cs b/src/Nethermind/Nethermind.Core/Caching/LruCache.cs index af2785f6aeb..453eb32d03a 100644 --- a/src/Nethermind/Nethermind.Core/Caching/LruCache.cs +++ b/src/Nethermind/Nethermind.Core/Caching/LruCache.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Linq; using System.Runtime.CompilerServices; using Nethermind.Core.Extensions; diff --git a/src/Nethermind/Nethermind.Core/Caching/LruKeyCache.cs b/src/Nethermind/Nethermind.Core/Caching/LruKeyCache.cs index 4dd895c9680..775aea8d68e 100644 --- a/src/Nethermind/Nethermind.Core/Caching/LruKeyCache.cs +++ b/src/Nethermind/Nethermind.Core/Caching/LruKeyCache.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Nethermind.Core.Extensions; diff --git a/src/Nethermind/Nethermind.Core/Collections/ClampedReadOnlyList.cs b/src/Nethermind/Nethermind.Core/Collections/ClampedReadOnlyList.cs deleted file mode 100644 index d81dbbf1a2c..00000000000 --- a/src/Nethermind/Nethermind.Core/Collections/ClampedReadOnlyList.cs +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; - -namespace Nethermind.Core.Test.Collections; - -public class ClampedReadOnlyList : IReadOnlyList -{ - private IReadOnlyList _baseImplementation; - - public ClampedReadOnlyList(IReadOnlyList toClampList, int maxSize) - { - _baseImplementation = toClampList; - Count = maxSize; - } - - public IEnumerator GetEnumerator() - { - return _baseImplementation.Take(Count).GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - int counter = 0; - while (counter < Count) - { - yield return _baseImplementation[counter]; - counter++; - } - } - - public int Count { get; } - - public T this[int index] - { - get - { - if (index >= Count) - { - throw new IndexOutOfRangeException(); - } - return _baseImplementation[index]; - } - } -} - -public static class ReadOnlyListExtensions -{ - public static IReadOnlyList Clamp(this IReadOnlyList toClampList, int maxSize) - { - if (toClampList.Count <= maxSize) - { - return toClampList; - } - - return new ClampedReadOnlyList(toClampList, maxSize); - } -} diff --git a/src/Nethermind/Nethermind.Core/Collections/EnuberableExtensions.cs b/src/Nethermind/Nethermind.Core/Collections/EnuberableExtensions.cs index 117e202d8a5..f9f1058b60a 100644 --- a/src/Nethermind/Nethermind.Core/Collections/EnuberableExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Collections/EnuberableExtensions.cs @@ -13,7 +13,4 @@ public static void ForEach(this IEnumerable list, Action action) { list.ToList().ForEach(action); } - - public static bool NullableSequenceEqual(this IEnumerable? first, IEnumerable? second) => - first is not null ? second is not null && first.SequenceEqual(second) : second is null; } diff --git a/src/Nethermind/Nethermind.Core/Collections/ISpanEqualityComparer.cs b/src/Nethermind/Nethermind.Core/Collections/ISpanEqualityComparer.cs index e5579b80057..f31d3232d9f 100644 --- a/src/Nethermind/Nethermind.Core/Collections/ISpanEqualityComparer.cs +++ b/src/Nethermind/Nethermind.Core/Collections/ISpanEqualityComparer.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Diagnostics.CodeAnalysis; namespace Nethermind.Core.Collections; diff --git a/src/Nethermind/Nethermind.Core/Collections/JournalCollection.cs b/src/Nethermind/Nethermind.Core/Collections/JournalCollection.cs index 389b72c1774..fe67d00436f 100644 --- a/src/Nethermind/Nethermind.Core/Collections/JournalCollection.cs +++ b/src/Nethermind/Nethermind.Core/Collections/JournalCollection.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Threading; namespace Nethermind.Core.Collections { diff --git a/src/Nethermind/Nethermind.Core/Collections/LockableConcurrentDictionary.cs b/src/Nethermind/Nethermind.Core/Collections/LockableConcurrentDictionary.cs index 6169b2c6abf..b465769fd6d 100644 --- a/src/Nethermind/Nethermind.Core/Collections/LockableConcurrentDictionary.cs +++ b/src/Nethermind/Nethermind.Core/Collections/LockableConcurrentDictionary.cs @@ -105,11 +105,6 @@ public static class ConcurrentDictionaryExtensions public static ConcurrentDictionaryLock.Lock AcquireLock(this ConcurrentDictionary dictionary) where TKey : notnull => ConcurrentDictionaryLock.Acquire(dictionary); - - public static void Increment(this ConcurrentDictionary dictionary, TKey key) where TKey : notnull - { - dictionary.AddOrUpdate(key, 1, (_, value) => value + 1); - } } diff --git a/src/Nethermind/Nethermind.Core/Crypto/KeccakHash.cs b/src/Nethermind/Nethermind.Core/Crypto/KeccakHash.cs index 3ca0d2f0dfe..8490b683ab5 100644 --- a/src/Nethermind/Nethermind.Core/Crypto/KeccakHash.cs +++ b/src/Nethermind/Nethermind.Core/Crypto/KeccakHash.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using static System.Numerics.BitOperations; diff --git a/src/Nethermind/Nethermind.Core/Eip2930/AccessList.cs b/src/Nethermind/Nethermind.Core/Eip2930/AccessList.cs index abe0233978b..ab081f810cd 100644 --- a/src/Nethermind/Nethermind.Core/Eip2930/AccessList.cs +++ b/src/Nethermind/Nethermind.Core/Eip2930/AccessList.cs @@ -1,113 +1,30 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; -using System.Collections; using System.Collections.Generic; using Nethermind.Int256; -namespace Nethermind.Core.Eip2930; - -public class AccessList : IEnumerable<(Address Address, AccessList.StorageKeysEnumerable StorageKeys)> +namespace Nethermind.Core.Eip2930 { - private readonly List _items; - - private AccessList(List items) - { - _items = items; - } - - public static AccessList Empty() => new(new List()); - - public class Builder + public class AccessList { - private readonly List _items = new(); - private Address? _currentAddress; - - public Builder AddAddress(Address address) + public AccessList(IReadOnlyDictionary> data, + Queue? orderQueue = null) { - _items.Add(address); - _currentAddress = address; - - return this; + Data = data; + OrderQueue = orderQueue; } - public Builder AddStorage(in UInt256 index) - { - if (_currentAddress is null) - { - throw new InvalidOperationException("No address known when adding index to the access list"); - } - _items.Add(index); + public IReadOnlyDictionary> Data { get; } - return this; - } - - public AccessList Build() - { - return new AccessList(_items); - } - } - - public Enumerator GetEnumerator() => new(_items); - IEnumerator<(Address Address, StorageKeysEnumerable StorageKeys)> IEnumerable<(Address Address, StorageKeysEnumerable StorageKeys)>.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - public struct Enumerator : IEnumerator<(Address Address, StorageKeysEnumerable StorageKeys)>, IEnumerator<(Address Address, IEnumerable StorageKeys)> - { - private readonly List _items; - private int _index = -1; - - public Enumerator(List items) - { - _items = items; - } - - public bool MoveNext() - { - while (++_index < _items.Count && _items[_index] is not Address) { } - return _index < _items.Count; - } - - public void Reset() => _index = -1; - public (Address Address, StorageKeysEnumerable StorageKeys) Current => ((Address)_items[_index], new StorageKeysEnumerable(_items, _index)); - (Address Address, IEnumerable StorageKeys) IEnumerator<(Address Address, IEnumerable StorageKeys)>.Current => Current; - object IEnumerator.Current => Current; - public void Dispose() { } - } - - public readonly struct StorageKeysEnumerable : IEnumerable - { - private readonly List _items; - private readonly int _index; - - public StorageKeysEnumerable(List items, int index) - { - _items = items; - _index = index; - } - - StorageKeysEnumerator GetEnumerator() => new(_items, _index); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - public struct StorageKeysEnumerator : IEnumerator - { - private readonly List _items; - private readonly int _startingIndex; - private int _index; - - public StorageKeysEnumerator(List items, int index) - { - _items = items; - _startingIndex = _index = index; - } + /// + /// Only used for access lists generated outside of Nethermind + /// + public IReadOnlyCollection? OrderQueue { get; } - public bool MoveNext() => ++_index < _items.Count && _items[_index] is UInt256; - public void Reset() => _index = _startingIndex; - public UInt256 Current => (UInt256)_items[_index]; - object IEnumerator.Current => Current; - public void Dispose() { } + /// + /// Has no duplicate entries (allows for more efficient serialization / deserialization) + /// + public bool IsNormalized => OrderQueue is null; } } diff --git a/src/Nethermind/Nethermind.Core/Eip2930/AccessListBuilder.cs b/src/Nethermind/Nethermind.Core/Eip2930/AccessListBuilder.cs new file mode 100644 index 00000000000..ff1d6821bdb --- /dev/null +++ b/src/Nethermind/Nethermind.Core/Eip2930/AccessListBuilder.cs @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Generic; +using Nethermind.Int256; + +namespace Nethermind.Core.Eip2930 +{ + /// + /// We store the extra information here to be able to recreate the order of the incoming transactions. + /// EIP-2930 (https://eips.ethereum.org/EIPS/eip-2930) states that: + /// 'Allowing duplicates + /// This is done because it maximizes simplicity, avoiding questions of what to prevent duplication against: + /// just between two addresses/keys in the access list, + /// between the access list and the tx sender/recipient/newly created contract, + /// other restrictions? + /// Because gas is charged per item, there is no gain and only cost in including a value in the access list twice, + /// so this should not lead to extra chain bloat in practice.' + /// + /// While spec is simplified in this matter (somewhat) it leads to a bit more edge cases. + /// We can no longer simply store the access list as a dictionary, we need to store the order of items + /// and info on duplicates. The way that I suggest is by adding an additional queue structure. + /// It be further optimized by only including a queue of integers and a strict ordering algorithm for the dictionary. + /// + /// I leave it for later in case such an optimization is needed. + /// + public class AccessListBuilder + { + private readonly Dictionary> _data = new(); + + private readonly Queue _orderQueue = new(); + + private Address? _currentAddress; + + public void AddAddress(Address address) + { + _currentAddress = address; + _orderQueue.Enqueue(_currentAddress); + if (!_data.ContainsKey(_currentAddress)) + { + _data[_currentAddress] = new HashSet(); + } + } + + public void AddStorage(in UInt256 index) + { + if (_currentAddress is null) + { + throw new InvalidOperationException("No address known when adding index to the access list"); + } + + _orderQueue.Enqueue(index); + (_data[_currentAddress] as HashSet)!.Add(index); + } + + public AccessList ToAccessList() + { + return new(_data, _orderQueue); + } + } +} diff --git a/src/Nethermind/Nethermind.Core/Eip4844Constants.cs b/src/Nethermind/Nethermind.Core/Eip4844Constants.cs index f64eb88ffc3..0df02f30d78 100644 --- a/src/Nethermind/Nethermind.Core/Eip4844Constants.cs +++ b/src/Nethermind/Nethermind.Core/Eip4844Constants.cs @@ -9,11 +9,11 @@ public class Eip4844Constants { public const int MinBlobsPerTransaction = 1; - public const ulong BlobGasPerBlob = 1 << 17; - public const ulong TargetBlobGasPerBlock = BlobGasPerBlob * 3; - public const ulong MaxBlobGasPerBlock = BlobGasPerBlob * 6; - public const ulong MaxBlobGasPerTransaction = MaxBlobGasPerBlock; + public const ulong DataGasPerBlob = 1 << 17; + public const ulong TargetDataGasPerBlock = DataGasPerBlob * 3; + public const ulong MaxDataGasPerBlock = DataGasPerBlob * 6; + public const ulong MaxDataGasPerTransaction = MaxDataGasPerBlock; - public static readonly UInt256 BlobGasUpdateFraction = 3338477; - public static readonly UInt256 MinBlobGasPrice = 1; + public static readonly UInt256 DataGasUpdateFraction = 3338477; + public static readonly UInt256 MinDataGasPrice = 1; } diff --git a/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs b/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs index 7ae6370774f..d9d04f10fa4 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/Bytes.cs @@ -534,12 +534,12 @@ public static string ToHexString(this byte[] bytes) return ByteArrayToHexViaLookup32(bytes, false, false, false); } - public static void StreamHex(this byte[] bytes, TextWriter streamWriter) + public static void StreamHex(this byte[] bytes, StreamWriter streamWriter) { bytes.AsSpan().StreamHex(streamWriter); } - public static void StreamHex(this Span bytes, TextWriter streamWriter) + public static void StreamHex(this Span bytes, StreamWriter streamWriter) { for (int i = 0; i < bytes.Length; i++) { diff --git a/src/Nethermind/Nethermind.Core/Extensions/DbDriveInfoProvider.cs b/src/Nethermind/Nethermind.Core/Extensions/DbDriveInfoProvider.cs index 57ec048c634..08ea1f1a32e 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/DbDriveInfoProvider.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/DbDriveInfoProvider.cs @@ -13,7 +13,7 @@ public static class DbDriveInfoProvider { public static IDriveInfo[] GetDriveInfos(this IFileSystem fileSystem, string dbPath) { - static IDriveInfo? FindDriveForDirectory(IDriveInfo[] drives, DirectoryInfo dir) + static IDriveInfo FindDriveForDirectory(IDriveInfo[] drives, DirectoryInfo dir) { string dPath = dir.LinkTarget ?? dir.FullName; IEnumerable candidateDrives = drives.Where(drive => dPath.StartsWith(drive.RootDirectory.FullName)); @@ -27,7 +27,7 @@ public static IDriveInfo[] GetDriveInfos(this IFileSystem fileSystem, string dbP } } - return result; + return result!; } DirectoryInfo topDir = new(dbPath); @@ -37,7 +37,7 @@ public static IDriveInfo[] GetDriveInfos(this IFileSystem fileSystem, string dbP //the following processing is to overcome specific behaviour on linux where creating DriveInfo for multiple paths on same logical drive //gives instances with these paths (and not logical drive) IDriveInfo[] allDrives = fileSystem.DriveInfo.GetDrives(); - IDriveInfo? topLevelDrive = FindDriveForDirectory(allDrives, topDir); + IDriveInfo topLevelDrive = FindDriveForDirectory(allDrives, topDir); if (topLevelDrive is not null) { driveInfos.Add(topLevelDrive); @@ -48,7 +48,7 @@ public static IDriveInfo[] GetDriveInfos(this IFileSystem fileSystem, string dbP //only want to handle symlinks - otherwise will be on same drive as parent if (di.LinkTarget is not null) { - IDriveInfo? matchedDrive = FindDriveForDirectory(allDrives, topDir); + IDriveInfo matchedDrive = FindDriveForDirectory(allDrives, topDir); if (matchedDrive is not null) { driveInfos.Add(matchedDrive); diff --git a/src/Nethermind/Nethermind.Core/Extensions/EnumerableExtensions.cs b/src/Nethermind/Nethermind.Core/Extensions/EnumerableExtensions.cs index f994b0bf00b..4230c89b29e 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/EnumerableExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/EnumerableExtensions.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.Linq; diff --git a/src/Nethermind/Nethermind.Core/Extensions/Int64Extensions.cs b/src/Nethermind/Nethermind.Core/Extensions/Int64Extensions.cs index 0017eec04d8..0bf1a3c7c66 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/Int64Extensions.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/Int64Extensions.cs @@ -5,199 +5,200 @@ using System.Buffers.Binary; using Nethermind.Int256; -namespace Nethermind.Core.Extensions; - -public static class Int64Extensions +namespace Nethermind.Core.Extensions { - public static byte[] ToBigEndianByteArrayWithoutLeadingZeros(this long value) + public static class Int64Extensions { - byte byte6 = (byte)(value >> 8); - byte byte5 = (byte)(value >> 16); - byte byte4 = (byte)(value >> 24); - byte byte3 = (byte)(value >> 32); - byte byte2 = (byte)(value >> 40); - byte byte1 = (byte)(value >> 48); - byte byte0 = (byte)(value >> 56); - - if (byte0 == 0) + public static byte[] ToBigEndianByteArrayWithoutLeadingZeros(this long value) { - if (byte1 == 0) + byte byte6 = (byte)(value >> 8); + byte byte5 = (byte)(value >> 16); + byte byte4 = (byte)(value >> 24); + byte byte3 = (byte)(value >> 32); + byte byte2 = (byte)(value >> 40); + byte byte1 = (byte)(value >> 48); + byte byte0 = (byte)(value >> 56); + + if (byte0 == 0) { - if (byte2 == 0) + if (byte1 == 0) { - if (byte3 == 0) + if (byte2 == 0) { - if (byte4 == 0) + if (byte3 == 0) { - if (byte5 == 0) + if (byte4 == 0) { - if (byte6 == 0) + if (byte5 == 0) { - byte[] bytes = new byte[1]; - bytes[0] = (byte)value; - return bytes; + if (byte6 == 0) + { + byte[] bytes = new byte[1]; + bytes[0] = (byte)value; + return bytes; + } + else + { + byte[] bytes = new byte[2]; + bytes[1] = (byte)value; + bytes[0] = byte6; + return bytes; + } } else { - byte[] bytes = new byte[2]; - bytes[1] = (byte)value; - bytes[0] = byte6; + byte[] bytes = new byte[3]; + bytes[2] = (byte)value; + bytes[1] = byte6; + bytes[0] = byte5; return bytes; } } else { - byte[] bytes = new byte[3]; - bytes[2] = (byte)value; - bytes[1] = byte6; - bytes[0] = byte5; + byte[] bytes = new byte[4]; + bytes[3] = (byte)value; + bytes[2] = byte6; + bytes[1] = byte5; + bytes[0] = byte4; return bytes; } } else { - byte[] bytes = new byte[4]; - bytes[3] = (byte)value; - bytes[2] = byte6; - bytes[1] = byte5; - bytes[0] = byte4; + byte[] bytes = new byte[5]; + bytes[4] = (byte)value; + bytes[3] = byte6; + bytes[2] = byte5; + bytes[1] = byte4; + bytes[0] = byte3; return bytes; } } else { - byte[] bytes = new byte[5]; - bytes[4] = (byte)value; - bytes[3] = byte6; - bytes[2] = byte5; - bytes[1] = byte4; - bytes[0] = byte3; + byte[] bytes = new byte[6]; + bytes[5] = (byte)value; + bytes[4] = byte6; + bytes[3] = byte5; + bytes[2] = byte4; + bytes[1] = byte3; + bytes[0] = byte2; return bytes; } } else { - byte[] bytes = new byte[6]; - bytes[5] = (byte)value; - bytes[4] = byte6; - bytes[3] = byte5; - bytes[2] = byte4; - bytes[1] = byte3; - bytes[0] = byte2; + byte[] bytes = new byte[7]; + bytes[6] = (byte)value; + bytes[5] = byte6; + bytes[4] = byte5; + bytes[3] = byte4; + bytes[2] = byte3; + bytes[1] = byte2; + bytes[0] = byte1; return bytes; } } else { - byte[] bytes = new byte[7]; - bytes[6] = (byte)value; - bytes[5] = byte6; - bytes[4] = byte5; - bytes[3] = byte4; - bytes[2] = byte3; - bytes[1] = byte2; - bytes[0] = byte1; + byte[] bytes = new byte[8]; + bytes[7] = (byte)value; + bytes[6] = byte6; + bytes[5] = byte5; + bytes[4] = byte4; + bytes[3] = byte3; + bytes[2] = byte2; + bytes[1] = byte1; + bytes[0] = byte0; return bytes; } } - else + + public static byte[] ToBigEndianByteArray(this long value) { - byte[] bytes = new byte[8]; - bytes[7] = (byte)value; - bytes[6] = byte6; - bytes[5] = byte5; - bytes[4] = byte4; - bytes[3] = byte3; - bytes[2] = byte2; - bytes[1] = byte1; - bytes[0] = byte0; + byte[] bytes = BitConverter.GetBytes(value); + if (BitConverter.IsLittleEndian) + { + Array.Reverse(bytes); + } + return bytes; } - } - public static byte[] ToBigEndianByteArray(this long value) - { - byte[] bytes = BitConverter.GetBytes(value); - if (BitConverter.IsLittleEndian) + public static void WriteBigEndian(this long value, Span output) { - Array.Reverse(bytes); + BinaryPrimitives.WriteInt64BigEndian(output, value); } - return bytes; - } + [ThreadStatic] + private static byte[]? t_byteBuffer64; + private static byte[] GetByteBuffer64() => t_byteBuffer64 ??= new byte[8]; - public static void WriteBigEndian(this long value, Span output) - { - BinaryPrimitives.WriteInt64BigEndian(output, value); - } + public static string ToHexString(this long value, bool skipLeadingZeros) + { + if (value == UInt256.Zero) + { + return "0x"; + } - [ThreadStatic] - private static byte[]? t_byteBuffer64; - private static byte[] GetByteBuffer64() => t_byteBuffer64 ??= new byte[8]; + byte[] bytes = GetByteBuffer64(); + BinaryPrimitives.WriteInt64BigEndian(bytes, value); + return bytes.ToHexString(true, skipLeadingZeros, false); + } - public static string ToHexString(this long value, bool skipLeadingZeros) - { - if (value == 0L) + public static string ToHexString(this ulong value, bool skipLeadingZeros) { - return "0x0"; + if (value == UInt256.Zero) + { + return "0x"; + } + + byte[] bytes = GetByteBuffer64(); + BinaryPrimitives.WriteUInt64BigEndian(bytes, value); + return bytes.ToHexString(true, skipLeadingZeros, false); } - byte[] bytes = GetByteBuffer64(); - BinaryPrimitives.WriteInt64BigEndian(bytes, value); - return bytes.ToHexString(true, skipLeadingZeros, false); - } + [ThreadStatic] + private static byte[]? t_byteBuffer256; + private static byte[] GetByteBuffer256() => t_byteBuffer256 ??= new byte[32]; - public static string ToHexString(this ulong value, bool skipLeadingZeros) - { - if (value == 0UL) + public static string ToHexString(this in UInt256 value, bool skipLeadingZeros) { - return "0x0"; - } + if (skipLeadingZeros) + { + if (value == UInt256.Zero) + { + return "0x"; + } - byte[] bytes = GetByteBuffer64(); - BinaryPrimitives.WriteUInt64BigEndian(bytes, value); - return bytes.ToHexString(true, skipLeadingZeros, false); - } + if (value == UInt256.One) + { + return "0x1"; + } + } - [ThreadStatic] - private static byte[]? t_byteBuffer256; - private static byte[] GetByteBuffer256() => t_byteBuffer256 ??= new byte[32]; + byte[] bytes = GetByteBuffer256(); + value.ToBigEndian(bytes); + return bytes.ToHexString(true, skipLeadingZeros, false); + } - public static string ToHexString(this in UInt256 value, bool skipLeadingZeros) - { - if (skipLeadingZeros) + public static long ToLongFromBigEndianByteArrayWithoutLeadingZeros(this byte[]? bytes) { - if (value == UInt256.Zero) + if (bytes is null) { - return "0x0"; + return 0L; } - if (value == UInt256.One) + long value = 0; + int length = bytes.Length; + + for (int i = 0; i < length; i++) { - return "0x1"; + value += (long)bytes[length - 1 - i] << 8 * i; } - } - - byte[] bytes = GetByteBuffer256(); - value.ToBigEndian(bytes); - return bytes.ToHexString(true, skipLeadingZeros, false); - } - public static long ToLongFromBigEndianByteArrayWithoutLeadingZeros(this byte[]? bytes) - { - if (bytes is null) - { - return 0L; + return value; } - - long value = 0; - int length = bytes.Length; - - for (int i = 0; i < length; i++) - { - value += (long)bytes[length - 1 - i] << 8 * i; - } - - return value; } } diff --git a/src/Nethermind/Nethermind.Core/Extensions/IntExtensions.cs b/src/Nethermind/Nethermind.Core/Extensions/IntExtensions.cs index 71505417f89..a1867c8bf92 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/IntExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/IntExtensions.cs @@ -5,45 +5,46 @@ using System.Buffers.Binary; using Nethermind.Int256; -namespace Nethermind.Core.Extensions; - -public static class IntExtensions +namespace Nethermind.Core.Extensions { - public static string ToHexString(this int @this) - { - return $"0x{@this:x}"; - } - - public static UInt256 Ether(this int @this) + public static class IntExtensions { - return (uint)@this * Unit.Ether; - } + public static string ToHexString(this int @this) + { + return $"0x{@this:X}"; + } - public static UInt256 Wei(this int @this) - { - return (uint)@this * Unit.Wei; - } + public static UInt256 Ether(this int @this) + { + return (uint)@this * Unit.Ether; + } - public static UInt256 GWei(this int @this) - { - return (uint)@this * Unit.GWei; - } + public static UInt256 Wei(this int @this) + { + return (uint)@this * Unit.Wei; + } - public static byte[] ToByteArray(this int value) - { - byte[] bytes = new byte[sizeof(int)]; - BinaryPrimitives.WriteInt32BigEndian(bytes, value); - return bytes; - } + public static UInt256 GWei(this int @this) + { + return (uint)@this * Unit.GWei; + } - public static byte[] ToBigEndianByteArray(this int value) - { - byte[] bytes = BitConverter.GetBytes(value); - if (BitConverter.IsLittleEndian) + public static byte[] ToByteArray(this int value) { - Array.Reverse(bytes); + byte[] bytes = new byte[sizeof(int)]; + BinaryPrimitives.WriteInt32BigEndian(bytes, value); + return bytes; } - return bytes; + public static byte[] ToBigEndianByteArray(this int value) + { + byte[] bytes = BitConverter.GetBytes(value); + if (BitConverter.IsLittleEndian) + { + Array.Reverse(bytes); + } + + return bytes; + } } } diff --git a/src/Nethermind/Nethermind.Core/Extensions/SizeExtensions.cs b/src/Nethermind/Nethermind.Core/Extensions/SizeExtensions.cs index 60c93c8a1bf..e55c8925cd2 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/SizeExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/SizeExtensions.cs @@ -1,6 +1,10 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Buffers.Binary; +using Nethermind.Int256; + namespace Nethermind.Core.Extensions { public static class SizeExtensions diff --git a/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs b/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs index e58a4f035d2..48daf3033f6 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs @@ -55,7 +55,6 @@ private static string ToHexViaLookup(ReadOnlySpan bytes, bool withZeroX, b { return ToHexStringWithEip55Checksum(bytes, withZeroX, skipLeadingZeros); } - if (bytes.Length == 0) return ""; int leadingZeros = skipLeadingZeros ? Bytes.CountLeadingZeros(bytes) : 0; int length = bytes.Length * 2 + (withZeroX ? 2 : 0) - leadingZeros; diff --git a/src/Nethermind/Nethermind.Core/Extensions/TypeExtensions.cs b/src/Nethermind/Nethermind.Core/Extensions/TypeExtensions.cs index 42aaddea5bd..515c3148892 100644 --- a/src/Nethermind/Nethermind.Core/Extensions/TypeExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Extensions/TypeExtensions.cs @@ -5,66 +5,55 @@ using System.Collections.Generic; using System.Linq; -namespace Nethermind.Core.Extensions; - -public static class TypeExtensions +namespace Nethermind.Core.Extensions { - public static Type GetDirectInterfaceImplementation(this Type interfaceType) + public static class TypeExtensions { - if (!interfaceType.IsInterface) + public static Type GetDirectInterfaceImplementation(this Type interfaceType) { - throw new NotSupportedException($"GetDirectInterfaceImplementation method is only allowed to use on interface types, got {interfaceType} instead"); - } + if (!interfaceType.IsInterface) + { + throw new NotSupportedException($"GetDirectInterfaceImplementation method is only allowed to use on interface types, got {interfaceType} instead"); + } - Type[] baseInterfaces = interfaceType.GetInterfaces(); - IEnumerable implementations = TypeDiscovery.FindNethermindBasedTypes(interfaceType).Where(i => i.IsClass); + Type[] baseInterfaces = interfaceType.GetInterfaces(); + IEnumerable implementations = TypeDiscovery.FindNethermindTypes(interfaceType).Where(i => i.IsClass); - foreach (Type implementation in implementations) - { - List interfaces = implementation.GetInterfaces().ToList(); + foreach (Type implementation in implementations) + { + List interfaces = implementation.GetInterfaces().ToList(); - interfaces.RemoveAll(i => baseInterfaces.Contains(i)); + interfaces.RemoveAll(i => baseInterfaces.Contains(i)); - if (interfaces.Contains(interfaceType)) - { - return implementation; + if (interfaces.Contains(interfaceType)) + { + return implementation; + } } - } - - throw new InvalidOperationException($"Couldn't find direct implementation of {interfaceType} interface"); - } - private static readonly ISet _valueTupleTypes = new HashSet( - new Type[] { - typeof(ValueTuple<>), - typeof(ValueTuple<,>), - typeof(ValueTuple<,,>), - typeof(ValueTuple<,,,>), - typeof(ValueTuple<,,,,>), - typeof(ValueTuple<,,,,,>), - typeof(ValueTuple<,,,,,,>), - typeof(ValueTuple<,,,,,,,>) + throw new InvalidOperationException($"Couldn't find direct implementation of {interfaceType} interface"); } - ); - public static bool IsValueTuple(this Type type) => - type.IsGenericType && _valueTupleTypes.Contains(type.GetGenericTypeDefinition()); + private static readonly ISet _valueTupleTypes = new HashSet( + new Type[] { + typeof(ValueTuple<>), + typeof(ValueTuple<,>), + typeof(ValueTuple<,,>), + typeof(ValueTuple<,,,>), + typeof(ValueTuple<,,,,>), + typeof(ValueTuple<,,,,,>), + typeof(ValueTuple<,,,,,,>), + typeof(ValueTuple<,,,,,,,>) + } + ); - public static bool CanBeAssignedNull(this Type type) => - !type.IsValueType || Nullable.GetUnderlyingType(type) is not null; + public static bool IsValueTuple(this Type type) => + type.IsGenericType && _valueTupleTypes.Contains(type.GetGenericTypeDefinition()); - public static bool CannotBeAssignedNull(this Type type) => - type.IsValueType && Nullable.GetUnderlyingType(type) is null; + public static bool CanBeAssignedNull(this Type type) => + !type.IsValueType || Nullable.GetUnderlyingType(type) is not null; - /// - /// Returns the type name. If this is a generic type, appends - /// the list of generic type arguments between angle brackets. - /// (Does not account for embedded / inner generic arguments.) - /// - /// The type. - /// System.String. - public static string NameWithGenerics(this Type type) => - type.IsGenericType - ? $"{type.Name[..type.Name.IndexOf("`", StringComparison.OrdinalIgnoreCase)]}<{string.Join(",", type.GetGenericArguments().Select(NameWithGenerics))}>" - : type.Name; + public static bool CannotBeAssignedNull(this Type type) => + type.IsValueType && Nullable.GetUnderlyingType(type) is null; + } } diff --git a/src/Nethermind/Nethermind.Core/IAccountStateProvider.cs b/src/Nethermind/Nethermind.Core/IAccountStateProvider.cs index 0f5ccc25728..a66d834f187 100644 --- a/src/Nethermind/Nethermind.Core/IAccountStateProvider.cs +++ b/src/Nethermind/Nethermind.Core/IAccountStateProvider.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core.Crypto; + namespace Nethermind.Core { public interface IAccountStateProvider diff --git a/src/Nethermind/Nethermind.Core/IKeyValueStore.cs b/src/Nethermind/Nethermind.Core/IKeyValueStore.cs index 27b7ded8b3f..da22dbe0501 100644 --- a/src/Nethermind/Nethermind.Core/IKeyValueStore.cs +++ b/src/Nethermind/Nethermind.Core/IKeyValueStore.cs @@ -9,8 +9,8 @@ public interface IKeyValueStore : IReadOnlyKeyValueStore { new byte[]? this[ReadOnlySpan key] { - get => Get(key); - set => Set(key, value); + get => Get(key, ReadFlags.None); + set => Set(key, value, WriteFlags.None); } void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteFlags.None); @@ -18,7 +18,7 @@ public interface IKeyValueStore : IReadOnlyKeyValueStore public interface IReadOnlyKeyValueStore { - byte[]? this[ReadOnlySpan key] => Get(key); + byte[]? this[ReadOnlySpan key] => Get(key, ReadFlags.None); byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None); } diff --git a/src/Nethermind/Nethermind.Core/Memory/MallocHelper.cs b/src/Nethermind/Nethermind.Core/Memory/MallocHelper.cs deleted file mode 100644 index d4063030198..00000000000 --- a/src/Nethermind/Nethermind.Core/Memory/MallocHelper.cs +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Runtime.InteropServices; - -namespace Nethermind.Core.Memory; - -/// -/// Wrapper around malloc apis -/// -public class MallocHelper -{ - [DllImport("libc")] - private static extern int mallopt(int opts, int value); - - [DllImport("libc")] - private static extern int malloc_trim(UIntPtr trailingSpace); - - private static MallocHelper? _instance; - public static MallocHelper Instance => _instance ??= new MallocHelper(); - - public bool MallOpt(Option option, int value) - { - // Windows can't find libc and osx does not have the method for some reason - // FreeBSD uses jemalloc by default anyway.... - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return true; - - return mallopt((int)option, value) == 1; - } - - public virtual bool MallocTrim(uint trailingSpace) - { - // Windows can't find libc and osx does not have the method for some reason - // FreeBSD uses jemalloc by default anyway.... - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return true; - - return malloc_trim(trailingSpace) == 1; - } - - public enum Option : int - { - M_MMAP_THRESHOLD = -3 - } -} diff --git a/src/Nethermind/Nethermind.Core/NetworkDiagTracer.cs b/src/Nethermind/Nethermind.Core/NetworkDiagTracer.cs index f1cebfd2534..02a2f83c322 100644 --- a/src/Nethermind/Nethermind.Core/NetworkDiagTracer.cs +++ b/src/Nethermind/Nethermind.Core/NetworkDiagTracer.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Net; +using System.Runtime.CompilerServices; using System.Text; using System.Timers; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Core/RateLimiter.cs b/src/Nethermind/Nethermind.Core/RateLimiter.cs deleted file mode 100644 index e2df5c6f400..00000000000 --- a/src/Nethermind/Nethermind.Core/RateLimiter.cs +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Diagnostics; -using System.Threading; -using System.Threading.Tasks; - -namespace Nethermind.Core; - -/// -/// Simple rate limiter that limits rate of event, by delaying the caller so that a minimum amount of time elapsed -/// between event. -/// -public class RateLimiter -{ - private readonly long _delay; - private long _nextSlot; - - public RateLimiter(int eventPerSec) : this(1.0 / eventPerSec) - { - } - - private RateLimiter(double intervalSec) - { - _delay = (long)(Stopwatch.Frequency * intervalSec); - - _nextSlot = GetCurrentTick(); - } - - public static long GetCurrentTick() - { - return Stopwatch.GetTimestamp(); - } - - private static double TickToMs(long tick) - { - return tick * 1000.0 / Stopwatch.Frequency; - } - - /// - /// Return true if its definitely will be throttled when calling WaitAsync. May still get throttled even if this - /// return false. - /// - /// - public bool IsThrottled() - { - return GetCurrentTick() < _nextSlot; - } - - public async ValueTask WaitAsync(CancellationToken ctx) - { - while (true) - { - long originalNextSlot = _nextSlot; - - // Technically its possible that two `GetCurrentTick()` call at the same time can return same value, - // but its very unlikely. - long now = GetCurrentTick(); - if (now >= originalNextSlot - && Interlocked.CompareExchange(ref _nextSlot, now + _delay, originalNextSlot) == originalNextSlot) - { - return; - } - - long toWait = originalNextSlot - now; - if (toWait < 0) continue; - - await Task.Delay(TimeSpan.FromMilliseconds(TickToMs(toWait)), ctx); - } - } -} diff --git a/src/Nethermind/Nethermind.Core/RequestSizer/AdaptiveRequestSizer.cs b/src/Nethermind/Nethermind.Core/RequestSizer/AdaptiveRequestSizer.cs deleted file mode 100644 index 398622252da..00000000000 --- a/src/Nethermind/Nethermind.Core/RequestSizer/AdaptiveRequestSizer.cs +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Threading.Tasks; - -namespace Nethermind.Core; - -/// -/// Encapsulate the pattern of adjusting request size depending on returned direction. -/// Usually that depends on another metrics (usually the latency). This class just handle changing the request size. -/// If the direction is Increase, the request size is increased, -/// if the direction is Decrease, the request size is decreased. -/// -public class AdaptiveRequestSizer -{ - private readonly int _minRequestLimit; - private readonly int _maxRequestLimit; - private readonly double _adjustmentFactor; - - internal int RequestSize { get; set; } - - public AdaptiveRequestSizer( - int minRequestLimit, - int maxRequestLimit, - int? initialRequestSize = null, - double adjustmentFactor = 1.5 - ) - { - _maxRequestLimit = maxRequestLimit; - _minRequestLimit = minRequestLimit; - _adjustmentFactor = adjustmentFactor; - - RequestSize = initialRequestSize ?? _minRequestLimit; - } - - /// - /// Adjust the RequestSize depending on the requested direction or if the request failed. - /// - /// - /// - /// - public async Task Run(Func> func) - { - // Record starting limit so that in case multiple concurrent request happens, we do not multiply the - // limit on top of other adjustment, so only the last adjustment will stick, which is fine. - int startingRequestSize = RequestSize; - Direction dir = Direction.Decrease; // For when it throws - try - { - (TResponse response, Direction d) = await func(startingRequestSize); - dir = d; - return response; - } - finally - { - if (dir == Direction.Increase && startingRequestSize < _maxRequestLimit) - { - RequestSize = Math.Min((int)(Math.Ceiling(startingRequestSize * _adjustmentFactor)), _maxRequestLimit); - } - else if (dir == Direction.Decrease && startingRequestSize > _minRequestLimit) - { - RequestSize = Math.Max((int)(startingRequestSize / _adjustmentFactor), _minRequestLimit); - } - } - } - - public enum Direction - { - Decrease, - Increase, - Stay - } -} diff --git a/src/Nethermind/Nethermind.Core/RequestSizer/LatencyAndMessageSizeBasedRequestSizer.cs b/src/Nethermind/Nethermind.Core/RequestSizer/LatencyAndMessageSizeBasedRequestSizer.cs deleted file mode 100644 index 9bf8836f329..00000000000 --- a/src/Nethermind/Nethermind.Core/RequestSizer/LatencyAndMessageSizeBasedRequestSizer.cs +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Threading.Tasks; -using Nethermind.Core.Test.Collections; - -namespace Nethermind.Core; - -/// -/// Encapsulate pattern of auto adjusting the request size depending on latency and response size. -/// Used for bodies and receipts where the response size affect memory usage also. -/// -public class LatencyAndMessageSizeBasedRequestSizer -{ - private readonly TimeSpan _upperLatencyWatermark; - private readonly TimeSpan _lowerLatencyWatermark; - private readonly long _maxResponseSize; - private readonly AdaptiveRequestSizer _requestSizer; - - public LatencyAndMessageSizeBasedRequestSizer( - int minRequestLimit, - int maxRequestLimit, - TimeSpan lowerLatencyWatermark, - TimeSpan upperLatencyWatermark, - long maxResponseSize, - int? initialRequestSize, - double adjustmentFactor = 1.5 - ) - { - _upperLatencyWatermark = upperLatencyWatermark; - _lowerLatencyWatermark = lowerLatencyWatermark; - _maxResponseSize = maxResponseSize; - - _requestSizer = new AdaptiveRequestSizer( - minRequestLimit, - maxRequestLimit, - initialRequestSize: initialRequestSize, - adjustmentFactor: adjustmentFactor); - } - - /// - /// Adjust the request size depending on the latency and response size. Accept a list as request which will be capped. - /// If the response size is too large, reduce request size. - /// If the latency is above watermark, reduce request size. - /// If the latency is below watermark and response size is not too large, increase request size. - /// - /// - /// - /// response type - /// request type - /// - public async Task Run(IReadOnlyList request, Func, Task<(TResponse, long)>> func) - { - return await _requestSizer.Run(async (adjustedRequestSize) => - { - long startTime = Stopwatch.GetTimestamp(); - (TResponse result, long messageSize) = await func(request.Clamp(adjustedRequestSize)); - TimeSpan duration = Stopwatch.GetElapsedTime(startTime); - if (messageSize > _maxResponseSize) - { - return (result, AdaptiveRequestSizer.Direction.Decrease); - } - - if (duration > _upperLatencyWatermark) - { - return (result, AdaptiveRequestSizer.Direction.Decrease); - } - - if ( - request.Count >= adjustedRequestSize // If the original request size is low, increasing wont do anything - && duration < _lowerLatencyWatermark) - { - return (result, AdaptiveRequestSizer.Direction.Increase); - } - - return (result, AdaptiveRequestSizer.Direction.Stay); - }); - } -} diff --git a/src/Nethermind/Nethermind.Core/RequestSizer/LatencyBasedRequestSizer.cs b/src/Nethermind/Nethermind.Core/RequestSizer/LatencyBasedRequestSizer.cs deleted file mode 100644 index 3d34bc6d392..00000000000 --- a/src/Nethermind/Nethermind.Core/RequestSizer/LatencyBasedRequestSizer.cs +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Diagnostics; -using System.Threading.Tasks; - -namespace Nethermind.Core; - -public class LatencyBasedRequestSizer -{ - private readonly TimeSpan _upperWatermark; - private readonly TimeSpan _lowerWatermark; - private readonly AdaptiveRequestSizer _requestSizer; - - public LatencyBasedRequestSizer( - int minRequestLimit, - int maxRequestLimit, - TimeSpan lowerWatermark, - TimeSpan upperWatermark, - double adjustmentFactor = 1.5 - ) - { - _upperWatermark = upperWatermark; - _lowerWatermark = lowerWatermark; - - _requestSizer = new AdaptiveRequestSizer(minRequestLimit, maxRequestLimit, adjustmentFactor: adjustmentFactor); - } - - /// - /// Adjust the RequestSize depending on the latency of the request - /// - /// - /// - /// - public async Task MeasureLatency(Func> func) - { - return await _requestSizer.Run(async (requestSize) => - { - long startTime = Stopwatch.GetTimestamp(); - TResponse result = await func(requestSize); - TimeSpan duration = Stopwatch.GetElapsedTime(startTime); - if (duration < _lowerWatermark) - { - return (result, AdaptiveRequestSizer.Direction.Increase); - } - - if (duration > _upperWatermark) - { - return (result, AdaptiveRequestSizer.Direction.Decrease); - } - - return (result, AdaptiveRequestSizer.Direction.Stay); - }); - } -} diff --git a/src/Nethermind/Nethermind.Core/Result.cs b/src/Nethermind/Nethermind.Core/Result.cs index 578dee61df0..724c2b65382 100644 --- a/src/Nethermind/Nethermind.Core/Result.cs +++ b/src/Nethermind/Nethermind.Core/Result.cs @@ -5,13 +5,14 @@ namespace Nethermind.Core { public class Result { - private Result() { } - public ResultType ResultType { get; set; } public string? Error { get; set; } - public static Result Fail(string error) => new() { ResultType = ResultType.Failure, Error = error }; + public static Result Fail(string error) + { + return new() { ResultType = ResultType.Failure, Error = error }; + } public static Result Success { get; } = new() { ResultType = ResultType.Success }; } diff --git a/src/Nethermind/Nethermind.Core/Specs/IReceiptSpec.cs b/src/Nethermind/Nethermind.Core/Specs/IReceiptSpec.cs index 60943fa2161..4b249ad7fd7 100644 --- a/src/Nethermind/Nethermind.Core/Specs/IReceiptSpec.cs +++ b/src/Nethermind/Nethermind.Core/Specs/IReceiptSpec.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Int256; + namespace Nethermind.Core.Specs { /// diff --git a/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs b/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs index f7e8519de72..3f1ad4dd96c 100644 --- a/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs @@ -245,11 +245,6 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec /// bool IsEip3855Enabled { get; } - /// - /// MCOPY instruction - /// - bool IsEip5656Enabled { get; } - /// /// EIP-3860: Limit and meter initcode /// @@ -267,17 +262,6 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec /// bool IsEip4844Enabled { get; } - /// - /// Parent Beacon Block precompile - /// - bool IsEip4788Enabled { get; } - Address Eip4788ContractAddress { get; } - - /// - /// SELFDESTRUCT only in same transaction - /// - bool IsEip6780Enabled { get; } - /// /// Should transactions be validated against chainId. /// @@ -356,10 +340,5 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec public bool TransientStorageEnabled => IsEip1153Enabled; public bool WithdrawalsEnabled => IsEip4895Enabled; - public bool SelfdestructOnlyOnSameTransaction => IsEip6780Enabled; - - public bool IsBeaconBlockRootAvailable => IsEip4788Enabled; - public bool MCopyIncluded => IsEip5656Enabled; - public bool BlobBaseFeeEnabled => IsEip4844Enabled; } } diff --git a/src/Nethermind/Nethermind.Core/Specs/ISpecProvider.cs b/src/Nethermind/Nethermind.Core/Specs/ISpecProvider.cs index f1c640f4835..133b16e99de 100644 --- a/src/Nethermind/Nethermind.Core/Specs/ISpecProvider.cs +++ b/src/Nethermind/Nethermind.Core/Specs/ISpecProvider.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Int256; namespace Nethermind.Core.Specs diff --git a/src/Nethermind/Nethermind.Core/Transaction.cs b/src/Nethermind/Nethermind.Core/Transaction.cs index 1847087924e..a2207032638 100644 --- a/src/Nethermind/Nethermind.Core/Transaction.cs +++ b/src/Nethermind/Nethermind.Core/Transaction.cs @@ -4,8 +4,8 @@ using System.Buffers; using System; using System.Diagnostics; +using System.Runtime.InteropServices; using System.Text; -using Microsoft.Extensions.ObjectPool; using Nethermind.Core.Crypto; using Nethermind.Core.Eip2930; using Nethermind.Core.Extensions; @@ -26,14 +26,23 @@ public class Transaction public TxType Type { get; set; } public UInt256 Nonce { get; set; } + + // max_priority_fee_per_gas public UInt256 GasPrice { get; set; } + + // max_fee_per_gas + public UInt256 DecodedMaxFeePerGas { get; set; } + + public UInt256? GasBottleneck { get; set; } public UInt256 MaxPriorityFeePerGas => GasPrice; - public UInt256 DecodedMaxFeePerGas { get; set; } + public UInt256 MaxFeePerGas => Supports1559 ? DecodedMaxFeePerGas : GasPrice; public bool SupportsAccessList => Type >= TxType.AccessList; public bool Supports1559 => Type >= TxType.EIP1559; public bool SupportsBlobs => Type == TxType.Blob; + + // gas_limit public long GasLimit { get; set; } public Address? To { get; set; } public UInt256 Value { get; set; } @@ -55,9 +64,9 @@ public Keccak? Hash { if (_hash is not null) return _hash; - if (_preHash.Length > 0) + if (_preHash.Count > 0) { - _hash = Keccak.Compute(_preHash.Span); + _hash = Keccak.Compute(_preHash.AsSpan()); ClearPreHashInternal(); } } @@ -71,38 +80,24 @@ public Keccak? Hash } } - private Memory _preHash; - private IMemoryOwner? _preHashMemoryOwner; + private ArraySegment _preHash; public void SetPreHash(ReadOnlySpan transactionSequence) { lock (this) { - SetPreHashNoLock(transactionSequence); - } - } - - public void SetPreHashNoLock(ReadOnlySpan transactionSequence) - { - // Used to delay hash generation, as may be filtered as having too low gas etc - _hash = null; + // Used to delay hash generation, as may be filtered as having too low gas etc + _hash = null; - int size = transactionSequence.Length; - _preHashMemoryOwner = MemoryPool.Shared.Rent(size); - _preHash = _preHashMemoryOwner.Memory[..size]; - transactionSequence.CopyTo(_preHash.Span); - } - - public void SetPreHashMemoryNoLock(Memory transactionSequence, IMemoryOwner? preHashMemoryOwner = null) - { - // Used to delay hash generation, as may be filtered as having too low gas etc - _hash = null; - _preHash = transactionSequence; - _preHashMemoryOwner = preHashMemoryOwner; + int size = transactionSequence.Length; + byte[] preHash = ArrayPool.Shared.Rent(size); + transactionSequence.CopyTo(preHash); + _preHash = new ArraySegment(preHash, 0, size); + } } public void ClearPreHash() { - if (_preHash.Length > 0) + if (_preHash.Count > 0) { lock (this) { @@ -113,10 +108,9 @@ public void ClearPreHash() private void ClearPreHashInternal() { - if (_preHash.Length > 0) + if (_preHash.Count > 0) { - _preHashMemoryOwner?.Dispose(); - _preHashMemoryOwner = null; + ArrayPool.Shared.Return(_preHash.Array!); _preHash = default; } } @@ -127,7 +121,7 @@ private void ClearPreHashInternal() public AccessList? AccessList { get; set; } // eip2930 - public UInt256? MaxFeePerBlobGas { get; set; } // eip4844 + public UInt256? MaxFeePerDataGas { get; set; } // eip4844 public byte[]?[]? BlobVersionedHashes { get; set; } // eip4844 @@ -188,7 +182,7 @@ public string ToString(string indent) if (SupportsBlobs) { - builder.AppendLine($"{indent}{nameof(MaxFeePerBlobGas)}: {MaxFeePerBlobGas}"); + builder.AppendLine($"{indent}{nameof(MaxFeePerDataGas)}: {MaxFeePerDataGas}"); builder.AppendLine($"{indent}{nameof(BlobVersionedHashes)}: {BlobVersionedHashes?.Length}"); } @@ -198,42 +192,6 @@ public string ToString(string indent) public override string ToString() => ToString(string.Empty); public bool MayHaveNetworkForm => Type is TxType.Blob; - - public class PoolPolicy : IPooledObjectPolicy - { - public Transaction Create() - { - return new Transaction(); - } - - public bool Return(Transaction obj) - { - obj.ClearPreHash(); - obj.Hash = default; - obj.ChainId = default; - obj.Type = default; - obj.Nonce = default; - obj.GasPrice = default; - obj.GasBottleneck = default; - obj.DecodedMaxFeePerGas = default; - obj.GasLimit = default; - obj.To = default; - obj.Value = default; - obj.Data = default; - obj.SenderAddress = default; - obj.Signature = default; - obj.Timestamp = default; - obj.AccessList = default; - obj.MaxFeePerBlobGas = default; - obj.BlobVersionedHashes = default; - obj.NetworkWrapper = default; - obj.IsServiceTransaction = default; - obj.PoolIndex = default; - obj._size = default; - - return true; - } - } } /// diff --git a/src/Nethermind/Nethermind.Core/TypeDiscovery.cs b/src/Nethermind/Nethermind.Core/TypeDiscovery.cs index a3731a2be2d..574dc3eb33e 100644 --- a/src/Nethermind/Nethermind.Core/TypeDiscovery.cs +++ b/src/Nethermind/Nethermind.Core/TypeDiscovery.cs @@ -8,153 +8,136 @@ using System.Runtime.Loader; using System.Threading; -namespace Nethermind.Core; - -public static class TypeDiscovery +namespace Nethermind.Core { - private static readonly HashSet _assembliesWithNethermindTypes = new(); - private static readonly object _lock = new(); - private static int _allLoaded; - private static Type? _pluginType; - - public static void Initialize(Type? pluginType = null) + public static class TypeDiscovery { - // Early return if initialised - if (Volatile.Read(ref _allLoaded) == 1) return; + private static readonly HashSet _nethermindAssemblies = new(); + private static readonly object _lock = new object(); + private static int _allLoaded; - if (pluginType is not null) + private static void LoadAll() { - _pluginType = pluginType; - } + // Early return if initialised + if (Volatile.Read(ref _allLoaded) == 1) return; - LoadAllImpl(); - } + LoadAllImpl(); + } - private static void LoadAllImpl() - { - lock (_lock) + private static void LoadAllImpl() { - // Early return if initialised while waiting for lock - if (Volatile.Read(ref _allLoaded) == 1) return; - - List loadedAssemblies = new(capacity: 48); - Dictionary considered = new(); - foreach (Assembly assembly in AssemblyLoadContext.Default.Assemblies) + lock (_lock) { - // Skip null names (shouldn't happen) - if (assembly.FullName is null) continue; - - // Skip top level upstream assemblies that are already loaded - // as they won't reference anything in Nethermind - if (assembly.FullName.StartsWith("System") - || assembly.FullName.StartsWith("Microsoft") - || assembly.FullName.StartsWith("NLog") - || assembly.FullName.StartsWith("netstandard") - || assembly.FullName.StartsWith("TestableIO") - || assembly.FullName.StartsWith("Newtonsoft") - || assembly.FullName.StartsWith("DotNetty")) + // Early return if initialised while waiting for lock + if (Volatile.Read(ref _allLoaded) == 1) return; + + List loadedAssemblies = new(capacity: 48); + Dictionary considered = new(); + foreach (Assembly assembly in AssemblyLoadContext.Default.Assemblies) { - continue; + // Skip null names (shouldn't happen) + if (assembly.FullName is null) continue; + + // Skip top level upstream assemblies that are already loaded + // as they won't reference anything in Nethermind + if (assembly.FullName.StartsWith("System") + || assembly.FullName.StartsWith("Microsoft") + || assembly.FullName.StartsWith("NLog") + || assembly.FullName.StartsWith("netstandard") + || assembly.FullName.StartsWith("TestableIO") + || assembly.FullName.StartsWith("Newtonsoft") + || assembly.FullName.StartsWith("DotNetty")) + { + continue; + } + + int commaIndex = assembly.FullName.IndexOf(','); + // Skip non full names (shouldn't happen) + if (commaIndex <= 0) continue; + + // Just add the .Name portion as that's what we'll use to compare with AssemblyName + // as full name (including version, culture, SN hash) is constructed on the fly + // for AssemblyName.FullName so long and allocating + string name = assembly.FullName[..commaIndex]; + if (considered.TryAdd(name, assembly)) + { + loadedAssemblies.Add(assembly); + } } - int commaIndex = assembly.FullName.IndexOf(','); - // Skip non full names (shouldn't happen) - if (commaIndex <= 0) continue; + LoadOnce(loadedAssemblies, considered); - // Just add the .Name portion as that's what we'll use to compare with AssemblyName - // as full name (including version, culture, SN hash) is constructed on the fly - // for AssemblyName.FullName so long and allocating - string name = assembly.FullName[..commaIndex]; - if (considered.TryAdd(name, assembly)) + foreach (KeyValuePair kv in considered.Where(static kv => kv.Key.StartsWith("Nethermind"))) { - loadedAssemblies.Add(assembly); + _nethermindAssemblies.Add(kv.Value); } - } - LoadOnce(loadedAssemblies, considered); - - foreach (KeyValuePair kv in considered.Where(static kv => - kv.Key.StartsWith("Nethermind") || (_pluginType is not null && FindNethermindBasedTypes(kv.Value, _pluginType).Any()))) - { - _assembliesWithNethermindTypes.Add(kv.Value); + // Mark initialised before releasing lock + Volatile.Write(ref _allLoaded, 1); } - - // Mark initialised before releasing lock - Volatile.Write(ref _allLoaded, 1); } - } - private static void LoadOnce(List loadedAssemblies, Dictionary considered) - { - // can potentially use https://docs.microsoft.com/en-us/dotnet/standard/assembly/unloadability + private static void LoadOnce(List loadedAssemblies, Dictionary considered) + { + // can potentially use https://docs.microsoft.com/en-us/dotnet/standard/assembly/unloadability - // Closure capture the dictionary once - bool whereFilter(AssemblyName an) => Filter(considered, an); + // Closure capture the dictionary once + Func whereFilter = an => Filter(considered, an); - List missingRefs = loadedAssemblies - .SelectMany(x => x.GetReferencedAssemblies().Where(whereFilter)) - .ToList(); + List missingRefs = loadedAssemblies + .SelectMany(x => x.GetReferencedAssemblies() + .Where(whereFilter)) + .ToList(); - for (int i = 0; i < missingRefs.Count; i++) - { - AssemblyName missingRef = missingRefs[i]; - if (missingRef.Name is null - // Only include new distinct assemblies - || considered.ContainsKey(missingRef.Name)) + for (int i = 0; i < missingRefs.Count; i++) { - continue; + AssemblyName missingRef = missingRefs[i]; + if (missingRef.Name is null + // Only include new distinct assemblies + || considered.ContainsKey(missingRef.Name)) + { + continue; + } + + Assembly assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(missingRef); + considered.Add(missingRef.Name, assembly); + if (assembly == null) + { + // Shouldn't happen (completeness) + continue; + } + + // Find the references of references, filtering out any we've already looked at + IEnumerable newRefs = assembly.GetReferencedAssemblies().Where(whereFilter); + + // Add any extra to end of the list so they will still get picked up from the for loop + missingRefs.AddRange(newRefs); } - Assembly assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(missingRef); - considered.Add(missingRef.Name, assembly); - if (assembly is null) + static bool Filter(Dictionary considered, AssemblyName an) { - // Shouldn't happen (completeness) - continue; + return an.Name is not null + && !considered.ContainsKey(an.Name) + && an.Name.StartsWith("Nethermind"); } - - // Find the references of references, filtering out any we've already looked at - IEnumerable newRefs = assembly.GetReferencedAssemblies().Where(whereFilter); - - // Add any extra to end of the list so they will still get picked up from the for loop - missingRefs.AddRange(newRefs); } - static bool Filter(Dictionary considered, AssemblyName an) + public static IEnumerable FindNethermindTypes(Type baseType) { - return an.Name is not null - && !considered.ContainsKey(an.Name) - && an.Name.StartsWith("Nethermind"); - } - } + LoadAll(); - public static IEnumerable FindNethermindBasedTypes(Type baseType) - { - Initialize(); - - return FindNethermindBasedTypes(_assembliesWithNethermindTypes, baseType); - } - - private static IEnumerable FindNethermindBasedTypes(IEnumerable assemblies, Type baseType) - { - IEnumerable assembliesSelector(Assembly a) => FindNethermindBasedTypes(a, baseType); - - return assemblies.SelectMany(assembliesSelector); - } - - private static IEnumerable FindNethermindBasedTypes(Assembly assembly, Type baseType) => - GetExportedTypes(assembly).Where(t => baseType.IsAssignableFrom(t) && baseType != t); - - private static IEnumerable GetExportedTypes(Assembly? a) - => a is null || a.IsDynamic ? Array.Empty() : a.GetExportedTypes(); - - public static IEnumerable FindNethermindBasedTypes(string typeName) - { - Initialize(); + return _nethermindAssemblies + .SelectMany(a => (a?.IsDynamic ?? false ? Array.Empty() : a?.GetExportedTypes())? + .Where(t => baseType.IsAssignableFrom(t) && baseType != t) ?? Array.Empty()); + } - Func> assembliesSelector = a => GetExportedTypes(a) - .Where(t => t.Name == typeName); + public static IEnumerable FindNethermindTypes(string typeName) + { + LoadAll(); - return _assembliesWithNethermindTypes.SelectMany(assembliesSelector); + return _nethermindAssemblies + .SelectMany(a => (a?.IsDynamic ?? false ? Array.Empty() : a?.GetExportedTypes())? + .Where(t => t.Name == typeName) ?? Array.Empty()); + } } } diff --git a/src/Nethermind/Nethermind.Crypto/AesEngineX86Intrinsic.cs b/src/Nethermind/Nethermind.Crypto/AesEngineX86Intrinsic.cs index 56313a582c5..65efc0606db 100644 --- a/src/Nethermind/Nethermind.Crypto/AesEngineX86Intrinsic.cs +++ b/src/Nethermind/Nethermind.Crypto/AesEngineX86Intrinsic.cs @@ -3,6 +3,7 @@ // Modified from BouncyCastle MIT using System; +using System.Buffers.Binary; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; diff --git a/src/Nethermind/Nethermind.Crypto/Keccak512.cs b/src/Nethermind/Nethermind.Crypto/Keccak512.cs index a3c12b804f3..a48ab4c0c89 100644 --- a/src/Nethermind/Nethermind.Crypto/Keccak512.cs +++ b/src/Nethermind/Nethermind.Crypto/Keccak512.cs @@ -5,6 +5,7 @@ using System.Buffers.Binary; using Nethermind.Serialization.Rlp; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; namespace Nethermind.Crypto { diff --git a/src/Nethermind/Nethermind.Crypto/Ripemd.cs b/src/Nethermind/Nethermind.Crypto/Ripemd.cs index fc02c2e524e..d8c88f07556 100644 --- a/src/Nethermind/Nethermind.Crypto/Ripemd.cs +++ b/src/Nethermind/Nethermind.Crypto/Ripemd.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Threading; using Nethermind.Core.Extensions; using Org.BouncyCastle.Crypto.Digests; diff --git a/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs b/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs index 1b86a363d86..408391db87f 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using Nethermind.Core; -using Nethermind.Core.Crypto; using RocksDbSharp; namespace Nethermind.Db.Rocks; @@ -92,7 +91,7 @@ public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteF } else { - _underlyingBatch.Set(key, value, _columnDb._columnFamily, flags); + _underlyingBatch.Set(key, value, _columnDb._columnFamily); } } } @@ -110,11 +109,6 @@ public void Flush() _mainDb.Flush(); } - public void Compact() - { - _rocksDb.CompactRange(Keccak.Zero.BytesToArray(), Keccak.MaxValue.BytesToArray(), _columnFamily); - } - /// /// Not sure how to handle delete of the columns DB /// @@ -125,15 +119,10 @@ public void Compact() public long GetIndexSize() => _mainDb.GetIndexSize(); public long GetMemtableSize() => _mainDb.GetMemtableSize(); - public Span GetSpan(ReadOnlySpan key) - { - _mainDb.UpdateReadMetrics(); - return _rocksDb.GetSpan(key, _columnFamily); - } + public Span GetSpan(ReadOnlySpan key) => _rocksDb.GetSpan(key, _columnFamily); public void PutSpan(ReadOnlySpan key, ReadOnlySpan value) { - _mainDb.UpdateWriteMetrics(); _rocksDb.Put(key, value, _columnFamily, _mainDb.WriteOptions); } diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs index 7691485e8de..39adbb30a21 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs @@ -19,25 +19,24 @@ public class DbConfig : IDbConfig public bool CacheIndexAndFilterBlocks { get; set; } = false; public int? MaxOpenFiles { get; set; } public long? MaxBytesPerSec { get; set; } + public long? MaxWriteBytesPerSec { get; set; } public int? BlockSize { get; set; } = 16 * 1024; public ulong? ReadAheadSize { get; set; } = (ulong)256.KiB(); public bool? UseDirectReads { get; set; } = false; public bool? UseDirectIoForFlushAndCompactions { get; set; } = false; public bool? DisableCompression { get; set; } = false; - public ulong? CompactionReadAhead { get; set; } public IDictionary? AdditionalRocksDbOptions { get; set; } - public ulong? MaxBytesForLevelBase { get; set; } = (ulong)256.MiB(); public ulong ReceiptsDbWriteBufferSize { get; set; } = (ulong)8.MiB(); public uint ReceiptsDbWriteBufferNumber { get; set; } = 4; public ulong ReceiptsDbBlockCacheSize { get; set; } = 0; public bool ReceiptsDbCacheIndexAndFilterBlocks { get; set; } = false; public int? ReceiptsDbMaxOpenFiles { get; set; } + public long? ReceiptsDbMaxWriteBytesPerSec { get; set; } public long? ReceiptsDbMaxBytesPerSec { get; set; } - public int? ReceiptsDbBlockSize { get; set; } - public bool? ReceiptsDbUseDirectReads { get; set; } - public bool? ReceiptsDbUseDirectIoForFlushAndCompactions { get; set; } - public ulong? ReceiptsDbCompactionReadAhead { get; set; } + public int? ReceiptsBlockSize { get; set; } + public bool? ReceiptsUseDirectReads { get; set; } = false; + public bool? ReceiptsUseDirectIoForFlushAndCompactions { get; set; } = false; public IDictionary? ReceiptsDbAdditionalRocksDbOptions { get; set; } public ulong BlocksDbWriteBufferSize { get; set; } = (ulong)8.MiB(); @@ -45,11 +44,11 @@ public class DbConfig : IDbConfig public ulong BlocksDbBlockCacheSize { get; set; } = 0; public bool BlocksDbCacheIndexAndFilterBlocks { get; set; } = false; public int? BlocksDbMaxOpenFiles { get; set; } + public long? BlocksDbMaxWriteBytesPerSec { get; set; } public long? BlocksDbMaxBytesPerSec { get; set; } public int? BlocksBlockSize { get; set; } - public bool? BlocksDbUseDirectReads { get; set; } - public bool? BlocksDbUseDirectIoForFlushAndCompactions { get; set; } - public ulong? BlocksDbCompactionReadAhead { get; set; } + public bool? BlocksUseDirectReads { get; set; } = false; + public bool? BlocksUseDirectIoForFlushAndCompactions { get; set; } = false; public IDictionary? BlocksDbAdditionalRocksDbOptions { get; set; } public ulong HeadersDbWriteBufferSize { get; set; } = (ulong)8.MiB(); @@ -57,24 +56,23 @@ public class DbConfig : IDbConfig public ulong HeadersDbBlockCacheSize { get; set; } = 0; public bool HeadersDbCacheIndexAndFilterBlocks { get; set; } = false; public int? HeadersDbMaxOpenFiles { get; set; } + public long? HeadersDbMaxWriteBytesPerSec { get; set; } public long? HeadersDbMaxBytesPerSec { get; set; } - public int? HeadersDbBlockSize { get; set; } - public bool? HeadersDbUseDirectReads { get; set; } - public bool? HeadersDbUseDirectIoForFlushAndCompactions { get; set; } - public ulong? HeadersDbCompactionReadAhead { get; set; } + public int? HeadersBlockSize { get; set; } = 4 * 1024; + public bool? HeadersUseDirectReads { get; set; } = false; + public bool? HeadersUseDirectIoForFlushAndCompactions { get; set; } = false; public IDictionary? HeadersDbAdditionalRocksDbOptions { get; set; } - public ulong? HeadersDbMaxBytesForLevelBase { get; set; } = (ulong)128.MiB(); public ulong BlockInfosDbWriteBufferSize { get; set; } = (ulong)8.MiB(); public uint BlockInfosDbWriteBufferNumber { get; set; } = 4; public ulong BlockInfosDbBlockCacheSize { get; set; } = 0; public bool BlockInfosDbCacheIndexAndFilterBlocks { get; set; } = false; public int? BlockInfosDbMaxOpenFiles { get; set; } + public long? BlockInfosDbMaxWriteBytesPerSec { get; set; } public long? BlockInfosDbMaxBytesPerSec { get; set; } - public int? BlockInfosDbBlockSize { get; set; } - public bool? BlockInfosDbUseDirectReads { get; set; } - public bool? BlockInfosDbUseDirectIoForFlushAndCompactions { get; set; } - public ulong? BlockInfosDbCompactionReadAhead { get; set; } + public int? BlockInfosBlockSize { get; set; } + public bool? BlockInfosUseDirectReads { get; set; } = false; + public bool? BlockInfosUseDirectIoForFlushAndCompactions { get; set; } = false; public IDictionary? BlockInfosDbAdditionalRocksDbOptions { get; set; } public ulong PendingTxsDbWriteBufferSize { get; set; } = (ulong)4.MiB(); @@ -82,11 +80,11 @@ public class DbConfig : IDbConfig public ulong PendingTxsDbBlockCacheSize { get; set; } = 0; public bool PendingTxsDbCacheIndexAndFilterBlocks { get; set; } = false; public int? PendingTxsDbMaxOpenFiles { get; set; } + public long? PendingTxsDbMaxWriteBytesPerSec { get; set; } public long? PendingTxsDbMaxBytesPerSec { get; set; } - public int? PendingTxsDbBlockSize { get; set; } - public bool? PendingTxsDbUseDirectReads { get; set; } - public bool? PendingTxsDbUseDirectIoForFlushAndCompactions { get; set; } - public ulong? PendingTxsDbCompactionReadAhead { get; set; } + public int? PendingTxsBlockSize { get; set; } + public bool? PendingTxsUseDirectReads { get; set; } = false; + public bool? PendingTxsUseDirectIoForFlushAndCompactions { get; set; } = false; public IDictionary? PendingTxsDbAdditionalRocksDbOptions { get; set; } public ulong CodeDbWriteBufferSize { get; set; } = (ulong)2.MiB(); @@ -94,11 +92,11 @@ public class DbConfig : IDbConfig public ulong CodeDbBlockCacheSize { get; set; } = 0; public bool CodeDbCacheIndexAndFilterBlocks { get; set; } = false; public int? CodeDbMaxOpenFiles { get; set; } + public long? CodeDbMaxWriteBytesPerSec { get; set; } public long? CodeDbMaxBytesPerSec { get; set; } - public int? CodeDbBlockSize { get; set; } + public int? CodeBlockSize { get; set; } public bool? CodeUseDirectReads { get; set; } = false; public bool? CodeUseDirectIoForFlushAndCompactions { get; set; } = false; - public ulong? CodeCompactionReadAhead { get; set; } public IDictionary? CodeDbAdditionalRocksDbOptions { get; set; } public ulong BloomDbWriteBufferSize { get; set; } = (ulong)1.KiB(); @@ -106,6 +104,7 @@ public class DbConfig : IDbConfig public ulong BloomDbBlockCacheSize { get; set; } = 0; public bool BloomDbCacheIndexAndFilterBlocks { get; set; } = false; public int? BloomDbMaxOpenFiles { get; set; } + public long? BloomDbMaxWriteBytesPerSec { get; set; } public long? BloomDbMaxBytesPerSec { get; set; } public IDictionary? BloomDbAdditionalRocksDbOptions { get; set; } @@ -114,11 +113,11 @@ public class DbConfig : IDbConfig public ulong WitnessDbBlockCacheSize { get; set; } = 0; public bool WitnessDbCacheIndexAndFilterBlocks { get; set; } = false; public int? WitnessDbMaxOpenFiles { get; set; } + public long? WitnessDbMaxWriteBytesPerSec { get; set; } public long? WitnessDbMaxBytesPerSec { get; set; } - public int? WitnessDbBlockSize { get; set; } + public int? WitnessBlockSize { get; set; } public bool? WitnessUseDirectReads { get; set; } = false; public bool? WitnessUseDirectIoForFlushAndCompactions { get; set; } = false; - public ulong? WitnessCompactionReadAhead { get; set; } public IDictionary? WitnessDbAdditionalRocksDbOptions { get; set; } // TODO - profile and customize @@ -127,11 +126,11 @@ public class DbConfig : IDbConfig public ulong CanonicalHashTrieDbBlockCacheSize { get; set; } = 0; public bool CanonicalHashTrieDbCacheIndexAndFilterBlocks { get; set; } = false; public int? CanonicalHashTrieDbMaxOpenFiles { get; set; } + public long? CanonicalHashTrieDbMaxWriteBytesPerSec { get; set; } public long? CanonicalHashTrieDbMaxBytesPerSec { get; set; } - public int? CanonicalHashTrieDbBlockSize { get; set; } + public int? CanonicalHashTrieBlockSize { get; set; } public bool? CanonicalHashTrieUseDirectReads { get; set; } = false; public bool? CanonicalHashTrieUseDirectIoForFlushAndCompactions { get; set; } = false; - public ulong? CanonicalHashTrieCompactionReadAhead { get; set; } public IDictionary? CanonicalHashTrieDbAdditionalRocksDbOptions { get; set; } public ulong MetadataDbWriteBufferSize { get; set; } = (ulong)1.KiB(); @@ -139,11 +138,11 @@ public class DbConfig : IDbConfig public ulong MetadataDbBlockCacheSize { get; set; } = 0; public bool MetadataDbCacheIndexAndFilterBlocks { get; set; } = false; public int? MetadataDbMaxOpenFiles { get; set; } + public long? MetadataDbMaxWriteBytesPerSec { get; set; } public long? MetadataDbMaxBytesPerSec { get; set; } - public int? MetadataDbBlockSize { get; set; } + public int? MetadataBlockSize { get; set; } public bool? MetadataUseDirectReads { get; set; } = false; public bool? MetadataUseDirectIoForFlushAndCompactions { get; set; } = false; - public ulong? MetadataCompactionReadAhead { get; set; } public IDictionary? MetadataDbAdditionalRocksDbOptions { get; set; } public ulong StateDbWriteBufferSize { get; set; } @@ -151,11 +150,11 @@ public class DbConfig : IDbConfig public ulong StateDbBlockCacheSize { get; set; } public bool StateDbCacheIndexAndFilterBlocks { get; set; } public int? StateDbMaxOpenFiles { get; set; } + public long? StateDbMaxWriteBytesPerSec { get; set; } public long? StateDbMaxBytesPerSec { get; set; } public int? StateDbBlockSize { get; set; } = 4 * 1024; public bool? StateDbUseDirectReads { get; set; } = false; public bool? StateDbUseDirectIoForFlushAndCompactions { get; set; } = false; - public ulong? StateDbCompactionReadAhead { get; set; } public bool? StateDbDisableCompression { get; set; } = false; public IDictionary? StateDbAdditionalRocksDbOptions { get; set; } diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs index e0e8933c061..27934242da4 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs @@ -25,9 +25,7 @@ public interface IDbConfig : IConfig bool? UseDirectReads { get; set; } bool? UseDirectIoForFlushAndCompactions { get; set; } bool? DisableCompression { get; set; } - ulong? CompactionReadAhead { get; set; } IDictionary? AdditionalRocksDbOptions { get; set; } - ulong? MaxBytesForLevelBase { get; set; } ulong ReceiptsDbWriteBufferSize { get; set; } uint ReceiptsDbWriteBufferNumber { get; set; } @@ -35,10 +33,9 @@ public interface IDbConfig : IConfig bool ReceiptsDbCacheIndexAndFilterBlocks { get; set; } int? ReceiptsDbMaxOpenFiles { get; set; } long? ReceiptsDbMaxBytesPerSec { get; set; } - int? ReceiptsDbBlockSize { get; set; } - bool? ReceiptsDbUseDirectReads { get; set; } - bool? ReceiptsDbUseDirectIoForFlushAndCompactions { get; set; } - ulong? ReceiptsDbCompactionReadAhead { get; set; } + int? ReceiptsBlockSize { get; set; } + bool? ReceiptsUseDirectReads { get; set; } + bool? ReceiptsUseDirectIoForFlushAndCompactions { get; set; } IDictionary? ReceiptsDbAdditionalRocksDbOptions { get; set; } ulong BlocksDbWriteBufferSize { get; set; } @@ -48,9 +45,8 @@ public interface IDbConfig : IConfig int? BlocksDbMaxOpenFiles { get; set; } long? BlocksDbMaxBytesPerSec { get; set; } int? BlocksBlockSize { get; set; } - bool? BlocksDbUseDirectReads { get; set; } - bool? BlocksDbUseDirectIoForFlushAndCompactions { get; set; } - ulong? BlocksDbCompactionReadAhead { get; set; } + bool? BlocksUseDirectReads { get; set; } + bool? BlocksUseDirectIoForFlushAndCompactions { get; set; } IDictionary? BlocksDbAdditionalRocksDbOptions { get; set; } ulong HeadersDbWriteBufferSize { get; set; } @@ -59,12 +55,10 @@ public interface IDbConfig : IConfig bool HeadersDbCacheIndexAndFilterBlocks { get; set; } int? HeadersDbMaxOpenFiles { get; set; } long? HeadersDbMaxBytesPerSec { get; set; } - int? HeadersDbBlockSize { get; set; } - bool? HeadersDbUseDirectReads { get; set; } - bool? HeadersDbUseDirectIoForFlushAndCompactions { get; set; } - ulong? HeadersDbCompactionReadAhead { get; set; } + int? HeadersBlockSize { get; set; } + bool? HeadersUseDirectReads { get; set; } + bool? HeadersUseDirectIoForFlushAndCompactions { get; set; } IDictionary? HeadersDbAdditionalRocksDbOptions { get; set; } - ulong? HeadersDbMaxBytesForLevelBase { get; set; } ulong BlockInfosDbWriteBufferSize { get; set; } uint BlockInfosDbWriteBufferNumber { get; set; } @@ -72,10 +66,9 @@ public interface IDbConfig : IConfig bool BlockInfosDbCacheIndexAndFilterBlocks { get; set; } int? BlockInfosDbMaxOpenFiles { get; set; } long? BlockInfosDbMaxBytesPerSec { get; set; } - int? BlockInfosDbBlockSize { get; set; } - bool? BlockInfosDbUseDirectReads { get; set; } - bool? BlockInfosDbUseDirectIoForFlushAndCompactions { get; set; } - ulong? BlockInfosDbCompactionReadAhead { get; set; } + int? BlockInfosBlockSize { get; set; } + bool? BlockInfosUseDirectReads { get; set; } + bool? BlockInfosUseDirectIoForFlushAndCompactions { get; set; } IDictionary? BlockInfosDbAdditionalRocksDbOptions { get; set; } ulong PendingTxsDbWriteBufferSize { get; set; } @@ -84,10 +77,9 @@ public interface IDbConfig : IConfig bool PendingTxsDbCacheIndexAndFilterBlocks { get; set; } int? PendingTxsDbMaxOpenFiles { get; set; } long? PendingTxsDbMaxBytesPerSec { get; set; } - int? PendingTxsDbBlockSize { get; set; } - bool? PendingTxsDbUseDirectReads { get; set; } - bool? PendingTxsDbUseDirectIoForFlushAndCompactions { get; set; } - ulong? PendingTxsDbCompactionReadAhead { get; set; } + int? PendingTxsBlockSize { get; set; } + bool? PendingTxsUseDirectReads { get; set; } + bool? PendingTxsUseDirectIoForFlushAndCompactions { get; set; } IDictionary? PendingTxsDbAdditionalRocksDbOptions { get; set; } ulong CodeDbWriteBufferSize { get; set; } @@ -96,10 +88,9 @@ public interface IDbConfig : IConfig bool CodeDbCacheIndexAndFilterBlocks { get; set; } int? CodeDbMaxOpenFiles { get; set; } long? CodeDbMaxBytesPerSec { get; set; } - int? CodeDbBlockSize { get; set; } + int? CodeBlockSize { get; set; } bool? CodeUseDirectReads { get; set; } bool? CodeUseDirectIoForFlushAndCompactions { get; set; } - ulong? CodeCompactionReadAhead { get; set; } IDictionary? CodeDbAdditionalRocksDbOptions { get; set; } ulong BloomDbWriteBufferSize { get; set; } @@ -116,10 +107,9 @@ public interface IDbConfig : IConfig bool WitnessDbCacheIndexAndFilterBlocks { get; set; } int? WitnessDbMaxOpenFiles { get; set; } long? WitnessDbMaxBytesPerSec { get; set; } - int? WitnessDbBlockSize { get; set; } + int? WitnessBlockSize { get; set; } bool? WitnessUseDirectReads { get; set; } bool? WitnessUseDirectIoForFlushAndCompactions { get; set; } - ulong? WitnessCompactionReadAhead { get; set; } IDictionary? WitnessDbAdditionalRocksDbOptions { get; set; } ulong CanonicalHashTrieDbWriteBufferSize { get; set; } @@ -128,10 +118,9 @@ public interface IDbConfig : IConfig bool CanonicalHashTrieDbCacheIndexAndFilterBlocks { get; set; } int? CanonicalHashTrieDbMaxOpenFiles { get; set; } long? CanonicalHashTrieDbMaxBytesPerSec { get; set; } - int? CanonicalHashTrieDbBlockSize { get; set; } + int? CanonicalHashTrieBlockSize { get; set; } bool? CanonicalHashTrieUseDirectReads { get; set; } bool? CanonicalHashTrieUseDirectIoForFlushAndCompactions { get; set; } - ulong? CanonicalHashTrieCompactionReadAhead { get; set; } IDictionary? CanonicalHashTrieDbAdditionalRocksDbOptions { get; set; } ulong MetadataDbWriteBufferSize { get; set; } @@ -140,10 +129,9 @@ public interface IDbConfig : IConfig bool MetadataDbCacheIndexAndFilterBlocks { get; set; } int? MetadataDbMaxOpenFiles { get; set; } long? MetadataDbMaxBytesPerSec { get; set; } - int? MetadataDbBlockSize { get; set; } + int? MetadataBlockSize { get; set; } bool? MetadataUseDirectReads { get; set; } bool? MetadataUseDirectIoForFlushAndCompactions { get; set; } - ulong? MetadataCompactionReadAhead { get; set; } IDictionary? MetadataDbAdditionalRocksDbOptions { get; set; } ulong StateDbWriteBufferSize { get; set; } @@ -155,7 +143,6 @@ public interface IDbConfig : IConfig int? StateDbBlockSize { get; set; } bool? StateDbUseDirectReads { get; set; } bool? StateDbUseDirectIoForFlushAndCompactions { get; set; } - ulong? StateDbCompactionReadAhead { get; set; } bool? StateDbDisableCompression { get; set; } IDictionary? StateDbAdditionalRocksDbOptions { get; set; } diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs index 0ff698c63c5..b5d48552e46 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs @@ -40,15 +40,13 @@ public PerTableDbConfig(IDbConfig dbConfig, RocksDbSettings rocksDbSettings, str public long? MaxBytesPerSec => ReadConfig(nameof(MaxBytesPerSec)); public uint RecycleLogFileNum => ReadConfig(nameof(RecycleLogFileNum)); public bool WriteAheadLogSync => ReadConfig(nameof(WriteAheadLogSync)); - public bool? UseDirectReads => ReadConfig(nameof(UseDirectReads)); - public bool? UseDirectIoForFlushAndCompactions => ReadConfig(nameof(UseDirectIoForFlushAndCompactions)); + public bool UseDirectReads => ReadConfig(nameof(UseDirectReads)); + public bool UseDirectIoForFlushAndCompactions => ReadConfig(nameof(UseDirectIoForFlushAndCompactions)); public int? BlockSize => ReadConfig(nameof(BlockSize)); public ulong? ReadAheadSize => ReadConfig(nameof(ReadAheadSize)); public bool EnableDbStatistics => _dbConfig.EnableDbStatistics; public uint StatsDumpPeriodSec => _dbConfig.StatsDumpPeriodSec; public bool? DisableCompression => ReadConfig(nameof(DisableCompression)); - public ulong? CompactionReadAhead => ReadConfig(nameof(CompactionReadAhead)); - public ulong MaxBytesForLevelBase => ReadConfig(nameof(MaxBytesForLevelBase)); private T? ReadConfig(string propertyName) { diff --git a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs index e0fa2cc004f..75426a497da 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs @@ -12,7 +12,6 @@ using ConcurrentCollections; using Nethermind.Core; using Nethermind.Core.Collections; -using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Db.Rocks.Config; using Nethermind.Db.Rocks.Statistics; @@ -140,7 +139,7 @@ private RocksDb Init(string basePath, string dbPath, IDbConfig dbConfig, ILogMan } // ReSharper disable once VirtualMemberCallInConstructor - if (_logger.IsDebug) _logger.Debug($"Loading DB {Name,-13} from {_fullPath} with max memory footprint of {_maxThisDbSize / 1000 / 1000,5} MB"); + if (_logger.IsDebug) _logger.Debug($"Loading DB {Name,-13} from {_fullPath} with max memory footprint of {_maxThisDbSize / 1000 / 1000}MB"); RocksDb db = _dbsByPath.GetOrAdd(_fullPath, (s, tuple) => Open(s, tuple), (DbOptions, columnFamilies)); if (dbConfig.EnableMetricsUpdater) @@ -369,6 +368,7 @@ protected virtual void BuildOptions(PerTableDbConfig dbConfig, Options opt options.SetWriteBufferSize(writeBufferSize); int writeBufferNumber = (int)dbConfig.WriteBufferNumber; options.SetMaxWriteBufferNumber(writeBufferNumber); + options.SetMinWriteBufferNumberToMerge(2); lock (_dbsByPath) { @@ -376,9 +376,9 @@ protected virtual void BuildOptions(PerTableDbConfig dbConfig, Options opt Interlocked.Add(ref _maxRocksSize, _maxThisDbSize); if (_logger.IsDebug) _logger.Debug( - $"Expected max memory footprint of {Name} DB is {_maxThisDbSize / 1000 / 1000} MB ({writeBufferNumber} * {writeBufferSize / 1000 / 1000} MB + {blockCacheSize / 1000 / 1000} MB)"); - if (_logger.IsDebug) _logger.Debug($"Total max DB footprint so far is {_maxRocksSize / 1000 / 1000} MB"); - ThisNodeInfo.AddInfo("Mem est DB :", $"{_maxRocksSize / 1000 / 1000} MB".PadLeft(8)); + $"Expected max memory footprint of {Name} DB is {_maxThisDbSize / 1000 / 1000}MB ({writeBufferNumber} * {writeBufferSize / 1000 / 1000}MB + {blockCacheSize / 1000 / 1000}MB)"); + if (_logger.IsDebug) _logger.Debug($"Total max DB footprint so far is {_maxRocksSize / 1000 / 1000}MB"); + ThisNodeInfo.AddInfo("Mem est DB :", $"{_maxRocksSize / 1000 / 1000}MB".PadLeft(8)); } options.SetBlockBasedTableFactory(tableOptions); @@ -388,38 +388,27 @@ protected virtual void BuildOptions(PerTableDbConfig dbConfig, Options opt options.SetRecycleLogFileNum(dbConfig .RecycleLogFileNum); // potential optimization for reusing allocated log files - options.SetMaxBytesForLevelBase(dbConfig.MaxBytesForLevelBase); - options.SetUseDirectReads(dbConfig.UseDirectReads.GetValueOrDefault()); - options.SetUseDirectIoForFlushAndCompaction(dbConfig.UseDirectIoForFlushAndCompactions.GetValueOrDefault()); + options.SetUseDirectReads(dbConfig.UseDirectReads); + options.SetUseDirectIoForFlushAndCompaction(dbConfig.UseDirectIoForFlushAndCompactions); // VERY important to reduce stalls. Allow L0->L1 compaction to happen with multiple thread. _rocksDbNative.rocksdb_options_set_max_subcompactions(options.Handle, (uint)Environment.ProcessorCount); - if (dbConfig.CompactionReadAhead != null && dbConfig.CompactionReadAhead != 0) - { - options.SetCompactionReadaheadSize(dbConfig.CompactionReadAhead.Value); - } + // options.SetLevelCompactionDynamicLevelBytes(true); // only switch on on empty DBs + WriteOptions = new WriteOptions(); + WriteOptions.SetSync(dbConfig + .WriteAheadLogSync); // potential fix for corruption on hard process termination, may cause performance degradation - if (dbConfig.DisableCompression == true) - { - options.SetCompression(Compression.No); - } - - if (dbConfig.EnableDbStatistics) - { - options.EnableStatistics(); - } - options.SetStatsDumpPeriodSec(dbConfig.StatsDumpPeriodSec); - - WriteOptions = CreateWriteOptions(dbConfig); - - _noWalWrite = CreateWriteOptions(dbConfig); + _noWalWrite = new WriteOptions(); + _noWalWrite.SetSync(dbConfig.WriteAheadLogSync); _noWalWrite.DisableWal(1); - _lowPriorityWriteOptions = CreateWriteOptions(dbConfig); + _lowPriorityWriteOptions = new WriteOptions(); + _lowPriorityWriteOptions.SetSync(dbConfig.WriteAheadLogSync); Native.Instance.rocksdb_writeoptions_set_low_pri(_lowPriorityWriteOptions.Handle, true); - _lowPriorityAndNoWalWrite = CreateWriteOptions(dbConfig); + _lowPriorityAndNoWalWrite = new WriteOptions(); + _lowPriorityAndNoWalWrite.SetSync(dbConfig.WriteAheadLogSync); _lowPriorityAndNoWalWrite.DisableWal(1); Native.Instance.rocksdb_writeoptions_set_low_pri(_lowPriorityAndNoWalWrite.Handle, true); @@ -434,14 +423,17 @@ protected virtual void BuildOptions(PerTableDbConfig dbConfig, Options opt _readAheadReadOptions.SetReadaheadSize(dbConfig.ReadAheadSize ?? (ulong)256.KiB()); _readAheadReadOptions.SetTailing(true); } - } - private WriteOptions CreateWriteOptions(PerTableDbConfig dbConfig) - { - WriteOptions options = new(); - // potential fix for corruption on hard process termination, may cause performance degradation - options.SetSync(dbConfig.WriteAheadLogSync); - return options; + if (dbConfig.DisableCompression == true) + { + options.SetCompression(Compression.No); + } + + if (dbConfig.EnableDbStatistics) + { + options.EnableStatistics(); + } + options.SetStatsDumpPeriodSec(dbConfig.StatsDumpPeriodSec); } public byte[]? this[ReadOnlySpan key] @@ -784,26 +776,20 @@ public IBatch StartBatch() internal class RocksDbBatch : IBatch { + private const int InitialBatchSize = 300; + private static readonly int MaxCached = Environment.ProcessorCount; + + private static ConcurrentQueue> s_cache = new(); + private readonly DbOnTheRocks _dbOnTheRocks; - private WriteBatch _rocksBatch; private WriteFlags _writeFlags = WriteFlags.None; private bool _isDisposed; - [ThreadStatic] - private static WriteBatch? _reusableWriteBatch; - - /// - /// Because of how rocksdb parallelize writes, a large write batch can stall other new concurrent writes, so - /// we writes the batch in smaller batches. This removes atomicity so its only turned on when NoWAL flag is on. - /// It does not work as well as just turning on unordered_write, but Snapshot and Iterator can still works. - /// - private const int MaxWritesOnNoWal = 128; - private int _writeCount; + private SpanDictionary _batchData = CreateOrGetFromCache(); public RocksDbBatch(DbOnTheRocks dbOnTheRocks) { _dbOnTheRocks = dbOnTheRocks; - _rocksBatch = CreateWriteBatch(); if (_dbOnTheRocks._isDisposing) { @@ -811,28 +797,6 @@ public RocksDbBatch(DbOnTheRocks dbOnTheRocks) } } - private static WriteBatch CreateWriteBatch() - { - if (_reusableWriteBatch == null) return new WriteBatch(); - - WriteBatch batch = _reusableWriteBatch; - _reusableWriteBatch = null; - return batch; - } - - private static void ReturnWriteBatch(WriteBatch batch) - { - Native.Instance.rocksdb_writebatch_data(batch.Handle, out UIntPtr size); - if (size > (uint)16.KiB() || _reusableWriteBatch != null) - { - batch.Dispose(); - return; - } - - batch.Clear(); - _reusableWriteBatch = batch; - } - public void Dispose() { if (_dbOnTheRocks._isDisposed) @@ -846,11 +810,37 @@ public void Dispose() } _isDisposed = true; + SpanDictionary batchData = _batchData; + // Clear the _batchData reference so is null if Get is called. + _batchData = null!; + if (batchData.Count == 0) + { + // No data to write, skip empty batches + ReturnToCache(batchData); + _dbOnTheRocks._currentBatches.TryRemove(this); + return; + } + try { - _dbOnTheRocks._db.Write(_rocksBatch, _dbOnTheRocks.WriteFlagsToWriteOptions(_writeFlags)); + WriteBatch rocksBatch = new(); + // Sort the batch by key + foreach (var kv in batchData.OrderBy(i => i.Key, Bytes.Comparer)) + { + if (kv.Value.data is null) + { + rocksBatch.Delete(kv.Key, kv.Value.cf); + } + else + { + rocksBatch.Put(kv.Key, kv.Value.data, kv.Value.cf); + } + } + ReturnToCache(batchData); + + _dbOnTheRocks._db.Write(rocksBatch, _dbOnTheRocks.WriteFlagsToWriteOptions(_writeFlags)); _dbOnTheRocks._currentBatches.TryRemove(this); - ReturnWriteBatch(_rocksBatch); + rocksBatch.Dispose(); } catch (RocksDbSharpException e) { @@ -862,9 +852,7 @@ public void Dispose() public byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) { // Not checking _isDisposing here as for some reason, sometimes is is read after dispose - // Note: The batch itself is not checked. Will need to use WriteBatchWithIndex to do that, but that will - // hurt perf. - return _dbOnTheRocks.Get(key, flags); + return _batchData?.TryGetValue(key, out var value) ?? false ? value.data : _dbOnTheRocks.Get(key, flags); } public void Delete(ReadOnlySpan key, ColumnFamilyHandle? cf = null) @@ -874,20 +862,17 @@ public void Delete(ReadOnlySpan key, ColumnFamilyHandle? cf = null) throw new ObjectDisposedException($"Attempted to write a disposed batch {_dbOnTheRocks.Name}"); } - _rocksBatch.Delete(key, cf); + _batchData[key] = (null, cf); } - public void Set(ReadOnlySpan key, byte[]? value, ColumnFamilyHandle? cf = null, WriteFlags flags = WriteFlags.None) + public void Set(ReadOnlySpan key, byte[]? value, ColumnFamilyHandle? cf = null) { if (_isDisposed) { throw new ObjectDisposedException($"Attempted to write a disposed batch {_dbOnTheRocks.Name}"); } - _rocksBatch.Put(key, value, cf); - _writeFlags = flags; - - if ((flags & WriteFlags.DisableWAL) != 0) FlushOnTooManyWrites(); + _batchData[key] = (value, cf); } public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteFlags.None) @@ -897,28 +882,28 @@ public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteF throw new ObjectDisposedException($"Attempted to write a disposed batch {_dbOnTheRocks.Name}"); } - _rocksBatch.Put(key, value); - _writeFlags = flags; + _batchData[key] = (value, null); - if ((flags & WriteFlags.DisableWAL) != 0) FlushOnTooManyWrites(); + _writeFlags = flags; } - private void FlushOnTooManyWrites() + private static SpanDictionary CreateOrGetFromCache() { - if (Interlocked.Increment(ref _writeCount) % MaxWritesOnNoWal != 0) return; - - WriteBatch currentBatch = Interlocked.Exchange(ref _rocksBatch, CreateWriteBatch()); - - try + if (s_cache.TryDequeue(out SpanDictionary? batchData)) { - _dbOnTheRocks._db.Write(currentBatch, _dbOnTheRocks.WriteFlagsToWriteOptions(_writeFlags)); - ReturnWriteBatch(currentBatch); - } - catch (RocksDbSharpException e) - { - _dbOnTheRocks.CreateMarkerIfCorrupt(e); - throw; + return batchData; } + + return new(InitialBatchSize, Bytes.SpanEqualityComparer); + } + + private static void ReturnToCache(SpanDictionary batchData) + { + if (s_cache.Count >= MaxCached) return; + + batchData.Clear(); + batchData.TrimExcess(capacity: InitialBatchSize); + s_cache.Enqueue(batchData); } } @@ -932,11 +917,6 @@ public void Flush() InnerFlush(); } - public void Compact() - { - _db.CompactRange(Keccak.Zero.BytesToArray(), Keccak.MaxValue.BytesToArray()); - } - private void InnerFlush() { try @@ -1076,25 +1056,25 @@ public virtual void Tune(ITunableDb.TuneType type) // smoothens this spike somewhat by not blocking writes while allowing compaction to happen in background // at 1/10th the specified speed (if rate limited). // - // Total writes written on different tune during mainnet sync in TB. - // +-----------------------+-------+-------+-------+-------+-------+---------+ - // | L0FileNumTarget | Total | State | Code | Header| Blocks| Receipts | - // +-----------------------+-------+-------+-------+-------+-------+---------+ - // | Default | 5.055 | 2.27 | 0.242 | 0.123 | 1.14 | 1.280 | - // | WriteBias | 4.962 | 2.12 | 0.049 | 0.132 | 1.14 | 1.080 | - // | HeavyWrite | 3.592 | 1.32 | 0.032 | 0.116 | 1.14 | 0.984 | - // | AggressiveHeavyWrite | 3.029 | 0.92 | 0.024 | 0.118 | 1.14 | 0.827 | - // | DisableCompaction | 2.215 | 0.36 | 0.031 | 0.137 | 1.14 | 0.547 | - // +-----------------------+-------+-------+-------+-------+-------+---------+ + // Read and writes written on different tune during mainnet sync in TB. + // +-----------------------------+----------------+--------------+---------------+---------------+--------------+----------------+---------------------+ + // | L0FileNumTarget | Total (R/W) | State | Code | Header | Blocks | Receipts_Blocks | Receipt_Transactions | + // +-----------------------------+----------------+--------------+---------------+---------------+--------------+----------------+---------------------+ + // | 4 (Default) | 7.853 / 8.41 | 2.58 / 2.78 | 0.104 / 0.107 | 0.133 / 0.141 | 4.34 / 4.58 | 0.502 / 0.593 | 0.194 / 0.209 | + // | 4 (8GB memory hint) | 7.875 / 8.393 | 2.40 / 2.56 | 0.103 / 0.106 | 0.114 / 0.122 | 4.51 / 4.75 | 0.556 / 0.648 | 0.192 / 0.207 | + // | 14 | 7.001 / 7.514 | 2.38 / 2.54 | 0.029 / 0.032 | 0.132 / 0.141 | 4.04 / 4.27 | 0.287 / 0.378 | 0.138 / 0.153 | + // | 64 (WriteBias) | 5.986 / 6.493 | 1.63 / 1.79 | 0.023 / 0.026 | 0.120 / 0.128 | 3.82 / 4.05 | 0.280 / 0.371 | 0.113 / 0.128 | + // | 256 (HeavyWrite) | 4.386 / 4.895 | 1.12 / 1.28 | 0.013 / 0.016 | 0.131 / 0.140 | 2.89 / 3.12 | 0.178 / 0.270 | 0.054 / 0.069 | + // | 1024 (AggressiveHeavyWrite) | 2.942 / 3.452 | 0.60 / 0.76 | 0.006 / 0.009 | 0.133 / 0.142 | 2.01 / 2.24 | 0.171 / 0.263 | 0.022 / 0.038 | + // +-----------------------------+-----------------+--------------+---------------+--------------+--------------+----------------+---------------------+ // Note, in practice on my machine, the reads does not reach the SSD. Read measured from SSD is much lower // than read measured from process. It is likely that most files are cached as I have 128GB of RAM. // Also notice that the heavier the tune, the higher the reads. case ITunableDb.TuneType.WriteBias: - // Keep the same l1 size but apply other adjustment which should increase buffer number and make - // l0 the same size as l1, but keep the LSM the same. This improve flush parallelization, and - // write amplification due to mismatch of l0 and l1 size, but does not reduce compaction from other - // levels. - ApplyOptions(GetHeavyWriteOptions(_perTableDbConfig.MaxBytesForLevelBase / (ulong)8.MiB())); + // The default l1SizeTarget is 256MB, so the compaction is fairly light. But the default options is not very + // efficient for write amplification to conserve memory, so the write amplification reduction is noticeable. + // Does not seems to impact sync performance, might improve sync time slightly if user is IO limited. + ApplyOptions(GetHeavyWriteOptions(64)); break; case ITunableDb.TuneType.HeavyWrite: // Compaction spikes are clear at this point. Will definitely affect attestation performance. @@ -1127,7 +1107,9 @@ public virtual void Tune(ITunableDb.TuneType type) // user config may not be able to handle this. // With all those cons, this result in the minimum write amplification possible via tweaking compaction // without changing memory budget. Not recommended for mainnet, unless you are very desperate. - ApplyOptions(GetDisableCompactionOptions()); + IDictionary heavyWriteOption = GetHeavyWriteOptions(2048); + heavyWriteOption["disable_auto_compactions"] = "true"; + ApplyOptions(heavyWriteOption); break; case ITunableDb.TuneType.EnableBlobFiles: ApplyOptions(GetBlobFilesOptions()); @@ -1151,17 +1133,15 @@ private IDictionary GetStandardOptions() // Defaults are from rocksdb source code return new Dictionary() { - { "write_buffer_size", _perTableDbConfig.WriteBufferSize.ToString() }, - { "max_write_buffer_number", _perTableDbConfig.WriteBufferNumber.ToString() }, - { "level0_file_num_compaction_trigger", 4.ToString() }, { "level0_slowdown_writes_trigger", 20.ToString() }, { "level0_stop_writes_trigger", 36.ToString() }, - { "max_bytes_for_level_base", _perTableDbConfig.MaxBytesForLevelBase.ToString() }, + { "max_bytes_for_level_base", 256.MiB().ToString() }, { "target_file_size_base", 64.MiB().ToString() }, { "disable_auto_compactions", "false" }, + { "write_buffer_size", _perTableDbConfig.WriteBufferSize.ToString() }, { "enable_blob_files", "false" }, { "soft_pending_compaction_bytes_limit", 64.GiB().ToString() }, @@ -1182,25 +1162,17 @@ private IDictionary GetStandardOptions() /// private IDictionary GetHeavyWriteOptions(ulong l0FileNumTarget) { - // Make buffer (probably) smaller so that it does not take too much memory to have many of them. - // More buffer means more parallel flush, but each read have to go through all buffer one by one much like l0 - // but no io, only cpu. - // bufferSize*maxBufferNumber = 128MB, which is the max memory used, which tend to be the case as its now - // stalled by compaction instead of flush. - ulong bufferSize = (ulong)16.MiB(); - ulong maxBufferNumber = 8; - // Guide recommend to have l0 and l1 to be the same size. They have to be compacted together so if l1 is larger, // the extra size in l1 is basically extra rewrites. If l0 is larger... then I don't know why not. Even so, it seems to // always get triggered when l0 size exceed max_bytes_for_level_base even if file num is less than l0FileNumTarget. - ulong l1SizeTarget = l0FileNumTarget * bufferSize; + // The 2 here is MinWriteBufferToMerge. Note, that this does highly depends on the WriteBufferSize as do standard + // config. + ulong l1SizeTarget = l0FileNumTarget * _perTableDbConfig.WriteBufferSize * 2; return new Dictionary() { - { "write_buffer_size", bufferSize.ToString() }, - { "max_write_buffer_number", maxBufferNumber.ToString() }, - { "max_bytes_for_level_base", l1SizeTarget.ToString() }, + { "level0_file_num_compaction_trigger", l0FileNumTarget.ToString() }, // Note: If ratelimiter is not specified and if delayed_write_rate is not specified, the default is 16MBps. @@ -1214,21 +1186,6 @@ private IDictionary GetHeavyWriteOptions(ulong l0FileNumTarget) }; } - private IDictionary GetDisableCompactionOptions() - { - IDictionary heavyWriteOption = GetHeavyWriteOptions(2048); - - heavyWriteOption["disable_auto_compactions"] = "true"; - // Increase the size of the write buffer, which reduces the number of l0 file by 4x. This does slows down - // the memtable a little bit. So if you are not write limited, you'll get memtable limited instead. - // This does increase the total memory buffer size, but counterintuitively, this reduces overall memory usage - // as it ran out of bloom filter cache so it need to do actual IO. - heavyWriteOption["write_buffer_size"] = 64.MiB().ToString(); - - return heavyWriteOption; - } - - private IDictionary GetBlobFilesOptions() { // Enable blob files, see: https://rocksdb.org/blog/2021/05/26/integrated-blob-db.html diff --git a/src/Nethermind/Nethermind.Db.Test/DbMetricsUpdaterTests.cs b/src/Nethermind/Nethermind.Db.Test/DbMetricsUpdaterTests.cs index 9907105410e..dc7cc600bed 100644 --- a/src/Nethermind/Nethermind.Db.Test/DbMetricsUpdaterTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/DbMetricsUpdaterTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.IO; using Nethermind.Db.Rocks.Statistics; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs b/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs index 770256d056d..b29e0304284 100644 --- a/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs @@ -235,24 +235,6 @@ public void Smoke_test() Assert.That(_db[new byte[] { 2, 3, 4 }], Is.EqualTo(new byte[] { 5, 6, 7 })); } - [Test] - public void Smoke_test_large_writes_with_nowal() - { - IBatch batch = _db.StartBatch(); - - for (int i = 0; i < 1000; i++) - { - batch.Set(i.ToBigEndianByteArray(), i.ToBigEndianByteArray(), WriteFlags.DisableWAL); - } - - batch.Dispose(); - - for (int i = 0; i < 1000; i++) - { - _db[i.ToBigEndianByteArray()].Should().BeEquivalentTo(i.ToBigEndianByteArray()); - } - } - [Test] public void Smoke_test_readahead() { diff --git a/src/Nethermind/Nethermind.Db.Test/MemDbTests.cs b/src/Nethermind/Nethermind.Db.Test/MemDbTests.cs index ac6a87ad925..fa61014e164 100644 --- a/src/Nethermind/Nethermind.Db.Test/MemDbTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/MemDbTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using FluentAssertions; +using Nethermind.Core; using Nethermind.Core.Test.Builders; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Db.Test/RocksDbTests.cs b/src/Nethermind/Nethermind.Db.Test/RocksDbTests.cs index 12124fad3bc..a54ef02a3fd 100644 --- a/src/Nethermind/Nethermind.Db.Test/RocksDbTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/RocksDbTests.cs @@ -11,5 +11,5 @@ namespace Nethermind.Db.Test; internal static class RocksDbTests { [Test] - public static void Should_have_required_version() => DbOnTheRocks.GetRocksDbVersion().Should().Be("8.3.2"); + public static void Should_have_required_version() => DbOnTheRocks.GetRocksDbVersion().Should().Be("8.0.0"); } diff --git a/src/Nethermind/Nethermind.Db.Test/Rpc/RpcDbFactoryTests.cs b/src/Nethermind/Nethermind.Db.Test/Rpc/RpcDbFactoryTests.cs index 415289c4550..e291ab82e09 100644 --- a/src/Nethermind/Nethermind.Db.Test/Rpc/RpcDbFactoryTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/Rpc/RpcDbFactoryTests.cs @@ -4,6 +4,7 @@ using System.IO.Abstractions; using FluentAssertions; using Nethermind.Db.FullPruning; +using Nethermind.Db.Rocks; using Nethermind.Db.Rpc; using Nethermind.JsonRpc.Client; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Db.Test/Rpc/RpcDbTests.cs b/src/Nethermind/Nethermind.Db.Test/Rpc/RpcDbTests.cs index 71c7bb09b14..a4f5d3e851c 100644 --- a/src/Nethermind/Nethermind.Db.Test/Rpc/RpcDbTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/Rpc/RpcDbTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Linq; using FluentAssertions; using Nethermind.Core.Extensions; using Nethermind.Db.Rpc; diff --git a/src/Nethermind/Nethermind.Db.Test/SimpleFilePublicKeyDbTests.cs b/src/Nethermind/Nethermind.Db.Test/SimpleFilePublicKeyDbTests.cs index 09bcd6ac1e7..ccc29d05402 100644 --- a/src/Nethermind/Nethermind.Db.Test/SimpleFilePublicKeyDbTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/SimpleFilePublicKeyDbTests.cs @@ -6,6 +6,7 @@ using System.IO; using Nethermind.Core.Extensions; +using Nethermind.Core.Test.Builders; using Nethermind.Core.Test.IO; using Nethermind.Logging; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Db/DbExtensions.cs b/src/Nethermind/Nethermind.Db/DbExtensions.cs index efbd19c61f3..28635fa22f4 100644 --- a/src/Nethermind/Nethermind.Db/DbExtensions.cs +++ b/src/Nethermind/Nethermind.Db/DbExtensions.cs @@ -19,9 +19,9 @@ public static ReadOnlyDb AsReadOnly(this IDb db, bool createInMemoryWriteStore) return new(db, createInMemoryWriteStore); } - public static void Set(this IDb db, Keccak key, byte[] value, WriteFlags writeFlags = WriteFlags.None) + public static void Set(this IDb db, Keccak key, byte[] value) { - db.Set(key.Bytes, value, writeFlags); + db[key.Bytes] = value; } public static byte[]? Get(this IDb db, Keccak key) diff --git a/src/Nethermind/Nethermind.Db/FullPruning/FullPruningInnerDbFactory.cs b/src/Nethermind/Nethermind.Db/FullPruning/FullPruningInnerDbFactory.cs index d0d767c833b..b8f730bc939 100644 --- a/src/Nethermind/Nethermind.Db/FullPruning/FullPruningInnerDbFactory.cs +++ b/src/Nethermind/Nethermind.Db/FullPruning/FullPruningInnerDbFactory.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.IO; using System.IO.Abstractions; using System.Linq; diff --git a/src/Nethermind/Nethermind.Db/FullPruningCompletionBehavior.cs b/src/Nethermind/Nethermind.Db/FullPruningCompletionBehavior.cs index 36b0b5e4706..aeff2dc2d97 100755 --- a/src/Nethermind/Nethermind.Db/FullPruningCompletionBehavior.cs +++ b/src/Nethermind/Nethermind.Db/FullPruningCompletionBehavior.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; + namespace Nethermind.Db { /// diff --git a/src/Nethermind/Nethermind.Db/IDb.cs b/src/Nethermind/Nethermind.Db/IDb.cs index 0c8b41c3302..e24c8ac95a0 100644 --- a/src/Nethermind/Nethermind.Db/IDb.cs +++ b/src/Nethermind/Nethermind.Db/IDb.cs @@ -21,8 +21,8 @@ public interface IDb : IKeyValueStoreWithBatching, IDisposable long GetMemtableSize(); void Flush(); + void Clear(); - void Compact() { } public IReadOnlyDb CreateReadOnly(bool createInMemWriteStore) => new ReadOnlyDb(this, createInMemWriteStore); } diff --git a/src/Nethermind/Nethermind.Db/IPruningConfig.cs b/src/Nethermind/Nethermind.Db/IPruningConfig.cs index 39019b4df88..dc297eb701e 100755 --- a/src/Nethermind/Nethermind.Db/IPruningConfig.cs +++ b/src/Nethermind/Nethermind.Db/IPruningConfig.cs @@ -37,16 +37,16 @@ public interface IPruningConfig : IConfig FullPruningTrigger FullPruningTrigger { get; set; } [ConfigItem( - Description = "'Full' pruning: Defines how many parallel tasks and potentially used threads can be created by full pruning. -1 - number of logical processors, 0 - 25% of logical processors, 1 - full pruning will run on single thread. " + - "Recommended value depends on the type of the node. If the node needs to be responsive (its RPC or Validator node) then recommended value is the default value or below is recommended. " + - "If the node doesn't have much other responsibilities but needs to be reliably be able to follow the chain without any delays and produce live logs - the default value or above is recommended. " + - "If the node doesn't have to be responsive, has very fast I/O (like NVME) and the shortest pruning time is to be achieved, this can be set to the number of logical processors (-1).", + Description = "'Full' pruning: Defines how many parallel tasks and potentially used threads can be created by full pruning. 0 - number of logical processors, 1 - full pruning will run on single thread. " + + "Recommended value depends on the type of the node. If the node needs to be responsive (its RPC or Validator node) then recommended value is below the number of logical processors. " + + "If the node doesn't have much other responsibilities but needs to be reliably be able to follow the chain without any delays and produce live logs - the default value is recommended. " + + "If the node doesn't have to be responsive, has very fast I/O (like NVME) and the shortest pruning time is to be achieved, this can be set to 2-3x of the number of logical processors.", DefaultValue = "0")] int FullPruningMaxDegreeOfParallelism { get; set; } [ConfigItem( Description = "Set the memory budget used for the trie visit. Increasing this significantly reduces read iops requirement at expense of RAM. Default depend on network. Set to 0 to disable.", - DefaultValue = "4000")] + DefaultValue = "0")] int FullPruningMemoryBudgetMb { get; set; } [ConfigItem( diff --git a/src/Nethermind/Nethermind.Db/MemDb.cs b/src/Nethermind/Nethermind.Db/MemDb.cs index 3b9e2af0147..bf8cbadcc03 100644 --- a/src/Nethermind/Nethermind.Db/MemDb.cs +++ b/src/Nethermind/Nethermind.Db/MemDb.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using Nethermind.Core; +using Nethermind.Core.Attributes; using Nethermind.Core.Collections; using Nethermind.Core.Extensions; @@ -77,7 +78,7 @@ public bool KeyExists(ReadOnlySpan key) public IDb Innermost => this; - public virtual void Flush() + public void Flush() { } diff --git a/src/Nethermind/Nethermind.Db/PruningConfig.cs b/src/Nethermind/Nethermind.Db/PruningConfig.cs index 102720f2a6c..5d894a611af 100755 --- a/src/Nethermind/Nethermind.Db/PruningConfig.cs +++ b/src/Nethermind/Nethermind.Db/PruningConfig.cs @@ -26,8 +26,8 @@ public bool Enabled public long PersistenceInterval { get; set; } = 8192; public long FullPruningThresholdMb { get; set; } = 256000; public FullPruningTrigger FullPruningTrigger { get; set; } = FullPruningTrigger.Manual; - public int FullPruningMaxDegreeOfParallelism { get; set; } - public int FullPruningMemoryBudgetMb { get; set; } = 4000; + public int FullPruningMaxDegreeOfParallelism { get; set; } = 0; + public int FullPruningMemoryBudgetMb { get; set; } = 0; public bool FullPruningDisableLowPriorityWrites { get; set; } = false; public int FullPruningMinimumDelayHours { get; set; } = 240; public FullPruningCompletionBehavior FullPruningCompletionBehavior { get; set; } = FullPruningCompletionBehavior.None; diff --git a/src/Nethermind/Nethermind.Db/SimpleFilePublicKeyDb.cs b/src/Nethermind/Nethermind.Db/SimpleFilePublicKeyDb.cs index 1d367ee696b..4e607a4a745 100644 --- a/src/Nethermind/Nethermind.Db/SimpleFilePublicKeyDb.cs +++ b/src/Nethermind/Nethermind.Db/SimpleFilePublicKeyDb.cs @@ -3,6 +3,7 @@ using System; using System.Buffers; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -21,7 +22,7 @@ public class SimpleFilePublicKeyDb : IFullDb { public const string DbFileName = "SimpleFileDb.db"; - private readonly ILogger _logger; + private ILogger _logger; private bool _hasPendingChanges; private SpanConcurrentDictionary _cache; @@ -121,25 +122,15 @@ private void CommitBatch() if (_logger.IsDebug) _logger.Debug($"Saving data in {DbPath} | backup stored in {backup.BackupPath}"); try { - using StreamWriter fileWriter = new(DbPath); - StringBuilder lineBuilder = new(400); // longest found in practice was 320, adding some headroom - using StringWriter lineWriter = new(lineBuilder); - foreach ((byte[] key, byte[]? value) in snapshot) + using StreamWriter streamWriter = new(DbPath); + foreach ((byte[] key, byte[] value) in snapshot) { - lineBuilder.Clear(); - if (value is not null) { - key.StreamHex(lineWriter); - lineWriter.Write(','); - value.StreamHex(lineWriter); - lineWriter.WriteLine(); - lineWriter.Flush(); - - foreach (ReadOnlyMemory chunk in lineBuilder.GetChunks()) - { - fileWriter.Write(chunk.Span); - } + key.StreamHex(streamWriter); + streamWriter.Write(','); + value.StreamHex(streamWriter); + streamWriter.WriteLine(); } } } @@ -277,7 +268,7 @@ private void LoadData() ArrayPool.Shared.Return(rentedBuffer); if (bytes.Length > 0) { - if (_logger.IsWarn) _logger.Warn($"Malformed {Name}. Ignoring..."); + ThrowInvalidDataException(); } void RecordError(Span data) @@ -285,9 +276,14 @@ void RecordError(Span data) if (_logger.IsError) { string line = Encoding.UTF8.GetString(data); - if (_logger.IsError) _logger.Error($"Error when loading data from {Name} - expected two items separated by a comma and got '{line}')"); + _logger.Error($"Error when loading data from {Name} - expected two items separated by a comma and got '{line}')"); } } + + static void ThrowInvalidDataException() + { + throw new InvalidDataException("Malformed data"); + } } private byte[] Update(byte[] oldValue, byte[] newValue) diff --git a/src/Nethermind/Nethermind.EthStats.Test/EthStatsClientTests.cs b/src/Nethermind/Nethermind.EthStats.Test/EthStatsClientTests.cs index 2aeb0a231fc..edb8afa94d0 100644 --- a/src/Nethermind/Nethermind.EthStats.Test/EthStatsClientTests.cs +++ b/src/Nethermind/Nethermind.EthStats.Test/EthStatsClientTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Drawing; using Nethermind.EthStats.Clients; using Nethermind.Logging; using NSubstitute; diff --git a/src/Nethermind/Nethermind.EthStats/Configs/EthStatsConfig.cs b/src/Nethermind/Nethermind.EthStats/Configs/EthStatsConfig.cs index 74c5429a757..6fe7dbae153 100644 --- a/src/Nethermind/Nethermind.EthStats/Configs/EthStatsConfig.cs +++ b/src/Nethermind/Nethermind.EthStats/Configs/EthStatsConfig.cs @@ -10,6 +10,5 @@ public class EthStatsConfig : IEthStatsConfig public string? Name { get; set; } = "Nethermind"; public string? Secret { get; set; } = "secret"; public string? Contact { get; set; } = "hello@nethermind.io"; - public int SendInterval { get; set; } = 15; } } diff --git a/src/Nethermind/Nethermind.EthStats/EthStatsPlugin.cs b/src/Nethermind/Nethermind.EthStats/EthStatsPlugin.cs index 4a4b80459ef..da5b4ebe0e5 100644 --- a/src/Nethermind/Nethermind.EthStats/EthStatsPlugin.cs +++ b/src/Nethermind/Nethermind.EthStats/EthStatsPlugin.cs @@ -1,8 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using System.Threading.Tasks; +using Grpc.Core.Logging; using Nethermind.Api; using Nethermind.Api.Extensions; using Nethermind.Core; @@ -65,7 +65,7 @@ public Task Init(INethermindApi nethermindApi) public async Task InitNetworkProtocol() { - (IApiWithNetwork getFromAPi, _) = _api.ForNetwork; + var (getFromAPi, _) = _api.ForNetwork; INetworkConfig networkConfig = _api.Config(); IInitConfig initConfig = _api.Config(); @@ -105,13 +105,12 @@ public async Task InitNetworkProtocol() _ethStatsConfig.Secret!, _ethStatsClient, sender, - getFromAPi.TxPool!, - getFromAPi.BlockTree!, - getFromAPi.PeerManager!, - getFromAPi.GasPriceOracle!, + getFromAPi.TxPool, + getFromAPi.BlockTree, + getFromAPi.PeerManager, + getFromAPi.GasPriceOracle, getFromAPi.EthSyncingInfo!, initConfig.IsMining, - TimeSpan.FromSeconds(_ethStatsConfig.SendInterval), getFromAPi.LogManager); await _ethStatsIntegration.InitAsync(); diff --git a/src/Nethermind/Nethermind.EthStats/IEthStatsConfig.cs b/src/Nethermind/Nethermind.EthStats/IEthStatsConfig.cs index d7328d7bf7c..aec88a48735 100644 --- a/src/Nethermind/Nethermind.EthStats/IEthStatsConfig.cs +++ b/src/Nethermind/Nethermind.EthStats/IEthStatsConfig.cs @@ -13,16 +13,13 @@ public interface IEthStatsConfig : IConfig [ConfigItem(Description = "EthStats server wss://hostname:port/api/", DefaultValue = "ws://localhost:3000/api")] string? Server { get; } - [ConfigItem(Description = "Node name displayed on the given EthStats server.", DefaultValue = "Nethermind")] + [ConfigItem(Description = "Node name displayed on the given ethstats server.", DefaultValue = "Nethermind")] string? Name { get; } - [ConfigItem(Description = "Password for publishing to a given EthStats server.", DefaultValue = "secret")] + [ConfigItem(Description = "Password for publishing to a given ethstats server.", DefaultValue = "secret")] string? Secret { get; } - [ConfigItem(Description = "Node owner contact details displayed on the EthStats page.", DefaultValue = "hello@nethermind.io")] + [ConfigItem(Description = "Node owner contact details displayed on the ethstats page.", DefaultValue = "hello@nethermind.io")] string? Contact { get; } - - [ConfigItem(Description = "Time in seconds between statistics updates", DefaultValue = "15")] - int SendInterval { get; } } } diff --git a/src/Nethermind/Nethermind.EthStats/Integrations/EthStatsIntegration.cs b/src/Nethermind/Nethermind.EthStats/Integrations/EthStatsIntegration.cs index 238d5772f0a..47d4a01c686 100644 --- a/src/Nethermind/Nethermind.EthStats/Integrations/EthStatsIntegration.cs +++ b/src/Nethermind/Nethermind.EthStats/Integrations/EthStatsIntegration.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using System.Runtime.InteropServices; +using System.Threading; using System.Threading.Tasks; using System.Timers; using Nethermind.Blockchain; @@ -45,13 +46,12 @@ public class EthStatsIntegration : IEthStatsIntegration private readonly IGasPriceOracle _gasPriceOracle; private readonly IEthSyncingInfo _ethSyncingInfo; private readonly bool _isMining; - private readonly TimeSpan _sendStatsInterval; - private IWebsocketClient? _websocketClient; private bool _connected; private long _lastBlockProcessedTimestamp; private Timer? _timer; private const int ThrottlingThreshold = 250; + private const int SendStatsInterval = 1000; public EthStatsIntegration( string name, @@ -64,16 +64,15 @@ public EthStatsIntegration( string contact, bool canUpdateHistory, string secret, - IEthStatsClient ethStatsClient, - IMessageSender sender, - ITxPool txPool, - IBlockTree blockTree, - IPeerManager peerManager, - IGasPriceOracle gasPriceOracle, + IEthStatsClient? ethStatsClient, + IMessageSender? sender, + ITxPool? txPool, + IBlockTree? blockTree, + IPeerManager? peerManager, + IGasPriceOracle? gasPriceOracle, IEthSyncingInfo ethSyncingInfo, bool isMining, - TimeSpan sendStatsInterval, - ILogManager logManager) + ILogManager? logManager) { _name = name; _node = node; @@ -85,23 +84,20 @@ public EthStatsIntegration( _contact = contact; _canUpdateHistory = canUpdateHistory; _secret = secret; - _ethStatsClient = ethStatsClient; - _sender = sender; - _txPool = txPool; - _blockTree = blockTree; - _peerManager = peerManager; - _gasPriceOracle = gasPriceOracle; - _ethSyncingInfo = ethSyncingInfo; + _ethStatsClient = ethStatsClient ?? throw new ArgumentNullException(nameof(ethStatsClient)); + _sender = sender ?? throw new ArgumentNullException(nameof(sender)); + _txPool = txPool ?? throw new ArgumentNullException(nameof(txPool)); + _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); + _peerManager = peerManager ?? throw new ArgumentNullException(nameof(peerManager)); + _gasPriceOracle = gasPriceOracle ?? throw new ArgumentNullException(nameof(gasPriceOracle)); + _ethSyncingInfo = ethSyncingInfo ?? throw new ArgumentNullException(nameof(ethSyncingInfo)); _isMining = isMining; - _sendStatsInterval = sendStatsInterval > TimeSpan.Zero - ? sendStatsInterval - : throw new ArgumentOutOfRangeException(nameof(sendStatsInterval)); - _logger = logManager.GetClassLogger(); + _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); } public async Task InitAsync() { - _timer = new Timer { Interval = _sendStatsInterval.TotalMilliseconds }; + _timer = new Timer { Interval = SendStatsInterval }; _timer.Elapsed += TimerOnElapsed; _blockTree.NewHeadBlock += BlockTreeOnNewHeadBlock; _websocketClient = await _ethStatsClient.InitAsync(); diff --git a/src/Nethermind/Nethermind.EthStats/Messages/Models/Stats.cs b/src/Nethermind/Nethermind.EthStats/Messages/Models/Stats.cs index bc0b233dbbb..5aa8e273f10 100644 --- a/src/Nethermind/Nethermind.EthStats/Messages/Models/Stats.cs +++ b/src/Nethermind/Nethermind.EthStats/Messages/Models/Stats.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Int256; + namespace Nethermind.EthStats.Messages.Models { public class Stats diff --git a/src/Nethermind/Nethermind.Ethash.Test/DifficultyCalculatorTests.cs b/src/Nethermind/Nethermind.Ethash.Test/DifficultyCalculatorTests.cs index 5266141b0bc..e35c19c4ba3 100644 --- a/src/Nethermind/Nethermind.Ethash.Test/DifficultyCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Ethash.Test/DifficultyCalculatorTests.cs @@ -4,7 +4,9 @@ using Nethermind.Consensus.Ethash; using Nethermind.Core.Specs; using Nethermind.Int256; +using Nethermind.Specs; using Nethermind.Specs.Forks; +using Nethermind.Specs.Test; using NUnit.Framework; using NSubstitute; using Nethermind.Core; diff --git a/src/Nethermind/Nethermind.EthereumTests.Benchmark/EthereumTests.cs b/src/Nethermind/Nethermind.EthereumTests.Benchmark/EthereumTests.cs index b51f3ace548..809b729f40b 100644 --- a/src/Nethermind/Nethermind.EthereumTests.Benchmark/EthereumTests.cs +++ b/src/Nethermind/Nethermind.EthereumTests.Benchmark/EthereumTests.cs @@ -1,10 +1,14 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.IO; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Engines; +using BenchmarkDotNet.Jobs; using Ethereum.Test.Base; +using Nethermind.Evm; namespace Nethermind.EthereumTests.Benchmark { diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs index 1a46d8e9d58..4eaddfd55df 100644 --- a/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs +++ b/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs @@ -65,7 +65,7 @@ public void GlobalSetup() [Benchmark] public void ExecuteCode() { - _virtualMachine.Run(_evmState, _stateProvider, _txTracer); + _virtualMachine.Run(_evmState, _stateProvider, _txTracer); _stateProvider.Reset(); } } diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/EvmStackBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/EvmStackBenchmarks.cs index 2825bb7e5a8..6aafb6962b4 100644 --- a/src/Nethermind/Nethermind.Evm.Benchmark/EvmStackBenchmarks.cs +++ b/src/Nethermind/Nethermind.Evm.Benchmark/EvmStackBenchmarks.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Evm.Tracing; using Nethermind.Int256; @@ -30,7 +31,7 @@ public void GlobalSetup() [ArgumentsSource(nameof(ValueSource))] public UInt256 Uint256(UInt256 v) { - EvmStack stack = new(_stack.AsSpan(), 0, NullTxTracer.Instance); + EvmStack stack = new(_stack.AsSpan(), 0, NullTxTracer.Instance); stack.PushUInt256(in v); stack.PopUInt256(out UInt256 value); @@ -51,7 +52,7 @@ public UInt256 Uint256(UInt256 v) [ArgumentsSource(nameof(ValueSource))] public Int256.Int256 Int256(UInt256 v) { - EvmStack stack = new(_stack.AsSpan(), 0, NullTxTracer.Instance); + EvmStack stack = new(_stack.AsSpan(), 0, NullTxTracer.Instance); stack.PushSignedInt256(new Int256.Int256(v)); stack.PopSignedInt256(out Int256.Int256 value); @@ -71,7 +72,7 @@ public Int256.Int256 Int256(UInt256 v) [Benchmark(OperationsPerInvoke = 4)] public byte Byte() { - EvmStack stack = new(_stack.AsSpan(), 0, NullTxTracer.Instance); + EvmStack stack = new(_stack.AsSpan(), 0, NullTxTracer.Instance); byte b = 1; @@ -93,7 +94,7 @@ public byte Byte() [Benchmark(OperationsPerInvoke = 4)] public void PushZero() { - EvmStack stack = new(_stack.AsSpan(), 0, NullTxTracer.Instance); + EvmStack stack = new(_stack.AsSpan(), 0, NullTxTracer.Instance); stack.PushZero(); stack.PushZero(); @@ -104,7 +105,7 @@ public void PushZero() [Benchmark(OperationsPerInvoke = 4)] public void PushOne() { - EvmStack stack = new(_stack.AsSpan(), 0, NullTxTracer.Instance); + EvmStack stack = new(_stack.AsSpan(), 0, NullTxTracer.Instance); stack.PushOne(); stack.PushOne(); @@ -115,7 +116,7 @@ public void PushOne() [Benchmark(OperationsPerInvoke = 4)] public void Swap() { - EvmStack stack = new(_stack.AsSpan(), 2, NullTxTracer.Instance); + EvmStack stack = new(_stack.AsSpan(), 2, NullTxTracer.Instance); stack.Swap(2); stack.Swap(2); @@ -126,7 +127,7 @@ public void Swap() [Benchmark(OperationsPerInvoke = 4)] public void Dup() { - EvmStack stack = new(_stack.AsSpan(), 1, NullTxTracer.Instance); + EvmStack stack = new(_stack.AsSpan(), 1, NullTxTracer.Instance); stack.Dup(1); stack.Dup(1); diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs b/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs index 90c6604b0f5..fa84e6b624f 100644 --- a/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs +++ b/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs @@ -96,7 +96,7 @@ public void GlobalSetup() [Benchmark] public void ExecuteCode() { - _virtualMachine.Run(_evmState, _stateProvider, _txTracer); + _virtualMachine.Run(_evmState, _stateProvider, _txTracer); _stateProvider.Reset(); } diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs index 282adcba05d..5d5254ed069 100644 --- a/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs +++ b/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs @@ -104,17 +104,10 @@ public void GlobalSetup() _evmState = new EvmState(100_000_000L, _environment, ExecutionType.Transaction, true, _stateProvider.TakeSnapshot(), false); } - [Benchmark(Baseline = true)] - public void ExecuteCode() - { - _virtualMachine.Run(_evmState, _stateProvider, _txTracer); - _stateProvider.Reset(); - } - [Benchmark] - public void ExecuteCodeNoTracing() + public void ExecuteCode() { - _virtualMachine.Run(_evmState, _stateProvider, _txTracer); + _virtualMachine.Run(_evmState, _stateProvider, _txTracer); _stateProvider.Reset(); } diff --git a/src/Nethermind/Nethermind.Evm.Test/BeaconParentBlockRootPrecompileTests.cs b/src/Nethermind/Nethermind.Evm.Test/BeaconParentBlockRootPrecompileTests.cs deleted file mode 100644 index 206a2059c2f..00000000000 --- a/src/Nethermind/Nethermind.Evm.Test/BeaconParentBlockRootPrecompileTests.cs +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using Nethermind.Core; -using Nethermind.Core.Extensions; -using Nethermind.Core.Specs; -using Nethermind.Core.Test.Builders; -using Nethermind.Int256; -using Nethermind.Specs; -using Nethermind.Specs.Forks; -using Nethermind.State; -using NUnit.Framework; -using Nethermind.Core.Crypto; -using Nethermind.Core.Test.Blockchain; - -namespace Nethermind.Evm.Test; - -public class Eip4788Tests : TestBlockchain -{ - private ISpecProvider specProvider = new TestSpecProvider(Cancun.Instance); - protected static IEnumerable<(IReleaseSpec Spec, bool ShouldFail)> BeaconBlockRootGetPayloadV3ForDifferentSpecTestSource() - { - yield return (Shanghai.Instance, true); - yield return (Cancun.Instance, false); - } - - [TestCaseSource(nameof(BeaconBlockRootGetPayloadV3ForDifferentSpecTestSource))] - public void BeaconBlockRoot_Is_Stored_Correctly_and_Only_Valid_PostCancun((IReleaseSpec Spec, bool ShouldFail) testCase) - { - // empty placeholder for tests - } - - Block CreateBlock(IWorldState testState, IReleaseSpec spec) - { - Keccak parentBeaconBlockRoot = TestItem.KeccakG; - - byte[] bytecode = Prepare - .EvmCode - .TIMESTAMP() - .MSTORE(0) - .CALL(100.Ether(), Address.FromNumber(0x0B), 0, 0, 32, 32, 32) - .MLOAD(32) - .EQ(new UInt256(parentBeaconBlockRoot.Bytes, true)) - .JUMPI(0x57) - .INVALID() - .JUMPDEST() - .STOP() - .Done; - - testState.InsertCode(TestBlockchain.AccountA, bytecode, specProvider.GenesisSpec); - Transaction tx = Core.Test.Builders.Build.A.Transaction - .WithGasLimit(1_000_000) - .WithGasPrice(1) - .WithValue(1) - .WithSenderAddress(TestBlockchain.AccountB) - .WithNonce(testState.GetNonce(TestBlockchain.AccountB)) - .To(TestBlockchain.AccountA) - .TestObject; - - testState.Commit(spec); - testState.CommitTree(0); - testState.RecalculateStateRoot(); - BlockBuilder blockBuilder = Core.Test.Builders.Build.A.Block.Genesis - .WithDifficulty(1) - .WithTotalDifficulty(1L) - .WithTransactions(tx) - .WithPostMergeFlag(true); - - if (spec.IsBeaconBlockRootAvailable) - { - blockBuilder.WithParentBeaconBlockRoot(parentBeaconBlockRoot); - } - - return blockBuilder.TestObject; - } -} diff --git a/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs b/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs index 7c6ffef480b..490162e882c 100644 --- a/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs @@ -3,13 +3,26 @@ using FluentAssertions; using Nethermind.Core.Extensions; +using Nethermind.Core.Specs; +using Nethermind.Specs; using Nethermind.Core.Test.Builders; using NUnit.Framework; using Nethermind.Core; +using System.Collections; using System.Collections.Generic; +using Nethermind.Evm; +using System.Runtime.ConstrainedExecution; +using Nethermind.Core.Test; +using FluentAssertions.Execution; using System.Reflection; using System.Linq; +using System.Reflection.Emit; using Nethermind.Int256; +using System.Reflection.Metadata; +using FastEnumUtility; +using System; +using System.Text.RegularExpressions; +using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; namespace Nethermind.Evm.Test { @@ -99,6 +112,8 @@ public static IEnumerable opcodes_with_0_arg() Instruction.PC, Instruction.JUMPDEST, Instruction.MSIZE, + Instruction.BEGINSUB, + Instruction.RETURNSUB, Instruction.INVALID, Instruction.SWAP1, Instruction.SWAP5, Instruction.SWAP9 , Instruction.SWAP13, @@ -157,7 +172,8 @@ public static IEnumerable opcodes_with_1_arg() Instruction.JUMP, Instruction.SLOAD, Instruction.TLOAD, - Instruction.MLOAD + Instruction.MLOAD, + Instruction.JUMPSUB, }; foreach (Instruction opcode in address_opcodes) @@ -210,6 +226,7 @@ public static IEnumerable opcodes_with_2_arg() Instruction.MSTORE, Instruction.BYTE, Instruction.MSTORE8, + Instruction.TSTORE, Instruction.SSTORE, Instruction.JUMPI }; @@ -232,10 +249,11 @@ public static IEnumerable opcodes_with_2_arg() Instruction.AND, Instruction.OR, Instruction.XOR, - Instruction.KECCAK256, + Instruction.SHA3, Instruction.SHL, Instruction.SHR, Instruction.SAR, + Instruction.SHA3, Instruction.RETURN, Instruction.REVERT, diff --git a/src/Nethermind/Nethermind.Evm.Test/CmpTests.cs b/src/Nethermind/Nethermind.Evm.Test/CmpTests.cs index 3d1ef905b80..f1f386fd978 100644 --- a/src/Nethermind/Nethermind.Evm.Test/CmpTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/CmpTests.cs @@ -1,20 +1,35 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Specs; using NUnit.Framework; namespace Nethermind.Evm.Test { + [TestFixture(true)] + [TestFixture(false)] [Parallelizable(ParallelScope.Self)] public class CmpTests : VirtualMachineTestsBase { + private readonly bool _simdDisabled; protected override long BlockNumber => MainnetSpecProvider.ConstantinopleFixBlockNumber; + public CmpTests(bool simdDisabled) + { + _simdDisabled = simdDisabled; + } + [Test] public void Gt() { + if (_simdDisabled) + { + Machine.DisableSimdInstructions(); + } + byte[] a = Bytes.FromHexString("0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0ff"); byte[] b = Bytes.FromHexString("0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); byte[] result = Bytes.FromHexString("0x0000000000000000000000000000000000000000000000000000000000000000"); @@ -34,6 +49,11 @@ public void Gt() [Test] public void Lt() { + if (_simdDisabled) + { + Machine.DisableSimdInstructions(); + } + byte[] a = Bytes.FromHexString("0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); byte[] b = Bytes.FromHexString("0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0"); byte[] result = Bytes.FromHexString("0x0000000000000000000000000000000000000000000000000000000000000000"); @@ -53,6 +73,11 @@ public void Lt() [Test] public void Eq() { + if (_simdDisabled) + { + Machine.DisableSimdInstructions(); + } + byte[] a = Bytes.FromHexString("0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0"); byte[] b = Bytes.FromHexString("0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); byte[] result = Bytes.FromHexString("0x0000000000000000000000000000000000000000000000000000000000000000"); diff --git a/src/Nethermind/Nethermind.Evm.Test/CodeAnalysis/CodeInfoTests.cs b/src/Nethermind/Nethermind.Evm.Test/CodeAnalysis/CodeInfoTests.cs index c2cf0817de1..fd126d0f974 100644 --- a/src/Nethermind/Nethermind.Evm.Test/CodeAnalysis/CodeInfoTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/CodeAnalysis/CodeInfoTests.cs @@ -5,6 +5,7 @@ using System.Reflection; using FluentAssertions; using Nethermind.Evm.CodeAnalysis; +using NuGet.Frameworks; using NUnit.Framework; namespace Nethermind.Evm.Test.CodeAnalysis diff --git a/src/Nethermind/Nethermind.Evm.Test/CoinbaseTests.cs b/src/Nethermind/Nethermind.Evm.Test/CoinbaseTests.cs index 1bfe7c2aee7..fbead389dd6 100644 --- a/src/Nethermind/Nethermind.Evm.Test/CoinbaseTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/CoinbaseTests.cs @@ -5,7 +5,6 @@ using Nethermind.Specs; using Nethermind.Core.Test.Builders; using NUnit.Framework; -using Nethermind.Core.Specs; namespace Nethermind.Evm.Test { @@ -16,10 +15,10 @@ public class CoinbaseTests : VirtualMachineTestsBase private bool _setAuthor; - protected override Block BuildBlock(ForkActivation activation, SenderRecipientAndMiner senderRecipientAndMiner, Transaction transaction, long blockGasLimit = DefaultBlockGasLimit, ulong exessBlobGas = 0) + protected override Block BuildBlock(long blockNumber, SenderRecipientAndMiner senderRecipientAndMiner, Transaction transaction, long blockGasLimit = DefaultBlockGasLimit, ulong timestamp = 0) { senderRecipientAndMiner ??= new SenderRecipientAndMiner(); - Block block = base.BuildBlock(activation, senderRecipientAndMiner, transaction, blockGasLimit); + Block block = base.BuildBlock(blockNumber, senderRecipientAndMiner, transaction, blockGasLimit, timestamp); if (_setAuthor) block.Header.Author = TestItem.AddressC; block.Header.Beneficiary = senderRecipientAndMiner.Recipient; return block; diff --git a/src/Nethermind/Nethermind.Evm.Test/DataGasCalculatorTests.cs b/src/Nethermind/Nethermind.Evm.Test/DataGasCalculatorTests.cs index a33c084b2ea..901fd7abae2 100644 --- a/src/Nethermind/Nethermind.Evm.Test/DataGasCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/DataGasCalculatorTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; @@ -12,18 +13,18 @@ namespace Nethermind.Evm.Test; [TestFixture] -public class BlobGasCalculatorTests +public class DataGasCalculatorTests { - [TestCaseSource(nameof(ExcessBlobGasTestCaseSource))] - public void Excess_blob_gas_is_calculated_properly((ulong parentExcessBlobGas, int parentBlobsCount, ulong expectedExcessBlobGas) testCase) + [TestCaseSource(nameof(ExcessDataGasTestCaseSource))] + public void Excess_data_gas_is_calculated_properly((ulong parentExcessDataGas, int parentBlobsCount, ulong expectedExcessDataGas) testCase) { void Test(IReleaseSpec spec, bool areBlobsEnabled) { BlockHeader parentHeader = Build.A.BlockHeader - .WithBlobGasUsed(BlobGasCalculator.CalculateBlobGas(testCase.parentBlobsCount)) - .WithExcessBlobGas(testCase.parentExcessBlobGas).TestObject; - - Assert.That(BlobGasCalculator.CalculateExcessBlobGas(parentHeader, spec), Is.EqualTo(areBlobsEnabled ? testCase.expectedExcessBlobGas : null)); + .WithDataGasUsed(DataGasCalculator.CalculateDataGas(testCase.parentBlobsCount)) + .WithExcessDataGas(testCase.parentExcessDataGas).TestObject; + DataGasCalculator.CalculateExcessDataGas(parentHeader, spec).Should() + .Be(areBlobsEnabled ? testCase.expectedExcessDataGas : null); } Test(Homestead.Instance, false); @@ -41,53 +42,38 @@ void Test(IReleaseSpec spec, bool areBlobsEnabled) Test(Cancun.Instance, true); } - [TestCaseSource(nameof(BlobGasCostTestCaseSource))] - public void Blob_gas_price_is_calculated_properly( - (Transaction tx, ulong excessBlobGas, UInt256 expectedCost) testCase) - { - BlockHeader header = Build.A.BlockHeader.WithExcessBlobGas(testCase.excessBlobGas).TestObject; - - bool success = BlobGasCalculator.TryCalculateBlobGasPrice(header, testCase.tx, out UInt256 blobGasPrice); - - Assert.That(success, Is.True); - Assert.That(blobGasPrice, Is.EqualTo(testCase.expectedCost)); - } - - [Test] - public void Blob_gas_price_may_overflow() + [TestCaseSource(nameof(BlobDataGasCostTestCaseSource))] + public void Data_gas_cost_is_calculated_properly( + (Transaction tx, ulong excessDataGas, UInt256 expectedCost) testCase) { - var tx = Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1000).TestObject; - BlockHeader header = Build.A.BlockHeader.WithExcessBlobGas(ulong.MaxValue).TestObject; - - bool success = BlobGasCalculator.TryCalculateBlobGasPrice(header, tx, out UInt256 blobGasPrice); - - Assert.That(success, Is.False); - Assert.That(blobGasPrice, Is.EqualTo(UInt256.MaxValue)); + BlockHeader header = Build.A.BlockHeader.WithExcessDataGas(testCase.excessDataGas).TestObject; + DataGasCalculator.CalculateDataGasPrice(header, testCase.tx).Should() + .Be(testCase.expectedCost); } - public static IEnumerable<(ulong parentExcessBlobGas, int parentBlobsCount, ulong expectedExcessBlobGas)> ExcessBlobGasTestCaseSource() + public static IEnumerable<(ulong parentExcessDataGas, int parentBlobsCount, ulong expectedExcessDataGas)> ExcessDataGasTestCaseSource() { yield return (0, 0, 0); - yield return (0, (int)(Eip4844Constants.TargetBlobGasPerBlock / Eip4844Constants.BlobGasPerBlob) - 1, 0); - yield return (0, (int)(Eip4844Constants.TargetBlobGasPerBlock / Eip4844Constants.BlobGasPerBlob), 0); - yield return (100000, (int)(Eip4844Constants.TargetBlobGasPerBlock / Eip4844Constants.BlobGasPerBlob), 100000); - yield return (0, (int)(Eip4844Constants.TargetBlobGasPerBlock / Eip4844Constants.BlobGasPerBlob) + 1, Eip4844Constants.BlobGasPerBlob * 1); - yield return (Eip4844Constants.TargetBlobGasPerBlock, 1, Eip4844Constants.BlobGasPerBlob * 1); - yield return (Eip4844Constants.TargetBlobGasPerBlock, 0, 0); - yield return (Eip4844Constants.TargetBlobGasPerBlock, 2, Eip4844Constants.BlobGasPerBlob * 2); - yield return (Eip4844Constants.MaxBlobGasPerBlock, 1, Eip4844Constants.TargetBlobGasPerBlock + Eip4844Constants.BlobGasPerBlob * 1); + yield return (0, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob) - 1, 0); + yield return (0, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob), 0); + yield return (100000, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob), 100000); + yield return (0, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob) + 1, Eip4844Constants.DataGasPerBlob * 1); + yield return (Eip4844Constants.TargetDataGasPerBlock, 1, Eip4844Constants.DataGasPerBlob * 1); + yield return (Eip4844Constants.TargetDataGasPerBlock, 0, 0); + yield return (Eip4844Constants.TargetDataGasPerBlock, 2, Eip4844Constants.DataGasPerBlob * 2); + yield return (Eip4844Constants.MaxDataGasPerBlock, 1, Eip4844Constants.TargetDataGasPerBlock + Eip4844Constants.DataGasPerBlob * 1); yield return ( - Eip4844Constants.MaxBlobGasPerBlock, - (int)(Eip4844Constants.TargetBlobGasPerBlock / Eip4844Constants.BlobGasPerBlob), - Eip4844Constants.MaxBlobGasPerBlock); + Eip4844Constants.MaxDataGasPerBlock, + (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob), + Eip4844Constants.MaxDataGasPerBlock); yield return ( - Eip4844Constants.MaxBlobGasPerBlock, - (int)(Eip4844Constants.MaxBlobGasPerBlock / Eip4844Constants.BlobGasPerBlob), - Eip4844Constants.MaxBlobGasPerBlock * 2 - Eip4844Constants.TargetBlobGasPerBlock + Eip4844Constants.MaxDataGasPerBlock, + (int)(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob), + Eip4844Constants.MaxDataGasPerBlock * 2 - Eip4844Constants.TargetDataGasPerBlock ); } - public static IEnumerable<(Transaction tx, ulong excessBlobGas, UInt256 expectedCost)> BlobGasCostTestCaseSource() + public static IEnumerable<(Transaction tx, ulong excessDataGas, UInt256 expectedCost)> BlobDataGasCostTestCaseSource() { yield return (Build.A.Transaction.TestObject, 0, 0); yield return (Build.A.Transaction.TestObject, 1000, 0); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip1014Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip1014Tests.cs index 3c5e26cabdb..cc4bad71381 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip1014Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip1014Tests.cs @@ -9,6 +9,7 @@ using Nethermind.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Evm.Tracing.GethStyle; +using Nethermind.State; using Nethermind.Trie; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip1052Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip1052Tests.cs index 65c160969cf..a809b73296b 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip1052Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip1052Tests.cs @@ -6,11 +6,10 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; +using Nethermind.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Int256; using Nethermind.Evm.Precompiles; -using Nethermind.Specs.Forks; -using Nethermind.Specs.Test; using NUnit.Framework; namespace Nethermind.Evm.Test @@ -18,10 +17,9 @@ namespace Nethermind.Evm.Test [TestFixture] public class Eip1052Tests : VirtualMachineTestsBase { - protected override long BlockNumber => 10000001; + protected override long BlockNumber => RopstenSpecProvider.ConstantinopleBlockNumber; - protected override ISpecProvider SpecProvider => new CustomSpecProvider( - ((ForkActivation)0, Byzantium.Instance), ((ForkActivation)10000001, Constantinople.Instance)); + protected override ISpecProvider SpecProvider => RopstenSpecProvider.Instance; [Test] public void Account_without_code_returns_empty_data_hash() @@ -59,7 +57,7 @@ public void Non_existing_account_returns_0() [Test] public void Non_existing_precompile_returns_0() { - Address precompileAddress = Sha256Precompile.Address; + Address precompileAddress = Sha256Precompile.Instance.Address; Assert.True(precompileAddress.IsPrecompile(Spec)); byte[] code = Prepare.EvmCode @@ -76,7 +74,7 @@ public void Non_existing_precompile_returns_0() [Test] public void Existing_precompile_returns_empty_data_hash() { - Address precompileAddress = Sha256Precompile.Address; + Address precompileAddress = Sha256Precompile.Instance.Address; Assert.True(precompileAddress.IsPrecompile(Spec)); TestState.CreateAccount(precompileAddress, 1.Wei()); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip1108Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip1108Tests.cs index 909e3ea32c9..0d299bb7c8e 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip1108Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip1108Tests.cs @@ -24,7 +24,7 @@ public void Test_add_before_istanbul() { _blockNumberAdjustment = -1; byte[] code = Prepare.EvmCode - .CallWithInput(Bn254AddPrecompile.Address, 1000L, new byte[128]) + .CallWithInput(Bn254AddPrecompile.Instance.Address, 1000L, new byte[128]) .Done; TestAllTracerWithOutput result = Execute(code); Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Success)); @@ -35,7 +35,7 @@ public void Test_add_before_istanbul() public void Test_add_after_istanbul() { byte[] code = Prepare.EvmCode - .CallWithInput(Bn254AddPrecompile.Address, 1000L, new byte[128]) + .CallWithInput(Bn254AddPrecompile.Instance.Address, 1000L, new byte[128]) .Done; TestAllTracerWithOutput result = Execute(code); Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Success)); @@ -47,7 +47,7 @@ public void Test_mul_before_istanbul() { _blockNumberAdjustment = -1; byte[] code = Prepare.EvmCode - .CallWithInput(Bn254MulPrecompile.Address, 50000L, new byte[128]) + .CallWithInput(Bn254MulPrecompile.Instance.Address, 50000L, new byte[128]) .Done; TestAllTracerWithOutput result = Execute(code); Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Success)); @@ -58,7 +58,7 @@ public void Test_mul_before_istanbul() public void Test_mul_after_istanbul() { byte[] code = Prepare.EvmCode - .CallWithInput(Bn254MulPrecompile.Address, 10000L, new byte[128]) + .CallWithInput(Bn254MulPrecompile.Instance.Address, 10000L, new byte[128]) .Done; TestAllTracerWithOutput result = Execute(code); Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Success)); @@ -70,7 +70,7 @@ public void Test_pairing_before_istanbul() { _blockNumberAdjustment = -1; byte[] code = Prepare.EvmCode - .CallWithInput(Bn254PairingPrecompile.Address, 200000L, new byte[192]) + .CallWithInput(Bn254PairingPrecompile.Instance.Address, 200000L, new byte[192]) .Done; TestAllTracerWithOutput result = Execute(BlockNumber, 1000000L, code); Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Success)); @@ -81,7 +81,7 @@ public void Test_pairing_before_istanbul() public void Test_pairing_after_istanbul() { byte[] code = Prepare.EvmCode - .CallWithInput(Bn254PairingPrecompile.Address, 200000L, new byte[192]) + .CallWithInput(Bn254PairingPrecompile.Instance.Address, 200000L, new byte[192]) .Done; TestAllTracerWithOutput result = Execute(BlockNumber, 1000000L, code); Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Success)); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip1153Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip1153Tests.cs index f908d1638a2..a2d702109ba 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip1153Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip1153Tests.cs @@ -1,7 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Core.Specs; using Nethermind.Specs; using Nethermind.Core.Test.Builders; using NUnit.Framework; @@ -42,14 +44,14 @@ public void before_activation_can_not_call_tstore_tload() .StoreDataInTransientStorage(1, 8) .Done; - TestAllTracerWithOutput result = Execute((MainnetSpecProvider.GrayGlacierBlockNumber, MainnetSpecProvider.CancunBlockTimestamp - 1), 100000, code); + TestAllTracerWithOutput result = Execute(MainnetSpecProvider.GrayGlacierBlockNumber, 100000, code, timestamp: MainnetSpecProvider.CancunBlockTimestamp - 1); Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Failure)); code = Prepare.EvmCode .LoadDataFromTransientStorage(1) .Done; - result = Execute((MainnetSpecProvider.GrayGlacierBlockNumber, MainnetSpecProvider.CancunBlockTimestamp - 1), 100000, code); + result = Execute(MainnetSpecProvider.GrayGlacierBlockNumber, 100000, code, timestamp: MainnetSpecProvider.CancunBlockTimestamp - 1); Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Failure)); } @@ -93,7 +95,7 @@ public void transient_storage_performance_test() byte[] code = prepare.Done; stopwatch.Start(); - TestAllTracerWithOutput result = Execute((MainnetSpecProvider.GrayGlacierBlockNumber, Timestamp), blockGasLimit, code, blockGasLimit); + TestAllTracerWithOutput result = Execute(MainnetSpecProvider.GrayGlacierBlockNumber, blockGasLimit, code, blockGasLimit, Timestamp); Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Success)); stopwatch.Stop(); Assert.IsTrue(stopwatch.ElapsedMilliseconds < 5000); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip1283Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip1283Tests.cs index 995cdf9d043..45ebf69d97f 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip1283Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip1283Tests.cs @@ -6,8 +6,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Specs; -using Nethermind.Specs.Forks; -using Nethermind.Specs.Test; +using Nethermind.State; using NUnit.Framework; namespace Nethermind.Evm.Test @@ -15,10 +14,9 @@ namespace Nethermind.Evm.Test [TestFixture] public class Eip1283Tests : VirtualMachineTestsBase { - protected override long BlockNumber => 1; + protected override long BlockNumber => RopstenSpecProvider.ConstantinopleBlockNumber; - protected override ISpecProvider SpecProvider => new CustomSpecProvider( - ((ForkActivation)0, Byzantium.Instance), ((ForkActivation)1, Constantinople.Instance)); + protected override ISpecProvider SpecProvider => RopstenSpecProvider.Instance; [TestCase("0x60006000556000600055", 412, 0, 0)] [TestCase("0x60006000556001600055", 20212, 0, 0)] @@ -41,7 +39,7 @@ public void Test(string codeHex, long gasUsed, long refund, byte originalValue) { TestState.CreateAccount(Recipient, 0); TestState.Set(new StorageCell(Recipient, 0), new[] { originalValue }); - TestState.Commit(MainnetSpecProvider.Instance.GenesisSpec); + TestState.Commit(RopstenSpecProvider.Instance.GenesisSpec); TestAllTracerWithOutput receipt = Execute(Bytes.FromHexString(codeHex)); AssertGas(receipt, gasUsed + GasCostOf.Transaction - Math.Min((gasUsed + GasCostOf.Transaction) / 2, refund)); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip1344Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip1344Tests.cs index 19239265741..03d2c8f76f5 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip1344Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip1344Tests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; using Nethermind.Specs; @@ -86,5 +87,17 @@ public void given_rinkeby_network_chain_id_opcode_puts_expected_value_onto_the_s Test(SpecProvider.ChainId); } } + + private class Ropsten : Eip1344Tests + { + protected override long BlockNumber => RopstenSpecProvider.IstanbulBlockNumber; + protected override ISpecProvider SpecProvider => RopstenSpecProvider.Instance; + + [Test] + public void given_ropsten_network_chain_id_opcode_puts_expected_value_onto_the_stack() + { + Test(SpecProvider.ChainId); + } + } } } diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip145Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip145Tests.cs index 4915bfae94b..9cf508919bf 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip145Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip145Tests.cs @@ -4,8 +4,7 @@ using System; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; -using Nethermind.Specs.Forks; -using Nethermind.Specs.Test; +using Nethermind.Specs; using NUnit.Framework; namespace Nethermind.Evm.Test @@ -13,10 +12,9 @@ namespace Nethermind.Evm.Test [TestFixture] public class Eip145Tests : VirtualMachineTestsBase { - protected override long BlockNumber => 1; + protected override long BlockNumber => RopstenSpecProvider.ConstantinopleBlockNumber; - protected override ISpecProvider SpecProvider => new CustomSpecProvider( - ((ForkActivation)0, Byzantium.Instance), ((ForkActivation)1, Constantinople.Instance)); + protected override ISpecProvider SpecProvider => RopstenSpecProvider.Instance; private void AssertEip145(TestAllTracerWithOutput receipt, string result) { diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip152Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip152Tests.cs index 78d8e701494..067f3c348dc 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip152Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip152Tests.cs @@ -25,7 +25,7 @@ public void TearDown() public void before_istanbul() { _blockNumberAdjustment = -1; - Address precompileAddress = Blake2FPrecompile.Address; + Address precompileAddress = Blake2FPrecompile.Instance.Address; Assert.False(precompileAddress.IsPrecompile(Spec)); } @@ -33,7 +33,7 @@ public void before_istanbul() public void after_istanbul() { byte[] code = Prepare.EvmCode - .CallWithInput(Blake2FPrecompile.Address, 1000L, new byte[InputLength]) + .CallWithInput(Blake2FPrecompile.Instance.Address, 1000L, new byte[InputLength]) .Done; TestAllTracerWithOutput result = Execute(code); Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Success)); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip1884Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip1884Tests.cs index aed97068526..85dc4dd5a27 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip1884Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip1884Tests.cs @@ -2,11 +2,13 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Int256; +using Nethermind.State; using NUnit.Framework; namespace Nethermind.Evm.Test diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip2200Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip2200Tests.cs index f7e749380a7..292ad2b8e03 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip2200Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip2200Tests.cs @@ -6,6 +6,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Specs; +using Nethermind.State; using NUnit.Framework; namespace Nethermind.Evm.Test @@ -13,9 +14,9 @@ namespace Nethermind.Evm.Test [TestFixture] public class Eip2200Tests : VirtualMachineTestsBase { - protected override long BlockNumber => MainnetSpecProvider.IstanbulBlockNumber; + protected override long BlockNumber => RopstenSpecProvider.IstanbulBlockNumber; - protected override ISpecProvider SpecProvider => MainnetSpecProvider.Instance; + protected override ISpecProvider SpecProvider => RopstenSpecProvider.Instance; [TestCase("0x60006000556000600055", 1612, 0, 0)] [TestCase("0x60006000556001600055", 20812, 0, 0)] @@ -38,7 +39,7 @@ public void Test(string codeHex, long gasUsed, long refund, byte originalValue) { TestState.CreateAccount(Recipient, 0); TestState.Set(new StorageCell(Recipient, 0), new[] { originalValue }); - TestState.Commit(MainnetSpecProvider.Instance.GenesisSpec); + TestState.Commit(RopstenSpecProvider.Instance.GenesisSpec); TestAllTracerWithOutput receipt = Execute(Bytes.FromHexString(codeHex)); AssertGas(receipt, gasUsed + GasCostOf.Transaction - Math.Min((gasUsed + GasCostOf.Transaction) / 2, refund)); @@ -66,7 +67,7 @@ public void Test_when_gas_at_stipend(string codeHex, long gasUsed, long refund, { TestState.CreateAccount(Recipient, 0); TestState.Set(new StorageCell(Recipient, 0), new[] { originalValue }); - TestState.Commit(MainnetSpecProvider.Instance.GenesisSpec); + TestState.Commit(RopstenSpecProvider.Instance.GenesisSpec); TestAllTracerWithOutput receipt = Execute(BlockNumber, 21000 + gasUsed + (2300 - 800), Bytes.FromHexString(codeHex)); Assert.That(receipt.StatusCode, Is.EqualTo(outOfGasExpected ? 0 : 1)); @@ -78,7 +79,7 @@ public void Test_when_gas_just_above_stipend(string codeHex, long gasUsed, long { TestState.CreateAccount(Recipient, 0); TestState.Set(new StorageCell(Recipient, 0), new[] { originalValue }); - TestState.Commit(MainnetSpecProvider.Instance.GenesisSpec); + TestState.Commit(RopstenSpecProvider.Instance.GenesisSpec); TestAllTracerWithOutput receipt = Execute(BlockNumber, 21000 + gasUsed + (2301 - 800), Bytes.FromHexString(codeHex)); Assert.That(receipt.StatusCode, Is.EqualTo(1)); @@ -90,7 +91,7 @@ public void Test_when_gas_just_below_stipend(string codeHex, long gasUsed, long { TestState.CreateAccount(Recipient, 0); TestState.Set(new StorageCell(Recipient, 0), new[] { originalValue }); - TestState.Commit(MainnetSpecProvider.Instance.GenesisSpec); + TestState.Commit(RopstenSpecProvider.Instance.GenesisSpec); TestAllTracerWithOutput receipt = Execute(BlockNumber, 21000 + gasUsed + (2299 - 800), Bytes.FromHexString(codeHex)); Assert.That(receipt.StatusCode, Is.EqualTo(0)); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs index 6b20654a11f..64d8b5810e3 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs @@ -3,6 +3,9 @@ using FluentAssertions; using Nethermind.Core; +using Nethermind.Core.Specs; +using Nethermind.Core.Test; +using Nethermind.Core.Test.Builders; using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; using Nethermind.Logging; @@ -34,7 +37,7 @@ public void Base_fee_opcode_should_return_expected_results(bool eip3198Enabled, .Done; long blockNumber = eip3198Enabled ? MainnetSpecProvider.LondonBlockNumber : MainnetSpecProvider.LondonBlockNumber - 1; - (Block block, Transaction transaction) = PrepareTx((blockNumber, 0), 100000, code); + (Block block, Transaction transaction) = PrepareTx(blockNumber, 100000, code); block.Header.BaseFeePerGas = (UInt256)baseFee; if (send1559Tx) { diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs index 4154e94f095..bef8582a4be 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs @@ -3,13 +3,17 @@ using System.Collections.Generic; using System.Linq; +using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Extensions; +using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Specs; +using Nethermind.Specs.Forks; +using NSubstitute; using NUnit.Framework; namespace Nethermind.Evm.Test diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3588Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3588Tests.cs index 8dc5e60f093..69905794e16 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3588Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3588Tests.cs @@ -1,9 +1,21 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using FluentAssertions; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Specs; +using Nethermind.Core.Test.Builders; +using Nethermind.Evm.Tracing.GethStyle; +using Nethermind.State; +using Nethermind.Trie; using NUnit.Framework; +using FluentAssertions.Execution; +using Nethermind.Core.Specs; +using NSubstitute; +using Nethermind.Specs.Forks; namespace Nethermind.Evm.Test { @@ -23,7 +35,7 @@ private TestAllTracerWithOutput testBase(int repeat, bool isShanghai) } byte[] code = codeInitializer.Done; - TestAllTracerWithOutput receipt = Execute((BlockNumber, timestampParam), 1_000_000, code); + TestAllTracerWithOutput receipt = Execute(BlockNumber, 1_000_000, code, timestamp: timestampParam); return receipt; } diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3651Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3651Tests.cs index 6d9fe4c1248..2e8e759e642 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3651Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3651Tests.cs @@ -3,9 +3,11 @@ using FluentAssertions; using Nethermind.Core.Extensions; +using Nethermind.Core.Specs; using Nethermind.Specs; using Nethermind.Core.Test.Builders; using NUnit.Framework; +using Nethermind.Core; namespace Nethermind.Evm.Test { @@ -39,7 +41,7 @@ public void Access_beneficiary_address_before_eip_3651() .Op(Instruction.BALANCE) .Op(Instruction.POP) .Done; - TestAllTracerWithOutput result = Execute((BlockNumber, Timestamp - 1), 100000, code); + TestAllTracerWithOutput result = Execute(BlockNumber, 100000, code, timestamp: Timestamp - 1); result.StatusCode.Should().Be(1); AssertGas(result, GasCostOf.Transaction + 2605); } diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3860Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3860Tests.cs index 377a40460f1..f626f3ca333 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3860Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3860Tests.cs @@ -6,6 +6,8 @@ using Nethermind.Core.Test.Builders; using NUnit.Framework; using Nethermind.Core; +using Nethermind.Core.Crypto; +using System; using Nethermind.Int256; namespace Nethermind.Evm.Test @@ -37,7 +39,7 @@ public void Test_EIP_3860_GasCost_Create(string createCode, bool eip3860Enabled, byte[] callCode = Prepare.EvmCode.Call(TestItem.AddressC, 100000).Done; - var tracer = Execute((BlockNumber, eip3860Enabled ? Timestamp : Timestamp - 1), callCode); + var tracer = Execute(BlockNumber, eip3860Enabled ? Timestamp : Timestamp - 1, callCode); Assert.That(tracer.StatusCode, Is.EqualTo(StatusCode.Success)); Assert.That(tracer.GasSpent - _transactionCallCost, Is.EqualTo(expectedGasUsage)); } @@ -102,7 +104,7 @@ protected TestAllTracerWithOutput PrepExecuteCreateTransaction(ulong timestamp, TestState.CreateAccount(TestItem.AddressC, 1.Ether()); - (Block block, Transaction transaction) = PrepareTx((BlockNumber, timestamp), 500000, createCode); + (Block block, Transaction transaction) = PrepareTx(BlockNumber, 500000, createCode, timestamp: timestamp); transaction.GasPrice = 2.GWei(); transaction.To = null; diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip4844Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip4844Tests.cs index 3f9cdffdfe3..2dc755650aa 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip4844Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip4844Tests.cs @@ -4,6 +4,7 @@ using FluentAssertions; using Nethermind.Specs; using NUnit.Framework; +using System; using Nethermind.Int256; using System.Linq; @@ -43,7 +44,7 @@ public void Test_blobhash_index_in_range(int index, int blobhashesCount) .Return(32, 0) .Done; - TestAllTracerWithOutput result = Execute(Activation, 50000, code, blobVersionedHashes: hashes); + TestAllTracerWithOutput result = Execute(BlockNumber, 50000, code, blobVersionedHashes: hashes, timestamp: Timestamp); result.StatusCode.Should().Be(StatusCode.Success); result.ReturnValue.SequenceEqual(expectedOutput); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip6780Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip6780Tests.cs deleted file mode 100644 index 95fa9e54b16..00000000000 --- a/src/Nethermind/Nethermind.Evm.Test/Eip6780Tests.cs +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) 2021 Demerzel Solutions Limited -// This file is part of the Nethermind library. -// -// The Nethermind library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The Nethermind library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the Nethermind. If not, see . - -using Nethermind.Core; -using Nethermind.Core.Extensions; -using Nethermind.Core.Test.Builders; -using Nethermind.Crypto; -using Nethermind.Int256; -using Nethermind.Logging; -using Nethermind.Specs; -using NUnit.Framework; -using FluentAssertions; -using Nethermind.Evm.Tracing; -using Nethermind.Core.Crypto; -using System; - -namespace Nethermind.Evm.Test -{ - [TestFixture] - public class Eip6780Tests : VirtualMachineTestsBase - { - - protected override long BlockNumber => MainnetSpecProvider.GrayGlacierBlockNumber; - protected override ulong Timestamp => MainnetSpecProvider.CancunBlockTimestamp; - - private byte[] _selfDestructCode; - private Address _contractAddress; - private byte[] _initCode; - private long _gasLimit = 1000000; - private EthereumEcdsa _ecdsa = new(1, LimboLogs.Instance); - - [SetUp] - public override void Setup() - { - base.Setup(); - TestState.CreateAccount(TestItem.PrivateKeyA.Address, 1000.Ether()); - TestState.Commit(SpecProvider.GenesisSpec); - TestState.CommitTree(0); - _selfDestructCode = Prepare.EvmCode - .SELFDESTRUCT(TestItem.PrivateKeyB.Address) - .Done; - _contractAddress = ContractAddress.From(TestItem.PrivateKeyA.Address, 0); - _initCode = Prepare.EvmCode - .ForInitOf(_selfDestructCode) - .Done; - } - - [TestCase(0ul, false)] - [TestCase(MainnetSpecProvider.CancunBlockTimestamp, true)] - public void self_destruct_not_in_same_transaction(ulong timestamp, bool onlyOnSameTransaction) - { - byte[] contractCall = Prepare.EvmCode - .Call(_contractAddress, 100000) - .Op(Instruction.STOP).Done; - Transaction initTx = Build.A.Transaction.WithCode(_initCode).WithValue(99.Ether()).WithGasLimit(_gasLimit).SignedAndResolved(_ecdsa, TestItem.PrivateKeyA).TestObject; - Transaction tx1 = Build.A.Transaction.WithCode(contractCall).WithGasLimit(_gasLimit).WithNonce(1).SignedAndResolved(_ecdsa, TestItem.PrivateKeyA).TestObject; - Block block = Build.A.Block.WithNumber(BlockNumber) - .WithTimestamp(timestamp) - .WithTransactions(initTx, tx1).WithGasLimit(2 * _gasLimit).TestObject; - - _processor.Execute(initTx, block.Header, NullTxTracer.Instance); - UInt256 contractBalanceAfterInit = TestState.GetBalance(_contractAddress); - _processor.Execute(tx1, block.Header, NullTxTracer.Instance); - - contractBalanceAfterInit.Should().Be(99.Ether()); - AssertSendAll(); - if (onlyOnSameTransaction) - AssertNotDestroyed(); - else - AssertDestroyed(); - } - - [TestCase(0ul, false)] - [TestCase(MainnetSpecProvider.CancunBlockTimestamp, true)] - public void self_destruct_not_in_same_transaction_should_not_burn(ulong timestamp, bool onlyOnSameTransaction) - { - _selfDestructCode = Prepare.EvmCode - .SELFDESTRUCT(_contractAddress) - .Done; - _initCode = Prepare.EvmCode - .ForInitOf(_selfDestructCode) - .Done; - byte[] contractCall = Prepare.EvmCode - .Call(_contractAddress, 100000) - .Op(Instruction.STOP).Done; - Transaction initTx = Build.A.Transaction.WithCode(_initCode).WithValue(99.Ether()).WithGasLimit(_gasLimit).SignedAndResolved(_ecdsa, TestItem.PrivateKeyA).TestObject; - Transaction tx1 = Build.A.Transaction.WithCode(contractCall).WithGasLimit(_gasLimit).WithNonce(1).SignedAndResolved(_ecdsa, TestItem.PrivateKeyA).TestObject; - Block block = Build.A.Block.WithNumber(BlockNumber) - .WithTimestamp(timestamp) - .WithTransactions(initTx, tx1).WithGasLimit(2 * _gasLimit).TestObject; - - _processor.Execute(initTx, block.Header, NullTxTracer.Instance); - UInt256 contractBalanceAfterInit = TestState.GetBalance(_contractAddress); - _processor.Execute(tx1, block.Header, NullTxTracer.Instance); - - contractBalanceAfterInit.Should().Be(99.Ether()); - if (onlyOnSameTransaction) - TestState.GetBalance(_contractAddress).Should().Be(99.Ether()); // not burnt - else - TestState.GetBalance(_contractAddress).Should().Be(0); // burnt - if (onlyOnSameTransaction) - AssertNotDestroyed(); - else - AssertDestroyed(); - } - - [Test] - public void self_destruct_in_same_transaction() - { - byte[] salt = new UInt256(123).ToBigEndian(); - Address createTxAddress = ContractAddress.From(TestItem.PrivateKeyA.Address, 0); - _contractAddress = ContractAddress.From(createTxAddress, salt, _initCode); - byte[] tx1 = Prepare.EvmCode - .Create2(_initCode, salt, 99.Ether()) - .Call(_contractAddress, 100000) - .STOP() - .Done; - - Transaction createTx = Build.A.Transaction.WithCode(tx1).WithValue(100.Ether()).WithGasLimit(_gasLimit).SignedAndResolved(_ecdsa, TestItem.PrivateKeyA).TestObject; - Block block = Build.A.Block.WithNumber(BlockNumber) - .WithTimestamp(Timestamp) - .WithTransactions(createTx).WithGasLimit(2 * _gasLimit).TestObject; - - _processor.Execute(createTx, block.Header, NullTxTracer.Instance); - - AssertDestroyed(); - AssertSendAll(); - } - - [Test] - public void self_destruct_in_initcode_of_create_opcodes() - { - byte[] salt = new UInt256(123).ToBigEndian(); - Address createTxAddress = ContractAddress.From(TestItem.PrivateKeyA.Address, 0); - _contractAddress = ContractAddress.From(createTxAddress, salt, _selfDestructCode); - byte[] tx1 = Prepare.EvmCode - .Create2(_selfDestructCode, salt, 99.Ether()) - .STOP() - .Done; - - Transaction createTx = Build.A.Transaction.WithCode(tx1).WithValue(100.Ether()).WithGasLimit(_gasLimit).SignedAndResolved(_ecdsa, TestItem.PrivateKeyA).TestObject; - Block block = Build.A.Block.WithNumber(BlockNumber) - .WithTimestamp(Timestamp) - .WithTransactions(createTx).WithGasLimit(2 * _gasLimit).TestObject; - - _processor.Execute(createTx, block.Header, NullTxTracer.Instance); - - AssertDestroyed(); - AssertSendAll(); - } - - [Test] - public void self_destruct_in_initcode_of_create_tx() - { - Transaction createTx = Build.A.Transaction.WithCode(_selfDestructCode).WithValue(99.Ether()).WithGasLimit(_gasLimit).SignedAndResolved(_ecdsa, TestItem.PrivateKeyA).TestObject; - Block block = Build.A.Block.WithNumber(BlockNumber) - .WithTimestamp(Timestamp) - .WithTransactions(createTx).WithGasLimit(2 * _gasLimit).TestObject; - - _processor.Execute(createTx, block.Header, NullTxTracer.Instance); - - AssertDestroyed(); - AssertSendAll(); - } - - private void AssertNotDestroyed() - { - AssertCodeHash(_contractAddress, Keccak.Compute(_selfDestructCode.AsSpan())); - } - - private void AssertDestroyed(Address address = null) - { - TestState.AccountExists(address ?? _contractAddress).Should().BeFalse(); - } - - private void AssertSendAll() - { - TestState.GetBalance(_contractAddress).Should().Be(0); - TestState.GetBalance(TestItem.PrivateKeyB.Address).Should().Be(99.Ether()); - } - - } -} diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip7516BlobBaseFeeTests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip7516BlobBaseFeeTests.cs deleted file mode 100644 index 1a1036de336..00000000000 --- a/src/Nethermind/Nethermind.Evm.Test/Eip7516BlobBaseFeeTests.cs +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using FluentAssertions; -using Nethermind.Core; -using Nethermind.Core.Specs; -using Nethermind.Evm.TransactionProcessing; -using Nethermind.Int256; -using Nethermind.Logging; -using Nethermind.Specs; -using NUnit.Framework; - -namespace Nethermind.Evm.Test; - -public class Eip7516BlobBaseFeeTests : VirtualMachineTestsBase -{ - - [TestCase(true, 0ul)] - [TestCase(true, 100ul)] - [TestCase(true, 20ul)] - [TestCase(false, 20ul)] - [TestCase(false, 0ul)] - [TestCase(true, 0ul)] - [TestCase(true, 100ul)] - [TestCase(true, 20ul)] - [TestCase(false, 20ul)] - [TestCase(false, 0ul)] - public void Blob_Base_fee_opcode_should_return_expected_results(bool eip7516Enabled, ulong excessBlobGas) - { - _processor = new TransactionProcessor(SpecProvider, TestState, Machine, LimboLogs.Instance); - byte[] code = Prepare.EvmCode - .Op(Instruction.BLOBBASEFEE) - .PushData(0) - .Op(Instruction.SSTORE) - .Done; - - ForkActivation activation = eip7516Enabled ? MainnetSpecProvider.CancunActivation : MainnetSpecProvider.ShanghaiActivation; - (Block block, Transaction transaction) = PrepareTx(activation, 100000, code); - block.Header.ExcessBlobGas = excessBlobGas; - - TestAllTracerWithOutput tracer = CreateTracer(); - _processor.Execute(transaction, block.Header, tracer); - - _ = BlobGasCalculator.TryCalculateBlobGasPricePerUnit(excessBlobGas, out UInt256 expectedGasPrice); - if (eip7516Enabled) - { - AssertStorage((UInt256)0, expectedGasPrice); - } - else - { - tracer.Error.Should().Be(EvmExceptionType.BadInstruction.ToString()); - AssertStorage((UInt256)0, (UInt256)0); - } - } -} diff --git a/src/Nethermind/Nethermind.Evm.Test/EvmMemoryTestsBase.cs b/src/Nethermind/Nethermind.Evm.Test/EvmMemoryTestsBase.cs index 8a4c112c3dc..5450a6d8ff6 100644 --- a/src/Nethermind/Nethermind.Evm.Test/EvmMemoryTestsBase.cs +++ b/src/Nethermind/Nethermind.Evm.Test/EvmMemoryTestsBase.cs @@ -1,82 +1,83 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Linq; +using System.Collections.Generic; using Nethermind.Int256; using NUnit.Framework; -namespace Nethermind.Evm.Test; - -[TestFixture] -public abstract class EvmMemoryTestsBase +namespace Nethermind.Evm.Test { - protected abstract IEvmMemory CreateEvmMemory(); - - [Test] - public void Save_empty_beyond_reasonable_size_does_not_throw() + [TestFixture] + public abstract class EvmMemoryTestsBase { - IEvmMemory memory = CreateEvmMemory(); - UInt256 dest = (UInt256)int.MaxValue + 1; - memory.Save(in dest, new byte[0]); - } + protected abstract IEvmMemory CreateEvmMemory(); - [Test] - public void Trace_one_word() - { - IEvmMemory memory = CreateEvmMemory(); - UInt256 dest = UInt256.Zero; - memory.SaveWord(in dest, new byte[EvmPooledMemory.WordSize]); - var trace = memory.GetTrace(); - Assert.That(trace.Count(), Is.EqualTo(1)); - } + [Test] + public void Save_empty_beyond_reasonable_size_does_not_throw() + { + IEvmMemory memory = CreateEvmMemory(); + UInt256 dest = (UInt256)int.MaxValue + 1; + memory.Save(in dest, new byte[0]); + } - [Test] - public void Trace_two_words() - { - IEvmMemory memory = CreateEvmMemory(); - UInt256 dest = EvmPooledMemory.WordSize; - memory.SaveWord(in dest, new byte[EvmPooledMemory.WordSize]); - var trace = memory.GetTrace(); - Assert.That(trace.Count(), Is.EqualTo(2)); - } + [Test] + public void Trace_one_word() + { + IEvmMemory memory = CreateEvmMemory(); + UInt256 dest = UInt256.Zero; + memory.SaveWord(in dest, new byte[EvmPooledMemory.WordSize]); + List trace = memory.GetTrace(); + Assert.That(trace.Count, Is.EqualTo(1)); + } - [Test] - public void Trace_overwrite() - { - IEvmMemory memory = CreateEvmMemory(); - UInt256 dest = EvmPooledMemory.WordSize; - memory.SaveWord(in dest, new byte[EvmPooledMemory.WordSize]); - memory.SaveWord(in dest, new byte[EvmPooledMemory.WordSize]); - var trace = memory.GetTrace(); - Assert.That(trace.Count(), Is.EqualTo(2)); - } + [Test] + public void Trace_two_words() + { + IEvmMemory memory = CreateEvmMemory(); + UInt256 dest = EvmPooledMemory.WordSize; + memory.SaveWord(in dest, new byte[EvmPooledMemory.WordSize]); + List trace = memory.GetTrace(); + Assert.That(trace.Count, Is.EqualTo(2)); + } - [Test] - public void Trace_when_position_not_on_word_border() - { - IEvmMemory memory = CreateEvmMemory(); - UInt256 dest = EvmPooledMemory.WordSize / 2; - memory.SaveByte(in dest, 1); - var trace = memory.GetTrace(); - Assert.That(trace.Count(), Is.EqualTo(1)); - } + [Test] + public void Trace_overwrite() + { + IEvmMemory memory = CreateEvmMemory(); + UInt256 dest = EvmPooledMemory.WordSize; + memory.SaveWord(in dest, new byte[EvmPooledMemory.WordSize]); + memory.SaveWord(in dest, new byte[EvmPooledMemory.WordSize]); + List trace = memory.GetTrace(); + Assert.That(trace.Count, Is.EqualTo(2)); + } - [Test] - public void Calculate_memory_cost_returns_0_for_subsequent_calls() - { - IEvmMemory memory = CreateEvmMemory(); - UInt256 dest = UInt256.One; - long cost1 = memory.CalculateMemoryCost(in dest, UInt256.One); - long cost2 = memory.CalculateMemoryCost(in dest, UInt256.One); - Assert.That(cost2, Is.EqualTo(0L)); - } + [Test] + public void Trace_when_position_not_on_word_border() + { + IEvmMemory memory = CreateEvmMemory(); + UInt256 dest = EvmPooledMemory.WordSize / 2; + memory.SaveByte(in dest, 1); + List trace = memory.GetTrace(); + Assert.That(trace.Count, Is.EqualTo(1)); + } - [Test] - public void Calculate_memory_cost_returns_0_for_0_length() - { - IEvmMemory memory = CreateEvmMemory(); - UInt256 dest = long.MaxValue; - long cost = memory.CalculateMemoryCost(in dest, UInt256.Zero); - Assert.That(cost, Is.EqualTo(0L)); + [Test] + public void Calculate_memory_cost_returns_0_for_subsequent_calls() + { + IEvmMemory memory = CreateEvmMemory(); + UInt256 dest = UInt256.One; + long cost1 = memory.CalculateMemoryCost(in dest, UInt256.One); + long cost2 = memory.CalculateMemoryCost(in dest, UInt256.One); + Assert.That(cost2, Is.EqualTo(0L)); + } + + [Test] + public void Calculate_memory_cost_returns_0_for_0_length() + { + IEvmMemory memory = CreateEvmMemory(); + UInt256 dest = long.MaxValue; + long cost = memory.CalculateMemoryCost(in dest, UInt256.Zero); + Assert.That(cost, Is.EqualTo(0L)); + } } } diff --git a/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs b/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs index fe675cf2ff6..ecc47f396d2 100644 --- a/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs @@ -6,6 +6,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Core.Resettables; using Nethermind.Core.Test.Builders; using Nethermind.State; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Evm.Test/GasPriceExtractorTests.cs b/src/Nethermind/Nethermind.Evm.Test/GasPriceExtractorTests.cs index 874b16e4908..263fb7d0b62 100644 --- a/src/Nethermind/Nethermind.Evm.Test/GasPriceExtractorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/GasPriceExtractorTests.cs @@ -53,7 +53,7 @@ public void Keccak_gas_cost_assumption_is_correct() .Op(Instruction.CALLDATACOPY) .PushData("0x0200") .PushData(0) - .Op(Instruction.KECCAK256) + .Op(Instruction.SHA3) .Done; (Block block, Transaction transaction) = PrepareTx( diff --git a/src/Nethermind/Nethermind.Evm.Test/InstructionTests.cs b/src/Nethermind/Nethermind.Evm.Test/InstructionTests.cs index 2a9f1677613..4f38b640043 100644 --- a/src/Nethermind/Nethermind.Evm.Test/InstructionTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/InstructionTests.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using FluentAssertions; -using Nethermind.Specs.Forks; using NUnit.Framework; namespace Nethermind.Evm.Test @@ -12,50 +11,13 @@ public class InstructionTests [Test] public void Return_difficulty_name_for_prevrandao_opcode_for_pre_merge() { - Instruction.PREVRANDAO.GetName(false, Cancun.Instance).Should().Be("DIFFICULTY"); + Instruction.PREVRANDAO.GetName(false).Should().Be("DIFFICULTY"); } [Test] public void Return_prevrandao_name_for_prevrandao_opcode_for_post_merge() { - Instruction.PREVRANDAO.GetName(true, Cancun.Instance).Should().Be("PREVRANDAO"); - } - - [Test] - public void Return_tload_name_for_beginsub_opcode_for_eip1153() - { - Instruction.BEGINSUB.GetName(true, Cancun.Instance).Should().Be("TLOAD"); - } - - [Test] - public void Return_beginsub_name_for_beginsub_opcode_for_eip1153() - { - Instruction.BEGINSUB.GetName(true, Shanghai.Instance).Should().Be("BEGINSUB"); - } - - [Test] - public void Return_returnsub_name_for_returnsub_opcode_for_eip1153() - { - Instruction.RETURNSUB.GetName(true, Shanghai.Instance).Should().Be("RETURNSUB"); - } - - [Test] - public void Return_tstore_name_for_returnsub_opcode_for_eip1153() - { - Instruction.RETURNSUB.GetName(true, Cancun.Instance).Should().Be("TSTORE"); - } - - - [Test] - public void Return_mcopy_name_for_mcopy_opcode_post_eip_5656() - { - Instruction.MCOPY.GetName(true, Cancun.Instance).Should().Be("MCOPY"); - } - - [Test] - public void Return_jumpsub_name_for_mcopy_opcode_pre_eip_5656() - { - Instruction.MCOPY.GetName(true, Shanghai.Instance).Should().Be("JUMPSUB"); + Instruction.PREVRANDAO.GetName(true).Should().Be("PREVRANDAO"); } } } diff --git a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs index 126efa7438b..f830b2483cc 100644 --- a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs @@ -49,7 +49,7 @@ public void Intrinsic_cost_is_calculated_properly((Transaction Tx, long Cost, st [TestCaseSource(nameof(AccessTestCaseSource))] public void Intrinsic_cost_is_calculated_properly((List orderQueue, long Cost) testCase) { - AccessList.Builder accessListBuilder = new(); + AccessListBuilder accessListBuilder = new(); foreach (object o in testCase.orderQueue) { if (o is Address address) @@ -62,7 +62,7 @@ public void Intrinsic_cost_is_calculated_properly((List orderQueue, long } } - AccessList accessList = accessListBuilder.Build(); + AccessList accessList = accessListBuilder.ToAccessList(); Transaction tx = Build.A.Transaction.SignedAndResolved().WithAccessList(accessList).TestObject; void Test(IReleaseSpec spec, bool supportsAccessLists) diff --git a/src/Nethermind/Nethermind.Evm.Test/InvalidOpcodeTests.cs b/src/Nethermind/Nethermind.Evm.Test/InvalidOpcodeTests.cs index 395a5c7fe8a..6eabb804f25 100644 --- a/src/Nethermind/Nethermind.Evm.Test/InvalidOpcodeTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/InvalidOpcodeTests.cs @@ -24,7 +24,7 @@ public class InvalidOpcodeTests : VirtualMachineTestsBase Instruction.MOD, Instruction.SMOD, Instruction.ADDMOD, Instruction.MULMOD, Instruction.EXP, Instruction.SIGNEXTEND, Instruction.LT, Instruction.GT, Instruction.SLT, Instruction.SGT, Instruction.EQ, Instruction.ISZERO, Instruction.AND, Instruction.OR, Instruction.XOR, Instruction.NOT, - Instruction.BYTE, Instruction.KECCAK256, Instruction.ADDRESS, Instruction.BALANCE, Instruction.ORIGIN, + Instruction.BYTE, Instruction.SHA3, Instruction.ADDRESS, Instruction.BALANCE, Instruction.ORIGIN, Instruction.CALLER, Instruction.CALLVALUE, Instruction.CALLDATALOAD, Instruction.CALLDATASIZE, Instruction.CALLDATACOPY, Instruction.CODESIZE, Instruction.CODECOPY, Instruction.GASPRICE, Instruction.EXTCODESIZE, Instruction.EXTCODECOPY, Instruction.BLOCKHASH, Instruction.COINBASE, @@ -106,9 +106,7 @@ public class InvalidOpcodeTests : VirtualMachineTestsBase { Instruction.TSTORE, Instruction.TLOAD, - Instruction.MCOPY, Instruction.BLOBHASH, - Instruction.BLOBBASEFEE } ).ToArray(); @@ -165,7 +163,7 @@ public void Test(long blockNumber, ulong? timestamp = null) .Done; bool isValidOpcode = ((Instruction)i != Instruction.INVALID) && validOpcodes.Contains((Instruction)i); - TestAllTracerWithOutput result = Execute((blockNumber, timestamp ?? 0), 1_000_000, code); + TestAllTracerWithOutput result = Execute(blockNumber, 1_000_000, code, timestamp: timestamp ?? 0); if (isValidOpcode) { diff --git a/src/Nethermind/Nethermind.Evm.Test/Nethermind.Evm.Test.csproj b/src/Nethermind/Nethermind.Evm.Test/Nethermind.Evm.Test.csproj index 017f9f5fa10..af76747a713 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Nethermind.Evm.Test.csproj +++ b/src/Nethermind/Nethermind.Evm.Test/Nethermind.Evm.Test.csproj @@ -21,7 +21,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/src/Nethermind/Nethermind.Evm.Test/Keccak256Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Sha3Tests.cs similarity index 65% rename from src/Nethermind/Nethermind.Evm.Test/Keccak256Tests.cs rename to src/Nethermind/Nethermind.Evm.Test/Sha3Tests.cs index 282671a9a86..4c2a92f2fb4 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Keccak256Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Sha3Tests.cs @@ -5,21 +5,20 @@ using Nethermind.Specs; using Nethermind.Core.Test.Builders; using NUnit.Framework; -using Nethermind.Core.Specs; namespace Nethermind.Evm.Test { [TestFixture] [Parallelizable(ParallelScope.All)] - public class Keccak256Tests : VirtualMachineTestsBase + public class Sha3Tests : VirtualMachineTestsBase { protected override long BlockNumber => RinkebySpecProvider.ConstantinopleFixBlockNumber; private bool _setAuthor; - protected override Block BuildBlock(ForkActivation activation, SenderRecipientAndMiner senderRecipientAndMiner, Transaction transaction, long blockGasLimit = DefaultBlockGasLimit, ulong excessBlobGas = 0) + protected override Block BuildBlock(long blockNumber, SenderRecipientAndMiner senderRecipientAndMiner, Transaction transaction, long blockGasLimit = DefaultBlockGasLimit, ulong timestamp = 0) { - Block block = base.BuildBlock(activation, senderRecipientAndMiner, transaction, blockGasLimit, excessBlobGas); + Block block = base.BuildBlock(blockNumber, senderRecipientAndMiner, transaction, blockGasLimit, timestamp); if (_setAuthor) block.Header.Author = TestItem.AddressC; block.Header.Beneficiary = TestItem.AddressB; return block; @@ -34,13 +33,13 @@ public void Spin_sha3() .Op(Instruction.JUMPDEST) .PushData(32) .PushData(0) - .Op(Instruction.KECCAK256) + .Op(Instruction.SHA3) .Op(Instruction.POP) .PushData(0) .Op(Instruction.JUMP) .Done; - TestAllTracerWithOutput receipt = Execute((8000000, 0), 8000000, code); + TestAllTracerWithOutput receipt = Execute(8000000, 8000000, code); AssertGas(receipt, 8000000); } diff --git a/src/Nethermind/Nethermind.Evm.Test/SimdTests.cs b/src/Nethermind/Nethermind.Evm.Test/SimdTests.cs index 062f9cd2db5..f648b10f041 100644 --- a/src/Nethermind/Nethermind.Evm.Test/SimdTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/SimdTests.cs @@ -2,20 +2,35 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Specs; using NUnit.Framework; namespace Nethermind.Evm.Test { + [TestFixture(true)] + [TestFixture(false)] [Parallelizable(ParallelScope.Self)] public class SimdTests : VirtualMachineTestsBase { + private readonly bool _simdDisabled; protected override long BlockNumber => MainnetSpecProvider.ConstantinopleFixBlockNumber; + public SimdTests(bool simdDisabled) + { + _simdDisabled = simdDisabled; + } + [Test] public void And() { + if (_simdDisabled) + { + Machine.DisableSimdInstructions(); + } + byte[] a = Bytes.FromHexString("0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0ff"); byte[] b = Bytes.FromHexString("0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); byte[] result = Bytes.FromHexString("0x000000000000000000000000000000000000000000000000000000000000000f"); @@ -35,6 +50,11 @@ public void And() [Test] public void Or() { + if (_simdDisabled) + { + Machine.DisableSimdInstructions(); + } + byte[] a = Bytes.FromHexString("0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0"); byte[] b = Bytes.FromHexString("0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); byte[] result = Bytes.FromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); @@ -54,6 +74,11 @@ public void Or() [Test] public void Xor() { + if (_simdDisabled) + { + Machine.DisableSimdInstructions(); + } + byte[] a = Bytes.FromHexString("0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0"); byte[] b = Bytes.FromHexString("0xff0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); byte[] result = Bytes.FromHexString("0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); @@ -73,6 +98,11 @@ public void Xor() [Test] public void Not() { + if (_simdDisabled) + { + Machine.DisableSimdInstructions(); + } + byte[] a = Bytes.FromHexString("0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0"); byte[] result = Bytes.FromHexString("0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); diff --git a/src/Nethermind/Nethermind.Evm.Test/StorageAndSelfDestructTests.cs b/src/Nethermind/Nethermind.Evm.Test/StorageAndSelfDestructTests.cs index 842bbc2f2b8..93328991347 100644 --- a/src/Nethermind/Nethermind.Evm.Test/StorageAndSelfDestructTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/StorageAndSelfDestructTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; @@ -11,6 +12,7 @@ using Nethermind.Logging; using Nethermind.Specs; using Nethermind.Specs.Forks; +using Nethermind.State; using NUnit.Framework; namespace Nethermind.Evm.Test diff --git a/src/Nethermind/Nethermind.Evm.Test/TestAllTracerWithOutput.cs b/src/Nethermind/Nethermind.Evm.Test/TestAllTracerWithOutput.cs index e66f75f8925..afb14848dab 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TestAllTracerWithOutput.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TestAllTracerWithOutput.cs @@ -6,50 +6,47 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Evm.Tracing; +using Nethermind.Int256; namespace Nethermind.Evm.Test { - public class TestAllTracerWithOutput : TxTracer + public class TestAllTracerWithOutput : ITxTracer { - public TestAllTracerWithOutput() - { - IsTracingAccess = true; - } - - public override bool IsTracingReceipt => true; - public override bool IsTracingActions => true; - public override bool IsTracingOpLevelStorage => true; - public override bool IsTracingMemory => true; - public override bool IsTracingInstructions => true; - public override bool IsTracingRefunds => true; - public override bool IsTracingCode => true; - public override bool IsTracingStack => true; - public override bool IsTracingState => true; - public override bool IsTracingStorage => true; - public override bool IsTracingBlockHash => true; - public new bool IsTracingAccess { get { return base.IsTracingAccess; } set { base.IsTracingAccess = value; } } - public override bool IsTracingFees => true; + public bool IsTracingReceipt => true; + public bool IsTracingActions => true; + public bool IsTracingOpLevelStorage => true; + public bool IsTracingMemory => true; + public bool IsTracingInstructions => true; + public bool IsTracingRefunds => true; + public bool IsTracingCode => true; + public bool IsTracingStack => true; + public bool IsTracingState => true; + public bool IsTracingStorage => true; + public bool IsTracingBlockHash => true; + public bool IsTracingAccess { get; set; } = true; + public bool IsTracingFees => true; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; - public byte[]? ReturnValue { get; private set; } + public byte[] ReturnValue { get; set; } - public long GasSpent { get; private set; } + public long GasSpent { get; set; } - public string? Error { get; private set; } + public string Error { get; set; } - public byte StatusCode { get; private set; } + public byte StatusCode { get; set; } - public long Refund { get; private set; } + public long Refund { get; set; } public List ReportedActionErrors { get; set; } = new List(); - public override void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak stateRoot = null) { GasSpent = gasSpent; ReturnValue = output; StatusCode = Evm.StatusCode.Success; } - public override void MarkAsFailed(Address recipient, long gasSpent, byte[]? output, string error, Keccak? stateRoot = null) + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak stateRoot = null) { GasSpent = gasSpent; Error = error; @@ -57,14 +54,122 @@ public override void MarkAsFailed(Address recipient, long gasSpent, byte[]? outp StatusCode = Evm.StatusCode.Failure; } - public override void ReportActionError(EvmExceptionType exceptionType) + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) + { + } + + public void ReportOperationError(EvmExceptionType error) + { + } + + public void ReportOperationRemainingGas(long gas) + { + } + + public void SetOperationStack(List stackTrace) + { + } + + public void ReportStackPush(in ReadOnlySpan stackItem) + { + } + + public void SetOperationMemory(List memoryTrace) + { + } + + public void SetOperationMemorySize(ulong newSize) + { + } + + public void ReportMemoryChange(long offset, in ReadOnlySpan data) + { + } + + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) + { + } + + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) + { + } + + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) + { + } + + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) + { + } + + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) + { + } + + public void ReportCodeChange(Address address, byte[] before, byte[] after) + { + } + + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) + { + } + + public void ReportAccountRead(Address address) + { + } + + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) + { + } + + public void ReportStorageRead(in StorageCell storageCell) + { + } + + public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) + { + } + + public void ReportActionEnd(long gas, ReadOnlyMemory output) + { + } + + public void ReportActionError(EvmExceptionType exceptionType) { ReportedActionErrors.Add(exceptionType); } - public override void ReportRefund(long refund) + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) + { + } + + public void ReportBlockHash(Keccak blockHash) + { + } + + public void ReportByteCode(byte[] byteCode) + { + } + + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) + { + } + + public void ReportRefund(long refund) { Refund += refund; } + + public void ReportExtraGasPressure(long extraGasPressure) + { + } + + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) + { + } + + public void ReportFees(UInt256 fees, UInt256 burntFees) + { + } } } diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/AccessTxTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/AccessTxTracerTests.cs index d291685f3a4..68975281e51 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/AccessTxTracerTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/AccessTxTracerTests.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Specs; @@ -31,11 +30,12 @@ public void Records_get_correct_accessed_addresses() (AccessTxTracer tracer, _, _) = ExecuteAndTraceAccessCall(SenderRecipientAndMiner.Default, code); - IEnumerable
addressesAccessed = tracer.AccessList!.Select(tuples => tuples.Address); + IEnumerable
addressesAccessed = tracer.AccessList.Data.Keys; IEnumerable
expected = new[] { SenderRecipientAndMiner.Default.Sender, SenderRecipientAndMiner.Default.Recipient, TestItem.AddressC }; + Assert.IsNotEmpty(addressesAccessed); addressesAccessed.Should().BeEquivalentTo(expected); } @@ -50,12 +50,13 @@ public void Records_get_correct_accessed_keys() (AccessTxTracer tracer, _, _) = ExecuteAndTraceAccessCall(SenderRecipientAndMiner.Default, code); - tracer.AccessList!.Should().BeEquivalentTo( - new[] - { - (SenderRecipientAndMiner.Default.Sender, new UInt256[] { }), - (SenderRecipientAndMiner.Default.Recipient, new UInt256[] { 105 }) - }); + IReadOnlyDictionary> accessedData = tracer.AccessList.Data; + + Assert.IsNotEmpty(accessedData); + accessedData.Should().BeEquivalentTo( + new Dictionary>{ + {SenderRecipientAndMiner.Default.Sender, ImmutableHashSet.Empty}, + {SenderRecipientAndMiner.Default.Recipient, new HashSet{105}}}); } protected override ISpecProvider SpecProvider => new TestSpecProvider(Berlin.Instance); diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/CompositeBlockTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/CompositeBlockTracerTests.cs index ccffc9134be..3584250d6b5 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/CompositeBlockTracerTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/CompositeBlockTracerTests.cs @@ -9,61 +9,63 @@ using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Evm.Tracing.ParityStyle; +using Nethermind.Specs; using NUnit.Framework; -namespace Nethermind.Evm.Test.Tracing; - -[TestFixture] -public class CompositeBlockTracerTests +namespace Nethermind.Evm.Test.Tracing { - [Test] - public void Should_create_tracer_correctly() + [TestFixture] + public class CompositeBlockTracerTests { - Keccak txHash = TestItem.KeccakA; - GethLikeBlockMemoryTracer gethLikeBlockTracer = new(GethTraceOptions.Default with { TxHash = txHash }); - ParityLikeBlockTracer parityLikeBlockTracer = new(txHash, ParityTraceTypes.All); + [Test] + public void Should_create_tracer_correctly() + { + Keccak txHash = TestItem.KeccakA; + GethLikeBlockTracer gethLikeBlockTracer = new(txHash, GethTraceOptions.Default); + ParityLikeBlockTracer parityLikeBlockTracer = new(txHash, ParityTraceTypes.All); - CompositeBlockTracer compositeBlockTracer = new CompositeBlockTracer(); - compositeBlockTracer.AddRange(gethLikeBlockTracer, parityLikeBlockTracer); + CompositeBlockTracer compositeBlockTracer = new CompositeBlockTracer(); + compositeBlockTracer.AddRange(gethLikeBlockTracer, parityLikeBlockTracer); - compositeBlockTracer.IsTracingRewards.Should().Be(true); - } + compositeBlockTracer.IsTracingRewards.Should().Be(true); + } - [Test] - public void Should_trace_properly() - { - Block block = Build.A.Block.TestObject; - Transaction tx1 = Build.A.Transaction.TestObject; - Transaction tx2 = Build.A.Transaction.TestObject; - Transaction tx3 = Build.A.Transaction.TestObject; + [Test] + public void Should_trace_properly() + { + Block block = Build.A.Block.TestObject; + Transaction tx1 = Build.A.Transaction.TestObject; + Transaction tx2 = Build.A.Transaction.TestObject; + Transaction tx3 = Build.A.Transaction.TestObject; - block = block.WithReplacedBody(new BlockBody(new[] { tx1, tx2, tx3 }, new BlockHeader[0])); + block = block.WithReplacedBody(new BlockBody(new[] { tx1, tx2, tx3 }, new BlockHeader[0])); - GethLikeBlockMemoryTracer gethLikeBlockTracer = new(GethTraceOptions.Default); - ParityLikeBlockTracer parityLikeBlockTracer = new(ParityTraceTypes.All); - NullBlockTracer nullBlockTracer = NullBlockTracer.Instance; - AlwaysCancelBlockTracer alwaysCancelBlockTracer = AlwaysCancelBlockTracer.Instance; + GethLikeBlockTracer gethLikeBlockTracer = new(GethTraceOptions.Default); + ParityLikeBlockTracer parityLikeBlockTracer = new(ParityTraceTypes.All); + NullBlockTracer nullBlockTracer = NullBlockTracer.Instance; + AlwaysCancelBlockTracer alwaysCancelBlockTracer = AlwaysCancelBlockTracer.Instance; - CompositeBlockTracer blockTracer = new CompositeBlockTracer(); - blockTracer.AddRange(gethLikeBlockTracer, parityLikeBlockTracer, nullBlockTracer, alwaysCancelBlockTracer); + CompositeBlockTracer blockTracer = new CompositeBlockTracer(); + blockTracer.AddRange(gethLikeBlockTracer, parityLikeBlockTracer, nullBlockTracer, alwaysCancelBlockTracer); - blockTracer.StartNewBlockTrace(block); + blockTracer.StartNewBlockTrace(block); - blockTracer.StartNewTxTrace(tx1); - blockTracer.EndTxTrace(); + blockTracer.StartNewTxTrace(tx1); + blockTracer.EndTxTrace(); - blockTracer.StartNewTxTrace(tx2); - blockTracer.EndTxTrace(); + blockTracer.StartNewTxTrace(tx2); + blockTracer.EndTxTrace(); - blockTracer.StartNewTxTrace(tx3); - blockTracer.EndTxTrace(); + blockTracer.StartNewTxTrace(tx3); + blockTracer.EndTxTrace(); - blockTracer.EndBlockTrace(); + blockTracer.EndBlockTrace(); - IReadOnlyCollection gethResult = gethLikeBlockTracer.BuildResult(); - gethResult.Count.Should().Be(3); + IReadOnlyCollection gethResult = gethLikeBlockTracer.BuildResult(); + gethResult.Count.Should().Be(3); - IReadOnlyCollection parityResult = parityLikeBlockTracer.BuildResult(); - parityResult.Count.Should().Be(3); + IReadOnlyCollection parityResult = parityLikeBlockTracer.BuildResult(); + parityResult.Count.Should().Be(3); + } } } diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs index 4a2a7140ee2..97b2aeedc08 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/DebugTracerTests.cs @@ -2,480 +2,485 @@ // SPDX-License-Identifier: LGPL-3.0-only #if DEBUG +using Nethermind.Evm.Tracing.DebugTrace; using Nethermind.Evm.Tracing.GethStyle; +using System.Threading.Tasks; +using System; +using Nethermind.Int256; +using Nethermind.Specs.Forks; using NUnit.Framework; +using System.Text.Json; using System.Threading; using Nethermind.Core.Extensions; -using Nethermind.Evm.Tracing.Debugger; -namespace Nethermind.Evm.Test; - -public class DebugTracerTests : VirtualMachineTestsBase +namespace Nethermind.Evm.Test { - public GethLikeTxMemoryTracer GethLikeTxTracer => new GethLikeTxMemoryTracer(GethTraceOptions.Default); - - [SetUp] - public override void Setup() + public class DebugTracerTests : VirtualMachineTestsBase { - base.Setup(); - } + public GethLikeTxTracer GethLikeTxTracer => new GethLikeTxTracer(GethTraceOptions.Default); - [TestCase("0x5b601760005600")] - public void Debugger_Halts_Execution_On_Breakpoint(string bytecodeHex) - { - // this bytecode create an infinite loop that keeps pushing 0x17 to the stack so it is bound to stackoverflow (or even to use up its gas) i.e : - byte[] bytecode = Bytes.FromHexString(bytecodeHex); + [SetUp] + public override void Setup() + { + base.Setup(); + } - (int depth, int pc) JUMP_OPCODE_PTR_BREAK_POINT = (0, 5); - using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + [TestCase("0x5b601760005600")] + public void Debugger_Halts_Execution_On_Breakpoint(string bytecodeHex) { - // we activate GoToNextBreakpoint mode (i.e : deactivate StepByStepMode) - IsStepByStepModeOn = false, - }; + // this bytecode create an infinite loop that keeps pushing 0x17 to the stack so it is bound to stackoverflow (or even to use up its gas) i.e : + byte[] bytecode = Bytes.FromHexString(bytecodeHex); - // we set the break point to BREAK_POINT - tracer.SetBreakPoint(JUMP_OPCODE_PTR_BREAK_POINT); + (int depth, int pc) JUMP_OPCODE_PTR_BREAK_POINT = (0, 5); + using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + { + // we activate GoToNextBreakpoint mode (i.e : deactivate StepByStepMode) + IsStepByStepModeOn = false, + }; - // we set the break point to BREAK_POINT - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); - vmThread.Start(); + // we set the break point to BREAK_POINT + tracer.SetBreakPoint(JUMP_OPCODE_PTR_BREAK_POINT); - // we run the bytecode for iteration and check how many times we stopped at BREAK_POINT - int confidenceLevelDesired = 100; - int confidenceLevelReached = 0; - int iterationsCount = 0; + // we set the break point to BREAK_POINT + Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + vmThread.Start(); - // Test fails if iterationsCount != confidenceLevelReached != confidenceLevelDesired - bool TestFailed = false; + // we run the bytecode for iteration and check how many times we stopped at BREAK_POINT + int confidenceLevelDesired = 100; + int confidenceLevelReached = 0; + int iterationsCount = 0; - while (vmThread.IsAlive) - { - if (tracer.CanReadState) + // Test fails if iterationsCount != confidenceLevelReached != confidenceLevelDesired + bool TestFailed = false; + + while (vmThread.IsAlive) { - iterationsCount++; - confidenceLevelReached += tracer.CurrentState.ProgramCounter == JUMP_OPCODE_PTR_BREAK_POINT.pc ? 1 : 0; - if (iterationsCount == confidenceLevelDesired) + if (tracer.CanReadState) { - TestFailed = confidenceLevelReached < confidenceLevelDesired; - tracer.Abort(); - vmThread.Interrupt(); - break; + iterationsCount++; + confidenceLevelReached += tracer.CurrentState.ProgramCounter == JUMP_OPCODE_PTR_BREAK_POINT.pc ? 1 : 0; + if (iterationsCount == confidenceLevelDesired) + { + TestFailed = confidenceLevelReached < confidenceLevelDesired; + tracer.Abort(); + vmThread.Interrupt(); + break; + } + + tracer.MoveNext(); } - tracer.MoveNext(); } + Assert.False(TestFailed); } - Assert.False(TestFailed); - } - - [TestCase("0x5b601760005600")] - public void Debugger_Halts_Execution_On_Breakpoint_If_Condition_Is_True(string bytecodeHex) - { - // this bytecode create an infinite loop that keeps pushing 0x17 to the stack so it is bound to stackoverflow (or even to use up its gas) i.e : - byte[] bytecode = Bytes.FromHexString(bytecodeHex); - - (int depth, int pc) JUMP_OPCODE_PTR_BREAK_POINT = (0, 5); - using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + [TestCase("0x5b601760005600")] + public void Debugger_Halts_Execution_On_Breakpoint_If_Condition_Is_True(string bytecodeHex) { - // we activate GoToNextBreakpoint mode (i.e : deactivate StepByStepMode) - IsStepByStepModeOn = false, - }; + // this bytecode create an infinite loop that keeps pushing 0x17 to the stack so it is bound to stackoverflow (or even to use up its gas) i.e : + byte[] bytecode = Bytes.FromHexString(bytecodeHex); - // we set the break point to BREAK_POINT - tracer.SetBreakPoint(JUMP_OPCODE_PTR_BREAK_POINT, state => - { - return state.DataStackHead == 23; - }); + (int depth, int pc) JUMP_OPCODE_PTR_BREAK_POINT = (0, 5); + using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + { + // we activate GoToNextBreakpoint mode (i.e : deactivate StepByStepMode) + IsStepByStepModeOn = false, + }; + + // we set the break point to BREAK_POINT + tracer.SetBreakPoint(JUMP_OPCODE_PTR_BREAK_POINT, state => + { + return state.DataStackHead == 23; + }); - Thread vmThread = new(() => Execute(tracer, bytecode)); - vmThread.Start(); + Thread vmThread = new(() => Execute(tracer, bytecode)); + vmThread.Start(); - // we run the bytecode for iteration and check how many times we stopped at BREAK_POINT - int confidenceLevelDesired = 100; - int confidenceLevelReached = 0; - int iterationsCount = 0; + // we run the bytecode for iteration and check how many times we stopped at BREAK_POINT + int confidenceLevelDesired = 100; + int confidenceLevelReached = 0; + int iterationsCount = 0; - // Test fails if confidenceLevelReached > 1 - bool TestFailed = false; + // Test fails if confidenceLevelReached > 1 + bool TestFailed = false; - while (vmThread.IsAlive) - { - if (tracer.CanReadState) + while (vmThread.IsAlive) { - iterationsCount++; - confidenceLevelReached += tracer.CurrentState.ProgramCounter == JUMP_OPCODE_PTR_BREAK_POINT.pc ? 1 : 0; - - if (iterationsCount == confidenceLevelDesired) + if (tracer.CanReadState) { - TestFailed = confidenceLevelReached > 1; + iterationsCount++; + confidenceLevelReached += tracer.CurrentState.ProgramCounter == JUMP_OPCODE_PTR_BREAK_POINT.pc ? 1 : 0; - tracer.Abort(); - vmThread.Interrupt(); - } + if (iterationsCount == confidenceLevelDesired) + { + TestFailed = confidenceLevelReached > 1; - tracer.MoveNext(); - } - } + tracer.Abort(); + vmThread.Interrupt(); + } - Assert.False(TestFailed); - } + tracer.MoveNext(); + } + } - [TestCase("0x5b5b5b5b5b5b5b5b5b5b00")] - public void Debugger_Halts_Execution_On_Eeach_Iteration_using_StepByStepMode(string bytecodeHex) - { - // this bytecode is just a bunch of NOP/JUMPDEST, the idea is it will take as much bytes in the bytecode as steps to go throught it - byte[] bytecode = Bytes.FromHexString(bytecodeHex); + Assert.False(TestFailed); + } - using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + [TestCase("0x5b5b5b5b5b5b5b5b5b5b00")] + public void Debugger_Halts_Execution_On_Eeach_Iteration_using_StepByStepMode(string bytecodeHex) { - // we activate step by step mode in tracer - IsStepByStepModeOn = true, - }; + // this bytecode is just a bunch of NOP/JUMPDEST, the idea is it will take as much bytes in the bytecode as steps to go throught it + byte[] bytecode = Bytes.FromHexString(bytecodeHex); + + using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + { + // we activate step by step mode in tracer + IsStepByStepModeOn = true, + }; - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); - vmThread.Start(); + Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + vmThread.Start(); - int countBreaks = 0; + int countBreaks = 0; - while (vmThread.IsAlive) - { - if (tracer.CanReadState) + while (vmThread.IsAlive) { - // we count how many steps it took to run the bytecode - countBreaks++; + if (tracer.CanReadState) + { + // we count how many steps it took to run the bytecode + countBreaks++; - tracer.MoveNext(); + tracer.MoveNext(); + } } - } - - countBreaks--; //Pre-run break - // we check that it matches the number of opcodes in the bytecode - Assert.That(bytecode.Length, Is.EqualTo(countBreaks)); - } + countBreaks--; //Pre-run break - [TestCase("0x5b5b5b5b5b5b5b5b5b5b00")] - public void Debugger_Skips_Single_Step_Breakpoints_When_MoveNext_Uses_Override(string bytecodeHex) - { - // this bytecode is just a bunch of NOP/JUMPDEST, the idea is it will take as much bytes in the bytecode as steps to go throught it - byte[] bytecode = Bytes.FromHexString(bytecodeHex); + // we check that it matches the number of opcodes in the bytecode + Assert.That(bytecode.Length, Is.EqualTo(countBreaks)); + } - using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + [TestCase("0x5b5b5b5b5b5b5b5b5b5b00")] + public void Debugger_Skips_Single_Step_Breakpoints_When_MoveNext_Uses_Override(string bytecodeHex) { - // we activate step by step mode in tracer - IsStepByStepModeOn = true, - }; + // this bytecode is just a bunch of NOP/JUMPDEST, the idea is it will take as much bytes in the bytecode as steps to go throught it + byte[] bytecode = Bytes.FromHexString(bytecodeHex); + + using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + { + // we activate step by step mode in tracer + IsStepByStepModeOn = true, + }; - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); - vmThread.Start(); + Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + vmThread.Start(); - int countBreaks = 0; + int countBreaks = 0; - while (vmThread.IsAlive) - { - if (tracer.CanReadState) + while (vmThread.IsAlive) { - // we count how many steps it took to run the bytecode - countBreaks++; + if (tracer.CanReadState) + { + // we count how many steps it took to run the bytecode + countBreaks++; - tracer.MoveNext(executeOneStep: false); + tracer.MoveNext(executeOneStep: false); + } } - } - - // we check that it matches the number of opcodes in the bytecode - Assert.That(countBreaks, Is.EqualTo(1)); - } - [TestCase("0x5b5b5b5b5b5b5b5b5b5b00")] - public void Debugger_Switches_To_Single_Steps_After_First_Breakpoint(string bytecodeHex) - { - // this bytecode is just a bunch of NOP/JUMPDEST, the idea is it will take as much bytes in the bytecode as steps to go throught it - byte[] bytecode = Bytes.FromHexString(bytecodeHex); + // we check that it matches the number of opcodes in the bytecode + Assert.That(countBreaks, Is.EqualTo(1)); + } - (int depth, int pc) BREAKPOINT = (0, 5); - using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + [TestCase("0x5b5b5b5b5b5b5b5b5b5b00")] + public void Debugger_Switches_To_Single_Steps_After_First_Breakpoint(string bytecodeHex) { - // we activate step by step mode in tracer - IsStepByStepModeOn = false, - }; + // this bytecode is just a bunch of NOP/JUMPDEST, the idea is it will take as much bytes in the bytecode as steps to go throught it + byte[] bytecode = Bytes.FromHexString(bytecodeHex); + + (int depth, int pc) BREAKPOINT = (0, 5); + using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + { + // we activate step by step mode in tracer + IsStepByStepModeOn = false, + }; - tracer.SetBreakPoint(BREAKPOINT); + tracer.SetBreakPoint(BREAKPOINT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); - vmThread.Start(); + Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + vmThread.Start(); - int countBreaks = -1; // not counting the post-run stop + int countBreaks = -1; // not counting the post-run stop - while (vmThread.IsAlive) - { - if (tracer.CanReadState) + while (vmThread.IsAlive) { - // we count how many steps it took to run the bytecode - countBreaks++; + if (tracer.CanReadState) + { + // we count how many steps it took to run the bytecode + countBreaks++; - tracer.MoveNext(executeOneStep: true); + tracer.MoveNext(executeOneStep: true); + } } - } - - // we check that it matches the number of opcodes in the bytecode - Assert.That(countBreaks, Is.EqualTo(bytecode.Length - BREAKPOINT.pc)); - } - [TestCase("0x5b601760005600")] - public void Debugger_Can_Alter_Program_Counter(string bytecodeHex) - { - // this bytecode create an infinite loop that keeps pushing 0x17 to the stack so it is bound to stackoverflow (or even to use up its gas) i.e : - byte[] bytecode = Bytes.FromHexString(bytecodeHex); + // we check that it matches the number of opcodes in the bytecode + Assert.That(countBreaks, Is.EqualTo(bytecode.Length - BREAKPOINT.pc)); + } - (int depth, int pc) JUMP_OPCODE_PTR_BREAK_POINT = (0, 5); - using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + [TestCase("0x5b601760005600")] + public void Debugger_Can_Alter_Program_Counter(string bytecodeHex) { - IsStepByStepModeOn = true, - }; + // this bytecode create an infinite loop that keeps pushing 0x17 to the stack so it is bound to stackoverflow (or even to use up its gas) i.e : + byte[] bytecode = Bytes.FromHexString(bytecodeHex); + + (int depth, int pc) JUMP_OPCODE_PTR_BREAK_POINT = (0, 5); + using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + { + IsStepByStepModeOn = true, + }; - tracer.SetBreakPoint(JUMP_OPCODE_PTR_BREAK_POINT); + tracer.SetBreakPoint(JUMP_OPCODE_PTR_BREAK_POINT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); - vmThread.Start(); + Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + vmThread.Start(); - while (vmThread.IsAlive) - { - if (tracer.CanReadState) + while (vmThread.IsAlive) { - tracer.CurrentState.ProgramCounter++; - tracer.MoveNext(); + if (tracer.CanReadState) + { + tracer.CurrentState.ProgramCounter++; + tracer.MoveNext(); + } } - } - - // we check if bytecode execution failed - var resultTraces = (tracer.InnerTracer as GethLikeTxMemoryTracer).BuildResult(); - Assert.IsFalse(resultTraces.Failed); - } - [TestCase("5b6017600160005700")] - public void Debugger_Can_Alter_Data_Stack(string bytecodeHex) - { - // this bytecode create an infinite loop that keeps pushing 0x17 to the stack so it is bound to stackoverflow (or even to use up its gas) i.e : - byte[] bytecode = Bytes.FromHexString(bytecodeHex); + // we check if bytecode execution failed + var resultTraces = (tracer.InnerTracer as GethLikeTxTracer).BuildResult(); + Assert.IsFalse(resultTraces.Failed); + } - (int depth, int pc) JUMP_OPCODE_PTR_BREAK_POINT = (0, 5); - using DebugTracer tracer = new(GethLikeTxTracer) + [TestCase("5b6017600160005700")] + public void Debugger_Can_Alter_Data_Stack(string bytecodeHex) { - IsStepByStepModeOn = false, - }; + // this bytecode create an infinite loop that keeps pushing 0x17 to the stack so it is bound to stackoverflow (or even to use up its gas) i.e : + byte[] bytecode = Bytes.FromHexString(bytecodeHex); + + (int depth, int pc) JUMP_OPCODE_PTR_BREAK_POINT = (0, 5); + using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + { + IsStepByStepModeOn = false, + }; - tracer.SetBreakPoint(JUMP_OPCODE_PTR_BREAK_POINT); + tracer.SetBreakPoint(JUMP_OPCODE_PTR_BREAK_POINT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); - vmThread.Start(); + Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + vmThread.Start(); - while (vmThread.IsAlive) - { - if (tracer.CanReadState) + while (vmThread.IsAlive) { - // we pop the condition and overwrite it with a false to force breaking out of the loop - EvmStack stack = new(tracer.CurrentState.DataStack, tracer.CurrentState.DataStackHead, tracer); - stack.PopLimbo(); - stack.PushByte(0x00); + if (tracer.CanReadState) + { + // we pop the condition and overwrite it with a false to force breaking out of the loop + EvmStack stack = new(tracer.CurrentState.DataStack, tracer.CurrentState.DataStackHead, tracer); + stack.PopLimbo(); + stack.PushByte(0x00); - tracer.MoveNext(); + tracer.MoveNext(); + } } - } - - // we check if bytecode execution failed - var resultTraces = (tracer.InnerTracer as GethLikeTxMemoryTracer).BuildResult(); - Assert.IsFalse(resultTraces.Failed); - } - [TestCase("6017806000526000511460005260206000f3")] - public void Debugger_Can_Alter_Memory(string bytecodeHex) - { - // this bytecode create an infinite loop that keeps pushing 0x17 to the stack so it is bound to stackoverflow (or even to use up its gas) i.e : - byte[] bytecode = Bytes.FromHexString(bytecodeHex); + // we check if bytecode execution failed + var resultTraces = (tracer.InnerTracer as GethLikeTxTracer).BuildResult(); + Assert.IsFalse(resultTraces.Failed); + } - (int depth, int pc) MSTORE_OPCODE_PTR_BREAK_POINT = (0, 6); - using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + [TestCase("6017806000526000511460005260206000f3")] + public void Debugger_Can_Alter_Memory(string bytecodeHex) { - IsStepByStepModeOn = false, - }; + // this bytecode create an infinite loop that keeps pushing 0x17 to the stack so it is bound to stackoverflow (or even to use up its gas) i.e : + byte[] bytecode = Bytes.FromHexString(bytecodeHex); + + (int depth, int pc) MSTORE_OPCODE_PTR_BREAK_POINT = (0, 6); + using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + { + IsStepByStepModeOn = false, + }; - tracer.SetBreakPoint(MSTORE_OPCODE_PTR_BREAK_POINT); + tracer.SetBreakPoint(MSTORE_OPCODE_PTR_BREAK_POINT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); - vmThread.Start(); + Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + vmThread.Start(); - while (vmThread.IsAlive) - { - if (tracer.CanReadState) + while (vmThread.IsAlive) { - // we alter the value stored in memory to force EQ check at the end to fail - tracer.CurrentState.Memory.SaveByte(31, 0x0A); + if (tracer.CanReadState) + { + // we alter the value stored in memory to force EQ check at the end to fail + tracer.CurrentState.Memory.SaveByte(31, 0x0A); - tracer.MoveNext(); + tracer.MoveNext(); + } } - } - - // we check if bytecode execution failed - var resultTraces = (tracer.InnerTracer as GethLikeTxMemoryTracer).BuildResult(); - Assert.IsTrue(resultTraces.ReturnValue[31] == 0); - } - [TestCase("6017806000526000511460005260206000f3")] - public void Use_Debug_Tracer_To_Check_Assertion_Live(string bytecodeHex) - { - // this bytecode create an infinite loop that keeps pushing 0x17 to the stack so it is bound to stackoverflow (or even to use up its gas) i.e : - byte[] bytecode = Bytes.FromHexString(bytecodeHex); + // we check if bytecode execution failed + var resultTraces = (tracer.InnerTracer as GethLikeTxTracer).BuildResult(); + Assert.IsTrue(resultTraces.ReturnValue[31] == 0); + } - (int depth, int pc) MSTORE_OPCODE_PTR_BREAK_POINT = (0, 6); - (int depth, int pc) POST_MSTORE_OPCODE_PTR_BREAK_POINT = MSTORE_OPCODE_PTR_BREAK_POINT with + [TestCase("6017806000526000511460005260206000f3")] + public void Use_Debug_Tracer_To_Check_Assertion_Live(string bytecodeHex) { - pc = MSTORE_OPCODE_PTR_BREAK_POINT.pc + 1 - }; + // this bytecode create an infinite loop that keeps pushing 0x17 to the stack so it is bound to stackoverflow (or even to use up its gas) i.e : + byte[] bytecode = Bytes.FromHexString(bytecodeHex); - using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) - { - IsStepByStepModeOn = false, - }; + (int depth, int pc) MSTORE_OPCODE_PTR_BREAK_POINT = (0, 6); + (int depth, int pc) POST_MSTORE_OPCODE_PTR_BREAK_POINT = MSTORE_OPCODE_PTR_BREAK_POINT with + { + pc = MSTORE_OPCODE_PTR_BREAK_POINT.pc + 1 + }; + + using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + { + IsStepByStepModeOn = false, + }; - tracer.SetBreakPoint(MSTORE_OPCODE_PTR_BREAK_POINT); - tracer.SetBreakPoint(POST_MSTORE_OPCODE_PTR_BREAK_POINT); + tracer.SetBreakPoint(MSTORE_OPCODE_PTR_BREAK_POINT); + tracer.SetBreakPoint(POST_MSTORE_OPCODE_PTR_BREAK_POINT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); - vmThread.Start(); + Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + vmThread.Start(); - long? gasAvailable_pre_MSTORE = null; - while (vmThread.IsAlive) - { - if (tracer.CanReadState) + long? gasAvailable_pre_MSTORE = null; + while (vmThread.IsAlive) { - // we alter the value stored in memory to force EQ check at the end to fail - if (gasAvailable_pre_MSTORE is null) gasAvailable_pre_MSTORE = tracer.CurrentState.GasAvailable; - else + if (tracer.CanReadState) { - long gasAvailable_post_MSTORE = tracer.CurrentState.GasAvailable; - Assert.That(gasAvailable_pre_MSTORE - gasAvailable_post_MSTORE, Is.EqualTo(GasCostOf.VeryLow)); + // we alter the value stored in memory to force EQ check at the end to fail + if (gasAvailable_pre_MSTORE is null) gasAvailable_pre_MSTORE = tracer.CurrentState.GasAvailable; + else + { + long gasAvailable_post_MSTORE = tracer.CurrentState.GasAvailable; + Assert.That(gasAvailable_pre_MSTORE - gasAvailable_post_MSTORE, Is.EqualTo(GasCostOf.VeryLow)); + } + tracer.MoveNext(); } - tracer.MoveNext(); } } - } - - [TestCase("ef601700")] - public void Use_Debug_Tracer_To_Check_failure_status(string bytecodeHex) - { - // this bytecode fails on first opcode INVALID - byte[] bytecode = Bytes.FromHexString(bytecodeHex); - using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + [TestCase("ef601700")] + public void Use_Debug_Tracer_To_Check_failure_status(string bytecodeHex) { - IsStepByStepModeOn = true, - }; + // this bytecode fails on first opcode INVALID + byte[] bytecode = Bytes.FromHexString(bytecodeHex); + + using DebugTracer tracer = new DebugTracer(GethLikeTxTracer) + { + IsStepByStepModeOn = true, + }; - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); - vmThread.Start(); + Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + vmThread.Start(); - while (vmThread.IsAlive) - { - if (tracer.CanReadState) + while (vmThread.IsAlive) { - tracer.MoveNext(); + if (tracer.CanReadState) + { + tracer.MoveNext(); + } } - } - // we check if bytecode execution failed - var resultTraces = (tracer.InnerTracer as GethLikeTxMemoryTracer).BuildResult(); - Assert.IsTrue(resultTraces.Failed); - } + // we check if bytecode execution failed + var resultTraces = (tracer.InnerTracer as GethLikeTxTracer).BuildResult(); + Assert.IsTrue(resultTraces.Failed); + } - [TestCase("0x716860176017601701500060005260096017f3600052601260006000f0")] - public void Debugger_stops_at_correct_breakpoint_depth(string bytecodeHex) - { - // this bytecode fails on first opcode INVALID - byte[] bytecode = Bytes.FromHexString(bytecodeHex); + [TestCase("0x716860176017601701500060005260096017f3600052601260006000f0")] + public void Debugger_stops_at_correct_breakpoint_depth(string bytecodeHex) + { + // this bytecode fails on first opcode INVALID + byte[] bytecode = Bytes.FromHexString(bytecodeHex); - (int depth, int pc) TARGET_OPCODE_PTR_BREAK_POINT = (1, 0); - using DebugTracer tracer = new DebugTracer(GethLikeTxTracer); + (int depth, int pc) TARGET_OPCODE_PTR_BREAK_POINT = (1, 0); + using DebugTracer tracer = new DebugTracer(GethLikeTxTracer); - tracer.SetBreakPoint(TARGET_OPCODE_PTR_BREAK_POINT); + tracer.SetBreakPoint(TARGET_OPCODE_PTR_BREAK_POINT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); - vmThread.Start(); + Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + vmThread.Start(); - bool stoppedAtCorrectBreakpoint = false; - while (vmThread.IsAlive) - { - if (tracer.CanReadState) + bool stoppedAtCorrectBreakpoint = false; + while (vmThread.IsAlive) { - if (tracer.CurrentState.Env.CallDepth == TARGET_OPCODE_PTR_BREAK_POINT.depth && tracer.CurrentState.ProgramCounter == TARGET_OPCODE_PTR_BREAK_POINT.pc) - { - stoppedAtCorrectBreakpoint = true; - } - else + if (tracer.CanReadState) { - stoppedAtCorrectBreakpoint = false; + if(tracer.CurrentState.Env.CallDepth == TARGET_OPCODE_PTR_BREAK_POINT.depth && tracer.CurrentState.ProgramCounter == TARGET_OPCODE_PTR_BREAK_POINT.pc) + { + stoppedAtCorrectBreakpoint = true; + } else + { + stoppedAtCorrectBreakpoint = false; + } + tracer.MoveNext(); } - tracer.MoveNext(); } - } - Assert.That(stoppedAtCorrectBreakpoint, Is.True); - } + Assert.That(stoppedAtCorrectBreakpoint, Is.True); + } - [TestCase("0x5b601760005600")] - public void Debugger_Halts_Execution_When_Global_Condition_Is_Met(string bytecodeHex) - { - // this bytecode fails on first opcode INVALID - byte[] bytecode = Bytes.FromHexString(bytecodeHex); + [TestCase("0x5b601760005600")] + public void Debugger_Halts_Execution_When_Global_Condition_Is_Met(string bytecodeHex) + { + // this bytecode fails on first opcode INVALID + byte[] bytecode = Bytes.FromHexString(bytecodeHex); - const int DATA_STACK_HEIGHT = 10; - using DebugTracer tracer = new DebugTracer(GethLikeTxTracer); + const int DATA_STACK_HEIGHT = 10; + using DebugTracer tracer = new DebugTracer(GethLikeTxTracer); - tracer.SetCondtion(state => state.DataStackHead == DATA_STACK_HEIGHT); + tracer.SetCondtion(state => state.DataStackHead == DATA_STACK_HEIGHT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); - vmThread.Start(); + Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + vmThread.Start(); - bool stoppedAtLeastOneTime = false; - while (vmThread.IsAlive) - { - if (tracer.CanReadState) + bool stoppedAtLeastOneTime = false; + while (vmThread.IsAlive) { - Assert.That(tracer.CurrentState.DataStackHead, Is.EqualTo(DATA_STACK_HEIGHT)); - stoppedAtLeastOneTime = true; - tracer.MoveNext(); + if (tracer.CanReadState) + { + Assert.That(tracer.CurrentState.DataStackHead, Is.EqualTo(DATA_STACK_HEIGHT)); + stoppedAtLeastOneTime = true; + tracer.MoveNext(); + } } - } - Assert.That(stoppedAtLeastOneTime, Is.True); - } + Assert.That(stoppedAtLeastOneTime, Is.True); + } - [TestCase("0x5b601760005600")] - public void Debugger_Wont_Halt_If_Breakpoint_Is_Unreacheable(string bytecodeHex) - { - byte[] bytecode = Bytes.FromHexString(bytecodeHex); + [TestCase("0x5b601760005600")] + public void Debugger_Wont_Halt_If_Breakpoint_Is_Unreacheable(string bytecodeHex) + { + byte[] bytecode = Bytes.FromHexString(bytecodeHex); - (int depth, int pc) TARGET_OPCODE_PTR_BREAK_POINT = (1, 0); - using DebugTracer tracer = new DebugTracer(GethLikeTxTracer); + (int depth, int pc) TARGET_OPCODE_PTR_BREAK_POINT = (1, 0); + using DebugTracer tracer = new DebugTracer(GethLikeTxTracer); - tracer.SetBreakPoint(TARGET_OPCODE_PTR_BREAK_POINT); + tracer.SetBreakPoint(TARGET_OPCODE_PTR_BREAK_POINT); - Thread vmThread = new Thread(() => Execute(tracer, bytecode)); - vmThread.Start(); + Thread vmThread = new Thread(() => Execute(tracer, bytecode)); + vmThread.Start(); - bool stoppedAtCorrectBreakpoint = false; - while (vmThread.IsAlive) - { - if (tracer.CanReadState) + bool stoppedAtCorrectBreakpoint = false; + while (vmThread.IsAlive) { - stoppedAtCorrectBreakpoint = true; - tracer.MoveNext(); + if (tracer.CanReadState) + { + stoppedAtCorrectBreakpoint = true; + tracer.MoveNext(); + } } - } - Assert.That(stoppedAtCorrectBreakpoint, Is.False); + Assert.That(stoppedAtCorrectBreakpoint, Is.False); + } } } #endif diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs index 28ef63cc595..eb9021f38f8 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs @@ -7,6 +7,7 @@ using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; +using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Db; @@ -141,9 +142,9 @@ public void Handles_well_errors() public void Handles_well_revert() { TestEnvironment testEnvironment = new(); - long gasLimit = 100_000_000; - Transaction tx = Build.A.Transaction.WithGasLimit(gasLimit).TestObject; - Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; + long gasLimit = 100000000; + Transaction tx = Build.A.Transaction.WithGasLimit(100000000).TestObject; + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; long gasLeft = gasLimit - 22000; testEnvironment.tracer.ReportAction(gasLeft, 0, Address.Zero, Address.Zero, Array.Empty(), diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeBlockFileTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeBlockFileTracerTests.cs deleted file mode 100644 index 8a8585b9861..00000000000 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeBlockFileTracerTests.cs +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Linq; -using FluentAssertions; -using Nethermind.Core.Extensions; -using Nethermind.Core.Crypto; -using Nethermind.Core.Test.Builders; -using Nethermind.Evm.Tracing; -using Nethermind.Evm.Tracing.GethStyle; -using NUnit.Framework; -using System.IO.Abstractions.TestingHelpers; - -namespace Nethermind.Evm.Test.Tracing; - -public class GethLikeBlockFileTracerTests : VirtualMachineTestsBase -{ - [Test] - public void Should_have_file_names_matching_block_and_transactions() - { - var fileSystem = new MockFileSystem(); - var block = Build.A.Block - .WithTransactions(new[] { - Build.A.Transaction.WithHash(Keccak.OfAnEmptyString).TestObject, - Build.A.Transaction.WithHash(Keccak.OfAnEmptySequenceRlp).TestObject - }) - .TestObject; - - var tracer = new GethLikeBlockFileTracer(block, GethTraceOptions.Default, fileSystem); - var blockTracer = (IBlockTracer)tracer; - - for (var i = 0; i < block.Transactions.Length; i++) - { - var tx = block.Transactions[i]; - - blockTracer.StartNewTxTrace(tx); - blockTracer.EndTxTrace(); - - var fileName = tracer.FileNames.Last(); - - fileName.Should().Contain($"block_{block.Hash.Bytes[..4].ToHexString(true)}-{i}-{tx.Hash.Bytes[..4].ToHexString(true)}-"); - fileName.Should().EndWith(".jsonl"); - } - } -} diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeBlockMemoryTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeBlockMemoryTracerTests.cs deleted file mode 100644 index 219a898f332..00000000000 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeBlockMemoryTracerTests.cs +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Linq; -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Core.Test.Builders; -using Nethermind.Evm.Tracing; -using Nethermind.Evm.Tracing.GethStyle; -using NUnit.Framework; - -namespace Nethermind.Evm.Test.Tracing; - -[TestFixture] -public class GethLikeBlockMemoryTracerTests -{ - [Test] - public void Starts_with_trace_set_to_null() - { - Keccak txHash = TestItem.KeccakA; - GethLikeBlockMemoryTracer blockTracer = new(GethTraceOptions.Default with { TxHash = txHash }); - Assert.IsNull(blockTracer.BuildResult().SingleOrDefault(), $"starts with trace set to null"); - } - - [Test] - public void Number_of_tx_traces_equals_number_of_txs_in_a_block() - { - Block block = Build.A.Block.TestObject; - block = block.WithReplacedBody(new BlockBody(new Transaction[3], new BlockHeader[0])); - - GethLikeBlockMemoryTracer blockTracer = new(GethTraceOptions.Default); - - for (int i = 0; i < block.Transactions.Length; i++) - { - ((IBlockTracer)blockTracer).StartNewTxTrace(Build.A.Transaction.TestObject); - ((IBlockTracer)blockTracer).EndTxTrace(); - } - - Assert.That(blockTracer.BuildResult().Count, Is.EqualTo(3)); - } - - [Test] - public void Records_trace_properly() - { - Block block = Build.A.Block.TestObject; - block = block.WithReplacedBody(new BlockBody(new Transaction[3], new BlockHeader[0])); - - GethLikeBlockMemoryTracer blockTracer = new(GethTraceOptions.Default); - ((IBlockTracer)blockTracer).StartNewTxTrace(Build.A.Transaction.SignedAndResolved(TestItem.PrivateKeyA).TestObject); - ((IBlockTracer)blockTracer).EndTxTrace(); - - ((IBlockTracer)blockTracer).StartNewTxTrace(Build.A.Transaction.SignedAndResolved(TestItem.PrivateKeyB).TestObject); - ((IBlockTracer)blockTracer).EndTxTrace(); - - ((IBlockTracer)blockTracer).StartNewTxTrace(Build.A.Transaction.SignedAndResolved(TestItem.PrivateKeyC).TestObject); - ((IBlockTracer)blockTracer).EndTxTrace(); - - Assert.NotNull(blockTracer.BuildResult().First(), "0"); - Assert.NotNull(blockTracer.BuildResult().Skip(1).First(), "1"); - Assert.NotNull(blockTracer.BuildResult().Last(), "2"); - } - - [Test] - [Ignore("It is not the actual behaviour at the moment")] - public void Throws_when_ending_without_starting() - { - Block block = Build.A.Block.TestObject; - block = block.WithReplacedBody(new BlockBody(new Transaction[3], new BlockHeader[0])); - block.Transactions[0] = Build.A.Transaction.TestObject; - block.Transactions[1] = Build.A.Transaction.TestObject; - block.Transactions[2] = Build.A.Transaction.TestObject; - - GethLikeBlockMemoryTracer blockTracer1 = new(GethTraceOptions.Default); - Assert.Throws(() => ((IBlockTracer)blockTracer1).EndTxTrace()); - - GethLikeBlockMemoryTracer blockTracer2 = new(GethTraceOptions.Default); - ((IBlockTracer)blockTracer2).StartNewTxTrace(block.Transactions[0]); - Assert.DoesNotThrow(() => ((IBlockTracer)blockTracer2).EndTxTrace()); - Assert.Throws(() => ((IBlockTracer)blockTracer2).EndTxTrace()); - } -} diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeBlockTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeBlockTracerTests.cs new file mode 100644 index 00000000000..5cdf946f0b9 --- /dev/null +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeBlockTracerTests.cs @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Linq; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Test.Builders; +using Nethermind.Evm.Tracing; +using Nethermind.Evm.Tracing.GethStyle; +using NUnit.Framework; + +namespace Nethermind.Evm.Test.Tracing +{ + [TestFixture] + public class GethLikeBlockTracerTests + { + [Test] + public void Starts_with_trace_set_to_null() + { + Keccak txHash = TestItem.KeccakA; + GethLikeBlockTracer blockTracer = new(txHash, GethTraceOptions.Default); + Assert.IsNull(blockTracer.BuildResult().SingleOrDefault(), $"starts with trace set to null"); + } + + [Test] + public void Number_of_tx_traces_equals_number_of_txs_in_a_block() + { + Block block = Build.A.Block.TestObject; + block = block.WithReplacedBody(new BlockBody(new Transaction[3], new BlockHeader[0])); + + GethLikeBlockTracer blockTracer = new(GethTraceOptions.Default); + + for (int i = 0; i < block.Transactions.Length; i++) + { + ((IBlockTracer)blockTracer).StartNewTxTrace(Build.A.Transaction.TestObject); + ((IBlockTracer)blockTracer).EndTxTrace(); + } + + Assert.That(blockTracer.BuildResult().Count, Is.EqualTo(3)); + } + + [Test] + public void Records_trace_properly() + { + Block block = Build.A.Block.TestObject; + block = block.WithReplacedBody(new BlockBody(new Transaction[3], new BlockHeader[0])); + + GethLikeBlockTracer blockTracer = new(GethTraceOptions.Default); + ((IBlockTracer)blockTracer).StartNewTxTrace(Build.A.Transaction.SignedAndResolved(TestItem.PrivateKeyA).TestObject); + ((IBlockTracer)blockTracer).EndTxTrace(); + + ((IBlockTracer)blockTracer).StartNewTxTrace(Build.A.Transaction.SignedAndResolved(TestItem.PrivateKeyB).TestObject); + ((IBlockTracer)blockTracer).EndTxTrace(); + + ((IBlockTracer)blockTracer).StartNewTxTrace(Build.A.Transaction.SignedAndResolved(TestItem.PrivateKeyC).TestObject); + ((IBlockTracer)blockTracer).EndTxTrace(); + + Assert.NotNull(blockTracer.BuildResult().First(), "0"); + Assert.NotNull(blockTracer.BuildResult().Skip(1).First(), "1"); + Assert.NotNull(blockTracer.BuildResult().Last(), "2"); + } + + [Test] + [Ignore("It is not the actual behaviour at the moment")] + public void Throws_when_ending_without_starting() + { + Block block = Build.A.Block.TestObject; + block = block.WithReplacedBody(new BlockBody(new Transaction[3], new BlockHeader[0])); + block.Transactions[0] = Build.A.Transaction.TestObject; + block.Transactions[1] = Build.A.Transaction.TestObject; + block.Transactions[2] = Build.A.Transaction.TestObject; + + GethLikeBlockTracer blockTracer1 = new(GethTraceOptions.Default); + Assert.Throws(() => ((IBlockTracer)blockTracer1).EndTxTrace()); + + GethLikeBlockTracer blockTracer2 = new(GethTraceOptions.Default); + ((IBlockTracer)blockTracer2).StartNewTxTrace(block.Transactions[0]); + Assert.DoesNotThrow(() => ((IBlockTracer)blockTracer2).EndTxTrace()); + Assert.Throws(() => ((IBlockTracer)blockTracer2).EndTxTrace()); + } + } +} diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeTxFileTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeTxFileTracerTests.cs deleted file mode 100644 index ad6a509a33e..00000000000 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeTxFileTracerTests.cs +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using System.Linq; -using System.Text.Json; -using FluentAssertions; -using Nethermind.Evm.Tracing.GethStyle; -using NUnit.Framework; - -namespace Nethermind.Evm.Test.Tracing; - -public class GethLikeTxFileTracerTests : VirtualMachineTestsBase -{ - [Test] - public void Should_have_expected_file_tracing_flags() - { - var tracer = new GethLikeTxFileTracer(e => { }, GethTraceOptions.Default); - - tracer.IsTracingMemory.Should().BeTrue(); - tracer.IsTracingOpLevelStorage.Should().BeFalse(); - tracer.IsTracingRefunds.Should().BeTrue(); - } - - [Test] - public void Should_return_gas_and_return_value_as_expected() - { - var trace = ExecuteAndTraceToFile(e => { }, GetBytecode(), GethTraceOptions.Default); - - trace.Gas.Should().Be(24); - trace.ReturnValue.Length.Should().Be(0); - } - - [Test] - public void Should_return_memory_size_with_memory_disabled() - { - var entries = new List(); - var trace = ExecuteAndTraceToFile(e => entries.Add(CloneTraceEntry(e)), GetBytecode(), GethTraceOptions.Default); - - entries[0].MemorySize.Should().Be(0); - entries[1].MemorySize.Should().Be(0); - entries[2].MemorySize.Should().Be(0); - entries[3].MemorySize.Should().Be(32); - entries[4].MemorySize.Should().Be(32); - entries[5].MemorySize.Should().Be(32); - entries[6].MemorySize.Should().Be(64); - - entries.All(e => e.Memory is null).Should().BeTrue(); - } - - [Test] - public void Should_return_memory_when_enabled() - { - var entries = new List(); - var trace = ExecuteAndTraceToFile(e => entries.Add(CloneTraceEntry(e)), GetBytecode(), GethTraceOptions.Default with { EnableMemory = true }); - - entries[0].Memory.Count.Should().Be(0); - entries[1].Memory.Count.Should().Be(0); - entries[2].Memory.Count.Should().Be(0); - entries[3].Memory.Count.Should().Be(1); - entries[4].Memory.Count.Should().Be(1); - entries[5].Memory.Count.Should().Be(1); - entries[6].Memory.Count.Should().Be(2); - } - - [Test] - public void Should_return_stack_when_enabled() - { - var entries = new List(); - var trace = ExecuteAndTraceToFile(e => entries.Add(CloneTraceEntry(e)), GetBytecode(), GethTraceOptions.Default); - - entries[0].Stack.Count.Should().Be(0); - entries[1].Stack.Count.Should().Be(1); - entries[2].Stack.Count.Should().Be(2); - entries[3].Stack.Count.Should().Be(0); - entries[4].Stack.Count.Should().Be(1); - entries[5].Stack.Count.Should().Be(2); - entries[6].Stack.Count.Should().Be(0); - } - - [Test] - public void Should_not_return_stack_when_disabled() - { - var entries = new List(); - var trace = ExecuteAndTraceToFile(e => entries.Add(CloneTraceEntry(e)), GetBytecode(), GethTraceOptions.Default with { DisableStack = true }); - - entries.All(e => e.Stack is null).Should().BeTrue(); - } - - /// - /// Clones the specified trace entry as - /// reuses the same instance for all entries. - /// - private static GethTxFileTraceEntry CloneTraceEntry(GethTxFileTraceEntry entry) => - JsonSerializer.Deserialize(JsonSerializer.Serialize(entry)); - - private static byte[] GetBytecode() => - Prepare.EvmCode - .PushData(SampleHexData1.PadLeft(64, '0')) - .PushData(0) - .Op(Instruction.MSTORE) - .PushData(SampleHexData2.PadLeft(64, '0')) - .PushData(32) - .Op(Instruction.MSTORE) - .Op(Instruction.STOP) - .Done; -} diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeTxMemoryTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeTxMemoryTracerTests.cs deleted file mode 100644 index 09d19f396a7..00000000000 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeTxMemoryTracerTests.cs +++ /dev/null @@ -1,397 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Linq; -using Nethermind.Core.Attributes; -using Nethermind.Core.Extensions; -using Nethermind.Core.Test.Builders; -using Nethermind.Evm.Tracing.GethStyle; -using NUnit.Framework; - -namespace Nethermind.Evm.Test.Tracing; - -[TestFixture] -[Parallelizable(ParallelScope.Self)] -public class GethLikeTxMemoryTracerTests : VirtualMachineTestsBase -{ - [Test] - public void Can_trace_gas() - { - byte[] code = Prepare.EvmCode - .PushData("0x1") - .PushData("0x2") - .Op(Instruction.ADD) - .Op(Instruction.STOP) - .Done; - - int[] gasCosts = new int[] { 3, 3, 3, 0 }; - - GethLikeTxTrace trace = ExecuteAndTrace(code); - - int gasTotal = 0; - for (int i = 0; i < gasCosts.Length; i++) - { - Assert.That(trace.Entries[i].Gas, Is.EqualTo(79000 - gasTotal), $"gas[{i}]"); - Assert.That(trace.Entries[i].GasCost, Is.EqualTo(gasCosts[i]), $"gasCost[{i}]"); - gasTotal += gasCosts[i]; - } - } - - [Test] - [Todo("Verify the exact error string in Geth")] - public void Can_trace_stack_underflow_failure() - { - byte[] code = Prepare.EvmCode - .Op(Instruction.ADD) - .Done; - - GethLikeTxTrace trace = ExecuteAndTrace(code); - Assert.That(trace.Failed, Is.EqualTo(true)); - Assert.That(trace.Entries[0].Error, Is.EqualTo("StackUnderflow")); - } - - [Test] - [Todo("Verify the exact error string in Geth")] - public void Can_trace_stack_overflow_failure() - { - byte[] code = Prepare.EvmCode - .Op(Instruction.JUMPDEST) - .PushData("0xab") - .PushData("0x0") - .Op(Instruction.JUMP) - .Done; - - GethLikeTxTrace trace = ExecuteAndTrace(code); - Assert.That(trace.Failed, Is.EqualTo(true)); - Assert.That(trace.Entries.Last().Error, Is.EqualTo("StackOverflow")); - } - - [Test] - [Todo("Verify the exact error string in Geth")] - public void Can_trace_invalid_jump_failure() - { - byte[] code = Prepare.EvmCode - .PushData("0xab") - .Op(Instruction.JUMP) - .Done; - - GethLikeTxTrace trace = ExecuteAndTrace(code); - Assert.That(trace.Failed, Is.EqualTo(true)); - Assert.That(trace.Entries.Last().Error, Is.EqualTo("BadJumpDestination")); - } - - [Test] - [Todo("Verify the exact error string in Geth")] - public void Can_trace_invalid_opcode_failure() - { - byte[] code = Prepare.EvmCode - .Op(Instruction.INVALID) - .Done; - - GethLikeTxTrace trace = ExecuteAndTrace(code); - Assert.That(trace.Failed, Is.EqualTo(true)); - Assert.That(trace.Entries.Last().Error, Is.EqualTo("BadInstruction")); - } - - [Test] - public void Can_trace_opcodes() - { - byte[] code = Prepare.EvmCode - .PushData("0xa01234") - .PushData("0x0") - .Op(Instruction.STOP) - .Done; - - string[] opCodes = new[] { "PUSH3", "PUSH1", "STOP" }; - - GethLikeTxTrace trace = ExecuteAndTrace(code); - for (int i = 0; i < opCodes.Length; i++) - { - Assert.That(trace.Entries[i].Opcode, Is.EqualTo(opCodes[i])); - } - } - - [Test] - public void Can_trace_call_depth() - { - byte[] deployedCode = new byte[3]; - - byte[] initCode = Prepare.EvmCode - .ForInitOf(deployedCode) - .Done; - - byte[] createCode = Prepare.EvmCode - .Create(initCode, 0) - .Op(Instruction.STOP) - .Done; - - TestState.CreateAccount(TestItem.AddressC, 1.Ether()); - TestState.InsertCode(TestItem.AddressC, createCode, Spec); - - byte[] code = Prepare.EvmCode - .Call(TestItem.AddressC, 50000) - .Op(Instruction.STOP) - .Done; - - GethLikeTxTrace trace = ExecuteAndTrace(code); - int[] depths = new int[] - { - 1, 1, 1, 1, 1, 1, 1, 1, // STACK FOR CALL - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // CALL - 3, 3, 3, 3, 3, 3, // CREATE - 2, // STOP - 1, // STOP - }; - - Assert.That(trace.Entries.Count, Is.EqualTo(depths.Length)); - for (int i = 0; i < depths.Length; i++) - { - Assert.That(trace.Entries[i].Depth, Is.EqualTo(depths[i]), $"entries[{i}]"); - } - } - - [Test] - public void Stack_is_cleared_and_restored_when_moving_between_call_levels() - { - byte[] deployedCode = new byte[3]; - - byte[] initCode = Prepare.EvmCode - .ForInitOf(deployedCode) - .Done; - - byte[] createCode = Prepare.EvmCode - .PushData(SampleHexData1) // just to test if stack is restored - .Create(initCode, 0) - .Op(Instruction.STOP) - .Done; - - TestState.CreateAccount(TestItem.AddressC, 1.Ether()); - TestState.InsertCode(TestItem.AddressC, createCode, Spec); - - byte[] code = Prepare.EvmCode - .PushData(SampleHexData1) // just to test if stack is restored - .Call(TestItem.AddressC, 50000) - .Op(Instruction.STOP) - .Done; - - GethLikeTxTrace trace = ExecuteAndTrace(code); - /* depths - { - 1, 1, 1, 1, 1, 1, 1, 1, 1, // SAMPLE STACK + STACK FOR CALL [0..8] - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // SAMPLE STACK + CALL [9..19] - 3, 3, 3, 3, 3, 3, // CREATE [20..25] - 2, // STOP [26] - 1, // STOP [27] - }; */ - - Assert.That(trace.Entries[0].Stack.Count, Is.EqualTo(0), "BEGIN 1"); - Assert.That(trace.Entries[8].Stack.Count, Is.EqualTo(8), "CALL FROM 1"); - Assert.That(trace.Entries[9].Stack.Count, Is.EqualTo(0), "BEGIN 2"); - Assert.That(trace.Entries[19].Stack.Count, Is.EqualTo(4), "CREATE FROM 2"); - Assert.That(trace.Entries[20].Stack.Count, Is.EqualTo(0), "BEGIN 3"); - Assert.That(trace.Entries[2].Stack.Count, Is.EqualTo(2), "END 3"); - Assert.That(trace.Entries[26].Stack.Count, Is.EqualTo(2), "END 2"); - Assert.That(trace.Entries[27].Stack.Count, Is.EqualTo(2), "END 1"); - } - - [Test] - public void Memory_is_cleared_and_restored_when_moving_between_call_levels() - { - byte[] deployedCode = new byte[3]; - - byte[] initCode = Prepare.EvmCode - .ForInitOf(deployedCode) - .Done; - - byte[] createCode = Prepare.EvmCode - .StoreDataInMemory(32, SampleHexData1.PadLeft(64, '0')) // just to test if memory is restored - .Create(initCode, 0) - .Op(Instruction.STOP) - .Done; - - TestState.CreateAccount(TestItem.AddressC, 1.Ether()); - TestState.InsertCode(TestItem.AddressC, createCode, Spec); - - byte[] code = Prepare.EvmCode - .StoreDataInMemory(64, SampleHexData2.PadLeft(64, '0')) // just to test if memory is restored - .Call(TestItem.AddressC, 50000) - .Op(Instruction.STOP) - .Done; - - GethLikeTxTrace trace = ExecuteAndTrace(code); - /* depths - { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // MEMORY + STACK FOR CALL [0..10] - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // MEMORY + CALL [11..23] - 3, 3, 3, 3, 3, 3, // CREATE [24..29] - 2, // STOP [30] - 1, // STOP [21] - }; */ - - Assert.That(trace.Entries[0].Memory.Count, Is.EqualTo(0), "BEGIN 1"); - Assert.That(trace.Entries[10].Memory.Count, Is.EqualTo(3), "CALL FROM 1"); - Assert.That(trace.Entries[11].Memory.Count, Is.EqualTo(0), "BEGIN 2"); - Assert.That(trace.Entries[23].Memory.Count, Is.EqualTo(2), "CREATE FROM 2"); - Assert.That(trace.Entries[24].Memory.Count, Is.EqualTo(0), "BEGIN 3"); - Assert.That(trace.Entries[29].Memory.Count, Is.EqualTo(1), "END 3"); - Assert.That(trace.Entries[30].Memory.Count, Is.EqualTo(2), "END 2"); - Assert.That(trace.Entries[31].Memory.Count, Is.EqualTo(3), "END 1"); - } - - [Test] - public void Storage_is_cleared_and_restored_when_moving_between_call_levels() - { - byte[] deployedCode = new byte[3]; - - byte[] initCode = Prepare.EvmCode - .ForInitOf(deployedCode) - .Done; - - byte[] createCode = Prepare.EvmCode - .PersistData("0x1", HexZero) // just to test if storage is restored - .Create(initCode, 0) - .Op(Instruction.STOP) - .Done; - - TestState.CreateAccount(TestItem.AddressC, 1.Ether()); - TestState.InsertCode(TestItem.AddressC, createCode, Spec); - - byte[] code = Prepare.EvmCode - .PersistData("0x2", HexZero) // just to test if storage is restored - .PersistData("0x3", HexZero) // just to test if storage is restored - .Call(TestItem.AddressC, 70000) - .Op(Instruction.STOP) - .Done; - - GethLikeTxTrace trace = ExecuteAndTrace(code); - /* depths - { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 2x SSTORE + STACK FOR CALL [0..13] - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // SSTORE + CALL [14..26] - 3, 3, 3, 3, 3, 3, // CREATE [27..32] - 2, // STOP [33] - 1, // STOP [34] - }; */ - - Assert.That(trace.Entries[0].Storage.Count, Is.EqualTo(0), "BEGIN 1"); - Assert.That(trace.Entries[13].Storage.Count, Is.EqualTo(2), "CALL FROM 1"); - Assert.That(trace.Entries[14].Storage.Count, Is.EqualTo(0), "BEGIN 2"); - Assert.That(trace.Entries[26].Storage.Count, Is.EqualTo(1), "CREATE FROM 2"); - Assert.That(trace.Entries[27].Storage.Count, Is.EqualTo(0), "BEGIN 3"); - Assert.That(trace.Entries[32].Storage.Count, Is.EqualTo(0), "END 3"); - Assert.That(trace.Entries[33].Storage.Count, Is.EqualTo(1), "END 2"); - Assert.That(trace.Entries[34].Storage.Count, Is.EqualTo(2), "END 1"); - } - - [Test] - public void Can_trace_pc() - { - byte[] code = Prepare.EvmCode - .PushData("0x0") // 0 - .Op(Instruction.JUMPDEST) // 2 - .PushData("0x1") // 3 - .Op(Instruction.ADD) // 5 - .Op(Instruction.DUP1) // 6 - .PushData("0x3") // 7 - .Op(Instruction.GT) // 9 - .PushData("0x2") // 10 - .Op(Instruction.JUMPI) // 12 - .Op(Instruction.STOP) // 13 - .Done; - - int[] pcs = new[] { 0, 2, 3, 5, 6, 7, 9, 10, 12, 2, 3, 5, 6, 7, 9, 10, 12, 2, 3, 5, 6, 7, 9, 10, 12, 13 }; - - GethLikeTxTrace trace = ExecuteAndTrace(code); - Assert.That(trace.Entries.Count, Is.EqualTo(pcs.Length)); - for (int i = 0; i < pcs.Length; i++) - { - Assert.That(trace.Entries[i].ProgramCounter, Is.EqualTo(pcs[i])); - } - } - - [Test] - public void Can_trace_stack() - { - byte[] code = Prepare.EvmCode - .PushData(SampleHexData1) - .PushData(HexZero) - .Op(Instruction.POP) - .Op(Instruction.STOP) - .Done; - - GethLikeTxTrace trace = ExecuteAndTrace(code); - - Assert.That(trace.Entries[0].Stack.Count, Is.EqualTo(0), "entry[0] length"); - - Assert.That(trace.Entries[1].Stack.Count, Is.EqualTo(1), "entry[1] length"); - Assert.That(trace.Entries[1].Stack[0], Is.EqualTo($"0x{SampleHexData1}"), "entry[1][0]"); - - Assert.That(trace.Entries[2].Stack.Count, Is.EqualTo(2), "entry[2] length"); - Assert.That(trace.Entries[2].Stack[0], Is.EqualTo($"0x{SampleHexData1}"), "entry[2][0]"); - Assert.That(trace.Entries[2].Stack[1], Is.EqualTo("0x0"), "entry[2][1]"); - - Assert.That(trace.Entries[3].Stack.Count, Is.EqualTo(1), "entry[3] length"); - Assert.That(trace.Entries[3].Stack[0], Is.EqualTo($"0x{SampleHexData1}"), "entry[3][0]"); - } - - [Test] - public void Can_trace_memory() - { - byte[] code = Prepare.EvmCode - .PushData(SampleHexData1.PadLeft(64, '0')) - .PushData(0) - .Op(Instruction.MSTORE) - .PushData(SampleHexData2.PadLeft(64, '0')) - .PushData(32) - .Op(Instruction.MSTORE) - .Op(Instruction.STOP) - .Done; - - GethLikeTxTrace trace = ExecuteAndTrace(code); - - /* note the curious Geth trace behaviour where memory grows now but is populated from the next trace entry */ - - Assert.That(trace.Entries[0].Memory.Count, Is.EqualTo(0), "entry[0] length"); - - Assert.That(trace.Entries[1].Memory.Count, Is.EqualTo(0), "entry[1] length"); - - Assert.That(trace.Entries[2].Memory.Count, Is.EqualTo(0), "entry[2] length"); - - Assert.That(trace.Entries[3].Memory.Count, Is.EqualTo(1), "entry[3] length"); - Assert.That(trace.Entries[3].Memory[0], Is.EqualTo(SampleHexData1.PadLeft(64, '0')), "entry[3][0]"); - - Assert.That(trace.Entries[4].Memory.Count, Is.EqualTo(1), "entry[4] length"); - Assert.That(trace.Entries[4].Memory[0], Is.EqualTo(SampleHexData1.PadLeft(64, '0')), "entry[4][0]"); - - Assert.That(trace.Entries[5].Memory.Count, Is.EqualTo(1), "entry[5] length"); - Assert.That(trace.Entries[5].Memory[0], Is.EqualTo(SampleHexData1.PadLeft(64, '0')), "entry[5][0]"); - } - - [Test] - public void Can_trace_extcodesize_optimization() - { - // From https://github.com/NethermindEth/nethermind/issues/5717 - byte[] code = Bytes.FromHexString("0x60246044607460d1606b60b9603369866833515b6d086c607f3b15749e4886579008320052006f"); - - GethLikeTxTrace trace = ExecuteAndTrace(code); - GethTxTraceEntry entry; - - entry = trace.Entries[^3]; - Assert.That(entry.ProgramCounter, Is.EqualTo(25)); - Assert.That(entry.Opcode, Is.EqualTo("EXTCODESIZE")); - Assert.That(entry.Stack[^1], Is.EqualTo("0x866833515b6d086c607f")); - Assert.That(entry.Stack.Count, Is.EqualTo(8)); - - entry = trace.Entries[^2]; - Assert.That(entry.ProgramCounter, Is.EqualTo(26)); - Assert.That(entry.Opcode, Is.EqualTo("ISZERO")); - Assert.That(entry.Stack[^1], Is.EqualTo("0x0")); - Assert.That(entry.Stack.Count, Is.EqualTo(8)); - - entry = trace.Entries[^1]; - Assert.That(entry.ProgramCounter, Is.EqualTo(27)); - Assert.That(entry.Opcode, Is.EqualTo("PUSH21")); - Assert.That(entry.Stack[^1], Is.EqualTo("0x1")); - Assert.That(entry.Stack.Count, Is.EqualTo(8)); - } -} diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeTxTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeTxTracerTests.cs new file mode 100644 index 00000000000..83fef4fb13f --- /dev/null +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/GethLikeTxTracerTests.cs @@ -0,0 +1,405 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Linq; +using Nethermind.Core.Attributes; +using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; +using Nethermind.Core.Test.Builders; +using Nethermind.Evm.Tracing.GethStyle; +using NUnit.Framework; + +namespace Nethermind.Evm.Test.Tracing +{ + [TestFixture] + [Parallelizable(ParallelScope.Self)] + public class GethLikeTxTracerTests : VirtualMachineTestsBase + { + [Test] + public void Can_trace_gas() + { + byte[] code = Prepare.EvmCode + .PushData("0x1") + .PushData("0x2") + .Op(Instruction.ADD) + .Op(Instruction.STOP) + .Done; + + int[] gasCosts = new int[] { 3, 3, 3, 0 }; + + GethLikeTxTrace trace = ExecuteAndTrace(code); + + int gasTotal = 0; + for (int i = 0; i < gasCosts.Length; i++) + { + Assert.That(trace.Entries[i].Gas, Is.EqualTo(79000 - gasTotal), $"gas[{i}]"); + Assert.That(trace.Entries[i].GasCost, Is.EqualTo(gasCosts[i]), $"gasCost[{i}]"); + gasTotal += gasCosts[i]; + } + } + + [Test] + [Todo("Verify the exact error string in Geth")] + public void Can_trace_stack_underflow_failure() + { + byte[] code = Prepare.EvmCode + .Op(Instruction.ADD) + .Done; + + GethLikeTxTrace trace = ExecuteAndTrace(code); + Assert.That(trace.Failed, Is.EqualTo(true)); + Assert.That(trace.Entries[0].Error, Is.EqualTo("StackUnderflow")); + } + + [Test] + [Todo("Verify the exact error string in Geth")] + public void Can_trace_stack_overflow_failure() + { + byte[] code = Prepare.EvmCode + .Op(Instruction.JUMPDEST) + .PushData("0xab") + .PushData("0x0") + .Op(Instruction.JUMP) + .Done; + + GethLikeTxTrace trace = ExecuteAndTrace(code); + Assert.That(trace.Failed, Is.EqualTo(true)); + Assert.That(trace.Entries.Last().Error, Is.EqualTo("StackOverflow")); + } + + [Test] + [Todo("Verify the exact error string in Geth")] + public void Can_trace_invalid_jump_failure() + { + byte[] code = Prepare.EvmCode + .PushData("0xab") + .Op(Instruction.JUMP) + .Done; + + GethLikeTxTrace trace = ExecuteAndTrace(code); + Assert.That(trace.Failed, Is.EqualTo(true)); + Assert.That(trace.Entries.Last().Error, Is.EqualTo("BadJumpDestination")); + } + + [Test] + [Todo("Verify the exact error string in Geth")] + public void Can_trace_invalid_opcode_failure() + { + byte[] code = Prepare.EvmCode + .Op(Instruction.INVALID) + .Done; + + GethLikeTxTrace trace = ExecuteAndTrace(code); + Assert.That(trace.Failed, Is.EqualTo(true)); + Assert.That(trace.Entries.Last().Error, Is.EqualTo("BadInstruction")); + } + + [Test] + public void Can_trace_opcodes() + { + byte[] code = Prepare.EvmCode + .PushData("0xa01234") + .PushData("0x0") + .Op(Instruction.STOP) + .Done; + + string[] opCodes = new[] { "PUSH3", "PUSH1", "STOP" }; + + GethLikeTxTrace trace = ExecuteAndTrace(code); + for (int i = 0; i < opCodes.Length; i++) + { + Assert.That(trace.Entries[i].Operation, Is.EqualTo(opCodes[i])); + } + } + + [Test] + public void Can_trace_call_depth() + { + byte[] deployedCode = new byte[3]; + + byte[] initCode = Prepare.EvmCode + .ForInitOf(deployedCode) + .Done; + + byte[] createCode = Prepare.EvmCode + .Create(initCode, 0) + .Op(Instruction.STOP) + .Done; + + TestState.CreateAccount(TestItem.AddressC, 1.Ether()); + TestState.InsertCode(TestItem.AddressC, createCode, Spec); + + byte[] code = Prepare.EvmCode + .Call(TestItem.AddressC, 50000) + .Op(Instruction.STOP) + .Done; + + GethLikeTxTrace trace = ExecuteAndTrace(code); + int[] depths = new int[] + { + 1, 1, 1, 1, 1, 1, 1, 1, // STACK FOR CALL + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // CALL + 3, 3, 3, 3, 3, 3, // CREATE + 2, // STOP + 1, // STOP + }; + + Assert.That(trace.Entries.Count, Is.EqualTo(depths.Length)); + for (int i = 0; i < depths.Length; i++) + { + Assert.That(trace.Entries[i].Depth, Is.EqualTo(depths[i]), $"entries[{i}]"); + } + } + + [Test] + public void Stack_is_cleared_and_restored_when_moving_between_call_levels() + { + byte[] deployedCode = new byte[3]; + + byte[] initCode = Prepare.EvmCode + .ForInitOf(deployedCode) + .Done; + + byte[] createCode = Prepare.EvmCode + .PushData(SampleHexData1) // just to test if stack is restored + .Create(initCode, 0) + .Op(Instruction.STOP) + .Done; + + TestState.CreateAccount(TestItem.AddressC, 1.Ether()); + TestState.InsertCode(TestItem.AddressC, createCode, Spec); + + byte[] code = Prepare.EvmCode + .PushData(SampleHexData1) // just to test if stack is restored + .Call(TestItem.AddressC, 50000) + .Op(Instruction.STOP) + .Done; + + GethLikeTxTrace trace = ExecuteAndTrace(code); + /* depths + { + 1, 1, 1, 1, 1, 1, 1, 1, 1, // SAMPLE STACK + STACK FOR CALL [0..8] + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // SAMPLE STACK + CALL [9..19] + 3, 3, 3, 3, 3, 3, // CREATE [20..25] + 2, // STOP [26] + 1, // STOP [27] + }; */ + + Assert.That(trace.Entries[0].Stack.Count, Is.EqualTo(0), "BEGIN 1"); + Assert.That(trace.Entries[8].Stack.Count, Is.EqualTo(8), "CALL FROM 1"); + Assert.That(trace.Entries[9].Stack.Count, Is.EqualTo(0), "BEGIN 2"); + Assert.That(trace.Entries[19].Stack.Count, Is.EqualTo(4), "CREATE FROM 2"); + Assert.That(trace.Entries[20].Stack.Count, Is.EqualTo(0), "BEGIN 3"); + Assert.That(trace.Entries[2].Stack.Count, Is.EqualTo(2), "END 3"); + Assert.That(trace.Entries[26].Stack.Count, Is.EqualTo(2), "END 2"); + Assert.That(trace.Entries[27].Stack.Count, Is.EqualTo(2), "END 1"); + } + + [Test] + public void Memory_is_cleared_and_restored_when_moving_between_call_levels() + { + byte[] deployedCode = new byte[3]; + + byte[] initCode = Prepare.EvmCode + .ForInitOf(deployedCode) + .Done; + + byte[] createCode = Prepare.EvmCode + .StoreDataInMemory(32, SampleHexData1.PadLeft(64, '0')) // just to test if memory is restored + .Create(initCode, 0) + .Op(Instruction.STOP) + .Done; + + TestState.CreateAccount(TestItem.AddressC, 1.Ether()); + TestState.InsertCode(TestItem.AddressC, createCode, Spec); + + byte[] code = Prepare.EvmCode + .StoreDataInMemory(64, SampleHexData2.PadLeft(64, '0')) // just to test if memory is restored + .Call(TestItem.AddressC, 50000) + .Op(Instruction.STOP) + .Done; + + GethLikeTxTrace trace = ExecuteAndTrace(code); + /* depths + { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // MEMORY + STACK FOR CALL [0..10] + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // MEMORY + CALL [11..23] + 3, 3, 3, 3, 3, 3, // CREATE [24..29] + 2, // STOP [30] + 1, // STOP [21] + }; */ + + Assert.That(trace.Entries[0].Memory.Count, Is.EqualTo(0), "BEGIN 1"); + Assert.That(trace.Entries[10].Memory.Count, Is.EqualTo(3), "CALL FROM 1"); + Assert.That(trace.Entries[11].Memory.Count, Is.EqualTo(0), "BEGIN 2"); + Assert.That(trace.Entries[23].Memory.Count, Is.EqualTo(2), "CREATE FROM 2"); + Assert.That(trace.Entries[24].Memory.Count, Is.EqualTo(0), "BEGIN 3"); + Assert.That(trace.Entries[29].Memory.Count, Is.EqualTo(1), "END 3"); + Assert.That(trace.Entries[30].Memory.Count, Is.EqualTo(2), "END 2"); + Assert.That(trace.Entries[31].Memory.Count, Is.EqualTo(3), "END 1"); + } + + [Test] + public void Storage_is_cleared_and_restored_when_moving_between_call_levels() + { + byte[] deployedCode = new byte[3]; + + byte[] initCode = Prepare.EvmCode + .ForInitOf(deployedCode) + .Done; + + byte[] createCode = Prepare.EvmCode + .PersistData("0x1", HexZero) // just to test if storage is restored + .Create(initCode, 0) + .Op(Instruction.STOP) + .Done; + + TestState.CreateAccount(TestItem.AddressC, 1.Ether()); + TestState.InsertCode(TestItem.AddressC, createCode, Spec); + + byte[] code = Prepare.EvmCode + .PersistData("0x2", HexZero) // just to test if storage is restored + .PersistData("0x3", HexZero) // just to test if storage is restored + .Call(TestItem.AddressC, 70000) + .Op(Instruction.STOP) + .Done; + + GethLikeTxTrace trace = ExecuteAndTrace(code); + /* depths + { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 2x SSTORE + STACK FOR CALL [0..13] + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // SSTORE + CALL [14..26] + 3, 3, 3, 3, 3, 3, // CREATE [27..32] + 2, // STOP [33] + 1, // STOP [34] + }; */ + + Assert.That(trace.Entries[0].SortedStorage.Count, Is.EqualTo(0), "BEGIN 1"); + Assert.That(trace.Entries[13].SortedStorage.Count, Is.EqualTo(2), "CALL FROM 1"); + Assert.That(trace.Entries[14].SortedStorage.Count, Is.EqualTo(0), "BEGIN 2"); + Assert.That(trace.Entries[26].SortedStorage.Count, Is.EqualTo(1), "CREATE FROM 2"); + Assert.That(trace.Entries[27].SortedStorage.Count, Is.EqualTo(0), "BEGIN 3"); + Assert.That(trace.Entries[32].SortedStorage.Count, Is.EqualTo(0), "END 3"); + Assert.That(trace.Entries[33].SortedStorage.Count, Is.EqualTo(1), "END 2"); + Assert.That(trace.Entries[34].SortedStorage.Count, Is.EqualTo(2), "END 1"); + } + + [Test] + public void Can_trace_pc() + { + byte[] code = Prepare.EvmCode + .PushData("0x0") // 0 + .Op(Instruction.JUMPDEST) // 2 + .PushData("0x1") // 3 + .Op(Instruction.ADD) // 5 + .Op(Instruction.DUP1) // 6 + .PushData("0x3") // 7 + .Op(Instruction.GT) // 9 + .PushData("0x2") // 10 + .Op(Instruction.JUMPI) // 12 + .Op(Instruction.STOP) // 13 + .Done; + + int[] pcs = new[] { 0, 2, 3, 5, 6, 7, 9, 10, 12, 2, 3, 5, 6, 7, 9, 10, 12, 2, 3, 5, 6, 7, 9, 10, 12, 13 }; + + GethLikeTxTrace trace = ExecuteAndTrace(code); + Assert.That(trace.Entries.Count, Is.EqualTo(pcs.Length)); + for (int i = 0; i < pcs.Length; i++) + { + Assert.That(trace.Entries[i].Pc, Is.EqualTo(pcs[i])); + } + } + + [Test] + public void Can_trace_stack() + { + byte[] code = Prepare.EvmCode + .PushData(SampleHexData1) + .PushData(HexZero) + .Op(Instruction.POP) + .Op(Instruction.STOP) + .Done; + + GethLikeTxTrace trace = ExecuteAndTrace(code); + + Assert.That(trace.Entries[0].Stack.Count, Is.EqualTo(0), "entry[0] length"); + + Assert.That(trace.Entries[1].Stack.Count, Is.EqualTo(1), "entry[1] length"); + Assert.That(trace.Entries[1].Stack[0], Is.EqualTo(SampleHexData1.PadLeft(64, '0')), "entry[1][0]"); + + Assert.That(trace.Entries[2].Stack.Count, Is.EqualTo(2), "entry[2] length"); + Assert.That(trace.Entries[2].Stack[0], Is.EqualTo(SampleHexData1.PadLeft(64, '0')), "entry[2][0]"); + Assert.That(trace.Entries[2].Stack[1], Is.EqualTo(HexZero.PadLeft(64, '0')), "entry[2][1]"); + + Assert.That(trace.Entries[3].Stack.Count, Is.EqualTo(1), "entry[3] length"); + Assert.That(trace.Entries[3].Stack[0], Is.EqualTo(SampleHexData1.PadLeft(64, '0')), "entry[3][0]"); + } + + [Test] + public void Can_trace_memory() + { + byte[] code = Prepare.EvmCode + .PushData(SampleHexData1.PadLeft(64, '0')) + .PushData(0) + .Op(Instruction.MSTORE) + .PushData(SampleHexData2.PadLeft(64, '0')) + .PushData(32) + .Op(Instruction.MSTORE) + .Op(Instruction.STOP) + .Done; + + GethLikeTxTrace trace = ExecuteAndTrace(code); + + /* note the curious Geth trace behaviour where memory grows now but is populated from the next trace entry */ + + Assert.That(trace.Entries[0].Memory.Count, Is.EqualTo(0), "entry[0] length"); + + Assert.That(trace.Entries[1].Memory.Count, Is.EqualTo(0), "entry[1] length"); + + Assert.That(trace.Entries[2].Memory.Count, Is.EqualTo(1), "entry[2] length"); + Assert.That(trace.Entries[2].Memory[0], Is.EqualTo(HexZero.PadLeft(64, '0')), "entry[2][0]"); + + Assert.That(trace.Entries[3].Memory.Count, Is.EqualTo(1), "entry[3] length"); + Assert.That(trace.Entries[3].Memory[0], Is.EqualTo(SampleHexData1.PadLeft(64, '0')), "entry[3][0]"); + + Assert.That(trace.Entries[4].Memory.Count, Is.EqualTo(1), "entry[4] length"); + Assert.That(trace.Entries[4].Memory[0], Is.EqualTo(SampleHexData1.PadLeft(64, '0')), "entry[4][0]"); + + Assert.That(trace.Entries[5].Memory.Count, Is.EqualTo(2), "entry[5] length"); + Assert.That(trace.Entries[5].Memory[0], Is.EqualTo(SampleHexData1.PadLeft(64, '0')), "entry[5][0]"); + Assert.That(trace.Entries[5].Memory[1], Is.EqualTo(HexZero.PadLeft(64, '0')), "entry[5][1]"); + + Assert.That(trace.Entries[6].Memory.Count, Is.EqualTo(2), "entry[2] length"); + Assert.That(trace.Entries[6].Memory[0], Is.EqualTo(SampleHexData1.PadLeft(64, '0')), "entry[6][0]"); + Assert.That(trace.Entries[6].Memory[1], Is.EqualTo(SampleHexData2.PadLeft(64, '0')), "entry[6][1]"); + } + + [Test] + public void Can_trace_extcodesize_optimization() + { + // From https://github.com/NethermindEth/nethermind/issues/5717 + byte[] code = Bytes.FromHexString("0x60246044607460d1606b60b9603369866833515b6d086c607f3b15749e4886579008320052006f"); + + GethLikeTxTrace trace = ExecuteAndTrace(code); + GethTxTraceEntry entry; + + entry = trace.Entries[^3]; + Assert.That(entry.Pc, Is.EqualTo(25)); + Assert.That(entry.Operation, Is.EqualTo("EXTCODESIZE")); + Assert.That(entry.Stack[^1], Is.EqualTo("866833515b6d086c607f".PadLeft(64, '0'))); + Assert.That(entry.Stack.Count, Is.EqualTo(8)); + + entry = trace.Entries[^2]; + Assert.That(entry.Pc, Is.EqualTo(26)); + Assert.That(entry.Operation, Is.EqualTo("ISZERO")); + Assert.That(entry.Stack[^1], Is.EqualTo("0".PadLeft(64, '0'))); + Assert.That(entry.Stack.Count, Is.EqualTo(8)); + + entry = trace.Entries[^1]; + Assert.That(entry.Pc, Is.EqualTo(27)); + Assert.That(entry.Operation, Is.EqualTo("PUSH21")); + Assert.That(entry.Stack[^1], Is.EqualTo("1".PadLeft(64, '0'))); + Assert.That(entry.Stack.Count, Is.EqualTo(8)); + } + } +} diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/ParityLikeTxTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/ParityLikeTxTracerTests.cs index a49df9e8e1f..c4cc04974c4 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/ParityLikeTxTracerTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/ParityLikeTxTracerTests.cs @@ -6,6 +6,7 @@ using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Attributes; +using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Int256; @@ -569,7 +570,7 @@ public void Can_trace_static_calls() public void Can_trace_precompile_calls() { byte[] code = Prepare.EvmCode - .Call(IdentityPrecompile.Address, 50000) + .Call(IdentityPrecompile.Instance.Address, 50000) .Op(Instruction.STOP) .Done; @@ -582,15 +583,16 @@ public void Can_trace_precompile_calls() 1, // STOP }; - Assert.That(trace.Action.Subtraces.Count, Is.EqualTo(0), "Should ignore precompile"); + Assert.That(trace.Action.Subtraces[0].CallType, Is.EqualTo("call"), "[0] type"); + Assert.That(trace.Action.Subtraces[0].To, Is.EqualTo(IdentityPrecompile.Instance.Address), "[0] to"); } [Test] public void Can_ignore_precompile_calls_in_contract() { byte[] deployedCode = Prepare.EvmCode - .Call(IdentityPrecompile.Address, 50000) - .CallWithValue(IdentityPrecompile.Address, 50000, 1.Ether()) + .Call(IdentityPrecompile.Instance.Address, 50000) + .CallWithValue(IdentityPrecompile.Instance.Address, 50000, 1.Ether()) .Op(Instruction.STOP) .Done; @@ -598,25 +600,35 @@ public void Can_ignore_precompile_calls_in_contract() TestState.InsertCode(TestItem.AddressC, deployedCode, Spec); byte[] code = Prepare.EvmCode - .Call(IdentityPrecompile.Address, 50000) + .Call(IdentityPrecompile.Instance.Address, 50000) .Call(TestItem.AddressC, 40000) .Op(Instruction.STOP) .Done; (ParityLikeTxTrace trace, Block block, Transaction tx) = ExecuteAndTraceParityCall(code); - // call to AddressC and should ignore precompile - Assert.That(trace.Action.Subtraces.Count, Is.EqualTo(1), "[] subtraces"); + // One call to precompile and the other call to AddressC + Assert.That(trace.Action.Subtraces.Count, Is.EqualTo(2), "[] subtraces"); Assert.That(trace.Action.CallType, Is.EqualTo("call"), "[] type"); + // Precompile call + Assert.That(trace.Action.Subtraces[0].Subtraces.Count, Is.EqualTo(0), "[0] subtraces"); + Assert.That(trace.Action.Subtraces[0].CallType, Is.EqualTo("call"), "[0] type"); + Assert.That(trace.Action.Subtraces[0].To, Is.EqualTo(IdentityPrecompile.Instance.Address), "[0] to"); + // AddressC call - only one call - Assert.That(trace.Action.Subtraces[0].Subtraces.Count, Is.EqualTo(1), "[1] subtraces"); - Assert.That(trace.Action.Subtraces[0].CallType, Is.EqualTo("call"), "[1] type"); + Assert.That(trace.Action.Subtraces[1].Subtraces.Count, Is.EqualTo(2), "[1] subtraces"); + Assert.That(trace.Action.Subtraces[1].CallType, Is.EqualTo("call"), "[1] type"); + + // Check the 1st subtrace - a precompile call + Assert.That(trace.Action.Subtraces[1].Subtraces[0].Subtraces.Count, Is.EqualTo(0), "[1, 0] subtraces"); + Assert.That(trace.Action.Subtraces[1].Subtraces[0].CallType, Is.EqualTo("call"), "[1, 0] type"); + Assert.That(trace.Action.Subtraces[1].Subtraces[0].IncludeInTrace, Is.EqualTo(false), "[1, 0] type"); // Check the 2nd subtrace - a precompile call with value - must be included - Assert.That(trace.Action.Subtraces[0].Subtraces[0].Subtraces.Count, Is.EqualTo(0), "[1, 1] subtraces"); - Assert.That(trace.Action.Subtraces[0].Subtraces[0].CallType, Is.EqualTo("call"), "[1, 1] type"); - Assert.That(trace.Action.Subtraces[0].Subtraces[0].IncludeInTrace, Is.EqualTo(true), "[1, 1] type"); + Assert.That(trace.Action.Subtraces[1].Subtraces[1].Subtraces.Count, Is.EqualTo(0), "[1, 1] subtraces"); + Assert.That(trace.Action.Subtraces[1].Subtraces[1].CallType, Is.EqualTo("call"), "[1, 1] type"); + Assert.That(trace.Action.Subtraces[1].Subtraces[1].IncludeInTrace, Is.EqualTo(true), "[1, 1] type"); } [Test] @@ -814,7 +826,7 @@ public void Is_tracing_rewards_only_when_rewards_trace_type_selected() private (ParityLikeTxTrace trace, Block block, Transaction tx) ExecuteInitAndTraceParityCall(params byte[] code) { - (Block block, Transaction transaction) = PrepareInitTx((BlockNumber, Timestamp), 100000, code); + (Block block, Transaction transaction) = PrepareInitTx(BlockNumber, 100000, code); ParityLikeTxTracer tracer = new(block, transaction, ParityTraceTypes.Trace | ParityTraceTypes.StateDiff); _processor.Execute(transaction, block.Header, tracer); return (tracer.BuildResult(), block, transaction); diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs index 278dde24f1f..6408fa4afe2 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs @@ -41,10 +41,9 @@ public void Setup() } - [TestCaseSource(nameof(BalanceIsAffectedByBlobGasTestCaseSource))] + [TestCaseSource(nameof(BalanceIsAffectedByDataGasTestCaseSource))] [TestCaseSource(nameof(BalanceIsNotAffectedWhenNotEnoughFunds))] - public UInt256 Balance_is_affected_by_blob_gas_on_execution(UInt256 balance, int blobCount, - ulong maxFeePerBlobGas, ulong excessBlobGas, ulong value) + public UInt256 Balance_is_affected_by_data_gas(UInt256 balance, int blobCount, ulong maxFeePerDataGas, ulong excessDataGas) { _stateProvider.CreateAccount(TestItem.AddressA, balance); _stateProvider.Commit(_specProvider.GenesisSpec); @@ -52,10 +51,10 @@ public UInt256 Balance_is_affected_by_blob_gas_on_execution(UInt256 balance, int long gasLimit = GasCostOf.Transaction; Transaction blobTx = Build.A.Transaction - .WithValue(value) + .WithValue(0) .WithGasPrice(1) .WithMaxFeePerGas(1) - .WithMaxFeePerBlobGas(maxFeePerBlobGas) + .WithMaxFeePerDataGas(maxFeePerDataGas) .WithGasLimit(gasLimit) .WithShardBlobTxTypeAndFields(blobCount) .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA) @@ -65,85 +64,93 @@ public UInt256 Balance_is_affected_by_blob_gas_on_execution(UInt256 balance, int .WithNumber(1) .WithTransactions(blobTx) .WithGasLimit(gasLimit) - .WithExcessBlobGas(excessBlobGas) + .WithExcessDataGas(excessDataGas) .WithBaseFeePerGas(1) .TestObject; - _transactionProcessor.CallAndRestore(blobTx, block.Header, NullTxTracer.Instance); - UInt256 deltaBalance = balance - _stateProvider.GetBalance(TestItem.PrivateKeyA.Address); - Assert.That(deltaBalance, Is.EqualTo(UInt256.Zero)); - _transactionProcessor.Execute(blobTx, block.Header, NullTxTracer.Instance); - deltaBalance = balance - _stateProvider.GetBalance(TestItem.PrivateKeyA.Address); + UInt256 deltaBalance = balance - _stateProvider.GetBalance(TestItem.PrivateKeyA.Address); return deltaBalance; } - public static IEnumerable BalanceIsAffectedByBlobGasTestCaseSource() + public static IEnumerable BalanceIsAffectedByDataGasTestCaseSource() { - yield return new TestCaseData((UInt256)(GasCostOf.Transaction + Eip4844Constants.BlobGasPerBlob), 1, 1ul, 0ul, 0ul) - { - TestName = "Blob gas consumed for 1 blob, minimal balance", - ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.BlobGasPerBlob), - }; - yield return new TestCaseData(1.Ether(), 1, 1ul, 0ul, 0ul) + yield return new TestCaseData((UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob), 1, 1ul, 0ul) { - TestName = "Blob gas consumed for 1 blob", - ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.BlobGasPerBlob), + TestName = "Data gas consumed for 1 blob, minimal balance", + ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob), }; - yield return new TestCaseData(1.Ether(), 2, 1ul, 0ul, 0ul) + yield return new TestCaseData(1.Ether(), 1, 1ul, 0ul) { - TestName = "Blob gas consumed for 2 blobs", - ExpectedResult = (UInt256)(GasCostOf.Transaction + 2 * Eip4844Constants.BlobGasPerBlob), + TestName = "Data gas consumed for 1 blob", + ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob), }; - yield return new TestCaseData(1.Ether(), (int)(Eip4844Constants.MaxBlobGasPerTransaction / Eip4844Constants.BlobGasPerBlob), 1ul, 0ul, 0ul) + yield return new TestCaseData(1.Ether(), 2, 1ul, 0ul) { - TestName = "Blob gas consumed for max blobs", - ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.MaxBlobGasPerTransaction), + TestName = "Data gas consumed for 2 blobs", + ExpectedResult = (UInt256)(GasCostOf.Transaction + 2 * Eip4844Constants.DataGasPerBlob), }; - yield return new TestCaseData(1.Ether(), 1, 10ul, 0ul, 0ul) + yield return new TestCaseData(1.Ether(), (int)(Eip4844Constants.MaxDataGasPerTransaction / Eip4844Constants.DataGasPerBlob), 1ul, 0ul) { - TestName = $"Blob gas consumed for 1 blob, with {nameof(Transaction.MaxFeePerBlobGas)} more than needed", - ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.BlobGasPerBlob), + TestName = "Data gas consumed for max blobs", + ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.MaxDataGasPerTransaction), }; - yield return new TestCaseData(1.Ether(), 1, 10ul, (ulong)Eip4844Constants.BlobGasUpdateFraction, 0ul) + yield return new TestCaseData(1.Ether(), 1, 10ul, 0ul) { - TestName = $"Blob gas consumed for 1 blob, with blob gas price hiking", - ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.BlobGasPerBlob * 2), + TestName = $"Data gas consumed for 1 blob, with {nameof(Transaction.MaxFeePerDataGas)} more than needed", + ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob), }; - yield return new TestCaseData(1.Ether(), 1, 10ul, (ulong)Eip4844Constants.BlobGasUpdateFraction, 2ul) + yield return new TestCaseData(1.Ether(), 1, 10ul, (ulong)Eip4844Constants.DataGasUpdateFraction) { - TestName = $"Blob gas consumed for 1 blob, with blob gas price hiking and some {nameof(Transaction.Value)}", - ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.BlobGasPerBlob * 2 + 2), + TestName = $"Data gas consumed for 1 blob, with data gas price hiking", + ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob * 2), }; } public static IEnumerable BalanceIsNotAffectedWhenNotEnoughFunds() { - yield return new TestCaseData((UInt256)(GasCostOf.Transaction + Eip4844Constants.BlobGasPerBlob - 1), 1, 1ul, 0ul, 0ul) + yield return new TestCaseData((UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob - 1), 1, 1ul, 0ul) { TestName = $"Rejected if balance is not enough, all funds are returned", ExpectedResult = UInt256.Zero, }; - yield return new TestCaseData((UInt256)(GasCostOf.Transaction + Eip4844Constants.BlobGasPerBlob + 41), 1, 1ul, 0ul, 42ul) + yield return new TestCaseData((UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob), 1, 10ul, (ulong)Eip4844Constants.DataGasUpdateFraction) { - TestName = $"Rejected if balance is not enough to cover {nameof(Transaction.Value)} also, all funds are returned", - ExpectedResult = UInt256.Zero, - }; - yield return new TestCaseData((UInt256)(GasCostOf.Transaction + Eip4844Constants.BlobGasPerBlob), 1, 10ul, (ulong)Eip4844Constants.BlobGasUpdateFraction, 0ul) - { - TestName = $"Rejected if balance is not enough due to blob gas price hiking, all funds are returned", - ExpectedResult = UInt256.Zero, - }; - yield return new TestCaseData((UInt256)(GasCostOf.Transaction + Eip4844Constants.BlobGasPerBlob), 1, 2ul, 0ul, 0ul) - { - TestName = $"Rejected if balance does not cover {nameof(Transaction.MaxFeePerBlobGas)}, all funds are returned", - ExpectedResult = UInt256.Zero, - }; - yield return new TestCaseData((UInt256)(GasCostOf.Transaction + 2 * Eip4844Constants.BlobGasPerBlob + 41), 1, 2ul, 0ul, 42ul) - { - TestName = $"Rejected if balance does not cover {nameof(Transaction.MaxFeePerBlobGas)} + {nameof(Transaction.Value)}, all funds are returned", + TestName = $"Rejected if balance is not enough due to data gas price hiking, all funds are returned", ExpectedResult = UInt256.Zero, }; } + + [Test] + public void Balance_is_not_changed_on_call_and_restore() + { + UInt256 initialBalance = 1.Ether(); + _stateProvider.CreateAccount(TestItem.AddressA, initialBalance); + _stateProvider.Commit(_specProvider.GenesisSpec); + _stateProvider.CommitTree(0); + + long gasLimit = GasCostOf.Transaction; + Transaction blobTx = Build.A.Transaction + .WithValue(0) + .WithGasPrice(1) + .WithMaxFeePerGas(1) + .WithMaxFeePerDataGas(1) + .WithGasLimit(gasLimit) + .WithShardBlobTxTypeAndFields(1) + .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA) + .TestObject; + + Block block = Build.A.Block + .WithNumber(1) + .WithTransactions(blobTx) + .WithGasLimit(gasLimit) + .WithExcessDataGas(0) + .WithBaseFeePerGas(1) + .TestObject; + + _transactionProcessor.CallAndRestore(blobTx, block.Header, NullTxTracer.Instance); + UInt256 newBalance = _stateProvider.GetBalance(TestItem.PrivateKeyA.Address); + Assert.That(newBalance, Is.EqualTo(initialBalance)); + } } diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs index d7f530768f3..e64c27bfcea 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs @@ -6,6 +6,7 @@ using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Extensions; +using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Db; diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs index 286829ec99d..ec566113d40 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs @@ -25,726 +25,691 @@ using NUnit.Framework; using Nethermind.Config; -namespace Nethermind.Evm.Test; - -[TestFixture(true)] -[TestFixture(false)] -[Todo(Improve.Refactor, "Check why fixture test cases did not work")] -[Parallelizable(ParallelScope.Self)] -public class TransactionProcessorTests +namespace Nethermind.Evm.Test { - private readonly bool _isEip155Enabled; - private readonly ISpecProvider _specProvider; - private IEthereumEcdsa _ethereumEcdsa; - private TransactionProcessor _transactionProcessor; - private IWorldState _stateProvider; - - public TransactionProcessorTests(bool eip155Enabled) - { - _isEip155Enabled = eip155Enabled; - _specProvider = MainnetSpecProvider.Instance; - } - - [SetUp] - public void Setup() - { - MemDb stateDb = new(); - TrieStore trieStore = new(stateDb, LimboLogs.Instance); - _stateProvider = new WorldState(trieStore, new MemDb(), LimboLogs.Instance); - _stateProvider.CreateAccount(TestItem.AddressA, 1.Ether()); - _stateProvider.Commit(_specProvider.GenesisSpec); - _stateProvider.CommitTree(0); - - VirtualMachine virtualMachine = new(TestBlockhashProvider.Instance, _specProvider, LimboLogs.Instance); - _transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, virtualMachine, LimboLogs.Instance); - _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId, LimboLogs.Instance); - } - - [TestCase(true, true)] - [TestCase(true, false)] - [TestCase(false, true)] - [TestCase(false, false)] - public void Can_process_simple_transaction(bool withStateDiff, bool withTrace) - { - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(100000).TestObject; - - Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; - - BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); - Execute(tracer, tx, block); - - Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Success)); - } - - [TestCase(true, true)] - [TestCase(true, false)] - [TestCase(false, true)] - [TestCase(false, false)] - public void Sets_state_root_on_receipts_before_eip658(bool withStateDiff, bool withTrace) - { - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(100000).TestObject; - - long blockNumber = _isEip155Enabled - ? MainnetSpecProvider.ByzantiumBlockNumber - : MainnetSpecProvider.ByzantiumBlockNumber - 1; - Block block = Build.A.Block.WithNumber(blockNumber).WithTransactions(tx).TestObject; - - BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); - Execute(tracer, tx, block); - - if (_isEip155Enabled) // we use eip155 check just as a proxy on 658 + [TestFixture(true)] + [TestFixture(false)] + [Todo(Improve.Refactor, "Check why fixture test cases did not work")] + [Parallelizable(ParallelScope.Self)] + public class TransactionProcessorTests + { + private readonly bool _isEip155Enabled; + private readonly ISpecProvider _specProvider; + private IEthereumEcdsa _ethereumEcdsa; + private TransactionProcessor _transactionProcessor; + private IWorldState _stateProvider; + + public TransactionProcessorTests(bool eip155Enabled) { - Assert.Null(tracer.TxReceipts![0].PostTransactionState); + _isEip155Enabled = eip155Enabled; + _specProvider = MainnetSpecProvider.Instance; } - else + + [SetUp] + public void Setup() { - Assert.NotNull(tracer.TxReceipts![0].PostTransactionState); + MemDb stateDb = new(); + TrieStore trieStore = new(stateDb, LimboLogs.Instance); + _stateProvider = new WorldState(trieStore, new MemDb(), LimboLogs.Instance); + _stateProvider.CreateAccount(TestItem.AddressA, 1.Ether()); + _stateProvider.Commit(_specProvider.GenesisSpec); + _stateProvider.CommitTree(0); + + VirtualMachine virtualMachine = new(TestBlockhashProvider.Instance, _specProvider, LimboLogs.Instance); + _transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, virtualMachine, LimboLogs.Instance); + _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId, LimboLogs.Instance); } - } - [TestCase(true, true)] - [TestCase(true, false)] - [TestCase(false, true)] - [TestCase(false, false)] - public void Can_handle_quick_fail_on_intrinsic_gas(bool withStateDiff, bool withTrace) - { - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(20000).TestObject; + [TestCase(true, true)] + [TestCase(true, false)] + [TestCase(false, true)] + [TestCase(false, false)] + public void Can_process_simple_transaction(bool withStateDiff, bool withTrace) + { + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(100000).TestObject; - Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; - BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); - Execute(tracer, tx, block); + BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); + Execute(tracer, tx, block); - Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); - } + Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Success)); + } - [TestCase(true, true)] - [TestCase(true, false)] - [TestCase(false, true)] - [TestCase(false, false)] - public void Can_handle_quick_fail_on_missing_sender(bool withStateDiff, bool withTrace) - { - Transaction tx = Build.A.Transaction.Signed(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(100000).TestObject; + [TestCase(true, true)] + [TestCase(true, false)] + [TestCase(false, true)] + [TestCase(false, false)] + public void Sets_state_root_on_receipts_before_eip658(bool withStateDiff, bool withTrace) + { + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(100000).TestObject; + + long blockNumber = _isEip155Enabled + ? MainnetSpecProvider.ByzantiumBlockNumber + : MainnetSpecProvider.ByzantiumBlockNumber - 1; + Block block = Build.A.Block.WithNumber(blockNumber).WithTransactions(tx).TestObject; + + BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); + Execute(tracer, tx, block); + + if (_isEip155Enabled) // we use eip155 check just as a proxy on 658 + { + Assert.Null(tracer.TxReceipts![0].PostTransactionState); + } + else + { + Assert.NotNull(tracer.TxReceipts![0].PostTransactionState); + } + } - Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; + [TestCase(true, true)] + [TestCase(true, false)] + [TestCase(false, true)] + [TestCase(false, false)] + public void Can_handle_quick_fail_on_intrinsic_gas(bool withStateDiff, bool withTrace) + { + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(20000).TestObject; - BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); - Execute(tracer, tx, block); + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; - Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); - } + BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); + Execute(tracer, tx, block); - [TestCase(true, true)] - [TestCase(true, false)] - [TestCase(false, true)] - [TestCase(false, false)] - public void Can_handle_quick_fail_on_non_existing_sender_account(bool withStateDiff, bool withTrace) - { - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyB, _isEip155Enabled).WithGasLimit(100000).TestObject; + Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); + } - Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; + [TestCase(true, true)] + [TestCase(true, false)] + [TestCase(false, true)] + [TestCase(false, false)] + public void Can_handle_quick_fail_on_missing_sender(bool withStateDiff, bool withTrace) + { + Transaction tx = Build.A.Transaction.Signed(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(100000).TestObject; - BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); - Execute(tracer, tx, block); + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; - Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); - } + BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); + Execute(tracer, tx, block); - [TestCase(true, true)] - [TestCase(true, false)] - [TestCase(false, true)] - [TestCase(false, false)] - public void Can_handle_quick_fail_on_invalid_nonce(bool withStateDiff, bool withTrace) - { - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(100000).WithNonce(100).TestObject; + Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); + } - Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; + [TestCase(true, true)] + [TestCase(true, false)] + [TestCase(false, true)] + [TestCase(false, false)] + public void Can_handle_quick_fail_on_non_existing_sender_account(bool withStateDiff, bool withTrace) + { + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyB, _isEip155Enabled).WithGasLimit(100000).TestObject; - BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); - Execute(tracer, tx, block); + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; - Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); - } + BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); + Execute(tracer, tx, block); - [TestCase(true, true)] - [TestCase(true, false)] - [TestCase(false, true)] - [TestCase(false, false)] - public void Can_handle_quick_fail_on_not_enough_balance_on_intrinsic_gas(bool withStateDiff, bool withTrace) - { - AccessList.Builder accessListBuilder = new(); - foreach (Address address in TestItem.Addresses) - { - accessListBuilder.AddAddress(address); + Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); } - Transaction tx = Build.A.Transaction - .WithGasLimit(GasCostOf.Transaction * 2) - .WithAccessList(accessListBuilder.Build()) - .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled) - .TestObject; + [TestCase(true, true)] + [TestCase(true, false)] + [TestCase(false, true)] + [TestCase(false, false)] + public void Can_handle_quick_fail_on_invalid_nonce(bool withStateDiff, bool withTrace) + { + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(100000).WithNonce(100).TestObject; - tx.Value = 1.Ether() - 3 * GasCostOf.Transaction; + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; - Block block = Build.A.Block.WithNumber(MainnetSpecProvider.BerlinBlockNumber).WithTransactions(tx).TestObject; + BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); + Execute(tracer, tx, block); - BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); - Execute(tracer, tx, block); + Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); + } - Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); - } + [TestCase(true, true)] + [TestCase(true, false)] + [TestCase(false, true)] + [TestCase(false, false)] + public void Can_handle_quick_fail_on_not_enough_balance_on_intrinsic_gas(bool withStateDiff, bool withTrace) + { + AccessListBuilder accessListBuilder = new(); + foreach (Address address in TestItem.Addresses) + { + accessListBuilder.AddAddress(address); + } - [TestCase(true, true)] - [TestCase(true, false)] - [TestCase(false, true)] - [TestCase(false, false)] - public void Can_handle_quick_fail_on_not_enough_balance_on_reserved_gas_payment(bool withStateDiff, bool withTrace) - { - Transaction tx = Build.A.Transaction - .WithGasLimit(GasCostOf.Transaction * 2) - .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled) - .TestObject; + Transaction tx = Build.A.Transaction + .WithGasLimit(GasCostOf.Transaction * 2) + .WithAccessList(accessListBuilder.ToAccessList()) + .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled) + .TestObject; - tx.Value = 1.Ether() - GasCostOf.Transaction; + tx.Value = 1.Ether() - 3 * GasCostOf.Transaction; - Block block = Build.A.Block.WithNumber(MainnetSpecProvider.BerlinBlockNumber).WithTransactions(tx).TestObject; + Block block = Build.A.Block.WithNumber(MainnetSpecProvider.BerlinBlockNumber).WithTransactions(tx).TestObject; - BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); - Execute(tracer, tx, block); + BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); + Execute(tracer, tx, block); - Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); - } + Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); + } - [TestCase(true, true)] - [TestCase(true, false)] - [TestCase(false, true)] - [TestCase(false, false)] - public void Can_handle_quick_fail_when_balance_is_lower_than_fee_cap_times_gas(bool withStateDiff, bool withTrace) - { - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled) - .WithMaxPriorityFeePerGas(5.GWei()) - .WithMaxFeePerGas(10.Ether()) - .WithType(TxType.EIP1559) - .WithGasLimit(100000).TestObject; + [TestCase(true, true)] + [TestCase(true, false)] + [TestCase(false, true)] + [TestCase(false, false)] + public void Can_handle_quick_fail_on_not_enough_balance_on_reserved_gas_payment(bool withStateDiff, bool withTrace) + { + Transaction tx = Build.A.Transaction + .WithGasLimit(GasCostOf.Transaction * 2) + .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled) + .TestObject; - Block block = Build.A.Block.WithNumber(MainnetSpecProvider.LondonBlockNumber).WithTransactions(tx).TestObject; + tx.Value = 1.Ether() - GasCostOf.Transaction; - BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); - Execute(tracer, tx, block); + Block block = Build.A.Block.WithNumber(MainnetSpecProvider.BerlinBlockNumber).WithTransactions(tx).TestObject; - Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); - } + BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); + Execute(tracer, tx, block); - [TestCase(true, true)] - [TestCase(true, false)] - [TestCase(false, true)] - [TestCase(false, false)] - public void Can_handle_quick_fail_on_above_block_gas_limit(bool withStateDiff, bool withTrace) - { - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(100000).TestObject; + Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); + } - Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(20000).TestObject; + [TestCase(true, true)] + [TestCase(true, false)] + [TestCase(false, true)] + [TestCase(false, false)] + public void Can_handle_quick_fail_when_balance_is_lower_than_fee_cap_times_gas(bool withStateDiff, bool withTrace) + { + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled) + .WithMaxPriorityFeePerGas(5.GWei()) + .WithMaxFeePerGas(10.Ether()) + .WithType(TxType.EIP1559) + .WithGasLimit(100000).TestObject; - BlockReceiptsTracer tracer = BuildTracer(block, tx, withTrace, withTrace); - Execute(tracer, tx, block); + Block block = Build.A.Block.WithNumber(MainnetSpecProvider.LondonBlockNumber).WithTransactions(tx).TestObject; - Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); - } + BlockReceiptsTracer tracer = BuildTracer(block, tx, withStateDiff, withTrace); + Execute(tracer, tx, block); - [TestCase(true, true)] - [TestCase(true, false)] - [TestCase(false, true)] - [TestCase(false, false)] - public void Will_not_cause_quick_fail_above_block_gas_limit_during_calls(bool withStateDiff, bool withTrace) - { - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(100000).TestObject; + Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); + } - Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(20000).TestObject; + [TestCase(true, true)] + [TestCase(true, false)] + [TestCase(false, true)] + [TestCase(false, false)] + public void Can_handle_quick_fail_on_above_block_gas_limit(bool withStateDiff, bool withTrace) + { + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(100000).TestObject; - BlockReceiptsTracer tracer = BuildTracer(block, tx, withTrace, withTrace); - CallAndRestore(tracer, tx, block); + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(20000).TestObject; - Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Success)); - } + BlockReceiptsTracer tracer = BuildTracer(block, tx, withTrace, withTrace); + Execute(tracer, tx, block); - [TestCase] - public void Balance_is_not_changed_on_call_and_restore() - { - long gasLimit = 100000; - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithValue(1.Ether() - (UInt256)gasLimit).WithGasPrice(1).WithGasLimit(gasLimit).TestObject; - Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; + Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Failure)); + } - _transactionProcessor.CallAndRestore(tx, block.Header, NullTxTracer.Instance); + [TestCase(true, true)] + [TestCase(true, false)] + [TestCase(false, true)] + [TestCase(false, false)] + public void Will_not_cause_quick_fail_above_block_gas_limit_during_calls(bool withStateDiff, bool withTrace) + { + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(100000).TestObject; - _stateProvider.GetBalance(TestItem.PrivateKeyA.Address).Should().Be(1.Ether()); - } + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(20000).TestObject; - [TestCase] - public void Account_is_not_created_on_call_and_restore() - { - long gasLimit = 100000; - Transaction tx = Build.A.Transaction - .WithValue(0.Ether()) - .WithGasPrice(1) - .WithGasLimit(gasLimit) - .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyD, _isEip155Enabled) - .TestObject; - Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; - - _stateProvider.AccountExists(TestItem.PrivateKeyD.Address).Should().BeFalse(); - _transactionProcessor.CallAndRestore(tx, block.Header, NullTxTracer.Instance); - _stateProvider.AccountExists(TestItem.PrivateKeyD.Address).Should().BeFalse(); - } + BlockReceiptsTracer tracer = BuildTracer(block, tx, withTrace, withTrace); + CallAndRestore(tracer, tx, block); - [TestCase] - public void Nonce_is_not_changed_on_call_and_restore() - { - long gasLimit = 100000; - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithValue(1.Ether() - (UInt256)gasLimit).WithGasPrice(1).WithGasLimit(gasLimit).TestObject; - Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; + Assert.That(tracer.TxReceipts[0].StatusCode, Is.EqualTo(StatusCode.Success)); + } - _transactionProcessor.CallAndRestore(tx, block.Header, NullTxTracer.Instance); - _stateProvider.GetNonce(TestItem.PrivateKeyA.Address).Should().Be(0); - } + [Test] + public void Balance_is_not_changed_on_call_and_restore() + { + long gasLimit = 100000; + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithValue(1.Ether() - (UInt256)gasLimit).WithGasPrice(1).WithGasLimit(gasLimit).TestObject; + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; - [TestCase(true)] - [TestCase(false)] - public void Can_estimate_with_value(bool systemUser) - { - long gasLimit = 100000; - Transaction tx = Build.A.Transaction.WithValue(UInt256.MaxValue).WithGasLimit(gasLimit) - .WithSenderAddress(systemUser ? Address.SystemUser : TestItem.AddressA).TestObject; - Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; + _transactionProcessor.CallAndRestore(tx, block.Header, NullTxTracer.Instance); - EstimateGasTracer tracer = new(); - Action action = () => _transactionProcessor.CallAndRestore(tx, block.Header, tracer); - if (!systemUser) - { - action.Should().Throw(); + _stateProvider.GetBalance(TestItem.PrivateKeyA.Address).Should().Be(1.Ether()); } - else + + [Test] + public void Account_is_not_created_on_call_and_restore() { - action.Should().NotThrow(); - tracer.GasSpent.Should().Be(21000); + long gasLimit = 100000; + Transaction tx = Build.A.Transaction + .WithValue(0.Ether()) + .WithGasPrice(1) + .WithGasLimit(gasLimit) + .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyD, _isEip155Enabled) + .TestObject; + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; + + _stateProvider.AccountExists(TestItem.PrivateKeyD.Address).Should().BeFalse(); + _transactionProcessor.CallAndRestore(tx, block.Header, NullTxTracer.Instance); + _stateProvider.AccountExists(TestItem.PrivateKeyD.Address).Should().BeFalse(); } - } - [Test] - public void Should_reject_tx_with_high_value() - { - Transaction tx = Build.A.Transaction.WithValue(UInt256.MaxValue).WithGasLimit(21000) - .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled) - .TestObject; - - long blockNumber = _isEip155Enabled - ? MainnetSpecProvider.ByzantiumBlockNumber - : MainnetSpecProvider.ByzantiumBlockNumber - 1; - Block block = Build.A.Block.WithNumber(blockNumber).WithTransactions(tx).TestObject; - BlockReceiptsTracer tracer = BuildTracer(block, tx, true, true); - - Execute(tracer, tx, block); - - tracer.TxReceipts[0].StatusCode.Should().Be(StatusCode.Failure); - } - - [TestCase(562949953421312ul)] - [TestCase(562949953421311ul)] - public void Should_reject_tx_with_high_max_fee_per_gas(ulong topDigit) - { - Transaction tx = Build.A.Transaction.WithMaxFeePerGas(new(0, 0, 0, topDigit)).WithGasLimit(32768) - .WithType(TxType.EIP1559).WithValue(0) - .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled) - .TestObject; - - long blockNumber = MainnetSpecProvider.LondonBlockNumber; - Block block = Build.A.Block.WithNumber(blockNumber).WithTransactions(tx).TestObject; - BlockReceiptsTracer tracer = BuildTracer(block, tx, true, true); + [Test] + public void Nonce_is_not_changed_on_call_and_restore() + { + long gasLimit = 100000; + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithValue(1.Ether() - (UInt256)gasLimit).WithGasPrice(1).WithGasLimit(gasLimit).TestObject; + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; - Execute(tracer, tx, block); + _transactionProcessor.CallAndRestore(tx, block.Header, NullTxTracer.Instance); + _stateProvider.GetNonce(TestItem.PrivateKeyA.Address).Should().Be(0); + } - tracer.TxReceipts[0].StatusCode.Should().Be(StatusCode.Failure); - } + [TestCase(true)] + [TestCase(false)] + public void Can_estimate_with_value(bool systemUser) + { + long gasLimit = 100000; + Transaction tx = Build.A.Transaction.WithValue(UInt256.MaxValue).WithGasLimit(gasLimit) + .WithSenderAddress(systemUser ? Address.SystemUser : TestItem.AddressA).TestObject; + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; + + EstimateGasTracer tracer = new(); + Action action = () => _transactionProcessor.CallAndRestore(tx, block.Header, tracer); + if (!systemUser) + { + action.Should().Throw(); + } + else + { + action.Should().NotThrow(); + tracer.GasSpent.Should().Be(21000); + } + } - [TestCase] - public void Can_estimate_simple() - { - long gasLimit = 100000; - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(gasLimit).TestObject; - Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; + [Test] + public void Can_estimate_simple() + { + long gasLimit = 100000; + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithGasLimit(gasLimit).TestObject; + Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; - EstimateGasTracer tracer = new(); - BlocksConfig blocksConfig = new(); - GasEstimator estimator = new(_transactionProcessor, _stateProvider, _specProvider, blocksConfig); - _transactionProcessor.CallAndRestore(tx, block.Header, tracer); + EstimateGasTracer tracer = new(); + BlocksConfig blocksConfig = new(); + GasEstimator estimator = new(_transactionProcessor, _stateProvider, _specProvider, blocksConfig); + _transactionProcessor.CallAndRestore(tx, block.Header, tracer); - tracer.GasSpent.Should().Be(21000); - estimator.Estimate(tx, block.Header, tracer).Should().Be(21000); - } + tracer.GasSpent.Should().Be(21000); + estimator.Estimate(tx, block.Header, tracer).Should().Be(21000); + } - [TestCase] - public void Can_estimate_with_refund() - { - byte[] initByteCode = Prepare.EvmCode - .PushData(1) - .PushData(1) - .Op(Instruction.SSTORE) - .PushData(0) - .PushData(1) - .Op(Instruction.SSTORE) - .Op(Instruction.STOP) - .Done; - - long gasLimit = 100000; - - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(initByteCode).WithGasLimit(gasLimit).TestObject; - Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; - - long intrinsic = IntrinsicGasCalculator.Calculate(tx, MuirGlacier.Instance); - - GethLikeTxMemoryTracer gethTracer = new(GethTraceOptions.Default); - _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer); - TestContext.WriteLine(new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true)); - - EstimateGasTracer tracer = new(); - _transactionProcessor.CallAndRestore(tx, block.Header, tracer); - - BlocksConfig blocksConfig = new(); - GasEstimator estimator = new(_transactionProcessor, _stateProvider, _specProvider, blocksConfig); - - long actualIntrinsic = tx.GasLimit - tracer.IntrinsicGasAt; - actualIntrinsic.Should().Be(intrinsic); - IReleaseSpec releaseSpec = Berlin.Instance; - tracer.CalculateAdditionalGasRequired(tx, releaseSpec).Should().Be(RefundOf.SSetReversedEip2200 + GasCostOf.CallStipend - GasCostOf.SStoreNetMeteredEip2200 + 1); - tracer.GasSpent.Should().Be(54764L); - long estimate = estimator.Estimate(tx, block.Header, tracer); - estimate.Should().Be(75465L); - - ConfirmEnoughEstimate(tx, block, estimate); - } + [Test] + public void Can_estimate_with_refund() + { + byte[] initByteCode = Prepare.EvmCode + .PushData(1) + .PushData(1) + .Op(Instruction.SSTORE) + .PushData(0) + .PushData(1) + .Op(Instruction.SSTORE) + .Op(Instruction.STOP) + .Done; + + long gasLimit = 100000; + + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(initByteCode).WithGasLimit(gasLimit).TestObject; + Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; + + long intrinsic = IntrinsicGasCalculator.Calculate(tx, MuirGlacier.Instance); + + GethLikeTxTracer gethTracer = new(GethTraceOptions.Default); + _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer); + TestContext.WriteLine(new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true)); + + EstimateGasTracer tracer = new(); + _transactionProcessor.CallAndRestore(tx, block.Header, tracer); + + BlocksConfig blocksConfig = new(); + GasEstimator estimator = new(_transactionProcessor, _stateProvider, _specProvider, blocksConfig); + + long actualIntrinsic = tx.GasLimit - tracer.IntrinsicGasAt; + actualIntrinsic.Should().Be(intrinsic); + IReleaseSpec releaseSpec = Berlin.Instance; + tracer.CalculateAdditionalGasRequired(tx, releaseSpec).Should().Be(RefundOf.SSetReversedEip2200 + GasCostOf.CallStipend - GasCostOf.SStoreNetMeteredEip2200 + 1); + tracer.GasSpent.Should().Be(54764L); + long estimate = estimator.Estimate(tx, block.Header, tracer); + estimate.Should().Be(75465L); + + ConfirmEnoughEstimate(tx, block, estimate); + } - [Test(Description = "Since the second call is a CREATE operation it has intrinsic gas of 21000 + 32000 + data")] - public void Can_estimate_with_destroy_refund_and_below_intrinsic_pre_berlin() - { - byte[] initByteCode = Prepare.EvmCode.ForInitOf(Prepare.EvmCode.PushData(Address.Zero).Op(Instruction.SELFDESTRUCT).Done).Done; - Address contractAddress = ContractAddress.From(TestItem.PrivateKeyA.Address, 0); + [Test(Description = "Since the second call is a CREATE operation it has intrinsic gas of 21000 + 32000 + data")] + public void Can_estimate_with_destroy_refund_and_below_intrinsic_pre_berlin() + { + byte[] initByteCode = Prepare.EvmCode.ForInitOf(Prepare.EvmCode.PushData(Address.Zero).Op(Instruction.SELFDESTRUCT).Done).Done; + Address contractAddress = ContractAddress.From(TestItem.PrivateKeyA.Address, 0); - byte[] byteCode = Prepare.EvmCode - .Call(contractAddress, 46179) - .Op(Instruction.STOP).Done; + byte[] byteCode = Prepare.EvmCode + .Call(contractAddress, 46179) + .Op(Instruction.STOP).Done; - long gasLimit = 100000; + long gasLimit = 100000; - Transaction initTx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(initByteCode).WithGasLimit(gasLimit).TestObject; - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(byteCode).WithGasLimit(gasLimit).WithNonce(1).TestObject; - Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; + Transaction initTx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(initByteCode).WithGasLimit(gasLimit).TestObject; + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(byteCode).WithGasLimit(gasLimit).WithNonce(1).TestObject; + Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; - IReleaseSpec releaseSpec = MuirGlacier.Instance; - long intrinsic = IntrinsicGasCalculator.Calculate(tx, releaseSpec); + IReleaseSpec releaseSpec = MuirGlacier.Instance; + long intrinsic = IntrinsicGasCalculator.Calculate(tx, releaseSpec); - _transactionProcessor.Execute(initTx, block.Header, NullTxTracer.Instance); + _transactionProcessor.Execute(initTx, block.Header, NullTxTracer.Instance); - EstimateGasTracer tracer = new(); - GethLikeTxMemoryTracer gethTracer = new(GethTraceOptions.Default); - _transactionProcessor.CallAndRestore(tx, block.Header, tracer); - _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer); - TestContext.WriteLine(new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true)); + EstimateGasTracer tracer = new(); + GethLikeTxTracer gethTracer = new(GethTraceOptions.Default); + _transactionProcessor.CallAndRestore(tx, block.Header, tracer); + _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer); + TestContext.WriteLine(new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true)); - BlocksConfig blocksConfig = new(); - GasEstimator estimator = new(_transactionProcessor, _stateProvider, _specProvider, blocksConfig); + BlocksConfig blocksConfig = new(); + GasEstimator estimator = new(_transactionProcessor, _stateProvider, _specProvider, blocksConfig); - long actualIntrinsic = tx.GasLimit - tracer.IntrinsicGasAt; - actualIntrinsic.Should().Be(intrinsic); - tracer.CalculateAdditionalGasRequired(tx, releaseSpec).Should().Be(24080); - tracer.GasSpent.Should().Be(35228L); - long estimate = estimator.Estimate(tx, block.Header, tracer); - estimate.Should().Be(59307); + long actualIntrinsic = tx.GasLimit - tracer.IntrinsicGasAt; + actualIntrinsic.Should().Be(intrinsic); + tracer.CalculateAdditionalGasRequired(tx, releaseSpec).Should().Be(24080); + tracer.GasSpent.Should().Be(35228L); + long estimate = estimator.Estimate(tx, block.Header, tracer); + estimate.Should().Be(59307); - ConfirmEnoughEstimate(tx, block, estimate); - } + ConfirmEnoughEstimate(tx, block, estimate); + } - private void ConfirmEnoughEstimate(Transaction tx, Block block, long estimate) - { - CallOutputTracer outputTracer = new(); - tx.GasLimit = estimate; - TestContext.WriteLine(tx.GasLimit); + private void ConfirmEnoughEstimate(Transaction tx, Block block, long estimate) + { + CallOutputTracer outputTracer = new(); + tx.GasLimit = estimate; + TestContext.WriteLine(tx.GasLimit); - GethLikeTxMemoryTracer gethTracer = new(GethTraceOptions.Default); - _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer); - string traceEnoughGas = new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true); + GethLikeTxTracer gethTracer = new(GethTraceOptions.Default); + _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer); + string traceEnoughGas = new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true); - _transactionProcessor.CallAndRestore(tx, block.Header, outputTracer); - traceEnoughGas.Should().NotContain("OutOfGas"); + _transactionProcessor.CallAndRestore(tx, block.Header, outputTracer); + traceEnoughGas.Should().NotContain("OutOfGas"); - outputTracer = new CallOutputTracer(); - tx.GasLimit = Math.Min(estimate - 1, estimate * 63 / 64); - TestContext.WriteLine(tx.GasLimit); + outputTracer = new CallOutputTracer(); + tx.GasLimit = Math.Min(estimate - 1, estimate * 63 / 64); + TestContext.WriteLine(tx.GasLimit); - gethTracer = new GethLikeTxMemoryTracer(GethTraceOptions.Default); - _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer); + gethTracer = new GethLikeTxTracer(GethTraceOptions.Default); + _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer); - string traceOutOfGas = new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true); - TestContext.WriteLine(traceOutOfGas); + string traceOutOfGas = new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true); + TestContext.WriteLine(traceOutOfGas); - _transactionProcessor.CallAndRestore(tx, block.Header, outputTracer); + _transactionProcessor.CallAndRestore(tx, block.Header, outputTracer); - bool failed = traceEnoughGas.Contains("failed") || traceEnoughGas.Contains("OutOfGas"); - failed.Should().BeTrue(); - } + bool failed = traceEnoughGas.Contains("failed") || traceEnoughGas.Contains("OutOfGas"); + failed.Should().BeTrue(); + } - [TestCase] - public void Can_estimate_with_stipend() - { - byte[] initByteCode = Prepare.EvmCode - .CallWithValue(Address.Zero, 0, 1) - .Op(Instruction.STOP) - .Done; + [Test] + public void Can_estimate_with_stipend() + { + byte[] initByteCode = Prepare.EvmCode + .CallWithValue(Address.Zero, 0, 1) + .Op(Instruction.STOP) + .Done; - long gasLimit = 100000; + long gasLimit = 100000; - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(initByteCode).WithGasLimit(gasLimit).TestObject; - Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(initByteCode).WithGasLimit(gasLimit).TestObject; + Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; - IReleaseSpec releaseSpec = MuirGlacier.Instance; - long intrinsic = IntrinsicGasCalculator.Calculate(tx, releaseSpec); + IReleaseSpec releaseSpec = MuirGlacier.Instance; + long intrinsic = IntrinsicGasCalculator.Calculate(tx, releaseSpec); - GethLikeTxMemoryTracer gethTracer = new(GethTraceOptions.Default); - _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer); - TestContext.WriteLine(new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true)); + GethLikeTxTracer gethTracer = new(GethTraceOptions.Default); + _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer); + TestContext.WriteLine(new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true)); - EstimateGasTracer tracer = new(); - _transactionProcessor.CallAndRestore(tx, block.Header, tracer); + EstimateGasTracer tracer = new(); + _transactionProcessor.CallAndRestore(tx, block.Header, tracer); - BlocksConfig blocksConfig = new(); - GasEstimator estimator = new(_transactionProcessor, _stateProvider, _specProvider, blocksConfig); + BlocksConfig blocksConfig = new(); + GasEstimator estimator = new(_transactionProcessor, _stateProvider, _specProvider, blocksConfig); - long actualIntrinsic = tx.GasLimit - tracer.IntrinsicGasAt; - actualIntrinsic.Should().Be(intrinsic); - tracer.CalculateAdditionalGasRequired(tx, releaseSpec).Should().Be(2300); - tracer.GasSpent.Should().Be(85669L); - long estimate = estimator.Estimate(tx, block.Header, tracer); - estimate.Should().Be(87969L); + long actualIntrinsic = tx.GasLimit - tracer.IntrinsicGasAt; + actualIntrinsic.Should().Be(intrinsic); + tracer.CalculateAdditionalGasRequired(tx, releaseSpec).Should().Be(2300); + tracer.GasSpent.Should().Be(85669L); + long estimate = estimator.Estimate(tx, block.Header, tracer); + estimate.Should().Be(87969L); - ConfirmEnoughEstimate(tx, block, estimate); - } + ConfirmEnoughEstimate(tx, block, estimate); + } - [TestCase] - public void Can_estimate_with_stipend_and_refund() - { - byte[] initByteCode = Prepare.EvmCode - .CallWithValue(Address.Zero, 0, 1) - .PushData(1) - .PushData(1) - .Op(Instruction.SSTORE) - .PushData(0) - .PushData(1) - .Op(Instruction.SSTORE) - .Op(Instruction.STOP) - .Done; - - long gasLimit = 200000; - - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(initByteCode).WithGasLimit(gasLimit).TestObject; - Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; - - IReleaseSpec releaseSpec = MuirGlacier.Instance; - long intrinsic = IntrinsicGasCalculator.Calculate(tx, releaseSpec); - - GethLikeTxMemoryTracer gethTracer = new(GethTraceOptions.Default); - _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer); - TestContext.WriteLine(new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true)); - - EstimateGasTracer tracer = new(); - _transactionProcessor.CallAndRestore(tx, block.Header, tracer); - - BlocksConfig blocksConfig = new(); - GasEstimator estimator = new(_transactionProcessor, _stateProvider, _specProvider, blocksConfig); - - long actualIntrinsic = tx.GasLimit - tracer.IntrinsicGasAt; - actualIntrinsic.Should().Be(intrinsic); - tracer.CalculateAdditionalGasRequired(tx, releaseSpec).Should().Be(RefundOf.SSetReversedEip2200 + GasCostOf.CallStipend); - tracer.GasSpent.Should().Be(87429L); - long estimate = estimator.Estimate(tx, block.Header, tracer); - estimate.Should().Be(108130L); - - ConfirmEnoughEstimate(tx, block, estimate); - } + [Test] + public void Can_estimate_with_stipend_and_refund() + { + byte[] initByteCode = Prepare.EvmCode + .CallWithValue(Address.Zero, 0, 1) + .PushData(1) + .PushData(1) + .Op(Instruction.SSTORE) + .PushData(0) + .PushData(1) + .Op(Instruction.SSTORE) + .Op(Instruction.STOP) + .Done; + + long gasLimit = 200000; + + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(initByteCode).WithGasLimit(gasLimit).TestObject; + Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; + + IReleaseSpec releaseSpec = MuirGlacier.Instance; + long intrinsic = IntrinsicGasCalculator.Calculate(tx, releaseSpec); + + GethLikeTxTracer gethTracer = new(GethTraceOptions.Default); + _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer); + TestContext.WriteLine(new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true)); + + EstimateGasTracer tracer = new(); + _transactionProcessor.CallAndRestore(tx, block.Header, tracer); + + BlocksConfig blocksConfig = new(); + GasEstimator estimator = new(_transactionProcessor, _stateProvider, _specProvider, blocksConfig); + + long actualIntrinsic = tx.GasLimit - tracer.IntrinsicGasAt; + actualIntrinsic.Should().Be(intrinsic); + tracer.CalculateAdditionalGasRequired(tx, releaseSpec).Should().Be(RefundOf.SSetReversedEip2200 + GasCostOf.CallStipend); + tracer.GasSpent.Should().Be(87429L); + long estimate = estimator.Estimate(tx, block.Header, tracer); + estimate.Should().Be(108130L); + + ConfirmEnoughEstimate(tx, block, estimate); + } - [TestCase] - public void Can_estimate_with_single_call() - { - byte[] initByteCode = Prepare.EvmCode - .ForInitOf(Bytes.FromHexString("6000")).Done; + [Test] + public void Can_estimate_with_single_call() + { + byte[] initByteCode = Prepare.EvmCode + .ForInitOf(Bytes.FromHexString("6000")).Done; - Address contractAddress = ContractAddress.From(TestItem.PrivateKeyA.Address, 0); + Address contractAddress = ContractAddress.From(TestItem.PrivateKeyA.Address, 0); - byte[] byteCode = Prepare.EvmCode - .Call(contractAddress, 46179).Done; + byte[] byteCode = Prepare.EvmCode + .Call(contractAddress, 46179).Done; - long gasLimit = 100000; + long gasLimit = 100000; - Transaction initTx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(initByteCode).WithGasLimit(gasLimit).TestObject; - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(byteCode).WithGasLimit(gasLimit).WithNonce(1).TestObject; - Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; + Transaction initTx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(initByteCode).WithGasLimit(gasLimit).TestObject; + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithCode(byteCode).WithGasLimit(gasLimit).WithNonce(1).TestObject; + Block block = Build.A.Block.WithNumber(MainnetSpecProvider.MuirGlacierBlockNumber).WithTransactions(tx).WithGasLimit(2 * gasLimit).TestObject; - IReleaseSpec releaseSpec = Berlin.Instance; - long intrinsic = IntrinsicGasCalculator.Calculate(tx, releaseSpec); + IReleaseSpec releaseSpec = Berlin.Instance; + long intrinsic = IntrinsicGasCalculator.Calculate(tx, releaseSpec); - _transactionProcessor.Execute(initTx, block.Header, NullTxTracer.Instance); + _transactionProcessor.Execute(initTx, block.Header, NullTxTracer.Instance); - EstimateGasTracer tracer = new(); - _transactionProcessor.CallAndRestore(tx, block.Header, tracer); + EstimateGasTracer tracer = new(); + _transactionProcessor.CallAndRestore(tx, block.Header, tracer); - BlocksConfig blocksConfig = new(); - GasEstimator estimator = new(_transactionProcessor, _stateProvider, _specProvider, blocksConfig); + BlocksConfig blocksConfig = new(); + GasEstimator estimator = new(_transactionProcessor, _stateProvider, _specProvider, blocksConfig); - long actualIntrinsic = tx.GasLimit - tracer.IntrinsicGasAt; - actualIntrinsic.Should().Be(intrinsic); - tracer.CalculateAdditionalGasRequired(tx, releaseSpec).Should().Be(1); - tracer.GasSpent.Should().Be(54224L); - long estimate = estimator.Estimate(tx, block.Header, tracer); - estimate.Should().Be(54224L); + long actualIntrinsic = tx.GasLimit - tracer.IntrinsicGasAt; + actualIntrinsic.Should().Be(intrinsic); + tracer.CalculateAdditionalGasRequired(tx, releaseSpec).Should().Be(1); + tracer.GasSpent.Should().Be(54224L); + long estimate = estimator.Estimate(tx, block.Header, tracer); + estimate.Should().Be(54224L); - ConfirmEnoughEstimate(tx, block, estimate); - } + ConfirmEnoughEstimate(tx, block, estimate); + } - [TestCase] - public void Disables_Eip158_for_system_transactions() - { - long blockNumber = MainnetSpecProvider.SpuriousDragonBlockNumber + 1; - _stateProvider.CreateAccount(TestItem.PrivateKeyA.Address, 0.Ether()); - IReleaseSpec spec = _specProvider.GetSpec((ForkActivation)blockNumber); - _stateProvider.Commit(spec); - Transaction tx = Build.A.SystemTransaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled) - .WithGasPrice(0) - .WithValue(0) - .TestObject; - - Block block = Build.A.Block.WithNumber(blockNumber).WithTransactions(tx).TestObject; - - BlockReceiptsTracer tracer = BuildTracer(block, tx, false, false); - Execute(tracer, tx, block); - _stateProvider.AccountExists(tx.SenderAddress).Should().BeTrue(); - } + [Test] + public void Disables_Eip158_for_system_transactions() + { + long blockNumber = MainnetSpecProvider.SpuriousDragonBlockNumber + 1; + _stateProvider.CreateAccount(TestItem.PrivateKeyA.Address, 0.Ether()); + IReleaseSpec spec = _specProvider.GetSpec((ForkActivation)blockNumber); + _stateProvider.Commit(spec); + Transaction tx = Build.A.SystemTransaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled) + .WithGasPrice(0) + .WithValue(0) + .TestObject; + + Block block = Build.A.Block.WithNumber(blockNumber).WithTransactions(tx).TestObject; + + BlockReceiptsTracer tracer = BuildTracer(block, tx, false, false); + Execute(tracer, tx, block); + _stateProvider.AccountExists(tx.SenderAddress).Should().BeTrue(); + } - [TestCase] - public void Balance_is_changed_on_buildup_and_restored() - { - long gasLimit = 100000; - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithValue(0).WithGasPrice(1).WithGasLimit(gasLimit).TestObject; - Block block = Build.A.Block.WithNumber(MainnetSpecProvider.ByzantiumBlockNumber).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; + [Test] + public void Balance_is_changed_on_buildup_and_restored() + { + long gasLimit = 100000; + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithValue(0).WithGasPrice(1).WithGasLimit(gasLimit).TestObject; + Block block = Build.A.Block.WithNumber(MainnetSpecProvider.ByzantiumBlockNumber).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; - Snapshot state = _stateProvider.TakeSnapshot(); - _transactionProcessor.BuildUp(tx, block.Header, NullTxTracer.Instance); - _stateProvider.GetBalance(TestItem.PrivateKeyA.Address).Should().Be(1.Ether() - 21000); + Snapshot state = _stateProvider.TakeSnapshot(); + _transactionProcessor.BuildUp(tx, block.Header, NullTxTracer.Instance); + _stateProvider.GetBalance(TestItem.PrivateKeyA.Address).Should().Be(1.Ether() - 21000); - _stateProvider.Restore(state); - _stateProvider.GetBalance(TestItem.PrivateKeyA.Address).Should().Be(1.Ether()); - } + _stateProvider.Restore(state); + _stateProvider.GetBalance(TestItem.PrivateKeyA.Address).Should().Be(1.Ether()); + } - [TestCase] - public void Account_is_not_created_on_buildup_and_restore() - { - long gasLimit = 100000; - Transaction tx = Build.A.Transaction - .WithValue(0.Ether()) - .WithGasPrice(1) - .WithGasLimit(gasLimit) - .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyD, _isEip155Enabled) - .TestObject; - Block block = Build.A.Block.WithNumber(MainnetSpecProvider.ByzantiumBlockNumber).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; - - _stateProvider.AccountExists(TestItem.PrivateKeyD.Address).Should().BeFalse(); - Snapshot state = _stateProvider.TakeSnapshot(); - _transactionProcessor.BuildUp(tx, block.Header, NullTxTracer.Instance); - _stateProvider.AccountExists(TestItem.PrivateKeyD.Address).Should().BeTrue(); - _stateProvider.Restore(state); - _stateProvider.AccountExists(TestItem.PrivateKeyD.Address).Should().BeFalse(); - } + [Test] + public void Account_is_not_created_on_buildup_and_restore() + { + long gasLimit = 100000; + Transaction tx = Build.A.Transaction + .WithValue(0.Ether()) + .WithGasPrice(1) + .WithGasLimit(gasLimit) + .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyD, _isEip155Enabled) + .TestObject; + Block block = Build.A.Block.WithNumber(MainnetSpecProvider.ByzantiumBlockNumber).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; + + _stateProvider.AccountExists(TestItem.PrivateKeyD.Address).Should().BeFalse(); + Snapshot state = _stateProvider.TakeSnapshot(); + _transactionProcessor.BuildUp(tx, block.Header, NullTxTracer.Instance); + _stateProvider.AccountExists(TestItem.PrivateKeyD.Address).Should().BeTrue(); + _stateProvider.Restore(state); + _stateProvider.AccountExists(TestItem.PrivateKeyD.Address).Should().BeFalse(); + } - [TestCase] - public void Nonce_is_not_changed_on_buildup_and_restore() - { - long gasLimit = 100000; - Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithValue(1.Ether() - (UInt256)gasLimit).WithGasPrice(1).WithGasLimit(gasLimit).TestObject; - Block block = Build.A.Block.WithNumber(MainnetSpecProvider.ByzantiumBlockNumber).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; - - Snapshot state = _stateProvider.TakeSnapshot(); - _transactionProcessor.BuildUp(tx, block.Header, NullTxTracer.Instance); - _stateProvider.GetNonce(TestItem.PrivateKeyA.Address).Should().Be(1); - _stateProvider.Restore(state); - _stateProvider.GetNonce(TestItem.PrivateKeyA.Address).Should().Be(0); - } + [Test] + public void Nonce_is_not_changed_on_buildup_and_restore() + { + long gasLimit = 100000; + Transaction tx = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithValue(1.Ether() - (UInt256)gasLimit).WithGasPrice(1).WithGasLimit(gasLimit).TestObject; + Block block = Build.A.Block.WithNumber(MainnetSpecProvider.ByzantiumBlockNumber).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; + + Snapshot state = _stateProvider.TakeSnapshot(); + _transactionProcessor.BuildUp(tx, block.Header, NullTxTracer.Instance); + _stateProvider.GetNonce(TestItem.PrivateKeyA.Address).Should().Be(1); + _stateProvider.Restore(state); + _stateProvider.GetNonce(TestItem.PrivateKeyA.Address).Should().Be(0); + } - [TestCase] - public void State_changed_twice_in_buildup_should_have_correct_gas_cost() - { - long gasLimit = 100000; - Transaction tx1 = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithValue(0).WithGasPrice(1).WithGasLimit(21000).TestObject; - Transaction tx2 = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithValue(0).WithNonce(1).WithGasPrice(1).WithGasLimit(21000).TestObject; - Block block = Build.A.Block.WithNumber(MainnetSpecProvider.ByzantiumBlockNumber).WithTransactions(tx1, tx2).WithGasLimit(gasLimit).TestObject; + [Test] + public void State_changed_twice_in_buildup_should_have_correct_gas_cost() + { + long gasLimit = 100000; + Transaction tx1 = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithValue(0).WithGasPrice(1).WithGasLimit(21000).TestObject; + Transaction tx2 = Build.A.Transaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled).WithValue(0).WithNonce(1).WithGasPrice(1).WithGasLimit(21000).TestObject; + Block block = Build.A.Block.WithNumber(MainnetSpecProvider.ByzantiumBlockNumber).WithTransactions(tx1, tx2).WithGasLimit(gasLimit).TestObject; - Snapshot state = _stateProvider.TakeSnapshot(); - _transactionProcessor.BuildUp(tx1, block.Header, NullTxTracer.Instance); - _stateProvider.GetBalance(TestItem.PrivateKeyA.Address).Should().Be(1.Ether() - 21000); + Snapshot state = _stateProvider.TakeSnapshot(); + _transactionProcessor.BuildUp(tx1, block.Header, NullTxTracer.Instance); + _stateProvider.GetBalance(TestItem.PrivateKeyA.Address).Should().Be(1.Ether() - 21000); - _transactionProcessor.BuildUp(tx2, block.Header, NullTxTracer.Instance); - _stateProvider.GetBalance(TestItem.PrivateKeyA.Address).Should().Be(1.Ether() - 42000); + _transactionProcessor.BuildUp(tx2, block.Header, NullTxTracer.Instance); + _stateProvider.GetBalance(TestItem.PrivateKeyA.Address).Should().Be(1.Ether() - 42000); - _stateProvider.Restore(state); - _stateProvider.GetBalance(TestItem.PrivateKeyA.Address).Should().Be(1.Ether()); - } + _stateProvider.Restore(state); + _stateProvider.GetBalance(TestItem.PrivateKeyA.Address).Should().Be(1.Ether()); + } - private BlockReceiptsTracer BuildTracer(Block block, Transaction tx, bool stateDiff, bool trace) - { - ParityTraceTypes types = ParityTraceTypes.None; - if (stateDiff) + private BlockReceiptsTracer BuildTracer(Block block, Transaction tx, bool stateDiff, bool trace) { - types = types | ParityTraceTypes.StateDiff; + ParityTraceTypes types = ParityTraceTypes.None; + if (stateDiff) + { + types = types | ParityTraceTypes.StateDiff; + } + + if (trace) + { + types = types | ParityTraceTypes.Trace; + } + + IBlockTracer otherTracer = types != ParityTraceTypes.None ? new ParityLikeBlockTracer(tx.Hash, ParityTraceTypes.Trace | ParityTraceTypes.StateDiff) : (IBlockTracer)NullBlockTracer.Instance; + BlockReceiptsTracer tracer = new(); + tracer.SetOtherTracer(otherTracer); + return tracer; } - if (trace) + private void Execute(BlockReceiptsTracer tracer, Transaction tx, Block block) { - types = types | ParityTraceTypes.Trace; + tracer.StartNewBlockTrace(block); + tracer.StartNewTxTrace(tx); + _transactionProcessor.Execute(tx, block.Header, tracer); + tracer.EndTxTrace(); + tracer.EndBlockTrace(); } - IBlockTracer otherTracer = types != ParityTraceTypes.None ? new ParityLikeBlockTracer(tx.Hash, ParityTraceTypes.Trace | ParityTraceTypes.StateDiff) : (IBlockTracer)NullBlockTracer.Instance; - BlockReceiptsTracer tracer = new(); - tracer.SetOtherTracer(otherTracer); - return tracer; - } - - private void Execute(BlockReceiptsTracer tracer, Transaction tx, Block block) - { - tracer.StartNewBlockTrace(block); - tracer.StartNewTxTrace(tx); - _transactionProcessor.Execute(tx, block.Header, tracer); - tracer.EndTxTrace(); - tracer.EndBlockTrace(); - } - - private void CallAndRestore(BlockReceiptsTracer tracer, Transaction tx, Block block) - { - tracer.StartNewBlockTrace(block); - tracer.StartNewTxTrace(tx); - _transactionProcessor.CallAndRestore(tx, block.Header, tracer); - tracer.EndTxTrace(); - tracer.EndBlockTrace(); + private void CallAndRestore(BlockReceiptsTracer tracer, Transaction tx, Block block) + { + tracer.StartNewBlockTrace(block); + tracer.StartNewTxTrace(tx); + _transactionProcessor.CallAndRestore(tx, block.Header, tracer); + tracer.EndTxTrace(); + tracer.EndBlockTrace(); + } } } diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTraceTest.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTraceTest.cs index 637a39ca3b9..2bf7a02c469 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTraceTest.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTraceTest.cs @@ -5,6 +5,7 @@ using Nethermind.Core; using Nethermind.Core.Test.Builders; using Nethermind.Evm.Tracing.ParityStyle; +using Nethermind.Int256; using Nethermind.Specs; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionSubstateTests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionSubstateTests.cs index a6177beaf5a..ae9b27e339c 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionSubstateTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionSubstateTests.cs @@ -4,7 +4,6 @@ using System; using FluentAssertions; using Nethermind.Core; -using Nethermind.Core.Extensions; using NUnit.Framework; namespace Nethermind.Evm.Test @@ -43,46 +42,5 @@ public void should_return_proper_revert_error_when_there_is_exception() true); transactionSubstate.Error.Should().Be("Reverted 0x0506070809"); } - - [Test] - [Description($"Replace with {nameof(should_return_proper_revert_error_when_revert_custom_error)} once fixed")] - public void should_return_proper_revert_error_when_revert_custom_error_badly_implemented() - { - // See: https://github.com/NethermindEth/nethermind/issues/6024 - - string hex = - "0x220266b600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001741413231206469646e2774207061792070726566756e64000000000000000000"; - byte[] data = Bytes.FromHexString(hex); - ReadOnlyMemory readOnlyMemory = new(data); - TransactionSubstate transactionSubstate = new( - readOnlyMemory, - 0, - new ArraySegment
(), - new LogEntry[] { }, - true, - true); - transactionSubstate.Error.Should().Be($"Reverted {hex}"); - } - - [Test] - [Ignore("Badly implemented")] - public void should_return_proper_revert_error_when_revert_custom_error() - { - byte[] data = { - 0x22, 0x02, 0x66, 0xb6, // Keccak of `FailedOp(uint256,string)` == 0x220266b6 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, - 0x17, - 0x41, 0x41, 0x32, 0x31, 0x20, 0x64, 0x69, 0x64, 0x6e, 0x27, 0x74, 0x20, 0x70, 0x61, 0x79, 0x20, 0x70, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, // "AA21 didn't pay prefund" - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - ReadOnlyMemory readOnlyMemory = new(data); - TransactionSubstate transactionSubstate = new( - readOnlyMemory, - 0, - new ArraySegment
(), - new LogEntry[] { }, - true, - true); - transactionSubstate.Error.Should().Be("Reverted 0x41413231206469646e2774207061792070726566756e64"); - } } } diff --git a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTests.cs b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTests.cs index baa5d866b0a..0a068e8ede8 100644 --- a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTests.cs @@ -10,551 +10,509 @@ using NUnit.Framework; using Nethermind.Specs; -namespace Nethermind.Evm.Test; - -[TestFixture] -[Parallelizable(ParallelScope.Self)] -public class VirtualMachineTests : VirtualMachineTestsBase +namespace Nethermind.Evm.Test { - [Test] - public void Stop() - { - TestAllTracerWithOutput receipt = Execute((byte)Instruction.STOP); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction)); - } - - [Test] - public void Trace() - { - GethLikeTxTrace trace = ExecuteAndTrace( - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.ADD, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - - Assert.That(trace.Entries.Count, Is.EqualTo(5), "number of entries"); - GethTxTraceEntry entry = trace.Entries[1]; - Assert.That(entry.Depth, Is.EqualTo(1), nameof(entry.Depth)); - Assert.That(entry.Gas, Is.EqualTo(79000 - GasCostOf.VeryLow), nameof(entry.Gas)); - Assert.That(entry.GasCost, Is.EqualTo(GasCostOf.VeryLow), nameof(entry.GasCost)); - Assert.That(entry.Memory.Count, Is.EqualTo(0), nameof(entry.Memory)); - Assert.That(entry.Stack.Count, Is.EqualTo(1), nameof(entry.Stack)); - Assert.That(trace.Entries[4].Storage.Count, Is.EqualTo(1), nameof(entry.Storage)); - Assert.That(entry.ProgramCounter, Is.EqualTo(2), nameof(entry.ProgramCounter)); - Assert.That(entry.Opcode, Is.EqualTo("PUSH1"), nameof(entry.Opcode)); - } - - [Test] - public void Trace_vm_errors() - { - GethLikeTxTrace trace = ExecuteAndTrace(1L, 21000L + 19000L, - (byte)Instruction.PUSH1, - 1, - (byte)Instruction.PUSH1, - 1, - (byte)Instruction.ADD, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - - Assert.True(trace.Entries.Any(e => e.Error is not null)); - } - - [Test] - public void Trace_memory_out_of_gas_exception() - { - byte[] code = Prepare.EvmCode - .PushData((UInt256)(10 * 1000 * 1000)) - .Op(Instruction.MLOAD) - .Done; - - GethLikeTxTrace trace = ExecuteAndTrace(1L, 21000L + 19000L, code); - - Assert.True(trace.Entries.Any(e => e.Error is not null)); - } - - [Test] - [Ignore("// https://github.com/NethermindEth/nethermind/issues/140")] - public void Trace_invalid_jump_exception() - { - byte[] code = Prepare.EvmCode - .PushData(255) - .Op(Instruction.JUMP) - .Done; - - GethLikeTxTrace trace = ExecuteAndTrace(1L, 21000L + 19000L, code); - - Assert.True(trace.Entries.Any(e => e.Error is not null)); - } - - [Test] - [Ignore("// https://github.com/NethermindEth/nethermind/issues/140")] - public void Trace_invalid_jumpi_exception() - { - byte[] code = Prepare.EvmCode - .PushData(1) - .PushData(255) - .Op(Instruction.JUMPI) - .Done; - - GethLikeTxTrace trace = ExecuteAndTrace(1L, 21000L + 19000L, code); - - Assert.True(trace.Entries.Any(e => e.Error is not null)); - } - - [Test(Description = "Test a case where the trace is created for one transaction and subsequent untraced transactions keep adding entries to the first trace created.")] - public void Trace_each_tx_separate() - { - GethLikeTxTrace trace = ExecuteAndTrace( - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.ADD, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - - Execute( - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.ADD, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - - Assert.That(trace.Entries.Count, Is.EqualTo(5), "number of entries"); - GethTxTraceEntry entry = trace.Entries[1]; - Assert.That(entry.Depth, Is.EqualTo(1), nameof(entry.Depth)); - Assert.That(entry.Gas, Is.EqualTo(79000 - GasCostOf.VeryLow), nameof(entry.Gas)); - Assert.That(entry.GasCost, Is.EqualTo(GasCostOf.VeryLow), nameof(entry.GasCost)); - Assert.That(entry.Memory.Count, Is.EqualTo(0), nameof(entry.Memory)); - Assert.That(entry.Stack.Count, Is.EqualTo(1), nameof(entry.Stack)); - Assert.That(trace.Entries[4].Storage.Count, Is.EqualTo(1), nameof(entry.Storage)); - Assert.That(entry.ProgramCounter, Is.EqualTo(2), nameof(entry.ProgramCounter)); - Assert.That(entry.Opcode, Is.EqualTo("PUSH1"), nameof(entry.Opcode)); - } - - [Test] - public void Add_0_0() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.ADD, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + 4 * GasCostOf.VeryLow + GasCostOf.SReset), "gas"); - Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(new byte[] { 0 }), "storage"); - } - - [Test] - public void Add_0_1() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.PUSH1, - 1, - (byte)Instruction.ADD, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + 4 * GasCostOf.VeryLow + GasCostOf.SSet), "gas"); - Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(new byte[] { 1 }), "storage"); - } - - [Test] - public void Add_1_0() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 1, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.ADD, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + 4 * GasCostOf.VeryLow + GasCostOf.SSet), "gas"); - Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(new byte[] { 1 }), "storage"); - } - - [Test] - public void Mstore() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 96, // data - (byte)Instruction.PUSH1, - 64, // position - (byte)Instruction.MSTORE); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 3 + GasCostOf.Memory * 3), "gas"); - } - - [Test] - public void Mstore_twice_same_location() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 96, - (byte)Instruction.PUSH1, - 64, - (byte)Instruction.MSTORE, - (byte)Instruction.PUSH1, - 96, - (byte)Instruction.PUSH1, - 64, - (byte)Instruction.MSTORE); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 6 + GasCostOf.Memory * 3), "gas"); - } - - [Test] - public void Mload() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 64, // position - (byte)Instruction.MLOAD); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 2 + GasCostOf.Memory * 3), "gas"); - } - - [Test] - public void Mload_after_mstore() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 96, - (byte)Instruction.PUSH1, - 64, - (byte)Instruction.MSTORE, - (byte)Instruction.PUSH1, - 64, - (byte)Instruction.MLOAD); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 5 + GasCostOf.Memory * 3), "gas"); - } - - [Test] - public void Dup1() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.DUP1); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 2), "gas"); - } - - [Test] - public void Codecopy() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 32, // length - (byte)Instruction.PUSH1, - 0, // src - (byte)Instruction.PUSH1, - 32, // dest - (byte)Instruction.CODECOPY); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 4 + GasCostOf.Memory * 3), "gas"); - } - - [Test] - public void Swap() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 32, // length - (byte)Instruction.PUSH1, - 0, // src - (byte)Instruction.SWAP1); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 3), "gas"); - } - - [Test] - public void Sload() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 0, // index - (byte)Instruction.SLOAD); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 1 + GasCostOf.SLoadEip150), "gas"); - } - - [Test] - public void Exp_2_160() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 160, - (byte)Instruction.PUSH1, - 2, - (byte)Instruction.EXP, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 3 + GasCostOf.SSet + GasCostOf.Exp + GasCostOf.ExpByteEip160), "gas"); - Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(BigInteger.Pow(2, 160).ToBigEndianByteArray()), "storage"); - } - - [Test] - public void Exp_0_0() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.EXP, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 3 + GasCostOf.Exp + GasCostOf.SSet), "gas"); - Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(BigInteger.One.ToBigEndianByteArray()), "storage"); - } - - [Test] - public void Exp_0_160() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 160, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.EXP, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 3 + GasCostOf.Exp + GasCostOf.ExpByteEip160 + GasCostOf.SReset), "gas"); - Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(BigInteger.Zero.ToBigEndianByteArray()), "storage"); - } - - [Test] - public void Exp_1_160() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 160, - (byte)Instruction.PUSH1, - 1, - (byte)Instruction.EXP, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 3 + GasCostOf.Exp + GasCostOf.ExpByteEip160 + GasCostOf.SSet), "gas"); - Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(BigInteger.One.ToBigEndianByteArray()), "storage"); - } - - [Test] - public void Sub_0_0() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SUB, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 4 + GasCostOf.SReset), "gas"); - Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(new byte[] { 0 }), "storage"); - } - - [Test] - public void Not_0() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.NOT, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 3 + GasCostOf.SSet), "gas"); - Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo((BigInteger.Pow(2, 256) - 1).ToBigEndianByteArray()), "storage"); - } - - [Test] - public void Or_0_0() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.OR, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 4 + GasCostOf.SReset), "gas"); - Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(BigInteger.Zero.ToBigEndianByteArray()), "storage"); - } - - [Test] - public void Sstore_twice_0_same_storage_should_refund_only_once() - { - TestAllTracerWithOutput receipt = Execute( - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.PUSH1, - 0, - (byte)Instruction.SSTORE); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 2 + GasCostOf.SReset), "gas"); - Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(BigInteger.Zero.ToBigEndianByteArray()), "storage"); - } - - /// - /// TLoad gas cost check - /// - [Test] - public void Tload() - { - byte[] code = Prepare.EvmCode - .PushData(96) - .Op(Instruction.TLOAD) - .Done; - - TestAllTracerWithOutput receipt = Execute((MainnetSpecProvider.GrayGlacierBlockNumber, MainnetSpecProvider.CancunBlockTimestamp), 100000, code); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 1 + GasCostOf.TLoad), "gas"); - } - - /// - /// MCOPY gas cost check - /// - [Test] - public void MCopy() - { - byte[] data = new byte[] { 0x60, 0x17, 0x60, 0x03, 0x02, 0x00 }; - byte[] code = Prepare.EvmCode - .MSTORE(0, data.PadRight(32)) - .MCOPY(6, 0, 6) - .STOP() - .Done; - GethLikeTxTrace traces = Execute(new GethLikeTxMemoryTracer(GethTraceOptions.Default), code, MainnetSpecProvider.CancunActivation).BuildResult(); - - Assert.That(traces.Entries[^2].GasCost, Is.EqualTo(GasCostOf.VeryLow + GasCostOf.VeryLow * ((data.Length + 31) / 32) + GasCostOf.Memory * 0), "gas"); - } - - [Test] - public void MCopy_exclusive_areas() - { - byte[] data = Bytes.FromHexString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"); - byte[] bytecode = Prepare.EvmCode - .MSTORE(0, data) - .MCOPY(32, 0, 32) - .STOP() - .Done; - GethLikeTxTrace traces = Execute( - new GethLikeTxMemoryTracer(GethTraceOptions.Default with { EnableMemory = true }), - bytecode, - MainnetSpecProvider.CancunActivation) - .BuildResult(); - - var copied = traces.Entries.Last().Memory[0]; - var origin = traces.Entries.Last().Memory[1]; - - Assert.That(traces.Entries[^2].GasCost, Is.EqualTo(GasCostOf.VeryLow + GasCostOf.VeryLow * ((data.Length + 31) / 32) + GasCostOf.Memory * 1), "gas"); - Assert.That(origin, Is.EqualTo(copied)); - } - - - [Test] - public void MCopy_Overwrite_areas_copy_right() - { - int SLICE_SIZE = 8; - byte[] data = Bytes.FromHexString("0102030405060708000000000000000000000000000000000000000000000000"); - byte[] bytecode = Prepare.EvmCode - .MSTORE(0, data) - .MCOPY(1, 0, (UInt256)SLICE_SIZE) - .STOP() - .Done; - GethLikeTxTrace traces = Execute( - new GethLikeTxMemoryTracer(GethTraceOptions.Default with { EnableMemory = true }), - bytecode, - MainnetSpecProvider.CancunActivation) - .BuildResult(); - - var result = traces.Entries.Last().Memory[0]; - - Assert.That(traces.Entries[^2].GasCost, Is.EqualTo(GasCostOf.VeryLow + GasCostOf.VeryLow * (SLICE_SIZE + 31) / 32), "gas"); - Assert.That(result, Is.EqualTo("0101020304050607080000000000000000000000000000000000000000000000"), "memory state"); - } - - [Test] - public void MCopy_twice_same_location() - { - byte[] data = Bytes.FromHexString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"); - byte[] bytecode = Prepare.EvmCode - .MSTORE(0, data) - .MCOPY(0, 0, 32) - .STOP() - .Done; - GethLikeTxTrace traces = Execute( - new GethLikeTxMemoryTracer(GethTraceOptions.Default with { EnableMemory = true }), - bytecode, - MainnetSpecProvider.CancunActivation) - .BuildResult(); - - Assert.That(traces.Entries[^2].GasCost, Is.EqualTo(GasCostOf.VeryLow + GasCostOf.VeryLow * ((data.Length + 31) / 32)), "gas"); - Assert.That(traces.Entries.Last().Memory.Count, Is.EqualTo(1)); - } - - [Test] - public void MCopy_Overwrite_areas_copy_left() - { - int SLICE_SIZE = 8; - byte[] data = Bytes.FromHexString("0001020304050607080000000000000000000000000000000000000000000000"); - byte[] bytecode = Prepare.EvmCode - .MSTORE(0, data) - .MCOPY(0, 1, (UInt256)SLICE_SIZE) - .STOP() - .Done; - GethLikeTxTrace traces = Execute( - new GethLikeTxMemoryTracer(GethTraceOptions.Default with { EnableMemory = true }), - bytecode, - MainnetSpecProvider.CancunActivation) - .BuildResult(); - - var result = traces.Entries.Last().Memory[0]; - - Assert.That(traces.Entries[^2].GasCost, Is.EqualTo(GasCostOf.VeryLow + GasCostOf.VeryLow * (SLICE_SIZE + 31) / 32), "gas"); - Assert.That(result, Is.EqualTo("0102030405060708080000000000000000000000000000000000000000000000"), "memory state"); - } - - /// - /// TStore gas cost check - /// - [Test] - public void Tstore() - { - byte[] code = Prepare.EvmCode - .PushData(96) - .PushData(64) - .Op(Instruction.TSTORE) - .Done; - - TestAllTracerWithOutput receipt = Execute((MainnetSpecProvider.GrayGlacierBlockNumber, MainnetSpecProvider.CancunBlockTimestamp), 100000, code); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 2 + GasCostOf.TStore), "gas"); - } - - [Test] - public void Revert() - { - // See: https://eips.ethereum.org/EIPS/eip-140 - - byte[] code = Bytes.FromHexString("0x6c726576657274656420646174616000557f726576657274206d657373616765000000000000000000000000000000000000600052600e6000fd"); - TestAllTracerWithOutput receipt = Execute(blockNumber: MainnetSpecProvider.ByzantiumBlockNumber, 100_000, code); - - Assert.That(receipt.Error, Is.EqualTo("Reverted 0x726576657274206d657373616765")); - Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + 20024)); + [TestFixture] + [Parallelizable(ParallelScope.Self)] + public class VirtualMachineTests : VirtualMachineTestsBase + { + [Test] + public void Stop() + { + TestAllTracerWithOutput receipt = Execute((byte)Instruction.STOP); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction)); + } + + [Test] + public void Trace() + { + GethLikeTxTrace trace = ExecuteAndTrace( + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.ADD, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + + Assert.That(trace.Entries.Count, Is.EqualTo(5), "number of entries"); + GethTxTraceEntry entry = trace.Entries[1]; + Assert.That(entry.Depth, Is.EqualTo(1), nameof(entry.Depth)); + Assert.That(entry.Gas, Is.EqualTo(79000 - GasCostOf.VeryLow), nameof(entry.Gas)); + Assert.That(entry.GasCost, Is.EqualTo(GasCostOf.VeryLow), nameof(entry.GasCost)); + Assert.That(entry.Memory.Count, Is.EqualTo(0), nameof(entry.Memory)); + Assert.That(entry.Stack.Count, Is.EqualTo(1), nameof(entry.Stack)); + Assert.That(trace.Entries[4].Storage.Count, Is.EqualTo(1), nameof(entry.Storage)); + Assert.That(entry.Pc, Is.EqualTo(2), nameof(entry.Pc)); + Assert.That(entry.Operation, Is.EqualTo("PUSH1"), nameof(entry.Operation)); + } + + [Test] + public void Trace_vm_errors() + { + GethLikeTxTrace trace = ExecuteAndTrace(1L, 21000L + 19000L, + (byte)Instruction.PUSH1, + 1, + (byte)Instruction.PUSH1, + 1, + (byte)Instruction.ADD, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + + Assert.True(trace.Entries.Any(e => e.Error is not null)); + } + + [Test] + public void Trace_memory_out_of_gas_exception() + { + byte[] code = Prepare.EvmCode + .PushData((UInt256)(10 * 1000 * 1000)) + .Op(Instruction.MLOAD) + .Done; + + GethLikeTxTrace trace = ExecuteAndTrace(1L, 21000L + 19000L, code); + + Assert.True(trace.Entries.Any(e => e.Error is not null)); + } + + [Test] + [Ignore("// https://github.com/NethermindEth/nethermind/issues/140")] + public void Trace_invalid_jump_exception() + { + byte[] code = Prepare.EvmCode + .PushData(255) + .Op(Instruction.JUMP) + .Done; + + GethLikeTxTrace trace = ExecuteAndTrace(1L, 21000L + 19000L, code); + + Assert.True(trace.Entries.Any(e => e.Error is not null)); + } + + [Test] + [Ignore("// https://github.com/NethermindEth/nethermind/issues/140")] + public void Trace_invalid_jumpi_exception() + { + byte[] code = Prepare.EvmCode + .PushData(1) + .PushData(255) + .Op(Instruction.JUMPI) + .Done; + + GethLikeTxTrace trace = ExecuteAndTrace(1L, 21000L + 19000L, code); + + Assert.True(trace.Entries.Any(e => e.Error is not null)); + } + + [Test(Description = "Test a case where the trace is created for one transaction and subsequent untraced transactions keep adding entries to the first trace created.")] + public void Trace_each_tx_separate() + { + GethLikeTxTrace trace = ExecuteAndTrace( + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.ADD, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + + Execute( + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.ADD, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + + Assert.That(trace.Entries.Count, Is.EqualTo(5), "number of entries"); + GethTxTraceEntry entry = trace.Entries[1]; + Assert.That(entry.Depth, Is.EqualTo(1), nameof(entry.Depth)); + Assert.That(entry.Gas, Is.EqualTo(79000 - GasCostOf.VeryLow), nameof(entry.Gas)); + Assert.That(entry.GasCost, Is.EqualTo(GasCostOf.VeryLow), nameof(entry.GasCost)); + Assert.That(entry.Memory.Count, Is.EqualTo(0), nameof(entry.Memory)); + Assert.That(entry.Stack.Count, Is.EqualTo(1), nameof(entry.Stack)); + Assert.That(trace.Entries[4].Storage.Count, Is.EqualTo(1), nameof(entry.Storage)); + Assert.That(entry.Pc, Is.EqualTo(2), nameof(entry.Pc)); + Assert.That(entry.Operation, Is.EqualTo("PUSH1"), nameof(entry.Operation)); + } + + [Test] + public void Add_0_0() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.ADD, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + 4 * GasCostOf.VeryLow + GasCostOf.SReset), "gas"); + Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(new byte[] { 0 }), "storage"); + } + + [Test] + public void Add_0_1() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.PUSH1, + 1, + (byte)Instruction.ADD, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + 4 * GasCostOf.VeryLow + GasCostOf.SSet), "gas"); + Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(new byte[] { 1 }), "storage"); + } + + [Test] + public void Add_1_0() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 1, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.ADD, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + 4 * GasCostOf.VeryLow + GasCostOf.SSet), "gas"); + Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(new byte[] { 1 }), "storage"); + } + + [Test] + public void Mstore() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 96, // data + (byte)Instruction.PUSH1, + 64, // position + (byte)Instruction.MSTORE); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 3 + GasCostOf.Memory * 3), "gas"); + } + + [Test] + public void Mstore_twice_same_location() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 96, + (byte)Instruction.PUSH1, + 64, + (byte)Instruction.MSTORE, + (byte)Instruction.PUSH1, + 96, + (byte)Instruction.PUSH1, + 64, + (byte)Instruction.MSTORE); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 6 + GasCostOf.Memory * 3), "gas"); + } + + [Test] + public void Mload() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 64, // position + (byte)Instruction.MLOAD); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 2 + GasCostOf.Memory * 3), "gas"); + } + + [Test] + public void Mload_after_mstore() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 96, + (byte)Instruction.PUSH1, + 64, + (byte)Instruction.MSTORE, + (byte)Instruction.PUSH1, + 64, + (byte)Instruction.MLOAD); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 5 + GasCostOf.Memory * 3), "gas"); + } + + [Test] + public void Dup1() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.DUP1); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 2), "gas"); + } + + [Test] + public void Codecopy() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 32, // length + (byte)Instruction.PUSH1, + 0, // src + (byte)Instruction.PUSH1, + 32, // dest + (byte)Instruction.CODECOPY); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 4 + GasCostOf.Memory * 3), "gas"); + } + + [Test] + public void Swap() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 32, // length + (byte)Instruction.PUSH1, + 0, // src + (byte)Instruction.SWAP1); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 3), "gas"); + } + + [Test] + public void Sload() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 0, // index + (byte)Instruction.SLOAD); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 1 + GasCostOf.SLoadEip150), "gas"); + } + + [Test] + public void Exp_2_160() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 160, + (byte)Instruction.PUSH1, + 2, + (byte)Instruction.EXP, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 3 + GasCostOf.SSet + GasCostOf.Exp + GasCostOf.ExpByteEip160), "gas"); + Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(BigInteger.Pow(2, 160).ToBigEndianByteArray()), "storage"); + } + + [Test] + public void Exp_0_0() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.EXP, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 3 + GasCostOf.Exp + GasCostOf.SSet), "gas"); + Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(BigInteger.One.ToBigEndianByteArray()), "storage"); + } + + [Test] + public void Exp_0_160() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 160, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.EXP, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 3 + GasCostOf.Exp + GasCostOf.ExpByteEip160 + GasCostOf.SReset), "gas"); + Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(BigInteger.Zero.ToBigEndianByteArray()), "storage"); + } + + [Test] + public void Exp_1_160() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 160, + (byte)Instruction.PUSH1, + 1, + (byte)Instruction.EXP, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 3 + GasCostOf.Exp + GasCostOf.ExpByteEip160 + GasCostOf.SSet), "gas"); + Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(BigInteger.One.ToBigEndianByteArray()), "storage"); + } + + [Test] + public void Sub_0_0() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SUB, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 4 + GasCostOf.SReset), "gas"); + Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(new byte[] { 0 }), "storage"); + } + + [Test] + public void Not_0() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.NOT, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 3 + GasCostOf.SSet), "gas"); + Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo((BigInteger.Pow(2, 256) - 1).ToBigEndianByteArray()), "storage"); + } + + [Test] + public void Or_0_0() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.OR, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 4 + GasCostOf.SReset), "gas"); + Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(BigInteger.Zero.ToBigEndianByteArray()), "storage"); + } + + [Test] + public void Sstore_twice_0_same_storage_should_refund_only_once() + { + TestAllTracerWithOutput receipt = Execute( + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.PUSH1, + 0, + (byte)Instruction.SSTORE); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 2 + GasCostOf.SReset), "gas"); + Assert.That(TestState.Get(new StorageCell(Recipient, 0)), Is.EqualTo(BigInteger.Zero.ToBigEndianByteArray()), "storage"); + } + + /// + /// TLoad gas cost check + /// + [Test] + public void Tload() + { + byte[] code = Prepare.EvmCode + .PushData(96) + .Op(Instruction.TLOAD) + .Done; + + TestAllTracerWithOutput receipt = Execute(MainnetSpecProvider.GrayGlacierBlockNumber, 100000, code, timestamp: MainnetSpecProvider.CancunBlockTimestamp); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 1 + GasCostOf.TLoad), "gas"); + } + + /// + /// TStore gas cost check + /// + [Test] + public void Tstore() + { + byte[] code = Prepare.EvmCode + .PushData(96) + .PushData(64) + .Op(Instruction.TSTORE) + .Done; + + TestAllTracerWithOutput receipt = Execute(MainnetSpecProvider.GrayGlacierBlockNumber, 100000, code, timestamp: MainnetSpecProvider.CancunBlockTimestamp); + Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 2 + GasCostOf.TStore), "gas"); + } + + [Test] + [Ignore("Not yet implemented")] + public void Ropsten_attack_contract_test() + { + //PUSH1 0x60 + //PUSH1 0x40 + //MSTORE + //PUSH4 0xffffffff + //PUSH1 0xe0 + //PUSH1 0x02 + //EXP + //PUSH1 0x00 + //CALLDATALOAD + //DIV + //AND + //PUSH4 0x9fe12a6a + //DUP2 + //EQ + //PUSH1 0x22 + //JUMPI + //JUMPDEST + //PUSH1 0x00 + //JUMP + //JUMPDEST + //CALLVALUE + //PUSH1 0x00 + //JUMPI + //PUSH1 0x38 + //PUSH1 0x04 + //CALLDATALOAD + //PUSH1 0x24 + //CALLDATALOAD + //PUSH1 0xff + //PUSH1 0x44 + //CALLDATALOAD + //AND + //PUSH1 0x3a + //JUMP + //JUMPDEST + //STOP + //JUMPDEST + //PUSH1 0x40 + //DUP1 + //MLOAD + //PUSH1 0xff + //DUP4 + //AND + //DUP2 + //MSTORE + //SWAP1 + //MLOAD + //DUP4 + //SWAP2 + //DUP6 + //SWAP2 + //PUSH32 0x2f554056349a3530a4cabe3891d711b94a109411500421e48fc5256d660d7a79 + //SWAP2 + //DUP2 + //SWAP1 + //SUB + //PUSH1 0x20 + //ADD + //SWAP1 + //LOG3 + //JUMPDEST + //POP + //POP + //POP + //JUMP + //STOP + } } } diff --git a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs index 0a902722594..10bd69c260a 100644 --- a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs +++ b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs @@ -3,10 +3,12 @@ using System; using System.Numerics; +using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; +using Nethermind.Core.Test; using Nethermind.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; @@ -20,339 +22,284 @@ using Nethermind.Trie.Pruning; using NUnit.Framework; -namespace Nethermind.Evm.Test; - -public class VirtualMachineTestsBase +namespace Nethermind.Evm.Test { - protected const string SampleHexData1 = "a01234"; - protected const string SampleHexData2 = "b15678"; - protected const string HexZero = "00"; - protected const long DefaultBlockGasLimit = 8000000; - - private IEthereumEcdsa _ethereumEcdsa; - protected ITransactionProcessor _processor; - private IDb _stateDb; - - protected VirtualMachine Machine { get; private set; } - protected IWorldState TestState { get; private set; } - protected static Address Contract { get; } = new("0xd75a3a95360e44a3874e691fb48d77855f127069"); - protected static Address Sender { get; } = TestItem.AddressA; - protected static Address Recipient { get; } = TestItem.AddressB; - protected static Address Miner { get; } = TestItem.AddressD; - - protected static PrivateKey SenderKey { get; } = TestItem.PrivateKeyA; - protected static PrivateKey RecipientKey { get; } = TestItem.PrivateKeyB; - protected static PrivateKey MinerKey { get; } = TestItem.PrivateKeyD; - - protected virtual ForkActivation Activation => (BlockNumber, Timestamp); - protected virtual long BlockNumber { get; } = MainnetSpecProvider.ByzantiumBlockNumber; - protected virtual ulong Timestamp => 0UL; - protected virtual ISpecProvider SpecProvider => MainnetSpecProvider.Instance; - protected IReleaseSpec Spec => SpecProvider.GetSpec(Activation); - - protected virtual ILogManager GetLogManager() - { - return LimboLogs.Instance; - } - - [SetUp] - public virtual void Setup() - { - ILogManager logManager = GetLogManager(); - - IDb codeDb = new MemDb(); - _stateDb = new MemDb(); - ITrieStore trieStore = new TrieStore(_stateDb, logManager); - TestState = new WorldState(trieStore, codeDb, logManager); - _ethereumEcdsa = new EthereumEcdsa(SpecProvider.ChainId, logManager); - IBlockhashProvider blockhashProvider = TestBlockhashProvider.Instance; - Machine = new VirtualMachine(blockhashProvider, SpecProvider, logManager); - _processor = new TransactionProcessor(SpecProvider, TestState, Machine, logManager); - } - - protected GethLikeTxTrace ExecuteAndTrace(params byte[] code) - { - GethLikeTxMemoryTracer tracer = new(GethTraceOptions.Default with { EnableMemory = true }); - (Block block, Transaction transaction) = PrepareTx(Activation, 100000, code); - _processor.Execute(transaction, block.Header, tracer); - return tracer.BuildResult(); - } - - protected GethLikeTxTrace ExecuteAndTrace(long blockNumber, long gasLimit, params byte[] code) - { - GethLikeTxMemoryTracer tracer = new(GethTraceOptions.Default); - (Block block, Transaction transaction) = PrepareTx((blockNumber, Timestamp), gasLimit, code); - _processor.Execute(transaction, block.Header, tracer); - return tracer.BuildResult(); - } - - protected GethLikeTxTrace ExecuteAndTraceToFile(Action dumpCallback, byte[] code, GethTraceOptions options) + public class VirtualMachineTestsBase { - GethLikeTxFileTracer tracer = new(dumpCallback, options); - (Block block, Transaction transaction) = PrepareTx(Activation, 100000, code); - _processor.Execute(transaction, block.Header, tracer); - return tracer.BuildResult(); - } - - /// - /// deprecated. Please use activation instead of blockNumber. - /// - protected TestAllTracerWithOutput Execute(long blockNumber, params byte[] code) - { - return Execute((blockNumber, Timestamp), code); - } - - protected TestAllTracerWithOutput Execute(ForkActivation activation, params byte[] code) - { - (Block block, Transaction transaction) = PrepareTx(activation, 100000, code); - TestAllTracerWithOutput tracer = CreateTracer(); - _processor.Execute(transaction, block.Header, tracer); - return tracer; - } + protected const string SampleHexData1 = "a01234"; + protected const string SampleHexData2 = "b15678"; + protected const string HexZero = "00"; + protected const long DefaultBlockGasLimit = 8000000; + + private IEthereumEcdsa _ethereumEcdsa; + protected ITransactionProcessor _processor; + private IDb _stateDb; + + protected VirtualMachine Machine { get; private set; } + protected IWorldState TestState { get; private set; } + protected static Address Contract { get; } = new("0xd75a3a95360e44a3874e691fb48d77855f127069"); + protected static Address Sender { get; } = TestItem.AddressA; + protected static Address Recipient { get; } = TestItem.AddressB; + protected static Address Miner { get; } = TestItem.AddressD; + + protected static PrivateKey SenderKey { get; } = TestItem.PrivateKeyA; + protected static PrivateKey RecipientKey { get; } = TestItem.PrivateKeyB; + protected static PrivateKey MinerKey { get; } = TestItem.PrivateKeyD; + + protected virtual long BlockNumber => MainnetSpecProvider.ByzantiumBlockNumber; + protected virtual ulong Timestamp => 0UL; + protected virtual ISpecProvider SpecProvider => MainnetSpecProvider.Instance; + protected IReleaseSpec Spec => SpecProvider.GetSpec(BlockNumber, Timestamp); + + protected virtual ILogManager GetLogManager() + { + return LimboLogs.Instance; + } - protected TestAllTracerWithOutput Execute(params byte[] code) - { - return Execute(Activation, code); - } + [SetUp] + public virtual void Setup() + { + ILogManager logManager = GetLogManager(); + + IDb codeDb = new MemDb(); + _stateDb = new MemDb(); + ITrieStore trieStore = new TrieStore(_stateDb, logManager); + TestState = new WorldState(trieStore, codeDb, logManager); + _ethereumEcdsa = new EthereumEcdsa(SpecProvider.ChainId, logManager); + IBlockhashProvider blockhashProvider = TestBlockhashProvider.Instance; + Machine = new VirtualMachine(blockhashProvider, SpecProvider, logManager); + _processor = new TransactionProcessor(SpecProvider, TestState, Machine, logManager); + } - protected virtual TestAllTracerWithOutput CreateTracer() => new(); + protected GethLikeTxTrace ExecuteAndTrace(params byte[] code) + { + GethLikeTxTracer tracer = new(GethTraceOptions.Default); + (Block block, Transaction transaction) = PrepareTx(BlockNumber, 100000, code); + _processor.Execute(transaction, block.Header, tracer); + return tracer.BuildResult(); + } - protected T Execute(T tracer, byte[] code, ForkActivation? forkActivation = null) where T : ITxTracer - { - (Block block, Transaction transaction) = PrepareTx(forkActivation ?? Activation, 100000, code); - _processor.Execute(transaction, block.Header, tracer); - return tracer; - } + protected GethLikeTxTrace ExecuteAndTrace(long blockNumber, long gasLimit, params byte[] code) + { + GethLikeTxTracer tracer = new(GethTraceOptions.Default); + (Block block, Transaction transaction) = PrepareTx(blockNumber, gasLimit, code); + _processor.Execute(transaction, block.Header, tracer); + return tracer.BuildResult(); + } - /// - /// deprecated. Please use activation instead of blockNumber. - /// - protected TestAllTracerWithOutput Execute(long blockNumber, long gasLimit, byte[] code, - long blockGasLimit = DefaultBlockGasLimit, byte[][] blobVersionedHashes = null) - { - (Block block, Transaction transaction) = PrepareTx((blockNumber, Timestamp), gasLimit, code, - blockGasLimit: blockGasLimit, blobVersionedHashes: blobVersionedHashes); - TestAllTracerWithOutput tracer = CreateTracer(); - _processor.Execute(transaction, block.Header, tracer); - return tracer; - } + protected TestAllTracerWithOutput Execute(long blockNumber, ulong timestamp, params byte[] code) + { + (Block block, Transaction transaction) = PrepareTx(blockNumber, 100000, code, timestamp: timestamp); + TestAllTracerWithOutput tracer = CreateTracer(); + _processor.Execute(transaction, block.Header, tracer); + return tracer; + } - protected TestAllTracerWithOutput Execute(ForkActivation activation, long gasLimit, byte[] code, - long blockGasLimit = DefaultBlockGasLimit, byte[][] blobVersionedHashes = null) - { - (Block block, Transaction transaction) = PrepareTx(activation, gasLimit, code, - blockGasLimit: blockGasLimit, blobVersionedHashes: blobVersionedHashes); - TestAllTracerWithOutput tracer = CreateTracer(); - _processor.Execute(transaction, block.Header, tracer); - return tracer; - } + protected TestAllTracerWithOutput Execute(params byte[] code) + { + return Execute(BlockNumber, Timestamp, code); + } - /// - /// deprecated. Please use activation instead of blockNumber. - /// - protected (Block block, Transaction transaction) PrepareTx( - long blockNumber, - long gasLimit, - byte[]? code = null, - SenderRecipientAndMiner? senderRecipientAndMiner = null, - int value = 1, - long blockGasLimit = DefaultBlockGasLimit, - byte[][]? blobVersionedHashes = null, - ulong excessBlobGas = 0) - { - return PrepareTx((blockNumber, Timestamp), gasLimit, code, senderRecipientAndMiner, value, blockGasLimit, blobVersionedHashes, excessBlobGas); - } + protected virtual TestAllTracerWithOutput CreateTracer() => new(); - protected (Block block, Transaction transaction) PrepareTx( - ForkActivation activation, - long gasLimit, - byte[]? code = null, - SenderRecipientAndMiner? senderRecipientAndMiner = null, - int value = 1, - long blockGasLimit = DefaultBlockGasLimit, - byte[][]? blobVersionedHashes = null, - ulong excessBlobGas = 0) - { - senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; + protected T Execute(T tracer, params byte[] code) where T : ITxTracer + { + (Block block, Transaction transaction) = PrepareTx(BlockNumber, 100000, code, timestamp: Timestamp); + _processor.Execute(transaction, block.Header, tracer); + return tracer; + } - // checking if account exists - because creating new accounts overwrites already existing accounts, - // thus overwriting storage roots - essentially clearing the storage slots - // earlier it used to work - because the cache mapping address:storageTree was never cleared on account of - // TestState.CommitTrees() not being called. But now the WorldState.CommitTrees which also calls TestState.CommitTrees, clearing the cache. - if (!TestState.AccountExists(senderRecipientAndMiner.Sender)) - TestState.CreateAccount(senderRecipientAndMiner.Sender, 100.Ether()); - else - TestState.AddToBalance(senderRecipientAndMiner.Sender, 100.Ether(), SpecProvider.GenesisSpec); + protected TestAllTracerWithOutput Execute(long blockNumber, long gasLimit, byte[] code, + long blockGasLimit = DefaultBlockGasLimit, ulong timestamp = 0, byte[][] blobVersionedHashes = null) + { + (Block block, Transaction transaction) = PrepareTx(blockNumber, gasLimit, code, + blockGasLimit: blockGasLimit, timestamp: timestamp, blobVersionedHashes: blobVersionedHashes); + TestAllTracerWithOutput tracer = CreateTracer(); + _processor.Execute(transaction, block.Header, tracer); + return tracer; + } - if (!TestState.AccountExists(senderRecipientAndMiner.Recipient)) - TestState.CreateAccount(senderRecipientAndMiner.Recipient, 100.Ether()); - else - TestState.AddToBalance(senderRecipientAndMiner.Recipient, 100.Ether(), SpecProvider.GenesisSpec); + protected (Block block, Transaction transaction) PrepareTx( + long blockNumber, + long gasLimit, + byte[]? code = null, + SenderRecipientAndMiner? senderRecipientAndMiner = null, + int value = 1, + long blockGasLimit = DefaultBlockGasLimit, + ulong timestamp = 0, + byte[][]? blobVersionedHashes = null) + { + senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; + + // checking if account exists - because creating new accounts overwrites already existing accounts, + // thus overwriting storage roots - essentially clearing the storage slots + // earlier it used to work - because the cache mapping address:storageTree was never cleared on account of + // TestState.CommitTrees() not being called. But now the WorldState.CommitTrees which also calls TestState.CommitTrees, clearing the cache. + if (!TestState.AccountExists(senderRecipientAndMiner.Sender)) + TestState.CreateAccount(senderRecipientAndMiner.Sender, 100.Ether()); + else + TestState.AddToBalance(senderRecipientAndMiner.Sender, 100.Ether(), SpecProvider.GenesisSpec); + + if (!TestState.AccountExists(senderRecipientAndMiner.Recipient)) + TestState.CreateAccount(senderRecipientAndMiner.Recipient, 100.Ether()); + else + TestState.AddToBalance(senderRecipientAndMiner.Recipient, 100.Ether(), SpecProvider.GenesisSpec); + + if (code is not null) + { + TestState.InsertCode(senderRecipientAndMiner.Recipient, code, SpecProvider.GenesisSpec); + } + + GetLogManager().GetClassLogger().Debug("Committing initial state"); + TestState.Commit(SpecProvider.GenesisSpec); + GetLogManager().GetClassLogger().Debug("Committed initial state"); + GetLogManager().GetClassLogger().Debug("Committing initial tree"); + TestState.CommitTree(0); + GetLogManager().GetClassLogger().Debug("Committed initial tree"); + + Transaction transaction = Build.A.Transaction + .WithGasLimit(gasLimit) + .WithGasPrice(1) + .WithValue(value) + .WithBlobVersionedHashes(blobVersionedHashes) + .WithNonce(TestState.GetNonce(senderRecipientAndMiner.Sender)) + .To(senderRecipientAndMiner.Recipient) + .SignedAndResolved(_ethereumEcdsa, senderRecipientAndMiner.SenderKey) + .TestObject; + + Block block = BuildBlock(blockNumber, senderRecipientAndMiner, transaction, blockGasLimit, timestamp); + return (block, transaction); + } - if (code is not null) + protected (Block block, Transaction transaction) PrepareTx(long blockNumber, long gasLimit, byte[] code, + byte[] input, UInt256 value, SenderRecipientAndMiner senderRecipientAndMiner = null) { + senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; + + // checking if account exists - because creating new accounts overwrites already existing accounts, + // thus overwriting storage roots - essentially clearing the storage slots + // earlier it used to work - because the cache mapping address:storageTree was never cleared on account of + // TestState.CommitTrees() not being called. But now the WorldState.CommitTrees which also calls TestState.CommitTrees, clearing the cache. + if (!TestState.AccountExists(senderRecipientAndMiner.Sender)) + TestState.CreateAccount(senderRecipientAndMiner.Sender, 100.Ether()); + else + TestState.AddToBalance(senderRecipientAndMiner.Sender, 100.Ether(), SpecProvider.GenesisSpec); + + if (!TestState.AccountExists(senderRecipientAndMiner.Recipient)) + TestState.CreateAccount(senderRecipientAndMiner.Recipient, 100.Ether()); + else + TestState.AddToBalance(senderRecipientAndMiner.Recipient, 100.Ether(), SpecProvider.GenesisSpec); TestState.InsertCode(senderRecipientAndMiner.Recipient, code, SpecProvider.GenesisSpec); - } - GetLogManager().GetClassLogger().Debug("Committing initial state"); - TestState.Commit(SpecProvider.GenesisSpec); - GetLogManager().GetClassLogger().Debug("Committed initial state"); - GetLogManager().GetClassLogger().Debug("Committing initial tree"); - TestState.CommitTree(0); - GetLogManager().GetClassLogger().Debug("Committed initial tree"); - - Transaction transaction = Build.A.Transaction - .WithGasLimit(gasLimit) - .WithGasPrice(1) - .WithValue(value) - .WithBlobVersionedHashes(blobVersionedHashes) - .WithNonce(TestState.GetNonce(senderRecipientAndMiner.Sender)) - .To(senderRecipientAndMiner.Recipient) - .SignedAndResolved(_ethereumEcdsa, senderRecipientAndMiner.SenderKey) - .TestObject; - - Block block = BuildBlock(activation, senderRecipientAndMiner, transaction, blockGasLimit, excessBlobGas); - return (block, transaction); - } + TestState.Commit(SpecProvider.GenesisSpec); - /// - /// deprecated. Please use activation instead of blockNumber. - /// - protected (Block block, Transaction transaction) PrepareTx(long blockNumber, long gasLimit, byte[] code, - byte[] input, UInt256 value, SenderRecipientAndMiner senderRecipientAndMiner = null) - { - return PrepareTx((blockNumber, Timestamp), gasLimit, code, input, value, senderRecipientAndMiner); - } + Transaction transaction = Build.A.Transaction + .WithGasLimit(gasLimit) + .WithGasPrice(1) + .WithNonce(TestState.GetNonce(senderRecipientAndMiner.Sender)) + .WithData(input) + .WithValue(value) + .To(senderRecipientAndMiner.Recipient) + .SignedAndResolved(_ethereumEcdsa, senderRecipientAndMiner.SenderKey) + .TestObject; - protected (Block block, Transaction transaction) PrepareTx(ForkActivation activation, long gasLimit, byte[] code, - byte[] input, UInt256 value, SenderRecipientAndMiner senderRecipientAndMiner = null) - { - senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; + Block block = BuildBlock(blockNumber, senderRecipientAndMiner); + return (block, transaction); + } - // checking if account exists - because creating new accounts overwrites already existing accounts, - // thus overwriting storage roots - essentially clearing the storage slots - // earlier it used to work - because the cache mapping address:storageTree was never cleared on account of - // TestState.CommitTrees() not being called. But now the WorldState.CommitTrees which also calls TestState.CommitTrees, clearing the cache. - if (!TestState.AccountExists(senderRecipientAndMiner.Sender)) + protected (Block block, Transaction transaction) PrepareInitTx(long blockNumber, long gasLimit, byte[] code, + SenderRecipientAndMiner senderRecipientAndMiner = null) + { + senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; TestState.CreateAccount(senderRecipientAndMiner.Sender, 100.Ether()); - else - TestState.AddToBalance(senderRecipientAndMiner.Sender, 100.Ether(), SpecProvider.GenesisSpec); - - if (!TestState.AccountExists(senderRecipientAndMiner.Recipient)) - TestState.CreateAccount(senderRecipientAndMiner.Recipient, 100.Ether()); - else - TestState.AddToBalance(senderRecipientAndMiner.Recipient, 100.Ether(), SpecProvider.GenesisSpec); - TestState.InsertCode(senderRecipientAndMiner.Recipient, code, SpecProvider.GenesisSpec); - - TestState.Commit(SpecProvider.GenesisSpec); - - Transaction transaction = Build.A.Transaction - .WithGasLimit(gasLimit) - .WithGasPrice(1) - .WithNonce(TestState.GetNonce(senderRecipientAndMiner.Sender)) - .WithData(input) - .WithValue(value) - .To(senderRecipientAndMiner.Recipient) - .SignedAndResolved(_ethereumEcdsa, senderRecipientAndMiner.SenderKey) - .TestObject; - - Block block = BuildBlock(activation, senderRecipientAndMiner); - return (block, transaction); - } - - protected (Block block, Transaction transaction) PrepareInitTx(ForkActivation activation, long gasLimit, byte[] code, - SenderRecipientAndMiner senderRecipientAndMiner = null) - { - senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; - TestState.CreateAccount(senderRecipientAndMiner.Sender, 100.Ether()); - TestState.Commit(SpecProvider.GenesisSpec); - - Transaction transaction = Build.A.Transaction - .WithTo(null) - .WithGasLimit(gasLimit) - .WithGasPrice(1) - .WithCode(code) - .SignedAndResolved(_ethereumEcdsa, senderRecipientAndMiner.SenderKey) - .TestObject; - - Block block = BuildBlock(activation, senderRecipientAndMiner); - return (block, transaction); - } + TestState.Commit(SpecProvider.GenesisSpec); + + Transaction transaction = Build.A.Transaction + .WithTo(null) + .WithGasLimit(gasLimit) + .WithGasPrice(1) + .WithCode(code) + .SignedAndResolved(_ethereumEcdsa, senderRecipientAndMiner.SenderKey) + .TestObject; + + Block block = BuildBlock(blockNumber, senderRecipientAndMiner); + return (block, transaction); + } - protected Block BuildBlock(ForkActivation activation, SenderRecipientAndMiner senderRecipientAndMiner) - { - return BuildBlock(activation, senderRecipientAndMiner, null); - } + protected Block BuildBlock(long blockNumber, SenderRecipientAndMiner senderRecipientAndMiner) + { + return BuildBlock(blockNumber, senderRecipientAndMiner, null); + } - protected virtual Block BuildBlock(ForkActivation activation, SenderRecipientAndMiner senderRecipientAndMiner, - Transaction tx, long blockGasLimit = DefaultBlockGasLimit, ulong excessBlobGas = 0) - { - senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; - return Build.A.Block.WithNumber(activation.BlockNumber) - .WithTimestamp(activation.Timestamp ?? 0) - .WithTransactions(tx is null ? Array.Empty() : new[] { tx }) - .WithGasLimit(blockGasLimit) - .WithBeneficiary(senderRecipientAndMiner.Miner) - .WithBlobGasUsed(0) - .WithExcessBlobGas(0) - .WithParentBeaconBlockRoot(TestItem.KeccakG) - .WithExcessBlobGas(excessBlobGas) - .TestObject; - } + protected virtual Block BuildBlock(long blockNumber, SenderRecipientAndMiner senderRecipientAndMiner, + Transaction tx, long blockGasLimit = DefaultBlockGasLimit, + ulong timestamp = 0) + { + senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; + return Build.A.Block.WithNumber(blockNumber) + .WithTransactions(tx is null ? new Transaction[0] : new[] { tx }) + .WithGasLimit(blockGasLimit) + .WithBeneficiary(senderRecipientAndMiner.Miner) + .WithDataGasUsed(0) + .WithExcessDataGas(0) + .WithTimestamp(timestamp) + .TestObject; + } - protected void AssertGas(TestAllTracerWithOutput receipt, long gas) - { - Assert.That(receipt.GasSpent, Is.EqualTo(gas), "gas"); - } + protected void AssertGas(TestAllTracerWithOutput receipt, long gas) + { + Assert.That(receipt.GasSpent, Is.EqualTo(gas), "gas"); + } - protected void AssertStorage(UInt256 address, Address value) - { - Assert.That(TestState.Get(new StorageCell(Recipient, address)).PadLeft(32), Is.EqualTo(value.Bytes.PadLeft(32)), "storage"); - } + protected void AssertStorage(UInt256 address, Address value) + { + Assert.That(TestState.Get(new StorageCell(Recipient, address)).PadLeft(32), Is.EqualTo(value.Bytes.PadLeft(32)), "storage"); + } - protected void AssertStorage(UInt256 address, Keccak value) - { - Assert.That(TestState.Get(new StorageCell(Recipient, address)).PadLeft(32), Is.EqualTo(value.BytesToArray()), "storage"); - } + protected void AssertStorage(UInt256 address, Keccak value) + { + Assert.That(TestState.Get(new StorageCell(Recipient, address)).PadLeft(32), Is.EqualTo(value.BytesToArray()), "storage"); + } - protected void AssertStorage(UInt256 address, ReadOnlySpan value) - { - Assert.That(TestState.Get(new StorageCell(Recipient, address)).PadLeft(32), Is.EqualTo(new ZeroPaddedSpan(value, 32 - value.Length, PadDirection.Left).ToArray()), "storage"); - } + protected void AssertStorage(UInt256 address, ReadOnlySpan value) + { + Assert.That(TestState.Get(new StorageCell(Recipient, address)).PadLeft(32), Is.EqualTo(new ZeroPaddedSpan(value, 32 - value.Length, PadDirection.Left).ToArray()), "storage"); + } - protected void AssertStorage(UInt256 address, BigInteger expectedValue) - { - byte[] actualValue = TestState.Get(new StorageCell(Recipient, address)); - byte[] expected = expectedValue < 0 ? expectedValue.ToBigEndianByteArray(32) : expectedValue.ToBigEndianByteArray(); - Assert.That(actualValue, Is.EqualTo(expected), "storage"); - } + protected void AssertStorage(UInt256 address, BigInteger expectedValue) + { + byte[] actualValue = TestState.Get(new StorageCell(Recipient, address)); + byte[] expected = expectedValue < 0 ? expectedValue.ToBigEndianByteArray(32) : expectedValue.ToBigEndianByteArray(); + Assert.That(actualValue, Is.EqualTo(expected), "storage"); + } - protected void AssertStorage(UInt256 address, UInt256 expectedValue) - { - byte[] bytes = ((BigInteger)expectedValue).ToBigEndianByteArray(); + protected void AssertStorage(UInt256 address, UInt256 expectedValue) + { + byte[] bytes = ((BigInteger)expectedValue).ToBigEndianByteArray(); - byte[] actualValue = TestState.Get(new StorageCell(Recipient, address)); - Assert.That(actualValue, Is.EqualTo(bytes), "storage"); - } + byte[] actualValue = TestState.Get(new StorageCell(Recipient, address)); + Assert.That(actualValue, Is.EqualTo(bytes), "storage"); + } - private static int _callIndex = -1; + private static int _callIndex = -1; - protected void AssertStorage(StorageCell storageCell, UInt256 expectedValue) - { - _callIndex++; - if (!TestState.AccountExists(storageCell.Address)) + protected void AssertStorage(StorageCell storageCell, UInt256 expectedValue) { - Assert.That(new byte[] { 0 }, Is.EqualTo(expectedValue.ToBigEndian().WithoutLeadingZeros().ToArray()), $"storage {storageCell}, call {_callIndex}"); + _callIndex++; + if (!TestState.AccountExists(storageCell.Address)) + { + Assert.That(new byte[] { 0 }, Is.EqualTo(expectedValue.ToBigEndian().WithoutLeadingZeros().ToArray()), $"storage {storageCell}, call {_callIndex}"); + } + else + { + byte[] actualValue = TestState.Get(storageCell); + Assert.That(actualValue, Is.EqualTo(expectedValue.ToBigEndian().WithoutLeadingZeros().ToArray()), $"storage {storageCell}, call {_callIndex}"); + } } - else + + protected void AssertCodeHash(Address address, Keccak codeHash) { - byte[] actualValue = TestState.Get(storageCell); - Assert.That(actualValue, Is.EqualTo(expectedValue.ToBigEndian().WithoutLeadingZeros().ToArray()), $"storage {storageCell}, call {_callIndex}"); + Assert.That(TestState.GetCodeHash(address), Is.EqualTo(codeHash), "code hash"); } } - - protected void AssertCodeHash(Address address, Keccak codeHash) - { - Assert.That(TestState.GetCodeHash(address), Is.EqualTo(codeHash), "code hash"); - } } diff --git a/src/Nethermind/Nethermind.Evm.Test/VmCodeDepositTests.cs b/src/Nethermind/Nethermind.Evm.Test/VmCodeDepositTests.cs index 4554f5a319c..5d3e4e59bc9 100644 --- a/src/Nethermind/Nethermind.Evm.Test/VmCodeDepositTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/VmCodeDepositTests.cs @@ -2,9 +2,11 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Specs; using Nethermind.Core.Test.Builders; +using Nethermind.State; using NUnit.Framework; namespace Nethermind.Evm.Test diff --git a/src/Nethermind/Nethermind.Evm/BlockExecutionContext.cs b/src/Nethermind/Nethermind.Evm/BlockExecutionContext.cs deleted file mode 100644 index 759dc5ee04f..00000000000 --- a/src/Nethermind/Nethermind.Evm/BlockExecutionContext.cs +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using Nethermind.Core; -using Nethermind.Int256; - -namespace Nethermind.Evm; - -public readonly struct BlockExecutionContext -{ - public BlockHeader Header { get; } - public UInt256? BlobBaseFee { get; } - - public BlockExecutionContext(BlockHeader blockHeader) - { - Header = blockHeader; - if (blockHeader?.ExcessBlobGas is not null) - { - if (!BlobGasCalculator.TryCalculateBlobGasPricePerUnit(blockHeader.ExcessBlobGas.Value, out UInt256 blobBaseFeeResult)) - { - throw new OverflowException("Blob gas price calculation led to overflow."); - } - BlobBaseFee = blobBaseFeeResult; - } - } - - public static implicit operator BlockExecutionContext(BlockHeader header) - { - return new BlockExecutionContext(header); - } - -} diff --git a/src/Nethermind/Nethermind.Evm/ByteArrayExtensions.cs b/src/Nethermind/Nethermind.Evm/ByteArrayExtensions.cs index ec6368ac113..3383bba3f6c 100644 --- a/src/Nethermind/Nethermind.Evm/ByteArrayExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/ByteArrayExtensions.cs @@ -2,19 +2,13 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Runtime.CompilerServices; - using Nethermind.Int256; namespace Nethermind.Evm { public static class ByteArrayExtensions { - [MethodImpl(MethodImplOptions.NoInlining)] private static ZeroPaddedSpan SliceWithZeroPadding(this Span span, int startIndex, int length, PadDirection padDirection) - => ((ReadOnlySpan)span).SliceWithZeroPadding(startIndex, length, padDirection); - - private static ZeroPaddedSpan SliceWithZeroPadding(this ReadOnlySpan span, int startIndex, int length, PadDirection padDirection) { if (startIndex >= span.Length) { @@ -34,6 +28,26 @@ private static ZeroPaddedSpan SliceWithZeroPadding(this ReadOnlySpan span, return new ZeroPaddedSpan(span.Slice(startIndex, copiedLength), length - copiedLength, padDirection); } + private static ZeroPaddedMemory MemoryWithZeroPadding(this ReadOnlyMemory memory, int startIndex, int length, PadDirection padDirection) + { + if (startIndex >= memory.Length) + { + return new ZeroPaddedMemory(default, length, padDirection); + } + + if (length == 1) + { + // why do we return zero length here? + // it was passing all the tests like this... + // return bytes.Length == 0 ? new byte[0] : new[] {bytes[startIndex]}; + return memory.Length == 0 ? new ZeroPaddedMemory(default, 0, padDirection) : new ZeroPaddedMemory(memory.Slice(startIndex, 1), 0, padDirection); + // return bytes.Length == 0 ? new ZeroPaddedSpan(default, 1) : new ZeroPaddedSpan(bytes.Slice(startIndex, 1), 0); + } + + int copiedLength = Math.Min(memory.Length - startIndex, length); + return new ZeroPaddedMemory(memory.Slice(startIndex, copiedLength), length - copiedLength, padDirection); + } + public static ZeroPaddedSpan SliceWithZeroPadding(this Span span, scoped in UInt256 startIndex, int length, PadDirection padDirection = PadDirection.Right) { if (startIndex >= span.Length || startIndex > int.MaxValue) @@ -44,17 +58,17 @@ public static ZeroPaddedSpan SliceWithZeroPadding(this Span span, scoped i return SliceWithZeroPadding(span, (int)startIndex, length, padDirection); } - public static ZeroPaddedSpan SliceWithZeroPadding(this ReadOnlyMemory bytes, scoped in UInt256 startIndex, int length, PadDirection padDirection = PadDirection.Right) + public static ZeroPaddedMemory SliceWithZeroPadding(this ReadOnlyMemory bytes, scoped in UInt256 startIndex, int length, PadDirection padDirection = PadDirection.Right) { if (startIndex >= bytes.Length || startIndex > int.MaxValue) { - return new ZeroPaddedSpan(default, length, PadDirection.Right); + return new ZeroPaddedMemory(default, length, PadDirection.Right); } - return SliceWithZeroPadding(bytes.Span, (int)startIndex, length, padDirection); + return MemoryWithZeroPadding(bytes, (int)startIndex, length, padDirection); } - public static ZeroPaddedSpan SliceWithZeroPadding(this byte[] bytes, scoped in UInt256 startIndex, int length, PadDirection padDirection = PadDirection.Right) => + public static ZeroPaddedSpan SliceWithZeroPadding(this byte[] bytes, in UInt256 startIndex, int length, PadDirection padDirection = PadDirection.Right) => bytes.AsSpan().SliceWithZeroPadding(startIndex, length, padDirection); public static ZeroPaddedSpan SliceWithZeroPadding(this byte[] bytes, int startIndex, int length, PadDirection padDirection = PadDirection.Right) => diff --git a/src/Nethermind/Nethermind.Evm/ByteCodeBuilder.cs b/src/Nethermind/Nethermind.Evm/ByteCodeBuilder.cs index b23c7b1122d..835eba41008 100644 --- a/src/Nethermind/Nethermind.Evm/ByteCodeBuilder.cs +++ b/src/Nethermind/Nethermind.Evm/ByteCodeBuilder.cs @@ -295,7 +295,7 @@ public Prepare StoreDataInMemory(int position, string hexString) return StoreDataInMemory(position, Bytes.FromHexString(hexString)); } - public Prepare StoreDataInMemory(int position, byte[] data) + private Prepare StoreDataInMemory(int position, byte[] data) { for (int i = 0; i < data.Length; i += 32) { diff --git a/src/Nethermind/Nethermind.Evm/ByteCodeBuilderExtensions.cs b/src/Nethermind/Nethermind.Evm/ByteCodeBuilderExtensions.cs index 8ceccf331af..e6f314dfcb1 100644 --- a/src/Nethermind/Nethermind.Evm/ByteCodeBuilderExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/ByteCodeBuilderExtensions.cs @@ -210,9 +210,9 @@ public static Prepare BYTE(this Prepare @this, UInt256? pos, byte[] bytes = null => @this.PushSingle(bytes) .PushSingle(pos) .Op(Instruction.BYTE); - public static Prepare KECCAK256(this Prepare @this, UInt256? pos = null, UInt256? len = null) + public static Prepare SHA3(this Prepare @this, UInt256? pos = null, UInt256? len = null) => @this.PushSequence(len, pos) - .Op(Instruction.KECCAK256); + .Op(Instruction.SHA3); public static Prepare SHL(this Prepare @this, UInt256? lhs = null, UInt256? rhs = null) => @this.PushSequence(rhs, lhs) .Op(Instruction.SHL); @@ -254,9 +254,6 @@ public static Prepare REVERT(this Prepare @this, UInt256? pos = null, UInt256? l #endregion #region opcodes_with_3_args - public static Prepare MCOPY(this Prepare @this, UInt256? dst = null, UInt256? src = null, UInt256? len = null) - => @this.PushSequence(len, src, dst) - .Op(Instruction.MCOPY); public static Prepare ADDMOD(this Prepare @this, UInt256? lhs = null, UInt256? rhs = null, UInt256? mod = null) => @this.PushSequence(mod, rhs, lhs) .Op(Instruction.ADDMOD); diff --git a/src/Nethermind/Nethermind.Evm/CodeAnalysis/CodeDataAnalyzer.cs b/src/Nethermind/Nethermind.Evm/CodeAnalysis/CodeDataAnalyzer.cs index a3dd20dcb53..129c04faec5 100644 --- a/src/Nethermind/Nethermind.Evm/CodeAnalysis/CodeDataAnalyzer.cs +++ b/src/Nethermind/Nethermind.Evm/CodeAnalysis/CodeDataAnalyzer.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Threading; namespace Nethermind.Evm.CodeAnalysis { diff --git a/src/Nethermind/Nethermind.Evm/CodeAnalysis/CodeInfo.cs b/src/Nethermind/Nethermind.Evm/CodeAnalysis/CodeInfo.cs index d8cec2c0adb..3be8b18785b 100644 --- a/src/Nethermind/Nethermind.Evm/CodeAnalysis/CodeInfo.cs +++ b/src/Nethermind/Nethermind.Evm/CodeAnalysis/CodeInfo.cs @@ -2,6 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections; +using System.Reflection.PortableExecutable; +using System.Threading; using Nethermind.Evm.Precompiles; namespace Nethermind.Evm.CodeAnalysis diff --git a/src/Nethermind/Nethermind.Evm/CodeAnalysis/JumpdestAnalyzer.cs b/src/Nethermind/Nethermind.Evm/CodeAnalysis/JumpdestAnalyzer.cs index 5753199dd4b..d3757b8f7b9 100644 --- a/src/Nethermind/Nethermind.Evm/CodeAnalysis/JumpdestAnalyzer.cs +++ b/src/Nethermind/Nethermind.Evm/CodeAnalysis/JumpdestAnalyzer.cs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections; +using System.Threading; +using Nethermind.Evm.Precompiles; namespace Nethermind.Evm.CodeAnalysis { diff --git a/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs b/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs index 2a4d9eebef8..346d3743ea7 100644 --- a/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs @@ -1,94 +1,53 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; namespace Nethermind.Evm; -public static class BlobGasCalculator +public static class DataGasCalculator { - public static ulong CalculateBlobGas(int blobCount) => - (ulong)blobCount * Eip4844Constants.BlobGasPerBlob; + public static ulong CalculateDataGas(int blobCount) => + (ulong)blobCount * Eip4844Constants.DataGasPerBlob; - public static ulong CalculateBlobGas(Transaction transaction) => - CalculateBlobGas(transaction.BlobVersionedHashes?.Length ?? 0); + public static ulong CalculateDataGas(Transaction transaction) => + CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0); - public static ulong CalculateBlobGas(Transaction[] transactions) - { - int blobCount = 0; - foreach (Transaction tx in transactions) - { - if (tx.SupportsBlobs) - { - blobCount += tx.BlobVersionedHashes!.Length; - } - } + public static UInt256 CalculateDataGasPrice(BlockHeader header, Transaction transaction) => + CalculateDataGas(transaction) * CalculateDataGasPricePerUnit(header); - return CalculateBlobGas(blobCount); - } + public static UInt256 CalculateDataGasPricePerUnit(BlockHeader header) => + header.ExcessDataGas is null + ? throw new ArgumentException(nameof(BlockHeader.ExcessDataGas)) + : CalculateDataGasPricePerUnit(header.ExcessDataGas.Value); - public static bool TryCalculateBlobGasPrice(BlockHeader header, Transaction transaction, out UInt256 blobGasPrice) + public static UInt256 CalculateDataGasPricePerUnit(ulong excessDataGas) { - if (!TryCalculateBlobGasPricePerUnit(header.ExcessBlobGas.Value, out UInt256 blobGasPricePerUnit)) - { - blobGasPrice = UInt256.MaxValue; - return false; - } - return !UInt256.MultiplyOverflow(CalculateBlobGas(transaction), blobGasPricePerUnit, out blobGasPrice); - } - - public static bool TryCalculateBlobGasPricePerUnit(BlockHeader header, out UInt256 blobGasPricePerUnit) - { - blobGasPricePerUnit = UInt256.MaxValue; - return header.ExcessBlobGas is not null - && TryCalculateBlobGasPricePerUnit(header.ExcessBlobGas.Value, out blobGasPricePerUnit); - } - - public static bool TryCalculateBlobGasPricePerUnit(ulong excessBlobGas, out UInt256 blobGasPricePerUnit) - { - static bool FakeExponentialOverflow(UInt256 factor, UInt256 num, UInt256 denominator, out UInt256 blobGasPricePerUnit) + static UInt256 FakeExponential(UInt256 factor, UInt256 num, UInt256 denominator) { UInt256 output = UInt256.Zero; - if (UInt256.MultiplyOverflow(factor, denominator, out UInt256 numAccum)) - { - blobGasPricePerUnit = UInt256.MaxValue; - return true; - } + UInt256 numAccum = factor * denominator; for (UInt256 i = 1; numAccum > 0; i++) { - if (UInt256.AddOverflow(output, numAccum, out output)) - { - blobGasPricePerUnit = UInt256.MaxValue; - return true; - } - - if (UInt256.MultiplyOverflow(numAccum, num, out UInt256 updatedNumAccum)) - { - blobGasPricePerUnit = UInt256.MaxValue; - return true; - } - - if (UInt256.MultiplyOverflow(i, denominator, out UInt256 multipliedDeniminator)) - { - blobGasPricePerUnit = UInt256.MaxValue; - return true; - } - - numAccum = updatedNumAccum / multipliedDeniminator; + output += numAccum; + numAccum *= num; + numAccum /= i * denominator; } - blobGasPricePerUnit = output / denominator; - return false; + return output / denominator; } - return !FakeExponentialOverflow(Eip4844Constants.MinBlobGasPrice, excessBlobGas, Eip4844Constants.BlobGasUpdateFraction, out blobGasPricePerUnit); + UInt256 scaleDueToParentExcessDataGas = + FakeExponential(Eip4844Constants.MinDataGasPrice, excessDataGas, Eip4844Constants.DataGasUpdateFraction); + return scaleDueToParentExcessDataGas; } - public static ulong? CalculateExcessBlobGas(BlockHeader? parentBlockHeader, IReleaseSpec releaseSpec) + public static ulong? CalculateExcessDataGas(BlockHeader? parentBlockHeader, IReleaseSpec releaseSpec) { if (!releaseSpec.IsEip4844Enabled) { @@ -100,10 +59,19 @@ static bool FakeExponentialOverflow(UInt256 factor, UInt256 num, UInt256 denomin return 0; } - ulong excessBlobGas = parentBlockHeader.ExcessBlobGas ?? 0; - excessBlobGas += parentBlockHeader.BlobGasUsed ?? 0; - return excessBlobGas < Eip4844Constants.TargetBlobGasPerBlock + ulong excessDataGas = parentBlockHeader.ExcessDataGas ?? 0; + excessDataGas += parentBlockHeader.DataGasUsed ?? 0; + return excessDataGas < Eip4844Constants.TargetDataGasPerBlock + ? 0 + : (excessDataGas - Eip4844Constants.TargetDataGasPerBlock); + } + + public static ulong? CalculateExcessDataGas(ulong? parentExcessDataGas, ulong? parentDataGasUsed) + { + ulong excessDataGas = parentExcessDataGas ?? 0; + excessDataGas += parentDataGasUsed ?? 0; + return excessDataGas < Eip4844Constants.TargetDataGasPerBlock ? 0 - : (excessBlobGas - Eip4844Constants.TargetBlobGasPerBlock); + : (excessDataGas - Eip4844Constants.TargetDataGasPerBlock); } } diff --git a/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs b/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs index 56f2ece66c7..29c1043db21 100644 --- a/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs +++ b/src/Nethermind/Nethermind.Evm/EvmPooledMemory.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; @@ -12,323 +13,327 @@ using Nethermind.Core.Extensions; using Nethermind.Int256; -namespace Nethermind.Evm; - -public class EvmPooledMemory : IEvmMemory +namespace Nethermind.Evm { - public const int WordSize = 32; - - private static readonly LargerArrayPool Pool = LargerArrayPool.Shared; - - private int _lastZeroedSize; - - private byte[]? _memory; - public ulong Length { get; private set; } - public ulong Size { get; private set; } - - public void SaveWord(in UInt256 location, Span word) + public class EvmPooledMemory : IEvmMemory { - if (word.Length != WordSize) ThrowArgumentOutOfRangeException(); + public const int WordSize = 32; + private static readonly UInt256 WordSize256 = WordSize; - CheckMemoryAccessViolation(in location, WordSize, out ulong newLength); - UpdateSize(newLength); + private static readonly ArrayPool Pool = LargerArrayPool.Shared; - int offset = (int)location; + private int _lastZeroedSize; - // Direct 256bit register copy rather than invoke Memmove - Unsafe.WriteUnaligned( - ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_memory), offset), - Unsafe.As>(ref MemoryMarshal.GetReference(word)) - ); - } - - public void SaveByte(in UInt256 location, byte value) - { - CheckMemoryAccessViolation(in location, WordSize, out _); - UpdateSize(in location, in UInt256.One); + private byte[]? _memory; + public ulong Length { get; private set; } + public ulong Size { get; private set; } - _memory![(long)location] = value; - } - - public void Save(in UInt256 location, Span value) - { - if (value.Length == 0) + public void SaveWord(in UInt256 location, Span word) { - return; - } + if (word.Length != WordSize) ThrowArgumentOutOfRangeException(); - CheckMemoryAccessViolation(in location, (ulong)value.Length, out ulong newLength); - UpdateSize(newLength); + CheckMemoryAccessViolation(in location, in WordSize256, out ulong newLength); + UpdateSize(newLength); - value.CopyTo(_memory.AsSpan((int)location, value.Length)); - } + int offset = (int)location; - private static void CheckMemoryAccessViolation(in UInt256 location, in UInt256 length, out ulong newLength) - { - if (location.IsLargerThanULong() || length.IsLargerThanULong()) - { - ThrowOutOfGasException(); + // Direct 256bit register copy rather than invoke Memmove + Unsafe.WriteUnaligned( + ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_memory), offset), + Unsafe.As>(ref MemoryMarshal.GetReference(word)) + ); } - CheckMemoryAccessViolation(location.u0, length.u0, out newLength); - } - - private static void CheckMemoryAccessViolation(in UInt256 location, ulong length, out ulong newLength) - { - if (location.IsLargerThanULong()) + public void SaveByte(in UInt256 location, byte value) { - ThrowOutOfGasException(); - } - - CheckMemoryAccessViolation(location.u0, length, out newLength); - } + CheckMemoryAccessViolation(in location, in WordSize256); + UpdateSize(in location, in UInt256.One); - private static void CheckMemoryAccessViolation(ulong location, ulong length, out ulong newLength) - { - ulong totalSize = location + length; - if (totalSize < location || totalSize > long.MaxValue) - { - ThrowOutOfGasException(); + _memory![(long)location] = value; } - newLength = totalSize; - } - - public void Save(in UInt256 location, byte[] value) - { - if (value.Length == 0) + public void Save(in UInt256 location, Span value) { - return; - } + if (value.Length == 0) + { + return; + } - UInt256 length = (UInt256)value.Length; - CheckMemoryAccessViolation(in location, in length, out ulong newLength); - UpdateSize(newLength); + UInt256 length = (UInt256)value.Length; + CheckMemoryAccessViolation(in location, in length, out ulong newLength); + UpdateSize(newLength); - Array.Copy(value, 0, _memory!, (long)location, value.Length); - } + value.CopyTo(_memory.AsSpan((int)location, value.Length)); + } - public void Save(in UInt256 location, in ZeroPaddedSpan value) - { - if (value.Length == 0) + private static void CheckMemoryAccessViolation(in UInt256 location, in UInt256 length) { - return; + UInt256 totalSize = location + length; + if (totalSize < location || totalSize > long.MaxValue) + { + ThrowOutOfGasException(); + } } - UInt256 length = (UInt256)value.Length; - CheckMemoryAccessViolation(in location, in length, out ulong newLength); - UpdateSize(newLength); + private static void CheckMemoryAccessViolation(in UInt256 location, in UInt256 length, out ulong newLength) + { + UInt256 totalSize = location + length; + if (totalSize < location || totalSize > long.MaxValue) + { + ThrowOutOfGasException(); + } - int intLocation = (int)location; - value.Span.CopyTo(_memory.AsSpan(intLocation, value.Span.Length)); - _memory.AsSpan(intLocation + value.Span.Length, value.PaddingLength).Clear(); - } + newLength = (ulong)totalSize; + } - public Span LoadSpan(scoped in UInt256 location) - { - CheckMemoryAccessViolation(in location, WordSize, out ulong newLength); - UpdateSize(newLength); + public void Save(in UInt256 location, byte[] value) + { + if (value.Length == 0) + { + return; + } - return _memory.AsSpan((int)location, WordSize); - } + UInt256 length = (UInt256)value.Length; + CheckMemoryAccessViolation(in location, in length, out ulong newLength); + UpdateSize(newLength); - public Span LoadSpan(scoped in UInt256 location, scoped in UInt256 length) - { - if (length.IsZero) - { - return Array.Empty(); + Array.Copy(value, 0, _memory!, (long)location, value.Length); } - CheckMemoryAccessViolation(in location, in length, out ulong newLength); - UpdateSize(newLength); + public void Save(in UInt256 location, ZeroPaddedSpan value) + { + if (value.Length == 0) + { + return; + } - return _memory.AsSpan((int)location, (int)length); - } + UInt256 length = (UInt256)value.Length; + CheckMemoryAccessViolation(in location, in length, out ulong newLength); + UpdateSize(newLength); - public ReadOnlyMemory Load(in UInt256 location, in UInt256 length) - { - if (length.IsZero) - { - return default; + int intLocation = (int)location; + value.Span.CopyTo(_memory.AsSpan(intLocation, value.Span.Length)); + _memory.AsSpan(intLocation + value.Span.Length, value.PaddingLength).Clear(); } - if (location > int.MaxValue) + public void Save(in UInt256 location, ZeroPaddedMemory value) { - return new byte[(long)length]; - } - - UpdateSize(in location, in length); + if (value.Length == 0) + { + return; + } - return _memory.AsMemory((int)location, (int)length); - } + UInt256 length = (UInt256)value.Length; + CheckMemoryAccessViolation(in location, in length, out ulong newLength); + UpdateSize(newLength); - public ReadOnlyMemory Inspect(in UInt256 location, in UInt256 length) - { - if (length.IsZero) - { - return default; + int intLocation = (int)location; + value.Memory.CopyTo(_memory.AsMemory().Slice(intLocation, value.Memory.Length)); + _memory.AsSpan(intLocation + value.Memory.Length, value.PaddingLength).Clear(); } - if (location > int.MaxValue) + public Span LoadSpan(scoped in UInt256 location) { - return new byte[(long)length]; + CheckMemoryAccessViolation(in location, in WordSize256, out ulong newLength); + UpdateSize(newLength); + + return _memory.AsSpan((int)location, WordSize); } - if (_memory is null || location + length > _memory.Length) + public Span LoadSpan(in UInt256 location, in UInt256 length) { - return default; - } + if (length.IsZero) + { + return Array.Empty(); + } - return _memory.AsMemory((int)location, (int)length); - } + CheckMemoryAccessViolation(in location, in length, out ulong newLength); + UpdateSize(newLength); - public long CalculateMemoryCost(in UInt256 location, in UInt256 length) - { - if (length.IsZero) - { - return 0L; + return _memory.AsSpan((int)location, (int)length); } - CheckMemoryAccessViolation(in location, in length, out ulong newSize); - - if (newSize > Size) + public ReadOnlyMemory Load(in UInt256 location, in UInt256 length) { - long newActiveWords = Div32Ceiling(newSize); - long activeWords = Div32Ceiling(Size); - - // TODO: guess it would be well within ranges but this needs to be checked and comment need to be added with calculations - ulong cost = (ulong) - ((newActiveWords - activeWords) * GasCostOf.Memory + - ((newActiveWords * newActiveWords) >> 9) - - ((activeWords * activeWords) >> 9)); + if (length.IsZero) + { + return default; + } - if (cost > long.MaxValue) + if (location > int.MaxValue) { - return long.MaxValue; + return new byte[(long)length]; } - UpdateSize(newSize, rentIfNeeded: false); + UpdateSize(in location, in length); - return (long)cost; + return _memory.AsMemory((int)location, (int)length); } - return 0L; - } - - public IEnumerable GetTrace() - { - int traceLocation = 0; - - while ((ulong)traceLocation < Size) + public ReadOnlyMemory Inspect(in UInt256 location, in UInt256 length) { - int sizeAvailable = Math.Min(WordSize, (_memory?.Length ?? 0) - traceLocation); - if (sizeAvailable > 0) + if (length.IsZero) { - Span bytes = _memory.AsSpan(traceLocation, sizeAvailable); + return default; + } - yield return bytes.ToHexString(); + if (location > int.MaxValue) + { + return new byte[(long)length]; } - else // Memory might not be initialized + + if (_memory is null || location + length > _memory.Length) { - yield return Bytes.Zero32.ToHexString(); + return default; } - traceLocation += WordSize; + return _memory.AsMemory((int)location, (int)length); } - } - public void Dispose() - { - if (_memory is not null) + public long CalculateMemoryCost(in UInt256 location, in UInt256 length) { - Pool.Return(_memory); - _memory = null; - } - } + if (length.IsZero) + { + return 0L; + } - public static long Div32Ceiling(in UInt256 length) - { - if (length.IsLargerThanULong()) - { - ThrowOutOfGasException(); + CheckMemoryAccessViolation(in location, in length); + UInt256 newSize = location + length; + + if (newSize > Size) + { + long newActiveWords = Div32Ceiling(newSize); + long activeWords = Div32Ceiling(Size); + + // TODO: guess it would be well within ranges but this needs to be checked and comment need to be added with calculations + ulong cost = (ulong) + ((newActiveWords - activeWords) * GasCostOf.Memory + + ((newActiveWords * newActiveWords) >> 9) - + ((activeWords * activeWords) >> 9)); + + if (cost > long.MaxValue) + { + return long.MaxValue; + } + + UpdateSize(in newSize, in UInt256.Zero, false); + + return (long)cost; + } + + return 0L; } - ulong result = length.u0; - ulong rem = result & 31; - result >>= 5; - if (rem > 0) + public List GetTrace() { - result++; + int traceLocation = 0; + List memoryTrace = new(); + + while ((ulong)traceLocation < Size) + { + int sizeAvailable = Math.Min(WordSize, (_memory?.Length ?? 0) - traceLocation); + if (sizeAvailable > 0) + { + Span bytes = _memory.AsSpan(traceLocation, sizeAvailable); + memoryTrace.Add(bytes.ToHexString()); + } + else // Memory might not be initialized + { + memoryTrace.Add(Bytes.Zero32.ToHexString()); + } + + traceLocation += WordSize; + } + + return memoryTrace; } - if (result > int.MaxValue) + public void Dispose() { - ThrowOutOfGasException(); + if (_memory is not null) + { + Pool.Return(_memory); + } } - return (long)result; - } + private static UInt256 MaxInt32 = (UInt256)int.MaxValue; - private void UpdateSize(in UInt256 location, in UInt256 length, bool rentIfNeeded = true) - { - UpdateSize((ulong)(location + length), rentIfNeeded); - } + public static long Div32Ceiling(in UInt256 length) + { + UInt256 rem = length & 31; + UInt256 result = length >> 5; + if (!rem.IsZero) + { + result += UInt256.One; + } - private void UpdateSize(ulong length, bool rentIfNeeded = true) - { - Length = length; + if (result > MaxInt32) + { + ThrowOutOfGasException(); + } + + return (long)result; + } - if (Length > Size) + private void UpdateSize(in UInt256 location, in UInt256 length, bool rentIfNeeded = true) { - ulong remainder = Length % WordSize; - Size = remainder != 0 ? Length + WordSize - remainder : Length; + UpdateSize((ulong)(location + length), rentIfNeeded); } - if (rentIfNeeded) + private void UpdateSize(ulong length, bool rentIfNeeded = true) { - if (_memory is null) - { - _memory = Pool.Rent((int)Size); - Array.Clear(_memory, 0, (int)Size); - } - else if (Size > (ulong)_memory.LongLength) + Length = length; + if (Length > Size) { - byte[] beforeResize = _memory; - _memory = Pool.Rent((int)Size); - Array.Copy(beforeResize, 0, _memory, 0, _lastZeroedSize); - Array.Clear(_memory, _lastZeroedSize, (int)Size - _lastZeroedSize); - Pool.Return(beforeResize); + ulong remainder = Length % WordSize; + if (remainder != 0) + { + Size = Length + WordSize - remainder; + } + else + { + Size = Length; + } } - else if (Size > (ulong)_lastZeroedSize) + + if (rentIfNeeded) { - Array.Clear(_memory, _lastZeroedSize, (int)Size - _lastZeroedSize); + if (_memory is null) + { + _memory = Pool.Rent((int)Size); + Array.Clear(_memory, 0, (int)Size); + } + else if (Size > (ulong)_memory.LongLength) + { + byte[] beforeResize = _memory; + _memory = Pool.Rent((int)Size); + Array.Copy(beforeResize, 0, _memory, 0, _lastZeroedSize); + Array.Clear(_memory, _lastZeroedSize, (int)Size - _lastZeroedSize); + Pool.Return(beforeResize); + } + else if (Size > (ulong)_lastZeroedSize) + { + Array.Clear(_memory, _lastZeroedSize, (int)Size - _lastZeroedSize); + } + + _lastZeroedSize = (int)Size; } - - _lastZeroedSize = (int)Size; } - } - [DoesNotReturn] - [StackTraceHidden] - private static void ThrowArgumentOutOfRangeException() - { - Metrics.EvmExceptions++; - throw new ArgumentOutOfRangeException("Word size must be 32 bytes"); - } - - [DoesNotReturn] - [StackTraceHidden] - private static void ThrowOutOfGasException() - { - Metrics.EvmExceptions++; - throw new OutOfGasException(); - } -} + [DoesNotReturn] + [StackTraceHidden] + private static void ThrowArgumentOutOfRangeException() + { + Metrics.EvmExceptions++; + throw new ArgumentOutOfRangeException("Word size must be 32 bytes"); + } -internal static class UInt256Extensions -{ - public static bool IsLargerThanULong(in this UInt256 value) - { - return (value.u1 | value.u2 | value.u3) != 0; + [DoesNotReturn] + [StackTraceHidden] + private static void ThrowOutOfGasException() + { + Metrics.EvmExceptions++; + throw new OutOfGasException(); + } } } diff --git a/src/Nethermind/Nethermind.Evm/EvmStack.cs b/src/Nethermind/Nethermind.Evm/EvmStack.cs index 45f59874b5c..99a94369de5 100644 --- a/src/Nethermind/Nethermind.Evm/EvmStack.cs +++ b/src/Nethermind/Nethermind.Evm/EvmStack.cs @@ -13,175 +13,179 @@ using System.Diagnostics.CodeAnalysis; using System.Runtime.Intrinsics; using System.Diagnostics; -using System.Runtime.Intrinsics.X86; -namespace Nethermind.Evm; - -using static Nethermind.Evm.VirtualMachine; - -using Word = Vector256; - -public ref struct EvmStack - where TTracing : struct, IIsTracing +namespace Nethermind.Evm { - public const int RegisterLength = 1; - public const int MaxStackSize = 1025; - public const int ReturnStackSize = 1023; - public const int WordSize = 32; - public const int AddressSize = 20; + using Word = System.Runtime.Intrinsics.Vector256; - public EvmStack(scoped in Span bytes, scoped in int head, ITxTracer txTracer) + public ref struct EvmStack { - _bytes = bytes; - Head = head; - _tracer = txTracer; - } + public const int RegisterLength = 1; + public const int MaxStackSize = 1025; + public const int ReturnStackSize = 1023; - public int Head; + public EvmStack(scoped in Span bytes, scoped in int head, ITxTracer txTracer) + { + _bytes = bytes; + Head = head; + _tracer = txTracer; + Register = _bytes.Slice(MaxStackSize * 32, 32); + Register.Clear(); + } - private Span _bytes; + public int Head; - private ITxTracer _tracer; + public Span Register; - public void PushBytes(scoped in Span value) - { - if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(value); + private Span _bytes; - if (value.Length != WordSize) - { - ClearWordAtHead(); - value.CopyTo(_bytes.Slice(Head * WordSize + WordSize - value.Length, value.Length)); - } - else - { - Unsafe.WriteUnaligned(ref Unsafe.Add(ref MemoryMarshal.GetReference(_bytes), Head * WordSize), Unsafe.As(ref MemoryMarshal.GetReference(value))); - } + private ITxTracer _tracer; - if (++Head >= MaxStackSize) + public void PushBytes(scoped in Span value) { - EvmStack.ThrowEvmStackOverflowException(); - } - } + if (_tracer.IsTracingInstructions) _tracer.ReportStackPush(value); - public void PushBytes(scoped in ZeroPaddedSpan value) - { - if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(value); + Span word = _bytes.Slice(Head * 32, 32); + if (value.Length != 32) + { + word.Clear(); + value.CopyTo(word.Slice(32 - value.Length, value.Length)); + } + else + { + value.CopyTo(word); + } - ReadOnlySpan valueSpan = value.Span; - if (valueSpan.Length != WordSize) - { - ClearWordAtHead(); - Span stack = _bytes.Slice(Head * WordSize, valueSpan.Length); - valueSpan.CopyTo(stack); - } - else - { - Unsafe.WriteUnaligned(ref Unsafe.Add(ref MemoryMarshal.GetReference(_bytes), Head * WordSize), Unsafe.As(ref MemoryMarshal.GetReference(valueSpan))); + if (++Head >= MaxStackSize) + { + Metrics.EvmExceptions++; + ThrowEvmStackOverflowException(); + } } - if (++Head >= MaxStackSize) + public void PushBytes(scoped in ZeroPaddedSpan value) { - EvmStack.ThrowEvmStackOverflowException(); - } - } + if (_tracer.IsTracingInstructions) _tracer.ReportStackPush(value); - public ref byte PushBytesRef() - { - ref byte bytes = ref _bytes[Head * WordSize]; + Span word = _bytes.Slice(Head * 32, 32); + if (value.Span.Length != 32) + { + word.Clear(); + value.Span.CopyTo(word[..value.Span.Length]); + } + else + { + value.Span.CopyTo(word); + } - if (++Head >= MaxStackSize) - { - EvmStack.ThrowEvmStackOverflowException(); + if (++Head >= MaxStackSize) + { + Metrics.EvmExceptions++; + ThrowEvmStackOverflowException(); + } } - return ref bytes; - } + public void PushBytes(scoped in ZeroPaddedMemory value) + { + if (_tracer.IsTracingInstructions) _tracer.ReportStackPush(value); - public void PushByte(byte value) - { - if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(value); + Span word = _bytes.Slice(Head * 32, 32); + if (value.Memory.Length != 32) + { + word.Clear(); + value.Memory.Span.CopyTo(word[..value.Memory.Length]); + } + else + { + value.Memory.Span.CopyTo(word); + } - ClearWordAtHead(); - _bytes[Head * WordSize + WordSize - sizeof(byte)] = value; + if (++Head >= MaxStackSize) + { + Metrics.EvmExceptions++; + ThrowEvmStackOverflowException(); + } + } - if (++Head >= MaxStackSize) + public void PushByte(byte value) { - EvmStack.ThrowEvmStackOverflowException(); - } - } + if (_tracer.IsTracingInstructions) _tracer.ReportStackPush(value); - private static ReadOnlySpan OneStackItem() => new byte[] { 1 }; + Span word = _bytes.Slice(Head * 32, 32); + word.Clear(); + word[31] = value; - public void PushOne() - { - if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(OneStackItem()); + if (++Head >= MaxStackSize) + { + Metrics.EvmExceptions++; + ThrowEvmStackOverflowException(); + } + } - ClearWordAtHead(); - _bytes[Head * WordSize + WordSize - sizeof(byte)] = 1; + private static readonly byte[] OneStackItem = { 1 }; - if (++Head >= MaxStackSize) + public void PushOne() { - EvmStack.ThrowEvmStackOverflowException(); - } - } + if (_tracer.IsTracingInstructions) _tracer.ReportStackPush(OneStackItem); - private static ReadOnlySpan ZeroStackItem() => new byte[] { 0 }; + int start = Head * 32; + Span word = _bytes.Slice(start, 32); + word.Clear(); + word[31] = 1; - public void PushZero() - { - if (typeof(TTracing) == typeof(IsTracing)) - { - _tracer.ReportStackPush(ZeroStackItem()); + if (++Head >= MaxStackSize) + { + Metrics.EvmExceptions++; + ThrowEvmStackOverflowException(); + } } - ClearWordAtHead(); + private static readonly byte[] ZeroStackItem = { 0 }; - if (++Head >= MaxStackSize) + public void PushZero() { - EvmStack.ThrowEvmStackOverflowException(); - } - } - - public void PushUInt32(in int value) - { - ClearWordAtHead(); + if (_tracer.IsTracingInstructions) + { + _tracer.ReportStackPush(ZeroStackItem); + } - Span intPlace = _bytes.Slice(Head * WordSize + WordSize - sizeof(uint), sizeof(uint)); - BinaryPrimitives.WriteInt32BigEndian(intPlace, value); + _bytes.Slice(Head * 32, 32).Clear(); - if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(intPlace); + if (++Head >= MaxStackSize) + { + Metrics.EvmExceptions++; + ThrowEvmStackOverflowException(); + } + } - if (++Head >= MaxStackSize) + public void PushUInt32(in int value) { - EvmStack.ThrowEvmStackOverflowException(); - } - } + Span word = _bytes.Slice(Head * 32, 28); + word.Clear(); - /// - /// Pushes an Uint256 written in big endian. - /// - /// - /// This method is a counterpart to and uses the same, raw data approach to write data back. - /// - public void PushUInt256(in UInt256 value) - { - Span word = _bytes.Slice(Head * WordSize, WordSize); - ref byte bytes = ref MemoryMarshal.GetReference(word); + Span intPlace = _bytes.Slice(Head * 32 + 28, 4); + BinaryPrimitives.WriteInt32BigEndian(intPlace, value); - if (Avx2.IsSupported) - { - Vector256 permute = Unsafe.As>(ref Unsafe.AsRef(value)); - Vector256 convert = Avx2.Permute4x64(permute, 0b_01_00_11_10); - Word shuffle = Vector256.Create( - (byte) - 31, 30, 29, 28, 27, 26, 25, 24, - 23, 22, 21, 20, 19, 18, 17, 16, - 15, 14, 13, 12, 11, 10, 9, 8, - 7, 6, 5, 4, 3, 2, 1, 0); - Unsafe.WriteUnaligned(ref bytes, Avx2.Shuffle(Unsafe.As, Word>(ref convert), shuffle)); + if (_tracer.IsTracingInstructions) _tracer.ReportStackPush(word); + + if (++Head >= MaxStackSize) + { + Metrics.EvmExceptions++; + ThrowEvmStackOverflowException(); + } } - else + + /// + /// Pushes an Uint256 written in big endian. + /// + /// + /// This method is a counterpart to and uses the same, raw data approach to write data back. + /// + public void PushUInt256(in UInt256 value) { + Span word = _bytes.Slice(Head * 32, 32); + ref byte bytes = ref word[0]; + ulong u3, u2, u1, u0; if (BitConverter.IsLittleEndian) { @@ -199,64 +203,50 @@ public void PushUInt256(in UInt256 value) } Unsafe.WriteUnaligned(ref bytes, Vector256.Create(u3, u2, u1, u0)); - } - if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(word); + if (_tracer.IsTracingInstructions) _tracer.ReportStackPush(word); - if (++Head >= MaxStackSize) - { - EvmStack.ThrowEvmStackOverflowException(); + if (++Head >= MaxStackSize) + { + Metrics.EvmExceptions++; + ThrowEvmStackOverflowException(); + } } - } - - public void PushSignedInt256(in Int256.Int256 value) - { - // tail call into UInt256 - PushUInt256(Unsafe.As(ref Unsafe.AsRef(in value))); - } - public void PopLimbo() - { - if (Head-- == 0) + public void PushSignedInt256(in Int256.Int256 value) { - EvmStack.ThrowEvmStackUnderflowException(); + // tail call into UInt256 + PushUInt256(Unsafe.As(ref Unsafe.AsRef(in value))); } - } - public void PopSignedInt256(out Int256.Int256 result) - { - // tail call into UInt256 - Unsafe.SkipInit(out result); - PopUInt256(out Unsafe.As(ref result)); - } - - /// - /// Pops an Uint256 written in big endian. - /// - /// - /// This method does its own calculations to create the . It knows that 32 bytes were popped with . It doesn't have to check the size of span or slice it. - /// All it does is and then reverse endianness if needed. Then it creates . - /// - /// The returned value. - public void PopUInt256(out UInt256 result) - { - ref byte bytes = ref PopBytesByRef(); + public void PopLimbo() + { + if (Head-- == 0) + { + Metrics.EvmExceptions++; + ThrowEvmStackUnderflowException(); + } + } - if (Avx2.IsSupported) + public void PopSignedInt256(out Int256.Int256 result) { - Word data = Unsafe.ReadUnaligned(ref bytes); - Word shuffle = Vector256.Create( - (byte) - 31, 30, 29, 28, 27, 26, 25, 24, - 23, 22, 21, 20, 19, 18, 17, 16, - 15, 14, 13, 12, 11, 10, 9, 8, - 7, 6, 5, 4, 3, 2, 1, 0); - Word convert = Avx2.Shuffle(data, shuffle); - Vector256 permute = Avx2.Permute4x64(Unsafe.As>(ref convert), 0b_01_00_11_10); - result = Unsafe.As, UInt256>(ref permute); + // tail call into UInt256 + Unsafe.SkipInit(out result); + PopUInt256(out Unsafe.As(ref result)); } - else + + /// + /// Pops an Uint256 written in big endian. + /// + /// + /// This method does its own calculations to create the . It knows that 32 bytes were popped with . It doesn't have to check the size of span or slice it. + /// All it does is and then reverse endianness if needed. Then it creates . + /// + /// The returned value. + public void PopUInt256(out UInt256 result) { + ref byte bytes = ref PopBytesByRef(); + ulong u3, u2, u1, u0; if (BitConverter.IsLittleEndian) { @@ -276,186 +266,164 @@ public void PopUInt256(out UInt256 result) result = new UInt256(u0, u1, u2, u3); } - } - public bool PeekUInt256IsZero() - { - int head = Head; - if (head-- == 0) + public bool PeekUInt256IsZero() { - return false; - } + int head = Head - 1; + if (head <= 0) + { + return false; + } - ref byte bytes = ref _bytes[head * WordSize]; - return Unsafe.ReadUnaligned(ref bytes).IsZero; - } + ref byte bytes = ref _bytes[head * 32]; + return Unsafe.ReadUnaligned(ref bytes).IsZero; + } - public readonly Span PeekWord256() - { - int head = Head; - if (head-- == 0) + public Address PopAddress() { - EvmStack.ThrowEvmStackUnderflowException(); - } + if (Head-- == 0) + { + Metrics.EvmExceptions++; + ThrowEvmStackUnderflowException(); + } - return _bytes.Slice(head * WordSize, WordSize); - } + return new Address(_bytes.Slice(Head * 32 + 12, 20).ToArray()); + } - public Address PopAddress() - { - if (Head-- == 0) + private ref byte PopBytesByRef() { - EvmStack.ThrowEvmStackUnderflowException(); - } + if (Head-- == 0) + { + Metrics.EvmExceptions++; + ThrowEvmStackUnderflowException(); + } - return new Address(_bytes.Slice(Head * WordSize + WordSize - AddressSize, AddressSize).ToArray()); - } + return ref _bytes[Head * 32]; + } - public ref byte PopBytesByRef() - { - if (Head-- == 0) + public Span PopWord256() { - EvmStack.ThrowEvmStackUnderflowException(); - } + if (Head-- == 0) + { + Metrics.EvmExceptions++; + ThrowEvmStackUnderflowException(); + } - return ref _bytes[Head * WordSize]; - } + return _bytes.Slice(Head * 32, 32); + } - public Span PopWord256() - { - if (Head-- == 0) + public byte PopByte() { - EvmStack.ThrowEvmStackUnderflowException(); - } + if (Head-- == 0) + { + Metrics.EvmExceptions++; + ThrowEvmStackUnderflowException(); + } - return _bytes.Slice(Head * WordSize, WordSize); - } + return _bytes[Head * 32 + 31]; + } - public byte PopByte() - { - if (Head-- == 0) + public void PushLeftPaddedBytes(Span value, int paddingLength) { - EvmStack.ThrowEvmStackUnderflowException(); - } + if (_tracer.IsTracingInstructions) _tracer.ReportStackPush(value); - return _bytes[Head * WordSize + WordSize - sizeof(byte)]; - } + if (value.Length != 32) + { + _bytes.Slice(Head * 32, 32).Clear(); + } - public void PushLeftPaddedBytes(Span value, int paddingLength) - { - if (typeof(TTracing) == typeof(IsTracing)) _tracer.ReportStackPush(value); + value.CopyTo(_bytes.Slice(Head * 32 + 32 - paddingLength, value.Length)); - if (value.Length != WordSize) - { - ClearWordAtHead(); - value.CopyTo(_bytes.Slice(Head * WordSize + WordSize - paddingLength, value.Length)); - } - else - { - Unsafe.WriteUnaligned(ref Unsafe.Add(ref MemoryMarshal.GetReference(_bytes), Head * WordSize), Unsafe.As(ref MemoryMarshal.GetReference(value))); + if (++Head >= MaxStackSize) + { + Metrics.EvmExceptions++; + ThrowEvmStackOverflowException(); + } } - if (++Head >= MaxStackSize) + public void Dup(in int depth) { - EvmStack.ThrowEvmStackOverflowException(); - } - } + EnsureDepth(depth); - public void Dup(in int depth) - { - EnsureDepth(depth); + ref byte bytes = ref MemoryMarshal.GetReference(_bytes); - ref byte bytes = ref MemoryMarshal.GetReference(_bytes); + ref byte from = ref Unsafe.Add(ref bytes, (Head - depth) * 32); + ref byte to = ref Unsafe.Add(ref bytes, Head * 32); - ref byte from = ref Unsafe.Add(ref bytes, (Head - depth) * WordSize); - ref byte to = ref Unsafe.Add(ref bytes, Head * WordSize); + Unsafe.WriteUnaligned(ref to, Unsafe.ReadUnaligned(ref from)); - Unsafe.WriteUnaligned(ref to, Unsafe.ReadUnaligned(ref from)); + if (_tracer.IsTracingInstructions) + { + Trace(depth); + } - if (typeof(TTracing) == typeof(IsTracing)) - { - Trace(depth); + if (++Head >= MaxStackSize) + { + Metrics.EvmExceptions++; + ThrowEvmStackOverflowException(); + } } - if (++Head >= MaxStackSize) + public void EnsureDepth(int depth) { - EvmStack.ThrowEvmStackOverflowException(); + if (Head < depth) + { + Metrics.EvmExceptions++; + ThrowEvmStackUnderflowException(); + } } - } - public readonly void EnsureDepth(int depth) - { - if (Head < depth) + public void Swap(int depth) { - EvmStack.ThrowEvmStackUnderflowException(); - } - } + EnsureDepth(depth); - public readonly void Swap(int depth) - { - EnsureDepth(depth); + ref byte bytes = ref MemoryMarshal.GetReference(_bytes); - ref byte bytes = ref MemoryMarshal.GetReference(_bytes); + ref byte bottom = ref Unsafe.Add(ref bytes, (Head - depth) * 32); + ref byte top = ref Unsafe.Add(ref bytes, (Head - 1) * 32); - ref byte bottom = ref Unsafe.Add(ref bytes, (Head - depth) * WordSize); - ref byte top = ref Unsafe.Add(ref bytes, (Head - 1) * WordSize); + Word buffer = Unsafe.ReadUnaligned(ref bottom); + Unsafe.WriteUnaligned(ref bottom, Unsafe.ReadUnaligned(ref top)); + Unsafe.WriteUnaligned(ref top, buffer); - Word buffer = Unsafe.ReadUnaligned(ref bottom); - Unsafe.WriteUnaligned(ref bottom, Unsafe.ReadUnaligned(ref top)); - Unsafe.WriteUnaligned(ref top, buffer); + if (_tracer.IsTracingInstructions) + { + Trace(depth); + } + } - if (typeof(TTracing) == typeof(IsTracing)) + private readonly void Trace(int depth) { - Trace(depth); + for (int i = depth; i > 0; i--) + { + _tracer.ReportStackPush(_bytes.Slice(Head * 32 - i * 32, 32)); + } } - } - private readonly void Trace(int depth) - { - for (int i = depth; i > 0; i--) + public List GetStackTrace() { - _tracer.ReportStackPush(_bytes.Slice(Head * WordSize - i * WordSize, WordSize)); + List stackTrace = new(); + for (int i = 0; i < Head; i++) + { + Span stackItem = _bytes.Slice(i * 32, 32); + stackTrace.Add(stackItem.ToArray().ToHexString()); + } + + return stackTrace; } - } - public readonly List GetStackTrace() - { - List stackTrace = new(); - for (int i = 0; i < Head; i++) + [StackTraceHidden] + [DoesNotReturn] + private static void ThrowEvmStackUnderflowException() { - Span stackItem = _bytes.Slice(i * WordSize, WordSize); - stackTrace.Add(stackItem.ToArray().ToHexString(true, true)); + throw new EvmStackUnderflowException(); } - return stackTrace; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private readonly void ClearWordAtHead() - { - Unsafe.WriteUnaligned(ref Unsafe.Add(ref MemoryMarshal.GetReference(_bytes), Head * WordSize), Word.Zero); - } -} - -public static class EvmStack -{ - public const int RegisterLength = 1; - public const int MaxStackSize = 1025; - public const int ReturnStackSize = 1023; - - [StackTraceHidden] - [DoesNotReturn] - internal static void ThrowEvmStackUnderflowException() - { - Metrics.EvmExceptions++; - throw new EvmStackUnderflowException(); - } - - [StackTraceHidden] - [DoesNotReturn] - internal static void ThrowEvmStackOverflowException() - { - Metrics.EvmExceptions++; - throw new EvmStackOverflowException(); + [StackTraceHidden] + [DoesNotReturn] + internal static void ThrowEvmStackOverflowException() + { + throw new EvmStackOverflowException(); + } } } diff --git a/src/Nethermind/Nethermind.Evm/EvmState.cs b/src/Nethermind/Nethermind.Evm/EvmState.cs index 23604d3e79f..fd00178f4e8 100644 --- a/src/Nethermind/Nethermind.Evm/EvmState.cs +++ b/src/Nethermind/Nethermind.Evm/EvmState.cs @@ -38,7 +38,7 @@ public StackPool(int maxCallStackDepth = VirtualMachine.MaxCallDepth * 2) /// /// The word 'return' acts here once as a verb 'to return stack to the pool' and once as a part of the - /// compound noun 'return stack' which is a stack of subroutine return values. + /// compound noun 'return stack' which is a stack of subroutine return values. /// /// /// @@ -104,15 +104,12 @@ private int[] RentReturnStack() // As we can add here from VM, we need it as ICollection public ICollection
DestroyList => _destroyList; // As we can add here from VM, we need it as ICollection - public ICollection
CreateList => _createList; - // As we can add here from VM, we need it as ICollection public ICollection Logs => _logs; private readonly JournalSet
_accessedAddresses; private readonly JournalSet _accessedStorageCells; private readonly JournalCollection _logs; private readonly JournalSet
_destroyList; - private readonly HashSet
_createList; private readonly int _accessedAddressesSnapshot; private readonly int _accessedStorageKeysSnapshot; private readonly int _destroyListSnapshot; @@ -181,7 +178,6 @@ internal EvmState( _accessedAddresses = stateForAccessLists._accessedAddresses; _accessedStorageCells = stateForAccessLists._accessedStorageCells; _destroyList = stateForAccessLists._destroyList; - _createList = stateForAccessLists._createList; _logs = stateForAccessLists._logs; } else @@ -190,13 +186,8 @@ internal EvmState( _accessedAddresses = new JournalSet
(); _accessedStorageCells = new JournalSet(); _destroyList = new JournalSet
(); - _createList = new HashSet
(); _logs = new JournalCollection(); } - if (executionType.IsAnyCreate()) - { - _createList.Add(env.ExecutingAccount); - } _accessedAddressesSnapshot = _accessedAddresses.TakeSnapshot(); _accessedStorageKeysSnapshot = _accessedStorageCells.TakeSnapshot(); @@ -269,13 +260,13 @@ public void InitStacks() public bool IsCold(Address? address) => !_accessedAddresses.Contains(address); - public bool IsCold(in StorageCell storageCell) => !_accessedStorageCells.Contains(storageCell); + public bool IsCold(StorageCell storageCell) => !_accessedStorageCells.Contains(storageCell); public void WarmUp(AccessList? accessList) { if (accessList is not null) { - foreach ((Address address, AccessList.StorageKeysEnumerable storages) in accessList) + foreach ((Address address, IReadOnlySet storages) in accessList.Data) { WarmUp(address); foreach (UInt256 storage in storages) @@ -288,7 +279,7 @@ public void WarmUp(AccessList? accessList) public void WarmUp(Address address) => _accessedAddresses.Add(address); - public void WarmUp(in StorageCell storageCell) => _accessedStorageCells.Add(storageCell); + public void WarmUp(StorageCell storageCell) => _accessedStorageCells.Add(storageCell); public void CommitToParent(EvmState parentState) { diff --git a/src/Nethermind/Nethermind.Evm/GasCostOf.cs b/src/Nethermind/Nethermind.Evm/GasCostOf.cs index 68dc8cae654..5e8b2291dc1 100644 --- a/src/Nethermind/Nethermind.Evm/GasCostOf.cs +++ b/src/Nethermind/Nethermind.Evm/GasCostOf.cs @@ -54,7 +54,6 @@ public static class GasCostOf public const long InitCodeWord = 2; //eip-3860 gas per word cost for init code size public const long ColdSLoad = 2100; // eip-2929 - public const long ColdAccountAccess = 2600; // eip-2929 public const long WarmStateRead = 100; // eip-2929 diff --git a/src/Nethermind/Nethermind.Evm/IEvmMemory.cs b/src/Nethermind/Nethermind.Evm/IEvmMemory.cs index 15d7053bbed..12e0c0f9030 100644 --- a/src/Nethermind/Nethermind.Evm/IEvmMemory.cs +++ b/src/Nethermind/Nethermind.Evm/IEvmMemory.cs @@ -5,18 +5,105 @@ using System.Collections.Generic; using Nethermind.Int256; -namespace Nethermind.Evm; - -public interface IEvmMemory : IDisposable +namespace Nethermind.Evm { - ulong Size { get; } - void SaveWord(in UInt256 location, Span word); - void SaveByte(in UInt256 location, byte value); - void Save(in UInt256 location, Span value); - void Save(in UInt256 location, byte[] value); - Span LoadSpan(in UInt256 location); - Span LoadSpan(in UInt256 location, in UInt256 length); - ReadOnlyMemory Load(in UInt256 location, in UInt256 length); - long CalculateMemoryCost(in UInt256 location, in UInt256 length); - IEnumerable GetTrace(); + public interface IEvmMemory : IDisposable + { + ulong Size { get; } + void SaveWord(in UInt256 location, Span word); + void SaveByte(in UInt256 location, byte value); + void Save(in UInt256 location, Span value); + void Save(in UInt256 location, byte[] value); + Span LoadSpan(in UInt256 location); + Span LoadSpan(in UInt256 location, in UInt256 length); + ReadOnlyMemory Load(in UInt256 location, in UInt256 length); + long CalculateMemoryCost(in UInt256 location, in UInt256 length); + List GetTrace(); + } + + public class StackableEvmMemory : IEvmMemory + { + private StackableEvmMemory _parent; + + private EvmPooledMemory _pooled; + + private ulong _offset; + + public StackableEvmMemory() + { + _pooled = new EvmPooledMemory(); + } + + public StackableEvmMemory(StackableEvmMemory stackableEvmMemory, ulong offset) + { + _pooled = stackableEvmMemory._pooled; + _offset = stackableEvmMemory._offset + offset; + _parent = stackableEvmMemory; + } + + // need to add a method to shrink the EvmPooled - not too difficult + + public void Dispose() + { + if (_parent is null) + { + _pooled.Dispose(); + } + } + + public ulong Size => _pooled.Size - _offset / 32; + + public void SaveWord(in UInt256 location, Span word) + { + _pooled.SaveWord(location + _offset, word); + } + + public void SaveByte(in UInt256 location, byte value) + { + // obvious + throw new NotImplementedException(); + } + + public void Save(in UInt256 location, Span value) + { + // obvious + throw new NotImplementedException(); + } + + public void Save(in UInt256 location, byte[] value) + { + // obvious + throw new NotImplementedException(); + } + + public Span LoadSpan(in UInt256 location) + { + // obvious + throw new NotImplementedException(); + } + + public Span LoadSpan(in UInt256 location, in UInt256 length) + { + // obvious + throw new NotImplementedException(); + } + + public ReadOnlyMemory Load(in UInt256 location, in UInt256 length) + { + // obvious + throw new NotImplementedException(); + } + + public long CalculateMemoryCost(in UInt256 location, in UInt256 length) + { + // need to rewrite, minor challenge + throw new NotImplementedException(); + } + + public List GetTrace() + { + // need to rewrite but simple + throw new NotImplementedException(); + } + } } diff --git a/src/Nethermind/Nethermind.Evm/IVirtualMachine.cs b/src/Nethermind/Nethermind.Evm/IVirtualMachine.cs index 2a8188828b3..25629701e52 100644 --- a/src/Nethermind/Nethermind.Evm/IVirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/IVirtualMachine.cs @@ -7,14 +7,11 @@ using Nethermind.Evm.Tracing; using Nethermind.State; -using static Nethermind.Evm.VirtualMachine; - namespace Nethermind.Evm { public interface IVirtualMachine { - TransactionSubstate Run(EvmState state, IWorldState worldState, ITxTracer txTracer) - where TTracingActions : struct, IIsTracing; + TransactionSubstate Run(EvmState state, IWorldState worldState, ITxTracer tracer); CodeInfo GetCachedCodeInfo(IWorldState worldState, Address codeSource, IReleaseSpec spec); } diff --git a/src/Nethermind/Nethermind.Evm/Instruction.cs b/src/Nethermind/Nethermind.Evm/Instruction.cs index 1b82f66113e..7f7d95eb75a 100644 --- a/src/Nethermind/Nethermind.Evm/Instruction.cs +++ b/src/Nethermind/Nethermind.Evm/Instruction.cs @@ -1,9 +1,10 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using FastEnumUtility; -using Nethermind.Core.Specs; namespace Nethermind.Evm { @@ -38,7 +39,7 @@ public enum Instruction : byte SHR = 0x1c, // EIP-145 SAR = 0x1d, // EIP-145 - KECCAK256 = 0x20, + SHA3 = 0x20, ADDRESS = 0x30, BALANCE = 0x31, @@ -67,7 +68,6 @@ public enum Instruction : byte SELFBALANCE = 0x47, BASEFEE = 0x48, BLOBHASH = 0x49, - BLOBBASEFEE = 0x4a, POP = 0x50, MLOAD = 0x51, @@ -84,7 +84,6 @@ public enum Instruction : byte BEGINSUB = 0x5c, RETURNSUB = 0x5d, JUMPSUB = 0x5e, - MCOPY = 0x5e, PUSH0 = 0x5f, // EIP-3855 PUSH1 = 0x60, @@ -161,8 +160,8 @@ public enum Instruction : byte LOG4 = 0xa4, // EIP-1153 - TLOAD = 0x5c, - TSTORE = 0x5d, + TLOAD = 0xb3, + TSTORE = 0xb4, CREATE = 0xf0, CALL = 0xf1, @@ -178,15 +177,12 @@ public enum Instruction : byte public static class InstructionExtensions { - public static string? GetName(this Instruction instruction, bool isPostMerge = false, IReleaseSpec? spec = null) => - instruction switch - { - Instruction.PREVRANDAO when !isPostMerge => "DIFFICULTY", - Instruction.TLOAD or Instruction.BEGINSUB => spec?.TransientStorageEnabled == true ? "TLOAD" : "BEGINSUB", - Instruction.TSTORE or Instruction.RETURNSUB => spec?.TransientStorageEnabled == true ? "TSTORE" : "RETURNSUB", - Instruction.JUMPSUB or Instruction.MCOPY => spec?.IsEip5656Enabled == true ? "MCOPY" : "JUMPSUB", - _ => FastEnum.IsDefined(instruction) ? FastEnum.GetName(instruction) : null - }; + public static string? GetName(this Instruction instruction, bool isPostMerge = false) => + (instruction == Instruction.PREVRANDAO && !isPostMerge) + ? "DIFFICULTY" + : FastEnum.IsDefined(instruction) + ? FastEnum.GetName(instruction) + : null; } } diff --git a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs index bb90b262e99..b030b204bb2 100644 --- a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using System.IO; +using System.Linq; using Nethermind.Core; using Nethermind.Core.Eip2930; using Nethermind.Core.Specs; @@ -61,19 +61,33 @@ private static long AccessListCost(Transaction transaction, IReleaseSpec release long accessListCost = 0; if (accessList is not null) { - if (!releaseSpec.UseTxAccessLists) + if (releaseSpec.UseTxAccessLists) { - throw new InvalidDataException( - $"Transaction with an access list received within the context of {releaseSpec.Name}. Eip-2930 is not enabled."); - } - - foreach ((Address address, AccessList.StorageKeysEnumerable storageKeys) entry in accessList) - { - accessListCost += GasCostOf.AccessAccountListEntry; - foreach (UInt256 _ in entry.storageKeys) + if (accessList.IsNormalized) { - accessListCost += GasCostOf.AccessStorageListEntry; + accessListCost += accessList.Data.Count * GasCostOf.AccessAccountListEntry; + accessListCost += accessList.Data.Sum(d => d.Value.Count) * + GasCostOf.AccessStorageListEntry; } + else + { + foreach (object o in accessList.OrderQueue!) + { + if (o is Address) + { + accessListCost += GasCostOf.AccessAccountListEntry; + } + else + { + accessListCost += GasCostOf.AccessStorageListEntry; + } + } + } + } + else + { + throw new InvalidDataException( + $"Transaction with an access list received within the context of {releaseSpec.Name}. Eip-2930 is not enabled."); } } diff --git a/src/Nethermind/Nethermind.Evm/Metrics.cs b/src/Nethermind/Nethermind.Evm/Metrics.cs index b904d0cd249..daae9be5b2f 100644 --- a/src/Nethermind/Nethermind.Evm/Metrics.cs +++ b/src/Nethermind/Nethermind.Evm/Metrics.cs @@ -2,16 +2,28 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.ComponentModel; -using System.Runtime.CompilerServices; - using Nethermind.Core.Attributes; -[assembly: InternalsVisibleTo("Nethermind.Consensus")] - namespace Nethermind.Evm; public class Metrics { + [CounterMetric] + [Description("Number of EXTCODESIZE opcodes executed.")] + public static long ExtCodeSizeOpcode; + + [CounterMetric] + [Description("Number of EXTCODESIZE ISZERO optimizations.")] + public static long ExtCodeSizeOptimizedIsZero; + + [CounterMetric] + [Description("Number of EXTCODESIZE GT optimizations.")] + public static long ExtCodeSizeOptimizedGT; + + [CounterMetric] + [Description("Number of EXTCODESIZE EQ optimizations.")] + public static long ExtCodeSizeOptimizedEQ; + [CounterMetric] [Description("Number of EVM exceptions thrown by contracts.")] public static long EvmExceptions { get; set; } @@ -40,10 +52,6 @@ public class Metrics [Description("Number of TSTORE opcodes executed.")] public static long TstoreOpcode { get; set; } - [CounterMetric] - [Description("Number of MCOPY opcodes executed.")] - public static long MCopyOpcode { get; set; } - [CounterMetric] [Description("Number of MODEXP precompiles executed.")] public static long ModExpOpcode { get; set; } @@ -83,30 +91,4 @@ public class Metrics [CounterMetric] [Description("Number of Point Evaluation precompile calls.")] public static long PointEvaluationPrecompile { get; set; } - - [Description("Number of calls made to addresses without code.")] - public static long EmptyCalls { get; set; } - - [Description("Number of contract create calls.")] - public static long Creates { get; set; } - internal static long Transactions { get; set; } - internal static decimal AveGasPrice { get; set; } - internal static decimal MinGasPrice { get; set; } = decimal.MaxValue; - internal static decimal MaxGasPrice { get; set; } - internal static decimal EstMedianGasPrice { get; set; } - - internal static long BlockTransactions { get; set; } - internal static decimal BlockAveGasPrice { get; set; } - internal static decimal BlockMinGasPrice { get; set; } = decimal.MaxValue; - internal static decimal BlockMaxGasPrice { get; set; } - internal static decimal BlockEstMedianGasPrice { get; set; } - - public static void ResetBlockStats() - { - BlockTransactions = 0; - BlockAveGasPrice = 0m; - BlockMaxGasPrice = 0m; - BlockEstMedianGasPrice = 0m; - BlockMinGasPrice = decimal.MaxValue; - } } diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/AddressExtensions.cs b/src/Nethermind/Nethermind.Evm/Precompiles/AddressExtensions.cs index 560ef8ca8e7..2bb5272518b 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/AddressExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/AddressExtensions.cs @@ -2,41 +2,47 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Runtime.InteropServices; using Nethermind.Core; +using Nethermind.Core.Extensions; using Nethermind.Core.Specs; -namespace Nethermind.Evm.Precompiles; - -public static class AddressExtensions +namespace Nethermind.Evm.Precompiles { - public static bool IsPrecompile(this Address address, IReleaseSpec releaseSpec) + public static class AddressExtensions { - Span data = MemoryMarshal.Cast(address.Bytes.AsSpan()); - return (data[4] & 0x00ffffff) == 0 - && data[3] == 0 && data[2] == 0 && data[1] == 0 && data[0] == 0 - && (data[4] >>> 24) switch + private static byte[] _nineteenZeros = new byte[19]; + + public static bool IsPrecompile(this Address address, IReleaseSpec releaseSpec) + { + if (!Bytes.AreEqual(address.Bytes.AsSpan(0, 19), _nineteenZeros)) + { + return false; + } + + int precompileCode = address[19]; + return precompileCode switch { - 0x01 => true, - 0x02 => true, - 0x03 => true, - 0x04 => true, - 0x05 => releaseSpec.ModExpEnabled, - 0x06 => releaseSpec.Bn128Enabled, - 0x07 => releaseSpec.Bn128Enabled, - 0x08 => releaseSpec.Bn128Enabled, - 0x09 => releaseSpec.BlakeEnabled, - 0x0a => releaseSpec.IsEip4844Enabled, - 0x0c => releaseSpec.Bls381Enabled, - 0x0d => releaseSpec.Bls381Enabled, - 0x0e => releaseSpec.Bls381Enabled, - 0x0f => releaseSpec.Bls381Enabled, - 0x10 => releaseSpec.Bls381Enabled, - 0x11 => releaseSpec.Bls381Enabled, - 0x12 => releaseSpec.Bls381Enabled, - 0x13 => releaseSpec.Bls381Enabled, - 0x14 => releaseSpec.Bls381Enabled, + 1 => true, + 2 => true, + 3 => true, + 4 => true, + 5 => releaseSpec.ModExpEnabled, + 6 => releaseSpec.Bn128Enabled, + 7 => releaseSpec.Bn128Enabled, + 8 => releaseSpec.Bn128Enabled, + 9 => releaseSpec.BlakeEnabled, + 10 => releaseSpec.Bls381Enabled, + 11 => releaseSpec.Bls381Enabled, + 12 => releaseSpec.Bls381Enabled, + 13 => releaseSpec.Bls381Enabled, + 14 => releaseSpec.Bls381Enabled, + 15 => releaseSpec.Bls381Enabled, + 16 => releaseSpec.Bls381Enabled, + 17 => releaseSpec.Bls381Enabled, + 18 => releaseSpec.Bls381Enabled, + 20 => releaseSpec.IsEip4844Enabled, _ => false }; + } } } diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Blake2FPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Blake2FPrecompile.cs index 3688f39f8c2..985eeafd6b3 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Blake2FPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Blake2FPrecompile.cs @@ -9,15 +9,15 @@ namespace Nethermind.Evm.Precompiles { - public class Blake2FPrecompile : IPrecompile + public class Blake2FPrecompile : IPrecompile { private const int RequiredInputLength = 213; private Blake2Compression _blake = new(); - public static readonly Blake2FPrecompile Instance = new Blake2FPrecompile(); + public static readonly IPrecompile Instance = new Blake2FPrecompile(); - public static Address Address { get; } = Address.FromNumber(9); + public Address Address { get; } = Address.FromNumber(9); public long BaseGasCost(IReleaseSpec releaseSpec) => 0; diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1AddPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1AddPrecompile.cs index bd7c93001af..53f01b9d8d9 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1AddPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1AddPrecompile.cs @@ -11,15 +11,15 @@ namespace Nethermind.Evm.Precompiles.Bls; /// /// https://eips.ethereum.org/EIPS/eip-2537 /// -public class G1AddPrecompile : IPrecompile +public class G1AddPrecompile : IPrecompile { - public static G1AddPrecompile Instance = new G1AddPrecompile(); + public static IPrecompile Instance = new G1AddPrecompile(); private G1AddPrecompile() { } - public static Address Address { get; } = Address.FromNumber(0x0c); + public Address Address { get; } = Address.FromNumber(10); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1MulPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1MulPrecompile.cs index 5c629f79f5b..c01d96586dc 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1MulPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1MulPrecompile.cs @@ -11,15 +11,15 @@ namespace Nethermind.Evm.Precompiles.Bls; /// /// https://eips.ethereum.org/EIPS/eip-2537 /// -public class G1MulPrecompile : IPrecompile +public class G1MulPrecompile : IPrecompile { - public static G1MulPrecompile Instance = new G1MulPrecompile(); + public static IPrecompile Instance = new G1MulPrecompile(); private G1MulPrecompile() { } - public static Address Address { get; } = Address.FromNumber(0x0d); + public Address Address { get; } = Address.FromNumber(11); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1MultiExpPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1MultiExpPrecompile.cs index 8311db6b26f..6a6eadb0c28 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1MultiExpPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G1MultiExpPrecompile.cs @@ -11,15 +11,15 @@ namespace Nethermind.Evm.Precompiles.Bls; /// /// https://eips.ethereum.org/EIPS/eip-2537 /// -public class G1MultiExpPrecompile : IPrecompile +public class G1MultiExpPrecompile : IPrecompile { - public static G1MultiExpPrecompile Instance = new G1MultiExpPrecompile(); + public static IPrecompile Instance = new G1MultiExpPrecompile(); private G1MultiExpPrecompile() { } - public static Address Address { get; } = Address.FromNumber(0x0e); + public Address Address { get; } = Address.FromNumber(12); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2AddPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2AddPrecompile.cs index 24d3b505ea8..6cff52b269d 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2AddPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2AddPrecompile.cs @@ -11,15 +11,15 @@ namespace Nethermind.Evm.Precompiles.Bls; /// /// https://eips.ethereum.org/EIPS/eip-2537 /// -public class G2AddPrecompile : IPrecompile +public class G2AddPrecompile : IPrecompile { - public static G2AddPrecompile Instance = new G2AddPrecompile(); + public static IPrecompile Instance = new G2AddPrecompile(); private G2AddPrecompile() { } - public static Address Address { get; } = Address.FromNumber(0x0f); + public Address Address { get; } = Address.FromNumber(13); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2MulPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2MulPrecompile.cs index aac75281db2..1f5145ba4a0 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2MulPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2MulPrecompile.cs @@ -11,15 +11,15 @@ namespace Nethermind.Evm.Precompiles.Bls; /// /// https://eips.ethereum.org/EIPS/eip-2537 /// -public class G2MulPrecompile : IPrecompile +public class G2MulPrecompile : IPrecompile { - public static G2MulPrecompile Instance = new G2MulPrecompile(); + public static IPrecompile Instance = new G2MulPrecompile(); private G2MulPrecompile() { } - public static Address Address { get; } = Address.FromNumber(0x10); + public Address Address { get; } = Address.FromNumber(14); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2MultiExpPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2MultiExpPrecompile.cs index 98047a600b7..b4118cd13f1 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2MultiExpPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/G2MultiExpPrecompile.cs @@ -11,15 +11,15 @@ namespace Nethermind.Evm.Precompiles.Bls; /// /// https://eips.ethereum.org/EIPS/eip-2537 /// -public class G2MultiExpPrecompile : IPrecompile +public class G2MultiExpPrecompile : IPrecompile { - public static G2MultiExpPrecompile Instance = new G2MultiExpPrecompile(); + public static IPrecompile Instance = new G2MultiExpPrecompile(); private G2MultiExpPrecompile() { } - public static Address Address { get; } = Address.FromNumber(0x11); + public Address Address { get; } = Address.FromNumber(15); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/MapToG1Precompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/MapToG1Precompile.cs index 40cc774de91..ca8ce9fd93e 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/MapToG1Precompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/MapToG1Precompile.cs @@ -11,15 +11,15 @@ namespace Nethermind.Evm.Precompiles.Bls; /// /// https://eips.ethereum.org/EIPS/eip-2537 /// -public class MapToG1Precompile : IPrecompile +public class MapToG1Precompile : IPrecompile { - public static MapToG1Precompile Instance = new MapToG1Precompile(); + public static IPrecompile Instance = new MapToG1Precompile(); private MapToG1Precompile() { } - public static Address Address { get; } = Address.FromNumber(0x13); + public Address Address { get; } = Address.FromNumber(17); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/MapToG2Precompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/MapToG2Precompile.cs index b2ffcdc3fa2..e79aafeb536 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/MapToG2Precompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/MapToG2Precompile.cs @@ -11,15 +11,15 @@ namespace Nethermind.Evm.Precompiles.Bls; /// /// https://eips.ethereum.org/EIPS/eip-2537 /// -public class MapToG2Precompile : IPrecompile +public class MapToG2Precompile : IPrecompile { - public static MapToG2Precompile Instance = new MapToG2Precompile(); + public static IPrecompile Instance = new MapToG2Precompile(); private MapToG2Precompile() { } - public static Address Address { get; } = Address.FromNumber(0x14); + public Address Address { get; } = Address.FromNumber(18); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/PairingPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/PairingPrecompile.cs index c115d7fad30..660df65af64 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Bls/PairingPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Bls/PairingPrecompile.cs @@ -11,15 +11,15 @@ namespace Nethermind.Evm.Precompiles.Bls; /// /// https://eips.ethereum.org/EIPS/eip-2537 /// -public class PairingPrecompile : IPrecompile +public class PairingPrecompile : IPrecompile { private const int PairSize = 384; private PairingPrecompile() { } - public static Address Address { get; } = Address.FromNumber(0x12); + public Address Address { get; } = Address.FromNumber(16); - public static PairingPrecompile Instance = new PairingPrecompile(); + public static IPrecompile Instance = new PairingPrecompile(); public long BaseGasCost(IReleaseSpec releaseSpec) => 115000L; diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/EcRecoverPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/EcRecoverPrecompile.cs index 7698f636aca..c633aa52998 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/EcRecoverPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/EcRecoverPrecompile.cs @@ -11,15 +11,15 @@ namespace Nethermind.Evm.Precompiles { - public class EcRecoverPrecompile : IPrecompile + public class EcRecoverPrecompile : IPrecompile { - public static readonly EcRecoverPrecompile Instance = new EcRecoverPrecompile(); + public static readonly IPrecompile Instance = new EcRecoverPrecompile(); private EcRecoverPrecompile() { } - public static Address Address { get; } = Address.FromNumber(1); + public Address Address { get; } = Address.FromNumber(1); public long DataGasCost(in ReadOnlyMemory inputData, IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/IPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/IPrecompile.cs index e159783132a..90229ea43e9 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/IPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/IPrecompile.cs @@ -9,7 +9,7 @@ namespace Nethermind.Evm.Precompiles { public interface IPrecompile { - static Address Address { get; } + Address Address { get; } long BaseGasCost(IReleaseSpec releaseSpec); @@ -17,10 +17,4 @@ public interface IPrecompile (ReadOnlyMemory, bool) Run(in ReadOnlyMemory inputData, IReleaseSpec releaseSpec); } - - - public interface IPrecompile : IPrecompile - { - static TPrecompileTypeInstance Instance { get; } - } } diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/IdentityPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/IdentityPrecompile.cs index e26dc714acc..8f3f624e4d4 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/IdentityPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/IdentityPrecompile.cs @@ -7,15 +7,15 @@ namespace Nethermind.Evm.Precompiles { - public class IdentityPrecompile : IPrecompile + public class IdentityPrecompile : IPrecompile { - public static readonly IdentityPrecompile Instance = new IdentityPrecompile(); + public static readonly IPrecompile Instance = new IdentityPrecompile(); private IdentityPrecompile() { } - public static Address Address { get; } = Address.FromNumber(4); + public Address Address { get; } = Address.FromNumber(4); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/ModExpPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/ModExpPrecompile.cs index 9f096e519ad..b6372c15e57 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/ModExpPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/ModExpPrecompile.cs @@ -15,15 +15,15 @@ namespace Nethermind.Evm.Precompiles /// /// https://github.com/ethereum/EIPs/blob/vbuterin-patch-2/EIPS/bigint_modexp.md /// - public class ModExpPrecompile : IPrecompile + public class ModExpPrecompile : IPrecompile { - public static readonly ModExpPrecompile Instance = new ModExpPrecompile(); + public static readonly IPrecompile Instance = new ModExpPrecompile(); private ModExpPrecompile() { } - public static Address Address { get; } = Address.FromNumber(5); + public Address Address { get; } = Address.FromNumber(5); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/ModExpPrecompilePreEip2565.cs b/src/Nethermind/Nethermind.Evm/Precompiles/ModExpPrecompilePreEip2565.cs index 3af18341264..1f5c23d3e36 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/ModExpPrecompilePreEip2565.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/ModExpPrecompilePreEip2565.cs @@ -14,15 +14,15 @@ namespace Nethermind.Evm.Precompiles /// https://github.com/ethereum/EIPs/blob/vbuterin-patch-2/EIPS/bigint_modexp.md /// [Obsolete("Pre-eip2565 implementation")] - public class ModExpPrecompilePreEip2565 : IPrecompile + public class ModExpPrecompilePreEip2565 : IPrecompile { - public static ModExpPrecompilePreEip2565 Instance = new ModExpPrecompilePreEip2565(); + public static IPrecompile Instance = new ModExpPrecompilePreEip2565(); private ModExpPrecompilePreEip2565() { } - public static Address Address { get; } = Address.FromNumber(5); + public Address Address { get; } = Address.FromNumber(5); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/PointEvaluationPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/PointEvaluationPrecompile.cs index a00b1baa934..d46e4c69d4c 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/PointEvaluationPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/PointEvaluationPrecompile.cs @@ -11,16 +11,16 @@ namespace Nethermind.Evm.Precompiles; -public class PointEvaluationPrecompile : IPrecompile +public class PointEvaluationPrecompile : IPrecompile { - public static readonly PointEvaluationPrecompile Instance = new PointEvaluationPrecompile(); + public static readonly IPrecompile Instance = new PointEvaluationPrecompile(); private static readonly ReadOnlyMemory PointEvaluationSuccessfulResponse = ((UInt256)Ckzg.Ckzg.FieldElementsPerBlob).ToBigEndian() .Concat(KzgPolynomialCommitments.BlsModulus.ToBigEndian()) .ToArray(); - public static Address Address { get; } = Address.FromNumber(0x0a); + public Address Address { get; } = Address.FromNumber(0x14); public long BaseGasCost(IReleaseSpec releaseSpec) => 50000L; diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Ripemd160Precompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Ripemd160Precompile.cs index 60b9b62198f..fced018d33a 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Ripemd160Precompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Ripemd160Precompile.cs @@ -9,9 +9,9 @@ namespace Nethermind.Evm.Precompiles { - public class Ripemd160Precompile : IPrecompile + public class Ripemd160Precompile : IPrecompile { - public static readonly Ripemd160Precompile Instance = new Ripemd160Precompile(); + public static readonly IPrecompile Instance = new Ripemd160Precompile(); // missing in .NET Core // private static RIPEMD160 _ripemd; @@ -23,7 +23,7 @@ private Ripemd160Precompile() // _ripemd.Initialize(); } - public static Address Address { get; } = Address.FromNumber(3); + public Address Address { get; } = Address.FromNumber(3); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Sha256Precompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Sha256Precompile.cs index 9946514d023..fefba43a16e 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Sha256Precompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Sha256Precompile.cs @@ -9,11 +9,11 @@ namespace Nethermind.Evm.Precompiles { - public class Sha256Precompile : IPrecompile + public class Sha256Precompile : IPrecompile { private static ThreadLocal _sha256 = new(); - public static readonly Sha256Precompile Instance = new Sha256Precompile(); + public static readonly IPrecompile Instance = new Sha256Precompile(); private Sha256Precompile() { @@ -30,7 +30,7 @@ private static void InitIfNeeded() } } - public static Address Address { get; } = Address.FromNumber(2); + public Address Address { get; } = Address.FromNumber(2); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Snarks/Bn254AddPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Snarks/Bn254AddPrecompile.cs index d2babd6cd7b..3b0e64f6e89 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Snarks/Bn254AddPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Snarks/Bn254AddPrecompile.cs @@ -11,11 +11,11 @@ namespace Nethermind.Evm.Precompiles.Snarks; /// /// https://github.com/matter-labs/eip1962/blob/master/eip196_header.h /// -public class Bn254AddPrecompile : IPrecompile +public class Bn254AddPrecompile : IPrecompile { - public static Bn254AddPrecompile Instance = new Bn254AddPrecompile(); + public static IPrecompile Instance = new Bn254AddPrecompile(); - public static Address Address { get; } = Address.FromNumber(6); + public Address Address { get; } = Address.FromNumber(6); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Snarks/Bn254MulPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Snarks/Bn254MulPrecompile.cs index d50e1f6bb2a..b14becb7039 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Snarks/Bn254MulPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Snarks/Bn254MulPrecompile.cs @@ -11,11 +11,11 @@ namespace Nethermind.Evm.Precompiles.Snarks; /// /// https://github.com/herumi/mcl/blob/master/api.md /// -public class Bn254MulPrecompile : IPrecompile +public class Bn254MulPrecompile : IPrecompile { - public static Bn254MulPrecompile Instance = new Bn254MulPrecompile(); + public static IPrecompile Instance = new Bn254MulPrecompile(); - public static Address Address { get; } = Address.FromNumber(7); + public Address Address { get; } = Address.FromNumber(7); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Precompiles/Snarks/Bn254PairingPrecompile.cs b/src/Nethermind/Nethermind.Evm/Precompiles/Snarks/Bn254PairingPrecompile.cs index 3757d30aa41..a46bc55e061 100644 --- a/src/Nethermind/Nethermind.Evm/Precompiles/Snarks/Bn254PairingPrecompile.cs +++ b/src/Nethermind/Nethermind.Evm/Precompiles/Snarks/Bn254PairingPrecompile.cs @@ -11,13 +11,13 @@ namespace Nethermind.Evm.Precompiles.Snarks; /// /// https://github.com/herumi/mcl/blob/master/api.md /// -public class Bn254PairingPrecompile : IPrecompile +public class Bn254PairingPrecompile : IPrecompile { private const int PairSize = 192; - public static Bn254PairingPrecompile Instance = new Bn254PairingPrecompile(); + public static IPrecompile Instance = new Bn254PairingPrecompile(); - public static Address Address { get; } = Address.FromNumber(8); + public Address Address { get; } = Address.FromNumber(8); public long BaseGasCost(IReleaseSpec releaseSpec) { diff --git a/src/Nethermind/Nethermind.Evm/Tracing/AccessTxTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/AccessTxTracer.cs index 9959ecf1b1a..ebd851a145e 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/AccessTxTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/AccessTxTracer.cs @@ -1,7 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; +using System.Linq; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Eip2930; @@ -9,32 +11,179 @@ namespace Nethermind.Evm.Tracing { - public class AccessTxTracer : TxTracer + public class AccessTxTracer : ITxTracer { - private const long ColdVsWarmSLoadDelta = GasCostOf.ColdSLoad - GasCostOf.AccessStorageListEntry; - public const long MaxStorageAccessToOptimize = GasCostOf.AccessAccountListEntry / ColdVsWarmSLoadDelta; + private const long ColdVsWarmSloadDelta = GasCostOf.ColdSLoad - GasCostOf.AccessStorageListEntry; + public const long MaxStorageAccessToOptimize = GasCostOf.AccessAccountListEntry / ColdVsWarmSloadDelta; private readonly Address[] _addressesToOptimize; - public override bool IsTracingReceipt => true; - public override bool IsTracingAccess => true; + public bool IsTracingState => false; + public bool IsTracingStorage => false; + public bool IsTracingReceipt => true; + public bool IsTracingActions => false; + public bool IsTracingOpLevelStorage => false; + public bool IsTracingMemory => false; + public bool IsTracingInstructions => false; + public bool IsTracingRefunds => false; + public bool IsTracingCode => false; + public bool IsTracingStack => false; + public bool IsTracingBlockHash => false; + public bool IsTracingAccess => true; + public bool IsTracingFees => false; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; public AccessTxTracer(params Address[] addressesToOptimize) { _addressesToOptimize = addressesToOptimize; } - public override void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) + { + throw new NotImplementedException(); + } + + public void ReportCodeChange(Address address, byte[]? before, byte[]? after) + { + throw new NotImplementedException(); + } + + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) + { + throw new NotImplementedException(); + } + + public void ReportAccountRead(Address address) + { + throw new NotImplementedException(); + } + + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) + { + throw new NotImplementedException(); + } + + public void ReportStorageRead(in StorageCell storageCell) + { + throw new NotImplementedException(); + } + + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) { GasSpent += gasSpent; } - public override void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) { GasSpent += gasSpent; } - public override void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) + { + throw new NotImplementedException(); + } + + public void ReportOperationError(EvmExceptionType error) + { + throw new NotImplementedException(); + } + + public void ReportOperationRemainingGas(long gas) + { + throw new NotImplementedException(); + } + + public void SetOperationStack(List stackTrace) + { + throw new NotImplementedException(); + } + + public void ReportStackPush(in ReadOnlySpan stackItem) + { + throw new NotImplementedException(); + } + + public void SetOperationMemory(List memoryTrace) + { + throw new NotImplementedException(); + } + + public void SetOperationMemorySize(ulong newSize) + { + throw new NotImplementedException(); + } + + public void ReportMemoryChange(long offset, in ReadOnlySpan data) + { + throw new NotImplementedException(); + } + + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) + { + throw new NotImplementedException(); + } + + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) + { + throw new NotImplementedException(); + } + + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) + { + throw new NotImplementedException(); + } + + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) + { + throw new NotImplementedException(); + } + + public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) + { + throw new NotImplementedException(); + } + + public void ReportActionEnd(long gas, ReadOnlyMemory output) + { + throw new NotImplementedException(); + } + + public void ReportActionError(EvmExceptionType evmExceptionType) + { + throw new NotImplementedException(); + } + + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) + { + throw new NotImplementedException(); + } + + public void ReportBlockHash(Keccak blockHash) + { + throw new NotImplementedException(); + } + + public void ReportByteCode(byte[] byteCode) + { + throw new NotImplementedException(); + } + + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) + { + throw new NotImplementedException(); + } + + public void ReportRefund(long refund) + { + throw new NotImplementedException(); + } + + public void ReportExtraGasPressure(long extraGasPressure) + { + throw new NotImplementedException(); + } + + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) { Dictionary> dictionary = new(); foreach (Address address in accessedAddresses) @@ -62,16 +211,12 @@ public override void ReportAccess(IReadOnlySet
accessedAddresses, IRead } } - AccessList.Builder builder = new(); - foreach ((Address address, ISet storageKeys) in dictionary) - { - builder.AddAddress(address); - foreach (UInt256 storageKey in storageKeys) - { - builder.AddStorage(storageKey); - } - } - AccessList = builder.Build(); + AccessList = new AccessList(dictionary.ToDictionary(k => k.Key, v => (IReadOnlySet)v.Value)); + } + + public void ReportFees(UInt256 fees, UInt256 burntFees) + { + throw new NotImplementedException(); } public long GasSpent { get; set; } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/AlwaysCancelBlockTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/AlwaysCancelBlockTracer.cs index 34963b0e6a4..0839a51a248 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/AlwaysCancelBlockTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/AlwaysCancelBlockTracer.cs @@ -3,12 +3,14 @@ using System.Threading; using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Int256; namespace Nethermind.Evm.Tracing { - public class AlwaysCancelBlockTracer : BlockTracer + public class AlwaysCancelBlockTracer : IBlockTracer { - private static AlwaysCancelBlockTracer? _instance; + private static AlwaysCancelBlockTracer _instance; private AlwaysCancelBlockTracer() { @@ -19,11 +21,27 @@ public static AlwaysCancelBlockTracer Instance get { return LazyInitializer.EnsureInitialized(ref _instance, () => new AlwaysCancelBlockTracer()); } } - public override bool IsTracingRewards => true; + public bool IsTracingRewards => true; - public override ITxTracer StartNewTxTrace(Transaction? tx) + public void ReportReward(Address author, string rewardType, UInt256 rewardValue) + { + } + + public void StartNewBlockTrace(Block block) + { + } + + public ITxTracer StartNewTxTrace(Transaction? tx) { return AlwaysCancelTxTracer.Instance; } + + public void EndTxTrace() + { + } + + public void EndBlockTrace() + { + } } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/AlwaysCancelTxTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/AlwaysCancelTxTracer.cs index 1057672ba78..29b6c00dc34 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/AlwaysCancelTxTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/AlwaysCancelTxTracer.cs @@ -8,91 +8,93 @@ using Nethermind.Core.Crypto; using Nethermind.Int256; -namespace Nethermind.Evm.Tracing; - -/// -/// For testing -/// -public class AlwaysCancelTxTracer : ITxTracer +namespace Nethermind.Evm.Tracing { - private const string ErrorMessage = "Cancelling tracer invoked."; + /// + /// For testing + /// + public class AlwaysCancelTxTracer : ITxTracer + { + private const string ErrorMessage = "Cancelling tracer invoked."; - private static AlwaysCancelTxTracer? _instance; + private static AlwaysCancelTxTracer _instance; - private AlwaysCancelTxTracer() - { - } + private AlwaysCancelTxTracer() + { + } - public static AlwaysCancelTxTracer Instance - { - get { return LazyInitializer.EnsureInitialized(ref _instance, () => new AlwaysCancelTxTracer()); } - } + public static AlwaysCancelTxTracer Instance + { + get { return LazyInitializer.EnsureInitialized(ref _instance, () => new AlwaysCancelTxTracer()); } + } - public bool IsTracingReceipt => true; - public bool IsTracingActions => true; - public bool IsTracingOpLevelStorage => true; - public bool IsTracingMemory => true; - public bool IsTracingInstructions => true; - public bool IsTracingRefunds => true; - public bool IsTracingCode => true; - public bool IsTracingStack => true; - public bool IsTracingState => true; - public bool IsTracingStorage => true; - public bool IsTracingBlockHash => true; - public bool IsTracingAccess => true; - public bool IsTracingFees => true; + public bool IsTracingReceipt => true; + public bool IsTracingActions => true; + public bool IsTracingOpLevelStorage => true; + public bool IsTracingMemory => true; + public bool IsTracingInstructions => true; + public bool IsTracingRefunds => true; + public bool IsTracingCode => true; + public bool IsTracingStack => true; + public bool IsTracingState => true; + public bool IsTracingStorage => true; + public bool IsTracingBlockHash => true; + public bool IsTracingAccess => true; + public bool IsTracingFees => true; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; - public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) => throw new OperationCanceledException(ErrorMessage); + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak stateRoot = null) => throw new OperationCanceledException(ErrorMessage); - public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) => throw new OperationCanceledException(ErrorMessage); + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak stateRoot = null) => throw new OperationCanceledException(ErrorMessage); - public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) => throw new OperationCanceledException(ErrorMessage); + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) => throw new OperationCanceledException(ErrorMessage); - public void ReportOperationError(EvmExceptionType error) => throw new OperationCanceledException(ErrorMessage); + public void ReportOperationError(EvmExceptionType error) => throw new OperationCanceledException(ErrorMessage); - public void ReportOperationRemainingGas(long gas) => throw new OperationCanceledException(ErrorMessage); + public void ReportOperationRemainingGas(long gas) => throw new OperationCanceledException(ErrorMessage); - public void SetOperationMemorySize(ulong newSize) => throw new OperationCanceledException(ErrorMessage); + public void SetOperationMemorySize(ulong newSize) => throw new OperationCanceledException(ErrorMessage); - public void ReportMemoryChange(long offset, in ReadOnlySpan data) => throw new OperationCanceledException(ErrorMessage); - public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) => throw new OperationCanceledException(ErrorMessage); + public void ReportMemoryChange(long offset, in ReadOnlySpan data) => throw new OperationCanceledException(ErrorMessage); + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) => throw new OperationCanceledException(ErrorMessage); - public void SetOperationStack(List stackTrace) => throw new OperationCanceledException(ErrorMessage); + public void SetOperationStack(List stackTrace) => throw new OperationCanceledException(ErrorMessage); - public void ReportStackPush(in ReadOnlySpan stackItem) => throw new OperationCanceledException(ErrorMessage); + public void ReportStackPush(in ReadOnlySpan stackItem) => throw new OperationCanceledException(ErrorMessage); - public void SetOperationMemory(IEnumerable memoryTrace) => throw new OperationCanceledException(ErrorMessage); + public void SetOperationMemory(List memoryTrace) => throw new OperationCanceledException(ErrorMessage); - public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) => throw new OperationCanceledException(ErrorMessage); + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) => throw new OperationCanceledException(ErrorMessage); - public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) => throw new OperationCanceledException(ErrorMessage); + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) => throw new OperationCanceledException(ErrorMessage); - public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) => throw new OperationCanceledException(ErrorMessage); + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) => throw new OperationCanceledException(ErrorMessage); - public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) => throw new OperationCanceledException(ErrorMessage); + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) => throw new OperationCanceledException(ErrorMessage); - public void ReportCodeChange(Address address, byte[] before, byte[] after) => throw new OperationCanceledException(ErrorMessage); + public void ReportCodeChange(Address address, byte[] before, byte[] after) => throw new OperationCanceledException(ErrorMessage); - public void ReportNonceChange(Address address, UInt256? before, UInt256? after) => throw new OperationCanceledException(ErrorMessage); + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) => throw new OperationCanceledException(ErrorMessage); - public void ReportAccountRead(Address address) => throw new OperationCanceledException(ErrorMessage); + public void ReportAccountRead(Address address) => throw new OperationCanceledException(ErrorMessage); - public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) => throw new OperationCanceledException(ErrorMessage); + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) => throw new OperationCanceledException(ErrorMessage); - public void ReportStorageRead(in StorageCell storageCell) => throw new OperationCanceledException(ErrorMessage); + public void ReportStorageRead(in StorageCell storageCell) => throw new OperationCanceledException(ErrorMessage); - public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) => throw new OperationCanceledException(ErrorMessage); + public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) => throw new OperationCanceledException(ErrorMessage); - public void ReportActionEnd(long gas, ReadOnlyMemory output) => throw new OperationCanceledException(ErrorMessage); - public void ReportActionError(EvmExceptionType exceptionType) => throw new OperationCanceledException(ErrorMessage); + public void ReportActionEnd(long gas, ReadOnlyMemory output) => throw new OperationCanceledException(ErrorMessage); + public void ReportActionError(EvmExceptionType exceptionType) => throw new OperationCanceledException(ErrorMessage); - public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) => throw new OperationCanceledException(ErrorMessage); - public void ReportBlockHash(Keccak blockHash) => throw new OperationCanceledException(ErrorMessage); + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) => throw new OperationCanceledException(ErrorMessage); + public void ReportBlockHash(Keccak blockHash) => throw new OperationCanceledException(ErrorMessage); - public void ReportByteCode(byte[] byteCode) => throw new OperationCanceledException(ErrorMessage); - public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) => throw new OperationCanceledException(ErrorMessage); - public void ReportRefund(long refund) => throw new OperationCanceledException(ErrorMessage); - public void ReportExtraGasPressure(long extraGasPressure) => throw new OperationCanceledException(ErrorMessage); - public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) => throw new OperationCanceledException(ErrorMessage); - public void ReportFees(UInt256 fees, UInt256 burntFees) => throw new OperationCanceledException(ErrorMessage); + public void ReportByteCode(byte[] byteCode) => throw new OperationCanceledException(ErrorMessage); + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) => throw new OperationCanceledException(ErrorMessage); + public void ReportRefund(long refund) => throw new OperationCanceledException(ErrorMessage); + public void ReportExtraGasPressure(long extraGasPressure) => throw new OperationCanceledException(ErrorMessage); + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) => throw new OperationCanceledException(ErrorMessage); + public void ReportFees(UInt256 fees, UInt256 burntFees) => throw new OperationCanceledException(ErrorMessage); + } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/BlockCallOutputTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/BlockCallOutputTracer.cs index 3f64766046f..3134ff5ea2d 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/BlockCallOutputTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/BlockCallOutputTracer.cs @@ -2,15 +2,26 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using System.Linq; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Int256; namespace Nethermind.Evm.Tracing { - public class BlockCallOutputTracer : BlockTracer + public class BlockCallOutputTracer : IBlockTracer { private readonly Dictionary _results = new(); - public override ITxTracer StartNewTxTrace(Transaction? tx) => _results[tx?.Hash ?? Keccak.Zero] = new CallOutputTracer(); + public bool IsTracingRewards => false; + public void ReportReward(Address author, string rewardType, UInt256 rewardValue) { } + public void StartNewBlockTrace(Block block) { } + public ITxTracer StartNewTxTrace(Transaction? tx) + { + return _results[tx?.Hash ?? Keccak.Zero] = new CallOutputTracer(); + } + + public void EndTxTrace() { } + public void EndBlockTrace() { } public IReadOnlyDictionary BuildResults() => _results; } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/BlockReceiptsTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/BlockReceiptsTracer.cs index 7517f3ab54f..83be8013b87 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/BlockReceiptsTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/BlockReceiptsTracer.cs @@ -7,259 +7,262 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Int256; +using Nethermind.State; -namespace Nethermind.Evm.Tracing; - -public class BlockReceiptsTracer : IBlockTracer, ITxTracer, IJournal, ITxTracerWrapper +namespace Nethermind.Evm.Tracing { - private Block _block = null!; - public bool IsTracingReceipt => true; - public bool IsTracingActions => _currentTxTracer.IsTracingActions; - public bool IsTracingOpLevelStorage => _currentTxTracer.IsTracingOpLevelStorage; - public bool IsTracingMemory => _currentTxTracer.IsTracingMemory; - public bool IsTracingInstructions => _currentTxTracer.IsTracingInstructions; - public bool IsTracingRefunds => _currentTxTracer.IsTracingRefunds; - public bool IsTracingCode => _currentTxTracer.IsTracingCode; - public bool IsTracingStack => _currentTxTracer.IsTracingStack; - public bool IsTracingState => _currentTxTracer.IsTracingState; - public bool IsTracingStorage => _currentTxTracer.IsTracingStorage; - - public bool IsTracingBlockHash => _currentTxTracer.IsTracingBlockHash; - public bool IsTracingAccess => _currentTxTracer.IsTracingAccess; - public bool IsTracingFees => _currentTxTracer.IsTracingFees; - - private IBlockTracer _otherTracer = NullBlockTracer.Instance; - - public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) + public class BlockReceiptsTracer : IBlockTracer, ITxTracer, IJournal, ITxTracerWrapper { - _txReceipts.Add(BuildReceipt(recipient, gasSpent, StatusCode.Success, logs, stateRoot)); - - // hacky way to support nested receipt tracers - if (_otherTracer is ITxTracer otherTxTracer) + private Block _block = null!; + public bool IsTracingReceipt => true; + public bool IsTracingActions => _currentTxTracer.IsTracingActions; + public bool IsTracingOpLevelStorage => _currentTxTracer.IsTracingOpLevelStorage; + public bool IsTracingMemory => _currentTxTracer.IsTracingMemory; + public bool IsTracingInstructions => _currentTxTracer.IsTracingInstructions; + public bool IsTracingRefunds => _currentTxTracer.IsTracingRefunds; + public bool IsTracingCode => _currentTxTracer.IsTracingCode; + public bool IsTracingStack => _currentTxTracer.IsTracingStack; + public bool IsTracingState => _currentTxTracer.IsTracingState; + public bool IsTracingStorage => _currentTxTracer.IsTracingStorage; + + public bool IsTracingBlockHash => _currentTxTracer.IsTracingBlockHash; + public bool IsTracingAccess => _currentTxTracer.IsTracingAccess; + public bool IsTracingFees => _currentTxTracer.IsTracingFees; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; + + private IBlockTracer _otherTracer = NullBlockTracer.Instance; + + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak stateRoot = null) { - otherTxTracer.MarkAsSuccess(recipient, gasSpent, output, logs, stateRoot); + _txReceipts.Add(BuildReceipt(recipient, gasSpent, StatusCode.Success, logs, stateRoot)); + + // hacky way to support nested receipt tracers + if (_otherTracer is ITxTracer otherTxTracer) + { + otherTxTracer.MarkAsSuccess(recipient, gasSpent, output, logs, stateRoot); + } + + if (_currentTxTracer.IsTracingReceipt) + { + _currentTxTracer.MarkAsSuccess(recipient, gasSpent, output, logs); + } } - if (_currentTxTracer.IsTracingReceipt) + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak stateRoot = null) { - _currentTxTracer.MarkAsSuccess(recipient, gasSpent, output, logs); - } - } + _txReceipts.Add(BuildFailedReceipt(recipient, gasSpent, error, stateRoot)); - public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) - { - _txReceipts.Add(BuildFailedReceipt(recipient, gasSpent, error, stateRoot)); + // hacky way to support nested receipt tracers + if (_otherTracer is ITxTracer otherTxTracer) + { + otherTxTracer.MarkAsFailed(recipient, gasSpent, output, error, stateRoot); + } - // hacky way to support nested receipt tracers - if (_otherTracer is ITxTracer otherTxTracer) - { - otherTxTracer.MarkAsFailed(recipient, gasSpent, output, error, stateRoot); + if (_currentTxTracer.IsTracingReceipt) + { + _currentTxTracer.MarkAsFailed(recipient, gasSpent, output, error); + } } - if (_currentTxTracer.IsTracingReceipt) + private TxReceipt BuildFailedReceipt(Address recipient, long gasSpent, string error, Keccak stateRoot = null) { - _currentTxTracer.MarkAsFailed(recipient, gasSpent, output, error); + TxReceipt receipt = BuildReceipt(recipient, gasSpent, StatusCode.Failure, Array.Empty(), stateRoot); + receipt.Error = error; + return receipt; } - } - private TxReceipt BuildFailedReceipt(Address recipient, long gasSpent, string error, Keccak? stateRoot = null) - { - TxReceipt receipt = BuildReceipt(recipient, gasSpent, StatusCode.Failure, Array.Empty(), stateRoot); - receipt.Error = error; - return receipt; - } - - private TxReceipt BuildReceipt(Address recipient, long spentGas, byte statusCode, LogEntry[] logEntries, Keccak? stateRoot = null) - { - Transaction transaction = _currentTx!; - TxReceipt txReceipt = new() + private TxReceipt BuildReceipt(Address recipient, long spentGas, byte statusCode, LogEntry[] logEntries, Keccak stateRoot = null) { - Logs = logEntries, - TxType = transaction.Type, - Bloom = logEntries.Length == 0 ? Bloom.Empty : new Bloom(logEntries), - GasUsedTotal = _block.GasUsed, - StatusCode = statusCode, - Recipient = transaction.IsContractCreation ? null : recipient, - BlockHash = _block.Hash, - BlockNumber = _block.Number, - Index = _currentIndex, - GasUsed = spentGas, - Sender = transaction.SenderAddress, - ContractAddress = transaction.IsContractCreation ? recipient : null, - TxHash = transaction.Hash, - PostTransactionState = stateRoot - }; - - return txReceipt; - } + Transaction transaction = _currentTx; + TxReceipt txReceipt = new() + { + Logs = logEntries, + TxType = transaction.Type, + Bloom = logEntries.Length == 0 ? Bloom.Empty : new Bloom(logEntries), + GasUsedTotal = _block.GasUsed, + StatusCode = statusCode, + Recipient = transaction.IsContractCreation ? null : recipient, + BlockHash = _block.Hash, + BlockNumber = _block.Number, + Index = _currentIndex, + GasUsed = spentGas, + Sender = transaction.SenderAddress, + ContractAddress = transaction.IsContractCreation ? recipient : null, + TxHash = transaction.Hash, + PostTransactionState = stateRoot + }; + + return txReceipt; + } - public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) => - _currentTxTracer.StartOperation(depth, gas, opcode, pc, isPostMerge); + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) => + _currentTxTracer.StartOperation(depth, gas, opcode, pc, isPostMerge); - public void ReportOperationError(EvmExceptionType error) => - _currentTxTracer.ReportOperationError(error); + public void ReportOperationError(EvmExceptionType error) => + _currentTxTracer.ReportOperationError(error); - public void ReportOperationRemainingGas(long gas) => - _currentTxTracer.ReportOperationRemainingGas(gas); + public void ReportOperationRemainingGas(long gas) => + _currentTxTracer.ReportOperationRemainingGas(gas); - public void SetOperationMemorySize(ulong newSize) => - _currentTxTracer.SetOperationMemorySize(newSize); + public void SetOperationMemorySize(ulong newSize) => + _currentTxTracer.SetOperationMemorySize(newSize); - public void ReportMemoryChange(long offset, in ReadOnlySpan data) => - _currentTxTracer.ReportMemoryChange(offset, data); + public void ReportMemoryChange(long offset, in ReadOnlySpan data) => + _currentTxTracer.ReportMemoryChange(offset, data); - public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) => - _currentTxTracer.ReportStorageChange(key, value); + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) => + _currentTxTracer.ReportStorageChange(key, value); - public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) => - _currentTxTracer.SetOperationStorage(address, storageIndex, newValue, currentValue); + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) => + _currentTxTracer.SetOperationStorage(address, storageIndex, newValue, currentValue); - public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) => - _currentTxTracer.LoadOperationStorage(address, storageIndex, value); + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) => + _currentTxTracer.LoadOperationStorage(address, storageIndex, value); - public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) => - _currentTxTracer.ReportSelfDestruct(address, balance, refundAddress); + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) => + _currentTxTracer.ReportSelfDestruct(address, balance, refundAddress); - public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) => - _currentTxTracer.ReportBalanceChange(address, before, after); + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) => + _currentTxTracer.ReportBalanceChange(address, before, after); - public void ReportCodeChange(Address address, byte[] before, byte[] after) => - _currentTxTracer.ReportCodeChange(address, before, after); + public void ReportCodeChange(Address address, byte[] before, byte[] after) => + _currentTxTracer.ReportCodeChange(address, before, after); - public void ReportNonceChange(Address address, UInt256? before, UInt256? after) => - _currentTxTracer.ReportNonceChange(address, before, after); + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) => + _currentTxTracer.ReportNonceChange(address, before, after); - public void ReportAccountRead(Address address) => - _currentTxTracer.ReportAccountRead(address); + public void ReportAccountRead(Address address) => + _currentTxTracer.ReportAccountRead(address); - public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) => - _currentTxTracer.ReportStorageChange(storageCell, before, after); + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) => + _currentTxTracer.ReportStorageChange(storageCell, before, after); - public void ReportStorageRead(in StorageCell storageCell) => - _currentTxTracer.ReportStorageRead(storageCell); + public void ReportStorageRead(in StorageCell storageCell) => + _currentTxTracer.ReportStorageRead(storageCell); - public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) => - _currentTxTracer.ReportAction(gas, value, @from, to, input, callType, isPrecompileCall); + public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) => + _currentTxTracer.ReportAction(gas, value, @from, to, input, callType, isPrecompileCall); - public void ReportActionEnd(long gas, ReadOnlyMemory output) => - _currentTxTracer.ReportActionEnd(gas, output); + public void ReportActionEnd(long gas, ReadOnlyMemory output) => + _currentTxTracer.ReportActionEnd(gas, output); - public void ReportActionError(EvmExceptionType exceptionType) => - _currentTxTracer.ReportActionError(exceptionType); + public void ReportActionError(EvmExceptionType exceptionType) => + _currentTxTracer.ReportActionError(exceptionType); - public void ReportActionError(EvmExceptionType exceptionType, long gasLeft) => - _currentTxTracer.ReportActionError(exceptionType, gasLeft); + public void ReportActionError(EvmExceptionType exceptionType, long gasLeft) => + _currentTxTracer.ReportActionError(exceptionType, gasLeft); - public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) => - _currentTxTracer.ReportActionEnd(gas, deploymentAddress, deployedCode); + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) => + _currentTxTracer.ReportActionEnd(gas, deploymentAddress, deployedCode); - public void ReportByteCode(byte[] byteCode) => - _currentTxTracer.ReportByteCode(byteCode); + public void ReportByteCode(byte[] byteCode) => + _currentTxTracer.ReportByteCode(byteCode); - public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) => - _currentTxTracer.ReportGasUpdateForVmTrace(refund, gasAvailable); + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) => + _currentTxTracer.ReportGasUpdateForVmTrace(refund, gasAvailable); - public void ReportRefund(long refund) => - _currentTxTracer.ReportRefund(refund); + public void ReportRefund(long refund) => + _currentTxTracer.ReportRefund(refund); - public void ReportExtraGasPressure(long extraGasPressure) => - _currentTxTracer.ReportExtraGasPressure(extraGasPressure); + public void ReportExtraGasPressure(long extraGasPressure) => + _currentTxTracer.ReportExtraGasPressure(extraGasPressure); - public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) => - _currentTxTracer.ReportAccess(accessedAddresses, accessedStorageCells); + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) => + _currentTxTracer.ReportAccess(accessedAddresses, accessedStorageCells); - public void SetOperationStack(List stackTrace) => - _currentTxTracer.SetOperationStack(stackTrace); + public void SetOperationStack(List stackTrace) => + _currentTxTracer.SetOperationStack(stackTrace); - public void ReportStackPush(in ReadOnlySpan stackItem) => - _currentTxTracer.ReportStackPush(stackItem); + public void ReportStackPush(in ReadOnlySpan stackItem) => + _currentTxTracer.ReportStackPush(stackItem); - public void ReportBlockHash(Keccak blockHash) => - _currentTxTracer.ReportBlockHash(blockHash); + public void ReportBlockHash(Keccak blockHash) => + _currentTxTracer.ReportBlockHash(blockHash); - public void SetOperationMemory(IEnumerable memoryTrace) => - _currentTxTracer.SetOperationMemory(memoryTrace); + public void SetOperationMemory(List memoryTrace) => + _currentTxTracer.SetOperationMemory(memoryTrace); - public void ReportFees(UInt256 fees, UInt256 burntFees) - { - if (_currentTxTracer.IsTracingFees) + public void ReportFees(UInt256 fees, UInt256 burntFees) { - _currentTxTracer.ReportFees(fees, burntFees); + if (_currentTxTracer.IsTracingFees) + { + _currentTxTracer.ReportFees(fees, burntFees); + } } - } - private ITxTracer _currentTxTracer = NullTxTracer.Instance; - private int _currentIndex; - private readonly List _txReceipts = new(); - private Transaction? _currentTx; - public IReadOnlyList TxReceipts => _txReceipts; - public TxReceipt LastReceipt => _txReceipts[^1]; - public bool IsTracingRewards => _otherTracer.IsTracingRewards; + private ITxTracer _currentTxTracer = NullTxTracer.Instance; + private int _currentIndex; + private readonly List _txReceipts = new(); + private Transaction? _currentTx; + public IReadOnlyList TxReceipts => _txReceipts; + public TxReceipt LastReceipt => _txReceipts[^1]; + public bool IsTracingRewards => _otherTracer.IsTracingRewards; - public ITxTracer InnerTracer => _currentTxTracer; + public ITxTracer InnerTracer => _currentTxTracer; - public int TakeSnapshot() => _txReceipts.Count; - public void Restore(int snapshot) - { - int numToRemove = _txReceipts.Count - snapshot; - - for (int i = 0; i < numToRemove; i++) + public int TakeSnapshot() => _txReceipts.Count; + public void Restore(int snapshot) { - _txReceipts.RemoveAt(_txReceipts.Count - 1); - } + int numToRemove = _txReceipts.Count - snapshot; - _block.Header.GasUsed = _txReceipts.Count > 0 ? _txReceipts.Last().GasUsedTotal : 0; - } + for (int i = 0; i < numToRemove; i++) + { + _txReceipts.RemoveAt(_txReceipts.Count - 1); + } + + _block.Header.GasUsed = _txReceipts.Count > 0 ? _txReceipts.Last().GasUsedTotal : 0; + } - public void ReportReward(Address author, string rewardType, UInt256 rewardValue) => - _otherTracer.ReportReward(author, rewardType, rewardValue); + public void ReportReward(Address author, string rewardType, UInt256 rewardValue) => + _otherTracer.ReportReward(author, rewardType, rewardValue); - public void StartNewBlockTrace(Block block) - { - if (_otherTracer is null) + public void StartNewBlockTrace(Block block) { - throw new InvalidOperationException("other tracer not set in receipts tracer"); - } + if (_otherTracer is null) + { + throw new InvalidOperationException("other tracer not set in receipts tracer"); + } - _block = block; - _currentIndex = 0; - _txReceipts.Clear(); + _block = block; + _currentIndex = 0; + _txReceipts.Clear(); - _otherTracer.StartNewBlockTrace(block); - } + _otherTracer.StartNewBlockTrace(block); + } - public ITxTracer StartNewTxTrace(Transaction? tx) - { - _currentTx = tx; - _currentTxTracer = _otherTracer.StartNewTxTrace(tx); - return _currentTxTracer; - } + public ITxTracer StartNewTxTrace(Transaction? tx) + { + _currentTx = tx; + _currentTxTracer = _otherTracer.StartNewTxTrace(tx); + return _currentTxTracer; + } - public void EndTxTrace() - { - _otherTracer.EndTxTrace(); - _currentIndex++; - } + public void EndTxTrace() + { + _otherTracer.EndTxTrace(); + _currentIndex++; + } - public void EndBlockTrace() - { - _otherTracer.EndBlockTrace(); - if (_txReceipts.Count > 0) + public void EndBlockTrace() { - Bloom blockBloom = new(); - _block.Header.Bloom = blockBloom; - for (int index = 0; index < _txReceipts.Count; index++) + _otherTracer.EndBlockTrace(); + if (_txReceipts.Count > 0) { - TxReceipt? receipt = _txReceipts[index]; - blockBloom.Accumulate(receipt.Bloom!); + Bloom blockBloom = new(); + _block.Header.Bloom = blockBloom; + for (var index = 0; index < _txReceipts.Count; index++) + { + var receipt = _txReceipts[index]; + blockBloom.Accumulate(receipt.Bloom!); + } } } - } - public void SetOtherTracer(IBlockTracer blockTracer) - { - _otherTracer = blockTracer; + public void SetOtherTracer(IBlockTracer blockTracer) + { + _otherTracer = blockTracer; + } } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/BlockTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/BlockTracer.cs deleted file mode 100644 index 57b95f564aa..00000000000 --- a/src/Nethermind/Nethermind.Evm/Tracing/BlockTracer.cs +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core; -using Nethermind.Int256; - -namespace Nethermind.Evm.Tracing; - -public abstract class BlockTracer : IBlockTracer -{ - public virtual bool IsTracingRewards => false; - public virtual void ReportReward(Address author, string rewardType, UInt256 rewardValue) { } - public virtual void StartNewBlockTrace(Block block) { } - public abstract ITxTracer StartNewTxTrace(Transaction? tx); - public virtual void EndTxTrace() { } - public virtual void EndBlockTrace() { } -} diff --git a/src/Nethermind/Nethermind.Evm/Tracing/BlockTracerBase.cs b/src/Nethermind/Nethermind.Evm/Tracing/BlockTracerBase.cs index 6926ede8062..34a74ca56d4 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/BlockTracerBase.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/BlockTracerBase.cs @@ -7,70 +7,70 @@ using Nethermind.Core.Resettables; using Nethermind.Int256; -namespace Nethermind.Evm.Tracing; - -public abstract class BlockTracerBase : IBlockTracer where TTracer : class, ITxTracer +namespace Nethermind.Evm.Tracing { - private readonly Keccak? _txHash; - - protected BlockTracerBase() + public abstract class BlockTracerBase : IBlockTracer where TTracer : class, ITxTracer { - TxTraces = new ResettableList(); - } + private readonly Keccak? _txHash; - protected BlockTracerBase(Keccak? txHash) - { - _txHash = txHash; - TxTraces = new ResettableList(); - } + private bool IsTracingEntireBlock => _txHash is null; - private TTracer? CurrentTxTracer { get; set; } + protected BlockTracerBase() + { + TxTraces = new ResettableList(); + } - protected abstract TTracer OnStart(Transaction? tx); - protected abstract TTrace OnEnd(TTracer txTracer); + protected BlockTracerBase(Keccak? txHash) + { + _txHash = txHash; + TxTraces = new ResettableList(); + } - public virtual bool IsTracingRewards => false; + private TTracer? CurrentTxTracer { get; set; } - public virtual void ReportReward(Address author, string rewardType, UInt256 rewardValue) - { - } + protected abstract TTracer OnStart(Transaction? tx); + protected abstract TTrace OnEnd(TTracer txTracer); - public virtual void StartNewBlockTrace(Block block) - { - TxTraces.Reset(); - } + public virtual bool IsTracingRewards => false; - ITxTracer IBlockTracer.StartNewTxTrace(Transaction? tx) - { - if (ShouldTraceTx(tx)) + public virtual void ReportReward(Address author, string rewardType, UInt256 rewardValue) { - CurrentTxTracer = OnStart(tx); - return CurrentTxTracer; } - return NullTxTracer.Instance; - } - - void IBlockTracer.EndTxTrace() - { - if (CurrentTxTracer is null) - return; + public virtual void StartNewBlockTrace(Block block) + { + TxTraces.Reset(); + } - AddTrace(OnEnd(CurrentTxTracer)); + ITxTracer IBlockTracer.StartNewTxTrace(Transaction? tx) + { + if (ShouldTraceTx(tx)) + { + CurrentTxTracer = OnStart(tx); + return CurrentTxTracer; + } - CurrentTxTracer = null; - } + return NullTxTracer.Instance; + } - public virtual void EndBlockTrace() { } + void IBlockTracer.EndTxTrace() + { + if (CurrentTxTracer is not null) + { + TxTraces.Add(OnEnd(CurrentTxTracer)); + CurrentTxTracer = null; + } + } - protected virtual bool ShouldTraceTx(Transaction? tx) - { - return _txHash is null || tx?.Hash == _txHash; - } + public virtual void EndBlockTrace() { } - protected ResettableList TxTraces { get; } + protected virtual bool ShouldTraceTx(Transaction? tx) + { + return IsTracingEntireBlock || tx?.Hash == _txHash; + } - public IReadOnlyCollection BuildResult() => TxTraces; + protected ResettableList TxTraces { get; } - protected virtual void AddTrace(TTrace trace) => TxTraces.Add(trace); + public IReadOnlyCollection BuildResult() => TxTraces; + } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/CallOutputTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/CallOutputTracer.cs index 96b28eaffd0..478911d573a 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/CallOutputTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/CallOutputTracer.cs @@ -1,35 +1,198 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Int256; +using Nethermind.State; namespace Nethermind.Evm.Tracing { - public class CallOutputTracer : TxTracer + public class CallOutputTracer : ITxTracer { - public override bool IsTracingReceipt => true; - public byte[]? ReturnValue { get; set; } + public bool IsTracingReceipt => true; + public bool IsTracingActions => false; + public bool IsTracingOpLevelStorage => false; + public bool IsTracingMemory => false; + public bool IsTracingInstructions => false; + public bool IsTracingRefunds => false; + public bool IsTracingCode => false; + public bool IsTracingStack => false; + public bool IsTracingState => false; + public bool IsTracingStorage => false; + public bool IsTracingBlockHash => false; + public bool IsTracingAccess => false; + public bool IsTracingFees => false; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; + + public byte[] ReturnValue { get; set; } public long GasSpent { get; set; } - public string? Error { get; set; } + public string Error { get; set; } public byte StatusCode { get; set; } - public override void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak stateRoot = null) { GasSpent = gasSpent; ReturnValue = output; StatusCode = Evm.StatusCode.Success; } - public override void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak stateRoot = null) { GasSpent = gasSpent; Error = error; - ReturnValue = output; + ReturnValue = output ?? Array.Empty(); StatusCode = Evm.StatusCode.Failure; } + + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) + { + throw new NotSupportedException(); + } + + public void ReportOperationError(EvmExceptionType error) + { + throw new NotSupportedException(); + } + + public void ReportOperationRemainingGas(long gas) + { + throw new NotSupportedException(); + } + + public void SetOperationStack(List stackTrace) + { + throw new NotSupportedException(); + } + + public void ReportStackPush(in ReadOnlySpan stackItem) + { + throw new NotSupportedException(); + } + + public void SetOperationMemory(List memoryTrace) + { + throw new NotSupportedException(); + } + + public void SetOperationMemorySize(ulong newSize) + { + throw new NotSupportedException(); + } + + public void ReportMemoryChange(long offset, in ReadOnlySpan data) + { + throw new NotSupportedException(); + } + + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) + { + throw new NotSupportedException(); + } + + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) + { + throw new NotSupportedException(); + } + + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) + { + throw new NotSupportedException(); + } + + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) + { + throw new NotSupportedException(); + } + + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) + { + throw new NotSupportedException(); + } + + public void ReportCodeChange(Address address, byte[] before, byte[] after) + { + throw new NotSupportedException(); + } + + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) + { + throw new NotSupportedException(); + } + + public void ReportAccountRead(Address address) + { + throw new NotSupportedException(); + } + + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) + { + throw new NotSupportedException(); + } + + public void ReportStorageRead(in StorageCell storageCell) + { + throw new NotImplementedException(); + } + + public void ReportAction(long gas, UInt256 value, Address from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) + { + throw new NotSupportedException(); + } + + public void ReportActionEnd(long gas, ReadOnlyMemory output) + { + throw new NotSupportedException(); + } + + public void ReportActionError(EvmExceptionType exceptionType) + { + throw new NotSupportedException(); + } + + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) + { + throw new NotSupportedException(); + } + + public void ReportBlockHash(Keccak blockHash) + { + throw new NotSupportedException(); + } + + public void ReportByteCode(byte[] byteCode) + { + throw new NotSupportedException(); + } + + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) + { + throw new NotSupportedException(); + } + + public void ReportRefund(long refund) + { + throw new NotSupportedException(); + } + + public void ReportExtraGasPressure(long extraGasPressure) + { + throw new NotImplementedException(); + } + + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) + { + throw new NotImplementedException(); + } + + public void ReportFees(UInt256 fees, UInt256 burntFees) + { + throw new NotImplementedException(); + } } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/CancellationBlockTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/CancellationBlockTracer.cs index 2fabb220ca2..4ea69996f06 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/CancellationBlockTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/CancellationBlockTracer.cs @@ -3,6 +3,7 @@ using System.Threading; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Int256; namespace Nethermind.Evm.Tracing diff --git a/src/Nethermind/Nethermind.Evm/Tracing/CancellationTxTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/CancellationTxTracer.cs index 83ecbab0e86..58047b538ec 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/CancellationTxTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/CancellationTxTracer.cs @@ -3,438 +3,441 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Int256; -namespace Nethermind.Evm.Tracing; - -public class CancellationTxTracer : ITxTracer, ITxTracerWrapper +namespace Nethermind.Evm.Tracing { - private readonly ITxTracer _innerTracer; - private readonly CancellationToken _token; - private readonly bool _isTracingReceipt; - private readonly bool _isTracingActions; - private readonly bool _isTracingOpLevelStorage; - private readonly bool _isTracingMemory; - private readonly bool _isTracingInstructions; - private readonly bool _isTracingRefunds; - private readonly bool _isTracingCode; - private readonly bool _isTracingStack; - private readonly bool _isTracingState; - private readonly bool _isTracingStorage; - private readonly bool _isTracingBlockHash; - private readonly bool _isTracingBlockAccess; - private readonly bool _isTracingFees; - - public ITxTracer InnerTracer => _innerTracer; - - public CancellationTxTracer(ITxTracer innerTracer, CancellationToken token = default) + public class CancellationTxTracer : ITxTracer, ITxTracerWrapper { - _innerTracer = innerTracer; - _token = token; - } + private readonly ITxTracer _innerTracer; + private readonly CancellationToken _token; + private readonly bool _isTracingReceipt; + private readonly bool _isTracingActions; + private readonly bool _isTracingOpLevelStorage; + private readonly bool _isTracingMemory; + private readonly bool _isTracingInstructions; + private readonly bool _isTracingRefunds; + private readonly bool _isTracingCode; + private readonly bool _isTracingStack; + private readonly bool _isTracingState; + private readonly bool _isTracingStorage; + private readonly bool _isTracingBlockHash; + private readonly bool _isTracingBlockAccess; + private readonly bool _isTracingFees; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; - public bool IsTracingReceipt - { - get => _isTracingReceipt || _innerTracer.IsTracingReceipt; - init => _isTracingReceipt = value; - } + public ITxTracer InnerTracer => _innerTracer; - public bool IsTracingActions - { - get => _isTracingActions || _innerTracer.IsTracingActions; - init => _isTracingActions = value; - } + public CancellationTxTracer(ITxTracer innerTracer, CancellationToken token = default) + { + _innerTracer = innerTracer; + _token = token; + } - public bool IsTracingOpLevelStorage - { - get => _isTracingOpLevelStorage || _innerTracer.IsTracingOpLevelStorage; - init => _isTracingOpLevelStorage = value; - } + public bool IsTracingReceipt + { + get => _isTracingReceipt || _innerTracer.IsTracingReceipt; + init => _isTracingReceipt = value; + } - public bool IsTracingMemory - { - get => _isTracingMemory || _innerTracer.IsTracingMemory; - init => _isTracingMemory = value; - } + public bool IsTracingActions + { + get => _isTracingActions || _innerTracer.IsTracingActions; + init => _isTracingActions = value; + } - public bool IsTracingInstructions - { - get => _isTracingInstructions || _innerTracer.IsTracingInstructions; - init => _isTracingInstructions = value; - } + public bool IsTracingOpLevelStorage + { + get => _isTracingOpLevelStorage || _innerTracer.IsTracingOpLevelStorage; + init => _isTracingOpLevelStorage = value; + } - public bool IsTracingRefunds - { - get => _isTracingRefunds || _innerTracer.IsTracingRefunds; - init => _isTracingRefunds = value; - } + public bool IsTracingMemory + { + get => _isTracingMemory || _innerTracer.IsTracingMemory; + init => _isTracingMemory = value; + } - public bool IsTracingCode - { - get => _isTracingCode || _innerTracer.IsTracingCode; - init => _isTracingCode = value; - } + public bool IsTracingInstructions + { + get => _isTracingInstructions || _innerTracer.IsTracingInstructions; + init => _isTracingInstructions = value; + } - public bool IsTracingStack - { - get => _isTracingStack || _innerTracer.IsTracingStack; - init => _isTracingStack = value; - } + public bool IsTracingRefunds + { + get => _isTracingRefunds || _innerTracer.IsTracingRefunds; + init => _isTracingRefunds = value; + } - public bool IsTracingState - { - get => _isTracingState || _innerTracer.IsTracingState; - init => _isTracingState = value; - } + public bool IsTracingCode + { + get => _isTracingCode || _innerTracer.IsTracingCode; + init => _isTracingCode = value; + } - public bool IsTracingStorage - { - get => _isTracingStorage || _innerTracer.IsTracingStorage; - init => _isTracingStorage = value; - } + public bool IsTracingStack + { + get => _isTracingStack || _innerTracer.IsTracingStack; + init => _isTracingStack = value; + } - public bool IsTracingBlockHash - { - get => _isTracingBlockHash || _innerTracer.IsTracingBlockHash; - init => _isTracingBlockHash = value; - } + public bool IsTracingState + { + get => _isTracingState || _innerTracer.IsTracingState; + init => _isTracingState = value; + } - public bool IsTracingAccess - { - get => _isTracingBlockAccess || _innerTracer.IsTracingAccess; - init => _isTracingBlockAccess = value; - } + public bool IsTracingStorage + { + get => _isTracingStorage || _innerTracer.IsTracingStorage; + init => _isTracingStorage = value; + } - public bool IsTracingFees - { - get => _isTracingFees || _innerTracer.IsTracingFees; - init => _isTracingFees = value; - } + public bool IsTracingBlockHash + { + get => _isTracingBlockHash || _innerTracer.IsTracingBlockHash; + init => _isTracingBlockHash = value; + } - public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingState) + public bool IsTracingAccess { - _innerTracer.ReportBalanceChange(address, before, after); + get => _isTracingBlockAccess || _innerTracer.IsTracingAccess; + init => _isTracingBlockAccess = value; } - } - public void ReportCodeChange(Address address, byte[] before, byte[] after) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingState) + public bool IsTracingFees { - _innerTracer.ReportCodeChange(address, before, after); + get => _isTracingFees || _innerTracer.IsTracingFees; + init => _isTracingFees = value; } - } - public void ReportNonceChange(Address address, UInt256? before, UInt256? after) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingState) + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) { - _innerTracer.ReportNonceChange(address, before, after); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingState) + { + _innerTracer.ReportBalanceChange(address, before, after); + } } - } - public void ReportAccountRead(Address address) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingState) + public void ReportCodeChange(Address address, byte[] before, byte[] after) { - _innerTracer.ReportAccountRead(address); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingState) + { + _innerTracer.ReportCodeChange(address, before, after); + } } - } - public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingStorage) + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) { - _innerTracer.ReportStorageChange(storageCell, before, after); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingState) + { + _innerTracer.ReportNonceChange(address, before, after); + } } - } - public void ReportStorageRead(in StorageCell storageCell) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingStorage) + public void ReportAccountRead(Address address) { - _innerTracer.ReportStorageRead(storageCell); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingState) + { + _innerTracer.ReportAccountRead(address); + } } - } - public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingReceipt) + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) { - _innerTracer.MarkAsSuccess(recipient, gasSpent, output, logs, stateRoot); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingStorage) + { + _innerTracer.ReportStorageChange(storageCell, before, after); + } } - } - public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingReceipt) + public void ReportStorageRead(in StorageCell storageCell) { - _innerTracer.MarkAsFailed(recipient, gasSpent, output, error, stateRoot); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingStorage) + { + _innerTracer.ReportStorageRead(storageCell); + } } - } - public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingInstructions) + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) { - _innerTracer.StartOperation(depth, gas, opcode, pc, isPostMerge); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingReceipt) + { + _innerTracer.MarkAsSuccess(recipient, gasSpent, output, logs, stateRoot); + } } - } - public void ReportOperationError(EvmExceptionType error) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingInstructions) + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) { - _innerTracer.ReportOperationError(error); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingReceipt) + { + _innerTracer.MarkAsFailed(recipient, gasSpent, output, error, stateRoot); + } } - } - public void ReportOperationRemainingGas(long gas) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingInstructions) + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) { - _innerTracer.ReportOperationRemainingGas(gas); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingInstructions) + { + _innerTracer.StartOperation(depth, gas, opcode, pc, isPostMerge); + } } - } - public void SetOperationStack(List stackTrace) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingStack) + public void ReportOperationError(EvmExceptionType error) { - _innerTracer.SetOperationStack(stackTrace); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingInstructions) + { + _innerTracer.ReportOperationError(error); + } } - } - public void ReportStackPush(in ReadOnlySpan stackItem) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingInstructions) + public void ReportOperationRemainingGas(long gas) { - _innerTracer.ReportStackPush(stackItem); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingInstructions) + { + _innerTracer.ReportOperationRemainingGas(gas); + } } - } - public void ReportStackPush(in ZeroPaddedSpan stackItem) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingInstructions) + public void SetOperationStack(List stackTrace) { - _innerTracer.ReportStackPush(stackItem); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingStack) + { + _innerTracer.SetOperationStack(stackTrace); + } } - } - public void ReportStackPush(byte stackItem) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingInstructions) + public void ReportStackPush(in ReadOnlySpan stackItem) { - _innerTracer.ReportStackPush(stackItem); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingInstructions) + { + _innerTracer.ReportStackPush(stackItem); + } } - } - public void SetOperationMemory(IEnumerable memoryTrace) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingMemory) + public void ReportStackPush(in ZeroPaddedSpan stackItem) { - _innerTracer.SetOperationMemory(memoryTrace); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingInstructions) + { + _innerTracer.ReportStackPush(stackItem); + } } - } - public void SetOperationMemorySize(ulong newSize) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingMemory) + public void ReportStackPush(byte stackItem) { - _innerTracer.SetOperationMemorySize(newSize); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingInstructions) + { + _innerTracer.ReportStackPush(stackItem); + } } - } - public void ReportMemoryChange(long offset, in ReadOnlySpan data) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingInstructions) + public void SetOperationMemory(List memoryTrace) { - _innerTracer.ReportMemoryChange(offset, data); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingMemory) + { + _innerTracer.SetOperationMemory(memoryTrace); + } } - } - public void ReportMemoryChange(long offset, in ZeroPaddedSpan data) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingInstructions) + public void SetOperationMemorySize(ulong newSize) { - _innerTracer.ReportMemoryChange(offset, data); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingMemory) + { + _innerTracer.SetOperationMemorySize(newSize); + } } - } - public void ReportMemoryChange(long offset, byte data) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingInstructions) + public void ReportMemoryChange(long offset, in ReadOnlySpan data) { - _innerTracer.ReportMemoryChange(offset, data); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingInstructions) + { + _innerTracer.ReportMemoryChange(offset, data); + } } - } - public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingInstructions) + public void ReportMemoryChange(long offset, in ZeroPaddedSpan data) { - _innerTracer.ReportStorageChange(key, value); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingInstructions) + { + _innerTracer.ReportMemoryChange(offset, data); + } } - } - public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingOpLevelStorage) + public void ReportMemoryChange(long offset, byte data) { - _innerTracer.SetOperationStorage(address, storageIndex, newValue, currentValue); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingInstructions) + { + _innerTracer.ReportMemoryChange(offset, data); + } } - } - public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingOpLevelStorage) + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) { - _innerTracer.LoadOperationStorage(address, storageIndex, value); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingInstructions) + { + _innerTracer.ReportStorageChange(key, value); + } } - } - public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingActions) + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) { - _innerTracer.ReportSelfDestruct(address, balance, refundAddress); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingOpLevelStorage) + { + _innerTracer.SetOperationStorage(address, storageIndex, newValue, currentValue); + } } - } - public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingActions) + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) { - _innerTracer.ReportAction(gas, value, @from, to, input, callType, isPrecompileCall); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingOpLevelStorage) + { + _innerTracer.LoadOperationStorage(address, storageIndex, value); + } } - } - public void ReportActionEnd(long gas, ReadOnlyMemory output) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingActions) + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) { - _innerTracer.ReportActionEnd(gas, output); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingActions) + { + _innerTracer.ReportSelfDestruct(address, balance, refundAddress); + } } - } - public void ReportActionError(EvmExceptionType evmExceptionType) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingActions) + public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) { - _innerTracer.ReportActionError(evmExceptionType); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingActions) + { + _innerTracer.ReportAction(gas, value, @from, to, input, callType, isPrecompileCall); + } } - } - public void ReportActionError(EvmExceptionType evmExceptionType, long gasLeft) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingActions) + public void ReportActionEnd(long gas, ReadOnlyMemory output) { - _innerTracer.ReportActionError(evmExceptionType, gasLeft); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingActions) + { + _innerTracer.ReportActionEnd(gas, output); + } } - } - public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingActions) + public void ReportActionError(EvmExceptionType evmExceptionType) { - _innerTracer.ReportActionEnd(gas, deploymentAddress, deployedCode); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingActions) + { + _innerTracer.ReportActionError(evmExceptionType); + } } - } - public void ReportBlockHash(Keccak blockHash) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingBlockHash) + public void ReportActionError(EvmExceptionType evmExceptionType, long gasLeft) { - _innerTracer.ReportBlockHash(blockHash); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingActions) + { + _innerTracer.ReportActionError(evmExceptionType, gasLeft); + } } - } - public void ReportByteCode(byte[] byteCode) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingCode) + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) { - _innerTracer.ReportByteCode(byteCode); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingActions) + { + _innerTracer.ReportActionEnd(gas, deploymentAddress, deployedCode); + } } - } - public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingInstructions) + public void ReportBlockHash(Keccak blockHash) { - _innerTracer.ReportGasUpdateForVmTrace(refund, gasAvailable); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingBlockHash) + { + _innerTracer.ReportBlockHash(blockHash); + } } - } - public void ReportRefund(long refund) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingRefunds) + public void ReportByteCode(byte[] byteCode) { - _innerTracer.ReportRefund(refund); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingCode) + { + _innerTracer.ReportByteCode(byteCode); + } } - } - public void ReportExtraGasPressure(long extraGasPressure) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingRefunds) + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) { - _innerTracer.ReportExtraGasPressure(extraGasPressure); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingInstructions) + { + _innerTracer.ReportGasUpdateForVmTrace(refund, gasAvailable); + } } - } - public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingAccess) + public void ReportRefund(long refund) { - _innerTracer.ReportAccess(accessedAddresses, accessedStorageCells); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingRefunds) + { + _innerTracer.ReportRefund(refund); + } } - } - public void ReportFees(UInt256 fees, UInt256 burntFees) - { - _token.ThrowIfCancellationRequested(); - if (_innerTracer.IsTracingFees) + public void ReportExtraGasPressure(long extraGasPressure) + { + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingRefunds) + { + _innerTracer.ReportExtraGasPressure(extraGasPressure); + } + } + + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) + { + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingAccess) + { + _innerTracer.ReportAccess(accessedAddresses, accessedStorageCells); + } + } + + public void ReportFees(UInt256 fees, UInt256 burntFees) { - _innerTracer.ReportFees(fees, burntFees); + _token.ThrowIfCancellationRequested(); + if (_innerTracer.IsTracingFees) + { + _innerTracer.ReportFees(fees, burntFees); + } } } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/CompositeBlockTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/CompositeBlockTracer.cs index 50ad0315993..60c6f1d6ac6 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/CompositeBlockTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/CompositeBlockTracer.cs @@ -2,15 +2,17 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Int256; namespace Nethermind.Evm.Tracing { public class CompositeBlockTracer : IBlockTracer, ITracerBag { - private readonly List _childTracers = new(); + private readonly List _childTracers = new List(); public bool IsTracingRewards { get; private set; } public CompositeBlockTracer() diff --git a/src/Nethermind/Nethermind.Evm/Tracing/CompositeTxTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/CompositeTxTracer.cs index dcaff07c657..306863545ac 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/CompositeTxTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/CompositeTxTracer.cs @@ -7,480 +7,482 @@ using Nethermind.Core.Crypto; using Nethermind.Int256; -namespace Nethermind.Evm.Tracing; - -public class CompositeTxTracer : ITxTracer +namespace Nethermind.Evm.Tracing { - internal readonly IList _txTracers; - - public CompositeTxTracer(params ITxTracer[] txTracers) : this((IList)txTracers) + public class CompositeTxTracer : ITxTracer { - } + internal readonly IList _txTracers; - public CompositeTxTracer(IList txTracers) - { - _txTracers = txTracers; - for (int index = 0; index < txTracers.Count; index++) - { - ITxTracer t = txTracers[index]; - IsTracingState |= t.IsTracingState; - IsTracingReceipt |= t.IsTracingReceipt; - IsTracingActions |= t.IsTracingActions; - IsTracingOpLevelStorage |= t.IsTracingOpLevelStorage; - IsTracingMemory |= t.IsTracingMemory; - IsTracingInstructions |= t.IsTracingInstructions; - IsTracingRefunds |= t.IsTracingRefunds; - IsTracingCode |= t.IsTracingCode; - IsTracingStack |= t.IsTracingStack; - IsTracingBlockHash |= t.IsTracingBlockHash; - IsTracingStorage |= t.IsTracingStorage; - IsTracingAccess |= t.IsTracingAccess; - IsTracingFees |= t.IsTracingFees; + public CompositeTxTracer(params ITxTracer[] txTracers) : this((IList)txTracers) + { } - } - public bool IsTracingState { get; } - public bool IsTracingStorage { get; } - public bool IsTracingReceipt { get; } - public bool IsTracingActions { get; } - public bool IsTracingOpLevelStorage { get; } - public bool IsTracingMemory { get; } - public bool IsTracingInstructions { get; } - public bool IsTracingRefunds { get; } - public bool IsTracingCode { get; } - public bool IsTracingStack { get; } - public bool IsTracingBlockHash { get; } - public bool IsTracingAccess { get; } - public bool IsTracingFees { get; } - - public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) - { - for (int index = 0; index < _txTracers.Count; index++) + public CompositeTxTracer(IList txTracers) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingState) + _txTracers = txTracers; + for (int index = 0; index < txTracers.Count; index++) { - innerTracer.ReportBalanceChange(address, before, after); + ITxTracer t = txTracers[index]; + IsTracingState |= t.IsTracingState; + IsTracingReceipt |= t.IsTracingReceipt; + IsTracingActions |= t.IsTracingActions; + IsTracingOpLevelStorage |= t.IsTracingOpLevelStorage; + IsTracingMemory |= t.IsTracingMemory; + IsTracingInstructions |= t.IsTracingInstructions; + IsTracingRefunds |= t.IsTracingRefunds; + IsTracingCode |= t.IsTracingCode; + IsTracingStack |= t.IsTracingStack; + IsTracingBlockHash |= t.IsTracingBlockHash; + IsTracingStorage |= t.IsTracingStorage; + IsTracingAccess |= t.IsTracingAccess; + IsTracingFees |= t.IsTracingFees; } } - } - public void ReportCodeChange(Address address, byte[] before, byte[] after) - { - for (int index = 0; index < _txTracers.Count; index++) + public bool IsTracingState { get; } + public bool IsTracingStorage { get; } + public bool IsTracingReceipt { get; } + public bool IsTracingActions { get; } + public bool IsTracingOpLevelStorage { get; } + public bool IsTracingMemory { get; } + public bool IsTracingInstructions { get; } + public bool IsTracingRefunds { get; } + public bool IsTracingCode { get; } + public bool IsTracingStack { get; } + public bool IsTracingBlockHash { get; } + public bool IsTracingAccess { get; } + public bool IsTracingFees { get; } + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; + + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingState) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportCodeChange(address, before, after); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingState) + { + innerTracer.ReportBalanceChange(address, before, after); + } } } - } - public void ReportNonceChange(Address address, UInt256? before, UInt256? after) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportCodeChange(Address address, byte[] before, byte[] after) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingState) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportNonceChange(address, before, after); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingState) + { + innerTracer.ReportCodeChange(address, before, after); + } } } - } - public void ReportAccountRead(Address address) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingState) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportAccountRead(address); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingState) + { + innerTracer.ReportNonceChange(address, before, after); + } } } - } - public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportAccountRead(Address address) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingStorage) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportStorageChange(storageCell, before, after); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingState) + { + innerTracer.ReportAccountRead(address); + } } } - } - public void ReportStorageRead(in StorageCell storageCell) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingStorage) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportStorageRead(storageCell); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingStorage) + { + innerTracer.ReportStorageChange(storageCell, before, after); + } } } - } - public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportStorageRead(in StorageCell storageCell) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingReceipt) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.MarkAsSuccess(recipient, gasSpent, output, logs, stateRoot); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingStorage) + { + innerTracer.ReportStorageRead(storageCell); + } } } - } - public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) - { - for (int index = 0; index < _txTracers.Count; index++) + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingReceipt) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.MarkAsFailed(recipient, gasSpent, output, error, stateRoot); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingReceipt) + { + innerTracer.MarkAsSuccess(recipient, gasSpent, output, logs, stateRoot); + } } } - } - public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) - { - for (int index = 0; index < _txTracers.Count; index++) + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingInstructions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.StartOperation(depth, gas, opcode, pc, isPostMerge); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingReceipt) + { + innerTracer.MarkAsFailed(recipient, gasSpent, output, error, stateRoot); + } } } - } - public void ReportOperationError(EvmExceptionType error) - { - for (int index = 0; index < _txTracers.Count; index++) + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingInstructions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportOperationError(error); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingInstructions) + { + innerTracer.StartOperation(depth, gas, opcode, pc, isPostMerge); + } } } - } - public void ReportOperationRemainingGas(long gas) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportOperationError(EvmExceptionType error) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingInstructions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportOperationRemainingGas(gas); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingInstructions) + { + innerTracer.ReportOperationError(error); + } } } - } - public void SetOperationStack(List stackTrace) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportOperationRemainingGas(long gas) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingStack) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.SetOperationStack(stackTrace); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingInstructions) + { + innerTracer.ReportOperationRemainingGas(gas); + } } } - } - public void ReportStackPush(in ReadOnlySpan stackItem) - { - for (int index = 0; index < _txTracers.Count; index++) + public void SetOperationStack(List stackTrace) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingInstructions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportStackPush(stackItem); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingStack) + { + innerTracer.SetOperationStack(stackTrace); + } } } - } - public void ReportStackPush(in ZeroPaddedSpan stackItem) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportStackPush(in ReadOnlySpan stackItem) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingInstructions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportStackPush(stackItem); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingInstructions) + { + innerTracer.ReportStackPush(stackItem); + } } } - } - public void ReportStackPush(byte stackItem) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportStackPush(in ZeroPaddedSpan stackItem) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingInstructions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportStackPush(stackItem); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingInstructions) + { + innerTracer.ReportStackPush(stackItem); + } } } - } - public void SetOperationMemory(IEnumerable memoryTrace) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportStackPush(byte stackItem) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingMemory) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.SetOperationMemory(memoryTrace); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingInstructions) + { + innerTracer.ReportStackPush(stackItem); + } } } - } - public void SetOperationMemorySize(ulong newSize) - { - for (int index = 0; index < _txTracers.Count; index++) + public void SetOperationMemory(List memoryTrace) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingMemory) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.SetOperationMemorySize(newSize); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingMemory) + { + innerTracer.SetOperationMemory(memoryTrace); + } } } - } - public void ReportMemoryChange(long offset, in ReadOnlySpan data) - { - for (int index = 0; index < _txTracers.Count; index++) + public void SetOperationMemorySize(ulong newSize) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingInstructions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportMemoryChange(offset, data); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingMemory) + { + innerTracer.SetOperationMemorySize(newSize); + } } } - } - public void ReportMemoryChange(long offset, in ZeroPaddedSpan data) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportMemoryChange(long offset, in ReadOnlySpan data) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingInstructions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportMemoryChange(offset, data); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingInstructions) + { + innerTracer.ReportMemoryChange(offset, data); + } } } - } - public void ReportMemoryChange(long offset, byte data) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportMemoryChange(long offset, in ZeroPaddedSpan data) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingInstructions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportMemoryChange(offset, data); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingInstructions) + { + innerTracer.ReportMemoryChange(offset, data); + } } } - } - public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportMemoryChange(long offset, byte data) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingInstructions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportStorageChange(key, value); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingInstructions) + { + innerTracer.ReportMemoryChange(offset, data); + } } } - } - public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingOpLevelStorage) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.SetOperationStorage(address, storageIndex, newValue, currentValue); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingInstructions) + { + innerTracer.ReportStorageChange(key, value); + } } } - } - public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) - { - for (int index = 0; index < _txTracers.Count; index++) + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingOpLevelStorage) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.LoadOperationStorage(address, storageIndex, value); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingOpLevelStorage) + { + innerTracer.SetOperationStorage(address, storageIndex, newValue, currentValue); + } } } - } - public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) - { - for (int index = 0; index < _txTracers.Count; index++) + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingActions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportSelfDestruct(address, balance, refundAddress); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingOpLevelStorage) + { + innerTracer.LoadOperationStorage(address, storageIndex, value); + } } } - } - public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingActions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportAction(gas, value, @from, to, input, callType, isPrecompileCall); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingActions) + { + innerTracer.ReportSelfDestruct(address, balance, refundAddress); + } } } - } - public void ReportActionEnd(long gas, ReadOnlyMemory output) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingActions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportActionEnd(gas, output); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingActions) + { + innerTracer.ReportAction(gas, value, @from, to, input, callType, isPrecompileCall); + } } } - } - public void ReportActionError(EvmExceptionType evmExceptionType) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportActionEnd(long gas, ReadOnlyMemory output) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingActions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportActionError(evmExceptionType); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingActions) + { + innerTracer.ReportActionEnd(gas, output); + } } } - } - public void ReportActionError(EvmExceptionType evmExceptionType, long gasLeft) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportActionError(EvmExceptionType evmExceptionType) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingActions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportActionError(evmExceptionType, gasLeft); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingActions) + { + innerTracer.ReportActionError(evmExceptionType); + } } } - } - public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportActionError(EvmExceptionType evmExceptionType, long gasLeft) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingActions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportActionEnd(gas, deploymentAddress, deployedCode); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingActions) + { + innerTracer.ReportActionError(evmExceptionType, gasLeft); + } } } - } - public void ReportBlockHash(Keccak blockHash) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingBlockHash) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportBlockHash(blockHash); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingActions) + { + innerTracer.ReportActionEnd(gas, deploymentAddress, deployedCode); + } } } - } - public void ReportByteCode(byte[] byteCode) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportBlockHash(Keccak blockHash) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingCode) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportByteCode(byteCode); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingBlockHash) + { + innerTracer.ReportBlockHash(blockHash); + } } } - } - public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportByteCode(byte[] byteCode) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingInstructions) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportGasUpdateForVmTrace(refund, gasAvailable); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingCode) + { + innerTracer.ReportByteCode(byteCode); + } } } - } - public void ReportRefund(long refund) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingRefunds) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportRefund(refund); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingInstructions) + { + innerTracer.ReportGasUpdateForVmTrace(refund, gasAvailable); + } } } - } - public void ReportExtraGasPressure(long extraGasPressure) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportRefund(long refund) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingRefunds) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportExtraGasPressure(extraGasPressure); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingRefunds) + { + innerTracer.ReportRefund(refund); + } } } - } - public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportExtraGasPressure(long extraGasPressure) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingAccess) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportAccess(accessedAddresses, accessedStorageCells); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingRefunds) + { + innerTracer.ReportExtraGasPressure(extraGasPressure); + } } } - } - public void ReportFees(UInt256 fees, UInt256 burntFees) - { - for (int index = 0; index < _txTracers.Count; index++) + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) + { + for (int index = 0; index < _txTracers.Count; index++) + { + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingAccess) + { + innerTracer.ReportAccess(accessedAddresses, accessedStorageCells); + } + } + } + + public void ReportFees(UInt256 fees, UInt256 burntFees) { - ITxTracer innerTracer = _txTracers[index]; - if (innerTracer.IsTracingFees) + for (int index = 0; index < _txTracers.Count; index++) { - innerTracer.ReportFees(fees, burntFees); + ITxTracer innerTracer = _txTracers[index]; + if (innerTracer.IsTracingFees) + { + innerTracer.ReportFees(fees, burntFees); + } } } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs index 22b7e3d10ed..6cf0aa5cd2f 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/Debugger/DebugTracer.cs @@ -4,63 +4,71 @@ #if DEBUG using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; using System.Threading; +using System.Threading.Tasks; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Int256; +using Nethermind.State; +using Nethermind.State.Tracing; -namespace Nethermind.Evm.Tracing.Debugger; - +namespace Nethermind.Evm.Tracing.DebugTrace; public class DebugTracer : ITxTracer, ITxTracerWrapper, IDisposable { - public enum DebugPhase { Starting, Blocked, Running, Aborted } - - private readonly AutoResetEvent _autoResetEvent = new(false); - private readonly Dictionary<(int depth, int pc), Func> _breakPoints = new(); - private Func? _globalBreakCondition; - private readonly object _lock = new(); + public enum DebugPhase + { + Starting, Blocked, Running, Aborted + } public DebugTracer(ITxTracer tracer) { InnerTracer = tracer; } - public event Action? BreakPointReached; - public event Action? ExecutionThreadSet; public ITxTracer InnerTracer { get; private set; } public DebugPhase CurrentPhase { get; private set; } = DebugPhase.Starting; public bool CanReadState => CurrentPhase is DebugPhase.Blocked; - public bool IsStepByStepModeOn { get; set; } - public EvmState? CurrentState { get; set; } - public bool IsTracingReceipt => InnerTracer.IsTracingReceipt; + private AutoResetEvent _autoResetEvent = new AutoResetEvent(false); + + public event Action BreakPointReached; + public event Action ExecutionThreadSet; - public bool IsTracingActions => InnerTracer.IsTracingActions; - public bool IsTracingOpLevelStorage => InnerTracer.IsTracingOpLevelStorage; + public bool IsTracingReceipt => ((ITxTracer)InnerTracer).IsTracingReceipt; - public bool IsTracingMemory => InnerTracer.IsTracingMemory; + public bool IsTracingActions => ((ITxTracer)InnerTracer).IsTracingActions; - public bool IsTracingInstructions => InnerTracer.IsTracingInstructions; + public bool IsTracingOpLevelStorage => ((ITxTracer)InnerTracer).IsTracingOpLevelStorage; - public bool IsTracingRefunds => InnerTracer.IsTracingRefunds; + public bool IsTracingMemory => ((ITxTracer)InnerTracer).IsTracingMemory; - public bool IsTracingCode => InnerTracer.IsTracingCode; + public bool IsTracingInstructions => ((ITxTracer)InnerTracer).IsTracingInstructions; - public bool IsTracingStack => InnerTracer.IsTracingStack; + public bool IsTracingRefunds => ((ITxTracer)InnerTracer).IsTracingRefunds; - public bool IsTracingBlockHash => InnerTracer.IsTracingBlockHash; + public bool IsTracingCode => ((ITxTracer)InnerTracer).IsTracingCode; - public bool IsTracingAccess => InnerTracer.IsTracingAccess; + public bool IsTracingStack => ((ITxTracer)InnerTracer).IsTracingStack; - public bool IsTracingFees => InnerTracer.IsTracingFees; + public bool IsTracingBlockHash => ((ITxTracer)InnerTracer).IsTracingBlockHash; - public bool IsTracingState => InnerTracer.IsTracingState; + public bool IsTracingAccess => ((ITxTracer)InnerTracer).IsTracingAccess; - public bool IsTracingStorage => InnerTracer.IsTracingStorage; + public bool IsTracingFees => ((ITxTracer)InnerTracer).IsTracingFees; - public bool IsBreakpoitnSet(int depth, int programCounter) => _breakPoints.ContainsKey((depth, programCounter)); + public bool IsTracingState => ((IStateTracer)InnerTracer).IsTracingState; + public bool IsTracingStorage => ((IStorageTracer)InnerTracer).IsTracingStorage; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; + + internal Dictionary<(int depth, int pc), Func> _breakPoints = new(); + public bool IsBreakpoitnSet(int depth, int programCounter) + => _breakPoints.ContainsKey((depth, programCounter)); public void SetBreakPoint((int depth, int pc) point, Func condition = null) { if (CurrentPhase is DebugPhase.Blocked or DebugPhase.Starting) @@ -75,12 +83,15 @@ public void UnsetBreakPoint(int depth, int programCounter) _breakPoints.Remove((depth, programCounter)); } } - - public void SetCondtion(Func? condition = null) + private Func _globalBreakCondition = null; + public void SetCondtion(Func condition = null) { if (CurrentPhase is DebugPhase.Blocked or DebugPhase.Starting) _globalBreakCondition = condition; } + private object _lock = new(); + public bool IsStepByStepModeOn { get; set; } = false; + public EvmState CurrentState; public void TryWait(ref EvmState evmState, ref int programCounter, ref long gasAvailable, ref int stackHead) { if (CurrentPhase is DebugPhase.Aborted) @@ -158,11 +169,11 @@ public void MoveNext(bool? executeOneStep = null) public void CheckBreakPoint() { - (int CallDepth, int ProgramCounter) breakpoint = (CurrentState!.Env.CallDepth, CurrentState.ProgramCounter); - - if (_breakPoints.TryGetValue(breakpoint, out Func? point)) + var breakpoint = (CurrentState.Env.CallDepth, CurrentState.ProgramCounter); + if (_breakPoints.ContainsKey(breakpoint)) { - bool conditionResults = point?.Invoke(CurrentState) ?? true; + Func condition = _breakPoints[breakpoint]; + bool conditionResults = condition is null ? true : condition.Invoke(CurrentState); if (conditionResults) { Block(); @@ -186,101 +197,163 @@ public void CheckBreakPoint() } public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) - => InnerTracer.MarkAsSuccess(recipient, gasSpent, output, logs, stateRoot); + { + ((ITxTracer)InnerTracer).MarkAsSuccess(recipient, gasSpent, output, logs, stateRoot); + } public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) - => InnerTracer.MarkAsFailed(recipient, gasSpent, output, error, stateRoot); + { + ((ITxTracer)InnerTracer).MarkAsFailed(recipient, gasSpent, output, error, stateRoot); + } public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) - => InnerTracer.StartOperation(depth, gas, opcode, pc, isPostMerge); + { + ((ITxTracer)InnerTracer).StartOperation(depth, gas, opcode, pc, isPostMerge); + } public void ReportOperationError(EvmExceptionType error) - => InnerTracer.ReportOperationError(error); + { + ((ITxTracer)InnerTracer).ReportOperationError(error); + } public void ReportOperationRemainingGas(long gas) - => InnerTracer.ReportOperationRemainingGas(gas); + { + ((ITxTracer)InnerTracer).ReportOperationRemainingGas(gas); + } public void SetOperationStack(List stackTrace) - => InnerTracer.SetOperationStack(stackTrace); + { + ((ITxTracer)InnerTracer).SetOperationStack(stackTrace); + } public void ReportStackPush(in ReadOnlySpan stackItem) - => InnerTracer.ReportStackPush(stackItem); + { + ((ITxTracer)InnerTracer).ReportStackPush(stackItem); + } - public void SetOperationMemory(IEnumerable memoryTrace) - => InnerTracer.SetOperationMemory(memoryTrace); + public void SetOperationMemory(List memoryTrace) + { + ((ITxTracer)InnerTracer).SetOperationMemory(memoryTrace); + } public void SetOperationMemorySize(ulong newSize) - => InnerTracer.SetOperationMemorySize(newSize); + { + ((ITxTracer)InnerTracer).SetOperationMemorySize(newSize); + } public void ReportMemoryChange(long offset, in ReadOnlySpan data) - => InnerTracer.ReportMemoryChange(offset, data); + { + ((ITxTracer)InnerTracer).ReportMemoryChange(offset, data); + } public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) - => InnerTracer.SetOperationStorage(address, storageIndex, newValue, currentValue); + { + ((ITxTracer)InnerTracer).SetOperationStorage(address, storageIndex, newValue, currentValue); + } public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) - => InnerTracer.LoadOperationStorage(address, storageIndex, value); + { + ((ITxTracer)InnerTracer).LoadOperationStorage(address, storageIndex, value); + } public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) - => InnerTracer.ReportSelfDestruct(address, balance, refundAddress); + { + ((ITxTracer)InnerTracer).ReportSelfDestruct(address, balance, refundAddress); + } public void ReportAction(long gas, UInt256 value, Address from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) - => InnerTracer.ReportAction(gas, value, from, to, input, callType, isPrecompileCall); + { + ((ITxTracer)InnerTracer).ReportAction(gas, value, from, to, input, callType, isPrecompileCall); + } public void ReportActionEnd(long gas, ReadOnlyMemory output) - => InnerTracer.ReportActionEnd(gas, output); + { + ((ITxTracer)InnerTracer).ReportActionEnd(gas, output); + } public void ReportActionError(EvmExceptionType evmExceptionType) - => InnerTracer.ReportActionError(evmExceptionType); + { + ((ITxTracer)InnerTracer).ReportActionError(evmExceptionType); + } public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) - => InnerTracer.ReportActionEnd(gas, deploymentAddress, deployedCode); + { + ((ITxTracer)InnerTracer).ReportActionEnd(gas, deploymentAddress, deployedCode); + } public void ReportBlockHash(Keccak blockHash) - => InnerTracer.ReportBlockHash(blockHash); + { + ((ITxTracer)InnerTracer).ReportBlockHash(blockHash); + } public void ReportByteCode(byte[] byteCode) - => InnerTracer.ReportByteCode(byteCode); + { + ((ITxTracer)InnerTracer).ReportByteCode(byteCode); + } public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) - => InnerTracer.ReportGasUpdateForVmTrace(refund, gasAvailable); + { + ((ITxTracer)InnerTracer).ReportGasUpdateForVmTrace(refund, gasAvailable); + } public void ReportRefund(long refund) - => InnerTracer.ReportRefund(refund); + { + ((ITxTracer)InnerTracer).ReportRefund(refund); + } public void ReportExtraGasPressure(long extraGasPressure) - => InnerTracer.ReportExtraGasPressure(extraGasPressure); + { + ((ITxTracer)InnerTracer).ReportExtraGasPressure(extraGasPressure); + } public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) - => InnerTracer.ReportAccess(accessedAddresses, accessedStorageCells); + { + ((ITxTracer)InnerTracer).ReportAccess(accessedAddresses, accessedStorageCells); + } public void ReportFees(UInt256 fees, UInt256 burntFees) - => InnerTracer.ReportFees(fees, burntFees); + { + ((ITxTracer)InnerTracer).ReportFees(fees, burntFees); + } public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) - => InnerTracer.ReportBalanceChange(address, before, after); + { + ((IStateTracer)InnerTracer).ReportBalanceChange(address, before, after); + } public void ReportCodeChange(Address address, byte[]? before, byte[]? after) - => InnerTracer.ReportCodeChange(address, before, after); + { + ((IStateTracer)InnerTracer).ReportCodeChange(address, before, after); + } public void ReportNonceChange(Address address, UInt256? before, UInt256? after) - => InnerTracer.ReportNonceChange(address, before, after); + { + ((IStateTracer)InnerTracer).ReportNonceChange(address, before, after); + } public void ReportAccountRead(Address address) - => InnerTracer.ReportAccountRead(address); + { + ((IStateTracer)InnerTracer).ReportAccountRead(address); + } public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) - => InnerTracer.ReportStorageChange(key, value); + { + ((IStorageTracer)InnerTracer).ReportStorageChange(key, value); + } public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) - => InnerTracer.ReportStorageChange(storageCell, before, after); + { + ((IStorageTracer)InnerTracer).ReportStorageChange(storageCell, before, after); + } public void ReportStorageRead(in StorageCell storageCell) - => InnerTracer.ReportStorageRead(storageCell); + { + ((IStorageTracer)InnerTracer).ReportStorageRead(storageCell); + } public void Dispose() { - _autoResetEvent.Dispose(); + _autoResetEvent?.Dispose(); } } #endif diff --git a/src/Nethermind/Nethermind.Evm/Tracing/EstimateGasTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/EstimateGasTracer.cs index 76ca66c480b..a2bc2186853 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/EstimateGasTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/EstimateGasTracer.cs @@ -6,43 +6,56 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; +using Nethermind.State; namespace Nethermind.Evm.Tracing { - public class EstimateGasTracer : TxTracer + public class EstimateGasTracer : ITxTracer { public EstimateGasTracer() { _currentGasAndNesting.Push(new GasAndNesting(0, -1)); } - public override bool IsTracingReceipt => true; - public override bool IsTracingActions => true; - public override bool IsTracingRefunds => true; - - public byte[]? ReturnValue { get; set; } - - private long NonIntrinsicGasSpentBeforeRefund { get; set; } + public bool IsTracingReceipt => true; + public bool IsTracingActions => true; + public bool IsTracingOpLevelStorage => false; + public bool IsTracingMemory => false; + public bool IsTracingInstructions => false; + public bool IsTracingRefunds => true; + public bool IsTracingCode => false; + public bool IsTracingStack => false; + public bool IsTracingState => false; + public bool IsTracingStorage => false; + public bool IsTracingBlockHash => false; + public bool IsTracingAccess => false; + public bool IsTracingFees => false; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; + + public byte[] ReturnValue { get; set; } + + internal long NonIntrinsicGasSpentBeforeRefund { get; set; } internal long GasSpent { get; set; } internal long IntrinsicGasAt { get; set; } - private long TotalRefund { get; set; } + internal long TotalRefund { get; set; } - public string? Error { get; set; } + public string Error { get; set; } public byte StatusCode { get; set; } - public override void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) { GasSpent = gasSpent; ReturnValue = output; StatusCode = Evm.StatusCode.Success; } - public override void MarkAsFailed(Address recipient, long gasSpent, byte[]? output, string error, Keccak? stateRoot = null) + public void MarkAsFailed(Address recipient, long gasSpent, byte[]? output, string error, Keccak? stateRoot = null) { GasSpent = gasSpent; Error = error; @@ -50,6 +63,95 @@ public override void MarkAsFailed(Address recipient, long gasSpent, byte[]? outp StatusCode = Evm.StatusCode.Failure; } + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) + { + throw new NotSupportedException(); + } + + public void ReportOperationError(EvmExceptionType error) + { + throw new NotSupportedException(); + } + + public void ReportOperationRemainingGas(long gas) + { + throw new NotSupportedException(); + } + + public void SetOperationStack(List stackTrace) + { + throw new NotSupportedException(); + } + + public void ReportStackPush(in ReadOnlySpan stackItem) + { + throw new NotSupportedException(); + } + + public void SetOperationMemory(List memoryTrace) + { + throw new NotSupportedException(); + } + + public void SetOperationMemorySize(ulong newSize) + { + throw new NotSupportedException(); + } + + public void ReportMemoryChange(long offset, in ReadOnlySpan data) + { + throw new NotSupportedException(); + } + + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) + { + throw new NotSupportedException(); + } + + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) + { + throw new NotSupportedException(); + } + + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) + { + throw new NotSupportedException(); + } + + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) + { + } + + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) + { + throw new NotSupportedException(); + } + + public void ReportCodeChange(Address address, byte[] before, byte[] after) + { + throw new NotSupportedException(); + } + + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) + { + throw new NotSupportedException(); + } + + public void ReportAccountRead(Address address) + { + throw new NotSupportedException(); + } + + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) + { + throw new NotSupportedException(); + } + + public void ReportStorageRead(in StorageCell storageCell) + { + throw new NotSupportedException(); + } + private class GasAndNesting { public GasAndNesting(long gasOnStart, int nestingLevel) @@ -91,9 +193,9 @@ internal long CalculateAdditionalGasRequired(Transaction tx, IReleaseSpec releas private bool _isInPrecompile; - private readonly Stack _currentGasAndNesting = new(); + private Stack _currentGasAndNesting = new(); - public override void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) + public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) { if (_currentNestingLevel == -1) { @@ -111,7 +213,7 @@ public override void ReportAction(long gas, UInt256 value, Address @from, Addres } } - public override void ReportActionEnd(long gas, ReadOnlyMemory output) + public void ReportActionEnd(long gas, ReadOnlyMemory output) { if (!_isInPrecompile) { @@ -123,7 +225,7 @@ public override void ReportActionEnd(long gas, ReadOnlyMemory output) } } - public override void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) { if (!_isInPrecompile) { @@ -135,7 +237,7 @@ public override void ReportActionEnd(long gas, Address deploymentAddress, ReadOn } } - public override void ReportActionError(EvmExceptionType exceptionType) + public void ReportActionError(EvmExceptionType exceptionType) { UpdateAdditionalGas(); } @@ -163,14 +265,39 @@ private void UpdateAdditionalGas(long? gasLeft = null) } } - public override void ReportRefund(long refund) + public void ReportBlockHash(Keccak blockHash) + { + throw new NotSupportedException(); + } + + public void ReportByteCode(byte[] byteCode) + { + throw new NotSupportedException(); + } + + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) + { + throw new NotSupportedException(); + } + + public void ReportRefund(long refund) { TotalRefund += refund; } - public override void ReportExtraGasPressure(long extraGasPressure) + public void ReportExtraGasPressure(long extraGasPressure) { _currentGasAndNesting.Peek().ExtraGasPressure = Math.Max(_currentGasAndNesting.Peek().ExtraGasPressure, extraGasPressure); } + + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) + { + throw new NotImplementedException(); + } + + public void ReportFees(UInt256 fees, UInt256 burntFees) + { + throw new NotImplementedException(); + } } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/FeesTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/FeesTracer.cs index cfa5ea57305..3c66d810a0a 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/FeesTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/FeesTracer.cs @@ -1,28 +1,41 @@ // Copyright 2022 Demerzel Solutions Limited // Licensed under the LGPL-3.0. For full terms, see LICENSE-LGPL in the project root. +using System; +using System.Collections.Generic; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Int256; namespace Nethermind.Evm.Tracing; -public class FeesTracer : TxTracer, IBlockTracer +public class FeesTracer : IBlockTracer, ITxTracer { - public override bool IsTracingFees => true; + public bool IsTracingRewards => false; + public bool IsTracingState => false; + public bool IsTracingActions => false; + public bool IsTracingOpLevelStorage => false; + public bool IsTracingMemory => false; + public bool IsTracingInstructions => false; + public bool IsTracingRefunds => false; + public bool IsTracingCode => false; + public bool IsTracingStack => false; + public bool IsTracingBlockHash => false; + public bool IsTracingAccess => false; + public bool IsTracingStorage => false; + public bool IsTracingReceipt => false; + public bool IsTracingFees => true; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; public UInt256 Fees { get; private set; } = UInt256.Zero; public UInt256 BurntFees { get; private set; } = UInt256.Zero; - public override void ReportFees(UInt256 fees, UInt256 burntFees) + public void ReportFees(UInt256 fees, UInt256 burntFees) { Fees += fees; BurntFees += burntFees; } - public bool IsTracingRewards => false; - - public void ReportReward(Address author, string rewardType, UInt256 rewardValue) { } - public void StartNewBlockTrace(Block block) { Fees = UInt256.Zero; @@ -34,4 +47,152 @@ public void StartNewBlockTrace(Block block) public void EndTxTrace() { } public void EndBlockTrace() { } + + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) { } + + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) { } + + public void ReportReward(Address author, string rewardType, UInt256 rewardValue) + { + throw new NotImplementedException(); + } + + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) + { + throw new NotImplementedException(); + } + + public void ReportCodeChange(Address address, byte[]? before, byte[]? after) + { + throw new NotImplementedException(); + } + + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) + { + throw new NotImplementedException(); + } + + public void ReportAccountRead(Address address) + { + throw new NotImplementedException(); + } + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) + { + throw new NotImplementedException(); + } + + public void ReportStorageRead(in StorageCell storageCell) + { + throw new NotImplementedException(); + } + + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) + { + throw new NotImplementedException(); + } + + public void ReportOperationError(EvmExceptionType error) + { + throw new NotImplementedException(); + } + + public void ReportOperationRemainingGas(long gas) + { + throw new NotImplementedException(); + } + + public void SetOperationStack(List stackTrace) + { + throw new NotImplementedException(); + } + + public void ReportStackPush(in ReadOnlySpan stackItem) + { + throw new NotImplementedException(); + } + + public void SetOperationMemory(List memoryTrace) + { + throw new NotImplementedException(); + } + + public void SetOperationMemorySize(ulong newSize) + { + throw new NotImplementedException(); + } + + public void ReportMemoryChange(long offset, in ReadOnlySpan data) + { + throw new NotImplementedException(); + } + + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) + { + throw new NotImplementedException(); + } + + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) + { + throw new NotImplementedException(); + } + + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) + { + throw new NotImplementedException(); + } + + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) + { + throw new NotImplementedException(); + } + + public void ReportAction(long gas, UInt256 value, Address from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) + { + throw new NotImplementedException(); + } + + public void ReportActionEnd(long gas, ReadOnlyMemory output) + { + throw new NotImplementedException(); + } + + public void ReportActionError(EvmExceptionType evmExceptionType) + { + throw new NotImplementedException(); + } + + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) + { + throw new NotImplementedException(); + } + + public void ReportBlockHash(Keccak blockHash) + { + throw new NotImplementedException(); + } + + public void ReportByteCode(byte[] byteCode) + { + throw new NotImplementedException(); + } + + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) + { + throw new NotImplementedException(); + } + + public void ReportRefund(long refund) + { + throw new NotImplementedException(); + } + + public void ReportExtraGasPressure(long extraGasPressure) + { + throw new NotImplementedException(); + } + + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) + { + throw new NotImplementedException(); + } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GasEstimator.cs b/src/Nethermind/Nethermind.Evm/Tracing/GasEstimator.cs index f9e24d2c1d7..aeb16e89c4e 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/GasEstimator.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/GasEstimator.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Threading; +using System.Collections.Generic; +using System.Linq; +using System.Text; using Nethermind.Config; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -29,20 +31,18 @@ public GasEstimator(ITransactionProcessor transactionProcessor, IReadOnlyStatePr _blocksConfig = blocksConfig; } - public long Estimate(Transaction tx, BlockHeader header, EstimateGasTracer gasTracer, CancellationToken token = new()) + public long Estimate(Transaction tx, BlockHeader header, EstimateGasTracer gasTracer) { IReleaseSpec releaseSpec = _specProvider.GetSpec(header.Number + 1, header.Timestamp + _blocksConfig.SecondsPerSlot); - tx.SenderAddress ??= Address.Zero; // If sender is not specified, use zero address. - tx.GasLimit = Math.Min(tx.GasLimit, header.GasLimit); // Limit Gas to the header - - // Calculate and return additional gas required in case of insufficient funds. - UInt256 senderBalance = _stateProvider.GetBalance(tx.SenderAddress); - if (tx.Value != UInt256.Zero && tx.Value >= senderBalance) + long intrinsicGas = tx.GasLimit - gasTracer.IntrinsicGasAt; + if (tx.GasLimit > header.GasLimit) { - return gasTracer.CalculateAdditionalGasRequired(tx, releaseSpec); + return Math.Max(intrinsicGas, gasTracer.GasSpent + gasTracer.CalculateAdditionalGasRequired(tx, releaseSpec)); } + tx.SenderAddress ??= Address.Zero; //If sender is not specified, use zero address. + // Setting boundaries for binary search - determine lowest and highest gas can be used during the estimation: long leftBound = (gasTracer.GasSpent != 0 && gasTracer.GasSpent >= Transaction.BaseTxGasCost) ? gasTracer.GasSpent - 1 @@ -51,17 +51,24 @@ public GasEstimator(ITransactionProcessor transactionProcessor, IReadOnlyStatePr ? tx.GasLimit : header.GasLimit; + UInt256 senderBalance = _stateProvider.GetBalance(tx.SenderAddress); + + // Calculate and return additional gas required in case of insufficient funds. + if (tx.Value != UInt256.Zero && tx.Value >= senderBalance) + { + return gasTracer.CalculateAdditionalGasRequired(tx, releaseSpec); + } + // Execute binary search to find the optimal gas estimation. - return BinarySearchEstimate(leftBound, rightBound, tx, header, token); + return BinarySearchEstimate(leftBound, rightBound, rightBound, tx, header); } - private long BinarySearchEstimate(long leftBound, long rightBound, Transaction tx, BlockHeader header, CancellationToken token) + private long BinarySearchEstimate(long leftBound, long rightBound, long cap, Transaction tx, BlockHeader header) { - long cap = rightBound; while (leftBound + 1 < rightBound) { long mid = (leftBound + rightBound) / 2; - if (!TryExecutableTransaction(tx, header, mid, token)) + if (!TryExecutableTransaction(tx, header, mid)) { leftBound = mid; } @@ -71,7 +78,7 @@ private long BinarySearchEstimate(long leftBound, long rightBound, Transaction t } } - if (rightBound == cap && !TryExecutableTransaction(tx, header, rightBound, token)) + if (rightBound == cap && !TryExecutableTransaction(tx, header, rightBound)) { return 0; } @@ -79,45 +86,186 @@ private long BinarySearchEstimate(long leftBound, long rightBound, Transaction t return rightBound; } - private bool TryExecutableTransaction(Transaction transaction, BlockHeader block, long gasLimit, CancellationToken token) + private bool TryExecutableTransaction(Transaction transaction, BlockHeader block, long gasLimit) { OutOfGasTracer tracer = new(); - - // TODO: Workaround to not mutate the original Tx - long originalGasLimit = transaction.GasLimit; - - transaction.GasLimit = gasLimit; - - BlockExecutionContext blCtx = new(block); - _transactionProcessor.CallAndRestore(transaction, blCtx, tracer.WithCancellation(token)); - - transaction.GasLimit = originalGasLimit; + transaction.GasLimit = (long)gasLimit; + _transactionProcessor.CallAndRestore(transaction, block, tracer); return !tracer.OutOfGas; } - private class OutOfGasTracer : TxTracer + private class OutOfGasTracer : ITxTracer { public OutOfGasTracer() { OutOfGas = false; } - public override bool IsTracingReceipt => true; - public override bool IsTracingInstructions => true; - public bool OutOfGas { get; private set; } + public bool IsTracingReceipt => true; + public bool IsTracingActions => false; + public bool IsTracingOpLevelStorage => false; + public bool IsTracingMemory => false; + public bool IsTracingInstructions => true; + public bool IsTracingRefunds => false; + public bool IsTracingCode => false; + public bool IsTracingStack => false; + public bool IsTracingState => false; + public bool IsTracingStorage => false; + public bool IsTracingBlockHash => false; + public bool IsTracingAccess => false; + public bool IsTracingFees => false; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; + + public bool OutOfGas { get; set; } + + public byte[] ReturnValue { get; set; } + + public byte StatusCode { get; set; } - public override void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak stateRoot = null) { + ReturnValue = output; + StatusCode = Evm.StatusCode.Success; } - public override void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak stateRoot = null) { + ReturnValue = output ?? Array.Empty(); + StatusCode = Evm.StatusCode.Failure; } - public override void ReportOperationError(EvmExceptionType error) + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) + { + } + + public void ReportOperationError(EvmExceptionType error) { OutOfGas |= error == EvmExceptionType.OutOfGas; } + + public void ReportOperationRemainingGas(long gas) + { + } + + public void SetOperationMemorySize(ulong newSize) + { + } + + public void ReportMemoryChange(long offset, in ReadOnlySpan data) + { + } + + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) + { + } + + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) + { + } + + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) + { + } + + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) + { + throw new NotSupportedException(); + } + + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) + { + throw new NotSupportedException(); + } + + public void ReportCodeChange(Address address, byte[] before, byte[] after) + { + throw new NotSupportedException(); + } + + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) + { + throw new NotSupportedException(); + } + + public void ReportAccountRead(Address address) + { + } + + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) + { + throw new NotSupportedException(); + } + + public void ReportStorageRead(in StorageCell storageCell) + { + throw new NotSupportedException(); + } + + public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) + { + throw new NotSupportedException(); + } + + public void ReportActionEnd(long gas, ReadOnlyMemory output) + { + throw new NotSupportedException(); + } + + public void ReportActionError(EvmExceptionType exceptionType) + { + throw new NotSupportedException(); + } + + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) + { + throw new NotSupportedException(); + } + + public void ReportBlockHash(Keccak blockHash) + { + throw new NotSupportedException(); + } + + public void ReportByteCode(byte[] byteCode) + { + throw new NotSupportedException(); + } + + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) + { + } + + public void ReportRefund(long refund) + { + throw new NotSupportedException(); + } + + public void ReportExtraGasPressure(long extraGasPressure) + { + throw new NotSupportedException(); + } + + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) + { + throw new NotSupportedException(); + } + + public void SetOperationStack(List stackTrace) + { + } + + public void ReportStackPush(in ReadOnlySpan stackItem) + { + } + + public void SetOperationMemory(List memoryTrace) + { + } + + public void ReportFees(UInt256 fees, UInt256 burntFees) + { + throw new NotImplementedException(); + } } } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeBlockFileTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeBlockFileTracer.cs deleted file mode 100644 index 3cd36b6339b..00000000000 --- a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeBlockFileTracer.cs +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.Json; -using Nethermind.Core.Crypto; -using Nethermind.Core; -using Nethermind.Core.Extensions; -using System.IO.Abstractions; - -namespace Nethermind.Evm.Tracing.GethStyle; - -public class GethLikeBlockFileTracer : BlockTracerBase -{ - private const string _alphabet = "abcdefghijklmnopqrstuvwxyz0123456789"; - - private readonly Block _block; - private Stream _file; - private readonly string _fileNameFormat; - private readonly List _fileNames = new(); - private IFileSystem _fileSystem; - private Utf8JsonWriter _jsonWriter; - private readonly GethTraceOptions _options; - private readonly JsonSerializerOptions _serializerOptions = new(); - - public GethLikeBlockFileTracer(Block block, GethTraceOptions options, IFileSystem fileSystem) : base(options?.TxHash) - { - _block = block ?? throw new ArgumentNullException(nameof(block)); - _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); - _options = options ?? throw new ArgumentNullException(nameof(options)); - - var hash = _block.Hash.Bytes[..4].ToHexString(true); - - _fileNameFormat = _fileSystem.Path.Combine(_fileSystem.Path.GetTempPath(), $"block_{hash}-{{0}}-{{1}}-{{2}}.jsonl"); - - _serializerOptions.Converters.Add(new GethLikeTxTraceJsonLinesConverter()); - } - - public IReadOnlyCollection FileNames => _fileNames.AsReadOnly(); - - public override void EndBlockTrace() - { - base.EndBlockTrace(); - - DisposeFileStreamIfAny(); - } - - protected override void AddTrace(GethLikeTxTrace trace) { } - - protected override GethLikeTxTrace OnEnd(GethLikeTxFileTracer txTracer) - { - var trace = txTracer.BuildResult(); - - JsonSerializer.Serialize(_jsonWriter, - new - { - output = trace.ReturnValue.ToHexString(true), - gasUsed = $"0x{trace.Gas:x}" - }, - _serializerOptions); - - DisposeFileStreamIfAny(); - - return trace; - } - - protected override GethLikeTxFileTracer OnStart(Transaction? tx) - { - // Ensure the current file stream is disposed in case of API misuse - DisposeFileStreamIfAny(); - - _fileNames.Add(GetFileName(tx.Hash)); - - _file = _fileSystem.File.OpenWrite(_fileNames.Last()); - _jsonWriter = new(_file); - - return new(DumpTraceEntry, _options); - } - - private void DisposeFileStreamIfAny() - { - _jsonWriter?.Dispose(); - _file?.Dispose(); - - _file = null; - _jsonWriter = null; - } - - private void DumpTraceEntry(GethTxFileTraceEntry entry) => JsonSerializer.Serialize(_jsonWriter, entry, _serializerOptions); - - private string GetFileName(Keccak txHash) - { - var hash = txHash.Bytes[..4].ToHexString(true); - var index = 0; - var suffix = string.Create(8, Random.Shared, - (chars, rand) => - { - for (var i = 0; i < chars.Length; i++) - chars[i] = _alphabet[rand.Next(0, _alphabet.Length)]; - }); - - for (; index < _block.Transactions.Length; index++) - if (_block.Transactions[index].Hash == txHash) - break; - - return string.Format(_fileNameFormat, index, hash, suffix); - } -} diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeBlockMemoryTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeBlockMemoryTracer.cs deleted file mode 100644 index 6070135e480..00000000000 --- a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeBlockMemoryTracer.cs +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core; - -namespace Nethermind.Evm.Tracing.GethStyle; - -public class GethLikeBlockMemoryTracer : BlockTracerBase -{ - private readonly GethTraceOptions _options; - - public GethLikeBlockMemoryTracer(GethTraceOptions options) : base(options.TxHash) => _options = options; - - protected override GethLikeTxMemoryTracer OnStart(Transaction? tx) => new(_options); - - protected override GethLikeTxTrace OnEnd(GethLikeTxMemoryTracer txTracer) => txTracer.BuildResult(); -} diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeBlockTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeBlockTracer.cs new file mode 100644 index 00000000000..4dd03ca6f5e --- /dev/null +++ b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeBlockTracer.cs @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core; +using Nethermind.Core.Crypto; + +namespace Nethermind.Evm.Tracing.GethStyle +{ + public class GethLikeBlockTracer : BlockTracerBase + { + private readonly GethTraceOptions _options; + + public GethLikeBlockTracer(GethTraceOptions options) + { + _options = options; + } + + public GethLikeBlockTracer(Keccak txHash, GethTraceOptions options) + : base(txHash) + { + _options = options; + } + + protected override GethLikeTxTracer OnStart(Transaction? tx) => new(_options); + + protected override GethLikeTxTrace OnEnd(GethLikeTxTracer txTracer) => txTracer.BuildResult(); + } +} diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxFileTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxFileTracer.cs deleted file mode 100644 index 9d3d8ed6957..00000000000 --- a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxFileTracer.cs +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; - -namespace Nethermind.Evm.Tracing.GethStyle; - -public class GethLikeTxFileTracer : GethLikeTxTracer -{ - private readonly Action _dumpCallback; - private long? _startGas; - - public GethLikeTxFileTracer(Action dumpCallback, GethTraceOptions options) : base(options) - { - _dumpCallback = dumpCallback ?? throw new ArgumentNullException(nameof(dumpCallback)); - - IsTracingMemory = true; - IsTracingOpLevelStorage = false; - IsTracingRefunds = true; - } - - public override GethLikeTxTrace BuildResult() - { - var trace = base.BuildResult(); - - if (_startGas.HasValue) - trace.Gas = _startGas.Value - CurrentTraceEntry.Gas; - - return trace; - } - - public override void ReportRefund(long refund) => CurrentTraceEntry.Refund = refund; - - protected override void AddTraceEntry(GethTxFileTraceEntry entry) - { - _dumpCallback(entry); - - _startGas ??= entry.Gas; - } - - protected override GethTxFileTraceEntry CreateTraceEntry(Instruction opcode) - { - var entry = GetOrCreateTraceEntry(); - - entry.OpcodeRaw = opcode; - - return entry; - } - - private GethTxFileTraceEntry GetOrCreateTraceEntry() - { - if (CurrentTraceEntry is null) - return new(); - - var entry = CurrentTraceEntry; - - entry.Depth = default; - entry.Error = default; - entry.Gas = default; - entry.GasCost = default; - entry.Memory = default; - entry.MemorySize = default; - entry.Opcode = default; - entry.OpcodeRaw = default; - entry.ProgramCounter = default; - entry.Refund = default; - entry.Stack = default; - entry.Storage = default; - - return entry; - } -} diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxMemoryTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxMemoryTracer.cs deleted file mode 100644 index 32cb1218edf..00000000000 --- a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxMemoryTracer.cs +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using Nethermind.Core.Crypto; -using Nethermind.Core.Extensions; -using Nethermind.Core; -using Nethermind.Int256; - -namespace Nethermind.Evm.Tracing.GethStyle; - -public class GethLikeTxMemoryTracer : GethLikeTxTracer -{ - public GethLikeTxMemoryTracer(GethTraceOptions options) : base(options) => IsTracingMemory = IsTracingFullMemory; - - public override void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) - { - base.MarkAsSuccess(recipient, gasSpent, output, logs, stateRoot); - - Trace.Gas = gasSpent; - } - - public override void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) - { - base.SetOperationStorage(address, storageIndex, newValue, currentValue); - - byte[] bigEndian = new byte[32]; - - storageIndex.ToBigEndian(bigEndian); - - CurrentTraceEntry.Storage[bigEndian.ToHexString(false)] = new ZeroPaddedSpan(newValue, 32 - newValue.Length, PadDirection.Left) - .ToArray() - .ToHexString(false); - } - - public override void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge) - { - var previousTraceEntry = CurrentTraceEntry; - var previousDepth = CurrentTraceEntry?.Depth ?? 0; - - base.StartOperation(depth, gas, opcode, pc, isPostMerge); - - if (CurrentTraceEntry.Depth > previousDepth) - { - CurrentTraceEntry.Storage = new Dictionary(); - - Trace.StoragesByDepth.Push(previousTraceEntry is null ? new() : previousTraceEntry.Storage); - } - else if (CurrentTraceEntry.Depth < previousDepth) - { - if (previousTraceEntry is null) - throw new InvalidOperationException("Missing the previous trace on leaving the call."); - - CurrentTraceEntry.Storage = new Dictionary(Trace.StoragesByDepth.Pop()); - } - else - { - if (previousTraceEntry is null) - throw new InvalidOperationException("Missing the previous trace on continuation."); - - CurrentTraceEntry.Storage = new Dictionary(previousTraceEntry.Storage); - } - } - - protected override void AddTraceEntry(GethTxMemoryTraceEntry entry) => Trace.Entries.Add(entry); - - protected override GethTxMemoryTraceEntry CreateTraceEntry(Instruction opcode) => new(); -} diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxTrace.cs b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxTrace.cs index 1cd18fc47c6..7f1cd01e14f 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxTrace.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxTrace.cs @@ -1,24 +1,27 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using System.Collections.Generic; using Newtonsoft.Json; -namespace Nethermind.Evm.Tracing.GethStyle; - -public class GethLikeTxTrace +namespace Nethermind.Evm.Tracing.GethStyle { - public GethLikeTxTrace() => Entries = new List(); + public class GethLikeTxTrace + { + public Stack> StoragesByDepth { get; } = new(); - public Stack> StoragesByDepth { get; } = new(); + public GethLikeTxTrace() + { + Entries = new List(); + } - public long Gas { get; set; } + public long Gas { get; set; } - public bool Failed { get; set; } + public bool Failed { get; set; } - public byte[] ReturnValue { get; set; } = Array.Empty(); + public byte[] ReturnValue { get; set; } - [JsonProperty(PropertyName = "structLogs")] - public List Entries { get; set; } + [JsonProperty(PropertyName = "structLogs")] + public List Entries { get; set; } + } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxTraceJsonLinesConverter.cs b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxTraceJsonLinesConverter.cs deleted file mode 100644 index 266079badef..00000000000 --- a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxTraceJsonLinesConverter.cs +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace Nethermind.Evm.Tracing.GethStyle; - -/// -/// Converts a transaction trace entry to the -/// JSON Lines format. -/// This converter is write-only. -/// -internal class GethLikeTxTraceJsonLinesConverter : JsonConverter -{ - /// - /// This method is not supported. - /// - /// - public override GethTxFileTraceEntry? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - => throw new NotSupportedException(); - - /// - /// Writes specified transaction entry as JSON adding a new line at the end. - /// - /// - /// This method flushes and resets the writer before returning. - /// - /// - public override void Write(Utf8JsonWriter writer, GethTxFileTraceEntry value, JsonSerializerOptions options) - { - if (value is null) - { - writer.WriteNullValue(); - return; - } - - writer.WriteStartObject(); - - writer.WritePropertyName("pc"); - writer.WriteNumberValue(value.ProgramCounter); - - writer.WritePropertyName("op"); - writer.WriteNumberValue((byte)value.OpcodeRaw); - - writer.WritePropertyName("gas"); - writer.WriteStringValue($"0x{value.Gas:x}"); - - writer.WritePropertyName("gasCost"); - writer.WriteStringValue($"0x{value.GasCost:x}"); - - writer.WritePropertyName("memSize"); - writer.WriteNumberValue(value.MemorySize ?? 0UL); - - if ((value.Memory?.Count ?? 0) != 0) - { - var memory = string.Concat(value.Memory); - - writer.WritePropertyName("memory"); - writer.WriteStringValue($"0x{memory}"); - } - - if (value.Stack is not null) - { - writer.WritePropertyName("stack"); - writer.WriteStartArray(); - - foreach (var s in value.Stack) - writer.WriteStringValue(s); - - writer.WriteEndArray(); - } - - writer.WritePropertyName("depth"); - writer.WriteNumberValue(value.Depth); - - writer.WritePropertyName("refund"); - writer.WriteNumberValue(value.Refund ?? 0L); - - writer.WritePropertyName("opName"); - writer.WriteStringValue(value.Opcode); - - if (value.Error is not null) - { - writer.WritePropertyName("error"); - writer.WriteStringValue(value.Error); - } - - writer.WriteEndObject(); - - // Before writing a new line, flush and reset the writer - // to avoid adding comma (depth tracking) - writer.Flush(); - writer.Reset(); - writer.WriteRawValue(Environment.NewLine, true); - // After writing the new line, flush and reset the writer again - // to avoid adding comma on writer reuse - writer.Flush(); - writer.Reset(); - } -} diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxTracer.cs index 167a1878cfa..497b35a72a7 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethLikeTxTracer.cs @@ -3,96 +3,247 @@ using System; using System.Collections.Generic; -using System.Linq; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; +using Nethermind.Int256; +using Nethermind.State; +using Nethermind.State.Tracing; -namespace Nethermind.Evm.Tracing.GethStyle; - -public abstract class GethLikeTxTracer : TxTracer where TEntry : GethTxTraceEntry +namespace Nethermind.Evm.Tracing.GethStyle { - protected GethLikeTxTracer(GethTraceOptions options) + public class GethLikeTxTracer : ITxTracer { - ArgumentNullException.ThrowIfNull(options); + private GethTxTraceEntry? _traceEntry; + private readonly GethLikeTxTrace _trace = new(); - IsTracingFullMemory = options.EnableMemory; - IsTracingOpLevelStorage = !options.DisableStorage; - IsTracingStack = !options.DisableStack; - IsTracing = IsTracing || IsTracingFullMemory; - } + public GethLikeTxTracer(GethTraceOptions options) + { + IsTracingStack = !options.DisableStack; + IsTracingMemory = !options.DisableMemory; + IsTracingOpLevelStorage = !options.DisableStorage; + } + + bool IStateTracer.IsTracingState => false; + bool IStorageTracer.IsTracingStorage => false; + public bool IsTracingReceipt => true; + public bool IsTracingActions => false; + public bool IsTracingOpLevelStorage { get; } + public bool IsTracingMemory { get; } + public bool IsTracingInstructions => true; + public bool IsTracingRefunds => false; + public bool IsTracingCode => false; + public bool IsTracingStack { get; } + public bool IsTracingBlockHash => false; + public bool IsTracingAccess => false; + public bool IsTracingFees => false; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; + + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) + { + _trace.ReturnValue = output; + _trace.Gas = gasSpent; + } - public sealed override bool IsTracingOpLevelStorage { get; protected set; } - public override bool IsTracingReceipt => true; - public sealed override bool IsTracingMemory { get; protected set; } - public override bool IsTracingInstructions => true; - public sealed override bool IsTracingStack { get; protected set; } - protected bool IsTracingFullMemory { get; } - protected TEntry? CurrentTraceEntry { get; set; } - protected GethLikeTxTrace Trace { get; } = new(); + public void MarkAsFailed(Address recipient, long gasSpent, byte[]? output, string error, Keccak? stateRoot = null) + { + _trace.Failed = true; + _trace.ReturnValue = output ?? Array.Empty(); + } - public override void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) - { - Trace.ReturnValue = output; - } + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge) + { + GethTxTraceEntry previousTraceEntry = _traceEntry; + _traceEntry = new GethTxTraceEntry(); + _traceEntry.Pc = pc; + _traceEntry.Operation = opcode.GetName(isPostMerge); + _traceEntry.Gas = gas; + _traceEntry.Depth = depth; + _trace.Entries.Add(_traceEntry); + + if (_traceEntry.Depth > (previousTraceEntry?.Depth ?? 0)) + { + _traceEntry.Storage = new Dictionary(); + _trace.StoragesByDepth.Push(previousTraceEntry is not null ? previousTraceEntry.Storage : new Dictionary()); + } + else if (_traceEntry.Depth < (previousTraceEntry?.Depth ?? 0)) + { + if (previousTraceEntry is null) + { + throw new InvalidOperationException("Unexpected missing previous trace when leaving a call."); + } + + _traceEntry.Storage = new Dictionary(_trace.StoragesByDepth.Pop()); + } + else + { + if (previousTraceEntry is null) + { + throw new InvalidOperationException("Unexpected missing previous trace on continuation."); + } + + _traceEntry.Storage = new Dictionary(previousTraceEntry.Storage); + } + } + + public void ReportOperationError(EvmExceptionType error) + { + _traceEntry.Error = GetErrorDescription(error); + } - public override void MarkAsFailed(Address recipient, long gasSpent, byte[]? output, string error, Keccak? stateRoot = null) - { - Trace.Failed = true; - Trace.ReturnValue = output ?? Array.Empty(); - } + private string? GetErrorDescription(EvmExceptionType evmExceptionType) + { + return evmExceptionType switch + { + EvmExceptionType.None => null, + EvmExceptionType.BadInstruction => "BadInstruction", + EvmExceptionType.StackOverflow => "StackOverflow", + EvmExceptionType.StackUnderflow => "StackUnderflow", + EvmExceptionType.OutOfGas => "OutOfGas", + EvmExceptionType.InvalidSubroutineEntry => "InvalidSubroutineEntry", + EvmExceptionType.InvalidSubroutineReturn => "InvalidSubroutineReturn", + EvmExceptionType.InvalidJumpDestination => "BadJumpDestination", + EvmExceptionType.AccessViolation => "AccessViolation", + EvmExceptionType.StaticCallViolation => "StaticCallViolation", + _ => "Error" + }; + } + + public void ReportOperationRemainingGas(long gas) + { + _traceEntry.GasCost = _traceEntry.Gas - gas; + } - public override void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) - { - if (CurrentTraceEntry is not null) - AddTraceEntry(CurrentTraceEntry); - - CurrentTraceEntry = CreateTraceEntry(opcode); - CurrentTraceEntry.Depth = depth; - CurrentTraceEntry.Gas = gas; - CurrentTraceEntry.Opcode = opcode.GetName(isPostMerge); - CurrentTraceEntry.ProgramCounter = pc; - } + public void SetOperationMemorySize(ulong newSize) + { + _traceEntry.UpdateMemorySize(newSize); + } + + public void ReportMemoryChange(long offset, in ReadOnlySpan data) + { + } - public override void ReportOperationError(EvmExceptionType error) => CurrentTraceEntry.Error = GetErrorDescription(error); + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) + { + } - private string? GetErrorDescription(EvmExceptionType evmExceptionType) - { - return evmExceptionType switch - { - EvmExceptionType.None => null, - EvmExceptionType.BadInstruction => "BadInstruction", - EvmExceptionType.StackOverflow => "StackOverflow", - EvmExceptionType.StackUnderflow => "StackUnderflow", - EvmExceptionType.OutOfGas => "OutOfGas", - EvmExceptionType.InvalidSubroutineEntry => "InvalidSubroutineEntry", - EvmExceptionType.InvalidSubroutineReturn => "InvalidSubroutineReturn", - EvmExceptionType.InvalidJumpDestination => "BadJumpDestination", - EvmExceptionType.AccessViolation => "AccessViolation", - EvmExceptionType.StaticCallViolation => "StaticCallViolation", - _ => "Error" - }; - } + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) + { + byte[] bigEndian = new byte[32]; + storageIndex.ToBigEndian(bigEndian); + _traceEntry.Storage[bigEndian.ToHexString(false)] = new ZeroPaddedSpan(newValue, 32 - newValue.Length, PadDirection.Left).ToArray().ToHexString(false); + } - public override void ReportOperationRemainingGas(long gas) => CurrentTraceEntry.GasCost = CurrentTraceEntry.Gas - gas; + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) + { - public override void SetOperationMemorySize(ulong newSize) => CurrentTraceEntry.UpdateMemorySize(newSize); + } - public override void SetOperationStack(List stackTrace) => CurrentTraceEntry.Stack = stackTrace; + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) + { + throw new NotSupportedException(); + } - public override void SetOperationMemory(IEnumerable memoryTrace) - { - if (IsTracingFullMemory) - CurrentTraceEntry.Memory = memoryTrace.ToList(); - } + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) + { + throw new NotSupportedException(); + } - public virtual GethLikeTxTrace BuildResult() - { - if (CurrentTraceEntry is not null) - AddTraceEntry(CurrentTraceEntry); + public void ReportCodeChange(Address address, byte[] before, byte[] after) + { + throw new NotSupportedException(); + } - return Trace; - } - protected abstract void AddTraceEntry(TEntry entry); + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) + { + throw new NotSupportedException(); + } + + public void ReportAccountRead(Address address) + { + } - protected abstract TEntry CreateTraceEntry(Instruction opcode); + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) + { + throw new NotSupportedException(); + } + + public void ReportStorageRead(in StorageCell storageCell) + { + throw new NotSupportedException(); + } + + public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) + { + throw new NotSupportedException(); + } + + public void ReportActionEnd(long gas, ReadOnlyMemory output) + { + throw new NotSupportedException(); + } + + public void ReportActionError(EvmExceptionType exceptionType) + { + throw new NotSupportedException(); + } + + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) + { + throw new NotSupportedException(); + } + + public void ReportBlockHash(Keccak blockHash) + { + throw new NotSupportedException(); + } + + public void ReportByteCode(byte[] byteCode) + { + throw new NotSupportedException(); + } + + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) + { + } + + public void ReportRefund(long refund) + { + throw new NotSupportedException(); + } + + public void ReportExtraGasPressure(long extraGasPressure) + { + throw new NotImplementedException(); + } + + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) + { + throw new NotImplementedException(); + } + + public void SetOperationStack(List stackTrace) + { + _traceEntry.Stack = stackTrace; + } + + public void ReportStackPush(in ReadOnlySpan stackItem) + { + } + + public void SetOperationMemory(List memoryTrace) + { + _traceEntry.Memory = memoryTrace; + } + + public void ReportFees(UInt256 fees, UInt256 burntFees) + { + throw new NotImplementedException(); + } + + public GethLikeTxTrace BuildResult() + { + return _trace; + } + } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTraceOptions.cs b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTraceOptions.cs index 8d3ffb38cc8..d4cd635afa1 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTraceOptions.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTraceOptions.cs @@ -1,35 +1,27 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; -using Nethermind.Core.Crypto; using Newtonsoft.Json; -namespace Nethermind.Evm.Tracing.GethStyle; - -public record GethTraceOptions +namespace Nethermind.Evm.Tracing.GethStyle { - [JsonProperty("disableMemory")] - [Obsolete("Use EnableMemory instead.")] - public bool DisableMemory { get => !EnableMemory; init => EnableMemory = !value; } - - [JsonProperty("disableStack")] - public bool DisableStack { get; init; } - - [JsonProperty("disableStorage")] - public bool DisableStorage { get; init; } + public class GethTraceOptions + { + [JsonProperty("disableStorage")] + public bool DisableStorage { get; set; } - [JsonProperty("enableMemory")] - public bool EnableMemory { get; init; } + [JsonProperty("disableMemory")] + public bool DisableMemory { get; set; } - [JsonProperty("timeout")] - public string Timeout { get; init; } + [JsonProperty("disableStack")] + public bool DisableStack { get; set; } - [JsonProperty("tracer")] - public string Tracer { get; init; } + [JsonProperty("tracer")] + public string Tracer { get; set; } - [JsonProperty("txHash")] - public Keccak? TxHash { get; init; } + [JsonProperty("timeout")] + public string Timeout { get; set; } - public static GethTraceOptions Default { get; } = new(); + public static GethTraceOptions Default = new(); + } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTxFileTraceEntry.cs b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTxFileTraceEntry.cs deleted file mode 100644 index c0d0efcf076..00000000000 --- a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTxFileTraceEntry.cs +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Evm.Tracing.GethStyle; - -public class GethTxFileTraceEntry : GethTxTraceEntry -{ - public ulong? MemorySize { get; set; } - - public Instruction? OpcodeRaw { get; set; } - - public long? Refund { get; set; } - - internal override void UpdateMemorySize(ulong size) - { - base.UpdateMemorySize(size); - - MemorySize = size; - } -} diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTxMemoryTraceEntry.cs b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTxMemoryTraceEntry.cs deleted file mode 100644 index 8407b387968..00000000000 --- a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTxMemoryTraceEntry.cs +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; - -namespace Nethermind.Evm.Tracing.GethStyle; - -public class GethTxMemoryTraceEntry : GethTxTraceEntry -{ - internal override void UpdateMemorySize(ulong size) - { - base.UpdateMemorySize(size); - - // Geth's approach to memory trace is to show empty memory spaces on entry for the values that are being set by the operation - Memory ??= new List(); - - int missingChunks = (int)((size - (ulong)Memory.Count * EvmPooledMemory.WordSize) / EvmPooledMemory.WordSize); - - for (int i = 0; i < missingChunks; i++) - { - Memory.Add("0000000000000000000000000000000000000000000000000000000000000000"); - } - } -} diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTxTraceEntry.cs b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTxTraceEntry.cs index 54165d66f60..0ecd6dc433d 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTxTraceEntry.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/GethStyle/GethTxTraceEntry.cs @@ -2,28 +2,50 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; -namespace Nethermind.Evm.Tracing.GethStyle; - -public class GethTxTraceEntry +namespace Nethermind.Evm.Tracing.GethStyle { - public int Depth { get; set; } + public class GethTxTraceEntry + { + public GethTxTraceEntry() + { + Stack = new List(); + Memory = new List(); + } + + public long Pc { get; set; } + + [JsonProperty(PropertyName = "op")] + public string? Operation { get; set; } + + public long Gas { get; set; } - public string? Error { get; set; } + public long GasCost { get; set; } - public long Gas { get; set; } + public int Depth { get; set; } - public long GasCost { get; set; } + public List? Stack { get; set; } - public IList? Memory { get; set; } + public string? Error { get; set; } - public string? Opcode { get; set; } + public List? Memory { get; set; } - public long ProgramCounter { get; set; } + public Dictionary? Storage { get; set; } - public IList? Stack { get; set; } + public Dictionary? SortedStorage => Storage?.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value); - public Dictionary? Storage { get; set; } + internal void UpdateMemorySize(ulong size) + { + // Geth's approach to memory trace is to show empty memory spaces on entry for the values that are being set by the operation + Memory ??= new List(); - internal virtual void UpdateMemorySize(ulong size) { } + int missingChunks = (int)((size - (ulong)Memory.Count * EvmPooledMemory.WordSize) / EvmPooledMemory.WordSize); + for (int i = 0; i < missingChunks; i++) + { + Memory.Add("0000000000000000000000000000000000000000000000000000000000000000"); + } + } + } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/IBlockTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/IBlockTracer.cs index e00177e15ec..9e9aad8b2e9 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/IBlockTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/IBlockTracer.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Int256; namespace Nethermind.Evm.Tracing diff --git a/src/Nethermind/Nethermind.Evm/Tracing/ITxTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/ITxTracer.cs index 9de921c9797..8a752a71ec2 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/ITxTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/ITxTracer.cs @@ -2,421 +2,433 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Buffers; using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Int256; +using Nethermind.State; using Nethermind.State.Tracing; -namespace Nethermind.Evm.Tracing; - -public interface ITxTracer : IWorldStateTracer +namespace Nethermind.Evm.Tracing { - /// - /// Defines whether MarkAsSuccess or MarkAsFailed will be called - /// - /// - /// Controls - /// - - /// - - /// - bool IsTracingReceipt { get; } - - /// - /// High level calls with information on the target account - /// - /// - /// Controls - /// - - /// - - /// - - /// - - /// - bool IsTracingActions { get; } - - /// - /// SSTORE and SLOAD level storage operations - /// - /// - /// Controls - /// - - /// - - /// - - /// - - /// - bool IsTracingOpLevelStorage { get; } - - /// - /// EVM memory access operations - /// - /// - /// Controls - /// - - /// - - /// - bool IsTracingMemory { get; } - - /// - /// EVM instructions - /// - /// - /// Controls - /// - - /// - - /// - - /// - - /// - - /// - - /// - bool IsTracingInstructions { get; } - - /// - /// Updates of refund counter - /// - /// - /// Controls - /// - - /// - - /// - bool IsTracingRefunds { get; } - - /// - /// Code deployment - /// - /// - /// Controls - /// - - /// - bool IsTracingCode { get; } - - /// - /// EVM stack tracing after each operation - /// - /// - /// Controls - /// - - /// - bool IsTracingStack { get; } - - /// - /// Traces blockhash calls - /// - /// - /// Controls - /// - - /// - bool IsTracingBlockHash { get; } - - /// - /// Traces storage access - /// - /// - /// Controls - /// - - /// - bool IsTracingAccess { get; } - - /// - /// Traces fees and burned fees - /// - /// - /// Controls - /// - - /// - bool IsTracingFees { get; } - - bool IsTracing => IsTracingReceipt - || IsTracingActions - || IsTracingOpLevelStorage - || IsTracingMemory - || IsTracingInstructions - || IsTracingRefunds - || IsTracingCode - || IsTracingStack - || IsTracingBlockHash - || IsTracingAccess - || IsTracingFees; - - /// - /// Transaction completed successfully - /// - /// Transaction recipient - /// Gas spent on transaction execution - /// Output of transaction - /// Logs for transaction - /// State root after transaction, depends on EIP-658 - /// Depends on - void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null); - - /// - /// Transaction failed - /// - /// Transaction recipient - /// Gas spent on transaction execution - /// Output of transaction - /// Error that failed the transaction - /// State root after transaction, depends on EIP-658 - /// Depends on - void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null); - - /// - /// - /// - /// - /// - /// - /// - /// - /// Depends on - void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false); - - /// - /// - /// - /// - /// Depends on - void ReportOperationError(EvmExceptionType error); - - /// - /// - /// - /// - /// Depends on - void ReportOperationRemainingGas(long gas); - - /// - /// - /// - /// - /// Depends on - void SetOperationStack(List stackTrace); - - /// - /// - /// - /// - /// Depends on - void ReportStackPush(in ReadOnlySpan stackItem); - - /// - - /// - /// - /// Depends on - void ReportStackPush(byte stackItem) + public interface ITxTracer : IWorldStateTracer { - ReportStackPush(new[] { stackItem }); - } + /// + /// Defines whether MarkAsSuccess or MarkAsFailed will be called + /// + /// + /// Controls + /// - + /// - + /// + bool IsTracingReceipt { get; } + + /// + /// High level calls with information on the target account + /// + /// + /// Controls + /// - + /// - + /// - + /// - + /// + bool IsTracingActions { get; } + + /// + /// SSTORE and SLOAD level storage operations + /// + /// + /// Controls + /// - + /// - + /// - + /// - + /// + bool IsTracingOpLevelStorage { get; } + + /// + /// EVM memory access operations + /// + /// + /// Controls + /// - + /// - + /// + bool IsTracingMemory { get; } + + /// + /// EVM instructions + /// + /// + /// Controls + /// - + /// - + /// - + /// - + /// - + /// - + /// + bool IsTracingInstructions { get; } + + /// + /// Updates of refund counter + /// + /// + /// Controls + /// - + /// - + /// + bool IsTracingRefunds { get; } + + /// + /// Code deployment + /// + /// + /// Controls + /// - + /// + bool IsTracingCode { get; } + + /// + /// EVM stack tracing after each operation + /// + /// + /// Controls + /// - + /// + bool IsTracingStack { get; } + + /// + /// Traces blockhash calls + /// + /// + /// Controls + /// - + /// + bool IsTracingBlockHash { get; } + + /// + /// Traces storage access + /// + /// + /// Controls + /// - + /// + bool IsTracingAccess { get; } + + /// + /// Traces fees and burned fees + /// + /// + /// Controls + /// - + /// + bool IsTracingFees { get; } + + bool IsTracing { get; } + + /// + /// Transaction completed successfully + /// + /// Transaction recipient + /// Gas spent on transaction execution + /// Output of transaction + /// Logs for transaction + /// State root after transaction, depends on EIP-658 + /// Depends on + void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null); + + /// + /// Transaction failed + /// + /// Transaction recipient + /// Gas spent on transaction execution + /// Output of transaction + /// Error that failed the transaction + /// State root after transaction, depends on EIP-658 + /// Depends on + void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null); + + /// + /// + /// + /// + /// + /// + /// + /// + /// Depends on + void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false); + + /// + /// + /// + /// + /// Depends on + void ReportOperationError(EvmExceptionType error); + + /// + /// + /// + /// + /// Depends on + void ReportOperationRemainingGas(long gas); + + /// + /// + /// + /// + /// Depends on + void SetOperationStack(List stackTrace); + + /// + /// + /// + /// + /// Depends on + void ReportStackPush(in ReadOnlySpan stackItem); + + /// + + /// + /// + /// Depends on + void ReportStackPush(byte stackItem) + { + ReportStackPush(new[] { stackItem }); + } - /// - /// - /// - /// - /// Depends on - void ReportStackPush(in ZeroPaddedSpan stackItem) - { - ReportStackPush(stackItem.ToArray().AsSpan()); - } + /// + /// + /// + /// + /// Depends on + void ReportStackPush(in ZeroPaddedSpan stackItem) + { + ReportStackPush(stackItem.ToArray().AsSpan()); + } - /// - /// - /// - /// - /// Depends on - void SetOperationMemory(IEnumerable memoryTrace); - - /// - /// - /// - /// - /// Depends on - void SetOperationMemorySize(ulong newSize); - - /// - /// - /// - /// - /// - /// Depends on - void ReportMemoryChange(long offset, in ReadOnlySpan data); - - /// - /// - /// - /// - /// - /// Depends on - void ReportMemoryChange(UInt256 offset, in ReadOnlySpan data) - { - if (offset.u1 <= 0 && offset.u2 <= 0 && offset.u3 <= 0 && offset.u0 <= long.MaxValue) + /// + /// + /// + /// Depends on + void ReportStackPush(in ZeroPaddedMemory stackItem) { - ReportMemoryChange((long)offset, data); + ReportStackPush(stackItem.ToArray().AsSpan()); } - } - /// - /// - /// - /// - /// - /// Depends on - void ReportMemoryChange(long offset, byte data) - { - ReportMemoryChange(offset, new[] { data }); - } + /// + /// + /// + /// + /// Depends on + void SetOperationMemory(List memoryTrace); + + /// + /// + /// + /// + /// Depends on + void SetOperationMemorySize(ulong newSize); + + /// + /// + /// + /// + /// + /// Depends on + void ReportMemoryChange(long offset, in ReadOnlySpan data); + + /// + /// + /// + /// + /// + /// Depends on + void ReportMemoryChange(UInt256 offset, in ReadOnlySpan data) + { + if (offset.u1 <= 0 && offset.u2 <= 0 && offset.u3 <= 0 && offset.u0 <= long.MaxValue) + { + ReportMemoryChange((long)offset, data); + } + } - /// - /// - /// - /// - /// - /// Depends on - void ReportMemoryChange(long offset, in ZeroPaddedSpan data) - { - ReportMemoryChange(offset, data.ToArray()); - } + /// + /// + /// + /// + /// + /// Depends on + void ReportMemoryChange(long offset, byte data) + { + ReportMemoryChange(offset, new[] { data }); + } + + /// + /// + /// + /// + /// + /// Depends on + void ReportMemoryChange(long offset, in ZeroPaddedSpan data) + { + ReportMemoryChange(offset, data.ToArray()); + } + + /// + /// + /// + /// + /// Depends on + void ReportMemoryChange(long offset, in ZeroPaddedMemory data) + { + ReportMemoryChange(offset, data.ToArray()); + } - /// - /// - /// - /// - /// - /// - /// - /// Depends on - void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue); - - /// - /// - /// - /// - /// - /// - /// - /// Depends on - void SetOperationTransientStorage(Address storageCellAddress, UInt256 storageIndex, ReadOnlySpan newValue, byte[] currentValue) { } - - /// - /// - /// - /// - /// - /// - /// Depends on - void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value); - - /// - /// - /// - /// - /// - /// - /// Depends on - void LoadOperationTransientStorage(Address storageCellAddress, UInt256 storageIndex, byte[] value) { } - - /// - /// - /// - /// - /// - /// - /// Depends on - void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress); - - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// Depends on - void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false); - - /// - /// - /// - /// - /// - /// Depends on - void ReportActionEnd(long gas, ReadOnlyMemory output); - - /// - /// - /// - /// - /// - /// Depends on - void ReportActionError(EvmExceptionType evmExceptionType, long gasLeft) => ReportActionError(evmExceptionType); - - /// - /// - /// - /// - /// Depends on - void ReportActionError(EvmExceptionType evmExceptionType); - - /// - /// - /// - /// - /// - /// - /// Depends on - void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode); - - /// - /// - /// - /// - /// Depends on - void ReportBlockHash(Keccak blockHash); - - /// - /// - /// - /// - /// Depends on - void ReportByteCode(byte[] byteCode); - - /// - /// Special case for VM trace in Parity but we consider removing support for it - /// - /// - /// - /// Depends on - void ReportGasUpdateForVmTrace(long refund, long gasAvailable); - - /// - /// - /// - /// - /// Depends on - void ReportRefund(long refund); - - /// - /// - /// - /// - /// Depends on - void ReportExtraGasPressure(long extraGasPressure); - - /// - /// Reports access to storage cell - /// - /// address - /// cell - /// Depends on - void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells); - - /// - /// Reports fees of a transaction - /// - /// Fees sent to block author - /// EIP-1559 burnt fees - /// Depends on - void ReportFees(UInt256 fees, UInt256 burntFees); + /// + /// + /// + /// + /// + /// + /// + /// Depends on + void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue); + + /// + /// + /// + /// + /// + /// + /// + /// Depends on + void SetOperationTransientStorage(Address storageCellAddress, UInt256 storageIndex, Span newValue, byte[] currentValue) { } + + /// + /// + /// + /// + /// + /// + /// Depends on + void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value); + + /// + /// + /// + /// + /// + /// + /// Depends on + void LoadOperationTransientStorage(Address storageCellAddress, UInt256 storageIndex, byte[] value) { } + + /// + /// + /// + /// + /// + /// + /// Depends on + void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress); + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// Depends on + void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false); + + /// + /// + /// + /// + /// + /// Depends on + void ReportActionEnd(long gas, ReadOnlyMemory output); + + /// + /// + /// + /// + /// + /// Depends on + void ReportActionError(EvmExceptionType evmExceptionType, long gasLeft) => ReportActionError(evmExceptionType); + + /// + /// + /// + /// + /// Depends on + void ReportActionError(EvmExceptionType evmExceptionType); + + /// + /// + /// + /// + /// + /// + /// Depends on + void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode); + + /// + /// + /// + /// + /// Depends on + void ReportBlockHash(Keccak blockHash); + + /// + /// + /// + /// + /// Depends on + void ReportByteCode(byte[] byteCode); + + /// + /// Special case for VM trace in Parity but we consider removing support for it + /// + /// + /// + /// Depends on + void ReportGasUpdateForVmTrace(long refund, long gasAvailable); + + /// + /// + /// + /// + /// Depends on + void ReportRefund(long refund); + + /// + /// + /// + /// + /// Depends on + void ReportExtraGasPressure(long extraGasPressure); + + /// + /// Reports access to storage cell + /// + /// address + /// cell + /// Depends on + void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells); + + /// + /// Reports fees of a transaction + /// + /// Fees sent to block author + /// EIP-1559 burnt fees + /// Depends on + void ReportFees(UInt256 fees, UInt256 burntFees); + } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/ITxTracerWrapper.cs b/src/Nethermind/Nethermind.Evm/Tracing/ITxTracerWrapper.cs index 14b770ccd15..40c0ff9f5fe 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/ITxTracerWrapper.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/ITxTracerWrapper.cs @@ -1,6 +1,14 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Buffers; +using System.Collections.Generic; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Int256; +using Nethermind.State; + namespace Nethermind.Evm.Tracing { public interface ITxTracerWrapper diff --git a/src/Nethermind/Nethermind.Evm/Tracing/NullBlockTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/NullBlockTracer.cs index f3c270572fb..a97a39bc501 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/NullBlockTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/NullBlockTracer.cs @@ -3,13 +3,45 @@ using System.Threading; using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Int256; namespace Nethermind.Evm.Tracing { - public class NullBlockTracer : BlockTracer + public class NullBlockTracer : IBlockTracer { - private static NullBlockTracer? _instance; - public static NullBlockTracer Instance => LazyInitializer.EnsureInitialized(ref _instance, () => new NullBlockTracer()); - public override ITxTracer StartNewTxTrace(Transaction? tx) => NullTxTracer.Instance; + private static NullBlockTracer _instance; + + private NullBlockTracer() + { + } + + public static NullBlockTracer Instance + { + get { return LazyInitializer.EnsureInitialized(ref _instance, () => new NullBlockTracer()); } + } + + public bool IsTracingRewards => false; + + public void ReportReward(Address author, string rewardType, UInt256 rewardValue) + { + } + + public void StartNewBlockTrace(Block block) + { + } + + public ITxTracer StartNewTxTrace(Transaction? tx) + { + return NullTxTracer.Instance; + } + + public void EndTxTrace() + { + } + + public void EndBlockTrace() + { + } } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/NullTxTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/NullTxTracer.cs index dcefa85d530..87e2a69ce33 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/NullTxTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/NullTxTracer.cs @@ -3,85 +3,118 @@ using System; using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Int256; -namespace Nethermind.Evm.Tracing; - -public class NullTxTracer : TxTracer +namespace Nethermind.Evm.Tracing { - public static ITxTracer Instance { get; } = new NullTxTracer(); - - private const string ErrorMessage = "Null tracer should never receive any calls."; - private NullTxTracer() { } - - [DoesNotReturn] - [StackTraceHidden] - private static void ThrowInvalidOperationException() => throw new InvalidOperationException(ErrorMessage); - - public override void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) - => ThrowInvalidOperationException(); - public override void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) - => ThrowInvalidOperationException(); - public override void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) - => ThrowInvalidOperationException(); - public override void ReportOperationError(EvmExceptionType error) - => ThrowInvalidOperationException(); - public override void ReportOperationRemainingGas(long gas) - => ThrowInvalidOperationException(); - public override void SetOperationMemorySize(ulong newSize) - => ThrowInvalidOperationException(); - public override void ReportMemoryChange(long offset, in ReadOnlySpan data) - => ThrowInvalidOperationException(); - public override void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) - => ThrowInvalidOperationException(); - public override void SetOperationStack(List stackTrace) - => ThrowInvalidOperationException(); - public override void ReportStackPush(in ReadOnlySpan stackItem) - => ThrowInvalidOperationException(); - public override void SetOperationMemory(IEnumerable memoryTrace) - => ThrowInvalidOperationException(); - public override void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) - => ThrowInvalidOperationException(); - public override void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) - => ThrowInvalidOperationException(); - public override void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) - => ThrowInvalidOperationException(); - public override void ReportBalanceChange(Address address, UInt256? before, UInt256? after) - => ThrowInvalidOperationException(); - public override void ReportCodeChange(Address address, byte[] before, byte[] after) - => ThrowInvalidOperationException(); - public override void ReportNonceChange(Address address, UInt256? before, UInt256? after) - => ThrowInvalidOperationException(); - public override void ReportAccountRead(Address address) - => ThrowInvalidOperationException(); - public override void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) - => ThrowInvalidOperationException(); - public override void ReportStorageRead(in StorageCell storageCell) - => ThrowInvalidOperationException(); - public override void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) - => ThrowInvalidOperationException(); - public override void ReportActionEnd(long gas, ReadOnlyMemory output) - => ThrowInvalidOperationException(); - public override void ReportActionError(EvmExceptionType exceptionType) - => ThrowInvalidOperationException(); - public override void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) - => ThrowInvalidOperationException(); - public override void ReportBlockHash(Keccak blockHash) - => ThrowInvalidOperationException(); - public override void ReportByteCode(byte[] byteCode) - => ThrowInvalidOperationException(); - public override void ReportGasUpdateForVmTrace(long refund, long gasAvailable) - => ThrowInvalidOperationException(); - public override void ReportRefund(long refund) - => ThrowInvalidOperationException(); - public override void ReportExtraGasPressure(long extraGasPressure) - => ThrowInvalidOperationException(); - public override void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) - => ThrowInvalidOperationException(); - public override void ReportFees(UInt256 fees, UInt256 burntFees) - => ThrowInvalidOperationException(); + public class NullTxTracer : ITxTracer + { + public static ITxTracer Instance { get; } = new NullTxTracer(); + + private const string ErrorMessage = "Null tracer should never receive any calls."; + private NullTxTracer() { } + + public bool IsTracingReceipt => false; + public bool IsTracingActions => false; + public bool IsTracingOpLevelStorage => false; + public bool IsTracingMemory => false; + public bool IsTracingInstructions => false; + public bool IsTracingRefunds => false; + public bool IsTracingCode => false; + public bool IsTracingStack => false; + public bool IsTracingState => false; + public bool IsTracingStorage => false; + public bool IsTracingBlockHash => false; + public bool IsTracingAccess => false; + public bool IsTracingFees => false; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; + + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) + => throw new InvalidOperationException(ErrorMessage); + + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) + => throw new InvalidOperationException(ErrorMessage); + + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportOperationError(EvmExceptionType error) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportOperationRemainingGas(long gas) + => throw new InvalidOperationException(ErrorMessage); + + public void SetOperationMemorySize(ulong newSize) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportMemoryChange(long offset, in ReadOnlySpan data) + => throw new InvalidOperationException(ErrorMessage); + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) + => throw new InvalidOperationException(ErrorMessage); + + public void SetOperationStack(List stackTrace) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportStackPush(in ReadOnlySpan stackItem) + => throw new InvalidOperationException(ErrorMessage); + + public void SetOperationMemory(List memoryTrace) + => throw new InvalidOperationException(ErrorMessage); + + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) + => throw new InvalidOperationException(ErrorMessage); + + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportCodeChange(Address address, byte[] before, byte[] after) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportAccountRead(Address address) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) + => throw new InvalidOperationException(ErrorMessage); + public void ReportStorageRead(in StorageCell storageCell) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportActionEnd(long gas, ReadOnlyMemory output) + => throw new InvalidOperationException(ErrorMessage); + public void ReportActionError(EvmExceptionType exceptionType) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) + => throw new InvalidOperationException(ErrorMessage); + public void ReportBlockHash(Keccak blockHash) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportByteCode(byte[] byteCode) + => throw new InvalidOperationException(ErrorMessage); + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) + => throw new InvalidOperationException(ErrorMessage); + public void ReportRefund(long refund) + => throw new InvalidOperationException(ErrorMessage); + public void ReportExtraGasPressure(long extraGasPressure) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) + => throw new InvalidOperationException(ErrorMessage); + + public void ReportFees(UInt256 fees, UInt256 burntFees) + => throw new InvalidOperationException(ErrorMessage); + } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityAccountStateChange.cs b/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityAccountStateChange.cs index f02d54a9fd1..31bbe0f84ec 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityAccountStateChange.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityAccountStateChange.cs @@ -8,9 +8,9 @@ namespace Nethermind.Evm.Tracing.ParityStyle { public class ParityAccountStateChange { - public ParityStateChange? Code { get; set; } - public ParityStateChange? Balance { get; set; } - public ParityStateChange? Nonce { get; set; } - public Dictionary>? Storage { get; set; } + public ParityStateChange Code { get; set; } + public ParityStateChange Balance { get; set; } + public ParityStateChange Nonce { get; set; } + public Dictionary> Storage { get; set; } } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityLikeBlockTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityLikeBlockTracer.cs index 374d75027d2..62e6c1e8964 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityLikeBlockTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityLikeBlockTracer.cs @@ -13,7 +13,7 @@ namespace Nethermind.Evm.Tracing.ParityStyle public class ParityLikeBlockTracer : BlockTracerBase { private readonly IDictionary? _typesByTransaction; - private Block? _block; + private Block _block; private readonly ParityTraceTypes _types; public ParityLikeBlockTracer(Keccak txHash, ParityTraceTypes types) diff --git a/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityLikeTxTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityLikeTxTracer.cs index ebb8b205ea7..14791c6a469 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityLikeTxTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityLikeTxTracer.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using FastEnumUtility; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; @@ -11,7 +12,7 @@ namespace Nethermind.Evm.Tracing.ParityStyle { - public class ParityLikeTxTracer : TxTracer + public class ParityLikeTxTracer : ITxTracer { private readonly Transaction? _tx; private readonly ParityTraceTypes _parityTraceTypes; @@ -64,12 +65,20 @@ public ParityLikeTxTracer(Block block, Transaction? tx, ParityTraceTypes parityT } } - public sealed override bool IsTracingActions { get; protected set; } - public sealed override bool IsTracingReceipt { get; protected set; } - public sealed override bool IsTracingInstructions { get; protected set; } - public sealed override bool IsTracingCode { get; protected set; } - public sealed override bool IsTracingState { get; protected set; } - public sealed override bool IsTracingStorage { get; protected set; } + public bool IsTracingReceipt { get; } + public bool IsTracingActions { get; } + public bool IsTracingOpLevelStorage => false; + public bool IsTracingMemory => false; + public bool IsTracingInstructions { get; } + public bool IsTracingRefunds => false; + public bool IsTracingCode { get; } + public bool IsTracingStack => false; + public bool IsTracingState { get; } + public bool IsTracingStorage { get; } + public bool IsTracingBlockHash => false; + public bool IsTracingAccess => false; + public bool IsTracingFees => false; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; private static string GetCallType(ExecutionType executionType) { @@ -162,17 +171,14 @@ private void PushAction(ParityTraceAction action) { if (_currentAction is not null) { - action.TraceAddress = new int[_currentAction!.TraceAddress!.Length + 1]; + action.TraceAddress = new int[_currentAction.TraceAddress.Length + 1]; for (int i = 0; i < _currentAction.TraceAddress.Length; i++) { action.TraceAddress[i] = _currentAction.TraceAddress[i]; } action.TraceAddress[_currentAction.TraceAddress.Length] = _currentAction.Subtraces.Count(st => st.IncludeInTrace); - if (action.IncludeInTrace) - { - _currentAction.Subtraces.Add(action); - } + _currentAction.Subtraces.Add(action); } else { @@ -220,26 +226,26 @@ private void PopAction() _currentAction = _actionStack.Count == 0 ? null : _actionStack.Peek(); } - public override void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak stateRoot = null) { if (_currentAction is not null) { throw new InvalidOperationException($"Closing trace at level {_currentAction.TraceAddress?.Length ?? 0}"); } - if (_trace.Action!.TraceAddress!.Length == 0) + if (_trace.Action.TraceAddress.Length == 0) { _trace.Output = output; } - _trace.Action!.Result!.Output = output; + _trace.Action.Result.Output = output; } - public override void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak stateRoot = null) { if (_currentAction is not null) { - throw new InvalidOperationException($"Closing trace at level {_currentAction!.TraceAddress!.Length}"); + throw new InvalidOperationException($"Closing trace at level {_currentAction.TraceAddress.Length}"); } _trace.Output = output; @@ -247,20 +253,18 @@ public override void MarkAsFailed(Address recipient, long gasSpent, byte[] outpu // quick tx fail (before execution) if (_trace.Action is null) { - _trace.Action = new ParityTraceAction - { - From = _tx!.SenderAddress, - To = _tx.To, - Value = _tx.Value, - Input = _tx.Data.AsArray(), - Gas = _tx.GasLimit, - CallType = _tx.IsMessageCall ? "call" : "init", - Error = error - }; + _trace.Action = new ParityTraceAction(); + _trace.Action.From = _tx.SenderAddress; + _trace.Action.To = _tx.To; + _trace.Action.Value = _tx.Value; + _trace.Action.Input = _tx.Data.AsArray(); + _trace.Action.Gas = _tx.GasLimit; + _trace.Action.CallType = _tx.IsMessageCall ? "call" : "init"; + _trace.Action.Error = error; } } - public override void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) { ParityVmOperationTrace operationTrace = new(); _gasAlreadySetForCurrentOp = false; @@ -271,7 +275,7 @@ public override void StartOperation(int depth, long gas, Instruction opcode, int _currentVmTrace.Ops.Add(operationTrace); } - public override void ReportOperationError(EvmExceptionType error) + public void ReportOperationError(EvmExceptionType error) { if (error != EvmExceptionType.InvalidJumpDestination && error != EvmExceptionType.NotEnoughBalance) @@ -280,13 +284,13 @@ public override void ReportOperationError(EvmExceptionType error) } } - public override void ReportOperationRemainingGas(long gas) + public void ReportOperationRemainingGas(long gas) { if (!_gasAlreadySetForCurrentOp) { _gasAlreadySetForCurrentOp = true; - _currentOperation!.Cost -= (_treatGasParityStyle ? 0 : gas); + _currentOperation.Cost -= (_treatGasParityStyle ? 0 : gas); // based on Parity behaviour - adding stipend to the gas cost if (_currentOperation.Cost == 7400) @@ -301,25 +305,35 @@ public override void ReportOperationRemainingGas(long gas) } } - public override void ReportStackPush(in ReadOnlySpan stackItem) + public void ReportStackPush(in ReadOnlySpan stackItem) { _currentPushList.Add(stackItem.ToArray()); } - public override void ReportMemoryChange(long offset, in ReadOnlySpan data) + public void SetOperationStack(List stackTrace) => throw new NotSupportedException(); + + public void SetOperationMemory(List memoryTrace) => throw new NotSupportedException(); + + public void SetOperationMemorySize(ulong newSize) => throw new NotSupportedException(); + + public void ReportMemoryChange(long offset, in ReadOnlySpan data) { if (data.Length != 0) { - _currentOperation!.Memory = new ParityMemoryChangeTrace { Offset = offset, Data = data.ToArray() }; + _currentOperation.Memory = new ParityMemoryChangeTrace { Offset = offset, Data = data.ToArray() }; } } - public override void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) { - _currentOperation!.Store = new ParityStorageChangeTrace { Key = key.ToArray(), Value = value.ToArray() }; + _currentOperation.Store = new ParityStorageChangeTrace { Key = key.ToArray(), Value = value.ToArray() }; } - public override void ReportBalanceChange(Address address, UInt256? before, UInt256? after) + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) => throw new NotSupportedException(); + + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) => throw new NotSupportedException(); + + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) { if (_trace.StateChanges is null) { @@ -338,7 +352,7 @@ public override void ReportBalanceChange(Address address, UInt256? before, UInt2 _trace.StateChanges[address].Balance = new ParityStateChange(before, after); } - public override void ReportCodeChange(Address address, byte[] before, byte[] after) + public void ReportCodeChange(Address address, byte[] before, byte[] after) { if (_trace.StateChanges is null) { @@ -357,9 +371,9 @@ public override void ReportCodeChange(Address address, byte[] before, byte[] aft _trace.StateChanges[address].Code = new ParityStateChange(before, after); } - public override void ReportNonceChange(Address address, UInt256? before, UInt256? after) + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) { - if (!_trace.StateChanges!.ContainsKey(address)) + if (!_trace.StateChanges.ContainsKey(address)) { _trace.StateChanges[address] = new ParityAccountStateChange(); } @@ -371,15 +385,19 @@ public override void ReportNonceChange(Address address, UInt256? before, UInt256 _trace.StateChanges[address].Nonce = new ParityStateChange(before, after); } - public override void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) + public void ReportAccountRead(Address address) + { + } + + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) { - if (!_trace.StateChanges!.ContainsKey(storageCell.Address)) + Dictionary> storage; + if (!_trace.StateChanges.ContainsKey(storageCell.Address)) { _trace.StateChanges[storageCell.Address] = new ParityAccountStateChange(); } - Dictionary> storage = - _trace.StateChanges[storageCell.Address].Storage ?? (_trace.StateChanges[storageCell.Address].Storage = new Dictionary>()); + storage = _trace.StateChanges[storageCell.Address].Storage ?? (_trace.StateChanges[storageCell.Address].Storage = new Dictionary>()); if (storage.TryGetValue(storageCell.Index, out ParityStateChange value)) { @@ -389,9 +407,13 @@ public override void ReportStorageChange(in StorageCell storageCell, byte[] befo storage[storageCell.Index] = new ParityStateChange(before, after); } - public override void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) + public void ReportStorageRead(in StorageCell storageCell) { - ParityTraceAction action = new() + } + + public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) + { + ParityTraceAction action = new ParityTraceAction { IsPrecompiled = isPrecompileCall, // ignore pre compile calls with Zero value that originates from contracts @@ -428,17 +450,22 @@ public override void ReportAction(long gas, UInt256 value, Address @from, Addres } } - public override void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) { - ParityTraceAction action = new() { From = address, To = refundAddress, Value = balance, Type = "suicide" }; + ParityTraceAction action = new(); + action.From = address; + action.To = refundAddress; + action.Value = balance; + action.Type = "suicide"; + PushAction(action); - _currentAction!.Result = null; + _currentAction.Result = null; PopAction(); } - public override void ReportActionEnd(long gas, ReadOnlyMemory output) + public void ReportActionEnd(long gas, ReadOnlyMemory output) { - if (_currentAction!.Result is null) + if (_currentAction.Result is null) { throw new InvalidOperationException( $"{nameof(ReportActionEnd)} called when result is not yet prepared."); @@ -449,16 +476,16 @@ public override void ReportActionEnd(long gas, ReadOnlyMemory output) PopAction(); } - public override void ReportActionError(EvmExceptionType evmExceptionType) + public void ReportActionError(EvmExceptionType evmExceptionType) { - _currentAction!.Result = null; + _currentAction.Result = null; _currentAction.Error = GetErrorDescription(evmExceptionType); PopAction(); } - public override void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) { - if (_currentAction!.Result is null) + if (_currentAction.Result is null) { throw new InvalidOperationException( $"{nameof(ReportActionEnd)} called when result is not yet prepared."); @@ -470,14 +497,39 @@ public override void ReportActionEnd(long gas, Address deploymentAddress, ReadOn PopAction(); } - public override void ReportByteCode(byte[] byteCode) + public void ReportBlockHash(Keccak blockHash) + { + throw new NotSupportedException(); + } + + public void ReportByteCode(byte[] byteCode) { _currentVmTrace.VmTrace.Code = byteCode; } - public override void ReportGasUpdateForVmTrace(long refund, long gasAvailable) + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) + { + _currentOperation.Used = gasAvailable; + } + + public void ReportRefund(long refund) + { + throw new NotSupportedException(); + } + + public void ReportExtraGasPressure(long extraGasPressure) + { + throw new NotSupportedException(); + } + + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) + { + throw new NotImplementedException(); + } + + public void ReportFees(UInt256 fees, UInt256 burntFees) { - _currentOperation!.Used = gasAvailable; + throw new NotImplementedException(); } } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/Proofs/ProofTxTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/Proofs/ProofTxTracer.cs index 0a9beddae17..e027f8ffb7f 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/Proofs/ProofTxTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/Proofs/ProofTxTracer.cs @@ -9,7 +9,7 @@ namespace Nethermind.Evm.Tracing.Proofs { - public class ProofTxTracer : TxTracer + public class ProofTxTracer : ITxTracer { private readonly bool _treatSystemAccountDifferently; @@ -26,17 +26,57 @@ public ProofTxTracer(bool treatSystemAccountDifferently) public byte[]? Output { get; private set; } - public override bool IsTracingBlockHash => true; - public override bool IsTracingReceipt => true; - public override bool IsTracingState => true; - public override bool IsTracingStorage => true; + public bool IsTracingBlockHash => true; + public bool IsTracingAccess => false; + public bool IsTracingReceipt => true; + public bool IsTracingActions => false; + public bool IsTracingOpLevelStorage => false; + public bool IsTracingMemory => false; + public bool IsTracingInstructions => false; + public bool IsTracingRefunds => false; + public bool IsTracingCode => false; + public bool IsTracingStack => false; + public bool IsTracingState => true; + public bool IsTracingStorage => true; + public bool IsTracingFees => false; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; + + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) + { + throw new NotSupportedException(); + } - public override void ReportBlockHash(Keccak blockHash) + public void ReportBlockHash(Keccak blockHash) { BlockHashes.Add(blockHash); } - public override void ReportBalanceChange(Address address, UInt256? before, UInt256? after) + public void ReportByteCode(byte[] byteCode) + { + throw new NotSupportedException(); + } + + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) + { + throw new NotSupportedException(); + } + + public void ReportRefund(long refund) + { + throw new NotSupportedException(); + } + + public void ReportExtraGasPressure(long extraGasPressure) + { + throw new NotSupportedException(); + } + + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) + { + throw new NotImplementedException(); + } + + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) { if (_treatSystemAccountDifferently && Address.SystemUser == address && before is null && after == UInt256.Zero) { @@ -46,7 +86,7 @@ public override void ReportBalanceChange(Address address, UInt256? before, UInt2 Accounts.Add(address); } - public override void ReportCodeChange(Address address, byte[]? before, byte[]? after) + public void ReportCodeChange(Address address, byte[]? before, byte[]? after) { if (_treatSystemAccountDifferently && Address.SystemUser == address && before is null && after == Array.Empty()) { @@ -56,7 +96,7 @@ public override void ReportCodeChange(Address address, byte[]? before, byte[]? a Accounts.Add(address); } - public override void ReportNonceChange(Address address, UInt256? before, UInt256? after) + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) { if (_treatSystemAccountDifferently && Address.SystemUser == address && before is null && after == UInt256.Zero) { @@ -66,14 +106,14 @@ public override void ReportNonceChange(Address address, UInt256? before, UInt256 Accounts.Add(address); } - public override void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) { // implicit knowledge here that if we read storage then for sure we have at least asked for the account's balance // and so we do not need to add account to Accounts Storages.Add(storageCell); } - public override void ReportStorageRead(in StorageCell storageCell) + public void ReportStorageRead(in StorageCell storageCell) { // implicit knowledge here that if we read storage then for sure we have at least asked for the account's balance // and so we do not need to add account to Accounts @@ -82,7 +122,7 @@ public override void ReportStorageRead(in StorageCell storageCell) private bool _wasSystemAccountAccessedOnceAlready; - public override void ReportAccountRead(Address address) + public void ReportAccountRead(Address address) { if (_treatSystemAccountDifferently && !_wasSystemAccountAccessedOnceAlready && address == Address.SystemUser) { @@ -95,14 +135,94 @@ public override void ReportAccountRead(Address address) Accounts.Add(address); } - public override void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) { Output = output; } - public override void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) { Output = output; } + + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) + { + throw new NotSupportedException(); + } + + public void ReportOperationError(EvmExceptionType error) + { + throw new NotSupportedException(); + } + + public void ReportOperationRemainingGas(long gas) + { + throw new NotSupportedException(); + } + + public void SetOperationStack(List stackTrace) + { + throw new NotSupportedException(); + } + + public void ReportStackPush(in ReadOnlySpan stackItem) + { + throw new NotSupportedException(); + } + + public void SetOperationMemory(List memoryTrace) + { + throw new NotSupportedException(); + } + + public void SetOperationMemorySize(ulong newSize) + { + throw new NotSupportedException(); + } + + public void ReportMemoryChange(long offset, in ReadOnlySpan data) + { + throw new NotSupportedException(); + } + + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) + { + throw new NotSupportedException(); + } + + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) + { + throw new NotSupportedException(); + } + + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) + { + throw new NotSupportedException(); + } + + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) + { + throw new NotSupportedException(); + } + + public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) + { + throw new NotSupportedException(); + } + + public void ReportActionEnd(long gas, ReadOnlyMemory output) + { + throw new NotSupportedException(); + } + + public void ReportActionError(EvmExceptionType evmExceptionType) + { + throw new NotSupportedException(); + } + + public void ReportFees(UInt256 fees, UInt256 burntFees) + { + throw new NotImplementedException(); + } } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/TxTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/TxTracer.cs deleted file mode 100644 index 0944311b403..00000000000 --- a/src/Nethermind/Nethermind.Evm/Tracing/TxTracer.cs +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Int256; - -namespace Nethermind.Evm.Tracing; - -public class TxTracer : ITxTracer -{ - [SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")] - protected TxTracer() - { - IsTracing = IsTracingReceipt - || IsTracingActions - || IsTracingOpLevelStorage - || IsTracingMemory - || IsTracingInstructions - || IsTracingRefunds - || IsTracingCode - || IsTracingStack - || IsTracingBlockHash - || IsTracingAccess - || IsTracingFees; - } - public bool IsTracing { get; protected set; } - public virtual bool IsTracingState { get; protected set; } - public virtual bool IsTracingReceipt { get; protected set; } - public virtual bool IsTracingActions { get; protected set; } - public virtual bool IsTracingOpLevelStorage { get; protected set; } - public virtual bool IsTracingMemory { get; protected set; } - public virtual bool IsTracingInstructions { get; protected set; } - public virtual bool IsTracingRefunds { get; protected set; } - public virtual bool IsTracingCode { get; protected set; } - public virtual bool IsTracingStack { get; protected set; } - public virtual bool IsTracingBlockHash { get; protected set; } - public virtual bool IsTracingAccess { get; protected set; } - public virtual bool IsTracingFees { get; protected set; } - public virtual bool IsTracingStorage { get; protected set; } - public virtual void ReportBalanceChange(Address address, UInt256? before, UInt256? after) { } - public virtual void ReportCodeChange(Address address, byte[]? before, byte[]? after) { } - public virtual void ReportNonceChange(Address address, UInt256? before, UInt256? after) { } - public virtual void ReportAccountRead(Address address) { } - public virtual void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) { } - public virtual void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) { } - public virtual void ReportStorageRead(in StorageCell storageCell) { } - public virtual void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) { } - public virtual void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) { } - public virtual void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) { } - public virtual void ReportOperationError(EvmExceptionType error) { } - public virtual void ReportOperationRemainingGas(long gas) { } - public virtual void SetOperationStack(List stackTrace) { } - public virtual void ReportStackPush(in ReadOnlySpan stackItem) { } - public virtual void SetOperationMemory(IEnumerable memoryTrace) { } - public virtual void SetOperationMemorySize(ulong newSize) { } - public virtual void ReportMemoryChange(long offset, in ReadOnlySpan data) { } - public virtual void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) { } - public virtual void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) { } - public virtual void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) { } - public virtual void ReportAction(long gas, UInt256 value, Address from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) { } - public virtual void ReportActionEnd(long gas, ReadOnlyMemory output) { } - public virtual void ReportActionError(EvmExceptionType evmExceptionType) { } - public virtual void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) { } - public virtual void ReportBlockHash(Keccak blockHash) { } - public virtual void ReportByteCode(byte[] byteCode) { } - public virtual void ReportGasUpdateForVmTrace(long refund, long gasAvailable) { } - public virtual void ReportRefund(long refund) { } - public virtual void ReportExtraGasPressure(long extraGasPressure) { } - public virtual void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) { } - public virtual void ReportFees(UInt256 fees, UInt256 burntFees) { } -} diff --git a/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs b/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs index 5bba6aace32..a905242f6ca 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using Nethermind.Core; using Nethermind.Int256; @@ -19,24 +18,15 @@ tx.To is not null public static TxGasInfo GetGasInfo(this Transaction tx, bool is1559Enabled, BlockHeader header) { UInt256 effectiveGasPrice = tx.CalculateEffectiveGasPrice(is1559Enabled, header.BaseFeePerGas); - + ulong? dataGas = null; + UInt256? dataGasPrice = null; if (tx.SupportsBlobs) { - if (header.ExcessBlobGas is null) - { - throw new ArgumentException($"Block that contains Shard Blob Transactions should have {nameof(header.ExcessBlobGas)} set.", nameof(header.ExcessBlobGas)); - } - - if (!BlobGasCalculator.TryCalculateBlobGasPricePerUnit(header, out UInt256 blobGasPrice)) - { - throw new OverflowException("Blob gas price calculation led to overflow."); - } - ulong blobGas = BlobGasCalculator.CalculateBlobGas(tx); - - return new(effectiveGasPrice, blobGasPrice, blobGas); + dataGas = DataGasCalculator.CalculateDataGas(tx); + dataGasPrice = DataGasCalculator.CalculateDataGasPrice(header, tx); } - return new(effectiveGasPrice, null, null); + return new(effectiveGasPrice, dataGasPrice, dataGas); } } @@ -44,11 +34,11 @@ public struct TxGasInfo { public TxGasInfo() { } - public TxGasInfo(UInt256? effectiveGasPrice, UInt256? blobGasPrice, ulong? blobGasUsed) + public TxGasInfo(UInt256? effectiveGasPrice, UInt256? dataGasPrice, ulong? dataGasUsed) { EffectiveGasPrice = effectiveGasPrice; - BlobGasPrice = blobGasPrice; - BlobGasUsed = blobGasUsed; + DataGasPrice = dataGasPrice; + DataGasUsed = dataGasUsed; } public TxGasInfo(UInt256? effectiveGasPrice) @@ -57,7 +47,7 @@ public TxGasInfo(UInt256? effectiveGasPrice) } public UInt256? EffectiveGasPrice { get; private set; } - public UInt256? BlobGasPrice { get; private set; } - public ulong? BlobGasUsed { get; private set; } + public UInt256? DataGasPrice { get; private set; } + public ulong? DataGasUsed { get; private set; } } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs index 3583b6480b9..6c66de2e7ba 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs @@ -15,7 +15,7 @@ public BuildUpTransactionProcessorAdapter(ITransactionProcessor transactionProce _transactionProcessor = transactionProcessor; } - public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) => - _transactionProcessor.BuildUp(transaction, blkCtx, txTracer); + public void Execute(Transaction transaction, BlockHeader block, ITxTracer txTracer) => + _transactionProcessor.BuildUp(transaction, block, txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs index 7042c9337a1..8ede3451467 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs @@ -15,7 +15,7 @@ public CallAndRestoreTransactionProcessorAdapter(ITransactionProcessor transacti _transactionProcessor = transactionProcessor; } - public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) => - _transactionProcessor.CallAndRestore(transaction, blkCtx, txTracer); + public void Execute(Transaction transaction, BlockHeader block, ITxTracer txTracer) => + _transactionProcessor.CallAndRestore(transaction, block, txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs index 231950c656c..bc8948b8bba 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs @@ -22,9 +22,9 @@ public ChangeableTransactionProcessorAdapter(ITransactionProcessor transactionPr TransactionProcessor = transactionProcessor; } - public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) + public void Execute(Transaction transaction, BlockHeader block, ITxTracer txTracer) { - CurrentAdapter.Execute(transaction, blkCtx, txTracer); + CurrentAdapter.Execute(transaction, block, txTracer); } } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs index 2b4967dd3cd..c9f144a7b3f 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs @@ -15,7 +15,7 @@ public ExecuteTransactionProcessorAdapter(ITransactionProcessor transactionProce _transactionProcessor = transactionProcessor; } - public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) => - _transactionProcessor.Execute(transaction, blkCtx, txTracer); + public void Execute(Transaction transaction, BlockHeader block, ITxTracer txTracer) => + _transactionProcessor.Execute(transaction, block, txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs index 972ac5be1d8..7d8ec18031a 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs @@ -4,28 +4,29 @@ using Nethermind.Core; using Nethermind.Evm.Tracing; -namespace Nethermind.Evm.TransactionProcessing; - -public interface ITransactionProcessor +namespace Nethermind.Evm.TransactionProcessing { - /// - /// Execute transaction, commit state - /// - void Execute(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer); + public interface ITransactionProcessor + { + /// + /// Execute transaction, commit state + /// + void Execute(Transaction transaction, BlockHeader block, ITxTracer txTracer); - /// - /// Call transaction, rollback state - /// - void CallAndRestore(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer); + /// + /// Call transaction, rollback state + /// + void CallAndRestore(Transaction transaction, BlockHeader block, ITxTracer txTracer); - /// - /// Execute transaction, keep the state uncommitted - /// - void BuildUp(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer); + /// + /// Execute transaction, keep the state uncommitted + /// + void BuildUp(Transaction transaction, BlockHeader block, ITxTracer txTracer); - /// - /// Call transaction, no validations, commit state - /// Will NOT charge gas from sender account, so stateDiff will miss gas fee - /// - void Trace(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer); + /// + /// Call transaction, no validations, commit state + /// Will NOT charge gas from sender account, so stateDiff will miss gas fee + /// + void Trace(Transaction transaction, BlockHeader block, ITxTracer txTracer); + } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs index 06ab48f127e..a502c273267 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs @@ -8,6 +8,6 @@ namespace Nethermind.Evm.TransactionProcessing { public interface ITransactionProcessorAdapter { - void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer); + void Execute(Transaction transaction, BlockHeader block, ITxTracer txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ReadOnlyTransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ReadOnlyTransactionProcessor.cs index 55b484af884..09cda3ea1ca 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ReadOnlyTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ReadOnlyTransactionProcessor.cs @@ -4,6 +4,7 @@ using System; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Db; using Nethermind.Evm.Tracing; using Nethermind.State; @@ -23,17 +24,17 @@ public ReadOnlyTransactionProcessor(ITransactionProcessor transactionProcessor, _stateProvider.StateRoot = startState ?? throw new ArgumentNullException(nameof(startState)); } - public void Execute(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) => - _transactionProcessor.Execute(transaction, blCtx, txTracer); + public void Execute(Transaction transaction, BlockHeader block, ITxTracer txTracer) => + _transactionProcessor.Execute(transaction, block, txTracer); - public void CallAndRestore(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) => - _transactionProcessor.CallAndRestore(transaction, blCtx, txTracer); + public void CallAndRestore(Transaction transaction, BlockHeader block, ITxTracer txTracer) => + _transactionProcessor.CallAndRestore(transaction, block, txTracer); - public void BuildUp(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) => - _transactionProcessor.BuildUp(transaction, blCtx, txTracer); + public void BuildUp(Transaction transaction, BlockHeader block, ITxTracer txTracer) => + _transactionProcessor.BuildUp(transaction, block, txTracer); - public void Trace(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) => - _transactionProcessor.Trace(transaction, blCtx, txTracer); + public void Trace(Transaction transaction, BlockHeader block, ITxTracer txTracer) => + _transactionProcessor.Trace(transaction, block, txTracer); public bool IsContractDeployed(Address address) => _stateProvider.IsContract(address); diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs index 3b51b89ccee..7ae895330fa 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs @@ -15,7 +15,7 @@ public TraceTransactionProcessorAdapter(ITransactionProcessor transactionProcess _transactionProcessor = transactionProcessor; } - public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) => - _transactionProcessor.Trace(transaction, blkCtx, txTracer); + public void Execute(Transaction transaction, BlockHeader block, ITxTracer txTracer) => + _transactionProcessor.Trace(transaction, block, txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index 5ee2d4f5181..23276507354 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -4,10 +4,10 @@ using System; using System.IO; using System.Linq; -using System.Runtime.CompilerServices; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using static Nethermind.Core.Extensions.MemoryExtensions; using Nethermind.Crypto; using Nethermind.Evm.CodeAnalysis; using Nethermind.Evm.Tracing; @@ -16,9 +16,6 @@ using Nethermind.Specs; using Nethermind.State; using Nethermind.State.Tracing; -using static Nethermind.Core.Extensions.MemoryExtensions; - -using static Nethermind.Evm.VirtualMachine; namespace Nethermind.Evm.TransactionProcessing { @@ -31,7 +28,7 @@ public class TransactionProcessor : ITransactionProcessor private readonly IVirtualMachine _virtualMachine; [Flags] - protected enum ExecutionOptions + private enum ExecutionOptions { /// /// Just accumulate the state @@ -72,136 +69,31 @@ public TransactionProcessor( _ecdsa = new EthereumEcdsa(specProvider.ChainId, logManager); } - public void CallAndRestore(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) + public void CallAndRestore(Transaction transaction, BlockHeader block, ITxTracer txTracer) { - Execute(transaction, blCtx, txTracer, ExecutionOptions.CommitAndRestore); + Execute(transaction, block, txTracer, ExecutionOptions.CommitAndRestore); } - public void BuildUp(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) + public void BuildUp(Transaction transaction, BlockHeader block, ITxTracer txTracer) { // we need to treat the result of previous transaction as the original value of next transaction // when we do not commit _worldState.TakeSnapshot(true); - Execute(transaction, blCtx, txTracer, ExecutionOptions.None); + Execute(transaction, block, txTracer, ExecutionOptions.None); } - public void Execute(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) + public void Execute(Transaction transaction, BlockHeader block, ITxTracer txTracer) { - Execute(transaction, blCtx, txTracer, ExecutionOptions.Commit); + Execute(transaction, block, txTracer, ExecutionOptions.Commit); } - public void Trace(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) + public void Trace(Transaction transaction, BlockHeader block, ITxTracer txTracer) { - Execute(transaction, blCtx, txTracer, ExecutionOptions.NoValidation); - } - - protected virtual void Execute(Transaction tx, BlockExecutionContext blCtx, ITxTracer tracer, ExecutionOptions opts) - { - BlockHeader header = blCtx.Header; - IReleaseSpec spec = _specProvider.GetSpec(header); - if (tx.IsSystem()) - spec = new SystemTransactionReleaseSpec(spec); - - // restore is CallAndRestore - previous call, we will restore state after the execution - bool restore = opts.HasFlag(ExecutionOptions.Restore); - // commit - is for standard execute, we will commit thee state after execution - // !commit - is for build up during block production, we won't commit state after each transaction to support rollbacks - // we commit only after all block is constructed - bool commit = opts.HasFlag(ExecutionOptions.Commit) || !spec.IsEip658Enabled; - - if (!ValidateStatic(tx, header, spec, tracer, opts, out long intrinsicGas)) - return; - - UInt256 effectiveGasPrice = - tx.CalculateEffectiveGasPrice(spec.IsEip1559Enabled, header.BaseFeePerGas); - - if (opts == ExecutionOptions.Commit || opts == ExecutionOptions.None) - { - decimal gasPrice = (decimal)effectiveGasPrice / 1_000_000_000m; - Metrics.MinGasPrice = Math.Min(gasPrice, Metrics.MinGasPrice); - Metrics.MaxGasPrice = Math.Max(gasPrice, Metrics.MaxGasPrice); - - Metrics.BlockMinGasPrice = Math.Min(gasPrice, Metrics.BlockMinGasPrice); - Metrics.BlockMaxGasPrice = Math.Max(gasPrice, Metrics.BlockMaxGasPrice); - - Metrics.AveGasPrice = (Metrics.AveGasPrice * Metrics.Transactions + gasPrice) / (Metrics.Transactions + 1); - Metrics.EstMedianGasPrice += Metrics.AveGasPrice * 0.01m * decimal.Sign(gasPrice - Metrics.EstMedianGasPrice); - Metrics.Transactions++; - - Metrics.BlockAveGasPrice = (Metrics.BlockAveGasPrice * Metrics.BlockTransactions + gasPrice) / (Metrics.BlockTransactions + 1); - Metrics.BlockEstMedianGasPrice += Metrics.BlockAveGasPrice * 0.01m * decimal.Sign(gasPrice - Metrics.BlockEstMedianGasPrice); - Metrics.BlockTransactions++; - } - - bool deleteCallerAccount = RecoverSenderIfNeeded(tx, spec, opts, effectiveGasPrice); - - if (!ValidateSender(tx, header, spec, tracer, opts)) - return; - - if (!BuyGas(tx, header, spec, tracer, opts, effectiveGasPrice, out UInt256 premiumPerGas, out UInt256 senderReservedGasPayment)) - return; - - if (!IncrementNonce(tx, header, spec, tracer, opts)) - return; - - if (commit) - _worldState.Commit(spec, tracer.IsTracingState ? tracer : NullTxTracer.Instance); - - ExecutionEnvironment env = BuildExecutionEnvironmnet(tx, blCtx, spec, tracer, opts, effectiveGasPrice); - - long gasAvailable = tx.GasLimit - intrinsicGas; - if (!ExecuteEVMCall(tx, header, spec, tracer, opts, gasAvailable, env, out TransactionSubstate? substate, out long spentGas, out byte statusCode)) - return; - - if (!PayFees(tx, header, spec, tracer, substate, spentGas, premiumPerGas, statusCode)) - return; - - // Finalize - if (restore) - { - _worldState.Reset(); - if (deleteCallerAccount) - { - _worldState.DeleteAccount(tx.SenderAddress); - } - else - { - if (!opts.HasFlag(ExecutionOptions.NoValidation)) - _worldState.AddToBalance(tx.SenderAddress, senderReservedGasPayment, spec); - if (!tx.IsSystem()) - _worldState.DecrementNonce(tx.SenderAddress); - - _worldState.Commit(spec); - } - } - else if (commit) - { - _worldState.Commit(spec, tracer.IsTracingState ? tracer : NullStateTracer.Instance); - } - - if (tracer.IsTracingReceipt) - { - Keccak stateRoot = null; - if (!spec.IsEip658Enabled) - { - _worldState.RecalculateStateRoot(); - stateRoot = _worldState.StateRoot; - } - - if (statusCode == StatusCode.Failure) - { - byte[] output = (substate?.ShouldRevert ?? false) ? substate.Output.ToArray() : Array.Empty(); - tracer.MarkAsFailed(env.ExecutingAccount, spentGas, output, substate?.Error, stateRoot); - } - else - { - LogEntry[] logs = substate.Logs.Any() ? substate.Logs.ToArray() : Array.Empty(); - tracer.MarkAsSuccess(env.ExecutingAccount, spentGas, substate.Output.ToArray(), logs, stateRoot); - } - } + Execute(transaction, block, txTracer, ExecutionOptions.NoValidation); } - private void QuickFail(Transaction tx, BlockHeader block, IReleaseSpec spec, ITxTracer txTracer, string? reason) + private void QuickFail(Transaction tx, BlockHeader block, ITxTracer txTracer, bool eip658NotEnabled, + string? reason) { block.GasUsed += tx.GasLimit; @@ -212,7 +104,7 @@ private void QuickFail(Transaction tx, BlockHeader block, IReleaseSpec spec, ITx if (txTracer.IsTracingReceipt) { Keccak? stateRoot = null; - if (!spec.IsEip658Enabled) + if (eip658NotEnabled) { _worldState.RecalculateStateRoot(); stateRoot = _worldState.StateRoot; @@ -222,322 +114,260 @@ private void QuickFail(Transaction tx, BlockHeader block, IReleaseSpec spec, ITx } } - - /// - /// Validates the transaction, in a static manner (i.e. without accesing state/storage). - /// It basically ensures the transaction is well formed (i.e. no null values where not allowed, no overflows, etc). - /// As a part of validating the transaction the premium per gas will be calculated, to save computation this - /// is returned in an out parameter. - /// - /// The transaction to validate - /// The block containing the transaction. Only BaseFee is being used from the block atm. - /// The release spec with which the transaction will be executed - /// The transaction tracer - /// Options (Flags) to use for execution - /// Computed premium per gas - /// - protected virtual bool ValidateStatic(Transaction tx, BlockHeader header, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts, out long intrinsicGas) + private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTracer, + ExecutionOptions executionOptions) { - intrinsicGas = IntrinsicGasCalculator.Calculate(tx, spec); + IReleaseSpec spec = _specProvider.GetSpec(block); + bool eip658NotEnabled = !spec.IsEip658Enabled; - bool validate = !opts.HasFlag(ExecutionOptions.NoValidation); + // restore is CallAndRestore - previous call, we will restore state after the execution + bool restore = (executionOptions & ExecutionOptions.Restore) == ExecutionOptions.Restore; + bool noValidation = (executionOptions & ExecutionOptions.NoValidation) == ExecutionOptions.NoValidation; + // commit - is for standard execute, we will commit thee state after execution + bool commit = (executionOptions & ExecutionOptions.Commit) == ExecutionOptions.Commit || eip658NotEnabled; + //!commit - is for build up during block production, we won't commit state after each transaction to support rollbacks + //we commit only after all block is constructed + bool notSystemTransaction = !transaction.IsSystem(); + bool deleteCallerAccount = false; - if (tx.SenderAddress is null) + if (!notSystemTransaction) { - TraceLogInvalidTx(tx, "SENDER_NOT_SPECIFIED"); - QuickFail(tx, header, spec, tracer, "sender not specified"); - return false; + spec = new SystemTransactionReleaseSpec(spec); } - if (validate && tx.Nonce >= ulong.MaxValue - 1) + UInt256 value = transaction.Value; + + if (!transaction.TryCalculatePremiumPerGas(block.BaseFeePerGas, out UInt256 premiumPerGas) && !noValidation) + { + TraceLogInvalidTx(transaction, "MINER_PREMIUM_IS_NEGATIVE"); + QuickFail(transaction, block, txTracer, eip658NotEnabled, "miner premium is negative"); + return; + } + + UInt256 effectiveGasPrice = + transaction.CalculateEffectiveGasPrice(spec.IsEip1559Enabled, block.BaseFeePerGas); + + long gasLimit = transaction.GasLimit; + byte[] machineCode = transaction.IsContractCreation ? transaction.Data.AsArray() : null; + byte[] data = transaction.IsMessageCall ? transaction.Data.AsArray() : Array.Empty(); + + Address? caller = transaction.SenderAddress; + if (_logger.IsTrace) _logger.Trace($"Executing tx {transaction.Hash}"); + + if (caller is null) + { + TraceLogInvalidTx(transaction, "SENDER_NOT_SPECIFIED"); + QuickFail(transaction, block, txTracer, eip658NotEnabled, "sender not specified"); + return; + } + + if (!noValidation && _worldState.IsInvalidContractSender(spec, caller)) + { + TraceLogInvalidTx(transaction, "SENDER_IS_CONTRACT"); + QuickFail(transaction, block, txTracer, eip658NotEnabled, "sender has deployed code"); + return; + } + + if (!noValidation && transaction.Nonce >= ulong.MaxValue - 1) { // we are here if nonce is at least (ulong.MaxValue - 1). If tx is contract creation, // it is max possible value. Otherwise, (ulong.MaxValue - 1) is allowed, but ulong.MaxValue not. - if (tx.IsContractCreation || tx.Nonce == ulong.MaxValue) + if (transaction.IsContractCreation || transaction.Nonce == ulong.MaxValue) { - TraceLogInvalidTx(tx, "NONCE_OVERFLOW"); - QuickFail(tx, header, spec, tracer, "nonce overflow"); - return false; + TraceLogInvalidTx(transaction, "NONCE_OVERFLOW"); + QuickFail(transaction, block, txTracer, eip658NotEnabled, "nonce overflow"); + return; } } - if (tx.IsAboveInitCode(spec)) + if (transaction.IsAboveInitCode(spec)) { - TraceLogInvalidTx(tx, $"CREATE_TRANSACTION_SIZE_EXCEEDS_MAX_INIT_CODE_SIZE {tx.DataLength} > {spec.MaxInitCodeSize}"); - QuickFail(tx, header, spec, tracer, "EIP-3860 - transaction size over max init code size"); - return false; + TraceLogInvalidTx(transaction, $"CREATE_TRANSACTION_SIZE_EXCEEDS_MAX_INIT_CODE_SIZE {transaction.DataLength} > {spec.MaxInitCodeSize}"); + QuickFail(transaction, block, txTracer, eip658NotEnabled, "EIP-3860 - transaction size over max init code size"); + return; } - if (!tx.IsSystem()) + long intrinsicGas = IntrinsicGasCalculator.Calculate(transaction, spec); + if (_logger.IsTrace) _logger.Trace($"Intrinsic gas calculated for {transaction.Hash}: " + intrinsicGas); + + if (notSystemTransaction) { - if (tx.GasLimit < intrinsicGas) + if (gasLimit < intrinsicGas) { - TraceLogInvalidTx(tx, $"GAS_LIMIT_BELOW_INTRINSIC_GAS {tx.GasLimit} < {intrinsicGas}"); - QuickFail(tx, header, spec, tracer, "gas limit below intrinsic gas"); - return false; + TraceLogInvalidTx(transaction, $"GAS_LIMIT_BELOW_INTRINSIC_GAS {gasLimit} < {intrinsicGas}"); + QuickFail(transaction, block, txTracer, eip658NotEnabled, "gas limit below intrinsic gas"); + return; } - if (validate && tx.GasLimit > header.GasLimit - header.GasUsed) + if (!noValidation && gasLimit > block.GasLimit - block.GasUsed) { - TraceLogInvalidTx(tx, $"BLOCK_GAS_LIMIT_EXCEEDED {tx.GasLimit} > {header.GasLimit} - {header.GasUsed}"); - QuickFail(tx, header, spec, tracer, "block gas limit exceeded"); - return false; + TraceLogInvalidTx(transaction, + $"BLOCK_GAS_LIMIT_EXCEEDED {gasLimit} > {block.GasLimit} - {block.GasUsed}"); + QuickFail(transaction, block, txTracer, eip658NotEnabled, "block gas limit exceeded"); + return; } } - return true; - } - - // TODO Should we remove this already - private bool RecoverSenderIfNeeded(Transaction tx, IReleaseSpec spec, ExecutionOptions opts, in UInt256 effectiveGasPrice) - { - bool commit = opts.HasFlag(ExecutionOptions.Commit) || !spec.IsEip658Enabled; - bool restore = opts.HasFlag(ExecutionOptions.Restore); - bool noValidation = opts.HasFlag(ExecutionOptions.NoValidation); - - bool deleteCallerAccount = false; - - if (!_worldState.AccountExists(tx.SenderAddress)) + if (!_worldState.AccountExists(caller)) { - if (_logger.IsDebug) _logger.Debug($"TX sender account does not exist {tx.SenderAddress} - trying to recover it"); - - Address prevSender = tx.SenderAddress; // hacky fix for the potential recovery issue - if (tx.Signature is not null) - tx.SenderAddress = _ecdsa.RecoverAddress(tx, !spec.ValidateChainId); + if (transaction.Signature is not null) + { + transaction.SenderAddress = _ecdsa.RecoverAddress(transaction, !spec.ValidateChainId); + } - if (prevSender != tx.SenderAddress) + if (caller != transaction.SenderAddress) { if (_logger.IsWarn) - _logger.Warn($"TX recovery issue fixed - tx was coming with sender {prevSender} and the now it recovers to {tx.SenderAddress}"); + _logger.Warn( + $"TX recovery issue fixed - tx was coming with sender {caller} and the now it recovers to {transaction.SenderAddress}"); + caller = transaction.SenderAddress; } else { - TraceLogInvalidTx(tx, $"SENDER_ACCOUNT_DOES_NOT_EXIST {tx.SenderAddress}"); + TraceLogInvalidTx(transaction, $"SENDER_ACCOUNT_DOES_NOT_EXIST {caller}"); if (!commit || noValidation || effectiveGasPrice == UInt256.Zero) { deleteCallerAccount = !commit || restore; - _worldState.CreateAccount(tx.SenderAddress, UInt256.Zero); + _worldState.CreateAccount(caller, UInt256.Zero); } } - if (tx.SenderAddress is null) + if (caller is null) { - throw new InvalidDataException($"Failed to recover sender address on tx {tx.Hash} when previously recovered sender account did not exist."); + throw new InvalidDataException( + $"Failed to recover sender address on tx {transaction.Hash} when previously recovered sender account did not exist."); } } - return deleteCallerAccount; - } - - - protected virtual bool ValidateSender(Transaction tx, BlockHeader header, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts) - { - bool validate = !opts.HasFlag(ExecutionOptions.NoValidation); - - if (validate && _worldState.IsInvalidContractSender(spec, tx.SenderAddress)) - { - TraceLogInvalidTx(tx, "SENDER_IS_CONTRACT"); - QuickFail(tx, header, spec, tracer, "sender has deployed code"); - return false; - } - - return true; - } + UInt256 dataGasPrice = spec.IsEip4844Enabled + ? DataGasCalculator.CalculateDataGasPrice(block, transaction) + : UInt256.Zero; - private bool BuyGas(Transaction tx, BlockHeader header, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts, - in UInt256 effectiveGasPrice, out UInt256 premiumPerGas, out UInt256 senderReservedGasPayment) - { - premiumPerGas = UInt256.Zero; - senderReservedGasPayment = UInt256.Zero; - bool validate = !opts.HasFlag(ExecutionOptions.NoValidation); + UInt256 senderReservedGasPayment = (ulong)gasLimit * effectiveGasPrice + dataGasPrice; - if (!tx.IsSystem() && validate) + if (notSystemTransaction) { - if (!tx.TryCalculatePremiumPerGas(header.BaseFeePerGas, out premiumPerGas)) + UInt256 senderBalance = _worldState.GetBalance(caller); + if (!noValidation && ((ulong)intrinsicGas * effectiveGasPrice + value + dataGasPrice > senderBalance || + senderReservedGasPayment + value > senderBalance)) { - TraceLogInvalidTx(tx, "MINER_PREMIUM_IS_NEGATIVE"); - QuickFail(tx, header, spec, tracer, "miner premium is negative"); - return false; + TraceLogInvalidTx(transaction, + $"INSUFFICIENT_SENDER_BALANCE: ({caller})_BALANCE = {senderBalance}"); + QuickFail(transaction, block, txTracer, eip658NotEnabled, "insufficient sender balance"); + return; } - UInt256 senderBalance = _worldState.GetBalance(tx.SenderAddress); - if (UInt256.SubtractUnderflow(senderBalance, tx.Value, out UInt256 balanceLeft)) + if (!noValidation && spec.IsEip1559Enabled && !transaction.IsFree() && + (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + value + dataGasPrice > senderBalance) { - TraceLogInvalidTx(tx, $"INSUFFICIENT_SENDER_BALANCE: ({tx.SenderAddress})_BALANCE = {senderBalance}"); - QuickFail(tx, header, spec, tracer, "insufficient sender balance"); - return false; - } - - - bool overflows; - if (spec.IsEip1559Enabled && !tx.IsFree()) - { - overflows = UInt256.MultiplyOverflow((UInt256)tx.GasLimit, tx.MaxFeePerGas, out UInt256 maxGasFee); - if (overflows || balanceLeft < maxGasFee) - { - TraceLogInvalidTx(tx, $"INSUFFICIENT_MAX_FEE_PER_GAS_FOR_SENDER_BALANCE: ({tx.SenderAddress})_BALANCE = {senderBalance}, MAX_FEE_PER_GAS: {tx.MaxFeePerGas}"); - QuickFail(tx, header, spec, tracer, "insufficient MaxFeePerGas for sender balance"); - return false; - } - if (tx.SupportsBlobs) - { - overflows = UInt256.MultiplyOverflow(BlobGasCalculator.CalculateBlobGas(tx), (UInt256)tx.MaxFeePerBlobGas, out UInt256 maxBlobGasFee); - if (overflows || UInt256.AddOverflow(maxGasFee, maxBlobGasFee, out UInt256 multidimGasFee) || multidimGasFee > balanceLeft) - { - TraceLogInvalidTx(tx, $"INSUFFICIENT_MAX_FEE_PER_BLOB_GAS_FOR_SENDER_BALANCE: ({tx.SenderAddress})_BALANCE = {senderBalance}"); - QuickFail(tx, header, spec, tracer, "insufficient sender balance"); - return false; - } - } + TraceLogInvalidTx(transaction, + $"INSUFFICIENT_MAX_FEE_PER_GAS_FOR_SENDER_BALANCE: ({caller})_BALANCE = {senderBalance}, MAX_FEE_PER_GAS: {transaction.MaxFeePerGas}"); + QuickFail(transaction, block, txTracer, eip658NotEnabled, + "insufficient MaxFeePerGas for sender balance"); + return; } - overflows = UInt256.MultiplyOverflow((UInt256)tx.GasLimit, effectiveGasPrice, out senderReservedGasPayment); - if (!overflows && tx.SupportsBlobs) + if (transaction.Nonce != _worldState.GetNonce(caller)) { - overflows = !BlobGasCalculator.TryCalculateBlobGasPrice(header, tx, out UInt256 blobGasFee); - if (!overflows) - { - overflows = UInt256.AddOverflow(senderReservedGasPayment, blobGasFee, out senderReservedGasPayment); - } + TraceLogInvalidTx(transaction, + $"WRONG_TRANSACTION_NONCE: {transaction.Nonce} (expected {_worldState.GetNonce(caller)})"); + QuickFail(transaction, block, txTracer, eip658NotEnabled, "wrong transaction nonce"); + return; } - if (overflows || senderReservedGasPayment > balanceLeft) - { - TraceLogInvalidTx(tx, $"INSUFFICIENT_SENDER_BALANCE: ({tx.SenderAddress})_BALANCE = {senderBalance}"); - QuickFail(tx, header, spec, tracer, "insufficient sender balance"); - return false; - } + _worldState.IncrementNonce(caller); } - if (validate) - _worldState.SubtractFromBalance(tx.SenderAddress, senderReservedGasPayment, spec); - - return true; - } - - protected virtual bool IncrementNonce(Transaction tx, BlockHeader header, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts) - { - if (tx.IsSystem()) - return true; - - if (tx.Nonce != _worldState.GetNonce(tx.SenderAddress)) + // Do not charge gas if noValidation is set + if (!noValidation) _worldState.SubtractFromBalance(caller, senderReservedGasPayment, spec); + if (commit) { - TraceLogInvalidTx(tx, $"WRONG_TRANSACTION_NONCE: {tx.Nonce} (expected {_worldState.GetNonce(tx.SenderAddress)})"); - QuickFail(tx, header, spec, tracer, "wrong transaction nonce"); - return false; + _worldState.Commit(spec, txTracer.IsTracingState ? txTracer : NullTxTracer.Instance); } - _worldState.IncrementNonce(tx.SenderAddress); - return true; - } - - protected virtual ExecutionEnvironment BuildExecutionEnvironmnet( - Transaction tx, BlockExecutionContext blCtx, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts, - in UInt256 effectiveGasPrice) - { - Address recipient = tx.GetRecipient(tx.IsContractCreation ? _worldState.GetNonce(tx.SenderAddress) : 0) ?? - // this transaction is not a contract creation so it should have the recipient known and not null - throw new InvalidDataException("Recipient has not been resolved properly before tx execution"); - - TxExecutionContext executionContext = - new(blCtx, tx.SenderAddress, effectiveGasPrice, tx.BlobVersionedHashes); - - CodeInfo codeInfo = tx.IsContractCreation ? new(tx.Data.AsArray()) - : _virtualMachine.GetCachedCodeInfo(_worldState, recipient, spec); - - byte[] inputData = tx.IsMessageCall ? tx.Data.AsArray() ?? Array.Empty() : Array.Empty(); - - return new ExecutionEnvironment - ( - txExecutionContext: executionContext, - value: tx.Value, - transferValue: tx.Value, - caller: tx.SenderAddress, - codeSource: recipient, - executingAccount: recipient, - inputData: inputData, - codeInfo: codeInfo - ); - } - - protected virtual bool ExecuteEVMCall( - Transaction tx, BlockHeader header, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts, - in long gasAvailable, in ExecutionEnvironment env, - out TransactionSubstate? substate, out long spentGas, out byte statusCode) - { - bool validate = !opts.HasFlag(ExecutionOptions.NoValidation); - - substate = null; - spentGas = tx.GasLimit; - statusCode = StatusCode.Failure; - - long unspentGas = gasAvailable; + long unspentGas = gasLimit - intrinsicGas; + long spentGas = gasLimit; Snapshot snapshot = _worldState.TakeSnapshot(); + // Fixes eth_estimateGas. If sender is systemUser subtracting value will cause InsufficientBalanceException + if (!noValidation || notSystemTransaction) _worldState.SubtractFromBalance(caller, value, spec); + byte statusCode = StatusCode.Failure; + TransactionSubstate substate = null; - // Fixes eth_estimateGas. - // If sender is SystemUser subtracting value will cause InsufficientBalanceException - if (validate || !tx.IsSystem()) - _worldState.SubtractFromBalance(tx.SenderAddress, tx.Value, spec); - + Address? recipientOrNull = null; try { - if (tx.IsContractCreation) + Address? recipient = + transaction.GetRecipient(transaction.IsContractCreation ? _worldState.GetNonce(caller) : 0); + if (transaction.IsContractCreation) { // if transaction is a contract creation then recipient address is the contract deployment address - PrepareAccountForContractDeployment(env.ExecutingAccount, spec); + Address contractAddress = recipient; + PrepareAccountForContractDeployment(contractAddress!, spec); } - ExecutionType executionType = - tx.IsContractCreation ? ExecutionType.Create : ExecutionType.Transaction; + if (recipient is null) + { + // this transaction is not a contract creation so it should have the recipient known and not null + throw new InvalidDataException("Recipient has not been resolved properly before tx execution"); + } - using (EvmState state = new(unspentGas, env, executionType, true, snapshot, false)) + recipientOrNull = recipient; + + ExecutionEnvironment env = new + ( + txExecutionContext: new TxExecutionContext(block, caller, effectiveGasPrice, transaction.BlobVersionedHashes), + value: value, + transferValue: value, + caller: caller, + codeSource: recipient, + executingAccount: recipient, + inputData: data ?? Array.Empty(), + codeInfo: machineCode is null + ? _virtualMachine.GetCachedCodeInfo(_worldState, recipient, spec) + : new CodeInfo(machineCode) + ); + ExecutionType executionType = + transaction.IsContractCreation ? ExecutionType.Create : ExecutionType.Transaction; + using (EvmState state = + new(unspentGas, env, executionType, true, snapshot, false)) { if (spec.UseTxAccessLists) { - state.WarmUp(tx.AccessList); // eip-2930 + state.WarmUp(transaction.AccessList); // eip-2930 } if (spec.UseHotAndColdStorage) { - state.WarmUp(tx.SenderAddress); // eip-2929 - state.WarmUp(env.ExecutingAccount); // eip-2929 + state.WarmUp(caller); // eip-2929 + state.WarmUp(recipient); // eip-2929 } if (spec.AddCoinbaseToTxAccessList) { - state.WarmUp(header.GasBeneficiary); - } - - if (!tracer.IsTracingActions) - { - substate = _virtualMachine.Run(state, _worldState, tracer); - } - else - { - substate = _virtualMachine.Run(state, _worldState, tracer); + state.WarmUp(block.GasBeneficiary); } + substate = _virtualMachine.Run(state, _worldState, txTracer); unspentGas = state.GasAvailable; - if (tracer.IsTracingAccess) + if (txTracer.IsTracingAccess) { - tracer.ReportAccess(state.AccessedAddresses, state.AccessedStorageCells); + txTracer.ReportAccess(state.AccessedAddresses, state.AccessedStorageCells); } } if (substate.ShouldRevert || substate.IsError) { - if (_logger.IsTrace) - _logger.Trace("Restoring state from before transaction"); + if (_logger.IsTrace) _logger.Trace("Restoring state from before transaction"); _worldState.Restore(snapshot); } else { // tks: there is similar code fo contract creation from init and from CREATE // this may lead to inconsistencies (however it is tested extensively in blockchain tests) - if (tx.IsContractCreation) + if (transaction.IsContractCreation) { long codeDepositGasCost = CodeDepositHandler.CalculateCost(substate.Output.Length, spec); if (unspentGas < codeDepositGasCost && spec.ChargeForTopLevelCreate) @@ -552,63 +382,122 @@ protected virtual bool ExecuteEVMCall( if (unspentGas >= codeDepositGasCost) { - _worldState.InsertCode(env.ExecutingAccount, substate.Output, spec); + _worldState.InsertCode(recipient, substate.Output, spec); unspentGas -= codeDepositGasCost; } } foreach (Address toBeDestroyed in substate.DestroyList) { - if (_logger.IsTrace) - _logger.Trace($"Destroying account {toBeDestroyed}"); - + if (_logger.IsTrace) _logger.Trace($"Destroying account {toBeDestroyed}"); _worldState.ClearStorage(toBeDestroyed); _worldState.DeleteAccount(toBeDestroyed); - - if (tracer.IsTracingRefunds) - tracer.ReportRefund(RefundOf.Destroy(spec.IsEip3529Enabled)); + if (txTracer.IsTracingRefunds) txTracer.ReportRefund(RefundOf.Destroy(spec.IsEip3529Enabled)); } statusCode = StatusCode.Success; } - spentGas = Refund(tx.GasLimit, unspentGas, substate, tx.SenderAddress, env.TxExecutionContext.GasPrice, opts, spec); + spentGas = Refund(gasLimit, unspentGas, substate, caller, effectiveGasPrice, noValidation, spec); } - catch (Exception ex) when (ex is EvmException || ex is OverflowException) // TODO: OverflowException? still needed? hope not + catch (Exception ex) when ( + ex is EvmException || ex is OverflowException) // TODO: OverflowException? still needed? hope not { - if (_logger.IsTrace) - _logger.Trace($"EVM EXCEPTION: {ex.GetType().Name}"); + if (_logger.IsTrace) _logger.Trace($"EVM EXCEPTION: {ex.GetType().Name}"); _worldState.Restore(snapshot); } - if (validate && !tx.IsSystem()) - header.GasUsed += spentGas; - - return true; - } - - protected bool PayFees(Transaction tx, BlockHeader header, IReleaseSpec spec, ITxTracer tracer, in TransactionSubstate substate, in long spentGas, in UInt256 premiumPerGas, in byte statusCode) - { - if (tx.IsSystem()) - return true; + if (_logger.IsTrace) _logger.Trace("Gas spent: " + spentGas); - bool gasBeneficiaryNotDestroyed = substate?.DestroyList.Contains(header.GasBeneficiary) != true; + Address gasBeneficiary = block.GasBeneficiary; + bool gasBeneficiaryNotDestroyed = substate?.DestroyList.Contains(gasBeneficiary) != true; if (statusCode == StatusCode.Failure || gasBeneficiaryNotDestroyed) { + if (notSystemTransaction) + { + UInt256 fees = (ulong)spentGas * premiumPerGas; + if (_worldState.AccountExists(gasBeneficiary)) + { + _worldState.AddToBalance(gasBeneficiary, fees, spec); + } + else + { + _worldState.CreateAccount(gasBeneficiary, fees); + } - UInt256 fees = (UInt256)spentGas * premiumPerGas; - UInt256 burntFees = !tx.IsFree() ? (UInt256)spentGas * header.BaseFeePerGas : 0; + UInt256 burntFees = !transaction.IsFree() ? (ulong)spentGas * block.BaseFeePerGas : 0; - _worldState.AddToBalanceAndCreateIfNotExists(header.GasBeneficiary, fees, spec); + if (spec.IsEip1559Enabled && spec.Eip1559FeeCollector is not null) + { + if (!burntFees.IsZero) + { + if (_worldState.AccountExists(spec.Eip1559FeeCollector)) + { + _worldState.AddToBalance(spec.Eip1559FeeCollector, burntFees, spec); + } + else + { + _worldState.CreateAccount(spec.Eip1559FeeCollector, burntFees); + } + } + } - if (spec.IsEip1559Enabled && spec.Eip1559FeeCollector is not null && !burntFees.IsZero) - _worldState.AddToBalanceAndCreateIfNotExists(spec.Eip1559FeeCollector, burntFees, spec); ; + if (txTracer.IsTracingFees) + { + txTracer.ReportFees(fees, burntFees); + } + } + } - if (tracer.IsTracingFees) - tracer.ReportFees(fees, burntFees); + if (restore) + { + _worldState.Reset(); + if (deleteCallerAccount) + { + _worldState.DeleteAccount(caller); + } + else + { + if (!noValidation) _worldState.AddToBalance(caller, senderReservedGasPayment, spec); + if (notSystemTransaction) + { + _worldState.DecrementNonce(caller); + } + + _worldState.Commit(spec); + } + } + else if (commit) + { + _worldState.Commit(spec, txTracer.IsTracingState ? txTracer : NullStateTracer.Instance); } - return true; + if (!noValidation && notSystemTransaction) + { + block.GasUsed += spentGas; + } + + if (txTracer.IsTracingReceipt) + { + Keccak stateRoot = null; + if (eip658NotEnabled) + { + _worldState.RecalculateStateRoot(); + stateRoot = _worldState.StateRoot; + } + + if (statusCode == StatusCode.Failure) + { + txTracer.MarkAsFailed(recipientOrNull, spentGas, + (substate?.ShouldRevert ?? false) ? substate.Output.ToArray() : Array.Empty(), + substate?.Error, stateRoot); + } + else + { + txTracer.MarkAsSuccess(recipientOrNull, spentGas, substate.Output.ToArray(), + substate.Logs.Any() ? substate.Logs.ToArray() : Array.Empty(), stateRoot); + } + } } private void PrepareAccountForContractDeployment(Address contractAddress, IReleaseSpec spec) @@ -636,14 +525,13 @@ private void PrepareAccountForContractDeployment(Address contractAddress, IRelea } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] private void TraceLogInvalidTx(Transaction transaction, string reason) { if (_logger.IsTrace) _logger.Trace($"Invalid tx {transaction.Hash} ({reason})"); } - protected long Refund(long gasLimit, long unspentGas, TransactionSubstate substate, Address sender, - in UInt256 gasPrice, ExecutionOptions opts, IReleaseSpec spec) + private long Refund(long gasLimit, long unspentGas, TransactionSubstate substate, Address sender, + in UInt256 gasPrice, bool noValidation, IReleaseSpec spec) { long spentGas = gasLimit; if (!substate.IsError) @@ -657,8 +545,7 @@ protected long Refund(long gasLimit, long unspentGas, TransactionSubstate substa if (_logger.IsTrace) _logger.Trace("Refunding unused gas of " + unspentGas + " and refund of " + refund); // If noValidation we didn't charge for gas, so do not refund - if (!opts.HasFlag(ExecutionOptions.NoValidation)) - _worldState.AddToBalance(sender, (ulong)(unspentGas + refund) * gasPrice, spec); + if (!noValidation) _worldState.AddToBalance(sender, (ulong)(unspentGas + refund) * gasPrice, spec); spentGas -= refund; } diff --git a/src/Nethermind/Nethermind.Evm/TransactionSubstate.cs b/src/Nethermind/Nethermind.Evm/TransactionSubstate.cs index 04a8c663a67..dec8897ce91 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionSubstate.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionSubstate.cs @@ -3,105 +3,97 @@ using System; using System.Collections.Generic; +using System.Numerics; using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Int256; -namespace Nethermind.Evm; - -public class TransactionSubstate +namespace Nethermind.Evm { - private static readonly List
_emptyDestroyList = new(0); - private static readonly List _emptyLogs = new(0); - - private const string SomeError = "error"; - private const string Revert = "revert"; - - private const int RevertPrefix = 4; - - private const string RevertedErrorMessagePrefix = "Reverted "; - - public bool IsError => Error is not null && !ShouldRevert; - public string? Error { get; } - public ReadOnlyMemory Output { get; } - public bool ShouldRevert { get; } - public long Refund { get; } - public IReadOnlyCollection Logs { get; } - public IReadOnlyCollection
DestroyList { get; } - - public TransactionSubstate(EvmExceptionType exceptionType, bool isTracerConnected) + public class TransactionSubstate { - Error = isTracerConnected ? exceptionType.ToString() : SomeError; - Refund = 0; - DestroyList = _emptyDestroyList; - Logs = _emptyLogs; - ShouldRevert = false; - } + private static List
_emptyDestroyList = new(0); + private static List _emptyLogs = new(0); - public TransactionSubstate( - ReadOnlyMemory output, - long refund, - IReadOnlyCollection
destroyList, - IReadOnlyCollection logs, - bool shouldRevert, - bool isTracerConnected) - { - Output = output; - Refund = refund; - DestroyList = destroyList; - Logs = logs; - ShouldRevert = shouldRevert; + private const string SomeError = "error"; + private const string Revert = "revert"; - if (!ShouldRevert) + public TransactionSubstate(EvmExceptionType exceptionType, bool isTracerConnected) { - Error = null; - return; + Error = isTracerConnected ? exceptionType.ToString() : SomeError; + Refund = 0; + DestroyList = _emptyDestroyList; + Logs = _emptyLogs; + ShouldRevert = false; } - Error = Revert; + public unsafe TransactionSubstate( + ReadOnlyMemory output, + long refund, + IReadOnlyCollection
destroyList, + IReadOnlyCollection logs, + bool shouldRevert, + bool isTracerConnected) + { + const int revertPrefix = 4; + + Output = output; + Refund = refund; + DestroyList = destroyList; + Logs = logs; + ShouldRevert = shouldRevert; + if (ShouldRevert) + { + Error = Revert; + if (isTracerConnected) + { + if (Output.Length > 0) + { + ReadOnlySpan span = Output.Span; + if (span.Length >= sizeof(UInt256) * 2 + revertPrefix) + { + try + { + int start = (int)(new UInt256(span.Slice(revertPrefix, sizeof(UInt256)), isBigEndian: true)); + if (start + revertPrefix + sizeof(UInt256) <= span.Length) + { + int length = (int)new UInt256(span.Slice(start + revertPrefix, sizeof(UInt256)), isBigEndian: true); + if (checked(start + revertPrefix + sizeof(UInt256) + length) <= span.Length) + { + Error = string.Concat("Reverted ", + span.Slice(start + sizeof(UInt256) + revertPrefix, length).ToHexString(true)); + return; + } + } + } + catch + { + // ignore + } + } + + Error = string.Concat("Reverted ", span.ToHexString(true)); + } + } + } + else + { + Error = null; + } + } - if (!isTracerConnected) - return; + public bool IsError => Error is not null && !ShouldRevert; - if (Output.Length <= 0) - return; + public string Error { get; } - ReadOnlySpan span = Output.Span; - Error = TryGetErrorMessage(span) - ?? DefaultErrorMessage(span); - } + public ReadOnlyMemory Output { get; } - private string DefaultErrorMessage(ReadOnlySpan span) - { - return string.Concat(RevertedErrorMessagePrefix, span.ToHexString(true)); - } + public bool ShouldRevert { get; } - private unsafe string? TryGetErrorMessage(ReadOnlySpan span) - { - if (span.Length < RevertPrefix + sizeof(UInt256) * 2) - { - return null; - } - - try - { - int start = (int)new UInt256(span.Slice(RevertPrefix, sizeof(UInt256)), isBigEndian: true); - if (checked(RevertPrefix + start + sizeof(UInt256)) > span.Length) - { - return null; - } + public long Refund { get; } - int length = (int)new UInt256(span.Slice(RevertPrefix + start, sizeof(UInt256)), isBigEndian: true); - if (checked(RevertPrefix + start + sizeof(UInt256) + length) != span.Length) - { - return null; - } + public IReadOnlyCollection Logs { get; } - return string.Concat(RevertedErrorMessagePrefix, span.Slice(RevertPrefix + start + sizeof(UInt256), length).ToHexString(true)); - } - catch (OverflowException) - { - return null; - } + public IReadOnlyCollection
DestroyList { get; } } } diff --git a/src/Nethermind/Nethermind.Evm/TxExecutionContext.cs b/src/Nethermind/Nethermind.Evm/TxExecutionContext.cs index 2e00bddb906..427655f536b 100644 --- a/src/Nethermind/Nethermind.Evm/TxExecutionContext.cs +++ b/src/Nethermind/Nethermind.Evm/TxExecutionContext.cs @@ -8,14 +8,14 @@ namespace Nethermind.Evm { public readonly struct TxExecutionContext { - public readonly BlockExecutionContext BlockExecutionContext; + public BlockHeader Header { get; } public Address Origin { get; } public UInt256 GasPrice { get; } public byte[][]? BlobVersionedHashes { get; } - public TxExecutionContext(BlockExecutionContext blockExecutionContext, Address origin, in UInt256 gasPrice, byte[][] blobVersionedHashes) + public TxExecutionContext(BlockHeader blockHeader, Address origin, in UInt256 gasPrice, byte[][] blobVersionedHashes) { - BlockExecutionContext = blockExecutionContext; + Header = blockHeader; Origin = origin; GasPrice = gasPrice; BlobVersionedHashes = blobVersionedHashes; diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index 7b22ee795b4..b787c07ca19 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -4,13 +4,16 @@ using System; using System.Collections.Generic; +using System.Numerics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using Nethermind.Core; using Nethermind.Core.Caching; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Evm.CodeAnalysis; +using Nethermind.Int256; using Nethermind.Evm.Precompiles; using Nethermind.Evm.Precompiles.Bls; using Nethermind.Evm.Precompiles.Snarks; @@ -19,117 +22,21 @@ using Nethermind.State; using System.Diagnostics.CodeAnalysis; using System.Diagnostics; -using System.Runtime.Intrinsics; -using static Nethermind.Evm.VirtualMachine; -using static System.Runtime.CompilerServices.Unsafe; #if DEBUG -using Nethermind.Evm.Tracing.Debugger; +using Nethermind.Evm.Tracing.DebugTrace; #endif [assembly: InternalsVisibleTo("Nethermind.Evm.Test")] namespace Nethermind.Evm; -using System.Linq; -using Int256; - public class VirtualMachine : IVirtualMachine { public const int MaxCallDepth = 1024; - private readonly IVirtualMachine _evm; - - public VirtualMachine( - IBlockhashProvider? blockhashProvider, - ISpecProvider? specProvider, - ILogManager? logManager) - { - ILogger logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); - if (!logger.IsTrace) - { - _evm = new VirtualMachine(blockhashProvider, specProvider, logger); - } - else - { - _evm = new VirtualMachine(blockhashProvider, specProvider, logger); - } - } - - public CodeInfo GetCachedCodeInfo(IWorldState worldState, Address codeSource, IReleaseSpec spec) - => _evm.GetCachedCodeInfo(worldState, codeSource, spec); - - public TransactionSubstate Run(EvmState state, IWorldState worldState, ITxTracer txTracer) - where TTracingActions : struct, IIsTracing - => _evm.Run(state, worldState, txTracer); - - internal readonly ref struct CallResult - { - public static CallResult InvalidSubroutineEntry => new(EvmExceptionType.InvalidSubroutineEntry); - public static CallResult InvalidSubroutineReturn => new(EvmExceptionType.InvalidSubroutineReturn); - public static CallResult OutOfGasException => new(EvmExceptionType.OutOfGas); - public static CallResult AccessViolationException => new(EvmExceptionType.AccessViolation); - public static CallResult InvalidJumpDestination => new(EvmExceptionType.InvalidJumpDestination); - public static CallResult InvalidInstructionException - { - get - { - return new(EvmExceptionType.BadInstruction); - } - } - - public static CallResult StaticCallViolationException => new(EvmExceptionType.StaticCallViolation); - public static CallResult StackOverflowException => new(EvmExceptionType.StackOverflow); // TODO: use these to avoid CALL POP attacks - public static CallResult StackUnderflowException => new(EvmExceptionType.StackUnderflow); // TODO: use these to avoid CALL POP attacks - - public static CallResult InvalidCodeException => new(EvmExceptionType.InvalidCode); - public static CallResult Empty => new(Array.Empty(), null); - - public CallResult(EvmState stateToExecute) - { - StateToExecute = stateToExecute; - Output = Array.Empty(); - PrecompileSuccess = null; - ShouldRevert = false; - ExceptionType = EvmExceptionType.None; - } - - private CallResult(EvmExceptionType exceptionType) - { - StateToExecute = null; - Output = StatusCode.FailureBytes; - PrecompileSuccess = null; - ShouldRevert = false; - ExceptionType = exceptionType; - } - - public CallResult(byte[] output, bool? precompileSuccess, bool shouldRevert = false, EvmExceptionType exceptionType = EvmExceptionType.None) - { - StateToExecute = null; - Output = output; - PrecompileSuccess = precompileSuccess; - ShouldRevert = shouldRevert; - ExceptionType = exceptionType; - } - - public EvmState? StateToExecute { get; } - public byte[] Output { get; } - public EvmExceptionType ExceptionType { get; } - public bool ShouldRevert { get; } - public bool? PrecompileSuccess { get; } // TODO: check this behaviour as it seems it is required and previously that was not the case - public bool IsReturn => StateToExecute is null; - public bool IsException => ExceptionType != EvmExceptionType.None; - } - - public interface IIsTracing { } - public readonly struct NotTracing : IIsTracing { } - public readonly struct IsTracing : IIsTracing { } -} - -internal sealed class VirtualMachine : IVirtualMachine - where TLogger : struct, IIsTracing -{ - private UInt256 P255Int = (UInt256)System.Numerics.BigInteger.Pow(2, 255); + private bool _simdOperationsEnabled = Vector.Count == 32; + private UInt256 P255Int = (UInt256)BigInteger.Pow(2, 255); private UInt256 P255 => P255Int; private UInt256 BigInt256 = 256; public UInt256 BigInt32 = 32; @@ -169,29 +76,27 @@ internal sealed class VirtualMachine : IVirtualMachine public VirtualMachine( IBlockhashProvider? blockhashProvider, ISpecProvider? specProvider, - ILogger? logger) + ILogManager? logManager) { - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); _blockhashProvider = blockhashProvider ?? throw new ArgumentNullException(nameof(blockhashProvider)); _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); _chainId = ((UInt256)specProvider.ChainId).ToBigEndian(); InitializePrecompiledContracts(); } - public TransactionSubstate Run(EvmState state, IWorldState worldState, ITxTracer txTracer) - where TTracingActions : struct, IIsTracing + public TransactionSubstate Run(EvmState state, IWorldState worldState, ITxTracer txTracer) { _txTracer = txTracer; + _state = worldState; _worldState = worldState; - IReleaseSpec spec = _specProvider.GetSpec(state.Env.TxExecutionContext.BlockExecutionContext.Header.Number, state.Env.TxExecutionContext.BlockExecutionContext.Header.Timestamp); + IReleaseSpec spec = _specProvider.GetSpec(state.Env.TxExecutionContext.Header.Number, state.Env.TxExecutionContext.Header.Timestamp); EvmState currentState = state; byte[] previousCallResult = null; ZeroPaddedSpan previousCallOutput = ZeroPaddedSpan.Empty; UInt256 previousCallOutputDestination = UInt256.Zero; - bool isTracing = _txTracer.IsTracing; - while (true) { if (!currentState.IsContinuation) @@ -204,7 +109,7 @@ public TransactionSubstate Run(EvmState state, IWorldState worl CallResult callResult; if (currentState.IsPrecompile) { - if (typeof(TTracingActions) == typeof(IsTracing)) + if (_txTracer.IsTracingActions) { _txTracer.ReportAction(currentState.GasAvailable, currentState.Env.Value, currentState.From, currentState.To, currentState.Env.InputData, currentState.ExecutionType, true); } @@ -226,21 +131,13 @@ public TransactionSubstate Run(EvmState state, IWorldState worl } else { - if (typeof(TTracingActions) == typeof(IsTracing) && !currentState.IsContinuation) + if (_txTracer.IsTracingActions && !currentState.IsContinuation) { _txTracer.ReportAction(currentState.GasAvailable, currentState.Env.Value, currentState.From, currentState.To, currentState.ExecutionType.IsAnyCreate() ? currentState.Env.CodeInfo.MachineCode : currentState.Env.InputData, currentState.ExecutionType); if (_txTracer.IsTracingCode) _txTracer.ReportByteCode(currentState.Env.CodeInfo.MachineCode); } - if (!_txTracer.IsTracingInstructions) - { - callResult = ExecuteCall(currentState, previousCallResult, previousCallOutput, previousCallOutputDestination, spec); - } - else - { - callResult = ExecuteCall(currentState, previousCallResult, previousCallOutput, previousCallOutputDestination, spec); - } - + callResult = ExecuteCall(currentState, previousCallResult, previousCallOutput, previousCallOutputDestination, spec); if (!callResult.IsReturn) { _stateStack.Push(currentState); @@ -253,14 +150,14 @@ public TransactionSubstate Run(EvmState state, IWorldState worl if (callResult.IsException) { - if (typeof(TTracingActions) == typeof(IsTracing)) _txTracer.ReportActionError(callResult.ExceptionType); + if (_txTracer.IsTracingActions) _txTracer.ReportActionError(callResult.ExceptionType); _worldState.Restore(currentState.Snapshot); RevertParityTouchBugAccount(spec); if (currentState.IsTopLevel) { - return new TransactionSubstate(callResult.ExceptionType, isTracing); + return new TransactionSubstate(callResult.ExceptionType, _txTracer.IsTracing); } previousCallResult = StatusCode.FailureBytes; @@ -277,7 +174,7 @@ public TransactionSubstate Run(EvmState state, IWorldState worl if (currentState.IsTopLevel) { - if (typeof(TTracingActions) == typeof(IsTracing)) + if (_txTracer.IsTracingActions) { long codeDepositGasCost = CodeDepositHandler.CalculateCost(callResult.Output.Length, spec); @@ -334,7 +231,7 @@ public TransactionSubstate Run(EvmState state, IWorldState worl (IReadOnlyCollection
)currentState.DestroyList, (IReadOnlyCollection)currentState.Logs, callResult.ShouldRevert, - isTracerConnected: isTracing); + isTracerConnected: _txTracer.IsTracing); } Address callCodeOwner = currentState.Env.ExecutingAccount; @@ -361,7 +258,7 @@ public TransactionSubstate Run(EvmState state, IWorldState worl _state.InsertCode(callCodeOwner, callResult.Output, spec); currentState.GasAvailable -= codeDepositGasCost; - if (typeof(TTracingActions) == typeof(IsTracing)) + if (_txTracer.IsTracingActions) { _txTracer.ReportActionEnd(previousState.GasAvailable - codeDepositGasCost, callCodeOwner, callResult.Output); } @@ -378,12 +275,12 @@ public TransactionSubstate Run(EvmState state, IWorldState worl previousCallResult = BytesZero; previousStateSucceeded = false; - if (typeof(TTracingActions) == typeof(IsTracing)) + if (_txTracer.IsTracingActions) { _txTracer.ReportActionError(invalidCode ? EvmExceptionType.InvalidCode : EvmExceptionType.OutOfGas); } } - else if (typeof(TTracingActions) == typeof(IsTracing)) + else if (_txTracer.IsTracingActions) { _txTracer.ReportActionEnd(0L, callCodeOwner, callResult.Output); } @@ -403,7 +300,7 @@ public TransactionSubstate Run(EvmState state, IWorldState worl } } - if (typeof(TTracingActions) == typeof(IsTracing)) + if (_txTracer.IsTracingActions) { _txTracer.ReportActionEnd(previousState.GasAvailable, _returnDataBuffer); } @@ -423,7 +320,7 @@ public TransactionSubstate Run(EvmState state, IWorldState worl previousCallOutputDestination = (ulong)previousState.OutputDestination; - if (typeof(TTracingActions) == typeof(IsTracing)) + if (_txTracer.IsTracingActions) { _txTracer.ReportActionError(EvmExceptionType.Revert, previousState.GasAvailable); } @@ -431,7 +328,7 @@ public TransactionSubstate Run(EvmState state, IWorldState worl } catch (Exception ex) when (ex is EvmException or OverflowException) { - if (typeof(TLogger) == typeof(IsTracing)) _logger.Trace($"exception ({ex.GetType().Name}) in {currentState.ExecutionType} at depth {currentState.Env.CallDepth} - restoring snapshot"); + if (_logger.IsTrace) _logger.Trace($"exception ({ex.GetType().Name}) in {currentState.ExecutionType} at depth {currentState.Env.CallDepth} - restoring snapshot"); _worldState.Restore(currentState.Snapshot); @@ -443,7 +340,7 @@ public TransactionSubstate Run(EvmState state, IWorldState worl txTracer.ReportOperationRemainingGas(0); } - if (typeof(TTracingActions) == typeof(IsTracing)) + if (_txTracer.IsTracingActions) { EvmException evmException = ex as EvmException; _txTracer.ReportActionError(evmException?.ExceptionType ?? EvmExceptionType.Other); @@ -451,7 +348,7 @@ public TransactionSubstate Run(EvmState state, IWorldState worl if (currentState.IsTopLevel) { - return new TransactionSubstate(ex is OverflowException ? EvmExceptionType.Other : (ex as EvmException).ExceptionType, isTracing); + return new TransactionSubstate(ex is OverflowException ? EvmExceptionType.Other : (ex as EvmException).ExceptionType, _txTracer.IsTracing); } previousCallResult = StatusCode.FailureBytes; @@ -514,38 +411,44 @@ public CodeInfo GetCachedCodeInfo(IWorldState worldState, Address codeSource, IR return cachedCodeInfo; } + public void DisableSimdInstructions() + { + _simdOperationsEnabled = false; + } + private void InitializePrecompiledContracts() { _precompiles = new Dictionary { - [EcRecoverPrecompile.Address] = new(EcRecoverPrecompile.Instance), - [Sha256Precompile.Address] = new(Sha256Precompile.Instance), - [Ripemd160Precompile.Address] = new(Ripemd160Precompile.Instance), - [IdentityPrecompile.Address] = new(IdentityPrecompile.Instance), - - [Bn254AddPrecompile.Address] = new(Bn254AddPrecompile.Instance), - [Bn254MulPrecompile.Address] = new(Bn254MulPrecompile.Instance), - [Bn254PairingPrecompile.Address] = new(Bn254PairingPrecompile.Instance), - [ModExpPrecompile.Address] = new(ModExpPrecompile.Instance), - - [Blake2FPrecompile.Address] = new(Blake2FPrecompile.Instance), - - [G1AddPrecompile.Address] = new(G1AddPrecompile.Instance), - [G1MulPrecompile.Address] = new(G1MulPrecompile.Instance), - [G1MultiExpPrecompile.Address] = new(G1MultiExpPrecompile.Instance), - [G2AddPrecompile.Address] = new(G2AddPrecompile.Instance), - [G2MulPrecompile.Address] = new(G2MulPrecompile.Instance), - [G2MultiExpPrecompile.Address] = new(G2MultiExpPrecompile.Instance), - [PairingPrecompile.Address] = new(PairingPrecompile.Instance), - [MapToG1Precompile.Address] = new(MapToG1Precompile.Instance), - [MapToG2Precompile.Address] = new(MapToG2Precompile.Instance), - - [PointEvaluationPrecompile.Address] = new(PointEvaluationPrecompile.Instance), + [EcRecoverPrecompile.Instance.Address] = new(EcRecoverPrecompile.Instance), + [Sha256Precompile.Instance.Address] = new(Sha256Precompile.Instance), + [Ripemd160Precompile.Instance.Address] = new(Ripemd160Precompile.Instance), + [IdentityPrecompile.Instance.Address] = new(IdentityPrecompile.Instance), + + [Bn254AddPrecompile.Instance.Address] = new(Bn254AddPrecompile.Instance), + [Bn254MulPrecompile.Instance.Address] = new(Bn254MulPrecompile.Instance), + [Bn254PairingPrecompile.Instance.Address] = new(Bn254PairingPrecompile.Instance), + [ModExpPrecompile.Instance.Address] = new(ModExpPrecompile.Instance), + + [Blake2FPrecompile.Instance.Address] = new(Blake2FPrecompile.Instance), + + [G1AddPrecompile.Instance.Address] = new(G1AddPrecompile.Instance), + [G1MulPrecompile.Instance.Address] = new(G1MulPrecompile.Instance), + [G1MultiExpPrecompile.Instance.Address] = new(G1MultiExpPrecompile.Instance), + [G2AddPrecompile.Instance.Address] = new(G2AddPrecompile.Instance), + [G2MulPrecompile.Instance.Address] = new(G2MulPrecompile.Instance), + [G2MultiExpPrecompile.Instance.Address] = new(G2MultiExpPrecompile.Instance), + [PairingPrecompile.Instance.Address] = new(PairingPrecompile.Instance), + [MapToG1Precompile.Instance.Address] = new(MapToG1Precompile.Instance), + [MapToG2Precompile.Instance.Address] = new(MapToG2Precompile.Instance), + + [PointEvaluationPrecompile.Instance.Address] = new(PointEvaluationPrecompile.Instance), }; } private static bool UpdateGas(long gasCost, ref long gasAvailable) { + // Console.WriteLine($"{gasCost}"); if (gasAvailable < gasCost) { return false; @@ -595,7 +498,7 @@ private enum StorageAccessType private bool ChargeStorageAccessGas( ref long gasAvailable, EvmState vmState, - in StorageCell storageCell, + StorageCell storageCell, StorageAccessType storageAccessType, IReleaseSpec spec) { @@ -606,13 +509,13 @@ private bool ChargeStorageAccessGas( { if (_txTracer.IsTracingAccess) // when tracing access we want cost as if it was warmed up from access list { - vmState.WarmUp(in storageCell); + vmState.WarmUp(storageCell); } - if (vmState.IsCold(in storageCell)) + if (vmState.IsCold(storageCell)) { result = UpdateGas(GasCostOf.ColdSLoad, ref gasAvailable); - vmState.WarmUp(in storageCell); + vmState.WarmUp(storageCell); } else if (storageAccessType == StorageAccessType.SLOAD) { @@ -632,7 +535,7 @@ private CallResult ExecutePrecompile(EvmState state, IReleaseSpec spec) IPrecompile precompile = state.Env.CodeInfo.Precompile; long baseGasCost = precompile.BaseGasCost(spec); - long blobGasCost = precompile.DataGasCost(callData, spec); + long dataGasCost = precompile.DataGasCost(callData, spec); bool wasCreated = false; if (!_state.AccountExists(state.Env.ExecutingAccount)) @@ -661,7 +564,7 @@ private CallResult ExecutePrecompile(EvmState state, IReleaseSpec spec) _parityTouchBugAccount.ShouldDelete = true; } - if (!UpdateGas(checked(baseGasCost + blobGasCost), ref gasAvailable)) + if (!UpdateGas(checked(baseGasCost + dataGasCost), ref gasAvailable)) { Metrics.EvmExceptions++; throw new OutOfGasException(); @@ -688,16 +591,18 @@ private CallResult ExecutePrecompile(EvmState state, IReleaseSpec spec) } } - /// - /// Struct generic parameter is used to burn out all the if statements and inner code - /// by typeof(TTracingInstructions) == typeof(NotTracing) checks that are evaluated to constant - /// values at compile time. - /// [SkipLocalsInit] - private CallResult ExecuteCall(EvmState vmState, byte[]? previousCallResult, ZeroPaddedSpan previousCallOutput, scoped in UInt256 previousCallOutputDestination, IReleaseSpec spec) - where TTracingInstructions : struct, IIsTracing + private CallResult ExecuteCall(EvmState vmState, byte[]? previousCallResult, ZeroPaddedSpan previousCallOutput, scoped in UInt256 previousCallOutputDestination, IReleaseSpec spec) { + bool isTrace = _logger.IsTrace; + bool traceOpcodes = _txTracer.IsTracingInstructions; +#if DEBUG + DebugTracer? debugger = _txTracer.GetTracer(); +#endif + ref readonly ExecutionEnvironment env = ref vmState.Env; + ref readonly TxExecutionContext txCtx = ref env.TxExecutionContext; + if (!vmState.IsContinuation) { if (!_state.AccountExists(env.ExecutingAccount)) @@ -715,23 +620,28 @@ private CallResult ExecuteCall(EvmState vmState, byte[]? p } } - if (env.CodeInfo.MachineCode.Length == 0) + if (vmState.Env.CodeInfo.MachineCode.Length == 0) { - if (!vmState.IsTopLevel) - { - Metrics.EmptyCalls++; - } goto Empty; } vmState.InitStacks(); - EvmStack stack = new(vmState.DataStack.AsSpan(), vmState.DataStackHead, _txTracer); + EvmStack stack = new(vmState.DataStack.AsSpan(), vmState.DataStackHead, _txTracer); long gasAvailable = vmState.GasAvailable; + int programCounter = vmState.ProgramCounter; + Span code = env.CodeInfo.MachineCode.AsSpan(); + + static void UpdateCurrentState(EvmState state, int pc, long gas, int stackHead) + { + state.ProgramCounter = pc; + state.GasAvailable = gas; + state.DataStackHead = stackHead; + } if (previousCallResult is not null) { stack.PushBytes(previousCallResult); - if (typeof(TTracingInstructions) == typeof(IsTracing)) _txTracer.ReportOperationRemainingGas(vmState.GasAvailable); + if (_txTracer.IsTracingInstructions) _txTracer.ReportOperationRemainingGas(vmState.GasAvailable); } if (previousCallOutput.Length > 0) @@ -739,69 +649,24 @@ private CallResult ExecuteCall(EvmState vmState, byte[]? p UInt256 localPreviousDest = previousCallOutputDestination; if (!UpdateMemoryCost(vmState, ref gasAvailable, in localPreviousDest, (ulong)previousCallOutput.Length)) { + // Never ran any instructions, so nothing to trace (or mark as end of trace) + traceOpcodes = false; goto OutOfGas; } vmState.Memory.Save(in localPreviousDest, previousCallOutput); + // if(_txTracer.IsTracingInstructions) _txTracer.ReportMemoryChange((long)localPreviousDest, previousCallOutput); } - // Struct generic parameter is used to burn out all the if statements - // and inner code by typeof(TTracing) == typeof(NotTracing) - // checks that are evaluated to constant values at compile time. - // This only works for structs, not for classes or interface types - // which use shared generics. - if (!_txTracer.IsTracingRefunds) - { - return _txTracer.IsTracingOpLevelStorage ? - ExecuteCode(vmState, ref stack, gasAvailable, spec) : - ExecuteCode(vmState, ref stack, gasAvailable, spec); - } - else - { - return _txTracer.IsTracingOpLevelStorage ? - ExecuteCode(vmState, ref stack, gasAvailable, spec) : - ExecuteCode(vmState, ref stack, gasAvailable, spec); - } -Empty: - return CallResult.Empty; -OutOfGas: - return CallResult.OutOfGasException; - } - - [SkipLocalsInit] - private CallResult ExecuteCode(EvmState vmState, scoped ref EvmStack stack, long gasAvailable, IReleaseSpec spec) - where TTracingInstructions : struct, IIsTracing - where TTracingRefunds : struct, IIsTracing - where TTracingStorage : struct, IIsTracing - { - int programCounter = vmState.ProgramCounter; - ref readonly ExecutionEnvironment env = ref vmState.Env; - ref readonly TxExecutionContext txCtx = ref env.TxExecutionContext; - ref readonly BlockExecutionContext blkCtx = ref txCtx.BlockExecutionContext; - Span code = env.CodeInfo.MachineCode.AsSpan(); - EvmExceptionType exceptionType = EvmExceptionType.None; - bool isRevert = false; -#if DEBUG - DebugTracer? debugger = _txTracer.GetTracer(); -#endif - Span bytes; - SkipInit(out UInt256 a); - SkipInit(out UInt256 b); - SkipInit(out UInt256 c); - SkipInit(out UInt256 result); - SkipInit(out StorageCell storageCell); - object returnData; - ZeroPaddedSpan slice; - uint codeLength = (uint)code.Length; - while ((uint)programCounter < codeLength) + while (programCounter < code.Length) { #if DEBUG debugger?.TryWait(ref vmState, ref programCounter, ref gasAvailable, ref stack.Head); #endif Instruction instruction = (Instruction)code[programCounter]; + // Console.WriteLine(instruction); - // Evaluated to constant at compile time and code elided if not tracing - if (typeof(TTracingInstructions) == typeof(IsTracing)) + if (traceOpcodes) StartInstructionTrace(instruction, vmState, gasAvailable, programCounter, in stack); programCounter++; @@ -809,164 +674,165 @@ private CallResult ExecuteCode(ref b) == Int256.MinusOne && a == P255) + else if (b == Int256.Int256.MinusOne && a == P255) { - result = P255; - stack.PushUInt256(in result); + UInt256 res = P255; + stack.PushUInt256(in res); } else { - Int256.Divide(in As(ref a), in As(ref b), out As(ref result)); - stack.PushUInt256(in result); + Int256.Int256 signedA = new(a); + Int256.Int256.Divide(in signedA, in b, out Int256.Int256 res); + stack.PushSignedInt256(in res); } break; } case Instruction.MOD: { - gasAvailable -= GasCostOf.Low; + if (!UpdateGas(GasCostOf.Low, ref gasAvailable)) goto OutOfGas; - stack.PopUInt256(out a); - stack.PopUInt256(out b); - UInt256.Mod(in a, in b, out result); + stack.PopUInt256(out UInt256 a); + stack.PopUInt256(out UInt256 b); + UInt256.Mod(in a, in b, out UInt256 result); stack.PushUInt256(in result); break; } case Instruction.SMOD: { - gasAvailable -= GasCostOf.Low; + if (!UpdateGas(GasCostOf.Low, ref gasAvailable)) goto OutOfGas; - stack.PopUInt256(out a); - stack.PopUInt256(out b); - if (b.IsZeroOrOne) + stack.PopSignedInt256(out Int256.Int256 a); + stack.PopSignedInt256(out Int256.Int256 b); + if (b.IsZero || b.IsOne) { stack.PushZero(); } else { - As(ref a) - .Mod(in As(ref b), out As(ref result)); - stack.PushUInt256(in result); + a.Mod(in b, out Int256.Int256 mod); + stack.PushSignedInt256(in mod); } break; } case Instruction.ADDMOD: { - gasAvailable -= GasCostOf.Mid; + if (!UpdateGas(GasCostOf.Mid, ref gasAvailable)) goto OutOfGas; - stack.PopUInt256(out a); - stack.PopUInt256(out b); - stack.PopUInt256(out c); + stack.PopUInt256(out UInt256 a); + stack.PopUInt256(out UInt256 b); + stack.PopUInt256(out UInt256 mod); - if (c.IsZero) + if (mod.IsZero) { stack.PushZero(); } else { - UInt256.AddMod(a, b, c, out result); - stack.PushUInt256(in result); + UInt256.AddMod(a, b, mod, out UInt256 res); + stack.PushUInt256(in res); } break; } case Instruction.MULMOD: { - gasAvailable -= GasCostOf.Mid; + if (!UpdateGas(GasCostOf.Mid, ref gasAvailable)) goto OutOfGas; - stack.PopUInt256(out a); - stack.PopUInt256(out b); - stack.PopUInt256(out c); + stack.PopUInt256(out UInt256 a); + stack.PopUInt256(out UInt256 b); + stack.PopUInt256(out UInt256 mod); - if (c.IsZero) + if (mod.IsZero) { stack.PushZero(); } else { - UInt256.MultiplyMod(in a, in b, in c, out result); - stack.PushUInt256(in result); + UInt256.MultiplyMod(in a, in b, in mod, out UInt256 res); + stack.PushUInt256(in res); } break; } case Instruction.EXP: { - gasAvailable -= GasCostOf.Exp; + if (!UpdateGas(GasCostOf.Exp, ref gasAvailable)) goto OutOfGas; Metrics.ModExpOpcode++; - stack.PopUInt256(out a); - bytes = stack.PopWord256(); + stack.PopUInt256(out UInt256 baseInt); + Span exp = stack.PopWord256(); - int leadingZeros = bytes.LeadingZerosCount(); + int leadingZeros = exp.LeadingZerosCount(); if (leadingZeros != 32) { int expSize = 32 - leadingZeros; - gasAvailable -= spec.GetExpByteCost() * expSize; + if (!UpdateGas(spec.GetExpByteCost() * expSize, ref gasAvailable)) goto OutOfGas; } else { @@ -974,27 +840,27 @@ private CallResult ExecuteCode= BigInt32) { stack.EnsureDepth(1); @@ -1003,27 +869,27 @@ private CallResult ExecuteCode b = stack.PopWord256(); + sbyte sign = (sbyte)b[position]; if (sign >= 0) { - BytesZero32.AsSpan(0, position).CopyTo(bytes[..position]); + BytesZero32.AsSpan(0, position).CopyTo(b[..position]); } else { - BytesMax32.AsSpan(0, position).CopyTo(bytes[..position]); + BytesMax32.AsSpan(0, position).CopyTo(b[..position]); } - // Didn't remove from stack so don't need to push back + stack.PushBytes(b); break; } case Instruction.LT: { - gasAvailable -= GasCostOf.VeryLow; + if (!UpdateGas(GasCostOf.VeryLow, ref gasAvailable)) goto OutOfGas; - stack.PopUInt256(out a); - stack.PopUInt256(out b); + stack.PopUInt256(out UInt256 a); + stack.PopUInt256(out UInt256 b); if (a < b) { stack.PushOne(); @@ -1037,10 +903,10 @@ private CallResult ExecuteCode b) { stack.PushOne(); @@ -1054,12 +920,12 @@ private CallResult ExecuteCode(ref a).CompareTo(As(ref b)) < 0) + if (a.CompareTo(b) < 0) { stack.PushOne(); } @@ -1072,11 +938,11 @@ private CallResult ExecuteCode(ref a).CompareTo(As(ref b)) > 0) + stack.PopSignedInt256(out Int256.Int256 a); + stack.PopSignedInt256(out Int256.Int256 b); + if (a.CompareTo(b) > 0) { stack.PushOne(); } @@ -1089,11 +955,11 @@ private CallResult ExecuteCode a = stack.PopWord256(); + Span b = stack.PopWord256(); + if (a.SequenceEqual(b)) { stack.PushOne(); } @@ -1106,10 +972,10 @@ private CallResult ExecuteCode a = stack.PopWord256(); + if (a.SequenceEqual(BytesZero32)) { stack.PushOne(); } @@ -1122,57 +988,132 @@ private CallResult ExecuteCode a = stack.PopWord256(); + Span b = stack.PopWord256(); + + if (_simdOperationsEnabled) + { + Vector aVec = new(a); + Vector bVec = new(b); + + Vector.BitwiseAnd(aVec, bVec).CopyTo(stack.Register); + } + else + { + ref ulong refA = ref MemoryMarshal.AsRef(a); + ref ulong refB = ref MemoryMarshal.AsRef(b); + ref ulong refBuffer = ref MemoryMarshal.AsRef(stack.Register); - Vector256 aVec = ReadUnaligned>(ref stack.PopBytesByRef()); - Vector256 bVec = ReadUnaligned>(ref stack.PopBytesByRef()); + refBuffer = refA & refB; + Unsafe.Add(ref refBuffer, 1) = Unsafe.Add(ref refA, 1) & Unsafe.Add(ref refB, 1); + Unsafe.Add(ref refBuffer, 2) = Unsafe.Add(ref refA, 2) & Unsafe.Add(ref refB, 2); + Unsafe.Add(ref refBuffer, 3) = Unsafe.Add(ref refA, 3) & Unsafe.Add(ref refB, 3); + } - WriteUnaligned(ref stack.PushBytesRef(), Vector256.BitwiseAnd(aVec, bVec)); + stack.PushBytes(stack.Register); break; } case Instruction.OR: { - gasAvailable -= GasCostOf.VeryLow; + if (!UpdateGas(GasCostOf.VeryLow, ref gasAvailable)) goto OutOfGas; + + Span a = stack.PopWord256(); + Span b = stack.PopWord256(); + + if (_simdOperationsEnabled) + { + Vector aVec = new(a); + Vector bVec = new(b); + + Vector.BitwiseOr(aVec, bVec).CopyTo(stack.Register); + } + else + { + ref ulong refA = ref MemoryMarshal.AsRef(a); + ref ulong refB = ref MemoryMarshal.AsRef(b); + ref ulong refBuffer = ref MemoryMarshal.AsRef(stack.Register); - Vector256 aVec = ReadUnaligned>(ref stack.PopBytesByRef()); - Vector256 bVec = ReadUnaligned>(ref stack.PopBytesByRef()); + refBuffer = refA | refB; + Unsafe.Add(ref refBuffer, 1) = Unsafe.Add(ref refA, 1) | Unsafe.Add(ref refB, 1); + Unsafe.Add(ref refBuffer, 2) = Unsafe.Add(ref refA, 2) | Unsafe.Add(ref refB, 2); + Unsafe.Add(ref refBuffer, 3) = Unsafe.Add(ref refA, 3) | Unsafe.Add(ref refB, 3); + } - WriteUnaligned(ref stack.PushBytesRef(), Vector256.BitwiseOr(aVec, bVec)); + stack.PushBytes(stack.Register); break; } case Instruction.XOR: { - gasAvailable -= GasCostOf.VeryLow; + if (!UpdateGas(GasCostOf.VeryLow, ref gasAvailable)) goto OutOfGas; + + Span a = stack.PopWord256(); + Span b = stack.PopWord256(); + + if (_simdOperationsEnabled) + { + Vector aVec = new(a); + Vector bVec = new(b); + + Vector.Xor(aVec, bVec).CopyTo(stack.Register); + } + else + { + ref ulong refA = ref MemoryMarshal.AsRef(a); + ref ulong refB = ref MemoryMarshal.AsRef(b); + ref ulong refBuffer = ref MemoryMarshal.AsRef(stack.Register); - Vector256 aVec = ReadUnaligned>(ref stack.PopBytesByRef()); - Vector256 bVec = ReadUnaligned>(ref stack.PopBytesByRef()); + refBuffer = refA ^ refB; + Unsafe.Add(ref refBuffer, 1) = Unsafe.Add(ref refA, 1) ^ Unsafe.Add(ref refB, 1); + Unsafe.Add(ref refBuffer, 2) = Unsafe.Add(ref refA, 2) ^ Unsafe.Add(ref refB, 2); + Unsafe.Add(ref refBuffer, 3) = Unsafe.Add(ref refA, 3) ^ Unsafe.Add(ref refB, 3); + } - WriteUnaligned(ref stack.PushBytesRef(), Vector256.Xor(aVec, bVec)); + stack.PushBytes(stack.Register); break; } case Instruction.NOT: { - gasAvailable -= GasCostOf.VeryLow; + if (!UpdateGas(GasCostOf.VeryLow, ref gasAvailable)) goto OutOfGas; + + Span a = stack.PopWord256(); + + if (_simdOperationsEnabled) + { + Vector aVec = new(a); + Vector negVec = Vector.Xor(aVec, new Vector(BytesMax32)); + + negVec.CopyTo(stack.Register); + } + else + { + ref var refA = ref MemoryMarshal.AsRef(a); + ref var refBuffer = ref MemoryMarshal.AsRef(stack.Register); - Vector256 negVec = Vector256.OnesComplement(ReadUnaligned>(ref stack.PopBytesByRef())); + refBuffer = ~refA; + Unsafe.Add(ref refBuffer, 1) = ~Unsafe.Add(ref refA, 1); + Unsafe.Add(ref refBuffer, 2) = ~Unsafe.Add(ref refA, 2); + Unsafe.Add(ref refBuffer, 3) = ~Unsafe.Add(ref refA, 3); + } - WriteUnaligned(ref stack.PushBytesRef(), negVec); + stack.PushBytes(stack.Register); break; } case Instruction.BYTE: { - gasAvailable -= GasCostOf.VeryLow; + if (!UpdateGas(GasCostOf.VeryLow, ref gasAvailable)) goto OutOfGas; - stack.PopUInt256(out a); - bytes = stack.PopWord256(); + stack.PopUInt256(out UInt256 position); + Span bytes = stack.PopWord256(); - if (a >= BigInt32) + if (position >= BigInt32) { stack.PushZero(); break; } - int adjustedPosition = bytes.Length - 32 + (int)a; + int adjustedPosition = bytes.Length - 32 + (int)position; if (adjustedPosition < 0) { stack.PushZero(); @@ -1184,90 +1125,93 @@ private CallResult ExecuteCode memData = vmState.Memory.LoadSpan(in memSrc, memLength); + stack.PushBytes(ValueKeccak.Compute(memData).BytesAsSpan); break; } case Instruction.ADDRESS: { - gasAvailable -= GasCostOf.Base; + if (!UpdateGas(GasCostOf.Base, ref gasAvailable)) goto OutOfGas; stack.PushBytes(env.ExecutingAccount.Bytes); break; } case Instruction.BALANCE: { - gasAvailable -= spec.GetBalanceCost(); + long gasCost = spec.GetBalanceCost(); + if (gasCost != 0 && !UpdateGas(gasCost, ref gasAvailable)) goto OutOfGas; Address address = stack.PopAddress(); if (!ChargeAccountAccessGas(ref gasAvailable, vmState, address, spec)) goto OutOfGas; - result = _state.GetBalance(address); - stack.PushUInt256(in result); + UInt256 balance = _state.GetBalance(address); + stack.PushUInt256(in balance); break; } case Instruction.CALLER: { - gasAvailable -= GasCostOf.Base; + if (!UpdateGas(GasCostOf.Base, ref gasAvailable)) goto OutOfGas; stack.PushBytes(env.Caller.Bytes); break; } case Instruction.CALLVALUE: { - gasAvailable -= GasCostOf.Base; + if (!UpdateGas(GasCostOf.Base, ref gasAvailable)) goto OutOfGas; - result = env.Value; - stack.PushUInt256(in result); + UInt256 callValue = env.Value; + stack.PushUInt256(in callValue); break; } case Instruction.ORIGIN: { - gasAvailable -= GasCostOf.Base; + if (!UpdateGas(GasCostOf.Base, ref gasAvailable)) goto OutOfGas; stack.PushBytes(txCtx.Origin.Bytes); break; } case Instruction.CALLDATALOAD: { - gasAvailable -= GasCostOf.VeryLow; + if (!UpdateGas(GasCostOf.VeryLow, ref gasAvailable)) goto OutOfGas; - stack.PopUInt256(out result); - stack.PushBytes(env.InputData.SliceWithZeroPadding(result, 32)); + stack.PopUInt256(out UInt256 src); + stack.PushBytes(env.InputData.SliceWithZeroPadding(src, 32)); break; } case Instruction.CALLDATASIZE: { - gasAvailable -= GasCostOf.Base; + if (!UpdateGas(GasCostOf.Base, ref gasAvailable)) goto OutOfGas; - result = (UInt256)env.InputData.Length; - stack.PushUInt256(in result); + UInt256 callDataSize = (UInt256)env.InputData.Length; + stack.PushUInt256(in callDataSize); break; } case Instruction.CALLDATACOPY: { - stack.PopUInt256(out a); - stack.PopUInt256(out b); - stack.PopUInt256(out result); - gasAvailable -= GasCostOf.VeryLow + GasCostOf.Memory * EvmPooledMemory.Div32Ceiling(in result); + stack.PopUInt256(out UInt256 dest); + stack.PopUInt256(out UInt256 src); + stack.PopUInt256(out UInt256 length); + if (!UpdateGas(GasCostOf.VeryLow + GasCostOf.Memory * EvmPooledMemory.Div32Ceiling(length), + ref gasAvailable)) goto OutOfGas; - if (!result.IsZero) + if (length > UInt256.Zero) { - if (!UpdateMemoryCost(vmState, ref gasAvailable, in a, in result)) goto OutOfGas; + if (!UpdateMemoryCost(vmState, ref gasAvailable, in dest, length)) goto OutOfGas; - slice = env.InputData.SliceWithZeroPadding(b, (int)result); - vmState.Memory.Save(in a, in slice); - if (typeof(TTracingInstructions) == typeof(IsTracing)) + ZeroPaddedMemory callDataSlice = env.InputData.SliceWithZeroPadding(src, (int)length); + vmState.Memory.Save(in dest, callDataSlice); + if (_txTracer.IsTracingInstructions) { - _txTracer.ReportMemoryChange((long)a, slice); + _txTracer.ReportMemoryChange((long)dest, callDataSlice); } } @@ -1275,46 +1219,48 @@ private CallResult ExecuteCode UInt256.Zero) { - if (!UpdateMemoryCost(vmState, ref gasAvailable, in a, result)) goto OutOfGas; + if (!UpdateMemoryCost(vmState, ref gasAvailable, in dest, length)) goto OutOfGas; - slice = code.SliceWithZeroPadding(in b, (int)result); - vmState.Memory.Save(in a, in slice); - if (typeof(TTracingInstructions) == typeof(IsTracing)) _txTracer.ReportMemoryChange((long)a, in slice); + ZeroPaddedSpan codeSlice = code.SliceWithZeroPadding(src, (int)length); + vmState.Memory.Save(in dest, codeSlice); + if (_txTracer.IsTracingInstructions) _txTracer.ReportMemoryChange((long)dest, codeSlice); } break; } case Instruction.GASPRICE: { - gasAvailable -= GasCostOf.Base; + if (!UpdateGas(GasCostOf.Base, ref gasAvailable)) goto OutOfGas; - result = txCtx.GasPrice; - stack.PushUInt256(in result); + UInt256 gasPrice = txCtx.GasPrice; + stack.PushUInt256(in gasPrice); break; } case Instruction.EXTCODESIZE: { - gasAvailable -= spec.GetExtCodeCost(); + Metrics.ExtCodeSizeOpcode++; + long gasCost = spec.GetExtCodeCost(); + if (!UpdateGas(gasCost, ref gasAvailable)) goto OutOfGas; Address address = stack.PopAddress(); if (!ChargeAccountAccessGas(ref gasAvailable, vmState, address, spec)) goto OutOfGas; - if (typeof(TTracingInstructions) != typeof(IsTracing) && programCounter < code.Length) + if (!traceOpcodes && programCounter < code.Length) { bool optimizeAccess = false; Instruction nextInstruction = (Instruction)code[programCounter]; @@ -1322,6 +1268,7 @@ private CallResult ExecuteCode 0 || code.length == 0 else if ((nextInstruction == Instruction.GT || nextInstruction == Instruction.EQ) && @@ -1329,6 +1276,14 @@ private CallResult ExecuteCode UInt256.Zero) { - if (!UpdateMemoryCost(vmState, ref gasAvailable, in a, result)) goto OutOfGas; + if (!UpdateMemoryCost(vmState, ref gasAvailable, in dest, length)) goto OutOfGas; byte[] externalCode = GetCachedCodeInfo(_worldState, address, spec).MachineCode; - slice = externalCode.SliceWithZeroPadding(b, (int)result); - vmState.Memory.Save(in a, in slice); - if (typeof(TTracingInstructions) == typeof(IsTracing)) + ZeroPaddedSpan callDataSlice = externalCode.SliceWithZeroPadding(src, (int)length); + vmState.Memory.Save(in dest, callDataSlice); + if (_txTracer.IsTracingInstructions) { - _txTracer.ReportMemoryChange((long)a, in slice); + _txTracer.ReportMemoryChange((long)dest, callDataSlice); } } @@ -1396,35 +1355,35 @@ private CallResult ExecuteCode _returnDataBuffer.Length) + if (UInt256.AddOverflow(length, src, out UInt256 newLength) || newLength > _returnDataBuffer.Length) { goto AccessViolation; } - if (!result.IsZero) + if (length > UInt256.Zero) { - if (!UpdateMemoryCost(vmState, ref gasAvailable, in a, result)) goto OutOfGas; + if (!UpdateMemoryCost(vmState, ref gasAvailable, in dest, length)) goto OutOfGas; - slice = _returnDataBuffer.AsSpan().SliceWithZeroPadding(b, (int)result); - vmState.Memory.Save(in a, in slice); - if (typeof(TTracingInstructions) == typeof(IsTracing)) + ZeroPaddedSpan returnDataSlice = _returnDataBuffer.AsSpan().SliceWithZeroPadding(src, (int)length); + vmState.Memory.Save(in dest, returnDataSlice); + if (_txTracer.IsTracingInstructions) { - _txTracer.ReportMemoryChange((long)a, in slice); + _txTracer.ReportMemoryChange((long)dest, returnDataSlice); } } @@ -1434,14 +1393,14 @@ private CallResult ExecuteCode long.MaxValue ? long.MaxValue : (long)a; - Keccak blockHash = _blockhashProvider.GetBlockhash(blkCtx.Header, number); + Keccak blockHash = _blockhashProvider.GetBlockhash(txCtx.Header, number); stack.PushBytes(blockHash != null ? blockHash.Bytes : BytesZero32); - if (typeof(TLogger) == typeof(IsTracing)) + if (isTrace) { if (_txTracer.IsTracingBlockHash && blockHash is not null) { @@ -1453,55 +1412,55 @@ private CallResult ExecuteCode memData = vmState.Memory.LoadSpan(in memPosition); + if (_txTracer.IsTracingInstructions) _txTracer.ReportMemoryChange(memPosition, memData); - stack.PushBytes(bytes); + stack.PushBytes(memData); break; } case Instruction.MSTORE: { - gasAvailable -= GasCostOf.VeryLow; + if (!UpdateGas(GasCostOf.VeryLow, ref gasAvailable)) goto OutOfGas; - stack.PopUInt256(out result); + stack.PopUInt256(out UInt256 memPosition); - bytes = stack.PopWord256(); - if (!UpdateMemoryCost(vmState, ref gasAvailable, in result, in BigInt32)) goto OutOfGas; - vmState.Memory.SaveWord(in result, bytes); - if (typeof(TTracingInstructions) == typeof(IsTracing)) _txTracer.ReportMemoryChange((long)result, bytes); + Span word = stack.PopWord256(); + if (!UpdateMemoryCost(vmState, ref gasAvailable, in memPosition, 32)) goto OutOfGas; + vmState.Memory.SaveWord(in memPosition, word); + if (_txTracer.IsTracingInstructions) _txTracer.ReportMemoryChange((long)memPosition, word.SliceWithZeroPadding(0, 32, PadDirection.Left)); break; } case Instruction.MSTORE8: { - gasAvailable -= GasCostOf.VeryLow; + if (!UpdateGas(GasCostOf.VeryLow, ref gasAvailable)) goto OutOfGas; - stack.PopUInt256(out result); + stack.PopUInt256(out UInt256 memPosition); byte data = stack.PopByte(); - if (!UpdateMemoryCost(vmState, ref gasAvailable, in result, UInt256.One)) goto OutOfGas; - vmState.Memory.SaveByte(in result, data); - if (typeof(TTracingInstructions) == typeof(IsTracing)) _txTracer.ReportMemoryChange((long)result, data); + if (!UpdateMemoryCost(vmState, ref gasAvailable, in memPosition, UInt256.One)) goto OutOfGas; + vmState.Memory.SaveByte(in memPosition, data); + if (_txTracer.IsTracingInstructions) _txTracer.ReportMemoryChange((long)memPosition, data); break; } case Instruction.SLOAD: { Metrics.SloadOpcode++; - gasAvailable -= spec.GetSLoadCost(); + var gasCost = spec.GetSLoadCost(); + + if (!UpdateGas(gasCost, ref gasAvailable)) goto OutOfGas; - stack.PopUInt256(out result); - storageCell = new(env.ExecutingAccount, result); + stack.PopUInt256(out UInt256 storageIndex); + StorageCell storageCell = new(env.ExecutingAccount, storageIndex); if (!ChargeStorageAccessGas( ref gasAvailable, vmState, - in storageCell, + storageCell, StorageAccessType.SLOAD, spec)) goto OutOfGas; - byte[] value = _state.Get(in storageCell); + byte[] value = _state.Get(storageCell); stack.PushBytes(value); - if (typeof(TTracingStorage) == typeof(IsTracing)) + if (_txTracer.IsTracingOpLevelStorage) { - _txTracer.LoadOperationStorage(storageCell.Address, result, value); + _txTracer.LoadOperationStorage(storageCell.Address, storageIndex, value); } break; @@ -1628,74 +1579,269 @@ private CallResult ExecuteCode(vmState, ref stack, ref gasAvailable, spec)) - goto OutOfGas; + // fail fast before the first storage read if gas is not enough even for reset + if (!spec.UseNetGasMetering && !UpdateGas(spec.GetSStoreResetCost(), ref gasAvailable)) goto OutOfGas; + + if (spec.UseNetGasMeteringWithAStipendFix) + { + if (_txTracer.IsTracingRefunds) _txTracer.ReportExtraGasPressure(GasCostOf.CallStipend - spec.GetNetMeteredSStoreCost() + 1); + if (gasAvailable <= GasCostOf.CallStipend) goto OutOfGas; + } + + stack.PopUInt256(out UInt256 storageIndex); + Span newValue = stack.PopWord256(); + bool newIsZero = newValue.IsZero(); + if (!newIsZero) + { + newValue = newValue.WithoutLeadingZeros().ToArray(); + } + else + { + newValue = new byte[] { 0 }; + } + + StorageCell storageCell = new(env.ExecutingAccount, storageIndex); + + if (!ChargeStorageAccessGas( + ref gasAvailable, + vmState, + storageCell, + StorageAccessType.SSTORE, + spec)) goto OutOfGas; + + Span currentValue = _state.Get(storageCell); + // Console.WriteLine($"current: {currentValue.ToHexString()} newValue {newValue.ToHexString()}"); + bool currentIsZero = currentValue.IsZero(); + + bool newSameAsCurrent = (newIsZero && currentIsZero) || Bytes.AreEqual(currentValue, newValue); + long sClearRefunds = RefundOf.SClear(spec.IsEip3529Enabled); + + if (!spec.UseNetGasMetering) // note that for this case we already deducted 5000 + { + if (newIsZero) + { + if (!newSameAsCurrent) + { + vmState.Refund += sClearRefunds; + if (_txTracer.IsTracingRefunds) _txTracer.ReportRefund(sClearRefunds); + } + } + else if (currentIsZero) + { + if (!UpdateGas(GasCostOf.SSet - GasCostOf.SReset, ref gasAvailable)) goto OutOfGas; + } + } + else // net metered + { + if (newSameAsCurrent) + { + if (!UpdateGas(spec.GetNetMeteredSStoreCost(), ref gasAvailable)) goto OutOfGas; + } + else // net metered, C != N + { + Span originalValue = _state.GetOriginal(storageCell); + bool originalIsZero = originalValue.IsZero(); + + bool currentSameAsOriginal = Bytes.AreEqual(originalValue, currentValue); + if (currentSameAsOriginal) + { + if (currentIsZero) + { + if (!UpdateGas(GasCostOf.SSet, ref gasAvailable)) goto OutOfGas; + } + else // net metered, current == original != new, !currentIsZero + { + if (!UpdateGas(spec.GetSStoreResetCost(), ref gasAvailable)) goto OutOfGas; + + if (newIsZero) + { + vmState.Refund += sClearRefunds; + if (_txTracer.IsTracingRefunds) _txTracer.ReportRefund(sClearRefunds); + } + } + } + else // net metered, new != current != original + { + long netMeteredStoreCost = spec.GetNetMeteredSStoreCost(); + if (!UpdateGas(netMeteredStoreCost, ref gasAvailable)) goto OutOfGas; + + if (!originalIsZero) // net metered, new != current != original != 0 + { + if (currentIsZero) + { + vmState.Refund -= sClearRefunds; + if (_txTracer.IsTracingRefunds) _txTracer.ReportRefund(-sClearRefunds); + } + + if (newIsZero) + { + vmState.Refund += sClearRefunds; + if (_txTracer.IsTracingRefunds) _txTracer.ReportRefund(sClearRefunds); + } + } + + bool newSameAsOriginal = Bytes.AreEqual(originalValue, newValue); + if (newSameAsOriginal) + { + long refundFromReversal; + if (originalIsZero) + { + refundFromReversal = spec.GetSetReversalRefund(); + } + else + { + refundFromReversal = spec.GetClearReversalRefund(); + } + + vmState.Refund += refundFromReversal; + if (_txTracer.IsTracingRefunds) _txTracer.ReportRefund(refundFromReversal); + } + } + } + } + + if (!newSameAsCurrent) + { + Span valueToStore = newIsZero ? BytesZero : newValue; + _state.Set(storageCell, valueToStore.ToArray()); + } + + if (_txTracer.IsTracingInstructions) + { + Span valueToStore = newIsZero ? BytesZero : newValue; + Span span = new byte[32]; // do not stackalloc here + storageCell.Index.ToBigEndian(span); + _txTracer.ReportStorageChange(span, valueToStore); + } + + if (_txTracer.IsTracingOpLevelStorage) + { + _txTracer.SetOperationStorage(storageCell.Address, storageIndex, newValue, currentValue); + } + + break; + } + case Instruction.TLOAD: + { + Metrics.TloadOpcode++; + if (!spec.TransientStorageEnabled) goto InvalidInstruction; + var gasCost = GasCostOf.TLoad; + + if (!UpdateGas(gasCost, ref gasAvailable)) goto OutOfGas; + + stack.PopUInt256(out UInt256 storageIndex); + StorageCell storageCell = new(env.ExecutingAccount, storageIndex); + + byte[] value = _state.GetTransientState(storageCell); + stack.PushBytes(value); + + if (_txTracer.IsTracingOpLevelStorage) + { + _txTracer.LoadOperationTransientStorage(storageCell.Address, storageIndex, value); + } + + break; + } + case Instruction.TSTORE: + { + Metrics.TstoreOpcode++; + if (!spec.TransientStorageEnabled) goto InvalidInstruction; + + if (vmState.IsStatic) goto StaticCallViolation; + + long gasCost = GasCostOf.TStore; + if (!UpdateGas(gasCost, ref gasAvailable)) goto OutOfGas; + + stack.PopUInt256(out UInt256 storageIndex); + Span newValue = stack.PopWord256(); + bool newIsZero = newValue.IsZero(); + if (!newIsZero) + { + newValue = newValue.WithoutLeadingZeros().ToArray(); + } + else + { + newValue = BytesZero; + } + + StorageCell storageCell = new(env.ExecutingAccount, storageIndex); + byte[] currentValue = newValue.ToArray(); + _state.SetTransientState(storageCell, currentValue); + + if (_txTracer.IsTracingOpLevelStorage) + { + _txTracer.SetOperationTransientStorage(storageCell.Address, storageIndex, newValue, currentValue); + } break; } case Instruction.JUMP: { - gasAvailable -= GasCostOf.Mid; + if (!UpdateGas(GasCostOf.Mid, ref gasAvailable)) goto OutOfGas; - stack.PopUInt256(out result); - if (!Jump(result, ref programCounter, in env)) goto InvalidJumpDestination; + stack.PopUInt256(out UInt256 jumpDest); + if (!Jump(jumpDest, ref programCounter, in env)) goto InvalidJumpDestination; break; } case Instruction.JUMPI: { - gasAvailable -= GasCostOf.High; + if (!UpdateGas(GasCostOf.High, ref gasAvailable)) goto OutOfGas; - stack.PopUInt256(out result); - bytes = stack.PopWord256(); - if (!bytes.SequenceEqual(BytesZero32)) + stack.PopUInt256(out UInt256 jumpDest); + Span condition = stack.PopWord256(); + if (!condition.SequenceEqual(BytesZero32)) { - if (!Jump(result, ref programCounter, in env)) goto InvalidJumpDestination; + if (!Jump(jumpDest, ref programCounter, in env)) goto InvalidJumpDestination; } break; } case Instruction.PC: { - gasAvailable -= GasCostOf.Base; + if (!UpdateGas(GasCostOf.Base, ref gasAvailable)) goto OutOfGas; stack.PushUInt32(programCounter - 1); break; } case Instruction.MSIZE: { - gasAvailable -= GasCostOf.Base; + if (!UpdateGas(GasCostOf.Base, ref gasAvailable)) goto OutOfGas; - result = vmState.Memory.Size; - stack.PushUInt256(in result); + UInt256 size = vmState.Memory.Size; + stack.PushUInt256(in size); break; } case Instruction.GAS: { - gasAvailable -= GasCostOf.Base; - // Ensure gas is positive before pushing to stack - if (gasAvailable < 0) goto OutOfGas; + if (!UpdateGas(GasCostOf.Base, ref gasAvailable)) goto OutOfGas; - result = (UInt256)gasAvailable; - stack.PushUInt256(in result); + UInt256 gas = (UInt256)gasAvailable; + stack.PushUInt256(in gas); break; } case Instruction.JUMPDEST: { - gasAvailable -= GasCostOf.JumpDest; + if (!UpdateGas(GasCostOf.JumpDest, ref gasAvailable)) goto OutOfGas; break; } case Instruction.PUSH0: { - if (!spec.IncludePush0Instruction) goto InvalidInstruction; - gasAvailable -= GasCostOf.Base; + if (spec.IncludePush0Instruction) + { + if (!UpdateGas(GasCostOf.Base, ref gasAvailable)) goto OutOfGas; - stack.PushZero(); + stack.PushZero(); + } + else + { + goto InvalidInstruction; + } break; } case Instruction.PUSH1: { - gasAvailable -= GasCostOf.VeryLow; + if (!UpdateGas(GasCostOf.VeryLow, ref gasAvailable)) goto OutOfGas; int programCounterInt = programCounter; if (programCounterInt >= code.Length) @@ -1742,11 +1888,13 @@ private CallResult ExecuteCode data = vmState.Memory.Load(in memoryPos, length); + Keccak[] topics = new Keccak[topicsCount]; + for (int i = 0; i < topicsCount; i++) + { + topics[i] = new Keccak(stack.PopWord256()); + } + + LogEntry logEntry = new( + env.ExecutingAccount, + data.ToArray(), + topics); + vmState.Logs.Add(logEntry); break; } case Instruction.CREATE: case Instruction.CREATE2: { - Metrics.Creates++; if (!spec.Create2OpcodeEnabled && instruction == Instruction.CREATE2) goto InvalidInstruction; if (vmState.IsStatic) goto StaticCallViolation; - (bool outOfGas, returnData) = InstructionCreate(vmState, ref stack, ref gasAvailable, spec, instruction); + // TODO: happens in CREATE_empty000CreateInitCode_Transaction but probably has to be handled differently + if (!_state.AccountExists(env.ExecutingAccount)) + { + _state.CreateAccount(env.ExecutingAccount, UInt256.Zero); + } + + stack.PopUInt256(out UInt256 value); + stack.PopUInt256(out UInt256 memoryPositionOfInitCode); + stack.PopUInt256(out UInt256 initCodeLength); + Span salt = null; + if (instruction == Instruction.CREATE2) + { + salt = stack.PopWord256(); + } + + //EIP-3860 + if (spec.IsEip3860Enabled) + { + if (initCodeLength > spec.MaxInitCodeSize) goto OutOfGas; + } + + long gasCost = GasCostOf.Create + + (spec.IsEip3860Enabled ? GasCostOf.InitCodeWord * EvmPooledMemory.Div32Ceiling(initCodeLength) : 0) + + (instruction == Instruction.CREATE2 ? GasCostOf.Sha3Word * EvmPooledMemory.Div32Ceiling(initCodeLength) : 0); + + if (!UpdateGas(gasCost, ref gasAvailable)) goto OutOfGas; + + if (!UpdateMemoryCost(vmState, ref gasAvailable, in memoryPositionOfInitCode, initCodeLength)) goto OutOfGas; + + // TODO: copy pasted from CALL / DELEGATECALL, need to move it outside? + if (env.CallDepth >= MaxCallDepth) // TODO: fragile ordering / potential vulnerability for different clients + { + // TODO: need a test for this + _returnDataBuffer = Array.Empty(); + stack.PushZero(); + break; + } - if (outOfGas) goto OutOfGas; - if (returnData is null) break; + Span initCode = vmState.Memory.LoadSpan(in memoryPositionOfInitCode, initCodeLength); - goto DataReturnNoTrace; + UInt256 balance = _state.GetBalance(env.ExecutingAccount); + if (value > balance) + { + _returnDataBuffer = Array.Empty(); + stack.PushZero(); + break; + } + + UInt256 accountNonce = _state.GetNonce(env.ExecutingAccount); + UInt256 maxNonce = ulong.MaxValue; + if (accountNonce >= maxNonce) + { + _returnDataBuffer = Array.Empty(); + stack.PushZero(); + break; + } + + if (traceOpcodes) EndInstructionTrace(gasAvailable, vmState.Memory?.Size ?? 0); + // todo: === below is a new call - refactor / move + + long callGas = spec.Use63Over64Rule ? gasAvailable - gasAvailable / 64L : gasAvailable; + if (!UpdateGas(callGas, ref gasAvailable)) goto OutOfGas; + + Address contractAddress = instruction == Instruction.CREATE + ? ContractAddress.From(env.ExecutingAccount, _state.GetNonce(env.ExecutingAccount)) + : ContractAddress.From(env.ExecutingAccount, salt, initCode); + + if (spec.UseHotAndColdStorage) + { + // EIP-2929 assumes that warm-up cost is included in the costs of CREATE and CREATE2 + vmState.WarmUp(contractAddress); + } + + _state.IncrementNonce(env.ExecutingAccount); + + Snapshot snapshot = _worldState.TakeSnapshot(); + + bool accountExists = _state.AccountExists(contractAddress); + if (accountExists && (GetCachedCodeInfo(_worldState, contractAddress, spec).MachineCode.Length != 0 || _state.GetNonce(contractAddress) != 0)) + { + /* we get the snapshot before this as there is a possibility with that we will touch an empty account and remove it even if the REVERT operation follows */ + if (isTrace) _logger.Trace($"Contract collision at {contractAddress}"); + _returnDataBuffer = Array.Empty(); + stack.PushZero(); + break; + } + + if (accountExists) + { + _state.UpdateStorageRoot(contractAddress, Keccak.EmptyTreeHash); + } + else if (_state.IsDeadAccount(contractAddress)) + { + _state.ClearStorage(contractAddress); + } + + _state.SubtractFromBalance(env.ExecutingAccount, value, spec); + ExecutionEnvironment callEnv = new + ( + txExecutionContext: env.TxExecutionContext, + callDepth: env.CallDepth + 1, + caller: env.ExecutingAccount, + executingAccount: contractAddress, + codeSource: null, + codeInfo: new CodeInfo(initCode.ToArray()), + inputData: default, + transferValue: value, + value: value + ); + EvmState callState = new( + callGas, + callEnv, + instruction == Instruction.CREATE2 ? ExecutionType.Create2 : ExecutionType.Create, + false, + snapshot, + 0L, + 0L, + vmState.IsStatic, + vmState, + false, + accountExists); + + UpdateCurrentState(vmState, programCounter, gasAvailable, stack.Head); + return new CallResult(callState); } case Instruction.RETURN: { - if (!InstructionReturn(vmState, ref stack, ref gasAvailable, out returnData)) goto OutOfGas; + stack.PopUInt256(out UInt256 memoryPos); + stack.PopUInt256(out UInt256 length); + + if (!UpdateMemoryCost(vmState, ref gasAvailable, in memoryPos, length)) goto OutOfGas; + ReadOnlyMemory returnData = vmState.Memory.Load(in memoryPos, length); - goto DataReturn; + UpdateCurrentState(vmState, programCounter, gasAvailable, stack.Head); + if (traceOpcodes) EndInstructionTrace(gasAvailable, vmState.Memory?.Size ?? 0); + return new CallResult(returnData.ToArray(), null); } case Instruction.CALL: case Instruction.CALLCODE: case Instruction.DELEGATECALL: case Instruction.STATICCALL: { - exceptionType = InstructionCall(vmState, ref stack, ref gasAvailable, spec, instruction, out returnData); - if (exceptionType != EvmExceptionType.None) + Metrics.Calls++; + + if (instruction == Instruction.DELEGATECALL && !spec.DelegateCallEnabled || + instruction == Instruction.STATICCALL && !spec.StaticCallEnabled) goto InvalidInstruction; + + stack.PopUInt256(out UInt256 gasLimit); + Address codeSource = stack.PopAddress(); + + // Console.WriteLine($"CALLIN {codeSource}"); + if (!ChargeAccountAccessGas(ref gasAvailable, vmState, codeSource, spec)) goto OutOfGas; + + UInt256 callValue; + switch (instruction) { - goto ReturnFailure; + case Instruction.STATICCALL: + callValue = UInt256.Zero; + break; + case Instruction.DELEGATECALL: + callValue = env.Value; + break; + default: + stack.PopUInt256(out callValue); + break; } - if (returnData is null) + + UInt256 transferValue = instruction == Instruction.DELEGATECALL ? UInt256.Zero : callValue; + stack.PopUInt256(out UInt256 dataOffset); + stack.PopUInt256(out UInt256 dataLength); + stack.PopUInt256(out UInt256 outputOffset); + stack.PopUInt256(out UInt256 outputLength); + + if (vmState.IsStatic && !transferValue.IsZero && instruction != Instruction.CALLCODE) goto StaticCallViolation; + + Address caller = instruction == Instruction.DELEGATECALL ? env.Caller : env.ExecutingAccount; + Address target = instruction == Instruction.CALL || instruction == Instruction.STATICCALL ? codeSource : env.ExecutingAccount; + + if (isTrace) + { + _logger.Trace($"caller {caller}"); + _logger.Trace($"code source {codeSource}"); + _logger.Trace($"target {target}"); + _logger.Trace($"value {callValue}"); + _logger.Trace($"transfer value {transferValue}"); + } + + long gasExtra = 0L; + + if (!transferValue.IsZero) + { + gasExtra += GasCostOf.CallValue; + } + + if (!spec.ClearEmptyAccountWhenTouched && !_state.AccountExists(target)) + { + gasExtra += GasCostOf.NewAccount; + } + else if (spec.ClearEmptyAccountWhenTouched && transferValue != 0 && _state.IsDeadAccount(target)) + { + gasExtra += GasCostOf.NewAccount; + } + + if (!UpdateGas(spec.GetCallCost(), ref gasAvailable) || + !UpdateMemoryCost(vmState, ref gasAvailable, in dataOffset, dataLength) || + !UpdateMemoryCost(vmState, ref gasAvailable, in outputOffset, outputLength) || + !UpdateGas(gasExtra, ref gasAvailable)) goto OutOfGas; + + if (spec.Use63Over64Rule) + { + gasLimit = UInt256.Min((UInt256)(gasAvailable - gasAvailable / 64), gasLimit); + } + + if (gasLimit >= long.MaxValue) goto OutOfGas; + + long gasLimitUl = (long)gasLimit; + if (!UpdateGas(gasLimitUl, ref gasAvailable)) goto OutOfGas; + + if (!transferValue.IsZero) + { + if (_txTracer.IsTracingRefunds) _txTracer.ReportExtraGasPressure(GasCostOf.CallStipend); + gasLimitUl += GasCostOf.CallStipend; + } + + if (env.CallDepth >= MaxCallDepth || !transferValue.IsZero && _state.GetBalance(env.ExecutingAccount) < transferValue) { + _returnDataBuffer = Array.Empty(); + stack.PushZero(); + + if (_txTracer.IsTracingInstructions) + { + // very specific for Parity trace, need to find generalization - very peculiar 32 length... + ReadOnlyMemory memoryTrace = vmState.Memory.Inspect(in dataOffset, 32); + _txTracer.ReportMemoryChange(dataOffset, memoryTrace.Span); + } + + if (isTrace) _logger.Trace("FAIL - call depth"); + if (_txTracer.IsTracingInstructions) _txTracer.ReportOperationRemainingGas(gasAvailable); + if (_txTracer.IsTracingInstructions) _txTracer.ReportOperationError(EvmExceptionType.NotEnoughBalance); + + UpdateGasUp(gasLimitUl, ref gasAvailable); + if (_txTracer.IsTracingInstructions) _txTracer.ReportGasUpdateForVmTrace(gasLimitUl, gasAvailable); break; } - goto DataReturn; + ReadOnlyMemory callData = vmState.Memory.Load(in dataOffset, dataLength); + + Snapshot snapshot = _worldState.TakeSnapshot(); + _state.SubtractFromBalance(caller, transferValue, spec); + + ExecutionEnvironment callEnv = new + ( + txExecutionContext: env.TxExecutionContext, + callDepth: env.CallDepth + 1, + caller: caller, + codeSource: codeSource, + executingAccount: target, + transferValue: transferValue, + value: callValue, + inputData: callData, + codeInfo: GetCachedCodeInfo(_worldState, codeSource, spec) + ); + if (isTrace) _logger.Trace($"Tx call gas {gasLimitUl}"); + if (outputLength == 0) + { + // TODO: when output length is 0 outputOffset can have any value really + // and the value does not matter and it can cause trouble when beyond long range + outputOffset = 0; + } + + ExecutionType executionType = GetCallExecutionType(instruction, txCtx.Header.IsPostMerge); + EvmState callState = new( + gasLimitUl, + callEnv, + executionType, + false, + snapshot, + (long)outputOffset, + (long)outputLength, + instruction == Instruction.STATICCALL || vmState.IsStatic, + vmState, + false, + false); + + UpdateCurrentState(vmState, programCounter, gasAvailable, stack.Head); + if (traceOpcodes) EndInstructionTrace(gasAvailable, vmState.Memory?.Size ?? 0); + return new CallResult(callState); } case Instruction.REVERT: { if (!spec.RevertOpcodeEnabled) goto InvalidInstruction; - if (!InstructionRevert(vmState, ref stack, ref gasAvailable, out returnData)) goto OutOfGas; + stack.PopUInt256(out UInt256 memoryPos); + stack.PopUInt256(out UInt256 length); + + if (!UpdateMemoryCost(vmState, ref gasAvailable, in memoryPos, length)) goto OutOfGas; + ReadOnlyMemory errorDetails = vmState.Memory.Load(in memoryPos, length); - isRevert = true; - goto DataReturn; + UpdateCurrentState(vmState, programCounter, gasAvailable, stack.Head); + if (traceOpcodes) EndInstructionTrace(gasAvailable, vmState.Memory?.Size ?? 0); + return new CallResult(errorDetails.ToArray(), null, true); } case Instruction.INVALID: { - gasAvailable -= GasCostOf.High; + if (!UpdateGas(GasCostOf.High, ref gasAvailable)) goto OutOfGas; goto InvalidInstruction; } @@ -1863,22 +2292,49 @@ private CallResult ExecuteCode= 256UL) { stack.PopLimbo(); @@ -1886,9 +2342,9 @@ private CallResult ExecuteCode= 256) { stack.PopLimbo(); @@ -1907,9 +2363,9 @@ private CallResult ExecuteCode> (int)a.u0; - stack.PushUInt256(in result); + stack.PopUInt256(out UInt256 b); + UInt256 res = b >> (int)a.u0; + stack.PushUInt256(in res); } break; @@ -1918,25 +2374,26 @@ private CallResult ExecuteCode= BigInt256) { - if (As(ref b).Sign >= 0) + if (b.Sign >= 0) { stack.PushZero(); } else { - stack.PushSignedInt256(in Int256.MinusOne); + Int256.Int256 res = Int256.Int256.MinusOne; + stack.PushSignedInt256(in res); } } else { - As(ref b).RightShift((int)a, out As(ref result)); - stack.PushUInt256(in result); + b.RightShift((int)a, out Int256.Int256 res); + stack.PushSignedInt256(in res); } break; @@ -1945,7 +2402,8 @@ private CallResult ExecuteCode(gasAvailable, exceptionType); - } - - [SkipLocalsInit] - [MethodImpl(MethodImplOptions.NoInlining)] - private void InstructionExtCodeSize(Address address, ref EvmStack stack, IReleaseSpec spec) where TTracingInstructions : struct, IIsTracing - { - byte[] accountCode = GetCachedCodeInfo(_worldState, address, spec).MachineCode; - UInt256 result = (UInt256)accountCode.Length; - stack.PushUInt256(in result); + if (traceOpcodes) EndInstructionTraceError(gasAvailable, EvmExceptionType.AccessViolation); + return CallResult.AccessViolationException; } - [SkipLocalsInit] - private EvmExceptionType InstructionCall(EvmState vmState, ref EvmStack stack, ref long gasAvailable, IReleaseSpec spec, - Instruction instruction, out object returnData) - where TTracingInstructions : struct, IIsTracing - where TTracingRefunds : struct, IIsTracing - { - returnData = null; - ref readonly ExecutionEnvironment env = ref vmState.Env; - - Metrics.Calls++; - - if (instruction == Instruction.DELEGATECALL && !spec.DelegateCallEnabled || - instruction == Instruction.STATICCALL && !spec.StaticCallEnabled) return EvmExceptionType.BadInstruction; - - stack.PopUInt256(out UInt256 gasLimit); - Address codeSource = stack.PopAddress(); - - if (!ChargeAccountAccessGas(ref gasAvailable, vmState, codeSource, spec)) return EvmExceptionType.OutOfGas; - - UInt256 callValue; - switch (instruction) - { - case Instruction.STATICCALL: - callValue = UInt256.Zero; - break; - case Instruction.DELEGATECALL: - callValue = env.Value; - break; - default: - stack.PopUInt256(out callValue); - break; - } - - UInt256 transferValue = instruction == Instruction.DELEGATECALL ? UInt256.Zero : callValue; - stack.PopUInt256(out UInt256 dataOffset); - stack.PopUInt256(out UInt256 dataLength); - stack.PopUInt256(out UInt256 outputOffset); - stack.PopUInt256(out UInt256 outputLength); - - if (vmState.IsStatic && !transferValue.IsZero && instruction != Instruction.CALLCODE) return EvmExceptionType.StaticCallViolation; - - Address caller = instruction == Instruction.DELEGATECALL ? env.Caller : env.ExecutingAccount; - Address target = instruction == Instruction.CALL || instruction == Instruction.STATICCALL - ? codeSource - : env.ExecutingAccount; - - if (typeof(TLogger) == typeof(IsTracing)) - { - _logger.Trace($"caller {caller}"); - _logger.Trace($"code source {codeSource}"); - _logger.Trace($"target {target}"); - _logger.Trace($"value {callValue}"); - _logger.Trace($"transfer value {transferValue}"); - } - - long gasExtra = 0L; - - if (!transferValue.IsZero) - { - gasExtra += GasCostOf.CallValue; - } - - if (!spec.ClearEmptyAccountWhenTouched && !_state.AccountExists(target)) - { - gasExtra += GasCostOf.NewAccount; - } - else if (spec.ClearEmptyAccountWhenTouched && transferValue != 0 && _state.IsDeadAccount(target)) - { - gasExtra += GasCostOf.NewAccount; - } - - if (!UpdateGas(spec.GetCallCost(), ref gasAvailable) || - !UpdateMemoryCost(vmState, ref gasAvailable, in dataOffset, dataLength) || - !UpdateMemoryCost(vmState, ref gasAvailable, in outputOffset, outputLength) || - !UpdateGas(gasExtra, ref gasAvailable)) return EvmExceptionType.OutOfGas; - - if (spec.Use63Over64Rule) - { - gasLimit = UInt256.Min((UInt256)(gasAvailable - gasAvailable / 64), gasLimit); - } - - if (gasLimit >= long.MaxValue) return EvmExceptionType.OutOfGas; - - long gasLimitUl = (long)gasLimit; - if (!UpdateGas(gasLimitUl, ref gasAvailable)) return EvmExceptionType.OutOfGas; - - if (!transferValue.IsZero) - { - if (typeof(TTracingRefunds) == typeof(IsTracing)) _txTracer.ReportExtraGasPressure(GasCostOf.CallStipend); - gasLimitUl += GasCostOf.CallStipend; - } - - if (env.CallDepth >= MaxCallDepth || - !transferValue.IsZero && _state.GetBalance(env.ExecutingAccount) < transferValue) - { - _returnDataBuffer = Array.Empty(); - stack.PushZero(); - - if (typeof(TTracingInstructions) == typeof(IsTracing)) - { - // very specific for Parity trace, need to find generalization - very peculiar 32 length... - ReadOnlyMemory memoryTrace = vmState.Memory.Inspect(in dataOffset, 32); - _txTracer.ReportMemoryChange(dataOffset, memoryTrace.Span); - } - - if (typeof(TLogger) == typeof(IsTracing)) _logger.Trace("FAIL - call depth"); - if (typeof(TTracingInstructions) == typeof(IsTracing)) _txTracer.ReportOperationRemainingGas(gasAvailable); - if (typeof(TTracingInstructions) == typeof(IsTracing)) _txTracer.ReportOperationError(EvmExceptionType.NotEnoughBalance); - - UpdateGasUp(gasLimitUl, ref gasAvailable); - if (typeof(TTracingInstructions) == typeof(IsTracing)) _txTracer.ReportGasUpdateForVmTrace(gasLimitUl, gasAvailable); - return EvmExceptionType.None; - } - - ReadOnlyMemory callData = vmState.Memory.Load(in dataOffset, dataLength); - - Snapshot snapshot = _worldState.TakeSnapshot(); - _state.SubtractFromBalance(caller, transferValue, spec); - - ExecutionEnvironment callEnv = new - ( - txExecutionContext: env.TxExecutionContext, - callDepth: env.CallDepth + 1, - caller: caller, - codeSource: codeSource, - executingAccount: target, - transferValue: transferValue, - value: callValue, - inputData: callData, - codeInfo: GetCachedCodeInfo(_worldState, codeSource, spec) - ); - if (typeof(TLogger) == typeof(IsTracing)) _logger.Trace($"Tx call gas {gasLimitUl}"); - if (outputLength == 0) - { - // TODO: when output length is 0 outputOffset can have any value really - // and the value does not matter and it can cause trouble when beyond long range - outputOffset = 0; - } - - ExecutionType executionType = GetCallExecutionType(instruction, env.TxExecutionContext.BlockExecutionContext.Header.IsPostMerge); - returnData = new EvmState( - gasLimitUl, - callEnv, - executionType, - isTopLevel: false, - snapshot, - (long)outputOffset, - (long)outputLength, - instruction == Instruction.STATICCALL || vmState.IsStatic, - vmState, - isContinuation: false, - isCreateOnPreExistingAccount: false); - - return EvmExceptionType.None; - } - - [SkipLocalsInit] - private static bool InstructionRevert(EvmState vmState, ref EvmStack stack, ref long gasAvailable, out object returnData) - where TTracing : struct, IIsTracing - { - stack.PopUInt256(out UInt256 position); - stack.PopUInt256(out UInt256 length); - - if (!UpdateMemoryCost(vmState, ref gasAvailable, in position, in length)) - { - returnData = null; - return false; - } - - returnData = vmState.Memory.Load(in position, in length).ToArray(); - return true; - } - - [SkipLocalsInit] - private static bool InstructionReturn(EvmState vmState, ref EvmStack stack, ref long gasAvailable, out object returnData) - where TTracing : struct, IIsTracing - { - stack.PopUInt256(out UInt256 position); - stack.PopUInt256(out UInt256 length); - - if (!UpdateMemoryCost(vmState, ref gasAvailable, in position, in length)) - { - returnData = null; - return false; - } - - returnData = vmState.Memory.Load(in position, in length).ToArray(); - - return true; - } - - [SkipLocalsInit] - private bool InstructionSelfDestruct(EvmState vmState, ref EvmStack stack, ref long gasAvailable, IReleaseSpec spec) - where TTracing : struct, IIsTracing - { - Metrics.SelfDestructs++; - - Address inheritor = stack.PopAddress(); - if (!ChargeAccountAccessGas(ref gasAvailable, vmState, inheritor, spec, false)) return false; - - Address executingAccount = vmState.Env.ExecutingAccount; - bool createInSameTx = vmState.CreateList.Contains(executingAccount); - if (!spec.SelfdestructOnlyOnSameTransaction || createInSameTx) - vmState.DestroyList.Add(executingAccount); - - UInt256 result = _state.GetBalance(executingAccount); - if (_txTracer.IsTracingActions) _txTracer.ReportSelfDestruct(executingAccount, result, inheritor); - if (spec.ClearEmptyAccountWhenTouched && !result.IsZero && _state.IsDeadAccount(inheritor)) - { - if (!UpdateGas(GasCostOf.NewAccount, ref gasAvailable)) return false; - } - - bool inheritorAccountExists = _state.AccountExists(inheritor); - if (!spec.ClearEmptyAccountWhenTouched && !inheritorAccountExists && spec.UseShanghaiDDosProtection) - { - if (!UpdateGas(GasCostOf.NewAccount, ref gasAvailable)) return false; - } - - if (!inheritorAccountExists) - { - _state.CreateAccount(inheritor, result); - } - else if (!inheritor.Equals(executingAccount)) - { - _state.AddToBalance(inheritor, result, spec); - } - - if (spec.SelfdestructOnlyOnSameTransaction && !createInSameTx && inheritor.Equals(executingAccount)) - return true; // dont burn eth when contract is not destroyed per EIP clarification - - _state.SubtractFromBalance(executingAccount, result, spec); - return true; - } - - [SkipLocalsInit] - private (bool outOfGas, EvmState? callState) InstructionCreate(EvmState vmState, ref EvmStack stack, ref long gasAvailable, IReleaseSpec spec, Instruction instruction) - where TTracing : struct, IIsTracing - { - ref readonly ExecutionEnvironment env = ref vmState.Env; - - // TODO: happens in CREATE_empty000CreateInitCode_Transaction but probably has to be handled differently - if (!_state.AccountExists(env.ExecutingAccount)) - { - _state.CreateAccount(env.ExecutingAccount, UInt256.Zero); - } - - stack.PopUInt256(out UInt256 value); - stack.PopUInt256(out UInt256 memoryPositionOfInitCode); - stack.PopUInt256(out UInt256 initCodeLength); - Span salt = default; - if (instruction == Instruction.CREATE2) - { - salt = stack.PopWord256(); - } - - //EIP-3860 - if (spec.IsEip3860Enabled) - { - if (initCodeLength > spec.MaxInitCodeSize) return (outOfGas: true, null); - } - - long gasCost = GasCostOf.Create + - (spec.IsEip3860Enabled ? GasCostOf.InitCodeWord * EvmPooledMemory.Div32Ceiling(initCodeLength) : 0) + - (instruction == Instruction.CREATE2 - ? GasCostOf.Sha3Word * EvmPooledMemory.Div32Ceiling(initCodeLength) - : 0); - - if (!UpdateGas(gasCost, ref gasAvailable)) return (outOfGas: true, null); - - if (!UpdateMemoryCost(vmState, ref gasAvailable, in memoryPositionOfInitCode, initCodeLength)) return (outOfGas: true, null); - - // TODO: copy pasted from CALL / DELEGATECALL, need to move it outside? - if (env.CallDepth >= MaxCallDepth) // TODO: fragile ordering / potential vulnerability for different clients - { - // TODO: need a test for this - _returnDataBuffer = Array.Empty(); - stack.PushZero(); - return (outOfGas: false, null); - } - - Span initCode = vmState.Memory.LoadSpan(in memoryPositionOfInitCode, initCodeLength); - - UInt256 balance = _state.GetBalance(env.ExecutingAccount); - if (value > balance) - { - _returnDataBuffer = Array.Empty(); - stack.PushZero(); - return (outOfGas: false, null); - } - - UInt256 accountNonce = _state.GetNonce(env.ExecutingAccount); - UInt256 maxNonce = ulong.MaxValue; - if (accountNonce >= maxNonce) - { - _returnDataBuffer = Array.Empty(); - stack.PushZero(); - return (outOfGas: false, null); - } - - if (typeof(TTracing) == typeof(IsTracing)) EndInstructionTrace(gasAvailable, vmState.Memory?.Size ?? 0); - // todo: === below is a new call - refactor / move - - long callGas = spec.Use63Over64Rule ? gasAvailable - gasAvailable / 64L : gasAvailable; - if (!UpdateGas(callGas, ref gasAvailable)) return (outOfGas: true, null); - - Address contractAddress = instruction == Instruction.CREATE - ? ContractAddress.From(env.ExecutingAccount, _state.GetNonce(env.ExecutingAccount)) - : ContractAddress.From(env.ExecutingAccount, salt, initCode); - - if (spec.UseHotAndColdStorage) - { - // EIP-2929 assumes that warm-up cost is included in the costs of CREATE and CREATE2 - vmState.WarmUp(contractAddress); - } - - _state.IncrementNonce(env.ExecutingAccount); - - Snapshot snapshot = _worldState.TakeSnapshot(); - - bool accountExists = _state.AccountExists(contractAddress); - if (accountExists && (GetCachedCodeInfo(_worldState, contractAddress, spec).MachineCode.Length != 0 || - _state.GetNonce(contractAddress) != 0)) - { - /* we get the snapshot before this as there is a possibility with that we will touch an empty account and remove it even if the REVERT operation follows */ - if (typeof(TLogger) == typeof(IsTracing)) _logger.Trace($"Contract collision at {contractAddress}"); - _returnDataBuffer = Array.Empty(); - stack.PushZero(); - return (outOfGas: false, null); - } - - if (accountExists) - { - _state.UpdateStorageRoot(contractAddress, Keccak.EmptyTreeHash); - } - else if (_state.IsDeadAccount(contractAddress)) - { - _state.ClearStorage(contractAddress); - } - - _state.SubtractFromBalance(env.ExecutingAccount, value, spec); - - ValueKeccak codeHash = ValueKeccak.Compute(initCode); - // Prefer code from code cache (e.g. if create from a factory contract or copypasta) - if (!_codeCache.TryGet(codeHash, out CodeInfo codeInfo)) - { - codeInfo = new(initCode.ToArray()); - // Prime the code cache as likely to be used by more txs - _codeCache.Set(codeHash, codeInfo); - } - - ExecutionEnvironment callEnv = new - ( - txExecutionContext: env.TxExecutionContext, - callDepth: env.CallDepth + 1, - caller: env.ExecutingAccount, - executingAccount: contractAddress, - codeSource: null, - codeInfo: codeInfo, - inputData: default, - transferValue: value, - value: value - ); - EvmState callState = new( - callGas, - callEnv, - instruction == Instruction.CREATE2 ? ExecutionType.Create2 : ExecutionType.Create, - false, - snapshot, - 0L, - 0L, - vmState.IsStatic, - vmState, - false, - accountExists); - - return (outOfGas: false, callState); - } - - [SkipLocalsInit] - private static bool InstructionLog(EvmState vmState, ref EvmStack stack, ref long gasAvailable, Instruction instruction) - where TTracing : struct, IIsTracing - { - stack.PopUInt256(out UInt256 position); - stack.PopUInt256(out UInt256 length); - long topicsCount = instruction - Instruction.LOG0; - if (!UpdateMemoryCost(vmState, ref gasAvailable, in position, length)) return false; - if (!UpdateGas( - GasCostOf.Log + topicsCount * GasCostOf.LogTopic + - (long)length * GasCostOf.LogData, ref gasAvailable)) return false; - - ReadOnlyMemory data = vmState.Memory.Load(in position, length); - Keccak[] topics = new Keccak[topicsCount]; - for (int i = 0; i < topicsCount; i++) - { - topics[i] = new Keccak(stack.PopWord256()); - } - - LogEntry logEntry = new( - vmState.Env.ExecutingAccount, - data.ToArray(), - topics); - vmState.Logs.Add(logEntry); - - return true; - } - - [SkipLocalsInit] - private bool InstructionSStore(EvmState vmState, ref EvmStack stack, ref long gasAvailable, IReleaseSpec spec) - where TTracingInstructions : struct, IIsTracing - where TTracingRefunds : struct, IIsTracing - where TTracingStorage : struct, IIsTracing - { - // fail fast before the first storage read if gas is not enough even for reset - if (!spec.UseNetGasMetering && !UpdateGas(spec.GetSStoreResetCost(), ref gasAvailable)) return false; - - if (spec.UseNetGasMeteringWithAStipendFix) - { - if (typeof(TTracingRefunds) == typeof(IsTracing)) - _txTracer.ReportExtraGasPressure(GasCostOf.CallStipend - spec.GetNetMeteredSStoreCost() + 1); - if (gasAvailable <= GasCostOf.CallStipend) return false; - } - - stack.PopUInt256(out UInt256 result); - Span bytes = stack.PopWord256(); - bool newIsZero = bytes.IsZero(); - if (!newIsZero) - { - bytes = bytes.WithoutLeadingZeros().ToArray(); - } - else - { - bytes = new byte[] { 0 }; - } - - StorageCell storageCell = new(vmState.Env.ExecutingAccount, result); - - if (!ChargeStorageAccessGas( - ref gasAvailable, - vmState, - in storageCell, - StorageAccessType.SSTORE, - spec)) return false; - - Span currentValue = _state.Get(in storageCell); - // Console.WriteLine($"current: {currentValue.ToHexString()} newValue {newValue.ToHexString()}"); - bool currentIsZero = currentValue.IsZero(); - - bool newSameAsCurrent = (newIsZero && currentIsZero) || Bytes.AreEqual(currentValue, bytes); - long sClearRefunds = RefundOf.SClear(spec.IsEip3529Enabled); - - if (!spec.UseNetGasMetering) // note that for this case we already deducted 5000 - { - if (newIsZero) - { - if (!newSameAsCurrent) - { - vmState.Refund += sClearRefunds; - if (typeof(TTracingRefunds) == typeof(IsTracing)) _txTracer.ReportRefund(sClearRefunds); - } - } - else if (currentIsZero) - { - if (!UpdateGas(GasCostOf.SSet - GasCostOf.SReset, ref gasAvailable)) return false; - } - } - else // net metered - { - if (newSameAsCurrent) - { - if (!UpdateGas(spec.GetNetMeteredSStoreCost(), ref gasAvailable)) return false; - } - else // net metered, C != N - { - Span originalValue = _state.GetOriginal(in storageCell); - bool originalIsZero = originalValue.IsZero(); - - bool currentSameAsOriginal = Bytes.AreEqual(originalValue, currentValue); - if (currentSameAsOriginal) - { - if (currentIsZero) - { - if (!UpdateGas(GasCostOf.SSet, ref gasAvailable)) return false; - } - else // net metered, current == original != new, !currentIsZero - { - if (!UpdateGas(spec.GetSStoreResetCost(), ref gasAvailable)) return false; - - if (newIsZero) - { - vmState.Refund += sClearRefunds; - if (typeof(TTracingRefunds) == typeof(IsTracing)) _txTracer.ReportRefund(sClearRefunds); - } - } - } - else // net metered, new != current != original - { - long netMeteredStoreCost = spec.GetNetMeteredSStoreCost(); - if (!UpdateGas(netMeteredStoreCost, ref gasAvailable)) return false; - - if (!originalIsZero) // net metered, new != current != original != 0 - { - if (currentIsZero) - { - vmState.Refund -= sClearRefunds; - if (typeof(TTracingRefunds) == typeof(IsTracing)) _txTracer.ReportRefund(-sClearRefunds); - } - - if (newIsZero) - { - vmState.Refund += sClearRefunds; - if (typeof(TTracingRefunds) == typeof(IsTracing)) _txTracer.ReportRefund(sClearRefunds); - } - } - - bool newSameAsOriginal = Bytes.AreEqual(originalValue, bytes); - if (newSameAsOriginal) - { - long refundFromReversal; - if (originalIsZero) - { - refundFromReversal = spec.GetSetReversalRefund(); - } - else - { - refundFromReversal = spec.GetClearReversalRefund(); - } - - vmState.Refund += refundFromReversal; - if (typeof(TTracingRefunds) == typeof(IsTracing)) _txTracer.ReportRefund(refundFromReversal); - } - } - } - } - - if (!newSameAsCurrent) - { - _state.Set(in storageCell, newIsZero ? BytesZero : bytes.ToArray()); - } - - if (typeof(TTracingInstructions) == typeof(IsTracing)) - { - Span valueToStore = newIsZero ? BytesZero : bytes; - bytes = new byte[32]; // do not stackalloc here - storageCell.Index.ToBigEndian(bytes); - _txTracer.ReportStorageChange(bytes, valueToStore); - } - - if (typeof(TTracingStorage) == typeof(IsTracing)) - { - _txTracer.SetOperationStorage(storageCell.Address, result, bytes, currentValue); - } - - return true; - } - - private CallResult GetFailureReturn(long gasAvailable, EvmExceptionType exceptionType) - where TTracingInstructions : struct, IIsTracing - { - if (typeof(TTracingInstructions) == typeof(IsTracing)) EndInstructionTraceError(gasAvailable, exceptionType); - - return exceptionType switch - { - EvmExceptionType.OutOfGas => CallResult.OutOfGasException, - EvmExceptionType.BadInstruction => CallResult.InvalidInstructionException, - EvmExceptionType.StaticCallViolation => CallResult.StaticCallViolationException, - EvmExceptionType.InvalidSubroutineEntry => CallResult.InvalidSubroutineEntry, - EvmExceptionType.InvalidSubroutineReturn => CallResult.InvalidSubroutineReturn, - EvmExceptionType.StackOverflow => CallResult.StackOverflowException, - EvmExceptionType.InvalidJumpDestination => CallResult.InvalidJumpDestination, - EvmExceptionType.AccessViolation => CallResult.AccessViolationException, - _ => throw new ArgumentOutOfRangeException(nameof(exceptionType), exceptionType, "") - }; - } - - private static void UpdateCurrentState(EvmState state, int pc, long gas, int stackHead) - { - state.ProgramCounter = pc; - state.GasAvailable = gas; - state.DataStackHead = stackHead; - } - - private static bool UpdateMemoryCost(EvmState vmState, ref long gasAvailable, in UInt256 position, in UInt256 length) + static bool UpdateMemoryCost(EvmState vmState, ref long gasAvailable, in UInt256 position, in UInt256 length) { if (vmState.Memory is null) { @@ -2779,14 +2557,12 @@ private static bool Jump(in UInt256 jumpDest, ref int programCounter, in Executi } [MethodImpl(MethodImplOptions.NoInlining)] - private void StartInstructionTrace(Instruction instruction, EvmState vmState, long gasAvailable, int programCounter, in EvmStack stackValue) - where TIsTracing : struct, IIsTracing + private void StartInstructionTrace(Instruction instruction, EvmState vmState, long gasAvailable, int programCounter, in EvmStack stackValue) { - _txTracer.StartOperation(vmState.Env.CallDepth + 1, gasAvailable, instruction, programCounter, vmState.Env.TxExecutionContext.BlockExecutionContext.Header.IsPostMerge); + _txTracer.StartOperation(vmState.Env.CallDepth + 1, gasAvailable, instruction, programCounter, vmState.Env.TxExecutionContext.Header.IsPostMerge); if (_txTracer.IsTracingMemory) { - _txTracer.SetOperationMemory(vmState.Memory?.GetTrace() ?? Enumerable.Empty()); - _txTracer.SetOperationMemorySize(vmState.Memory?.Size ?? 0); + _txTracer.SetOperationMemory(vmState.Memory?.GetTrace() ?? new List()); } if (_txTracer.IsTracingStack) @@ -2798,6 +2574,11 @@ private void StartInstructionTrace(Instruction instruction, EvmState [MethodImpl(MethodImplOptions.NoInlining)] private void EndInstructionTrace(long gasAvailable, ulong memorySize) { + if (_txTracer.IsTracingMemory) + { + _txTracer.SetOperationMemorySize(memorySize); + } + _txTracer.ReportOperationRemainingGas(gasAvailable); } @@ -2834,4 +2615,62 @@ private static ExecutionType GetCallExecutionType(Instruction instruction, bool return executionType; } + + internal readonly ref struct CallResult + { + public static CallResult InvalidSubroutineEntry => new(EvmExceptionType.InvalidSubroutineEntry); + public static CallResult InvalidSubroutineReturn => new(EvmExceptionType.InvalidSubroutineReturn); + public static CallResult OutOfGasException => new(EvmExceptionType.OutOfGas); + public static CallResult AccessViolationException => new(EvmExceptionType.AccessViolation); + public static CallResult InvalidJumpDestination => new(EvmExceptionType.InvalidJumpDestination); + public static CallResult InvalidInstructionException + { + get + { + return new(EvmExceptionType.BadInstruction); + } + } + + public static CallResult StaticCallViolationException => new(EvmExceptionType.StaticCallViolation); + public static CallResult StackOverflowException => new(EvmExceptionType.StackOverflow); // TODO: use these to avoid CALL POP attacks + public static CallResult StackUnderflowException => new(EvmExceptionType.StackUnderflow); // TODO: use these to avoid CALL POP attacks + + public static CallResult InvalidCodeException => new(EvmExceptionType.InvalidCode); + public static CallResult Empty => new(Array.Empty(), null); + + public CallResult(EvmState stateToExecute) + { + StateToExecute = stateToExecute; + Output = Array.Empty(); + PrecompileSuccess = null; + ShouldRevert = false; + ExceptionType = EvmExceptionType.None; + } + + private CallResult(EvmExceptionType exceptionType) + { + StateToExecute = null; + Output = StatusCode.FailureBytes; + PrecompileSuccess = null; + ShouldRevert = false; + ExceptionType = exceptionType; + } + + public CallResult(byte[] output, bool? precompileSuccess, bool shouldRevert = false, EvmExceptionType exceptionType = EvmExceptionType.None) + { + StateToExecute = null; + Output = output; + PrecompileSuccess = precompileSuccess; + ShouldRevert = shouldRevert; + ExceptionType = exceptionType; + } + + public EvmState? StateToExecute { get; } + public byte[] Output { get; } + public EvmExceptionType ExceptionType { get; } + public bool ShouldRevert { get; } + public bool? PrecompileSuccess { get; } // TODO: check this behaviour as it seems it is required and previously that was not the case + public bool IsReturn => StateToExecute is null; + public bool IsException => ExceptionType != EvmExceptionType.None; + } } diff --git a/src/Nethermind/Nethermind.Evm/ZeroPaddedSpan.cs b/src/Nethermind/Nethermind.Evm/ZeroPaddedSpan.cs index 288654edef5..e285a6d9007 100644 --- a/src/Nethermind/Nethermind.Evm/ZeroPaddedSpan.cs +++ b/src/Nethermind/Nethermind.Evm/ZeroPaddedSpan.cs @@ -32,4 +32,32 @@ public readonly byte[] ToArray() return result; } } + + public ref struct ZeroPaddedMemory + { + public static ZeroPaddedMemory Empty => new(Memory.Empty, 0, PadDirection.Right); + + public ZeroPaddedMemory(ReadOnlyMemory memory, int paddingLength, PadDirection padDirection) + { + PadDirection = padDirection; + Memory = memory; + PaddingLength = paddingLength; + } + + public PadDirection PadDirection; + public ReadOnlyMemory Memory; + public int PaddingLength; + public int Length => Memory.Length + PaddingLength; + + /// + /// Temporary to handle old invocations + /// + /// + public readonly byte[] ToArray() + { + byte[] result = new byte[Memory.Length + PaddingLength]; + Memory.CopyTo(result.AsMemory().Slice(PadDirection == PadDirection.Right ? 0 : PaddingLength, Memory.Length)); + return result; + } + } } diff --git a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs index c25373a8f74..4dba1905c19 100644 --- a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs @@ -132,8 +132,8 @@ public void Estimate_gas_returns_the_estimate_from_the_tracer() _transactionProcessor.Received().CallAndRestore( tx, - Arg.Is(blkCtx => - blkCtx.Header.Number == 11 && blkCtx.Header.Timestamp == ((ITimestamper)_timestamper).UnixTime.Seconds), + Arg.Is(bh => + bh.Number == 11 && bh.Timestamp == ((ITimestamper)_timestamper).UnixTime.Seconds), Arg.Is(t => t.InnerTracer is EstimateGasTracer)); } @@ -150,8 +150,7 @@ public void Call_uses_valid_post_merge_and_random_value() _blockchainBridge.Call(header, tx, CancellationToken.None); _transactionProcessor.Received().CallAndRestore( tx, - Arg.Is(blkCtx => - blkCtx.Header.IsPostMerge && blkCtx.Header.Random == TestItem.KeccakA), + Arg.Is(header => header.IsPostMerge && header.Random == TestItem.KeccakA), Arg.Any()); } @@ -166,7 +165,7 @@ public void Call_uses_valid_block_number() _blockchainBridge.Call(header, tx, CancellationToken.None); _transactionProcessor.Received().CallAndRestore( tx, - Arg.Is(blkCtx => blkCtx.Header.Number == 10), + Arg.Is(bh => bh.Number == 10), Arg.Any()); } @@ -181,7 +180,7 @@ public void Call_uses_valid_mix_hash() _blockchainBridge.Call(header, tx, CancellationToken.None); _transactionProcessor.Received().CallAndRestore( tx, - Arg.Is(blkCtx => blkCtx.Header.MixHash == TestItem.KeccakA), + Arg.Is(bh => bh.MixHash == TestItem.KeccakA), Arg.Any()); } @@ -196,7 +195,7 @@ public void Call_uses_valid_beneficiary() _blockchainBridge.Call(header, tx, CancellationToken.None); _transactionProcessor.Received().CallAndRestore( tx, - Arg.Is(blkCtx => blkCtx.Header.Beneficiary == TestItem.AddressB), + Arg.Is(bh => bh.Beneficiary == TestItem.AddressB), Arg.Any()); } @@ -247,7 +246,7 @@ public void GetReceiptAndGasInfo_returns_correct_results(bool isCanonical, bool ? Build.A.Transaction .WithGasPrice(effectiveGasPrice) .WithType(TxType.Blob) - .WithMaxFeePerBlobGas(2) + .WithMaxFeePerDataGas(2) .WithBlobVersionedHashes(2) .TestObject : Build.A.Transaction @@ -256,7 +255,7 @@ public void GetReceiptAndGasInfo_returns_correct_results(bool isCanonical, bool Block block = postEip4844 ? Build.A.Block .WithTransactions(tx) - .WithExcessBlobGas(2) + .WithExcessDataGas(2) .TestObject : Build.A.Block .WithTransactions(tx) @@ -272,7 +271,7 @@ public void GetReceiptAndGasInfo_returns_correct_results(bool isCanonical, bool _receiptStorage.Get(block).Returns(new[] { receipt }); (TxReceipt? Receipt, TxGasInfo? GasInfo, int LogIndexStart) result = postEip4844 - ? (receipt, new(effectiveGasPrice, 1, 262144), 0) + ? (receipt, new(effectiveGasPrice, 262144, 262144), 0) : (receipt, new(effectiveGasPrice), 0); if (!isCanonical) diff --git a/src/Nethermind/Nethermind.Facade.Test/TxPoolBridgeTests.cs b/src/Nethermind/Nethermind.Facade.Test/TxPoolBridgeTests.cs index 65cc8729908..0dacce0af55 100644 --- a/src/Nethermind/Nethermind.Facade.Test/TxPoolBridgeTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/TxPoolBridgeTests.cs @@ -1,7 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Threading; using FluentAssertions; +using Nethermind.Consensus; using Nethermind.Core; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 810376364c1..28d3780250a 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -179,7 +179,7 @@ public CallOutput EstimateGas(BlockHeader header, Transaction tx, CancellationTo GasEstimator gasEstimator = new(readOnlyTransactionProcessor, _processingEnv.StateProvider, _specProvider, _blocksConfig); - long estimate = gasEstimator.Estimate(tx, header, estimateGasTracer, cancellationToken); + long estimate = gasEstimator.Estimate(tx, header, estimateGasTracer); return new CallOutput { @@ -251,7 +251,7 @@ private void CallAndRestore( UInt256.Zero, blockHeader.Number + 1, blockHeader.GasLimit, - Math.Max(blockHeader.Timestamp + _blocksConfig.SecondsPerSlot, _timestamper.UnixTime.Seconds), + Math.Max(blockHeader.Timestamp + 1, _timestamper.UnixTime.Seconds), Array.Empty()) : new( blockHeader.ParentHash!, @@ -270,15 +270,15 @@ private void CallAndRestore( if (releaseSpec.IsEip4844Enabled) { - callHeader.BlobGasUsed = BlobGasCalculator.CalculateBlobGas(transaction); - callHeader.ExcessBlobGas = treatBlockHeaderAsParentBlock - ? BlobGasCalculator.CalculateExcessBlobGas(blockHeader, releaseSpec) - : blockHeader.ExcessBlobGas; + callHeader.DataGasUsed = DataGasCalculator.CalculateDataGas(transaction); + callHeader.ExcessDataGas = treatBlockHeaderAsParentBlock + ? DataGasCalculator.CalculateExcessDataGas(blockHeader, releaseSpec) + : blockHeader.ExcessDataGas; } callHeader.MixHash = blockHeader.MixHash; callHeader.IsPostMerge = blockHeader.Difficulty == 0; transaction.Hash = transaction.CalculateHash(); - transactionProcessor.CallAndRestore(transaction, new(callHeader), tracer); + transactionProcessor.CallAndRestore(transaction, callHeader, tracer); } public ulong GetChainId() @@ -316,10 +316,10 @@ public bool TryGetLogs(int filterId, out IEnumerable filterLogs, Canc return filter is not null; } - public int NewFilter(BlockParameter? fromBlock, BlockParameter? toBlock, + public int NewFilter(BlockParameter fromBlock, BlockParameter toBlock, object? address = null, IEnumerable? topics = null) { - LogFilter filter = _filterStore.CreateLogFilter(fromBlock ?? BlockParameter.Latest, toBlock ?? BlockParameter.Latest, address, topics); + LogFilter filter = _filterStore.CreateLogFilter(fromBlock, toBlock, address, topics); _filterStore.SaveFilter(filter); return filter.Id; } diff --git a/src/Nethermind/Nethermind.Facade/Eth/EthSyncingInfo.cs b/src/Nethermind/Nethermind.Facade/Eth/EthSyncingInfo.cs index d2843b54013..c6aad7591c4 100644 --- a/src/Nethermind/Nethermind.Facade/Eth/EthSyncingInfo.cs +++ b/src/Nethermind/Nethermind.Facade/Eth/EthSyncingInfo.cs @@ -101,8 +101,6 @@ public TimeSpan UpdateAndGetSyncTime() return _syncStopwatch.Elapsed; } - public SyncMode SyncMode => _syncModeSelector.Current; - public bool IsSyncing() { return GetFullInfo().IsSyncing; diff --git a/src/Nethermind/Nethermind.Facade/Eth/IEthSyncingInfo.cs b/src/Nethermind/Nethermind.Facade/Eth/IEthSyncingInfo.cs index 80630ad1b21..51df6914ad5 100644 --- a/src/Nethermind/Nethermind.Facade/Eth/IEthSyncingInfo.cs +++ b/src/Nethermind/Nethermind.Facade/Eth/IEthSyncingInfo.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using Nethermind.Synchronization.ParallelSync; namespace Nethermind.Facade.Eth { @@ -13,7 +12,5 @@ public interface IEthSyncingInfo bool IsSyncing(); TimeSpan UpdateAndGetSyncTime(); - - SyncMode SyncMode { get; } } } diff --git a/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs b/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs index 84a0dbb7072..f3722216202 100644 --- a/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs +++ b/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs @@ -9,10 +9,10 @@ namespace Nethermind.Blockchain.Filters { public class AddressFilter { - public static readonly AddressFilter AnyAddress = new(addresses: new HashSet
()); + public static AddressFilter AnyAddress = new((Address)null); - private Bloom.BloomExtract[]? _addressesBloomIndexes; - private Bloom.BloomExtract? _addressBloomExtract; + private Core.Bloom.BloomExtract[] _addressesBloomIndexes; + private Core.Bloom.BloomExtract? _addressBloomExtract; public AddressFilter(Address address) { @@ -24,14 +24,14 @@ public AddressFilter(HashSet
addresses) Addresses = addresses; } - public Address? Address { get; } - public HashSet
? Addresses { get; } - private Bloom.BloomExtract[] AddressesBloomExtracts => _addressesBloomIndexes ??= CalculateBloomExtracts(); - private Bloom.BloomExtract AddressBloomExtract => _addressBloomExtract ??= Bloom.GetExtract(Address); + public Address? Address { get; set; } + public HashSet
? Addresses { get; set; } + private Core.Bloom.BloomExtract[] AddressesBloomExtracts => _addressesBloomIndexes ??= CalculateBloomExtracts(); + private Core.Bloom.BloomExtract AddressBloomExtract => _addressBloomExtract ??= Core.Bloom.GetExtract(Address); public bool Accepts(Address address) { - if (Addresses?.Count > 0) + if (Addresses is not null) { return Addresses.Contains(address); } @@ -41,7 +41,7 @@ public bool Accepts(Address address) public bool Accepts(ref AddressStructRef address) { - if (Addresses?.Count > 0) + if (Addresses is not null) { foreach (var a in Addresses) { @@ -54,7 +54,7 @@ public bool Accepts(ref AddressStructRef address) return Address is null || Address == address; } - public bool Matches(Bloom bloom) + public bool Matches(Core.Bloom bloom) { if (Addresses is not null) { @@ -71,11 +71,14 @@ public bool Matches(Bloom bloom) return result; } - if (Address is null) + else if (Address is null) { return true; } - return bloom.Matches(AddressBloomExtract); + else + { + return bloom.Matches(AddressBloomExtract); + } } public bool Matches(ref BloomStructRef bloom) @@ -95,13 +98,16 @@ public bool Matches(ref BloomStructRef bloom) return result; } - if (Address is null) + else if (Address is null) { return true; } - return bloom.Matches(AddressBloomExtract); + else + { + return bloom.Matches(AddressBloomExtract); + } } - private Bloom.BloomExtract[] CalculateBloomExtracts() => Addresses.Select(Bloom.GetExtract).ToArray(); + private Core.Bloom.BloomExtract[] CalculateBloomExtracts() => Addresses.Select(Core.Bloom.GetExtract).ToArray(); } } diff --git a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs index 48b1058460d..cccff0b75ea 100644 --- a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs @@ -31,7 +31,7 @@ public interface IBlockchainBridge : ILogFinder int NewBlockFilter(); int NewPendingTransactionFilter(); - int NewFilter(BlockParameter? fromBlock, BlockParameter? toBlock, object? address = null, IEnumerable? topics = null); + int NewFilter(BlockParameter fromBlock, BlockParameter toBlock, object? address = null, IEnumerable? topics = null); void UninstallFilter(int filterId); bool FilterExists(int filterId); Keccak[] GetBlockFilterChanges(int filterId); diff --git a/src/Nethermind/Nethermind.Facade/Proxy/IAdminJsonRpcClientProxy.cs b/src/Nethermind/Nethermind.Facade/Proxy/IAdminJsonRpcClientProxy.cs index e0f771f3e7a..0e7f3e59b0d 100644 --- a/src/Nethermind/Nethermind.Facade/Proxy/IAdminJsonRpcClientProxy.cs +++ b/src/Nethermind/Nethermind.Facade/Proxy/IAdminJsonRpcClientProxy.cs @@ -2,6 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading.Tasks; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Int256; using Nethermind.Facade.Proxy.Models; namespace Nethermind.Facade.Proxy diff --git a/src/Nethermind/Nethermind.GitBook/RpcAndCliDataProvider.cs b/src/Nethermind/Nethermind.GitBook/RpcAndCliDataProvider.cs index aa0cdc20025..7284e967d39 100644 --- a/src/Nethermind/Nethermind.GitBook/RpcAndCliDataProvider.cs +++ b/src/Nethermind/Nethermind.GitBook/RpcAndCliDataProvider.cs @@ -48,7 +48,7 @@ private List GetRpcModules() private List GetCliModules() { - Assembly assembly = Assembly.Load("nethermind-cli"); + Assembly assembly = Assembly.Load("Nethermind.Cli"); List cliModules = new List(); foreach (Type type in assembly.GetTypes() diff --git a/src/Nethermind/Nethermind.GitBook/SampleConfigGenerator.cs b/src/Nethermind/Nethermind.GitBook/SampleConfigGenerator.cs index d781a7fd9e1..6131b2e8283 100644 --- a/src/Nethermind/Nethermind.GitBook/SampleConfigGenerator.cs +++ b/src/Nethermind/Nethermind.GitBook/SampleConfigGenerator.cs @@ -22,7 +22,7 @@ public void Generate() string docsDir = DocsDirFinder.FindDocsDir(); string runnerDir = DocsDirFinder.FindRunnerDir(); string moduleName = "sample-configuration"; - string[] configs = { "mainnet.cfg", "goerli.cfg", "sepolia.cfg" }; + string[] configs = { "mainnet.cfg", "goerli.cfg", "rinkeby.cfg", "ropsten.cfg" }; StringBuilder docBuilder = new StringBuilder(); diff --git a/src/Nethermind/Nethermind.GitBook/docs b/src/Nethermind/Nethermind.GitBook/docs index 0e5359ecce7..51c81f93f99 160000 --- a/src/Nethermind/Nethermind.GitBook/docs +++ b/src/Nethermind/Nethermind.GitBook/docs @@ -1 +1 @@ -Subproject commit 0e5359ecce7609eb6c54305b7fe13ae25b9223aa +Subproject commit 51c81f93f99e824cd5f0b911bd160d8f63198578 diff --git a/src/Nethermind/Nethermind.HealthChecks.Test/FreeDiskSpaceCheckerTests.cs b/src/Nethermind/Nethermind.HealthChecks.Test/FreeDiskSpaceCheckerTests.cs index 5be9df68c1c..492a57a87fb 100644 --- a/src/Nethermind/Nethermind.HealthChecks.Test/FreeDiskSpaceCheckerTests.cs +++ b/src/Nethermind/Nethermind.HealthChecks.Test/FreeDiskSpaceCheckerTests.cs @@ -9,6 +9,7 @@ using Nethermind.Core.Extensions; using System.Threading.Tasks; using Nethermind.Config; +using NSubstitute.ReceivedExtensions; namespace Nethermind.HealthChecks.Test { diff --git a/src/Nethermind/Nethermind.HealthChecks.Test/HealthChecksWebhookInfoTests.cs b/src/Nethermind/Nethermind.HealthChecks.Test/HealthChecksWebhookInfoTests.cs index 0e7c23ff5f7..b35a4d422ab 100644 --- a/src/Nethermind/Nethermind.HealthChecks.Test/HealthChecksWebhookInfoTests.cs +++ b/src/Nethermind/Nethermind.HealthChecks.Test/HealthChecksWebhookInfoTests.cs @@ -3,8 +3,12 @@ using System.Net; using System; +using System.Collections.Generic; +using Nethermind.JsonRpc; using NSubstitute; using NUnit.Framework; +using Nethermind.HealthChecks; +using Nethermind.Monitoring.Metrics; using Nethermind.Monitoring.Config; using Nethermind.Network; diff --git a/src/Nethermind/Nethermind.HealthChecks/DriveInfoExtensions.cs b/src/Nethermind/Nethermind.HealthChecks/DriveInfoExtensions.cs index db174700849..03d31810b25 100644 --- a/src/Nethermind/Nethermind.HealthChecks/DriveInfoExtensions.cs +++ b/src/Nethermind/Nethermind.HealthChecks/DriveInfoExtensions.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.IO; using System.IO.Abstractions; using Nethermind.Core.Extensions; diff --git a/src/Nethermind/Nethermind.HealthChecks/FreeDiskSpaceChecker.cs b/src/Nethermind/Nethermind.HealthChecks/FreeDiskSpaceChecker.cs index 5d7d524a189..45d25ef9969 100644 --- a/src/Nethermind/Nethermind.HealthChecks/FreeDiskSpaceChecker.cs +++ b/src/Nethermind/Nethermind.HealthChecks/FreeDiskSpaceChecker.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Hosting; using Nethermind.Config; +using Nethermind.Core.Exceptions; using Nethermind.Core.Timers; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.HealthChecks/HealthChecksPlugin.cs b/src/Nethermind/Nethermind.HealthChecks/HealthChecksPlugin.cs index 05bee8c6d00..350395ab9dd 100644 --- a/src/Nethermind/Nethermind.HealthChecks/HealthChecksPlugin.cs +++ b/src/Nethermind/Nethermind.HealthChecks/HealthChecksPlugin.cs @@ -211,8 +211,7 @@ private void ReportClStatus(object _) { if (!_nodeHealthService.CheckClAlive()) { - if (_logger.IsWarn) - _logger.Warn("No incoming messages from the consensus client that is required for sync."); + if (_logger.IsWarn) _logger.Warn("No incoming messages from Consensus Client. Please make sure that it's working properly"); } } } diff --git a/src/Nethermind/Nethermind.HealthChecks/HealthChecksWebhookInfo.cs b/src/Nethermind/Nethermind.HealthChecks/HealthChecksWebhookInfo.cs index 3314176be13..da2e00ed821 100644 --- a/src/Nethermind/Nethermind.HealthChecks/HealthChecksWebhookInfo.cs +++ b/src/Nethermind/Nethermind.HealthChecks/HealthChecksWebhookInfo.cs @@ -2,6 +2,7 @@ using System.Net; using System; +using Nethermind.Monitoring.Metrics; using Nethermind.Monitoring.Config; using Nethermind.Network; diff --git a/src/Nethermind/Nethermind.HealthChecks/IHealthRpcModule.cs b/src/Nethermind/Nethermind.HealthChecks/IHealthRpcModule.cs index 65f42fff91e..8b85990f04e 100644 --- a/src/Nethermind/Nethermind.HealthChecks/IHealthRpcModule.cs +++ b/src/Nethermind/Nethermind.HealthChecks/IHealthRpcModule.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Threading.Tasks; using Nethermind.JsonRpc; using Nethermind.JsonRpc.Modules; diff --git a/src/Nethermind/Nethermind.HealthChecks/NodeHealthService.cs b/src/Nethermind/Nethermind.HealthChecks/NodeHealthService.cs index 9688d6629fc..89a9d5ce0ba 100644 --- a/src/Nethermind/Nethermind.HealthChecks/NodeHealthService.cs +++ b/src/Nethermind/Nethermind.HealthChecks/NodeHealthService.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.IO; using System.IO.Abstractions; using Nethermind.Api; using Nethermind.Blockchain.Services; diff --git a/src/Nethermind/Nethermind.Hive/HivePlugin.cs b/src/Nethermind/Nethermind.Hive/HivePlugin.cs index b615fbeb982..d58874c5186 100644 --- a/src/Nethermind/Nethermind.Hive/HivePlugin.cs +++ b/src/Nethermind/Nethermind.Hive/HivePlugin.cs @@ -52,8 +52,6 @@ public async Task InitNetworkProtocol() if (_api.FileSystem is null) throw new ArgumentNullException(nameof(_api.FileSystem)); if (_api.BlockValidator is null) throw new ArgumentNullException(nameof(_api.BlockValidator)); - _api.TxGossipPolicy.Policies.Clear(); - HiveRunner hiveRunner = new( _api.BlockTree, _api.BlockProcessingQueue, diff --git a/src/Nethermind/Nethermind.Init/Cpu/TimeUnit.cs b/src/Nethermind/Nethermind.Init/Cpu/TimeUnit.cs index 475ce19be3b..9e5ea1a3dfa 100644 --- a/src/Nethermind/Nethermind.Init/Cpu/TimeUnit.cs +++ b/src/Nethermind/Nethermind.Init/Cpu/TimeUnit.cs @@ -77,7 +77,7 @@ public bool Equals(TimeUnit? other) return false; } - if (ReferenceEquals((object)this, other)) + if ((object)this == other) { return true; } diff --git a/src/Nethermind/Nethermind.Init/MemoryHintMan.cs b/src/Nethermind/Nethermind.Init/MemoryHintMan.cs index c5b47d218ba..85c48a2a345 100644 --- a/src/Nethermind/Nethermind.Init/MemoryHintMan.cs +++ b/src/Nethermind/Nethermind.Init/MemoryHintMan.cs @@ -8,7 +8,6 @@ using Nethermind.Api; using Nethermind.Blockchain.Synchronization; using Nethermind.Core.Extensions; -using Nethermind.Core.Memory; using Nethermind.Db.Rocks.Config; using Nethermind.Init.Steps; using Nethermind.Logging; @@ -23,11 +22,9 @@ namespace Nethermind.Init public class MemoryHintMan { private ILogger _logger; - private MallocHelper _mallocHelper; - public MemoryHintMan(ILogManager logManager, MallocHelper? mallocHelper = null) + public MemoryHintMan(ILogManager logManager) { - _mallocHelper = mallocHelper ?? MallocHelper.Instance; _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); } @@ -45,54 +42,33 @@ public void SetMemoryAllowances( checked { - SetupMallocOpts(initConfig); - if (_logger.IsInfo) _logger.Info("Setting up memory allowances"); - if (_logger.IsInfo) _logger.Info($" Memory hint: {TotalMemory / 1000 / 1000,5} MB"); + if (_logger.IsInfo) _logger.Info($" memory hint: {TotalMemory / 1000 / 1000}MB"); _remainingMemory = initConfig.MemoryHint ?? 2.GB(); _remainingMemory -= GeneralMemory; - if (_logger.IsInfo) _logger.Info($" General memory: {GeneralMemory / 1000 / 1000,5} MB"); + if (_logger.IsInfo) _logger.Info($" general memory: {GeneralMemory / 1000 / 1000}MB"); AssignPeersMemory(networkConfig); _remainingMemory -= PeersMemory; - if (_logger.IsInfo) _logger.Info($" Peers memory: {PeersMemory / 1000 / 1000,5} MB"); + if (_logger.IsInfo) _logger.Info($" peers memory: {PeersMemory / 1000 / 1000}MB"); AssignNettyMemory(networkConfig, cpuCount); _remainingMemory -= NettyMemory; - if (_logger.IsInfo) _logger.Info($" Netty memory: {NettyMemory / 1000 / 1000,5} MB"); + if (_logger.IsInfo) _logger.Info($" Netty memory: {NettyMemory / 1000 / 1000}MB"); AssignTxPoolMemory(txPoolConfig); _remainingMemory -= TxPoolMemory; - if (_logger.IsInfo) _logger.Info($" Mempool memory: {TxPoolMemory / 1000 / 1000,5} MB"); + if (_logger.IsInfo) _logger.Info($" mempool memory: {TxPoolMemory / 1000 / 1000}MB"); AssignFastBlocksMemory(syncConfig); _remainingMemory -= FastBlocksMemory; - if (_logger.IsInfo) _logger.Info($" Fast blocks memory: {FastBlocksMemory / 1000 / 1000,5} MB"); + if (_logger.IsInfo) _logger.Info($" fast blocks memory: {FastBlocksMemory / 1000 / 1000}MB"); AssignTrieCacheMemory(); _remainingMemory -= TrieCacheMemory; - if (_logger.IsInfo) _logger.Info($" Trie memory: {TrieCacheMemory / 1000 / 1000,5} MB"); + if (_logger.IsInfo) _logger.Info($" trie memory: {TrieCacheMemory / 1000 / 1000}MB"); UpdateDbConfig(cpuCount, syncConfig, dbConfig, initConfig); _remainingMemory -= DbMemory; - if (_logger.IsInfo) _logger.Info($" DB memory: {DbMemory / 1000 / 1000,5} MB"); + if (_logger.IsInfo) _logger.Info($" DB memory: {DbMemory / 1000 / 1000}MB"); } } - private void SetupMallocOpts(IInitConfig initConfig) - { - if (initConfig.DisableMallocOpts) return; - - if (_logger.IsDebug) _logger.Debug("Setting malloc parameters.."); - - // The MMAP threshold is the minimum size of allocation before glibc uses mmap to allocate the memory - // instead of sbrk. This means the whole allocation can be released on its own without incurring fragmentation - // but its not reusable and incur a system call. It turns out by default this value is dynamically adjusted - // from 128KB up to 32MB in size on 64bit machine, so most of the memory reduction is due to just disabling - // this auto adjustment. - // Setting this essentially reduces the maximum size of a `hole` in the heap, but it causes extra system call. - // On 16C/32T machine, this reduces memory usage by about 7GB. - // There aren't much difference between 16KB to 64KB, but the system cpu time increase slightly as threshold - // lowers. 4k significantly increase cpu system time. - bool success = _mallocHelper.MallOpt(MallocHelper.Option.M_MMAP_THRESHOLD, (int)64.KiB()); - if (!success && _logger.IsDebug) _logger.Debug("Unable to set M_MAP_THRESHOLD"); - } - private long _remainingMemory; public long TotalMemory = 1024 * 1024 * 1024; @@ -171,49 +147,49 @@ private void UpdateDbConfig(uint cpuCount, ISyncConfig syncConfig, IDbConfig dbC DbMemory = _remainingMemory; long remaining = DbMemory; - DbNeeds dbNeeds = GetHeaderNeeds(cpuCount); + DbNeeds dbNeeds = GetHeaderNeeds(cpuCount, syncConfig); DbGets dbGets = GiveItWhatYouCan(dbNeeds, DbMemory, remaining); remaining -= dbGets.CacheMem + dbGets.Buffers * dbGets.SingleBufferMem; dbConfig.HeadersDbWriteBufferNumber = dbGets.Buffers; dbConfig.HeadersDbWriteBufferSize = (ulong)dbGets.SingleBufferMem; dbConfig.HeadersDbBlockCacheSize = (ulong)dbGets.CacheMem; - dbNeeds = GetBlocksNeeds(cpuCount); + dbNeeds = GetBlocksNeeds(cpuCount, syncConfig); dbGets = GiveItWhatYouCan(dbNeeds, DbMemory, remaining); remaining -= dbGets.CacheMem + dbGets.Buffers * dbGets.SingleBufferMem; dbConfig.BlocksDbWriteBufferNumber = dbGets.Buffers; dbConfig.BlocksDbWriteBufferSize = (ulong)dbGets.SingleBufferMem; dbConfig.BlocksDbBlockCacheSize = (ulong)dbGets.CacheMem; - dbNeeds = GetBlockInfosNeeds(cpuCount); + dbNeeds = GetBlockInfosNeeds(cpuCount, syncConfig); dbGets = GiveItWhatYouCan(dbNeeds, DbMemory, remaining); remaining -= dbGets.CacheMem + dbGets.Buffers * dbGets.SingleBufferMem; dbConfig.BlockInfosDbWriteBufferNumber = dbGets.Buffers; dbConfig.BlockInfosDbWriteBufferSize = (ulong)dbGets.SingleBufferMem; dbConfig.BlockInfosDbBlockCacheSize = (ulong)dbGets.CacheMem; - dbNeeds = GetReceiptsNeeds(cpuCount); + dbNeeds = GetReceiptsNeeds(cpuCount, syncConfig); dbGets = GiveItWhatYouCan(dbNeeds, DbMemory, remaining); remaining -= dbGets.CacheMem + dbGets.Buffers * dbGets.SingleBufferMem; dbConfig.ReceiptsDbWriteBufferNumber = dbGets.Buffers; dbConfig.ReceiptsDbWriteBufferSize = (ulong)dbGets.SingleBufferMem; dbConfig.ReceiptsDbBlockCacheSize = (ulong)dbGets.CacheMem; - dbNeeds = GetCodeNeeds(cpuCount); + dbNeeds = GetCodeNeeds(cpuCount, syncConfig); dbGets = GiveItWhatYouCan(dbNeeds, DbMemory, remaining); remaining -= dbGets.CacheMem + dbGets.Buffers * dbGets.SingleBufferMem; dbConfig.CodeDbWriteBufferNumber = dbGets.Buffers; dbConfig.CodeDbWriteBufferSize = (ulong)dbGets.SingleBufferMem; dbConfig.CodeDbBlockCacheSize = (ulong)dbGets.CacheMem; - dbNeeds = GetPendingTxNeeds(cpuCount); + dbNeeds = GetPendingTxNeeds(cpuCount, syncConfig); dbGets = GiveItWhatYouCan(dbNeeds, DbMemory, remaining); remaining -= dbGets.CacheMem + dbGets.Buffers * dbGets.SingleBufferMem; dbConfig.PendingTxsDbWriteBufferNumber = dbGets.Buffers; dbConfig.PendingTxsDbWriteBufferSize = (ulong)dbGets.SingleBufferMem; dbConfig.PendingTxsDbBlockCacheSize = (ulong)dbGets.CacheMem; - dbNeeds = GetStateNeeds(cpuCount); + dbNeeds = GetStateNeeds(cpuCount, syncConfig); dbGets = GiveItWhatYouCan(dbNeeds, DbMemory, remaining); remaining -= dbGets.CacheMem + dbGets.Buffers * dbGets.SingleBufferMem; dbConfig.StateDbWriteBufferNumber = dbGets.Buffers; @@ -239,7 +215,7 @@ private DbGets GiveItWhatYouCan(DbNeeds dbNeeds, long memoryHint, long remaining long maxWantedMemory = Math.Max(minMemory, (long)(memoryHint * maxPercentage)); long availableDynamic = minMemory >= maxWantedMemory ? 0L : maxWantedMemory - minMemory; - long availableForBuffer = (long)(availableDynamic * 0.2m); + long availableForBuffer = (long)(availableDynamic * 0.05m); long bufferDynamic = Math.Min(maxBufferMem, availableForBuffer); long bufferMem = minBufferMem + bufferDynamic; long cacheDynamic = availableDynamic - bufferDynamic; @@ -293,9 +269,9 @@ public DbNeeds( public decimal PreferredMemoryPercentage { get; set; } } - private DbNeeds GetStateNeeds(uint cpuCount) + private DbNeeds GetStateNeeds(uint cpuCount, ISyncConfig syncConfig) { - uint preferredBuffers = Math.Min(cpuCount, 2u); + uint preferredBuffers = Math.Min(cpuCount, syncConfig.FastSync ? 8u : 4u); // remove optimize for point lookup here? return new DbNeeds( preferredBuffers, @@ -306,9 +282,9 @@ private DbNeeds GetStateNeeds(uint cpuCount) 1m); // db memory % } - private DbNeeds GetBlockInfosNeeds(uint cpuCount) + private DbNeeds GetBlockInfosNeeds(uint cpuCount, ISyncConfig syncConfig) { - uint preferredBuffers = Math.Min(cpuCount, 2u); + uint preferredBuffers = Math.Min(cpuCount, syncConfig.FastBlocks ? 4u : 2u); // remove optimize for point lookup here? return new DbNeeds( preferredBuffers, @@ -319,21 +295,21 @@ private DbNeeds GetBlockInfosNeeds(uint cpuCount) 0.02m); // db memory % } - private DbNeeds GetHeaderNeeds(uint cpuCount) + private DbNeeds GetHeaderNeeds(uint cpuCount, ISyncConfig syncConfig) { - uint preferredBuffers = Math.Min(cpuCount, 2u); + uint preferredBuffers = Math.Min(cpuCount, syncConfig.FastBlocks ? 4u : 2u); return new DbNeeds( preferredBuffers, - 4.MB(), // min buffer size - 16.MB(), // max buffer size + 1.MB(), // min buffer size + 8.MB(), // max buffer size 1.MB(), // min block cache 1.GB(), // max block cache - 0.05m); // db memory % + 0.02m); // db memory % } - private DbNeeds GetBlocksNeeds(uint cpuCount) + private DbNeeds GetBlocksNeeds(uint cpuCount, ISyncConfig syncConfig) { - uint preferredBuffers = Math.Min(cpuCount, 2u); + uint preferredBuffers = Math.Min(cpuCount, syncConfig.FastBlocks ? 4u : 2u); return new DbNeeds( preferredBuffers, 4.MB(), // min buffer size @@ -343,9 +319,9 @@ private DbNeeds GetBlocksNeeds(uint cpuCount) 0.04m); // db memory % } - private DbNeeds GetReceiptsNeeds(uint cpuCount) + private DbNeeds GetReceiptsNeeds(uint cpuCount, ISyncConfig syncConfig) { - uint preferredBuffers = Math.Min(cpuCount, 2u); + uint preferredBuffers = Math.Min(cpuCount, syncConfig.FastBlocks ? 4u : 2u); return new DbNeeds( preferredBuffers, 2.MB(), // min buffer size @@ -355,7 +331,7 @@ private DbNeeds GetReceiptsNeeds(uint cpuCount) 0.01m); // db memory % } - private DbNeeds GetPendingTxNeeds(uint cpuCount) + private DbNeeds GetPendingTxNeeds(uint cpuCount, ISyncConfig syncConfig) { return new DbNeeds( 4, @@ -366,9 +342,9 @@ private DbNeeds GetPendingTxNeeds(uint cpuCount) 0.01m); // db memory % } - private DbNeeds GetCodeNeeds(uint cpuCount) + private DbNeeds GetCodeNeeds(uint cpuCount, ISyncConfig syncConfig) { - uint preferredBuffers = Math.Min(cpuCount, 2u); + uint preferredBuffers = Math.Min(cpuCount, syncConfig.FastSync ? 4u : 2u); return new DbNeeds( preferredBuffers, 1.MB(), // min buffer size diff --git a/src/Nethermind/Nethermind.Init/Metrics.cs b/src/Nethermind/Nethermind.Init/Metrics.cs index 24e94cdb648..a51909d8897 100644 --- a/src/Nethermind/Nethermind.Init/Metrics.cs +++ b/src/Nethermind/Nethermind.Init/Metrics.cs @@ -2,6 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.ComponentModel; +using Nethermind.Core; +using Nethermind.Db; +using Nethermind.Monitoring.Metrics; namespace Nethermind.Init { diff --git a/src/Nethermind/Nethermind.Init/Nethermind.Init.csproj b/src/Nethermind/Nethermind.Init/Nethermind.Init.csproj index 7394b8e42fb..ba77bbd83cc 100644 --- a/src/Nethermind/Nethermind.Init/Nethermind.Init.csproj +++ b/src/Nethermind/Nethermind.Init/Nethermind.Init.csproj @@ -14,10 +14,6 @@ - - - <_Parameter1>Nethermind.Runner.Test - diff --git a/src/Nethermind/Nethermind.Init/Steps/DatabaseMigrations.cs b/src/Nethermind/Nethermind.Init/Steps/DatabaseMigrations.cs index a1295dc6281..4b7e9b76015 100644 --- a/src/Nethermind/Nethermind.Init/Steps/DatabaseMigrations.cs +++ b/src/Nethermind/Nethermind.Init/Steps/DatabaseMigrations.cs @@ -10,7 +10,7 @@ namespace Nethermind.Init.Steps { - [RunnerStepDependencies(typeof(InitRlp), typeof(InitDatabase), typeof(InitializeBlockchain), typeof(InitializeNetwork))] + [RunnerStepDependencies(typeof(InitRlp), typeof(InitDatabase), typeof(InitializeBlockchain), typeof(InitializeNetwork), typeof(ResetDatabaseMigrations))] public sealed class DatabaseMigrations : IStep { private readonly IApiWithNetwork _api; diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockProducer.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockProducer.cs index a8a50aead51..b5b41c08b59 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockProducer.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockProducer.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using Nethermind.Api; diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs index 952bdaa678a..d988242765a 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.IO.Abstractions; -using System.Linq; using System.Threading; using System.Threading.Tasks; using Nethermind.Api; @@ -27,6 +26,7 @@ using Nethermind.Db.FullPruning; using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; +using Nethermind.Facade.Eth; using Nethermind.JsonRpc.Converters; using Nethermind.JsonRpc.Modules.DebugModule; using Nethermind.JsonRpc.Modules.Eth.GasPrice; @@ -35,7 +35,6 @@ using Nethermind.Serialization.Json; using Nethermind.State; using Nethermind.State.Witnesses; -using Nethermind.Synchronization.Trie; using Nethermind.Synchronization.Witness; using Nethermind.Trie; using Nethermind.Trie.Pruning; @@ -105,12 +104,11 @@ private Task InitBlockchain() IKeyValueStore codeDb = getApi.DbProvider.CodeDb .WitnessedBy(witnessCollector); + TrieStore trieStore; IKeyValueStoreWithBatching stateWitnessedBy = setApi.MainStateDbWithCache.WitnessedBy(witnessCollector); - IPersistenceStrategy persistenceStrategy; - IPruningStrategy pruningStrategy; if (pruningConfig.Mode.IsMemory()) { - persistenceStrategy = Persist.IfBlockOlderThan(pruningConfig.PersistenceInterval); // TODO: this should be based on time + IPersistenceStrategy persistenceStrategy = Persist.IfBlockOlderThan(pruningConfig.PersistenceInterval); // TODO: this should be based on time if (pruningConfig.Mode.IsFull()) { PruningTriggerPersistenceStrategy triggerPersistenceStrategy = new((IFullPruningDb)getApi.DbProvider!.StateDb, getApi.BlockTree!, getApi.LogManager); @@ -118,45 +116,29 @@ private Task InitBlockchain() persistenceStrategy = persistenceStrategy.Or(triggerPersistenceStrategy); } - pruningStrategy = Prune.WhenCacheReaches(pruningConfig.CacheMb.MB()); // TODO: memory hint should define this - } - else - { - pruningStrategy = No.Pruning; - persistenceStrategy = Persist.EveryBlock; - } - - TrieStore trieStore = syncConfig.TrieHealing - ? new HealingTrieStore( + setApi.TrieStore = trieStore = new TrieStore( stateWitnessedBy, - pruningStrategy, + Prune.WhenCacheReaches(pruningConfig.CacheMb.MB()), // TODO: memory hint should define this persistenceStrategy, - getApi.LogManager) - : new TrieStore( - stateWitnessedBy, - pruningStrategy, - persistenceStrategy, - getApi.LogManager); - setApi.TrieStore = trieStore; - - IWorldState worldState = setApi.WorldState = syncConfig.TrieHealing - ? new HealingWorldState( - trieStore, - codeDb, - getApi.LogManager) - : new WorldState( - trieStore, - codeDb, getApi.LogManager); - if (pruningConfig.Mode.IsFull()) - { - IFullPruningDb fullPruningDb = (IFullPruningDb)getApi.DbProvider!.StateDb; - fullPruningDb.PruningStarted += (_, args) => + if (pruningConfig.Mode.IsFull()) { - cachedStateDb.PersistCache(args.Context); - trieStore.PersistCache(args.Context, args.Context.CancellationTokenSource.Token); - }; + IFullPruningDb fullPruningDb = (IFullPruningDb)getApi.DbProvider!.StateDb; + fullPruningDb.PruningStarted += (_, args) => + { + cachedStateDb.PersistCache(args.Context); + trieStore.PersistCache(args.Context, args.Context.CancellationTokenSource.Token); + }; + } + } + else + { + setApi.TrieStore = trieStore = new TrieStore( + stateWitnessedBy, + No.Pruning, + Persist.EveryBlock, + getApi.LogManager); } TrieStoreBoundaryWatcher trieStoreBoundaryWatcher = new(trieStore, _api.BlockTree!, _api.LogManager); @@ -165,6 +147,11 @@ private Task InitBlockchain() ITrieStore readOnlyTrieStore = setApi.ReadOnlyTrieStore = trieStore.AsReadOnly(cachedStateDb); + IWorldState worldState = setApi.WorldState = new WorldState( + trieStore, + codeDb, + getApi.LogManager); + ReadOnlyDbProvider readOnly = new(getApi.DbProvider, false); IStateReader stateReader = setApi.StateReader = new StateReader(readOnlyTrieStore, readOnly.GetDb(DbNames.Code), getApi.LogManager); @@ -271,10 +258,7 @@ private Task InitBlockchain() { StoreReceiptsByDefault = initConfig.StoreReceipts, DumpOptions = initConfig.AutoDump - }) - { - IsMainProcessor = true - }; + }); setApi.BlockProcessingQueue = blockchainProcessor; setApi.BlockchainProcessor = blockchainProcessor; @@ -322,7 +306,7 @@ private static void InitializeFullPruning( api.PruningTrigger.Add(pruningTrigger); } - IDriveInfo? drive = api.FileSystem.GetDriveInfos(pruningDbPath).FirstOrDefault(); + IDriveInfo drive = api.FileSystem.GetDriveInfos(pruningDbPath)[0]; FullPruner pruner = new(fullPruningDb, api.PruningTrigger, pruningConfig, api.BlockTree!, stateReader, api.ProcessExit!, ChainSizes.CreateChainSizeInfo(api.ChainSpec.ChainId), drive, api.LogManager); @@ -348,8 +332,7 @@ protected virtual TxPool.TxPool CreateTxPool() => _api.Config(), _api.TxValidator!, _api.LogManager, - CreateTxPoolTxComparer(), - _api.TxGossipPolicy); + CreateTxPoolTxComparer()); protected IComparer CreateTxPoolTxComparer() => _api.TransactionComparerProvider!.GetDefaultComparer(); diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs index ceade1167cf..ff978bbd7cc 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs @@ -26,8 +26,8 @@ using Nethermind.Network.Enr; using Nethermind.Network.P2P.Analyzers; using Nethermind.Network.P2P.Messages; -using Nethermind.Network.P2P.Subprotocols.Eth; using Nethermind.Network.P2P.Subprotocols.Eth.V63.Messages; +using Nethermind.Network.P2P.Subprotocols.Eth.V65; using Nethermind.Network.Rlpx; using Nethermind.Network.Rlpx.Handshake; using Nethermind.Network.StaticNodes; @@ -39,7 +39,6 @@ using Nethermind.Synchronization.Peers; using Nethermind.Synchronization.Reporting; using Nethermind.Synchronization.SnapSync; -using Nethermind.Synchronization.Trie; namespace Nethermind.Init.Steps; @@ -88,7 +87,6 @@ public async Task Execute(CancellationToken cancellationToken) private async Task Initialize(CancellationToken cancellationToken) { if (_api.DbProvider is null) throw new StepDependencyException(nameof(_api.DbProvider)); - if (_api.BlockTree is null) throw new StepDependencyException(nameof(_api.BlockTree)); if (_networkConfig.DiagTracerEnabled) { @@ -102,11 +100,11 @@ private async Task Initialize(CancellationToken cancellationToken) CanonicalHashTrie cht = new CanonicalHashTrie(_api.DbProvider!.ChtDb); - ProgressTracker progressTracker = new(_api.BlockTree, _api.DbProvider.StateDb, _api.LogManager, _syncConfig.SnapSyncAccountRangePartitionCount); + ProgressTracker progressTracker = new(_api.BlockTree!, _api.DbProvider.StateDb, _api.LogManager, _syncConfig.SnapSyncAccountRangePartitionCount); _api.SnapProvider = new SnapProvider(progressTracker, _api.DbProvider, _api.LogManager); SyncProgressResolver syncProgressResolver = new( - _api.BlockTree, + _api.BlockTree!, _api.ReceiptStorage!, _api.DbProvider.StateDb, _api.ReadOnlyTrieStore!, @@ -120,22 +118,12 @@ private async Task Initialize(CancellationToken cancellationToken) int maxPeersCount = _networkConfig.ActivePeersMaxCount; int maxPriorityPeersCount = _networkConfig.PriorityPeersMaxCount; Network.Metrics.PeerLimit = maxPeersCount; - SyncPeerPool apiSyncPeerPool = new(_api.BlockTree, _api.NodeStatsManager!, _api.BetterPeerStrategy, _api.LogManager, maxPeersCount, maxPriorityPeersCount); + SyncPeerPool apiSyncPeerPool = new(_api.BlockTree!, _api.NodeStatsManager!, _api.BetterPeerStrategy, _api.LogManager, maxPeersCount, maxPriorityPeersCount); _api.SyncPeerPool = apiSyncPeerPool; _api.PeerDifficultyRefreshPool = apiSyncPeerPool; _api.DisposeStack.Push(_api.SyncPeerPool); - if (_api.TrieStore is HealingTrieStore healingTrieStore) - { - healingTrieStore.InitializeNetwork(new GetNodeDataTrieNodeRecovery(apiSyncPeerPool, _api.LogManager)); - } - - if (_api.WorldState is HealingWorldState healingWorldState) - { - healingWorldState.InitializeNetwork(new SnapTrieNodeRecovery(apiSyncPeerPool, _api.LogManager)); - } - IEnumerable synchronizationPlugins = _api.GetSynchronizationPlugins(); foreach (ISynchronizationPlugin plugin in synchronizationPlugins) { @@ -143,9 +131,7 @@ private async Task Initialize(CancellationToken cancellationToken) } _api.SyncModeSelector ??= CreateMultiSyncModeSelector(syncProgressResolver); - _api.TxGossipPolicy.Policies.Add(new SyncedTxGossipPolicy(_api.SyncModeSelector)); - - _api.EthSyncingInfo = new EthSyncingInfo(_api.BlockTree, _api.ReceiptStorage!, _syncConfig, _api.SyncModeSelector, _api.LogManager); + _api.EthSyncingInfo = new EthSyncingInfo(_api.BlockTree!, _api.ReceiptStorage!, _syncConfig, _api.SyncModeSelector, _api.LogManager); _api.DisposeStack.Push(_api.SyncModeSelector); _api.Pivot ??= new Pivot(_syncConfig); @@ -156,7 +142,7 @@ private async Task Initialize(CancellationToken cancellationToken) _api.BlockDownloaderFactory ??= new BlockDownloaderFactory( _api.SpecProvider!, - _api.BlockTree, + _api.BlockTree!, _api.ReceiptStorage!, _api.BlockValidator!, _api.SealValidator!, @@ -167,7 +153,7 @@ private async Task Initialize(CancellationToken cancellationToken) _api.Synchronizer ??= new Synchronizer( _api.DbProvider, _api.SpecProvider!, - _api.BlockTree, + _api.BlockTree!, _api.ReceiptStorage!, _api.SyncPeerPool, _api.NodeStatsManager!, @@ -177,16 +163,15 @@ private async Task Initialize(CancellationToken cancellationToken) _api.BlockDownloaderFactory, _api.Pivot, syncReport, - _api.ProcessExit!, _api.LogManager); } _api.DisposeStack.Push(_api.Synchronizer); ISyncServer syncServer = _api.SyncServer = new SyncServer( - _api.TrieStore!.AsKeyValueStore(), + _api.TrieStore!, _api.DbProvider.CodeDb, - _api.BlockTree, + _api.BlockTree!, _api.ReceiptStorage!, _api.BlockValidator!, _api.SealValidator!, @@ -227,9 +212,8 @@ await InitPeer().ContinueWith(initPeerTask => } else if (_logger.IsDebug) _logger.Debug("Skipped enabling eth67 & eth68 capabilities"); - if (_syncConfig.SnapSync) + if (_syncConfig.SnapSync && !stateSyncFinished) { - // TODO: Should we keep snap capability even after finishing sync? SnapCapabilitySwitcher snapCapabilitySwitcher = new(_api.ProtocolsManager, _api.SyncModeSelector, _api.LogManager); snapCapabilitySwitcher.EnableSnapCapabilityUntilSynced(); } @@ -527,7 +511,7 @@ private async Task InitPeer() ISyncServer syncServer = _api.SyncServer!; ForkInfo forkInfo = new(_api.SpecProvider!, syncServer.Genesis.Hash!); - ProtocolValidator protocolValidator = new(_api.NodeStatsManager!, _api.BlockTree, forkInfo, _api.LogManager); + ProtocolValidator protocolValidator = new(_api.NodeStatsManager!, _api.BlockTree!, forkInfo, _api.LogManager); PooledTxsRequestor pooledTxsRequestor = new(_api.TxPool!); _api.ProtocolsManager = new ProtocolsManager( _api.SyncPeerPool!, @@ -542,9 +526,7 @@ private async Task InitPeer() peerStorage, forkInfo, _api.GossipPolicy, - _networkConfig, - _api.LogManager, - _api.TxGossipPolicy); + _api.LogManager); if (_syncConfig.WitnessProtocolEnabled) { @@ -559,13 +541,6 @@ private async Task InitPeer() NodeRecordSigner nodeRecordSigner = new(_api.EthereumEcdsa, new PrivateKeyGenerator().Generate()); EnrRecordParser enrRecordParser = new(nodeRecordSigner); EnrDiscovery enrDiscovery = new(enrRecordParser, _api.LogManager); // initialize with a proper network - - if (!_networkConfig.DisableDiscV4DnsFeeder) - { - // Feed some nodes into discoveryApp in case all bootnodes is faulty. - _api.DisposeStack.Push(new NodeSourceToDiscV4Feeder(enrDiscovery, _api.DiscoveryApp, 50)); - } - CompositeNodeSource nodeSources = new(_api.StaticNodesManager, nodesLoader, enrDiscovery, _api.DiscoveryApp); _api.PeerPool = new PeerPool(nodeSources, _api.NodeStatsManager, peerStorage, _networkConfig, _api.LogManager); _api.PeerManager = new PeerManager( @@ -577,7 +552,9 @@ private async Task InitPeer() string chainName = BlockchainIds.GetBlockchainName(_api.ChainSpec!.NetworkId).ToLowerInvariant(); string domain = _networkConfig.DiscoveryDns ?? $"all.{chainName}.ethdisco.net"; - _ = enrDiscovery.SearchTree(domain).ContinueWith(t => +#pragma warning disable CS4014 + enrDiscovery.SearchTree(domain).ContinueWith(t => +#pragma warning restore CS4014 { if (t.IsFaulted) { diff --git a/src/Nethermind/Nethermind.Init/Steps/MigrateConfigs.cs b/src/Nethermind/Nethermind.Init/Steps/MigrateConfigs.cs index 7b38dc42ae9..f860a64a5de 100644 --- a/src/Nethermind/Nethermind.Init/Steps/MigrateConfigs.cs +++ b/src/Nethermind/Nethermind.Init/Steps/MigrateConfigs.cs @@ -4,6 +4,7 @@ using System.Reflection; using System.Threading; using System.Threading.Tasks; +using Google.Protobuf.WellKnownTypes; using Nethermind.Api; using Nethermind.Blockchain.Receipts; using Nethermind.Config; diff --git a/src/Nethermind/Nethermind.Init/Steps/Migrations/BloomMigration.cs b/src/Nethermind/Nethermind.Init/Steps/Migrations/BloomMigration.cs index 8726a04bfc2..6a27ab96a6f 100644 --- a/src/Nethermind/Nethermind.Init/Steps/Migrations/BloomMigration.cs +++ b/src/Nethermind/Nethermind.Init/Steps/Migrations/BloomMigration.cs @@ -223,7 +223,7 @@ bool TryGetMainChainBlockHashFromLevel(long number, out Keccak? blockHash) private string GetLogMessage(string status, string? suffix = null) { - string message = $"BloomDb migration {status} | {_stopwatch?.Elapsed:d\\:hh\\:mm\\:ss} | {_progress.CurrentValue.ToString().PadLeft(_migrateCount.ToString().Length)} / {_migrateCount} blocks migrated. | current {_progress.CurrentPerSecond:F2} Blk/s | total {_progress.TotalPerSecond:F2} Blk/s. {GeAveragesMessage()} {suffix}"; + string message = $"BloomDb migration {status} | {_stopwatch?.Elapsed:d\\:hh\\:mm\\:ss} | {_progress.CurrentValue.ToString().PadLeft(_migrateCount.ToString().Length)} / {_migrateCount} blocks migrated. | current {_progress.CurrentPerSecond:F2}bps | total {_progress.TotalPerSecond:F2}bps. {GeAveragesMessage()} {suffix}"; _progress.SetMeasuringPoint(); return message; } diff --git a/src/Nethermind/Nethermind.Init/Steps/Migrations/ReceiptFixMigration.cs b/src/Nethermind/Nethermind.Init/Steps/Migrations/ReceiptFixMigration.cs index 1a231238965..b3802e141d2 100644 --- a/src/Nethermind/Nethermind.Init/Steps/Migrations/ReceiptFixMigration.cs +++ b/src/Nethermind/Nethermind.Init/Steps/Migrations/ReceiptFixMigration.cs @@ -47,15 +47,14 @@ public void Run() _cancellationTokenSource = new CancellationTokenSource(); CancellationToken cancellationToken = _cancellationTokenSource.Token; - MissingReceiptsFixVisitor visitor = new( - syncConfig.AncientReceiptsBarrierCalc, + MissingReceiptsFixVisitor visitor = new MissingReceiptsFixVisitor( + syncConfig.PivotNumberParsed, _api.BlockTree.Head?.Number - 2 ?? 0, _api.ReceiptStorage!, _api.LogManager, _api.SyncPeerPool!, _api.BlockTree, - cancellationToken - ); + cancellationToken); _fixTask = _api.BlockTree.Accept(visitor, cancellationToken).ContinueWith(t => { @@ -110,11 +109,10 @@ public override async Task VisitBlock(Block block, Cancellati protected override async Task OnBlockWithoutReceipts(Block block, int transactionsLength, int txReceiptsLength) { - if (_logger.IsInfo) - _logger.Info($"Missing receipts for block {block.ToString(Block.Format.FullHashAndNumber)}, expected {transactionsLength} but got {txReceiptsLength}."); + if (_logger.IsInfo) _logger.Info($"Missing receipts for block {block.ToString(Block.Format.FullHashAndNumber)}, expected {transactionsLength} but got {txReceiptsLength}."); await Policy.HandleResult(downloaded => !downloaded) - .WaitAndRetryAsync(5, _ => _delay) + .WaitAndRetryAsync(5, i => _delay) .ExecuteAsync(async () => await DownloadReceiptsForBlock(block)); } @@ -133,7 +131,7 @@ private async Task DownloadReceiptsForBlock(Block block) try { TxReceipt[]?[] receipts = await currentSyncPeer.GetReceipts(new List { block.Hash }, _cancellationToken); - TxReceipt[]? txReceipts = receipts.FirstOrDefault(); + TxReceipt[]? txReceipts = receipts?.FirstOrDefault(); if (txReceipts is not null) { _receiptStorage.Insert(block, txReceipts); diff --git a/src/Nethermind/Nethermind.Init/Steps/Migrations/ReceiptMigration.cs b/src/Nethermind/Nethermind.Init/Steps/Migrations/ReceiptMigration.cs index 11d081fc57a..5f78ebeb713 100644 --- a/src/Nethermind/Nethermind.Init/Steps/Migrations/ReceiptMigration.cs +++ b/src/Nethermind/Nethermind.Init/Steps/Migrations/ReceiptMigration.cs @@ -8,17 +8,15 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.ObjectPool; +using System.Timers; using Nethermind.Api; using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Core.Extensions; using Nethermind.Db; using Nethermind.Int256; using Nethermind.Logging; -using Nethermind.Serialization.Rlp; using Nethermind.State.Repositories; using Nethermind.Synchronization.ParallelSync; using Timer = System.Timers.Timer; @@ -27,18 +25,19 @@ namespace Nethermind.Init.Steps.Migrations { public class ReceiptMigration : IDatabaseMigration, IReceiptsMigration { - private static readonly ObjectPool EmptyBlock = new DefaultObjectPool(new EmptyBlockObjectPolicy()); + private static readonly Block EmptyBlock = new Block(new BlockHeader(Keccak.Zero, Keccak.Zero, Address.Zero, UInt256.Zero, 0L, 0L, 0UL, Array.Empty())); private readonly ILogger _logger; private CancellationTokenSource? _cancellationTokenSource; - internal Task? _migrationTask; + private Task? _migrationTask; private Stopwatch? _stopwatch; private long _toBlock; - private readonly MeasuredProgress _progress = new MeasuredProgress(); [NotNull] private readonly IReceiptStorage? _receiptStorage; [NotNull] + private readonly IDbProvider? _dbProvider; + [NotNull] private readonly DisposableStack? _disposeStack; [NotNull] private readonly IBlockTree? _blockTree; @@ -47,52 +46,18 @@ public class ReceiptMigration : IDatabaseMigration, IReceiptsMigration [NotNull] private readonly IChainLevelInfoRepository? _chainLevelInfoRepository; - private readonly ReceiptArrayStorageDecoder _storageDecoder; - private readonly IReceiptConfig _receiptConfig; - private readonly IColumnsDb _receiptsDb; - private readonly IDbWithSpan _txIndexDb; - private readonly IDbWithSpan _receiptsBlockDb; - private readonly IReceiptsRecovery _recovery; - - public ReceiptMigration(IApiWithNetwork api) : this( - api.ReceiptStorage!, - api.DisposeStack, - api.BlockTree!, - api.SyncModeSelector!, - api.ChainLevelInfoRepository!, - api.Config(), - api.DbProvider?.ReceiptsDb!, - new ReceiptsRecovery(api.EthereumEcdsa, api.SpecProvider), - api.LogManager - ) - { - } - public ReceiptMigration( - IReceiptStorage receiptStorage, - DisposableStack disposeStack, - IBlockTree blockTree, - ISyncModeSelector syncModeSelector, - IChainLevelInfoRepository chainLevelInfoRepository, - IReceiptConfig receiptConfig, - IColumnsDb receiptsDb, - IReceiptsRecovery recovery, - ILogManager logManager - ) + public ReceiptMigration(IApiWithNetwork api) { - _receiptStorage = receiptStorage ?? throw new StepDependencyException(nameof(receiptStorage)); - _disposeStack = disposeStack ?? throw new StepDependencyException(nameof(disposeStack)); - _blockTree = blockTree ?? throw new StepDependencyException(nameof(blockTree)); - _syncModeSelector = syncModeSelector ?? throw new StepDependencyException(nameof(syncModeSelector)); - _chainLevelInfoRepository = chainLevelInfoRepository ?? throw new StepDependencyException(nameof(chainLevelInfoRepository)); - _receiptConfig = receiptConfig ?? throw new StepDependencyException("receiptConfig"); - _receiptsDb = receiptsDb; - _receiptsBlockDb = _receiptsDb.GetColumnDb(ReceiptsColumns.Blocks); - _txIndexDb = _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions); - _recovery = recovery; - _logger = logManager.GetClassLogger(); - _storageDecoder = new ReceiptArrayStorageDecoder(); // it just need to detect the type of the storage + _logger = api.LogManager.GetClassLogger(); + _receiptStorage = api.ReceiptStorage ?? throw new StepDependencyException(nameof(api.ReceiptStorage)); + _dbProvider = api.DbProvider ?? throw new StepDependencyException(nameof(api.DbProvider)); + _disposeStack = api.DisposeStack ?? throw new StepDependencyException(nameof(api.DisposeStack)); + _blockTree = api.BlockTree ?? throw new StepDependencyException(nameof(api.BlockTree)); + _syncModeSelector = api.SyncModeSelector ?? throw new StepDependencyException(nameof(api.SyncModeSelector)); + _chainLevelInfoRepository = api.ChainLevelInfoRepository ?? throw new StepDependencyException(nameof(api.ChainLevelInfoRepository)); + _receiptConfig = api.Config() ?? throw new StepDependencyException("initConfig"); } public async ValueTask DisposeAsync() @@ -106,7 +71,7 @@ public async Task Run(long blockNumber) _cancellationTokenSource?.Cancel(); await (_migrationTask ?? Task.CompletedTask); _receiptStorage.MigratedBlockNumber = Math.Min(Math.Max(_receiptStorage.MigratedBlockNumber, blockNumber), (_blockTree.Head?.Number ?? 0) + 1); - DoRun(); + Run(); return _receiptConfig.StoreReceipts && _receiptConfig.ReceiptsMigration; } @@ -116,25 +81,24 @@ public void Run() { if (_receiptConfig.ReceiptsMigration) { - ResetMigrationIndexIfNeeded(); - DoRun(); - } - } - } - - private void DoRun() - { - if (_receiptConfig.StoreReceipts) - { - if (CanMigrate(_syncModeSelector.Current)) - { - RunMigration(); + if (CanMigrate(_syncModeSelector.Current)) + { + RunMigration(); + } + else + { + _syncModeSelector.Changed -= OnSyncModeChanged; + _syncModeSelector.Changed += OnSyncModeChanged; + if (_logger.IsInfo) _logger.Info($"ReceiptsDb migration will start after switching to full sync."); + } } else { - _syncModeSelector.Changed -= OnSyncModeChanged; - _syncModeSelector.Changed += OnSyncModeChanged; - if (_logger.IsInfo) _logger.Info($"ReceiptsDb migration will start after switching to full sync."); + long migrateToBlockNumber = MigrateToBlockNumber; + if (migrateToBlockNumber > 0) + { + if (_logger.IsInfo) _logger.Info($"ReceiptsDb migration disabled. Finding logs when multiple blocks receipts need to be scanned might be slow below {migrateToBlockNumber} block."); + } } } } @@ -152,15 +116,7 @@ private void OnSyncModeChanged(object? sender, SyncModeChangedEventArgs e) private void RunMigration() { - // Note, it start in decreasing order from this high number. - long migrateToBlockNumber = _receiptStorage.MigratedBlockNumber == long.MaxValue - ? _syncModeSelector.Current.NotSyncing() - ? _blockTree.Head?.Number ?? 0 - : _blockTree.BestKnownNumber - : _receiptStorage.MigratedBlockNumber - 1; - _toBlock = migrateToBlockNumber; - - _logger.Warn($"Running migration to {_toBlock}"); + _toBlock = MigrateToBlockNumber; if (_toBlock > 0) { @@ -179,253 +135,135 @@ private void RunMigration() } else { - if (_logger.IsInfo) _logger.Info($"ReceiptsDb migration not needed. {migrateToBlockNumber} {_receiptStorage.MigratedBlockNumber}"); + if (_logger.IsDebug) _logger.Debug("ReceiptsDb migration not needed."); } } private void RunMigration(CancellationToken token) { + Block GetMissingBlock(long i, Keccak? blockHash) + { + if (_logger.IsWarn) _logger.Warn(GetLogMessage("warning", $"Block {i} not found. Logs will not be searchable for this block.")); + EmptyBlock.Header.Number = i; + EmptyBlock.Header.Hash = blockHash; + return EmptyBlock; + } + long synced = 1; + IDb receiptsDb = _dbProvider.ReceiptsDb; _progress.Reset(synced); if (_logger.IsInfo) _logger.Info(GetLogMessage("started")); - using Timer timer = new(1000); - timer.Enabled = true; - timer.Elapsed += (_, _) => + using (Timer timer = new(1000) { Enabled = true }) { - if (_logger.IsInfo) _logger.Info(GetLogMessage("in progress")); - }; - - try - { - int parallelism = _receiptConfig.ReceiptsMigrationDegreeOfParallelism; - if (parallelism == 0) + timer.Elapsed += (_, _) => { - parallelism = Environment.ProcessorCount; - } + if (_logger.IsInfo) _logger.Info(GetLogMessage("in progress")); + }; - GetBlockBodiesForMigration(token).AsParallel().WithDegreeOfParallelism(parallelism).ForAll((item) => + try { - (long blockNum, Keccak blockHash) = item; - Block? block = _blockTree.FindBlock(blockHash!, BlockTreeLookupOptions.None); - bool usingEmptyBlock = block == null; - if (usingEmptyBlock) - { - block = GetMissingBlock(blockNum, blockHash); - } - - _progress.Update(Interlocked.Increment(ref synced)); - MigrateBlock(block!); - - if (usingEmptyBlock) + foreach (Block block in GetBlockBodiesForMigration()) { - ReturnMissingBlock(block!); - } - }); - - if (!token.IsCancellationRequested) - { - if (_logger.IsInfo) _logger.Info(GetLogMessage("Compacting receipts database")); - _receiptsDb.Compact(); - if (_logger.IsInfo) _logger.Info(GetLogMessage("Compacting receipts tx index database")); - _txIndexDb.Compact(); - if (_logger.IsInfo) _logger.Info(GetLogMessage("Compacting receipts block database")); - _receiptsBlockDb.Compact(); - } - } - finally - { - _progress.MarkEnd(); - _stopwatch?.Stop(); - timer.Stop(); - } - - if (!token.IsCancellationRequested) - { - if (_logger.IsInfo) _logger.Info(GetLogMessage("finished")); - } - } + TxReceipt?[] receipts = _receiptStorage.Get(block); + TxReceipt[] notNullReceipts = receipts.Length == 0 + ? Array.Empty() + : receipts.Where(r => r is not null).Cast().ToArray(); - Block GetMissingBlock(long i, Keccak? blockHash) - { - if (_logger.IsDebug) _logger.Debug(GetLogMessage("warning", $"Block {i} not found. Logs will not be searchable for this block.")); - Block emptyBlock = EmptyBlock.Get(); - emptyBlock.Header.Number = i; - emptyBlock.Header.Hash = blockHash; - return emptyBlock; - } + if (receipts.Length == 0 || notNullReceipts.Length != 0) // if notNullReceipts.Length is 0 and receipts are not 0 - we are missing all receipts, they are not processed yet. + { + _receiptStorage.Insert(block, notNullReceipts); + _receiptStorage.MigratedBlockNumber = block.Number; - static void ReturnMissingBlock(Block emptyBlock) - { - EmptyBlock.Return(emptyBlock); - } + for (int i = 0; i < notNullReceipts.Length; i++) + { + receiptsDb.Delete(notNullReceipts[i].TxHash!); + } - IEnumerable<(long, Keccak)> GetBlockBodiesForMigration(CancellationToken token) - { - bool TryGetMainChainBlockHashFromLevel(long number, out Keccak? blockHash) - { - using BatchWrite batch = _chainLevelInfoRepository.StartBatch(); - ChainLevelInfo? level = _chainLevelInfoRepository.LoadLevel(number); - if (level is not null) - { - if (!level.HasBlockOnMainChain) - { - if (level.BlockInfos.Length > 0) + if (notNullReceipts.Length != receipts.Length) + { + if (_logger.IsWarn) _logger.Warn(GetLogMessage("warning", $"Block {block.ToString(Block.Format.FullHashAndNumber)} is missing {receipts.Length - notNullReceipts.Length} of {receipts.Length} receipts!")); + } + } + else if (block.Number <= _blockTree.Head?.Number) { - level.HasBlockOnMainChain = true; - _chainLevelInfoRepository.PersistLevel(number, level, batch); + if (_logger.IsWarn) _logger.Warn(GetLogMessage("warning", $"Block {block.ToString(Block.Format.FullHashAndNumber)} is missing {receipts.Length - notNullReceipts.Length} of {receipts.Length} receipts!")); } } - - blockHash = level.MainChainBlock?.BlockHash; - return blockHash is not null; } - else + finally { - blockHash = null; - return false; + _progress.MarkEnd(); + _stopwatch?.Stop(); } - } - for (long i = _toBlock - 1; i > 0; i--) - { - if (token.IsCancellationRequested) + IEnumerable GetBlockBodiesForMigration() { - if (_logger.IsInfo) _logger.Info(GetLogMessage("cancelled")); - yield break; - } - - if (TryGetMainChainBlockHashFromLevel(i, out Keccak? blockHash)) - { - yield return (i, blockHash!); - } - - if (_receiptStorage.MigratedBlockNumber > i) - { - _receiptStorage.MigratedBlockNumber = i; - } - } - } - - private void MigrateBlock(Block block) - { - TxReceipt?[] receipts = _receiptStorage.Get(block); - TxReceipt[] notNullReceipts = receipts.Length == 0 - ? Array.Empty() - : receipts.Where(r => r is not null).Cast().ToArray(); - - if (notNullReceipts.Length == 0) return; - - _receiptStorage.Insert(block, notNullReceipts); - - // I guess some old schema need this - { - using IBatch batch = _receiptsDb.StartBatch(); - for (int i = 0; i < notNullReceipts.Length; i++) - { - batch[notNullReceipts[i].TxHash!.Bytes] = null; - } - } - - // Receipts are now prefixed with block number. - _receiptsBlockDb.Delete(block.Hash!); - - // Remove old tx index - bool txIndexExpired = _receiptConfig.TxLookupLimit != 0 && _blockTree.Head?.Number - block.Number > _receiptConfig.TxLookupLimit; - bool neverIndexTx = _receiptConfig.TxLookupLimit == -1; - if (neverIndexTx || txIndexExpired) - { - using IBatch batch = _txIndexDb.StartBatch(); - foreach (TxReceipt? receipt in notNullReceipts) - { - batch[receipt.TxHash!.Bytes] = null; - } - } - - if (notNullReceipts.Length != receipts.Length) - { - if (_logger.IsWarn) - _logger.Warn(GetLogMessage("warning", - $"Block {block.ToString(Block.Format.FullHashAndNumber)} is missing {receipts.Length - notNullReceipts.Length} of {receipts.Length} receipts!")); - } - } - - private void ResetMigrationIndexIfNeeded() - { - if (_receiptConfig.ForceReceiptsMigration) - { - _receiptStorage.MigratedBlockNumber = long.MaxValue; - return; - } - - if (_receiptStorage.MigratedBlockNumber != long.MaxValue) - { - long blockNumber = _blockTree.Head?.Number ?? 0; - while (blockNumber > 0) - { - ChainLevelInfo? level = _chainLevelInfoRepository.LoadLevel(blockNumber); - BlockInfo? firstBlockInfo = level?.BlockInfos.FirstOrDefault(); - if (firstBlockInfo is not null) + bool TryGetMainChainBlockHashFromLevel(long number, out Keccak? blockHash) { - TxReceipt[] receipts = _receiptStorage.Get(firstBlockInfo.BlockHash); - if (receipts.Length > 0) + using BatchWrite batch = _chainLevelInfoRepository.StartBatch(); + ChainLevelInfo? level = _chainLevelInfoRepository.LoadLevel(number); + if (level is not null) { - if (IsMigrationNeeded(blockNumber, firstBlockInfo.BlockHash, receipts)) + if (!level.HasBlockOnMainChain) { - _receiptStorage.MigratedBlockNumber = long.MaxValue; + if (level.BlockInfos.Length > 0) + { + level.HasBlockOnMainChain = true; + _chainLevelInfoRepository.PersistLevel(number, level, batch); + } } - break; + blockHash = level.MainChainBlock?.BlockHash; + return blockHash is not null; + } + else + { + blockHash = null; + return false; } } - blockNumber--; - } - } - } + for (long i = _toBlock - 1; i > 0; i--) + { + if (token.IsCancellationRequested) + { + timer.Stop(); + if (_logger.IsInfo) _logger.Info(GetLogMessage("cancelled")); + yield break; + } - private bool IsMigrationNeeded(long blockNumber, Keccak blockHash, TxReceipt[] receipts) - { - if (!_receiptConfig.CompactReceiptStore && _recovery.NeedRecover(receipts)) - { - return true; - } + if (TryGetMainChainBlockHashFromLevel(i, out Keccak? blockHash)) + { + Block? header = _blockTree.FindBlock(blockHash!, BlockTreeLookupOptions.None); + yield return header ?? GetMissingBlock(i, blockHash); + } - byte[]? receiptData = _receiptsBlockDb.Get(blockHash.Bytes); - if (receiptData == null) - { - receiptData = _receiptsBlockDb.Get(Bytes.Concat(blockNumber.ToBigEndianByteArray(), blockHash.Bytes)); + _progress.Update(++synced); + } + } } - if (receiptData == null) + if (!token.IsCancellationRequested) { - return true; + if (_logger.IsInfo) _logger.Info(GetLogMessage("finished")); } - - bool isCompactEncoding = _storageDecoder.IsCompactEncoding(receiptData!); - return _receiptConfig.CompactReceiptStore != isCompactEncoding; } private string GetLogMessage(string status, string? suffix = null) { - string message = $"ReceiptsDb migration {status} | {_stopwatch?.Elapsed:d\\:hh\\:mm\\:ss} | {_progress.CurrentValue.ToString().PadLeft(_toBlock.ToString().Length)} / {_toBlock} blocks migrated. | current {_progress.CurrentPerSecond:F2} Blk/s | total {_progress.TotalPerSecond:F2} Blk/s. {suffix}"; + string message = $"ReceiptsDb migration {status} | {_stopwatch?.Elapsed:d\\:hh\\:mm\\:ss} | {_progress.CurrentValue.ToString().PadLeft(_toBlock.ToString().Length)} / {_toBlock} blocks migrated. | current {_progress.CurrentPerSecond:F2}bps | total {_progress.TotalPerSecond:F2}bps. {suffix}"; _progress.SetMeasuringPoint(); return message; } - private class EmptyBlockObjectPolicy : IPooledObjectPolicy - { - public Block Create() - { - return new Block(new BlockHeader(Keccak.Zero, Keccak.Zero, Address.Zero, UInt256.Zero, 0L, 0L, 0UL, Array.Empty())); - } - - public bool Return(Block obj) - { - return true; - } - } + private long MigrateToBlockNumber => + _receiptStorage.MigratedBlockNumber == long.MaxValue + ? _syncModeSelector.Current.NotSyncing() + ? _blockTree.Head?.Number ?? 0 + : _blockTree.BestKnownNumber + : _receiptStorage.MigratedBlockNumber - 1; } } diff --git a/src/Nethermind/Nethermind.Init/Steps/Migrations/TotalDifficultyFixMigration.cs b/src/Nethermind/Nethermind.Init/Steps/Migrations/TotalDifficultyFixMigration.cs index bb8e8e9b381..70f79815525 100644 --- a/src/Nethermind/Nethermind.Init/Steps/Migrations/TotalDifficultyFixMigration.cs +++ b/src/Nethermind/Nethermind.Init/Steps/Migrations/TotalDifficultyFixMigration.cs @@ -4,7 +4,10 @@ using System; using System.Threading; using System.Threading.Tasks; +using FastEnumUtility; +using Nethermind.Api; using Nethermind.Blockchain; +using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Synchronization; using Nethermind.Core; using Nethermind.Core.Crypto; diff --git a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs index e04b1f7c225..9ee8920ae69 100644 --- a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs +++ b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs @@ -7,7 +7,9 @@ using System.Threading.Tasks; using Nethermind.Api; using Nethermind.Api.Extensions; +using Nethermind.Blockchain; using Nethermind.Blockchain.FullPruning; +using Nethermind.Consensus; using Nethermind.Core; using Nethermind.Init.Steps.Migrations; using Nethermind.JsonRpc; @@ -15,6 +17,7 @@ using Nethermind.JsonRpc.Modules.Admin; using Nethermind.JsonRpc.Modules.DebugModule; using Nethermind.JsonRpc.Modules.Eth; +using Nethermind.JsonRpc.Modules.Eth.GasPrice; using Nethermind.JsonRpc.Modules.Evm; using Nethermind.JsonRpc.Modules.Net; using Nethermind.JsonRpc.Modules.Parity; @@ -27,221 +30,220 @@ using Nethermind.JsonRpc.Modules.Witness; using Nethermind.Logging; using Nethermind.Network.Config; +using Nethermind.JsonRpc.Modules.Eth.FeeHistory; using Nethermind.JsonRpc.Modules.Rpc; -namespace Nethermind.Init.Steps; - -[RunnerStepDependencies(typeof(InitializeNetwork), typeof(SetupKeyStore), typeof(InitializeBlockchain), typeof(InitializePlugins), typeof(InitializeBlockProducer))] -public class RegisterRpcModules : IStep +namespace Nethermind.Init.Steps { - private readonly INethermindApi _api; - - public RegisterRpcModules(INethermindApi api) + [RunnerStepDependencies(typeof(InitializeNetwork), typeof(SetupKeyStore), typeof(InitializeBlockchain), typeof(InitializePlugins), typeof(InitializeBlockProducer))] + public class RegisterRpcModules : IStep { - _api = api; - } + private readonly INethermindApi _api; - public virtual async Task Execute(CancellationToken cancellationToken) - { - if (_api.BlockTree is null) throw new StepDependencyException(nameof(_api.BlockTree)); - if (_api.ReceiptFinder is null) throw new StepDependencyException(nameof(_api.ReceiptFinder)); - if (_api.BloomStorage is null) throw new StepDependencyException(nameof(_api.BloomStorage)); - if (_api.LogManager is null) throw new StepDependencyException(nameof(_api.LogManager)); - - IJsonRpcConfig jsonRpcConfig = _api.Config(); - if (!jsonRpcConfig.Enabled) + public RegisterRpcModules(INethermindApi api) { - return; + _api = api; } - if (_api.FileSystem is null) throw new StepDependencyException(nameof(_api.FileSystem)); - if (_api.TxPool is null) throw new StepDependencyException(nameof(_api.TxPool)); - if (_api.Wallet is null) throw new StepDependencyException(nameof(_api.Wallet)); - if (_api.SpecProvider is null) throw new StepDependencyException(nameof(_api.SpecProvider)); - if (_api.SyncModeSelector is null) throw new StepDependencyException(nameof(_api.SyncModeSelector)); - if (_api.TxSender is null) throw new StepDependencyException(nameof(_api.TxSender)); - if (_api.StateReader is null) throw new StepDependencyException(nameof(_api.StateReader)); - if (_api.PeerManager is null) throw new StepDependencyException(nameof(_api.PeerManager)); - - if (jsonRpcConfig.Enabled) + public virtual async Task Execute(CancellationToken cancellationToken) { - _api.RpcModuleProvider = new RpcModuleProvider(_api.FileSystem, jsonRpcConfig, _api.LogManager); + if (_api.BlockTree is null) throw new StepDependencyException(nameof(_api.BlockTree)); + if (_api.ReceiptFinder is null) throw new StepDependencyException(nameof(_api.ReceiptFinder)); + if (_api.BloomStorage is null) throw new StepDependencyException(nameof(_api.BloomStorage)); + if (_api.LogManager is null) throw new StepDependencyException(nameof(_api.LogManager)); + + IJsonRpcConfig jsonRpcConfig = _api.Config(); + if (!jsonRpcConfig.Enabled) + { + return; + } + + if (_api.FileSystem is null) throw new StepDependencyException(nameof(_api.FileSystem)); + if (_api.TxPool is null) throw new StepDependencyException(nameof(_api.TxPool)); + if (_api.Wallet is null) throw new StepDependencyException(nameof(_api.Wallet)); + if (_api.SpecProvider is null) throw new StepDependencyException(nameof(_api.SpecProvider)); + if (_api.SyncModeSelector is null) throw new StepDependencyException(nameof(_api.SyncModeSelector)); + if (_api.TxSender is null) throw new StepDependencyException(nameof(_api.TxSender)); + if (_api.StateReader is null) throw new StepDependencyException(nameof(_api.StateReader)); + if (_api.PeerManager is null) throw new StepDependencyException(nameof(_api.PeerManager)); + + if (jsonRpcConfig.Enabled) + { + _api.RpcModuleProvider = new RpcModuleProvider(_api.FileSystem, jsonRpcConfig, _api.LogManager); + } + else + { + _api.RpcModuleProvider ??= NullModuleProvider.Instance; + } + + IRpcModuleProvider rpcModuleProvider = _api.RpcModuleProvider; + + // the following line needs to be called in order to make sure that the CLI library is referenced from runner and built alongside + ILogger logger = _api.LogManager.GetClassLogger(); + + IInitConfig initConfig = _api.Config(); + IJsonRpcConfig rpcConfig = _api.Config(); + INetworkConfig networkConfig = _api.Config(); + + // lets add threads to support parallel eth_getLogs + ThreadPool.GetMinThreads(out int workerThreads, out int completionPortThreads); + ThreadPool.SetMinThreads(workerThreads + Environment.ProcessorCount, completionPortThreads + Environment.ProcessorCount); + + if (_api.ReceiptStorage is null) throw new StepDependencyException(nameof(_api.ReceiptStorage)); + if (_api.GasPriceOracle is null) throw new StepDependencyException(nameof(_api.GasPriceOracle)); + if (_api.EthSyncingInfo is null) throw new StepDependencyException(nameof(_api.EthSyncingInfo)); + if (_api.ReadOnlyTrieStore is null) throw new StepDependencyException(nameof(_api.ReadOnlyTrieStore)); + + EthModuleFactory ethModuleFactory = new( + _api.TxPool, + _api.TxSender, + _api.Wallet, + _api.BlockTree, + rpcConfig, + _api.LogManager, + _api.StateReader, + _api, + _api.SpecProvider, + _api.ReceiptStorage, + _api.GasPriceOracle, + _api.EthSyncingInfo); + + rpcModuleProvider.RegisterBounded(ethModuleFactory, rpcConfig.EthModuleConcurrentInstances ?? Environment.ProcessorCount, rpcConfig.Timeout); + + if (_api.DbProvider is null) throw new StepDependencyException(nameof(_api.DbProvider)); + if (_api.BlockPreprocessor is null) throw new StepDependencyException(nameof(_api.BlockPreprocessor)); + if (_api.BlockValidator is null) throw new StepDependencyException(nameof(_api.BlockValidator)); + if (_api.RewardCalculatorSource is null) throw new StepDependencyException(nameof(_api.RewardCalculatorSource)); + if (_api.KeyStore is null) throw new StepDependencyException(nameof(_api.KeyStore)); + if (_api.PeerPool is null) throw new StepDependencyException(nameof(_api.PeerPool)); + if (_api.WitnessRepository is null) throw new StepDependencyException(nameof(_api.WitnessRepository)); + + ProofModuleFactory proofModuleFactory = new(_api.DbProvider, _api.BlockTree, _api.ReadOnlyTrieStore, _api.BlockPreprocessor, _api.ReceiptFinder, _api.SpecProvider, _api.LogManager); + rpcModuleProvider.RegisterBounded(proofModuleFactory, 2, rpcConfig.Timeout); + + DebugModuleFactory debugModuleFactory = new( + _api.DbProvider, + _api.BlockTree, + rpcConfig, + _api.BlockValidator, + _api.BlockPreprocessor, + _api.RewardCalculatorSource, + _api.ReceiptStorage, + new ReceiptMigration(_api), + _api.ReadOnlyTrieStore, + _api.ConfigProvider, + _api.SpecProvider, + _api.SyncModeSelector, + _api.LogManager); + rpcModuleProvider.RegisterBoundedByCpuCount(debugModuleFactory, rpcConfig.Timeout); + + TraceModuleFactory traceModuleFactory = new( + _api.DbProvider, + _api.BlockTree, + _api.ReadOnlyTrieStore, + rpcConfig, + _api.BlockPreprocessor, + _api.RewardCalculatorSource, + _api.ReceiptStorage, + _api.SpecProvider, + _api.PoSSwitcher, + _api.LogManager); + + rpcModuleProvider.RegisterBoundedByCpuCount(traceModuleFactory, rpcConfig.Timeout); + + if (_api.EthereumEcdsa is null) throw new StepDependencyException(nameof(_api.EthereumEcdsa)); + if (_api.Wallet is null) throw new StepDependencyException(nameof(_api.Wallet)); + + PersonalRpcModule personalRpcModule = new( + _api.EthereumEcdsa, + _api.Wallet, + _api.KeyStore); + rpcModuleProvider.RegisterSingle(personalRpcModule); + + if (_api.PeerManager is null) throw new StepDependencyException(nameof(_api.PeerManager)); + if (_api.StaticNodesManager is null) throw new StepDependencyException(nameof(_api.StaticNodesManager)); + if (_api.Enode is null) throw new StepDependencyException(nameof(_api.Enode)); + + ManualPruningTrigger pruningTrigger = new(); + _api.PruningTrigger.Add(pruningTrigger); + AdminRpcModule adminRpcModule = new( + _api.BlockTree, + networkConfig, + _api.PeerPool, + _api.StaticNodesManager, + _api.Enode, + initConfig.BaseDbPath, + pruningTrigger); + rpcModuleProvider.RegisterSingle(adminRpcModule); + + if (_api.TxPoolInfoProvider is null) throw new StepDependencyException(nameof(_api.TxPoolInfoProvider)); + + TxPoolRpcModule txPoolRpcModule = new(_api.TxPoolInfoProvider, _api.LogManager); + rpcModuleProvider.RegisterSingle(txPoolRpcModule); + + if (_api.SyncServer is null) throw new StepDependencyException(nameof(_api.SyncServer)); + if (_api.EngineSignerStore is null) throw new StepDependencyException(nameof(_api.EngineSignerStore)); + + NetRpcModule netRpcModule = new(_api.LogManager, new NetBridge(_api.Enode, _api.SyncServer)); + rpcModuleProvider.RegisterSingle(netRpcModule); + + ParityRpcModule parityRpcModule = new( + _api.EthereumEcdsa, + _api.TxPool, + _api.BlockTree, + _api.ReceiptFinder, + _api.Enode, + _api.EngineSignerStore, + _api.KeyStore, + _api.SpecProvider, + _api.PeerManager); + rpcModuleProvider.RegisterSingle(parityRpcModule); + + WitnessRpcModule witnessRpcModule = new(_api.WitnessRepository, _api.BlockTree); + rpcModuleProvider.RegisterSingle(witnessRpcModule); + + if (_api.ReceiptMonitor is null) throw new StepDependencyException(nameof(_api.ReceiptMonitor)); + + JsonRpcLocalStats jsonRpcLocalStats = new( + _api.Timestamper, + jsonRpcConfig, + _api.LogManager); + + _api.JsonRpcLocalStats = jsonRpcLocalStats; + + SubscriptionFactory subscriptionFactory = new( + _api.LogManager, + _api.BlockTree, + _api.TxPool, + _api.ReceiptMonitor, + _api.FilterStore, + _api.EthSyncingInfo!, + _api.SpecProvider, + rpcModuleProvider.Serializer); + + _api.SubscriptionFactory = subscriptionFactory; + + SubscriptionManager subscriptionManager = new(subscriptionFactory, _api.LogManager); + + SubscribeRpcModule subscribeRpcModule = new(subscriptionManager); + rpcModuleProvider.RegisterSingle(subscribeRpcModule); + + Web3RpcModule web3RpcModule = new(_api.LogManager); + rpcModuleProvider.RegisterSingle(web3RpcModule); + + EvmRpcModule evmRpcModule = new(_api.ManualBlockProductionTrigger); + rpcModuleProvider.RegisterSingle(evmRpcModule); + + foreach (INethermindPlugin plugin in _api.Plugins) + { + await plugin.InitRpcModules(); + } + + RpcRpcModule rpcRpcModule = new(rpcModuleProvider.Enabled); + rpcModuleProvider.RegisterSingle(rpcRpcModule); + + if (logger.IsDebug) logger.Debug($"RPC modules : {string.Join(", ", rpcModuleProvider.Enabled.OrderBy(x => x))}"); + ThisNodeInfo.AddInfo("RPC modules :", $"{string.Join(", ", rpcModuleProvider.Enabled.OrderBy(x => x))}"); } - else - { - _api.RpcModuleProvider ??= NullModuleProvider.Instance; - } - - IRpcModuleProvider rpcModuleProvider = _api.RpcModuleProvider; - - // the following line needs to be called in order to make sure that the CLI library is referenced from runner and built alongside - ILogger logger = _api.LogManager.GetClassLogger(); - - IInitConfig initConfig = _api.Config(); - IJsonRpcConfig rpcConfig = _api.Config(); - INetworkConfig networkConfig = _api.Config(); - - // lets add threads to support parallel eth_getLogs - ThreadPool.GetMinThreads(out int workerThreads, out int completionPortThreads); - ThreadPool.SetMinThreads(workerThreads + Environment.ProcessorCount, completionPortThreads + Environment.ProcessorCount); - - if (_api.ReceiptStorage is null) throw new StepDependencyException(nameof(_api.ReceiptStorage)); - if (_api.GasPriceOracle is null) throw new StepDependencyException(nameof(_api.GasPriceOracle)); - if (_api.EthSyncingInfo is null) throw new StepDependencyException(nameof(_api.EthSyncingInfo)); - if (_api.ReadOnlyTrieStore is null) throw new StepDependencyException(nameof(_api.ReadOnlyTrieStore)); - - - EthModuleFactory ethModuleFactory = new( - _api.TxPool, - _api.TxSender, - _api.Wallet, - _api.BlockTree, - rpcConfig, - _api.LogManager, - _api.StateReader, - _api, - _api.SpecProvider, - _api.ReceiptStorage, - _api.GasPriceOracle, - _api.EthSyncingInfo); - - RpcLimits.Init(rpcConfig.RequestQueueLimit); - rpcModuleProvider.RegisterBounded(ethModuleFactory, rpcConfig.EthModuleConcurrentInstances ?? Environment.ProcessorCount, rpcConfig.Timeout); - - if (_api.DbProvider is null) throw new StepDependencyException(nameof(_api.DbProvider)); - if (_api.BlockPreprocessor is null) throw new StepDependencyException(nameof(_api.BlockPreprocessor)); - if (_api.BlockValidator is null) throw new StepDependencyException(nameof(_api.BlockValidator)); - if (_api.RewardCalculatorSource is null) throw new StepDependencyException(nameof(_api.RewardCalculatorSource)); - if (_api.KeyStore is null) throw new StepDependencyException(nameof(_api.KeyStore)); - if (_api.PeerPool is null) throw new StepDependencyException(nameof(_api.PeerPool)); - if (_api.WitnessRepository is null) throw new StepDependencyException(nameof(_api.WitnessRepository)); - - ProofModuleFactory proofModuleFactory = new(_api.DbProvider, _api.BlockTree, _api.ReadOnlyTrieStore, _api.BlockPreprocessor, _api.ReceiptFinder, _api.SpecProvider, _api.LogManager); - rpcModuleProvider.RegisterBounded(proofModuleFactory, 2, rpcConfig.Timeout); - - DebugModuleFactory debugModuleFactory = new( - _api.DbProvider, - _api.BlockTree, - rpcConfig, - _api.BlockValidator, - _api.BlockPreprocessor, - _api.RewardCalculatorSource, - _api.ReceiptStorage, - new ReceiptMigration(_api), - _api.ReadOnlyTrieStore, - _api.ConfigProvider, - _api.SpecProvider, - _api.SyncModeSelector, - _api.FileSystem, - _api.LogManager); - rpcModuleProvider.RegisterBoundedByCpuCount(debugModuleFactory, rpcConfig.Timeout); - - TraceModuleFactory traceModuleFactory = new( - _api.DbProvider, - _api.BlockTree, - _api.ReadOnlyTrieStore, - rpcConfig, - _api.BlockPreprocessor, - _api.RewardCalculatorSource, - _api.ReceiptStorage, - _api.SpecProvider, - _api.PoSSwitcher, - _api.LogManager); - - rpcModuleProvider.RegisterBoundedByCpuCount(traceModuleFactory, rpcConfig.Timeout); - - if (_api.EthereumEcdsa is null) throw new StepDependencyException(nameof(_api.EthereumEcdsa)); - if (_api.Wallet is null) throw new StepDependencyException(nameof(_api.Wallet)); - - PersonalRpcModule personalRpcModule = new( - _api.EthereumEcdsa, - _api.Wallet, - _api.KeyStore); - rpcModuleProvider.RegisterSingle(personalRpcModule); - - if (_api.PeerManager is null) throw new StepDependencyException(nameof(_api.PeerManager)); - if (_api.StaticNodesManager is null) throw new StepDependencyException(nameof(_api.StaticNodesManager)); - if (_api.Enode is null) throw new StepDependencyException(nameof(_api.Enode)); - - ManualPruningTrigger pruningTrigger = new(); - _api.PruningTrigger.Add(pruningTrigger); - AdminRpcModule adminRpcModule = new( - _api.BlockTree, - networkConfig, - _api.PeerPool, - _api.StaticNodesManager, - _api.Enode, - initConfig.BaseDbPath, - pruningTrigger); - rpcModuleProvider.RegisterSingle(adminRpcModule); - - if (_api.TxPoolInfoProvider is null) throw new StepDependencyException(nameof(_api.TxPoolInfoProvider)); - - TxPoolRpcModule txPoolRpcModule = new(_api.TxPoolInfoProvider, _api.LogManager); - rpcModuleProvider.RegisterSingle(txPoolRpcModule); - - if (_api.SyncServer is null) throw new StepDependencyException(nameof(_api.SyncServer)); - if (_api.EngineSignerStore is null) throw new StepDependencyException(nameof(_api.EngineSignerStore)); - - NetRpcModule netRpcModule = new(_api.LogManager, new NetBridge(_api.Enode, _api.SyncServer)); - rpcModuleProvider.RegisterSingle(netRpcModule); - - ParityRpcModule parityRpcModule = new( - _api.EthereumEcdsa, - _api.TxPool, - _api.BlockTree, - _api.ReceiptFinder, - _api.Enode, - _api.EngineSignerStore, - _api.KeyStore, - _api.SpecProvider, - _api.PeerManager); - rpcModuleProvider.RegisterSingle(parityRpcModule); - - WitnessRpcModule witnessRpcModule = new(_api.WitnessRepository, _api.BlockTree); - rpcModuleProvider.RegisterSingle(witnessRpcModule); - - if (_api.ReceiptMonitor is null) throw new StepDependencyException(nameof(_api.ReceiptMonitor)); - - JsonRpcLocalStats jsonRpcLocalStats = new( - _api.Timestamper, - jsonRpcConfig, - _api.LogManager); - - _api.JsonRpcLocalStats = jsonRpcLocalStats; - - SubscriptionFactory subscriptionFactory = new( - _api.LogManager, - _api.BlockTree, - _api.TxPool, - _api.ReceiptMonitor, - _api.FilterStore, - _api.EthSyncingInfo!, - _api.SpecProvider, - rpcModuleProvider.Serializer); - - _api.SubscriptionFactory = subscriptionFactory; - - SubscriptionManager subscriptionManager = new(subscriptionFactory, _api.LogManager); - - SubscribeRpcModule subscribeRpcModule = new(subscriptionManager); - rpcModuleProvider.RegisterSingle(subscribeRpcModule); - - Web3RpcModule web3RpcModule = new(_api.LogManager); - rpcModuleProvider.RegisterSingle(web3RpcModule); - - EvmRpcModule evmRpcModule = new(_api.ManualBlockProductionTrigger); - rpcModuleProvider.RegisterSingle(evmRpcModule); - - foreach (INethermindPlugin plugin in _api.Plugins) - { - await plugin.InitRpcModules(); - } - - RpcRpcModule rpcRpcModule = new(rpcModuleProvider.Enabled); - rpcModuleProvider.RegisterSingle(rpcRpcModule); - - if (logger.IsDebug) logger.Debug($"RPC modules : {string.Join(", ", rpcModuleProvider.Enabled.OrderBy(x => x))}"); - ThisNodeInfo.AddInfo("RPC modules :", $"{string.Join(", ", rpcModuleProvider.Enabled.OrderBy(x => x))}"); } } diff --git a/src/Nethermind/Nethermind.Init/Steps/ResetDatabaseMigrations.cs b/src/Nethermind/Nethermind.Init/Steps/ResetDatabaseMigrations.cs new file mode 100644 index 00000000000..8535e934238 --- /dev/null +++ b/src/Nethermind/Nethermind.Init/Steps/ResetDatabaseMigrations.cs @@ -0,0 +1,75 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Nethermind.Api; +using Nethermind.Blockchain; +using Nethermind.Blockchain.Receipts; +using Nethermind.Core; +using Nethermind.State.Repositories; + +namespace Nethermind.Init.Steps +{ + [RunnerStepDependencies(typeof(InitRlp), typeof(InitDatabase), typeof(InitializeBlockchain))] + public class ResetDatabaseMigrations : IStep + { + private readonly IApiWithNetwork _api; + private IReceiptStorage _receiptStorage = null!; + private IBlockTree _blockTree = null!; + private IChainLevelInfoRepository _chainLevelInfoRepository = null!; + + public ResetDatabaseMigrations(INethermindApi api) + { + _api = api; + } + + public Task Execute(CancellationToken cancellationToken) + { + _receiptStorage = _api.ReceiptStorage ?? throw new StepDependencyException(nameof(_api.ReceiptStorage)); + _blockTree = _api.BlockTree ?? throw new StepDependencyException(nameof(_api.BlockTree)); + _chainLevelInfoRepository = _api.ChainLevelInfoRepository ?? throw new StepDependencyException(nameof(_api.ChainLevelInfoRepository)); + + IInitConfig initConfig = _api.Config(); + + if (initConfig.StoreReceipts) + { + ResetMigrationIndexIfNeeded(); + } + + return Task.CompletedTask; + } + + private void ResetMigrationIndexIfNeeded() + { + ReceiptsRecovery recovery = new ReceiptsRecovery(_api.EthereumEcdsa, _api.SpecProvider); + + if (_receiptStorage.MigratedBlockNumber != long.MaxValue) + { + long blockNumber = _blockTree.Head?.Number ?? 0; + while (blockNumber > 0) + { + ChainLevelInfo? level = _chainLevelInfoRepository.LoadLevel(blockNumber); + BlockInfo? firstBlockInfo = level?.BlockInfos.FirstOrDefault(); + if (firstBlockInfo is not null) + { + TxReceipt[] receipts = _receiptStorage.Get(firstBlockInfo.BlockHash); + if (receipts.Length > 0) + { + if (recovery.NeedRecover(receipts)) + { + _receiptStorage.MigratedBlockNumber = long.MaxValue; + } + + break; + } + } + + blockNumber--; + } + } + } + } +} diff --git a/src/Nethermind/Nethermind.Init/Steps/StartBlockProcessor.cs b/src/Nethermind/Nethermind.Init/Steps/StartBlockProcessor.cs index 129888475d6..de86094b565 100644 --- a/src/Nethermind/Nethermind.Init/Steps/StartBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Init/Steps/StartBlockProcessor.cs @@ -7,7 +7,7 @@ namespace Nethermind.Init.Steps { - [RunnerStepDependencies(typeof(InitializeBlockchain))] + [RunnerStepDependencies(typeof(InitializeBlockchain), typeof(ResetDatabaseMigrations))] public class StartBlockProcessor : IStep { private readonly IApiWithBlockchain _api; diff --git a/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs b/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs index eba010e3c0e..80b1bd93682 100644 --- a/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs +++ b/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -44,7 +45,7 @@ public async Task Execute(CancellationToken cancellationToken) PrepareProductInfoMetrics(); controller = new(_metricsConfig); - IEnumerable metrics = TypeDiscovery.FindNethermindBasedTypes(nameof(Metrics)); + IEnumerable metrics = TypeDiscovery.FindNethermindTypes(nameof(Metrics)); foreach (Type metric in metrics) { controller.RegisterMetrics(metric); @@ -53,17 +54,17 @@ public async Task Execute(CancellationToken cancellationToken) if (_metricsConfig.Enabled) { - IMonitoringService monitoringService = _api.MonitoringService = new MonitoringService(controller, _metricsConfig, _api.LogManager); + _api.MonitoringService = new MonitoringService(controller, _metricsConfig, _api.LogManager); - SetupMetrics(monitoringService); - - await monitoringService.StartAsync().ContinueWith(x => + await _api.MonitoringService.StartAsync().ContinueWith(x => { if (x.IsFaulted && _logger.IsError) _logger.Error("Error during starting a monitoring.", x.Exception); }, cancellationToken); - _api.DisposeStack.Push(new Reactive.AnonymousDisposable(() => monitoringService.StopAsync())); // do not await + SetupMetrics(); + + _api.DisposeStack.Push(new Reactive.AnonymousDisposable(() => _api.MonitoringService.StopAsync())); // do not await } else { @@ -79,11 +80,11 @@ await monitoringService.StartAsync().ContinueWith(x => } } - private void SetupMetrics(IMonitoringService monitoringService) + private void SetupMetrics() { if (_metricsConfig.EnableDbSizeMetrics) { - monitoringService.AddMetricsUpdateAction(() => + _api.MonitoringService.AddMetricsUpdateAction(() => { IDbProvider? dbProvider = _api.DbProvider; if (dbProvider is null) @@ -142,7 +143,7 @@ private void SetupMetrics(IMonitoringService monitoringService) }); } - monitoringService.AddMetricsUpdateAction(() => + _api.MonitoringService.AddMetricsUpdateAction(() => { Synchronization.Metrics.SyncTime = (long?)_api.EthSyncingInfo?.UpdateAndGetSyncTime().TotalSeconds ?? 0; }); diff --git a/src/Nethermind/Nethermind.Init/Steps/UpdateDiscoveryConfig.cs b/src/Nethermind/Nethermind.Init/Steps/UpdateDiscoveryConfig.cs index cb4c3f1b6b2..66210634004 100644 --- a/src/Nethermind/Nethermind.Init/Steps/UpdateDiscoveryConfig.cs +++ b/src/Nethermind/Nethermind.Init/Steps/UpdateDiscoveryConfig.cs @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks; using Nethermind.Api; +using Nethermind.Network.Config; using Nethermind.Network.Discovery; namespace Nethermind.Init.Steps diff --git a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs index 6f64edef12d..922541c2d0c 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs @@ -31,6 +31,7 @@ using Nethermind.Trie.Pruning; using Nethermind.TxPool; using Nethermind.Wallet; +using NSubstitute; using BlockTree = Nethermind.Blockchain.BlockTree; using Nethermind.Blockchain.Synchronization; using Nethermind.Config; @@ -140,6 +141,7 @@ TransactionProcessor transactionProcessor NullTxPool.Instance, NullTxSender.Instance, NullWallet.Instance, + Substitute.For(), LimboLogs.Instance, specProvider, gasPriceOracle, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.JsonRpcDataSource.cs b/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.JsonRpcDataSource.cs index cc24a2f2260..fbcf8809278 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.JsonRpcDataSource.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.JsonRpcDataSource.cs @@ -48,19 +48,19 @@ protected JsonRpcRequestWithParams CreateRequest(string methodName, params objec public void Dispose() { - _httpClient.Dispose(); + _httpClient?.Dispose(); } protected class JsonRpcSuccessResponse : JsonRpcSuccessResponse { [JsonProperty(PropertyName = "result", NullValueHandling = NullValueHandling.Include, Order = 1)] - public new T Result { get { return (T)base.Result!; } set { base.Result = value; } } + public new T Result { get { return (T)base.Result; } set { base.Result = value; } } } public virtual async Task<(T2, string)> GetData() { string jsonData = await GetJsonData(); - return (_serializer.Deserialize>(jsonData).Result!, jsonData); + return (_serializer.Deserialize>(jsonData).Result, jsonData); } public abstract Task GetJsonData(); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.ReceiptsJsonRpcDataSource.cs b/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.ReceiptsJsonRpcDataSource.cs index 78886a095e5..5502d5c5d19 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.ReceiptsJsonRpcDataSource.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.ReceiptsJsonRpcDataSource.cs @@ -31,7 +31,7 @@ private async Task> GetJsonDatas() JsonRpcRequest request = CreateRequest("eth_getBlockByHash", Parameter.ToString(), false); string blockJson = await SendRequest(request); BlockForRpcTxHashes block = _serializer.Deserialize>(blockJson).Result; - List transactionsJsons = new(block.Transactions!.Length); + List transactionsJsons = new(block.Transactions.Length); foreach (string tx in block.Transactions) { transactionsJsons.Add(await SendRequest(CreateRequest("eth_getTransactionReceipt", tx))); @@ -48,7 +48,7 @@ private async Task> GetJsonDatas() private class BlockForRpcTxHashes : BlockForRpc { - public new string[]? Transactions { get; set; } + public new string[] Transactions { get; set; } } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Data/AccessListItemForRpcTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Data/AccessListItemForRpcTests.cs deleted file mode 100644 index 31345ac4e63..00000000000 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Data/AccessListItemForRpcTests.cs +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using FluentAssertions; -using Nethermind.Core; -using Nethermind.Core.Eip2930; -using Nethermind.Core.Test.Builders; -using Nethermind.Int256; -using Nethermind.JsonRpc.Data; -using NUnit.Framework; - -namespace Nethermind.JsonRpc.Test.Data; - -public class AccessListItemForRpcTests -{ - [Test] - public void Single_address_with_no_storage() - { - Address address = TestItem.AddressA; - AccessList accessList = new AccessList.Builder() - .AddAddress(address) - .Build(); - - IEnumerable forRpc = AccessListItemForRpc.FromAccessList(accessList); - AccessListItemForRpc[] expected = { new(address, new UInt256[] { }) }; - forRpc.Should().BeEquivalentTo(expected); - } - - [Test] - public void Single_address_with_multiple_storage_keys() - { - Address address = TestItem.AddressA; - UInt256 storageKey1 = (UInt256)1; - UInt256 storageKey2 = (UInt256)2; - UInt256 storageKey3 = (UInt256)3; - - AccessList accessList = new AccessList.Builder() - .AddAddress(address) - .AddStorage(storageKey1) - .AddStorage(storageKey2) - .AddStorage(storageKey3) - .Build(); - - IEnumerable forRpc = AccessListItemForRpc.FromAccessList(accessList); - AccessListItemForRpc[] expected = { new(address, new[] { storageKey1, storageKey2, storageKey3 }) }; - forRpc.Should().BeEquivalentTo(expected); - } - - [Test] - public void Single_address_with_duplicated_storage_keys() - { - Address address = TestItem.AddressA; - UInt256 storageKey1 = (UInt256)1; - UInt256 storageKey2 = (UInt256)2; - UInt256 storageKey3 = (UInt256)3; - - AccessList accessList = new AccessList.Builder() - .AddAddress(address) - .AddStorage(storageKey1) - .AddStorage(storageKey2) - .AddStorage(storageKey3) - .AddStorage(storageKey1) - .Build(); - - IEnumerable forRpc = AccessListItemForRpc.FromAccessList(accessList); - - AccessListItemForRpc[] expected = { new(address, new[] { storageKey1, storageKey2, storageKey3, storageKey1 }) }; - forRpc.Should().BeEquivalentTo(expected); - } - - [Test] - public void Duplicated_address_with_multiple_storage_keys() - { - Address address = TestItem.AddressA; - UInt256 storageKey1 = (UInt256)1; - UInt256 storageKey2 = (UInt256)2; - UInt256 storageKey3 = (UInt256)3; - - AccessList accessList = new AccessList.Builder() - .AddAddress(address) - .AddStorage(storageKey1) - .AddStorage(storageKey2) - .AddAddress(address) - .AddStorage(storageKey3) - .Build(); - - IEnumerable forRpc = AccessListItemForRpc.FromAccessList(accessList); - - AccessListItemForRpc[] expected = { new(address, new[] { storageKey1, storageKey2 }), new(address, new[] { storageKey3 }) }; - forRpc.Should().BeEquivalentTo(expected); - } - - [Test] - public void Duplicated_address_with_duplicated_storage_keys() - { - Address address = TestItem.AddressA; - UInt256 storageKey1 = (UInt256)1; - UInt256 storageKey2 = (UInt256)2; - UInt256 storageKey3 = (UInt256)3; - - AccessList accessList = new AccessList.Builder() - .AddAddress(address) - .AddStorage(storageKey1) - .AddStorage(storageKey2) - .AddAddress(address) - .AddStorage(storageKey1) - .AddStorage(storageKey3) - .Build(); - - IEnumerable forRpc = AccessListItemForRpc.FromAccessList(accessList); - AccessListItemForRpc[] expected = { new(address, new[] { storageKey1, storageKey2 }), new(address, new[] { storageKey1, storageKey3 }) }; - forRpc.Should().BeEquivalentTo(expected); - } -} diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs index a9176491bdf..1981a60accf 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using FluentAssertions; -using FluentAssertions.Json; using Nethermind.Core; using Nethermind.Core.Eip2930; using Nethermind.Core.Extensions; @@ -11,231 +10,201 @@ using Nethermind.Int256; using Nethermind.JsonRpc.Data; using Nethermind.Serialization.Json; -using Newtonsoft.Json.Linq; using NUnit.Framework; -namespace Nethermind.JsonRpc.Test.Data; - -public class Eip2930Tests +namespace Nethermind.JsonRpc.Test.Data { - private readonly EthereumJsonSerializer _serializer = new(); - - private AccessList GetTestAccessList() + public class Eip2930Tests { - return new AccessList.Builder() - .AddAddress(TestItem.AddressA) - .AddStorage(1) - .AddStorage(2) - .AddStorage(3) - .AddStorage(5) - .AddStorage(8) - .AddAddress(TestItem.AddressB) - .AddStorage(42) - .Build(); - } + private readonly EthereumJsonSerializer _serializer = new(); + private Transaction _transaction = new(); + private Dictionary> _data = new(); + private TransactionForRpc _transactionForRpc = new(); + private HashSet _storageKeys = new(); - [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x1","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000003","0x0000000000000000000000000000000000000000000000000000000000000005","0x0000000000000000000000000000000000000000000000000000000000000008"]},{"address":"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358","storageKeys":["0x000000000000000000000000000000000000000000000000000000000000002a"]}]}""")] - [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x2","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000003","0x0000000000000000000000000000000000000000000000000000000000000005","0x0000000000000000000000000000000000000000000000000000000000000008"]},{"address":"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358","storageKeys":["0x000000000000000000000000000000000000000000000000000000000000002a"]}]}""")] - public void can_serialize_valid_accessList(TxType txType, string txJson) - { - Transaction transaction = new() + private AccessList GetTestAccessList() { - Type = txType, - AccessList = GetTestAccessList(), - }; - TransactionForRpc transactionForRpc = new(transaction); - - string serialized = _serializer.Serialize(transactionForRpc); - - JToken.Parse(serialized).Should().BeEquivalentTo(JToken.Parse(txJson)); - } - - [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x01","chainId":"0x01","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":["0x1","0x2","0x3","0x5","0x8"]},{"address":"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358","storageKeys":["0x2a"]}]}""")] - [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxFeePerGas":"0x0","maxPriorityFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x02","chainId":"0x01","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":["0x1","0x2","0x3","0x5","0x8"]},{"address":"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358","storageKeys":["0x2a"]}]}""")] - public void can_deserialize_valid_accessList(TxType txType, string txJson) - { - Transaction transaction = new() + AccessListBuilder accessListBuilder = new(); + + accessListBuilder.AddAddress(TestItem.AddressA); + accessListBuilder.AddStorage(1); + accessListBuilder.AddStorage(2); + accessListBuilder.AddStorage(3); + accessListBuilder.AddStorage(5); + accessListBuilder.AddStorage(8); + accessListBuilder.AddAddress(TestItem.AddressB); + accessListBuilder.AddStorage(42); + + return accessListBuilder.ToAccessList(); + } + + [TestCase(TxType.AccessList, "{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x1\",\"accessList\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"storageKeys\":[\"0x0000000000000000000000000000000000000000000000000000000000000001\",\"0x0000000000000000000000000000000000000000000000000000000000000002\",\"0x0000000000000000000000000000000000000000000000000000000000000003\",\"0x0000000000000000000000000000000000000000000000000000000000000005\",\"0x0000000000000000000000000000000000000000000000000000000000000008\"]},{\"address\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"storageKeys\":[\"0x000000000000000000000000000000000000000000000000000000000000002a\"]}]}")] + [TestCase(TxType.EIP1559, "{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"maxPriorityFeePerGas\":\"0x0\",\"maxFeePerGas\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x2\",\"accessList\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"storageKeys\":[\"0x0000000000000000000000000000000000000000000000000000000000000001\",\"0x0000000000000000000000000000000000000000000000000000000000000002\",\"0x0000000000000000000000000000000000000000000000000000000000000003\",\"0x0000000000000000000000000000000000000000000000000000000000000005\",\"0x0000000000000000000000000000000000000000000000000000000000000008\"]},{\"address\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"storageKeys\":[\"0x000000000000000000000000000000000000000000000000000000000000002a\"]}]}")] + public void can_serialize_valid_accessList(TxType txType, string txJson) { - Type = txType, - AccessList = GetTestAccessList(), - }; - TransactionForRpc transactionForRpc = new(transaction); - - TransactionForRpc deserializedTxForRpc = _serializer.Deserialize(txJson); - - deserializedTxForRpc.Should().BeEquivalentTo(transactionForRpc); - } - - [TestCase(TxType.Legacy)] - public void can_serialize_null_accessList_to_nothing(TxType txType) - { - Transaction transaction = new() + _transaction = new Transaction(); + _transaction.Type = txType; + _transaction.AccessList = GetTestAccessList(); + _transactionForRpc = new TransactionForRpc(_transaction); + + string serialized = _serializer.Serialize(_transactionForRpc); + txJson.Should().Be(serialized); + } + + [TestCase(TxType.AccessList, "{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x01\",\"accessList\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"storageKeys\":[\"0x1\",\"0x2\",\"0x3\",\"0x5\",\"0x8\"]},{\"address\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"storageKeys\":[\"0x2a\"]}]}")] + [TestCase(TxType.EIP1559, "{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"maxFeePerGas\":\"0x0\",\"maxPriorityFeePerGas\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x02\",\"accessList\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"storageKeys\":[\"0x1\",\"0x2\",\"0x3\",\"0x5\",\"0x8\"]},{\"address\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"storageKeys\":[\"0x2a\"]}]}")] + public void can_deserialize_valid_accessList(TxType txType, string txJson) { - Type = txType, - }; - TransactionForRpc rpc = new(transaction); + TransactionForRpc deserializedTxForRpc = _serializer.Deserialize(txJson); - string serialized = _serializer.Serialize(rpc); + _transaction = new Transaction(); + _transaction.Type = txType; + _transaction.AccessList = GetTestAccessList(); + _transactionForRpc = new TransactionForRpc(_transaction); - JObject.Parse(serialized).Should().NotHaveElement("accessList"); - } + deserializedTxForRpc.Should().BeEquivalentTo(_transactionForRpc); + } - [TestCase(TxType.AccessList)] - [TestCase(TxType.EIP1559)] - public void can_serialize_null_accessList_to_empty_array(TxType txType) - { - Transaction transaction = new() + [TestCase(TxType.AccessList, "{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x1\"}")] + [TestCase(TxType.EIP1559, "{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"maxPriorityFeePerGas\":\"0x0\",\"maxFeePerGas\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x2\"}")] + public void can_serialize_null_accessList(TxType txType, string txJson) { - Type = txType, - }; - TransactionForRpc rpc = new(transaction); - - string serialized = _serializer.Serialize(rpc); - - JObject.Parse(serialized).GetValue("accessList").Should().BeEquivalentTo(new JArray()); - } - - [Test] - public void can_deserialize_null_accessList() - { - string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x01"}"""; - - TransactionForRpc transactionForRpc = _serializer.Deserialize(json); + _transaction = new Transaction(); + _transaction.Type = txType; + _transactionForRpc = new TransactionForRpc(_transaction); - transactionForRpc.Type.Should().Be(TxType.AccessList); - transactionForRpc.AccessList.Should().BeNull(); - } - - [Test] - public void can_deserialize_no_accessList() - { - string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x0"}"""; - - TransactionForRpc transactionForRpc = _serializer.Deserialize(json); + string serialized = _serializer.Serialize(_transactionForRpc); + txJson.Should().Be(serialized); + } - transactionForRpc.Type.Should().Be(TxType.Legacy); - transactionForRpc.AccessList.Should().BeNull(); - } - - [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x1","chainId":"0x1","accessList":[]}""")] - [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x2","chainId":"0x1","accessList":[]}""")] - public void can_serialize_empty_accessList(TxType txType, string txJson) - { - AccessList.Builder builder = new(); - Transaction transaction = new() + [Test] + public void can_deserialize_null_accessList() { - Type = txType, - AccessList = builder.Build(), - }; - TransactionForRpc transactionForRpc = new(transaction); + _transactionForRpc = _serializer.Deserialize("{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x01\"}"); - string serialized = _serializer.Serialize(transactionForRpc); + _transactionForRpc.Type.Should().Be(TxType.AccessList); + _transactionForRpc.AccessList.Should().BeNull(); + } - JToken.Parse(serialized).Should().BeEquivalentTo(JToken.Parse(txJson)); - } - - [Test] - public void can_deserialize_empty_accessList() - { - string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x01","accessList":[]}"""; - - TransactionForRpc transactionForRpc = _serializer.Deserialize(json); - - transactionForRpc.Type.Should().Be(TxType.AccessList); - transactionForRpc.AccessList!.Should().BeEmpty(); - } - - [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x1","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}""")] - [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x2","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}""")] - public void can_serialize_accessList_with_empty_storageKeys(TxType txType, string txJson) - { - AccessList.Builder builder = new AccessList.Builder() - .AddAddress(TestItem.AddressA); - Transaction transaction = new() + [TestCase(TxType.AccessList, "{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x1\",\"accessList\":[]}")] + [TestCase(TxType.EIP1559, "{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"maxPriorityFeePerGas\":\"0x0\",\"maxFeePerGas\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x2\",\"accessList\":[]}")] + public void can_serialize_empty_accessList(TxType txType, string txJson) { - Type = txType, - AccessList = builder.Build(), - }; + _data = new Dictionary>(); + _transaction = new Transaction(); + _transaction.Type = txType; + _transaction.AccessList = new AccessList(_data); + _transactionForRpc = new TransactionForRpc(_transaction); + + string serialized = _serializer.Serialize(_transactionForRpc); + txJson.Should().Be(serialized); + } + + [Test] + public void can_deserialize_empty_accessList() + { + _transactionForRpc = _serializer.Deserialize("{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x01\",\"accessList\":[]}")!; - TransactionForRpc transactionForRpc = new(transaction); + _transactionForRpc.Type.Should().Be(TxType.AccessList); + _transactionForRpc.AccessList!.Length.Should().Be(0); + } - string serialized = _serializer.Serialize(transactionForRpc); + [TestCase(TxType.AccessList, "{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x1\",\"accessList\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"storageKeys\":[]}]}")] + [TestCase(TxType.EIP1559, "{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"maxPriorityFeePerGas\":\"0x0\",\"maxFeePerGas\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x2\",\"accessList\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"storageKeys\":[]}]}")] + public void can_serialize_accessList_with_empty_storageKeys(TxType txType, string txJson) + { + _data = new Dictionary>(); + _transaction = new Transaction(); + _transaction.Type = txType; - JToken.Parse(serialized).Should().BeEquivalentTo(JToken.Parse(txJson)); - } + _storageKeys = new HashSet { }; + _data.Add(TestItem.AddressA, _storageKeys); + _transaction.AccessList = new AccessList(_data); + _transactionForRpc = new TransactionForRpc(_transaction); - [Test] - public void can_deserialize_accessList_with_empty_storageKeys() - { - string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x01","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}"""; - object[] accessList = { new AccessListItemForRpc(TestItem.AddressA, new HashSet()) }; + string serialized = _serializer.Serialize(_transactionForRpc); + txJson.Should().Be(serialized); + } - TransactionForRpc transactionForRpc = _serializer.Deserialize(json); + [Test] + public void can_deserialize_accessList_with_empty_storageKeys() + { + _transactionForRpc = _serializer.Deserialize("{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x01\",\"accessList\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"storageKeys\":[]}]}"); - transactionForRpc.Type.Should().Be(TxType.AccessList); - transactionForRpc.AccessList.Should().BeEquivalentTo(accessList); - } + object[] accessList = { new AccessListItemForRpc(TestItem.AddressA, new HashSet { }) }; + _transactionForRpc.Type.Should().Be(TxType.AccessList); + _transactionForRpc.AccessList.Should().BeEquivalentTo(accessList); + } - [Test] - public void can_deserialize_accessList_with_null_storageKeys() - { - string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x01","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099"}]}"""; - object[] accessList = { new AccessListItemForRpc(TestItem.AddressA, null) }; - - TransactionForRpc transactionForRpc = _serializer.Deserialize(json); + [TestCase(TxType.AccessList, "{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x1\",\"accessList\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"storageKeys\":[]}]}")] + [TestCase(TxType.EIP1559, "{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"maxPriorityFeePerGas\":\"0x0\",\"maxFeePerGas\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x2\",\"accessList\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"storageKeys\":[]}]}")] + public void can_serialize_accessList_with_null_storageKeys(TxType txType, string txJson) + { + _data = new Dictionary>(); + _transaction = new Transaction(); + _transaction.Type = txType; - transactionForRpc.Type.Should().Be(TxType.AccessList); - transactionForRpc.AccessList.Should().BeEquivalentTo(accessList); - } + _data.Add(TestItem.AddressA, null); + _transaction.AccessList = new AccessList(_data); + _transactionForRpc = new TransactionForRpc(_transaction); - [Test] - public void can_deserialize_accessList_with_null_storageKeys_and_eip1559_txType() - { - string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","maxFeePerGas":"0x10","gas":"0x0","input":null,"type":"0x02","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099"}]}"""; - AccessListItemForRpc[] accessList = { new(TestItem.AddressA, null) }; + string serialized = _serializer.Serialize(_transactionForRpc); + txJson.Should().Be(serialized); + } - TransactionForRpc transactionForRpc = _serializer.Deserialize(json); + [Test] + public void can_deserialize_accessList_with_null_storageKeys() + { + _transactionForRpc = _serializer.Deserialize("{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x01\",\"accessList\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\"}]}"); - transactionForRpc.Type.Should().Be(TxType.EIP1559); - transactionForRpc.AccessList.Should().BeEquivalentTo(accessList); - } + object[] accessList = { new AccessListItemForRpc(TestItem.AddressA, null) }; + _transactionForRpc.Type.Should().Be(TxType.AccessList); + _transactionForRpc.AccessList.Length.Should().Be(1); + _transactionForRpc.AccessList.Should().BeEquivalentTo(accessList); + } - [Test] - public void can_deserialize_not_provided_txType() - { - string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null}"""; + [Test] + public void can_deserialize_accessList_with_null_storageKeys_and_eip1559_txType() + { + _transactionForRpc = _serializer.Deserialize("{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"maxFeePerGas\":\"0x10\",\"gas\":\"0x0\",\"input\":null,\"type\":\"0x02\",\"accessList\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\"}]}"); - TransactionForRpc transactionForRpc = _serializer.Deserialize(json); + object[] accessList = { new AccessListItemForRpc(TestItem.AddressA, null) }; + _transactionForRpc.Type.Should().Be(TxType.EIP1559); + _transactionForRpc.AccessList.Length.Should().Be(1); + _transactionForRpc.AccessList.Should().BeEquivalentTo(accessList); + } - // if there is not TxType provided, default value should be TxType.Legacy equal 0 - transactionForRpc.Type.Should().Be(0); - } + [Test] + public void can_deserialize_not_provided_txType() + { + _transactionForRpc = _serializer.Deserialize("{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"gas\":\"0x0\",\"input\":null}"); - [Test] - public void can_deserialize_direct_null_txType() - { - string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":null}"""; + // if there is not TxType provided, default value should be TxType.Legacy equal 0 + _transactionForRpc.Type.Should().Be(0); + } - TransactionForRpc transactionForRpc = _serializer.Deserialize(json); + [Test] + public void can_deserialize_direct_null_txType() + { + _transactionForRpc = _serializer.Deserialize("{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":null,\"value\":\"0x0\",\"gasPrice\":\"0x0\",\"gas\":\"0x0\",\"input\":null,\"type\":null}"); - // if there is null TxType provided, still default value should be TxType.Legacy equal 0 - transactionForRpc.Type.Should().Be(0); - } + // if there is null TxType provided, still default value should be TxType.Legacy equal 0 + _transactionForRpc.Type.Should().Be(0); + } - [TestCase(TxType.AccessList)] - [TestCase(TxType.EIP1559)] - public void can_convert_fromTransaction_toTransactionForRpc_and_back(TxType txType) - { - Transaction transaction = new() + [TestCase(TxType.AccessList)] + [TestCase(TxType.EIP1559)] + public void can_convert_from_Transaction_to_TransactionForRpc_and_back(TxType txType) { - Type = txType, - AccessList = GetTestAccessList(), - }; - TransactionForRpc transactionForRpc = new(transaction); + _transaction = new Transaction(); + _transaction.Type = txType; - Transaction afterConversion = transactionForRpc.ToTransaction(); + _transaction.AccessList = GetTestAccessList(); + _transactionForRpc = new TransactionForRpc(_transaction); + Transaction afterConversion = _transactionForRpc.ToTransaction(); - afterConversion.Should().BeEquivalentTo(transaction, option => option.ComparingByMembers().Excluding(tx => tx.Data)); - afterConversion.Data.AsArray().Should().BeEquivalentTo(transaction.Data.AsArray()); + afterConversion.Should().BeEquivalentTo(_transaction, option => option.ComparingByMembers().Excluding(tx => tx.Data)); + afterConversion.Data.AsArray().Should().BeEquivalentTo(_transaction.Data.AsArray()); + } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcLocalStats.cs b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcLocalStats.cs index e735a5fbe51..00e7b2089bf 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcLocalStats.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcLocalStats.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Threading.Tasks; using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Test; @@ -32,54 +31,54 @@ public void Setup() } [Test] - public async Task Success_average_is_fine() + public void Success_average_is_fine() { JsonRpcLocalStats localStats = new(_manualTimestamper, _config, _logManager); - await localStats.ReportCall("A", 100, true); - await localStats.ReportCall("A", 200, true); + localStats.ReportCall("A", 100, true); + localStats.ReportCall("A", 200, true); MakeTimePass(); - await localStats.ReportCall("A", 300, true); + localStats.ReportCall("A", 300, true); CheckLogLine("A|2|150|200|0|0|0|"); CheckLogLine("TOTAL|2|150|200|0|0|0|"); } [Test] - public async Task Single_average_is_fine() + public void Single_average_is_fine() { JsonRpcLocalStats localStats = new(_manualTimestamper, _config, _logManager); - await localStats.ReportCall("A", 100, true); + localStats.ReportCall("A", 100, true); MakeTimePass(); - await localStats.ReportCall("A", 300, true); + localStats.ReportCall("A", 300, true); CheckLogLine("A|1|100|100|0|0|0|"); CheckLogLine("TOTAL|1|100|100|0|0|0|"); } [Test] - public async Task Swaps_properly() + public void Swaps_properly() { JsonRpcLocalStats localStats = new(_manualTimestamper, _config, _logManager); - await localStats.ReportCall("A", 100, true); + localStats.ReportCall("A", 100, true); MakeTimePass(); - await localStats.ReportCall("A", 300, true); + localStats.ReportCall("A", 300, true); CheckLogLine("A|1|100|100|0|0|0|"); _testLogger.LogList.Clear(); MakeTimePass(); - await localStats.ReportCall("A", 500, true); + localStats.ReportCall("A", 500, true); CheckLogLine("A|1|300|300|0|0|0|"); _testLogger.LogList.Clear(); MakeTimePass(); - await localStats.ReportCall("A", 700, true); + localStats.ReportCall("A", 700, true); CheckLogLine("A|1|500|500|0|0|0|"); _testLogger.LogList.Clear(); } [Test] - public async Task Calls_do_not_delay_report() + public void Calls_do_not_delay_report() { JsonRpcLocalStats localStats = new(_manualTimestamper, _config, _logManager); for (int i = 0; i < 100; i++) { - await localStats.ReportCall("A", 300, true); + localStats.ReportCall("A", 300, true); MakeTimePass(60); } @@ -110,45 +109,45 @@ public void Does_not_report_when_nothing_to_report() } [Test] - public async Task Multiple_have_no_decimal_places() + public void Multiple_have_no_decimal_places() { JsonRpcLocalStats localStats = new(_manualTimestamper, _config, _logManager); - await localStats.ReportCall("A", 30, true); - await localStats.ReportCall("A", 20, true); - await localStats.ReportCall("A", 50, true); - await localStats.ReportCall("A", 60, false); - await localStats.ReportCall("A", 40, false); - await localStats.ReportCall("A", 100, false); + localStats.ReportCall("A", 30, true); + localStats.ReportCall("A", 20, true); + localStats.ReportCall("A", 50, true); + localStats.ReportCall("A", 60, false); + localStats.ReportCall("A", 40, false); + localStats.ReportCall("A", 100, false); MakeTimePass(); - await localStats.ReportCall("A", 300, true); + localStats.ReportCall("A", 300, true); CheckLogLine("A|3|33|50|3|67|100|"); CheckLogLine("TOTAL|3|33|50|3|67|100|"); } [Test] - public async Task Single_of_each_is_fine() + public void Single_of_each_is_fine() { JsonRpcLocalStats localStats = new(_manualTimestamper, _config, _logManager); - await localStats.ReportCall("A", 25, true); - await localStats.ReportCall("A", 125, false); - await localStats.ReportCall("B", 75, true); - await localStats.ReportCall("B", 175, false); + localStats.ReportCall("A", 25, true); + localStats.ReportCall("A", 125, false); + localStats.ReportCall("B", 75, true); + localStats.ReportCall("B", 175, false); MakeTimePass(); - await localStats.ReportCall("A", 300, true); + localStats.ReportCall("A", 300, true); CheckLogLine("A|1|25|25|1|125|125|"); CheckLogLine("B|1|75|75|1|175|175|"); CheckLogLine("TOTAL|2|50|75|2|150|175|"); } [Test] - public async Task Orders_alphabetically() + public void Orders_alphabetically() { JsonRpcLocalStats localStats = new(_manualTimestamper, _config, _logManager); - await localStats.ReportCall("C", 1, true); - await localStats.ReportCall("A", 2, true); - await localStats.ReportCall("B", 3, false); + localStats.ReportCall("C", 1, true); + localStats.ReportCall("A", 2, true); + localStats.ReportCall("B", 3, false); MakeTimePass(); - await localStats.ReportCall("A", 300, true); + localStats.ReportCall("A", 300, true); _testLogger.LogList[0].IndexOf("A ", StringComparison.InvariantCulture).Should().BeLessThan(_testLogger.LogList[0].IndexOf("B ", StringComparison.InvariantCulture)); _testLogger.LogList[0].IndexOf("B ", StringComparison.InvariantCulture).Should().BeLessThan(_testLogger.LogList[0].IndexOf("C ", StringComparison.InvariantCulture)); } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcProcessorTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcProcessorTests.cs index 4fe9d78469e..e1c4985decc 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcProcessorTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcProcessorTests.cs @@ -36,7 +36,8 @@ private JsonRpcProcessor Initialize(JsonRpcConfig? config = null) { IJsonRpcService service = Substitute.For(); service.SendRequestAsync(Arg.Any(), Arg.Any()).Returns(ci => _returnErrors ? new JsonRpcErrorResponse { Id = ci.Arg().Id } : new JsonRpcSuccessResponse { Id = ci.Arg().Id }); - service.GetErrorResponse(0, null!, null!, null!).ReturnsForAnyArgs(_errorResponse); + service.GetErrorResponse(0, null!).ReturnsForAnyArgs(_errorResponse); + service.GetErrorResponse(null!, 0, null!, null!).ReturnsForAnyArgs(_errorResponse); service.Converters.Returns(new JsonConverter[] { new AddressConverter() }); // just to test converter loader IFileSystem fileSystem = Substitute.For(); @@ -380,5 +381,14 @@ public async Task Can_handle_null_request() result[0].BatchedResponses.Should().BeNull(); result[0].Response.Should().BeSameAs(_errorResponse); } + + [Test] + public void Cannot_accept_null_file_system() + { + Assert.Throws(() => new JsonRpcProcessor(Substitute.For(), + Substitute.For(), + Substitute.For(), + null, LimboLogs.Instance)); + } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcServiceTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcServiceTests.cs index 652e10cdd81..96f44044049 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcServiceTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcServiceTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO.Abstractions; using System.Linq; +using System.Reflection; using FluentAssertions; using Nethermind.Blockchain.Find; using Nethermind.Config; @@ -34,6 +35,7 @@ public class JsonRpcServiceTests [SetUp] public void Initialize() { + Assembly jConfig = typeof(JsonRpcConfig).Assembly; _configurationProvider = new ConfigProvider(); _logManager = LimboLogs.Instance; _context = new JsonRpcContext(RpcEndpoint.Http); @@ -47,7 +49,7 @@ public void Initialize() private JsonRpcResponse TestRequest(T module, string method, params string[] parameters) where T : IRpcModule { RpcModuleProvider moduleProvider = new(new FileSystem(), _configurationProvider.GetConfig(), LimboLogs.Instance); - moduleProvider.Register(new SingletonModulePool(new SingletonFactory(module), allowExclusive: true)); + moduleProvider.Register(new SingletonModulePool(new SingletonFactory(module), true)); _jsonRpcService = new JsonRpcService(moduleProvider, _logManager, _configurationProvider.GetConfig()); JsonRpcRequest request = RpcTest.GetJsonRequest(method, parameters); JsonRpcResponse response = _jsonRpcService.SendRequestAsync(request, _context).Result; @@ -60,7 +62,7 @@ public void GetBlockByNumberTest() { IEthRpcModule ethRpcModule = Substitute.For(); ISpecProvider specProvider = Substitute.For(); - ethRpcModule.eth_getBlockByNumber(Arg.Any(), true).ReturnsForAnyArgs(_ => ResultWrapper.Success(new BlockForRpc(Build.A.Block.WithNumber(2).TestObject, true, specProvider))); + ethRpcModule.eth_getBlockByNumber(Arg.Any(), true).ReturnsForAnyArgs(x => ResultWrapper.Success(new BlockForRpc(Build.A.Block.WithNumber(2).TestObject, true, specProvider))); JsonRpcSuccessResponse? response = TestRequest(ethRpcModule, "eth_getBlockByNumber", "0x1b4", "true") as JsonRpcSuccessResponse; Assert.That((response?.Result as BlockForRpc)?.Number, Is.EqualTo(2L)); } @@ -70,7 +72,7 @@ public void Eth_module_populates_size_when_returning_block_data() { IEthRpcModule ethRpcModule = Substitute.For(); ISpecProvider specProvider = Substitute.For(); - ethRpcModule.eth_getBlockByNumber(Arg.Any(), true).ReturnsForAnyArgs(_ => ResultWrapper.Success(new BlockForRpc(Build.A.Block.WithNumber(2).TestObject, true, specProvider))); + ethRpcModule.eth_getBlockByNumber(Arg.Any(), true).ReturnsForAnyArgs(x => ResultWrapper.Success(new BlockForRpc(Build.A.Block.WithNumber(2).TestObject, true, specProvider))); JsonRpcSuccessResponse? response = TestRequest(ethRpcModule, "eth_getBlockByNumber", "0x1b4", "true") as JsonRpcSuccessResponse; Assert.That((response?.Result as BlockForRpc)?.Size, Is.EqualTo(513L)); } @@ -81,7 +83,7 @@ public void CanHandleOptionalArguments() EthereumJsonSerializer serializer = new(); string serialized = serializer.Serialize(new TransactionForRpc()); IEthRpcModule ethRpcModule = Substitute.For(); - ethRpcModule.eth_call(Arg.Any()).ReturnsForAnyArgs(_ => ResultWrapper.Success("0x1")); + ethRpcModule.eth_call(Arg.Any()).ReturnsForAnyArgs(x => ResultWrapper.Success("0x1")); JsonRpcSuccessResponse? response = TestRequest(ethRpcModule, "eth_call", serialized) as JsonRpcSuccessResponse; Assert.That(response?.Result, Is.EqualTo("0x1")); } @@ -99,7 +101,7 @@ public void Case_sensitivity_test() public void GetNewFilterTest() { IEthRpcModule ethRpcModule = Substitute.For(); - ethRpcModule.eth_newFilter(Arg.Any()).ReturnsForAnyArgs(_ => ResultWrapper.Success(1)); + ethRpcModule.eth_newFilter(Arg.Any()).ReturnsForAnyArgs(x => ResultWrapper.Success(1)); var parameters = new { @@ -126,7 +128,7 @@ public void Eth_call_is_working_with_implicit_null_as_the_last_argument() { EthereumJsonSerializer serializer = new(); IEthRpcModule ethRpcModule = Substitute.For(); - ethRpcModule.eth_call(Arg.Any(), Arg.Any()).ReturnsForAnyArgs(_ => ResultWrapper.Success("0x")); + ethRpcModule.eth_call(Arg.Any(), Arg.Any()).ReturnsForAnyArgs(x => ResultWrapper.Success("0x")); string serialized = serializer.Serialize(new TransactionForRpc()); @@ -140,7 +142,7 @@ public void Eth_call_is_working_with_explicit_null_as_the_last_argument(string n { EthereumJsonSerializer serializer = new(); IEthRpcModule ethRpcModule = Substitute.For(); - ethRpcModule.eth_call(Arg.Any(), Arg.Any()).ReturnsForAnyArgs(_ => ResultWrapper.Success("0x")); + ethRpcModule.eth_call(Arg.Any(), Arg.Any()).ReturnsForAnyArgs(x => ResultWrapper.Success("0x")); string serialized = serializer.Serialize(new TransactionForRpc()); @@ -149,21 +151,14 @@ public void Eth_call_is_working_with_explicit_null_as_the_last_argument(string n } [Test] - public void Eth_getTransactionReceipt_properly_fails_given_wrong_parameters() + public void GetWorkTest() { IEthRpcModule ethRpcModule = Substitute.For(); - - string[] parameters = { - """["0x80757153e93d1b475e203406727b62a501187f63e23b8fa999279e219ee3be71"]""" - }; - JsonRpcResponse response = TestRequest(ethRpcModule, "eth_getTransactionReceipt", parameters); - - response.Should() - .BeAssignableTo() - .Which - .Error.Should().NotBeNull(); - Error error = (response as JsonRpcErrorResponse)!.Error!; - error.Code.Should().Be(ErrorCodes.InvalidParams); + ethRpcModule.eth_getWork().ReturnsForAnyArgs(x => ResultWrapper>.Success(new[] { Bytes.FromHexString("aa"), Bytes.FromHexString("01") })); + JsonRpcSuccessResponse? response = TestRequest(ethRpcModule, "eth_getWork") as JsonRpcSuccessResponse; + byte[][]? dataList = response?.Result as byte[][]; + Assert.NotNull(dataList?.SingleOrDefault(d => d.ToHexString(true) == "0xaa")); + Assert.NotNull(dataList?.SingleOrDefault(d => d.ToHexString(true) == "0x01")); } [Test] @@ -177,7 +172,7 @@ public void IncorrectMethodNameTest() public void NetVersionTest() { INetRpcModule netRpcModule = Substitute.For(); - netRpcModule.net_version().ReturnsForAnyArgs(_ => ResultWrapper.Success("1")); + netRpcModule.net_version().ReturnsForAnyArgs(x => ResultWrapper.Success("1")); JsonRpcSuccessResponse? response = TestRequest(netRpcModule, "net_version") as JsonRpcSuccessResponse; Assert.That(response?.Result, Is.EqualTo("1")); Assert.IsNotInstanceOf(response); @@ -187,7 +182,7 @@ public void NetVersionTest() public void Web3ShaTest() { IWeb3RpcModule web3RpcModule = Substitute.For(); - web3RpcModule.web3_sha3(Arg.Any()).ReturnsForAnyArgs(_ => ResultWrapper.Success(TestItem.KeccakA)); + web3RpcModule.web3_sha3(Arg.Any()).ReturnsForAnyArgs(x => ResultWrapper.Success(TestItem.KeccakA)); JsonRpcSuccessResponse? response = TestRequest(web3RpcModule, "web3_sha3", "0x68656c6c6f20776f726c64") as JsonRpcSuccessResponse; Assert.That(response?.Result, Is.EqualTo(TestItem.KeccakA)); } @@ -195,13 +190,13 @@ public void Web3ShaTest() [TestCaseSource(nameof(BlockForRpcTestSource))] public void BlockForRpc_should_expose_withdrawals_if_any((bool Expected, Block Block) item) { - ISpecProvider? specProvider = Substitute.For(); - BlockForRpc rpcBlock = new(item.Block, false, specProvider); + var specProvider = Substitute.For(); + var rpcBlock = new BlockForRpc(item.Block, false, specProvider); rpcBlock.WithdrawalsRoot.Should().BeEquivalentTo(item.Block.WithdrawalsRoot); rpcBlock.Withdrawals.Should().BeEquivalentTo(item.Block.Withdrawals); - string? json = new EthereumJsonSerializer().Serialize(rpcBlock); + var json = new EthereumJsonSerializer().Serialize(rpcBlock); json.Contains("withdrawals\"", StringComparison.Ordinal).Should().Be(item.Expected); json.Contains("withdrawalsRoot", StringComparison.Ordinal).Should().Be(item.Expected); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs deleted file mode 100644 index 8fe59998d75..00000000000 --- a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs +++ /dev/null @@ -1,444 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Sockets; -using System.Net.WebSockets; -using System.Threading; -using System.Threading.Tasks; -using Nethermind.Evm.Tracing.GethStyle; -using Nethermind.JsonRpc.Modules; -using Nethermind.JsonRpc.Modules.DebugModule; -using Nethermind.JsonRpc.WebSockets; -using Nethermind.Logging; -using Nethermind.Serialization.Json; -using Nethermind.Sockets; -using NUnit.Framework; - -namespace Nethermind.JsonRpc.Test; - -[TestFixture] -public class JsonRpcSocketsClientTests -{ - public class UsingIpc - { - [Test] - [Explicit("Takes too long to run")] - public async Task Can_handle_very_large_objects() - { - IPEndPoint ipEndPoint = IPEndPoint.Parse("127.0.0.1:1337"); - - Task receiveBytes = OneShotServer( - ipEndPoint, - CountNumberOfBytes - ); - - JsonRpcSuccessResponse bigObject = RandomSuccessResponse(200_000); - Task sendJsonRpcResult = Task.Run(async () => - { - using Socket socket = new(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); - await socket.ConnectAsync(ipEndPoint); - - ISocketHandler handler = new IpcSocketsHandler(socket); - JsonRpcSocketsClient client = new( - clientName: "TestClient", - handler: handler, - endpointType: RpcEndpoint.IPC, - jsonRpcProcessor: null!, - jsonRpcService: null!, - jsonRpcLocalStats: new NullJsonRpcLocalStats(), - jsonSerializer: new EthereumJsonSerializer(converters: new GethLikeTxTraceConverter()) - ); - JsonRpcResult result = JsonRpcResult.Single(bigObject, default); - - return await client.SendJsonRpcResult(result); - }); - - await Task.WhenAll(sendJsonRpcResult, receiveBytes); - int sent = sendJsonRpcResult.Result; - int received = receiveBytes.Result; - Assert.That(sent, Is.EqualTo(received)); - } - - [Test] - [TestCase(2)] - [TestCase(10)] - [TestCase(50)] - public async Task Can_send_multiple_messages(int messageCount) - { - IPEndPoint ipEndPoint = IPEndPoint.Parse("127.0.0.1:1337"); - - Task receiveBytes = OneShotServer( - ipEndPoint, - CountNumberOfBytes - ); - - Task sendJsonRpcResult = Task.Run(async () => - { - using Socket socket = new(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); - await socket.ConnectAsync(ipEndPoint); - - ISocketHandler handler = new IpcSocketsHandler(socket); - JsonRpcSocketsClient client = new( - clientName: "TestClient", - handler: handler, - endpointType: RpcEndpoint.IPC, - jsonRpcProcessor: null!, - jsonRpcService: null!, - jsonRpcLocalStats: new NullJsonRpcLocalStats(), - jsonSerializer: new EthereumJsonSerializer(converters: new GethLikeTxTraceConverter()) - ); - JsonRpcResult result = JsonRpcResult.Single(RandomSuccessResponse(1_000), default); - - int totalBytesSent = 0; - for (int i = 0; i < messageCount; i++) - { - totalBytesSent += await client.SendJsonRpcResult(result); - } - - return totalBytesSent; - }); - - await Task.WhenAll(sendJsonRpcResult, receiveBytes); - int sent = sendJsonRpcResult.Result; - int received = receiveBytes.Result; - Assert.That(sent, Is.EqualTo(received)); - } - - [TestCase(2)] - [TestCase(10)] - [TestCase(50)] - public async Task Can_send_collections(int elements) - { - IPEndPoint ipEndPoint = IPEndPoint.Parse("127.0.0.1:1337"); - - Task receiveBytes = OneShotServer( - ipEndPoint, - CountNumberOfBytes - ); - - Task sendCollection = Task.Run(async () => - { - using Socket socket = new(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); - await socket.ConnectAsync(ipEndPoint); - - ISocketHandler handler = new IpcSocketsHandler(socket); - JsonRpcSocketsClient client = new( - clientName: "TestClient", - handler: handler, - endpointType: RpcEndpoint.IPC, - jsonRpcProcessor: null!, - jsonRpcService: null!, - jsonRpcLocalStats: new NullJsonRpcLocalStats(), - jsonSerializer: new EthereumJsonSerializer(converters: new GethLikeTxTraceConverter()) - ); - JsonRpcResult result = JsonRpcResult.Collection(RandomBatchResult(10, 100)); - - return await client.SendJsonRpcResult(result); - }); - - await Task.WhenAll(sendCollection, receiveBytes); - int sent = sendCollection.Result; - int received = receiveBytes.Result; - Assert.That(sent, Is.EqualTo(received)); - } - - private static async Task OneShotServer(IPEndPoint ipEndPoint, Func> func) - { - using Socket socket = new(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); - socket.Bind(ipEndPoint); - socket.Listen(); - - Socket handler = await socket.AcceptAsync(); - - return await func(handler); - } - - private static async Task CountNumberOfBytes(Socket socket) - { - byte[] buffer = new byte[1024]; - int totalRead = 0; - - int read; - while ((read = await socket.ReceiveAsync(buffer)) != 0) - { - totalRead += read; - } - return totalRead; - } - } - - [Explicit] - public class UsingWebSockets - { - [Test] - [TestCase(2)] - [TestCase(10)] - [TestCase(50)] - public async Task Can_send_multiple_messages(int messageCount) - { - CancellationTokenSource cts = new(); - - Task receiveMessages = OneShotServer( - "http://localhost:1337/", - async webSocket => await CountNumberOfMessages(webSocket, cts.Token) - ); - - Task sendMessages = Task.Run(async () => - { - using ClientWebSocket socket = new(); - await socket.ConnectAsync(new Uri("ws://localhost:1337/"), CancellationToken.None); - - using ISocketHandler handler = new WebSocketHandler(socket, NullLogManager.Instance); - using JsonRpcSocketsClient client = new( - clientName: "TestClient", - handler: handler, - endpointType: RpcEndpoint.Ws, - jsonRpcProcessor: null!, - jsonRpcService: null!, - jsonRpcLocalStats: new NullJsonRpcLocalStats(), - jsonSerializer: new EthereumJsonSerializer() - ); - JsonRpcResult result = JsonRpcResult.Single(RandomSuccessResponse(1_000), default); - - for (int i = 0; i < messageCount; i++) - { - await client.SendJsonRpcResult(result); - await Task.Delay(100); - } - cts.Cancel(); - - return messageCount; - }); - - await Task.WhenAll(sendMessages, receiveMessages); - int sent = sendMessages.Result; - int received = receiveMessages.Result; - Assert.That(sent, Is.EqualTo(received)); - } - - [TestCase(2)] - [TestCase(10)] - [TestCase(50)] - public async Task Can_send_collections(int elements) - { - CancellationTokenSource cts = new(); - - Task server = OneShotServer( - "http://localhost:1337/", - async webSocket => await CountNumberOfMessages(webSocket, cts.Token) - ); - - Task sendCollection = Task.Run(async () => - { - using ClientWebSocket socket = new(); - await socket.ConnectAsync(new Uri("ws://localhost:1337/"), CancellationToken.None); - - using ISocketHandler handler = new WebSocketHandler(socket, NullLogManager.Instance); - using JsonRpcSocketsClient client = new( - clientName: "TestClient", - handler: handler, - endpointType: RpcEndpoint.Ws, - jsonRpcProcessor: null!, - jsonRpcService: null!, - jsonRpcLocalStats: new NullJsonRpcLocalStats(), - jsonSerializer: new EthereumJsonSerializer() - ); - JsonRpcResult result = JsonRpcResult.Collection(RandomBatchResult(10, 100)); - - await client.SendJsonRpcResult(result); - - await Task.Delay(100); - cts.Cancel(); - }); - - await Task.WhenAll(sendCollection, server); - Assert.That(server.Result, Is.EqualTo(1)); - } - - [TestCase(1_000)] - [TestCase(5_000)] - [TestCase(10_000)] - [Ignore("Feature does not work correctly")] - public async Task Stops_on_limited_body_size(int maxByteCount) - { - CancellationTokenSource cts = new(); - - Task receiveBytes = OneShotServer( - "http://localhost:1337/", - async webSocket => await CountNumberOfBytes(webSocket, cts.Token) - ); - - Task sendCollection = Task.Run(async () => - { - using ClientWebSocket socket = new(); - await socket.ConnectAsync(new Uri("ws://localhost:1337/"), CancellationToken.None); - - using ISocketHandler handler = new WebSocketHandler(socket, NullLogManager.Instance); - using JsonRpcSocketsClient client = new( - clientName: "TestClient", - handler: handler, - endpointType: RpcEndpoint.Ws, - jsonRpcProcessor: null!, - jsonRpcService: null!, - jsonRpcLocalStats: new NullJsonRpcLocalStats(), - jsonSerializer: new EthereumJsonSerializer(), - maxBatchResponseBodySize: maxByteCount - ); - JsonRpcResult result = JsonRpcResult.Collection(RandomBatchResult(10, 100)); - - int sent = await client.SendJsonRpcResult(result); - - await Task.Delay(100); - cts.Cancel(); - - return sent; - }); - - await Task.WhenAll(sendCollection, receiveBytes); - int sent = sendCollection.Result; - long received = receiveBytes.Result; - Assert.That(received, Is.LessThanOrEqualTo(Math.Min(sent, maxByteCount))); - } - - private static async Task OneShotServer(string uri, Func> func) - { - using HttpListener httpListener = new(); - httpListener.Prefixes.Add(uri); - httpListener.Start(); - - HttpListenerContext context = await httpListener.GetContextAsync(); - HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(null); - return await func(webSocketContext.WebSocket); - } - - private static async Task CountNumberOfMessages(WebSocket webSocket, CancellationToken token) - { - int messages = 0; - try - { - byte[] buffer = new byte[1024]; - - while (webSocket.State == WebSocketState.Open) - { - WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment(buffer), token); - if (result.EndOfMessage) - { - messages++; - } - } - } - catch (OperationCanceledException) { } - finally - { - if (webSocket.State == WebSocketState.Open) - { - await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, token); - } - webSocket.Dispose(); - } - - return messages; - } - - private static async Task CountNumberOfBytes(WebSocket webSocket, CancellationToken token) - { - long bytes = 0; - try - { - byte[] buffer = new byte[1024]; - - while (webSocket.State == WebSocketState.Open) - { - WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment(buffer), token); - bytes += result.Count; - } - } - catch (OperationCanceledException) { } - finally - { - if (webSocket.State == WebSocketState.Open) - { - await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, token); - } - webSocket.Dispose(); - } - - return bytes; - } - } - - private static JsonRpcBatchResult RandomBatchResult(int items, int size) - { - return new JsonRpcBatchResult((_, token) => - RandomAsyncEnumerable( - items, - () => Task.FromResult(new JsonRpcResult.Entry(RandomSuccessResponse(size), default)) - ).GetAsyncEnumerator(token) - ); - } - - private static JsonRpcSuccessResponse RandomSuccessResponse(int size) - { - return new JsonRpcSuccessResponse - { - MethodName = "mock", - Id = "42", - Result = RandomObject(size) - }; - } - - private static async IAsyncEnumerable RandomAsyncEnumerable(int items, Func> factory) - { - for (int i = 0; i < items; i++) - { - T value = await factory(); - yield return value; - } - } - - private static object RandomObject(int size) - { - string[] strings = RandomStringArray(size / 2); - object obj = new GethLikeTxTrace() - { - Entries = - { - new GethTxTraceEntry - { - Stack = strings, Memory = strings, - } - } - }; - return obj; - } - - private static string[] RandomStringArray(int length, bool runGc = true) - { - string[] array = new string[length]; - for (int i = 0; i < length; i++) - { - array[i] = RandomString(length); - if (runGc && i % 100 == 0) - { - GC.Collect(); - } - } - return array; - } - - private static string RandomString(int length) - { - const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - char[] stringChars = new char[length]; - Random random = new(); - - for (int i = 0; i < stringChars.Length; i++) - { - stringChars[i] = chars[random.Next(chars.Length)]; - } - return new string(stringChars); - } -} diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs index 7b114498289..11b2efc267b 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Concurrent; +using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using FluentAssertions; using Nethermind.Blockchain; using Nethermind.Blockchain.FullPruning; @@ -59,9 +59,9 @@ public void Setup() } [Test] - public async Task Test_node_info() + public void Test_node_info() { - string serialized = await RpcTest.TestSerializedRequest(_adminRpcModule, "admin_nodeInfo"); + string serialized = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_nodeInfo"); JsonRpcSuccessResponse response = _serializer.Deserialize(serialized); JsonSerializerSettings settings = new(); settings.Converters = EthereumJsonSerializer.CommonConverters.ToList(); @@ -83,26 +83,26 @@ public async Task Test_node_info() } [Test] - public async Task Test_data_dir() + public void Test_data_dir() { - string serialized = await RpcTest.TestSerializedRequest(_adminRpcModule, "admin_dataDir"); + string serialized = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_dataDir"); JsonRpcSuccessResponse response = _serializer.Deserialize(serialized); response.Result.Should().Be(_exampleDataDir); } [Test] - public async Task Smoke_solc() + public void Smoke_solc() { - string unused = await RpcTest.TestSerializedRequest(_adminRpcModule, "admin_setSolc"); + string unused = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_setSolc"); } [Test] - public async Task Smoke_test_peers() + public void Smoke_test_peers() { - string unused0 = await RpcTest.TestSerializedRequest(_adminRpcModule, "admin_addPeer", _enodeString); - string unused1 = await RpcTest.TestSerializedRequest(_adminRpcModule, "admin_removePeer", _enodeString); - string unused2 = await RpcTest.TestSerializedRequest(_adminRpcModule, "admin_addPeer", _enodeString, "true"); - string unused3 = await RpcTest.TestSerializedRequest(_adminRpcModule, "admin_removePeer", _enodeString, "true"); - string unused4 = await RpcTest.TestSerializedRequest(_adminRpcModule, "admin_peers"); + string unused0 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_addPeer", _enodeString); + string unused1 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_removePeer", _enodeString); + string unused2 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_addPeer", _enodeString, "true"); + string unused3 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_removePeer", _enodeString, "true"); + string unused4 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_peers"); } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/BoundedModulePoolTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/BoundedModulePoolTests.cs index 4cb4e61e2f6..40deff056b5 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/BoundedModulePoolTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/BoundedModulePoolTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Threading.Tasks; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; @@ -14,7 +15,7 @@ using Nethermind.Db.Blooms; using Nethermind.Facade; using Nethermind.Facade.Eth; -using Nethermind.JsonRpc.Exceptions; +using Nethermind.JsonRpc.Modules.Eth.FeeHistory; using Nethermind.JsonRpc.Modules.Eth.GasPrice; using Nethermind.State; using Nethermind.TxPool; @@ -23,131 +24,132 @@ using NUnit.Framework; using BlockTree = Nethermind.Blockchain.BlockTree; -namespace Nethermind.JsonRpc.Test.Modules; - -[Parallelizable(ParallelScope.Self)] -[TestFixture] -public class BoundedModulePoolTests +namespace Nethermind.JsonRpc.Test.Modules { - private BoundedModulePool _modulePool = null!; - - [SetUp] - public async Task Initialize() - { - ISpecProvider specProvider = MainnetSpecProvider.Instance; - ITxPool txPool = NullTxPool.Instance; - IDbProvider dbProvider = await TestMemDbProvider.InitAsync(); - - BlockTree blockTree = new( - dbProvider, - new ChainLevelInfoRepository(dbProvider.BlockInfosDb), - specProvider, - new BloomStorage(new BloomConfig(), dbProvider.HeadersDb, new InMemoryDictionaryFileStoreFactory()), - new SyncConfig(), - LimboLogs.Instance); - - _modulePool = new BoundedModulePool(new EthModuleFactory( - txPool, - Substitute.For(), - NullWallet.Instance, - blockTree, - new JsonRpcConfig(), - LimboLogs.Instance, - Substitute.For(), - Substitute.For(), - Substitute.For(), - Substitute.For(), - Substitute.For(), - Substitute.For()), - 1, 1000); - } - - [Test] - public async Task Ensure_concurrency() + [Parallelizable(ParallelScope.Self)] + [TestFixture] + public class BoundedModulePoolTests { - await _modulePool.GetModule(false); - } + private BoundedModulePool _modulePool = null!; - [Test] - public async Task Ensure_limited_exclusive() - { - await _modulePool.GetModule(false); - Assert.ThrowsAsync(() => _modulePool.GetModule(false)); - } - - [Test] - public async Task Ensure_returning_shared_does_not_change_concurrency() - { - IEthRpcModule shared = await _modulePool.GetModule(true); - _modulePool.ReturnModule(shared); - await _modulePool.GetModule(false); - Assert.ThrowsAsync(() => _modulePool.GetModule(false)); - } + [SetUp] + public async Task Initialize() + { + ISpecProvider specProvider = MainnetSpecProvider.Instance; + ITxPool txPool = NullTxPool.Instance; + IDbProvider dbProvider = await TestMemDbProvider.InitAsync(); + + BlockTree blockTree = new( + dbProvider, + new ChainLevelInfoRepository(dbProvider.BlockInfosDb), + specProvider, + new BloomStorage(new BloomConfig(), dbProvider.HeadersDb, new InMemoryDictionaryFileStoreFactory()), + new SyncConfig(), + LimboLogs.Instance); + + _modulePool = new BoundedModulePool(new EthModuleFactory( + txPool, + Substitute.For(), + NullWallet.Instance, + blockTree, + new JsonRpcConfig(), + LimboLogs.Instance, + Substitute.For(), + Substitute.For(), + Substitute.For(), + Substitute.For(), + Substitute.For(), + Substitute.For()), + 1, 1000); + } - [Test] - public async Task Ensure_unlimited_shared() - { - for (int i = 0; i < 1000; i++) + [Test] + public async Task Ensure_concurrency() { - await _modulePool.GetModule(true); + await _modulePool.GetModule(false); } - } - [Test] - public async Task Ensure_that_shared_is_never_returned_as_exclusive() - { - IEthRpcModule sharedRpcModule = await _modulePool.GetModule(true); - _modulePool.ReturnModule(sharedRpcModule); + [Test] + public async Task Ensure_limited_exclusive() + { + await _modulePool.GetModule(false); + Assert.ThrowsAsync(() => _modulePool.GetModule(false)); + } - const int iterations = 1000; - async Task rentReturnShared() + [Test] + public async Task Ensure_returning_shared_does_not_change_concurrency() { - for (int i = 0; i < iterations; i++) - { - // TestContext.Out.WriteLine($"Rent shared {i}"); - IEthRpcModule ethRpcModule = await _modulePool.GetModule(true); - Assert.That(ethRpcModule, Is.SameAs(sharedRpcModule)); - _modulePool.ReturnModule(ethRpcModule); - // TestContext.Out.WriteLine($"Return shared {i}"); - } + IEthRpcModule shared = await _modulePool.GetModule(true); + _modulePool.ReturnModule(shared); + await _modulePool.GetModule(false); + Assert.ThrowsAsync(() => _modulePool.GetModule(false)); } - async Task rentReturnExclusive() + [Test] + public async Task Ensure_unlimited_shared() { - for (int i = 0; i < iterations; i++) + for (int i = 0; i < 1000; i++) { - // TestContext.Out.WriteLine($"Rent exclusive {i}"); - IEthRpcModule ethRpcModule = await _modulePool.GetModule(false); - Assert.That(ethRpcModule, Is.Not.SameAs(sharedRpcModule)); - _modulePool.ReturnModule(ethRpcModule); - // TestContext.Out.WriteLine($"Return exclusive {i}"); + await _modulePool.GetModule(true); } } - Task a = Task.Run(rentReturnExclusive); - Task b = Task.Run(rentReturnExclusive); - Task c = Task.Run(rentReturnShared); - Task d = Task.Run(rentReturnShared); - - await Task.WhenAll(a, b, c, d); - } + [Test] + public async Task Ensure_that_shared_is_never_returned_as_exclusive() + { + IEthRpcModule sharedRpcModule = await _modulePool.GetModule(true); + _modulePool.ReturnModule(sharedRpcModule); - [TestCase(true)] - [TestCase(false)] - public async Task Can_rent_and_return(bool canBeShared) - { - IEthRpcModule ethRpcModule = await _modulePool.GetModule(canBeShared); - _modulePool.ReturnModule(ethRpcModule); - } + const int iterations = 1000; + Func rentReturnShared = async () => + { + for (int i = 0; i < iterations; i++) + { + TestContext.Out.WriteLine($"Rent shared {i}"); + IEthRpcModule ethRpcModule = await _modulePool.GetModule(true); + Assert.That(ethRpcModule, Is.SameAs(sharedRpcModule)); + _modulePool.ReturnModule(ethRpcModule); + TestContext.Out.WriteLine($"Return shared {i}"); + } + }; + + Func rentReturnExclusive = async () => + { + for (int i = 0; i < iterations; i++) + { + TestContext.Out.WriteLine($"Rent exclusive {i}"); + IEthRpcModule ethRpcModule = await _modulePool.GetModule(false); + Assert.That(ethRpcModule, Is.Not.SameAs(sharedRpcModule)); + _modulePool.ReturnModule(ethRpcModule); + TestContext.Out.WriteLine($"Return exclusive {i}"); + } + }; + + Task a = Task.Run(rentReturnExclusive); + Task b = Task.Run(rentReturnExclusive); + Task c = Task.Run(rentReturnShared); + Task d = Task.Run(rentReturnShared); + + await Task.WhenAll(a, b, c, d); + } - [TestCase(true)] - [TestCase(false)] - public async Task Can_rent_and_return_in_a_loop(bool canBeShared) - { - for (int i = 0; i < 1000; i++) + [TestCase(true)] + [TestCase(false)] + public async Task Can_rent_and_return(bool canBeShared) { IEthRpcModule ethRpcModule = await _modulePool.GetModule(canBeShared); _modulePool.ReturnModule(ethRpcModule); } + + [TestCase(true)] + [TestCase(false)] + public async Task Can_rent_and_return_in_a_loop(bool canBeShared) + { + for (int i = 0; i < 1000; i++) + { + IEthRpcModule ethRpcModule = await _modulePool.GetModule(canBeShared); + _modulePool.ReturnModule(ethRpcModule); + } + } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs index 6fe24479469..ceb7fb1207e 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs @@ -1,11 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using System.Collections.Generic; using System.Linq; using System.Threading; -using System.Threading.Tasks; using FluentAssertions; using Nethermind.Blockchain.Find; using Nethermind.Config; @@ -21,436 +19,418 @@ using NSubstitute; using NUnit.Framework; -namespace Nethermind.JsonRpc.Test.Modules; - -[Parallelizable(ParallelScope.Self)] -[TestFixture] -public class DebugModuleTests +namespace Nethermind.JsonRpc.Test.Modules { - private IJsonRpcConfig jsonRpcConfig = new JsonRpcConfig(); - private IDebugBridge debugBridge = Substitute.For(); - - [Test] - public void Get_from_db() + [Parallelizable(ParallelScope.Self)] + [TestFixture] + public class DebugModuleTests { - byte[] key = new byte[] { 1, 2, 3 }; - byte[] value = new byte[] { 4, 5, 6 }; - debugBridge.GetDbValue(Arg.Any(), Arg.Any()).Returns(value); + private IJsonRpcConfig jsonRpcConfig = new JsonRpcConfig(); + private IDebugBridge debugBridge = Substitute.For(); - IConfigProvider configProvider = Substitute.For(); - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); - JsonRpcSuccessResponse? response = - RpcTest.TestRequest(rpcModule, "debug_getFromDb", "STATE", key.ToHexString(true)) as - JsonRpcSuccessResponse; - - byte[]? result = response?.Result as byte[]; - } + [Test] + public void Get_from_db() + { + byte[] key = new byte[] { 1, 2, 3 }; + byte[] value = new byte[] { 4, 5, 6 }; + debugBridge.GetDbValue(Arg.Any(), Arg.Any()).Returns(value); - [Test] - public void Get_from_db_null_value() - { - byte[] key = new byte[] { 1, 2, 3 }; - debugBridge.GetDbValue(Arg.Any(), Arg.Any()).Returns((byte[])null!); + IConfigProvider configProvider = Substitute.For(); + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); + JsonRpcSuccessResponse? response = + RpcTest.TestRequest(rpcModule, "debug_getFromDb", "STATE", key.ToHexString(true)) as + JsonRpcSuccessResponse; - IConfigProvider configProvider = Substitute.For(); - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); - JsonRpcSuccessResponse? response = - RpcTest.TestRequest(rpcModule, "debug_getFromDb", "STATE", key.ToHexString(true)) as - JsonRpcSuccessResponse; + byte[]? result = response?.Result as byte[]; + } - Assert.NotNull(response); - } + [Test] + public void Get_from_db_null_value() + { + byte[] key = new byte[] { 1, 2, 3 }; + debugBridge.GetDbValue(Arg.Any(), Arg.Any()).Returns((byte[])null!); - [TestCase("1")] - [TestCase("0x1")] - public void Get_chain_level(string parameter) - { - debugBridge.GetLevelInfo(1).Returns( - new ChainLevelInfo( - true, - new[] - { - new BlockInfo(TestItem.KeccakA, 1000), - new BlockInfo(TestItem.KeccakB, 1001), - })); - - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); - JsonRpcSuccessResponse? response = RpcTest.TestRequest(rpcModule, "debug_getChainLevel", parameter) as JsonRpcSuccessResponse; - ChainLevelForRpc? chainLevel = response?.Result as ChainLevelForRpc; - Assert.NotNull(chainLevel); - Assert.That(chainLevel?.HasBlockOnMainChain, Is.EqualTo(true)); - Assert.That(chainLevel?.BlockInfos.Length, Is.EqualTo(2)); - } + IConfigProvider configProvider = Substitute.For(); + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); + JsonRpcSuccessResponse? response = + RpcTest.TestRequest(rpcModule, "debug_getFromDb", "STATE", key.ToHexString(true)) as + JsonRpcSuccessResponse; - [Test] - public void Get_block_rlp_by_hash() - { - BlockDecoder decoder = new(); - Rlp rlp = decoder.Encode(Build.A.Block.WithNumber(1).TestObject); - debugBridge.GetBlockRlp(Keccak.Zero).Returns(rlp.Bytes); + Assert.NotNull(response); + } - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); - JsonRpcSuccessResponse? response = RpcTest.TestRequest(rpcModule, "debug_getBlockRlpByHash", $"{Keccak.Zero.Bytes.ToHexString()}") as JsonRpcSuccessResponse; - Assert.That((byte[]?)response?.Result, Is.EqualTo(rlp.Bytes)); - } + [TestCase("1")] + [TestCase("0x1")] + public void Get_chain_level(string parameter) + { + debugBridge.GetLevelInfo(1).Returns( + new ChainLevelInfo( + true, + new[] + { + new BlockInfo(TestItem.KeccakA, 1000), + new BlockInfo(TestItem.KeccakB, 1001), + })); + + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); + JsonRpcSuccessResponse? response = RpcTest.TestRequest(rpcModule, "debug_getChainLevel", parameter) as JsonRpcSuccessResponse; + ChainLevelForRpc? chainLevel = response?.Result as ChainLevelForRpc; + Assert.NotNull(chainLevel); + Assert.That(chainLevel?.HasBlockOnMainChain, Is.EqualTo(true)); + Assert.That(chainLevel?.BlockInfos.Length, Is.EqualTo(2)); + } + + [Test] + public void Get_block_rlp_by_hash() + { + BlockDecoder decoder = new(); + Rlp rlp = decoder.Encode(Build.A.Block.WithNumber(1).TestObject); + debugBridge.GetBlockRlp(Keccak.Zero).Returns(rlp.Bytes); - [Test] - public void Get_block_rlp() - { - BlockDecoder decoder = new(); - IDebugBridge debugBridge = Substitute.For(); - Rlp rlp = decoder.Encode(Build.A.Block.WithNumber(1).TestObject); - debugBridge.GetBlockRlp(1).Returns(rlp.Bytes); + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); + JsonRpcSuccessResponse? response = RpcTest.TestRequest(rpcModule, "debug_getBlockRlpByHash", $"{Keccak.Zero.Bytes.ToHexString()}") as JsonRpcSuccessResponse; + Assert.That((byte[]?)response?.Result, Is.EqualTo(rlp.Bytes)); + } - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); - JsonRpcSuccessResponse? response = RpcTest.TestRequest(rpcModule, "debug_getBlockRlp", "1") as JsonRpcSuccessResponse; + [Test] + public void Get_block_rlp() + { + BlockDecoder decoder = new(); + IDebugBridge debugBridge = Substitute.For(); + Rlp rlp = decoder.Encode(Build.A.Block.WithNumber(1).TestObject); + debugBridge.GetBlockRlp(1).Returns(rlp.Bytes); - Assert.That((byte[]?)response?.Result, Is.EqualTo(rlp.Bytes)); - } + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); + JsonRpcSuccessResponse? response = RpcTest.TestRequest(rpcModule, "debug_getBlockRlp", "1") as JsonRpcSuccessResponse; - [Test] - public void Get_block_rlp_when_missing() - { - debugBridge.GetBlockRlp(1).Returns((byte[])null!); + Assert.That((byte[]?)response?.Result, Is.EqualTo(rlp.Bytes)); + } - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); - JsonRpcErrorResponse? response = RpcTest.TestRequest(rpcModule, "debug_getBlockRlp", "1") as JsonRpcErrorResponse; + [Test] + public void Get_block_rlp_when_missing() + { + debugBridge.GetBlockRlp(1).Returns((byte[])null!); - Assert.That(response?.Error?.Code, Is.EqualTo(-32001)); - } + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); + JsonRpcErrorResponse? response = RpcTest.TestRequest(rpcModule, "debug_getBlockRlp", "1") as JsonRpcErrorResponse; - [Test] - public void Get_block_rlp_by_hash_when_missing() - { - BlockDecoder decoder = new(); - Rlp rlp = decoder.Encode(Build.A.Block.WithNumber(1).TestObject); - debugBridge.GetBlockRlp(Keccak.Zero).Returns((byte[])null!); + Assert.That(response?.Error?.Code, Is.EqualTo(-32001)); + } - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); - JsonRpcErrorResponse? response = RpcTest.TestRequest(rpcModule, "debug_getBlockRlpByHash", $"{Keccak.Zero.Bytes.ToHexString()}") as JsonRpcErrorResponse; + [Test] + public void Get_block_rlp_by_hash_when_missing() + { + BlockDecoder decoder = new(); + Rlp rlp = decoder.Encode(Build.A.Block.WithNumber(1).TestObject); + debugBridge.GetBlockRlp(Keccak.Zero).Returns((byte[])null!); - Assert.That(response?.Error?.Code, Is.EqualTo(-32001)); - } + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); + JsonRpcErrorResponse? response = RpcTest.TestRequest(rpcModule, "debug_getBlockRlpByHash", $"{Keccak.Zero.Bytes.ToHexString()}") as JsonRpcErrorResponse; - [Test] - public async Task Get_trace() - { - GethTxTraceEntry entry = new(); - entry.Storage = new Dictionary - { - {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, - {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, - }; + Assert.That(response?.Error?.Code, Is.EqualTo(-32001)); + } - entry.Memory = new List + [Test] + public void Get_trace() { - "5".PadLeft(64, '0'), - "6".PadLeft(64, '0') - }; + GethTxTraceEntry entry = new(); + entry.Storage = new Dictionary + { + {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, + {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, + }; - entry.Stack = new List - { - "7".PadLeft(64, '0'), - "8".PadLeft(64, '0') - }; + entry.Memory = new List + { + "5".PadLeft(64, '0'), + "6".PadLeft(64, '0') + }; - entry.Opcode = "STOP"; - entry.Gas = 22000; - entry.GasCost = 1; - entry.Depth = 1; + entry.Stack = new List + { + "7".PadLeft(64, '0'), + "8".PadLeft(64, '0') + }; - var trace = new GethLikeTxTrace(); - trace.ReturnValue = Bytes.FromHexString("a2"); - trace.Entries.Add(entry); + entry.Operation = "STOP"; + entry.Gas = 22000; + entry.GasCost = 1; + entry.Depth = 1; - debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Any()).Returns(trace); + var trace = new GethLikeTxTrace(); + trace.ReturnValue = Bytes.FromHexString("a2"); + trace.Entries.Add(entry); - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); - string response = await RpcTest.TestSerializedRequest(DebugModuleFactory.Converters, rpcModule, "debug_traceTransaction", TestItem.KeccakA.ToString(true), "{}"); + debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Any()).Returns(trace); - Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"gas\":\"0x0\",\"failed\":false,\"returnValue\":\"0xa2\",\"structLogs\":[{\"pc\":0,\"op\":\"STOP\",\"gas\":22000,\"gasCost\":1,\"depth\":1,\"error\":null,\"stack\":[\"0000000000000000000000000000000000000000000000000000000000000007\",\"0000000000000000000000000000000000000000000000000000000000000008\"],\"memory\":[\"0000000000000000000000000000000000000000000000000000000000000005\",\"0000000000000000000000000000000000000000000000000000000000000006\"],\"storage\":{\"0000000000000000000000000000000000000000000000000000000000000001\":\"0000000000000000000000000000000000000000000000000000000000000002\",\"0000000000000000000000000000000000000000000000000000000000000003\":\"0000000000000000000000000000000000000000000000000000000000000004\"}}]},\"id\":67}")); - } + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); + string response = RpcTest.TestSerializedRequest(DebugModuleFactory.Converters, rpcModule, "debug_traceTransaction", TestItem.KeccakA.ToString(true), "{}"); - [Test] - public async Task Get_trace_with_options() - { - GethTxTraceEntry entry = new(); - entry.Storage = new Dictionary - { - {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, - {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, - }; + Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"gas\":\"0x0\",\"failed\":false,\"returnValue\":\"0xa2\",\"structLogs\":[{\"pc\":0,\"op\":\"STOP\",\"gas\":22000,\"gasCost\":1,\"depth\":1,\"error\":null,\"stack\":[\"0000000000000000000000000000000000000000000000000000000000000007\",\"0000000000000000000000000000000000000000000000000000000000000008\"],\"memory\":[\"0000000000000000000000000000000000000000000000000000000000000005\",\"0000000000000000000000000000000000000000000000000000000000000006\"],\"storage\":{\"0000000000000000000000000000000000000000000000000000000000000001\":\"0000000000000000000000000000000000000000000000000000000000000002\",\"0000000000000000000000000000000000000000000000000000000000000003\":\"0000000000000000000000000000000000000000000000000000000000000004\"}}]},\"id\":67}")); + } - entry.Memory = new List + [Test] + public void Get_trace_with_options() { - "5".PadLeft(64, '0'), - "6".PadLeft(64, '0') - }; + GethTxTraceEntry entry = new(); + entry.Storage = new Dictionary + { + {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, + {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, + }; - entry.Stack = new List - { - }; + entry.Memory = new List + { + "5".PadLeft(64, '0'), + "6".PadLeft(64, '0') + }; - entry.Opcode = "STOP"; - entry.Gas = 22000; - entry.GasCost = 1; - entry.Depth = 1; + entry.Stack = new List + { + }; - var trace = new GethLikeTxTrace(); - trace.ReturnValue = Bytes.FromHexString("a2"); - trace.Entries.Add(entry); + entry.Operation = "STOP"; + entry.Gas = 22000; + entry.GasCost = 1; + entry.Depth = 1; - debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Any()).Returns(trace); + var trace = new GethLikeTxTrace(); + trace.ReturnValue = Bytes.FromHexString("a2"); + trace.Entries.Add(entry); - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); - string response = await RpcTest.TestSerializedRequest(DebugModuleFactory.Converters, rpcModule, "debug_traceTransaction", TestItem.KeccakA.ToString(true), "{disableStack : true}"); + debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Any()).Returns(trace); - Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"gas\":\"0x0\",\"failed\":false,\"returnValue\":\"0xa2\",\"structLogs\":[{\"pc\":0,\"op\":\"STOP\",\"gas\":22000,\"gasCost\":1,\"depth\":1,\"error\":null,\"stack\":[],\"memory\":[\"0000000000000000000000000000000000000000000000000000000000000005\",\"0000000000000000000000000000000000000000000000000000000000000006\"],\"storage\":{\"0000000000000000000000000000000000000000000000000000000000000001\":\"0000000000000000000000000000000000000000000000000000000000000002\",\"0000000000000000000000000000000000000000000000000000000000000003\":\"0000000000000000000000000000000000000000000000000000000000000004\"}}]},\"id\":67}")); - } + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); + string response = RpcTest.TestSerializedRequest(DebugModuleFactory.Converters, rpcModule, "debug_traceTransaction", TestItem.KeccakA.ToString(true), "{disableStack : true}"); - [Test] - public void Debug_traceCall_test() - { - GethTxTraceEntry entry = new(); + Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"gas\":\"0x0\",\"failed\":false,\"returnValue\":\"0xa2\",\"structLogs\":[{\"pc\":0,\"op\":\"STOP\",\"gas\":22000,\"gasCost\":1,\"depth\":1,\"error\":null,\"stack\":[],\"memory\":[\"0000000000000000000000000000000000000000000000000000000000000005\",\"0000000000000000000000000000000000000000000000000000000000000006\"],\"storage\":{\"0000000000000000000000000000000000000000000000000000000000000001\":\"0000000000000000000000000000000000000000000000000000000000000002\",\"0000000000000000000000000000000000000000000000000000000000000003\":\"0000000000000000000000000000000000000000000000000000000000000004\"}}]},\"id\":67}")); + } - entry.Storage = new Dictionary + [Test] + public void Debug_traceCall_test() { - {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, - {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, - }; + GethTxTraceEntry entry = new(); - entry.Memory = new List - { - "5".PadLeft(64, '0'), - "6".PadLeft(64, '0') - }; + entry.Storage = new Dictionary + { + {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, + {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, + }; + + entry.Memory = new List + { + "5".PadLeft(64, '0'), + "6".PadLeft(64, '0') + }; - entry.Stack = new List { }; - entry.Opcode = "STOP"; - entry.Gas = 22000; - entry.GasCost = 1; - entry.Depth = 1; + entry.Stack = new List { }; + entry.Operation = "STOP"; + entry.Gas = 22000; + entry.GasCost = 1; + entry.Depth = 1; - var trace = new GethLikeTxTrace(); - trace.ReturnValue = Bytes.FromHexString("a2"); - trace.Entries.Add(entry); + var trace = new GethLikeTxTrace(); + trace.ReturnValue = Bytes.FromHexString("a2"); + trace.Entries.Add(entry); - GethTraceOptions gtOptions = new(); + GethTraceOptions gtOptions = new(); - Transaction transaction = Build.A.Transaction.WithTo(TestItem.AddressA).WithHash(TestItem.KeccakA).TestObject; - TransactionForRpc txForRpc = new(transaction); + Transaction transaction = Build.A.Transaction.WithTo(TestItem.AddressA).WithHash(TestItem.KeccakA).TestObject; + TransactionForRpc txForRpc = new(transaction); - debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()).Returns(trace); + debugBridge.GetTransactionTrace(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()).Returns(trace); - DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); - ResultWrapper debugTraceCall = rpcModule.debug_traceCall(txForRpc, null, gtOptions); - ResultWrapper expected = ResultWrapper.Success( - new GethLikeTxTrace() - { - Failed = false, - Entries = new List() + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); + ResultWrapper debugTraceCall = rpcModule.debug_traceCall(txForRpc, null, gtOptions); + ResultWrapper expected = ResultWrapper.Success( + new GethLikeTxTrace() { - new GethTxTraceEntry() + Failed = false, + Entries = new List() { - Gas = 22000, - GasCost = 1, - Depth = 1, - Memory = new List() - { - "0000000000000000000000000000000000000000000000000000000000000005", - "0000000000000000000000000000000000000000000000000000000000000006" - }, - Opcode = "STOP", - ProgramCounter = 0, - Stack = Array.Empty(), - Storage = new Dictionary() + new GethTxTraceEntry() { + Gas = 22000, + GasCost = 1, + Depth = 1, + Memory = new List() { - "0000000000000000000000000000000000000000000000000000000000000001", - "0000000000000000000000000000000000000000000000000000000000000002" + "0000000000000000000000000000000000000000000000000000000000000005", + "0000000000000000000000000000000000000000000000000000000000000006" }, + Operation = "STOP", + Pc = 0, + Stack = { }, + Storage = new Dictionary() { - "0000000000000000000000000000000000000000000000000000000000000003", - "0000000000000000000000000000000000000000000000000000000000000004" - }, + { + "0000000000000000000000000000000000000000000000000000000000000001", + "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "0000000000000000000000000000000000000000000000000000000000000003", + "0000000000000000000000000000000000000000000000000000000000000004" + }, + } } - } - }, - Gas = 0, - ReturnValue = new byte[] { 162 } - } - ); - - debugTraceCall.Should().BeEquivalentTo(expected); - } - - [Test] - public async Task Migrate_receipts() - { - debugBridge.MigrateReceipts(Arg.Any()).Returns(true); - IDebugRpcModule rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); - string response = await RpcTest.TestSerializedRequest(rpcModule, "debug_migrateReceipts", "100"); - Assert.NotNull(response); - } - - [Test] - public void Update_head_block() - { - debugBridge.UpdateHeadBlock(Arg.Any()); - IDebugRpcModule rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); - RpcTest.TestSerializedRequest(rpcModule, "debug_resetHead", TestItem.KeccakA.ToString()); - debugBridge.Received().UpdateHeadBlock(TestItem.KeccakA); - } + }, + Gas = 0, + ReturnValue = new byte[] { 162 } + } + ); - [Test] - public void TraceBlock_Success() - { - var traces = Enumerable.Repeat(MockGethLikeTrace(), 2).ToArray(); - var tracesClone = TestItem.CloneObject(traces); - var blockRlp = new Rlp(TestItem.RandomDataA); - - debugBridge - .GetBlockTrace(blockRlp, Arg.Any(), Arg.Any()) - .Returns(traces); - - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); - var actual = rpcModule.debug_traceBlock(blockRlp.Bytes); - var expected = ResultWrapper.Success(tracesClone); - - actual.Should().BeEquivalentTo(expected); - } - - [Test] - public void TraceBlock_Fail() - { - var blockRlp = new Rlp(TestItem.RandomDataA); + debugTraceCall.Should().BeEquivalentTo(expected); + } - debugBridge - .GetBlockTrace(blockRlp, Arg.Any(), Arg.Any()) - .Returns(default(GethLikeTxTrace[])); + [Test] + public void Migrate_receipts() + { + debugBridge.MigrateReceipts(Arg.Any()).Returns(true); + IDebugRpcModule rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); + string response = RpcTest.TestSerializedRequest(rpcModule, "debug_migrateReceipts", "100"); + Assert.NotNull(response); + } + + [Test] + public void Update_head_block() + { + debugBridge.UpdateHeadBlock(Arg.Any()); + IDebugRpcModule rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); + RpcTest.TestSerializedRequest(rpcModule, "debug_resetHead", TestItem.KeccakA.ToString()); + debugBridge.Received().UpdateHeadBlock(TestItem.KeccakA); + } + + [Test] + public void TraceBlock_Success() + { + var traces = Enumerable.Repeat(MockGethLikeTrace(), 2).ToArray(); + var tracesClone = TestItem.CloneObject(traces); + var blockRlp = new Rlp(TestItem.RandomDataA); - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); - var actual = rpcModule.debug_traceBlock(blockRlp.Bytes); - var expected = ResultWrapper.Fail($"Trace is null for RLP {blockRlp.Bytes.ToHexString()}", ErrorCodes.ResourceNotFound); + debugBridge + .GetBlockTrace(blockRlp, Arg.Any(), Arg.Any()) + .Returns(traces); - actual.Should().BeEquivalentTo(expected); - } + var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); + var actual = rpcModule.debug_traceBlock(blockRlp.Bytes); + var expected = ResultWrapper.Success(tracesClone); - [Test] - public void StandardTraceBlockToFile() - { - var blockHash = Keccak.EmptyTreeHash; - - static IEnumerable GetFileNames(Keccak hash) => - new[] { $"block_{hash.ToShortString()}-0", $"block_{hash.ToShortString()}-1" }; + actual.Should().BeEquivalentTo(expected); + } - debugBridge - .TraceBlockToFile(Arg.Is(blockHash), Arg.Any(), Arg.Any()) - .Returns(c => GetFileNames(c.ArgAt(0))); + [Test] + public void TraceBlock_Fail() + { + var blockRlp = new Rlp(TestItem.RandomDataA); - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); - var actual = rpcModule.debug_standardTraceBlockToFile(blockHash); - var expected = ResultWrapper>.Success(GetFileNames(blockHash)); + debugBridge + .GetBlockTrace(blockRlp, Arg.Any(), Arg.Any()) + .Returns(default(GethLikeTxTrace[])); - actual.Should().BeEquivalentTo(expected); - } + var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); + var actual = rpcModule.debug_traceBlock(blockRlp.Bytes); + var expected = ResultWrapper.Fail($"Trace is null for RLP {blockRlp.Bytes.ToHexString()}", ErrorCodes.ResourceNotFound); - [Test] - public void TraceBlockByHash_Success() - { - var traces = Enumerable.Repeat(MockGethLikeTrace(), 2).ToArray(); - var tracesClone = TestItem.CloneObject(traces); - var blockHash = TestItem.KeccakA; + actual.Should().BeEquivalentTo(expected); + } - debugBridge - .GetBlockTrace(new BlockParameter(blockHash), Arg.Any(), Arg.Any()) - .Returns(traces); + [Test] + public void TraceBlockByHash_Success() + { + var traces = Enumerable.Repeat(MockGethLikeTrace(), 2).ToArray(); + var tracesClone = TestItem.CloneObject(traces); + var blockHash = TestItem.KeccakA; - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); - var actual = rpcModule.debug_traceBlockByHash(blockHash); - var expected = ResultWrapper.Success(tracesClone); + debugBridge + .GetBlockTrace(new BlockParameter(blockHash), Arg.Any(), Arg.Any()) + .Returns(traces); - actual.Should().BeEquivalentTo(expected); - } + var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); + var actual = rpcModule.debug_traceBlockByHash(blockHash); + var expected = ResultWrapper.Success(tracesClone); - [Test] - public void TraceBlockByHash_Fail() - { - var blockHash = TestItem.KeccakA; + actual.Should().BeEquivalentTo(expected); + } - debugBridge - .GetBlockTrace(new BlockParameter(blockHash), Arg.Any(), Arg.Any()) - .Returns(default(GethLikeTxTrace[])); + [Test] + public void TraceBlockByHash_Fail() + { + var blockHash = TestItem.KeccakA; - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); - var actual = rpcModule.debug_traceBlockByHash(blockHash); - var expected = ResultWrapper.Fail($"Trace is null for block {blockHash}", ErrorCodes.ResourceNotFound); + debugBridge + .GetBlockTrace(new BlockParameter(blockHash), Arg.Any(), Arg.Any()) + .Returns(default(GethLikeTxTrace[])); - actual.Should().BeEquivalentTo(expected); - } + var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); + var actual = rpcModule.debug_traceBlockByHash(blockHash); + var expected = ResultWrapper.Fail($"Trace is null for block {blockHash}", ErrorCodes.ResourceNotFound); - [Test] - public void TraceBlockByNumber_Success() - { - var traces = Enumerable.Repeat(MockGethLikeTrace(), 2).ToArray(); - var tracesClone = TestItem.CloneObject(traces); - var blockNumber = BlockParameter.Latest; + actual.Should().BeEquivalentTo(expected); + } - debugBridge - .GetBlockTrace(blockNumber, Arg.Any(), Arg.Any()) - .Returns(traces); + [Test] + public void TraceBlockByNumber_Success() + { + var traces = Enumerable.Repeat(MockGethLikeTrace(), 2).ToArray(); + var tracesClone = TestItem.CloneObject(traces); + var blockNumber = BlockParameter.Latest; - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); - var actual = rpcModule.debug_traceBlockByNumber(blockNumber); - var expected = ResultWrapper.Success(tracesClone); + debugBridge + .GetBlockTrace(blockNumber, Arg.Any(), Arg.Any()) + .Returns(traces); - actual.Should().BeEquivalentTo(expected); - } + var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); + var actual = rpcModule.debug_traceBlockByNumber(blockNumber); + var expected = ResultWrapper.Success(tracesClone); - [Test] - public void TraceBlockByNumber_Fail() - { - var blockNumber = BlockParameter.Latest; + actual.Should().BeEquivalentTo(expected); + } - debugBridge - .GetBlockTrace(blockNumber, Arg.Any(), Arg.Any()) - .Returns(default(GethLikeTxTrace[])); + [Test] + public void TraceBlockByNumber_Fail() + { + var blockNumber = BlockParameter.Latest; - var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); - var actual = rpcModule.debug_traceBlockByNumber(blockNumber); - var expected = ResultWrapper.Fail($"Trace is null for block {blockNumber}", ErrorCodes.ResourceNotFound); + debugBridge + .GetBlockTrace(blockNumber, Arg.Any(), Arg.Any()) + .Returns(default(GethLikeTxTrace[])); - actual.Should().BeEquivalentTo(expected); - } + var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); + var actual = rpcModule.debug_traceBlockByNumber(blockNumber); + var expected = ResultWrapper.Fail($"Trace is null for block {blockNumber}", ErrorCodes.ResourceNotFound); - private static GethLikeTxTrace MockGethLikeTrace() - { - var trace = new GethLikeTxTrace { ReturnValue = new byte[] { 0xA2 } }; + actual.Should().BeEquivalentTo(expected); + } - trace.Entries.Add(new GethTxTraceEntry + private static GethLikeTxTrace MockGethLikeTrace() { - Depth = 1, - Gas = 22000, - GasCost = 1, - Memory = new List - { - "5".PadLeft(64, '0'), - "6".PadLeft(64, '0') - }, - Opcode = "STOP", - ProgramCounter = 32, - Stack = new List - { - "7".PadLeft(64, '0'), - "8".PadLeft(64, '0') - }, - Storage = new Dictionary + var trace = new GethLikeTxTrace { ReturnValue = new byte[] { 0xA2 } }; + + trace.Entries.Add(new GethTxTraceEntry { - {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, - {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, - } - }); + Depth = 1, + Gas = 22000, + GasCost = 1, + Memory = new List + { + "5".PadLeft(64, '0'), + "6".PadLeft(64, '0') + }, + Operation = "STOP", + Pc = 32, + Stack = new List + { + "7".PadLeft(64, '0'), + "8".PadLeft(64, '0') + }, + Storage = new Dictionary + { + {"1".PadLeft(64, '0'), "2".PadLeft(64, '0')}, + {"3".PadLeft(64, '0'), "4".PadLeft(64, '0')}, + } + }); - return trace; + return trace; + } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs index c0448532a2f..d2a7986c505 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EstimateGas.cs @@ -30,7 +30,7 @@ public async Task Eth_estimateGas_web3_should_return_insufficient_balance_error( TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"from\":\"0x0001020304050607080910111213141516171819\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\", \"value\": 500}"); string serialized = - await ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); + ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That( serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32000,\"message\":\"insufficient funds for transfer: address 0x0001020304050607080910111213141516171819\"},\"id\":67}")); ctx.Test.ReadOnlyState.AccountExists(someAccount).Should().BeFalse(); @@ -45,7 +45,7 @@ public async Task Eth_estimateGas_web3_sample_not_enough_gas_system_account() TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); string serialized = - await ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); + ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x53b8\",\"id\":67}")); ctx.Test.ReadOnlyState.AccountExists(Address.SystemUser).Should().BeFalse(); } @@ -59,7 +59,7 @@ public async Task Eth_estimateGas_web3_sample_not_enough_gas_other_account() TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"from\":\"0x0001020304050607080910111213141516171819\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); string serialized = - await ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); + ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x53b8\",\"id\":67}")); ctx.Test.ReadOnlyState.AccountExists(someAccount).Should().BeFalse(); } @@ -73,7 +73,7 @@ public async Task Eth_estimateGas_web3_above_block_gas_limit() TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"from\":\"0x0001020304050607080910111213141516171819\",\"gas\":\"0x100000000\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); string serialized = - await ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); + ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x53b8\",\"id\":67}")); ctx.Test.ReadOnlyState.AccountExists(someAccount).Should().BeFalse(); } @@ -91,7 +91,7 @@ public async Task Eth_create_access_list_calculates_proper_gas(bool optimize, lo TransactionForRpc transaction = test.JsonSerializer.Deserialize( $"{{\"type\":\"0x1\", \"data\": \"{code.ToHexString(true)}\"}}"); - string serializedCreateAccessList = await test.TestEthRpc("eth_createAccessList", + string serializedCreateAccessList = test.TestEthRpc("eth_createAccessList", test.JsonSerializer.Serialize(transaction), "0x0", optimize.ToString().ToLower()); if (optimize && loads <= AccessTxTracer.MaxStorageAccessToOptimize) @@ -101,7 +101,7 @@ public async Task Eth_create_access_list_calculates_proper_gas(bool optimize, lo transaction.AccessList = accessList; string serializedEstimateGas = - await test.TestEthRpc("eth_estimateGas", test.JsonSerializer.Serialize(transaction), "0x0"); + test.TestEthRpc("eth_estimateGas", test.JsonSerializer.Serialize(transaction), "0x0"); var gasUsedEstimateGas = JToken.Parse(serializedEstimateGas).Value("result"); var gasUsedCreateAccessList = @@ -122,12 +122,12 @@ public async Task Eth_estimate_gas_with_accessList(bool senderAccessList, long g TransactionForRpc transaction = test.JsonSerializer.Deserialize( $"{{\"type\":\"0x1\", \"data\": \"{code.ToHexString(true)}\"}}"); - string serialized = await test.TestEthRpc("eth_estimateGas", test.JsonSerializer.Serialize(transaction), "0x0"); + string serialized = test.TestEthRpc("eth_estimateGas", test.JsonSerializer.Serialize(transaction), "0x0"); Assert.That( serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"{gasPriceWithoutAccessList.ToHexString(true)}\",\"id\":67}}")); transaction.AccessList = accessList; - serialized = await test.TestEthRpc("eth_estimateGas", test.JsonSerializer.Serialize(transaction), "0x0"); + serialized = test.TestEthRpc("eth_estimateGas", test.JsonSerializer.Serialize(transaction), "0x0"); Assert.That( serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"{gasPriceWithAccessList.ToHexString(true)}\",\"id\":67}}")); } @@ -145,11 +145,11 @@ public async Task Eth_estimate_gas_is_lower_with_optimized_access_list() test.JsonSerializer.Deserialize( $"{{\"type\":\"0x1\", \"data\": \"{code.ToHexString(true)}\"}}"); transaction.AccessList = accessList; - string serialized = await test.TestEthRpc("eth_estimateGas", test.JsonSerializer.Serialize(transaction), "0x0"); + string serialized = test.TestEthRpc("eth_estimateGas", test.JsonSerializer.Serialize(transaction), "0x0"); long estimateGas = Convert.ToInt64(JToken.Parse(serialized).Value("result"), 16); transaction.AccessList = optimizedAccessList; - serialized = await test.TestEthRpc("eth_estimateGas", test.JsonSerializer.Serialize(transaction), "0x0"); + serialized = test.TestEthRpc("eth_estimateGas", test.JsonSerializer.Serialize(transaction), "0x0"); long optimizedEstimateGas = Convert.ToInt64(JToken.Parse(serialized).Value("result"), 16); optimizedEstimateGas.Should().BeLessThan(estimateGas); @@ -161,7 +161,7 @@ public async Task Estimate_gas_without_gas_pricing() using Context ctx = await Context.Create(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"from\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); - string serialized = await ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); + string serialized = ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x5208\",\"id\":67}")); } @@ -171,7 +171,7 @@ public async Task Estimate_gas_with_gas_pricing() using Context ctx = await Context.Create(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"gasPrice\": \"0x10\"}"); - string serialized = await ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); + string serialized = ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x5208\",\"id\":67}")); } @@ -181,7 +181,7 @@ public async Task Estimate_gas_without_gas_pricing_after_1559_legacy() using Context ctx = await Context.CreateWithLondonEnabled(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"gasPrice\": \"0x10\"}"); - string serialized = await ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); + string serialized = ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x5208\",\"id\":67}")); } @@ -191,7 +191,7 @@ public async Task Estimate_gas_without_gas_pricing_after_1559_new_type_of_transa using Context ctx = await Context.CreateWithLondonEnabled(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"type\": \"0x2\"}"); - string serialized = await ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); + string serialized = ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x5208\",\"id\":67}")); byte[] code = Prepare.EvmCode .Op(Instruction.BASEFEE) @@ -217,7 +217,7 @@ public async Task Estimate_gas_with_base_fee_opcode() string dataStr = code.ToHexString(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( $"{{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"type\": \"0x2\", \"data\": \"{dataStr}\"}}"); - string serialized = await ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); + string serialized = ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That( serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0xe891\",\"id\":67}")); } @@ -236,7 +236,7 @@ public async Task Estimate_gas_with_revert() string dataStr = code.ToHexString(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( $"{{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"type\": \"0x2\", \"data\": \"{dataStr}\"}}"); - string serialized = await ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); + string serialized = ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That( serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32015,\"message\":\"revert\"},\"id\":67}")); } @@ -254,7 +254,7 @@ public async Task should_estimate_transaction_with_deployed_code_when_eip3607_en transaction.To = TestItem.AddressB; string serialized = - await ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); + ctx.Test.TestEthRpc("eth_estimateGas", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x5208\",\"id\":67}")); } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index 30aba351ebd..5e495305b66 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -25,7 +25,7 @@ public async Task Eth_call_web3_sample() TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); string serialized = - await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "0x0"); + ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "0x0"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); } @@ -37,7 +37,7 @@ public async Task Eth_call_web3_sample_not_enough_gas_system_account() TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); string serialized = - await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "0x0"); + ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "0x0"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); ctx.Test.ReadOnlyState.AccountExists(Address.SystemUser).Should().BeFalse(); } @@ -50,7 +50,7 @@ public async Task Eth_call_web3_should_return_insufficient_balance_error() ctx.Test.ReadOnlyState.AccountExists(someAccount).Should().BeFalse(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"from\":\"0x0001020304050607080910111213141516171819\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\", \"value\": 500}"); - string serialized = await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction)); + string serialized = ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That( serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32000,\"message\":\"insufficient funds for transfer: address 0x0001020304050607080910111213141516171819\"},\"id\":67}")); ctx.Test.ReadOnlyState.AccountExists(someAccount).Should().BeFalse(); @@ -65,7 +65,7 @@ public async Task Eth_call_web3_sample_not_enough_gas_other_account() TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"from\":\"0x0001020304050607080910111213141516171819\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); string serialized = - await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "0x0"); + ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "0x0"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); ctx.Test.ReadOnlyState.AccountExists(someAccount).Should().BeFalse(); } @@ -78,7 +78,7 @@ public async Task Eth_call_no_sender() transaction.To = TestItem.AddressB; string serialized = - await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); + ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); } @@ -88,10 +88,10 @@ public async Task Eth_call_no_recipient_should_work_as_init() using Context ctx = await Context.Create(); TransactionForRpc transaction = new(Keccak.Zero, 1L, 1, new Transaction()); transaction.From = TestItem.AddressA; - transaction.Input = new byte[] { 1, 2, 3 }; + transaction.Data = new byte[] { 1, 2, 3 }; string serialized = - await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); + ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); Assert.That( serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32015,\"message\":\"VM execution error.\",\"data\":\"StackUnderflow\"},\"id\":67}")); } @@ -110,7 +110,7 @@ public async Task should_not_reject_transactions_with_deployed_code_when_eip3607 transaction.To = TestItem.AddressB; string serialized = - await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); + ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); } @@ -118,7 +118,7 @@ public async Task should_not_reject_transactions_with_deployed_code_when_eip3607 public async Task Eth_call_ethereum_recipient() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_call", + string serialized = ctx.Test.TestEthRpc("eth_call", "{\"data\":\"0x12\",\"from\":\"0x7301cfa0e1756b71869e93d4e4dca5c7d0eb0aa6\",\"to\":\"ethereum\"}", "latest"); Assert.True(serialized.StartsWith("{\"jsonrpc\":\"2.0\",\"error\"")); @@ -133,7 +133,7 @@ public async Task Eth_call_ok() transaction.To = TestItem.AddressB; string serialized = - await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); + ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); } @@ -149,7 +149,7 @@ public async Task Eth_call_missing_state_after_fast_sync() ctx.Test.TrieStore.ClearCache(); string serialized = - await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); + ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); serialized.Should().StartWith("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32002,"); } @@ -166,7 +166,7 @@ public async Task Eth_call_with_accessList() $"{{\"type\":\"0x1\", \"data\": \"{code.ToHexString(true)}\"}}"); transaction.AccessList = accessList; - string serialized = await test.TestEthRpc("eth_call", test.JsonSerializer.Serialize(transaction), "0x0"); + string serialized = test.TestEthRpc("eth_call", test.JsonSerializer.Serialize(transaction), "0x0"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x010203\",\"id\":67}")); } @@ -176,7 +176,7 @@ public async Task Eth_call_without_gas_pricing() using Context ctx = await Context.Create(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"from\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); - string serialized = await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction)); + string serialized = ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); } @@ -186,7 +186,7 @@ public async Task Eth_call_with_gas_pricing() using Context ctx = await Context.Create(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"gasPrice\": \"0x10\"}"); - string serialized = await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction)); + string serialized = ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); } @@ -196,7 +196,7 @@ public async Task Eth_call_without_gas_pricing_after_1559_legacy() using Context ctx = await Context.CreateWithLondonEnabled(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"gasPrice\": \"0x10\"}"); - string serialized = await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction)); + string serialized = ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); } @@ -206,7 +206,7 @@ public async Task Eth_call_without_gas_pricing_after_1559_new_type_of_transactio using Context ctx = await Context.CreateWithLondonEnabled(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( "{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"type\": \"0x2\"}"); - string serialized = await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction)); + string serialized = ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}")); byte[] code = Prepare.EvmCode .Op(Instruction.BASEFEE) @@ -232,7 +232,7 @@ public async Task Eth_call_with_base_fee_opcode() string dataStr = code.ToHexString(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( $"{{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"type\": \"0x2\", \"data\": \"{dataStr}\"}}"); - string serialized = await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction)); + string serialized = ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That( serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x000000000000000000000000000000000000000000000000000000002da282a8\",\"id\":67}")); } @@ -251,7 +251,7 @@ public async Task Eth_call_with_revert() string dataStr = code.ToHexString(); TransactionForRpc transaction = ctx.Test.JsonSerializer.Deserialize( $"{{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"type\": \"0x2\", \"data\": \"{dataStr}\"}}"); - string serialized = await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction)); + string serialized = ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction)); Assert.That( serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32015,\"message\":\"VM execution error.\",\"data\":\"revert\"},\"id\":67}")); } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.FeeHistory.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.FeeHistory.cs index 90ddb8d4235..ae2c0eb12b5 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.FeeHistory.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.FeeHistory.cs @@ -16,7 +16,7 @@ public partial class EthRpcModuleTests public async Task Eth_feeHistory(long blockCount, string blockParameter, string expected) { using Context ctx = await Context.CreateWithLondonEnabled(); - string serialized = await ctx.Test.TestEthRpc("eth_feeHistory", blockCount.ToString(), blockParameter, "[0,10.5,20,60,90]"); + string serialized = ctx.Test.TestEthRpc("eth_feeHistory", blockCount.ToString(), blockParameter, "[0,10.5,20,60,90]"); serialized.Should().Be(expected); } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.GasPrice.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.GasPrice.cs index 19e67118890..0b084a9ba01 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.GasPrice.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.GasPrice.cs @@ -27,7 +27,7 @@ public async Task Eth_gasPrice_BlocksAvailableLessThanBlocksToCheck_ShouldGiveCo ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockTree).WithGasPriceOracle(gasPriceOracle) .Build(); - string serialized = await ctx.Test.TestEthRpc("eth_gasPrice"); + string serialized = ctx.Test.TestEthRpc("eth_gasPrice"); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"{expected}\",\"id\":67}}")); } @@ -43,7 +43,7 @@ public async Task Eth_gasPrice_BlocksAvailableLessThanBlocksToCheckWith1559Tx_Sh ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockTree).WithGasPriceOracle(gasPriceOracle) .Build(); - string serialized = await ctx.Test.TestEthRpc("eth_gasPrice"); + string serialized = ctx.Test.TestEthRpc("eth_gasPrice"); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"{expected}\",\"id\":67}}")); } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs index d3366240dea..4f97badc663 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -34,6 +33,7 @@ using Nethermind.TxPool; using NSubstitute; using NSubstitute.ExceptionExtensions; +using NSubstitute.ReceivedExtensions; using NUnit.Framework; namespace Nethermind.JsonRpc.Test.Modules.Eth; @@ -49,7 +49,7 @@ public partial class EthRpcModuleTests public async Task Eth_get_balance(string blockParameter, string expectedResult) { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getBalance", TestItem.AddressA.Bytes.ToHexString(true), blockParameter); + string serialized = ctx.Test.TestEthRpc("eth_getBalance", TestItem.AddressA.Bytes.ToHexString(true), blockParameter); serialized.Should().Be($"{{\"jsonrpc\":\"2.0\",\"result\":\"{expectedResult}\",\"id\":67}}"); } @@ -57,7 +57,7 @@ public async Task Eth_get_balance(string blockParameter, string expectedResult) public async Task Eth_get_balance_default_block() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getBalance", TestItem.AddressA.Bytes.ToHexString(true)); + string serialized = ctx.Test.TestEthRpc("eth_getBalance", TestItem.AddressA.Bytes.ToHexString(true)); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x3635c9adc5de9f09e5\",\"id\":67}")); } @@ -65,7 +65,7 @@ public async Task Eth_get_balance_default_block() public async Task Eth_get_eth_feeHistory() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_feeHistory", "0x1", "latest", "[20,50,90]"); + string serialized = ctx.Test.TestEthRpc("eth_feeHistory", "0x1", "latest", "[20,50,90]"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"baseFeePerGas\":[\"0x0\",\"0x0\"],\"gasUsedRatio\":[0.0105],\"oldestBlock\":\"0x3\",\"reward\":[[\"0x1\",\"0x1\",\"0x1\"]]},\"id\":67}")); } @@ -73,23 +73,23 @@ public async Task Eth_get_eth_feeHistory() public async Task Eth_get_transaction_by_block_hash_and_index() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getTransactionByBlockHashAndIndex", ctx.Test.BlockTree.FindHeadBlock()!.Hash!.ToString(), "1"); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},\"id\":67}"), serialized.Replace("\"", "\\\"")); + string serialized = ctx.Test.TestEthRpc("eth_getTransactionByBlockHashAndIndex", ctx.Test.BlockTree.FindHeadBlock()!.Hash!.ToString(), "1"); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},\"id\":67}"), serialized.Replace("\"", "\\\"")); } [Test] public async Task Eth_get_transaction_by_hash() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getTransactionByHash", ctx.Test.BlockTree.FindHeadBlock()!.Transactions.Last().Hash!.ToString()); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},\"id\":67}"), serialized.Replace("\"", "\\\"")); + string serialized = ctx.Test.TestEthRpc("eth_getTransactionByHash", ctx.Test.BlockTree.FindHeadBlock()!.Transactions.Last().Hash!.ToString()); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},\"id\":67}"), serialized.Replace("\"", "\\\"")); } [Test] public async Task eth_maxPriorityFeePerGas_test() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_maxPriorityFeePerGas"); + string serialized = ctx.Test.TestEthRpc("eth_maxPriorityFeePerGas"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x1\",\"id\":67}"), serialized.Replace("\"", "\\\"")); } @@ -98,8 +98,8 @@ public async Task Eth_pending_transactions() { using Context ctx = await Context.Create(); ctx.Test.AddTransactions(Build.A.Transaction.SignedAndResolved(TestItem.PrivateKeyD).TestObject); - string serialized = await ctx.Test.TestEthRpc("eth_pendingTransactions"); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[{\"hash\":\"0x190d9a78dbc61b1856162ab909976a1b28ba4a41ee041341576ea69686cd3b29\",\"nonce\":\"0x0\",\"blockHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"blockNumber\":null,\"transactionIndex\":null,\"from\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x26\",\"s\":\"0x2d04e55699fa32e6b65a22189f7571f5030d636d7d44a8b53fe016a2c3ecde24\",\"r\":\"0xda3978c3a1430bd902cf5bbca73c5a1eca019b3f003c95ee16657fd0bb89534c\"}],\"id\":67}"), serialized.Replace("\"", "\\\"")); + string serialized = ctx.Test.TestEthRpc("eth_pendingTransactions"); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[{\"hash\":\"0x190d9a78dbc61b1856162ab909976a1b28ba4a41ee041341576ea69686cd3b29\",\"nonce\":\"0x0\",\"blockHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"blockNumber\":null,\"transactionIndex\":null,\"from\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x26\",\"s\":\"0x2d04e55699fa32e6b65a22189f7571f5030d636d7d44a8b53fe016a2c3ecde24\",\"r\":\"0xda3978c3a1430bd902cf5bbca73c5a1eca019b3f003c95ee16657fd0bb89534c\"}],\"id\":67}"), serialized.Replace("\"", "\\\"")); } [Test] @@ -107,8 +107,8 @@ public async Task Eth_pending_transactions_1559_tx() { using Context ctx = await Context.CreateWithLondonEnabled(); ctx.Test.AddTransactions(Build.A.Transaction.WithMaxPriorityFeePerGas(6.GWei()).WithMaxFeePerGas(11.GWei()).WithType(TxType.EIP1559).SignedAndResolved(TestItem.PrivateKeyC).TestObject); - const string addedTx = "\"hash\":\"0xc668c8940b7416fe06db0dac853210d6d64fb2e9528c439c135a53106517fca6\",\"nonce\":\"0x0\",\"blockHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"blockNumber\":null,\"transactionIndex\":null,\"from\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x28fa6ae00\",\"maxPriorityFeePerGas\":\"0x165a0bc00\",\"maxFeePerGas\":\"0x28fa6ae00\",\"gas\":\"0x5208\",\"input\":\"0x\",\"chainId\":\"0x1\",\"type\":\"0x2\",\"accessList\":[],\"v\":\"0x1\",\"s\":\"0x24e1404423c47d5c5fd9e0b6205811eaa3052f9acdb91a9c08821c2b7a0db1a4\",\"r\":\"0x408e34747109a32b924c61acb879d628505dbd0dcab15a3b1e3a4cfd589b65d2\",\"yParity\":\"0x1\""; - string serialized = await ctx.Test.TestEthRpc("eth_pendingTransactions"); + const string addedTx = "\"hash\":\"0xc668c8940b7416fe06db0dac853210d6d64fb2e9528c439c135a53106517fca6\",\"nonce\":\"0x0\",\"blockHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"blockNumber\":null,\"transactionIndex\":null,\"from\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x28fa6ae00\",\"maxPriorityFeePerGas\":\"0x165a0bc00\",\"maxFeePerGas\":\"0x28fa6ae00\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"chainId\":\"0x1\",\"type\":\"0x2\",\"v\":\"0x1\",\"s\":\"0x24e1404423c47d5c5fd9e0b6205811eaa3052f9acdb91a9c08821c2b7a0db1a4\",\"r\":\"0x408e34747109a32b924c61acb879d628505dbd0dcab15a3b1e3a4cfd589b65d2\",\"yParity\":\"0x1\""; + string serialized = ctx.Test.TestEthRpc("eth_pendingTransactions"); serialized.Contains(addedTx).Should().BeTrue(); } @@ -117,8 +117,8 @@ public async Task Eth_pending_transactions_2930_tx() { using Context ctx = await Context.CreateWithLondonEnabled(); ctx.Test.AddTransactions(Build.A.Transaction.WithMaxPriorityFeePerGas(6.GWei()).WithMaxFeePerGas(11.GWei()).WithType(TxType.AccessList).SignedAndResolved(TestItem.PrivateKeyC).TestObject); - const string addedTx = "\"hash\":\"0xa296c4cf8ece2d7788e4a71125133dfd8025fc35cc5ffa3e283bc62b027cf512\",\"nonce\":\"0x0\",\"blockHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"blockNumber\":null,\"transactionIndex\":null,\"from\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x165a0bc00\",\"gas\":\"0x5208\",\"input\":\"0x\",\"chainId\":\"0x1\",\"type\":\"0x1\",\"accessList\":[],\"v\":\"0x0\",\"s\":\"0x2b4cbea82cc417cdf510fb5fb0613a2881f2b8a76cd6cce6a5f77872f5124b44\",\"r\":\"0x925ede2e48031b060e6c4a0c7184eb58e37a19b41a3ba15a2d9767c0c41f6d76\",\"yParity\":\"0x0\""; - string serialized = await ctx.Test.TestEthRpc("eth_pendingTransactions"); + const string addedTx = "\"hash\":\"0xa296c4cf8ece2d7788e4a71125133dfd8025fc35cc5ffa3e283bc62b027cf512\",\"nonce\":\"0x0\",\"blockHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"blockNumber\":null,\"transactionIndex\":null,\"from\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x165a0bc00\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"chainId\":\"0x1\",\"type\":\"0x1\",\"v\":\"0x0\",\"s\":\"0x2b4cbea82cc417cdf510fb5fb0613a2881f2b8a76cd6cce6a5f77872f5124b44\",\"r\":\"0x925ede2e48031b060e6c4a0c7184eb58e37a19b41a3ba15a2d9767c0c41f6d76\",\"yParity\":\"0x0\""; + string serialized = ctx.Test.TestEthRpc("eth_pendingTransactions"); serialized.Contains(addedTx).Should().BeTrue(); } @@ -126,8 +126,8 @@ public async Task Eth_pending_transactions_2930_tx() public async Task Eth_get_transaction_by_block_number_and_index() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getTransactionByBlockNumberAndIndex", ctx.Test.BlockTree.FindHeadBlock()!.Number.ToString(), "1"); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},\"id\":67}"), serialized.Replace("\"", "\\\"")); + string serialized = ctx.Test.TestEthRpc("eth_getTransactionByBlockNumberAndIndex", ctx.Test.BlockTree.FindHeadBlock()!.Number.ToString(), "1"); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},\"id\":67}"), serialized.Replace("\"", "\\\"")); } [TestCase(false, "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0xf4240\",\"extraData\":\"0x010203\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0x0\",\"hash\":\"0xa2a9f03b9493046696099d27b2612b99497aa1f392ec966716ab393c715a5bb6\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x2ba5557a4c62a513c7e56d1bf13373e0da6bec016755483e91589fe1c6d212e2\",\"nonce\":\"0x00000000000003e8\",\"number\":\"0x0\",\"parentHash\":\"0xff483e972a04a9a62bb4b7d04ae403c615604e4090521ecc5bb7af67f71be09c\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x201\",\"stateRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"totalDifficulty\":\"0x0\",\"timestamp\":\"0xf4240\",\"transactions\":[],\"transactionsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"uncles\":[]},\"id\":67}")] @@ -146,7 +146,7 @@ public async Task Eth_get_uncle_by_block_number_and_index(bool eip1559, string e IBlockTree blockTree = Substitute.For(); blockTree.FindBlock((BlockParameter?)null).ReturnsForAnyArgs(block); ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockTree).Build(specProvider); - string serialized = await ctx.Test!.TestEthRpc("eth_getUncleByBlockNumberAndIndex", ctx.Test.BlockTree.FindHeadBlock()!.Number.ToString(), "1"); + string serialized = ctx.Test!.TestEthRpc("eth_getUncleByBlockNumberAndIndex", ctx.Test.BlockTree.FindHeadBlock()!.Number.ToString(), "1"); Assert.That(serialized, Is.EqualTo(expectedJson), serialized?.Replace("\"", "\\\"")); } @@ -167,7 +167,7 @@ public async Task Eth_get_uncle_by_block_hash_and_index(bool eip1559, string exp IBlockTree blockTree = Substitute.For(); blockTree.FindBlock((BlockParameter?)null).ReturnsForAnyArgs(block); ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockTree).Build(specProvider); - string serialized = await ctx.Test.TestEthRpc("eth_getUncleByBlockHashAndIndex", ctx.Test.BlockTree.FindHeadBlock()!.Hash!.ToString(), "1"); + string serialized = ctx.Test.TestEthRpc("eth_getUncleByBlockHashAndIndex", ctx.Test.BlockTree.FindHeadBlock()!.Hash!.ToString(), "1"); Assert.That(serialized, Is.EqualTo(expectedJson), serialized.Replace("\"", "\\\"")); } @@ -175,7 +175,7 @@ public async Task Eth_get_uncle_by_block_hash_and_index(bool eip1559, string exp public async Task Eth_get_uncle_count_by_block_hash() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getUncleCountByBlockHash", ctx.Test.BlockTree.FindHeadBlock()!.Hash!.ToString()); + string serialized = ctx.Test.TestEthRpc("eth_getUncleCountByBlockHash", ctx.Test.BlockTree.FindHeadBlock()!.Hash!.ToString()); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x0\",\"id\":67}"), serialized.Replace("\"", "\\\"")); } @@ -183,7 +183,7 @@ public async Task Eth_get_uncle_count_by_block_hash() public async Task Eth_get_uncle_count_by_block_number() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getUncleCountByBlockNumber", ctx.Test.BlockTree.FindHeadBlock()!.Number.ToString()); + string serialized = ctx.Test.TestEthRpc("eth_getUncleCountByBlockNumber", ctx.Test.BlockTree.FindHeadBlock()!.Number.ToString()); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x0\",\"id\":67}"), serialized.Replace("\"", "\\\"")); } @@ -201,13 +201,13 @@ public async Task Eth_get_tx_count(string blockParameter, string expectedResult) Transaction txWithFutureNonce = Build.A.Transaction.To(TestItem.AddressB) .SignedAndResolved(TestItem.PrivateKeyA).WithValue(0.Ether()).WithNonce(5).TestObject; ValueTask<(Keccak? Hash, AcceptTxResult? AddTxResult)> resultNextNonce = - ctx.Test.TxSender.SendTransaction(txWithNextNonce, TxHandlingOptions.None)!; + ctx.Test.TxSender.SendTransaction(txWithNextNonce, TxHandlingOptions.None); ValueTask<(Keccak? Hash, AcceptTxResult? AddTxResult)> resultFutureNonce = - ctx.Test.TxSender.SendTransaction(txWithFutureNonce, TxHandlingOptions.None)!; + ctx.Test.TxSender.SendTransaction(txWithFutureNonce, TxHandlingOptions.None); Assert.That(AcceptTxResult.Accepted, Is.EqualTo(resultNextNonce.Result.AddTxResult)); Assert.That(AcceptTxResult.Accepted, Is.EqualTo(resultFutureNonce.Result.AddTxResult)); - string serialized = await ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressA.Bytes.ToHexString(true), blockParameter); + string serialized = ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressA.Bytes.ToHexString(true), blockParameter); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"{expectedResult}\",\"id\":67}}")); } @@ -215,7 +215,7 @@ public async Task Eth_get_tx_count(string blockParameter, string expectedResult) public async Task Eth_get_tx_count_default_block() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressA.Bytes.ToHexString(true)); + string serialized = ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressA.Bytes.ToHexString(true)); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x3\",\"id\":67}")); } @@ -223,16 +223,16 @@ public async Task Eth_get_tx_count_default_block() public async Task Eth_get_tx_count_pending_block() { using Context ctx = await Context.Create(); - string serializedPendingBefore = await ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressB.Bytes.ToHexString(true), "pending"); + string serializedPendingBefore = ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressB.Bytes.ToHexString(true), "pending"); Assert.That(serializedPendingBefore, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x0\",\"id\":67}")); Transaction txWithNextNonce = Build.A.Transaction.To(TestItem.AddressA) .SignedAndResolved(TestItem.PrivateKeyB).WithValue(0.Ether()).WithNonce(0).TestObject; ValueTask<(Keccak? Hash, AcceptTxResult? AddTxResult)> resultNextNonce = - ctx.Test.TxSender.SendTransaction(txWithNextNonce, TxHandlingOptions.None)!; + ctx.Test.TxSender.SendTransaction(txWithNextNonce, TxHandlingOptions.None); Assert.That(AcceptTxResult.Accepted, Is.EqualTo(resultNextNonce.Result.AddTxResult)); - string serializedLatestAfter = await ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressB.Bytes.ToHexString(true)); + string serializedLatestAfter = ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressB.Bytes.ToHexString(true)); Assert.That(serializedLatestAfter, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x0\",\"id\":67}")); - string serializedPendingAfter = await ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressB.Bytes.ToHexString(true), "pending"); + string serializedPendingAfter = ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressB.Bytes.ToHexString(true), "pending"); Assert.That(serializedPendingAfter, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x1\",\"id\":67}")); } @@ -240,8 +240,8 @@ public async Task Eth_get_tx_count_pending_block() public async Task Eth_get_filter_changes_empty() { using Context ctx = await Context.Create(); - _ = await ctx.Test.TestEthRpc("eth_newBlockFilter"); - string serialized2 = await ctx.Test.TestEthRpc("eth_getFilterChanges", "0"); + _ = ctx.Test.TestEthRpc("eth_newBlockFilter"); + string serialized2 = ctx.Test.TestEthRpc("eth_getFilterChanges", "0"); Assert.That(serialized2, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[],\"id\":67}")); } @@ -249,7 +249,7 @@ public async Task Eth_get_filter_changes_empty() public async Task Eth_get_filter_changes_missing() { using Context ctx = await Context.Create(); - string serialized2 = await ctx.Test.TestEthRpc("eth_getFilterChanges", "0"); + string serialized2 = ctx.Test.TestEthRpc("eth_getFilterChanges", "0"); Assert.That(serialized2, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32000,\"message\":\"Filter not found\"},\"id\":67}")); } @@ -257,8 +257,8 @@ public async Task Eth_get_filter_changes_missing() public async Task Eth_uninstall_filter() { using Context ctx = await Context.Create(); - _ = await ctx.Test.TestEthRpc("eth_newBlockFilter"); - string serialized2 = await ctx.Test.TestEthRpc("eth_uninstallFilter", "0"); + _ = ctx.Test.TestEthRpc("eth_newBlockFilter"); + string serialized2 = ctx.Test.TestEthRpc("eth_uninstallFilter", "0"); Assert.That(serialized2, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}")); } @@ -266,9 +266,9 @@ public async Task Eth_uninstall_filter() public async Task Eth_get_filter_changes_with_block() { using Context ctx = await Context.Create(); - _ = await ctx.Test.TestEthRpc("eth_newBlockFilter"); + _ = ctx.Test.TestEthRpc("eth_newBlockFilter"); await ctx.Test.AddBlock(); - string serialized2 = await ctx.Test.TestEthRpc("eth_getFilterChanges", "0"); + string serialized2 = ctx.Test.TestEthRpc("eth_getFilterChanges", "0"); Assert.That(serialized2, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[\"0x166781de9c5f3328b7fc59c32e1dd1ec892021d95578258004ee221863a817a0\"],\"id\":67}"), serialized2.Replace("\"", "\\\"")); } @@ -298,7 +298,7 @@ void handleNewBlock(object? sender, BlockReplacementEventArgs e) test.BlockTree.BlockAddedToMain += handleNewBlock; var newFilterResp = RpcTest.TestRequest(test.EthRpcModule, "eth_newFilter", "{\"fromBlock\":\"latest\"}"); - string getFilterLogsSerialized1 = await test.TestEthRpc("eth_getFilterChanges", (newFilterResp as JsonRpcSuccessResponse)!.Result?.ToString() ?? "0x0"); + string getFilterLogsSerialized1 = test.TestEthRpc("eth_getFilterChanges", (newFilterResp as JsonRpcSuccessResponse)!.Result?.ToString() ?? "0x0"); //expect empty - no changes so far Assert.That(getFilterLogsSerialized1, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[],\"id\":67}")); @@ -306,11 +306,11 @@ void handleNewBlock(object? sender, BlockReplacementEventArgs e) await test.AddBlock(createCodeTx); //expect new transaction logs - string getFilterLogsSerialized2 = await test.TestEthRpc("eth_getFilterChanges", (newFilterResp as JsonRpcSuccessResponse)!.Result?.ToString() ?? "0x0"); + string getFilterLogsSerialized2 = test.TestEthRpc("eth_getFilterChanges", (newFilterResp as JsonRpcSuccessResponse)!.Result?.ToString() ?? "0x0"); Assert.That(getFilterLogsSerialized2, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[{\"address\":\"0x0ffd3e46594919c04bcfd4e146203c8255670828\",\"blockHash\":\"0x2eb166ba88c43f96f980a573aebcee792fda4d34ad4c353dfd3d08cdf80adfae\",\"blockNumber\":\"0x4\",\"data\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"logIndex\":\"0x0\",\"removed\":false,\"topics\":[],\"transactionHash\":\"0x8c9c109bff7969c8aed8e51ab4ea35c6f835a0c3266bc5c5721821a38cbf5445\",\"transactionIndex\":\"0x0\",\"transactionLogIndex\":\"0x0\"}],\"id\":67}")); //expect empty - previous call cleans logs - string getFilterLogsSerialized3 = await test.TestEthRpc("eth_getFilterChanges", (newFilterResp as JsonRpcSuccessResponse)!.Result?.ToString() ?? "0x0"); + string getFilterLogsSerialized3 = test.TestEthRpc("eth_getFilterChanges", (newFilterResp as JsonRpcSuccessResponse)!.Result?.ToString() ?? "0x0"); Assert.That(getFilterLogsSerialized3, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[],\"id\":67}")); } @@ -318,9 +318,9 @@ void handleNewBlock(object? sender, BlockReplacementEventArgs e) public async Task Eth_get_filter_changes_with_tx() { using Context ctx = await Context.Create(); - _ = await ctx.Test.TestEthRpc("eth_newPendingTransactionFilter"); + _ = ctx.Test.TestEthRpc("eth_newPendingTransactionFilter"); ctx.Test.AddTransactions(Build.A.Transaction.SignedAndResolved(TestItem.PrivateKeyD).TestObject); - string serialized2 = await ctx.Test.TestEthRpc("eth_getFilterChanges", "0"); + string serialized2 = ctx.Test.TestEthRpc("eth_getFilterChanges", "0"); Assert.That(serialized2, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[\"0x190d9a78dbc61b1856162ab909976a1b28ba4a41ee041341576ea69686cd3b29\"],\"id\":67}"), serialized2.Replace("\"", "\\\"")); } @@ -332,7 +332,7 @@ public async Task Eth_get_filter_changes_with_tx() public async Task Eth_get_storage_at(string blockParameter, string expectedResult) { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getStorageAt", TestItem.AddressA.Bytes.ToHexString(true), "0x1", blockParameter); + string serialized = ctx.Test.TestEthRpc("eth_getStorageAt", TestItem.AddressA.Bytes.ToHexString(true), "0x1", blockParameter); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"{expectedResult}\",\"id\":67}}")); } @@ -340,7 +340,7 @@ public async Task Eth_get_storage_at(string blockParameter, string expectedResul public async Task Eth_get_storage_at_default_block() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getStorageAt", TestItem.AddressA.Bytes.ToHexString(true), "0x1"); + string serialized = ctx.Test.TestEthRpc("eth_getStorageAt", TestItem.AddressA.Bytes.ToHexString(true), "0x1"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x0000000000000000000000000000000000000000000000000000000000abcdef\",\"id\":67}")); } @@ -348,7 +348,7 @@ public async Task Eth_get_storage_at_default_block() public async Task Eth_get_block_number() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_blockNumber"); + string serialized = ctx.Test.TestEthRpc("eth_blockNumber"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x3\",\"id\":67}")); } @@ -360,7 +360,7 @@ public async Task Eth_get_balance_internal_error() blockTree.Head.Returns((Block?)null); ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockTree).Build(); - string serialized = await ctx.Test.TestEthRpc("eth_getBalance", TestItem.AddressA.Bytes.ToHexString(true), "0x01"); + string serialized = ctx.Test.TestEthRpc("eth_getBalance", TestItem.AddressA.Bytes.ToHexString(true), "0x01"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32603,\"message\":\"Incorrect head block\"},\"id\":67}")); } @@ -369,7 +369,7 @@ public async Task Eth_get_balance_internal_error() public async Task Eth_get_balance_incorrect_parameters() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getBalance", TestItem.KeccakA.Bytes.ToHexString(true), "0x01"); + string serialized = ctx.Test.TestEthRpc("eth_getBalance", TestItem.KeccakA.Bytes.ToHexString(true), "0x01"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"Invalid params\"},\"id\":67}")); } @@ -392,7 +392,7 @@ public async Task Eth_syncing_true() header = newHeader; } - string serialized = await ctx.Test.TestEthRpc("eth_syncing"); + string serialized = ctx.Test.TestEthRpc("eth_syncing"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"startingBlock\":\"0x0\",\"currentBlock\":\"0x384\",\"highestBlock\":\"0x3e8\"},\"id\":67}")); } @@ -416,7 +416,7 @@ public async Task Eth_syncing_false() header = newHeader; } - string serialized = await ctx.Test.TestEthRpc("eth_syncing"); + string serialized = ctx.Test.TestEthRpc("eth_syncing"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":67}")); } @@ -434,7 +434,7 @@ public async Task Eth_get_filter_logs() }); ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).Build(); - string serialized = await ctx.Test.TestEthRpc("eth_getFilterLogs", "0x01"); + string serialized = ctx.Test.TestEthRpc("eth_getFilterLogs", "0x01"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[{\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"blockHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockNumber\":\"0x1\",\"data\":\"0x010203\",\"logIndex\":\"0x1\",\"removed\":false,\"topics\":[\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"0x6c3fd336b49dcb1c57dd4fbeaf5f898320b0da06a5ef64e798c6497600bb79f2\"],\"transactionHash\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"transactionIndex\":\"0x1\",\"transactionLogIndex\":\"0x0\"}],\"id\":67}")); } @@ -448,7 +448,7 @@ public async Task Eth_get_filter_logs_filter_not_found() .Returns(x => { x[1] = null; return false; }); ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).Build(); - string serialized = await ctx.Test.TestEthRpc("eth_getFilterLogs", "0x05"); + string serialized = ctx.Test.TestEthRpc("eth_getFilterLogs", "0x05"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32603,\"message\":\"Filter with id: '5' does not exist.\"},\"id\":67}")); } @@ -461,7 +461,7 @@ public async Task Eth_get_filter_logs_filterId_overflow() UInt256 filterId = int.MaxValue + (UInt256)10; ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).Build(); - string serialized = await ctx.Test.TestEthRpc("eth_getFilterLogs", $"0x{filterId.ToString("X")}"); + string serialized = ctx.Test.TestEthRpc("eth_getFilterLogs", $"0x{filterId.ToString("X")}"); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"error\":{{\"code\":-32603,\"message\":\"Filter with id: '{filterId}' does not exist.\"}},\"id\":67}}")); } @@ -492,13 +492,13 @@ void handleNewBlock(object? sender, BlockReplacementEventArgs e) await test.AddBlock(createCodeTx); - string getLogsSerialized = await test.TestEthRpc("eth_getLogs", $"{{\"fromBlock\":\"{blockHash}\"}}"); + string getLogsSerialized = test.TestEthRpc("eth_getLogs", $"{{\"fromBlock\":\"{blockHash}\"}}"); var newFilterResp = RpcTest.TestRequest(test.EthRpcModule, "eth_newFilter", $"{{\"fromBlock\":\"{blockHash}\"}}"); Assert.IsTrue(newFilterResp is not null && newFilterResp is JsonRpcSuccessResponse); - string getFilterLogsSerialized = await test.TestEthRpc("eth_getFilterLogs", (newFilterResp as JsonRpcSuccessResponse)!.Result?.ToString() ?? "0x0"); + string getFilterLogsSerialized = test.TestEthRpc("eth_getFilterLogs", (newFilterResp as JsonRpcSuccessResponse)!.Result?.ToString() ?? "0x0"); Assert.That(getFilterLogsSerialized, Is.EqualTo(getLogsSerialized)); } @@ -514,42 +514,15 @@ public async Task Eth_get_logs(string parameter, string expected) { using Context ctx = await Context.Create(); IBlockchainBridge bridge = Substitute.For(); - bridge.GetLogs(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any>(), Arg.Any()) - .Returns(new[] { new FilterLog(1, 0, 1, TestItem.KeccakA, 1, TestItem.KeccakB, TestItem.AddressA, new byte[] { 1, 2, 3 }, new[] { TestItem.KeccakC, TestItem.KeccakD }) }); + bridge.GetLogs(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any>(), Arg.Any()).Returns(new[] { new FilterLog(1, 0, 1, TestItem.KeccakA, 1, TestItem.KeccakB, TestItem.AddressA, new byte[] { 1, 2, 3 }, new[] { TestItem.KeccakC, TestItem.KeccakD }) }); bridge.FilterExists(1).Returns(true); ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).Build(); - string serialized = await ctx.Test.TestEthRpc("eth_getLogs", parameter); + string serialized = ctx.Test.TestEthRpc("eth_getLogs", parameter); Assert.That(serialized, Is.EqualTo(expected)); } - [Test] - public async Task Eth_get_logs_cancellation() - { - using Context ctx = await Context.Create(); - IBlockchainBridge bridge = Substitute.For(); - bridge.GetLogs(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any>(), Arg.Any()) - .Returns(c => - { - return GetLogs(c.ArgAt(4)); - - [DoesNotReturn] - IEnumerable GetLogs(CancellationToken ct) - { - while (true) - { - Thread.Sleep(10); - ct.ThrowIfCancellationRequested(); - } - } - }); - - ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).WithConfig(new JsonRpcConfig() { Timeout = 50 }).Build(); - string serialized = await ctx.Test.TestEthRpc("eth_getLogs", "{}"); - serialized.Should().Be("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32016,\"message\":\"eth_getLogs request was canceled due to enabled timeout.\"},\"id\":67}"); - } - [TestCase("{\"fromBlock\":\"earliest\",\"toBlock\":\"latest\"}", "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"resource not found message\"},\"id\":67}")] public async Task Eth_get_logs_with_resourceNotFound(string parameter, string expected) { @@ -560,7 +533,7 @@ public async Task Eth_get_logs_with_resourceNotFound(string parameter, string ex bridge.FilterExists(1).Returns(true); ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).Build(); - string serialized = await ctx.Test.TestEthRpc("eth_getLogs", parameter); + string serialized = ctx.Test.TestEthRpc("eth_getLogs", parameter); Assert.That(serialized, Is.EqualTo(expected)); } @@ -569,7 +542,7 @@ public async Task Eth_get_logs_with_resourceNotFound(string parameter, string ex public async Task Eth_tx_count_by_hash() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getBlockTransactionCountByHash", ctx.Test.BlockTree.Genesis!.Hash!.ToString()); + string serialized = ctx.Test.TestEthRpc("eth_getBlockTransactionCountByHash", ctx.Test.BlockTree.Genesis!.Hash!.ToString()); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x0\",\"id\":67}")); } @@ -577,7 +550,7 @@ public async Task Eth_tx_count_by_hash() public async Task Eth_uncle_count_by_hash() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getUncleCountByBlockHash", ctx.Test.BlockTree.Genesis!.Hash!.ToString()); + string serialized = ctx.Test.TestEthRpc("eth_getUncleCountByBlockHash", ctx.Test.BlockTree.Genesis!.Hash!.ToString()); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x0\",\"id\":67}")); } @@ -588,7 +561,7 @@ public async Task Eth_uncle_count_by_hash() public async Task Eth_uncle_count_by_number(string blockParameter, string expectedResult) { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getUncleCountByBlockNumber", blockParameter); + string serialized = ctx.Test.TestEthRpc("eth_getUncleCountByBlockNumber", blockParameter); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":{expectedResult},\"id\":67}}")); } @@ -599,7 +572,7 @@ public async Task Eth_uncle_count_by_number(string blockParameter, string expect public async Task Eth_tx_count_by_number(string blockParameter, string expectedResult) { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getBlockTransactionCountByNumber", blockParameter); + string serialized = ctx.Test.TestEthRpc("eth_getBlockTransactionCountByNumber", blockParameter); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":{expectedResult},\"id\":67}}")); } @@ -611,7 +584,7 @@ public async Task Eth_get_block_by_hash(bool aura, bool eip1559, string expected { using Context ctx = eip1559 ? await Context.CreateWithLondonEnabled() : await Context.Create(); TestRpcBlockchain testBlockchain = (aura ? ctx.AuraTest : ctx.Test); - string serialized = await testBlockchain.TestEthRpc("eth_getBlockByHash", testBlockchain.BlockTree.Genesis!.Hash!.ToString(), "true"); + string serialized = testBlockchain.TestEthRpc("eth_getBlockByHash", testBlockchain.BlockTree.Genesis!.Hash!.ToString(), "true"); Assert.That(serialized, Is.EqualTo(expected)); } @@ -619,22 +592,22 @@ public async Task Eth_get_block_by_hash(bool aura, bool eip1559, string expected public async Task Eth_get_block_by_hash_null() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getBlockByHash", Keccak.Zero.ToString(), "true"); + string serialized = ctx.Test.TestEthRpc("eth_getBlockByHash", Keccak.Zero.ToString(), "true"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":67}")); } [TestCase("0x71eac5e72c3b64431c246173352a8c625c8434d944eb5f3f58204fec3ec36b54", false, "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0xa410\",\"hash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x49e7d7466be0927347ff2f654c014a768b5a5fcd8c483635210466dd0d6d204c\",\"receiptsRoot\":\"0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x2cb\",\"stateRoot\":\"0x4e786afc8bed76b7299973ca70022b367cbb94c14ec30e9e7273b31b6b968de9\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"transactions\":[\"0x681c2b6f99e37fd6fe6046db8b51ec3460d699cacd6a376143fd5842ac50621f\",\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\"],\"transactionsRoot\":\"0x2e6e6deb19d24bd48eda6071ab38b1bae64c15ef1998c96f0d153711d3a3efc7\",\"uncles\":[]},\"id\":67}")] - [TestCase("0x71eac5e72c3b64431c246173352a8c625c8434d944eb5f3f58204fec3ec36b54", true, "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0xa410\",\"hash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x49e7d7466be0927347ff2f654c014a768b5a5fcd8c483635210466dd0d6d204c\",\"receiptsRoot\":\"0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x2cb\",\"stateRoot\":\"0x4e786afc8bed76b7299973ca70022b367cbb94c14ec30e9e7273b31b6b968de9\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"transactions\":[{\"hash\":\"0x681c2b6f99e37fd6fe6046db8b51ec3460d699cacd6a376143fd5842ac50621f\",\"nonce\":\"0x1\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x0\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"}],\"transactionsRoot\":\"0x2e6e6deb19d24bd48eda6071ab38b1bae64c15ef1998c96f0d153711d3a3efc7\",\"uncles\":[]},\"id\":67}")] + [TestCase("0x71eac5e72c3b64431c246173352a8c625c8434d944eb5f3f58204fec3ec36b54", true, "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0xa410\",\"hash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x49e7d7466be0927347ff2f654c014a768b5a5fcd8c483635210466dd0d6d204c\",\"receiptsRoot\":\"0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x2cb\",\"stateRoot\":\"0x4e786afc8bed76b7299973ca70022b367cbb94c14ec30e9e7273b31b6b968de9\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"transactions\":[{\"hash\":\"0x681c2b6f99e37fd6fe6046db8b51ec3460d699cacd6a376143fd5842ac50621f\",\"nonce\":\"0x1\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x0\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"}],\"transactionsRoot\":\"0x2e6e6deb19d24bd48eda6071ab38b1bae64c15ef1998c96f0d153711d3a3efc7\",\"uncles\":[]},\"id\":67}")] public async Task Eth_get_block_by_hash_with_tx(string blockParameter, bool withTxData, string expectedResult) { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getBlockByHash", ctx.Test.BlockTree.Head!.Hash!.ToString(), withTxData.ToString()); + string serialized = ctx.Test.TestEthRpc("eth_getBlockByHash", ctx.Test.BlockTree.Head!.Hash!.ToString(), withTxData.ToString()); Assert.That(serialized, Is.EqualTo(expectedResult), serialized.Replace("\"", "\\\"")); } [TestCase(false, "earliest", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0xf4240\",\"extraData\":\"0x010203\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0x0\",\"hash\":\"0x2167088a0f0de66028d2b728235af6d467108c1750c3e11a8f6e6cd60fddb0e4\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x00000000000003e8\",\"number\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x201\",\"stateRoot\":\"0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f\",\"totalDifficulty\":\"0xf4240\",\"timestamp\":\"0xf4240\",\"transactions\":[],\"transactionsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"uncles\":[]},\"id\":67}")] - [TestCase(false, "latest", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0xa410\",\"hash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x49e7d7466be0927347ff2f654c014a768b5a5fcd8c483635210466dd0d6d204c\",\"receiptsRoot\":\"0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x2cb\",\"stateRoot\":\"0x4e786afc8bed76b7299973ca70022b367cbb94c14ec30e9e7273b31b6b968de9\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"transactions\":[{\"hash\":\"0x681c2b6f99e37fd6fe6046db8b51ec3460d699cacd6a376143fd5842ac50621f\",\"nonce\":\"0x1\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x0\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"}],\"transactionsRoot\":\"0x2e6e6deb19d24bd48eda6071ab38b1bae64c15ef1998c96f0d153711d3a3efc7\",\"uncles\":[]},\"id\":67}")] - [TestCase(false, "pending", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0xa410\",\"hash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x49e7d7466be0927347ff2f654c014a768b5a5fcd8c483635210466dd0d6d204c\",\"receiptsRoot\":\"0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x2cb\",\"stateRoot\":\"0x4e786afc8bed76b7299973ca70022b367cbb94c14ec30e9e7273b31b6b968de9\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"transactions\":[{\"hash\":\"0x681c2b6f99e37fd6fe6046db8b51ec3460d699cacd6a376143fd5842ac50621f\",\"nonce\":\"0x1\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x0\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"}],\"transactionsRoot\":\"0x2e6e6deb19d24bd48eda6071ab38b1bae64c15ef1998c96f0d153711d3a3efc7\",\"uncles\":[]},\"id\":67}")] + [TestCase(false, "latest", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0xa410\",\"hash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x49e7d7466be0927347ff2f654c014a768b5a5fcd8c483635210466dd0d6d204c\",\"receiptsRoot\":\"0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x2cb\",\"stateRoot\":\"0x4e786afc8bed76b7299973ca70022b367cbb94c14ec30e9e7273b31b6b968de9\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"transactions\":[{\"hash\":\"0x681c2b6f99e37fd6fe6046db8b51ec3460d699cacd6a376143fd5842ac50621f\",\"nonce\":\"0x1\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x0\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"}],\"transactionsRoot\":\"0x2e6e6deb19d24bd48eda6071ab38b1bae64c15ef1998c96f0d153711d3a3efc7\",\"uncles\":[]},\"id\":67}")] + [TestCase(false, "pending", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0xa410\",\"hash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x49e7d7466be0927347ff2f654c014a768b5a5fcd8c483635210466dd0d6d204c\",\"receiptsRoot\":\"0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x2cb\",\"stateRoot\":\"0x4e786afc8bed76b7299973ca70022b367cbb94c14ec30e9e7273b31b6b968de9\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"transactions\":[{\"hash\":\"0x681c2b6f99e37fd6fe6046db8b51ec3460d699cacd6a376143fd5842ac50621f\",\"nonce\":\"0x1\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x0\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"}],\"transactionsRoot\":\"0x2e6e6deb19d24bd48eda6071ab38b1bae64c15ef1998c96f0d153711d3a3efc7\",\"uncles\":[]},\"id\":67}")] [TestCase(false, "0x0", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0xf4240\",\"extraData\":\"0x010203\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0x0\",\"hash\":\"0x2167088a0f0de66028d2b728235af6d467108c1750c3e11a8f6e6cd60fddb0e4\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x00000000000003e8\",\"number\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x201\",\"stateRoot\":\"0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f\",\"totalDifficulty\":\"0xf4240\",\"timestamp\":\"0xf4240\",\"transactions\":[],\"transactionsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"uncles\":[]},\"id\":67}")] [TestCase(true, "earliest", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0xf4240\",\"extraData\":\"0x010203\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0x0\",\"hash\":\"0x2167088a0f0de66028d2b728235af6d467108c1750c3e11a8f6e6cd60fddb0e4\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x00000000000003e8\",\"number\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x201\",\"stateRoot\":\"0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f\",\"totalDifficulty\":\"0xf4240\",\"timestamp\":\"0xf4240\",\"baseFeePerGas\":\"0x0\",\"transactions\":[],\"transactionsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"uncles\":[]},\"id\":67}")] [TestCase(true, "latest", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x7a1200\",\"gasUsed\":\"0x0\",\"hash\":\"0x16b111d85efa64c1c8e27f1e59c8ccd6bb6643b1999628ac37294c31158e2245\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x761cfe357802c8a2a68e37ad8325607920e72ce19b5b0d3e1ba01840f7e905ec\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x20b\",\"stateRoot\":\"0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"baseFeePerGas\":\"0x2da282a8\",\"transactions\":[],\"transactionsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"uncles\":[]},\"id\":67}")] @@ -643,7 +616,7 @@ public async Task Eth_get_block_by_hash_with_tx(string blockParameter, bool with public async Task Eth_get_block_by_number(bool eip1559, string blockParameter, string expectedResult) { using Context ctx = eip1559 ? await Context.CreateWithLondonEnabled() : await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getBlockByNumber", blockParameter, "true"); + string serialized = ctx.Test.TestEthRpc("eth_getBlockByNumber", blockParameter, "true"); Assert.That(serialized, Is.EqualTo(expectedResult), serialized.Replace("\"", "\\\"")); } @@ -655,10 +628,10 @@ public async Task Eth_get_block_by_number(bool eip1559, string blockParameter, s public async Task Eth_get_block_by_number_no_details(string blockParameter, string expectedResult) { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getBlockByNumber", blockParameter, "false"); + string serialized = ctx.Test.TestEthRpc("eth_getBlockByNumber", blockParameter, "false"); Assert.That(serialized, Is.EqualTo(expectedResult), serialized.Replace("\"", "\\\"")); - string serialized2 = await ctx.Test.TestEthRpc("eth_getBlockByNumber", blockParameter); + string serialized2 = ctx.Test.TestEthRpc("eth_getBlockByNumber", blockParameter); Assert.That(serialized2, Is.EqualTo(expectedResult), serialized2); } @@ -667,7 +640,7 @@ public async Task Eth_get_block_by_number_should_not_recover_tx_senders_for_requ { IBlockchainBridge? blockchainBridge = Substitute.For(); TestRpcBlockchain ctx = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(blockchainBridge).Build(MainnetSpecProvider.Instance); - await ctx.TestEthRpc("eth_getBlockByNumber", blockParameter, "false"); + ctx.TestEthRpc("eth_getBlockByNumber", blockParameter, "false"); blockchainBridge.Received(0).RecoverTxSenders(Arg.Any()); } @@ -676,7 +649,7 @@ public async Task Eth_get_block_by_number_should_not_recover_tx_senders_for_requ public async Task Eth_get_block_by_number_null() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getBlockByNumber", "1000000", "false"); + string serialized = ctx.Test.TestEthRpc("eth_getBlockByNumber", "1000000", "false"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":67}")); } @@ -684,7 +657,7 @@ public async Task Eth_get_block_by_number_null() public async Task Eth_protocol_version() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_protocolVersion"); + string serialized = ctx.Test.TestEthRpc("eth_protocolVersion"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x42\",\"id\":67}")); } @@ -692,7 +665,7 @@ public async Task Eth_protocol_version() public async Task Eth_get_code() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getCode", TestItem.AddressA.ToString(), "latest"); + string serialized = ctx.Test.TestEthRpc("eth_getCode", TestItem.AddressA.ToString(), "latest"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0xabcd\",\"id\":67}")); } @@ -700,15 +673,39 @@ public async Task Eth_get_code() public async Task Eth_get_code_default() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getCode", TestItem.AddressA.ToString()); + string serialized = ctx.Test.TestEthRpc("eth_getCode", TestItem.AddressA.ToString()); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0xabcd\",\"id\":67}")); } + [Test] + public async Task Eth_mining_true() + { + using Context ctx = await Context.Create(); + IBlockchainBridge bridge = Substitute.For(); + bridge.IsMining.Returns(true); + ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).Build(); + + string serialized = ctx.Test.TestEthRpc("eth_mining"); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}")); + } + + [Test] + public async Task Eth_mining_false() + { + using Context ctx = await Context.Create(); + IBlockchainBridge bridge = Substitute.For(); + bridge.IsMining.Returns(false); + ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).Build(); + + string serialized = ctx.Test.TestEthRpc("eth_mining"); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":67}")); + } + [Test] public async Task Eth_accounts() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_accounts"); + string serialized = ctx.Test.TestEthRpc("eth_accounts"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[\"0x7e5f4552091a69125d5dfcb7b8c2659029395bdf\",\"0x2b5ad5c4795c026514f8317c7a215e218dccd6cf\",\"0x6813eb9362372eef6200f3b1dbc3f819671cba69\",\"0x1eff47bc3a10a45d4b230b5d10e37751fe6aa718\",\"0xe1ab8145f7e55dc933d51a18c793f901a3a0b276\",\"0xe57bfe9f44b819898f47bf37e5af72a0783e1141\",\"0xd41c057fd1c78805aac12b0a94a405c0461a6fbb\",\"0xf1f6619b38a98d6de0800f1defc0a6399eb6d30c\",\"0xf7edc8fa1ecc32967f827c9043fcae6ba73afa5c\",\"0x4cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528\",\"0x3da8d322cb2435da26e9c9fee670f9fb7fe74e49\",\"0xdbc23ae43a150ff8884b02cea117b22d1c3b9796\",\"0x68e527780872cda0216ba0d8fbd58b67a5d5e351\",\"0x5a83529ff76ac5723a87008c4d9b436ad4ca7d28\",\"0x8735015837bd10e05d9cf5ea43a2486bf4be156f\",\"0xfae394561e33e242c551d15d4625309ea4c0b97f\",\"0x252dae0a4b9d9b80f504f6418acd2d364c0c59cd\",\"0x79196b90d1e952c5a43d4847caa08d50b967c34a\",\"0x4bd1280852cadb002734647305afc1db7ddd6acb\",\"0x811da72aca31e56f770fc33df0e45fd08720e157\",\"0x157bfbecd023fd6384dad2bded5dad7e27bf92e4\",\"0x37da28c050e3c0a1c0ac3be97913ec038783da4c\",\"0x3bc8287f1d872df4217283b7920d363f13cf39d8\",\"0xf4e2b0fcbd0dc4b326d8a52b718a7bb43bdbd072\",\"0x9a5279029e9a2d6e787c5a09cb068ab3d45e209d\",\"0xc39677f5f47d5fe65ab24e66750e8fca127c15be\",\"0x1dc728786e09f862e39be1f39dd218ee37feb68d\",\"0x636cc65783084b9f370789c90f733dbbeb88925d\",\"0x4a7a7c2e09209dbe44a582cd92b0edd7129e74be\",\"0xa56160a359f2eaa66f5c9df5245542b07339a9a6\",\"0x6b09d6433a379752157fd1a9e537c5cae5fa3168\",\"0x32e77de0d74a5c7af861aaed324c6a4c488142a8\",\"0x093d49d617a10f26915553255ec3fee532d2c12f\",\"0x138854708d8b603c9b7d4d6e55b6d32d40557f4d\",\"0x7dc0a40d64d72bb4590652b8f5c687bf7f26400c\",\"0x9358a525cc25aa571af0bcb5b98fbeab045a5e36\",\"0xd8e8ea89d71de89214fa39ba13ba9fcddc0d9467\",\"0xb56ed8f48979e1a948ad129199a600d0562cac51\",\"0xf65ac7003e905d72c666bfec1dc0960ecc9d0d6e\",\"0xd817d23c981472d703be36da777ffdb1abefd972\",\"0xf2adb90aa27a3c61a95c50063b20919d811e1476\",\"0xae3dffee97f92db0201d11cb8877c89738353bce\",\"0xeb3025e7ac2764040384316b33476e048961a71f\",\"0x9e3289708dc5709926a542fcf260fd4b210461f0\",\"0x6c23face014f20b3ebb65ae96d0d7ff32ab94c17\",\"0xb83b6241f966b1685c8b2ffce3956e21f35b4dcb\",\"0x6350872d7465864689def650443026f2f73a08da\",\"0x673c638147fe91e4277646d86d5ae82f775eea5c\",\"0xf472086186382fca55cd182de196520abd76f69d\",\"0x5ae58d2bc5145bff0c1bec0f32bfc2d079bc66ed\",\"0x2b29bea668b044b2b355c370f85b729bcb43ec40\",\"0x3797126345fb5fb6a37629db55ec692173cfb458\",\"0xe6869cc98283ab53e8a1a5312857ef0be9d189fe\",\"0xa5dfe354b3fc30c5c3a8ffefc8f9470d9177c334\",\"0xa1a625ae13b80a9c48b7c0331c83bc4541ac137f\",\"0xa33c9d26e1e33b84247defca631c1d30ffc76f5d\",\"0xf9807a8719ae154e74591cb2d452797707fadf73\",\"0xa1ba6fc3ea0e89f0e79f89d9aa0081d010571e4a\",\"0x366c20b40048556e5682e360997537c3715aca0e\",\"0xeb0e56f32246d043228fac8b63a71687d5199af1\",\"0xdb3ed822b78f0641623a12166607b5fa4df862ad\",\"0xb88c19426f03c6981d1a4281c7414d842b97619a\",\"0x32e04b012ac811c91d36a355a6d2859a0071a965\",\"0xe0dd44773f7657b11019062879d65f3d9862460c\",\"0x756be12856a8f44ab22fdbcbd42b70b843377d09\",\"0x6f4c950442e1af093bcff730381e63ae9171b87a\",\"0x4d1bf28514a4451249908e611366ec967c3d1558\",\"0xb0142d883494197b02c6ece84f571d81bd831124\",\"0x1326324f5a9fb193409e10006e4ea41b970df321\",\"0xf9a2c330a19e2fbfeb50fe7a7195b973bb0a3be9\",\"0x7a601ffa997cede6435aeabf4fa2091f09e149ec\",\"0xa92f4b5c4fddcc37e5139873ac28a4a0a42d68df\",\"0x850cc185d6cae4a7fdfb3dd81f977dd1df7d6503\",\"0xb1b7c87e8a0bf2e7fd1a1c582bd353e4c4529341\",\"0xff844fdb49e00776ad538db9ea2f9fa98ec0caf7\",\"0x1ac6f9601f2f616badcea8a0a307e1a3c14767a4\",\"0xc2aa6271409c10dee630e79df90c968989ccf2b7\",\"0x883d01eae6eaac077e126ddb32cd53550966ed76\",\"0x127688bbc070dd69a4db8c3ba5d43909e13d8f77\",\"0x0b54a50c0409dab2e63c3566324268ed53ec019a\",\"0xafd46e3549cc63d7a240d6177d056857679e6f99\",\"0x752481f35bb1d44d786c7b4dbe40db4a4266f96f\",\"0xac32def421e36b43629f785fd04523260e7f2b28\",\"0xfe6032a0810e90d025a3a39dd29844f964ee102c\",\"0x5cb6f3e6499d1f068b33351d0cae4b68cdf501bf\",\"0x84b743441b7bdf65cb4293126db4c1b709d7d95e\",\"0x8530a26f6c062f55597bd30c1a44e248decb0027\",\"0x5ce162cfa6208d7c50a7cb3525ac126155e7bce4\",\"0x2853dc9ca40d012969e25360cce0d9d326b24a86\",\"0x802271c02f76701929e1ea772e72783d28e4b60f\",\"0x7bd2aa0726ac3b9e752b120de8568e90b0423ae4\",\"0xb540c05d9b2516da9596a5ee75d750717a4be035\",\"0xa72392cd4be285ab6681da1bf1c45f0b370cb7b4\",\"0xcf484269182ac2388a4bfe6d19fb0687e3534b7f\",\"0x994907cb80bfd175f9b0b32672cfde0091368e2e\",\"0x36eab6ce7fededc098ef98c41e83548a89147131\",\"0x440db3ab842910d2a39f4e1be9e017c6823fb658\",\"0x25ac70ea6f44c4531a7117ea3620fa29cdaaca48\",\"0x24d881139ee639c2a774b4b1851cb7a9d0fce122\",\"0xd9a284367b6d3e25a91c91b5a430af2593886eb9\",\"0xe6b3367318c5e11a6eed3cd0d850ec06a02e9b90\",\"0x88c0e901bd1fd1a77bda342f0d2210fdc71cef6b\",\"0x7231c364597f3bfdb72cf52b197cc59111e71794\",\"0x043aed06383f290ee28fa02794ec7215ca099683\",\"0x0c95931d95694b3ef74071241827c09f25d40620\",\"0x417f3b59ef57c641283c2300fae0f27fe98d518c\",\"0xd6b931d8d441b1ec98f55f8ec8adb532dc140c78\",\"0x9220625b1a30680387d542e6b5f753786ca5530e\",\"0x997cf669860a1dcc76344866534d8679a7b562e2\",\"0xb961768b578514debf079017ff78c47b0a6adbf6\",\"0x052b91ad9732d1bce0ddae15a4545e5c65d02443\",\"0x8df64de79608f0ae9e72ecae3a400582aed8101c\",\"0x0e7b23cd1fdb7ea3ccc80320ab43843a2f193c36\",\"0xfbbc41289f834a76e4320ac238512035560467ee\",\"0x61e1da6c7b8b211e6e5dd921efe27e73ad226dac\",\"0x87fcbe64187317c59a944be5b9c5c830b9373730\",\"0x2acf0d6fdac920081a446868b2f09a8dac797448\",\"0x1715eb68afba4d516ef1e068b55f5093bb4a2f59\",\"0x58bab2f728dc4fc227a4c38cab2ec93b73b4e828\",\"0x25346934b4faa00dee0190c2069156bde6010c18\",\"0xa01cca6367a84304b6607b76676c66c360b74741\",\"0x872917cec8992487651ee633dba73bd3a9dca309\",\"0x6c1a01c2ab554930a937b0a2e8105fb47946c679\",\"0x13c0e7c715fdea35c7f9663c719e4d36601275b9\",\"0xe8c5025c803f3279d94ea55598e147f601929bf4\",\"0x639acdbd838b81cea8d6a970136812783fa5bf5e\",\"0xb3087f34edab33a8182ba29adea4d739d9831a94\",\"0xc6a210606f2ee6e64afb9584db054f3476a5cc66\",\"0xd01c9d93efc83c00b30f768f832182beff65696f\",\"0x00edf2d16afbc028fb1e879559b07997af79539f\",\"0xf5d722030d17ca01f2813af9e7be158d7a037997\",\"0xae3d43ab6fdcd35386db427099ff11aa670ee0f4\",\"0x0dc8b8ef8457b1e45ac277d65ac5987b547ba775\",\"0xde521346f9327a4314a18b2cda96b2a33603177a\",\"0x69842e12d6f36f9f93f06086b70795bfc7e02745\",\"0x9b7bdf6ad17d5fc9a168acaa24495e52a65f3b79\",\"0xa2d47d2c42009520075cb15f5855052008d0c44d\",\"0xb0c249f6f92fb2491fc9750a5299d856ba2ea3c6\",\"0x839d96957f21e82fbcca0d42a1f12ef6e1cf82e9\",\"0x2a0d6b92b042497013e5549d6579202608ce0c80\",\"0xa4f8c598927eab2f1898f8f2d6f8121578de2344\",\"0xdb21655b672dacc8da6f538c899f9d6969604117\",\"0x21289cd01f9f58fc44962b6e213a0fbbd015beb6\",\"0x0b62d63c314d94dfa85b11a9c652ffe438382d6c\",\"0x9383e3096133f464d516b518b12851fd10d891f4\",\"0x64e582c17ab7c3b90e171795b504ca3c04108501\",\"0x848406919d014b1e5c27a82f951caff840fd63ef\",\"0x5fe015779fb36006b01f9c5a5dbcaa6ffa56f0c0\",\"0x28b6e15f86025b8ea8beaa6855a81069bfb6ab1e\",\"0x271d65af9a5a7b4cd7af264f251184c2a4b9e7a3\",\"0xddf44e34ed40c40624c7b9f20a1030b505a4fac0\",\"0xe5854075272ca5ef71663d5b87e0cd5ac53b2f36\",\"0x2798ba84d7830c5f60d750f37f87d93277106905\",\"0x7e9961fa09dd52f945f8143844785cf0e51bb4ce\",\"0xf33d2f7d96f92d912ca8418f9d62eb54c1a9889f\",\"0xeec566c793a89f388bbabfc0225183a6a95c4263\",\"0x2001f8cdcdeef1bbcc188ca59cf04fb44133d55a\",\"0x3bf958fa0626e898f548a8f95cf9ab3a4db65169\",\"0xb0d744fde06bbcb6655eb55288ec94fa6a0b2a52\",\"0x18eb36d090eeadf82f3454a6da690fc398d3eba1\",\"0xd2431ca38735c2fd438e2caa23f094191d89675b\",\"0x612b7be154a64292aae070aaa86fcd66ba218071\",\"0x681ce2f439fdc80e70c1eea8b8a085dfb976d32a\",\"0x2174ca3ee9ace7dd8c946c97054c72f2b384c4c2\",\"0x1d694d5ad94f32132ff5c14c901d3ddbee90a550\",\"0x0b6fe046e6fd8d7a7a36d5ad1ffb82d2e3e5c3bb\",\"0x258f4ed0560e290a95066d9dee3628f2f179302b\",\"0xe2a09565167d4e3f826adec6bef82b97e0a4383f\",\"0x9af70704e9ec5f505cdba564ff4dec03503ddaa2\",\"0xeb9afe072c781401bf364224c75a036e4d832f52\",\"0x07748403082b29a45abd6c124a37e6b14e6b1803\",\"0x63486b70d804464766cfd096bba5552c4bcdac30\",\"0x5181be40152caaba8e123a55b7762755d4e8e416\",\"0x9481da7766c043eefeecc9589ee7ade61316b0ff\",\"0x42aba3530dd1ccb1dda27bfaa7c6a832cfdb4446\",\"0x05650444ace15a01762bd97ee8fdeb495b3c2436\",\"0xd83d18a2eae2440e272a53f86e617cd9f33c8d68\",\"0x4a35a802dbd623561040dd50f6293842d0901731\",\"0x4dbaf6c348d8cd1f174a7a6155f80ea8d4a8baf8\",\"0x9efc4e49be8ff70d596ac20efec9b7842e1ea963\",\"0x68efde0cdd917c6da6dab02c23f69e7c9cff51a9\",\"0x99b52813933a46d95bd4265ea2f674e58827da97\",\"0x7b35461cc5adbdc415c1f9562ccc342adbf09bd4\",\"0x8ee8813fb9d41cc58ef87d28b36e948b1234e71d\",\"0x69c1bc7883a7bb7696c7726d025867cd16564c9c\",\"0x31eb18dd6f5a8064ab750eabb281cf162f43ccd0\",\"0xf5d122e123d9d7998d2bea685d11b10fec3e4508\",\"0xf762854586a40a93d1fdcde32c062829f3754de9\",\"0x1e3f8fb9f840325983d6e5c68b6b846ff66a20ac\",\"0x3c1638a25ad7e8c2a84b53b661dd1bd048407e8f\",\"0x2eedf8a799b73bc02e4664183eb72422c377153b\",\"0xcdef6f23a26f960b53468f497967ce74c026af52\",\"0x0a2035683fe5587b0b09db0e757306ad729fe6c1\",\"0x158cc083cfbcffb2f983a3aa8b027eb0711c9831\",\"0x691cb1645a4f21d879973b3a3b98a714fc1970d6\",\"0x754164c0cb85dda1b5b18e5b62adbb4d60c3efbf\",\"0x556330e8d92912ccf133851ba03abd2db70da404\",\"0x1745ceba112b0a41638e235ec59b35adf37b70ab\",\"0xa24c85b16a440587793f82e358fa6b204468735b\",\"0x5304fb08724d73f2bb5e04c582407c33cde6c8d3\",\"0x256a11785fc43141324cf61efb5f491378c10c85\",\"0xa9f161a2badd44f3fe45b91a044a9484b72f1dc4\",\"0xd5cc10c45fc0f9f956acd7559f61edbfec9f6c3d\",\"0x381c7a71035bdb42fb5d77523df2ff00d9f9df1b\",\"0x45cdbeea730d8212f451a6a8d0eb5998b04cccca\",\"0x6367283f25a32be0c28623d787c319e237c3b7bd\",\"0x598e94eb5e050045272d8417f6ab363bd874d568\",\"0x379ff6375f4a44f458683629ef05141d73fae55a\",\"0x18df8ba2ef19083ddff68f8b33976cf22e8419c6\",\"0xffceebc37a7351d5df9aa3b077ed39cc3b5192ff\",\"0x1cd21f00b58894260f7abed65ad23dce3cea0226\",\"0x26324733d604abb6176cf18e4f4a0624ceeddc09\",\"0x4102d394d723ff141b82ef9a6053fb89f90c67f4\",\"0x269c370cb95b63f9b6a7cad47998167f160a2689\",\"0x3bb9557113fbb052dae3008a2801a072c432c018\",\"0x3f588a72d94d0d0986b112c671c2343320a19386\",\"0x7cfa9eee1d752da599211bc8a68d0687708dabfc\",\"0x7bc23966c419eadcb8a2fc5f83e635c4d4ad0c2f\",\"0xc4ad60337b04fc721912531a52a5d77878293fb9\",\"0xfc5ba3041f750f9b6820ce066c153eb396aac1ff\",\"0x32480c2d857941d2fff4e34f0910b20c0f9c23bc\",\"0x8041c9a96585053db2d7214b5de56828645b8e62\",\"0x444ca66b3ceb4187840cb1a205566a1413d5fecb\",\"0xf084bbaabee1a700a8faa404027db620a5aa0059\",\"0x602d562b4ef2544f851587619b56f77a9d965d45\",\"0x216faec139a61329ef8b31d982de427d9c007a9e\",\"0x11eb17b20113ae923d72e52870d40bf59a08b40d\",\"0xe69017fcc36bbc7fb167b9585bdd47a950ba1992\",\"0xe5549f429a72bfa618cf5c1afdac22a730df6a1a\",\"0x161c2e10407e2a87959c0bae1f342c80eaea28f3\",\"0x4161220db043a7d682e0ad123a3f8fea165711aa\",\"0xb33609811fb3d9fc8955dc6e9e086f1f08fc3a65\",\"0x4148555ea4c00e14f81ef399bbe67ef2fd9811b1\",\"0x4f81e991f76276a17ca92a1321f37189b1727f77\",\"0xba95e317ead06b55c8b70276fc63904b3339dfa1\",\"0xf6203c4fb14da640d11fbd9573e3958d017e6745\",\"0x73377d6228266393747efa710017872d6dd5b9a6\",\"0xf7862d105fc6ee69604decc30aa89472ad405961\",\"0xfa1205e19719c248323563bd55cd8bfd08b0cbc6\",\"0x4f46630115b446f8f7cebe1e5961ef7858c25204\",\"0x7492ebbc1e7f2838fc7191edc031581d5712978a\",\"0xc0af3981f9c0dfcb8955fea07a3e4f23806fab51\",\"0x8621dd642245df371b584b48c081e8863313a70d\",\"0xc328de035c91b39efa07d2fe620813253c9b4ec2\",\"0xa11308e3b741227d41973ddb17534ceb27b8206f\",\"0xc4ff1b4565ee203fa12636e100fe9c89cd18acb7\",\"0x63a36aea8570219476ef835f09024acdedfee95a\",\"0xf7205066c153f7c88dc3653ebc72b438884ae109\",\"0xa8ce5c40c4aa9278ddeaa418e775985549960e7a\",\"0x81f58f2194b0413806bf2ce8e1654bc855dc65a1\",\"0xf0218008120201e66b65fce4df9035007e811228\",\"0x90f022e3ca8453f5e5765cd3054003b544526eec\",\"0x1d1f873ba1ddf7915e6e26f93f5624b40efaefe2\",\"0x0311afd3bc2ae250d5f9f2706bae2ef4164d6912\",\"0x5044a80bd3eff58302e638018534bbda8896c48a\"],\"id\":67}"), serialized.Replace("\"", "\\\"")); } @@ -716,7 +713,7 @@ public async Task Eth_accounts() public async Task Eth_get_block_by_number_with_number_bad_number() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getBlockByNumber", "'0x1234567890123456789012345678901234567890123456789012345678901234567890'", "true"); + string serialized = ctx.Test.TestEthRpc("eth_getBlockByNumber", "'0x1234567890123456789012345678901234567890123456789012345678901234567890'", "true"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"Invalid params\"},\"id\":67}")); } @@ -724,7 +721,7 @@ public async Task Eth_get_block_by_number_with_number_bad_number() public async Task Eth_get_proof() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getProof", TestBlockchain.AccountA.ToString(), "[]", "0x2"); + string serialized = ctx.Test.TestEthRpc("eth_getProof", TestBlockchain.AccountA.ToString(), "[]", "0x2"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"accountProof\":[\"0xf8718080808080a0fc8311b2cabe1a1b33ea04f1865132a44aa0c17c567acd233422f9cfb516877480808080a0be8ea164b2fb1567e2505295dae6d8a9fe5f09e9c5ac854a7da23b2bc5f8523ca053692ab7cdc9bb02a28b1f45afe7be86cb27041ea98586e6ff05d98c9b0667138080808080\",\"0xf8518080808080a00dd1727b2abb59c0a6ac75c01176a9d1a276b0049d5fe32da3e1551096549e258080808080808080a038ca33d3070331da1ccf804819da57fcfc83358cadbef1d8bde89e1a346de5098080\",\"0xf872a020227dead52ea912e013e7641ccd6b3b174498e55066b0c174a09c8c3cc4bf5eb84ff84d01893635c9adc5de9fadf7a0475ae75f323761db271e75cbdae41aede237e48bc04127fb6611f0f33298f72ba0dbe576b4818846aa77e82f4ed5fa78f92766b141f282d36703886d196df39322\"],\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"balance\":\"0x3635c9adc5de9fadf7\",\"codeHash\":\"0xdbe576b4818846aa77e82f4ed5fa78f92766b141f282d36703886d196df39322\",\"nonce\":\"0x1\",\"storageHash\":\"0x475ae75f323761db271e75cbdae41aede237e48bc04127fb6611f0f33298f72b\",\"storageProof\":[]},\"id\":67}"), serialized.Replace("\"", "\\\"")); } @@ -732,7 +729,7 @@ public async Task Eth_get_proof() public async Task Eth_get_proof_withTrimmedStorageKey() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getProof", TestBlockchain.AccountA.ToString(), "[\"0x1\"]", "0x2"); + string serialized = ctx.Test.TestEthRpc("eth_getProof", TestBlockchain.AccountA.ToString(), "[\"0x1\"]", "0x2"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"accountProof\":[\"0xf8718080808080a0fc8311b2cabe1a1b33ea04f1865132a44aa0c17c567acd233422f9cfb516877480808080a0be8ea164b2fb1567e2505295dae6d8a9fe5f09e9c5ac854a7da23b2bc5f8523ca053692ab7cdc9bb02a28b1f45afe7be86cb27041ea98586e6ff05d98c9b0667138080808080\",\"0xf8518080808080a00dd1727b2abb59c0a6ac75c01176a9d1a276b0049d5fe32da3e1551096549e258080808080808080a038ca33d3070331da1ccf804819da57fcfc83358cadbef1d8bde89e1a346de5098080\",\"0xf872a020227dead52ea912e013e7641ccd6b3b174498e55066b0c174a09c8c3cc4bf5eb84ff84d01893635c9adc5de9fadf7a0475ae75f323761db271e75cbdae41aede237e48bc04127fb6611f0f33298f72ba0dbe576b4818846aa77e82f4ed5fa78f92766b141f282d36703886d196df39322\"],\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"balance\":\"0x3635c9adc5de9fadf7\",\"codeHash\":\"0xdbe576b4818846aa77e82f4ed5fa78f92766b141f282d36703886d196df39322\",\"nonce\":\"0x1\",\"storageHash\":\"0x475ae75f323761db271e75cbdae41aede237e48bc04127fb6611f0f33298f72b\",\"storageProof\":[{\"key\":\"0x0000000000000000000000000000000000000000000000000000000000000001\",\"proof\":[\"0xe7a120b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf68483abcdef\"],\"value\":\"0xabcdef\"}]},\"id\":67}"), serialized.Replace("\"", "\\\"")); } @@ -740,7 +737,7 @@ public async Task Eth_get_proof_withTrimmedStorageKey() public async Task Eth_get_block_by_number_empty_param() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getBlockByNumber", "", "true"); + string serialized = ctx.Test.TestEthRpc("eth_getBlockByNumber", "", "true"); Assert.True(serialized.StartsWith("{\"jsonrpc\":\"2.0\",\"error\"")); } @@ -748,7 +745,7 @@ public async Task Eth_get_block_by_number_empty_param() public async Task Eth_get_account_notfound() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getAccount", "0x000000000000000000000000000000000000dead", "latest"); + string serialized = ctx.Test.TestEthRpc("eth_getAccount", "0x000000000000000000000000000000000000dead", "latest"); serialized.Should().Be("{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":67}"); } @@ -759,7 +756,7 @@ public async Task Eth_get_account_found() using Context ctx = await Context.Create(); string account_address = TestBlockchain.AccountC.ToString(); - string serialized = await ctx.Test.TestEthRpc("eth_getAccount", account_address, "latest"); + string serialized = ctx.Test.TestEthRpc("eth_getAccount", account_address, "latest"); string expected = "{\"jsonrpc\":\"2.0\",\"result\":{\"codeHash\":\"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470\",\"storageRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"balance\":\"0x3635c9adc5dea00000\",\"nonce\":\"0x0\"},\"id\":67}"; serialized.Should().Be(expected); @@ -771,9 +768,9 @@ public async Task Eth_get_account_incorrect_block() using Context ctx = await Context.Create(); string account_address = TestBlockchain.AccountC.ToString(); - string serialized = await ctx.Test.TestEthRpc("eth_getAccount", account_address, "0xffff"); + string serialized = ctx.Test.TestEthRpc("eth_getAccount", account_address, "0xffff"); - serialized.Should().Be("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"65535 could not be found\"},\"id\":67}"); + serialized.Should().Be("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32000,\"message\":\"header not found\"},\"id\":67}"); } [Test] @@ -782,7 +779,7 @@ public async Task Eth_get_account_no_block_argument() using Context ctx = await Context.Create(); string account_address = TestBlockchain.AccountC.ToString(); - string serialized = await ctx.Test.TestEthRpc("eth_getAccount", account_address); + string serialized = ctx.Test.TestEthRpc("eth_getAccount", account_address); string expected = "{\"jsonrpc\":\"2.0\",\"result\":{\"codeHash\":\"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470\",\"storageRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"balance\":\"0x3635c9adc5dea00000\",\"nonce\":\"0x0\"},\"id\":67}"; serialized.Should().Be(expected); @@ -816,9 +813,9 @@ public async Task Eth_get_block_by_number_with_recovering_sender_from_receipts() receiptFinder.Get(Arg.Any()).Returns(receiptsTab); ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockFinder).WithReceiptFinder(receiptFinder).Build(); - string serialized = await ctx.Test.TestEthRpc("eth_getBlockByNumber", TestItem.KeccakA.ToString(), "true"); + string serialized = ctx.Test.TestEthRpc("eth_getBlockByNumber", TestItem.KeccakA.ToString(), "true"); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0xf4240\",\"extraData\":\"0x010203\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0x0\",\"hash\":\"0xe3026a6708b90d5cb25557ac38ddc3f5ef550af10f31e1cf771524da8553fa1c\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x2ba5557a4c62a513c7e56d1bf13373e0da6bec016755483e91589fe1c6d212e2\",\"nonce\":\"0x00000000000003e8\",\"number\":\"0x1\",\"parentHash\":\"0xff483e972a04a9a62bb4b7d04ae403c615604e4090521ecc5bb7af67f71be09c\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x221\",\"stateRoot\":\"0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f\",\"totalDifficulty\":\"0x0\",\"timestamp\":\"0xf4240\",\"transactions\":[{\"nonce\":\"0x0\",\"blockHash\":\"0xe3026a6708b90d5cb25557ac38ddc3f5ef550af10f31e1cf771524da8553fa1c\",\"blockNumber\":\"0x1\",\"transactionIndex\":\"0x0\",\"from\":\"0x2d36e6c27c34ea22620e7b7c45de774599406cf3\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\"}],\"transactionsRoot\":\"0x29cc403075ed3d1d6af940d577125cc378ee5a26f7746cbaf87f1cf4a38258b5\",\"uncles\":[]},\"id\":67}")); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0xf4240\",\"extraData\":\"0x010203\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0x0\",\"hash\":\"0xe3026a6708b90d5cb25557ac38ddc3f5ef550af10f31e1cf771524da8553fa1c\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x2ba5557a4c62a513c7e56d1bf13373e0da6bec016755483e91589fe1c6d212e2\",\"nonce\":\"0x00000000000003e8\",\"number\":\"0x1\",\"parentHash\":\"0xff483e972a04a9a62bb4b7d04ae403c615604e4090521ecc5bb7af67f71be09c\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x221\",\"stateRoot\":\"0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f\",\"totalDifficulty\":\"0x0\",\"timestamp\":\"0xf4240\",\"transactions\":[{\"nonce\":\"0x0\",\"blockHash\":\"0xe3026a6708b90d5cb25557ac38ddc3f5ef550af10f31e1cf771524da8553fa1c\",\"blockNumber\":\"0x1\",\"transactionIndex\":\"0x0\",\"from\":\"0x2d36e6c27c34ea22620e7b7c45de774599406cf3\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\"}],\"transactionsRoot\":\"0x29cc403075ed3d1d6af940d577125cc378ee5a26f7746cbaf87f1cf4a38258b5\",\"uncles\":[]},\"id\":67}")); } [TestCase(false)] @@ -852,10 +849,10 @@ public async Task Eth_get_transaction_receipt(bool postEip4844) receiptFinder.Get(Arg.Any()).Returns(receiptsTab); ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockFinder).WithReceiptFinder(receiptFinder).WithBlockchainBridge(blockchainBridge).Build(); - string serialized = await ctx.Test.TestEthRpc("eth_getTransactionReceipt", TestItem.KeccakA.ToString()); + string serialized = ctx.Test.TestEthRpc("eth_getTransactionReceipt", TestItem.KeccakA.ToString()); if (postEip4844) - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"transactionIndex\":\"0x2\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"cumulativeGasUsed\":\"0x3e8\",\"gasUsed\":\"0x64\",\"blobGasUsed\":\"0x3\",\"blobGasPrice\":\"0x2\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x0\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]},{\"removed\":false,\"logIndex\":\"0x1\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"root\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"status\":\"0x1\",\"error\":\"error\",\"type\":\"0x0\"},\"id\":67}")); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"transactionIndex\":\"0x2\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"cumulativeGasUsed\":\"0x3e8\",\"gasUsed\":\"0x64\",\"dataGasUsed\":\"0x3\",\"dataGasPrice\":\"0x2\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x0\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]},{\"removed\":false,\"logIndex\":\"0x1\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"root\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"status\":\"0x1\",\"error\":\"error\",\"type\":\"0x0\"},\"id\":67}")); else Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"transactionIndex\":\"0x2\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"cumulativeGasUsed\":\"0x3e8\",\"gasUsed\":\"0x64\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x0\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]},{\"removed\":false,\"logIndex\":\"0x1\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"root\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"status\":\"0x1\",\"error\":\"error\",\"type\":\"0x0\"},\"id\":67}")); } @@ -923,7 +920,7 @@ public async Task Eth_get_transaction_receipt_when_block_has_few_receipts() receiptFinder.Get(Arg.Any()).Returns(receipts); ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockFinder).WithBlockchainBridge(blockchainBridge).WithReceiptFinder(receiptFinder).Build(); - string serialized = await ctx.Test.TestEthRpc("eth_getTransactionReceipt", TestItem.KeccakA.ToString()); + string serialized = ctx.Test.TestEthRpc("eth_getTransactionReceipt", TestItem.KeccakA.ToString()); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"transactionIndex\":\"0x2\",\"blockHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockNumber\":\"0x1\",\"cumulativeGasUsed\":\"0x7d0\",\"gasUsed\":\"0x3e8\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"to\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x2\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"blockHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockNumber\":\"0x1\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]},{\"removed\":false,\"logIndex\":\"0x3\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"blockHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockNumber\":\"0x1\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"status\":\"0x0\",\"type\":\"0x0\"},\"id\":67}")); } @@ -932,7 +929,7 @@ public async Task Eth_get_transaction_receipt_when_block_has_few_receipts() public async Task Eth_get_transaction_receipt_returns_null_on_missing_receipt() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_getTransactionReceipt", TestItem.KeccakA.ToString()); + string serialized = ctx.Test.TestEthRpc("eth_getTransactionReceipt", TestItem.KeccakA.ToString()); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":67}")); } @@ -971,7 +968,7 @@ public async Task Eth_getTransactionReceipt_return_info_about_mined_tx() blockchainBridge.GetReceiptAndGasInfo(Arg.Any()).Returns((receipt, new(UInt256.One), 0)); ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockFinder).WithReceiptFinder(receiptFinder).WithBlockchainBridge(blockchainBridge).Build(); - string serialized = await ctx.Test.TestEthRpc("eth_getTransactionReceipt", tx.Hash!.ToString()); + string serialized = ctx.Test.TestEthRpc("eth_getTransactionReceipt", tx.Hash!.ToString()); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"transactionHash\":\"0xda6b4df2595675cbee0d4889f41c3d0790204e8ed1b8ad4cadaa45a7d50dace5\",\"transactionIndex\":\"0x2\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"cumulativeGasUsed\":\"0x3e8\",\"gasUsed\":\"0x64\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x0\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"root\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"status\":\"0x1\",\"error\":\"error\",\"type\":\"0x0\"},\"id\":67}")); } @@ -986,7 +983,7 @@ public async Task Eth_getTransactionReceipt_return_info_about_mined_1559tx() .SignedAndResolved().WithChainId(TestBlockchainIds.ChainId).WithGasPrice(0).WithValue(0).WithGasLimit(210200) .WithType(TxType.EIP1559).WithMaxFeePerGas(20.GWei()).WithMaxPriorityFeePerGas(1.GWei()).TestObject; await ctx.Test.AddBlock(tx); - string serialized = await ctx.Test.TestEthRpc("eth_getTransactionReceipt", tx.Hash!.ToString()); + string serialized = ctx.Test.TestEthRpc("eth_getTransactionReceipt", tx.Hash!.ToString()); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"transactionHash\":\"0x31501f80bf2ec493c368a519cb8ed6f132f0be26202304bbf1e1728642affb7f\",\"transactionIndex\":\"0x0\",\"blockHash\":\"0x54515a11aa6c392ee2e1071fca3a579bc9a520930ef757dbf9b7d85fe155c691\",\"blockNumber\":\"0x5\",\"cumulativeGasUsed\":\"0x521c\",\"gasUsed\":\"0x521c\",\"effectiveGasPrice\":\"0x5e91eb5d\",\"from\":\"0x723847c97bc651c7e8c013dbbe65a70712f02ad3\",\"to\":\"0x0000000000000000000000000000000000000000\",\"contractAddress\":null,\"logs\":[],\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"status\":\"0x1\",\"type\":\"0x2\"},\"id\":67}")); } @@ -1000,7 +997,7 @@ public async Task Eth_getTransactionByHash_return_info_about_mined_1559tx() .SignedAndResolved().WithChainId(TestBlockchainIds.ChainId).WithGasPrice(0).WithValue(0).WithGasLimit(210200) .WithType(TxType.EIP1559).WithMaxFeePerGas(20.GWei()).WithMaxPriorityFeePerGas(1.GWei()).TestObject; await ctx.Test.AddBlock(tx); - string serialized = await ctx.Test.TestEthRpc("eth_getTransactionByHash", tx.Hash!.ToString()); + string serialized = ctx.Test.TestEthRpc("eth_getTransactionByHash", tx.Hash!.ToString()); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"hash\":\"0x31501f80bf2ec493c368a519cb8ed6f132f0be26202304bbf1e1728642affb7f\",\"nonce\":\"0x0\",\"blockHash\":\"0x54515a11aa6c392ee2e1071fca3a579bc9a520930ef757dbf9b7d85fe155c691\",\"blockNumber\":\"0x5\",\"transactionIndex\":\"0x0\",\"from\":\"0x723847c97bc651c7e8c013dbbe65a70712f02ad3\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x0\",\"gasPrice\":\"0x5e91eb5d\",\"maxPriorityFeePerGas\":\"0x3b9aca00\",\"maxFeePerGas\":\"0x4a817c800\",\"gas\":\"0x33518\",\"data\":\"0x0001\",\"input\":\"0x0001\",\"chainId\":\"0x1\",\"type\":\"0x2\",\"v\":\"0x0\",\"s\":\"0x6b82095065a599e6b5e52bed0043702baf3411418af679ac483f9fc75a8f6aef\",\"r\":\"0x8654517f7822e7a4e10e79f3f5a4136703c7d1b51d98e47686e201c3c2845f92\"},\"id\":67}")); } @@ -1008,7 +1005,7 @@ public async Task Eth_getTransactionByHash_return_info_about_mined_1559tx() public async Task Eth_chain_id() { using Context ctx = await Context.Create(); - string serialized = await ctx.Test.TestEthRpc("eth_chainId"); + string serialized = ctx.Test.TestEthRpc("eth_chainId"); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"0x{TestBlockchainIds.ChainId:X}\",\"id\":67}}")); } @@ -1022,7 +1019,7 @@ public async Task Send_transaction_with_signature_will_not_try_to_sign() ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).WithTxSender(txSender).Build(); Transaction tx = Build.A.Transaction.Signed(new EthereumEcdsa(TestBlockchainIds.ChainId, LimboLogs.Instance), TestItem.PrivateKeyA).TestObject; - string serialized = await ctx.Test.TestEthRpc("eth_sendRawTransaction", Rlp.Encode(tx, RlpBehaviors.None).Bytes.ToHexString()); + string serialized = ctx.Test.TestEthRpc("eth_sendRawTransaction", Rlp.Encode(tx, RlpBehaviors.None).Bytes.ToHexString()); await txSender.Received().SendTransaction(Arg.Any(), TxHandlingOptions.PersistentBroadcast); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"{TestItem.KeccakA.Bytes.ToHexString(true)}\",\"id\":67}}")); @@ -1036,7 +1033,7 @@ public async Task Send_raw_transaction_will_send_transaction(string rawTransacti ctx.Test.NonceManager, ctx.Test.EthereumEcdsa); IBlockchainBridge bridge = Substitute.For(); ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).WithTxSender(txSender).Build(); - string serialized = await ctx.Test.TestEthRpc("eth_sendRawTransaction", rawTransaction); + string serialized = ctx.Test.TestEthRpc("eth_sendRawTransaction", rawTransaction); Transaction tx = Rlp.Decode(Bytes.FromHexString(rawTransaction)); await txSender.Received().SendTransaction(tx, TxHandlingOptions.PersistentBroadcast); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32010,\"message\":\"Invalid\"},\"id\":67}")); @@ -1056,7 +1053,7 @@ public async Task Send_transaction_without_signature_will_not_set_nonce_when_zer Transaction tx = Build.A.Transaction.TestObject; TransactionForRpc rpcTx = new(tx); rpcTx.Nonce = 0; - string serialized = await ctx.Test.TestEthRpc("eth_sendTransaction", new EthereumJsonSerializer().Serialize(rpcTx)); + string serialized = ctx.Test.TestEthRpc("eth_sendTransaction", new EthereumJsonSerializer().Serialize(rpcTx)); // TODO: actual test missing now await txSender.Received().SendTransaction(Arg.Any(), TxHandlingOptions.PersistentBroadcast); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"{TestItem.KeccakA.Bytes.ToHexString(true)}\",\"id\":67}}")); @@ -1076,7 +1073,7 @@ public async Task Send_transaction_without_signature_will_manage_nonce_when_null Transaction tx = Build.A.Transaction.TestObject; TransactionForRpc rpcTx = new(tx); rpcTx.Nonce = null; - string serialized = await ctx.Test.TestEthRpc("eth_sendTransaction", new EthereumJsonSerializer().Serialize(rpcTx)); + string serialized = ctx.Test.TestEthRpc("eth_sendTransaction", new EthereumJsonSerializer().Serialize(rpcTx)); await txSender.Received().SendTransaction(Arg.Any(), TxHandlingOptions.PersistentBroadcast | TxHandlingOptions.ManagedNonce); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"{TestItem.KeccakA.Bytes.ToHexString(true)}\",\"id\":67}}")); @@ -1089,7 +1086,7 @@ public async Task Send_transaction_should_return_ErrorCode_if_tx_not_added() Transaction tx = Build.A.Transaction.WithValue(10000).SignedAndResolved(new PrivateKey("0x0000000000000000000000000000000000000000000000000000000000000001")).WithNonce(0).TestObject; TransactionForRpc txForRpc = new(tx); - string serialized = await ctx.Test.TestEthRpc("eth_sendTransaction", new EthereumJsonSerializer().Serialize(txForRpc)); + string serialized = ctx.Test.TestEthRpc("eth_sendTransaction", new EthereumJsonSerializer().Serialize(txForRpc)); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32010,\"message\":\"InsufficientFunds, Balance is zero, cannot pay gas\"},\"id\":67}")); } @@ -1130,7 +1127,7 @@ public async Task Eth_create_access_list_sample(AccessListProvided accessListPro transaction.AccessList = GetTestAccessList(2, accessListProvided == AccessListProvided.Full).AccessList; } - string serialized = await test.TestEthRpc("eth_createAccessList", test.JsonSerializer.Serialize(transaction), "0x0", optimize.ToString().ToLower()); + string serialized = test.TestEthRpc("eth_createAccessList", test.JsonSerializer.Serialize(transaction), "0x0", optimize.ToString().ToLower()); Assert.That(serialized, Is.EqualTo(expected)); } @@ -1173,7 +1170,7 @@ public async Task eth_getBlockByNumber_should_return_withdrawals_correctly() receiptFinder.Get(Arg.Any()).Returns(receiptsTab); ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockFinder).WithReceiptFinder(receiptFinder).Build(); - string result = await ctx.Test.TestEthRpc("eth_getBlockByNumber", TestItem.KeccakA.ToString(), "true"); + string result = ctx.Test.TestEthRpc("eth_getBlockByNumber", TestItem.KeccakA.ToString(), "true"); result.Should().Be(new EthereumJsonSerializer().Serialize(new { diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/EvmModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/EvmModuleTests.cs index 141627bd070..33ad3ca6ff6 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/EvmModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/EvmModuleTests.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Threading.Tasks; using Nethermind.Consensus.Producers; using Nethermind.JsonRpc.Modules.Evm; using NSubstitute; @@ -14,13 +13,13 @@ namespace Nethermind.JsonRpc.Test.Modules public class EvmModuleTests { [Test] - public async Task Evm_mine() + public void Evm_mine() { IManualBlockProductionTrigger trigger = Substitute.For(); EvmRpcModule rpcModule = new(trigger); - string response = await RpcTest.TestSerializedRequest(rpcModule, "evm_mine"); + string response = RpcTest.TestSerializedRequest(rpcModule, "evm_mine"); Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}")); - await trigger.Received().BuildBlock(); + trigger.Received().BuildBlock(); } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/FeeHistoryOracleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/FeeHistoryOracleTests.cs index 37d56b329a8..fdbbd9c98b7 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/FeeHistoryOracleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/FeeHistoryOracleTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.Linq; using FluentAssertions; @@ -10,9 +11,11 @@ using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; +using Nethermind.Facade; using Nethermind.Int256; using Nethermind.JsonRpc.Modules.Eth; using Nethermind.JsonRpc.Modules.Eth.FeeHistory; +using Nethermind.Logging; using NSubstitute; using NUnit.Framework; using static Nethermind.JsonRpc.Test.Modules.GasPriceOracleTests; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/GasPriceOracleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/GasPriceOracleTests.cs index 5e659965e8d..74205b5df85 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/GasPriceOracleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/GasPriceOracleTests.cs @@ -13,6 +13,7 @@ using Nethermind.Int256; using Nethermind.JsonRpc.Modules.Eth.GasPrice; using Nethermind.Logging; +using Nethermind.Specs; using Nethermind.Specs.Forks; using Nethermind.Specs.Test; using NSubstitute; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/GetBlockLogFirstIndexTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/GetBlockLogFirstIndexTests.cs index 1daf60f14f9..af13b6a9999 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/GetBlockLogFirstIndexTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/GetBlockLogFirstIndexTests.cs @@ -1,9 +1,11 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Threading.Tasks; using Nethermind.Blockchain.Receipts; using Nethermind.Core; using Nethermind.Core.Test.Builders; +using Nethermind.JsonRpc.Modules; using NUnit.Framework; namespace Nethermind.JsonRpc.Test.Modules diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/NetModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/NetModuleTests.cs index baadbcb415f..128b7c5e600 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/NetModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/NetModuleTests.cs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Net; -using System.Threading.Tasks; +using Google.Protobuf.WellKnownTypes; using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; @@ -13,8 +13,10 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; +using Nethermind.Db; using Nethermind.JsonRpc.Modules.Net; using Nethermind.Logging; +using Nethermind.Specs; using Nethermind.State; using Nethermind.Synchronization; using Nethermind.Synchronization.ParallelSync; @@ -29,17 +31,17 @@ namespace Nethermind.JsonRpc.Test.Modules public class NetModuleTests { [Test] - public async Task NetPeerCountSuccessTest() + public void NetPeerCountSuccessTest() { Enode enode = new(TestItem.PublicKeyA, IPAddress.Loopback, 30303); NetBridge netBridge = new(enode, Substitute.For()); NetRpcModule rpcModule = new(LimboLogs.Instance, netBridge); - string response = await RpcTest.TestSerializedRequest(rpcModule, "net_peerCount"); + string response = RpcTest.TestSerializedRequest(rpcModule, "net_peerCount"); Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x0\",\"id\":67}")); } [Test] - public async Task NetVersionSuccessTest() + public void NetVersionSuccessTest() { Enode enode = new(TestItem.PublicKeyA, IPAddress.Loopback, 30303); var blockTree = Substitute.For(); @@ -63,7 +65,7 @@ public async Task NetVersionSuccessTest() Substitute.For()); NetBridge netBridge = new(enode, syncServer); NetRpcModule rpcModule = new(LimboLogs.Instance, netBridge); - string response = await RpcTest.TestSerializedRequest(rpcModule, "net_version"); + string response = RpcTest.TestSerializedRequest(rpcModule, "net_version"); Assert.That(response, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"{TestBlockchainIds.NetworkId}\",\"id\":67}}")); _ = blockTree.DidNotReceive().ChainId; @@ -71,12 +73,12 @@ public async Task NetVersionSuccessTest() } [Test] - public async Task NetListeningSuccessTest() + public void NetListeningSuccessTest() { Enode enode = new(TestItem.PublicKeyA, IPAddress.Loopback, 30303); NetBridge netBridge = new(enode, Substitute.For()); NetRpcModule rpcModule = new(LimboLogs.Instance, netBridge); - string response = await RpcTest.TestSerializedRequest(rpcModule, "net_listening"); + string response = RpcTest.TestSerializedRequest(rpcModule, "net_listening"); Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}")); } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/ParityRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/ParityRpcModuleTests.cs index 578f579bb92..1691cdc8cc4 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/ParityRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/ParityRpcModuleTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.IO; using System.Net; @@ -46,17 +47,13 @@ public class ParityRpcModuleTests { private IParityRpcModule _parityRpcModule = null!; private Signer _signerStore = null!; - private EthereumEcdsa _ethereumEcdsa = null!; - private ITxPool _txPool = null!; - private IBlockTree _blockTree = null!; - private IReceiptStorage _receiptStorage = null!; [SetUp] public void Initialize() { LimboLogs logger = LimboLogs.Instance; MainnetSpecProvider specProvider = MainnetSpecProvider.Instance; - _ethereumEcdsa = new(specProvider.ChainId, logger); + EthereumEcdsa ethereumEcdsa = new(specProvider.ChainId, logger); Peer peerA = SetUpPeerA(); //standard case Peer peerB = SetUpPeerB(); //Session is null @@ -71,40 +68,41 @@ public void Initialize() IDb blockDb = new MemDb(); IDb headerDb = new MemDb(); IDb blockInfoDb = new MemDb(); - _blockTree = new BlockTree(blockDb, headerDb, blockInfoDb, new ChainLevelInfoRepository(blockInfoDb), specProvider, NullBloomStorage.Instance, logger); + IBlockTree blockTree = new BlockTree(blockDb, headerDb, blockInfoDb, new ChainLevelInfoRepository(blockInfoDb), specProvider, NullBloomStorage.Instance, LimboLogs.Instance); - _txPool = new TxPool.TxPool(_ethereumEcdsa, - new ChainHeadInfoProvider(new FixedForkActivationChainHeadSpecProvider(specProvider), _blockTree, stateProvider), - new TxPoolConfig(), - new TxValidator(specProvider.ChainId), - LimboLogs.Instance, - new TransactionComparerProvider(specProvider, _blockTree).GetDefaultComparer()); + ITransactionComparerProvider transactionComparerProvider = + new TransactionComparerProvider(specProvider, blockTree); + TxPool.TxPool txPool = new(ethereumEcdsa, new ChainHeadInfoProvider(new FixedForkActivationChainHeadSpecProvider(specProvider), blockTree, stateProvider), new TxPoolConfig(), + new TxValidator(specProvider.ChainId), LimboLogs.Instance, transactionComparerProvider.GetDefaultComparer()); - _receiptStorage = new InMemoryReceiptStorage(); + IReceiptStorage receiptStorage = new InMemoryReceiptStorage(); _signerStore = new Signer(specProvider.ChainId, TestItem.PrivateKeyB, logger); - _parityRpcModule = CreateParityRpcModule(peerManager); + _parityRpcModule = new ParityRpcModule(ethereumEcdsa, txPool, blockTree, receiptStorage, + new Enode(TestItem.PublicKeyA, IPAddress.Loopback, 8545), _signerStore, + new MemKeyStore(new[] { TestItem.PrivateKeyA }, Environment.SpecialFolder.ApplicationData.ToString()), + MainnetSpecProvider.Instance, peerManager); int blockNumber = 2; - Transaction pendingTransaction = Build.A.Transaction.Signed(_ethereumEcdsa, TestItem.PrivateKeyD, false) + Transaction pendingTransaction = Build.A.Transaction.Signed(ethereumEcdsa, TestItem.PrivateKeyD, false) .WithSenderAddress(Address.FromNumber((UInt256)blockNumber)).TestObject; pendingTransaction.Signature!.V = 37; stateProvider.CreateAccount(pendingTransaction.SenderAddress!, UInt256.UInt128MaxValue); - _txPool.SubmitTx(pendingTransaction, TxHandlingOptions.None); + txPool.SubmitTx(pendingTransaction, TxHandlingOptions.None); blockNumber = 1; - Transaction transaction1 = Build.A.Transaction.Signed(_ethereumEcdsa, TestItem.PrivateKeyD, false) + Transaction transaction1 = Build.A.Transaction.Signed(ethereumEcdsa, TestItem.PrivateKeyD, false) .WithSenderAddress(Address.FromNumber((UInt256)blockNumber)) .WithNonce(100).TestObject; transaction1.Signature!.V = 37; stateProvider.CreateAccount(transaction1.SenderAddress!, UInt256.UInt128MaxValue); - var transaction2 = Build.A.Transaction.Signed(_ethereumEcdsa, TestItem.PrivateKeyD, false) + var transaction2 = Build.A.Transaction.Signed(ethereumEcdsa, TestItem.PrivateKeyD, false) .WithSenderAddress(Address.FromNumber((UInt256)blockNumber)) .WithNonce(120).TestObject; transaction2.Signature!.V = 37; - var transaction3 = Build.A.Transaction.Signed(_ethereumEcdsa, TestItem.PrivateKeyD, false) + var transaction3 = Build.A.Transaction.Signed(ethereumEcdsa, TestItem.PrivateKeyD, false) .WithSenderAddress(Address.FromNumber((UInt256)blockNumber)) .WithNonce(110).TestObject; transaction2.Signature.V = 37; @@ -113,8 +111,8 @@ public void Initialize() .WithStateRoot(new Keccak("0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f")) .TestObject; - _blockTree.SuggestBlock(genesis); - _blockTree.UpdateMainChain(new[] { genesis }, true); + blockTree.SuggestBlock(genesis); + blockTree.UpdateMainChain(new[] { genesis }, true); Block previousBlock = genesis; Block block = Build.A.Block.WithNumber(blockNumber).WithParent(previousBlock) @@ -122,8 +120,8 @@ public void Initialize() .WithTransactions(transaction1, transaction2, transaction3) .TestObject; - _blockTree.SuggestBlock(block); - _blockTree.UpdateMainChain(new[] { block }, true); + blockTree.SuggestBlock(block); + blockTree.UpdateMainChain(new[] { block }, true); LogEntry[] logEntries = new[] { Build.A.LogEntry.TestObject }; @@ -175,7 +173,7 @@ public void Initialize() Logs = logEntries }; - _receiptStorage.Insert(block, receipt1, receipt2, receipt3); + receiptStorage.Insert(block, receipt1, receipt2, receipt3); } private static Peer SetUpPeerA() @@ -252,24 +250,11 @@ private static Peer SetUpPeerC() return peer; } - private IParityRpcModule CreateParityRpcModule(IPeerManager? peerManager = null) - { - return new ParityRpcModule(_ethereumEcdsa, - _txPool, - _blockTree, - _receiptStorage, - new Enode(TestItem.PublicKeyA, IPAddress.Loopback, 8545), - _signerStore, - new MemKeyStore(new[] { TestItem.PrivateKeyA }, Path.Combine("testKeyStoreDir", Path.GetRandomFileName())), - MainnetSpecProvider.Instance, - peerManager ?? Substitute.For()); - } - [Test] public async Task parity_pendingTransactions() { await Task.Delay(100); - string serialized = await RpcTest.TestSerializedRequest(_parityRpcModule, "parity_pendingTransactions"); + string serialized = RpcTest.TestSerializedRequest(_parityRpcModule, "parity_pendingTransactions"); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[{\"hash\":\"0xd4720d1b81c70ed4478553a213a83bd2bf6988291677f5d05c6aae0b287f947e\",\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"from\":\"0x0000000000000000000000000000000000000002\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"raw\":\"0xf85f8001825208940000000000000000000000000000000000000000018025a0ef2effb79771cbe42fc7f9cc79440b2a334eedad6e528ea45c2040789def4803a0515bdfe298808be2e07879faaeacd0ad17f3b13305b9f971647bbd5d5b584642\",\"creates\":null,\"publicKey\":\"0x15a1cc027cfd2b970c8aa2b3b22dfad04d29171109f6502d5fb5bde18afe86dddd44b9f8d561577527f096860ee03f571cc7f481ea9a14cb48cc7c20c964373a\",\"chainId\":\"0x1\",\"condition\":null,\"r\":\"0xef2effb79771cbe42fc7f9cc79440b2a334eedad6e528ea45c2040789def4803\",\"s\":\"0x515bdfe298808be2e07879faaeacd0ad17f3b13305b9f971647bbd5d5b584642\",\"v\":\"0x25\",\"standardV\":\"0x0\"}],\"id\":67}"; Assert.That(serialized, Is.EqualTo(expectedResult)); } @@ -278,7 +263,7 @@ public async Task parity_pendingTransactions() public async Task parity_pendingTransactions_With_Address() { await Task.Delay(100); - string serialized = await RpcTest.TestSerializedRequest(_parityRpcModule, "parity_pendingTransactions", "0x0000000000000000000000000000000000000002"); + string serialized = RpcTest.TestSerializedRequest(_parityRpcModule, "parity_pendingTransactions", "0x0000000000000000000000000000000000000002"); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[{\"hash\":\"0xd4720d1b81c70ed4478553a213a83bd2bf6988291677f5d05c6aae0b287f947e\",\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"from\":\"0x0000000000000000000000000000000000000002\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"raw\":\"0xf85f8001825208940000000000000000000000000000000000000000018025a0ef2effb79771cbe42fc7f9cc79440b2a334eedad6e528ea45c2040789def4803a0515bdfe298808be2e07879faaeacd0ad17f3b13305b9f971647bbd5d5b584642\",\"creates\":null,\"publicKey\":\"0x15a1cc027cfd2b970c8aa2b3b22dfad04d29171109f6502d5fb5bde18afe86dddd44b9f8d561577527f096860ee03f571cc7f481ea9a14cb48cc7c20c964373a\",\"chainId\":\"0x1\",\"condition\":null,\"r\":\"0xef2effb79771cbe42fc7f9cc79440b2a334eedad6e528ea45c2040789def4803\",\"s\":\"0x515bdfe298808be2e07879faaeacd0ad17f3b13305b9f971647bbd5d5b584642\",\"v\":\"0x25\",\"standardV\":\"0x0\"}],\"id\":67}"; Assert.That(serialized, Is.EqualTo(expectedResult)); } @@ -287,31 +272,31 @@ public async Task parity_pendingTransactions_With_Address() public async Task parity_pendingTransactions_With_Address_Empty_Result() { await Task.Delay(100); - string serialized = await RpcTest.TestSerializedRequest(_parityRpcModule, "parity_pendingTransactions", "0x0000000000000000000000000000000000000005"); + string serialized = RpcTest.TestSerializedRequest(_parityRpcModule, "parity_pendingTransactions", "0x0000000000000000000000000000000000000005"); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[],\"id\":67}"; Assert.That(serialized, Is.EqualTo(expectedResult)); } [Test] - public async Task parity_getBlockReceipts() + public void parity_getBlockReceipts() { - string serialized = await RpcTest.TestSerializedRequest(_parityRpcModule, "parity_getBlockReceipts", "latest"); + string serialized = RpcTest.TestSerializedRequest(_parityRpcModule, "parity_getBlockReceipts", "latest"); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[{\"transactionHash\":\"0x026217c3c4eb1f0e9e899553759b6e909b965a789c6136d256674718617c8142\",\"transactionIndex\":\"0x0\",\"blockHash\":\"0x5077d73d2e82d0b7799392db86827826f181df13e3f50fed89cbb5aa03f5230f\",\"blockNumber\":\"0x1\",\"cumulativeGasUsed\":\"0x7d0\",\"gasUsed\":\"0x3e8\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"to\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x0\",\"transactionIndex\":\"0x0\",\"transactionHash\":\"0x026217c3c4eb1f0e9e899553759b6e909b965a789c6136d256674718617c8142\",\"blockHash\":\"0x5077d73d2e82d0b7799392db86827826f181df13e3f50fed89cbb5aa03f5230f\",\"blockNumber\":\"0x1\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"status\":\"0x0\",\"type\":\"0x0\"},{\"transactionHash\":\"0xd0183bfd42ccd8fccb7722b108e052d12d2cf5a32a144b6a6f3a975c4d7d14a1\",\"transactionIndex\":\"0x1\",\"blockHash\":\"0x5077d73d2e82d0b7799392db86827826f181df13e3f50fed89cbb5aa03f5230f\",\"blockNumber\":\"0x1\",\"cumulativeGasUsed\":\"0x7d0\",\"gasUsed\":\"0x3e8\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"to\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x1\",\"transactionIndex\":\"0x1\",\"transactionHash\":\"0xd0183bfd42ccd8fccb7722b108e052d12d2cf5a32a144b6a6f3a975c4d7d14a1\",\"blockHash\":\"0x5077d73d2e82d0b7799392db86827826f181df13e3f50fed89cbb5aa03f5230f\",\"blockNumber\":\"0x1\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"status\":\"0x0\",\"type\":\"0x0\"},{\"transactionHash\":\"0xf8ab484b10dc0398f03957d1062bbe3526048b74d429f8a8c9c57fa7ac5fa436\",\"transactionIndex\":\"0x2\",\"blockHash\":\"0x5077d73d2e82d0b7799392db86827826f181df13e3f50fed89cbb5aa03f5230f\",\"blockNumber\":\"0x1\",\"cumulativeGasUsed\":\"0x7d0\",\"gasUsed\":\"0x3e8\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"to\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x2\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0xf8ab484b10dc0398f03957d1062bbe3526048b74d429f8a8c9c57fa7ac5fa436\",\"blockHash\":\"0x5077d73d2e82d0b7799392db86827826f181df13e3f50fed89cbb5aa03f5230f\",\"blockNumber\":\"0x1\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"status\":\"0x0\",\"type\":\"0x0\"}],\"id\":67}"; Assert.That(serialized, Is.EqualTo(expectedResult)); } [Test] - public async Task parity_enode() + public void parity_enode() { - string serialized = await RpcTest.TestSerializedRequest(_parityRpcModule, "parity_enode"); + string serialized = RpcTest.TestSerializedRequest(_parityRpcModule, "parity_enode"); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"enode://a49ac7010c2e0a444dfeeabadbafa4856ba4a2d732acb86d20c577b3b365fdaeb0a70ce47f890cf2f9fca562a7ed784f76eb870a2c75c0f2ab476a70ccb67e92@127.0.0.1:8545\",\"id\":67}"; Assert.That(serialized, Is.EqualTo(expectedResult)); } [Test] - public async Task parity_setEngineSigner() + public void parity_setEngineSigner() { - string serialized = await RpcTest.TestSerializedRequest(_parityRpcModule, "parity_setEngineSigner", TestItem.AddressA.ToString(), "password"); + string serialized = RpcTest.TestSerializedRequest(_parityRpcModule, "parity_setEngineSigner", TestItem.AddressA.ToString(), "password"); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}"; Assert.That(serialized, Is.EqualTo(expectedResult)); _signerStore.Address.Should().Be(TestItem.AddressA); @@ -319,9 +304,9 @@ public async Task parity_setEngineSigner() } [Test] - public async Task parity_setEngineSignerSecret() + public void parity_setEngineSignerSecret() { - string serialized = await RpcTest.TestSerializedRequest(_parityRpcModule, "parity_setEngineSignerSecret", TestItem.PrivateKeyA.ToString()); + string serialized = RpcTest.TestSerializedRequest(_parityRpcModule, "parity_setEngineSignerSecret", TestItem.PrivateKeyA.ToString()); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}"; Assert.That(serialized, Is.EqualTo(expectedResult)); _signerStore.Address.Should().Be(TestItem.AddressA); @@ -329,10 +314,10 @@ public async Task parity_setEngineSignerSecret() } [Test] - public async Task parity_clearEngineSigner() + public void parity_clearEngineSigner() { - await RpcTest.TestSerializedRequest(_parityRpcModule, "parity_setEngineSigner", TestItem.AddressA.ToString(), "password"); - string serialized = await RpcTest.TestSerializedRequest(_parityRpcModule, "parity_clearEngineSigner"); + RpcTest.TestSerializedRequest(_parityRpcModule, "parity_setEngineSigner", TestItem.AddressA.ToString(), "password"); + string serialized = RpcTest.TestSerializedRequest(_parityRpcModule, "parity_clearEngineSigner"); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}"; serialized.Should().Be(expectedResult); _signerStore.Address.Should().Be(Address.Zero); @@ -340,33 +325,70 @@ public async Task parity_clearEngineSigner() } [Test] - public async Task parity_netPeers_standard_case() + public void parity_netPeers_standard_case() { - string serialized = await RpcTest.TestSerializedRequest(_parityRpcModule, "parity_netPeers"); + string serialized = RpcTest.TestSerializedRequest(_parityRpcModule, "parity_netPeers"); string expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":{\"active\":3,\"connected\":5,\"max\":15,\"peers\":[{\"id\":\"", TestItem.PublicKeyA, "\",\"name\":\"Geth/v1.9.21-stable/linux-amd64/go1.15.2\",\"caps\":[\"eth/65\",\"eth/64\"],\"network\":{\"localAddress\":\"127.0.0.1\",\"remoteAddress\":\"Handshake\"},\"protocols\":{\"eth\":{\"version\":65,\"difficulty\":\"0x5ea4ed\",\"head\":\"", TestItem.KeccakA, "\"}}},{\"name\":\"Geth/v1.9.26-unstable/linux-amd64/go1.15.6\",\"caps\":[],\"network\":{\"localAddress\":\"95.217.106.25\"},\"protocols\":{\"eth\":{\"version\":0,\"difficulty\":\"0x0\"}}},{\"id\":\"", TestItem.PublicKeyB, "\",\"caps\":[],\"network\":{\"remoteAddress\":\"Handshake\"},\"protocols\":{\"eth\":{\"version\":0,\"difficulty\":\"0x0\"}}}]},\"id\":67}"); Assert.That(serialized, Is.EqualTo(expectedResult)); } [Test] - public async Task parity_netPeers_empty_ActivePeers() + public void parity_netPeers_empty_ActivePeers() { + LimboLogs logger = LimboLogs.Instance; + MainnetSpecProvider specProvider = MainnetSpecProvider.Instance; + EthereumEcdsa ethereumEcdsa = new(specProvider.ChainId, logger); + IDb blockDb = new MemDb(); + IDb headerDb = new MemDb(); + IDb blockInfoDb = new MemDb(); + IBlockTree blockTree = new BlockTree(blockDb, headerDb, blockInfoDb, new ChainLevelInfoRepository(blockInfoDb), specProvider, NullBloomStorage.Instance, LimboLogs.Instance); + + ITransactionComparerProvider transactionComparerProvider = + new TransactionComparerProvider(specProvider, blockTree); + TxPool.TxPool txPool = new(ethereumEcdsa, new ChainHeadInfoProvider(new FixedForkActivationChainHeadSpecProvider(specProvider), blockTree, new WorldState(new TrieStore(new MemDb(), LimboLogs.Instance), new MemDb(), LimboLogs.Instance)), new TxPoolConfig(), + new TxValidator(specProvider.ChainId), LimboLogs.Instance, transactionComparerProvider.GetDefaultComparer()); + + IReceiptStorage receiptStorage = new InMemoryReceiptStorage(); + IPeerManager peerManager = Substitute.For(); peerManager.ActivePeers.Returns(new List { }); peerManager.ConnectedPeers.Returns(new List { new(new Node(TestItem.PublicKeyA, "111.1.1.1", 11111, true)) }); - IParityRpcModule parityRpcModule = CreateParityRpcModule(peerManager); + IParityRpcModule parityRpcModule = new ParityRpcModule(ethereumEcdsa, txPool, blockTree, receiptStorage, + new Enode(TestItem.PublicKeyA, IPAddress.Loopback, 8545), + _signerStore, new MemKeyStore(new[] { TestItem.PrivateKeyA }, Path.Combine("testKeyStoreDir", Path.GetRandomFileName())), + MainnetSpecProvider.Instance, peerManager); - string serialized = await RpcTest.TestSerializedRequest(parityRpcModule, "parity_netPeers"); + string serialized = RpcTest.TestSerializedRequest(parityRpcModule, "parity_netPeers"); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":{\"active\":0,\"connected\":1,\"max\":0,\"peers\":[]},\"id\":67}"; Assert.That(serialized, Is.EqualTo(expectedResult)); } [Test] - public async Task parity_netPeers_null_ActivePeers() + public void parity_netPeers_null_ActivePeers() { - IParityRpcModule parityRpcModule = CreateParityRpcModule(); + LimboLogs logger = LimboLogs.Instance; + MainnetSpecProvider specProvider = MainnetSpecProvider.Instance; + EthereumEcdsa ethereumEcdsa = new(specProvider.ChainId, logger); - string serialized = await RpcTest.TestSerializedRequest(parityRpcModule, "parity_netPeers"); + IDb blockDb = new MemDb(); + IDb headerDb = new MemDb(); + IDb blockInfoDb = new MemDb(); + IBlockTree blockTree = new BlockTree(blockDb, headerDb, blockInfoDb, new ChainLevelInfoRepository(blockInfoDb), specProvider, NullBloomStorage.Instance, LimboLogs.Instance); + ITransactionComparerProvider transactionComparerProvider = + new TransactionComparerProvider(specProvider, blockTree); + TxPool.TxPool txPool = new(ethereumEcdsa, new ChainHeadInfoProvider(specProvider, blockTree, new StateReader(new TrieStore(new MemDb(), LimboLogs.Instance), new MemDb(), LimboLogs.Instance)), new TxPoolConfig(), + new TxValidator(specProvider.ChainId), LimboLogs.Instance, transactionComparerProvider.GetDefaultComparer()); + + IReceiptStorage receiptStorage = new InMemoryReceiptStorage(); + + IPeerManager peerManager = Substitute.For(); + + IParityRpcModule parityRpcModule = new ParityRpcModule(ethereumEcdsa, txPool, blockTree, receiptStorage, + new Enode(TestItem.PublicKeyA, IPAddress.Loopback, 8545), + _signerStore, new MemKeyStore(new[] { TestItem.PrivateKeyA }, Path.Combine("testKeyStoreDir", Path.GetRandomFileName())), + MainnetSpecProvider.Instance, peerManager); + string serialized = RpcTest.TestSerializedRequest(parityRpcModule, "parity_netPeers"); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":{\"active\":0,\"connected\":0,\"max\":0,\"peers\":[]},\"id\":67}"; Assert.That(serialized, Is.EqualTo(expectedResult)); } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/PersonalRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/PersonalRpcModuleTests.cs index ce707f19bab..c9a40469887 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/PersonalRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/PersonalRpcModuleTests.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Linq; -using System.Threading.Tasks; using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Crypto; @@ -32,33 +31,33 @@ public void Initialize() private DevWallet _wallet = null!; [Test] - public async Task Personal_list_accounts() + public void Personal_list_accounts() { IPersonalRpcModule rpcModule = new PersonalRpcModule(_ecdsa, _wallet, _keyStore); - string serialized = await RpcTest.TestSerializedRequest(rpcModule, "personal_listAccounts"); + string serialized = RpcTest.TestSerializedRequest(rpcModule, "personal_listAccounts"); string expectedAccounts = string.Join(',', _wallet.GetAccounts().Select(a => $"\"{a.ToString()}\"")); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":[{expectedAccounts}],\"id\":67}}")); } [Test] - public async Task Personal_import_raw_key() + public void Personal_import_raw_key() { Address expectedAddress = new("707Fc13C0eB628c074f7ff514Ae21ACaeE0ec072"); PrivateKey privateKey = new("a8fceb14d53045b1c8baedf7bc1f38b2540ce132ac28b1ec8b93b8113165abc0"); string passphrase = "testPass"; IPersonalRpcModule rpcModule = new PersonalRpcModule(_ecdsa, _wallet, _keyStore); - string serialized = await RpcTest.TestSerializedRequest(rpcModule, "personal_importRawKey", privateKey.KeyBytes.ToHexString(), passphrase); + string serialized = RpcTest.TestSerializedRequest(rpcModule, "personal_importRawKey", privateKey.KeyBytes.ToHexString(), passphrase); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"{expectedAddress.ToString()}\",\"id\":67}}")); _keyStore.DeleteKey(expectedAddress); } [Test] - public async Task Personal_new_account() + public void Personal_new_account() { int accountsBefore = _wallet.GetAccounts().Length; string passphrase = "testPass"; IPersonalRpcModule rpcModule = new PersonalRpcModule(_ecdsa, _wallet, _keyStore); - string serialized = await RpcTest.TestSerializedRequest(rpcModule, "personal_newAccount", passphrase); + string serialized = RpcTest.TestSerializedRequest(rpcModule, "personal_newAccount", passphrase); var accountsNow = _wallet.GetAccounts(); Assert.That(accountsNow.Length, Is.EqualTo(accountsBefore + 1), "length"); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"{accountsNow.Last()}\",\"id\":67}}")); @@ -66,19 +65,19 @@ public async Task Personal_new_account() [Test] [Ignore("Cannot reproduce GO signing yet")] - public async Task Personal_ec_sign() + public void Personal_ec_sign() { IPersonalRpcModule rpcModule = new PersonalRpcModule(_ecdsa, _wallet, _keyStore); - string serialized = await RpcTest.TestSerializedRequest(rpcModule, "personal_sign", "0xdeadbeaf", "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83"); + string serialized = RpcTest.TestSerializedRequest(rpcModule, "personal_sign", "0xdeadbeaf", "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83"); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b\"}}")); } [Test] [Ignore("Cannot reproduce GO signing yet")] - public async Task Personal_ec_recover() + public void Personal_ec_recover() { IPersonalRpcModule rpcModule = new PersonalRpcModule(_ecdsa, _wallet, _keyStore); - string serialized = await RpcTest.TestSerializedRequest(rpcModule, "personal_ecRecover", "0xdeadbeaf", "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b"); + string serialized = RpcTest.TestSerializedRequest(rpcModule, "personal_ecRecover", "0xdeadbeaf", "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b"); Assert.That(serialized, Is.EqualTo($"{{\"jsonrpc\":\"2.0\",\"result\":\"0x9b2055d370f73ec7d8a03e965129118dc8f5bf83\"}}")); } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs index 4cb6b4541c1..bab7705398e 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs @@ -40,10 +40,10 @@ public class ProofRpcModuleTests { private readonly bool _createSystemAccount; private readonly bool _useNonZeroGasPrice; - private IProofRpcModule _proofRpcModule = null!; - private IBlockTree _blockTree = null!; - private IDbProvider _dbProvider = null!; - private TestSpecProvider _specProvider = null!; + private IProofRpcModule _proofRpcModule; + private IBlockTree _blockTree; + private IDbProvider _dbProvider; + private TestSpecProvider _specProvider; public ProofRpcModuleTests(bool createSystemAccount, bool useNonZeroGasPrice) { @@ -73,9 +73,9 @@ public async Task Setup() [TestCase(true)] [TestCase(false)] - public async Task Can_get_transaction(bool withHeader) + public void Can_get_transaction(bool withHeader) { - Keccak txHash = _blockTree.FindBlock(1)!.Transactions[0].Hash!; + Keccak txHash = _blockTree.FindBlock(1).Transactions[0].Hash; TransactionWithProof txWithProof = _proofRpcModule.proof_getTransactionByHash(txHash, withHeader).Data; Assert.NotNull(txWithProof.Transaction); Assert.That(txWithProof.TxProof.Length, Is.EqualTo(2)); @@ -88,59 +88,59 @@ public async Task Can_get_transaction(bool withHeader) Assert.Null(txWithProof.BlockHeader); } - string response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionByHash", $"{txHash}", $"{withHeader}"); + string response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionByHash", $"{txHash}", $"{withHeader}"); Assert.True(response.Contains("\"result\"")); } [TestCase(true)] [TestCase(false)] - public async Task When_getting_non_existing_tx_correct_error_code_is_returned(bool withHeader) + public void When_getting_non_existing_tx_correct_error_code_is_returned(bool withHeader) { Keccak txHash = TestItem.KeccakH; - string response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionByHash", $"{txHash}", $"{withHeader}"); + string response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionByHash", $"{txHash}", $"{withHeader}"); Assert.True(response.Contains($"{ErrorCodes.ResourceNotFound}")); } [TestCase(true)] [TestCase(false)] - public async Task When_getting_non_existing_receipt_correct_error_code_is_returned(bool withHeader) + public void When_getting_non_existing_receipt_correct_error_code_is_returned(bool withHeader) { Keccak txHash = TestItem.KeccakH; - string response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionReceipt", $"{txHash}", $"{withHeader}"); + string response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionReceipt", $"{txHash}", $"{withHeader}"); Assert.True(response.Contains($"{ErrorCodes.ResourceNotFound}")); } - [TestCase] - public async Task On_incorrect_params_returns_correct_error_code() + [Test] + public void On_incorrect_params_returns_correct_error_code() { Keccak txHash = TestItem.KeccakH; // missing with header - string response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionReceipt", $"{txHash}"); + string response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionReceipt", $"{txHash}"); Assert.True(response.Contains($"{ErrorCodes.InvalidParams}"), "missing"); // too many - response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionReceipt", $"{txHash}", "true", "false"); + response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionReceipt", $"{txHash}", "true", "false"); Assert.True(response.Contains($"{ErrorCodes.InvalidParams}"), "too many"); // missing with header - response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionByHash", $"{txHash}"); + response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionByHash", $"{txHash}"); Assert.True(response.Contains($"{ErrorCodes.InvalidParams}"), "missing"); // too many - response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionByHash", $"{txHash}", "true", "false"); + response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionByHash", $"{txHash}", "true", "false"); Assert.True(response.Contains($"{ErrorCodes.InvalidParams}"), "too many"); // all wrong - response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{txHash}"); + response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{txHash}"); Assert.True(response.Contains($"{ErrorCodes.InvalidParams}"), "missing"); } [TestCase(true, "{\"jsonrpc\":\"2.0\",\"result\":{\"receipt\":{\"transactionHash\":\"0x6db23e4d6e1f23a0f67ae8637cd675363ec59aea22acd86300ac1f1cb42c9011\",\"transactionIndex\":\"0x0\",\"blockHash\":\"0x77f368c23226eee1583f671719f117df588fc5bf19c2a73e190e404a8be570f1\",\"blockNumber\":\"0x1\",\"cumulativeGasUsed\":\"0x0\",\"gasUsed\":\"0x0\",\"effectiveGasPrice\":\"0x1\",\"to\":null,\"contractAddress\":null,\"logs\":[],\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"status\":\"0x0\",\"type\":\"0x0\"},\"txProof\":[\"0xf851a0e244ea69b68d9f3fd5eff812a4a7e1e105a8c1143ff82206458ad45fe1801c9b80808080808080a08a1641bd871a8d574e81653362ae89e549a9ab0660bd5b180328d00f13e9c6bb8080808080808080\",\"0xf86530b862f860800182520894000000000000000000000000000000000000000001818025a0e7b18371f1b94890bd11e7f67ba7e7a3a6b263d68b2d18e258f6e063d6abd90ea00a015b31944dee0bde211cec1636a3f05bfea0678e240ae8dfe309b2aac22d93\"],\"receiptProof\":[\"0xf851a053e4a8d7d8438fa45d6b75bbd6fb699b08049c1caf1c21ada42a746ddfb61d0b80808080808080a04de834bd23b53a3d82923ae5f359239b326c66758f2ae636ab934844dba2b9658080808080808080\",\"0xf9010f30b9010bf9010880825208b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0\"],\"blockHeader\":\"0xf901f9a0b3157bcccab04639f6393042690a6c9862deebe88c781f911e8dfd265531e9ffa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a038b96dec209c13afedbb48916f68cb38a423d13c469f5f1e338ad7415c9cf5e3a0e1b1585a222beceb3887dc6701802facccf186c2d0f6aa69e26ae0c431fc2b5db9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830f424001833d090080830f424183010203a02ba5557a4c62a513c7e56d1bf13373e0da6bec016755483e91589fe1c6d212e28800000000000003e8\"},\"id\":67}")] [TestCase(false, "{\"jsonrpc\":\"2.0\",\"result\":{\"receipt\":{\"transactionHash\":\"0x6db23e4d6e1f23a0f67ae8637cd675363ec59aea22acd86300ac1f1cb42c9011\",\"transactionIndex\":\"0x0\",\"blockHash\":\"0x77f368c23226eee1583f671719f117df588fc5bf19c2a73e190e404a8be570f1\",\"blockNumber\":\"0x1\",\"cumulativeGasUsed\":\"0x0\",\"gasUsed\":\"0x0\",\"effectiveGasPrice\":\"0x1\",\"to\":null,\"contractAddress\":null,\"logs\":[],\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"status\":\"0x0\",\"type\":\"0x0\"},\"txProof\":[\"0xf851a0e244ea69b68d9f3fd5eff812a4a7e1e105a8c1143ff82206458ad45fe1801c9b80808080808080a08a1641bd871a8d574e81653362ae89e549a9ab0660bd5b180328d00f13e9c6bb8080808080808080\",\"0xf86530b862f860800182520894000000000000000000000000000000000000000001818025a0e7b18371f1b94890bd11e7f67ba7e7a3a6b263d68b2d18e258f6e063d6abd90ea00a015b31944dee0bde211cec1636a3f05bfea0678e240ae8dfe309b2aac22d93\"],\"receiptProof\":[\"0xf851a053e4a8d7d8438fa45d6b75bbd6fb699b08049c1caf1c21ada42a746ddfb61d0b80808080808080a04de834bd23b53a3d82923ae5f359239b326c66758f2ae636ab934844dba2b9658080808080808080\",\"0xf9010f30b9010bf9010880825208b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0\"]},\"id\":67}")] - public async Task Can_get_receipt(bool withHeader, string expectedResult) + public void Can_get_receipt(bool withHeader, string expectedResult) { - Keccak txHash = _blockTree.FindBlock(1)!.Transactions[0].Hash!; + Keccak txHash = _blockTree.FindBlock(1).Transactions[0].Hash; ReceiptWithProof receiptWithProof = _proofRpcModule.proof_getTransactionReceipt(txHash, withHeader).Data; Assert.NotNull(receiptWithProof.Receipt); Assert.That(receiptWithProof.ReceiptProof.Length, Is.EqualTo(2)); @@ -154,13 +154,13 @@ public async Task Can_get_receipt(bool withHeader, string expectedResult) Assert.Null(receiptWithProof.BlockHeader); } - string response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionReceipt", $"{txHash}", $"{withHeader}"); + string response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionReceipt", $"{txHash}", $"{withHeader}"); Assert.That(response, Is.EqualTo(expectedResult)); } [TestCase(true, "{\"jsonrpc\":\"2.0\",\"result\":{\"receipt\":{\"transactionHash\":\"0x1d4bacd3b4db06677ec7f43b6be43a6c1c4285ba7c8e2e63021b53701cf8189b\",\"transactionIndex\":\"0x1\",\"blockHash\":\"0x77f368c23226eee1583f671719f117df588fc5bf19c2a73e190e404a8be570f1\",\"blockNumber\":\"0x1\",\"cumulativeGasUsed\":\"0x7d0\",\"gasUsed\":\"0x3e8\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"to\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x2\",\"transactionIndex\":\"0x1\",\"transactionHash\":\"0x1d4bacd3b4db06677ec7f43b6be43a6c1c4285ba7c8e2e63021b53701cf8189b\",\"blockHash\":\"0x77f368c23226eee1583f671719f117df588fc5bf19c2a73e190e404a8be570f1\",\"blockNumber\":\"0x1\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]},{\"removed\":false,\"logIndex\":\"0x3\",\"transactionIndex\":\"0x1\",\"transactionHash\":\"0x1d4bacd3b4db06677ec7f43b6be43a6c1c4285ba7c8e2e63021b53701cf8189b\",\"blockHash\":\"0x77f368c23226eee1583f671719f117df588fc5bf19c2a73e190e404a8be570f1\",\"blockNumber\":\"0x1\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"status\":\"0x0\",\"type\":\"0x0\"},\"txProof\":[\"0xf851a0e244ea69b68d9f3fd5eff812a4a7e1e105a8c1143ff82206458ad45fe1801c9b80808080808080a08a1641bd871a8d574e81653362ae89e549a9ab0660bd5b180328d00f13e9c6bb8080808080808080\",\"0xf86431b861f85f8001825208940000000000000000000000000000000000000000020125a00861eb73c37c3560fc40047523506de00ecfa6b96dff7d37e5ce75dc3986078da032e161403eae434b0f94a36fcc7e6ad46ccffc00fe90f0756118506e918eaef9\"],\"receiptProof\":[\"0xf851a053e4a8d7d8438fa45d6b75bbd6fb699b08049c1caf1c21ada42a746ddfb61d0b80808080808080a04de834bd23b53a3d82923ae5f359239b326c66758f2ae636ab934844dba2b9658080808080808080\",\"0xf9010f31b9010bf901088082a410b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0\"],\"blockHeader\":\"0xf901f9a0b3157bcccab04639f6393042690a6c9862deebe88c781f911e8dfd265531e9ffa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a038b96dec209c13afedbb48916f68cb38a423d13c469f5f1e338ad7415c9cf5e3a0e1b1585a222beceb3887dc6701802facccf186c2d0f6aa69e26ae0c431fc2b5db9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830f424001833d090080830f424183010203a02ba5557a4c62a513c7e56d1bf13373e0da6bec016755483e91589fe1c6d212e28800000000000003e8\"},\"id\":67}")] [TestCase(false, "{\"jsonrpc\":\"2.0\",\"result\":{\"receipt\":{\"transactionHash\":\"0x1d4bacd3b4db06677ec7f43b6be43a6c1c4285ba7c8e2e63021b53701cf8189b\",\"transactionIndex\":\"0x1\",\"blockHash\":\"0x77f368c23226eee1583f671719f117df588fc5bf19c2a73e190e404a8be570f1\",\"blockNumber\":\"0x1\",\"cumulativeGasUsed\":\"0x7d0\",\"gasUsed\":\"0x3e8\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"to\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x2\",\"transactionIndex\":\"0x1\",\"transactionHash\":\"0x1d4bacd3b4db06677ec7f43b6be43a6c1c4285ba7c8e2e63021b53701cf8189b\",\"blockHash\":\"0x77f368c23226eee1583f671719f117df588fc5bf19c2a73e190e404a8be570f1\",\"blockNumber\":\"0x1\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]},{\"removed\":false,\"logIndex\":\"0x3\",\"transactionIndex\":\"0x1\",\"transactionHash\":\"0x1d4bacd3b4db06677ec7f43b6be43a6c1c4285ba7c8e2e63021b53701cf8189b\",\"blockHash\":\"0x77f368c23226eee1583f671719f117df588fc5bf19c2a73e190e404a8be570f1\",\"blockNumber\":\"0x1\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"status\":\"0x0\",\"type\":\"0x0\"},\"txProof\":[\"0xf851a0e244ea69b68d9f3fd5eff812a4a7e1e105a8c1143ff82206458ad45fe1801c9b80808080808080a08a1641bd871a8d574e81653362ae89e549a9ab0660bd5b180328d00f13e9c6bb8080808080808080\",\"0xf86431b861f85f8001825208940000000000000000000000000000000000000000020125a00861eb73c37c3560fc40047523506de00ecfa6b96dff7d37e5ce75dc3986078da032e161403eae434b0f94a36fcc7e6ad46ccffc00fe90f0756118506e918eaef9\"],\"receiptProof\":[\"0xf851a053e4a8d7d8438fa45d6b75bbd6fb699b08049c1caf1c21ada42a746ddfb61d0b80808080808080a04de834bd23b53a3d82923ae5f359239b326c66758f2ae636ab934844dba2b9658080808080808080\",\"0xf9010f31b9010bf901088082a410b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0\"]},\"id\":67}")] - public async Task Get_receipt_when_block_has_few_receipts(bool withHeader, string expectedResult) + public void Get_receipt_when_block_has_few_receipts(bool withHeader, string expectedResult) { IReceiptFinder _receiptFinder = Substitute.For(); LogEntry[] logEntries = new[] { Build.A.LogEntry.TestObject, Build.A.LogEntry.TestObject }; @@ -171,11 +171,11 @@ public async Task Get_receipt_when_block_has_few_receipts(bool withHeader, strin Index = 0, Recipient = TestItem.AddressA, Sender = TestItem.AddressB, - BlockHash = _blockTree.FindBlock(1)!.Hash, + BlockHash = _blockTree.FindBlock(1).Hash, BlockNumber = 1, ContractAddress = TestItem.AddressC, GasUsed = 1000, - TxHash = _blockTree.FindBlock(1)!.Transactions[0].Hash, + TxHash = _blockTree.FindBlock(1).Transactions[0].Hash, StatusCode = 0, GasUsedTotal = 2000, Logs = logEntries @@ -187,22 +187,22 @@ public async Task Get_receipt_when_block_has_few_receipts(bool withHeader, strin Index = 1, Recipient = TestItem.AddressC, Sender = TestItem.AddressD, - BlockHash = _blockTree.FindBlock(1)!.Hash, + BlockHash = _blockTree.FindBlock(1).Hash, BlockNumber = 1, ContractAddress = TestItem.AddressC, GasUsed = 1000, - TxHash = _blockTree.FindBlock(1)!.Transactions[1].Hash, + TxHash = _blockTree.FindBlock(1).Transactions[1].Hash, StatusCode = 0, GasUsedTotal = 2000, Logs = logEntries }; - Block block = _blockTree.FindBlock(1)!; - Keccak txHash = _blockTree.FindBlock(1)!.Transactions[1].Hash!; + Block block = _blockTree.FindBlock(1); + Keccak txHash = _blockTree.FindBlock(1).Transactions[1].Hash; TxReceipt[] receipts = { receipt1, receipt2 }; _receiptFinder.Get(Arg.Any()).Returns(receipts); _receiptFinder.Get(Arg.Any()).Returns(receipts); - _receiptFinder.FindBlockHash(Arg.Any()).Returns(_blockTree.FindBlock(1)!.Hash); + _receiptFinder.FindBlockHash(Arg.Any()).Returns(_blockTree.FindBlock(1).Hash); ProofModuleFactory moduleFactory = new ProofModuleFactory( _dbProvider, @@ -225,17 +225,17 @@ public async Task Get_receipt_when_block_has_few_receipts(bool withHeader, strin Assert.Null(receiptWithProof.BlockHeader); } - string response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionReceipt", $"{txHash}", $"{withHeader}"); + string response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_getTransactionReceipt", $"{txHash}", $"{withHeader}"); Assert.That(response, Is.EqualTo(expectedResult)); } - [TestCase] - public async Task Can_call() + [Test] + public void Can_call() { WorldState stateProvider = CreateInitialState(null); Keccak root = stateProvider.StateRoot; - Block block = Build.A.Block.WithParent(_blockTree.Head!).WithStateRoot(root).TestObject; + Block block = Build.A.Block.WithParent(_blockTree.Head).WithStateRoot(root).TestObject; BlockTreeBuilder.AddBlock(_blockTree, block); // would need to setup state root somehow... @@ -250,17 +250,17 @@ public async Task Can_call() _proofRpcModule.proof_call(tx, new BlockParameter(block.Number)); EthereumJsonSerializer serializer = new(); - string response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{serializer.Serialize(tx)}", $"{block.Number}"); + string response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{serializer.Serialize(tx)}", $"{block.Number}"); Assert.True(response.Contains("\"result\"")); } - [TestCase] - public async Task Can_call_by_hash() + [Test] + public void Can_call_by_hash() { WorldState stateProvider = CreateInitialState(null); Keccak root = stateProvider.StateRoot; - Block block = Build.A.Block.WithParent(_blockTree.Head!).WithStateRoot(root).TestObject; + Block block = Build.A.Block.WithParent(_blockTree.Head).WithStateRoot(root).TestObject; BlockTreeBuilder.AddBlock(_blockTree, block); // would need to setup state root somehow... @@ -271,17 +271,17 @@ public async Task Can_call_by_hash() To = TestItem.AddressB, GasPrice = _useNonZeroGasPrice ? 10.GWei() : 0 }; - _proofRpcModule.proof_call(tx, new BlockParameter(block.Hash!)); + _proofRpcModule.proof_call(tx, new BlockParameter(block.Hash)); EthereumJsonSerializer serializer = new(); - string response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{serializer.Serialize(tx)}", $"{block.Hash}"); + string response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{serializer.Serialize(tx)}", $"{block.Hash}"); Assert.True(response.Contains("\"result\"")); } - [TestCase] - public async Task Can_call_by_hash_canonical() + [Test] + public void Can_call_by_hash_canonical() { - Block lastHead = _blockTree.Head!; + Block lastHead = _blockTree.Head; Block block = Build.A.Block.WithParent(lastHead).TestObject; Block newBlockOnMain = Build.A.Block.WithParent(lastHead).WithDifficulty(block.Difficulty + 1).TestObject; BlockTreeBuilder.AddBlock(_blockTree, block); @@ -297,26 +297,26 @@ public async Task Can_call_by_hash_canonical() }; EthereumJsonSerializer serializer = new(); - string response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{serializer.Serialize(tx)}", $"{{\"blockHash\" : \"{block.Hash}\", \"requireCanonical\" : true}}"); + string response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{serializer.Serialize(tx)}", $"{{\"blockHash\" : \"{block.Hash}\", \"requireCanonical\" : true}}"); Assert.True(response.Contains("-32000")); - response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{serializer.Serialize(tx)}", $"{{\"blockHash\" : \"{TestItem.KeccakG}\", \"requireCanonical\" : true}}"); + response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{serializer.Serialize(tx)}", $"{{\"blockHash\" : \"{TestItem.KeccakG}\", \"requireCanonical\" : true}}"); Assert.True(response.Contains("-32001")); } - [TestCase] - public async Task Can_call_with_block_hashes() + [Test] + public void Can_call_with_block_hashes() { byte[] code = Prepare.EvmCode .PushData("0x01") .Op(Instruction.BLOCKHASH) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.BlockHeaders.Length, Is.EqualTo(2)); } - [TestCase] - public async Task Can_call_with_many_block_hashes() + [Test] + public void Can_call_with_many_block_hashes() { byte[] code = Prepare.EvmCode .PushData("0x01") @@ -324,12 +324,12 @@ public async Task Can_call_with_many_block_hashes() .PushData("0x02") .Op(Instruction.BLOCKHASH) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.BlockHeaders.Length, Is.EqualTo(3)); } - [TestCase] - public async Task Can_call_with_same_block_hash_many_time() + [Test] + public void Can_call_with_same_block_hash_many_time() { byte[] code = Prepare.EvmCode .PushData("0x01") @@ -337,24 +337,24 @@ public async Task Can_call_with_same_block_hash_many_time() .PushData("0x01") .Op(Instruction.BLOCKHASH) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.BlockHeaders.Length, Is.EqualTo(2)); } - [TestCase] - public async Task Can_call_with_storage_load() + [Test] + public void Can_call_with_storage_load() { byte[] code = Prepare.EvmCode .PushData("0x01") .Op(Instruction.SLOAD) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(1 + (_useNonZeroGasPrice ? 1 : 0))); } - [TestCase] - public async Task Can_call_with_many_storage_loads() + [Test] + public void Can_call_with_many_storage_loads() { byte[] code = Prepare.EvmCode .PushData("0x01") @@ -362,12 +362,12 @@ public async Task Can_call_with_many_storage_loads() .PushData("0x02") .Op(Instruction.SLOAD) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(1 + (_useNonZeroGasPrice ? 1 : 0))); } - [TestCase] - public async Task Can_call_with_storage_write() + [Test] + public void Can_call_with_storage_write() { byte[] code = Prepare.EvmCode .PushData("0x01") @@ -375,12 +375,12 @@ public async Task Can_call_with_storage_write() .Op(Instruction.SSTORE) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(1 + (_useNonZeroGasPrice ? 1 : 0))); } - [TestCase] - public async Task Can_call_with_extcodecopy() + [Test] + public void Can_call_with_extcodecopy() { byte[] code = Prepare.EvmCode .PushData("0x20") @@ -389,12 +389,12 @@ public async Task Can_call_with_extcodecopy() .PushData(TestItem.AddressC) .Op(Instruction.EXTCODECOPY) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2 + (_useNonZeroGasPrice ? 1 : 0))); } - [TestCase] - public async Task Can_call_with_extcodecopy_to_system_account() + [Test] + public void Can_call_with_extcodecopy_to_system_account() { byte[] code = Prepare.EvmCode .PushData("0x20") @@ -403,69 +403,69 @@ public async Task Can_call_with_extcodecopy_to_system_account() .PushData(Address.SystemUser) .Op(Instruction.EXTCODECOPY) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2)); } - [TestCase] - public async Task Can_call_with_extcodesize() + [Test] + public void Can_call_with_extcodesize() { byte[] code = Prepare.EvmCode .PushData(TestItem.AddressC) .Op(Instruction.EXTCODESIZE) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2 + (_useNonZeroGasPrice ? 1 : 0))); } - [TestCase] - public async Task Can_call_with_extcodesize_to_system_account() + [Test] + public void Can_call_with_extcodesize_to_system_account() { byte[] code = Prepare.EvmCode .PushData(Address.SystemUser) .Op(Instruction.EXTCODESIZE) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2)); } - [TestCase] - public async Task Can_call_with_extcodehash() + [Test] + public void Can_call_with_extcodehash() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode .PushData(TestItem.AddressC) .Op(Instruction.EXTCODEHASH) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2 + (_useNonZeroGasPrice ? 1 : 0))); } - [TestCase] - public async Task Can_call_with_extcodehash_to_system_account() + [Test] + public void Can_call_with_extcodehash_to_system_account() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode .PushData(Address.SystemUser) .Op(Instruction.EXTCODEHASH) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2)); } - [TestCase] - public async Task Can_call_with_just_basic_addresses() + [Test] + public void Can_call_with_just_basic_addresses() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode .Op(Instruction.STOP) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(1 + (_useNonZeroGasPrice ? 1 : 0))); } - [TestCase] - public async Task Can_call_with_balance() + [Test] + public void Can_call_with_balance() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode @@ -473,36 +473,36 @@ public async Task Can_call_with_balance() .Op(Instruction.BALANCE) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2 + (_useNonZeroGasPrice ? 1 : 0))); } - [TestCase] - public async Task Can_call_with_self_balance() + [Test] + public void Can_call_with_self_balance() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode .Op(Instruction.SELFBALANCE) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(1 + (_useNonZeroGasPrice ? 1 : 0))); } - [TestCase] - public async Task Can_call_with_balance_of_system_account() + [Test] + public void Can_call_with_balance_of_system_account() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode .PushData(Address.SystemUser) .Op(Instruction.BALANCE) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2)); } - [TestCase] - public async Task Can_call_with_call_to_system_account_with_zero_value() + [Test] + public void Can_call_with_call_to_system_account_with_zero_value() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode @@ -515,12 +515,12 @@ public async Task Can_call_with_call_to_system_account_with_zero_value() .PushData(1000000) .Op(Instruction.CALL) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2)); } - [TestCase] - public async Task Can_call_with_static_call_to_system_account() + [Test] + public void Can_call_with_static_call_to_system_account() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode @@ -532,12 +532,12 @@ public async Task Can_call_with_static_call_to_system_account() .PushData(1000000) .Op(Instruction.STATICCALL) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2)); } - [TestCase] - public async Task Can_call_with_delegate_call_to_system_account() + [Test] + public void Can_call_with_delegate_call_to_system_account() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode @@ -549,12 +549,12 @@ public async Task Can_call_with_delegate_call_to_system_account() .PushData(1000000) .Op(Instruction.DELEGATECALL) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2)); } - [TestCase] - public async Task Can_call_with_call_to_system_account_with_non_zero_value() + [Test] + public void Can_call_with_call_to_system_account_with_non_zero_value() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode @@ -567,12 +567,12 @@ public async Task Can_call_with_call_to_system_account_with_non_zero_value() .PushData(1000000) .Op(Instruction.CALL) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2)); } - [TestCase] - public async Task Can_call_with_call_with_zero_value() + [Test] + public void Can_call_with_call_with_zero_value() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode @@ -585,12 +585,12 @@ public async Task Can_call_with_call_with_zero_value() .PushData(1000000) .Op(Instruction.CALL) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2 + (_useNonZeroGasPrice ? 1 : 0))); } - [TestCase] - public async Task Can_call_with_static_call() + [Test] + public void Can_call_with_static_call() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode @@ -602,12 +602,12 @@ public async Task Can_call_with_static_call() .PushData(1000000) .Op(Instruction.STATICCALL) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2 + (_useNonZeroGasPrice ? 1 : 0))); } - [TestCase] - public async Task Can_call_with_delegate_call() + [Test] + public void Can_call_with_delegate_call() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode @@ -619,12 +619,12 @@ public async Task Can_call_with_delegate_call() .PushData(1000000) .Op(Instruction.DELEGATECALL) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(3)); } - [TestCase] - public async Task Can_call_with_call_with_non_zero_value() + [Test] + public void Can_call_with_call_with_non_zero_value() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode @@ -637,38 +637,38 @@ public async Task Can_call_with_call_with_non_zero_value() .PushData(1000000) .Op(Instruction.CALL) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2 + (_useNonZeroGasPrice ? 1 : 0))); } - [TestCase] - public async Task Can_call_with_self_destruct() + [Test] + public void Can_call_with_self_destruct() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode .PushData(TestItem.AddressC) .Op(Instruction.SELFDESTRUCT) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2 + (_useNonZeroGasPrice ? 1 : 0))); } - [TestCase] - public async Task Can_call_with_self_destruct_to_system_account() + [Test] + public void Can_call_with_self_destruct_to_system_account() { _specProvider.SpecToReturn = MuirGlacier.Instance; byte[] code = Prepare.EvmCode .PushData(Address.SystemUser) .Op(Instruction.SELFDESTRUCT) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(2)); } - [TestCase] - public async Task Can_call_with_many_storage_writes() + [Test] + public void Can_call_with_many_storage_writes() { byte[] code = Prepare.EvmCode .PushData("0x01") @@ -678,12 +678,12 @@ public async Task Can_call_with_many_storage_writes() .PushData("0x02") .Op(Instruction.SSTORE) .Done; - CallResultWithProof result = await TestCallWithCode(code); + CallResultWithProof result = TestCallWithCode(code); Assert.That(result.Accounts.Length, Is.EqualTo(1 + (_useNonZeroGasPrice ? 1 : 0))); } - [TestCase] - public async Task Can_call_with_mix_of_everything() + [Test] + public void Can_call_with_mix_of_everything() { byte[] code = Prepare.EvmCode .PushData(TestItem.AddressC) @@ -704,11 +704,11 @@ public async Task Can_call_with_mix_of_everything() .Op(Instruction.SSTORE) .Done; - await TestCallWithCode(code); + TestCallWithCode(code); } - [TestCase] - public async Task Can_call_with_mix_of_everything_and_storage() + [Test] + public void Can_call_with_mix_of_everything_and_storage() { byte[] code = Prepare.EvmCode .PushData(TestItem.AddressC) @@ -729,11 +729,11 @@ public async Task Can_call_with_mix_of_everything_and_storage() .Op(Instruction.SSTORE) .Done; - await TestCallWithStorageAndCode(code, _useNonZeroGasPrice ? 10.GWei() : 0); + TestCallWithStorageAndCode(code, _useNonZeroGasPrice ? 10.GWei() : 0); } - [TestCase] - public async Task Can_call_with_mix_of_everything_and_storage_from_another_account_wrong_nonce() + [Test] + public void Can_call_with_mix_of_everything_and_storage_from_another_account_wrong_nonce() { byte[] code = Prepare.EvmCode .PushData(TestItem.AddressC) @@ -754,10 +754,10 @@ public async Task Can_call_with_mix_of_everything_and_storage_from_another_accou .Op(Instruction.SSTORE) .Done; - await TestCallWithStorageAndCode(code, 0, TestItem.AddressD); + TestCallWithStorageAndCode(code, 0, TestItem.AddressD); } - private async Task TestCallWithCode(byte[] code, Address? from = null) + private CallResultWithProof TestCallWithCode(byte[] code, Address? from = null) { WorldState stateProvider = CreateInitialState(code); @@ -789,13 +789,13 @@ private async Task TestCallWithCode(byte[] code, Address? f } EthereumJsonSerializer serializer = new(); - string response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{serializer.Serialize(tx)}", $"{blockOnTop.Number}"); + string response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{serializer.Serialize(tx)}", $"{blockOnTop.Number}"); Assert.True(response.Contains("\"result\"")); return callResultWithProof; } - private async Task TestCallWithStorageAndCode(byte[] code, UInt256 gasPrice, Address? from = null) + private void TestCallWithStorageAndCode(byte[] code, UInt256 gasPrice, Address? from = null) { WorldState stateProvider = CreateInitialState(code); @@ -829,7 +829,7 @@ private async Task TestCallWithStorageAndCode(byte[] code, UInt256 gasPrice, Add Assert.Greater(callResultWithProof.Accounts.Length, 0); // just the keys for debugging - byte[] span = new byte[32]; + Span span = stackalloc byte[32]; new UInt256(0).ToBigEndian(span); Keccak unused = Keccak.Compute(span); @@ -846,29 +846,29 @@ private async Task TestCallWithStorageAndCode(byte[] code, UInt256 gasPrice, Add // this is here for diagnostics - so you can read what happens in the test // generally the account here should be consistent with the values inside the proof // the exception will be thrown if the account did not exist before the call + Account account; try { - byte[] verifyOneProof = ProofVerifier.VerifyOneProof(accountProof.Proof!, block.StateRoot!)!; - new AccountDecoder().Decode(new RlpStream(verifyOneProof)); + account = new AccountDecoder().Decode(new RlpStream(ProofVerifier.VerifyOneProof(accountProof.Proof, block.StateRoot))); } catch (Exception) { // ignored } - foreach (StorageProof storageProof in accountProof.StorageProofs!) + foreach (StorageProof storageProof in accountProof.StorageProofs) { // we read the values here just to allow easier debugging so you can confirm that the value is same as the one in the proof and in the trie - ProofVerifier.VerifyOneProof(storageProof.Proof!, accountProof.StorageRoot); + byte[] value = ProofVerifier.VerifyOneProof(storageProof.Proof, accountProof.StorageRoot); } } EthereumJsonSerializer serializer = new(); - string response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{serializer.Serialize(tx)}", $"{blockOnTop.Number}"); + string response = RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{serializer.Serialize(tx)}", $"{blockOnTop.Number}"); Assert.True(response.Contains("\"result\"")); } - private WorldState CreateInitialState(byte[]? code) + private WorldState CreateInitialState(byte[] code) { WorldState stateProvider = new(new TrieStore(_dbProvider.StateDb, LimboLogs.Instance), _dbProvider.CodeDb, LimboLogs.Instance); AddAccount(stateProvider, TestItem.AddressA, 1.Ether()); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/RpcModuleProviderTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/RpcModuleProviderTests.cs index 980d8f169c2..9ba5ec17022 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/RpcModuleProviderTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/RpcModuleProviderTests.cs @@ -16,9 +16,9 @@ namespace Nethermind.JsonRpc.Test.Modules [TestFixture] public class RpcModuleProviderTests { - private RpcModuleProvider _moduleProvider = null!; - private IFileSystem _fileSystem = null!; - private JsonRpcContext _context = null!; + private RpcModuleProvider _moduleProvider; + private IFileSystem _fileSystem; + private JsonRpcContext _context; [SetUp] public void Initialize() diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs index 68419d76ffd..ec9f159653b 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs @@ -40,18 +40,18 @@ namespace Nethermind.JsonRpc.Test.Modules [TestFixture] public class SubscribeModuleTests { - private ISubscribeRpcModule _subscribeRpcModule = null!; - private ILogManager _logManager = null!; - private IBlockTree _blockTree = null!; - private ITxPool _txPool = null!; - private IReceiptStorage _receiptStorage = null!; - private IFilterStore _filterStore = null!; - private ISubscriptionManager _subscriptionManager = null!; - private IJsonRpcDuplexClient _jsonRpcDuplexClient = null!; - private IJsonSerializer _jsonSerializer = null!; - private ISpecProvider _specProvider = null!; - private IReceiptMonitor _receiptCanonicalityMonitor = null!; - private ISyncConfig _syncConfig = null!; + private ISubscribeRpcModule _subscribeRpcModule; + private ILogManager _logManager; + private IBlockTree _blockTree; + private ITxPool _txPool; + private IReceiptStorage _receiptStorage; + private IFilterStore _filterStore; + private ISubscriptionManager _subscriptionManager; + private IJsonRpcDuplexClient _jsonRpcDuplexClient; + private IJsonSerializer _jsonSerializer; + private ISpecProvider _specProvider; + private IReceiptMonitor _receiptCanonicalityMonitor; + private ISyncConfig _syncConfig; [SetUp] public void Setup() @@ -206,33 +206,33 @@ private JsonRpcResult GetSyncingSubscriptionResult(bool newHead, SyncingSubscrip } [Test] - public async Task Wrong_subscription_name() + public void Wrong_subscription_name() { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "wrongSubscriptionType"); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "wrongSubscriptionType"); var expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32603,\"message\":\"Wrong subscription type: wrongSubscriptionType.\"},\"id\":67}"; expectedResult.Should().Be(serialized); } [Test] - public async Task No_subscription_name() + public void No_subscription_name() { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe"); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe"); var expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"Invalid params\",\"data\":\"Incorrect parameters count, expected: 2, actual: 0\"},\"id\":67}"; expectedResult.Should().Be(serialized); } [Test] - public async Task NewHeadSubscription_creating_result() + public void NewHeadSubscription_creating_result() { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newHeads"); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newHeads"); var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", serialized.Substring(serialized.Length - 44, 34), "\",\"id\":67}"); expectedResult.Should().Be(serialized); } [Test] - public async Task NewHeadSubscription_with_includeTransactions_arg() + public void NewHeadSubscription_with_includeTransactions_arg() { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newHeads", "{\"includeTransactions\":true}"); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newHeads", "{\"includeTransactions\":true}"); var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", serialized.Substring(serialized.Length - 44, 34), "\",\"id\":67}"); expectedResult.Should().Be(serialized); } @@ -241,9 +241,9 @@ public async Task NewHeadSubscription_with_includeTransactions_arg() [TestCase("True")] [TestCase("false")] [TestCase("False")] - public async Task NewHeadSubscription_with_bool_arg(string boolArg) + public void NewHeadSubscription_with_bool_arg(string boolArg) { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newHeads", boolArg); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newHeads", boolArg); var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", serialized.Substring(serialized.Length - 44, 34), "\",\"id\":67}"); expectedResult.Should().Be(serialized); } @@ -283,7 +283,7 @@ public void NewHeadSubscription_on_BlockAddedToMain_event() [Test] public void NewHeadSubscription_on_BlockAddedToMain_event_with_null_block() { - BlockReplacementEventArgs blockReplacementEventArgs = new(null!); + BlockReplacementEventArgs blockReplacementEventArgs = new(null); JsonRpcResult jsonRpcResult = GetBlockAddedToMainResult(blockReplacementEventArgs, out _, shouldReceiveResult: false); @@ -409,25 +409,25 @@ public void NewHeadSubscription_should_send_notifications_in_order() } [Test] - public async Task LogsSubscription_with_null_arguments_creating_result() + public void LogsSubscription_with_null_arguments_creating_result() { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "logs"); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "logs"); var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", serialized.Substring(serialized.Length - 44, 34), "\",\"id\":67}"); expectedResult.Should().Be(serialized); } [Test] - public async Task LogsSubscription_with_valid_arguments_creating_result() + public void LogsSubscription_with_valid_arguments_creating_result() { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "logs", "{\"fromBlock\":\"latest\",\"toBlock\":\"latest\",\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"topics\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\"}"); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "logs", "{\"fromBlock\":\"latest\",\"toBlock\":\"latest\",\"address\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"topics\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\"}"); var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", serialized.Substring(serialized.Length - 44, 34), "\",\"id\":67}"); expectedResult.Should().Be(serialized); } [Test] - public async Task LogsSubscription_with_invalid_arguments_creating_result() + public void LogsSubscription_with_invalid_arguments_creating_result() { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "logs", "trambabamba"); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "logs", "trambabamba"); var expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"Invalid params\"},\"id\":67}"; expectedResult.Should().Be(serialized); } @@ -437,7 +437,7 @@ public async Task LogsSubscription_with_invalid_arguments_creating_result() public void LogsSubscription_with_null_arguments_on_NewHeadBlock_event() { int blockNumber = 55555; - Filter filter = Substitute.For(); + Filter filter = null; LogEntry logEntry = Build.A.LogEntry.WithAddress(TestItem.AddressA).WithTopics(TestItem.KeccakA).WithData(TestItem.RandomDataA).TestObject; TxReceipt[] txReceipts = { Build.A.Receipt.WithBlockNumber(blockNumber).WithLogs(logEntry).TestObject }; @@ -458,7 +458,7 @@ public void LogsSubscription_with_null_arguments_on_NewHeadBlock_event() public void LogsSubscription_with_not_matching_block_on_NewHeadBlock_event() { int blockNumber = 22222; - Filter filter = Substitute.For(); + Filter filter = null; LogEntry logEntry = Build.A.LogEntry.WithAddress(TestItem.AddressA).WithTopics(TestItem.KeccakA).WithData(TestItem.RandomDataA).TestObject; TxReceipt[] txReceipts = { Build.A.Receipt.WithBlockNumber(blockNumber).WithLogs(logEntry).TestObject }; @@ -476,7 +476,7 @@ public void LogsSubscription_with_not_matching_block_on_NewHeadBlock_event() public void LogsSubscription_with_null_arguments_on_NewHeadBlock_event_with_one_TxReceipt_with_few_logs() { int blockNumber = 77777; - Filter filter = Substitute.For(); + Filter filter = null; LogEntry logEntryA = Build.A.LogEntry.WithAddress(TestItem.AddressA).WithTopics(TestItem.KeccakA).WithData(TestItem.RandomDataA).TestObject; LogEntry logEntryB = Build.A.LogEntry.WithAddress(TestItem.AddressB).WithTopics(TestItem.KeccakB).TestObject; @@ -508,7 +508,7 @@ public void LogsSubscription_with_null_arguments_on_NewHeadBlock_event_with_one_ public void LogsSubscription_with_null_arguments_on_NewHeadBlock_event_with_few_TxReceipts_with_few_logs() { int blockNumber = 55555; - Filter filter = Substitute.For(); + Filter filter = null; LogEntry logEntryA = Build.A.LogEntry.WithAddress(TestItem.AddressA).WithTopics(TestItem.KeccakA).WithData(TestItem.RandomDataA).TestObject; LogEntry logEntryB = Build.A.LogEntry.WithAddress(TestItem.AddressB).WithTopics(TestItem.KeccakB).TestObject; @@ -698,7 +698,7 @@ public void LogsSubscription_on_NewHeadBlock_event_with_few_TxReceipts_with_few_ public void LogsSubscription_should_not_send_logs_of_new_txs_on_ReceiptsInserted_event_but_on_NewHeadBlock_event() { int blockNumber = 55555; - Filter filter = Substitute.For(); + Filter filter = null; LogsSubscription logsSubscription = new(_jsonRpcDuplexClient, _receiptCanonicalityMonitor, _filterStore, _blockTree, _logManager, filter); @@ -733,17 +733,17 @@ public void LogsSubscription_should_not_send_logs_of_new_txs_on_ReceiptsInserted } [Test] - public async Task NewPendingTransactionsSubscription_creating_result() + public void NewPendingTransactionsSubscription_creating_result() { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newPendingTransactions"); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newPendingTransactions"); var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", serialized.Substring(serialized.Length - 44, 34), "\",\"id\":67}"); expectedResult.Should().Be(serialized); } [Test] - public async Task NewPendingTransactionsSubscription_creating_result_with_includeTransactions_arg() + public void NewPendingTransactionsSubscription_creating_result_with_includeTransactions_arg() { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newPendingTransactions", "{\"includeTransactions\":true}"); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newPendingTransactions", "{\"includeTransactions\":true}"); var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", serialized.Substring(serialized.Length - 44, 34), "\",\"id\":67}"); expectedResult.Should().Be(serialized); } @@ -752,9 +752,9 @@ public async Task NewPendingTransactionsSubscription_creating_result_with_includ [TestCase("True")] [TestCase("false")] [TestCase("False")] - public async Task NewPendingTransactionsSubscription_creating_result_with_bool_arg(string boolArg) + public void NewPendingTransactionsSubscription_creating_result_with_bool_arg(string boolArg) { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newPendingTransactions", boolArg); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newPendingTransactions", boolArg); var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", serialized.Substring(serialized.Length - 44, 34), "\",\"id\":67}"); expectedResult.Should().Be(serialized); } @@ -777,7 +777,7 @@ public void NewPendingTransactionsSubscription_on_NewPending_event() [Test] public void NewPendingTransactionsSubscription_on_NewPending_event_with_null_transaction() { - TxEventArgs txEventArgs = new(null!); + TxEventArgs txEventArgs = new(null); JsonRpcResult jsonRpcResult = GetNewPendingTransactionsResult(txEventArgs, out _); @@ -815,7 +815,7 @@ public void NewPendingTransactionsSubscription_on_NewPending_with_includeTransac jsonRpcResult.Response.Should().NotBeNull(); string serialized = _jsonSerializer.Serialize(jsonRpcResult.Response); - var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"method\":\"eth_subscription\",\"params\":{\"subscription\":\"", subscriptionId, "\",\"result\":{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\"}}}"); + var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"method\":\"eth_subscription\",\"params\":{\"subscription\":\"", subscriptionId, "\",\"result\":{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\"}}}"); expectedResult.Should().Be(serialized); } @@ -837,9 +837,9 @@ public void NewHeadSubscription_with_baseFeePerGas_test() } [Test] - public async Task DroppedPendingTransactionsSubscription_creating_result() + public void DroppedPendingTransactionsSubscription_creating_result() { - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "droppedPendingTransactions"); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "droppedPendingTransactions"); var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", serialized.Substring(serialized.Length - 44, 34), "\",\"id\":67}"); expectedResult.Should().Be(serialized); } @@ -862,7 +862,7 @@ public void DroppedPendingTransactionsSubscription_on_EvictedPending_event() [Test] public void DroppedPendingTransactionsSubscription_on_EvictedPending_event_with_null_transaction() { - TxEventArgs txEventArgs = new(null!); + TxEventArgs txEventArgs = new(null); JsonRpcResult jsonRpcResult = GetDroppedPendingTransactionsResult(txEventArgs, out _); @@ -885,7 +885,7 @@ public void DroppedPendingTransactionsSubscription_on_EvictedPending_event_with_ } [Test] - public async Task SyncingSubscription_creating_result() + public void SyncingSubscription_creating_result() { BlockHeader blockHeader = Build.A.BlockHeader.TestObject; _blockTree.FindBestSuggestedHeader().Returns(blockHeader); @@ -893,7 +893,7 @@ public async Task SyncingSubscription_creating_result() Block block = Build.A.Block.TestObject; _blockTree.Head.Returns(block); - string serialized = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "syncing"); + string serialized = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "syncing"); var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", serialized.Substring(serialized.Length - 44, 34), "\",\"id\":67}"); expectedResult.Should().Be(serialized); } @@ -998,29 +998,30 @@ public void SyncingSubscription_on_NewBestSuggestedBlock_event_when_sync_changed } [Test] - public async Task Eth_unsubscribe_success() + public void Eth_unsubscribe_success() { - string serializedSub = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newHeads"); + string serializedSub = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newHeads"); string subscriptionId = serializedSub.Substring(serializedSub.Length - 44, 34); string expectedSub = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", subscriptionId, "\",\"id\":67}"); expectedSub.Should().Be(serializedSub); - string serializedUnsub = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_unsubscribe", subscriptionId); + string serializedUnsub = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_unsubscribe", subscriptionId); string expectedUnsub = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}"; expectedUnsub.Should().Be(serializedUnsub); } [Test] - public async Task Subscriptions_remove_after_closing_websockets_client() + public void Subscriptions_remove_after_closing_websockets_client() { - string serializedLogs = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "logs"); + string serializedLogs = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "logs"); string logsId = serializedLogs.Substring(serializedLogs.Length - 44, 34); string expectedLogs = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", logsId, "\",\"id\":67}"); expectedLogs.Should().Be(serializedLogs); - string serializedNewPendingTx = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newPendingTransactions"); + string serializedNewPendingTx = + RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_subscribe", "newPendingTransactions"); string newPendingTxId = serializedNewPendingTx.Substring(serializedNewPendingTx.Length - 44, 34); string expectedNewPendingTx = string.Concat("{\"jsonrpc\":\"2.0\",\"result\":\"", newPendingTxId, "\",\"id\":67}"); @@ -1028,13 +1029,14 @@ public async Task Subscriptions_remove_after_closing_websockets_client() _jsonRpcDuplexClient.Closed += Raise.Event(); - string serializedLogsUnsub = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_unsubscribe", logsId); + string serializedLogsUnsub = RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_unsubscribe", logsId); string expectedLogsUnsub = string.Concat("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32603,\"message\":\"Failed to unsubscribe: ", logsId, ".\",\"data\":false},\"id\":67}"); expectedLogsUnsub.Should().Be(serializedLogsUnsub); - string serializedNewPendingTxUnsub = await RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_unsubscribe", newPendingTxId); + string serializedNewPendingTxUnsub = + RpcTest.TestSerializedRequest(_subscribeRpcModule, "eth_unsubscribe", newPendingTxId); string expectedNewPendingTxUnsub = string.Concat("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32603,\"message\":\"Failed to unsubscribe: ", newPendingTxId, ".\",\"data\":false},\"id\":67}"); @@ -1045,7 +1047,7 @@ public async Task Subscriptions_remove_after_closing_websockets_client() public void LogsSubscription_can_send_logs_with_removed_txs_when_inserted() { int blockNumber = 55555; - Filter filter = Substitute.For(); + Filter filter = null; LogsSubscription logsSubscription = new(_jsonRpcDuplexClient, _receiptCanonicalityMonitor, _filterStore, _blockTree, _logManager, filter); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs index 5c3e29fe46c..d49722ee754 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using System.IO; using System.Threading.Tasks; using Nethermind.Blockchain; @@ -37,7 +36,6 @@ namespace Nethermind.JsonRpc.Test.Modules { public class TestRpcBlockchain : TestBlockchain { - public IJsonRpcConfig RpcConfig { get; private set; } = new JsonRpcConfig(); public IEthRpcModule EthRpcModule { get; private set; } = null!; public IBlockchainBridge Bridge { get; private set; } = null!; public ITxSealer TxSealer { get; private set; } = null!; @@ -103,19 +101,13 @@ public Builder WithGasPriceOracle(IGasPriceOracle gasPriceOracle) return this; } - public Builder WithConfig(IJsonRpcConfig config) - { - _blockchain.RpcConfig = config; - return this; - } - public async Task Build(ISpecProvider? specProvider = null, UInt256? initialValues = null) { return (T)(await _blockchain.Build(specProvider, initialValues)); } } - protected override async Task Build(ISpecProvider? specProvider = null, UInt256? initialValues = null, bool addBlockOnStart = true) + protected override async Task Build(ISpecProvider? specProvider = null, UInt256? initialValues = null) { specProvider ??= new TestSpecProvider(Berlin.Instance); await base.Build(specProvider, initialValues); @@ -142,13 +134,14 @@ protected override async Task Build(ISpecProvider? specProvider FeeHistoryOracle ??= new FeeHistoryOracle(BlockFinder, ReceiptStorage, SpecProvider); ISyncConfig syncConfig = new SyncConfig(); EthRpcModule = new EthRpcModule( - RpcConfig, + new JsonRpcConfig(), Bridge, BlockFinder, StateReader, TxPool, TxSender, TestWallet, + ReceiptFinder, LimboLogs.Instance, SpecProvider, GasPriceOracle, @@ -158,10 +151,14 @@ protected override async Task Build(ISpecProvider? specProvider return this; } - public Task TestEthRpc(string method, params string[] parameters) => - RpcTest.TestSerializedRequest(EthModuleFactory.Converters, EthRpcModule, method, parameters); + public string TestEthRpc(string method, params string[] parameters) + { + return RpcTest.TestSerializedRequest(EthModuleFactory.Converters, EthRpcModule, method, parameters); + } - public Task TestSerializedRequest(T module, string method, params string[] parameters) where T : class, IRpcModule => - RpcTest.TestSerializedRequest(Array.Empty(), module, method, parameters); + public string TestSerializedRequest(T module, string method, params string[] parameters) where T : class, IRpcModule + { + return RpcTest.TestSerializedRequest(new JsonConverter[0], module, method, parameters); + } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs index 75add1e5da1..b956aa649f5 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs @@ -4,6 +4,7 @@ using System.Linq; using FluentAssertions; using Nethermind.Blockchain; +using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; @@ -12,6 +13,7 @@ using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Tracing; using Nethermind.Consensus.Validators; +using Nethermind.Consensus.Withdrawals; using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; @@ -107,8 +109,8 @@ public void Can_trace_raw_parity_style_berlin_tx() public void Should_return_correct_block_reward(bool isPostMerge) { Block block = Build.A.Block.WithParent(Build.A.Block.Genesis.TestObject).TestObject; - _blockTree!.SuggestBlock(block).Should().Be(AddBlockResult.Added); - _poSSwitcher!.IsPostMerge(Arg.Any()).Returns(isPostMerge); + _blockTree.SuggestBlock(block).Should().Be(AddBlockResult.Added); + _poSSwitcher.IsPostMerge(Arg.Any()).Returns(isPostMerge); TraceRpcModule traceRpcModule = new(NullReceiptStorage.Instance, _tracer, _blockTree, _jsonRpcConfig, MainnetSpecProvider.Instance, LimboLogs.Instance); ParityTxTraceFromStore[] result = traceRpcModule.trace_block(new BlockParameter(block.Number)).Data.ToArray(); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/TxTraceFilterTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/TxTraceFilterTests.cs index 370f349e1f6..33f330957e4 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/TxTraceFilterTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/TxTraceFilterTests.cs @@ -2,8 +2,11 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Core.Test.Builders; +using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.ParityStyle; using Nethermind.JsonRpc.Modules.Trace; +using Nethermind.Logging; +using Nethermind.Specs; using NUnit.Framework; namespace Nethermind.JsonRpc.Test.Modules.Trace; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index 9540b744758..ecde467d8a8 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -24,7 +25,6 @@ using Nethermind.Consensus.Validators; using Nethermind.Db; using Nethermind.Evm; -using Nethermind.Evm.Tracing.ParityStyle; using Nethermind.Serialization.Json; using Nethermind.Specs.Forks; using Nethermind.Specs.Test; @@ -97,7 +97,7 @@ public async Task Tx_positions_are_fine() { Context context = new(); await context.Build(); - string serialized = await RpcTest.TestSerializedRequest( + string serialized = RpcTest.TestSerializedRequest( EthModuleFactory.Converters.Union(TraceModuleFactory.Converters).ToList(), context.TraceRpcModule, "trace_block", "latest"); Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[{\"action\":{\"callType\":\"call\",\"from\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"gas\":\"0x0\",\"input\":\"0x\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\"},\"blockHash\":\"0xcd3d2c10309822aec4cbbfa80ba905ba1de62834a3b40f8012520734db2763ca\",\"blockNumber\":15,\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"transactionHash\":\"0xa1e0e640b433d5a8931881b8eee7b1a125474b04e430c0bf8afff52584c53273\",\"transactionPosition\":0,\"type\":\"call\"},{\"action\":{\"callType\":\"call\",\"from\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"gas\":\"0x0\",\"input\":\"0x\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\"},\"blockHash\":\"0xcd3d2c10309822aec4cbbfa80ba905ba1de62834a3b40f8012520734db2763ca\",\"blockNumber\":15,\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"transactionHash\":\"0x5cf5d4a0a93000beb1cfb373508ce4c0153ab491be99b3c927f482346c86a0e1\",\"transactionPosition\":1,\"type\":\"call\"},{\"action\":{\"callType\":\"call\",\"from\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"gas\":\"0x0\",\"input\":\"0x\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\"},\"blockHash\":\"0xcd3d2c10309822aec4cbbfa80ba905ba1de62834a3b40f8012520734db2763ca\",\"blockNumber\":15,\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"transactionHash\":\"0x02d2cde9120e37722f607771ebaa0d4e98c5d99a8a9e7df6872e8c8c9f5c0bc5\",\"transactionPosition\":2,\"type\":\"call\"},{\"action\":{\"callType\":\"call\",\"from\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"gas\":\"0x0\",\"input\":\"0x\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\"},\"blockHash\":\"0xcd3d2c10309822aec4cbbfa80ba905ba1de62834a3b40f8012520734db2763ca\",\"blockNumber\":15,\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"transactionHash\":\"0xe50a2a2d170011b1f9ee080c3810bed0c63dbb1b2b2c541c78ada5b222cc3fd2\",\"transactionPosition\":3,\"type\":\"call\"},{\"action\":{\"callType\":\"call\",\"from\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"gas\":\"0x0\",\"input\":\"0x\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\"},\"blockHash\":\"0xcd3d2c10309822aec4cbbfa80ba905ba1de62834a3b40f8012520734db2763ca\",\"blockNumber\":15,\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"transactionHash\":\"0xff0d4524d379fc15c41a9b0444b943e1a530779b7d09c8863858267c5ef92b24\",\"transactionPosition\":4,\"type\":\"call\"},{\"action\":{\"callType\":\"call\",\"from\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"gas\":\"0x0\",\"input\":\"0x\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\"},\"blockHash\":\"0xcd3d2c10309822aec4cbbfa80ba905ba1de62834a3b40f8012520734db2763ca\",\"blockNumber\":15,\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"transactionHash\":\"0xf9b69366c82084e3799dc4a7ad87dc173ef4923d853bc250de86b81786f2972a\",\"transactionPosition\":5,\"type\":\"call\"},{\"action\":{\"callType\":\"call\",\"from\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"gas\":\"0x0\",\"input\":\"0x\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\"},\"blockHash\":\"0xcd3d2c10309822aec4cbbfa80ba905ba1de62834a3b40f8012520734db2763ca\",\"blockNumber\":15,\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"transactionHash\":\"0x28171c29b23cd96f032fe43f444402af4555ee5f074d5d0d0a1089d940f136e7\",\"transactionPosition\":6,\"type\":\"call\"},{\"action\":{\"callType\":\"call\",\"from\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"gas\":\"0x0\",\"input\":\"0x\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\"},\"blockHash\":\"0xcd3d2c10309822aec4cbbfa80ba905ba1de62834a3b40f8012520734db2763ca\",\"blockNumber\":15,\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"transactionHash\":\"0x09b01caf4b7ecfe9d02251b2e478f2da0fdf08412e3fa1ff963fa80635dab031\",\"transactionPosition\":7,\"type\":\"call\"},{\"action\":{\"callType\":\"call\",\"from\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"gas\":\"0x0\",\"input\":\"0x\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\"},\"blockHash\":\"0xcd3d2c10309822aec4cbbfa80ba905ba1de62834a3b40f8012520734db2763ca\",\"blockNumber\":15,\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"transactionHash\":\"0xd82382905afbe4ca4c2b8e54cea43818c91e0014c3827e3020fbd82b732b8239\",\"transactionPosition\":8,\"type\":\"call\"},{\"action\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"rewardType\":\"block\",\"value\":\"0x1bc16d674ec80000\"},\"blockHash\":\"0xcd3d2c10309822aec4cbbfa80ba905ba1de62834a3b40f8012520734db2763ca\",\"blockNumber\":15,\"subtraces\":0,\"traceAddress\":[],\"type\":\"reward\"}],\"id\":67}")); @@ -109,7 +109,7 @@ public async Task Trace_filter_return_fail_with_not_existing_block() Context context = new(); await context.Build(); string request = "{\"fromBlock\":\"0x154\",\"after\":0}"; - string serialized = await RpcTest.TestSerializedRequest( + string serialized = RpcTest.TestSerializedRequest( EthModuleFactory.Converters.Union(TraceModuleFactory.Converters).ToList(), context.TraceRpcModule, "trace_filter", request); Assert.That( @@ -122,7 +122,7 @@ public async Task Trace_filter_return_fail_from_block_higher_than_to_block() Context context = new(); await context.Build(); string request = "{\"fromBlock\":\"0x8\",\"toBlock\":\"0x6\"}"; - string serialized = await RpcTest.TestSerializedRequest( + string serialized = RpcTest.TestSerializedRequest( EthModuleFactory.Converters.Union(TraceModuleFactory.Converters).ToList(), context.TraceRpcModule, "trace_filter", request); Assert.That( @@ -135,7 +135,7 @@ public async Task Trace_filter_return_empty_result_with_count_0() Context context = new(); await context.Build(); string request = "{\"count\":0x0, \"fromBlock\":\"0x3\",\"toBlock\":\"0x3\"}"; - string serialized = await RpcTest.TestSerializedRequest( + string serialized = RpcTest.TestSerializedRequest( EthModuleFactory.Converters.Union(TraceModuleFactory.Converters).ToList(), context.TraceRpcModule, "trace_filter", request); Assert.That( @@ -148,7 +148,7 @@ public async Task Trace_filter_return_expected_json() Context context = new(); await context.Build(); TraceFilterForRpc traceFilterRequest = new(); - string serialized = await RpcTest.TestSerializedRequest( + string serialized = RpcTest.TestSerializedRequest( EthModuleFactory.Converters.Union(TraceModuleFactory.Converters).ToList(), context.TraceRpcModule, "trace_filter", new EthereumJsonSerializer().Serialize(traceFilterRequest)); @@ -581,7 +581,7 @@ public async Task Trace_replayTransaction_test() Assert.That(traces.Data.Action!.From, Is.EqualTo(TestItem.AddressB)); Assert.That(traces.Data.Action.To, Is.EqualTo(TestItem.AddressC)); Assert.That(traces.Data.Action.CallType, Is.EqualTo("call")); - Assert.IsTrue(traces.Result == Result.Success); + Assert.IsTrue(traces.GetResult().ResultType == ResultType.Success); } [Test] @@ -609,7 +609,7 @@ public async Task Trace_replayTransaction_reward_test() ResultWrapper traces = context.TraceRpcModule.trace_replayTransaction(transaction.Hash!, traceTypes); Assert.That(traces.Data.Action!.CallType, Is.EqualTo("reward")); Assert.That(traces.Data.Action.Value, Is.EqualTo(UInt256.Parse("2000000000000000000"))); - Assert.IsTrue(traces.Result == Result.Success); + Assert.IsTrue(traces.GetResult().ResultType == ResultType.Success); } [Test] @@ -684,7 +684,7 @@ public async Task Trace_call_simple_tx_test() string blockParameter = "latest"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":{\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{\"action\":{\"callType\":\"call\",\"from\":\"0xaaaaaaaa8583de65cc752fe3fad5098643244d22\",\"gas\":\"0x5f58ef8\",\"input\":\"0x\",\"to\":\"0xd6a8d04cb9846759416457e2c593c99390092df6\",\"value\":\"0x0\"},\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}],\"vmTrace\":null},\"id\":67}"; - string serialized = await RpcTest.TestSerializedRequest( + string serialized = RpcTest.TestSerializedRequest( EthModuleFactory.Converters.Union(TraceModuleFactory.Converters).ToList(), context.TraceRpcModule, "trace_call", transaction, traceTypes, blockParameter); @@ -697,7 +697,7 @@ public async Task Trace_call_without_blockParameter_test(string transaction, str { Context context = new(); await context.Build(); - string serialized = await RpcTest.TestSerializedRequest( + string serialized = RpcTest.TestSerializedRequest( EthModuleFactory.Converters.Union(TraceModuleFactory.Converters).ToList(), context.TraceRpcModule, "trace_call", transaction, traceTypes); @@ -746,11 +746,11 @@ public async Task Trace_callMany_is_blockParameter_optional_test() await context.Build(); string calls = "[[{\"from\":\"0xfe35e70599578efef562e1f1cdc9ef693b865e9d\",\"to\":\"0x8cf85548ae57a91f8132d0831634c0fcef06e505\"},[\"trace\"]],[{\"from\":\"0x2a6ae6f33729384a00b4ffbd25e3f1bf1b9f5b8d\",\"to\":\"0xab736519b5433974059da38da74b8db5376942cd\",\"gasPrice\":\"0xb2b29a6dc\"},[\"trace\"]]]"; - string serialized = await RpcTest.TestSerializedRequest( + string serialized = RpcTest.TestSerializedRequest( EthModuleFactory.Converters.Union(TraceModuleFactory.Converters).ToList(), context.TraceRpcModule, "trace_callMany", calls, "latest"); - string serialized_without_blockParameter_param = await RpcTest.TestSerializedRequest( + string serialized_without_blockParameter_param = RpcTest.TestSerializedRequest( EthModuleFactory.Converters.Union(TraceModuleFactory.Converters).ToList(), context.TraceRpcModule, "trace_callMany", calls); @@ -766,7 +766,7 @@ public async Task Trace_callMany_accumulates_state_changes() string calls = $"[[{{\"from\":\"{TestItem.AddressA}\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"1\"}},[\"statediff\"]],[{{\"from\":\"{TestItem.AddressA}\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"1\"}},[\"statediff\"]]]"; - string serialized = await RpcTest.TestSerializedRequest( + string serialized = RpcTest.TestSerializedRequest( EthModuleFactory.Converters.Union(TraceModuleFactory.Converters).ToList(), context.TraceRpcModule, "trace_callMany", calls); @@ -835,18 +835,18 @@ public async Task Trace_replayBlockTransactions_stateDiff() ResultWrapper> traces = context.TraceRpcModule.trace_replayBlockTransactions(new BlockParameter(blockchain.BlockFinder.FindLatestBlock()!.Number), traceTypes); traces.Data.Should().HaveCount(1); - Dictionary state = traces.Data.ElementAt(0).StateChanges!; + var state = traces.Data.ElementAt(0).StateChanges; state.Count.Should().Be(3); - state[TestItem.AddressA].Nonce!.Before.Should().Be(accountA.Nonce); - state[TestItem.AddressD].Balance!.Before.Should().Be(accountD.Balance); - state[TestItem.AddressA].Balance!.Before.Should().Be(accountA.Balance); - state[TestItem.AddressF].Balance!.Before.Should().Be(null); - - state[TestItem.AddressA].Nonce!.After.Should().Be(accountA.Nonce + 1); - state[TestItem.AddressD].Balance!.After.Should().Be(accountD.Balance + 21000 * tx.GasPrice); - state[TestItem.AddressA].Balance!.After.Should().Be(accountA.Balance - 21000 * tx.GasPrice - tx.Value); - state[TestItem.AddressF].Balance!.After.Should().Be(accountF.Balance + tx.Value); + state[TestItem.AddressA].Nonce.Before.Should().Be(accountA.Nonce); + state[TestItem.AddressD].Balance.Before.Should().Be(accountD.Balance); + state[TestItem.AddressA].Balance.Before.Should().Be(accountA.Balance); + state[TestItem.AddressF].Balance.Before.Should().Be(null); + + state[TestItem.AddressA].Nonce.After.Should().Be(accountA.Nonce + 1); + state[TestItem.AddressD].Balance.After.Should().Be(accountD.Balance + 21000 * tx.GasPrice); + state[TestItem.AddressA].Balance.After.Should().Be(accountA.Balance - 21000 * tx.GasPrice - tx.Value); + state[TestItem.AddressF].Balance.After.Should().Be(accountF.Balance + tx.Value); } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/WitnessModuleRpcTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/WitnessModuleRpcTests.cs index 55791cb01ce..40279881943 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/WitnessModuleRpcTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/WitnessModuleRpcTests.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Threading.Tasks; using FluentAssertions; using Nethermind.Blockchain; using Nethermind.Blockchain.Find; @@ -47,7 +46,7 @@ public void Setup() } [Test] - public async Task GetOneWitnessHash() + public void GetOneWitnessHash() { _blockFinder.FindHeader((BlockParameter)null!).ReturnsForAnyArgs(_block.Header); _blockFinder.Head.Returns(_block); @@ -56,24 +55,26 @@ public async Task GetOneWitnessHash() _witnessRepository.Add(_block.Hash!); _witnessRepository.Persist(_block.Hash!); - string serialized = await RpcTest.TestSerializedRequest(_witnessRpcModule, "get_witnesses", _block.CalculateHash().ToString()); + string serialized = RpcTest.TestSerializedRequest(_witnessRpcModule, "get_witnesses", _block.CalculateHash().ToString()); serialized.Should().Be(GetOneWitnessHashResponse); } [Test] - public async Task BlockNotFound() + public void BlockNotFound() { - string serialized = await RpcTest.TestSerializedRequest(_witnessRpcModule, "get_witnesses", "0x583"); + string serialized = + RpcTest.TestSerializedRequest(_witnessRpcModule, "get_witnesses", "0x583"); serialized.Should().Be(BlockNotFoundResponse); } [Test] - public async Task WitnessNotFound() + public void WitnessNotFound() { _blockFinder.FindHeader((BlockParameter)null!).ReturnsForAnyArgs(_block.Header); _blockFinder.Head.Returns(_block); - string serialized = await RpcTest.TestSerializedRequest(_witnessRpcModule, "get_witnesses", "0x1"); + string serialized = + RpcTest.TestSerializedRequest(_witnessRpcModule, "get_witnesses", "0x1"); serialized.Should().Be(WitnessNotFoundResponse); } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Nethermind.JsonRpc.Test.csproj b/src/Nethermind/Nethermind.JsonRpc.Test/Nethermind.JsonRpc.Test.csproj index 96d7c4fb467..a58fc99534a 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Nethermind.JsonRpc.Test.csproj +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Nethermind.JsonRpc.Test.csproj @@ -4,7 +4,6 @@ false latest enable - true diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/RpcTest.cs b/src/Nethermind/Nethermind.JsonRpc.Test/RpcTest.cs index 667a947f9b4..cab41c01dbf 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/RpcTest.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/RpcTest.cs @@ -5,112 +5,100 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Threading.Tasks; using FluentAssertions; using Nethermind.JsonRpc.Modules; using Nethermind.JsonRpc.Test.Modules; using Nethermind.Logging; using Nethermind.Serialization.Json; using Newtonsoft.Json; +using NUnit.Framework; -namespace Nethermind.JsonRpc.Test; - -public static class RpcTest +namespace Nethermind.JsonRpc.Test { - public static JsonRpcResponse TestRequest(T module, string method, params string[] parameters) where T : class, IRpcModule + public static class RpcTest { - IJsonRpcService service = BuildRpcService(module); - JsonRpcRequest request = GetJsonRequest(method, parameters); - return service.SendRequestAsync(request, new JsonRpcContext(RpcEndpoint.Http)).Result; - } + public static JsonRpcResponse TestRequest(T module, string method, params string[] parameters) where T : class, IRpcModule + { + IJsonRpcService service = BuildRpcService(module); + JsonRpcRequest request = GetJsonRequest(method, parameters); + return service.SendRequestAsync(request, new JsonRpcContext(RpcEndpoint.Http)).Result; + } - public static async Task TestSerializedRequest(IReadOnlyCollection converters, T module, string method, params string[] parameters) where T : class, IRpcModule - { - long Serialize(EthereumJsonSerializer ethereumJsonSerializer, JsonRpcResponse jsonRpcResponse, IJsonRpcService jsonRpcService, Stream stream, bool indented = false) + public static string TestSerializedRequest(IReadOnlyCollection converters, T module, string method, params string[] parameters) where T : class, IRpcModule { - try - { - return ethereumJsonSerializer.SerializeWaitForEnumeration(stream, jsonRpcResponse, indented); - } - catch (Exception e) when (e.InnerException is OperationCanceledException) + IJsonRpcService service = BuildRpcService(module, converters); + JsonRpcRequest request = GetJsonRequest(method, parameters); + + JsonRpcContext context = new JsonRpcContext(RpcEndpoint.Http); + if (module is IContextAwareRpcModule contextAwareModule + && contextAwareModule.Context is not null) { - return SerializeTimeoutException(ethereumJsonSerializer, jsonRpcResponse, jsonRpcService, stream); + context = contextAwareModule.Context; } - catch (OperationCanceledException) + JsonRpcResponse response = service.SendRequestAsync(request, context).Result; + + EthereumJsonSerializer serializer = new(); + foreach (JsonConverter converter in converters) { - return SerializeTimeoutException(ethereumJsonSerializer, jsonRpcResponse, jsonRpcService, stream); + serializer.RegisterConverter(converter); } - } - static long SerializeTimeoutException(IJsonSerializer jsonSerializer, JsonRpcResponse response, IJsonRpcService service, Stream resultStream) => - jsonSerializer.Serialize(resultStream, service.GetErrorResponse(ErrorCodes.Timeout, "Request was canceled due to enabled timeout.", response.Id, response.MethodName)); + Stream stream = new MemoryStream(); + long size = serializer.Serialize(stream, response); - IJsonRpcService service = BuildRpcService(module, converters); - JsonRpcRequest request = GetJsonRequest(method, parameters); + // for coverage (and to prove that it does not throw + Stream indentedStream = new MemoryStream(); + serializer.Serialize(indentedStream, response, true); - JsonRpcContext context = module is IContextAwareRpcModule { Context: not null } contextAwareModule - ? contextAwareModule.Context - : new JsonRpcContext(RpcEndpoint.Http); + stream.Seek(0, SeekOrigin.Begin); + string serialized = new StreamReader(stream).ReadToEnd(); + TestContext.Out?.WriteLine("Serialized:"); + TestContext.Out?.WriteLine(serialized); - JsonRpcResponse response = await service.SendRequestAsync(request, context); + size.Should().Be(serialized.Length); - EthereumJsonSerializer serializer = new(); - foreach (JsonConverter converter in converters) - { - serializer.RegisterConverter(converter); + return serialized; } - await using Stream stream = new MemoryStream(); - long size = Serialize(serializer, response, service, stream); - - // for coverage (and to prove that it does not throw - await using Stream indentedStream = new MemoryStream(); - Serialize(serializer, response, service, indentedStream, true); - - stream.Seek(0, SeekOrigin.Begin); - string serialized = await new StreamReader(stream).ReadToEndAsync(); - - size.Should().Be(serialized.Length); + public static string TestSerializedRequest(T module, string method, params string[] parameters) where T : class, IRpcModule + { + return TestSerializedRequest(new JsonConverter[0], module, method, parameters); + } - return serialized; - } + public static IJsonRpcService BuildRpcService(T module, IReadOnlyCollection? converters = null) where T : class, IRpcModule + { + var moduleProvider = new TestRpcModuleProvider(module); - public static Task TestSerializedRequest(T module, string method, params string[] parameters) where T : class, IRpcModule - { - return TestSerializedRequest(Array.Empty(), module, method, parameters); - } + moduleProvider.Register(new SingletonModulePool(new TestSingletonFactory(module, converters), true)); + IJsonRpcService service = new JsonRpcService(moduleProvider, LimboLogs.Instance, new JsonRpcConfig()); + return service; + } - public static IJsonRpcService BuildRpcService(T module, IReadOnlyCollection? converters = null) where T : class, IRpcModule - { - var moduleProvider = new TestRpcModuleProvider(module); + public static JsonRpcRequest GetJsonRequest(string method, params string[] parameters) + { + var request = new JsonRpcRequest() + { + JsonRpc = "2.0", + Method = method, + Params = parameters?.ToArray() ?? Array.Empty(), + Id = 67 + }; - moduleProvider.Register(new SingletonModulePool(new TestSingletonFactory(module, converters), true)); - IJsonRpcService service = new JsonRpcService(moduleProvider, LimboLogs.Instance, new JsonRpcConfig()); - return service; - } + return request; + } - public static JsonRpcRequest GetJsonRequest(string method, params string[] parameters) - { - var request = new JsonRpcRequest() + private class TestSingletonFactory : SingletonFactory where T : IRpcModule { - JsonRpc = "2.0", - Method = method, - Params = parameters?.ToArray() ?? Array.Empty(), - Id = 67 - }; + private readonly IReadOnlyCollection? _converters; - return request; - } - - private class TestSingletonFactory : SingletonFactory where T : IRpcModule - { - private readonly IReadOnlyCollection? _converters; + public TestSingletonFactory(T module, IReadOnlyCollection? converters) : base(module) + { + _converters = converters; + } - public TestSingletonFactory(T module, IReadOnlyCollection? converters) : base(module) - { - _converters = converters; + public override IReadOnlyCollection GetConverters() => _converters ?? base.GetConverters(); } - - public override IReadOnlyCollection GetConverters() => _converters ?? base.GetConverters(); } + + } diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/DbPersistingBlockTracerTests.cs b/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/DbPersistingBlockTracerTests.cs index 808ca83af13..4f8562f4089 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/DbPersistingBlockTracerTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/DbPersistingBlockTracerTests.cs @@ -2,8 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using System.Text.Json; using FluentAssertions; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Db; using Nethermind.Evm.Tracing.ParityStyle; diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/Nethermind.JsonRpc.TraceStore.Test.csproj b/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/Nethermind.JsonRpc.TraceStore.Test.csproj index 22643661044..8d40955d0ae 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/Nethermind.JsonRpc.TraceStore.Test.csproj +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/Nethermind.JsonRpc.TraceStore.Test.csproj @@ -6,10 +6,16 @@ - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/TraceStoreRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/TraceStoreRpcModuleTests.cs index e21774bc248..b5a3eec71df 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/TraceStoreRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/TraceStoreRpcModuleTests.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Linq; +using FastEnumUtility; using FluentAssertions; using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; +using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore/DbPersistingBlockTracer.cs b/src/Nethermind/Nethermind.JsonRpc.TraceStore/DbPersistingBlockTracer.cs index 30b77d6040b..cbb508c9e70 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore/DbPersistingBlockTracer.cs +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore/DbPersistingBlockTracer.cs @@ -15,7 +15,7 @@ namespace Nethermind.JsonRpc.TraceStore; /// /// Trace type /// Transaction tracer type -public class DbPersistingBlockTracer : BlockTracer where TTracer : class, ITxTracer +public class DbPersistingBlockTracer : IBlockTracer where TTracer : class, ITxTracer { private readonly IDb _db; private readonly ITraceSerializer _traceSerializer; @@ -43,23 +43,23 @@ public DbPersistingBlockTracer(BlockTracerBase blockTracer, _logger = logManager.GetClassLogger>(); } - public override bool IsTracingRewards => _blockTracer.IsTracingRewards; + public bool IsTracingRewards => _blockTracer.IsTracingRewards; - public override void ReportReward(Address author, string rewardType, UInt256 rewardValue) => + public void ReportReward(Address author, string rewardType, UInt256 rewardValue) => _blockTracer.ReportReward(author, rewardType, rewardValue); - public override void StartNewBlockTrace(Block block) + public void StartNewBlockTrace(Block block) { _currentBlockHash = block.Hash!; _currentBlockNumber = block.Number; _blockTracer.StartNewBlockTrace(block); } - public override ITxTracer StartNewTxTrace(Transaction? tx) => _blockTracer.StartNewTxTrace(tx); + public ITxTracer StartNewTxTrace(Transaction? tx) => _blockTracer.StartNewTxTrace(tx); - public override void EndTxTrace() => _blockTracer.EndTxTrace(); + public void EndTxTrace() => _blockTracer.EndTxTrace(); - public override void EndBlockTrace() + public void EndBlockTrace() { _blockTracer.EndBlockTrace(); IReadOnlyCollection result = _tracerWithResults.BuildResult(); diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore/ITraceSerializer.cs b/src/Nethermind/Nethermind.JsonRpc.TraceStore/ITraceSerializer.cs index 3788f7621ef..646376a0479 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore/ITraceSerializer.cs +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore/ITraceSerializer.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Evm.Tracing.ParityStyle; + namespace Nethermind.JsonRpc.TraceStore; public interface ITraceSerializer diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore/ParityLikeTraceSerializer.cs b/src/Nethermind/Nethermind.JsonRpc.TraceStore/ParityLikeTraceSerializer.cs index 8d54aef92e6..dc3ee7dac21 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore/ParityLikeTraceSerializer.cs +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore/ParityLikeTraceSerializer.cs @@ -1,8 +1,11 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Buffers; using System.IO.Compression; +using Nethermind.Core.Collections; using Nethermind.Evm.Tracing.ParityStyle; +using Nethermind.JsonRpc.Modules.Trace; using Nethermind.Logging; using Nethermind.Serialization.Json; diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStorePlugin.cs b/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStorePlugin.cs index c9fdcfc1110..09ed3d3fe80 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStorePlugin.cs +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStorePlugin.cs @@ -1,8 +1,11 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Text.Json; +using FastEnumUtility; using Nethermind.Api; using Nethermind.Api.Extensions; +using Nethermind.Blockchain.Find; using Nethermind.Db; using Nethermind.Evm.Tracing.ParityStyle; using Nethermind.JsonRpc.Modules; diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs index 4e0085a27ba..6f073ba7de8 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreRpcModule.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Text.Json; using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Core; diff --git a/src/Nethermind/Nethermind.JsonRpc/Data/AccessListForRpc.cs b/src/Nethermind/Nethermind.JsonRpc/Data/AccessListForRpc.cs index f4d05e7575b..816c42ff0f1 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Data/AccessListForRpc.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Data/AccessListForRpc.cs @@ -1,20 +1,20 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; +using System; using Nethermind.Int256; namespace Nethermind.JsonRpc.Data { - public struct AccessListForRpc + public class AccessListForRpc { - public AccessListForRpc(IEnumerable accessList, in UInt256 gasUsed) + public AccessListForRpc(AccessListItemForRpc[] accessList, in UInt256 gasUsed) { AccessList = accessList; GasUsed = gasUsed; } - public IEnumerable AccessList { get; } + public AccessListItemForRpc[] AccessList { get; } public UInt256 GasUsed { get; } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Data/AccessListItemForRpc.cs b/src/Nethermind/Nethermind.JsonRpc/Data/AccessListItemForRpc.cs index 1eed1d5a03d..512cb2977c4 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Data/AccessListItemForRpc.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Data/AccessListItemForRpc.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using Nethermind.Core; -using Nethermind.Core.Collections; using Nethermind.Core.Eip2930; using Nethermind.Int256; using Nethermind.Serialization.Json; @@ -13,42 +12,38 @@ namespace Nethermind.JsonRpc.Data { - public struct AccessListItemForRpc : IEquatable + public class AccessListItemForRpc { - public AccessListItemForRpc(Address address, IEnumerable? storageKeys) + public AccessListItemForRpc(Address address, IReadOnlyCollection? storageKeys) { Address = address; - StorageKeys = storageKeys; + StorageKeys = storageKeys?.ToArray() ?? Array.Empty(); } public Address Address { get; set; } [JsonProperty(ItemConverterType = typeof(StorageCellIndexConverter))] - public IEnumerable? StorageKeys { get; set; } + public UInt256[]? StorageKeys { get; set; } - public static IEnumerable FromAccessList(AccessList accessList) => - accessList.Select(tuple => new AccessListItemForRpc(tuple.Address, tuple.StorageKeys)); + public static AccessListItemForRpc[] FromAccessList(AccessList accessList) => + accessList.Data.Select(kvp => new AccessListItemForRpc(kvp.Key, kvp.Value)).ToArray(); - public static AccessList ToAccessList(IEnumerable accessList) + public static AccessList ToAccessList(AccessListItemForRpc[] accessList) { - AccessList.Builder builder = new(); - foreach (AccessListItemForRpc accessListItem in accessList) + AccessListBuilder accessListBuilder = new(); + for (int i = 0; i < accessList.Length; i++) { - builder.AddAddress(accessListItem.Address); + var accessListItem = accessList[i]; + accessListBuilder.AddAddress(accessListItem.Address); if (accessListItem.StorageKeys is not null) { - foreach (UInt256 index in accessListItem.StorageKeys) + for (int j = 0; j < accessListItem.StorageKeys.Length; j++) { - builder.AddStorage(index); + accessListBuilder.AddStorage(accessListItem.StorageKeys[j]); } } } - - return builder.Build(); + return accessListBuilder.ToAccessList(); } - - public bool Equals(AccessListItemForRpc other) => Equals(Address, other.Address) && StorageKeys.NullableSequenceEqual(other.StorageKeys); - public override bool Equals(object? obj) => obj is AccessListItemForRpc other && Equals(other); - public override int GetHashCode() => HashCode.Combine(Address, StorageKeys); } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Data/BlockParameterConverter.cs b/src/Nethermind/Nethermind.JsonRpc/Data/BlockParameterConverter.cs index cbac013a8ae..b4146ca1042 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Data/BlockParameterConverter.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Data/BlockParameterConverter.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Blockchain; using Nethermind.Blockchain.Find; using Nethermind.Core.Crypto; using Nethermind.JsonRpc.Modules.Trace; diff --git a/src/Nethermind/Nethermind.JsonRpc/Data/ReceiptForRpc.cs b/src/Nethermind/Nethermind.JsonRpc/Data/ReceiptForRpc.cs index 57cf46b4e87..7ce43ff3411 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Data/ReceiptForRpc.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Data/ReceiptForRpc.cs @@ -25,8 +25,8 @@ public ReceiptForRpc(Keccak txHash, TxReceipt receipt, TxGasInfo gasInfo, int lo CumulativeGasUsed = receipt.GasUsedTotal; GasUsed = receipt.GasUsed; EffectiveGasPrice = gasInfo.EffectiveGasPrice; - BlobGasUsed = gasInfo.BlobGasUsed; - BlobGasPrice = gasInfo.BlobGasPrice; + DataGasUsed = gasInfo.DataGasUsed; + DataGasPrice = gasInfo.DataGasPrice; From = receipt.Sender; To = receipt.Recipient; ContractAddress = receipt.ContractAddress; @@ -44,12 +44,10 @@ public ReceiptForRpc(Keccak txHash, TxReceipt receipt, TxGasInfo gasInfo, int lo public long BlockNumber { get; set; } public long CumulativeGasUsed { get; set; } public long GasUsed { get; set; } - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public ulong? BlobGasUsed { get; set; } - + public ulong? DataGasUsed { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public UInt256? BlobGasPrice { get; set; } + public UInt256? DataGasPrice { get; set; } public UInt256? EffectiveGasPrice { get; set; } public Address From { get; set; } diff --git a/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs b/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs index 9116a6c8eea..4455d773fae 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Eip2930; @@ -14,10 +13,6 @@ namespace Nethermind.JsonRpc.Data; public class TransactionForRpc { - // HACK: To ensure that serialized Txs always have a `ChainId` we keep the last loaded `ChainSpec`. - // See: https://github.com/NethermindEth/nethermind/pull/6061#discussion_r1321634914 - public static UInt256? DefaultChainId { get; set; } - public TransactionForRpc(Transaction transaction) : this(null, null, null, transaction) { } public TransactionForRpc(Keccak? blockHash, long? blockNumber, int? txIndex, Transaction transaction, UInt256? baseFee = null) @@ -41,26 +36,10 @@ public TransactionForRpc(Keccak? blockHash, long? blockNumber, int? txIndex, Tra MaxFeePerGas = transaction.MaxFeePerGas; MaxPriorityFeePerGas = transaction.MaxPriorityFeePerGas; } - if (transaction.Type > TxType.Legacy) - { - ChainId = transaction.ChainId - ?? DefaultChainId - ?? BlockchainIds.Mainnet; - } - else - { - ChainId = transaction.ChainId; - } + ChainId = transaction.ChainId; Type = transaction.Type; - if (transaction.SupportsAccessList) - { - AccessList = transaction.AccessList is null ? Array.Empty() : AccessListItemForRpc.FromAccessList(transaction.AccessList); - } - else - { - AccessList = null; - } - MaxFeePerBlobGas = transaction.MaxFeePerBlobGas; + AccessList = transaction.AccessList is null ? null : AccessListItemForRpc.FromAccessList(transaction.AccessList); + MaxFeePerDataGas = transaction.MaxFeePerDataGas; BlobVersionedHashes = transaction.BlobVersionedHashes; Signature? signature = transaction.Signature; @@ -70,9 +49,7 @@ public TransactionForRpc(Keccak? blockHash, long? blockNumber, int? txIndex, Tra YParity = transaction.SupportsAccessList ? signature.RecoveryId : null; R = new UInt256(signature.R, true); S = new UInt256(signature.S, true); - // V must be null for non-legacy transactions. Temporarily set to recovery id for Geth compatibility. - // See https://github.com/ethereum/go-ethereum/issues/27727 - V = transaction.Type == TxType.Legacy ? signature.V : signature.RecoveryId; + V = transaction.Type == TxType.Legacy ? (UInt256?)signature.V : (UInt256?)signature.RecoveryId; } } @@ -105,12 +82,7 @@ public TransactionForRpc() public UInt256? MaxFeePerGas { get; set; } public long? Gas { get; set; } - - // Required for compatibility with some CLs like Prysm - // Accept during deserialization, ignore during serialization - // See: https://github.com/NethermindEth/nethermind/pull/6067 - [JsonProperty(nameof(Data))] - private byte[]? Data { set { Input = value; } } + public byte[]? Data { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Include)] public byte[]? Input { get; set; } @@ -119,11 +91,11 @@ public TransactionForRpc() public TxType Type { get; set; } - public IEnumerable? AccessList { get; set; } + public AccessListItemForRpc[]? AccessList { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public UInt256? MaxFeePerBlobGas { get; set; } // eip4844 + public UInt256? MaxFeePerDataGas { get; set; } // eip4844 [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public byte[][]? BlobVersionedHashes { get; set; } // eip4844 @@ -149,7 +121,7 @@ public TransactionForRpc() To = To, SenderAddress = From, Value = Value ?? 0, - Data = Input, + Data = Data ?? Input, Type = Type, AccessList = TryGetAccessList(), ChainId = chainId, @@ -164,7 +136,7 @@ public TransactionForRpc() if (tx.SupportsBlobs) { - tx.MaxFeePerBlobGas = MaxFeePerBlobGas; + tx.MaxFeePerDataGas = MaxFeePerDataGas; tx.BlobVersionedHashes = BlobVersionedHashes; } @@ -175,7 +147,7 @@ public TransactionForRpc() public T ToTransaction(ulong? chainId = null) where T : Transaction, new() { - byte[]? data = Input; + byte[]? data = Data ?? Input; T tx = new() { @@ -204,7 +176,7 @@ public TransactionForRpc() if (tx.SupportsBlobs) { - tx.MaxFeePerBlobGas = MaxFeePerBlobGas; + tx.MaxFeePerDataGas = MaxFeePerDataGas; tx.BlobVersionedHashes = BlobVersionedHashes; } diff --git a/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpcWithTraceTypes.cs b/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpcWithTraceTypes.cs index 3f118399476..d95c6574e71 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpcWithTraceTypes.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpcWithTraceTypes.cs @@ -1,6 +1,10 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + namespace Nethermind.JsonRpc.Data { public class TransactionForRpcWithTraceTypes diff --git a/src/Nethermind/Nethermind.JsonRpc/Error.cs b/src/Nethermind/Nethermind.JsonRpc/Error.cs index dc6b1ffe26f..fbbb4172136 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Error.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Error.cs @@ -15,8 +15,5 @@ public class Error [JsonProperty(PropertyName = "data", Order = 2)] public object? Data { get; set; } - - [JsonIgnore] - public bool SuppressWarning { get; set; } } } diff --git a/src/Nethermind/Nethermind.JsonRpc/ErrorType.cs b/src/Nethermind/Nethermind.JsonRpc/ErrorType.cs index 8ae4af13215..3b4da6c3c8d 100644 --- a/src/Nethermind/Nethermind.JsonRpc/ErrorType.cs +++ b/src/Nethermind/Nethermind.JsonRpc/ErrorType.cs @@ -87,9 +87,5 @@ public static class ErrorCodes /// public const int UnknownBlockError = -39001; - /// - /// Unsupported fork error - /// - public const int UnsupportedFork = -38005; } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Exceptions/LimitExceededException.cs b/src/Nethermind/Nethermind.JsonRpc/Exceptions/LimitExceededException.cs deleted file mode 100644 index 8fcbdcc963e..00000000000 --- a/src/Nethermind/Nethermind.JsonRpc/Exceptions/LimitExceededException.cs +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; - -namespace Nethermind.JsonRpc.Exceptions; - -public class LimitExceededException : Exception -{ - public LimitExceededException(string message) - : base(message) - { - } -} diff --git a/src/Nethermind/Nethermind.JsonRpc/IJsonRpcConfig.cs b/src/Nethermind/Nethermind.JsonRpc/IJsonRpcConfig.cs index 506f7b4749b..de57492245c 100644 --- a/src/Nethermind/Nethermind.JsonRpc/IJsonRpcConfig.cs +++ b/src/Nethermind/Nethermind.JsonRpc/IJsonRpcConfig.cs @@ -23,19 +23,6 @@ public interface IJsonRpcConfig : IConfig DefaultValue = "20000")] int Timeout { get; set; } - [ConfigItem( - Description = "The queued request limit for calls above the max concurrency amount for (" + - nameof(IEthRpcModule.eth_call) + ", " + - nameof(IEthRpcModule.eth_estimateGas) + ", " + - nameof(IEthRpcModule.eth_getLogs) + ", " + - nameof(IEthRpcModule.eth_newFilter) + ", " + - nameof(IEthRpcModule.eth_newBlockFilter) + ", " + - nameof(IEthRpcModule.eth_newPendingTransactionFilter) + ", " + - nameof(IEthRpcModule.eth_uninstallFilter) + "). " + - " If value is set to 0 limit won't be applied.", - DefaultValue = "500")] - int RequestQueueLimit { get; set; } - [ConfigItem( Description = "Base file path for diagnostic JSON RPC recorder.", DefaultValue = "\"logs/rpc.{counter}.txt\"")] diff --git a/src/Nethermind/Nethermind.JsonRpc/IJsonRpcLocalStats.cs b/src/Nethermind/Nethermind.JsonRpc/IJsonRpcLocalStats.cs index 160adfd1082..873d9d8b1ae 100644 --- a/src/Nethermind/Nethermind.JsonRpc/IJsonRpcLocalStats.cs +++ b/src/Nethermind/Nethermind.JsonRpc/IJsonRpcLocalStats.cs @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Threading.Tasks; +using System.Collections.Generic; namespace Nethermind.JsonRpc { @@ -20,7 +20,7 @@ public class MethodStats public interface IJsonRpcLocalStats { - Task ReportCall(RpcReport report, long elapsedMicroseconds = 0, long? size = null); + void ReportCall(in RpcReport report, long elapsedMicroseconds = 0, long? size = null); MethodStats GetMethodStats(string methodName); } diff --git a/src/Nethermind/Nethermind.JsonRpc/IJsonRpcProcessor.cs b/src/Nethermind/Nethermind.JsonRpc/IJsonRpcProcessor.cs index 3749ea84488..d06be4db23e 100644 --- a/src/Nethermind/Nethermind.JsonRpc/IJsonRpcProcessor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/IJsonRpcProcessor.cs @@ -3,6 +3,9 @@ using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; +using Nethermind.JsonRpc.Modules; +using Nethermind.Serialization.Json; namespace Nethermind.JsonRpc { diff --git a/src/Nethermind/Nethermind.JsonRpc/IJsonRpcService.cs b/src/Nethermind/Nethermind.JsonRpc/IJsonRpcService.cs index 54a311fa875..ce11a15714d 100644 --- a/src/Nethermind/Nethermind.JsonRpc/IJsonRpcService.cs +++ b/src/Nethermind/Nethermind.JsonRpc/IJsonRpcService.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading.Tasks; +using Nethermind.JsonRpc.Modules; using Newtonsoft.Json; namespace Nethermind.JsonRpc @@ -9,7 +10,8 @@ namespace Nethermind.JsonRpc public interface IJsonRpcService { Task SendRequestAsync(JsonRpcRequest request, JsonRpcContext context); - JsonRpcErrorResponse GetErrorResponse(int errorCode, string errorMessage, object? id = null, string? methodName = null); + JsonRpcErrorResponse GetErrorResponse(int errorCode, string errorMessage); + JsonRpcErrorResponse GetErrorResponse(string methodName, int errorCode, string errorMessage, object id); JsonConverter[] Converters { get; } } } diff --git a/src/Nethermind/Nethermind.JsonRpc/IJsonRpcUrlCollection.cs b/src/Nethermind/Nethermind.JsonRpc/IJsonRpcUrlCollection.cs index 5e43723d16f..18aa18db527 100644 --- a/src/Nethermind/Nethermind.JsonRpc/IJsonRpcUrlCollection.cs +++ b/src/Nethermind/Nethermind.JsonRpc/IJsonRpcUrlCollection.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; namespace Nethermind.JsonRpc diff --git a/src/Nethermind/Nethermind.JsonRpc/IResultWrapper.cs b/src/Nethermind/Nethermind.JsonRpc/IResultWrapper.cs index 2fe9750e717..94f01b78590 100644 --- a/src/Nethermind/Nethermind.JsonRpc/IResultWrapper.cs +++ b/src/Nethermind/Nethermind.JsonRpc/IResultWrapper.cs @@ -7,9 +7,10 @@ namespace Nethermind.JsonRpc { public interface IResultWrapper { - public object Data { get; } - public Result Result { get; } - public int ErrorCode { get; } - public bool IsTemporary { get; } + Result? GetResult(); + + object GetData(); + + int GetErrorCode(); } } diff --git a/src/Nethermind/Nethermind.JsonRpc/JsonRpcConfig.cs b/src/Nethermind/Nethermind.JsonRpc/JsonRpcConfig.cs index 79bdf2dd36c..96a7326b854 100644 --- a/src/Nethermind/Nethermind.JsonRpc/JsonRpcConfig.cs +++ b/src/Nethermind/Nethermind.JsonRpc/JsonRpcConfig.cs @@ -15,7 +15,6 @@ public class JsonRpcConfig : IJsonRpcConfig public bool Enabled { get; set; } public string Host { get; set; } = "127.0.0.1"; public int Timeout { get; set; } = 20000; - public int RequestQueueLimit { get; set; } = 500; public string RpcRecorderBaseFilePath { get; set; } = "logs/rpc.{counter}.txt"; public RpcRecorderState RpcRecorderState { get; set; } = RpcRecorderState.None; diff --git a/src/Nethermind/Nethermind.JsonRpc/JsonRpcLocalStats.cs b/src/Nethermind/Nethermind.JsonRpc/JsonRpcLocalStats.cs index 2c3eba2ffac..d9323725a96 100644 --- a/src/Nethermind/Nethermind.JsonRpc/JsonRpcLocalStats.cs +++ b/src/Nethermind/Nethermind.JsonRpc/JsonRpcLocalStats.cs @@ -8,7 +8,6 @@ using System.Globalization; using System.Linq; using System.Text; -using System.Threading.Tasks; using Nethermind.Core; using Nethermind.Logging; @@ -17,51 +16,46 @@ namespace Nethermind.JsonRpc public class JsonRpcLocalStats : IJsonRpcLocalStats { private readonly ITimestamper _timestamper; + private readonly IJsonRpcConfig _jsonRpcConfig; private readonly TimeSpan _reportingInterval; + private ConcurrentDictionary _currentStats = new(); private ConcurrentDictionary _previousStats = new(); private readonly ConcurrentDictionary _allTimeStats = new(); - private DateTime _lastReport; + private DateTime _lastReport = DateTime.MinValue; private readonly ILogger _logger; - private readonly StringBuilder _reportStringBuilder = new(); public JsonRpcLocalStats(ITimestamper timestamper, IJsonRpcConfig jsonRpcConfig, ILogManager logManager) { _timestamper = timestamper ?? throw new ArgumentNullException(nameof(timestamper)); + _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); _reportingInterval = TimeSpan.FromSeconds(jsonRpcConfig.ReportIntervalSeconds); - _lastReport = timestamper.UtcNow; } public MethodStats GetMethodStats(string methodName) => _allTimeStats.GetValueOrDefault(methodName, new MethodStats()); - public Task ReportCall(string method, long handlingTimeMicroseconds, bool success) => + public void ReportCall(string method, long handlingTimeMicroseconds, bool success) => ReportCall(new RpcReport(method, handlingTimeMicroseconds, success)); - public Task ReportCall(RpcReport report, long elapsedMicroseconds = 0, long? size = null) + public void ReportCall(in RpcReport report, long elapsedMicroseconds = 0, long? size = null) { if (string.IsNullOrWhiteSpace(report.Method)) { - return Task.CompletedTask; + return; } - if (!_logger.IsInfo) + DateTime thisTime = _timestamper.UtcNow; + if (thisTime - _lastReport > _reportingInterval) { - return Task.CompletedTask; + _lastReport = thisTime; + BuildReport(); } - return ReportCallInternal(report, elapsedMicroseconds, size); - } - - private async Task ReportCallInternal(RpcReport report, long elapsedMicroseconds, long? size) - { - // we don't want to block RPC calls any longer than required - await Task.Yield(); - - BuildReport(); - - MethodStats methodStats = _currentStats.GetOrAdd(report.Method, _ => new MethodStats()); - MethodStats allTimeMethodStats = _allTimeStats.GetOrAdd(report.Method, _ => new MethodStats()); + _currentStats.TryGetValue(report.Method, out MethodStats methodStats); + _allTimeStats.TryGetValue(report.Method, out MethodStats allTimeMethodStats); + methodStats ??= _currentStats.GetOrAdd(report.Method, _ => new MethodStats()); + allTimeMethodStats ??= _allTimeStats.GetOrAdd(report.Method, _ => new MethodStats()); long reportHandlingTimeMicroseconds = elapsedMicroseconds == 0 ? report.HandlingTimeMicroseconds : elapsedMicroseconds; @@ -79,7 +73,7 @@ private async Task ReportCallInternal(RpcReport report, long elapsedMicroseconds allTimeMethodStats.AvgTimeOfSuccesses = (allTimeMethodStats.Successes * allTimeMethodStats.AvgTimeOfSuccesses + - reportHandlingTimeMicroseconds) / + reportHandlingTimeMicroseconds) / ++allTimeMethodStats.Successes; allTimeMethodStats.MaxTimeOfSuccess = Math.Max(allTimeMethodStats.MaxTimeOfSuccess, reportHandlingTimeMicroseconds); @@ -102,73 +96,61 @@ private async Task ReportCallInternal(RpcReport report, long elapsedMicroseconds } } - private const string ReportHeader = "method | " + - "successes | " + - " avg time (µs) | " + - " max time (µs) | " + - " errors | " + - " avg time (µs) | " + - " max time (µs) |" + - " avg size |" + - " total size |"; - - private static readonly string _divider = new('-', ReportHeader.Length); - private void BuildReport() { - DateTime thisTime = _timestamper.UtcNow; - if (thisTime - _lastReport <= _reportingInterval) + if (!_logger.IsInfo) { return; } - lock (_logger) - { - if (thisTime - _lastReport <= _reportingInterval) - { - return; - } - - _lastReport = thisTime; - - Swap(); + Swap(); - if (!_previousStats.Any()) - { - return; - } + if (!_previousStats.Any()) + { + return; + } - _reportStringBuilder.AppendLine("***** JSON RPC report *****"); - _reportStringBuilder.AppendLine(_divider); - _reportStringBuilder.AppendLine(ReportHeader); - _reportStringBuilder.AppendLine(_divider); - MethodStats total = new(); - foreach (KeyValuePair methodStats in _previousStats.OrderBy(kv => kv.Key)) - { - total.AvgTimeOfSuccesses = total.Successes + methodStats.Value.Successes == 0 - ? 0 - : (total.AvgTimeOfSuccesses * total.Successes + methodStats.Value.Successes * methodStats.Value.AvgTimeOfSuccesses) - / (total.Successes + methodStats.Value.Successes); - total.AvgTimeOfErrors = total.Errors + methodStats.Value.Errors == 0 - ? 0 - : (total.AvgTimeOfErrors * total.Errors + methodStats.Value.Errors * methodStats.Value.AvgTimeOfErrors) - / (total.Errors + methodStats.Value.Errors); - total.Successes += methodStats.Value.Successes; - total.Errors += methodStats.Value.Errors; - total.MaxTimeOfSuccess = Math.Max(total.MaxTimeOfSuccess, methodStats.Value.MaxTimeOfSuccess); - total.MaxTimeOfError = Math.Max(total.MaxTimeOfError, methodStats.Value.MaxTimeOfError); - total.TotalSize += methodStats.Value.TotalSize; - _reportStringBuilder.AppendLine(PrepareReportLine(methodStats.Key, methodStats.Value)); - } + const string reportHeader = "method | " + + "successes | " + + " avg time (µs) | " + + " max time (µs) | " + + " errors | " + + " avg time (µs) | " + + " max time (µs) |" + + " avg size |" + + " total size |"; + + StringBuilder stringBuilder = new(); + stringBuilder.AppendLine("***** JSON RPC report *****"); + string divider = new(Enumerable.Repeat('-', reportHeader.Length).ToArray()); + stringBuilder.AppendLine(divider); + stringBuilder.AppendLine(reportHeader); + stringBuilder.AppendLine(divider); + MethodStats total = new(); + foreach (KeyValuePair methodStats in _previousStats.OrderBy(kv => kv.Key)) + { + total.AvgTimeOfSuccesses = total.Successes + methodStats.Value.Successes == 0 + ? 0 + : (total.AvgTimeOfSuccesses * total.Successes + methodStats.Value.Successes * methodStats.Value.AvgTimeOfSuccesses) + / (total.Successes + methodStats.Value.Successes); + total.AvgTimeOfErrors = total.Errors + methodStats.Value.Errors == 0 + ? 0 + : (total.AvgTimeOfErrors * total.Errors + methodStats.Value.Errors * methodStats.Value.AvgTimeOfErrors) + / (total.Errors + methodStats.Value.Errors); + total.Successes += methodStats.Value.Successes; + total.Errors += methodStats.Value.Errors; + total.MaxTimeOfSuccess = Math.Max(total.MaxTimeOfSuccess, methodStats.Value.MaxTimeOfSuccess); + total.MaxTimeOfError = Math.Max(total.MaxTimeOfError, methodStats.Value.MaxTimeOfError); + total.TotalSize += methodStats.Value.TotalSize; + stringBuilder.AppendLine(PrepareReportLine(methodStats.Key, methodStats.Value)); + } - _reportStringBuilder.AppendLine(_divider); - _reportStringBuilder.AppendLine(PrepareReportLine("TOTAL", total)); - _reportStringBuilder.AppendLine(_divider); + stringBuilder.AppendLine(divider); + stringBuilder.AppendLine(PrepareReportLine("TOTAL", total)); + stringBuilder.AppendLine(divider); - _logger.Info(_reportStringBuilder.ToString()); - _reportStringBuilder.Clear(); - _previousStats.Clear(); - } + _logger.Info(stringBuilder.ToString()); + _previousStats.Clear(); } private void Swap() @@ -177,15 +159,19 @@ private void Swap() } [Pure] - private string PrepareReportLine(in string key, MethodStats methodStats) => - $"{key,-40}| " + - $"{methodStats.Successes.ToString(),9} | " + - $"{methodStats.AvgTimeOfSuccesses.ToString("0", CultureInfo.InvariantCulture),14} | " + - $"{methodStats.MaxTimeOfSuccess.ToString(CultureInfo.InvariantCulture),14} | " + - $"{methodStats.Errors.ToString(),9} | " + - $"{methodStats.AvgTimeOfErrors.ToString("0", CultureInfo.InvariantCulture),14} | " + - $"{methodStats.MaxTimeOfError.ToString(CultureInfo.InvariantCulture),14} | " + - $"{methodStats.AvgSize.ToString("0", CultureInfo.InvariantCulture),8} | " + - $"{methodStats.TotalSize.ToString("0", CultureInfo.InvariantCulture),10} | "; + private string PrepareReportLine(in string key, MethodStats methodStats) + { + string reportLine = $"{key,-40}| " + + $"{methodStats.Successes.ToString(),9} | " + + $"{methodStats.AvgTimeOfSuccesses.ToString("0", CultureInfo.InvariantCulture),14} | " + + $"{methodStats.MaxTimeOfSuccess.ToString(CultureInfo.InvariantCulture),14} | " + + $"{methodStats.Errors.ToString(),9} | " + + $"{methodStats.AvgTimeOfErrors.ToString("0", CultureInfo.InvariantCulture),14} | " + + $"{methodStats.MaxTimeOfError.ToString(CultureInfo.InvariantCulture),14} | " + + $"{methodStats.AvgSize.ToString("0", CultureInfo.InvariantCulture),8} | " + + $"{methodStats.TotalSize.ToString("0", CultureInfo.InvariantCulture),10} | "; + + return reportLine; + } } } diff --git a/src/Nethermind/Nethermind.JsonRpc/JsonRpcProcessor.cs b/src/Nethermind/Nethermind.JsonRpc/JsonRpcProcessor.cs index 40dc11b572b..d5393d65132 100644 --- a/src/Nethermind/Nethermind.JsonRpc/JsonRpcProcessor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/JsonRpcProcessor.cs @@ -6,9 +6,11 @@ using System.Diagnostics; using System.IO; using System.IO.Abstractions; +using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.JsonRpc.Utils; using Nethermind.Logging; @@ -17,25 +19,26 @@ using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; -#nullable enable namespace Nethermind.JsonRpc { public class JsonRpcProcessor : IJsonRpcProcessor { - private readonly JsonSerializer _traceSerializer; + private JsonSerializer _traceSerializer; private readonly IJsonRpcConfig _jsonRpcConfig; private readonly ILogger _logger; private readonly JsonSerializer _obsoleteBasicJsonSerializer = new(); private readonly IJsonRpcService _jsonRpcService; private readonly IJsonSerializer _jsonSerializer; - private readonly Recorder? _recorder; + private readonly Recorder _recorder; public JsonRpcProcessor(IJsonRpcService jsonRpcService, IJsonSerializer jsonSerializer, IJsonRpcConfig jsonRpcConfig, IFileSystem fileSystem, ILogManager logManager) { - _logger = logManager.GetClassLogger(); - _jsonRpcService = jsonRpcService; - _jsonRpcConfig = jsonRpcConfig; - _jsonSerializer = jsonSerializer; + _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); + if (fileSystem is null) throw new ArgumentNullException(nameof(fileSystem)); + + _jsonRpcService = jsonRpcService ?? throw new ArgumentNullException(nameof(jsonRpcService)); + _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); + _jsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer)); if (_jsonRpcConfig.RpcRecorderState != RpcRecorderState.None) { @@ -44,14 +47,14 @@ public JsonRpcProcessor(IJsonRpcService jsonRpcService, IJsonSerializer jsonSeri _recorder = new Recorder(recorderBaseFilePath, fileSystem, _logger); } - _traceSerializer = BuildTraceJsonSerializer(); + BuildTraceJsonSerializer(); } /// /// The serializer is created in a way that mimics the behaviour of the Kestrel serialization /// and can be used for recording and replaying JSON RPC calls. /// - private JsonSerializer BuildTraceJsonSerializer() + private void BuildTraceJsonSerializer() { JsonSerializerSettings jsonSettings = new() { @@ -63,10 +66,10 @@ private JsonSerializer BuildTraceJsonSerializer() jsonSettings.Converters.Add(converter); } - return JsonSerializer.Create(jsonSettings); + _traceSerializer = JsonSerializer.Create(jsonSettings); } - private IEnumerable<(JsonRpcRequest? Model, List? Collection)> DeserializeObjectOrArray(TextReader json) + private IEnumerable<(JsonRpcRequest Model, List Collection)> DeserializeObjectOrArray(TextReader json) { IEnumerable parsedJson = JTokenUtils.ParseMulticontent(json); @@ -111,7 +114,7 @@ private void UpdateParams(JToken token) { if (arrayToken[i].Type == JTokenType.Array || arrayToken[i].Type == JTokenType.Object) { - arrayToken[i].Replace(JToken.Parse(_jsonSerializer.Serialize(arrayToken[i].Value()!.ToString()))); + arrayToken[i].Replace(JToken.Parse(_jsonSerializer.Serialize(arrayToken[i].Value().ToString()))); } } } @@ -120,9 +123,9 @@ public async IAsyncEnumerable ProcessAsync(TextReader request, Js { request = await RecordRequest(request); Stopwatch stopwatch = Stopwatch.StartNew(); - IEnumerable<(JsonRpcRequest? Model, List? Collection)> rpcRequests = DeserializeObjectOrArray(request); + IEnumerable<(JsonRpcRequest Model, List Collection)> rpcRequests = DeserializeObjectOrArray(request); - using IEnumerator<(JsonRpcRequest? Model, List? Collection)> enumerator = rpcRequests.GetEnumerator(); + using IEnumerator<(JsonRpcRequest Model, List Collection)> enumerator = rpcRequests.GetEnumerator(); bool moveNext = true; @@ -157,7 +160,7 @@ public async IAsyncEnumerable ProcessAsync(TextReader request, Js } else if (moveNext) { - (JsonRpcRequest? Model, List? Collection) rpcRequest = enumerator.Current; + (JsonRpcRequest Model, List Collection) rpcRequest = enumerator.Current; if (rpcRequest.Model is not null) { @@ -175,7 +178,7 @@ public async IAsyncEnumerable ProcessAsync(TextReader request, Js if (!context.IsAuthenticated && rpcRequest.Collection.Count > _jsonRpcConfig.MaxBatchSize) { if (_logger.IsWarn) _logger.Warn($"The batch size limit was exceeded. The requested batch size {rpcRequest.Collection.Count}, and the current config setting is JsonRpc.{nameof(_jsonRpcConfig.MaxBatchSize)} = {_jsonRpcConfig.MaxBatchSize}."); - JsonRpcErrorResponse response = _jsonRpcService.GetErrorResponse(ErrorCodes.LimitExceeded, "Batch size limit exceeded"); + JsonRpcErrorResponse? response = _jsonRpcService.GetErrorResponse(ErrorCodes.LimitExceeded, "Batch size limit exceeded"); yield return JsonRpcResult.Single(RecordResponse(response, RpcReport.Error)); continue; @@ -213,10 +216,10 @@ public async IAsyncEnumerable ProcessAsync(TextReader request, Js JsonRpcResult.Entry response = enumerator.IsStopped ? new JsonRpcResult.Entry( _jsonRpcService.GetErrorResponse( + jsonRpcRequest.Method, ErrorCodes.LimitExceeded, $"{nameof(IJsonRpcConfig.MaxBatchResponseBodySize)} of {_jsonRpcConfig.MaxBatchResponseBodySize / 1.KB()}KB exceeded", - jsonRpcRequest.Id, - jsonRpcRequest.Method), + jsonRpcRequest.Id), RpcReport.Error) : await HandleSingleRequest(jsonRpcRequest, context); @@ -234,15 +237,11 @@ public async IAsyncEnumerable ProcessAsync(TextReader request, Js Stopwatch stopwatch = Stopwatch.StartNew(); JsonRpcResponse response = await _jsonRpcService.SendRequestAsync(request, context); - JsonRpcErrorResponse? localErrorResponse = response as JsonRpcErrorResponse; + JsonRpcErrorResponse localErrorResponse = response as JsonRpcErrorResponse; bool isSuccess = localErrorResponse is null; if (!isSuccess) { - if (localErrorResponse?.Error?.SuppressWarning == false) - { - if (_logger.IsWarn) _logger.Warn($"Error when handling {request} | {_jsonSerializer.Serialize(localErrorResponse)}"); - } - + if (_logger.IsWarn) _logger.Warn($"Error when handling {request} | {_jsonSerializer.Serialize(localErrorResponse)}"); Metrics.JsonRpcErrors++; } else @@ -267,7 +266,7 @@ private JsonRpcResult.Entry RecordResponse(JsonRpcResult.Entry result) { if ((_jsonRpcConfig.RpcRecorderState & RpcRecorderState.Response) != 0) { - _recorder!.RecordResponse(_jsonSerializer.Serialize(result)); + _recorder.RecordResponse(_jsonSerializer.Serialize(result)); } return result; @@ -278,7 +277,7 @@ private async ValueTask RecordRequest(TextReader request) if ((_jsonRpcConfig.RpcRecorderState & RpcRecorderState.Request) != 0) { string requestString = await request.ReadToEndAsync(); - _recorder!.RecordRequest(requestString); + _recorder.RecordRequest(requestString); return new StringReader(requestString); } diff --git a/src/Nethermind/Nethermind.JsonRpc/JsonRpcResult.cs b/src/Nethermind/Nethermind.JsonRpc/JsonRpcResult.cs index 02b0c9e0af1..c0a18d4a26c 100644 --- a/src/Nethermind/Nethermind.JsonRpc/JsonRpcResult.cs +++ b/src/Nethermind/Nethermind.JsonRpc/JsonRpcResult.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.Threading; namespace Nethermind.JsonRpc { diff --git a/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs b/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs index 761e49e2e54..38a3edaa392 100644 --- a/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs +++ b/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Reflection; @@ -11,7 +12,6 @@ using Nethermind.Core; using Nethermind.Core.Attributes; using Nethermind.JsonRpc.Data; -using Nethermind.JsonRpc.Exceptions; using Nethermind.JsonRpc.Modules; using Nethermind.Logging; using Nethermind.Serialization.Json; @@ -76,15 +76,8 @@ public async Task SendRequestAsync(JsonRpcRequest rpcRequest, J } catch (TargetInvocationException ex) { - if (_logger.IsError) - _logger.Error($"Error during method execution, request: {rpcRequest}", ex.InnerException); - return GetErrorResponse(rpcRequest.Method, ErrorCodes.InternalError, "Internal error", - ex.InnerException?.ToString(), rpcRequest.Id); - } - catch (LimitExceededException ex) - { - if (_logger.IsError) _logger.Error($"Error during method execution, request: {rpcRequest}", ex); - return GetErrorResponse(rpcRequest.Method, ErrorCodes.LimitExceeded, "Too many requests", ex.ToString(), rpcRequest.Id); + if (_logger.IsError) _logger.Error($"Error during method execution, request: {rpcRequest}", ex.InnerException); + return GetErrorResponse(rpcRequest.Method, ErrorCodes.InternalError, "Internal error", ex.InnerException?.ToString(), rpcRequest.Id); } catch (ModuleRentalTimeoutException ex) { @@ -100,7 +93,7 @@ public async Task SendRequestAsync(JsonRpcRequest rpcRequest, J catch (Exception ex) { if (_logger.IsError) _logger.Error($"Error during validation, request: {rpcRequest}", ex); - return GetErrorResponse(ErrorCodes.ParseError, "Parse error", rpcRequest.Id, rpcRequest.Method); + return GetErrorResponse(ErrorCodes.ParseError, "Parse error"); } } @@ -180,7 +173,7 @@ private async Task ExecuteAsync(JsonRpcRequest request, string contextAwareModule.Context = context; } bool returnImmediately = methodName != "eth_getLogs"; - Action? returnAction = returnImmediately ? null : () => _rpcModuleProvider.Return(methodName, rpcModule); + Action? returnAction = returnImmediately ? (Action)null : () => _rpcModuleProvider.Return(methodName, rpcModule); try { object invocationResult = method.Info.Invoke(rpcModule, parameters); @@ -195,7 +188,7 @@ private async Task ExecuteAsync(JsonRpcRequest request, string break; } } - catch (Exception e) when (e is TargetParameterCountException || e is ArgumentException) + catch (TargetParameterCountException e) { return GetErrorResponse(methodName, ErrorCodes.InvalidParams, e.Message, e.ToString(), request.Id, returnAction); } @@ -227,11 +220,19 @@ private async Task ExecuteAsync(JsonRpcRequest request, string return GetErrorResponse(methodName, ErrorCodes.InternalError, errorMessage, null, request.Id, returnAction); } - Result? result = resultWrapper.Result; + Result? result = resultWrapper.GetResult(); + if (result is null) + { + if (_logger.IsError) _logger.Error($"Error during method: {methodName} execution: no result"); + return GetErrorResponse(methodName, resultWrapper.GetErrorCode(), "Internal error", resultWrapper.GetData(), request.Id, returnAction); + } - return result.ResultType != ResultType.Success - ? GetErrorResponse(methodName, resultWrapper.ErrorCode, result.Error, resultWrapper.Data, request.Id, returnAction, resultWrapper.IsTemporary) - : GetSuccessResponse(methodName, resultWrapper.Data, request.Id, returnAction); + if (result.ResultType == ResultType.Failure) + { + return GetErrorResponse(methodName, resultWrapper.GetErrorCode(), result.Error, resultWrapper.GetData(), request.Id, returnAction); + } + + return GetSuccessResponse(methodName, resultWrapper.GetData(), request.Id, returnAction); } private void LogRequest(string methodName, string?[] providedParameters, ParameterInfo[] expectedParameters) @@ -325,18 +326,10 @@ private void LogRequest(string methodName, string?[] providedParameters, Paramet if (providedParameter.StartsWith('[') || providedParameter.StartsWith('{')) { executionParam = _serializer.Deserialize(new JsonTextReader(new StringReader(providedParameter)), paramType); - if (executionParam is null && !IsNullableParameter(expectedParameter)) - { - executionParameters.Add(Type.Missing); - } } else { - var stringReader = providedParameter.StartsWith('\"') && providedParameter.EndsWith('\"') - ? new StringReader(providedParameter) - : new StringReader($"\"{providedParameter}\""); - var jsonTextReader = new JsonTextReader(stringReader); - executionParam = _serializer.Deserialize(jsonTextReader, paramType); + executionParam = _serializer.Deserialize(new JsonTextReader(new StringReader($"\"{providedParameter}\"")), paramType); } } @@ -374,6 +367,14 @@ private bool IsNullableParameter(ParameterInfo parameterInfo) { return (byte)attributeArgument.Value! == 2; } + if (attributeArgument.ArgumentType == typeof(byte[])) + { + var args = (ReadOnlyCollection)attributeArgument.Value!; + if (args.Count > 0 && args[0].ArgumentType == typeof(byte)) + { + return (byte)args[0].Value! == 2; + } + } } return false; } @@ -390,21 +391,17 @@ private JsonRpcResponse GetSuccessResponse(string methodName, object result, obj return response; } - public JsonRpcErrorResponse GetErrorResponse(int errorCode, string errorMessage, object? id = null, string? methodName = null) => - GetErrorResponse(methodName ?? string.Empty, errorCode, errorMessage, null, id); + public JsonRpcErrorResponse GetErrorResponse(int errorCode, string errorMessage) => + GetErrorResponse(null, errorCode, errorMessage, null, null); + + public JsonRpcErrorResponse GetErrorResponse(string methodName, int errorCode, string errorMessage, object id) => + GetErrorResponse(methodName, errorCode, errorMessage, null, id); public JsonConverter[] Converters { get; } - private JsonRpcErrorResponse GetErrorResponse( - string methodName, - int errorCode, - string? errorMessage, - object? errorData, - object? id, - Action? disposableAction = null, - bool suppressWarning = false) + private JsonRpcErrorResponse GetErrorResponse(string? methodName, int errorCode, string? errorMessage, object? errorData, object? id, Action? disposableAction = null) { - if (_logger.IsDebug) _logger.Debug($"Sending error response, method: {(string.IsNullOrEmpty(methodName) ? "none" : methodName)}, id: {id}, errorType: {errorCode}, message: {errorMessage}, errorData: {errorData}"); + if (_logger.IsDebug) _logger.Debug($"Sending error response, method: {methodName ?? "none"}, id: {id}, errorType: {errorCode}, message: {errorMessage}, errorData: {errorData}"); JsonRpcErrorResponse response = new(disposableAction) { Error = new Error @@ -412,7 +409,6 @@ private JsonRpcErrorResponse GetErrorResponse( Code = errorCode, Message = errorMessage, Data = errorData, - SuppressWarning = suppressWarning }, Id = id, MethodName = methodName diff --git a/src/Nethermind/Nethermind.JsonRpc/JsonSerializerExtensions.cs b/src/Nethermind/Nethermind.JsonRpc/JsonSerializerExtensions.cs deleted file mode 100644 index 3f65b0c1f21..00000000000 --- a/src/Nethermind/Nethermind.JsonRpc/JsonSerializerExtensions.cs +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections; -using System.IO; -using Nethermind.Serialization.Json; - -namespace Nethermind.JsonRpc; - -public static class JsonSerializerExtensions -{ - public static long SerializeWaitForEnumeration(this IJsonSerializer serializer, Stream stream, T value, bool indented = false) - { - AmendValue(value); - return serializer.Serialize(stream, value, indented); - } - - private static void AmendValue(T value) - { - static IEnumerable NewEnumerable(IEnumerator enumerator) - { - yield return enumerator.Current; - while (enumerator.MoveNext()) - { - yield return enumerator.Current; - } - } - - // try target actually lazy enumerators - if (value is JsonRpcSuccessResponse - { - Result: IEnumerable enumerable - and not string - and not Array - and not IList - and not ICollection - and not IDictionary - and IEnumerator - } response) - { - IEnumerator enumerator = enumerable.GetEnumerator(); - if (enumerator.MoveNext()) - { - response.Result = NewEnumerable(enumerator); - } - } - } -} diff --git a/src/Nethermind/Nethermind.JsonRpc/Metrics.cs b/src/Nethermind/Nethermind.JsonRpc/Metrics.cs index b7af3bb2707..1b34c3a1154 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Metrics.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Metrics.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.ComponentModel; +using System.Threading; using Nethermind.Core.Attributes; namespace Nethermind.JsonRpc diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/IAdminRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/IAdminRpcModule.cs index d7e8df3f724..90daba4dcd3 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/IAdminRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/IAdminRpcModule.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Nethermind.Blockchain.FullPruning; +using Newtonsoft.Json; namespace Nethermind.JsonRpc.Modules.Admin { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/NodeInfo.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/NodeInfo.cs index 31f8d5296c9..766fdc064b3 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/NodeInfo.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/NodeInfo.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using Nethermind.Core; using Newtonsoft.Json; namespace Nethermind.JsonRpc.Modules.Admin diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs index 966cc3a42ba..a86269f07ba 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/BlockFinderExtensions.cs @@ -43,14 +43,12 @@ public static SearchResult SearchForHeader(this IBlockFinder blockF : new SearchResult(header); } - public static SearchResult SearchForBlock(this IBlockFinder blockFinder, BlockParameter? blockParameter, bool allowNulls = false) + public static SearchResult SearchForBlock(this IBlockFinder blockFinder, BlockParameter blockParameter, bool allowNulls = false) { - blockParameter ??= BlockParameter.Latest; - Block block; if (blockParameter.RequireCanonical) { - block = blockFinder.FindBlock(blockParameter.BlockHash!, BlockTreeLookupOptions.RequireCanonical); + block = blockFinder.FindBlock(blockParameter.BlockHash, BlockTreeLookupOptions.RequireCanonical); if (block is null && !allowNulls) { BlockHeader? header = blockFinder.FindHeader(blockParameter.BlockHash); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/BoundedModulePool.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/BoundedModulePool.cs index 51ab56c9b89..0d02062c663 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/BoundedModulePool.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/BoundedModulePool.cs @@ -1,44 +1,13 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; -using Nethermind.JsonRpc.Exceptions; namespace Nethermind.JsonRpc.Modules { - public static class RpcLimits - { - public static void Init(int limit) - { - Limit = limit; - } - - private static int Limit { get; set; } - private static bool Enabled => Limit > 0; - private static int _queuedCalls = 0; - - public static void IncrementQueuedCalls() - { - if (Enabled) - Interlocked.Increment(ref _queuedCalls); - } - - public static void DecrementQueuedCalls() - { - if (Enabled) - Interlocked.Decrement(ref _queuedCalls); - } - - public static void EnsureLimits() - { - if (Enabled && _queuedCalls > Limit) - { - throw new LimitExceededException($"Unable to start new queued requests. Too many queued requests. Queued calls {_queuedCalls}."); - } - } - } public class BoundedModulePool : IRpcModulePool where T : IRpcModule { private readonly int _timeout; @@ -66,16 +35,11 @@ public BoundedModulePool(IRpcModuleFactory factory, int exclusiveCapacity, in private async Task SlowPath() { - RpcLimits.EnsureLimits(); - RpcLimits.IncrementQueuedCalls(); - if (!await _semaphore.WaitAsync(_timeout)) { - RpcLimits.DecrementQueuedCalls(); throw new ModuleRentalTimeoutException($"Unable to rent an instance of {typeof(T).Name}. Too many concurrent requests."); } - RpcLimits.DecrementQueuedCalls(); _pool.TryDequeue(out T result); return result; } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs index a617d4ab003..3080004a380 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs @@ -21,161 +21,156 @@ using Nethermind.Synchronization.ParallelSync; using Nethermind.Synchronization.Reporting; -namespace Nethermind.JsonRpc.Modules.DebugModule; - -public class DebugBridge : IDebugBridge +namespace Nethermind.JsonRpc.Modules.DebugModule { - private readonly IConfigProvider _configProvider; - private readonly IGethStyleTracer _tracer; - private readonly IBlockTree _blockTree; - private readonly IReceiptStorage _receiptStorage; - private readonly IReceiptsMigration _receiptsMigration; - private readonly ISpecProvider _specProvider; - private readonly ISyncModeSelector _syncModeSelector; - private readonly Dictionary _dbMappings; - - public DebugBridge( - IConfigProvider configProvider, - IReadOnlyDbProvider dbProvider, - IGethStyleTracer tracer, - IBlockTree blockTree, - IReceiptStorage receiptStorage, - IReceiptsMigration receiptsMigration, - ISpecProvider specProvider, - ISyncModeSelector syncModeSelector) - { - _configProvider = configProvider ?? throw new ArgumentNullException(nameof(configProvider)); - _tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); - _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); - _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage)); - _receiptsMigration = receiptsMigration ?? throw new ArgumentNullException(nameof(receiptsMigration)); - _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); - _syncModeSelector = syncModeSelector ?? throw new ArgumentNullException(nameof(syncModeSelector)); - dbProvider = dbProvider ?? throw new ArgumentNullException(nameof(dbProvider)); - IDb blockInfosDb = dbProvider.BlockInfosDb ?? throw new ArgumentNullException(nameof(dbProvider.BlockInfosDb)); - IDb blocksDb = dbProvider.BlocksDb ?? throw new ArgumentNullException(nameof(dbProvider.BlocksDb)); - IDb headersDb = dbProvider.HeadersDb ?? throw new ArgumentNullException(nameof(dbProvider.HeadersDb)); - IDb receiptsDb = dbProvider.ReceiptsDb ?? throw new ArgumentNullException(nameof(dbProvider.ReceiptsDb)); - IDb codeDb = dbProvider.CodeDb ?? throw new ArgumentNullException(nameof(dbProvider.CodeDb)); - IDb metadataDb = dbProvider.MetadataDb ?? throw new ArgumentNullException(nameof(dbProvider.MetadataDb)); - - _dbMappings = new Dictionary(StringComparer.InvariantCultureIgnoreCase) - { - {DbNames.State, dbProvider.StateDb}, - {DbNames.Storage, dbProvider.StateDb}, - {DbNames.BlockInfos, blockInfosDb}, - {DbNames.Blocks, blocksDb}, - {DbNames.Headers, headersDb}, - {DbNames.Metadata, metadataDb}, - {DbNames.Code, codeDb}, - {DbNames.Receipts, receiptsDb}, - }; - } + public class DebugBridge : IDebugBridge + { + private readonly IConfigProvider _configProvider; + private readonly IGethStyleTracer _tracer; + private readonly IBlockTree _blockTree; + private readonly IReceiptStorage _receiptStorage; + private readonly IReceiptsMigration _receiptsMigration; + private readonly ISpecProvider _specProvider; + private readonly ISyncModeSelector _syncModeSelector; + private readonly Dictionary _dbMappings; + + public DebugBridge( + IConfigProvider configProvider, + IReadOnlyDbProvider dbProvider, + IGethStyleTracer tracer, + IBlockTree blockTree, + IReceiptStorage receiptStorage, + IReceiptsMigration receiptsMigration, + ISpecProvider specProvider, + ISyncModeSelector syncModeSelector) + { + _configProvider = configProvider ?? throw new ArgumentNullException(nameof(configProvider)); + _tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); + _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); + _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage)); + _receiptsMigration = receiptsMigration ?? throw new ArgumentNullException(nameof(receiptsMigration)); + _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); + _syncModeSelector = syncModeSelector ?? throw new ArgumentNullException(nameof(syncModeSelector)); + dbProvider = dbProvider ?? throw new ArgumentNullException(nameof(dbProvider)); + IDb blockInfosDb = dbProvider.BlockInfosDb ?? throw new ArgumentNullException(nameof(dbProvider.BlockInfosDb)); + IDb blocksDb = dbProvider.BlocksDb ?? throw new ArgumentNullException(nameof(dbProvider.BlocksDb)); + IDb headersDb = dbProvider.HeadersDb ?? throw new ArgumentNullException(nameof(dbProvider.HeadersDb)); + IDb receiptsDb = dbProvider.ReceiptsDb ?? throw new ArgumentNullException(nameof(dbProvider.ReceiptsDb)); + IDb codeDb = dbProvider.CodeDb ?? throw new ArgumentNullException(nameof(dbProvider.CodeDb)); + IDb metadataDb = dbProvider.MetadataDb ?? throw new ArgumentNullException(nameof(dbProvider.MetadataDb)); + + _dbMappings = new Dictionary(StringComparer.InvariantCultureIgnoreCase) + { + {DbNames.State, dbProvider.StateDb}, + {DbNames.Storage, dbProvider.StateDb}, + {DbNames.BlockInfos, blockInfosDb}, + {DbNames.Blocks, blocksDb}, + {DbNames.Headers, headersDb}, + {DbNames.Metadata, metadataDb}, + {DbNames.Code, codeDb}, + {DbNames.Receipts, receiptsDb}, + }; + } - public byte[] GetDbValue(string dbName, byte[] key) - { - return _dbMappings[dbName][key]; - } + public byte[] GetDbValue(string dbName, byte[] key) + { + return _dbMappings[dbName][key]; + } - public ChainLevelInfo GetLevelInfo(long number) - { - return _blockTree.FindLevel(number); - } + public ChainLevelInfo GetLevelInfo(long number) + { + return _blockTree.FindLevel(number); + } - public int DeleteChainSlice(long startNumber) - { - return _blockTree.DeleteChainSlice(startNumber); - } + public int DeleteChainSlice(long startNumber) + { + return _blockTree.DeleteChainSlice(startNumber); + } - public void UpdateHeadBlock(Keccak blockHash) - { - _blockTree.UpdateHeadBlock(blockHash); - } + public void UpdateHeadBlock(Keccak blockHash) + { + _blockTree.UpdateHeadBlock(blockHash); + } - public Task MigrateReceipts(long blockNumber) - => _receiptsMigration.Run(blockNumber + 1); // add 1 to make go from inclusive (better for API) to exclusive (better for internal) + public Task MigrateReceipts(long blockNumber) + => _receiptsMigration.Run(blockNumber + 1); // add 1 to make go from inclusive (better for API) to exclusive (better for internal) - public void InsertReceipts(BlockParameter blockParameter, TxReceipt[] txReceipts) - { - SearchResult searchResult = _blockTree.SearchForBlock(blockParameter); - if (searchResult.IsError) + public void InsertReceipts(BlockParameter blockParameter, TxReceipt[] txReceipts) { - throw new InvalidDataException(searchResult.Error); + SearchResult searchResult = _blockTree.SearchForBlock(blockParameter); + if (searchResult.IsError) + { + throw new InvalidDataException(searchResult.Error); + } + + Block block = searchResult.Object; + ReceiptTrie receiptTrie = new(_specProvider.GetSpec(block.Header), txReceipts); + receiptTrie.UpdateRootHash(); + if (block.ReceiptsRoot != receiptTrie.RootHash) + { + throw new InvalidDataException("Receipts root mismatch"); + } + + _receiptStorage.Insert(block, txReceipts); } - Block block = searchResult.Object; - ReceiptTrie receiptTrie = new(_specProvider.GetSpec(block.Header), txReceipts); - receiptTrie.UpdateRootHash(); - if (block.ReceiptsRoot != receiptTrie.RootHash) + public GethLikeTxTrace GetTransactionTrace(Keccak transactionHash, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) { - throw new InvalidDataException("Receipts root mismatch"); + return _tracer.Trace(transactionHash, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); } - _receiptStorage.Insert(block, txReceipts); - } - - public GethLikeTxTrace GetTransactionTrace(Keccak transactionHash, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) - { - return _tracer.Trace(transactionHash, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - } - - public GethLikeTxTrace GetTransactionTrace(long blockNumber, int index, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) - { - return _tracer.Trace(blockNumber, index, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - } + public GethLikeTxTrace GetTransactionTrace(long blockNumber, int index, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) + { + return _tracer.Trace(blockNumber, index, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); + } - public GethLikeTxTrace GetTransactionTrace(Keccak blockHash, int index, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) - { - return _tracer.Trace(blockHash, index, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - } + public GethLikeTxTrace GetTransactionTrace(Keccak blockHash, int index, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) + { + return _tracer.Trace(blockHash, index, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); + } - public GethLikeTxTrace GetTransactionTrace(Rlp blockRlp, Keccak transactionHash, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) - { - return _tracer.Trace(blockRlp, transactionHash, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - } + public GethLikeTxTrace GetTransactionTrace(Rlp blockRlp, Keccak transactionHash, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) + { + return _tracer.Trace(blockRlp, transactionHash, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); + } - public GethLikeTxTrace? GetTransactionTrace(Transaction transaction, BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) - { - return _tracer.Trace(blockParameter, transaction, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - } + public GethLikeTxTrace? GetTransactionTrace(Transaction transaction, BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) + { + return _tracer.Trace(blockParameter, transaction, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); + } - public GethLikeTxTrace[] GetBlockTrace(BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) - { - return _tracer.TraceBlock(blockParameter, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - } + public GethLikeTxTrace[] GetBlockTrace(BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) + { + return _tracer.TraceBlock(blockParameter, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); + } - public GethLikeTxTrace[] GetBlockTrace(Rlp blockRlp, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) - { - return _tracer.TraceBlock(blockRlp, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - } + public GethLikeTxTrace[] GetBlockTrace(Rlp blockRlp, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) + { + return _tracer.TraceBlock(blockRlp, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); + } - public byte[] GetBlockRlp(Keccak blockHash) - { - return _dbMappings[DbNames.Blocks].Get(blockHash); - } + public byte[] GetBlockRlp(Keccak blockHash) + { + return _dbMappings[DbNames.Blocks].Get(blockHash); + } - public byte[] GetBlockRlp(long number) - { - Keccak hash = _blockTree.FindHash(number); - return hash is null ? null : _dbMappings[DbNames.Blocks].Get(hash); - } + public byte[] GetBlockRlp(long number) + { + Keccak hash = _blockTree.FindHash(number); + return hash is null ? null : _dbMappings[DbNames.Blocks].Get(hash); + } - public object GetConfigValue(string category, string name) - { - return _configProvider.GetRawValue(category, name); - } + public object GetConfigValue(string category, string name) + { + return _configProvider.GetRawValue(category, name); + } - public SyncReportSymmary GetCurrentSyncStage() - { - return new SyncReportSymmary + public SyncReportSymmary GetCurrentSyncStage() { - CurrentStage = _syncModeSelector.Current.ToString() - }; + return new SyncReportSymmary + { + CurrentStage = _syncModeSelector.Current.ToString() + }; + } } - - public IEnumerable TraceBlockToFile( - Keccak blockHash, - CancellationToken cancellationToken, - GethTraceOptions? gethTraceOptions = null) => - _tracer.TraceBlockToFile(blockHash, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs index 802d9cb0c94..552fd207632 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.IO.Abstractions; using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; using Nethermind.Config; @@ -19,102 +18,99 @@ using Nethermind.Trie.Pruning; using Newtonsoft.Json; -namespace Nethermind.JsonRpc.Modules.DebugModule; - -public class DebugModuleFactory : ModuleFactoryBase +namespace Nethermind.JsonRpc.Modules.DebugModule { - private readonly IJsonRpcConfig _jsonRpcConfig; - private readonly IBlockValidator _blockValidator; - private readonly IRewardCalculatorSource _rewardCalculatorSource; - private readonly IReceiptStorage _receiptStorage; - private readonly IReceiptsMigration _receiptsMigration; - private readonly IReadOnlyTrieStore _trieStore; - private readonly IConfigProvider _configProvider; - private readonly ISpecProvider _specProvider; - private readonly ILogManager _logManager; - private readonly IBlockPreprocessorStep _recoveryStep; - private readonly IReadOnlyDbProvider _dbProvider; - private readonly IReadOnlyBlockTree _blockTree; - private readonly ISyncModeSelector _syncModeSelector; - private readonly IFileSystem _fileSystem; - private ILogger _logger; - - public DebugModuleFactory( - IDbProvider dbProvider, - IBlockTree blockTree, - IJsonRpcConfig jsonRpcConfig, - IBlockValidator blockValidator, - IBlockPreprocessorStep recoveryStep, - IRewardCalculatorSource rewardCalculator, - IReceiptStorage receiptStorage, - IReceiptsMigration receiptsMigration, - IReadOnlyTrieStore trieStore, - IConfigProvider configProvider, - ISpecProvider specProvider, - ISyncModeSelector syncModeSelector, - IFileSystem fileSystem, - ILogManager logManager) + public class DebugModuleFactory : ModuleFactoryBase { - _dbProvider = dbProvider.AsReadOnly(false); - _blockTree = blockTree.AsReadOnly(); - _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); - _blockValidator = blockValidator ?? throw new ArgumentNullException(nameof(blockValidator)); - _recoveryStep = recoveryStep ?? throw new ArgumentNullException(nameof(recoveryStep)); - _rewardCalculatorSource = rewardCalculator ?? throw new ArgumentNullException(nameof(rewardCalculator)); - _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage)); - _receiptsMigration = receiptsMigration ?? throw new ArgumentNullException(nameof(receiptsMigration)); - _trieStore = (trieStore ?? throw new ArgumentNullException(nameof(trieStore))); - _configProvider = configProvider ?? throw new ArgumentNullException(nameof(configProvider)); - _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); - _logManager = logManager ?? throw new ArgumentNullException(nameof(logManager)); - _syncModeSelector = syncModeSelector ?? throw new ArgumentNullException(nameof(syncModeSelector)); - _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); - _logger = logManager.GetClassLogger(); - } + private readonly IJsonRpcConfig _jsonRpcConfig; + private readonly IBlockValidator _blockValidator; + private readonly IRewardCalculatorSource _rewardCalculatorSource; + private readonly IReceiptStorage _receiptStorage; + private readonly IReceiptsMigration _receiptsMigration; + private readonly IReadOnlyTrieStore _trieStore; + private readonly IConfigProvider _configProvider; + private readonly ISpecProvider _specProvider; + private readonly ILogManager _logManager; + private readonly IBlockPreprocessorStep _recoveryStep; + private readonly IReadOnlyDbProvider _dbProvider; + private readonly IReadOnlyBlockTree _blockTree; + private readonly ISyncModeSelector _syncModeSelector; + private ILogger _logger; - public override IDebugRpcModule Create() - { - ReadOnlyTxProcessingEnv txEnv = new( - _dbProvider, - _trieStore, - _blockTree, - _specProvider, - _logManager); + public DebugModuleFactory( + IDbProvider dbProvider, + IBlockTree blockTree, + IJsonRpcConfig jsonRpcConfig, + IBlockValidator blockValidator, + IBlockPreprocessorStep recoveryStep, + IRewardCalculatorSource rewardCalculator, + IReceiptStorage receiptStorage, + IReceiptsMigration receiptsMigration, + IReadOnlyTrieStore trieStore, + IConfigProvider configProvider, + ISpecProvider specProvider, + ISyncModeSelector syncModeSelector, + ILogManager logManager) + { + _dbProvider = dbProvider.AsReadOnly(false); + _blockTree = blockTree.AsReadOnly(); + _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); + _blockValidator = blockValidator ?? throw new ArgumentNullException(nameof(blockValidator)); + _recoveryStep = recoveryStep ?? throw new ArgumentNullException(nameof(recoveryStep)); + _rewardCalculatorSource = rewardCalculator ?? throw new ArgumentNullException(nameof(rewardCalculator)); + _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage)); + _receiptsMigration = receiptsMigration ?? throw new ArgumentNullException(nameof(receiptsMigration)); + _trieStore = (trieStore ?? throw new ArgumentNullException(nameof(trieStore))); + _configProvider = configProvider ?? throw new ArgumentNullException(nameof(configProvider)); + _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); + _logManager = logManager ?? throw new ArgumentNullException(nameof(logManager)); + _syncModeSelector = syncModeSelector ?? throw new ArgumentNullException(nameof(syncModeSelector)); + _logger = logManager.GetClassLogger(); + } - ChangeableTransactionProcessorAdapter transactionProcessorAdapter = new(txEnv.TransactionProcessor); - BlockProcessor.BlockValidationTransactionsExecutor transactionsExecutor = new(transactionProcessorAdapter, txEnv.StateProvider); - ReadOnlyChainProcessingEnv chainProcessingEnv = new( - txEnv, - _blockValidator, - _recoveryStep, - _rewardCalculatorSource.Get(txEnv.TransactionProcessor), - _receiptStorage, - _dbProvider, - _specProvider, - _logManager, - transactionsExecutor); + public override IDebugRpcModule Create() + { + ReadOnlyTxProcessingEnv txEnv = new( + _dbProvider, + _trieStore, + _blockTree, + _specProvider, + _logManager); - GethStyleTracer tracer = new( - chainProcessingEnv.ChainProcessor, - _receiptStorage, - _blockTree, - transactionProcessorAdapter, - _fileSystem); + ChangeableTransactionProcessorAdapter transactionProcessorAdapter = new(txEnv.TransactionProcessor); + BlockProcessor.BlockValidationTransactionsExecutor transactionsExecutor = new(transactionProcessorAdapter, txEnv.StateProvider); + ReadOnlyChainProcessingEnv chainProcessingEnv = new( + txEnv, + _blockValidator, + _recoveryStep, + _rewardCalculatorSource.Get(txEnv.TransactionProcessor), + _receiptStorage, + _dbProvider, + _specProvider, + _logManager, + transactionsExecutor); - DebugBridge debugBridge = new( - _configProvider, - _dbProvider, - tracer, - _blockTree, - _receiptStorage, - _receiptsMigration, - _specProvider, - _syncModeSelector); + GethStyleTracer tracer = new( + chainProcessingEnv.ChainProcessor, + _receiptStorage, + _blockTree, + transactionProcessorAdapter); - return new DebugRpcModule(_logManager, debugBridge, _jsonRpcConfig); - } + DebugBridge debugBridge = new( + _configProvider, + _dbProvider, + tracer, + _blockTree, + _receiptStorage, + _receiptsMigration, + _specProvider, + _syncModeSelector); + + return new DebugRpcModule(_logManager, debugBridge, _jsonRpcConfig); + } - public static JsonConverter[] Converters = { new GethLikeTxTraceConverter() }; + public static JsonConverter[] Converters = { new GethLikeTxTraceConverter() }; - public override IReadOnlyCollection GetConverters() => Converters; + public override IReadOnlyCollection GetConverters() => Converters; + } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs index 68f82756a1c..9e2c0a01cf4 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs @@ -10,271 +10,260 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Int256; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.JsonRpc.Data; using Nethermind.Logging; using Nethermind.Serialization.Rlp; using Nethermind.Synchronization.Reporting; -using System.Collections.Generic; -namespace Nethermind.JsonRpc.Modules.DebugModule; - -public class DebugRpcModule : IDebugRpcModule +namespace Nethermind.JsonRpc.Modules.DebugModule { - private readonly IDebugBridge _debugBridge; - private readonly ILogger _logger; - private readonly TimeSpan _traceTimeout; - private readonly IJsonRpcConfig _jsonRpcConfig; - - public DebugRpcModule(ILogManager logManager, IDebugBridge debugBridge, IJsonRpcConfig jsonRpcConfig) - { - _debugBridge = debugBridge ?? throw new ArgumentNullException(nameof(debugBridge)); - _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); - _logger = logManager.GetClassLogger(); - _traceTimeout = TimeSpan.FromMilliseconds(_jsonRpcConfig.Timeout); - } - - public ResultWrapper debug_getChainLevel(in long number) - { - ChainLevelInfo levelInfo = _debugBridge.GetLevelInfo(number); - return levelInfo is null - ? ResultWrapper.Fail($"Chain level {number} does not exist", ErrorCodes.ResourceNotFound) - : ResultWrapper.Success(new ChainLevelForRpc(levelInfo)); - } - - public ResultWrapper debug_deleteChainSlice(in long startNumber) + public class DebugRpcModule : IDebugRpcModule { - return ResultWrapper.Success(_debugBridge.DeleteChainSlice(startNumber)); - } + private readonly IDebugBridge _debugBridge; + private readonly ILogger _logger; + private readonly TimeSpan _traceTimeout; + private readonly IJsonRpcConfig _jsonRpcConfig; - public ResultWrapper debug_traceTransaction(Keccak transactionHash, GethTraceOptions options = null) - { - using CancellationTokenSource cancellationTokenSource = new(_traceTimeout); - CancellationToken cancellationToken = cancellationTokenSource.Token; - GethLikeTxTrace transactionTrace = _debugBridge.GetTransactionTrace(transactionHash, cancellationToken, options); - if (transactionTrace is null) + public DebugRpcModule(ILogManager logManager, IDebugBridge debugBridge, IJsonRpcConfig jsonRpcConfig) { - return ResultWrapper.Fail($"Cannot find transactionTrace for hash: {transactionHash}", ErrorCodes.ResourceNotFound); + _debugBridge = debugBridge ?? throw new ArgumentNullException(nameof(debugBridge)); + _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); + _logger = logManager.GetClassLogger(); + _traceTimeout = TimeSpan.FromMilliseconds(_jsonRpcConfig.Timeout); } - if (_logger.IsTrace) _logger.Trace($"{nameof(debug_traceTransaction)} request {transactionHash}, result: trace"); - return ResultWrapper.Success(transactionTrace); - } - - public ResultWrapper debug_traceCall(TransactionForRpc call, BlockParameter? blockParameter = null, GethTraceOptions? options = null) - { - blockParameter ??= BlockParameter.Latest; - call.EnsureDefaults(_jsonRpcConfig.GasCap); - Transaction tx = call.ToTransaction(); - using CancellationTokenSource cancellationTokenSource = new(_traceTimeout); - CancellationToken cancellationToken = cancellationTokenSource.Token; - - GethLikeTxTrace transactionTrace = _debugBridge.GetTransactionTrace(tx, blockParameter, cancellationToken, options); - if (transactionTrace is null) + public ResultWrapper debug_getChainLevel(in long number) { - return ResultWrapper.Fail($"Cannot find transactionTrace for hash: {tx.Hash}", ErrorCodes.ResourceNotFound); + ChainLevelInfo levelInfo = _debugBridge.GetLevelInfo(number); + return levelInfo is null + ? ResultWrapper.Fail($"Chain level {number} does not exist", ErrorCodes.ResourceNotFound) + : ResultWrapper.Success(new ChainLevelForRpc(levelInfo)); } - if (_logger.IsTrace) _logger.Trace($"{nameof(debug_traceTransaction)} request {tx.Hash}, result: trace"); - return ResultWrapper.Success(transactionTrace); - } - - public ResultWrapper debug_traceTransactionByBlockhashAndIndex(Keccak blockhash, int index, GethTraceOptions options = null) - { - using CancellationTokenSource cancellationTokenSource = new(_traceTimeout); - CancellationToken cancellationToken = cancellationTokenSource.Token; - var transactionTrace = _debugBridge.GetTransactionTrace(blockhash, index, cancellationToken, options); - if (transactionTrace is null) + public ResultWrapper debug_deleteChainSlice(in long startNumber) { - return ResultWrapper.Fail($"Cannot find transactionTrace {blockhash}", ErrorCodes.ResourceNotFound); + return ResultWrapper.Success(_debugBridge.DeleteChainSlice(startNumber)); } - if (_logger.IsTrace) _logger.Trace($"{nameof(debug_traceTransactionByBlockhashAndIndex)} request {blockhash}, result: trace"); - return ResultWrapper.Success(transactionTrace); - } - - public ResultWrapper debug_traceTransactionByBlockAndIndex(BlockParameter blockParameter, int index, GethTraceOptions options = null) - { - using CancellationTokenSource cancellationTokenSource = new(_traceTimeout); - CancellationToken cancellationToken = cancellationTokenSource.Token; - long? blockNo = blockParameter.BlockNumber; - if (!blockNo.HasValue) + public ResultWrapper debug_traceTransaction(Keccak transactionHash, GethTraceOptions options = null) { - throw new InvalidDataException("Block number value incorrect"); + using CancellationTokenSource cancellationTokenSource = new(_traceTimeout); + CancellationToken cancellationToken = cancellationTokenSource.Token; + GethLikeTxTrace transactionTrace = _debugBridge.GetTransactionTrace(transactionHash, cancellationToken, options); + if (transactionTrace is null) + { + return ResultWrapper.Fail($"Cannot find transactionTrace for hash: {transactionHash}", ErrorCodes.ResourceNotFound); + } + + if (_logger.IsTrace) _logger.Trace($"{nameof(debug_traceTransaction)} request {transactionHash}, result: trace"); + return ResultWrapper.Success(transactionTrace); } - var transactionTrace = _debugBridge.GetTransactionTrace(blockNo.Value, index, cancellationToken, options); - if (transactionTrace is null) + public ResultWrapper debug_traceCall(TransactionForRpc call, BlockParameter? blockParameter = null, GethTraceOptions? options = null) { - return ResultWrapper.Fail($"Cannot find transactionTrace {blockNo}", ErrorCodes.ResourceNotFound); + blockParameter ??= BlockParameter.Latest; + call.EnsureDefaults(_jsonRpcConfig.GasCap); + Transaction tx = call.ToTransaction(); + using CancellationTokenSource cancellationTokenSource = new(_traceTimeout); + CancellationToken cancellationToken = cancellationTokenSource.Token; + + GethLikeTxTrace transactionTrace = _debugBridge.GetTransactionTrace(tx, blockParameter, cancellationToken, options); + if (transactionTrace is null) + { + return ResultWrapper.Fail($"Cannot find transactionTrace for hash: {tx.Hash}", ErrorCodes.ResourceNotFound); + } + + if (_logger.IsTrace) _logger.Trace($"{nameof(debug_traceTransaction)} request {tx.Hash}, result: trace"); + return ResultWrapper.Success(transactionTrace); } - if (_logger.IsTrace) _logger.Trace($"{nameof(debug_traceTransactionByBlockAndIndex)} request {blockNo}, result: trace"); - return ResultWrapper.Success(transactionTrace); - } - - public ResultWrapper debug_traceTransactionInBlockByHash(byte[] blockRlp, Keccak transactionHash, GethTraceOptions options = null) - { - using CancellationTokenSource cancellationTokenSource = new(_traceTimeout); - CancellationToken cancellationToken = cancellationTokenSource.Token; - var transactionTrace = _debugBridge.GetTransactionTrace(new Rlp(blockRlp), transactionHash, cancellationToken, options); - if (transactionTrace is null) + public ResultWrapper debug_traceTransactionByBlockhashAndIndex(Keccak blockhash, int index, GethTraceOptions options = null) { - return ResultWrapper.Fail($"Trace is null for RLP {blockRlp.ToHexString()} and transactionTrace hash {transactionHash}", ErrorCodes.ResourceNotFound); + using CancellationTokenSource cancellationTokenSource = new(_traceTimeout); + CancellationToken cancellationToken = cancellationTokenSource.Token; + var transactionTrace = _debugBridge.GetTransactionTrace(blockhash, index, cancellationToken, options); + if (transactionTrace is null) + { + return ResultWrapper.Fail($"Cannot find transactionTrace {blockhash}", ErrorCodes.ResourceNotFound); + } + + if (_logger.IsTrace) _logger.Trace($"{nameof(debug_traceTransactionByBlockhashAndIndex)} request {blockhash}, result: trace"); + return ResultWrapper.Success(transactionTrace); } - return ResultWrapper.Success(transactionTrace); - } - - public ResultWrapper debug_traceTransactionInBlockByIndex(byte[] blockRlp, int txIndex, GethTraceOptions options = null) - { - using CancellationTokenSource cancellationTokenSource = new(_traceTimeout); - CancellationToken cancellationToken = cancellationTokenSource.Token; - var blockTrace = _debugBridge.GetBlockTrace(new Rlp(blockRlp), cancellationToken, options); - var transactionTrace = blockTrace?.ElementAtOrDefault(txIndex); - if (transactionTrace is null) + public ResultWrapper debug_traceTransactionByBlockAndIndex(BlockParameter blockParameter, int index, GethTraceOptions options = null) { - return ResultWrapper.Fail($"Trace is null for RLP {blockRlp.ToHexString()} and transaction index {txIndex}", ErrorCodes.ResourceNotFound); + using CancellationTokenSource cancellationTokenSource = new(_traceTimeout); + CancellationToken cancellationToken = cancellationTokenSource.Token; + long? blockNo = blockParameter.BlockNumber; + if (!blockNo.HasValue) + { + throw new InvalidDataException("Block number value incorrect"); + } + + var transactionTrace = _debugBridge.GetTransactionTrace(blockNo.Value, index, cancellationToken, options); + if (transactionTrace is null) + { + return ResultWrapper.Fail($"Cannot find transactionTrace {blockNo}", ErrorCodes.ResourceNotFound); + } + + if (_logger.IsTrace) _logger.Trace($"{nameof(debug_traceTransactionByBlockAndIndex)} request {blockNo}, result: trace"); + return ResultWrapper.Success(transactionTrace); } - return ResultWrapper.Success(transactionTrace); - } - - public async Task> debug_migrateReceipts(long blockNumber) => - ResultWrapper.Success(await _debugBridge.MigrateReceipts(blockNumber)); - - public Task> debug_insertReceipts(BlockParameter blockParameter, ReceiptForRpc[] receiptForRpc) - { - _debugBridge.InsertReceipts(blockParameter, receiptForRpc.Select(r => r.ToReceipt()).ToArray()); - return Task.FromResult(ResultWrapper.Success(true)); - } + public ResultWrapper debug_traceTransactionInBlockByHash(byte[] blockRlp, Keccak transactionHash, GethTraceOptions options = null) + { + using CancellationTokenSource cancellationTokenSource = new(_traceTimeout); + CancellationToken cancellationToken = cancellationTokenSource.Token; + var transactionTrace = _debugBridge.GetTransactionTrace(new Rlp(blockRlp), transactionHash, cancellationToken, options); + if (transactionTrace is null) + { + return ResultWrapper.Fail($"Trace is null for RLP {blockRlp.ToHexString()} and transactionTrace hash {transactionHash}", ErrorCodes.ResourceNotFound); + } + + return ResultWrapper.Success(transactionTrace); + } - public ResultWrapper debug_traceBlock(byte[] blockRlp, GethTraceOptions options = null) - { - using var cancellationTokenSource = new CancellationTokenSource(_traceTimeout); - var cancellationToken = cancellationTokenSource.Token; - var blockTrace = _debugBridge.GetBlockTrace(new Rlp(blockRlp), cancellationToken, options); + public ResultWrapper debug_traceTransactionInBlockByIndex(byte[] blockRlp, int txIndex, GethTraceOptions options = null) + { + using CancellationTokenSource cancellationTokenSource = new(_traceTimeout); + CancellationToken cancellationToken = cancellationTokenSource.Token; + var blockTrace = _debugBridge.GetBlockTrace(new Rlp(blockRlp), cancellationToken, options); + var transactionTrace = blockTrace?.ElementAtOrDefault(txIndex); + if (transactionTrace is null) + { + return ResultWrapper.Fail($"Trace is null for RLP {blockRlp.ToHexString()} and transaction index {txIndex}", ErrorCodes.ResourceNotFound); + } + + return ResultWrapper.Success(transactionTrace); + } - if (blockTrace is null) - return ResultWrapper.Fail($"Trace is null for RLP {blockRlp.ToHexString()}", ErrorCodes.ResourceNotFound); + public async Task> debug_migrateReceipts(long blockNumber) => + ResultWrapper.Success(await _debugBridge.MigrateReceipts(blockNumber)); - if (_logger.IsTrace) _logger.Trace($"{nameof(debug_traceBlock)} request {blockRlp.ToHexString()}, result: {blockTrace}"); + public Task> debug_insertReceipts(BlockParameter blockParameter, ReceiptForRpc[] receiptForRpc) + { + _debugBridge.InsertReceipts(blockParameter, receiptForRpc.Select(r => r.ToReceipt()).ToArray()); + return Task.FromResult(ResultWrapper.Success(true)); + } - return ResultWrapper.Success(blockTrace); - } + public ResultWrapper debug_traceBlock(byte[] blockRlp, GethTraceOptions options = null) + { + using var cancellationTokenSource = new CancellationTokenSource(_traceTimeout); + var cancellationToken = cancellationTokenSource.Token; + var blockTrace = _debugBridge.GetBlockTrace(new Rlp(blockRlp), cancellationToken, options); - public ResultWrapper debug_traceBlockByNumber(BlockParameter blockNumber, GethTraceOptions options = null) - { - using var cancellationTokenSource = new CancellationTokenSource(_traceTimeout); - var cancellationToken = cancellationTokenSource.Token; - var blockTrace = _debugBridge.GetBlockTrace(blockNumber, cancellationToken, options); + if (blockTrace is null) + return ResultWrapper.Fail($"Trace is null for RLP {blockRlp.ToHexString()}", ErrorCodes.ResourceNotFound); - if (blockTrace is null) - return ResultWrapper.Fail($"Trace is null for block {blockNumber}", ErrorCodes.ResourceNotFound); + if (_logger.IsTrace) _logger.Trace($"{nameof(debug_traceBlock)} request {blockRlp.ToHexString()}, result: {blockTrace}"); - if (_logger.IsTrace) _logger.Trace($"{nameof(debug_traceBlockByNumber)} request {blockNumber}, result: {blockTrace}"); + return ResultWrapper.Success(blockTrace); + } - return ResultWrapper.Success(blockTrace); - } + public ResultWrapper debug_traceBlockByNumber(BlockParameter blockNumber, GethTraceOptions options = null) + { + using var cancellationTokenSource = new CancellationTokenSource(_traceTimeout); + var cancellationToken = cancellationTokenSource.Token; + var blockTrace = _debugBridge.GetBlockTrace(blockNumber, cancellationToken, options); - public ResultWrapper debug_traceBlockByHash(Keccak blockHash, GethTraceOptions options = null) - { - using var cancellationTokenSource = new CancellationTokenSource(_traceTimeout); - var cancellationToken = cancellationTokenSource.Token; - var blockTrace = _debugBridge.GetBlockTrace(new BlockParameter(blockHash), cancellationToken, options); + if (blockTrace is null) + return ResultWrapper.Fail($"Trace is null for block {blockNumber}", ErrorCodes.ResourceNotFound); - if (blockTrace is null) - return ResultWrapper.Fail($"Trace is null for block {blockHash}", ErrorCodes.ResourceNotFound); + if (_logger.IsTrace) _logger.Trace($"{nameof(debug_traceBlockByNumber)} request {blockNumber}, result: {blockTrace}"); - if (_logger.IsTrace) _logger.Trace($"{nameof(debug_traceBlockByHash)} request {blockHash}, result: {blockTrace}"); + return ResultWrapper.Success(blockTrace); + } - return ResultWrapper.Success(blockTrace); - } + public ResultWrapper debug_traceBlockByHash(Keccak blockHash, GethTraceOptions options = null) + { + using var cancellationTokenSource = new CancellationTokenSource(_traceTimeout); + var cancellationToken = cancellationTokenSource.Token; + var blockTrace = _debugBridge.GetBlockTrace(new BlockParameter(blockHash), cancellationToken, options); - public ResultWrapper debug_traceBlockFromFile(string fileName, GethTraceOptions options = null) - { - throw new NotImplementedException(); - } + if (blockTrace is null) + return ResultWrapper.Fail($"Trace is null for block {blockHash}", ErrorCodes.ResourceNotFound); - public ResultWrapper debug_dumpBlock(BlockParameter blockParameter) - { - throw new NotImplementedException(); - } + if (_logger.IsTrace) _logger.Trace($"{nameof(debug_traceBlockByHash)} request {blockHash}, result: {blockTrace}"); - public ResultWrapper debug_gcStats() - { - throw new NotImplementedException(); - } + return ResultWrapper.Success(blockTrace); + } - public ResultWrapper debug_getBlockRlp(long blockNumber) - { - byte[] rlp = _debugBridge.GetBlockRlp(blockNumber); - if (rlp is null) + public ResultWrapper debug_traceBlockFromFile(string fileName, GethTraceOptions options = null) { - return ResultWrapper.Fail($"Block {blockNumber} was not found", ErrorCodes.ResourceNotFound); + throw new NotImplementedException(); } - return ResultWrapper.Success(rlp); - } - - public ResultWrapper debug_getBlockRlpByHash(Keccak hash) - { - byte[] rlp = _debugBridge.GetBlockRlp(hash); - if (rlp is null) + public ResultWrapper debug_dumpBlock(BlockParameter blockParameter) { - return ResultWrapper.Fail($"Block {hash} was not found", ErrorCodes.ResourceNotFound); + throw new NotImplementedException(); } - return ResultWrapper.Success(rlp); - } + public ResultWrapper debug_gcStats() + { + throw new NotImplementedException(); + } - public ResultWrapper debug_memStats(BlockParameter blockParameter) - { - throw new NotImplementedException(); - } + public ResultWrapper debug_getBlockRlp(long blockNumber) + { + byte[] rlp = _debugBridge.GetBlockRlp(blockNumber); + if (rlp is null) + { + return ResultWrapper.Fail($"Block {blockNumber} was not found", ErrorCodes.ResourceNotFound); + } - public ResultWrapper debug_seedHash(BlockParameter blockParameter) - { - throw new NotImplementedException(); - } + return ResultWrapper.Success(rlp); + } - public ResultWrapper debug_setHead(BlockParameter blockParameter) - { - throw new NotImplementedException(); - } + public ResultWrapper debug_getBlockRlpByHash(Keccak hash) + { + byte[] rlp = _debugBridge.GetBlockRlp(hash); + if (rlp is null) + { + return ResultWrapper.Fail($"Block {hash} was not found", ErrorCodes.ResourceNotFound); + } - public ResultWrapper debug_getFromDb(string dbName, byte[] key) - { - var dbValue = _debugBridge.GetDbValue(dbName, key); - return ResultWrapper.Success(dbValue); - } + return ResultWrapper.Success(rlp); + } - public ResultWrapper debug_getConfigValue(string category, string name) - { - var configValue = _debugBridge.GetConfigValue(category, name); - return ResultWrapper.Success(configValue); - } + public ResultWrapper debug_memStats(BlockParameter blockParameter) + { + throw new NotImplementedException(); + } - public ResultWrapper debug_resetHead(Keccak blockHash) - { - _debugBridge.UpdateHeadBlock(blockHash); - return ResultWrapper.Success(true); - } + public ResultWrapper debug_seedHash(BlockParameter blockParameter) + { + throw new NotImplementedException(); + } - public Task> debug_getSyncStage() - { - return ResultWrapper.Success(_debugBridge.GetCurrentSyncStage()); - } + public ResultWrapper debug_setHead(BlockParameter blockParameter) + { + throw new NotImplementedException(); + } - public ResultWrapper> debug_standardTraceBlockToFile(Keccak blockHash, GethTraceOptions options = null) - { - using var cancellationTokenSource = new CancellationTokenSource(_traceTimeout); - var cancellationToken = cancellationTokenSource.Token; + public ResultWrapper debug_getFromDb(string dbName, byte[] key) + { + var dbValue = _debugBridge.GetDbValue(dbName, key); + return ResultWrapper.Success(dbValue); + } - var files = _debugBridge.TraceBlockToFile(blockHash, cancellationToken, options); + public ResultWrapper debug_getConfigValue(string category, string name) + { + var configValue = _debugBridge.GetConfigValue(category, name); + return ResultWrapper.Success(configValue); + } - if (_logger.IsTrace) _logger.Trace($"{nameof(debug_standardTraceBlockToFile)} request {blockHash}, result: {files}"); + public ResultWrapper debug_resetHead(Keccak blockHash) + { + _debugBridge.UpdateHeadBlock(blockHash); + return ResultWrapper.Success(true); + } - return ResultWrapper>.Success(files); + public Task> debug_getSyncStage() + { + return ResultWrapper.Success(_debugBridge.GetCurrentSyncStage()); + } } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/GethLikeTxTraceConverter.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/GethLikeTxTraceConverter.cs index 32b6ad690db..980199bb25e 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/GethLikeTxTraceConverter.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/GethLikeTxTraceConverter.cs @@ -3,65 +3,55 @@ using System; using System.Collections.Generic; -using System.Linq; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.JsonRpc.Modules.Trace; using Newtonsoft.Json; -namespace Nethermind.JsonRpc.Modules.DebugModule; - -public class GethLikeTxTraceConverter : JsonConverter +namespace Nethermind.JsonRpc.Modules.DebugModule { - public override GethLikeTxTrace ReadJson( - JsonReader reader, - Type objectType, - GethLikeTxTrace existingValue, - bool hasExistingValue, - JsonSerializer serializer) => throw new NotSupportedException(); - - public override void WriteJson(JsonWriter writer, GethLikeTxTrace value, JsonSerializer serializer) + public class GethLikeTxTraceConverter : JsonConverter { - if (value is null) + public override void WriteJson(JsonWriter writer, GethLikeTxTrace value, JsonSerializer serializer) { - writer.WriteNull(); - return; - } + if (value is null) + { + writer.WriteNull(); + return; + } - writer.WriteStartObject(); + writer.WriteStartObject(); - writer.WriteProperty("gas", value.Gas, serializer); - writer.WriteProperty("failed", value.Failed); - writer.WriteProperty("returnValue", value.ReturnValue, serializer); + writer.WriteProperty("gas", value.Gas, serializer); + writer.WriteProperty("failed", value.Failed); + writer.WriteProperty("returnValue", value.ReturnValue, serializer); - writer.WritePropertyName("structLogs"); - WriteEntries(writer, value.Entries, serializer); + writer.WritePropertyName("structLogs"); + WriteEntries(writer, value.Entries, serializer); - writer.WriteEndObject(); - } + writer.WriteEndObject(); + } - private static void WriteEntries(JsonWriter writer, List entries, JsonSerializer _) - { - writer.WriteStartArray(); - foreach (GethTxTraceEntry entry in entries) + private static void WriteEntries(JsonWriter writer, List entries, JsonSerializer serializer) { - writer.WriteStartObject(); - writer.WriteProperty("pc", entry.ProgramCounter); - writer.WriteProperty("op", entry.Opcode); - writer.WriteProperty("gas", entry.Gas); - writer.WriteProperty("gasCost", entry.GasCost); - writer.WriteProperty("depth", entry.Depth); - writer.WriteProperty("error", entry.Error); - writer.WritePropertyName("stack"); writer.WriteStartArray(); - foreach (string stackItem in entry.Stack) + foreach (GethTxTraceEntry entry in entries) { - writer.WriteValue(stackItem); - } + writer.WriteStartObject(); + writer.WriteProperty("pc", entry.Pc); + writer.WriteProperty("op", entry.Operation); + writer.WriteProperty("gas", entry.Gas); + writer.WriteProperty("gasCost", entry.GasCost); + writer.WriteProperty("depth", entry.Depth); + writer.WriteProperty("error", entry.Error); + writer.WritePropertyName("stack"); + writer.WriteStartArray(); + foreach (string stackItem in entry.Stack) + { + writer.WriteValue(stackItem); + } - writer.WriteEndArray(); + writer.WriteEndArray(); - if (entry.Memory is not null) - { writer.WritePropertyName("memory"); writer.WriteStartArray(); foreach (string memory in entry.Memory) @@ -69,24 +59,25 @@ private static void WriteEntries(JsonWriter writer, List entri writer.WriteValue(memory); } writer.WriteEndArray(); - } - if (entry.Storage is not null) - { writer.WritePropertyName("storage"); writer.WriteStartObject(); - - foreach (var item in entry.Storage.OrderBy(s => s.Key)) + foreach ((string storageIndex, string storageValue) in entry.SortedStorage) { - writer.WriteProperty(item.Key, item.Value); + writer.WriteProperty(storageIndex, storageValue); } writer.WriteEndObject(); + + writer.WriteEndObject(); } - writer.WriteEndObject(); + writer.WriteEndArray(); } - writer.WriteEndArray(); + public override GethLikeTxTrace ReadJson(JsonReader reader, Type objectType, GethLikeTxTrace existingValue, bool hasExistingValue, JsonSerializer serializer) + { + throw new NotSupportedException(); + } } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs index 3ba8c2eebad..80895c74ec4 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain.Find; @@ -11,26 +10,26 @@ using Nethermind.Serialization.Rlp; using Nethermind.Synchronization.Reporting; -namespace Nethermind.JsonRpc.Modules.DebugModule; - -public interface IDebugBridge +namespace Nethermind.JsonRpc.Modules.DebugModule { - GethLikeTxTrace GetTransactionTrace(Keccak transactionHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); - GethLikeTxTrace GetTransactionTrace(long blockNumber, int index, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); - GethLikeTxTrace GetTransactionTrace(Keccak blockHash, int index, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); - GethLikeTxTrace GetTransactionTrace(Rlp blockRlp, Keccak transactionHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); - GethLikeTxTrace? GetTransactionTrace(Transaction transaction, BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); - GethLikeTxTrace[] GetBlockTrace(BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null); - GethLikeTxTrace[] GetBlockTrace(Rlp blockRlp, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); - byte[] GetBlockRlp(Keccak blockHash); - byte[] GetBlockRlp(long number); - byte[] GetDbValue(string dbName, byte[] key); - object GetConfigValue(string category, string name); - public ChainLevelInfo GetLevelInfo(long number); - public int DeleteChainSlice(long startNumber); - public void UpdateHeadBlock(Keccak blockHash); - Task MigrateReceipts(long blockNumber); - void InsertReceipts(BlockParameter blockParameter, TxReceipt[] receipts); - SyncReportSymmary GetCurrentSyncStage(); - IEnumerable TraceBlockToFile(Keccak blockHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); + public interface IDebugBridge + { + GethLikeTxTrace GetTransactionTrace(Keccak transactionHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); + GethLikeTxTrace GetTransactionTrace(long blockNumber, int index, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); + GethLikeTxTrace GetTransactionTrace(Keccak blockHash, int index, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); + GethLikeTxTrace GetTransactionTrace(Rlp blockRlp, Keccak transactionHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); + GethLikeTxTrace? GetTransactionTrace(Transaction transaction, BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); + GethLikeTxTrace[] GetBlockTrace(BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null); + GethLikeTxTrace[] GetBlockTrace(Rlp blockRlp, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); + byte[] GetBlockRlp(Keccak blockHash); + byte[] GetBlockRlp(long number); + byte[] GetDbValue(string dbName, byte[] key); + object GetConfigValue(string category, string name); + public ChainLevelInfo GetLevelInfo(long number); + public int DeleteChainSlice(long startNumber); + public void UpdateHeadBlock(Keccak blockHash); + Task MigrateReceipts(long blockNumber); + void InsertReceipts(BlockParameter blockParameter, TxReceipt[] receipts); + SyncReportSymmary GetCurrentSyncStage(); + } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs index 0862a6ec951..18a3066d064 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs @@ -1,97 +1,92 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; using System.Threading.Tasks; using Nethermind.Blockchain.Find; using Nethermind.Core.Crypto; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.JsonRpc.Data; using Nethermind.Synchronization.Reporting; - -namespace Nethermind.JsonRpc.Modules.DebugModule; - -[RpcModule(ModuleType.Debug)] -public interface IDebugRpcModule : IRpcModule +namespace Nethermind.JsonRpc.Modules.DebugModule { - [JsonRpcMethod(Description = "Retrieves a representation of tree branches on a given chain level (Nethermind specific).", IsImplemented = true, IsSharable = true)] - ResultWrapper debug_getChainLevel(in long number); - - [JsonRpcMethod(Description = "Deletes a slice of a chain from the tree on all branches (Nethermind specific).", IsImplemented = true, IsSharable = true)] - ResultWrapper debug_deleteChainSlice(in long startNumber); + [RpcModule(ModuleType.Debug)] + public interface IDebugRpcModule : IRpcModule + { + [JsonRpcMethod(Description = "Retrieves a representation of tree branches on a given chain level (Nethermind specific).", IsImplemented = true, IsSharable = true)] + ResultWrapper debug_getChainLevel(in long number); - [JsonRpcMethod( - Description = "Updates / resets head block - use only when the node got stuck due to DB / memory corruption (Nethermind specific).", - IsSharable = true)] - ResultWrapper debug_resetHead(Keccak blockHash); + [JsonRpcMethod(Description = "Deletes a slice of a chain from the tree on all branches (Nethermind specific).", IsImplemented = true, IsSharable = true)] + ResultWrapper debug_deleteChainSlice(in long startNumber); - [JsonRpcMethod(Description = "This method will attempt to run the transaction in the exact same manner as it was executed on the network. It will replay any transaction that may have been executed prior to this one before it will finally attempt to execute the transaction that corresponds to the given hash.", IsImplemented = true, IsSharable = true)] - ResultWrapper debug_traceTransaction(Keccak transactionHash, GethTraceOptions options = null); + [JsonRpcMethod( + Description = "Updates / resets head block - use only when the node got stuck due to DB / memory corruption (Nethermind specific).", + IsSharable = true)] + ResultWrapper debug_resetHead(Keccak blockHash); - [JsonRpcMethod(Description = "This method lets you run an eth_call within the context of the given block execution using the final state of parent block as the base. The block can be specified either by hash or by number. It takes the same input object as a eth_call. It returns the same output as debug_traceTransaction.", IsImplemented = true, IsSharable = true)] - ResultWrapper debug_traceCall(TransactionForRpc call, BlockParameter? blockParameter = null, GethTraceOptions? options = null); + [JsonRpcMethod(Description = "This method will attempt to run the transaction in the exact same manner as it was executed on the network. It will replay any transaction that may have been executed prior to this one before it will finally attempt to execute the transaction that corresponds to the given hash.", IsImplemented = true, IsSharable = true)] + ResultWrapper debug_traceTransaction(Keccak transactionHash, GethTraceOptions options = null); - [JsonRpcMethod(Description = "", IsSharable = true)] - ResultWrapper debug_traceTransactionByBlockAndIndex(BlockParameter blockParameter, int txIndex, GethTraceOptions options = null); + [JsonRpcMethod(Description = "This method lets you run an eth_call within the context of the given block execution using the final state of parent block as the base. The block can be specified either by hash or by number. It takes the same input object as a eth_call. It returns the same output as debug_traceTransaction.", IsImplemented = true, IsSharable = true)] + ResultWrapper debug_traceCall(TransactionForRpc call, BlockParameter? blockParameter = null, GethTraceOptions? options = null); - [JsonRpcMethod(Description = "", IsSharable = true)] - ResultWrapper debug_traceTransactionByBlockhashAndIndex(Keccak blockHash, int txIndex, GethTraceOptions options = null); + [JsonRpcMethod(Description = "", IsSharable = true)] + ResultWrapper debug_traceTransactionByBlockAndIndex(BlockParameter blockParameter, int txIndex, GethTraceOptions options = null); - [JsonRpcMethod(Description = "Returns the full stack trace of all invoked opcodes of all transactions that were included in the block specified. The parent of the block must be present or it will fail.", IsImplemented = true, IsSharable = true)] - ResultWrapper debug_traceBlock(byte[] blockRlp, GethTraceOptions options = null); + [JsonRpcMethod(Description = "", IsSharable = true)] + ResultWrapper debug_traceTransactionByBlockhashAndIndex(Keccak blockHash, int txIndex, GethTraceOptions options = null); - [JsonRpcMethod(Description = "Similar to debug_traceBlock, this method accepts a block number as well as \"latest\" or \"finalized\" and replays the block that is already present in the database.", IsImplemented = true, IsSharable = true)] - ResultWrapper debug_traceBlockByNumber(BlockParameter blockParameter, GethTraceOptions options = null); + [JsonRpcMethod(Description = "Returns the full stack trace of all invoked opcodes of all transactions that were included in the block specified. The parent of the block must be present or it will fail.", IsImplemented = true, IsSharable = true)] + ResultWrapper debug_traceBlock(byte[] blockRlp, GethTraceOptions options = null); - [JsonRpcMethod(Description = "Similar to debug_traceBlock, this method accepts a block hash and replays the block that is already present in the database.", IsImplemented = true, IsSharable = true)] - ResultWrapper debug_traceBlockByHash(Keccak blockHash, GethTraceOptions options = null); + [JsonRpcMethod(Description = "Similar to debug_traceBlock, this method accepts a block number as well as \"latest\" or \"finalized\" and replays the block that is already present in the database.", IsImplemented = true, IsSharable = true)] + ResultWrapper debug_traceBlockByNumber(BlockParameter blockParameter, GethTraceOptions options = null); - [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = false)] - ResultWrapper debug_traceBlockFromFile(string fileName, GethTraceOptions options = null); + [JsonRpcMethod(Description = "Similar to debug_traceBlock, this method accepts a block hash and replays the block that is already present in the database.", IsImplemented = true, IsSharable = true)] + ResultWrapper debug_traceBlockByHash(Keccak blockHash, GethTraceOptions options = null); - [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = false)] - ResultWrapper debug_dumpBlock(BlockParameter blockParameter); + [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = false)] + ResultWrapper debug_traceBlockFromFile(string fileName, GethTraceOptions options = null); - [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = true)] - ResultWrapper debug_gcStats(); + [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = false)] + ResultWrapper debug_dumpBlock(BlockParameter blockParameter); - [JsonRpcMethod(Description = "Retrieves a block in the RLP-serialized form.", IsImplemented = true, IsSharable = true)] - ResultWrapper debug_getBlockRlp(long number); + [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = true)] + ResultWrapper debug_gcStats(); - [JsonRpcMethod(Description = "Retrieves a block in the RLP-serialized form.", IsImplemented = true, IsSharable = false)] - ResultWrapper debug_getBlockRlpByHash(Keccak hash); + [JsonRpcMethod(Description = "Retrieves a block in the RLP-serialized form.", IsImplemented = true, IsSharable = true)] + ResultWrapper debug_getBlockRlp(long number); - [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = true)] - ResultWrapper debug_memStats(BlockParameter blockParameter); + [JsonRpcMethod(Description = "Retrieves a block in the RLP-serialized form.", IsImplemented = true, IsSharable = false)] + ResultWrapper debug_getBlockRlpByHash(Keccak hash); - [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = true)] - ResultWrapper debug_seedHash(BlockParameter blockParameter); + [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = true)] + ResultWrapper debug_memStats(BlockParameter blockParameter); - [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = false)] - ResultWrapper debug_setHead(BlockParameter blockParameter); + [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = true)] + ResultWrapper debug_seedHash(BlockParameter blockParameter); - [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = true)] - ResultWrapper debug_getFromDb(string dbName, byte[] key); + [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = false)] + ResultWrapper debug_setHead(BlockParameter blockParameter); - [JsonRpcMethod(Description = "Retrieves the Nethermind configuration value, e.g. JsonRpc.Enabled", IsImplemented = true, IsSharable = true)] - ResultWrapper debug_getConfigValue(string category, string name); + [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = true)] + ResultWrapper debug_getFromDb(string dbName, byte[] key); - [JsonRpcMethod(Description = "", IsImplemented = true, IsSharable = false)] - ResultWrapper debug_traceTransactionInBlockByHash(byte[] blockRlp, Keccak transactionHash, GethTraceOptions options = null); + [JsonRpcMethod(Description = "Retrieves the Nethermind configuration value, e.g. JsonRpc.Enabled", IsImplemented = true, IsSharable = true)] + ResultWrapper debug_getConfigValue(string category, string name); - [JsonRpcMethod(Description = "", IsImplemented = true, IsSharable = false)] - ResultWrapper debug_traceTransactionInBlockByIndex(byte[] blockRlp, int txIndex, GethTraceOptions options = null); + [JsonRpcMethod(Description = "", IsImplemented = true, IsSharable = false)] + ResultWrapper debug_traceTransactionInBlockByHash(byte[] blockRlp, Keccak transactionHash, GethTraceOptions options = null); - [JsonRpcMethod(Description = "Sets the block number up to which receipts will be migrated to (Nethermind specific).")] - Task> debug_migrateReceipts(long blockNumber); + [JsonRpcMethod(Description = "", IsImplemented = true, IsSharable = false)] + ResultWrapper debug_traceTransactionInBlockByIndex(byte[] blockRlp, int txIndex, GethTraceOptions options = null); - [JsonRpcMethod(Description = "Insert receipts for the block after verifying receipts root correctness.")] - Task> debug_insertReceipts(BlockParameter blockParameter, ReceiptForRpc[] receiptForRpc); + [JsonRpcMethod(Description = "Sets the block number up to which receipts will be migrated to (Nethermind specific).")] + Task> debug_migrateReceipts(long blockNumber); - [JsonRpcMethod(Description = "Retrives Nethermind Sync Stage, With extra Metadata")] - Task> debug_getSyncStage(); + [JsonRpcMethod(Description = "Insert receipts for the block after verifying receipts root correctness.")] + Task> debug_insertReceipts(BlockParameter blockParameter, ReceiptForRpc[] receiptForRpc); - [JsonRpcMethod(Description = "Writes to a file the full stack trace of all invoked opcodes of the transaction specified (or all transactions if not specified) that was included in the block specified. The parent of the block must be present or it will fail.", - IsImplemented = true, IsSharable = false)] - ResultWrapper> debug_standardTraceBlockToFile(Keccak blockHash, GethTraceOptions options = null); + [JsonRpcMethod(Description = "Retrives Nethermind Sync Stage, With extra Metadata")] + Task> debug_getSyncStage(); + } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/BlockForRpc.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/BlockForRpc.cs index 002d32256af..6e9a82cf353 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/BlockForRpc.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/BlockForRpc.cs @@ -58,13 +58,8 @@ public BlockForRpc(Block block, bool includeFullTransactionData, ISpecProvider s if (spec.IsEip4844Enabled) { - BlobGasUsed = block.Header.BlobGasUsed; - ExcessBlobGas = block.Header.ExcessBlobGas; - } - - if (spec.IsEip4788Enabled) - { - ParentBeaconBlockRoot = block.ParentBeaconBlockRoot; + DataGasUsed = block.Header.DataGasUsed; + ExcessDataGas = block.Header.ExcessDataGas; } } @@ -131,11 +126,8 @@ public BlockForRpc(Block block, bool includeFullTransactionData, ISpecProvider s public Keccak? WithdrawalsRoot { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public ulong? BlobGasUsed { get; set; } - - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public ulong? ExcessBlobGas { get; set; } + public ulong? DataGasUsed { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public Keccak? ParentBeaconBlockRoot { get; set; } + public ulong? ExcessDataGas { get; set; } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthModule.TransactionExecutor.cs similarity index 93% rename from src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs rename to src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthModule.TransactionExecutor.cs index 101ce8e5cb8..b1c7675f8ce 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthModule.TransactionExecutor.cs @@ -2,8 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; -using System.Linq; using System.Threading; using Nethermind.Blockchain.Find; using Nethermind.Core; @@ -127,13 +125,13 @@ protected override ResultWrapper ExecuteTx(BlockHeader header, return result.InputError ? GetInputError(result) - : ResultWrapper.Fail(result.Error, ErrorCodes.ExecutionError, new AccessListForRpc(GetResultAccessList(tx, result), GetResultGas(tx, result))); + : ResultWrapper.Fail(result.Error, ErrorCodes.ExecutionError, new(GetResultAccessList(tx, result), GetResultGas(tx, result))); } - private static IEnumerable GetResultAccessList(Transaction tx, BlockchainBridge.CallOutput result) + private static AccessListItemForRpc[] GetResultAccessList(Transaction tx, BlockchainBridge.CallOutput result) { AccessList? accessList = result.AccessList ?? tx.AccessList; - return accessList is null ? Enumerable.Empty() : AccessListItemForRpc.FromAccessList(accessList); + return accessList is null ? Array.Empty() : AccessListItemForRpc.FromAccessList(accessList); } private static UInt256 GetResultGas(Transaction transaction, BlockchainBridge.CallOutput result) diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthModuleFactory.cs index a27c263fb99..9ca52f2cc8a 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthModuleFactory.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; +using Nethermind.Consensus; using Nethermind.Core.Specs; using Nethermind.Facade; using Nethermind.Facade.Eth; @@ -72,6 +73,7 @@ public override IEthRpcModule Create() _txPool, _txSender, _wallet, + _receiptStorage, _logManager, _specProvider, _gasPriceOracle, diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs index 27b56d954b8..2fb9ce4c21a 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Nethermind.Blockchain.Filters; using Nethermind.Blockchain.Find; +using Nethermind.Blockchain.Receipts; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; @@ -27,7 +28,6 @@ using Nethermind.Serialization.Rlp; using Nethermind.State; using Nethermind.State.Proofs; -using Nethermind.Synchronization.ParallelSync; using Nethermind.Trie; using Nethermind.TxPool; using Nethermind.Wallet; @@ -44,6 +44,7 @@ public partial class EthRpcModule : IEthRpcModule private readonly IJsonRpcConfig _rpcConfig; private readonly IBlockchainBridge _blockchainBridge; private readonly IBlockFinder _blockFinder; + private readonly IReceiptFinder _receiptFinder; private readonly IStateReader _stateReader; private readonly ITxPool _txPoolBridge; private readonly ITxSender _txSender; @@ -57,7 +58,7 @@ public partial class EthRpcModule : IEthRpcModule private static bool HasStateForBlock(IBlockchainBridge blockchainBridge, BlockHeader header) { RootCheckVisitor rootCheckVisitor = new(); - blockchainBridge.RunTreeVisitor(rootCheckVisitor, header.StateRoot!); + blockchainBridge.RunTreeVisitor(rootCheckVisitor, header.StateRoot); return rootCheckVisitor.HasRoot; } @@ -69,6 +70,7 @@ public EthRpcModule( ITxPool txPool, ITxSender txSender, IWallet wallet, + IReceiptFinder receiptFinder, ILogManager logManager, ISpecProvider specProvider, IGasPriceOracle gasPriceOracle, @@ -83,6 +85,7 @@ public EthRpcModule( _txPoolBridge = txPool ?? throw new ArgumentNullException(nameof(txPool)); _txSender = txSender ?? throw new ArgumentNullException(nameof(txSender)); _wallet = wallet ?? throw new ArgumentNullException(nameof(wallet)); + _receiptFinder = receiptFinder ?? throw new ArgumentNullException(nameof(receiptFinder)); ; _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); _gasPriceOracle = gasPriceOracle ?? throw new ArgumentNullException(nameof(gasPriceOracle)); _ethSyncingInfo = ethSyncingInfo ?? throw new ArgumentNullException(nameof(ethSyncingInfo)); @@ -110,6 +113,16 @@ public ResultWrapper
eth_coinbase() return ResultWrapper
.Success(Address.Zero); } + public ResultWrapper eth_mining() + { + return ResultWrapper.Success(_blockchainBridge.IsMining); + } + + public ResultWrapper eth_hashrate() + { + return ResultWrapper.Success(0); + } + public ResultWrapper eth_gasPrice() { return ResultWrapper.Success(_gasPriceOracle.GetGasPriceEstimate()); @@ -151,16 +164,17 @@ public ResultWrapper> eth_accounts() SearchResult searchResult = _blockFinder.SearchForHeader(blockParameter); if (searchResult.IsError) { - return Task.FromResult(GetFailureResult(searchResult, _ethSyncingInfo.SyncMode.HaveNotSyncedHeadersYet())); + return Task.FromResult(ResultWrapper.Fail(searchResult)); } BlockHeader header = searchResult.Object; - if (!HasStateForBlock(_blockchainBridge, header!)) + if (!HasStateForBlock(_blockchainBridge, header)) { - return Task.FromResult(GetStateFailureResult(header)); + return Task.FromResult(ResultWrapper.Fail($"No state available for block {header.Hash}", + ErrorCodes.ResourceUnavailable)); } - Account account = _stateReader.GetAccount(header!.StateRoot!, address); + Account account = _stateReader.GetAccount(header.StateRoot, address); return Task.FromResult(ResultWrapper.Success(account?.Balance ?? UInt256.Zero)); } @@ -170,41 +184,44 @@ public ResultWrapper eth_getStorageAt(Address address, UInt256 positionI SearchResult searchResult = _blockFinder.SearchForHeader(blockParameter); if (searchResult.IsError) { - return GetFailureResult(searchResult, _ethSyncingInfo.SyncMode.HaveNotSyncedHeadersYet()); + return ResultWrapper.Fail(searchResult); } BlockHeader? header = searchResult.Object; - Account account = _stateReader.GetAccount(header!.StateRoot!, address); + Account account = _stateReader.GetAccount(header.StateRoot, address); if (account is null) { return ResultWrapper.Success(Array.Empty()); } byte[] storage = _stateReader.GetStorage(account.StorageRoot, positionIndex); - return ResultWrapper.Success(storage!.PadLeft(32)); + return ResultWrapper.Success(storage.PadLeft(32)); } public Task> eth_getTransactionCount(Address address, BlockParameter blockParameter) { + if (blockParameter == BlockParameter.Pending) { UInt256 pendingNonce = _txPoolBridge.GetLatestPendingNonce(address); return Task.FromResult(ResultWrapper.Success(pendingNonce)); + } SearchResult searchResult = _blockFinder.SearchForHeader(blockParameter); if (searchResult.IsError) { - return Task.FromResult(GetFailureResult(searchResult, _ethSyncingInfo.SyncMode.HaveNotSyncedHeadersYet())); + return Task.FromResult(ResultWrapper.Fail(searchResult)); } BlockHeader header = searchResult.Object; - if (!HasStateForBlock(_blockchainBridge, header!)) + if (!HasStateForBlock(_blockchainBridge, header)) { - return Task.FromResult(GetStateFailureResult(header)); + return Task.FromResult(ResultWrapper.Fail($"No state available for block {header.Hash}", + ErrorCodes.ResourceUnavailable)); } - Account account = _stateReader.GetAccount(header!.StateRoot!, address); + Account account = _stateReader.GetAccount(header.StateRoot, address); UInt256 nonce = account?.Nonce ?? 0; return Task.FromResult(ResultWrapper.Success(nonce)); @@ -213,33 +230,45 @@ public Task> eth_getTransactionCount(Address address, Blo public ResultWrapper eth_getBlockTransactionCountByHash(Keccak blockHash) { SearchResult searchResult = _blockFinder.SearchForBlock(new BlockParameter(blockHash)); - return searchResult.IsError - ? GetFailureResult(searchResult, _ethSyncingInfo.SyncMode.HaveNotSyncedBodiesYet()) - : ResultWrapper.Success((UInt256)searchResult.Object!.Transactions.Length); + if (searchResult.IsError) + { + return ResultWrapper.Fail(searchResult); + } + + return ResultWrapper.Success((UInt256)searchResult.Object.Transactions.Length); } public ResultWrapper eth_getBlockTransactionCountByNumber(BlockParameter blockParameter) { SearchResult searchResult = _blockFinder.SearchForBlock(blockParameter); - return searchResult.IsError - ? GetFailureResult(searchResult, _ethSyncingInfo.SyncMode.HaveNotSyncedBodiesYet()) - : ResultWrapper.Success((UInt256)searchResult.Object!.Transactions.Length); + if (searchResult.IsError) + { + return ResultWrapper.Fail(searchResult); + } + + return ResultWrapper.Success((UInt256)searchResult.Object.Transactions.Length); } public ResultWrapper eth_getUncleCountByBlockHash(Keccak blockHash) { SearchResult searchResult = _blockFinder.SearchForBlock(new BlockParameter(blockHash)); - return searchResult.IsError - ? GetFailureResult(searchResult, _ethSyncingInfo.SyncMode.HaveNotSyncedBodiesYet()) - : ResultWrapper.Success((UInt256)searchResult.Object!.Uncles.Length); + if (searchResult.IsError) + { + return ResultWrapper.Fail(searchResult); + } + + return ResultWrapper.Success((UInt256)searchResult.Object.Uncles.Length); } public ResultWrapper eth_getUncleCountByBlockNumber(BlockParameter? blockParameter) { SearchResult searchResult = _blockFinder.SearchForBlock(blockParameter); - return searchResult.IsError - ? GetFailureResult(searchResult, _ethSyncingInfo.SyncMode.HaveNotSyncedBodiesYet()) - : ResultWrapper.Success((UInt256)searchResult.Object!.Uncles.Length); + if (searchResult.IsError) + { + return ResultWrapper.Fail(searchResult); + } + + return ResultWrapper.Success((UInt256)searchResult.Object.Uncles.Length); } public ResultWrapper eth_getCode(Address address, BlockParameter? blockParameter = null) @@ -247,16 +276,17 @@ public ResultWrapper eth_getCode(Address address, BlockParameter? blockP SearchResult searchResult = _blockFinder.SearchForHeader(blockParameter); if (searchResult.IsError) { - return GetFailureResult(searchResult, _ethSyncingInfo.SyncMode.HaveNotSyncedHeadersYet()); + return ResultWrapper.Fail(searchResult); } BlockHeader header = searchResult.Object; - if (!HasStateForBlock(_blockchainBridge, header!)) + if (!HasStateForBlock(_blockchainBridge, header)) { - return GetStateFailureResult(header); + return ResultWrapper.Fail($"No state available for block {header.Hash}", + ErrorCodes.ResourceUnavailable); } - Account account = _stateReader.GetAccount(header!.StateRoot!, address); + Account account = _stateReader.GetAccount(header.StateRoot, address); if (account is null) { return ResultWrapper.Success(Array.Empty()); @@ -362,7 +392,7 @@ private ResultWrapper GetBlock(BlockParameter blockParameter, bool SearchResult searchResult = _blockFinder.SearchForBlock(blockParameter, true); if (searchResult.IsError) { - return GetFailureResult(searchResult, _ethSyncingInfo.SyncMode.HaveNotSyncedBodiesYet()); + return ResultWrapper.Fail(searchResult); } Block? block = searchResult.Object; @@ -420,11 +450,11 @@ public ResultWrapper eth_getTransactionByBlockHashAndIndex(Ke SearchResult searchResult = _blockFinder.SearchForBlock(new BlockParameter(blockHash)); if (searchResult.IsError) { - return GetFailureResult(searchResult, _ethSyncingInfo.SyncMode.HaveNotSyncedBodiesYet()); + return ResultWrapper.Fail(searchResult); } Block block = searchResult.Object; - if (positionIndex < 0 || positionIndex > block!.Transactions.Length - 1) + if (positionIndex < 0 || positionIndex > block.Transactions.Length - 1) { return ResultWrapper.Fail("Position Index is incorrect", ErrorCodes.InvalidParams); } @@ -443,11 +473,11 @@ public ResultWrapper eth_getTransactionByBlockNumberAndIndex( SearchResult searchResult = _blockFinder.SearchForBlock(blockParameter); if (searchResult.IsError) { - return GetFailureResult(searchResult, _ethSyncingInfo.SyncMode.HaveNotSyncedBodiesYet()); + return ResultWrapper.Fail(searchResult); } Block? block = searchResult.Object; - if (positionIndex < 0 || positionIndex > block!.Transactions.Length - 1) + if (positionIndex < 0 || positionIndex > block.Transactions.Length - 1) { return ResultWrapper.Fail("Position Index is incorrect", ErrorCodes.InvalidParams); } @@ -491,11 +521,11 @@ private ResultWrapper GetUncle(BlockParameter blockParameter, UInt2 SearchResult searchResult = _blockFinder.SearchForBlock(blockParameter); if (searchResult.IsError) { - return GetFailureResult(searchResult, _ethSyncingInfo.SyncMode.HaveNotSyncedBodiesYet()); + return ResultWrapper.Fail(searchResult); } Block block = searchResult.Object; - if (positionIndex < 0 || positionIndex > block!.Uncles.Length - 1) + if (positionIndex < 0 || positionIndex > block.Uncles.Length - 1) { return ResultWrapper.Fail("Position Index is incorrect", ErrorCodes.InvalidParams); } @@ -583,7 +613,7 @@ public ResultWrapper> eth_getFilterLogs(UInt256 filterId) catch (ResourceNotFoundException exception) { cancellationTokenSource.Dispose(); - return GetFailureResult>(exception, _ethSyncingInfo.SyncMode.HaveNotSyncedReceiptsYet()); + return ResultWrapper>.Fail(exception.Message, ErrorCodes.ResourceNotFound); } } @@ -605,17 +635,20 @@ public ResultWrapper> eth_getLogs(Filter filter) if (toBlockResult.IsError) { cancellationTokenSource.Dispose(); - return GetFailureResult, BlockHeader>(toBlockResult, _ethSyncingInfo.SyncMode.HaveNotSyncedHeadersYet()); + + return ResultWrapper>.Fail(toBlockResult); } cancellationToken.ThrowIfCancellationRequested(); + fromBlockResult = _blockFinder.SearchForHeader(filter.FromBlock); } if (fromBlockResult.IsError) { cancellationTokenSource.Dispose(); - return GetFailureResult, BlockHeader>(fromBlockResult, _ethSyncingInfo.SyncMode.HaveNotSyncedHeadersYet()); + + return ResultWrapper>.Fail(fromBlockResult); } cancellationToken.ThrowIfCancellationRequested(); @@ -626,41 +659,66 @@ public ResultWrapper> eth_getLogs(Filter filter) if (fromBlockNumber > toBlockNumber && toBlockNumber != 0) { cancellationTokenSource.Dispose(); + return ResultWrapper>.Fail($"'From' block '{fromBlockNumber}' is later than 'to' block '{toBlockNumber}'.", ErrorCodes.InvalidParams); } try { - IEnumerable filterLogs = _blockchainBridge.GetLogs(filter.FromBlock!, filter.ToBlock!, + IEnumerable filterLogs = _blockchainBridge.GetLogs(filter.FromBlock, filter.ToBlock, filter.Address, filter.Topics, cancellationToken); return ResultWrapper>.Success(GetLogs(filterLogs, cancellationTokenSource)); } catch (ResourceNotFoundException exception) { - return GetFailureResult>(exception, _ethSyncingInfo.SyncMode.HaveNotSyncedReceiptsYet()); + return ResultWrapper>.Fail(exception.Message, ErrorCodes.ResourceNotFound); } } + public ResultWrapper> eth_getWork() + { + return ResultWrapper>.Fail("eth_getWork not supported", ErrorCodes.MethodNotFound); + } + + public ResultWrapper eth_submitWork(byte[] nonce, Keccak headerPowHash, byte[] mixDigest) + { + return ResultWrapper.Fail("eth_submitWork not supported", ErrorCodes.MethodNotFound, null); + } + + public ResultWrapper eth_submitHashrate(string hashRate, string id) + { + return ResultWrapper.Fail("eth_submitHashrate not supported", ErrorCodes.MethodNotFound, null); + } + // https://github.com/ethereum/EIPs/issues/1186 public ResultWrapper eth_getProof(Address accountAddress, UInt256[] storageKeys, BlockParameter blockParameter) { - SearchResult searchResult = _blockFinder.SearchForHeader(blockParameter); - if (searchResult.IsError) + BlockHeader header; + try { - return GetFailureResult(searchResult, _ethSyncingInfo.SyncMode.HaveNotSyncedHeadersYet()); - } - - BlockHeader header = searchResult.Object; + header = _blockFinder.FindHeader(blockParameter); + if (header is null) + { + return ResultWrapper.Fail($"{blockParameter} block not found", + ErrorCodes.ResourceNotFound, null); + } - if (!HasStateForBlock(_blockchainBridge, header!)) + if (!HasStateForBlock(_blockchainBridge, header)) + { + return ResultWrapper.Fail($"No state available for block {header.Hash}", + ErrorCodes.ResourceUnavailable); + } + } + catch (Exception ex) { - return GetStateFailureResult(header); + return ResultWrapper.Fail(ex.Message, ErrorCodes.InternalError, null); } AccountProofCollector accountProofCollector = new(accountAddress, storageKeys); - _blockchainBridge.RunTreeVisitor(accountProofCollector, header!.StateRoot!); + _blockchainBridge.RunTreeVisitor(accountProofCollector, header.StateRoot); + return ResultWrapper.Success(accountProofCollector.BuildResult()); } @@ -695,28 +753,19 @@ private IEnumerable GetLogs(IEnumerable logs, Cancellation public ResultWrapper eth_getAccount(Address accountAddress, BlockParameter? blockParameter) { - SearchResult searchResult = _blockFinder.SearchForHeader(blockParameter); + SearchResult searchResult = _blockFinder.SearchForHeader(blockParameter ?? BlockParameter.Latest); if (searchResult.IsError) { - return GetFailureResult(searchResult, _ethSyncingInfo.SyncMode.HaveNotSyncedHeadersYet()); + // probably better forward Error of searchResult + return ResultWrapper.Fail($"header not found", ErrorCodes.InvalidInput); } - BlockHeader header = searchResult.Object; - if (!HasStateForBlock(_blockchainBridge, header!)) + if (!HasStateForBlock(_blockchainBridge, header)) { - return GetStateFailureResult(header); + return ResultWrapper.Fail($"No state available for {blockParameter}", + ErrorCodes.ResourceUnavailable); } - - Account account = _stateReader.GetAccount(header!.StateRoot!, accountAddress); + Account account = _stateReader.GetAccount(header.StateRoot, accountAddress); return ResultWrapper.Success(account is null ? null : new AccountForRpc(account)); } - - private static ResultWrapper GetFailureResult(SearchResult searchResult, bool isTemporary) where TSearch : class => - ResultWrapper.Fail(searchResult, isTemporary && searchResult.ErrorCode == ErrorCodes.ResourceNotFound); - - private static ResultWrapper GetFailureResult(ResourceNotFoundException exception, bool isTemporary) => - ResultWrapper.Fail(exception.Message, ErrorCodes.ResourceNotFound, isTemporary); - - private ResultWrapper GetStateFailureResult(BlockHeader header) => - ResultWrapper.Fail($"No state available for block {header.ToString(BlockHeader.Format.FullHashAndNumber)}", ErrorCodes.ResourceUnavailable, _ethSyncingInfo.SyncMode.HaveNotSyncedStateYet()); } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/FeeHistory/FeeHistoryOracle.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/FeeHistory/FeeHistoryOracle.cs index 69440a1991a..c4e1f60c9a3 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/FeeHistory/FeeHistoryOracle.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/FeeHistory/FeeHistoryOracle.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.Linq; using Nethermind.Blockchain; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/GasPrice/IGasPriceOracle.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/GasPrice/IGasPriceOracle.cs index 57e4bcf04ae..8f25fe04644 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/GasPrice/IGasPriceOracle.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/GasPrice/IGasPriceOracle.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Int256; namespace Nethermind.JsonRpc.Modules.Eth.GasPrice diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs index 79a7ba6f8a0..bf844a5d701 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs @@ -41,6 +41,9 @@ public interface IEthRpcModule : IRpcModule ExampleResponse = "0x0000000000000000000000000000000000000000")] ResultWrapper
eth_coinbase(); + [JsonRpcMethod(IsImplemented = false, Description = "Returns mining status", IsSharable = true)] + ResultWrapper eth_mining(); + [JsonRpcMethod(IsImplemented = true, Description = "Returns block fee history.", IsSharable = true, @@ -53,6 +56,12 @@ public interface IEthRpcModule : IRpcModule [JsonRpcMethod(IsImplemented = false, Description = "", IsSharable = true)] ResultWrapper eth_maxPriorityFeePerGas(); + [JsonRpcMethod(IsImplemented = false, + Description = "Returns mining hashrate", + IsSharable = true, + ExampleResponse = "0x0")] + ResultWrapper eth_hashrate(); + [JsonRpcMethod(IsImplemented = false, Description = "Returns miner's gas price", IsSharable = true, @@ -249,6 +258,15 @@ ResultWrapper eth_getTransactionByBlockNumberAndIndex( [JsonRpcMethod(IsImplemented = true, Description = "Reads logs", IsSharable = false)] ResultWrapper> eth_getLogs(Filter filter); + [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = true)] + ResultWrapper> eth_getWork(); + + [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = false)] + ResultWrapper eth_submitWork(byte[] nonce, Keccak headerPowHash, byte[] mixDigest); + + [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = false)] + ResultWrapper eth_submitHashrate(string hashRate, string id); + [JsonRpcMethod(Description = "https://github.com/ethereum/EIPs/issues/1186", IsImplemented = true, IsSharable = true, diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/IRpcModulePool.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/IRpcModulePool.cs index da51813c678..4776aab783c 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/IRpcModulePool.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/IRpcModulePool.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Threading; using System.Threading.Tasks; namespace Nethermind.JsonRpc.Modules diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/IRpcModuleProviderExtensions.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/IRpcModuleProviderExtensions.cs index 050e859925a..d718bb6ade3 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/IRpcModuleProviderExtensions.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/IRpcModuleProviderExtensions.cs @@ -3,37 +3,38 @@ using System; -namespace Nethermind.JsonRpc.Modules; - -public static class IRpcModuleProviderExtensions +namespace Nethermind.JsonRpc.Modules { - private static readonly int _cpuCount = Environment.ProcessorCount; - - public static void RegisterBounded( - this IRpcModuleProvider rpcModuleProvider, - ModuleFactoryBase factory, - int maxCount, - int timeout) - where T : IRpcModule + public static class IRpcModuleProviderExtensions { - rpcModuleProvider.Register(new BoundedModulePool(factory, maxCount, timeout)); - } + private static readonly int _cpuCount = Environment.ProcessorCount; - public static void RegisterBoundedByCpuCount( - this IRpcModuleProvider rpcModuleProvider, - ModuleFactoryBase factory, - int timeout) - where T : IRpcModule - { - RegisterBounded(rpcModuleProvider, factory, _cpuCount, timeout); - } + public static void RegisterBounded( + this IRpcModuleProvider rpcModuleProvider, + ModuleFactoryBase factory, + int maxCount, + int timeout) + where T : IRpcModule + { + rpcModuleProvider.Register(new BoundedModulePool(factory, maxCount, timeout)); + } - public static void RegisterSingle( - this IRpcModuleProvider rpcModuleProvider, - T module, - bool allowExclusive = true) - where T : IRpcModule - { - rpcModuleProvider.Register(new SingletonModulePool(module, allowExclusive)); + public static void RegisterBoundedByCpuCount( + this IRpcModuleProvider rpcModuleProvider, + ModuleFactoryBase factory, + int timeout) + where T : IRpcModule + { + RegisterBounded(rpcModuleProvider, factory, _cpuCount, timeout); + } + + public static void RegisterSingle( + this IRpcModuleProvider rpcModuleProvider, + T module, + bool allowExclusive = true) + where T : IRpcModule + { + rpcModuleProvider.Register(new SingletonModulePool(module, allowExclusive)); + } } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Module/IRpcRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Module/IRpcRpcModule.cs index cb894ba444e..1f18196b4dc 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Module/IRpcRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Module/IRpcRpcModule.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections; using System.Collections.Generic; namespace Nethermind.JsonRpc.Modules.Rpc; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Module/RpcRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Module/RpcRpcModule.cs index 0742e3639ee..5a6f3104383 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Module/RpcRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Module/RpcRpcModule.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.Linq; diff --git a/src/Nethermind/Nethermind.JsonRpc/Exceptions/ModuleRentalTimeoutException.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/ModuleRentalTimeoutException.cs similarity index 92% rename from src/Nethermind/Nethermind.JsonRpc/Exceptions/ModuleRentalTimeoutException.cs rename to src/Nethermind/Nethermind.JsonRpc/Modules/ModuleRentalTimeoutException.cs index f0e6434c913..c29c30d6352 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Exceptions/ModuleRentalTimeoutException.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/ModuleRentalTimeoutException.cs @@ -3,7 +3,7 @@ using System; -namespace Nethermind.JsonRpc.Exceptions +namespace Nethermind.JsonRpc.Modules { public class ModuleRentalTimeoutException : TimeoutException { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Net/NetBridge.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Net/NetBridge.cs index 1e905f3f687..32c8b10d2b9 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Net/NetBridge.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Net/NetBridge.cs @@ -2,8 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Blockchain.Synchronization; using Nethermind.Config; using Nethermind.Core; +using Nethermind.Network; using Nethermind.Synchronization; namespace Nethermind.JsonRpc.Modules.Net diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Net/NetRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Net/NetRpcModule.cs index 89a8d4875ca..40f53a98bb6 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Net/NetRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Net/NetRpcModule.cs @@ -3,6 +3,7 @@ using System; using Nethermind.Core; +using Nethermind.Core.Attributes; using Nethermind.Logging; namespace Nethermind.JsonRpc.Modules.Net diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Parity/IParityRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Parity/IParityRpcModule.cs index d765f94ce11..7a6bb766892 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Parity/IParityRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Parity/IParityRpcModule.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Blockchain; using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.JsonRpc.Data; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Personal/PersonalRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Personal/PersonalRpcModule.cs index 0d07339f722..0d9ab9cb549 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Personal/PersonalRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Personal/PersonalRpcModule.cs @@ -6,9 +6,12 @@ using Nethermind.Core; using Nethermind.Core.Attributes; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Crypto; using Nethermind.JsonRpc.Data; using Nethermind.KeyStore; +using Nethermind.Logging; +using Nethermind.Serialization.Rlp; using Nethermind.Wallet; namespace Nethermind.JsonRpc.Modules.Personal @@ -78,7 +81,7 @@ public ResultWrapper
personal_ecRecover(byte[] message, byte[] signatur private static byte[] ToEthSignedMessage(byte[] message) { - string messageString = $"\u0019Ethereum Signed Message:\n{message.Length}{UTF8Encoding.UTF8.GetString(message)}"; + string messageString = $"\\x19Ethereum Signed Message:\\n{message.Length}{UTF8Encoding.UTF8.GetString(message)}"; message = UTF8Encoding.UTF8.GetBytes(messageString); return message; } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/IProofRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/IProofRpcModule.cs index 2f3dc352dc5..9afdef8bd92 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/IProofRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/IProofRpcModule.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Blockchain; using Nethermind.Blockchain.Find; using Nethermind.Core.Crypto; using Nethermind.JsonRpc.Data; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs index 39693f5b682..adf28739a1c 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Nethermind.Blockchain; +using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Rewards; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/ReceiptFinderExtensions.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/ReceiptFinderExtensions.cs index af8ae7a9684..bbd3b8aadeb 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/ReceiptFinderExtensions.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/ReceiptFinderExtensions.cs @@ -1,7 +1,10 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Linq; using Nethermind.Blockchain.Receipts; +using Nethermind.Core; using Nethermind.Core.Crypto; namespace Nethermind.JsonRpc.Modules diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/RpcMethodFilter.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/RpcMethodFilter.cs index 69ee6d67ae9..3c1859dfdbb 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/RpcMethodFilter.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/RpcMethodFilter.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.IO; using System.IO.Abstractions; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/RpcModuleProvider.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/RpcModuleProvider.cs index bc2e304d873..3e6e8ff890b 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/RpcModuleProvider.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/RpcModuleProvider.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.IO.Abstractions; using System.Linq; using System.Reflection; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/SearchResult.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/SearchResult.cs index 7c0b04e6343..32516aa16b0 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/SearchResult.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/SearchResult.cs @@ -1,8 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Diagnostics.CodeAnalysis; - namespace Nethermind.JsonRpc.Modules { public struct SearchResult where T : class @@ -21,7 +19,6 @@ public SearchResult(T @object) ErrorCode = 0; } - [MemberNotNullWhen(false, nameof(IsError))] public T? Object { get; set; } public string? Error { get; set; } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/ISubscribeRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/ISubscribeRpcModule.cs index 1a6c7533eec..bc84ce5a5ad 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/ISubscribeRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/ISubscribeRpcModule.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.JsonRpc.Modules.Eth; + namespace Nethermind.JsonRpc.Modules.Subscribe { [RpcModule(ModuleType.Subscribe)] diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/ISubscriptionFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/ISubscriptionFactory.cs index 93dc086dd08..5e91b6a9e27 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/ISubscriptionFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/ISubscriptionFactory.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.JsonRpc.Modules.Eth; namespace Nethermind.JsonRpc.Modules.Subscribe { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/ISubscriptionManager.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/ISubscriptionManager.cs index b7540ebf129..3fed6250db2 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/ISubscriptionManager.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/ISubscriptionManager.cs @@ -1,6 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; +using Nethermind.JsonRpc.Modules.Eth; + namespace Nethermind.JsonRpc.Modules.Subscribe { public interface ISubscriptionManager diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/LogsSubscription.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/LogsSubscription.cs index d8da821b039..2c7c58159c9 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/LogsSubscription.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/LogsSubscription.cs @@ -3,6 +3,8 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; using Nethermind.Blockchain; using Nethermind.Blockchain.Filters; using Nethermind.Blockchain.Find; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/NewHeadSubscription.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/NewHeadSubscription.cs index c49d1fe0d20..60af442e264 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/NewHeadSubscription.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/NewHeadSubscription.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Threading.Tasks; using Nethermind.Blockchain; using Nethermind.Core; using Nethermind.Core.Specs; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/NewPendingTransactionsSubscription.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/NewPendingTransactionsSubscription.cs index c2abec205d5..ff5aa929f68 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/NewPendingTransactionsSubscription.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/NewPendingTransactionsSubscription.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Threading.Tasks; using Nethermind.JsonRpc.Data; using Nethermind.JsonRpc.Modules.Eth; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SubscriptionManager.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SubscriptionManager.cs index e83e6c3b78a..9b9b3fb63a3 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SubscriptionManager.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SubscriptionManager.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using Nethermind.JsonRpc.Modules.Eth; using Nethermind.Logging; namespace Nethermind.JsonRpc.Modules.Subscribe diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SubscriptionType.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SubscriptionType.cs index d3ebc86f4ba..0d895be7fa7 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SubscriptionType.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Subscribe/SubscriptionType.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; + namespace Nethermind.JsonRpc.Modules.Subscribe { public struct SubscriptionType diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ITraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ITraceRpcModule.cs index 2f7ab05bb8d..5fafb6b8e91 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ITraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ITraceRpcModule.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using Nethermind.Blockchain.Find; using Nethermind.Core.Crypto; @@ -12,7 +13,7 @@ namespace Nethermind.JsonRpc.Modules.Trace public interface ITraceRpcModule : IRpcModule { [JsonRpcMethod(Description = "", IsImplemented = true, IsSharable = false)] - ResultWrapper trace_call(TransactionForRpc call, [JsonRpcParameter(Description = "Possible values : [\"VmTrace\", \"StateDiff\", \"Trace\", \"Rewards\", \"All\"]")] string[] traceTypes, BlockParameter? blockParameter = null); + ResultWrapper trace_call(TransactionForRpc call, string[] traceTypes, BlockParameter? blockParameter = null); [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = false)] ResultWrapper> trace_callMany(TransactionForRpcWithTraceTypes[] calls, BlockParameter? blockParameter = null); @@ -21,16 +22,16 @@ public interface ITraceRpcModule : IRpcModule IsImplemented = true, IsSharable = false, ExampleResponse = "\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{\"action\":{\"callType\":\"call\",\"from\":\"0xc451c26cc24c25e46b148ac4716804c12c34e7d2\",\"gas\":\"0x0\",\"input\":\"0x\",\"to\":\"0xb943b13292086848d8180d75c73361107920bb1a\",\"value\":\"0x0\"},\"result\":{\"gasUsed\":\"0x0\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}],\"vmTrace\":null")] - ResultWrapper trace_rawTransaction([JsonRpcParameter(ExampleValue = "[\"0xf86380843b9aca0082520894b943b13292086848d8180d75c73361107920bb1a80802ea0385656b91b8f1f5139e9ba3449b946a446c9cfe7adb91b180ddc22c33b17ac4da01fe821879d386b140fd8080dcaaa98b8c709c5025c8c4dea1334609ebac41b6c\",[\"trace\"]]")] byte[] data, [JsonRpcParameter(Description = "Possible values : [\"VmTrace\", \"StateDiff\", \"Trace\", \"Rewards\", \"All\"]")] string[] traceTypes); + ResultWrapper trace_rawTransaction([JsonRpcParameter(ExampleValue = "[\"0xf86380843b9aca0082520894b943b13292086848d8180d75c73361107920bb1a80802ea0385656b91b8f1f5139e9ba3449b946a446c9cfe7adb91b180ddc22c33b17ac4da01fe821879d386b140fd8080dcaaa98b8c709c5025c8c4dea1334609ebac41b6c\",[\"trace\"]]")] byte[] data, string[] traceTypes); [JsonRpcMethod(Description = "", IsImplemented = true, IsSharable = false, ExampleResponse = "{\"output\":\"0x\",\"stateDiff\":null,\"trace\":[{\"action\":{\"callType\":\"call\",\"from\":\"0x3c436c8ec40e0679fe64168545812ac13220f150\",\"gas\":\"0xc118\",\"input\":\"0xd46eb119\",\"to\":\"0x9e00de186f33e9fac9e28d69127f7f637b96c177\",\"value\":\"0xde0b6b3a7640000\"},\"result\":{\"gasUsed\":\"0xc118\",\"output\":\"0x\"},\"subtraces\":4,\"traceAddress\":[],\"type\":\"call\"},{\"action\":{\"callType\":\"call\",\"from\":\"0x9e00de186f33e9fac9e28d69127f7f637b96c177\",\"gas\":\"0xa965\",\"input\":\"0x40c10f190000000000000000000000009e00de186f33e9fac9e28d69127f7f637b96c1770000000000000000000000000000000000000000000000000de0b6b3a7640000\",\"to\":\"0x766cd52cb91f4d2d7ea8b4c175aff0aba3696be1\",\"value\":\"0x0\"},\"result\":{\"gasUsed\":\"0x76b8\",\"output\":\"0x\"},\"subtraces\":0,\"traceAddress\":[0],\"type\":\"call\"}, (...)}]}")] - ResultWrapper trace_replayTransaction([JsonRpcParameter(ExampleValue = "[\"0x203abf19610ce15bc509d4b341e907ff8c5a8287ae61186fd4da82146408c28c\",[\"trace\"]]")] Keccak txHash, [JsonRpcParameter(Description = "Possible values : [\"VmTrace\", \"StateDiff\", \"Trace\", \"Rewards\", \"All\"]")] string[] traceTypes); + ResultWrapper trace_replayTransaction([JsonRpcParameter(ExampleValue = "[\"0x203abf19610ce15bc509d4b341e907ff8c5a8287ae61186fd4da82146408c28c\",[\"trace\"]]")] Keccak txHash, string[] traceTypes); [JsonRpcMethod(Description = "", IsImplemented = true, IsSharable = false, ExampleResponse = "[{\"output\":\"0x0000000000000000000000000000000000000000000000000000000000000001\",\"stateDiff\":null,\"trace\":[{\"action\":{\"callType\":\"call\",\"from\":\"0x37f207b3ebda37de11ad2b6d306464e313c4841a\",\"gas\":\"0x3c36\",\"input\":\"0xa9059cbb000000000000000000000000d20d2f4c0b595abedef821a4157b0b990a37dae60000000000000000000000000000000000000000000000008ac7230489e80000\",\"to\":\"0x59a524d1f5dcbde3224fd42171795283596a8103\",\"value\":\"0x0\"},\"result\":{\"gasUsed\":\"0x3c36\",\"output\":\"0x0000000000000000000000000000000000000000000000000000000000000001\"},\"subtraces\":0,\"traceAddress\":[],\"type\":\"call\"}],\"transactionHash\":\"0x17dc0fef36bb997c79ee2a0a126d059227000a2d47c9bbd1f49b5902a4e7385a\",\"vmTrace\":null}, (...)]")] - ResultWrapper> trace_replayBlockTransactions([JsonRpcParameter(ExampleValue = "[\"0x88df42\",[\"trace\"]]")] BlockParameter blockParameter, [JsonRpcParameter(Description = "Possible values : [\"VmTrace\", \"StateDiff\", \"Trace\", \"Rewards\", \"All\"]")] string[] traceTypes); + ResultWrapper> trace_replayBlockTransactions([JsonRpcParameter(ExampleValue = "[\"0x88df42\",[\"trace\"]]")] BlockParameter blockParameter, string[] traceTypes); [JsonRpcMethod(Description = "", IsImplemented = true, IsSharable = false)] ResultWrapper> trace_filter(TraceFilterForRpc traceFilterForRpc); @@ -47,6 +48,6 @@ public interface ITraceRpcModule : IRpcModule [JsonRpcMethod(Description = "", IsImplemented = true, IsSharable = false, ExampleResponse = "[{\"action\":{\"callType\":\"call\",\"from\":\"0x3c436c8ec40e0679fe64168545812ac13220f150\",\"gas\":\"0xc118\",\"input\":\"0xd46eb119\",\"to\":\"0x9e00de186f33e9fac9e28d69127f7f637b96c177\",\"value\":\"0xde0b6b3a7640000\"},\"blockHash\":\"0xf40b4c9faaeaf116a50380ce3795297bc02068b062f1797cd507875347c3372e\",\"blockNumber\":8970132,\"result\":{\"gasUsed\":\"0xc118\",\"output\":\"0x\"},\"subtraces\":4,\"traceAddress\":[],\"transactionHash\":\"0x203abf19610ce15bc509d4b341e907ff8c5a8287ae61186fd4da82146408c28c\",\"transactionPosition\":9,\"type\":\"call\"},(...)]")] - ResultWrapper> trace_transaction([JsonRpcParameter(ExampleValue = "\"0x203abf19610ce15bc509d4b341e907ff8c5a8287ae61186fd4da82146408c28c\"")] Keccak txHash); + ResultWrapper> trace_transaction([JsonRpcParameter(ExampleValue = "[\"0x203abf19610ce15bc509d4b341e907ff8c5a8287ae61186fd4da82146408c28c\"]")] Keccak txHash); } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ParityVmTraceConverter.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ParityVmTraceConverter.cs index a0a2f3296c6..32e953d1f48 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ParityVmTraceConverter.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ParityVmTraceConverter.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Core.Extensions; using Nethermind.Evm.Tracing.ParityStyle; using Newtonsoft.Json; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceFilterForRpc.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceFilterForRpc.cs index 6b2d397c2cc..892a55ba887 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceFilterForRpc.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceFilterForRpc.cs @@ -3,6 +3,7 @@ using Nethermind.Blockchain.Find; using Nethermind.Core; +using Nethermind.Evm.Tracing; using Newtonsoft.Json; namespace Nethermind.JsonRpc.Modules.Trace diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index b0f7c8872ff..92799bf6d51 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Threading; using FastEnumUtility; @@ -129,8 +130,8 @@ private SearchResult SearchBlockHeaderForTraceCall(BlockParameter b header.GasLimit, header.Timestamp + 1, header.ExtraData, - header.BlobGasUsed, - header.ExcessBlobGas); + header.DataGasUsed, + header.ExcessDataGas); header.TotalDifficulty = 2 * header.Difficulty; header.BaseFeePerGas = baseFee; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TxTraceFilter.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TxTraceFilter.cs index 471c7619fd1..379dd01cd62 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TxTraceFilter.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TxTraceFilter.cs @@ -4,7 +4,10 @@ using System.Collections.Generic; using System.Linq; using Nethermind.Core; +using Nethermind.Core.Specs; +using Nethermind.Crypto; using Nethermind.Evm.Tracing.ParityStyle; +using Nethermind.Logging; namespace Nethermind.JsonRpc.Modules.Trace { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/TxPool/TxPoolRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/TxPool/TxPoolRpcModule.cs index da0a5893561..ad977e79e73 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/TxPool/TxPoolRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/TxPool/TxPoolRpcModule.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Blockchain.Find; using Nethermind.Logging; using Nethermind.TxPool; diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Witness/WitnessRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Witness/WitnessRpcModule.cs index bfdc18b82b6..5acc6cfc4e4 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Witness/WitnessRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Witness/WitnessRpcModule.cs @@ -5,6 +5,7 @@ using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Crypto; using Nethermind.State; namespace Nethermind.JsonRpc.Modules.Witness diff --git a/src/Nethermind/Nethermind.JsonRpc/NullJsonRpcLocalStats.cs b/src/Nethermind/Nethermind.JsonRpc/NullJsonRpcLocalStats.cs deleted file mode 100644 index 20a298e9e54..00000000000 --- a/src/Nethermind/Nethermind.JsonRpc/NullJsonRpcLocalStats.cs +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Threading.Tasks; - -namespace Nethermind.JsonRpc; - -public class NullJsonRpcLocalStats : IJsonRpcLocalStats -{ - - public Task ReportCall(RpcReport report, long elapsedMicroseconds = 0, long? size = null) - { - return Task.CompletedTask; - } - public MethodStats GetMethodStats(string methodName) - { - return new MethodStats(); - } -} diff --git a/src/Nethermind/Nethermind.JsonRpc/ResultWrapper.cs b/src/Nethermind/Nethermind.JsonRpc/ResultWrapper.cs index a3f4ae540d7..968bd13b0c1 100644 --- a/src/Nethermind/Nethermind.JsonRpc/ResultWrapper.cs +++ b/src/Nethermind/Nethermind.JsonRpc/ResultWrapper.cs @@ -11,41 +11,73 @@ namespace Nethermind.JsonRpc { public class ResultWrapper : IResultWrapper { - object IResultWrapper.Data => Data; - public T Data { get; init; } - public Result Result { get; init; } = Result.Success; - public int ErrorCode { get; init; } - public bool IsTemporary { get; init; } + public T Data { get; set; } + public Result Result { get; set; } = null!; + public int ErrorCode { get; set; } private ResultWrapper() { } - public static ResultWrapper Fail(SearchResult searchResult, bool isTemporary = false) where TSearch : class => - new() { Result = Result.Fail(searchResult.Error!), ErrorCode = searchResult.ErrorCode, IsTemporary = isTemporary }; + public static ResultWrapper Fail(SearchResult searchResult) where TSearch : class + { + return new() { Result = Result.Fail(searchResult.Error), ErrorCode = searchResult.ErrorCode }; + } + + public static ResultWrapper Fail(string error) + { + return new() { Result = Result.Fail(error), ErrorCode = ErrorCodes.InternalError }; + } + + public static ResultWrapper Fail(Exception e) + { + return new() { Result = Result.Fail(e.ToString()), ErrorCode = ErrorCodes.InternalError }; + } + + public static ResultWrapper Fail(string error, int errorCode, T outputData) + { + return new() { Result = Result.Fail(error), ErrorCode = errorCode, Data = outputData }; + } + + public static ResultWrapper Fail(string error, int errorCode) + { + return new() { Result = Result.Fail(error), ErrorCode = errorCode }; + } - public static ResultWrapper Fail(string error) => - new() { Result = Result.Fail(error), ErrorCode = ErrorCodes.InternalError }; + public static ResultWrapper Fail(string error, T data) + { + return new() { Data = data, Result = Result.Fail(error) }; + } - public static ResultWrapper Fail(Exception e) => - new() { Result = Result.Fail(e.ToString()), ErrorCode = ErrorCodes.InternalError }; + public static ResultWrapper Success(T data) + { + return new() { Data = data, Result = Result.Success }; + } - public static ResultWrapper Fail(string error, int errorCode, T outputData) => - new() { Result = Result.Fail(error), ErrorCode = errorCode, Data = outputData }; + public Result GetResult() + { + return Result; + } - public static ResultWrapper Fail(string error, int errorCode, bool isTemporary = false) => - new() { Result = Result.Fail(error), ErrorCode = errorCode, IsTemporary = isTemporary }; + public object? GetData() + { + return Data; + } - public static ResultWrapper Fail(string error, T data) => - new() { Data = data, Result = Result.Fail(error) }; + public int GetErrorCode() + { + return ErrorCode; + } - public static ResultWrapper Success(T data) => - new() { Data = data, Result = Result.Success }; + public static ResultWrapper From(RpcResult? rpcResult) + { + if (rpcResult is null) + { + return Fail("Missing result."); + } - public static ResultWrapper From(RpcResult? rpcResult) => - rpcResult is null - ? Fail("Missing result.") - : rpcResult.IsValid ? Success(rpcResult.Result) : Fail(rpcResult.Error.Message); + return rpcResult.IsValid ? Success(rpcResult.Result) : Fail(rpcResult.Error.Message); + } public static implicit operator Task>(ResultWrapper resultWrapper) => Task.FromResult(resultWrapper); } diff --git a/src/Nethermind/Nethermind.JsonRpc/WebSockets/JsonRpcSocketsClient.cs b/src/Nethermind/Nethermind.JsonRpc/WebSockets/JsonRpcSocketsClient.cs index d6451445bfd..792885a040b 100644 --- a/src/Nethermind/Nethermind.JsonRpc/WebSockets/JsonRpcSocketsClient.cs +++ b/src/Nethermind/Nethermind.JsonRpc/WebSockets/JsonRpcSocketsClient.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; @@ -70,12 +71,12 @@ public override async Task ProcessAsync(ArraySegment data) if (result.IsCollection) { long handlingTimeMicroseconds = stopwatch.ElapsedMicroseconds(); - _ = _jsonRpcLocalStats.ReportCall(new RpcReport("# collection serialization #", handlingTimeMicroseconds, true), handlingTimeMicroseconds, singleResponseSize); + _jsonRpcLocalStats.ReportCall(new RpcReport("# collection serialization #", handlingTimeMicroseconds, true), handlingTimeMicroseconds, singleResponseSize); } else { long handlingTimeMicroseconds = stopwatch.ElapsedMicroseconds(); - _ = _jsonRpcLocalStats.ReportCall(result.Report!.Value, handlingTimeMicroseconds, singleResponseSize); + _jsonRpcLocalStats.ReportCall(result.Report!.Value, handlingTimeMicroseconds, singleResponseSize); } stopwatch.Restart(); } @@ -111,14 +112,11 @@ private void IncrementBytesSentMetric(int size) public virtual async Task SendJsonRpcResult(JsonRpcResult result) { - await using Stream stream = _handler.SendUsingStream(); - await using Stream buffered = new BufferedStream(stream); - await using CounterStream resultData = new CounterStream(buffered); - if (result.IsCollection) { + int singleResponseSize = 1; bool isFirst = true; - await resultData.WriteAsync(_jsonOpeningBracket); + await _handler.SendRawAsync(_jsonOpeningBracket, false); JsonRpcBatchResultAsyncEnumerator enumerator = result.BatchedResponses!.GetAsyncEnumerator(CancellationToken.None); try { @@ -129,14 +127,16 @@ public virtual async Task SendJsonRpcResult(JsonRpcResult result) { if (!isFirst) { - await resultData.WriteAsync(_jsonComma); + await _handler.SendRawAsync(_jsonComma, false); + singleResponseSize += 1; } + isFirst = false; - SendJsonRpcResultEntry(resultData, entry); - _ = _jsonRpcLocalStats.ReportCall(entry.Report); + singleResponseSize += await SendJsonRpcResultEntry(entry, false); + _jsonRpcLocalStats.ReportCall(entry.Report); // We reached the limit and don't want to responded to more request in the batch - if (!_jsonRpcContext.IsAuthenticated && resultData.WrittenBytes > _maxBatchResponseBodySize) + if (!_jsonRpcContext.IsAuthenticated && singleResponseSize > _maxBatchResponseBodySize) { enumerator.IsStopped = true; } @@ -148,37 +148,49 @@ public virtual async Task SendJsonRpcResult(JsonRpcResult result) await enumerator.DisposeAsync(); } - await resultData.WriteAsync(_jsonClosingBracket); + await _handler.SendRawAsync(_jsonClosingBracket, true); + singleResponseSize += 1; + + return singleResponseSize; } else { - SendJsonRpcResultEntry(resultData, result.SingleResponse!.Value); + return await SendJsonRpcResultEntry(result.SingleResponse!.Value); } - - // ? What if we write more than int.MaxValue. - // Result could be negative - return (int)resultData.WrittenBytes; } - private void SendJsonRpcResultEntry(Stream dest, JsonRpcResult.Entry result) + private async Task SendJsonRpcResultEntry(JsonRpcResult.Entry result, bool endOfMessage = true) { - using JsonRpcResult.Entry entry = result; - - try + void SerializeTimeoutException(MemoryStream stream) { - _jsonSerializer.SerializeWaitForEnumeration(dest, result.Response); + JsonRpcErrorResponse error = _jsonRpcService.GetErrorResponse(ErrorCodes.Timeout, "Request was canceled due to enabled timeout."); + _jsonSerializer.Serialize(stream, error); } - catch (Exception e) when (e is OperationCanceledException || e.InnerException is OperationCanceledException) + + using (result) { - _jsonSerializer.Serialize( - dest, - _jsonRpcService.GetErrorResponse( - ErrorCodes.Timeout, - "Request was canceled due to enabled timeout.", - result.Response.Id, - result.Response.MethodName - ) - ); + await using MemoryStream resultData = new(); + + try + { + _jsonSerializer.Serialize(resultData, result.Response); + } + catch (Exception e) when (e.InnerException is OperationCanceledException) + { + SerializeTimeoutException(resultData); + } + catch (OperationCanceledException) + { + SerializeTimeoutException(resultData); + } + + if (resultData.TryGetBuffer(out ArraySegment data)) + { + await _handler.SendRawAsync(data, endOfMessage); + return data.Count; + } + + return (int)resultData.Length; } } } diff --git a/src/Nethermind/Nethermind.JsonRpc/WebSockets/JsonRpcWebSocketsModule.cs b/src/Nethermind/Nethermind.JsonRpc/WebSockets/JsonRpcWebSocketsModule.cs index 2c56b1696f6..ec88f1938f7 100644 --- a/src/Nethermind/Nethermind.JsonRpc/WebSockets/JsonRpcWebSocketsModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/WebSockets/JsonRpcWebSocketsModule.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Net.WebSockets; using System.Threading.Tasks; +using System.Linq; using Microsoft.AspNetCore.Http; using Nethermind.Core.Authentication; using Nethermind.JsonRpc.Modules; diff --git a/src/Nethermind/Ethereum.KeyStore.Test/KeyStoreJsonTests.cs b/src/Nethermind/Nethermind.KeyStore.Test/KeyStoreJsonTests.cs similarity index 98% rename from src/Nethermind/Ethereum.KeyStore.Test/KeyStoreJsonTests.cs rename to src/Nethermind/Nethermind.KeyStore.Test/KeyStoreJsonTests.cs index d40a1079ed3..ac140c8a621 100644 --- a/src/Nethermind/Ethereum.KeyStore.Test/KeyStoreJsonTests.cs +++ b/src/Nethermind/Nethermind.KeyStore.Test/KeyStoreJsonTests.cs @@ -3,18 +3,18 @@ using System; using System.IO; +using System.Linq; using System.Security; using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Crypto; -using Nethermind.KeyStore; using Nethermind.KeyStore.Config; using Nethermind.Logging; using Nethermind.Serialization.Json; using Newtonsoft.Json; using NUnit.Framework; -namespace Ethereum.KeyStore.Test +namespace Nethermind.KeyStore.Test { [Parallelizable(ParallelScope.Self)] [TestFixture] @@ -35,7 +35,9 @@ public void Initialize() _keyStoreDir = _config.KeyStoreDirectory; if (!Directory.Exists(_keyStoreDir)) + { Directory.CreateDirectory(_keyStoreDir); + } ILogManager logManager = LimboLogs.Instance; _serializer = new EthereumJsonSerializer(); diff --git a/src/Nethermind/Nethermind.KeyStore.Test/KeyStorePasswordProviderTests.cs b/src/Nethermind/Nethermind.KeyStore.Test/KeyStorePasswordProviderTests.cs index 0f57ad1111e..9801c5360e4 100644 --- a/src/Nethermind/Nethermind.KeyStore.Test/KeyStorePasswordProviderTests.cs +++ b/src/Nethermind/Nethermind.KeyStore.Test/KeyStorePasswordProviderTests.cs @@ -11,6 +11,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.KeyStore.Config; +using Nethermind.Logging; using NSubstitute; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.KeyStore.Test/KeyStoreTests.cs b/src/Nethermind/Nethermind.KeyStore.Test/KeyStoreTests.cs index 5abdfcff083..d68966bb79e 100644 --- a/src/Nethermind/Nethermind.KeyStore.Test/KeyStoreTests.cs +++ b/src/Nethermind/Nethermind.KeyStore.Test/KeyStoreTests.cs @@ -5,9 +5,11 @@ using System.IO; using System.Linq; using System.Security; +using System.Text; using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Extensions; +using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.KeyStore.Config; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.KeyStore/FileKeyStore.cs b/src/Nethermind/Nethermind.KeyStore/FileKeyStore.cs index beef4996d15..7da08b3b09d 100644 --- a/src/Nethermind/Nethermind.KeyStore/FileKeyStore.cs +++ b/src/Nethermind/Nethermind.KeyStore/FileKeyStore.cs @@ -297,7 +297,7 @@ public Result StoreKey(PrivateKey key, SecureString password) { var files = Directory.GetFiles(_keyStoreIOSettingsProvider.StoreDirectory, "UTC--*--*"); var addresses = files.Select(Path.GetFileName).Select(fn => fn.Split("--").LastOrDefault()).Where(x => Address.IsValidAddress(x, false)).Select(x => new Address(x)).ToArray(); - return (addresses, Result.Success); + return (addresses, new Result { ResultType = ResultType.Success }); } catch (Exception e) { @@ -332,7 +332,7 @@ private Result PersistKey(Address address, KeyStoreItem keyData) var storeDirectory = _keyStoreIOSettingsProvider.StoreDirectory; var path = Path.Combine(storeDirectory, keyFileName); File.WriteAllText(path, serializedKey, _keyStoreEncoding); - return Result.Success; + return new Result { ResultType = ResultType.Success }; } catch (Exception e) { @@ -358,7 +358,7 @@ public Result DeleteKey(Address address) File.Delete(file); } - return Result.Success; + return new Result { ResultType = ResultType.Success }; } catch (Exception e) { diff --git a/src/Nethermind/Nethermind.KeyStore/PrivateKeyStoreIOSettingsProvider.cs b/src/Nethermind/Nethermind.KeyStore/PrivateKeyStoreIOSettingsProvider.cs index 62a1bfc7644..689b24f1b88 100644 --- a/src/Nethermind/Nethermind.KeyStore/PrivateKeyStoreIOSettingsProvider.cs +++ b/src/Nethermind/Nethermind.KeyStore/PrivateKeyStoreIOSettingsProvider.cs @@ -2,8 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.IO; using Nethermind.Core; using Nethermind.KeyStore.Config; +using Nethermind.Logging; namespace Nethermind.KeyStore { diff --git a/src/Nethermind/Nethermind.Logging.NLog.Test/NLogManagerTests.cs b/src/Nethermind/Nethermind.Logging.NLog.Test/NLogManagerTests.cs index 0f7bdc7a414..2f2ad484411 100644 --- a/src/Nethermind/Nethermind.Logging.NLog.Test/NLogManagerTests.cs +++ b/src/Nethermind/Nethermind.Logging.NLog.Test/NLogManagerTests.cs @@ -1,11 +1,13 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.Linq; using FluentAssertions; using NLog; using NLog.Config; +using NLog.Targets; using NUnit.Framework; namespace Nethermind.Logging.NLog.Test diff --git a/src/Nethermind/Nethermind.Logging.NLog/NLogLogger.cs b/src/Nethermind/Nethermind.Logging.NLog/NLogLogger.cs index 2e5685766a3..ffc65550692 100644 --- a/src/Nethermind/Nethermind.Logging.NLog/NLogLogger.cs +++ b/src/Nethermind/Nethermind.Logging.NLog/NLogLogger.cs @@ -2,7 +2,11 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; using NLog; +using NLog.Targets; namespace Nethermind.Logging.NLog { @@ -41,32 +45,27 @@ public NLogLogger(string loggerName = null) public void Info(string text) { - if (IsInfo) - _logger.Info(text); + _logger.Info(text); } public void Warn(string text) { - if (IsWarn) - _logger.Warn(text); + _logger.Warn(text); } public void Debug(string text) { - if (IsDebug) - _logger.Debug(text); + _logger.Debug(text); } public void Trace(string text) { - if (IsTrace) - _logger.Trace(text); + _logger.Trace(text); } public void Error(string text, Exception ex = null) { - if (IsError) - _logger.Error(ex, text); + _logger.Error(ex, text); } } } diff --git a/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs b/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs index 20ad3867675..38ca6eff602 100644 --- a/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs +++ b/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text.RegularExpressions; @@ -14,20 +15,11 @@ namespace Nethermind.Logging.NLog { - public class NLogManager : ILogManager, IDisposable + public class NLogManager : ILogManager { private const string DefaultFileTargetName = "file-async_wrapped"; - private const string DefaultFolder = "logs"; public NLogManager(string logFileName, string logDirectory = null, string logRules = null) - { - Setup(logFileName, logDirectory, logRules); - // Required since 'NLog.config' could change during runtime, we need to re-apply the configuration - _logManagerOnConfigurationChanged = (sender, args) => Setup(logFileName, logDirectory, logRules); - LogManager.ConfigurationChanged += _logManagerOnConfigurationChanged; - } - - private void Setup(string logFileName, string logDirectory = null, string logRules = null) { logDirectory = SetupLogDirectory(logDirectory); SetupLogFile(logFileName, logDirectory); @@ -48,7 +40,7 @@ private static void SetupLogFile(string logFileName, string logDirectory) private static string SetupLogDirectory(string logDirectory) { - logDirectory = (string.IsNullOrEmpty(logDirectory) ? DefaultFolder : logDirectory).GetApplicationResourcePath(); + logDirectory = (string.IsNullOrEmpty(logDirectory) ? "logs" : logDirectory).GetApplicationResourcePath(); if (!Directory.Exists(logDirectory)) { Directory.CreateDirectory(logDirectory); @@ -58,7 +50,6 @@ private static string SetupLogDirectory(string logDirectory) } private ConcurrentDictionary _loggers = new(); - private EventHandler _logManagerOnConfigurationChanged; private NLogLogger BuildLogger(Type type) => new(type); @@ -157,10 +148,5 @@ public static void Shutdown() { LogManager.Shutdown(); } - - public void Dispose() - { - LogManager.ConfigurationChanged -= _logManagerOnConfigurationChanged; - } } } diff --git a/src/Nethermind/Nethermind.Logging/ConsoleAsyncLogger.cs b/src/Nethermind/Nethermind.Logging/ConsoleAsyncLogger.cs index ac6226ecbc1..4323c6829ee 100644 --- a/src/Nethermind/Nethermind.Logging/ConsoleAsyncLogger.cs +++ b/src/Nethermind/Nethermind.Logging/ConsoleAsyncLogger.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Concurrent; +using System.Threading; using System.Threading.Tasks; namespace Nethermind.Logging diff --git a/src/Nethermind/Nethermind.Merge.AuRa.Test/AssertionsSetup.cs b/src/Nethermind/Nethermind.Merge.AuRa.Test/AssertionsSetup.cs index 51b2b167fec..4ea6730bd46 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa.Test/AssertionsSetup.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa.Test/AssertionsSetup.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using NUnit.Framework; +using NUnit.Framework.Internal; using FluentAssertions; using Nethermind.Core; diff --git a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs index e640c01301d..91d9c6d6c87 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs @@ -9,10 +9,8 @@ using Nethermind.Consensus; using Nethermind.Consensus.AuRa; using Nethermind.Consensus.AuRa.Config; -using Nethermind.Consensus.AuRa.InitializationSteps; using Nethermind.Consensus.AuRa.Validators; using Nethermind.Consensus.Comparers; -using Nethermind.Consensus.Processing; using Nethermind.Consensus.Producers; using Nethermind.Consensus.Rewards; using Nethermind.Core; @@ -22,7 +20,6 @@ using Nethermind.Facade.Eth; using Nethermind.Int256; using Nethermind.Logging; -using Nethermind.Merge.AuRa.Withdrawals; using Nethermind.Merge.Plugin; using Nethermind.Merge.Plugin.BlockProduction; using Nethermind.Merge.Plugin.Handlers; @@ -30,7 +27,6 @@ using Nethermind.Serialization.Json; using Nethermind.Specs; using Nethermind.Specs.ChainSpecStyle; -using Nethermind.State; using Nethermind.Synchronization.ParallelSync; using NSubstitute; using NUnit.Framework; @@ -55,11 +51,12 @@ string BlockHash ) input) => base.forkchoiceUpdatedV2_should_validate_withdrawals(input); + [Ignore("engine_newPayloadV2 fails")] [TestCase( "0xe168b70ac8a6f7d90734010030801fbb2dcce03a657155c4024b36ba8d1e3926", "0x3e604e45a9a74b66a7e03f828cc2597f0cb5f5e7dc50c9211be3a62fbcd6396d", "0xdbd87b98a6be7d4e3f11ff8500c38a0736d9a5e7a47b5cb25628d37187a98cb9", - "0x80ac487e132512b1")] + "0x78ecfec08729d895")] public override Task Should_process_block_as_expected_V2(string latestValidHash, string blockHash, string stateRoot, string payloadId) => base.Should_process_block_as_expected_V2(latestValidHash, blockHash, stateRoot, payloadId); @@ -80,64 +77,50 @@ public override Task processing_block_should_serialize_valid_responses(string bl public override Task forkchoiceUpdatedV1_should_communicate_with_boost_relay_through_http(string blockHash, string parentHash) => base.forkchoiceUpdatedV1_should_communicate_with_boost_relay_through_http(blockHash, parentHash); - [Ignore("Withdrawals are not withdrawan due to lack of Aura contract in tests")] + [Ignore("engine_newPayloadV2 fails")] public override Task Can_apply_withdrawals_correctly((Withdrawal[][] Withdrawals, (Address Account, UInt256 BalanceIncrease)[] ExpectedAccountIncrease) input) { return base.Can_apply_withdrawals_correctly(input); } - class MergeAuRaTestBlockchain : MergeTestBlockchain + [Ignore("engine_newPayloadV2 fails")] + public override Task Empty_block_is_valid_with_withdrawals_V2() + { + return base.Empty_block_is_valid_with_withdrawals_V2(); + } + + [Ignore("engine_newPayloadV2 fails")] + public override Task Should_handle_withdrawals_transition_when_Shanghai_fork_activated() + { + return base.Should_handle_withdrawals_transition_when_Shanghai_fork_activated(); + } + + [Ignore("engine_newPayloadV2 fails")] + public override Task getPayloadBodiesByHashV1_should_return_payload_bodies_in_order_of_request_block_hashes_and_null_for_unknown_hashes(IList withdrawals) + { + return base.getPayloadBodiesByHashV1_should_return_payload_bodies_in_order_of_request_block_hashes_and_null_for_unknown_hashes(withdrawals); + } + + [Ignore("engine_newPayloadV2 fails")] + public override Task getPayloadBodiesByRangeV1_should_return_canonical(IList withdrawals) + { + return base.getPayloadBodiesByRangeV1_should_return_canonical(withdrawals); + } + + [Ignore("engine_newPayloadV2 fails")] + public override Task getPayloadBodiesByRangeV1_should_return_payload_bodies_in_order_of_request_range_and_null_for_unknown_indexes(IList withdrawals) { - private AuRaNethermindApi? _api; + return base.getPayloadBodiesByRangeV1_should_return_payload_bodies_in_order_of_request_range_and_null_for_unknown_indexes(withdrawals); + } + class MergeAuRaTestBlockchain : MergeTestBlockchain + { public MergeAuRaTestBlockchain(IMergeConfig? mergeConfig = null, IPayloadPreparationService? mockedPayloadPreparationService = null) : base(mergeConfig, mockedPayloadPreparationService) { SealEngineType = Core.SealEngineType.AuRa; } - protected override IBlockProcessor CreateBlockProcessor() - { - _api = new(new ConfigProvider(), new EthereumJsonSerializer(), LogManager, - new ChainSpec - { - AuRa = new() - { - WithdrawalContractAddress = new("0xbabe2bed00000000000000000000000000000003") - }, - Parameters = new() - }) - { - BlockTree = BlockTree, - DbProvider = DbProvider, - ReadOnlyTrieStore = ReadOnlyTrieStore, - SpecProvider = SpecProvider, - TransactionComparerProvider = TransactionComparerProvider, - TxPool = TxPool - }; - - WithdrawalContractFactory withdrawalContractFactory = new(_api.ChainSpec!.AuRa, _api.AbiEncoder); - WithdrawalProcessor = new AuraWithdrawalProcessor( - withdrawalContractFactory.Create(TxProcessor), - LogManager - ); - - BlockValidator = CreateBlockValidator(); - IBlockProcessor processor = new BlockProcessor( - SpecProvider, - BlockValidator, - NoBlockRewards.Instance, - new BlockProcessor.BlockValidationTransactionsExecutor(TxProcessor, State), - State, - ReceiptStorage, - NullWitnessCollector.Instance, - LogManager, - WithdrawalProcessor); - - return new TestBlockProcessorInterceptor(processor, _blockProcessingThrottle); - } - - protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolTxSource, ISealer sealer, ITransactionComparerProvider transactionComparerProvider) { SealEngine = new MergeSealEngine(SealEngine, PoSSwitcher, SealValidator!, LogManager); @@ -154,7 +137,23 @@ protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolT targetAdjustedGasLimitCalculator); AuRaMergeBlockProducerEnvFactory blockProducerEnvFactory = new( - _api!, + new(new ConfigProvider(), new EthereumJsonSerializer(), LogManager, + new ChainSpec + { + AuRa = new() + { + WithdrawalContractAddress = new("0xbabe2bed00000000000000000000000000000003") + }, + Parameters = new() + }) + { + BlockTree = BlockTree, + DbProvider = DbProvider, + ReadOnlyTrieStore = ReadOnlyTrieStore, + SpecProvider = SpecProvider, + TransactionComparerProvider = TransactionComparerProvider, + TxPool = TxPool + }, new AuRaConfig(), new DisposableStack(), DbProvider, @@ -208,3 +207,4 @@ protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolT } } } + diff --git a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs index 9f97c9e2574..9e675bab24c 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProcessor.cs @@ -3,6 +3,7 @@ using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; +using Nethermind.Consensus; using Nethermind.Consensus.AuRa; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Rewards; diff --git a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProducerEnvFactory.cs b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProducerEnvFactory.cs index b8e311bd306..a16c283a4ec 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProducerEnvFactory.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProducerEnvFactory.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; using Nethermind.Config; @@ -86,7 +87,8 @@ protected override BlockProcessor CreateBlockProcessor( withdrawalContractFactory.Create(readOnlyTxProcessingEnv.TransactionProcessor), logManager ) - )); + ) + ); } protected override TxPoolTxSource CreateTxPoolTxSource( diff --git a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergePlugin.cs b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergePlugin.cs index 2ede357293e..0df6c268432 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergePlugin.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergePlugin.cs @@ -4,13 +4,18 @@ using System.Threading.Tasks; using Nethermind.Api; using Nethermind.Api.Extensions; +using Nethermind.Blockchain; using Nethermind.Config; using Nethermind.Consensus; using Nethermind.Consensus.AuRa.Config; using Nethermind.Consensus.AuRa.InitializationSteps; using Nethermind.Consensus.AuRa.Transactions; +using Nethermind.Consensus.Processing; +using Nethermind.Consensus.Transactions; +using Nethermind.Db; using Nethermind.Merge.Plugin; using Nethermind.Merge.Plugin.BlockProduction; +using Nethermind.State; namespace Nethermind.Merge.AuRa { diff --git a/src/Nethermind/Nethermind.Merge.AuRa/InitializationSteps/InitializeBlockchainAuRaMerge.cs b/src/Nethermind/Nethermind.Merge.AuRa/InitializationSteps/InitializeBlockchainAuRaMerge.cs index 7bdf6ee9311..d599ae32a96 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa/InitializationSteps/InitializeBlockchainAuRaMerge.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa/InitializationSteps/InitializeBlockchainAuRaMerge.cs @@ -1,10 +1,15 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; +using Nethermind; using Nethermind.Consensus.AuRa; using Nethermind.Consensus.AuRa.InitializationSteps; +using Nethermind.Consensus.AuRa.Transactions; +using Nethermind.Consensus.AuRa.Validators; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Transactions; +using Nethermind.Core; using Nethermind.Init.Steps; using Nethermind.Merge.AuRa.Withdrawals; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/AssertionsSetup.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/AssertionsSetup.cs index 51b2b167fec..4ea6730bd46 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/AssertionsSetup.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/AssertionsSetup.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using NUnit.Framework; +using NUnit.Framework.Internal; using FluentAssertions; using Nethermind.Core; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/BlockTreeTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/BlockTreeTests.cs index 8d4f289ed71..d38e7ae15fd 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/BlockTreeTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/BlockTreeTests.cs @@ -11,7 +11,6 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; -using Nethermind.Crypto; using Nethermind.Db; using Nethermind.Db.Blooms; using Nethermind.Int256; @@ -199,7 +198,7 @@ public void Can_start_insert_pivot_block_with_correct_pointers() (BlockTree notSyncedTree, BlockTree syncedTree) = BuildBlockTrees(10, 20); Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None); BlockTreeInsertHeaderOptions insertHeaderOption = BlockTreeInsertHeaderOptions.BeaconBlockInsert; - AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock!, BlockTreeInsertBlockOptions.SaveHeader, insertHeaderOption); + AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock, BlockTreeInsertBlockOptions.SaveHeader, insertHeaderOption); Assert.That(insertResult, Is.EqualTo(AddBlockResult.Added)); Assert.That(notSyncedTree.BestKnownNumber, Is.EqualTo(9)); @@ -218,7 +217,7 @@ public void Can_insert_beacon_headers() Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None); BlockTreeInsertHeaderOptions headerOptions = BlockTreeInsertHeaderOptions.BeaconBlockInsert; - AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock!, BlockTreeInsertBlockOptions.SaveHeader, headerOptions); + AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock, BlockTreeInsertBlockOptions.SaveHeader, headerOptions); for (int i = 13; i > 9; --i) { BlockHeader? beaconHeader = syncedTree.FindHeader(i, BlockTreeLookupOptions.None); @@ -232,7 +231,7 @@ public void Can_fill_beacon_headers_gap() { (BlockTree notSyncedTree, BlockTree syncedTree) = BuildBlockTrees(10, 20); - Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None)!; + Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None); BlockTreeInsertHeaderOptions headerOptions = BlockTreeInsertHeaderOptions.BeaconBlockInsert; AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock, BlockTreeInsertBlockOptions.SaveHeader, headerOptions); @@ -258,16 +257,16 @@ public void FindHeader_will_not_change_total_difficulty_when_it_is_zero() { (BlockTree notSyncedTree, BlockTree syncedTree) = BuildBlockTrees(10, 20); - Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None)!; + Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None); BlockTreeInsertHeaderOptions headerOptions = BlockTreeInsertHeaderOptions.BeaconBlockInsert; AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock, BlockTreeInsertBlockOptions.SaveHeader, headerOptions); BlockHeader? beaconHeader = syncedTree.FindHeader(13, BlockTreeLookupOptions.None); - beaconHeader!.TotalDifficulty = null; + beaconHeader.TotalDifficulty = null; AddBlockResult insertOutcome = notSyncedTree.Insert(beaconHeader!, headerOptions); Assert.That(insertResult, Is.EqualTo(insertOutcome)); BlockHeader? headerToCheck = notSyncedTree.FindHeader(beaconHeader.Hash, BlockTreeLookupOptions.None); - Assert.IsNull(headerToCheck!.TotalDifficulty); + Assert.IsNull(headerToCheck.TotalDifficulty); } [Test] @@ -275,16 +274,16 @@ public void FindBlock_will_not_change_total_difficulty_when_it_is_zero() { (BlockTree notSyncedTree, BlockTree syncedTree) = BuildBlockTrees(10, 20); - Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None)!; + Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None); BlockTreeInsertHeaderOptions headerOptions = BlockTreeInsertHeaderOptions.BeaconBlockInsert; AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock, BlockTreeInsertBlockOptions.SaveHeader, headerOptions); Block? beaconBlock2 = syncedTree.FindBlock(13, BlockTreeLookupOptions.None); - beaconBlock2!.Header.TotalDifficulty = null; + beaconBlock2.Header.TotalDifficulty = null; AddBlockResult insertOutcome = notSyncedTree.Insert(beaconBlock2, BlockTreeInsertBlockOptions.None); Assert.That(insertResult, Is.EqualTo(insertOutcome)); Block? blockToCheck = notSyncedTree.FindBlock(beaconBlock2.Hash, BlockTreeLookupOptions.None); - Assert.IsNull(blockToCheck!.TotalDifficulty); + Assert.IsNull(blockToCheck.TotalDifficulty); } @@ -294,7 +293,7 @@ public class ScenarioBuilder { private BlockTreeBuilder? _syncedTreeBuilder; private IChainLevelHelper? _chainLevelHelper; - private IBeaconPivot? _beaconPivot; + private IBeaconPivot _beaconPivot; public ScenarioBuilder WithBlockTrees( int notSyncedTreeSize, @@ -362,7 +361,7 @@ public ScenarioBuilder InsertBeaconPivot(long num) public ScenarioBuilder SetProcessDestination(long num) { - _beaconPivot!.ProcessDestination = SyncedTree.FindHeader(num, BlockTreeLookupOptions.None); + _beaconPivot.ProcessDestination = SyncedTree.FindHeader(num, BlockTreeLookupOptions.None); return this; } @@ -387,7 +386,7 @@ public ScenarioBuilder SuggestBlocks(long low, long high) public ScenarioBuilder SuggestBlocksUsingChainLevels(int maxCount = 2, long maxHeaderNumber = long.MaxValue) { - BlockHeader[] headers = _chainLevelHelper!.GetNextHeaders(maxCount, maxHeaderNumber, 0)!; + BlockHeader[] headers = _chainLevelHelper!.GetNextHeaders(maxCount, maxHeaderNumber, 0); while (headers is not null && headers.Length > 1) { BlockDownloadContext blockDownloadContext = new( @@ -411,14 +410,14 @@ public ScenarioBuilder SuggestBlocksUsingChainLevels(int maxCount = 2, long maxH { beaconBlock = SyncedTree.FindBlock(headers[i].Hash!, BlockTreeLookupOptions.None); - beaconBlock!.Header.TotalDifficulty = null; + beaconBlock.Header.TotalDifficulty = null; } AddBlockResult insertResult = NotSyncedTree.SuggestBlock(beaconBlock, BlockTreeSuggestOptions.ShouldProcess | BlockTreeSuggestOptions.FillBeaconBlock | BlockTreeSuggestOptions.ForceSetAsMain); Assert.True(AddBlockResult.Added == insertResult, $"BeaconBlock {beaconBlock!.ToString(Block.Format.FullHashAndNumber)} result {insertResult}"); } - headers = _chainLevelHelper!.GetNextHeaders(maxCount, maxHeaderNumber, 0)!; + headers = _chainLevelHelper!.GetNextHeaders(maxCount, maxHeaderNumber, 0); } return this; @@ -438,10 +437,10 @@ public ScenarioBuilder InsertBeaconHeaders(long low, long high, TotalDifficultyM headerOptions |= BlockTreeInsertHeaderOptions.TotalDifficultyNotNeeded; for (long i = high; i >= low; --i) { - BlockHeader? beaconHeader = SyncedTree!.FindHeader(i, BlockTreeLookupOptions.None)!; + BlockHeader? beaconHeader = SyncedTree!.FindHeader(i, BlockTreeLookupOptions.None); if (tdMode == TotalDifficultyMode.Null) - beaconHeader.TotalDifficulty = null; + beaconHeader!.TotalDifficulty = null; else if (tdMode == TotalDifficultyMode.Zero) beaconHeader.TotalDifficulty = 0; AddBlockResult insertResult = NotSyncedTree!.Insert(beaconHeader!, headerOptions); @@ -482,7 +481,7 @@ public ScenarioBuilder InsertFork(long low, long high, bool moveToBeaconMainChai NotSyncedTree.Insert(blockToInsert, BlockTreeInsertBlockOptions.SaveHeader, BlockTreeInsertHeaderOptions.BeaconBlockInsert); SyncedTree.Insert(blockToInsert, BlockTreeInsertBlockOptions.SaveHeader, BlockTreeInsertHeaderOptions.NotOnMainChain); - BlockInfo newBlockInfo = new(blockToInsert.GetOrCalculateHash(), UInt256.Zero, BlockMetadata.BeaconBody | BlockMetadata.BeaconHeader); + BlockInfo newBlockInfo = new(blockToInsert.Hash, UInt256.Zero, BlockMetadata.BeaconBody | BlockMetadata.BeaconHeader); newBlockInfo.BlockNumber = blockToInsert.Number; blockInfos.Add(newBlockInfo); blocks.Add(blockToInsert); @@ -511,7 +510,7 @@ public ScenarioBuilder InsertOtherChainToMain(BlockTree blockTree, long low, lon blockTree.Insert(blockToInsert, BlockTreeInsertBlockOptions.SaveHeader, BlockTreeInsertHeaderOptions.BeaconBlockInsert); newBlocks.Add(blockToInsert); - BlockInfo newBlockInfo = new(blockToInsert.GetOrCalculateHash(), UInt256.Zero, BlockMetadata.BeaconBody | BlockMetadata.BeaconHeader); + BlockInfo newBlockInfo = new(blockToInsert.Hash, UInt256.Zero, BlockMetadata.BeaconBody | BlockMetadata.BeaconHeader); newBlockInfo.BlockNumber = blockToInsert.Number; parent = blockToInsert; } @@ -533,7 +532,7 @@ public ScenarioBuilder Restart() NullBloomStorage.Instance, new SyncConfig(), LimboLogs.Instance); - _chainLevelHelper = new ChainLevelHelper(NotSyncedTree, _beaconPivot!, new SyncConfig(), LimboLogs.Instance); + _chainLevelHelper = new ChainLevelHelper(NotSyncedTree, _beaconPivot, new SyncConfig(), LimboLogs.Instance); return this; } @@ -589,7 +588,7 @@ public ScenarioBuilder InsertToBlockDb(Block block) { BlockDecoder blockDecoder = new(); Rlp newRlp = blockDecoder.Encode(block); - NotSyncedTreeBuilder.BlocksDb.Set(block.GetOrCalculateHash(), newRlp.Bytes); + NotSyncedTreeBuilder.BlocksDb.Set(block.Hash, newRlp.Bytes); return this; } @@ -614,13 +613,13 @@ public ScenarioBuilder AssertChainLevel(int startNumber, int finalNumber) { for (int i = startNumber; i < finalNumber; ++i) { - ChainLevelInfo? level = NotSyncedTree.FindLevel(i)!; + ChainLevelInfo? level = NotSyncedTree.FindLevel(i); BlockInfo? blockInfo = level.MainChainBlock; blockInfo.Should().NotBe(null, $"Current block number: {i}"); - blockInfo!.TotalDifficulty.Should().NotBe(0, $"Current block number: {i}"); + blockInfo.TotalDifficulty.Should().NotBe(0, $"Current block number: {i}"); ChainLevelInfo? syncedLevel = SyncedTree.FindLevel(i); - blockInfo.BlockHash.Should().Be(syncedLevel?.MainChainBlock!.BlockHash!, $"Current block number: {i}"); + blockInfo.BlockHash.Should().Be(syncedLevel?.MainChainBlock.BlockHash, $"Current block number: {i}"); } return this; @@ -628,14 +627,14 @@ public ScenarioBuilder AssertChainLevel(int startNumber, int finalNumber) public ScenarioBuilder AssertForceNewBeaconSync() { - _beaconPivot!.ShouldForceStartNewSync.Should().BeTrue(); + _beaconPivot.ShouldForceStartNewSync.Should().BeTrue(); return this; } public ScenarioBuilder AssertNotForceNewBeaconSync() { - _beaconPivot!.ShouldForceStartNewSync.Should().BeFalse(); + _beaconPivot.ShouldForceStartNewSync.Should().BeFalse(); return this; } @@ -644,19 +643,19 @@ public ScenarioBuilder print() { // Console.WriteLine("LowestInsertedBeaconHeader:"+_notSyncedTree!.LowestInsertedBeaconHeader.Number); Console.WriteLine("Head:" + NotSyncedTree!.Head!.Number); - Console.WriteLine("BestSuggestedHeader:" + NotSyncedTree!.BestSuggestedHeader!.Number); - Console.WriteLine("BestSuggestedBody:" + NotSyncedTree!.BestSuggestedBody!.Number); + Console.WriteLine("BestSuggestedHeader:" + NotSyncedTree!.BestSuggestedHeader.Number); + Console.WriteLine("BestSuggestedBody:" + NotSyncedTree!.BestSuggestedBody.Number); // Console.WriteLine("LowestInsertedHeader:"+_notSyncedTree!.LowestInsertedHeader.Number); Console.WriteLine("BestKnownNumber:" + NotSyncedTree!.BestKnownNumber); Console.WriteLine("BestKnownBeaconNumber:" + NotSyncedTree!.BestKnownBeaconNumber); return this; } - public BlockTree SyncedTree { get; private set; } = null!; + public BlockTree SyncedTree { get; private set; } - public BlockTree NotSyncedTree { get; private set; } = null!; + public BlockTree NotSyncedTree { get; private set; } - public BlockTreeBuilder NotSyncedTreeBuilder { get; private set; } = null!; + public BlockTreeBuilder NotSyncedTreeBuilder { get; private set; } } public static ScenarioBuilder GoesLikeThis() @@ -672,7 +671,7 @@ public void FindHeader_should_throw_exception_when_trying_to_find_dangling_block .WithBlockTrees(10, 20); Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None); - scenario.InsertToHeaderDb(beaconBlock!.Header); + scenario.InsertToHeaderDb(beaconBlock.Header); Assert.Throws(() => scenario.NotSyncedTree.FindHeader(beaconBlock.Header.Hash, BlockTreeLookupOptions.None)); } @@ -682,7 +681,7 @@ public void FindBlock_should_throw_exception_when_trying_to_find_dangling_block( BlockTreeTestScenario.ScenarioBuilder scenario = BlockTreeTestScenario.GoesLikeThis() .WithBlockTrees(10, 20); - Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None)!; + Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None); scenario.InsertToBlockDb(beaconBlock); Assert.Throws(() => scenario.NotSyncedTree.FindBlock(beaconBlock.Header.Hash, BlockTreeLookupOptions.None)); } @@ -695,7 +694,7 @@ public void FindHeader_should_not_throw_exception_when_finding_blocks_with_known .InsertBeaconBlocks(18, 19); Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None); - scenario.InsertToHeaderDb(beaconBlock!.Header); + scenario.InsertToHeaderDb(beaconBlock.Header); Assert.DoesNotThrow(() => scenario.NotSyncedTree.FindHeader(beaconBlock.Header.Hash, BlockTreeLookupOptions.None)); } @@ -706,7 +705,7 @@ public void FindBlock_should_not_throw_exception_when_finding_blocks_with_known_ .WithBlockTrees(10, 20) .InsertBeaconBlocks(18, 19); - Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None)!; + Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None); scenario.InsertToBlockDb(beaconBlock); Assert.DoesNotThrow(() => scenario.NotSyncedTree.FindBlock(beaconBlock.Header.Hash, BlockTreeLookupOptions.None)); } @@ -717,7 +716,7 @@ public void FindHeader_should_not_throw_exception_when_create_level_is_missing() BlockTreeTestScenario.ScenarioBuilder scenario = BlockTreeTestScenario.GoesLikeThis() .WithBlockTrees(10, 20); - Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None)!; + Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None); scenario.InsertToHeaderDb(beaconBlock.Header); Assert.DoesNotThrow(() => scenario.NotSyncedTree.FindHeader(beaconBlock.Header.Hash, BlockTreeLookupOptions.DoNotCreateLevelIfMissing)); } @@ -728,7 +727,7 @@ public void FindBlock_should_not_throw_exception_when_create_level_is_missing() BlockTreeTestScenario.ScenarioBuilder scenario = BlockTreeTestScenario.GoesLikeThis() .WithBlockTrees(10, 20); - Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None)!; + Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None); scenario.InsertToBlockDb(beaconBlock!); Assert.DoesNotThrow(() => scenario.NotSyncedTree.FindBlock(beaconBlock.Header.Hash, BlockTreeLookupOptions.DoNotCreateLevelIfMissing)); } @@ -872,13 +871,13 @@ public void Fork_do_not_change_beacon_main_chain_block() .WithBlockTrees(4, 10) .InsertBeaconBlocks(5, 9); - ChainLevelInfo? level6 = scenario.NotSyncedTree.FindLevel(6)!; - Keccak previousBlockHash = level6.BeaconMainChainBlock!.BlockHash; + ChainLevelInfo? level6 = scenario.NotSyncedTree.FindLevel(6); + Keccak previousBlockHash = level6.BeaconMainChainBlock.BlockHash; scenario.InsertFork(6, 8); level6 = scenario.NotSyncedTree.FindLevel(6); - level6!.BlockInfos.Length.Should().Be(2); - level6.BeaconMainChainBlock!.BlockHash.Should().Be(previousBlockHash); + level6.BlockInfos.Length.Should().Be(2); + level6.BeaconMainChainBlock.BlockHash.Should().Be(previousBlockHash); } [Test] @@ -900,9 +899,9 @@ public void Can_set_total_difficulty_when_suggested_with_0() .InsertBeaconPivot(7) .InsertBeaconBlocks(8, 9, BlockTreeTestScenario.ScenarioBuilder.TotalDifficultyMode.Zero); - Block block = scenario.NotSyncedTree.FindBlock(8, BlockTreeLookupOptions.None)!; + Block? block = scenario.NotSyncedTree.FindBlock(8, BlockTreeLookupOptions.None); AddBlockResult result = scenario.NotSyncedTree.SuggestBlock(block); result.Should().Be(AddBlockResult.Added); - scenario.NotSyncedTree.FindBlock(8, BlockTreeLookupOptions.None)!.TotalDifficulty.Should().NotBe((UInt256)0); + scenario.NotSyncedTree.FindBlock(8, BlockTreeLookupOptions.None).TotalDifficulty.Should().NotBe((UInt256)0); } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/ChainSpecBasedSpecProviderTests.TheMerge.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/ChainSpecBasedSpecProviderTests.TheMerge.cs index 9968796f479..9882500831e 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/ChainSpecBasedSpecProviderTests.TheMerge.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/ChainSpecBasedSpecProviderTests.TheMerge.cs @@ -21,7 +21,7 @@ public void Correctly_read_merge_block_number() { Parameters = new ChainParameters { - TerminalPoWBlockNumber = terminalBlockNumber + TerminalPowBlockNumber = terminalBlockNumber } }; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs index 55b3df0ac92..36459b7444e 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs @@ -20,10 +20,6 @@ using Nethermind.Specs; using Nethermind.Specs.Forks; using Nethermind.State; -using Nethermind.Core.Specs; -using Nethermind.Consensus.BeaconBlockRoot; -using Nethermind.Consensus.Withdrawals; -using Nethermind.Core.Test.Blockchain; namespace Nethermind.Merge.Plugin.Test { @@ -31,8 +27,8 @@ namespace Nethermind.Merge.Plugin.Test public partial class EngineModuleTests { private static readonly DateTime Timestamp = DateTimeOffset.FromUnixTimeSeconds(1000).UtcDateTime; - private static readonly IBeaconBlockRootHandler _beaconBlockRootHandler = new BeaconBlockRootHandler(); private ITimestamper Timestamper { get; } = new ManualTimestamper(Timestamp); + private void AssertExecutionStatusChanged(IBlockFinder blockFinder, Keccak headBlockHash, Keccak finalizedBlockHash, Keccak safeBlockHash) { @@ -88,49 +84,9 @@ private ExecutionPayload CreateParentBlockRequestOnHead(IBlockTree blockTree) }; } - private static ExecutionPayload CreateBlockRequest(MergeTestBlockchain chain, ExecutionPayload parent, Address miner, IList? withdrawals = null, - ulong? blobGasUsed = null, ulong? excessBlobGas = null, Transaction[]? transactions = null, Keccak? parentBeaconBlockRoot = null) - { - ExecutionPayload blockRequest = CreateBlockRequestInternal(parent, miner, withdrawals, blobGasUsed, excessBlobGas, transactions: transactions, parentBeaconBlockRoot: parentBeaconBlockRoot); - blockRequest.TryGetBlock(out Block? block); - - Snapshot before = chain.State.TakeSnapshot(); - chain.WithdrawalProcessor?.ProcessWithdrawals(block!, chain.SpecProvider.GenesisSpec); - - chain.State.Commit(chain.SpecProvider.GenesisSpec); - chain.State.RecalculateStateRoot(); - blockRequest.StateRoot = chain.State.StateRoot; - chain.State.Restore(before); - - TryCalculateHash(blockRequest, out Keccak? hash); - blockRequest.BlockHash = hash; - return blockRequest; - } - - private static ExecutionPayloadV3 CreateBlockRequestV3(MergeTestBlockchain chain, ExecutionPayload parent, Address miner, IList? withdrawals = null, - ulong? blobGasUsed = null, ulong? excessBlobGas = null, Transaction[]? transactions = null, Keccak? parentBeaconBlockRoot = null) - { - ExecutionPayloadV3 blockRequestV3 = CreateBlockRequestInternal(parent, miner, withdrawals, blobGasUsed, excessBlobGas, transactions: transactions, parentBeaconBlockRoot: parentBeaconBlockRoot); - blockRequestV3.TryGetBlock(out Block? block); - - Snapshot before = chain.State.TakeSnapshot(); - _beaconBlockRootHandler.ApplyContractStateChanges(block!, chain.SpecProvider.GenesisSpec, chain.State); - chain.WithdrawalProcessor?.ProcessWithdrawals(block!, chain.SpecProvider.GenesisSpec); - - chain.State.Commit(chain.SpecProvider.GenesisSpec); - chain.State.RecalculateStateRoot(); - blockRequestV3.StateRoot = chain.State.StateRoot; - chain.State.Restore(before); - - TryCalculateHash(blockRequestV3, out Keccak? hash); - blockRequestV3.BlockHash = hash; - return blockRequestV3; - } - - private static T CreateBlockRequestInternal(ExecutionPayload parent, Address miner, IList? withdrawals = null, - ulong? blobGasUsed = null, ulong? excessBlobGas = null, Transaction[]? transactions = null, Keccak? parentBeaconBlockRoot = null) where T : ExecutionPayload, new() + private static ExecutionPayload CreateBlockRequest(ExecutionPayload parent, Address miner, IList? withdrawals = null, ulong? dataGasUsed = null, ulong? excessDataGas = null, Transaction[]? transactions = null) { - T blockRequest = new() + ExecutionPayload blockRequest = new() { ParentHash = parent.BlockHash, FeeRecipient = miner, @@ -142,9 +98,8 @@ private static T CreateBlockRequestInternal(ExecutionPayload parent, Address LogsBloom = Bloom.Empty, Timestamp = parent.Timestamp + 1, Withdrawals = withdrawals, - BlobGasUsed = blobGasUsed, - ExcessBlobGas = excessBlobGas, - ParentBeaconBlockRoot = parentBeaconBlockRoot, + DataGasUsed = dataGasUsed, + ExcessDataGas = excessDataGas, }; blockRequest.SetTransactions(transactions ?? Array.Empty()); @@ -153,13 +108,13 @@ private static T CreateBlockRequestInternal(ExecutionPayload parent, Address return blockRequest; } - private static ExecutionPayload[] CreateBlockRequestBranch(MergeTestBlockchain chain, ExecutionPayload parent, Address miner, int count) + private static ExecutionPayload[] CreateBlockRequestBranch(ExecutionPayload parent, Address miner, int count) { ExecutionPayload currentBlock = parent; ExecutionPayload[] blockRequests = new ExecutionPayload[count]; for (int i = 0; i < count; i++) { - currentBlock = CreateBlockRequest(chain, currentBlock, miner); + currentBlock = CreateBlockRequest(currentBlock, miner); blockRequests[i] = currentBlock; } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.PayloadProduction.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.PayloadProduction.cs index 09d747829a5..771fdaa1484 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.PayloadProduction.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.PayloadProduction.cs @@ -223,7 +223,7 @@ public async Task getPayload_correctlyEncodeTransactions() using MergeTestBlockchain chain = await CreateBlockchain(null, null, payloadPreparationService); IEngineRpcModule rpc = CreateEngineModule(chain); - string result = await RpcTest.TestSerializedRequest(rpc, "engine_getPayloadV1", payload.ToHexString(true)); + string result = RpcTest.TestSerializedRequest(rpc, "engine_getPayloadV1", payload.ToHexString(true)); Assert.That(chain.JsonSerializer.Serialize(new { jsonrpc = "2.0", @@ -264,7 +264,7 @@ public async Task getPayload_should_serialize_unknown_payload_response_properly( byte[] payloadId = Bytes.FromHexString("0x1111111111111111"); string parameters = payloadId.ToHexString(true); - string result = await RpcTest.TestSerializedRequest(rpc, "engine_getPayloadV1", parameters); + string result = RpcTest.TestSerializedRequest(rpc, "engine_getPayloadV1", parameters); result.Should().Be("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-38001,\"message\":\"unknown payload\"},\"id\":67}"); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs index feab59ee82e..ba012651ea7 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs @@ -15,7 +15,6 @@ using Nethermind.Consensus.Producers; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; -using Nethermind.Consensus.Withdrawals; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; @@ -81,15 +80,12 @@ private IEngineRpcModule CreateEngineModule(MergeTestBlockchain chain, ISyncConf return new EngineRpcModule( new GetPayloadV1Handler( chain.PayloadPreparationService!, - chain.SpecProvider!, chain.LogManager), new GetPayloadV2Handler( chain.PayloadPreparationService!, - chain.SpecProvider!, chain.LogManager), new GetPayloadV3Handler( chain.PayloadPreparationService!, - chain.SpecProvider!, chain.LogManager), new NewPayloadHandler( chain.BlockValidator, @@ -117,7 +113,6 @@ private IEngineRpcModule CreateEngineModule(MergeTestBlockchain chain, ISyncConf chain.BeaconSync, chain.BeaconPivot, peerRefresher, - chain.SpecProvider, chain.LogManager), new GetPayloadBodiesByHashV1Handler(chain.BlockTree, chain.LogManager), new GetPayloadBodiesByRangeV1Handler(chain.BlockTree, chain.LogManager), @@ -142,9 +137,7 @@ public class MergeTestBlockchain : TestBlockchain public BeaconSync? BeaconSync { get; set; } - public IWithdrawalProcessor? WithdrawalProcessor { get; set; } - - protected int _blockProcessingThrottle = 0; + private int _blockProcessingThrottle = 0; public MergeTestBlockchain ThrottleBlockProcessor(int delayMs) { @@ -219,7 +212,6 @@ protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolT protected override IBlockProcessor CreateBlockProcessor() { BlockValidator = CreateBlockValidator(); - WithdrawalProcessor = new WithdrawalProcessor(State, LogManager); IBlockProcessor processor = new BlockProcessor( SpecProvider, BlockValidator, @@ -228,13 +220,12 @@ protected override IBlockProcessor CreateBlockProcessor() State, ReceiptStorage, NullWitnessCollector.Instance, - LogManager, - WithdrawalProcessor); + LogManager); return new TestBlockProcessorInterceptor(processor, _blockProcessingThrottle); } - protected IBlockValidator CreateBlockValidator() + private IBlockValidator CreateBlockValidator() { IBlockCacheService blockCacheService = new BlockCacheService(); PoSSwitcher = new PoSSwitcher(MergeConfig, SyncConfig.Default, new MemDb(), BlockTree, SpecProvider, LogManager); @@ -252,7 +243,7 @@ protected IBlockValidator CreateBlockValidator() public IManualBlockFinalizationManager BlockFinalizationManager { get; } = new ManualBlockFinalizationManager(); - protected override async Task Build(ISpecProvider? specProvider = null, UInt256? initialValues = null, bool addBlockOnStart = true) + protected override async Task Build(ISpecProvider? specProvider = null, UInt256? initialValues = null) { TestBlockchain chain = await base.Build(specProvider, initialValues); return chain; @@ -263,7 +254,7 @@ public async Task Build(ISpecProvider? specProvider = null) } } -public class TestBlockProcessorInterceptor : IBlockProcessor +internal class TestBlockProcessorInterceptor : IBlockProcessor { private readonly IBlockProcessor _blockProcessorImplementation; public int DelayMs { get; set; } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs index f97848f41dd..256557f1d8b 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs @@ -11,12 +11,14 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; +using Nethermind.Core.Timers; using Nethermind.Crypto; using Nethermind.Int256; using Nethermind.JsonRpc; using Nethermind.Logging; using Nethermind.Merge.Plugin.Data; using Nethermind.Merge.Plugin.Synchronization; +using Nethermind.Stats; using Nethermind.Synchronization; using Nethermind.Synchronization.ParallelSync; using Nethermind.Synchronization.Peers; @@ -202,14 +204,14 @@ public async Task should_return_invalid_lvh_null_on_invalid_blocks_during_the_sy forkchoiceUpdatedResult.Data.PayloadStatus.Status.Should() .Be(nameof(PayloadStatusV1.Syncing).ToUpper()); - ExecutionPayload[] requests = CreateBlockRequestBranch(chain, startingNewPayload, TestItem.AddressD, 1); + ExecutionPayload[] requests = CreateBlockRequestBranch(startingNewPayload, TestItem.AddressD, 1); foreach (ExecutionPayload r in requests) { ResultWrapper payloadStatus = await rpc.engine_newPayloadV1(r); payloadStatus.Data.Status.Should().Be(nameof(PayloadStatusV1.Syncing).ToUpper()); } - ExecutionPayload[] invalidRequests = CreateBlockRequestBranch(chain, requests[0], TestItem.AddressD, 1); + ExecutionPayload[] invalidRequests = CreateBlockRequestBranch(requests[0], TestItem.AddressD, 1); foreach (ExecutionPayload r in invalidRequests) { r.TryGetBlock(out Block? newBlock); @@ -229,7 +231,7 @@ public async Task newPayloadV1_can_insert_blocks_from_cache_when_syncing() Keccak startingHead = chain.BlockTree.HeadHash; ExecutionPayload parentBlockRequest = new(Build.A.Block.WithNumber(2).TestObject); - ExecutionPayload[] requests = CreateBlockRequestBranch(chain, parentBlockRequest, Address.Zero, 7); + ExecutionPayload[] requests = CreateBlockRequestBranch(parentBlockRequest, Address.Zero, 7); ResultWrapper payloadStatus; foreach (ExecutionPayload r in requests) { @@ -293,7 +295,7 @@ public async Task first_new_payload_set_beacon_main_chain() await rpc.engine_forkchoiceUpdatedV1(forkchoiceStateV1); forkchoiceUpdatedResult.Data.PayloadStatus.Status.Should() .Be(nameof(PayloadStatusV1.Syncing).ToUpper()); - ExecutionPayload[] requests = CreateBlockRequestBranch(chain, startingNewPayload, Address.Zero, 4); + ExecutionPayload[] requests = CreateBlockRequestBranch(startingNewPayload, Address.Zero, 4); foreach (ExecutionPayload r in requests) { ResultWrapper payloadStatus = await rpc.engine_newPayloadV1(r); @@ -334,7 +336,7 @@ public async Task repeated_new_payloads_do_not_change_metadata() await rpc.engine_forkchoiceUpdatedV1(forkchoiceStateV1); forkchoiceUpdatedResult.Data.PayloadStatus.Status.Should() .Be(nameof(PayloadStatusV1.Syncing).ToUpper()); - ExecutionPayload[] requests = CreateBlockRequestBranch(chain, startingNewPayload, Address.Zero, 4); + ExecutionPayload[] requests = CreateBlockRequestBranch(startingNewPayload, Address.Zero, 4); foreach (ExecutionPayload r in requests) { ResultWrapper payloadStatus = await rpc.engine_newPayloadV1(r); @@ -492,7 +494,7 @@ public async Task second_new_payload_should_not_set_beacon_main_chain() await rpc.engine_forkchoiceUpdatedV1(forkchoiceStateV1); forkchoiceUpdatedResult.Data.PayloadStatus.Status.Should() .Be(nameof(PayloadStatusV1.Syncing).ToUpper()); - ExecutionPayload[] requests = CreateBlockRequestBranch(chain, startingNewPayload, Address.Zero, 4); + ExecutionPayload[] requests = CreateBlockRequestBranch(startingNewPayload, Address.Zero, 4); foreach (ExecutionPayload r in requests) { ResultWrapper payloadStatus = await rpc.engine_newPayloadV1(r); @@ -503,7 +505,7 @@ public async Task second_new_payload_should_not_set_beacon_main_chain() lvl!.BlockInfos[0].Metadata.Should().Be(BlockMetadata.BeaconBody | BlockMetadata.BeaconHeader | BlockMetadata.BeaconMainChain); } - ExecutionPayload[] secondNewPayloads = CreateBlockRequestBranch(chain, startingNewPayload, TestItem.AddressD, 4); + ExecutionPayload[] secondNewPayloads = CreateBlockRequestBranch(startingNewPayload, TestItem.AddressD, 4); foreach (ExecutionPayload r in secondNewPayloads) { ResultWrapper payloadStatus = await rpc.engine_newPayloadV1(r); @@ -549,13 +551,13 @@ public async Task should_reorg_during_the_sync(int initialChainPayloadsCount, in await rpc.engine_newPayloadV1(startingNewPayload); ForkchoiceStateV1 forkchoiceStateV1 = new(block.Hash!, startingHead, startingHead); await rpc.engine_forkchoiceUpdatedV1(forkchoiceStateV1); - ExecutionPayload[] initialBranchPayloads = CreateBlockRequestBranch(chain, startingNewPayload, Address.Zero, initialChainPayloadsCount); + ExecutionPayload[] initialBranchPayloads = CreateBlockRequestBranch(startingNewPayload, Address.Zero, initialChainPayloadsCount); foreach (ExecutionPayload r in initialBranchPayloads) { await rpc.engine_newPayloadV1(r); } - ExecutionPayload[] newBranchPayloads = CreateBlockRequestBranch(chain, startingNewPayload, TestItem.AddressD, reorgedChainPayloadCount); + ExecutionPayload[] newBranchPayloads = CreateBlockRequestBranch(startingNewPayload, TestItem.AddressD, reorgedChainPayloadCount); foreach (ExecutionPayload r in newBranchPayloads) { await rpc.engine_newPayloadV1(r); @@ -586,7 +588,7 @@ public async Task Blocks_from_cache_inserted_when_fast_headers_sync_finish_befor using MergeTestBlockchain chain = await CreateBlockchain(); Keccak startingHead = chain.BlockTree.HeadHash; IEngineRpcModule rpc = CreateEngineModule(chain); - ExecutionPayload[] requests = CreateBlockRequestBranch(chain, new ExecutionPayload(chain.BlockTree.Head!), Address.Zero, 7); + ExecutionPayload[] requests = CreateBlockRequestBranch(new ExecutionPayload(chain.BlockTree.Head!), Address.Zero, 7); ResultWrapper payloadStatus; for (int i = 4; i < requests.Length - 1; i++) @@ -638,13 +640,13 @@ public async Task Maintain_correct_pointers_for_beacon_sync_in_archive_sync() Block[] missingBlocks = new Block[gap]; for (int i = 0; i < gap; i++) { - headBlockRequest = CreateBlockRequest(chain, headBlockRequest, Address.Zero); + headBlockRequest = CreateBlockRequest(headBlockRequest, Address.Zero); headBlockRequest.TryGetBlock(out Block? block); missingBlocks[i] = block!; } // setting up beacon pivot - ExecutionPayload pivotRequest = CreateBlockRequest(chain, headBlockRequest, Address.Zero); + ExecutionPayload pivotRequest = CreateBlockRequest(headBlockRequest, Address.Zero); ResultWrapper payloadStatus = await rpc.engine_newPayloadV1(pivotRequest); payloadStatus.Data.Status.Should().Be(nameof(PayloadStatusV1.Syncing).ToUpper()); pivotRequest.TryGetBlock(out Block? pivotBlock); @@ -666,7 +668,7 @@ public async Task Maintain_correct_pointers_for_beacon_sync_in_archive_sync() forkchoiceUpdatedResult.Data.PayloadStatus.Status.Should() .Be(nameof(PayloadStatusV1.Syncing).ToUpper()); // trigger insertion of blocks in cache into block tree by adding new block - ExecutionPayload bestBeaconBlockRequest = CreateBlockRequest(chain, pivotRequest, Address.Zero); + ExecutionPayload bestBeaconBlockRequest = CreateBlockRequest(pivotRequest, Address.Zero); payloadStatus = await rpc.engine_newPayloadV1(bestBeaconBlockRequest); payloadStatus.Data.Status.Should().Be(nameof(PayloadStatusV1.Syncing).ToUpper()); // simulate headers sync by inserting 3 headers from pivot backwards @@ -720,7 +722,7 @@ public async Task Maintain_correct_pointers_for_beacon_sync_in_archive_sync() await bestBlockProcessed.WaitAsync(); // beacon sync should be finished, eventually - bestBeaconBlockRequest = CreateBlockRequest(chain, bestBeaconBlockRequest, Address.Zero); + bestBeaconBlockRequest = CreateBlockRequest(bestBeaconBlockRequest, Address.Zero); Assert.That( () => rpc.engine_newPayloadV1(bestBeaconBlockRequest).Result.Data.Status, Is.EqualTo(PayloadStatus.Valid).After(1000, 100) @@ -796,9 +798,9 @@ public async Task Maintain_correct_pointers_for_beacon_sync_in_fast_sync() // create block gap from fast sync pivot int gap = 7; ExecutionPayload[] requests = - CreateBlockRequestBranch(chain, new ExecutionPayload(syncedBlockTree.Head!), Address.Zero, gap); + CreateBlockRequestBranch(new ExecutionPayload(syncedBlockTree.Head!), Address.Zero, gap); // setting up beacon pivot - ExecutionPayload pivotRequest = CreateBlockRequest(chain, requests[^1], Address.Zero); + ExecutionPayload pivotRequest = CreateBlockRequest(requests[^1], Address.Zero); ResultWrapper payloadStatus = await rpc.engine_newPayloadV1(pivotRequest); payloadStatus.Data.Status.Should().Be(nameof(PayloadStatusV1.Syncing).ToUpper()); pivotRequest.TryGetBlock(out Block? pivotBlock); @@ -821,7 +823,7 @@ public async Task Maintain_correct_pointers_for_beacon_sync_in_fast_sync() forkchoiceUpdatedResult.Data.PayloadStatus.Status.Should() .Be(nameof(PayloadStatusV1.Syncing).ToUpper()); // trigger insertion of blocks in cache into block tree by adding new block - ExecutionPayload bestBeaconBlockRequest = CreateBlockRequest(chain, pivotRequest, Address.Zero); + ExecutionPayload bestBeaconBlockRequest = CreateBlockRequest(pivotRequest, Address.Zero); payloadStatus = await rpc.engine_newPayloadV1(bestBeaconBlockRequest); payloadStatus.Data.Status.Should().Be(nameof(PayloadStatusV1.Syncing).ToUpper()); // fill in beacon headers until fast headers pivot @@ -855,12 +857,12 @@ public async Task Invalid_block_can_create_invalid_best_state_issue_but_recalcul chain.BlockTree.HeadHash.Should().Be(lastHash); // send newPayload - ExecutionPayload validBlockOnTopOfHead = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); + ExecutionPayload validBlockOnTopOfHead = CreateBlockRequest(CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); PayloadStatusV1 payloadStatusResponse = (await rpc.engine_newPayloadV1(validBlockOnTopOfHead)).Data; payloadStatusResponse.Status.Should().Be(PayloadStatus.Valid); // send block with invalid state root - ExecutionPayload blockWithInvalidStateRoot = CreateBlockRequest(chain, validBlockOnTopOfHead, TestItem.AddressA); + ExecutionPayload blockWithInvalidStateRoot = CreateBlockRequest(validBlockOnTopOfHead, TestItem.AddressA); blockWithInvalidStateRoot.StateRoot = TestItem.KeccakB; TryCalculateHash(blockWithInvalidStateRoot, out Keccak? hash); blockWithInvalidStateRoot.BlockHash = hash; @@ -892,12 +894,12 @@ public async Task MultiSyncModeSelector_should_fix_block_tree_levels_if_needed() chain.BlockTree.HeadHash.Should().Be(lastHash); // send newPayload - ExecutionPayload validBlockOnTopOfHead = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); + ExecutionPayload validBlockOnTopOfHead = CreateBlockRequest(CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); PayloadStatusV1 payloadStatusResponse = (await rpc.engine_newPayloadV1(validBlockOnTopOfHead)).Data; payloadStatusResponse.Status.Should().Be(PayloadStatus.Valid); // send block with invalid state root - ExecutionPayload blockWithInvalidStateRoot = CreateBlockRequest(chain, validBlockOnTopOfHead, TestItem.AddressA); + ExecutionPayload blockWithInvalidStateRoot = CreateBlockRequest(validBlockOnTopOfHead, TestItem.AddressA); blockWithInvalidStateRoot.StateRoot = TestItem.KeccakB; TryCalculateHash(blockWithInvalidStateRoot, out Keccak? hash); blockWithInvalidStateRoot.BlockHash = hash; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs index 1dd1e1d5a6f..8f339d5ed6c 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs @@ -76,7 +76,7 @@ public virtual async Task processing_block_should_serialize_valid_responses(stri JsonConvert.SerializeObject(preparePayloadParams) }; // prepare a payload - string result = await RpcTest.TestSerializedRequest(rpc, "engine_forkchoiceUpdatedV1", parameters!); + string result = RpcTest.TestSerializedRequest(rpc, "engine_forkchoiceUpdatedV1", parameters!); byte[] expectedPayloadId = Bytes.FromHexString(payloadId); result.Should().Be($"{{\"jsonrpc\":\"2.0\",\"result\":{{\"payloadStatus\":{{\"status\":\"VALID\",\"latestValidHash\":\"{latestValidHash}\",\"validationError\":null}},\"payloadId\":\"{expectedPayloadId.ToHexString(true)}\"}},\"id\":67}}"); @@ -99,10 +99,10 @@ public virtual async Task processing_block_should_serialize_valid_responses(stri Transactions = Array.Empty() }); // get the payload - result = await RpcTest.TestSerializedRequest(rpc, "engine_getPayloadV1", expectedPayloadId.ToHexString(true)); + result = RpcTest.TestSerializedRequest(rpc, "engine_getPayloadV1", expectedPayloadId.ToHexString(true)); result.Should().Be($"{{\"jsonrpc\":\"2.0\",\"result\":{expectedPayload},\"id\":67}}"); // execute the payload - result = await RpcTest.TestSerializedRequest(rpc, "engine_newPayloadV1", expectedPayload); + result = RpcTest.TestSerializedRequest(rpc, "engine_newPayloadV1", expectedPayload); result.Should().Be($"{{\"jsonrpc\":\"2.0\",\"result\":{{\"status\":\"VALID\",\"latestValidHash\":\"{expectedBlockHash}\",\"validationError\":null}},\"id\":67}}"); forkChoiceUpdatedParams = new @@ -113,7 +113,7 @@ public virtual async Task processing_block_should_serialize_valid_responses(stri }; parameters = new[] { JsonConvert.SerializeObject(forkChoiceUpdatedParams), null }; // update the fork choice - result = await RpcTest.TestSerializedRequest(rpc, "engine_forkchoiceUpdatedV1", parameters!); + result = RpcTest.TestSerializedRequest(rpc, "engine_forkchoiceUpdatedV1", parameters!); result.Should().Be("{\"jsonrpc\":\"2.0\",\"result\":{\"payloadStatus\":{\"status\":\"VALID\",\"latestValidHash\":\"" + expectedBlockHash + "\",\"validationError\":null},\"payloadId\":null},\"id\":67}"); @@ -131,7 +131,7 @@ public async Task can_parse_forkchoiceUpdated_with_implicit_null_payloadAttribut finalizedBlockHash = Keccak.Zero.ToString(), }; string[] parameters = new[] { JsonConvert.SerializeObject(forkChoiceUpdatedParams) }; - string? result = await RpcTest.TestSerializedRequest(rpc, "engine_forkchoiceUpdatedV1", parameters); + string? result = RpcTest.TestSerializedRequest(rpc, "engine_forkchoiceUpdatedV1", parameters); result.Should().Be("{\"jsonrpc\":\"2.0\",\"result\":{\"payloadStatus\":{\"status\":\"SYNCING\",\"latestValidHash\":null,\"validationError\":null},\"payloadId\":null},\"id\":67}"); } @@ -139,14 +139,7 @@ public async Task can_parse_forkchoiceUpdated_with_implicit_null_payloadAttribut public void ForkchoiceV1_ToString_returns_correct_results() { ForkchoiceStateV1 forkchoiceState = new(TestItem.KeccakA, TestItem.KeccakF, TestItem.KeccakC); - forkchoiceState.ToString().Should().Be("ForkChoice: Head: 0x03783f...35b760, Safe: 0x017e66...b18f72, Finalized: 0xe61d9a...97c37a"); - } - - [Test] - public void ForkchoiceV1_ToString_with_block_numbers_returns_correct_results() - { - ForkchoiceStateV1 forkchoiceState = new(TestItem.KeccakA, TestItem.KeccakF, TestItem.KeccakC); - forkchoiceState.ToString(1, 2, 3).Should().Be("ForkChoice: Head: 1 (0x03783f...35b760), Safe: 2 (0x017e66...b18f72), Finalized: 3 (0xe61d9a...97c37a)"); + forkchoiceState.ToString().Should().Be("ForkchoiceState: (HeadBlockHash: 0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760, SafeBlockHash: 0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72, FinalizedBlockHash: 0xe61d9a3d3848fb2cdd9a2ab61e2f21a10ea431275aed628a0557f9dee697c37a)"); } [Test] @@ -450,7 +443,7 @@ public async Task executePayloadV1_result_is_fail_when_blockchainprocessor_repor ((TestBlockProcessorInterceptor)chain.BlockProcessor).ExceptionToThrow = new Exception("unxpected exception"); - ExecutionPayload executionPayload = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); + ExecutionPayload executionPayload = CreateBlockRequest(CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper resultWrapper = await rpc.engine_newPayloadV1(executionPayload); resultWrapper.Result.ResultType.Should().Be(ResultType.Failure); } @@ -786,7 +779,7 @@ public async Task executePayloadV1_should_not_accept_blocks_with_incorrect_ttd(l TerminalTotalDifficulty = $"{terminalTotalDifficulty}" }); IEngineRpcModule rpc = CreateEngineModule(chain); - ExecutionPayload executionPayload = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); + ExecutionPayload executionPayload = CreateBlockRequest(CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper resultWrapper = await rpc.engine_newPayloadV1(executionPayload); resultWrapper.Data.Status.Should().Be(PayloadStatus.Invalid); resultWrapper.Data.LatestValidHash.Should().Be(Keccak.Zero); @@ -903,7 +896,7 @@ public async Task executePayloadV1_accepts_first_block() { using MergeTestBlockchain chain = await CreateBlockchain(); IEngineRpcModule rpc = CreateEngineModule(chain); - ExecutionPayload executionPayload = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); + ExecutionPayload executionPayload = CreateBlockRequest(CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper resultWrapper = await rpc.engine_newPayloadV1(executionPayload); resultWrapper.Data.Status.Should().Be(PayloadStatus.Valid); new ExecutionPayload(chain.BlockTree.BestSuggestedBody!).Should().BeEquivalentTo(executionPayload); @@ -915,7 +908,7 @@ public async Task executePayloadV1_calculate_hash_for_cached_blocks() using MergeTestBlockchain chain = await CreateBlockchain(); IEngineRpcModule rpc = CreateEngineModule(chain); ExecutionPayload executionPayload = CreateBlockRequest( - chain, CreateParentBlockRequestOnHead(chain.BlockTree), + CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper resultWrapper = await rpc.engine_newPayloadV1(executionPayload); resultWrapper.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1000,7 +993,7 @@ public async Task newPayloadV1_should_return_accepted_for_side_branch() { using MergeTestBlockchain chain = await CreateBlockchain(); IEngineRpcModule rpc = CreateEngineModule(chain); - ExecutionPayload executionPayload = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); + ExecutionPayload executionPayload = CreateBlockRequest(CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper resultWrapper = await rpc.engine_newPayloadV1(executionPayload); resultWrapper.Data.Status.Should().Be(PayloadStatus.Valid); ForkchoiceStateV1 forkChoiceUpdatedRequest = new(executionPayload.BlockHash, executionPayload.BlockHash, executionPayload.BlockHash); @@ -1025,7 +1018,7 @@ public async Task executePayloadV1_processes_passed_transactions(bool moveHead) foreach (ExecutionPayload block in branch) { uint count = 10; - ExecutionPayload executePayloadRequest = CreateBlockRequest(chain, block, TestItem.AddressA); + ExecutionPayload executePayloadRequest = CreateBlockRequest(block, TestItem.AddressA); PrivateKey from = TestItem.PrivateKeyB; Address to = TestItem.AddressD; (_, UInt256 toBalanceAfter) = AddTransactions(chain, executePayloadRequest, from, to, count, 1, out BlockHeader? parentHeader); @@ -1062,7 +1055,7 @@ public async Task executePayloadV1_transactions_produce_receipts() foreach (ExecutionPayload block in branch) { uint count = 10; - ExecutionPayload executionPayload = CreateBlockRequest(chain, block, TestItem.AddressA); + ExecutionPayload executionPayload = CreateBlockRequest(block, TestItem.AddressA); PrivateKey from = TestItem.PrivateKeyB; Address to = TestItem.AddressD; (_, UInt256 toBalanceAfter) = AddTransactions(chain, executionPayload, from, to, count, 1, out BlockHeader parentHeader); @@ -1215,7 +1208,7 @@ public async Task exchangeTransitionConfiguration_return_with_empty_Nethermind_c private async Task SendNewBlockV1(IEngineRpcModule rpc, MergeTestBlockchain chain) { ExecutionPayload executionPayload = CreateBlockRequest( - chain, CreateParentBlockRequestOnHead(chain.BlockTree), + CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper executePayloadResult = await rpc.engine_newPayloadV1(executionPayload); @@ -1262,7 +1255,7 @@ public async Task repeat_the_same_payload_after_fcu_should_return_valid_and_be_i // Correct new payload ExecutionPayload executionPayloadV11 = CreateBlockRequest( - chain, CreateParentBlockRequestOnHead(chain.BlockTree), + CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressA); ResultWrapper newPayloadResult1 = await rpc.engine_newPayloadV1(executionPayloadV11); newPayloadResult1.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1289,7 +1282,7 @@ public async Task payloadV1_invalid_parent_hash() // Correct new payload ExecutionPayload executionPayloadV11 = CreateBlockRequest( - chain, CreateParentBlockRequestOnHead(chain.BlockTree), + CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressA); ResultWrapper newPayloadResult1 = await rpc.engine_newPayloadV1(executionPayloadV11); newPayloadResult1.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1301,7 +1294,7 @@ public async Task payloadV1_invalid_parent_hash() forkchoiceUpdatedResult1.Data.PayloadStatus.Status.Should().Be(PayloadStatus.Valid); // New payload unknown parent hash - ExecutionPayload executionPayloadV12A = CreateBlockRequest(chain, executionPayloadV11, TestItem.AddressA); + ExecutionPayload executionPayloadV12A = CreateBlockRequest(executionPayloadV11, TestItem.AddressA); executionPayloadV12A.ParentHash = TestItem.KeccakB; TryCalculateHash(executionPayloadV12A, out Keccak? hash); executionPayloadV12A.BlockHash = hash; @@ -1316,7 +1309,7 @@ public async Task payloadV1_invalid_parent_hash() forkchoiceUpdatedResult2A.Data.PayloadStatus.Status.Should().Be(PayloadStatus.Syncing); // New payload with correct parent hash - ExecutionPayload executionPayloadV12B = CreateBlockRequest(chain, executionPayloadV11, TestItem.AddressA); + ExecutionPayload executionPayloadV12B = CreateBlockRequest(executionPayloadV11, TestItem.AddressA); ResultWrapper newPayloadResult2B = await rpc.engine_newPayloadV1(executionPayloadV12B); newPayloadResult2B.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1327,7 +1320,7 @@ public async Task payloadV1_invalid_parent_hash() forkchoiceUpdatedResult2B.Data.PayloadStatus.Status.Should().Be(PayloadStatus.Valid); // New payload unknown parent hash - ExecutionPayload executionPayloadV13A = CreateBlockRequest(chain, executionPayloadV12A, TestItem.AddressA); + ExecutionPayload executionPayloadV13A = CreateBlockRequest(executionPayloadV12A, TestItem.AddressA); ResultWrapper newPayloadResult3A = await rpc.engine_newPayloadV1(executionPayloadV13A); newPayloadResult3A.Data.Status.Should().Be(PayloadStatus.Syncing); @@ -1338,7 +1331,7 @@ public async Task payloadV1_invalid_parent_hash() ResultWrapper forkchoiceUpdatedResult3A = await rpc.engine_forkchoiceUpdatedV1(forkChoiceState3A); forkchoiceUpdatedResult3A.Data.PayloadStatus.Status.Should().Be(PayloadStatus.Syncing); - ExecutionPayload executionPayloadV13B = CreateBlockRequest(chain, executionPayloadV12B, TestItem.AddressA); + ExecutionPayload executionPayloadV13B = CreateBlockRequest(executionPayloadV12B, TestItem.AddressA); ResultWrapper newPayloadResult3B = await rpc.engine_newPayloadV1(executionPayloadV13B); newPayloadResult3B.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1357,7 +1350,7 @@ public async Task inconsistent_finalized_hash() IEngineRpcModule rpc = CreateEngineModule(chain); ExecutionPayload blockRequestResult1 = CreateBlockRequest( - chain, CreateParentBlockRequestOnHead(chain.BlockTree), + CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressA); ResultWrapper newPayloadResult1 = await rpc.engine_newPayloadV1(blockRequestResult1); newPayloadResult1.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1367,15 +1360,15 @@ public async Task inconsistent_finalized_hash() ResultWrapper forkchoiceUpdatedResult1 = await rpc.engine_forkchoiceUpdatedV1(forkChoiceState1); forkchoiceUpdatedResult1.Data.PayloadStatus.Status.Should().Be(PayloadStatus.Valid); - ExecutionPayload blockRequestResult2A = CreateBlockRequest(chain, blockRequestResult1, TestItem.AddressB); + ExecutionPayload blockRequestResult2A = CreateBlockRequest(blockRequestResult1, TestItem.AddressB); ResultWrapper newPayloadResult2A = await rpc.engine_newPayloadV1(blockRequestResult2A); newPayloadResult2A.Data.Status.Should().Be(PayloadStatus.Valid); - ExecutionPayload blockRequestResult2B = CreateBlockRequest(chain, blockRequestResult1, TestItem.AddressA); + ExecutionPayload blockRequestResult2B = CreateBlockRequest(blockRequestResult1, TestItem.AddressA); ResultWrapper newPayloadResult2B = await rpc.engine_newPayloadV1(blockRequestResult2B); newPayloadResult2B.Data.Status.Should().Be(PayloadStatus.Valid); - ExecutionPayload blockRequestResult3B = CreateBlockRequest(chain, blockRequestResult2B, TestItem.AddressA); + ExecutionPayload blockRequestResult3B = CreateBlockRequest(blockRequestResult2B, TestItem.AddressA); ResultWrapper newPayloadResult3B = await rpc.engine_newPayloadV1(blockRequestResult3B); newPayloadResult3B.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1393,7 +1386,7 @@ public async Task inconsistent_safe_hash() IEngineRpcModule rpc = CreateEngineModule(chain); ExecutionPayload blockRequestResult1 = CreateBlockRequest( - chain, CreateParentBlockRequestOnHead(chain.BlockTree), + CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressA); ResultWrapper newPayloadResult1 = await rpc.engine_newPayloadV1(blockRequestResult1); newPayloadResult1.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1403,15 +1396,15 @@ public async Task inconsistent_safe_hash() ResultWrapper forkchoiceUpdatedResult1 = await rpc.engine_forkchoiceUpdatedV1(forkChoiceState1); forkchoiceUpdatedResult1.Data.PayloadStatus.Status.Should().Be(PayloadStatus.Valid); - ExecutionPayload blockRequestResult2A = CreateBlockRequest(chain, blockRequestResult1, TestItem.AddressB); + ExecutionPayload blockRequestResult2A = CreateBlockRequest(blockRequestResult1, TestItem.AddressB); ResultWrapper newPayloadResult2A = await rpc.engine_newPayloadV1(blockRequestResult2A); newPayloadResult2A.Data.Status.Should().Be(PayloadStatus.Valid); - ExecutionPayload blockRequestResult2B = CreateBlockRequest(chain, blockRequestResult1, TestItem.AddressA); + ExecutionPayload blockRequestResult2B = CreateBlockRequest(blockRequestResult1, TestItem.AddressA); ResultWrapper newPayloadResult2B = await rpc.engine_newPayloadV1(blockRequestResult2B); newPayloadResult2B.Data.Status.Should().Be(PayloadStatus.Valid); - ExecutionPayload blockRequestResult3B = CreateBlockRequest(chain, blockRequestResult2B, TestItem.AddressA); + ExecutionPayload blockRequestResult3B = CreateBlockRequest(blockRequestResult2B, TestItem.AddressA); ResultWrapper newPayloadResult3B = await rpc.engine_newPayloadV1(blockRequestResult3B); newPayloadResult3B.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1449,7 +1442,7 @@ await rpc.engine_forkchoiceUpdatedV1(forkChoiceStateGen, // Add one block ExecutionPayload executionPayloadV11 = CreateBlockRequest( - chain, CreateParentBlockRequestOnHead(chain.BlockTree), + CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressA); executionPayloadV11.PrevRandao = prevRandao1; @@ -1474,7 +1467,7 @@ await rpc.engine_forkchoiceUpdatedV1(forkChoiceState1, { ExecutionPayload executionPayloadV12 = CreateBlockRequest( - chain, executionPayloadV11, + executionPayloadV11, TestItem.AddressA); executionPayloadV12.PrevRandao = prevRandao3; @@ -1497,7 +1490,9 @@ await rpc.engine_forkchoiceUpdatedV1(forkChoiceState1, // re-org { - ExecutionPayload executionPayloadV13 = CreateBlockRequest(chain, executionPayloadV11, TestItem.AddressA); + ExecutionPayload executionPayloadV13 = CreateBlockRequest( + executionPayloadV11, + TestItem.AddressA); executionPayloadV13.PrevRandao = prevRandao2; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V2.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V2.cs index 88afacbe088..92081e7ef40 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V2.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V2.cs @@ -68,7 +68,7 @@ public virtual async Task Should_process_block_as_expected_V2(string latestValid }; string expectedPayloadId = payloadId; - string response = await RpcTest.TestSerializedRequest(rpc, "engine_forkchoiceUpdatedV2", @params!); + string response = RpcTest.TestSerializedRequest(rpc, "engine_forkchoiceUpdatedV2", @params!); JsonRpcSuccessResponse? successResponse = chain.JsonSerializer.Deserialize(response); successResponse.Should().NotBeNull(); @@ -114,7 +114,7 @@ public virtual async Task Should_process_block_as_expected_V2(string latestValid ); GetPayloadV2Result expectedPayload = new(block, UInt256.Zero); - response = await RpcTest.TestSerializedRequest(rpc, "engine_getPayloadV2", expectedPayloadId); + response = RpcTest.TestSerializedRequest(rpc, "engine_getPayloadV2", expectedPayloadId); successResponse = chain.JsonSerializer.Deserialize(response); successResponse.Should().NotBeNull(); @@ -124,7 +124,7 @@ public virtual async Task Should_process_block_as_expected_V2(string latestValid Result = expectedPayload })); - response = await RpcTest.TestSerializedRequest(rpc, "engine_newPayloadV2", + response = RpcTest.TestSerializedRequest(rpc, "engine_newPayloadV2", chain.JsonSerializer.Serialize(new ExecutionPayload(block))); successResponse = chain.JsonSerializer.Deserialize(response); @@ -148,7 +148,7 @@ public virtual async Task Should_process_block_as_expected_V2(string latestValid }; @params = new[] { chain.JsonSerializer.Serialize(fcuState), null }; - response = await RpcTest.TestSerializedRequest(rpc, "engine_forkchoiceUpdatedV2", @params!); + response = RpcTest.TestSerializedRequest(rpc, "engine_forkchoiceUpdatedV2", @params!); successResponse = chain.JsonSerializer.Deserialize(response); successResponse.Should().NotBeNull(); @@ -191,7 +191,7 @@ public virtual async Task forkchoiceUpdatedV1_should_fail_with_withdrawals() chain.JsonSerializer.Serialize(fcuState), chain.JsonSerializer.Serialize(payloadAttrs) }; - string response = await RpcTest.TestSerializedRequest(rpcModule, "engine_forkchoiceUpdatedV1", @params); + string response = RpcTest.TestSerializedRequest(rpcModule, "engine_forkchoiceUpdatedV1", @params); JsonRpcErrorResponse? errorResponse = chain.JsonSerializer.Deserialize(response); errorResponse.Should().NotBeNull(); @@ -228,7 +228,7 @@ string BlockHash chain.JsonSerializer.Serialize(fcuState), chain.JsonSerializer.Serialize(payloadAttrs) }; - string response = await RpcTest.TestSerializedRequest(rpcModule, "engine_forkchoiceUpdatedV2", @params); + string response = RpcTest.TestSerializedRequest(rpcModule, "engine_forkchoiceUpdatedV2", @params); JsonRpcErrorResponse? errorResponse = chain.JsonSerializer.Deserialize(response); errorResponse.Should().NotBeNull(); @@ -340,7 +340,8 @@ public virtual async Task }; IEnumerable payloadBodies = rpc.engine_getPayloadBodiesByHashV1(blockHashes).Result.Data; - ExecutionPayloadBodyV1Result?[] expected = { + ExecutionPayloadBodyV1Result[] expected = new ExecutionPayloadBodyV1Result?[] + { new(Array.Empty(), withdrawals), null, new(txs, withdrawals) }; @@ -368,7 +369,7 @@ await rpc.engine_forkchoiceUpdatedV2(new ForkchoiceStateV1(executionPayload2.Blo IEnumerable payloadBodies = rpc.engine_getPayloadBodiesByRangeV1(1, 3).Result.Data; - ExecutionPayloadBodyV1Result?[] expected = { new(txs, withdrawals) }; + ExecutionPayloadBodyV1Result[] expected = new ExecutionPayloadBodyV1Result?[] { new(txs, withdrawals) }; payloadBodies.Should().BeEquivalentTo(expected, o => o.WithStrictOrdering()); } @@ -380,7 +381,7 @@ public async Task getPayloadBodiesByRangeV1_empty_response() IEngineRpcModule rpc = CreateEngineModule(chain); IEnumerable payloadBodies = rpc.engine_getPayloadBodiesByRangeV1(1, 1).Result.Data; - ExecutionPayloadBodyV1Result?[] expected = Array.Empty(); + ExecutionPayloadBodyV1Result[] expected = Array.Empty(); payloadBodies.Should().BeEquivalentTo(expected); } @@ -556,7 +557,7 @@ public virtual async Task newPayloadV1_should_fail_with_withdrawals() Withdrawals = Enumerable.Empty() }; - string response = await RpcTest.TestSerializedRequest(rpcModule, "engine_newPayloadV1", + string response = RpcTest.TestSerializedRequest(rpcModule, "engine_newPayloadV1", chain.JsonSerializer.Serialize(expectedPayload)); JsonRpcErrorResponse? errorResponse = chain.JsonSerializer.Deserialize(response); @@ -600,7 +601,7 @@ string BlockHash Withdrawals = input.Withdrawals }; - string response = await RpcTest.TestSerializedRequest(rpcModule, "engine_newPayloadV2", + string response = RpcTest.TestSerializedRequest(rpcModule, "engine_newPayloadV2", chain.JsonSerializer.Serialize(expectedPayload)); JsonRpcErrorResponse? errorResponse = chain.JsonSerializer.Deserialize(response); @@ -637,8 +638,7 @@ public async Task executePayloadV2_works_correctly_when_0_withdrawals_applied(( { using MergeTestBlockchain chain = await CreateBlockchain(input.ReleaseSpec); IEngineRpcModule rpc = CreateEngineModule(chain); - ExecutionPayload executionPayload = CreateBlockRequest(chain, - CreateParentBlockRequestOnHead(chain.BlockTree), + ExecutionPayload executionPayload = CreateBlockRequest(CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, input.Withdrawals); ResultWrapper resultWrapper = await rpc.engine_newPayloadV2(executionPayload); @@ -707,7 +707,7 @@ public virtual async Task Should_handle_withdrawals_transition_when_Shanghai_for // Block without withdrawals, Timestamp = 2 ExecutionPayload executionPayload = - CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); + CreateBlockRequest(CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper resultWrapper = await rpc.engine_newPayloadV2(executionPayload); resultWrapper.Data.Status.Should().Be(PayloadStatus.Valid); @@ -873,7 +873,8 @@ private async Task BuildAndSendNewBlockV2( private async Task SendNewBlockV2(IEngineRpcModule rpc, MergeTestBlockchain chain, IList? withdrawals) { - ExecutionPayload executionPayload = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals); + ExecutionPayload executionPayload = CreateBlockRequest( + CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals); ResultWrapper executePayloadResult = await rpc.engine_newPayloadV2(executionPayload); executePayloadResult.Data.Status.Should().Be(PayloadStatus.Valid); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs index 43b935389f2..45ac44b43cc 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs @@ -3,12 +3,9 @@ using System; using System.Collections.Generic; -using System.IO.Abstractions; -using System.Linq; using System.Threading; using System.Threading.Tasks; using FluentAssertions; -using k8s.Models; using Nethermind.Consensus.Producers; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -18,95 +15,27 @@ using Nethermind.Crypto; using Nethermind.Evm; using Nethermind.JsonRpc; -using Nethermind.JsonRpc.Modules; -using Nethermind.JsonRpc.Test; using Nethermind.Logging; using Nethermind.Merge.Plugin.Data; using Nethermind.Merge.Plugin.GC; using Nethermind.Merge.Plugin.Handlers; -using Nethermind.Serialization.Json; -using Nethermind.Serialization.Rlp; -using Nethermind.Specs; using Nethermind.Specs.Forks; -using Newtonsoft.Json.Linq; using NSubstitute; using NUnit.Framework; +using Transaction = Nethermind.Core.Transaction; namespace Nethermind.Merge.Plugin.Test; public partial class EngineModuleTests { - [Test] - public async Task NewPayloadV1_should_decline_post_cancun() - { - MergeTestBlockchain chain = await CreateBlockchain(releaseSpec: Cancun.Instance); - IEngineRpcModule rpcModule = CreateEngineModule(chain); - ExecutionPayload executionPayload = CreateBlockRequest( - chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty()); - - ResultWrapper result = await rpcModule.engine_newPayloadV1(executionPayload); - - Assert.That(result.ErrorCode, Is.EqualTo(ErrorCodes.InvalidParams)); - } - - [Test] - public async Task NewPayloadV2_should_decline_post_cancun() - { - MergeTestBlockchain chain = await CreateBlockchain(releaseSpec: Cancun.Instance); - IEngineRpcModule rpcModule = CreateEngineModule(chain); - ExecutionPayload executionPayload = CreateBlockRequest( - chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty()); - - ResultWrapper result = await rpcModule.engine_newPayloadV2(executionPayload); - - Assert.That(result.ErrorCode, Is.EqualTo(ErrorCodes.UnsupportedFork)); - } - - [TestCaseSource(nameof(CancunFieldsTestSource))] - public async Task NewPayloadV2_should_decline_pre_cancun_with_cancun_fields(ulong? blobGasUsed, ulong? excessBlobGas, Keccak? parentBlockBeaconRoot) - { - MergeTestBlockchain chain = await CreateBlockchain(releaseSpec: Shanghai.Instance); - IEngineRpcModule rpcModule = CreateEngineModule(chain); - ExecutionPayload executionPayload = CreateBlockRequest( - chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty(), - blobGasUsed: blobGasUsed, excessBlobGas: excessBlobGas, parentBeaconBlockRoot: parentBlockBeaconRoot); - - ResultWrapper result = await rpcModule.engine_newPayloadV2(executionPayload); - - return result.ErrorCode; - } - - [Test] - public async Task NewPayloadV3_should_decline_pre_cancun_payloads() - { - MergeTestBlockchain chain = await CreateBlockchain(releaseSpec: Shanghai.Instance); - IEngineRpcModule rpcModule = CreateEngineModule(chain); - ExecutionPayloadV3 executionPayload = CreateBlockRequestV3( - chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty()); - - ResultWrapper result = await rpcModule.engine_newPayloadV3(executionPayload, new byte[0][], executionPayload.ParentBeaconBlockRoot); - - Assert.That(result.ErrorCode, Is.EqualTo(ErrorCodes.UnsupportedFork)); - } - - [Test] - public async Task GetPayloadV3_should_decline_pre_cancun_payloads() + [TestCaseSource(nameof(ExcessDataGasInGetPayloadV3ForDifferentSpecTestSource))] + public async Task ExccessDataGas_should_present_in_cancun_only((IReleaseSpec Spec, bool IsExcessDataGasSet) input) { - (IEngineRpcModule rpcModule, string payloadId, _, _) = await BuildAndGetPayloadV3Result(Shanghai.Instance); + (IEngineRpcModule rpcModule, string payloadId) = await BuildAndGetPayloadV3Result(input.Spec); ResultWrapper getPayloadResult = await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId)); - Assert.That(getPayloadResult.ErrorCode, - Is.EqualTo(ErrorCodes.UnsupportedFork)); - } - - [Test] - public async Task GetPayloadV2_should_decline_post_cancun_payloads() - { - (IEngineRpcModule rpcModule, string payloadId, _, _) = await BuildAndGetPayloadV3Result(Cancun.Instance); - ResultWrapper getPayloadResult = - await rpcModule.engine_getPayloadV2(Bytes.FromHexString(payloadId)); - Assert.That(getPayloadResult.ErrorCode, - Is.EqualTo(ErrorCodes.UnsupportedFork)); + Assert.That(getPayloadResult.Data!.ExecutionPayload.ExcessDataGas.HasValue, + Is.EqualTo(input.IsExcessDataGasSet)); } [Test] @@ -128,160 +57,29 @@ public async Task GetPayloadV3_should_fail_on_unknown_payload() [TestCase(2)] [TestCase(3)] [TestCase(4)] - public async Task GetPayloadV3_should_return_all_the_blobs(int blobTxCount) + public async Task PayloadV3_should_return_all_the_blobs(int blobTxCount) { - (IEngineRpcModule rpcModule, string payloadId, _, _) = await BuildAndGetPayloadV3Result(Cancun.Instance, blobTxCount); - ResultWrapper result = await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId)); + (IEngineRpcModule rpcModule, string payloadId) = await BuildAndGetPayloadV3Result(Cancun.Instance, blobTxCount); + var result = await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId)); BlobsBundleV1 getPayloadResultBlobsBundle = result.Data!.BlobsBundle!; - Assert.That(result.Data.ExecutionPayload.BlobGasUsed, Is.EqualTo(BlobGasCalculator.CalculateBlobGas(blobTxCount))); + Assert.That(result.Data.ExecutionPayload.DataGasUsed, Is.EqualTo(DataGasCalculator.CalculateDataGas(blobTxCount))); + Assert.That(result.Data.ExecutionPayload.ExcessDataGas, Is.Not.Null); Assert.That(getPayloadResultBlobsBundle.Blobs!.Length, Is.EqualTo(blobTxCount)); Assert.That(getPayloadResultBlobsBundle.Commitments!.Length, Is.EqualTo(blobTxCount)); Assert.That(getPayloadResultBlobsBundle.Proofs!.Length, Is.EqualTo(blobTxCount)); } - [TestCase(false, PayloadStatus.Valid)] - [TestCase(true, PayloadStatus.Invalid)] - public virtual async Task NewPayloadV3_should_decline_mempool_encoding(bool inMempoolForm, string expectedPayloadStatus) - { - (IEngineRpcModule rpcModule, string payloadId, Transaction[] transactions, _) = await BuildAndGetPayloadV3Result(Cancun.Instance, 1); - - ExecutionPayloadV3 payload = (await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId))).Data!.ExecutionPayload; - - TxDecoder rlpEncoder = new(); - RlpBehaviors rlpBehaviors = (inMempoolForm ? RlpBehaviors.InMempoolForm : RlpBehaviors.None) | RlpBehaviors.SkipTypedWrapping; - payload.Transactions = transactions.Select(tx => rlpEncoder.Encode(tx, rlpBehaviors).Bytes).ToArray(); - byte[]?[] blobVersionedHashes = transactions.SelectMany(tx => tx.BlobVersionedHashes ?? Array.Empty()).ToArray(); - - ResultWrapper result = await rpcModule.engine_newPayloadV3(payload, blobVersionedHashes, payload.ParentBeaconBlockRoot); - - Assert.That(result.ErrorCode, Is.EqualTo(ErrorCodes.None)); - result.Data.Status.Should().Be(expectedPayloadStatus); - } - - [TestCase(false, PayloadStatus.Syncing)] - [TestCase(true, PayloadStatus.Invalid)] - public virtual async Task NewPayloadV3_should_decline_incorrect_blobgasused(bool isBlobGasUsedBroken, string expectedPayloadStatus) - { - (IEngineRpcModule prevRpcModule, string payloadId, Transaction[] transactions, _) = await BuildAndGetPayloadV3Result(Cancun.Instance, 1); - ExecutionPayloadV3 payload = (await prevRpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId))).Data!.ExecutionPayload; - - if (isBlobGasUsedBroken) - { - payload.BlobGasUsed += 1; - } - - payload.ParentHash = TestItem.KeccakA; - payload.BlockNumber = 2; - payload.TryGetBlock(out Block? b); - payload.BlockHash = b!.CalculateHash(); - - byte[]?[] blobVersionedHashes = transactions.SelectMany(tx => tx.BlobVersionedHashes ?? Array.Empty()).ToArray(); - ResultWrapper result = await prevRpcModule.engine_newPayloadV3(payload, blobVersionedHashes, payload.ParentBeaconBlockRoot); - - Assert.That(result.ErrorCode, Is.EqualTo(ErrorCodes.None)); - result.Data.Status.Should().Be(expectedPayloadStatus); - } - [Test] public async Task NewPayloadV3_should_decline_null_blobversionedhashes() - { - (JsonRpcService jsonRpcService, JsonRpcContext context, EthereumJsonSerializer serializer, ExecutionPayloadV3 executionPayload) - = await PreparePayloadRequestEnv(); - - string executionPayloadString = serializer.Serialize(executionPayload); - string blobsString = serializer.Serialize(Array.Empty()); - - JsonRpcRequest request = RpcTest.GetJsonRequest(nameof(IEngineRpcModule.engine_newPayloadV3), - executionPayloadString, null!); - JsonRpcErrorResponse? response = (await jsonRpcService.SendRequestAsync(request, context)) as JsonRpcErrorResponse; - Assert.That(response?.Error, Is.Not.Null); - Assert.That(response!.Error!.Code, Is.EqualTo(ErrorCodes.InvalidParams)); - } - - private async Task<(JsonRpcService jsonRpcService, JsonRpcContext context, EthereumJsonSerializer serializer, ExecutionPayloadV3 correctExecutionPayload)> - PreparePayloadRequestEnv() { MergeTestBlockchain chain = await CreateBlockchain(releaseSpec: Cancun.Instance); IEngineRpcModule rpcModule = CreateEngineModule(chain); - JsonRpcConfig jsonRpcConfig = new() { EnabledModules = new[] { "Engine" } }; - RpcModuleProvider moduleProvider = new(new FileSystem(), jsonRpcConfig, LimboLogs.Instance); - moduleProvider.Register(new SingletonModulePool(new SingletonFactory(rpcModule), true)); - - ExecutionPayloadV3 executionPayload = CreateBlockRequestV3( - chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty(), blobGasUsed: 0, excessBlobGas: 0, parentBeaconBlockRoot: TestItem.KeccakA); - - return (new(moduleProvider, LimboLogs.Instance, jsonRpcConfig), new(RpcEndpoint.Http), new(), executionPayload); - } - - [Test] - public async Task NewPayloadV3_should_decline_empty_fields() - { - (JsonRpcService jsonRpcService, JsonRpcContext context, EthereumJsonSerializer serializer, ExecutionPayloadV3 executionPayload) - = await PreparePayloadRequestEnv(); - - string executionPayloadString = serializer.Serialize(executionPayload); - string blobsString = serializer.Serialize(Array.Empty()); - string parentBeaconBlockRootString = serializer.Serialize(TestItem.KeccakA.BytesToArray()); - - { - JObject executionPayloadAsJObject = serializer.Deserialize(executionPayloadString); - JsonRpcRequest request = RpcTest.GetJsonRequest(nameof(IEngineRpcModule.engine_newPayloadV3), - serializer.Serialize(executionPayloadAsJObject), blobsString, parentBeaconBlockRootString); - JsonRpcResponse response = await jsonRpcService.SendRequestAsync(request, context); - Assert.That(response is JsonRpcSuccessResponse); - } - - string[] props = serializer.Deserialize(serializer.Serialize(new ExecutionPayload())) - .Properties().Select(prop => prop.Name).ToArray(); - - foreach (string prop in props) - { - JObject executionPayloadAsJObject = serializer.Deserialize(executionPayloadString); - executionPayloadAsJObject[prop] = null; - - JsonRpcRequest request = RpcTest.GetJsonRequest(nameof(IEngineRpcModule.engine_newPayloadV3), - serializer.Serialize(executionPayloadAsJObject), blobsString); - JsonRpcErrorResponse? response = (await jsonRpcService.SendRequestAsync(request, context)) as JsonRpcErrorResponse; - Assert.That(response?.Error, Is.Not.Null); - Assert.That(response!.Error!.Code, Is.EqualTo(ErrorCodes.InvalidParams)); - } - - foreach (string prop in props) - { - JObject executionPayloadAsJObject = serializer.Deserialize(executionPayloadString); - executionPayloadAsJObject.Remove(prop); - - JsonRpcRequest request = RpcTest.GetJsonRequest(nameof(IEngineRpcModule.engine_newPayloadV3), - serializer.Serialize(executionPayloadAsJObject), blobsString); - JsonRpcErrorResponse? response = (await jsonRpcService.SendRequestAsync(request, context)) as JsonRpcErrorResponse; - Assert.That(response?.Error, Is.Not.Null); - Assert.That(response!.Error!.Code, Is.EqualTo(ErrorCodes.InvalidParams)); - } - } - - [TestCaseSource(nameof(ForkchoiceUpdatedV3DeclinedTestCaseSource))] - [TestCaseSource(nameof(ForkchoiceUpdatedV3AcceptedTestCaseSource))] - - public async Task ForkChoiceUpdated_should_return_proper_error_code(IReleaseSpec releaseSpec, string method, bool isBeaconRootSet) - { - MergeTestBlockchain chain = await CreateBlockchain(releaseSpec: releaseSpec); - IEngineRpcModule rpcModule = CreateEngineModule(chain); - ForkchoiceStateV1 fcuState = new(Keccak.Zero, Keccak.Zero, Keccak.Zero); - PayloadAttributes payloadAttributes = new() - { - Timestamp = chain.BlockTree.Head!.Timestamp, - PrevRandao = Keccak.Zero, - SuggestedFeeRecipient = Address.Zero, - Withdrawals = new List(), - ParentBeaconBlockRoot = isBeaconRootSet ? Keccak.Zero : null, - }; + ExecutionPayload executionPayload = CreateBlockRequest( + CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty()); - string response = await RpcTest.TestSerializedRequest(rpcModule, method, - chain.JsonSerializer.Serialize(fcuState), - chain.JsonSerializer.Serialize(payloadAttributes)); - JsonRpcErrorResponse errorResponse = chain.JsonSerializer.Deserialize(response); + ResultWrapper errorCode = (await rpcModule.engine_newPayloadV3(executionPayload, null!)); - return errorResponse.Error?.Code ?? ErrorCodes.None; + Assert.That(errorCode.Data.Status, Is.EqualTo(PayloadStatus.Invalid)); } private const string FurtherValidationStatus = "FurtherValidation"; @@ -349,7 +147,7 @@ public async Task NewPayloadV3_should_verify_blob_versioned_hashes_again .WithTo(TestItem.AddressB) .WithValue(1.GWei()) .WithGasPrice(1.GWei()) - .WithMaxFeePerBlobGas(1.GWei()) + .WithMaxFeePerDataGas(1.GWei()) .WithChainId(chainId) .WithSenderAddress(TestItem.AddressA) .WithBlobVersionedHashes(txBlobVersionedHashes) @@ -364,121 +162,13 @@ public async Task NewPayloadV3_should_verify_blob_versioned_hashes_again (MergeTestBlockchain blockchain, IEngineRpcModule engineRpcModule) = await MockRpc(); (byte[][] blobVersionedHashes, Transaction[] transactions) = BuildTransactionsAndBlobVersionedHashesList(hashesFirstBytes, transactionsAndFirstBytesOfTheirHashes, blockchain.SpecProvider.ChainId); - ExecutionPayloadV3 executionPayload = CreateBlockRequestV3( - blockchain, CreateParentBlockRequestOnHead(blockchain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty(), 0, 0, transactions: transactions, parentBeaconBlockRoot: Keccak.Zero); - ResultWrapper result = await engineRpcModule.engine_newPayloadV3(executionPayload, blobVersionedHashes, Keccak.Zero); + ExecutionPayload executionPayload = CreateBlockRequest( + CreateParentBlockRequestOnHead(blockchain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty(), transactions: transactions); + ResultWrapper result = await engineRpcModule.engine_newPayloadV3(executionPayload, blobVersionedHashes); return result.Data.Status; } - [Test] - public async Task ForkChoiceUpdated_should_return_invalid_params_but_change_latest_block() - { - (IEngineRpcModule rpcModule, string payloadId, Transaction[] transactions, MergeTestBlockchain chain) = - await BuildAndGetPayloadV3Result(Cancun.Instance, 0); - ExecutionPayloadV3 payload = (await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId))).Data!.ExecutionPayload; - - ForkchoiceStateV1 fcuState = new(payload.BlockHash, payload.BlockHash, payload.BlockHash); - PayloadAttributes payloadAttributes = new() - { - Timestamp = payload.Timestamp + 1, - PrevRandao = Keccak.Zero, - SuggestedFeeRecipient = Address.Zero, - Withdrawals = new List(), - ParentBeaconBlockRoot = null, - }; - - await rpcModule.engine_newPayloadV3(payload, Array.Empty(), payload.ParentBeaconBlockRoot); - ResultWrapper fcuResponse = await rpcModule.engine_forkchoiceUpdatedV3(fcuState, payloadAttributes); - Assert.Multiple(() => - { - Assert.That(fcuResponse.Result.ResultType, Is.EqualTo(ResultType.Failure)); - Assert.That(fcuResponse.ErrorCode, Is.EqualTo(ErrorCodes.InvalidParams)); - Assert.That(chain.BlockTree.Head!.Hash, Is.EqualTo(payload.BlockHash)); - }); - } - - [Test] - public async Task ForkChoiceUpdated_should_return_unsupported_fork_but_change_latest_block() - { - (IEngineRpcModule rpcModule, string payloadId, Transaction[] transactions, MergeTestBlockchain chain) = - await BuildAndGetPayloadV3Result(Cancun.Instance, 0); - ExecutionPayloadV3 payload = (await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId))).Data!.ExecutionPayload; - - ForkchoiceStateV1 fcuState = new(payload.BlockHash, payload.BlockHash, payload.BlockHash); - PayloadAttributes payloadAttributes = new() - { - Timestamp = payload.Timestamp + 1, - PrevRandao = Keccak.Zero, - SuggestedFeeRecipient = Address.Zero, - Withdrawals = new List(), - }; - - await rpcModule.engine_newPayloadV3(payload, Array.Empty(), payload.ParentBeaconBlockRoot); - ResultWrapper fcuResponse = await rpcModule.engine_forkchoiceUpdatedV2(fcuState, payloadAttributes); - Assert.Multiple(() => - { - Assert.That(fcuResponse.Result.ResultType, Is.EqualTo(ResultType.Failure)); - Assert.That(fcuResponse.ErrorCode, Is.EqualTo(ErrorCodes.UnsupportedFork)); - Assert.That(chain.BlockTree.Head!.Hash, Is.EqualTo(payload.BlockHash)); - }); - } - - public static IEnumerable ForkchoiceUpdatedV3DeclinedTestCaseSource - { - get - { - yield return new TestCaseData(Shanghai.Instance, nameof(IEngineRpcModule.engine_forkchoiceUpdatedV3), false) - { - TestName = "ForkchoiceUpdatedV3 To Request Shanghai Payload, Nil Beacon Root", - ExpectedResult = ErrorCodes.InvalidParams, - }; - yield return new TestCaseData(Shanghai.Instance, nameof(IEngineRpcModule.engine_forkchoiceUpdatedV3), true) - { - TestName = "ForkchoiceUpdatedV3 To Request Shanghai Payload, Zero Beacon Root", - ExpectedResult = ErrorCodes.UnsupportedFork, - }; - yield return new TestCaseData(Shanghai.Instance, nameof(IEngineRpcModule.engine_forkchoiceUpdatedV2), true) - { - TestName = "ForkchoiceUpdatedV2 To Request Shanghai Payload, Zero Beacon Root", - ExpectedResult = ErrorCodes.InvalidParams, - }; - - yield return new TestCaseData(Cancun.Instance, nameof(IEngineRpcModule.engine_forkchoiceUpdatedV2), true) - { - TestName = "ForkchoiceUpdatedV2 To Request Cancun Payload, Zero Beacon Root", - ExpectedResult = ErrorCodes.InvalidParams, - }; - yield return new TestCaseData(Cancun.Instance, nameof(IEngineRpcModule.engine_forkchoiceUpdatedV2), false) - { - TestName = "ForkchoiceUpdatedV2 To Request Cancun Payload, Nil Beacon Root", - ExpectedResult = ErrorCodes.UnsupportedFork, - }; - yield return new TestCaseData(Cancun.Instance, nameof(IEngineRpcModule.engine_forkchoiceUpdatedV3), false) - { - TestName = "ForkchoiceUpdatedV3 To Request Cancun Payload, Nil Beacon Root", - ExpectedResult = ErrorCodes.InvalidParams, - }; - } - } - - public static IEnumerable ForkchoiceUpdatedV3AcceptedTestCaseSource - { - get - { - yield return new TestCaseData(Shanghai.Instance, nameof(IEngineRpcModule.engine_forkchoiceUpdatedV2), false) - { - TestName = "ForkchoiceUpdatedV2 To Request Shanghai Payload, Nil Beacon Root", - ExpectedResult = ErrorCodes.None, - }; - yield return new TestCaseData(Cancun.Instance, nameof(IEngineRpcModule.engine_forkchoiceUpdatedV3), true) - { - TestName = "ForkchoiceUpdatedV3 To Request Cancun Payload, Zero Beacon Root", - ExpectedResult = ErrorCodes.None, - }; - } - } - public static IEnumerable BlobVersionedHashesMatchTestSource { get @@ -533,72 +223,29 @@ public static IEnumerable BlobVersionedHashesDoNotMatchTestSource } } - public static IEnumerable CancunFieldsTestSource - { - get - { - yield return new TestCaseData(null, null, null) - { - ExpectedResult = ErrorCodes.None, - TestName = "No Cancun fields", - }; - yield return new TestCaseData(0ul, null, null) - { - ExpectedResult = ErrorCodes.InvalidParams, - TestName = $"{nameof(ExecutionPayloadV3.BlobGasUsed)} is set", - }; - yield return new TestCaseData(null, 0ul, null) - { - ExpectedResult = ErrorCodes.InvalidParams, - TestName = $"{nameof(ExecutionPayloadV3.ExcessBlobGas)} is set", - }; - yield return new TestCaseData(null, null, Keccak.Zero) - { - ExpectedResult = ErrorCodes.InvalidParams, - TestName = $"{nameof(ExecutionPayloadV3.ParentBeaconBlockRoot)} is set", - }; - yield return new TestCaseData(1ul, 1ul, null) - { - ExpectedResult = ErrorCodes.InvalidParams, - TestName = $"Multiple fields #1", - }; - yield return new TestCaseData(1ul, 1ul, Keccak.Zero) - { - ExpectedResult = ErrorCodes.InvalidParams, - TestName = $"Multiple fields #2", - }; - yield return new TestCaseData(1ul, null, Keccak.Zero) - { - ExpectedResult = ErrorCodes.InvalidParams, - TestName = $"Multiple fields #3", - }; - } - } - private async Task SendNewBlockV3(IEngineRpcModule rpc, MergeTestBlockchain chain, IList? withdrawals) { - ExecutionPayloadV3 executionPayload = CreateBlockRequestV3( - chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals, 0, 0, parentBeaconBlockRoot: TestItem.KeccakE); - ResultWrapper executePayloadResult = await rpc.engine_newPayloadV3(executionPayload, Array.Empty(), executionPayload.ParentBeaconBlockRoot); + ExecutionPayload executionPayload = CreateBlockRequest( + CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals, 0, 0); + ResultWrapper executePayloadResult = await rpc.engine_newPayloadV3(executionPayload, Array.Empty()); executePayloadResult.Data.Status.Should().Be(PayloadStatus.Valid); return executionPayload; } - private async Task<(IEngineRpcModule, string, Transaction[], MergeTestBlockchain chain)> BuildAndGetPayloadV3Result( + private async Task<(IEngineRpcModule, string)> BuildAndGetPayloadV3Result( IReleaseSpec spec, int transactionCount = 0) { MergeTestBlockchain chain = await CreateBlockchain(releaseSpec: spec, null); IEngineRpcModule rpcModule = CreateEngineModule(chain); - Transaction[] txs = Array.Empty(); - if (transactionCount is not 0) { using SemaphoreSlim blockImprovementLock = new(0); ExecutionPayload executionPayload1 = await SendNewBlockV3(rpcModule, chain, new List()); - txs = BuildTransactions(chain, executionPayload1.BlockHash, TestItem.PrivateKeyA, TestItem.AddressB, (uint)transactionCount, 0, out _, out _, 1); + Transaction[] txs = BuildTransactions( + chain, executionPayload1.BlockHash, TestItem.PrivateKeyA, TestItem.AddressB, (uint)transactionCount, 0, out _, out _, 1); chain.AddTransactions(txs); EventHandler onBlockImprovedHandler = (_, _) => blockImprovementLock.Release(1); @@ -613,14 +260,18 @@ private async Task SendNewBlockV3(IEngineRpcModule rpc, MergeT Timestamp = chain.BlockTree.Head!.Timestamp + 1, PrevRandao = TestItem.KeccakH, SuggestedFeeRecipient = TestItem.AddressF, - Withdrawals = new List { TestItem.WithdrawalA_1Eth }, - ParentBeaconBlockRoot = spec.IsBeaconBlockRootAvailable ? TestItem.KeccakE : null + Withdrawals = new List { TestItem.WithdrawalA_1Eth } }; Keccak currentHeadHash = chain.BlockTree.HeadHash; ForkchoiceStateV1 forkchoiceState = new(currentHeadHash, currentHeadHash, currentHeadHash); - string payloadId = spec.IsBeaconBlockRootAvailable - ? rpcModule.engine_forkchoiceUpdatedV3(forkchoiceState, payloadAttributes).Result.Data.PayloadId! - : rpcModule.engine_forkchoiceUpdatedV2(forkchoiceState, payloadAttributes).Result.Data.PayloadId!; - return (rpcModule, payloadId, txs, chain); + string payloadId = rpcModule.engine_forkchoiceUpdatedV2(forkchoiceState, payloadAttributes).Result.Data + .PayloadId!; + return (rpcModule, payloadId); + } + + protected static IEnumerable<(IReleaseSpec Spec, bool IsExcessDataGasSet)> ExcessDataGasInGetPayloadV3ForDifferentSpecTestSource() + { + yield return (Shanghai.Instance, false); + yield return (Cancun.Instance, true); } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidBlockInterceptorTest.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidBlockInterceptorTest.cs index 90e1e1d1955..044eef33269 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidBlockInterceptorTest.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidBlockInterceptorTest.cs @@ -6,7 +6,6 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; -using Nethermind.Crypto; using Nethermind.Logging; using Nethermind.Merge.Plugin.InvalidChainTracker; using Nethermind.Specs; @@ -17,9 +16,9 @@ namespace Nethermind.Merge.Plugin.Test; public class InvalidBlockInterceptorTest { - private IBlockValidator _baseValidator = null!; - private IInvalidChainTracker _tracker = null!; - private InvalidBlockInterceptor _invalidBlockInterceptor = null!; + private IBlockValidator _baseValidator; + private IInvalidChainTracker _tracker; + private InvalidBlockInterceptor _invalidBlockInterceptor; [SetUp] public void Setup() @@ -40,14 +39,14 @@ public void TestValidateSuggestedBlock(bool baseReturnValue, bool isInvalidBlock _baseValidator.ValidateSuggestedBlock(block).Returns(baseReturnValue); _invalidBlockInterceptor.ValidateSuggestedBlock(block); - _tracker.Received().SetChildParent(block.GetOrCalculateHash(), block.ParentHash!); + _tracker.Received().SetChildParent(block.Hash, block.ParentHash); if (isInvalidBlockReported) { - _tracker.Received().OnInvalidBlock(block.GetOrCalculateHash(), block.ParentHash); + _tracker.Received().OnInvalidBlock(block.Hash, block.ParentHash); } else { - _tracker.DidNotReceive().OnInvalidBlock(block.GetOrCalculateHash(), block.ParentHash); + _tracker.DidNotReceive().OnInvalidBlock(block.Hash, block.ParentHash); } } @@ -61,14 +60,14 @@ public void TestValidateProcessedBlock(bool baseReturnValue, bool isInvalidBlock _baseValidator.ValidateProcessedBlock(block, txs, suggestedBlock).Returns(baseReturnValue); _invalidBlockInterceptor.ValidateProcessedBlock(block, txs, suggestedBlock); - _tracker.Received().SetChildParent(suggestedBlock.GetOrCalculateHash(), suggestedBlock.ParentHash!); + _tracker.Received().SetChildParent(suggestedBlock.Hash, suggestedBlock.ParentHash); if (isInvalidBlockReported) { - _tracker.Received().OnInvalidBlock(suggestedBlock.GetOrCalculateHash(), suggestedBlock.ParentHash); + _tracker.Received().OnInvalidBlock(suggestedBlock.Hash, suggestedBlock.ParentHash); } else { - _tracker.DidNotReceive().OnInvalidBlock(suggestedBlock.GetOrCalculateHash(), suggestedBlock.ParentHash); + _tracker.DidNotReceive().OnInvalidBlock(suggestedBlock.Hash, suggestedBlock.ParentHash); } } @@ -81,8 +80,8 @@ public void TestInvalidBlockhashShouldNotGetTracked() _baseValidator.ValidateSuggestedBlock(block).Returns(false); _invalidBlockInterceptor.ValidateSuggestedBlock(block); - _tracker.DidNotReceive().SetChildParent(block.GetOrCalculateHash(), block.ParentHash!); - _tracker.DidNotReceive().OnInvalidBlock(block.GetOrCalculateHash(), block.ParentHash); + _tracker.DidNotReceive().SetChildParent(block.Hash, block.ParentHash); + _tracker.DidNotReceive().OnInvalidBlock(block.Hash, block.ParentHash); } [Test] @@ -99,8 +98,8 @@ public void TestBlockWithNotMatchingTxShouldNotGetTracked() _baseValidator.ValidateSuggestedBlock(block).Returns(false); _invalidBlockInterceptor.ValidateSuggestedBlock(block); - _tracker.DidNotReceive().SetChildParent(block.GetOrCalculateHash(), block.ParentHash!); - _tracker.DidNotReceive().OnInvalidBlock(block.GetOrCalculateHash(), block.ParentHash); + _tracker.DidNotReceive().SetChildParent(block.Hash, block.ParentHash); + _tracker.DidNotReceive().OnInvalidBlock(block.Hash, block.ParentHash); } [Test] @@ -111,14 +110,14 @@ public void TestBlockWithIncorrectWithdrawalsShouldNotGetTracked() .TestObject; block = new Block(block.Header, block.Body.WithChangedWithdrawals( - block.Withdrawals!.Take(8).ToArray() + block.Withdrawals.Take(8).ToArray() )); _baseValidator.ValidateSuggestedBlock(block).Returns(false); _invalidBlockInterceptor.ValidateSuggestedBlock(block); - _tracker.DidNotReceive().SetChildParent(block.GetOrCalculateHash(), block.ParentHash!); - _tracker.DidNotReceive().OnInvalidBlock(block.GetOrCalculateHash(), block.ParentHash); + _tracker.DidNotReceive().SetChildParent(block.Hash, block.ParentHash); + _tracker.DidNotReceive().OnInvalidBlock(block.Hash, block.ParentHash); } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidChainTrackerTest.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidChainTrackerTest.cs index bc702268373..2893f170e96 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidChainTrackerTest.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidChainTrackerTest.cs @@ -9,7 +9,6 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; -using Nethermind.Crypto; using Nethermind.Logging; using Nethermind.Merge.Plugin.Handlers; using NSubstitute; @@ -20,7 +19,7 @@ namespace Nethermind.Merge.Plugin.Test; [TestFixture] public class InvalidChainTrackerTest { - private InvalidChainTracker.InvalidChainTracker _tracker = null!; + private InvalidChainTracker.InvalidChainTracker _tracker; [SetUp] public void Setup() @@ -181,7 +180,7 @@ public void givenAnInvalidBlock_ifParentIsNotPostMerge_thenLastValidHashShouldBe Keccak invalidBlock = Keccak.Compute("A"); BlockHeader parentBlockHeader = new BlockHeaderBuilder().TestObject; - blockCacheService.BlockCache[parentBlockHeader.GetOrCalculateHash()] = new Block(parentBlockHeader); + blockCacheService.BlockCache[parentBlockHeader.Hash] = new Block(parentBlockHeader); IPoSSwitcher poSSwitcher = Substitute.For(); poSSwitcher.IsPostMerge(parentBlockHeader).Returns(false); @@ -201,18 +200,18 @@ public void givenAnInvalidBlock_WithUnknownParent_thenGetParentFromCache() BlockHeader parentBlockHeader = new BlockHeaderBuilder() .TestObject; BlockHeader blockHeader = new BlockHeaderBuilder() - .WithParentHash(parentBlockHeader.GetOrCalculateHash()).TestObject; + .WithParentHash(parentBlockHeader.Hash).TestObject; - blockCacheService.BlockCache[blockHeader.GetOrCalculateHash()] = new Block(blockHeader); - blockCacheService.BlockCache[parentBlockHeader.GetOrCalculateHash()] = new Block(parentBlockHeader); + blockCacheService.BlockCache[blockHeader.Hash] = new Block(blockHeader); + blockCacheService.BlockCache[parentBlockHeader.Hash] = new Block(parentBlockHeader); IPoSSwitcher alwaysPos = Substitute.For(); alwaysPos.IsPostMerge(Arg.Any()).Returns(true); _tracker = new(alwaysPos, blockFinder, blockCacheService, new TestLogManager()); // Small max section size, to make sure things propagate correctly - _tracker.OnInvalidBlock(blockHeader.GetOrCalculateHash(), null); + _tracker.OnInvalidBlock(blockHeader.Hash, null); - AssertInvalid(blockHeader.GetOrCalculateHash(), parentBlockHeader.Hash); + AssertInvalid(blockHeader.Hash, parentBlockHeader.Hash); } private void AssertValid(Keccak hash) diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidHeaderInterceptorTest.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidHeaderInterceptorTest.cs index 9e876ec8552..76da84f0e28 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidHeaderInterceptorTest.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidHeaderInterceptorTest.cs @@ -5,7 +5,6 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; -using Nethermind.Crypto; using Nethermind.Logging; using Nethermind.Merge.Plugin.InvalidChainTracker; using NSubstitute; @@ -15,9 +14,9 @@ namespace Nethermind.Merge.Plugin.Test; public class InvalidHeaderInterceptorTest { - private IHeaderValidator _baseValidator = null!; - private IInvalidChainTracker _tracker = null!; - private InvalidHeaderInterceptor _invalidHeaderInterceptor = null!; + private IHeaderValidator _baseValidator; + private IInvalidChainTracker _tracker; + private InvalidHeaderInterceptor _invalidHeaderInterceptor; [SetUp] public void Setup() @@ -38,14 +37,14 @@ public void TestValidateHeader(bool baseReturnValue, bool isInvalidBlockReported _baseValidator.Validate(header, false).Returns(baseReturnValue); _invalidHeaderInterceptor.Validate(header, false); - _tracker.Received().SetChildParent(header.GetOrCalculateHash(), header.ParentHash!); + _tracker.Received().SetChildParent(header.Hash, header.ParentHash); if (isInvalidBlockReported) { - _tracker.Received().OnInvalidBlock(header.GetOrCalculateHash(), header.ParentHash); + _tracker.Received().OnInvalidBlock(header.Hash, header.ParentHash); } else { - _tracker.DidNotReceive().OnInvalidBlock(header.GetOrCalculateHash(), header.ParentHash); + _tracker.DidNotReceive().OnInvalidBlock(header.Hash, header.ParentHash); } } @@ -61,14 +60,14 @@ public void TestValidateHeaderWithParent(bool baseReturnValue, bool isInvalidBlo _baseValidator.Validate(header, parent, false).Returns(baseReturnValue); _invalidHeaderInterceptor.Validate(header, parent, false); - _tracker.Received().SetChildParent(header.GetOrCalculateHash(), header.ParentHash!); + _tracker.Received().SetChildParent(header.Hash, header.ParentHash); if (isInvalidBlockReported) { - _tracker.Received().OnInvalidBlock(header.GetOrCalculateHash(), header.ParentHash); + _tracker.Received().OnInvalidBlock(header.Hash, header.ParentHash); } else { - _tracker.DidNotReceive().OnInvalidBlock(header.GetOrCalculateHash(), header.ParentHash); + _tracker.DidNotReceive().OnInvalidBlock(header.Hash, header.ParentHash); } } @@ -85,7 +84,7 @@ public void TestInvalidBlockhashShouldNotGetTracked() _baseValidator.Validate(header, parent, false).Returns(false); _invalidHeaderInterceptor.Validate(header, parent, false); - _tracker.DidNotReceive().SetChildParent(header.GetOrCalculateHash(), header.ParentHash!); - _tracker.DidNotReceive().OnInvalidBlock(header.GetOrCalculateHash(), header.ParentHash); + _tracker.DidNotReceive().SetChildParent(header.Hash, header.ParentHash); + _tracker.DidNotReceive().OnInvalidBlock(header.Hash, header.ParentHash); } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeHeaderValidatorTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeHeaderValidatorTests.cs index 8f181c1679e..e23313b01b3 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeHeaderValidatorTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeHeaderValidatorTests.cs @@ -19,17 +19,22 @@ public class MergeHeaderValidatorTests private class Context { public IPoSSwitcher PoSSwitcher => Substitute.For(); - public IHeaderValidator PreMergeHeaderValidator => Substitute.For(); - public IBlockTree BlockTree => Substitute.For(); + private IHeaderValidator? _preMergeHeaderValidator; + public IHeaderValidator PreMergeHeaderValidator => _preMergeHeaderValidator ?? Substitute.For(); - public ISealValidator SealValidator => Substitute.For(); + private IBlockTree? _blockTree; + public IBlockTree BlockTree => _blockTree ?? Substitute.For(); - public MergeHeaderValidator MergeHeaderValidator => new( + private ISealValidator? _sealValidator; + public ISealValidator SealValidator => _sealValidator ?? Substitute.For(); + + private MergeHeaderValidator? _mergeHeaderValidator = null; + public MergeHeaderValidator MergeHeaderValidator => _mergeHeaderValidator ?? new MergeHeaderValidator( PoSSwitcher, PreMergeHeaderValidator, BlockTree, - MainnetSpecProvider.Instance, + RopstenSpecProvider.Instance, SealValidator, LimboLogs.Instance ); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs index 2460ac097f4..b3271279b1b 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs @@ -27,7 +27,7 @@ public class MergePluginTests private MergeConfig _mergeConfig = null!; private NethermindApi _context = null!; private MergePlugin _plugin = null!; - private CliquePlugin? _consensusPlugin = null; + private CliquePlugin _consensusPlugin = null; [SetUp] public void Setup() @@ -54,10 +54,9 @@ public void Setup() _context.ReceiptStorage!, _context.BlockPreprocessor!, _context.TxPool!, - _context.TransactionComparerProvider!, + _context.TransactionComparerProvider, miningConfig, _context.LogManager!); - _context.ProcessExit = Substitute.For(); _context.ChainSpec!.Clique = new CliqueParameters() { Epoch = CliqueConfig.Default.Epoch, @@ -89,11 +88,11 @@ public void SlotPerSeconds_has_different_value_in_mergeConfig_and_blocksConfig() public void Init_merge_plugin_does_not_throw_exception(bool enabled) { _mergeConfig.TerminalTotalDifficulty = enabled ? "0" : null; - Assert.DoesNotThrowAsync(async () => await _consensusPlugin!.Init(_context)); + Assert.DoesNotThrowAsync(async () => await _consensusPlugin.Init(_context)); Assert.DoesNotThrowAsync(async () => await _plugin.Init(_context)); Assert.DoesNotThrowAsync(async () => await _plugin.InitNetworkProtocol()); Assert.DoesNotThrowAsync(async () => await _plugin.InitSynchronization()); - Assert.DoesNotThrowAsync(async () => await _plugin.InitBlockProducer(_consensusPlugin!)); + Assert.DoesNotThrowAsync(async () => await _plugin.InitBlockProducer(_consensusPlugin)); Assert.DoesNotThrowAsync(async () => await _plugin.InitRpcModules()); Assert.DoesNotThrowAsync(async () => await _plugin.DisposeAsync()); } @@ -101,17 +100,17 @@ public void Init_merge_plugin_does_not_throw_exception(bool enabled) [Test] public async Task Initializes_correctly() { - Assert.DoesNotThrowAsync(async () => await _consensusPlugin!.Init(_context)); + Assert.DoesNotThrowAsync(async () => await _consensusPlugin.Init(_context)); await _plugin.Init(_context); await _plugin.InitSynchronization(); await _plugin.InitNetworkProtocol(); ISyncConfig syncConfig = _context.Config(); Assert.IsTrue(syncConfig.NetworkingEnabled); Assert.IsTrue(_context.GossipPolicy.CanGossipBlocks); - await _plugin.InitBlockProducer(_consensusPlugin!); + await _plugin.InitBlockProducer(_consensusPlugin); Assert.IsInstanceOf(_context.BlockProducer); await _plugin.InitRpcModules(); - _context.RpcModuleProvider!.Received().Register(Arg.Is>(m => m is SingletonModulePool)); + _context.RpcModuleProvider.Received().Register(Arg.Is>(m => m is SingletonModulePool)); await _plugin.DisposeAsync(); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeRewardCalculatorTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeRewardCalculatorTests.cs index 8175a677e5f..af4358b1fbf 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeRewardCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeRewardCalculatorTests.cs @@ -28,7 +28,7 @@ public void Two_uncles_from_the_same_coinbase() PoSSwitcher poSSwitcher = CreatePosSwitcher(); poSSwitcher.TryUpdateTerminalBlock(block.Header); - MergeRewardCalculator calculator = new(new RewardCalculator(MainnetSpecProvider.Instance), poSSwitcher); + MergeRewardCalculator calculator = new(new RewardCalculator(RopstenSpecProvider.Instance), poSSwitcher); BlockReward[] rewards = calculator.CalculateRewards(block); Assert.That(rewards.Length, Is.EqualTo(3)); @@ -51,7 +51,7 @@ public void One_uncle() PoSSwitcher poSSwitcher = CreatePosSwitcher(); poSSwitcher.TryUpdateTerminalBlock(block.Header); - MergeRewardCalculator calculator = new(new RewardCalculator(MainnetSpecProvider.Instance), poSSwitcher); + MergeRewardCalculator calculator = new(new RewardCalculator(RopstenSpecProvider.Instance), poSSwitcher); BlockReward[] rewards = calculator.CalculateRewards(block); Assert.That(rewards.Length, Is.EqualTo(2)); @@ -71,7 +71,7 @@ public void No_uncles() PoSSwitcher poSSwitcher = CreatePosSwitcher(); poSSwitcher.TryUpdateTerminalBlock(block.Header); - MergeRewardCalculator calculator = new(new RewardCalculator(MainnetSpecProvider.Instance), poSSwitcher); + MergeRewardCalculator calculator = new(new RewardCalculator(RopstenSpecProvider.Instance), poSSwitcher); BlockReward[] rewards = calculator.CalculateRewards(block); Assert.That(rewards.Length, Is.EqualTo(1)); @@ -84,7 +84,7 @@ public void No_uncles() [Test] public void Byzantium_reward_two_uncles() { - long blockNumber = MainnetSpecProvider.ByzantiumBlockNumber; + long blockNumber = RopstenSpecProvider.ByzantiumBlockNumber; Block uncle = Build.A.Block.WithNumber(blockNumber - 2).TestObject; Block uncle2 = Build.A.Block.WithNumber(blockNumber - 2).TestObject; Block block = Build.A.Block.WithNumber(blockNumber).WithUncles(uncle, uncle2).WithTotalDifficulty(1L).WithDifficulty(300).TestObject; @@ -93,7 +93,7 @@ public void Byzantium_reward_two_uncles() PoSSwitcher poSSwitcher = CreatePosSwitcher(); poSSwitcher.TryUpdateTerminalBlock(block.Header); - MergeRewardCalculator calculator = new(new RewardCalculator(MainnetSpecProvider.Instance), poSSwitcher); + MergeRewardCalculator calculator = new(new RewardCalculator(RopstenSpecProvider.Instance), poSSwitcher); BlockReward[] rewards = calculator.CalculateRewards(block); Assert.That(rewards.Length, Is.EqualTo(3)); @@ -109,7 +109,7 @@ public void Byzantium_reward_two_uncles() [Test] public void Constantinople_reward_two_uncles() { - long blockNumber = MainnetSpecProvider.ConstantinopleFixBlockNumber; + long blockNumber = RopstenSpecProvider.ConstantinopleBlockNumber; Block uncle = Build.A.Block.WithNumber(blockNumber - 2).TestObject; Block uncle2 = Build.A.Block.WithNumber(blockNumber - 2).TestObject; Block block = Build.A.Block.WithNumber(blockNumber).WithUncles(uncle, uncle2).WithTotalDifficulty(1L).WithDifficulty(300).TestObject; @@ -118,7 +118,7 @@ public void Constantinople_reward_two_uncles() PoSSwitcher poSSwitcher = CreatePosSwitcher(); poSSwitcher.TryUpdateTerminalBlock(block.Header); - MergeRewardCalculator calculator = new(new RewardCalculator(MainnetSpecProvider.Instance), poSSwitcher); + MergeRewardCalculator calculator = new(new RewardCalculator(RopstenSpecProvider.Instance), poSSwitcher); BlockReward[] rewards = calculator.CalculateRewards(block); Assert.That(rewards.Length, Is.EqualTo(3)); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/Nethermind.Merge.Plugin.Test.csproj b/src/Nethermind/Nethermind.Merge.Plugin.Test/Nethermind.Merge.Plugin.Test.csproj index 28c97e3f106..0b9de6e87ac 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/Nethermind.Merge.Plugin.Test.csproj +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/Nethermind.Merge.Plugin.Test.csproj @@ -3,7 +3,6 @@ net7.0 enable - true diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs index bc78258de4a..764f7403721 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs @@ -10,7 +10,6 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; -using Nethermind.Crypto; using Nethermind.Db; using Nethermind.Db.Blooms; using Nethermind.Logging; @@ -36,7 +35,7 @@ public class BeaconHeadersSyncTests { private class Context { - private IBlockTree? _blockTree; + private IBlockTree _blockTree; public IBlockTree BlockTree { get @@ -237,7 +236,7 @@ public async Task Finishes_when_all_downloaded() } [Test] - public void Feed_able_to_sync_when_new_pivot_is_set() + public async Task Feed_able_to_sync_when_new_pivot_is_set() { BlockTree syncedBlockTree = Build.A.BlockTree().OfChainLength(1000).TestObject; Block genesisBlock = syncedBlockTree.FindBlock(syncedBlockTree.GenesisHash, BlockTreeLookupOptions.None)!; @@ -278,7 +277,7 @@ public async Task Feed_able_to_connect_to_existing_chain_through_block_hash() Block genesisBlock = syncedBlockTree.FindBlock(syncedBlockTree.GenesisHash, BlockTreeLookupOptions.None)!; BlockTree blockTree = Build.A.BlockTree().TestObject; blockTree.SuggestBlock(genesisBlock); - Block? firstBlock = syncedBlockTree.FindBlock(1, BlockTreeLookupOptions.None)!; + Block? firstBlock = syncedBlockTree.FindBlock(1, BlockTreeLookupOptions.None); blockTree.SuggestBlock(firstBlock); BlockHeader? pivotHeader = syncedBlockTree.FindHeader(500, BlockTreeLookupOptions.None); IBeaconPivot pivot = PreparePivot(500, new SyncConfig(), blockTree, pivotHeader); @@ -296,7 +295,7 @@ public async Task Feed_able_to_connect_to_existing_chain_through_block_hash() ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeTrue(); blockTree.BestKnownNumber.Should().Be(6); BuildHeadersSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 2); - HeadersSyncBatch? result = await ctx.Feed.PrepareRequest(); + HeadersSyncBatch result = await ctx.Feed.PrepareRequest(); result.Should().BeNull(); blockTree.BestKnownNumber.Should().Be(6); ctx.Feed.CurrentState.Should().Be(SyncFeedState.Dormant); @@ -315,15 +314,15 @@ public void Feed_connect_invalid_chain() ctx.BeaconPivot = PreparePivot(99, new SyncConfig(), ctx.BlockTree, syncedBlockTree.FindHeader(99, BlockTreeLookupOptions.None)); ctx.Feed.InitializeFeed(); - HeadersSyncBatch? batch = ctx.Feed.PrepareRequest().Result; - batch!.Response = syncedBlockTree.FindHeaders(syncedBlockTree.FindHeader(batch.StartNumber, BlockTreeLookupOptions.None)!.Hash, batch.RequestSize, 0, false); + HeadersSyncBatch batch = ctx.Feed.PrepareRequest().Result; + batch.Response = syncedBlockTree.FindHeaders(syncedBlockTree.FindHeader(batch.StartNumber, BlockTreeLookupOptions.None)!.Hash, batch.RequestSize, 0, false); ctx.Feed.HandleResponse(batch); - Keccak lastHeader = syncedBlockTree.FindHeader(batch.EndNumber, BlockTreeLookupOptions.None)!.GetOrCalculateHash(); - Keccak headerToInvalidate = syncedBlockTree.FindHeader(batch.StartNumber + 10, BlockTreeLookupOptions.None)!.GetOrCalculateHash(); - Keccak lastValidHeader = syncedBlockTree.FindHeader(batch.StartNumber + 9, BlockTreeLookupOptions.None)!.GetOrCalculateHash(); + Keccak lastHeader = syncedBlockTree.FindHeader(batch.EndNumber, BlockTreeLookupOptions.None).Hash; + Keccak headerToInvalidate = syncedBlockTree.FindHeader(batch.StartNumber + 10, BlockTreeLookupOptions.None).Hash; + Keccak lastValidHeader = syncedBlockTree.FindHeader(batch.StartNumber + 9, BlockTreeLookupOptions.None).Hash; invalidChainTracker.OnInvalidBlock(headerToInvalidate, lastValidHeader); - invalidChainTracker.IsOnKnownInvalidChain(lastHeader, out Keccak? storedLastValidHash).Should().BeTrue(); + invalidChainTracker.IsOnKnownInvalidChain(lastHeader, out Keccak storedLastValidHash).Should().BeTrue(); storedLastValidHash.Should().Be(lastValidHeader); } @@ -354,8 +353,8 @@ public async Task When_pivot_changed_during_header_sync_after_chain_merged__do_n // First batch, should be enough to merge chain HeadersSyncBatch? request = await ctx.Feed.PrepareRequest(); - request!.Should().NotBeNull(); - request!.Response = Enumerable.Range((int)request.StartNumber, request.RequestSize) + request.Should().NotBeNull(); + request.Response = Enumerable.Range((int)request.StartNumber, request.RequestSize) .Select((blockNumber) => ctx.RemoteBlockTree.FindHeader(blockNumber)) .ToArray(); @@ -370,7 +369,7 @@ public async Task When_pivot_changed_during_header_sync_after_chain_merged__do_n request.Should().NotBeNull(); // We respond it again - request!.Response = Enumerable.Range((int)request.StartNumber, request.RequestSize) + request.Response = Enumerable.Range((int)request.StartNumber, request.RequestSize) .Select((blockNumber) => ctx.RemoteBlockTree.FindHeader(blockNumber)) .ToArray(); ctx.Feed.HandleResponse(request); @@ -397,7 +396,7 @@ private async void BuildAndProcessHeaderSyncBatches( BuildHeadersSyncBatches(ctx, blockTree, syncedBlockTree, pivot, endLowestBeaconHeader); - HeadersSyncBatch? result = await ctx.Feed.PrepareRequest(); + HeadersSyncBatch result = await ctx.Feed.PrepareRequest(); result.Should().BeNull(); // check headers are inserted into block tree during sync blockTree.FindHeader(pivot.PivotNumber - 1, BlockTreeLookupOptions.TotalDifficultyNotNeeded).Should().NotBeNull(); @@ -419,11 +418,11 @@ private async void BuildHeadersSyncBatches( long lowestHeaderNumber = pivot.PivotNumber; while (lowestHeaderNumber > endLowestBeaconHeader) { - HeadersSyncBatch? batch = await ctx.Feed.PrepareRequest(); + HeadersSyncBatch batch = await ctx.Feed.PrepareRequest(); batch.Should().NotBeNull(); BuildHeadersSyncBatchResponse(batch, syncedBlockTree); ctx.Feed.HandleResponse(batch); - lowestHeaderNumber = lowestHeaderNumber - batch!.RequestSize < endLowestBeaconHeader + lowestHeaderNumber = lowestHeaderNumber - batch.RequestSize < endLowestBeaconHeader ? endLowestBeaconHeader : lowestHeaderNumber - batch.RequestSize; @@ -432,9 +431,9 @@ private async void BuildHeadersSyncBatches( } } - private void BuildHeadersSyncBatchResponse(HeadersSyncBatch? batch, IBlockTree blockTree) + private void BuildHeadersSyncBatchResponse(HeadersSyncBatch batch, IBlockTree blockTree) { - batch!.MarkSent(); + batch.MarkSent(); BlockHeader? startHeader = blockTree.FindHeader(batch.StartNumber); if (startHeader is null) { diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconPivotTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconPivotTests.cs index 2dbe02bd60a..8e19239aadc 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconPivotTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconPivotTests.cs @@ -7,7 +7,6 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; -using Nethermind.Crypto; using Nethermind.Db; using Nethermind.Logging; using Nethermind.Merge.Plugin.Synchronization; @@ -38,7 +37,7 @@ public void Setup() public void Beacon_pivot_defaults_to_sync_config_values_when_there_is_no_pivot() { IBeaconPivot pivot = new BeaconPivot(_syncConfig, new MemDb(), Substitute.For(), LimboLogs.Instance); - pivot.PivotHash.Should().Be(_syncConfig.PivotHashParsed!); + pivot.PivotHash.Should().Be(_syncConfig.PivotHashParsed); pivot.PivotNumber.Should().Be(_syncConfig.PivotNumberParsed); pivot.PivotDestinationNumber.Should().Be(0); } @@ -52,9 +51,9 @@ public void Beacon_pivot_set_to_pivot_when_set(int processedBlocks, int expected .TestObject; IBeaconPivot pivot = new BeaconPivot(_syncConfig, new MemDb(), blockTree, LimboLogs.Instance); - BlockHeader pivotHeader = blockTree.FindHeader(10, BlockTreeLookupOptions.AllowInvalid)!; + BlockHeader pivotHeader = blockTree.FindHeader(10, BlockTreeLookupOptions.AllowInvalid); pivot.EnsurePivot(pivotHeader); - pivot.PivotHash.Should().Be(pivotHeader.GetOrCalculateHash()); + pivot.PivotHash.Should().Be(pivotHeader.Hash); pivot.PivotNumber.Should().Be(pivotHeader.Number); pivot.PivotDestinationNumber.Should().Be(expectedPivotDestinationNumber); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/BlockImprovementContextFactory.cs b/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/BlockImprovementContextFactory.cs index 9540077a323..36c06be992b 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/BlockImprovementContextFactory.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/BlockImprovementContextFactory.cs @@ -4,6 +4,7 @@ using System; using Nethermind.Consensus.Producers; using Nethermind.Core; +using Org.BouncyCastle.Asn1.Cms; namespace Nethermind.Merge.Plugin.BlockProduction; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/Boost/BoostBlockImprovementContextFactory.cs b/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/Boost/BoostBlockImprovementContextFactory.cs index 06c6bf79956..184b808c568 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/Boost/BoostBlockImprovementContextFactory.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/Boost/BoostBlockImprovementContextFactory.cs @@ -2,8 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Net.Http; using Nethermind.Consensus.Producers; using Nethermind.Core; +using Nethermind.Facade.Proxy; using Nethermind.State; namespace Nethermind.Merge.Plugin.BlockProduction.Boost; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/Boost/BoostRelay.cs b/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/Boost/BoostRelay.cs index bbaf6d458db..0fd907f1d75 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/Boost/BoostRelay.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/Boost/BoostRelay.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Threading; using System.Threading.Tasks; using Nethermind.Consensus.Producers; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs b/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs index 5093c2ee4db..df8bc662810 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs @@ -11,6 +11,9 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Crypto; +using Nethermind.Core.Extensions; +using System.Threading; using Nethermind.Logging; using Nethermind.State; using Nethermind.Evm; @@ -97,8 +100,8 @@ private void AmendHeader(BlockHeader blockHeader, BlockHeader parent) if (spec.IsEip4844Enabled) { - blockHeader.BlobGasUsed = 0; - blockHeader.ExcessBlobGas = BlobGasCalculator.CalculateExcessBlobGas(parent, spec); + blockHeader.DataGasUsed = 0; + blockHeader.ExcessDataGas = DataGasCalculator.CalculateExcessDataGas(parent, spec); } } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs index 8c4e47af93b..fc75a7cf6fc 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs @@ -3,12 +3,13 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Int256; -using Nethermind.Merge.Plugin.Handlers; +using Nethermind.Serialization.Json; using Nethermind.Serialization.Rlp; using Nethermind.State.Proofs; using Newtonsoft.Json; @@ -18,7 +19,7 @@ namespace Nethermind.Merge.Plugin.Data; /// /// Represents an object mapping the ExecutionPayload structure of the beacon chain spec. /// -public class ExecutionPayload : IForkValidator, IExecutionPayloadParams +public class ExecutionPayload { public ExecutionPayload() { } // Needed for tests @@ -38,6 +39,8 @@ public ExecutionPayload(Block block) Timestamp = block.Timestamp; BaseFeePerGas = block.BaseFeePerGas; Withdrawals = block.Withdrawals; + DataGasUsed = block.DataGasUsed; + ExcessDataGas = block.ExcessDataGas; SetTransactions(block.Transactions); } @@ -91,25 +94,20 @@ public byte[][] Transactions /// public IEnumerable? Withdrawals { get; set; } - /// - /// Gets or sets as defined in + /// Gets or sets as defined in /// EIP-4844. /// - public ulong? BlobGasUsed { get; set; } + [JsonProperty(ItemConverterType = typeof(NullableUInt256Converter), NullValueHandling = NullValueHandling.Ignore)] + public ulong? DataGasUsed { get; set; } /// - /// Gets or sets as defined in + /// Gets or sets as defined in /// EIP-4844. /// - public ulong? ExcessBlobGas { get; set; } + [JsonProperty(ItemConverterType = typeof(NullableUInt256Converter), NullValueHandling = NullValueHandling.Ignore)] + public ulong? ExcessDataGas { get; set; } - /// - /// Gets or sets as defined in - /// EIP-4788. - /// - [JsonIgnore] - public Keccak? ParentBeaconBlockRoot { get; set; } /// /// Creates the execution block from payload. @@ -130,7 +128,9 @@ public virtual bool TryGetBlock(out Block? block, UInt256? totalDifficulty = nul BlockNumber, GasLimit, Timestamp, - ExtraData) + ExtraData, + DataGasUsed, + ExcessDataGas) { Hash = BlockHash, ReceiptsRoot = ReceiptsRoot, @@ -159,7 +159,6 @@ public virtual bool TryGetBlock(out Block? block, UInt256? totalDifficulty = nul } } - private Transaction[]? _transactions = null; /// @@ -182,24 +181,21 @@ public void SetTransactions(params Transaction[] transactions) _transactions = transactions; } - public override string ToString() => $"{BlockNumber} ({BlockHash.ToShortString()})"; - - ExecutionPayload IExecutionPayloadParams.ExecutionPayload => this; + public override string ToString() => $"{BlockNumber} ({BlockHash})"; +} - public virtual ValidationResult ValidateParams(IReleaseSpec spec, int version, out string? error) +public static class ExecutionPayloadExtensions +{ + public static int GetVersion(this ExecutionPayload executionPayload) => + executionPayload.Withdrawals is null ? 1 : 2; + + public static bool Validate( + this ExecutionPayload executionPayload, + IReleaseSpec spec, + int version, + [NotNullWhen(false)] out string? error) { - if (spec.IsEip4844Enabled) - { - error = "ExecutionPayloadV3 expected"; - return ValidationResult.Fail; - } - - int actualVersion = this switch - { - { BlobGasUsed: not null } or { ExcessBlobGas: not null } or { ParentBeaconBlockRoot: not null } => 3, - { Withdrawals: not null } => 2, - _ => 1 - }; + int actualVersion = executionPayload.GetVersion(); error = actualVersion switch { @@ -208,9 +204,15 @@ public virtual ValidationResult ValidateParams(IReleaseSpec spec, int version, o _ => actualVersion > version ? $"ExecutionPayloadV{version} expected" : null }; - return error is null ? ValidationResult.Success : ValidationResult.Fail; + return error is null; } - public virtual bool ValidateFork(ISpecProvider specProvider) => - !specProvider.GetSpec(BlockNumber, Timestamp).IsEip4844Enabled; + public static bool Validate(this ExecutionPayload executionPayload, + ISpecProvider specProvider, + int version, + [NotNullWhen(false)] out string? error) => + executionPayload.Validate( + specProvider.GetSpec(executionPayload.BlockNumber, executionPayload.Timestamp), + version, + out error); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayloadV3.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayloadV3.cs deleted file mode 100644 index d365264b554..00000000000 --- a/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayloadV3.cs +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core; -using Nethermind.Core.Specs; -using Nethermind.Int256; -using Newtonsoft.Json; - -namespace Nethermind.Merge.Plugin.Data; - -/// -/// Represents an object mapping the ExecutionPayloadV3 structure of the beacon chain spec. -/// -[JsonObject(ItemRequired = Required.Always)] -public class ExecutionPayloadV3 : ExecutionPayload -{ - public ExecutionPayloadV3() { } // Needed for tests - - public ExecutionPayloadV3(Block block) : base(block) - { - ParentBeaconBlockRoot = block.ParentBeaconBlockRoot; - BlobGasUsed = block.BlobGasUsed; - ExcessBlobGas = block.ExcessBlobGas; - } - - public override bool TryGetBlock(out Block? block, UInt256? totalDifficulty = null) - { - if (!base.TryGetBlock(out block, totalDifficulty)) - { - return false; - } - - block!.Header.ParentBeaconBlockRoot = ParentBeaconBlockRoot; - block!.Header.BlobGasUsed = BlobGasUsed; - block!.Header.ExcessBlobGas = ExcessBlobGas; - return true; - } - - public override bool ValidateFork(ISpecProvider specProvider) => - specProvider.GetSpec(BlockNumber, Timestamp).IsEip4844Enabled; -} diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/ForkchoiceStateV1.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/ForkchoiceStateV1.cs index 865925aae5e..4eb029b3734 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Data/ForkchoiceStateV1.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Data/ForkchoiceStateV1.cs @@ -36,9 +36,5 @@ public ForkchoiceStateV1(Keccak headBlockHash, Keccak finalizedBlockHash, Keccak /// Can be when transition block is not finalized yet. public Keccak FinalizedBlockHash { get; set; } - public override string ToString() => $"ForkChoice: Head: {HeadBlockHash.ToShortString()}, Safe: {SafeBlockHash.ToShortString()}, Finalized: {FinalizedBlockHash.ToShortString()}"; - public string ToString(long? headNumber, long? safeNumber, long? finalizedNumber) => - headNumber is null || safeNumber is null || finalizedNumber is null - ? ToString() - : $"ForkChoice: Head: {headNumber} ({HeadBlockHash.ToShortString()}), Safe: {safeNumber} ({SafeBlockHash.ToShortString()}), Finalized: {finalizedNumber} ({FinalizedBlockHash.ToShortString()})"; + public override string ToString() => $"ForkchoiceState: ({nameof(HeadBlockHash)}: {HeadBlockHash}, {nameof(SafeBlockHash)}: {SafeBlockHash}, {nameof(FinalizedBlockHash)}: {FinalizedBlockHash})"; } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/GetPayloadV2Result.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/GetPayloadV2Result.cs index 78fffe38a86..1d261ca65d2 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Data/GetPayloadV2Result.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Data/GetPayloadV2Result.cs @@ -2,13 +2,12 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Core; -using Nethermind.Core.Specs; using Nethermind.Int256; -using Nethermind.Merge.Plugin.Handlers; +using Newtonsoft.Json; namespace Nethermind.Merge.Plugin.Data; -public class GetPayloadV2Result : IForkValidator +public class GetPayloadV2Result { public GetPayloadV2Result(Block block, UInt256 blockFees) { @@ -18,9 +17,7 @@ public GetPayloadV2Result(Block block, UInt256 blockFees) public UInt256 BlockValue { get; } - public virtual ExecutionPayload ExecutionPayload { get; } - - public bool ValidateFork(ISpecProvider specProvider) => ExecutionPayload.ValidateFork(specProvider); + public ExecutionPayload ExecutionPayload { get; } public override string ToString() => $"{{ExecutionPayload: {ExecutionPayload}, Fees: {BlockValue}}}"; } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/GetPayloadV3Result.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/GetPayloadV3Result.cs index 492d81ad71e..b3730948fad 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Data/GetPayloadV3Result.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Data/GetPayloadV3Result.cs @@ -10,16 +10,11 @@ public class GetPayloadV3Result : GetPayloadV2Result { public GetPayloadV3Result(Block block, UInt256 blockFees, BlobsBundleV1 blobsBundle) : base(block, blockFees) { - ExecutionPayload = new(block); BlobsBundle = blobsBundle; } public BlobsBundleV1 BlobsBundle { get; } - public override ExecutionPayloadV3 ExecutionPayload { get; } - - public bool ShouldOverrideBuilder { get; } - public override string ToString() => - $"{{ExecutionPayload: {ExecutionPayload}, Fees: {BlockValue}, BlobsBundle blobs count: {BlobsBundle.Blobs.Length}, ShouldOverrideBuilder {ShouldOverrideBuilder}}}"; + $"{{ExecutionPayload: {ExecutionPayload}, Fees: {BlockValue}, BlobsBundle blobs count: {BlobsBundle.Blobs.Length}}}"; } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/IExecutionPayloadParams.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/IExecutionPayloadParams.cs deleted file mode 100644 index 5995400a3d3..00000000000 --- a/src/Nethermind/Nethermind.Merge.Plugin/Data/IExecutionPayloadParams.cs +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using System.Linq; -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Core.Extensions; -using Nethermind.Core.Specs; -using Nethermind.Serialization.Rlp; - -namespace Nethermind.Merge.Plugin.Data; - -public interface IExecutionPayloadParams -{ - ExecutionPayload ExecutionPayload { get; } - ValidationResult ValidateParams(IReleaseSpec spec, int version, out string? error); -} - -public enum ValidationResult : byte { Success, Fail, Invalid }; - -public class ExecutionPayloadV3Params : IExecutionPayloadParams -{ - private readonly ExecutionPayloadV3 _executionPayload; - private readonly byte[]?[] _blobVersionedHashes; - private readonly Keccak? _parentBeaconBlockRoot; - - public ExecutionPayloadV3Params(ExecutionPayloadV3 executionPayload, byte[]?[] blobVersionedHashes, Keccak? parentBeaconBlockRoot) - { - _executionPayload = executionPayload; - _blobVersionedHashes = blobVersionedHashes; - _parentBeaconBlockRoot = parentBeaconBlockRoot; - } - - public ExecutionPayload ExecutionPayload => _executionPayload; - - public ValidationResult ValidateParams(IReleaseSpec spec, int version, out string? error) - { - Transaction[]? transactions = null; - try - { - transactions = _executionPayload.GetTransactions(); - } - catch (RlpException rlpException) - { - error = rlpException.Message; - return ValidationResult.Invalid; - } - - static IEnumerable FlattenHashesFromTransactions(Transaction[] transactions) => - transactions - .Where(t => t.BlobVersionedHashes is not null) - .SelectMany(t => t.BlobVersionedHashes!); - - if (!FlattenHashesFromTransactions(transactions).SequenceEqual(_blobVersionedHashes, Bytes.NullableEqualityComparer)) - { - error = "Blob versioned hashes do not match"; - return ValidationResult.Invalid; - } - - if (_parentBeaconBlockRoot is null) - { - error = "Parent beacon block root must be set"; - return ValidationResult.Fail; - } - - _executionPayload.ParentBeaconBlockRoot = new Keccak(_parentBeaconBlockRoot); - - error = null; - return ValidationResult.Success; - } -} diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/PayloadStatusV1.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/PayloadStatusV1.cs index 8a27a65fb10..c92f8b9475d 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Data/PayloadStatusV1.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Data/PayloadStatusV1.cs @@ -17,11 +17,10 @@ public class PayloadStatusV1 public static readonly PayloadStatusV1 Accepted = new() { Status = PayloadStatus.Accepted }; - public static PayloadStatusV1 Invalid(Keccak? latestValidHash, string? validationError = null) => new() + public static PayloadStatusV1 Invalid(Keccak? latestValidHash) => new() { Status = PayloadStatus.Invalid, - LatestValidHash = latestValidHash, - ValidationError = validationError + LatestValidHash = latestValidHash }; /// diff --git a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Cancun.cs b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Cancun.cs index 0f13e581361..0b4748112f5 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Cancun.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Cancun.cs @@ -1,10 +1,10 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; -using Nethermind.Consensus; -using Nethermind.Consensus.Producers; -using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.JsonRpc; using Nethermind.Merge.Plugin.Data; using Nethermind.Merge.Plugin.Handlers; @@ -15,11 +15,34 @@ public partial class EngineRpcModule : IEngineRpcModule { private readonly IAsyncHandler _getPayloadHandlerV3; - public Task> engine_forkchoiceUpdatedV3(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes = null) - => ForkchoiceUpdated(forkchoiceState, payloadAttributes, EngineApiVersions.Cancun); + public async Task> engine_newPayloadV3(ExecutionPayload executionPayload, byte[]?[]? blobVersionedHashes = null) => + (await Validate(executionPayload, blobVersionedHashes)) ?? await NewPayload(executionPayload, 3); - public Task> engine_newPayloadV3(ExecutionPayloadV3 executionPayload, byte[]?[] blobVersionedHashes, Keccak? parentBeaconBlockRoot) => - NewPayload(new ExecutionPayloadV3Params(executionPayload, blobVersionedHashes, parentBeaconBlockRoot), EngineApiVersions.Cancun); + private async Task?> Validate(ExecutionPayload executionPayload, byte[]?[]? blobVersionedHashes) + { + ResultWrapper ErrorResult(string error) + { + if (_logger.IsWarn) _logger.Warn(error); + return ResultWrapper.Success( + new PayloadStatusV1 + { + Status = PayloadStatus.Invalid, + LatestValidHash = null, + ValidationError = error + }); + } + + static IEnumerable FlattenHashesFromTransactions(ExecutionPayload payload) => + payload.GetTransactions() + .Where(t => t.BlobVersionedHashes is not null) + .SelectMany(t => t.BlobVersionedHashes!); + + return blobVersionedHashes is null ? + !_specProvider.GetSpec(executionPayload.BlockNumber, executionPayload.Timestamp).IsEip4844Enabled ? await engine_newPayloadV2(executionPayload) + : ErrorResult("Blob versioned hashes must be set") + : !FlattenHashesFromTransactions(executionPayload).SequenceEqual(blobVersionedHashes, Bytes.NullableEqualityComparer) ? ErrorResult("Blob versioned hashes do not match") + : null; + } public async Task> engine_getPayloadV3(byte[] payloadId) => await _getPayloadHandlerV3.HandleAsync(payloadId); diff --git a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs index f444d926b2d..3bb0ca79dc6 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs @@ -5,9 +5,7 @@ using System.Diagnostics; using System.Threading; using System.Threading.Tasks; -using Nethermind.Consensus; using Nethermind.Consensus.Producers; -using Nethermind.Core.Specs; using Nethermind.JsonRpc; using Nethermind.Merge.Plugin.Data; using Nethermind.Merge.Plugin.GC; @@ -29,22 +27,28 @@ public ResultWrapper engine_exchangeTransitionConfigu TransitionConfigurationV1 beaconTransitionConfiguration) => _transitionConfigurationHandler.Handle(beaconTransitionConfiguration); public async Task> engine_forkchoiceUpdatedV1(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes = null) - => await ForkchoiceUpdated(forkchoiceState, payloadAttributes, EngineApiVersions.Paris); + => await ForkchoiceUpdated(forkchoiceState, payloadAttributes, 1); public Task> engine_getPayloadV1(byte[] payloadId) => _getPayloadHandlerV1.HandleAsync(payloadId); public async Task> engine_newPayloadV1(ExecutionPayload executionPayload) - => await NewPayload(executionPayload, EngineApiVersions.Paris); + => await NewPayload(executionPayload, 1); private async Task> ForkchoiceUpdated(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes, int version) { + if (payloadAttributes?.Validate(_specProvider, version, out string? error) == false) + { + if (_logger.IsWarn) _logger.Warn(error); + return ResultWrapper.Fail(error, ErrorCodes.InvalidParams); + } + if (await _locker.WaitAsync(_timeout)) { Stopwatch watch = Stopwatch.StartNew(); try { - return await _forkchoiceUpdatedV1Handler.Handle(forkchoiceState, payloadAttributes, version); + return await _forkchoiceUpdatedV1Handler.Handle(forkchoiceState, payloadAttributes); } finally { @@ -60,24 +64,12 @@ private async Task> ForkchoiceUpdated(F } } - private async Task> NewPayload(IExecutionPayloadParams executionPayloadParams, int version) + private async Task> NewPayload(ExecutionPayload executionPayload, int version) { - ExecutionPayload executionPayload = executionPayloadParams.ExecutionPayload; - - if (!executionPayload.ValidateFork(_specProvider)) - { - if (_logger.IsWarn) _logger.Warn($"The payload is not supported by the current fork"); - return ResultWrapper.Fail("unsupported fork", version < 2 ? ErrorCodes.InvalidParams : ErrorCodes.UnsupportedFork); - } - - IReleaseSpec releaseSpec = _specProvider.GetSpec(executionPayload.BlockNumber, executionPayload.Timestamp); - ValidationResult validationResult = executionPayloadParams.ValidateParams(releaseSpec, version, out string? error); - if (validationResult != ValidationResult.Success) + if (!executionPayload.Validate(_specProvider, version, out string? error)) { if (_logger.IsWarn) _logger.Warn(error); - return validationResult == ValidationResult.Fail - ? ResultWrapper.Fail(error!, ErrorCodes.InvalidParams) - : ResultWrapper.Success(PayloadStatusV1.Invalid(null, error)); + return ResultWrapper.Fail(error, ErrorCodes.InvalidParams); } if (await _locker.WaitAsync(_timeout)) diff --git a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Shanghai.cs b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Shanghai.cs index 8c29a9ba971..99792015ae3 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Shanghai.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Shanghai.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Nethermind.Consensus; using Nethermind.Consensus.Producers; using Nethermind.Core.Crypto; using Nethermind.JsonRpc; @@ -19,7 +18,7 @@ public partial class EngineRpcModule : IEngineRpcModule private readonly IAsyncHandler _getPayloadHandlerV2; public Task> engine_forkchoiceUpdatedV2(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes = null) - => ForkchoiceUpdated(forkchoiceState, payloadAttributes, EngineApiVersions.Shanghai); + => ForkchoiceUpdated(forkchoiceState, payloadAttributes, 2); public Task> engine_getPayloadV2(byte[] payloadId) => _getPayloadHandlerV2.HandleAsync(payloadId); @@ -31,5 +30,5 @@ public Task> engine_forkchoiceUpdatedV2 => _executionGetPayloadBodiesByRangeV1Handler.Handle(start, count); public Task> engine_newPayloadV2(ExecutionPayload executionPayload) - => NewPayload(executionPayload, EngineApiVersions.Shanghai); + => NewPayload(executionPayload, 2); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs b/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs index 17d736dd280..0acdc6f4b64 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using FastEnumUtility; using Nethermind.Core.Extensions; -using Nethermind.Core.Memory; using Nethermind.Logging; namespace Nethermind.Merge.Plugin.GC; @@ -180,8 +179,6 @@ private async Task ScheduleGCInternal() } System.GC.Collect((int)generation, mode, blocking: true, compacting: compacting > 0); - - MallocHelper.Instance.MallocTrim((uint)1.MiB()); } } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/GC/NoSyncGcRegionStrategy.cs b/src/Nethermind/Nethermind.Merge.Plugin/GC/NoSyncGcRegionStrategy.cs index fcc3ea994b0..4a1002b1a1e 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/GC/NoSyncGcRegionStrategy.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/GC/NoSyncGcRegionStrategy.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using FastEnumUtility; using Nethermind.Synchronization.ParallelSync; namespace Nethermind.Merge.Plugin.GC; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/EngineRpcCapabilitiesProvider.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/EngineRpcCapabilitiesProvider.cs index 1d69034f935..2248b429359 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/EngineRpcCapabilitiesProvider.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/EngineRpcCapabilitiesProvider.cs @@ -42,7 +42,6 @@ public EngineRpcCapabilitiesProvider(ISpecProvider specProvider) #region Cancun _capabilities[nameof(IEngineRpcModule.engine_getPayloadV3)] = (spec.IsEip4844Enabled, spec.IsEip4844Enabled); - _capabilities[nameof(IEngineRpcModule.engine_forkchoiceUpdatedV3)] = (spec.IsEip4844Enabled, spec.IsEip4844Enabled); _capabilities[nameof(IEngineRpcModule.engine_newPayloadV3)] = (spec.IsEip4844Enabled, spec.IsEip4844Enabled); #endregion } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ExchangeCapabilitiesHandler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ExchangeCapabilitiesHandler.cs index a22f79beb5e..13605a718f7 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ExchangeCapabilitiesHandler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ExchangeCapabilitiesHandler.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Nethermind.Core.Specs; using Nethermind.JsonRpc; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ExchangeTransitionConfigurationV1Handler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ExchangeTransitionConfigurationV1Handler.cs index 788f10d468d..b79ce824abd 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ExchangeTransitionConfigurationV1Handler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ExchangeTransitionConfigurationV1Handler.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Consensus; using Nethermind.Core.Crypto; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ForkchoiceUpdatedHandler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ForkchoiceUpdatedHandler.cs index 6dfec16e0a5..8e7ef4e8b94 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ForkchoiceUpdatedHandler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ForkchoiceUpdatedHandler.cs @@ -11,7 +11,6 @@ using Nethermind.Consensus.Producers; using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Core.Specs; using Nethermind.Crypto; using Nethermind.JsonRpc; using Nethermind.Logging; @@ -43,7 +42,6 @@ public class ForkchoiceUpdatedHandler : IForkchoiceUpdatedHandler private readonly IBeaconPivot _beaconPivot; private readonly ILogger _logger; private readonly IPeerRefresher _peerRefresher; - private readonly ISpecProvider _specProvider; public ForkchoiceUpdatedHandler( IBlockTree blockTree, @@ -56,7 +54,6 @@ public ForkchoiceUpdatedHandler( IMergeSyncController mergeSyncController, IBeaconPivot beaconPivot, IPeerRefresher peerRefresher, - ISpecProvider specProvider, ILogManager logManager) { _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); @@ -69,67 +66,48 @@ public ForkchoiceUpdatedHandler( _mergeSyncController = mergeSyncController; _beaconPivot = beaconPivot; _peerRefresher = peerRefresher; - _specProvider = specProvider; _logger = logManager.GetClassLogger(); } - public Task> Handle(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes, int version) + public Task> Handle(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes) { - Block? newHeadBlock = GetBlock(forkchoiceState.HeadBlockHash); - ResultWrapper? payloadUpdateResult = ApplyForkchoiceUpdate(newHeadBlock, forkchoiceState, payloadAttributes); - return Task.FromResult( - ValidateAttributes(payloadAttributes, version) ?? - payloadUpdateResult ?? - StartBuildingPayload(newHeadBlock!, forkchoiceState, payloadAttributes) - ); - } + string requestStr = $"{forkchoiceState} {payloadAttributes}"; + if (_logger.IsInfo) _logger.Info($"Received: {requestStr}"); - public ResultWrapper? ApplyForkchoiceUpdate(Block? newHeadBlock, ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes) - { if (_invalidChainTracker.IsOnKnownInvalidChain(forkchoiceState.HeadBlockHash, out Keccak? lastValidHash)) { - if (_logger.IsInfo) _logger.Info($"Received Invalid {forkchoiceState} {payloadAttributes} - {forkchoiceState.HeadBlockHash} is known to be a part of an invalid chain."); + if (_logger.IsInfo) _logger.Info($" FCU - Invalid - {requestStr} {forkchoiceState.HeadBlockHash} is known to be a part of an invalid chain."); return ForkchoiceUpdatedV1Result.Invalid(lastValidHash); } + Block? newHeadBlock = GetBlock(forkchoiceState.HeadBlockHash); if (newHeadBlock is null) // if a head is unknown we are syncing { - string simpleRequestStr = payloadAttributes is null ? forkchoiceState.ToString() : $"{forkchoiceState} {payloadAttributes}"; - if (_logger.IsInfo) _logger.Info($"Received {simpleRequestStr}"); - if (_blockCacheService.BlockCache.TryGetValue(forkchoiceState.HeadBlockHash, out Block? block)) { - StartNewBeaconHeaderSync(forkchoiceState, block, $"{simpleRequestStr}"); + StartNewBeaconHeaderSync(forkchoiceState, block, requestStr); } else if (_logger.IsInfo) { - _logger.Info($"Syncing Unknown ForkChoiceState head hash Request: {simpleRequestStr}."); + _logger.Info($"Syncing... Unknown forkchoiceState head hash... Request: {requestStr}."); } return ForkchoiceUpdatedV1Result.Syncing; } BlockInfo? blockInfo = _blockTree.GetInfo(newHeadBlock.Number, newHeadBlock.GetOrCalculateHash()).Info; - BlockHeader? safeBlockHeader = ValidateBlockHash(forkchoiceState.SafeBlockHash, out string? safeBlockErrorMsg); - BlockHeader? finalizedHeader = ValidateBlockHash(forkchoiceState.FinalizedBlockHash, out string? finalizationErrorMsg); - string requestStr = payloadAttributes is null - ? forkchoiceState.ToString(newHeadBlock.Number, safeBlockHeader?.Number, finalizedHeader?.Number) - : $"{forkchoiceState.ToString(newHeadBlock.Number, safeBlockHeader?.Number, finalizedHeader?.Number)} {payloadAttributes}"; - - if (_logger.IsInfo) _logger.Info($"Received {requestStr}"); - if (blockInfo is null) { if (_logger.IsWarn) { _logger.Warn($"Block info for: {requestStr} wasn't found."); } return ForkchoiceUpdatedV1Result.Syncing; } - if (!blockInfo.WasProcessed) { BlockHeader? blockParent = _blockTree.FindHeader(newHeadBlock.ParentHash!); if (blockParent is null) { - if (_logger.IsInfo) _logger.Info($"Parent of block {newHeadBlock} not available. Starting new beacon header. sync."); + if (_logger.IsInfo) + _logger.Info($"Parent of block {newHeadBlock} not available. Starting new beacon header. sync."); StartNewBeaconHeaderSync(forkchoiceState, newHeadBlock!, requestStr); @@ -138,17 +116,16 @@ public Task> Handle(ForkchoiceStateV1 f if (_beaconPivot.ShouldForceStartNewSync) { - if (_logger.IsInfo) _logger.Info("Force starting new sync."); + if (_logger.IsInfo) + _logger.Info($"Force starting new sync."); StartNewBeaconHeaderSync(forkchoiceState, newHeadBlock!, requestStr); return ForkchoiceUpdatedV1Result.Syncing; } - if (blockInfo is { IsBeaconMainChain: false, IsBeaconInfo: true }) - { + if (!blockInfo.IsBeaconMainChain && blockInfo.IsBeaconInfo) ReorgBeaconChainDuringSync(newHeadBlock!, blockInfo); - } int processingQueueCount = _processingQueue.Count; if (processingQueueCount == 0) @@ -157,25 +134,27 @@ public Task> Handle(ForkchoiceStateV1 f _blockCacheService.FinalizedHash = forkchoiceState.FinalizedBlockHash; _mergeSyncController.StopBeaconModeControl(); - if (_logger.IsInfo) _logger.Info($"Syncing beacon headers, Request: {requestStr}"); + if (_logger.IsInfo) { _logger.Info($"Syncing beacon headers... Request: {requestStr}."); } } else { - if (_logger.IsInfo) _logger.Info($"Processing {_processingQueue.Count} blocks, Request: {requestStr}"); + if (_logger.IsInfo) { _logger.Info($"Processing {_processingQueue.Count} blocks... Request: {requestStr}."); } } _beaconPivot.ProcessDestination ??= newHeadBlock!.Header; return ForkchoiceUpdatedV1Result.Syncing; } - if (_logger.IsDebug) _logger.Debug($"ForkChoiceUpdate: block {newHeadBlock} was processed."); + if (_logger.IsInfo) _logger.Info($"FCU - block {newHeadBlock} was processed."); + BlockHeader? finalizedHeader = ValidateBlockHash(forkchoiceState.FinalizedBlockHash, out string? finalizationErrorMsg); if (finalizationErrorMsg is not null) { if (_logger.IsWarn) _logger.Warn($"Invalid finalized block hash {finalizationErrorMsg}. Request: {requestStr}."); return ForkchoiceUpdatedV1Result.Error(finalizationErrorMsg, MergeErrorCodes.InvalidForkchoiceState); } + ValidateBlockHash(forkchoiceState.SafeBlockHash, out string? safeBlockErrorMsg); if (safeBlockErrorMsg is not null) { if (_logger.IsWarn) _logger.Warn($"Invalid safe block hash {finalizationErrorMsg}. Request: {requestStr}."); @@ -200,7 +179,7 @@ public Task> Handle(ForkchoiceStateV1 f if (_blockTree.IsOnMainChainBehindHead(newHeadBlock)) { - if (_logger.IsInfo) _logger.Info($"Valid. ForkChoiceUpdated ignored - already in canonical chain. Request: {requestStr}."); + if (_logger.IsInfo) _logger.Info($"Valid. ForkchoiceUpdated ignored - already in canonical chain. Request: {requestStr}."); return ForkchoiceUpdatedV1Result.Valid(null, forkchoiceState.HeadBlockHash); } @@ -213,14 +192,14 @@ public Task> Handle(ForkchoiceStateV1 f if (IsInconsistent(forkchoiceState.FinalizedBlockHash)) { - string errorMsg = $"Inconsistent ForkChoiceState - finalized block hash. Request: {requestStr}"; + string errorMsg = $"Inconsistent forkchoiceState - finalized block hash. Request: {requestStr}"; if (_logger.IsWarn) _logger.Warn(errorMsg); return ForkchoiceUpdatedV1Result.Error(errorMsg, MergeErrorCodes.InvalidForkchoiceState); } if (IsInconsistent(forkchoiceState.SafeBlockHash)) { - string errorMsg = $"Inconsistent ForkChoiceState - safe block hash. Request: {requestStr}"; + string errorMsg = $"Inconsistent forkchoiceState - safe block hash. Request: {requestStr}"; if (_logger.IsWarn) _logger.Warn(errorMsg); return ForkchoiceUpdatedV1Result.Error(errorMsg, MergeErrorCodes.InvalidForkchoiceState); } @@ -234,20 +213,15 @@ public Task> Handle(ForkchoiceStateV1 f if (shouldUpdateHead) { _poSSwitcher.ForkchoiceUpdated(newHeadBlock.Header, forkchoiceState.FinalizedBlockHash); - if (_logger.IsInfo) _logger.Info($"Synced chain Head to {newHeadBlock.ToString(Block.Format.Short)}"); + if (_logger.IsInfo) _logger.Info($"Block {forkchoiceState.HeadBlockHash} was set as head."); } - return null; - } - - public ResultWrapper StartBuildingPayload(Block newHeadBlock, ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes) - { string? payloadId = null; if (payloadAttributes is not null) { if (newHeadBlock.Timestamp >= payloadAttributes.Timestamp) { - string error = $"Payload timestamp {payloadAttributes.Timestamp} must be greater than block timestamp {newHeadBlock.Timestamp}."; + var error = $"Payload timestamp {payloadAttributes.Timestamp} must be greater than block timestamp {newHeadBlock.Timestamp}."; if (_logger.IsWarn) _logger.Warn($"Invalid payload attributes: {error}"); @@ -258,23 +232,12 @@ public ResultWrapper StartBuildingPayload(Block newHe payloadId = _payloadPreparationService.StartPreparingPayload(newHeadBlock.Header, payloadAttributes); } + if (_logger.IsInfo) _logger.Info($"Valid. Request: {requestStr}."); + _blockTree.ForkChoiceUpdated(forkchoiceState.FinalizedBlockHash, forkchoiceState.SafeBlockHash); return ForkchoiceUpdatedV1Result.Valid(payloadId, forkchoiceState.HeadBlockHash); } - private ResultWrapper? ValidateAttributes(PayloadAttributes? payloadAttributes, int version) - { - string? error = null; - return payloadAttributes?.Validate(_specProvider, version, out error) switch - { - PayloadAttributesValidationResult.InvalidParams => - ResultWrapper.Fail(error!, ErrorCodes.InvalidParams), - PayloadAttributesValidationResult.UnsupportedFork => - ResultWrapper.Fail(error!, ErrorCodes.UnsupportedFork), - _ => null, - }; - } - private void StartNewBeaconHeaderSync(ForkchoiceStateV1 forkchoiceState, Block block, string requestStr) { _mergeSyncController.InitBeaconHeaderSync(block.Header); @@ -282,7 +245,7 @@ private void StartNewBeaconHeaderSync(ForkchoiceStateV1 forkchoiceState, Block b _peerRefresher.RefreshPeers(block.Hash!, block.ParentHash!, forkchoiceState.FinalizedBlockHash); _blockCacheService.FinalizedHash = forkchoiceState.FinalizedBlockHash; - if (_logger.IsInfo) _logger.Info($"Start a new sync process, Request: {requestStr}."); + if (_logger.IsInfo) _logger.Info($"Start a new sync process... Request: {requestStr}."); } private bool IsInconsistent(Keccak blockHash) => blockHash != Keccak.Zero && !_blockTree.IsMainChain(blockHash); @@ -292,7 +255,7 @@ private void StartNewBeaconHeaderSync(ForkchoiceStateV1 forkchoiceState, Block b Block? block = _blockTree.FindBlock(headBlockHash, BlockTreeLookupOptions.DoNotCreateLevelIfMissing); if (block is null) { - if (_logger.IsInfo) _logger.Info($"Syncing, Block {headBlockHash} not found."); + if (_logger.IsInfo) _logger.Info($"Syncing... Block {headBlockHash} not found."); } return block; @@ -327,6 +290,7 @@ private void StartNewBeaconHeaderSync(ForkchoiceStateV1 forkchoiceState, Block b if (blockHeader is null) { errorMessage = $"Block {blockHash} not found."; + if (_logger.IsWarn) _logger.Warn(errorMessage); } return blockHeader; } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadHandlerBase.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadHandlerBase.cs index 5e04823bfe6..501a6816707 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadHandlerBase.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadHandlerBase.cs @@ -4,26 +4,23 @@ using System.Threading.Tasks; using Nethermind.Core; using Nethermind.Core.Extensions; -using Nethermind.Core.Specs; using Nethermind.JsonRpc; using Nethermind.Logging; using Nethermind.Merge.Plugin.BlockProduction; +using Nethermind.Merge.Plugin.Data; namespace Nethermind.Merge.Plugin.Handlers; -public abstract class GetPayloadHandlerBase : IAsyncHandler where TGetPayloadResult : IForkValidator +public abstract class GetPayloadHandlerBase : IAsyncHandler { private readonly int _apiVersion; private readonly IPayloadPreparationService _payloadPreparationService; - private readonly ISpecProvider _specProvider; private readonly ILogger _logger; - protected GetPayloadHandlerBase(int apiVersion, IPayloadPreparationService payloadPreparationService, - ISpecProvider specProvider, ILogManager logManager) + protected GetPayloadHandlerBase(int apiVersion, IPayloadPreparationService payloadPreparationService, ILogManager logManager) { _apiVersion = apiVersion; _payloadPreparationService = payloadPreparationService; - _specProvider = specProvider; _logger = logManager.GetClassLogger(); } @@ -40,19 +37,11 @@ protected GetPayloadHandlerBase(int apiVersion, IPayloadPreparationService paylo return ResultWrapper.Fail("unknown payload", MergeErrorCodes.UnknownPayload); } - TGetPayloadResult getPayloadResult = GetPayloadResultFromBlock(blockContext); - - if (!getPayloadResult.ValidateFork(_specProvider)) - { - if (_logger.IsWarn) _logger.Warn($"The payload is not supported by the current fork"); - return ResultWrapper.Fail("unsupported fork", ErrorCodes.UnsupportedFork); - } - if (_logger.IsInfo) _logger.Info($"GetPayloadV{_apiVersion} result: {block.Header.ToString(BlockHeader.Format.Full)}."); Metrics.GetPayloadRequests++; Metrics.NumberOfTransactionsInGetPayload = block.Transactions.Length; - return ResultWrapper.Success(getPayloadResult); + return ResultWrapper.Success(GetPayloadResultFromBlock(blockContext)); } protected abstract TGetPayloadResult GetPayloadResultFromBlock(IBlockProductionContext blockProductionContext); diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadV1Handler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadV1Handler.cs index 20a27945f9b..295859ae19a 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadV1Handler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadV1Handler.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using Nethermind.Core.Specs; using Nethermind.Logging; using Nethermind.Merge.Plugin.BlockProduction; using Nethermind.Merge.Plugin.Data; @@ -25,8 +24,8 @@ namespace Nethermind.Merge.Plugin.Handlers; /// public class GetPayloadV1Handler : GetPayloadHandlerBase { - public GetPayloadV1Handler(IPayloadPreparationService payloadPreparationService, ISpecProvider specProvider, ILogManager logManager) : base( - 1, payloadPreparationService, specProvider, logManager) + public GetPayloadV1Handler(IPayloadPreparationService payloadPreparationService, ILogManager logManager) : base( + 1, payloadPreparationService, logManager) { } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadV2Handler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadV2Handler.cs index 1fd7b21355b..2932fe02cc0 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadV2Handler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadV2Handler.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using Nethermind.Core.Specs; using Nethermind.Logging; using Nethermind.Merge.Plugin.BlockProduction; using Nethermind.Merge.Plugin.Data; @@ -14,8 +13,8 @@ namespace Nethermind.Merge.Plugin.Handlers; /// public class GetPayloadV2Handler : GetPayloadHandlerBase { - public GetPayloadV2Handler(IPayloadPreparationService payloadPreparationService, ISpecProvider specProvider, ILogManager logManager) : base( - 2, payloadPreparationService, specProvider, logManager) + public GetPayloadV2Handler(IPayloadPreparationService payloadPreparationService, ILogManager logManager) : base( + 2, payloadPreparationService, logManager) { } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadV3Handler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadV3Handler.cs index 9555b51f1a9..dd1f0ba962c 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadV3Handler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/GetPayloadV3Handler.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using Nethermind.Core.Specs; using Nethermind.Logging; using Nethermind.Merge.Plugin.BlockProduction; using Nethermind.Merge.Plugin.Data; @@ -14,8 +13,8 @@ namespace Nethermind.Merge.Plugin.Handlers; /// public class GetPayloadV3Handler : GetPayloadHandlerBase { - public GetPayloadV3Handler(IPayloadPreparationService payloadPreparationService, ISpecProvider specProvider, ILogManager logManager) : base( - 3, payloadPreparationService, specProvider, logManager) + public GetPayloadV3Handler(IPayloadPreparationService payloadPreparationService, ILogManager logManager) : base( + 3, payloadPreparationService, logManager) { } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IForkValidator.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IForkValidator.cs deleted file mode 100644 index ea0592f9c9f..00000000000 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IForkValidator.cs +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core.Specs; - -namespace Nethermind.Merge.Plugin.Handlers; - -public interface IForkValidator -{ - bool ValidateFork(ISpecProvider specProvider); -} diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IForkchoiceUpdatedHandler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IForkchoiceUpdatedHandler.cs index d3e92a0654d..b390eb798af 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IForkchoiceUpdatedHandler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IForkchoiceUpdatedHandler.cs @@ -10,5 +10,5 @@ namespace Nethermind.Merge.Plugin.Handlers; public interface IForkchoiceUpdatedHandler { - Task> Handle(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes, int fcuVersion); + Task> Handle(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs index babc8965e7f..e9102a8061f 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs @@ -87,7 +87,7 @@ public NewPayloadHandler( /// public async Task> HandleAsync(ExecutionPayload request) { - string requestStr = $"new block: {request}"; + string requestStr = $"a new payload: {request}"; if (_logger.IsInfo) { _logger.Info($"Received {requestStr}"); } if (!request.TryGetBlock(out Block? block, _poSSwitcher.FinalTotalDifficulty)) @@ -126,12 +126,6 @@ public async Task> HandleAsync(ExecutionPayload r BlockHeader? parentHeader = _blockTree.FindHeader(block.ParentHash!, BlockTreeLookupOptions.DoNotCreateLevelIfMissing); if (parentHeader is null) { - if (!_blockValidator.ValidateOrphanedBlock(block!, out string? error)) - { - if (_logger.IsWarn) _logger.Info($"Invalid block without parent. Result of {requestStr}."); - return NewPayloadV1Result.Invalid(null, $"Invalid block without parent: {error}."); - } - // possible that headers sync finished before this was called, so blocks in cache weren't inserted if (!_beaconSyncStrategy.IsBeaconSyncFinished(parentHeader)) { @@ -148,7 +142,7 @@ public async Task> HandleAsync(ExecutionPayload r // we need to check if the head is greater than block.Number. In fast sync we could return Valid to CL without this if if (_blockTree.IsOnMainChainBehindOrEqualHead(block)) { - if (_logger.IsInfo) _logger.Info($"Valid... A new payload ignored. Block {block.ToString(Block.Format.Short)} found in main chain."); + if (_logger.IsInfo) _logger.Info($"Valid... A new payload ignored. Block {block.ToString(Block.Format.FullHashAndNumber)} found in main chain."); return NewPayloadV1Result.Valid(block.Hash); } @@ -215,7 +209,7 @@ public async Task> HandleAsync(ExecutionPayload r return NewPayloadV1Result.Syncing; } - if (_logger.IsDebug) _logger.Debug($"Valid. Result of {requestStr}."); + if (_logger.IsInfo) _logger.Info($"Valid. Result of {requestStr}."); return NewPayloadV1Result.Valid(block.Hash); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/IEngineRpcModule.Cancun.cs b/src/Nethermind/Nethermind.Merge.Plugin/IEngineRpcModule.Cancun.cs index 85157dabc97..43eb090084a 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/IEngineRpcModule.Cancun.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/IEngineRpcModule.Cancun.cs @@ -2,8 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading.Tasks; -using Nethermind.Consensus.Producers; -using Nethermind.Core.Crypto; using Nethermind.JsonRpc; using Nethermind.JsonRpc.Modules; using Nethermind.Merge.Plugin.Data; @@ -12,18 +10,11 @@ namespace Nethermind.Merge.Plugin; public partial interface IEngineRpcModule : IRpcModule { - - [JsonRpcMethod( - Description = "Verifies the payload according to the execution environment rules and returns the verification status and hash of the last valid block.", - IsSharable = true, - IsImplemented = true)] - Task> engine_forkchoiceUpdatedV3(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes = null); - [JsonRpcMethod( Description = "Verifies the payload according to the execution environment rules and returns the verification status and hash of the last valid block.", IsSharable = true, IsImplemented = true)] - Task> engine_newPayloadV3(ExecutionPayloadV3 executionPayload, byte[]?[] blobVersionedHashes, Keccak? parentBeaconBlockRoot); + Task> engine_newPayloadV3(ExecutionPayload executionPayload, byte[][]? blobVersionedHashes = null); [JsonRpcMethod( Description = "Returns the most recent version of an execution payload and fees with respect to the transaction set contained by the mempool.", diff --git a/src/Nethermind/Nethermind.Merge.Plugin/IMergeConfig.cs b/src/Nethermind/Nethermind.Merge.Plugin/IMergeConfig.cs index 1bcaa73f7f7..300377674b5 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/IMergeConfig.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/IMergeConfig.cs @@ -55,8 +55,5 @@ public interface IMergeConfig : IConfig [ConfigItem(Description = "Requests the GC to release process memory back to OS. Accept values `-1` which disables it, `0` which releases every time, and any positive integer which does it after that many EngineApi calls.", DefaultValue = "75")] public int CollectionsPerDecommit { get; set; } - - [ConfigItem(Description = "Maximum time in seconds for NewPayload request to be executed.", DefaultValue = "7", HiddenFromDocs = true)] - public int NewPayloadTimeout { get; } } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/InvalidChainTracker/InvalidBlockInterceptor.cs b/src/Nethermind/Nethermind.Merge.Plugin/InvalidChainTracker/InvalidBlockInterceptor.cs index 71034535de8..d4c24278e9d 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/InvalidChainTracker/InvalidBlockInterceptor.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/InvalidChainTracker/InvalidBlockInterceptor.cs @@ -3,6 +3,7 @@ using Nethermind.Consensus.Validators; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Logging; namespace Nethermind.Merge.Plugin.InvalidChainTracker; @@ -23,8 +24,6 @@ public InvalidBlockInterceptor( _logger = logManager.GetClassLogger(typeof(InvalidBlockInterceptor)); } - public bool ValidateOrphanedBlock(Block block, out string? error) => _baseValidator.ValidateOrphanedBlock(block, out error); - public bool Validate(BlockHeader header, BlockHeader? parent, bool isUncle = false) { bool result = _baseValidator.Validate(header, parent, isUncle); diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergeBetterPeerStrategy.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergeBetterPeerStrategy.cs index b7b53b517e6..abf757af625 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergeBetterPeerStrategy.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergeBetterPeerStrategy.cs @@ -1,7 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Blockchain.Synchronization; using Nethermind.Consensus; +using Nethermind.Core; using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Merge.Plugin.Synchronization; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergeConfig.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergeConfig.cs index e8a6e9f17b1..ae9d74ea0b5 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergeConfig.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergeConfig.cs @@ -30,7 +30,5 @@ public class MergeConfig : IMergeConfig public GcCompaction CompactMemory { get; set; } = GcCompaction.Yes; public int CollectionsPerDecommit { get; set; } = 75; - - public int NewPayloadTimeout { get; set; } = 7; } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergeHealthHintService.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergeHealthHintService.cs index 79e0ceecf25..a229d35b891 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergeHealthHintService.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergeHealthHintService.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Api; using Nethermind.Blockchain.Services; using Nethermind.Config; using Nethermind.Consensus; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs index 8a3569edd1d..5aa639b6662 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs @@ -307,9 +307,9 @@ public Task InitRpcModules() _api.RpcCapabilitiesProvider = new EngineRpcCapabilitiesProvider(_api.SpecProvider); IEngineRpcModule engineRpcModule = new EngineRpcModule( - new GetPayloadV1Handler(payloadPreparationService, _api.SpecProvider, _api.LogManager), - new GetPayloadV2Handler(payloadPreparationService, _api.SpecProvider, _api.LogManager), - new GetPayloadV3Handler(payloadPreparationService, _api.SpecProvider, _api.LogManager), + new GetPayloadV1Handler(payloadPreparationService, _api.LogManager), + new GetPayloadV2Handler(payloadPreparationService, _api.LogManager), + new GetPayloadV3Handler(payloadPreparationService, _api.LogManager), new NewPayloadHandler( _api.BlockValidator, _api.BlockTree, @@ -322,8 +322,7 @@ public Task InitRpcModules() _api.BlockProcessingQueue, _invalidChainTracker, _beaconSync, - _api.LogManager, - TimeSpan.FromSeconds(_mergeConfig.NewPayloadTimeout)), + _api.LogManager), new ForkchoiceUpdatedHandler( _api.BlockTree, _blockFinalizationManager, @@ -335,7 +334,6 @@ public Task InitRpcModules() _beaconSync, _beaconPivot, _peerRefresher, - _api.SpecProvider, _api.LogManager), new GetPayloadBodiesByHashV1Handler(_api.BlockTree, _api.LogManager), new GetPayloadBodiesByRangeV1Handler(_api.BlockTree, _api.LogManager), @@ -421,7 +419,6 @@ public Task InitSynchronization() _blockCacheService, _beaconSync, _api.DbProvider.MetadataDb, - _api.SyncProgressResolver, _api.LogManager); SyncReport syncReport = new(_api.SyncPeerPool, _api.NodeStatsManager, _api.SyncModeSelector, _syncConfig, _beaconPivot, _api.LogManager); @@ -455,7 +452,6 @@ public Task InitSynchronization() _poSSwitcher, _mergeConfig, _invalidChainTracker, - _api.ProcessExit!, _api.LogManager, syncReport); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergeSealValidator.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergeSealValidator.cs index a6bb70927de..fcbdd0985ac 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergeSealValidator.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergeSealValidator.cs @@ -3,6 +3,7 @@ using Nethermind.Consensus; using Nethermind.Core; +using Nethermind.Merge.Plugin.InvalidChainTracker; namespace Nethermind.Merge.Plugin; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/PoSSwitcher.cs b/src/Nethermind/Nethermind.Merge.Plugin/PoSSwitcher.cs index f790a41cdfd..6d0ea37e991 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/PoSSwitcher.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/PoSSwitcher.cs @@ -3,6 +3,7 @@ using System; using Nethermind.Blockchain; +using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Synchronization; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -11,6 +12,7 @@ using Nethermind.Core.Specs; using Nethermind.Db; using Nethermind.Logging; +using Nethermind.Merge.Plugin.Handlers; using Nethermind.Serialization.Rlp; namespace Nethermind.Merge.Plugin diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconHeadersSyncDownloader.cs b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconHeadersSyncDownloader.cs index 0edc10a441a..3a5c69510a5 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconHeadersSyncDownloader.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconHeadersSyncDownloader.cs @@ -3,6 +3,8 @@ using Nethermind.Logging; using Nethermind.Synchronization.FastBlocks; +using Nethermind.Synchronization.ParallelSync; +using Nethermind.Synchronization.Peers; namespace Nethermind.Merge.Plugin.Synchronization; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconHeadersSyncFeed.cs b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconHeadersSyncFeed.cs index f86253edfa6..814d8f52865 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconHeadersSyncFeed.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconHeadersSyncFeed.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain; @@ -12,6 +13,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Crypto; +using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Merge.Plugin.InvalidChainTracker; using Nethermind.Synchronization; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconSync.cs b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconSync.cs index 9af8aee8ea8..f99fa8b9a22 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconSync.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconSync.cs @@ -6,8 +6,10 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Crypto; +using Nethermind.Db; using Nethermind.Logging; using Nethermind.Merge.Plugin.Handlers; +using Nethermind.Serialization.Rlp; using Nethermind.Synchronization; namespace Nethermind.Merge.Plugin.Synchronization diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeBlockDownloader.cs b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeBlockDownloader.cs index 83ab84cbb2f..7e19c6a2fbc 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeBlockDownloader.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeBlockDownloader.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; @@ -11,9 +12,12 @@ using Nethermind.Consensus; using Nethermind.Consensus.Validators; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Crypto; using Nethermind.Logging; +using Nethermind.Merge.Plugin.Handlers; +using Nethermind.Merge.Plugin.InvalidChainTracker; using Nethermind.Synchronization; using Nethermind.Synchronization.Blocks; using Nethermind.Synchronization.ParallelSync; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeSynchronizer.cs b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeSynchronizer.cs index f10b7619db7..a07e2a25b64 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeSynchronizer.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/MergeSynchronizer.cs @@ -4,11 +4,13 @@ using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; -using Nethermind.Config; using Nethermind.Consensus; +using Nethermind.Consensus.Processing; +using Nethermind.Consensus.Validators; using Nethermind.Core.Specs; using Nethermind.Db; using Nethermind.Logging; +using Nethermind.Merge.Plugin.Handlers; using Nethermind.Merge.Plugin.InvalidChainTracker; using Nethermind.Stats; using Nethermind.Synchronization; @@ -42,7 +44,6 @@ public MergeSynchronizer( IPoSSwitcher poSSwitcher, IMergeConfig mergeConfig, IInvalidChainTracker invalidChainTracker, - IProcessExitSource exitSource, ILogManager logManager, ISyncReport syncReport) : base( @@ -58,7 +59,6 @@ public MergeSynchronizer( blockDownloaderFactory, pivot, syncReport, - exitSource, logManager) { _invalidChainTracker = invalidChainTracker; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/PeerRefresher.cs b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/PeerRefresher.cs index a363789082a..eb69a9e7221 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/PeerRefresher.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/PeerRefresher.cs @@ -2,6 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -11,6 +14,8 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Timers; using Nethermind.Logging; + +using Nethermind.Stats.Model; using Nethermind.Synchronization; using Nethermind.Synchronization.Peers; @@ -60,7 +65,9 @@ private void Refresh(Keccak headBlockhash, Keccak headParentBlockhash, Keccak fi _lastRefresh = DateTime.Now; foreach (PeerInfo peer in _syncPeerPool.AllPeers) { - _ = StartPeerRefreshTask(peer.SyncPeer, headBlockhash, headParentBlockhash, finalizedBlockhash); +#pragma warning disable CS4014 + StartPeerRefreshTask(peer.SyncPeer, headBlockhash, headParentBlockhash, finalizedBlockhash); +#pragma warning restore CS4014 } } @@ -102,7 +109,7 @@ internal async Task RefreshPeerForFcu( BlockHeader[] headAndParentHeaders = await getHeadParentHeaderTask; if (!TryGetHeadAndParent(headBlockhash, headParentBlockhash, headAndParentHeaders, out headBlockHeader, out headParentBlockHeader)) { - _syncPeerPool.ReportRefreshFailed(syncPeer, "ForkChoiceUpdate: unexpected response length"); + _syncPeerPool.ReportRefreshFailed(syncPeer, "FCU unexpected response length"); return; } @@ -110,17 +117,17 @@ internal async Task RefreshPeerForFcu( } catch (AggregateException exception) when (exception.InnerException is OperationCanceledException) { - _syncPeerPool.ReportRefreshFailed(syncPeer, "ForkChoiceUpdate: timeout", exception.InnerException); + _syncPeerPool.ReportRefreshFailed(syncPeer, "FCU timeout", exception.InnerException); return; } catch (OperationCanceledException exception) { - _syncPeerPool.ReportRefreshFailed(syncPeer, "ForkChoiceUpdate: timeout", exception); + _syncPeerPool.ReportRefreshFailed(syncPeer, "FCU timeout", exception); return; } catch (Exception exception) { - _syncPeerPool.ReportRefreshFailed(syncPeer, "ForkChoiceUpdate: faulted", exception); + _syncPeerPool.ReportRefreshFailed(syncPeer, "FCU faulted", exception); return; } @@ -128,7 +135,7 @@ internal async Task RefreshPeerForFcu( if (finalizedBlockhash != Keccak.Zero && finalizedBlockHeader is null) { - _syncPeerPool.ReportRefreshFailed(syncPeer, "ForkChoiceUpdate: no finalized block header"); + _syncPeerPool.ReportRefreshFailed(syncPeer, "FCU no finalized block header"); return; } @@ -156,7 +163,7 @@ private bool CheckHeader(ISyncPeer syncPeer, BlockHeader? header) { if (!HeaderValidator.ValidateHash(header)) { - _syncPeerPool.ReportRefreshFailed(syncPeer, "ForkChoiceUpdate: invalid header hash"); + _syncPeerPool.ReportRefreshFailed(syncPeer, "FCU invalid header hash"); return false; } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/PivotUpdator.cs b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/PivotUpdator.cs index d0200779e38..b5da377ad3c 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/PivotUpdator.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/PivotUpdator.cs @@ -29,12 +29,10 @@ public class PivotUpdator private readonly IBlockCacheService _blockCacheService; private readonly IBeaconSyncStrategy _beaconSyncStrategy; private readonly IDb _metadataDb; - private readonly ISyncProgressResolver _syncProgressResolver; private readonly ILogger _logger; private readonly CancellationTokenSource _cancellation = new(); - private static int _maxAttempts; private int _attemptsLeft; private int _updateInProgress; private Keccak _alreadyAnnouncedNewPivotHash = Keccak.Zero; @@ -46,7 +44,6 @@ public PivotUpdator(IBlockTree blockTree, IBlockCacheService blockCacheService, IBeaconSyncStrategy beaconSyncStrategy, IDb metadataDb, - ISyncProgressResolver syncProgressResolver, ILogManager logManager) { _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); @@ -56,10 +53,8 @@ public PivotUpdator(IBlockTree blockTree, _blockCacheService = blockCacheService ?? throw new ArgumentNullException(nameof(blockCacheService)); _beaconSyncStrategy = beaconSyncStrategy ?? throw new ArgumentNullException(nameof(beaconSyncStrategy)); _metadataDb = metadataDb ?? throw new ArgumentNullException(nameof(metadataDb)); - _syncProgressResolver = syncProgressResolver ?? throw new ArgumentNullException(nameof(syncProgressResolver)); _logger = logManager.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); - _maxAttempts = syncConfig.MaxAttemptsToUpdatePivot; _attemptsLeft = syncConfig.MaxAttemptsToUpdatePivot; if (!TryUpdateSyncConfigUsingDataFromDb()) @@ -79,7 +74,9 @@ private bool TryUpdateSyncConfigUsingDataFromDb() long updatedPivotBlockNumber = pivotStream.DecodeLong(); Keccak updatedPivotBlockHash = pivotStream.DecodeKeccak()!; - UpdateConfigValues(updatedPivotBlockHash, updatedPivotBlockNumber); + _syncConfig.PivotNumber = updatedPivotBlockNumber.ToString(); + _syncConfig.PivotHash = updatedPivotBlockHash.ToString(); + _syncConfig.MaxAttemptsToUpdatePivot = 0; if (_logger.IsInfo) _logger.Info($"Pivot block has been set based on data from db. Pivot block number: {updatedPivotBlockNumber}, hash: {updatedPivotBlockHash}"); return true; @@ -144,7 +141,7 @@ private async Task TrySetFreshPivot(CancellationToken cancellationToken) if (finalizedBlockHash is null || finalizedBlockHash == Keccak.Zero) { - if (_logger.IsInfo && (_maxAttempts - _attemptsLeft) % 10 == 0) _logger.Info($"Waiting for Forkchoice message from Consensus Layer to set fresh pivot block [{_maxAttempts - _attemptsLeft}s]"); + if (_logger.IsInfo && _attemptsLeft % 10 == 0) _logger.Info($"Waiting for Forkchoice message from Consensus Layer to set fresh pivot block. {_attemptsLeft} attempts left"); return null; } @@ -220,7 +217,7 @@ private async Task TrySetFreshPivot(CancellationToken cancellationToken) } } - if (_logger.IsInfo && (_maxAttempts - _attemptsLeft) % 10 == 0) _logger.Info($"Potential new pivot block hash: {finalizedBlockHash}. Waiting for pivot block header [{_maxAttempts - _attemptsLeft}s]"); + if (_logger.IsInfo) _logger.Info($"Potential new pivot block hash: {finalizedBlockHash}. Waiting for pivot block header. {_attemptsLeft} attempts left"); return null; } @@ -232,14 +229,16 @@ private bool TryOverwritePivot(Keccak finalizedBlockHash, long finalizedBlockNum if (isCloseToHead && newPivotHigherThanOld) { - UpdateConfigValues(finalizedBlockHash, finalizedBlockNumber); + _syncConfig.PivotHash = finalizedBlockHash.ToString(); + _syncConfig.PivotNumber = finalizedBlockNumber.ToString(); + _syncConfig.MaxAttemptsToUpdatePivot = 0; RlpStream pivotData = new(38); //1 byte (prefix) + 4 bytes (long) + 1 byte (prefix) + 32 bytes (Keccak) pivotData.Encode(finalizedBlockNumber); pivotData.Encode(finalizedBlockHash); _metadataDb.Set(MetadataDbKeys.UpdatedPivotData, pivotData.Data!); - if (_logger.IsInfo) _logger.Info($"New pivot block has been set based on ForkChoiceUpdate from CL. Pivot block number: {finalizedBlockNumber}, hash: {finalizedBlockHash}"); + if (_logger.IsInfo) _logger.Info($"New pivot block has been set based on FCU from CL. Pivot block number: {finalizedBlockNumber}, hash: {finalizedBlockHash}"); return true; } @@ -247,13 +246,4 @@ private bool TryOverwritePivot(Keccak finalizedBlockHash, long finalizedBlockNum if (!newPivotHigherThanOld && _logger.IsInfo) _logger.Info($"Pivot block from Consensus Layer isn't higher than pivot from initial config. New PivotBlockNumber: {finalizedBlockNumber}, old: {_syncConfig.PivotNumber}"); return false; } - - private void UpdateConfigValues(Keccak finalizedBlockHash, long finalizedBlockNumber) - { - _syncConfig.PivotHash = finalizedBlockHash.ToString(); - _syncConfig.PivotNumber = finalizedBlockNumber.ToString(); - _syncConfig.MaxAttemptsToUpdatePivot = 0; - _syncProgressResolver.UpdateBarriers(); - } - } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/PostMergeBlocksSyncPeerAllocationStrategy.cs b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/PostMergeBlocksSyncPeerAllocationStrategy.cs index 02a397da9f8..6a711033216 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/PostMergeBlocksSyncPeerAllocationStrategy.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/PostMergeBlocksSyncPeerAllocationStrategy.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.Linq; using Nethermind.Blockchain; diff --git a/src/Nethermind/Nethermind.Mev.Test/BundlePoolTests.cs b/src/Nethermind/Nethermind.Mev.Test/BundlePoolTests.cs index d6e73eaecc3..c19a43342f2 100644 --- a/src/Nethermind/Nethermind.Mev.Test/BundlePoolTests.cs +++ b/src/Nethermind/Nethermind.Mev.Test/BundlePoolTests.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Antlr4.Runtime.Atn; using FluentAssertions; using Nethermind.Blockchain; using Nethermind.Consensus.Validators; diff --git a/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs b/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs index add36b943b6..3e6e6b235e0 100644 --- a/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs @@ -16,9 +16,11 @@ using Nethermind.Consensus.Test; using Nethermind.Consensus.Transactions; using Nethermind.Consensus.Validators; +using Nethermind.Consensus.Withdrawals; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Core.Test; using Nethermind.Core.Test.Blockchain; using Nethermind.Core.Test.Builders; using Nethermind.Evm.Tracing; @@ -27,6 +29,8 @@ using Nethermind.JsonRpc.Test.Modules; using Nethermind.Logging; using Nethermind.Merge.Plugin.BlockProduction; +using Nethermind.Merge.Plugin.Data; +using Nethermind.Merge.Plugin.Handlers; using Nethermind.Mev.Data; using Nethermind.Mev.Execution; using Nethermind.Mev.Source; @@ -222,7 +226,7 @@ protected override BlockProcessor CreateBlockProcessor() } protected override async Task Build(ISpecProvider? specProvider = null, - UInt256? initialValues = null, bool addBlockOnStart = true) + UInt256? initialValues = null) { TestBlockchain chain = await base.Build(specProvider, initialValues); MevRpcModule = new MevRpcModule(new JsonRpcConfig(), @@ -261,9 +265,8 @@ public MevBundle SendBundle(int blockNumber, params BundleTransaction[] txs) RevertingTxHashes = revertingTxHashes }; ResultWrapper resultOfBundle = MevRpcModule.eth_sendBundle(mevBundleRpc); - - resultOfBundle.Result.Should().NotBe(Result.Success); - resultOfBundle.Data.Should().Be(true); + resultOfBundle.GetResult().ResultType.Should().NotBe(ResultType.Failure); + resultOfBundle.GetData().Should().Be(true); return new MevBundle(blockNumber, txs); } } diff --git a/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.cs b/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.cs index 1dc29be60f2..5341c56ec41 100644 --- a/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.cs @@ -16,6 +16,7 @@ using Nethermind.JsonRpc; using NUnit.Framework; using FluentAssertions; +using Nethermind.Core.Eip2930; using Nethermind.Evm; using Nethermind.Mev.Data; using Nethermind.Specs.Forks; @@ -45,7 +46,7 @@ public static class Contracts public static string CoinbaseDeposit = "0xd0e30db0"; public static int CoinbaseStartingBalanceInWei = 10000000; public static long LargeGasLimit = 9_000_000; - // 1203367 gas + // 1203367 gas public static string LooperInvokeLoop2000 = "0x0b7d796e00000000000000000000000000000000000000000000000000000000000007d0"; // 22000 gas about public static string ReverterInvokeFail = "0xa9cc4718"; @@ -70,7 +71,7 @@ public static class Contracts public static async Task
Deploy(TestMevRpcBlockchain chain, string code, ulong nonce = 0, int value = 1) { Transaction createContractTx = Build.A.Transaction.WithCode(Bytes.FromHexString(code)).WithGasLimit(LargeGasLimit).WithNonce(nonce).WithValue(0).SignedAndResolved(ContractCreatorPrivateKey).TestObject; - // guarantee state change + // guarantee state change await chain.AddBlock(true, createContractTx); TxReceipt? createContractTxReceipt = chain.Bridge.GetReceipt(createContractTx.Hash!); @@ -82,8 +83,8 @@ public static async Task
Deploy(TestMevRpcBlockchain chain, string code private static async Task SendSignedTransaction(TestMevRpcBlockchain chain, Transaction tx) { - ResultWrapper result = await chain.EthRpcModule.eth_sendRawTransaction(EncodeTx(tx).Bytes); - result.Result.Should().Be(Result.Success); + ResultWrapper? result = await chain.EthRpcModule.eth_sendRawTransaction(EncodeTx(tx).Bytes); + Assert.That(result.GetResult().ResultType, Is.Not.EqualTo(ResultType.Failure)); return result.Data; } @@ -107,8 +108,8 @@ private static MevBundle SendBundle(TestMevRpcBlockchain chain, int blockNumber, List revertingTxHashes = txs.Where(tx => tx.CanRevert).Select(tx => tx.Hash!).ToList(); MevBundleRpc mevBundleRpc = new() { BlockNumber = blockNumber, Txs = bundleBytes, RevertingTxHashes = revertingTxHashes.Count > 0 ? revertingTxHashes.ToArray() : null }; ResultWrapper resultOfBundle = chain.MevRpcModule.eth_sendBundle(mevBundleRpc); - resultOfBundle.Result.Should().Be(Result.Success); - resultOfBundle.Data.Should().Be(success); + resultOfBundle.GetResult().ResultType.Should().NotBe(ResultType.Failure); + resultOfBundle.GetData().Should().Be(success); return new MevBundle(blockNumber, txs); } @@ -127,8 +128,8 @@ private static MevMegabundle SendMegabundle(TestMevRpcBlockchain chain, int bloc RelaySignature = Bytes.FromHexString(relaySignature.ToString()) }; ResultWrapper resultOfBundle = chain.MevRpcModule.eth_sendMegabundle(mevMegabundleRpc); - resultOfBundle.Result.Should().Be(Result.Success); - resultOfBundle.Data.Should().Be(success); + resultOfBundle.GetResult().ResultType.Should().NotBe(ResultType.Failure); + resultOfBundle.GetData().Should().Be(success); return mevMegabundle; } @@ -142,7 +143,7 @@ public async Task Should_execute_eth_callBundle_and_serialize_successful_respons Transaction getTx = Build.A.Transaction.WithGasLimit(Contracts.LargeGasLimit).WithGasPrice(1ul).WithTo(contractAddress).WithData(Bytes.FromHexString(Contracts.CallableInvokeGet)).WithValue(0).SignedAndResolved(TestItem.PrivateKeyA).TestObject; Transaction setTx = Build.A.Transaction.WithGasLimit(Contracts.LargeGasLimit).WithGasPrice(1ul).WithTo(contractAddress).WithData(Bytes.FromHexString(Contracts.CallableInvokeSet)).WithValue(0).SignedAndResolved(TestItem.PrivateKeyB).TestObject; string parameters = $"{{\"txs\":[\"{EncodeTx(setTx).Bytes.ToHexString()}\",\"{EncodeTx(getTx).Bytes.ToHexString()}\"]}}"; - string result = await chain.TestSerializedRequest(chain.MevRpcModule, "eth_callBundle", parameters); + string result = chain.TestSerializedRequest(chain.MevRpcModule, "eth_callBundle", parameters); result.Should().Be($"{{\"jsonrpc\":\"2.0\",\"result\":{{\"{setTx.Hash!}\":{{\"value\":\"0x\"}},\"{getTx.Hash!}\":{{\"value\":\"0x000000000000000000000000000000000000000000000000000000000000000f\"}}}},\"id\":67}}"); } @@ -155,7 +156,7 @@ public async Task Should_execute_eth_callBundle_and_not_change_block() Transaction setTx = Build.A.Transaction.WithGasLimit(Contracts.LargeGasLimit).WithGasPrice(1ul).WithTo(contractAddress).WithData(Bytes.FromHexString(Contracts.CallableInvokeSet)).WithValue(0).SignedAndResolved(TestItem.PrivateKeyB).TestObject; string parameters = $"{{\"txs\":[\"{EncodeTx(setTx).Bytes.ToHexString()}\",\"{EncodeTx(getTx).Bytes.ToHexString()}\"],\"blockNumber\":0x1}}"; long headNumber = chain.BlockTree.Head!.Number; - await chain.TestSerializedRequest(chain.MevRpcModule, "eth_callBundle", parameters); + chain.TestSerializedRequest(chain.MevRpcModule, "eth_callBundle", parameters); chain.BlockTree.Head!.Number.Should().Be(headNumber); } @@ -166,7 +167,7 @@ public async Task Should_execute_eth_callBundle_and_serialize_failed_response_pr Address reverterContractAddress = await Contracts.Deploy(chain, Contracts.ReverterCode); Transaction failedTx = Build.A.Transaction.WithGasLimit(Contracts.LargeGasLimit).WithGasPrice(1ul).WithTo(reverterContractAddress).WithData(Bytes.FromHexString(Contracts.ReverterInvokeFail)).SignedAndResolved(TestItem.PrivateKeyC).TestObject; string parameters = $"{{\"txs\":[\"{EncodeTx(failedTx).Bytes.ToHexString()}\"]}}"; - string result = await chain.TestSerializedRequest(chain.MevRpcModule, "eth_callBundle", parameters); + string result = chain.TestSerializedRequest(chain.MevRpcModule, "eth_callBundle", parameters); result.Should().Be($"{{\"jsonrpc\":\"2.0\",\"result\":{{\"{failedTx.Hash!}\":{{\"error\":\"0x\"}}}},\"id\":67}}"); } @@ -180,7 +181,7 @@ public async Task Should_execute_eth_sendBundle_and_serialize_successful_respons Transaction getTx = Build.A.Transaction.WithGasLimit(Contracts.LargeGasLimit).WithGasPrice(1ul).WithTo(contractAddress).WithData(Bytes.FromHexString(Contracts.CallableInvokeGet)).WithValue(0).SignedAndResolved(TestItem.PrivateKeyA).TestObject; Transaction setTx = Build.A.Transaction.WithGasLimit(Contracts.LargeGasLimit).WithGasPrice(1ul).WithTo(contractAddress).WithData(Bytes.FromHexString(Contracts.CallableInvokeSet)).WithValue(0).SignedAndResolved(TestItem.PrivateKeyB).TestObject; string parameters = $"{{\"txs\":[\"{EncodeTx(setTx).Bytes.ToHexString()}\",\"{EncodeTx(getTx).Bytes.ToHexString()}\"],\"blockNumber\":\"0x4\"}}"; - string result = await chain.TestSerializedRequest(chain.MevRpcModule, "eth_sendBundle", parameters); + string result = chain.TestSerializedRequest(chain.MevRpcModule, "eth_sendBundle", parameters); result.Should().Be($"{{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}}"); } @@ -208,7 +209,7 @@ public async Task Should_execute_eth_sendMegabundle_and_serialize_successful_res string parameters = $"{{\"txs\":[\"{EncodeTx(setTx).Bytes.ToHexString()}\",\"{EncodeTx(getTx).Bytes.ToHexString()}\"]," + $"\"blockNumber\":\"0x4\",\"relaySignature\":\"{relaySignature}\"}}"; - string result = await chain.TestSerializedRequest(chain.MevRpcModule, "eth_sendMegabundle", parameters); + string result = chain.TestSerializedRequest(chain.MevRpcModule, "eth_sendMegabundle", parameters); result.Should().Be($"{{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}}"); } diff --git a/src/Nethermind/Nethermind.Mev/BeneficiaryTracer.cs b/src/Nethermind/Nethermind.Mev/BeneficiaryTracer.cs index 8e47875c1f6..e40914d60ab 100644 --- a/src/Nethermind/Nethermind.Mev/BeneficiaryTracer.cs +++ b/src/Nethermind/Nethermind.Mev/BeneficiaryTracer.cs @@ -1,24 +1,22 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Int256; namespace Nethermind.Mev { - public class BeneficiaryTracer : TxTracer, IBlockTracer + public class BeneficiaryTracer : IBlockTracer, ITxTracer { private Address _beneficiary = Address.Zero; - public UInt256 BeneficiaryBalance { get; private set; } - - public override bool IsTracingState => true; - + public bool IsTracingState => true; public bool IsTracingRewards => true; - - public void ReportReward(Address author, string rewardType, UInt256 rewardValue) { } - public void StartNewBlockTrace(Block block) { _beneficiary = block.Header.GasBeneficiary!; @@ -26,16 +24,59 @@ public void StartNewBlockTrace(Block block) public ITxTracer StartNewTxTrace(Transaction? tx) => this; - public void EndTxTrace() { } - - public void EndBlockTrace() { } - - public override void ReportBalanceChange(Address address, UInt256? before, UInt256? after) + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) { if (address == _beneficiary) { BeneficiaryBalance = after ?? UInt256.Zero; } } + + public void EndTxTrace() { } + public void EndBlockTrace() { } + public bool IsTracingStorage => false; + public bool IsTracingReceipt => false; + public bool IsTracingActions => false; + public bool IsTracingOpLevelStorage => false; + public bool IsTracingMemory => false; + public bool IsTracingInstructions => false; + public bool IsTracingRefunds => false; + public bool IsTracingCode => false; + public bool IsTracingStack => false; + public bool IsTracingBlockHash => false; + public bool IsTracingAccess => false; + public bool IsTracingFees => false; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; + public void ReportReward(Address author, string rewardType, UInt256 rewardValue) { } + public void ReportCodeChange(Address address, byte[]? before, byte[]? after) { } + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) { } + public void ReportAccountRead(Address address) { } + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) { } + public void ReportStorageRead(in StorageCell storageCell) { } + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) { } + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) { } + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) { } + public void ReportOperationError(EvmExceptionType error) { } + public void ReportOperationRemainingGas(long gas) { } + public void SetOperationStack(List stackTrace) { } + public void ReportStackPush(in ReadOnlySpan stackItem) { } + public void SetOperationMemory(List memoryTrace) { } + public void SetOperationMemorySize(ulong newSize) { } + public void ReportMemoryChange(long offset, in ReadOnlySpan data) { } + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) { } + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) { } + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) { } + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) { } + public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) { } + public void ReportActionEnd(long gas, ReadOnlyMemory output) { } + public void ReportActionError(EvmExceptionType evmExceptionType) { } + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) { } + public void ReportBlockHash(Keccak blockHash) { } + public void ReportByteCode(byte[] byteCode) { } + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) { } + public void ReportRefund(long refund) { } + public void ReportExtraGasPressure(long extraGasPressure) { } + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) { } + public void ReportFees(UInt256 fees, UInt256 burntFees) { } } } diff --git a/src/Nethermind/Nethermind.Mev/Data/BundleEventArgs.cs b/src/Nethermind/Nethermind.Mev/Data/BundleEventArgs.cs index 148effb64db..264f86d3bd8 100644 --- a/src/Nethermind/Nethermind.Mev/Data/BundleEventArgs.cs +++ b/src/Nethermind/Nethermind.Mev/Data/BundleEventArgs.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Core.Crypto; namespace Nethermind.Mev.Data { diff --git a/src/Nethermind/Nethermind.Mev/Data/BundleTransaction.cs b/src/Nethermind/Nethermind.Mev/Data/BundleTransaction.cs index 75918df848a..27305dc716c 100644 --- a/src/Nethermind/Nethermind.Mev/Data/BundleTransaction.cs +++ b/src/Nethermind/Nethermind.Mev/Data/BundleTransaction.cs @@ -1,9 +1,12 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Linq; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Int256; +using Org.BouncyCastle.Asn1.Cms; namespace Nethermind.Mev.Data { diff --git a/src/Nethermind/Nethermind.Mev/Data/MevCallBundleRpc.cs b/src/Nethermind/Nethermind.Mev/Data/MevCallBundleRpc.cs index 5cee7cb908c..5c845f4c61b 100644 --- a/src/Nethermind/Nethermind.Mev/Data/MevCallBundleRpc.cs +++ b/src/Nethermind/Nethermind.Mev/Data/MevCallBundleRpc.cs @@ -3,6 +3,7 @@ using System; using Nethermind.Blockchain.Find; +using Nethermind.Int256; namespace Nethermind.Mev.Data { diff --git a/src/Nethermind/Nethermind.Mev/Data/SimulatedMevBundle.cs b/src/Nethermind/Nethermind.Mev/Data/SimulatedMevBundle.cs index 0d1e674528d..a16c4a0951a 100644 --- a/src/Nethermind/Nethermind.Mev/Data/SimulatedMevBundle.cs +++ b/src/Nethermind/Nethermind.Mev/Data/SimulatedMevBundle.cs @@ -1,7 +1,14 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections; +using System.Linq; using Nethermind.Int256; +using Nethermind.TxPool; +using Nethermind.Core; +using System.Collections.Generic; +using Nethermind.Core.Crypto; namespace Nethermind.Mev.Data { diff --git a/src/Nethermind/Nethermind.Mev/Execution/CallTxBundleExecutor.cs b/src/Nethermind/Nethermind.Mev/Execution/CallTxBundleExecutor.cs index 422c91a0411..dc4ce4bc931 100644 --- a/src/Nethermind/Nethermind.Mev/Execution/CallTxBundleExecutor.cs +++ b/src/Nethermind/Nethermind.Mev/Execution/CallTxBundleExecutor.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Linq; +using System.Text; using Nethermind.Consensus; using Nethermind.Core.Specs; using Nethermind.Evm; diff --git a/src/Nethermind/Nethermind.Mev/Execution/TxBundleExecutor.cs b/src/Nethermind/Nethermind.Mev/Execution/TxBundleExecutor.cs index 17688769cdc..4453be3cb6e 100644 --- a/src/Nethermind/Nethermind.Mev/Execution/TxBundleExecutor.cs +++ b/src/Nethermind/Nethermind.Mev/Execution/TxBundleExecutor.cs @@ -12,8 +12,11 @@ using Nethermind.Crypto; using Nethermind.Evm.Tracing; using Nethermind.Facade; +using Nethermind.Int256; using Nethermind.JsonRpc; using Nethermind.Mev.Data; +using Nethermind.Specs; +using Nethermind.Specs.Forks; namespace Nethermind.Mev.Execution { diff --git a/src/Nethermind/Nethermind.Mev/Execution/TxBundleSimulator.cs b/src/Nethermind/Nethermind.Mev/Execution/TxBundleSimulator.cs index 355e994c574..6ade1a7da89 100644 --- a/src/Nethermind/Nethermind.Mev/Execution/TxBundleSimulator.cs +++ b/src/Nethermind/Nethermind.Mev/Execution/TxBundleSimulator.cs @@ -3,12 +3,16 @@ using System; using System.Collections; +using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; +using Nethermind.Blockchain; using Nethermind.Consensus; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Int256; using Nethermind.Mev.Data; @@ -85,7 +89,7 @@ protected override SimulatedMevBundle BuildResult(MevBundle bundle, BundleBlockT protected override BundleBlockTracer CreateBlockTracer(MevBundle mevBundle) => new(_gasLimit, Beneficiary, mevBundle.Transactions.Count); - public class BundleBlockTracer : BlockTracer + public class BundleBlockTracer : IBlockTracer { private readonly long _gasLimit; private readonly Address _beneficiary; @@ -95,7 +99,7 @@ public class BundleBlockTracer : BlockTracer private UInt256? _beneficiaryBalanceBefore; private UInt256? _beneficiaryBalanceAfter; - private int _index; + private int _index = 0; public long GasUsed { get; private set; } @@ -107,7 +111,7 @@ public BundleBlockTracer(long gasLimit, Address beneficiary, int txCount) TransactionResults = new BitArray(txCount); } - public override bool IsTracingRewards => true; + public bool IsTracingRewards => true; public UInt256 BundleFee { get; private set; } public UInt256[] TxFees { get; } @@ -128,7 +132,7 @@ public UInt256 CoinbasePayments public BitArray TransactionResults { get; } - public override void ReportReward(Address author, string rewardType, UInt256 rewardValue) + public void ReportReward(Address author, string rewardType, UInt256 rewardValue) { if (author == _beneficiary) { @@ -136,18 +140,18 @@ public override void ReportReward(Address author, string rewardType, UInt256 rew } } - public override void StartNewBlockTrace(Block block) + public void StartNewBlockTrace(Block block) { _block = block; } - public override ITxTracer StartNewTxTrace(Transaction? tx) + public ITxTracer StartNewTxTrace(Transaction? tx) { return tx is null ? new BundleTxTracer(_beneficiary, null, -1) : _tracer = new BundleTxTracer(_beneficiary, tx, _index++); } - public override void EndTxTrace() + public void EndTxTrace() { GasUsed += _tracer!.GasSpent; @@ -174,9 +178,13 @@ public override void EndTxTrace() throw new OperationCanceledException("Block gas limit exceeded."); } } + + public void EndBlockTrace() + { + } } - private class BundleTxTracer : TxTracer + public class BundleTxTracer : ITxTracer { public Transaction? Transaction { get; } public int Index { get; } @@ -189,28 +197,101 @@ public BundleTxTracer(Address beneficiary, Transaction? transaction, int index) _beneficiary = beneficiary; } - public override bool IsTracingReceipt => true; - public override bool IsTracingState => true; - public long GasSpent { get; private set; } + public bool IsTracingReceipt => true; + public bool IsTracingActions => false; + public bool IsTracingOpLevelStorage => false; + public bool IsTracingMemory => false; + public bool IsTracingInstructions => false; + public bool IsTracingRefunds => false; + public bool IsTracingCode => false; + public bool IsTracingStack => false; + public bool IsTracingState => true; + public bool IsTracingStorage => false; + public bool IsTracingBlockHash => false; + public bool IsTracingAccess => false; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; + public long GasSpent { get; set; } public UInt256? BeneficiaryBalanceBefore { get; private set; } public UInt256? BeneficiaryBalanceAfter { get; private set; } + public bool IsTracingFees => false; + public bool Success { get; private set; } public string? Error { get; private set; } - public override void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak? stateRoot = null) { GasSpent = gasSpent; Success = true; } - public override void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak? stateRoot = null) { GasSpent = gasSpent; Success = false; Error = error; } - public override void ReportBalanceChange(Address address, UInt256? before, UInt256? after) + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) + { + throw new NotSupportedException(); + } + + public void ReportOperationError(EvmExceptionType error) + { + throw new NotSupportedException(); + } + + public void ReportOperationRemainingGas(long gas) + { + throw new NotSupportedException(); + } + + public void SetOperationStack(List stackTrace) + { + throw new NotSupportedException(); + } + + public void ReportStackPush(in ReadOnlySpan stackItem) + { + throw new NotSupportedException(); + } + + public void SetOperationMemory(List memoryTrace) + { + throw new NotSupportedException(); + } + + public void SetOperationMemorySize(ulong newSize) + { + throw new NotSupportedException(); + } + + public void ReportMemoryChange(long offset, in ReadOnlySpan data) + { + throw new NotSupportedException(); + } + + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) + { + throw new NotSupportedException(); + } + + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) + { + throw new NotSupportedException(); + } + + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) + { + throw new NotSupportedException(); + } + + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) + { + throw new NotSupportedException(); + } + + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) { if (address == _beneficiary) { @@ -218,6 +299,84 @@ public override void ReportBalanceChange(Address address, UInt256? before, UInt2 BeneficiaryBalanceAfter = after; } } + + public void ReportCodeChange(Address address, byte[]? before, byte[]? after) + { + throw new NotSupportedException(); + } + + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) + { + } + + public void ReportAccountRead(Address address) + { + } + + public void ReportStorageChange(in StorageCell storageCell, byte[] before, byte[] after) + { + throw new NotSupportedException(); + } + + public void ReportStorageRead(in StorageCell storageCell) + { + throw new NotImplementedException(); + } + + public void ReportAction(long gas, UInt256 value, Address from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) + { + throw new NotSupportedException(); + } + + public void ReportActionEnd(long gas, ReadOnlyMemory output) + { + throw new NotSupportedException(); + } + + public void ReportActionError(EvmExceptionType exceptionType) + { + throw new NotSupportedException(); + } + + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) + { + throw new NotSupportedException(); + } + + public void ReportBlockHash(Keccak blockHash) + { + throw new NotSupportedException(); + } + + public void ReportByteCode(byte[] byteCode) + { + throw new NotSupportedException(); + } + + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) + { + throw new NotSupportedException(); + } + + public void ReportRefund(long refund) + { + throw new NotSupportedException(); + } + + public void ReportExtraGasPressure(long extraGasPressure) + { + throw new NotImplementedException(); + } + + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) + { + throw new NotImplementedException(); + } + + public void ReportFees(UInt256 fees, UInt256 burntFees) + { + throw new NotImplementedException(); + } } } } diff --git a/src/Nethermind/Nethermind.Mev/Metrics.cs b/src/Nethermind/Nethermind.Mev/Metrics.cs index 5e69506a579..515c7e5a859 100644 --- a/src/Nethermind/Nethermind.Mev/Metrics.cs +++ b/src/Nethermind/Nethermind.Mev/Metrics.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using Nethermind.Core.Attributes; +using Nethermind.Int256; namespace Nethermind.Mev { diff --git a/src/Nethermind/Nethermind.Mev/MevBlockProductionTransactionsExecutor.cs b/src/Nethermind/Nethermind.Mev/MevBlockProductionTransactionsExecutor.cs index d0bb75b435e..f0582000f77 100644 --- a/src/Nethermind/Nethermind.Mev/MevBlockProductionTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Mev/MevBlockProductionTransactionsExecutor.cs @@ -8,7 +8,6 @@ using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; -using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; @@ -54,7 +53,7 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p LinkedHashSet transactionsInBlock = new(ByHashTxComparer.Instance); List bundleTransactions = new(); Keccak? bundleHash = null; - BlockExecutionContext blkCtx = new(block.Header); + foreach (Transaction currentTx in transactions) { // if we don't accumulate bundle yet @@ -70,7 +69,7 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p else { // otherwise process transaction as usual - TxAction action = ProcessTransaction(block, blkCtx, currentTx, transactionsInBlock.Count, receiptsTracer, processingOptions, transactionsInBlock); + TxAction action = ProcessTransaction(block, currentTx, transactionsInBlock.Count, receiptsTracer, processingOptions, transactionsInBlock); if (action == TxAction.Stop) break; } } @@ -90,7 +89,7 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p else { // process accumulated bundle - TxAction action = ProcessBundle(block, blkCtx, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); + TxAction action = ProcessBundle(block, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); if (action == TxAction.Stop) break; // start accumulating new bundle @@ -103,11 +102,11 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p { // process the bundle and stop accumulating it bundleHash = null; - TxAction action = ProcessBundle(block, blkCtx, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); + TxAction action = ProcessBundle(block, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); if (action == TxAction.Stop) break; // process normal transaction - action = ProcessTransaction(block, blkCtx, currentTx, transactionsInBlock.Count, receiptsTracer, processingOptions, transactionsInBlock); + action = ProcessTransaction(block, currentTx, transactionsInBlock.Count, receiptsTracer, processingOptions, transactionsInBlock); if (action == TxAction.Stop) break; } } @@ -115,7 +114,7 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p // if we ended with accumulated bundle, lets process it if (bundleTransactions.Count > 0) { - ProcessBundle(block, blkCtx, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); + ProcessBundle(block, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); } _stateProvider.Commit(spec, receiptsTracer); @@ -125,7 +124,6 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p } private TxAction ProcessBundle(Block block, - BlockExecutionContext blkCtx, List bundleTransactions, LinkedHashSet transactionsInBlock, BlockReceiptsTracer receiptsTracer, @@ -149,7 +147,7 @@ bool CheckFeeNotManipulated() TxAction txAction = TxAction.Skip; for (int index = 0; index < bundleTransactions.Count && bundleSucceeded; index++) { - txAction = ProcessBundleTransaction(block, blkCtx, bundleTransactions[index], index, receiptsTracer, processingOptions, transactionsInBlock); + txAction = ProcessBundleTransaction(block, bundleTransactions[index], index, receiptsTracer, processingOptions, transactionsInBlock); bundleSucceeded &= txAction == TxAction.Add; // if we need to stop on not first tx in the bundle, we actually want to skip the bundle @@ -188,14 +186,13 @@ bool CheckFeeNotManipulated() private TxAction ProcessBundleTransaction( Block block, - BlockExecutionContext blkCtx, BundleTransaction currentTx, int index, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions, LinkedHashSet transactionsInBlock) { - TxAction action = ProcessTransaction(block, blkCtx, currentTx, index, receiptsTracer, processingOptions, transactionsInBlock, false); + TxAction action = ProcessTransaction(block, currentTx, index, receiptsTracer, processingOptions, transactionsInBlock, false); if (action == TxAction.Add) { string? error = receiptsTracer.LastReceipt.Error; diff --git a/src/Nethermind/Nethermind.Mev/MevConfig.cs b/src/Nethermind/Nethermind.Mev/MevConfig.cs index 08cc08f41c2..288fb596d94 100644 --- a/src/Nethermind/Nethermind.Mev/MevConfig.cs +++ b/src/Nethermind/Nethermind.Mev/MevConfig.cs @@ -1,6 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; +using System.Linq; +using Nethermind.Core; using Nethermind.Int256; namespace Nethermind.Mev diff --git a/src/Nethermind/Nethermind.Mev/MevModuleFactory.cs b/src/Nethermind/Nethermind.Mev/MevModuleFactory.cs index 2ffb7d6a59b..6c5cad8e8ad 100644 --- a/src/Nethermind/Nethermind.Mev/MevModuleFactory.cs +++ b/src/Nethermind/Nethermind.Mev/MevModuleFactory.cs @@ -2,13 +2,19 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Blockchain; +using Nethermind.Blockchain.Find; +using Nethermind.Blockchain.Receipts; using Nethermind.Consensus; +using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Db; using Nethermind.JsonRpc; using Nethermind.JsonRpc.Modules; +using Nethermind.Logging; using Nethermind.Mev.Execution; using Nethermind.Mev.Source; using Nethermind.State; +using Nethermind.Trie.Pruning; namespace Nethermind.Mev { diff --git a/src/Nethermind/Nethermind.Mev/MevPlugin.cs b/src/Nethermind/Nethermind.Mev/MevPlugin.cs index 96aaf787dd3..9996b4a252a 100644 --- a/src/Nethermind/Nethermind.Mev/MevPlugin.cs +++ b/src/Nethermind/Nethermind.Mev/MevPlugin.cs @@ -20,183 +20,184 @@ using Nethermind.Mev.Execution; using Nethermind.Mev.Source; -namespace Nethermind.Mev; - -public class MevPlugin : IConsensusWrapperPlugin +namespace Nethermind.Mev { - private static readonly ProcessingOptions SimulateBundleProcessingOptions = ProcessingOptions.ProducingBlock | ProcessingOptions.IgnoreParentNotOnMainChain; + public class MevPlugin : IConsensusWrapperPlugin + { + private static readonly ProcessingOptions SimulateBundleProcessingOptions = ProcessingOptions.ProducingBlock | ProcessingOptions.IgnoreParentNotOnMainChain; - private IMevConfig _mevConfig = null!; - private ILogger? _logger; - private INethermindApi _nethermindApi = null!; - private BundlePool? _bundlePool; - private ITracerFactory? _tracerFactory; + private IMevConfig _mevConfig = null!; + private ILogger? _logger; + private INethermindApi _nethermindApi = null!; + private BundlePool? _bundlePool; + private ITracerFactory? _tracerFactory; - public string Name => "MEV"; + public string Name => "MEV"; - public string Description => "Flashbots MEV spec implementation"; + public string Description => "Flashbots MEV spec implementation"; - public string Author => "Nethermind"; + public string Author => "Nethermind"; - public Task Init(INethermindApi? nethermindApi) - { - _nethermindApi = nethermindApi ?? throw new ArgumentNullException(nameof(nethermindApi)); - _mevConfig = _nethermindApi.Config(); - _logger = _nethermindApi.LogManager.GetClassLogger(); + public Task Init(INethermindApi? nethermindApi) + { + _nethermindApi = nethermindApi ?? throw new ArgumentNullException(nameof(nethermindApi)); + _mevConfig = _nethermindApi.Config(); + _logger = _nethermindApi.LogManager.GetClassLogger(); - return Task.CompletedTask; - } + return Task.CompletedTask; + } - public Task InitNetworkProtocol() => Task.CompletedTask; + public Task InitNetworkProtocol() => Task.CompletedTask; - public BundlePool BundlePool - { - get + public BundlePool BundlePool { - if (_bundlePool is null) + get { - var (getFromApi, _) = _nethermindApi!.ForProducer; - - TxBundleSimulator txBundleSimulator = new( - TracerFactory, - getFromApi.GasLimitCalculator!, - getFromApi.Timestamper, - getFromApi.TxPool!, - getFromApi.SpecProvider!, - getFromApi.EngineSigner); - - _bundlePool = new BundlePool( - getFromApi.BlockTree!, - txBundleSimulator, - getFromApi.Timestamper, - getFromApi.TxValidator!, - getFromApi.SpecProvider!, - _mevConfig, - getFromApi.ChainHeadStateProvider!, - getFromApi.LogManager, - getFromApi.EthereumEcdsa!); + if (_bundlePool is null) + { + var (getFromApi, _) = _nethermindApi!.ForProducer; + + TxBundleSimulator txBundleSimulator = new( + TracerFactory, + getFromApi.GasLimitCalculator!, + getFromApi.Timestamper, + getFromApi.TxPool!, + getFromApi.SpecProvider!, + getFromApi.EngineSigner); + + _bundlePool = new BundlePool( + getFromApi.BlockTree!, + txBundleSimulator, + getFromApi.Timestamper, + getFromApi.TxValidator!, + getFromApi.SpecProvider!, + _mevConfig, + getFromApi.ChainHeadStateProvider!, + getFromApi.LogManager, + getFromApi.EthereumEcdsa!); + } + + return _bundlePool; } - - return _bundlePool; } - } - private ITracerFactory TracerFactory - { - get + private ITracerFactory TracerFactory { - if (_tracerFactory is null) + get { - var (getFromApi, _) = _nethermindApi!.ForProducer; - - _tracerFactory = new TracerFactory( - getFromApi.DbProvider!, - getFromApi.BlockTree!, - getFromApi.ReadOnlyTrieStore!, - getFromApi.BlockPreprocessor!, - getFromApi.SpecProvider!, - getFromApi.LogManager!, - SimulateBundleProcessingOptions); + if (_tracerFactory is null) + { + var (getFromApi, _) = _nethermindApi!.ForProducer; + + _tracerFactory = new TracerFactory( + getFromApi.DbProvider!, + getFromApi.BlockTree!, + getFromApi.ReadOnlyTrieStore!, + getFromApi.BlockPreprocessor!, + getFromApi.SpecProvider!, + getFromApi.LogManager!, + SimulateBundleProcessingOptions); + } + + return _tracerFactory; } - - return _tracerFactory; } - } - public Task InitRpcModules() - { - if (_mevConfig.Enabled) + public Task InitRpcModules() { - (IApiWithNetwork getFromApi, _) = _nethermindApi!.ForRpc; + if (_mevConfig.Enabled) + { + (IApiWithNetwork getFromApi, _) = _nethermindApi!.ForRpc; + + IJsonRpcConfig rpcConfig = getFromApi.Config(); + rpcConfig.EnableModules(ModuleType.Mev); - IJsonRpcConfig rpcConfig = getFromApi.Config(); - rpcConfig.EnableModules(ModuleType.Mev); + MevModuleFactory mevModuleFactory = new(rpcConfig, + BundlePool, + getFromApi.BlockTree!, + getFromApi.StateReader!, + TracerFactory, + getFromApi.SpecProvider!, + getFromApi.EngineSigner); - MevModuleFactory mevModuleFactory = new(rpcConfig, - BundlePool, - getFromApi.BlockTree!, - getFromApi.StateReader!, - TracerFactory, - getFromApi.SpecProvider!, - getFromApi.EngineSigner); + getFromApi.RpcModuleProvider!.RegisterBoundedByCpuCount(mevModuleFactory, rpcConfig.Timeout); - getFromApi.RpcModuleProvider!.RegisterBoundedByCpuCount(mevModuleFactory, rpcConfig.Timeout); + if (_logger!.IsInfo) _logger.Info("Flashbots RPC plugin enabled"); + } + else + { + if (_logger!.IsWarn) _logger.Info("Skipping Flashbots RPC plugin"); + } - if (_logger!.IsInfo) _logger.Info("Flashbots RPC plugin enabled"); + return Task.CompletedTask; } - else + + public async Task InitBlockProducer(IConsensusPlugin consensusPlugin) { - if (_logger!.IsWarn) _logger.Info("Skipping Flashbots RPC plugin"); - } + if (!Enabled) + { + throw new InvalidOperationException("Plugin is disabled"); + } - return Task.CompletedTask; - } + _nethermindApi.BlockProducerEnvFactory!.TransactionsExecutorFactory = new MevBlockProducerTransactionsExecutorFactory(_nethermindApi.SpecProvider!, _nethermindApi.LogManager); - public async Task InitBlockProducer(IConsensusPlugin consensusPlugin) - { - if (!Enabled) - { - throw new InvalidOperationException("Plugin is disabled"); - } + int megabundleProducerCount = _mevConfig.GetTrustedRelayAddresses().Any() ? 1 : 0; + List blockProducers = + new(_mevConfig.MaxMergedBundles + megabundleProducerCount + 1); - _nethermindApi.BlockProducerEnvFactory!.TransactionsExecutorFactory = new MevBlockProducerTransactionsExecutorFactory(_nethermindApi.SpecProvider!, _nethermindApi.LogManager); + // Add non-mev block + MevBlockProducer.MevBlockProducerInfo standardProducer = await CreateProducer(consensusPlugin); + blockProducers.Add(standardProducer); - int megabundleProducerCount = _mevConfig.GetTrustedRelayAddresses().Any() ? 1 : 0; - List blockProducers = - new(_mevConfig.MaxMergedBundles + megabundleProducerCount + 1); + // Try blocks with all bundle numbers <= MaxMergedBundles + for (int bundleLimit = 1; bundleLimit <= _mevConfig.MaxMergedBundles; bundleLimit++) + { + BundleSelector bundleSelector = new(BundlePool, bundleLimit); + MevBlockProducer.MevBlockProducerInfo bundleProducer = await CreateProducer(consensusPlugin, bundleLimit, new BundleTxSource(bundleSelector, _nethermindApi.Timestamper)); + blockProducers.Add(bundleProducer); + } - // Add non-mev block - MevBlockProducer.MevBlockProducerInfo standardProducer = await CreateProducer(consensusPlugin); - blockProducers.Add(standardProducer); + if (megabundleProducerCount > 0) + { + MegabundleSelector megabundleSelector = new(BundlePool); + MevBlockProducer.MevBlockProducerInfo bundleProducer = await CreateProducer(consensusPlugin, 0, new BundleTxSource(megabundleSelector, _nethermindApi.Timestamper)); + blockProducers.Add(bundleProducer); + } - // Try blocks with all bundle numbers <= MaxMergedBundles - for (int bundleLimit = 1; bundleLimit <= _mevConfig.MaxMergedBundles; bundleLimit++) - { - BundleSelector bundleSelector = new(BundlePool, bundleLimit); - MevBlockProducer.MevBlockProducerInfo bundleProducer = await CreateProducer(consensusPlugin, bundleLimit, new BundleTxSource(bundleSelector, _nethermindApi.Timestamper)); - blockProducers.Add(bundleProducer); + return new MevBlockProducer(consensusPlugin.DefaultBlockProductionTrigger, _nethermindApi.LogManager, blockProducers.ToArray()); } - if (megabundleProducerCount > 0) + private async Task CreateProducer( + IConsensusPlugin consensusPlugin, + int bundleLimit = 0, + ITxSource? additionalTxSource = null) { - MegabundleSelector megabundleSelector = new(BundlePool); - MevBlockProducer.MevBlockProducerInfo bundleProducer = await CreateProducer(consensusPlugin, 0, new BundleTxSource(megabundleSelector, _nethermindApi.Timestamper)); - blockProducers.Add(bundleProducer); - } - - return new MevBlockProducer(consensusPlugin.DefaultBlockProductionTrigger, _nethermindApi.LogManager, blockProducers.ToArray()); - } + bool BundleLimitTriggerCondition(BlockProductionEventArgs e) + { + // TODO: why we are checking parent and not the currently produced block...? + BlockHeader? parent = _nethermindApi.BlockTree!.GetProducedBlockParent(e.ParentHeader); + if (parent is not null) + { + IEnumerable bundles = BundlePool.GetBundles(parent, _nethermindApi.Timestamper); + return bundles.Count() >= bundleLimit; + } + + return false; + } - private async Task CreateProducer( - IConsensusPlugin consensusPlugin, - int bundleLimit = 0, - ITxSource? additionalTxSource = null) - { - bool BundleLimitTriggerCondition(BlockProductionEventArgs e) - { - // TODO: why we are checking parent and not the currently produced block...? - BlockHeader? parent = _nethermindApi.BlockTree!.GetProducedBlockParent(e.ParentHeader); - if (parent is not null) + IManualBlockProductionTrigger manualTrigger = new BuildBlocksWhenRequested(); + IBlockProductionTrigger trigger = manualTrigger; + if (bundleLimit != 0) { - IEnumerable bundles = BundlePool.GetBundles(parent, _nethermindApi.Timestamper); - return bundles.Count() >= bundleLimit; + trigger = new TriggerWithCondition(manualTrigger, BundleLimitTriggerCondition); } - return false; + IBlockProducer producer = await consensusPlugin.InitBlockProducer(trigger, additionalTxSource); + return new MevBlockProducer.MevBlockProducerInfo(producer, manualTrigger, new BeneficiaryTracer()); } - IManualBlockProductionTrigger manualTrigger = new BuildBlocksWhenRequested(); - IBlockProductionTrigger trigger = manualTrigger; - if (bundleLimit != 0) - { - trigger = new TriggerWithCondition(manualTrigger, BundleLimitTriggerCondition); - } + public bool Enabled => _mevConfig.Enabled; - IBlockProducer producer = await consensusPlugin.InitBlockProducer(trigger, additionalTxSource); - return new MevBlockProducer.MevBlockProducerInfo(producer, manualTrigger, new BeneficiaryTracer()); + public ValueTask DisposeAsync() => ValueTask.CompletedTask; } - - public bool Enabled => _mevConfig.Enabled; - - public ValueTask DisposeAsync() => ValueTask.CompletedTask; } diff --git a/src/Nethermind/Nethermind.Mev/MevRpcModule.cs b/src/Nethermind/Nethermind.Mev/MevRpcModule.cs index 0609b4b19a7..a8f345951ca 100644 --- a/src/Nethermind/Nethermind.Mev/MevRpcModule.cs +++ b/src/Nethermind/Nethermind.Mev/MevRpcModule.cs @@ -10,6 +10,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Int256; using Nethermind.JsonRpc; using Nethermind.JsonRpc.Modules; using Nethermind.Mev.Data; diff --git a/src/Nethermind/Nethermind.Mev/Source/BundleSelector.cs b/src/Nethermind/Nethermind.Mev/Source/BundleSelector.cs index 04be22fedca..9d4256213a0 100644 --- a/src/Nethermind/Nethermind.Mev/Source/BundleSelector.cs +++ b/src/Nethermind/Nethermind.Mev/Source/BundleSelector.cs @@ -5,10 +5,13 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.VisualBasic; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm; using Nethermind.Int256; using Nethermind.Mev.Data; +using Nethermind.Mev.Execution; namespace Nethermind.Mev.Source { diff --git a/src/Nethermind/Nethermind.Mev/Source/BundleSortedPool.cs b/src/Nethermind/Nethermind.Mev/Source/BundleSortedPool.cs index bbda54f773f..af56a5dd9d9 100644 --- a/src/Nethermind/Nethermind.Mev/Source/BundleSortedPool.cs +++ b/src/Nethermind/Nethermind.Mev/Source/BundleSortedPool.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using System.Linq; using Nethermind.Core; +using Nethermind.Core.Collections; using Nethermind.Logging; using Nethermind.Mev.Data; using Nethermind.TxPool.Collections; diff --git a/src/Nethermind/Nethermind.Mining.Test/EthashSealEngineTests.cs b/src/Nethermind/Nethermind.Mining.Test/EthashSealEngineTests.cs index bc85b066fd7..2ae2e58b17b 100644 --- a/src/Nethermind/Nethermind.Mining.Test/EthashSealEngineTests.cs +++ b/src/Nethermind/Nethermind.Mining.Test/EthashSealEngineTests.cs @@ -12,6 +12,7 @@ using Nethermind.Crypto; using Nethermind.Int256; using Nethermind.Logging; +using NSubstitute; using NUnit.Framework; namespace Nethermind.Mining.Test diff --git a/src/Nethermind/Nethermind.Mining.Test/EthashTests.cs b/src/Nethermind/Nethermind.Mining.Test/EthashTests.cs index c68eb031272..d1163510cb0 100644 --- a/src/Nethermind/Nethermind.Mining.Test/EthashTests.cs +++ b/src/Nethermind/Nethermind.Mining.Test/EthashTests.cs @@ -1,12 +1,14 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using FluentAssertions; using Nethermind.Consensus; using Nethermind.Consensus.Ethash; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Logging; using Nethermind.Serialization.Rlp; diff --git a/src/Nethermind/Nethermind.Mining.Test/FollowOtherMinersTests.cs b/src/Nethermind/Nethermind.Mining.Test/FollowOtherMinersTests.cs index 766d7038e2f..b305720ace7 100644 --- a/src/Nethermind/Nethermind.Mining.Test/FollowOtherMinersTests.cs +++ b/src/Nethermind/Nethermind.Mining.Test/FollowOtherMinersTests.cs @@ -4,6 +4,7 @@ using FluentAssertions; using Nethermind.Consensus; using Nethermind.Core; +using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Specs; using Nethermind.Specs.Forks; diff --git a/src/Nethermind/Nethermind.Mining.Test/MiningConfigTest.cs b/src/Nethermind/Nethermind.Mining.Test/MiningConfigTest.cs index daa19ee6b57..6f49528dcd6 100644 --- a/src/Nethermind/Nethermind.Mining.Test/MiningConfigTest.cs +++ b/src/Nethermind/Nethermind.Mining.Test/MiningConfigTest.cs @@ -3,6 +3,7 @@ using System.Text; using Nethermind.Config; +using Nethermind.Consensus; using Nethermind.Core.Exceptions; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Monitoring.Test/MetricsTests.cs b/src/Nethermind/Nethermind.Monitoring.Test/MetricsTests.cs index 86859aa654c..a9709a4b968 100644 --- a/src/Nethermind/Nethermind.Monitoring.Test/MetricsTests.cs +++ b/src/Nethermind/Nethermind.Monitoring.Test/MetricsTests.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -10,156 +9,122 @@ using System.Runtime.Serialization; using FluentAssertions; using Nethermind.Core; -using Nethermind.Core.Attributes; using Nethermind.Logging; using Nethermind.Monitoring.Config; using Nethermind.Monitoring.Metrics; using NUnit.Framework; -namespace Nethermind.Monitoring.Test; - -[TestFixture] -public class MetricsTests +namespace Nethermind.Monitoring.Test { - public static class TestMetrics + [TestFixture] + public class MetricsTests { - [System.ComponentModel.Description("A test description")] - public static long OneTwoThree { get; set; } - - [System.ComponentModel.Description("Another test description.")] - [DataMember(Name = "one_two_three")] - public static long OneTwoThreeSpecial { get; set; } - - [System.ComponentModel.Description("Another test description.")] - [KeyIsLabel("somelabel")] - public static ConcurrentDictionary WithLabelledDictionary { get; set; } = new(); - - public static IDictionary OldDictionaryMetrics { get; set; } = new ConcurrentDictionary(); - } - - public enum SomeEnum - { - Option1, - Option2, - } - - [Test] - public void Test_update_correct_gauge() - { - MetricsConfig metricsConfig = new() + public static class TestMetrics { - Enabled = true - }; - MetricsController metricsController = new(metricsConfig); - metricsController.RegisterMetrics(typeof(TestMetrics)); - - TestMetrics.OneTwoThree = 123; - TestMetrics.OneTwoThreeSpecial = 1234; - TestMetrics.WithLabelledDictionary[SomeEnum.Option1] = 2; - TestMetrics.WithLabelledDictionary[SomeEnum.Option2] = 3; - TestMetrics.OldDictionaryMetrics["metrics0"] = 4; - TestMetrics.OldDictionaryMetrics["metrics1"] = 5; - metricsController.UpdateMetrics(null); + [System.ComponentModel.Description("A test description")] + public static long OneTwoThree { get; set; } - var gauges = metricsController._gauges; - var keyDefault = $"{nameof(TestMetrics)}.{nameof(TestMetrics.OneTwoThree)}"; - var keySpecial = $"{nameof(TestMetrics)}.{nameof(TestMetrics.OneTwoThreeSpecial)}"; - var keyDictionary = $"{nameof(TestMetrics)}.{nameof(TestMetrics.WithLabelledDictionary)}"; - var keyOldDictionary0 = $"{nameof(TestMetrics.OldDictionaryMetrics)}.metrics0"; - var keyOldDictionary1 = $"{nameof(TestMetrics.OldDictionaryMetrics)}.metrics1"; - - Assert.Contains(keyDefault, gauges.Keys); - Assert.Contains(keySpecial, gauges.Keys); - - Assert.That(gauges[keyDefault].Name, Is.EqualTo("nethermind_one_two_three")); - Assert.That(gauges[keySpecial].Name, Is.EqualTo("one_two_three")); - Assert.That(gauges[keyDictionary].Name, Is.EqualTo("nethermind_with_labelled_dictionary")); - Assert.That(gauges[keyOldDictionary0].Name, Is.EqualTo("nethermind_metrics0")); - Assert.That(gauges[keyOldDictionary1].Name, Is.EqualTo("nethermind_metrics1")); - - Assert.That(gauges[keyDefault].Value, Is.EqualTo(123)); - Assert.That(gauges[keySpecial].Value, Is.EqualTo(1234)); - Assert.That(gauges[keyDictionary].WithLabels(SomeEnum.Option1.ToString()).Value, Is.EqualTo(2)); - Assert.That(gauges[keyDictionary].WithLabels(SomeEnum.Option2.ToString()).Value, Is.EqualTo(3)); - Assert.That(gauges[keyOldDictionary0].Value, Is.EqualTo(4)); - Assert.That(gauges[keyOldDictionary1].Value, Is.EqualTo(5)); - } + [System.ComponentModel.Description("Another test description.")] + [DataMember(Name = "one_two_three")] + public static long OneTwoThreeSpecial { get; set; } + } - [Test] - public void Register_and_update_metrics_should_not_throw_exception() - { - MetricsConfig metricsConfig = new() + [Test] + public void Test_gauge_names() { - Enabled = true - }; - List knownMetricsTypes = new() - { - typeof(Mev.Metrics), - typeof(TxPool.Metrics), - typeof(Blockchain.Metrics), - typeof(Consensus.AuRa.Metrics), - typeof(Evm.Metrics), - typeof(JsonRpc.Metrics), - typeof(Db.Metrics), - typeof(Network.Metrics), - typeof(Init.Metrics), - typeof(Synchronization.Metrics), - typeof(Trie.Metrics), - typeof(Trie.Pruning.Metrics), - }; - MetricsController metricsController = new(metricsConfig); - MonitoringService monitoringService = new(metricsController, metricsConfig, LimboLogs.Instance); - List metrics = TypeDiscovery.FindNethermindBasedTypes(nameof(Metrics)).ToList(); - metrics.AddRange(knownMetricsTypes); + MetricsConfig metricsConfig = new() + { + Enabled = true + }; + MetricsController metricsController = new(metricsConfig); + metricsController.RegisterMetrics(typeof(TestMetrics)); + var gauges = metricsController._gauges; + var keyDefault = $"{nameof(TestMetrics)}.{nameof(TestMetrics.OneTwoThree)}"; + var keySpecial = $"{nameof(TestMetrics)}.{nameof(TestMetrics.OneTwoThreeSpecial)}"; + + Assert.Contains(keyDefault, gauges.Keys); + Assert.Contains(keySpecial, gauges.Keys); + + Assert.That(gauges[keyDefault].Name, Is.EqualTo("nethermind_one_two_three")); + Assert.That(gauges[keySpecial].Name, Is.EqualTo("one_two_three")); + } - Assert.DoesNotThrow(() => + [Test] + public void Register_and_update_metrics_should_not_throw_exception() { - foreach (Type metric in metrics) + MetricsConfig metricsConfig = new() { - metricsController.RegisterMetrics(metric); - } - - metricsController.UpdateMetrics(null); - }); - } + Enabled = true + }; + List knownMetricsTypes = new() + { + typeof(Nethermind.Mev.Metrics), + typeof(Nethermind.TxPool.Metrics), + typeof(Nethermind.Blockchain.Metrics), + typeof(Nethermind.Consensus.AuRa.Metrics), + typeof(Nethermind.Evm.Metrics), + typeof(Nethermind.JsonRpc.Metrics), + typeof(Nethermind.Db.Metrics), + typeof(Nethermind.Network.Metrics), + typeof(Init.Metrics), + typeof(Nethermind.Synchronization.Metrics), + typeof(Nethermind.Trie.Metrics), + typeof(Nethermind.Trie.Pruning.Metrics), + }; + MetricsController metricsController = new(metricsConfig); + MonitoringService monitoringService = new(metricsController, metricsConfig, LimboLogs.Instance); + List metrics = TypeDiscovery.FindNethermindTypes(nameof(Metrics)).ToList(); + metrics.AddRange(knownMetricsTypes); + + Assert.DoesNotThrow(() => + { + foreach (Type metric in metrics) + { + metricsController.RegisterMetrics(metric); + } - [Test] - public void All_config_items_have_descriptions() - { - ValidateMetricsDescriptions(); - } + metricsController.UpdateMetrics(null); + }); + } - public static void ValidateMetricsDescriptions() - { - ForEachProperty(CheckDescribedOrHidden); - } + [Test] + public void All_config_items_have_descriptions() + { + ValidateMetricsDescriptions(); + } - private static void CheckDescribedOrHidden(PropertyInfo property) - { - System.ComponentModel.DescriptionAttribute attribute = property.GetCustomAttribute(); - attribute.Should().NotBeNull(); - } + public static void ValidateMetricsDescriptions() + { + ForEachProperty(CheckDescribedOrHidden); + } - private static void ForEachProperty(Action verifier) - { - string[] dlls = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "Nethermind.*.dll"); - foreach (string dll in dlls) + private static void CheckDescribedOrHidden(PropertyInfo property) { - Assembly assembly = Assembly.LoadFile(dll); - Type[] configs = assembly.GetExportedTypes().Where(t => t.Name == "Metrics").ToArray(); + System.ComponentModel.DescriptionAttribute attribute = property.GetCustomAttribute(); + attribute.Should().NotBeNull(); + } - foreach (Type metricsType in configs) + private static void ForEachProperty(Action verifier) + { + string[] dlls = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "Nethermind.*.dll"); + foreach (string dll in dlls) { - PropertyInfo[] properties = metricsType.GetProperties(BindingFlags.Static | BindingFlags.Public); - foreach (PropertyInfo property in properties) + Assembly assembly = Assembly.LoadFile(dll); + Type[] configs = assembly.GetExportedTypes().Where(t => t.Name == "Metrics").ToArray(); + + foreach (Type metricsType in configs) { - try - { - verifier(property); - } - catch (Exception e) + PropertyInfo[] properties = metricsType.GetProperties(BindingFlags.Static | BindingFlags.Public); + foreach (PropertyInfo property in properties) { - throw new Exception(property.Name, e); + try + { + verifier(property); + } + catch (Exception e) + { + throw new Exception(property.Name, e); + } } } } diff --git a/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs b/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs index 4163ee88821..e42e1e46b1f 100644 --- a/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs +++ b/src/Nethermind/Nethermind.Monitoring/Metrics/MetricsController.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.Metrics; @@ -24,7 +23,7 @@ public partial class MetricsController : IMetricsController private readonly int _intervalSeconds; private Timer _timer; private readonly Dictionary)[]> _membersCache = new(); - private readonly Dictionary _dictionaryCache = new(); + private readonly Dictionary Dict)> _dynamicPropCache = new(); private readonly HashSet _metricTypes = new(); public readonly Dictionary _gauges = new(); @@ -32,15 +31,6 @@ public partial class MetricsController : IMetricsController private readonly List _callbacks = new(); - class DictionaryMetricInfo - { - internal MemberInfo MemberInfo; - internal string DictionaryName; - internal string LabelName; - internal string GaugeName; - internal IDictionary Dictionary; - } - public void RegisterMetrics(Type type) { if (_metricTypes.Add(type) == false) @@ -60,29 +50,23 @@ public void RegisterMetrics(Type type) _gauges[gaugeName] = CreateMemberInfoMetricsGauge(member); } - - foreach (DictionaryMetricInfo info in _dictionaryCache[type]) - { - if (info.LabelName is null) continue; // Old behaviour creates new metric as it is created - _gauges[info.GaugeName] = CreateMemberInfoMetricsGauge(info.MemberInfo, info.LabelName); - } } - private static Gauge CreateMemberInfoMetricsGauge(MemberInfo member, params string[] labels) + private static Gauge CreateMemberInfoMetricsGauge(MemberInfo member) { - string name = BuildGaugeName(member); string description = member.GetCustomAttribute()?.Description; + string name = BuildGaugeName(member); bool haveTagAttributes = member.GetCustomAttributes().Any(); if (!haveTagAttributes) { - return CreateGauge(name, description, _commonStaticTags, labels); + return CreateGauge(name, description, _commonStaticTags); } Dictionary tags = new(_commonStaticTags); member.GetCustomAttributes().ForEach(attribute => tags.Add(attribute.Label, GetStaticMemberInfo(attribute.Informer, attribute.Label))); - return CreateGauge(name, description, tags, labels); + return CreateGauge(name, description, tags); } // Tags that all metrics share @@ -154,24 +138,13 @@ static Func GetValueAccessor(MemberInfo member) .ToArray(); } - if (!_dictionaryCache.ContainsKey(type)) + if (!_dynamicPropCache.ContainsKey(type)) { - _dictionaryCache[type] = type.GetProperties() - .Where(p => - p.PropertyType.IsGenericType && - ( - p.PropertyType.GetGenericTypeDefinition().IsAssignableTo(typeof(IDictionary)) - || p.PropertyType.GetGenericTypeDefinition().IsAssignableTo(typeof(IDictionary<,>)) - )) - .Select(p => new DictionaryMetricInfo() - { - MemberInfo = p, - DictionaryName = p.Name, - LabelName = p.GetCustomAttribute()?.LabelName, - GaugeName = GetGaugeNameKey(type.Name, p.Name), - Dictionary = (IDictionary)p.GetValue(null) - }) - .ToArray(); + var p = type.GetProperties().FirstOrDefault(p => p.PropertyType.IsAssignableTo(typeof(IDictionary))); + if (p != null) + { + _dynamicPropCache[type] = (p.Name, (IDictionary)p.GetValue(null)); + } } } @@ -181,9 +154,9 @@ private static string BuildGaugeName(MemberInfo propertyInfo) => private static string BuildGaugeName(string propertyName) => $"nethermind_{GetGaugeNameRegex().Replace(propertyName, "$1_$2").ToLowerInvariant()}"; - private static Gauge CreateGauge(string name, string help = null, IDictionary staticLabels = null, params string[] labels) => staticLabels is null - ? Prometheus.Metrics.CreateGauge(name, help ?? string.Empty, labels) - : Prometheus.Metrics.WithLabels(staticLabels).CreateGauge(name, help ?? string.Empty, labels); + private static Gauge CreateGauge(string name, string help = null, IDictionary labels = null) => labels is null + ? Prometheus.Metrics.CreateGauge(name, help ?? string.Empty) + : Prometheus.Metrics.WithLabels(labels).CreateGauge(name, help ?? string.Empty); public MetricsController(IMetricsConfig metricsConfig) { @@ -222,55 +195,28 @@ private void UpdateMetrics(Type type) ReplaceValueIfChanged(accessor(), gaugeName); } - foreach (DictionaryMetricInfo info in _dictionaryCache[type]) + if (_dynamicPropCache.TryGetValue(type, out var dict)) { - if (info.LabelName is null) - { - IDictionary dict = info.Dictionary; - // Its fine that the key here need to call `ToString()`. Better here then in the metrics, where it might - // impact the performance of whatever is updating the metrics. - foreach (object keyObj in dict.Keys) // Different dictionary seems to iterate to different KV type. So need to use `Keys` here. - { - string keyStr = keyObj.ToString(); - double value = Convert.ToDouble(dict[keyObj]); - string gaugeName = GetGaugeNameKey(info.DictionaryName, keyStr); - - if (ReplaceValueIfChanged(value, gaugeName) is null) - { - // Don't know why it does not prefix with dictionary name or class name. Not gonna change behaviour now. - Gauge gauge = CreateGauge(BuildGaugeName(keyStr)); - _gauges[gaugeName] = gauge; - gauge.Set(value); - } - } - } - else + foreach (var kvp in dict.Dict) { - IDictionary dict = info.Dictionary; - string gaugeName = info.GaugeName; - foreach (object key in dict.Keys) + double value = Convert.ToDouble(kvp.Value); + var gaugeName = GetGaugeNameKey(dict.DictName, kvp.Key); + + if (ReplaceValueIfChanged(value, gaugeName) is null) { - double value = Convert.ToDouble(dict[key]); - ReplaceValueIfChanged(value, gaugeName, key.ToString()); + Gauge gauge = CreateGauge(BuildGaugeName(kvp.Key)); + _gauges[gaugeName] = gauge; + gauge.Set(value); } } } - Gauge ReplaceValueIfChanged(double value, string gaugeName, params string[] labels) + Gauge ReplaceValueIfChanged(double value, string gaugeName) { if (_gauges.TryGetValue(gaugeName, out Gauge gauge)) { - if (labels.Length > 0) - { - Gauge.Child ch = gauge.WithLabels(labels); - if (Math.Abs(ch.Value - value) > double.Epsilon) - ch.Set(value); - } - else - { - if (Math.Abs(gauge.Value - value) > double.Epsilon) - gauge.Set(value); - } + if (Math.Abs(gauge.Value - value) > double.Epsilon) + gauge.Set(value); } return gauge; diff --git a/src/Nethermind/Nethermind.Network.Benchmark/Eth62ProtocolHandlerBenchmarks.cs b/src/Nethermind/Nethermind.Network.Benchmark/Eth62ProtocolHandlerBenchmarks.cs index 4f2ccbd1125..9eb1afc1e71 100644 --- a/src/Nethermind/Nethermind.Network.Benchmark/Eth62ProtocolHandlerBenchmarks.cs +++ b/src/Nethermind/Nethermind.Network.Benchmark/Eth62ProtocolHandlerBenchmarks.cs @@ -6,6 +6,7 @@ using DotNetty.Buffers; using DotNetty.Transport.Channels; using Nethermind.Blockchain; +using Nethermind.Consensus; using Nethermind.Consensus.Comparers; using Nethermind.Consensus.Validators; using Nethermind.Core; @@ -64,7 +65,7 @@ public void SetUp() ISyncServer syncSrv = Substitute.For(); BlockHeader head = Build.A.BlockHeader.WithNumber(1).TestObject; syncSrv.Head.Returns(head); - _handler = new Eth62ProtocolHandler(session, _ser, stats, syncSrv, txPool, Consensus.ShouldGossip.Instance, LimboLogs.Instance); + _handler = new Eth62ProtocolHandler(session, _ser, stats, syncSrv, txPool, ShouldGossip.Instance, LimboLogs.Instance); _handler.DisableTxFiltering(); StatusMessage statusMessage = new StatusMessage(); diff --git a/src/Nethermind/Nethermind.Network.Benchmark/HandshakeBenchmarks.cs b/src/Nethermind/Nethermind.Network.Benchmark/HandshakeBenchmarks.cs index f41aba98baa..eba2e8962b0 100644 --- a/src/Nethermind/Nethermind.Network.Benchmark/HandshakeBenchmarks.cs +++ b/src/Nethermind/Nethermind.Network.Benchmark/HandshakeBenchmarks.cs @@ -76,7 +76,7 @@ public void Dispose() } } - private readonly IEthereumEcdsa _ecdsa = new EthereumEcdsa(BlockchainIds.Sepolia, LimboLogs.Instance); // TODO: separate general crypto signer from Ethereum transaction signing + private readonly IEthereumEcdsa _ecdsa = new EthereumEcdsa(BlockchainIds.Ropsten, LimboLogs.Instance); // TODO: separate general crypto signer from Ethereum transaction signing private IMessageSerializationService _messageSerializationService; diff --git a/src/Nethermind/Nethermind.Network.Benchmark/InFlowBenchmarks.cs b/src/Nethermind/Nethermind.Network.Benchmark/InFlowBenchmarks.cs index dc7ed40adfb..d41e103552d 100644 --- a/src/Nethermind/Nethermind.Network.Benchmark/InFlowBenchmarks.cs +++ b/src/Nethermind/Nethermind.Network.Benchmark/InFlowBenchmarks.cs @@ -10,6 +10,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Logging; +using Nethermind.Network.P2P.Subprotocols.Eth.V62; using Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages; using Nethermind.Network.Rlpx; using Nethermind.Network.Test; diff --git a/src/Nethermind/Nethermind.Network.Benchmark/OutFlowBenchmarks.cs b/src/Nethermind/Nethermind.Network.Benchmark/OutFlowBenchmarks.cs index a5c6e6e038b..710c4aeb3c8 100644 --- a/src/Nethermind/Nethermind.Network.Benchmark/OutFlowBenchmarks.cs +++ b/src/Nethermind/Nethermind.Network.Benchmark/OutFlowBenchmarks.cs @@ -9,6 +9,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Logging; +using Nethermind.Network.P2P.Subprotocols.Eth.V62; using Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages; using Nethermind.Network.Rlpx; using Nethermind.Network.Test; diff --git a/src/Nethermind/Nethermind.Network.Discovery.Test/NettyDiscoveryHandlerTests.cs b/src/Nethermind/Nethermind.Network.Discovery.Test/NettyDiscoveryHandlerTests.cs index d478f4c8471..de1e6e252a4 100644 --- a/src/Nethermind/Nethermind.Network.Discovery.Test/NettyDiscoveryHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Discovery.Test/NettyDiscoveryHandlerTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using System.Linq; using System.Net; using System.Net.Sockets; using System.Threading.Tasks; diff --git a/src/Nethermind/Nethermind.Network.Discovery.Test/NodeLifecycleManagerTests.cs b/src/Nethermind/Nethermind.Network.Discovery.Test/NodeLifecycleManagerTests.cs index 4fac93bb92e..e6d77ccba5f 100644 --- a/src/Nethermind/Nethermind.Network.Discovery.Test/NodeLifecycleManagerTests.cs +++ b/src/Nethermind/Nethermind.Network.Discovery.Test/NodeLifecycleManagerTests.cs @@ -6,8 +6,6 @@ using System.Linq; using System.Net; using System.Threading.Tasks; -using FluentAssertions; -using MathNet.Numerics.Random; using Nethermind.Config; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -109,87 +107,6 @@ public async Task sending_ping_receiving_proper_pong_sets_bounded() Assert.IsTrue(nodeManager.IsBonded); } - [Test] - public async Task handling_findnode_msg_will_limit_result_to_12() - { - IDiscoveryConfig discoveryConfig = new DiscoveryConfig(); - discoveryConfig.PongTimeout = 50; - discoveryConfig.BucketSize = 32; - discoveryConfig.BucketsCount = 1; - - _nodeTable = new NodeTable(new NodeDistanceCalculator(discoveryConfig), discoveryConfig, _networkConfig, LimboLogs.Instance); - _nodeTable.Initialize(TestItem.PublicKeyA); - - Node node = new(TestItem.PublicKeyB, _host, _port); - NodeLifecycleManager nodeManager = new(node, _discoveryManagerMock, _nodeTable, _evictionManagerMock, _nodeStatsMock, new NodeRecord(), _discoveryConfigMock, Timestamper.Default, _loggerMock); - - await BondWithSelf(nodeManager, node); - - for (int i = 0; i < 32; i++) - { - _nodeTable.AddNode( - new Node( - new PublicKey(Random.Shared.NextBytes(64)), - "127.0.0.1", - i - )); - } - - NeighborsMsg? sentMsg = null; - _discoveryManagerMock.SendMessage(Arg.Do(msg => - { - sentMsg = msg; - })); - - nodeManager.ProcessFindNodeMsg(new FindNodeMsg(TestItem.PublicKeyA, 1, new byte[] { 0 })); - - Assert.IsNotNull(sentMsg); - _nodeTable.Buckets[0].BondedItemsCount.Should().Be(32); - sentMsg!.Nodes.Length.Should().Be(12); - } - - [Test] - public async Task processNeighboursMessage_willCombineTwoSubsequentMessage() - { - IDiscoveryConfig discoveryConfig = new DiscoveryConfig(); - discoveryConfig.PongTimeout = 50; - discoveryConfig.BucketSize = 32; - discoveryConfig.BucketsCount = 1; - - _nodeTable = new NodeTable(new NodeDistanceCalculator(discoveryConfig), discoveryConfig, _networkConfig, LimboLogs.Instance); - _nodeTable.Initialize(TestItem.PublicKeyA); - - Node node = new(TestItem.PublicKeyB, _host, _port); - NodeLifecycleManager nodeManager = new(node, _discoveryManagerMock, _nodeTable, _evictionManagerMock, _nodeStatsMock, new NodeRecord(), _discoveryConfigMock, Timestamper.Default, _loggerMock); - - await BondWithSelf(nodeManager, node); - - _discoveryManagerMock - .Received(0) - .GetNodeLifecycleManager(Arg.Any(), Arg.Any()); - - nodeManager.SendFindNode(Array.Empty()); - - Node[] firstNodes = TestItem.PublicKeys - .Take(12) - .Select(pubkey => new Node(pubkey, "127.0.0.2", 0)) - .ToArray(); - NeighborsMsg firstNodeMsg = new NeighborsMsg(TestItem.PublicKeyA, 1, firstNodes); - Node[] secondNodes = TestItem.PublicKeys - .Skip(12) - .Take(4) - .Select(pubkey => new Node(pubkey, "127.0.0.2", 0)) - .ToArray(); - NeighborsMsg secondNodeMsg = new NeighborsMsg(TestItem.PublicKeyA, 1, secondNodes); - - nodeManager.ProcessNeighborsMsg(firstNodeMsg); - nodeManager.ProcessNeighborsMsg(secondNodeMsg); - - _discoveryManagerMock - .Received(16) - .GetNodeLifecycleManager(Arg.Any(), Arg.Any()); - } - [Test] public async Task sending_ping_receiving_incorrect_pong_does_not_bond() { @@ -383,19 +300,5 @@ private void SetupNodeIds() _nodeIds[i] = new PublicKey(nodeIdBytes); } } - - private async Task BondWithSelf(NodeLifecycleManager nodeManager, Node node) - { - byte[] mdc = new byte[32]; - PingMsg? sentPing = null; - _discoveryManagerMock.SendMessage(Arg.Do(msg => - { - msg.Mdc = mdc; - sentPing = msg; - })); - await nodeManager.SendPingAsync(); - nodeManager.ProcessPongMsg(new PongMsg(node.Address, GetExpirationTime(), sentPing!.Mdc!)); - } - } } diff --git a/src/Nethermind/Nethermind.Network.Discovery.Test/NodeSourceToDiscV4Feeder.cs b/src/Nethermind/Nethermind.Network.Discovery.Test/NodeSourceToDiscV4Feeder.cs deleted file mode 100644 index 8751b7a764a..00000000000 --- a/src/Nethermind/Nethermind.Network.Discovery.Test/NodeSourceToDiscV4Feeder.cs +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core.Test.Builders; -using Nethermind.Stats.Model; -using NSubstitute; -using NUnit.Framework; - -namespace Nethermind.Network.Discovery.Test; - -public class NodeSourceToDiscV4FeederTests -{ - [Test] - public void Test_ShouldAddNodeToDiscover() - { - INodeSource source = Substitute.For(); - IDiscoveryApp discoveryApp = Substitute.For(); - using NodeSourceToDiscV4Feeder feeder = new(source, discoveryApp, 10); - source.NodeAdded += Raise.EventWith(new NodeEventArgs(new Node(TestItem.PublicKeyA, TestItem.IPEndPointA))); - - discoveryApp.Received().AddNodeToDiscovery(Arg.Any()); - } - - [Test] - public void Test_ShouldLimitAddedNode() - { - INodeSource source = Substitute.For(); - IDiscoveryApp discoveryApp = Substitute.For(); - using NodeSourceToDiscV4Feeder feeder = new(source, discoveryApp, 10); - - for (int i = 0; i < 20; i++) - { - source.NodeAdded += Raise.EventWith(new NodeEventArgs(new Node(TestItem.PublicKeyA, TestItem.IPEndPointA))); - } - - discoveryApp.Received(10).AddNodeToDiscovery(Arg.Any()); - } -} diff --git a/src/Nethermind/Nethermind.Network.Discovery.Test/RoutingTable/NodeBucketTests.cs b/src/Nethermind/Nethermind.Network.Discovery.Test/RoutingTable/NodeBucketTests.cs index 256c4e9dcdf..700e4cea41f 100644 --- a/src/Nethermind/Nethermind.Network.Discovery.Test/RoutingTable/NodeBucketTests.cs +++ b/src/Nethermind/Nethermind.Network.Discovery.Test/RoutingTable/NodeBucketTests.cs @@ -107,38 +107,7 @@ public void Throws_when_replacing_non_existing(int nodesInTheBucket) IPAddress.Broadcast.ToString(), 30002); - Assert.DoesNotThrow(() => nodeBucket.ReplaceNode(nonExisting, node)); - } - - [Test] - public void When_addingToFullBucket_then_randomlyDropEntry() - { - NodeBucket nodeBucket = new(1, 16, dropFullBucketProbability: .5f); - for (int i = 0; i < 16; i++) - { - Node node = new( - TestItem.PublicKeys[i], - IPAddress.Broadcast.ToString(), - 30000); - - nodeBucket.AddNode(node); - } - - int dropCount = 0; - for (int i = 0; i < 100; i++) - { - Node node = new( - TestItem.PublicKeys[i + 16], - IPAddress.Broadcast.ToString(), - 30000); - - if (nodeBucket.AddNode(node).ResultType == NodeAddResultType.Dropped) - { - dropCount++; - } - } - - dropCount.Should().BeInRange(25, 75); + Assert.Throws(() => nodeBucket.ReplaceNode(nonExisting, node)); } private static void AddNodes(NodeBucket nodeBucket, int count) diff --git a/src/Nethermind/Nethermind.Network.Discovery/DiscoveryApp.cs b/src/Nethermind/Nethermind.Network.Discovery/DiscoveryApp.cs index a4f7a2862f0..2de4f5c1a4a 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/DiscoveryApp.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/DiscoveryApp.cs @@ -1,9 +1,12 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; using DotNetty.Handlers.Logging; using DotNetty.Transport.Bootstrapping; using DotNetty.Transport.Channels; @@ -179,12 +182,8 @@ private void OnChannelActivated(object? sender, EventArgs e) { if (_logger.IsDebug) _logger.Debug("Activated discovery channel."); - // Make sure this is non blocking code, otherwise netty will not process messages - // Explicitly use TaskScheduler.Default, otherwise it will use dotnetty's task scheduler which have a habit of - // not working sometimes. - Task.Factory - .StartNew(() => OnChannelActivated(_appShutdownSource.Token), _appShutdownSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default) - .ContinueWith + //Make sure this is non blocking code, otherwise netty will not process messages + Task.Run(() => OnChannelActivated(_appShutdownSource.Token)).ContinueWith ( t => { diff --git a/src/Nethermind/Nethermind.Network.Discovery/DiscoveryConfig.cs b/src/Nethermind/Nethermind.Network.Discovery/DiscoveryConfig.cs index bfd1cc934c7..192368bc885 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/DiscoveryConfig.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/DiscoveryConfig.cs @@ -1,11 +1,13 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Network.Config; + namespace Nethermind.Network.Discovery; public class DiscoveryConfig : IDiscoveryConfig { - public int BucketSize { get; set; } = 16; + public int BucketSize { get; set; } = 12; public int BucketsCount { get; set; } = 256; @@ -36,7 +38,6 @@ public class DiscoveryConfig : IDiscoveryConfig public int MaxNodeLifecycleManagersCount { get; set; } = 8000; public int NodeLifecycleManagersCleanupCount { get; set; } = 4000; - public float DropFullBucketNodeProbability { get; set; } = 0.05f; public string Bootnodes { get; set; } = string.Empty; } diff --git a/src/Nethermind/Nethermind.Network.Discovery/DiscoveryManager.cs b/src/Nethermind/Nethermind.Network.Discovery/DiscoveryManager.cs index 674929de680..aa901178dfa 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/DiscoveryManager.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/DiscoveryManager.cs @@ -4,8 +4,10 @@ using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; using Nethermind.Config; +using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Logging; +using Nethermind.Network.Config; using Nethermind.Network.Discovery.Lifecycle; using Nethermind.Network.Discovery.Messages; using Nethermind.Network.Discovery.RoutingTable; @@ -228,7 +230,7 @@ private void NotifySubscribersOnMsgReceived(MsgType msgType, Node node, Discover private TaskCompletionSource GetCompletionSource(Keccak senderAddressHash, int messageType) { MessageTypeKey key = new(senderAddressHash, messageType); - TaskCompletionSource completionSource = _waitingEvents.GetOrAdd(key, new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously)); + TaskCompletionSource completionSource = _waitingEvents.GetOrAdd(key, new TaskCompletionSource()); return completionSource; } diff --git a/src/Nethermind/Nethermind.Network.Discovery/IDiscoveryConfig.cs b/src/Nethermind/Nethermind.Network.Discovery/IDiscoveryConfig.cs index cec993e0092..6583c69aa1a 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/IDiscoveryConfig.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/IDiscoveryConfig.cs @@ -11,11 +11,11 @@ public interface IDiscoveryConfig : IConfig /// /// Kademlia - k /// - [ConfigItem(DefaultValue = "16")] + [ConfigItem(DisabledForCli = true)] int BucketSize { get; set; } /// - /// Buckets count. + /// Buckets count /// [ConfigItem(DisabledForCli = true)] int BucketsCount { get; set; } @@ -23,7 +23,7 @@ public interface IDiscoveryConfig : IConfig /// /// Kademlia - alpha /// - [ConfigItem(DefaultValue = "3")] + [ConfigItem(DisabledForCli = true)] int Concurrency { get; } /// @@ -35,55 +35,55 @@ public interface IDiscoveryConfig : IConfig /// /// Max Discovery Rounds /// - [ConfigItem(DefaultValue = "8")] + [ConfigItem(DisabledForCli = true)] int MaxDiscoveryRounds { get; } /// /// Eviction check interval in ms /// - [ConfigItem(DefaultValue = "75")] + [ConfigItem(DisabledForCli = true)] int EvictionCheckInterval { get; } /// /// Send Node Timeout in ms /// - [ConfigItem(DefaultValue = "500")] + [ConfigItem(DisabledForCli = true)] int SendNodeTimeout { get; } /// /// Pong Timeout in ms /// - [ConfigItem(DefaultValue = "15000")] + [ConfigItem(DisabledForCli = true)] int PongTimeout { get; set; } /// /// Boot Node Pong Timeout in ms /// - [ConfigItem(DefaultValue = "100000")] + [ConfigItem(DisabledForCli = true)] int BootnodePongTimeout { get; } /// /// Pong Timeout in ms /// - [ConfigItem(DefaultValue = "3")] + [ConfigItem(DisabledForCli = true)] int PingRetryCount { get; } /// /// Time between running discovery processes in milliseconds /// - [ConfigItem(DefaultValue = "30000")] + [ConfigItem(DisabledForCli = true)] int DiscoveryInterval { get; } /// /// Time between persisting discovered nodes in milliseconds /// - [ConfigItem(DefaultValue = "180000")] + [ConfigItem(DisabledForCli = true)] int DiscoveryPersistenceInterval { get; } /// /// Time between discovery cycles in milliseconds /// - [ConfigItem(DefaultValue = "50")] + [ConfigItem(DisabledForCli = true)] int DiscoveryNewCycleWaitTime { get; } /// @@ -94,21 +94,18 @@ public interface IDiscoveryConfig : IConfig /// /// Timeout for closing UDP channel in milliseconds /// - [ConfigItem(DefaultValue = "5000")] + [ConfigItem(DisabledForCli = true)] int UdpChannelCloseTimeout { get; } /// /// Maximum count of NodeLifecycleManagers stored in memory /// - [ConfigItem(DefaultValue = "8000")] + [ConfigItem(DisabledForCli = true)] int MaxNodeLifecycleManagersCount { get; } /// /// Count of NodeLifecycleManagers to remove in one cleanup cycle /// - [ConfigItem(DefaultValue = "4000")] + [ConfigItem(DisabledForCli = true)] int NodeLifecycleManagersCleanupCount { get; } - - [ConfigItem(DefaultValue = "0.05")] - float DropFullBucketNodeProbability { get; set; } } diff --git a/src/Nethermind/Nethermind.Network.Discovery/Lifecycle/NodeLifecycleManager.cs b/src/Nethermind/Nethermind.Network.Discovery/Lifecycle/NodeLifecycleManager.cs index c87fcd7ec9b..1800412add3 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/Lifecycle/NodeLifecycleManager.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/Lifecycle/NodeLifecycleManager.cs @@ -37,8 +37,6 @@ public class NodeLifecycleManager : INodeLifecycleManager // private bool _sentPong; private bool _receivedPong; - private int _lastNeighbourSize = 0; - public NodeLifecycleManager(Node node, IDiscoveryManager discoveryManager, INodeTable nodeTable, @@ -168,38 +166,25 @@ public void ProcessNeighborsMsg(NeighborsMsg? msg) return; } - if (_lastNeighbourSize + msg.Nodes.Length == 16) - { - // Turns out, other client will split the neighbour msg to two msg, whose size sum up to 16. - // Happens about 70% of the time. - ProcessNodes(msg); - } - else if (_isNeighborsExpected) + if (_isNeighborsExpected) { - ProcessNodes(msg); - } - - _lastNeighbourSize = msg.Nodes.Length; - _isNeighborsExpected = false; - } - - private void ProcessNodes(NeighborsMsg msg) - { - NodeStats.AddNodeStatsEvent(NodeStatsEventType.DiscoveryNeighboursIn); - RefreshNodeContactTime(); + NodeStats.AddNodeStatsEvent(NodeStatsEventType.DiscoveryNeighboursIn); + RefreshNodeContactTime(); - foreach (Node node in msg.Nodes) - { - if (node.Address.Address.ToString().Contains("127.0.0.1")) + foreach (Node node in msg.Nodes) { - if (_logger.IsTrace) - _logger.Trace($"Received localhost as node address from: {msg.FarPublicKey}, node: {node}"); - continue; - } + if (node.Address.Address.ToString().Contains("127.0.0.1")) + { + if (_logger.IsTrace) _logger.Trace($"Received localhost as node address from: {msg.FarPublicKey}, node: {node}"); + continue; + } - //If node is new it will create a new nodeLifecycleManager and will update state to New, which will trigger Ping - _discoveryManager.GetNodeLifecycleManager(node); + //If node is new it will create a new nodeLifecycleManager and will update state to New, which will trigger Ping + _discoveryManager.GetNodeLifecycleManager(node); + } } + + _isNeighborsExpected = false; } public void ProcessFindNodeMsg(FindNodeMsg msg) @@ -212,10 +197,7 @@ public void ProcessFindNodeMsg(FindNodeMsg msg) NodeStats.AddNodeStatsEvent(NodeStatsEventType.DiscoveryFindNodeIn); RefreshNodeContactTime(); - Node[] nodes = _nodeTable - .GetClosestNodes(msg.SearchedNodeId) - .Take(12) // Otherwise the payload may become too big, which is out of spec. - .ToArray(); + Node[] nodes = _nodeTable.GetClosestNodes(msg.SearchedNodeId).ToArray(); SendNeighbors(nodes); } diff --git a/src/Nethermind/Nethermind.Network.Discovery/Messages/EnrResponseMsg.cs b/src/Nethermind/Nethermind.Network.Discovery/Messages/EnrResponseMsg.cs index 56c44f5c1c5..c05932a8de1 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/Messages/EnrResponseMsg.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/Messages/EnrResponseMsg.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Net; +using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Network.Enr; diff --git a/src/Nethermind/Nethermind.Network.Discovery/NettyDiscoveryHandler.cs b/src/Nethermind/Nethermind.Network.Discovery/NettyDiscoveryHandler.cs index fa942d6ed1d..d97e73363de 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/NettyDiscoveryHandler.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/NettyDiscoveryHandler.cs @@ -153,13 +153,7 @@ protected override void ChannelRead0(IChannelHandlerContext ctx, DatagramPacket if (!ValidateMsg(msg, type, address, ctx, packet, size)) return; - // Explicitly run it on the default scheduler to prevent something down the line hanging netty task scheduler. - Task.Factory.StartNew( - () => _discoveryManager.OnIncomingMsg(msg), - CancellationToken.None, - TaskCreationOptions.RunContinuationsAsynchronously, - TaskScheduler.Default - ); + _discoveryManager.OnIncomingMsg(msg); } catch (Exception e) { diff --git a/src/Nethermind/Nethermind.Network.Discovery/NodeSourceToDiscV4Feeder.cs b/src/Nethermind/Nethermind.Network.Discovery/NodeSourceToDiscV4Feeder.cs deleted file mode 100644 index 8398d327d8e..00000000000 --- a/src/Nethermind/Nethermind.Network.Discovery/NodeSourceToDiscV4Feeder.cs +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Network.Discovery; - -public class NodeSourceToDiscV4Feeder : IDisposable -{ - private readonly INodeSource _nodeSource; - private readonly IDiscoveryApp _discoveryApp; - private readonly int _maxNodes; - private int _addedNodes = 0; - - public NodeSourceToDiscV4Feeder(INodeSource nodeSource, IDiscoveryApp discoveryApp, int maxNodes) - { - nodeSource.NodeAdded += AddToDiscoveryApp; - _nodeSource = nodeSource; - _discoveryApp = discoveryApp; - _maxNodes = maxNodes; - } - - private void AddToDiscoveryApp(object? sender, NodeEventArgs e) - { - if (_addedNodes >= _maxNodes) return; - _addedNodes++; - _discoveryApp.AddNodeToDiscovery(e.Node); - } - - public void Dispose() - { - _nodeSource.NodeAdded -= AddToDiscoveryApp; - } -} diff --git a/src/Nethermind/Nethermind.Network.Discovery/NodesLocator.cs b/src/Nethermind/Nethermind.Network.Discovery/NodesLocator.cs index f6328015e98..46d8c881719 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/NodesLocator.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/NodesLocator.cs @@ -5,6 +5,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Logging; +using Nethermind.Network.Config; using Nethermind.Network.Discovery.Lifecycle; using Nethermind.Network.Discovery.Messages; using Nethermind.Network.Discovery.RoutingTable; diff --git a/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeAddResult.cs b/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeAddResult.cs index 2c5064c4116..1190a8bff06 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeAddResult.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeAddResult.cs @@ -9,21 +9,13 @@ public class NodeAddResult public NodeBucketItem? EvictionCandidate { get; private init; } - private static NodeAddResult? _added = null; - private static NodeAddResult? _dropped = null; - public static NodeAddResult Added() { - return _added ?? new NodeAddResult { ResultType = NodeAddResultType.Added }; + return new NodeAddResult { ResultType = NodeAddResultType.Added }; } public static NodeAddResult Full(NodeBucketItem evictionCandidate) { return new NodeAddResult { ResultType = NodeAddResultType.Full, EvictionCandidate = evictionCandidate }; } - - public static NodeAddResult Dropped() - { - return _dropped ?? new NodeAddResult { ResultType = NodeAddResultType.Dropped }; - } } diff --git a/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeAddResultType.cs b/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeAddResultType.cs index ac7dd808e4c..b30065b2fcc 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeAddResultType.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeAddResultType.cs @@ -6,6 +6,5 @@ namespace Nethermind.Network.Discovery.RoutingTable; public enum NodeAddResultType { Added, - Full, - Dropped + Full } diff --git a/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeBucket.cs b/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeBucket.cs index 9fb1f8c8e85..4556e32350b 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeBucket.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeBucket.cs @@ -11,14 +11,12 @@ public class NodeBucket { private readonly object _nodeBucketLock = new(); private readonly LinkedList _items; - private readonly float _dropFullBucketProbability; - public NodeBucket(int distance, int bucketSize, float dropFullBucketProbability = 0.0f) + public NodeBucket(int distance, int bucketSize) { _items = new LinkedList(); Distance = distance; BucketSize = bucketSize; - _dropFullBucketProbability = dropFullBucketProbability; } /// @@ -90,18 +88,6 @@ public NodeAddResult AddNode(Node node) return NodeAddResult.Added(); } - if (Random.Shared.NextSingle() < _dropFullBucketProbability) - { - NodeBucketItem item = new(node, DateTime.UtcNow); - if (!_items.Contains(item)) - { - _items.AddFirst(item); - _items.RemoveLast(); - } - - return NodeAddResult.Dropped(); - } - NodeBucketItem evictionCandidate = GetEvictionCandidate(); return NodeAddResult.Full(evictionCandidate); } @@ -117,6 +103,11 @@ public void ReplaceNode(Node nodeToRemove, Node nodeToAdd) _items.Remove(item); AddNode(nodeToAdd); } + else + { + throw new InvalidOperationException( + "Cannot replace non-existing node in the node table bucket"); + } } } diff --git a/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeDistanceCalculator.cs b/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeDistanceCalculator.cs index b342365c188..6f6947a0e18 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeDistanceCalculator.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeDistanceCalculator.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Network.Config; + namespace Nethermind.Network.Discovery.RoutingTable; public class NodeDistanceCalculator : INodeDistanceCalculator diff --git a/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeTable.cs b/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeTable.cs index d610020cd61..caa0065deae 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeTable.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/RoutingTable/NodeTable.cs @@ -29,7 +29,7 @@ public NodeTable( Buckets = new NodeBucket[_discoveryConfig.BucketsCount]; for (int i = 0; i < Buckets.Length; i++) { - Buckets[i] = new NodeBucket(i, _discoveryConfig.BucketSize, _discoveryConfig.DropFullBucketNodeProbability); + Buckets[i] = new NodeBucket(i, _discoveryConfig.BucketSize); } } diff --git a/src/Nethermind/Nethermind.Network.Discovery/Serializers/DiscoveryMsgSerializerBase.cs b/src/Nethermind/Nethermind.Network.Discovery/Serializers/DiscoveryMsgSerializerBase.cs index 833324a7ede..d75395ed122 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/Serializers/DiscoveryMsgSerializerBase.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/Serializers/DiscoveryMsgSerializerBase.cs @@ -7,6 +7,7 @@ using Nethermind.Core.Extensions; using Nethermind.Crypto; using Nethermind.Network.Discovery.Messages; +using Nethermind.Network.P2P; using Nethermind.Serialization.Rlp; namespace Nethermind.Network.Discovery.Serializers; diff --git a/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrRequestMsgSerializer.cs b/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrRequestMsgSerializer.cs index 162fb4ab385..d946178d556 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrRequestMsgSerializer.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrRequestMsgSerializer.cs @@ -5,6 +5,7 @@ using Nethermind.Core.Crypto; using Nethermind.Crypto; using Nethermind.Network.Discovery.Messages; +using Nethermind.Network.P2P; using Nethermind.Serialization.Rlp; namespace Nethermind.Network.Discovery.Serializers; diff --git a/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrResponseMsgSerializer.cs b/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrResponseMsgSerializer.cs index e3aecd063eb..8399c25622f 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrResponseMsgSerializer.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrResponseMsgSerializer.cs @@ -6,6 +6,7 @@ using Nethermind.Crypto; using Nethermind.Network.Discovery.Messages; using Nethermind.Network.Enr; +using Nethermind.Network.P2P; using Nethermind.Serialization.Rlp; namespace Nethermind.Network.Discovery.Serializers; diff --git a/src/Nethermind/Nethermind.Network.Discovery/Serializers/FindNodeMsgSerializer.cs b/src/Nethermind/Nethermind.Network.Discovery/Serializers/FindNodeMsgSerializer.cs index abe65bb9878..783b65a31f5 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/Serializers/FindNodeMsgSerializer.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/Serializers/FindNodeMsgSerializer.cs @@ -5,6 +5,7 @@ using Nethermind.Core.Crypto; using Nethermind.Crypto; using Nethermind.Network.Discovery.Messages; +using Nethermind.Network.P2P; using Nethermind.Serialization.Rlp; namespace Nethermind.Network.Discovery.Serializers; diff --git a/src/Nethermind/Nethermind.Network.Discovery/Serializers/NeighborsMsgSerializer.cs b/src/Nethermind/Nethermind.Network.Discovery/Serializers/NeighborsMsgSerializer.cs index 5898d6db002..70047d03ded 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/Serializers/NeighborsMsgSerializer.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/Serializers/NeighborsMsgSerializer.cs @@ -6,6 +6,7 @@ using Nethermind.Core.Crypto; using Nethermind.Crypto; using Nethermind.Network.Discovery.Messages; +using Nethermind.Network.P2P; using Nethermind.Serialization.Rlp; using Nethermind.Stats.Model; diff --git a/src/Nethermind/Nethermind.Network.Discovery/Serializers/PingMsgSerializer.cs b/src/Nethermind/Nethermind.Network.Discovery/Serializers/PingMsgSerializer.cs index 093e8ca17cf..ec8bc7d9042 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/Serializers/PingMsgSerializer.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/Serializers/PingMsgSerializer.cs @@ -6,6 +6,7 @@ using Nethermind.Core.Crypto; using Nethermind.Crypto; using Nethermind.Network.Discovery.Messages; +using Nethermind.Network.P2P; using Nethermind.Serialization.Rlp; namespace Nethermind.Network.Discovery.Serializers; diff --git a/src/Nethermind/Nethermind.Network.Discovery/Serializers/PongMsgSerializer.cs b/src/Nethermind/Nethermind.Network.Discovery/Serializers/PongMsgSerializer.cs index dbe4ff97e28..45a58af9a63 100644 --- a/src/Nethermind/Nethermind.Network.Discovery/Serializers/PongMsgSerializer.cs +++ b/src/Nethermind/Nethermind.Network.Discovery/Serializers/PongMsgSerializer.cs @@ -5,6 +5,7 @@ using Nethermind.Core.Crypto; using Nethermind.Crypto; using Nethermind.Network.Discovery.Messages; +using Nethermind.Network.P2P; using Nethermind.Serialization.Rlp; namespace Nethermind.Network.Discovery.Serializers; diff --git a/src/Nethermind/Nethermind.Network.Dns.Test/EnrDiscoveryTests.cs b/src/Nethermind/Nethermind.Network.Dns.Test/EnrDiscoveryTests.cs index 004b48c8dfd..9676b49f60b 100644 --- a/src/Nethermind/Nethermind.Network.Dns.Test/EnrDiscoveryTests.cs +++ b/src/Nethermind/Nethermind.Network.Dns.Test/EnrDiscoveryTests.cs @@ -1,15 +1,21 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Threading; using System.Threading.Tasks; +using System.Web; +using DotNetty.Buffers; using FluentAssertions; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Logging; using Nethermind.Network.Config; using Nethermind.Network.Enr; +using Nethermind.Serialization.Rlp; +using Nethermind.Stats.Model; using NSubstitute; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Network.Dns/EnrDiscovery.cs b/src/Nethermind/Nethermind.Network.Dns/EnrDiscovery.cs index 15ffd4df564..b767143b040 100644 --- a/src/Nethermind/Nethermind.Network.Dns/EnrDiscovery.cs +++ b/src/Nethermind/Nethermind.Network.Dns/EnrDiscovery.cs @@ -1,10 +1,12 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Buffers.Text; using System.Net; using DnsClient; using DotNetty.Buffers; using Nethermind.Core.Crypto; +using Nethermind.Crypto; using Nethermind.Logging; using Nethermind.Network.Enr; using Nethermind.Stats.Model; diff --git a/src/Nethermind/Nethermind.Network.Dns/EnrRecordParser.cs b/src/Nethermind/Nethermind.Network.Dns/EnrRecordParser.cs index 7418c3a4517..2c8e39092bb 100644 --- a/src/Nethermind/Nethermind.Network.Dns/EnrRecordParser.cs +++ b/src/Nethermind/Nethermind.Network.Dns/EnrRecordParser.cs @@ -1,12 +1,16 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Net; using System.Text; using DotNetty.Buffers; using DotNetty.Codecs.Base64; using DotNetty.Common.Utilities; +using Nethermind.Core.Crypto; using Nethermind.Network.Enr; +using Nethermind.Network.P2P; using Nethermind.Serialization.Rlp; +using Nethermind.Stats.Model; namespace Nethermind.Network.Dns; diff --git a/src/Nethermind/Nethermind.Network.Dns/EnrTreeBranch.cs b/src/Nethermind/Nethermind.Network.Dns/EnrTreeBranch.cs index 8270dd45866..277fd8d4102 100644 --- a/src/Nethermind/Nethermind.Network.Dns/EnrTreeBranch.cs +++ b/src/Nethermind/Nethermind.Network.Dns/EnrTreeBranch.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Network.Enr; + namespace Nethermind.Network.Dns; /// diff --git a/src/Nethermind/Nethermind.Network.Enr.Test/NodeRecordSignerTests.cs b/src/Nethermind/Nethermind.Network.Enr.Test/NodeRecordSignerTests.cs index 5f595d82afa..48d85e8e4c4 100644 --- a/src/Nethermind/Nethermind.Network.Enr.Test/NodeRecordSignerTests.cs +++ b/src/Nethermind/Nethermind.Network.Enr.Test/NodeRecordSignerTests.cs @@ -10,6 +10,7 @@ using Nethermind.Crypto; using Nethermind.Serialization.Rlp; using NUnit.Framework; +using NUnit.Framework.Internal.Commands; namespace Nethermind.Network.Enr.Test; diff --git a/src/Nethermind/Nethermind.Network.Enr.Test/NodeRecordTests.cs b/src/Nethermind/Nethermind.Network.Enr.Test/NodeRecordTests.cs index d5e4549c19e..b0ff2304d98 100644 --- a/src/Nethermind/Nethermind.Network.Enr.Test/NodeRecordTests.cs +++ b/src/Nethermind/Nethermind.Network.Enr.Test/NodeRecordTests.cs @@ -4,6 +4,7 @@ using System; using FluentAssertions; using Nethermind.Core.Crypto; +using Nethermind.Serialization.Rlp; using NUnit.Framework; namespace Nethermind.Network.Enr.Test; diff --git a/src/Nethermind/Nethermind.Network.Enr/IpEntry.cs b/src/Nethermind/Nethermind.Network.Enr/IpEntry.cs index 1740f0a1df6..f52299f3505 100644 --- a/src/Nethermind/Nethermind.Network.Enr/IpEntry.cs +++ b/src/Nethermind/Nethermind.Network.Enr/IpEntry.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Data; using System.Net; using Nethermind.Serialization.Rlp; diff --git a/src/Nethermind/Nethermind.Network.Enr/NodeRecord.cs b/src/Nethermind/Nethermind.Network.Enr/NodeRecord.cs index 8dffd7bfa6e..82176e91f92 100644 --- a/src/Nethermind/Nethermind.Network.Enr/NodeRecord.cs +++ b/src/Nethermind/Nethermind.Network.Enr/NodeRecord.cs @@ -7,6 +7,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Crypto; +using Nethermind.Network.P2P; using Nethermind.Serialization.Rlp; namespace Nethermind.Network.Enr; diff --git a/src/Nethermind/Nethermind.Network.Stats/INodeStatsManager.cs b/src/Nethermind/Nethermind.Network.Stats/INodeStatsManager.cs index 49aebcf04b3..32e5edcd978 100644 --- a/src/Nethermind/Nethermind.Network.Stats/INodeStatsManager.cs +++ b/src/Nethermind/Nethermind.Network.Stats/INodeStatsManager.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using Nethermind.Stats.Model; diff --git a/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectDetails.cs b/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectDetails.cs new file mode 100644 index 00000000000..f775cbea3eb --- /dev/null +++ b/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectDetails.cs @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +namespace Nethermind.Stats.Model +{ + public class DisconnectDetails + { + public DisconnectType DisconnectType { get; set; } + public DisconnectReason DisconnectReason { get; set; } + } +} diff --git a/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectReason.cs b/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectReason.cs index 9f0efb56f62..5cd61b05790 100644 --- a/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectReason.cs +++ b/src/Nethermind/Nethermind.Network.Stats/Model/DisconnectReason.cs @@ -1,155 +1,25 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -namespace Nethermind.Stats.Model; - -/// -/// Nethermind level disconnect reason. This is different than `EthDisconnectReason` as its more detailed, specific -/// to Nethermind and does not map 1-1 with ethereum disconnect message code. Useful for metrics, debugging and -/// peer disconnect delays. -/// Don't forget to add the corresponding Eth level disconnect reason in `DisconnectReasonExtension`. -/// -public enum DisconnectReason : byte -{ - // Connection related - SessionIdAlreadyExists, - ConnectionClosed, - OutgoingConnectionFailed, - DuplicatedConnection, - PeerRemoved, - TooManyPeers, - SessionAlreadyExist, - ReplacingSessionWithOppositeDirection, - OppositeDirectionCleanup, - - // Non sync, non connection related disconnect - SnapServerNotImplemented, - IncompatibleP2PVersion, - InvalidNetworkId, - InvalidGenesis, - MissingForkId, - InvalidForkId, - ProtocolInitTimeout, - TxFlooding, - NoCapabilityMatched, - ClientFiltered, - AppClosing, - DropWorstPeer, - PeerRefreshFailed, - GossipingInPoS, - - // Sync related - ForwardSyncFailed, - InvalidTxOrUncle, - HeaderResponseTooLong, - InconsistentHeaderBatch, - UnexpectedHeaderHash, - HeaderBatchOnDifferentBranch, - UnexpectedParentHeader, - InvalidHeader, - InvalidReceiptRoot, - - // These are from EthDisconnectReason which does not necessarily used in Nethermind. - EthDisconnectRequested, - TcpSubSystemError, - BreachOfProtocol, - UselessPeer, - AlreadyConnected, - NullNodeIdentityReceived, - ClientQuitting, - UnexpectedIdentity, - IdentitySameAsSelf, - ReceiveMessageTimeout, - - // Try not to use this. Instead create a new one. - Other, -} - -public static class DisconnectReasonExtension +namespace Nethermind.Stats.Model { - public static EthDisconnectReason ToEthDisconnectReason(this DisconnectReason disconnectReason) + /// + /// Eth network level disconnect reason + /// + public enum DisconnectReason : byte { - switch (disconnectReason) - { - case DisconnectReason.TooManyPeers: - return EthDisconnectReason.TooManyPeers; - - case DisconnectReason.SessionAlreadyExist: - case DisconnectReason.ReplacingSessionWithOppositeDirection: - case DisconnectReason.OppositeDirectionCleanup: - case DisconnectReason.DuplicatedConnection: - case DisconnectReason.SessionIdAlreadyExists: - return EthDisconnectReason.AlreadyConnected; - - case DisconnectReason.ConnectionClosed: - case DisconnectReason.OutgoingConnectionFailed: - return EthDisconnectReason.TcpSubSystemError; - - case DisconnectReason.IncompatibleP2PVersion: - return EthDisconnectReason.IncompatibleP2PVersion; - - case DisconnectReason.InvalidNetworkId: - case DisconnectReason.InvalidGenesis: - case DisconnectReason.MissingForkId: - case DisconnectReason.InvalidForkId: - return EthDisconnectReason.BreachOfProtocol; - case DisconnectReason.ClientFiltered: - return EthDisconnectReason.DisconnectRequested; - - case DisconnectReason.ProtocolInitTimeout: - return EthDisconnectReason.ReceiveMessageTimeout; - - case DisconnectReason.SnapServerNotImplemented: - case DisconnectReason.TxFlooding: - case DisconnectReason.NoCapabilityMatched: - return EthDisconnectReason.UselessPeer; - - case DisconnectReason.DropWorstPeer: - return EthDisconnectReason.TooManyPeers; - - case DisconnectReason.PeerRemoved: - case DisconnectReason.PeerRefreshFailed: - return EthDisconnectReason.DisconnectRequested; - - case DisconnectReason.ForwardSyncFailed: - return EthDisconnectReason.DisconnectRequested; - case DisconnectReason.GossipingInPoS: - return EthDisconnectReason.BreachOfProtocol; - case DisconnectReason.AppClosing: - return EthDisconnectReason.ClientQuitting; - - case DisconnectReason.InvalidTxOrUncle: - case DisconnectReason.HeaderResponseTooLong: - case DisconnectReason.InconsistentHeaderBatch: - case DisconnectReason.UnexpectedHeaderHash: - case DisconnectReason.HeaderBatchOnDifferentBranch: - case DisconnectReason.UnexpectedParentHeader: - case DisconnectReason.InvalidHeader: - case DisconnectReason.InvalidReceiptRoot: - return EthDisconnectReason.BreachOfProtocol; - - case DisconnectReason.EthDisconnectRequested: - return EthDisconnectReason.DisconnectRequested; - case DisconnectReason.TcpSubSystemError: - return EthDisconnectReason.TcpSubSystemError; - case DisconnectReason.BreachOfProtocol: - return EthDisconnectReason.BreachOfProtocol; - case DisconnectReason.UselessPeer: - return EthDisconnectReason.UselessPeer; - case DisconnectReason.AlreadyConnected: - return EthDisconnectReason.AlreadyConnected; - case DisconnectReason.NullNodeIdentityReceived: - return EthDisconnectReason.NullNodeIdentityReceived; - case DisconnectReason.ClientQuitting: - return EthDisconnectReason.ClientQuitting; - case DisconnectReason.UnexpectedIdentity: - return EthDisconnectReason.UnexpectedIdentity; - case DisconnectReason.IdentitySameAsSelf: - return EthDisconnectReason.IdentitySameAsSelf; - case DisconnectReason.ReceiveMessageTimeout: - return EthDisconnectReason.ReceiveMessageTimeout; - } - - return EthDisconnectReason.Other; + DisconnectRequested = 0x00, + TcpSubSystemError = 0x01, + BreachOfProtocol = 0x02, + UselessPeer = 0x03, + TooManyPeers = 0x04, + AlreadyConnected = 0x05, + IncompatibleP2PVersion = 0x06, + NullNodeIdentityReceived = 0x07, + ClientQuitting = 0x08, + UnexpectedIdentity = 0x09, + IdentitySameAsSelf = 0x0a, + ReceiveMessageTimeout = 0x0b, + Other = 0x10 } } diff --git a/src/Nethermind/Nethermind.Network.Stats/Model/EthDisconnectReason.cs b/src/Nethermind/Nethermind.Network.Stats/Model/EthDisconnectReason.cs deleted file mode 100644 index 193e0e26790..00000000000 --- a/src/Nethermind/Nethermind.Network.Stats/Model/EthDisconnectReason.cs +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Stats.Model -{ - /// - /// Eth network level disconnect reason - /// - public enum EthDisconnectReason : byte - { - DisconnectRequested = 0x00, - TcpSubSystemError = 0x01, - BreachOfProtocol = 0x02, - UselessPeer = 0x03, - TooManyPeers = 0x04, - AlreadyConnected = 0x05, - IncompatibleP2PVersion = 0x06, - NullNodeIdentityReceived = 0x07, - ClientQuitting = 0x08, - UnexpectedIdentity = 0x09, - IdentitySameAsSelf = 0x0a, - ReceiveMessageTimeout = 0x0b, - Other = 0x10 - } - - public static class EthDisconnectReasonExtensions - { - public static DisconnectReason ToDisconnectReason(this EthDisconnectReason reason) - { - switch (reason) - { - case EthDisconnectReason.DisconnectRequested: - return DisconnectReason.EthDisconnectRequested; - case EthDisconnectReason.TcpSubSystemError: - return DisconnectReason.TcpSubSystemError; - case EthDisconnectReason.BreachOfProtocol: - return DisconnectReason.BreachOfProtocol; - case EthDisconnectReason.UselessPeer: - return DisconnectReason.UselessPeer; - case EthDisconnectReason.TooManyPeers: - return DisconnectReason.TooManyPeers; - case EthDisconnectReason.AlreadyConnected: - return DisconnectReason.AlreadyConnected; - case EthDisconnectReason.IncompatibleP2PVersion: - return DisconnectReason.IncompatibleP2PVersion; - case EthDisconnectReason.NullNodeIdentityReceived: - return DisconnectReason.NullNodeIdentityReceived; - case EthDisconnectReason.ClientQuitting: - return DisconnectReason.ClientQuitting; - case EthDisconnectReason.UnexpectedIdentity: - return DisconnectReason.UnexpectedIdentity; - case EthDisconnectReason.IdentitySameAsSelf: - return DisconnectReason.IdentitySameAsSelf; - case EthDisconnectReason.ReceiveMessageTimeout: - return DisconnectReason.ReceiveMessageTimeout; - default: - return DisconnectReason.Other; - } - } - } -} diff --git a/src/Nethermind/Nethermind.Network.Stats/Model/InitiateDisconnectReason.cs b/src/Nethermind/Nethermind.Network.Stats/Model/InitiateDisconnectReason.cs new file mode 100644 index 00000000000..d8496d9f5a5 --- /dev/null +++ b/src/Nethermind/Nethermind.Network.Stats/Model/InitiateDisconnectReason.cs @@ -0,0 +1,105 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +namespace Nethermind.Stats.Model; + +/// +/// Nethermind level disconnect reason. Don't forget to add the corresponding Eth level disconnect reason in `InitiateDisconnectReasonExtension`. +/// +public enum InitiateDisconnectReason : byte +{ + TooManyPeers, + SessionAlreadyExist, + ReplacingSessionWithOppositeDirection, + OppositeDirectionCleanup, + + SnapServerNotImplemented, + IncompatibleP2PVersion, + InvalidNetworkId, + InvalidGenesis, + MissingForkId, + InvalidForkId, + ProtocolInitTimeout, + TxFlooding, + NoCapabilityMatched, + + DropWorstPeer, + PeerRefreshFailed, + + ForwardSyncFailed, + GossipingInPoS, + SessionIdAlreadyExists, + AppClosing, + + // Sync related + InvalidTxOrUncle, + HeaderResponseTooLong, + InconsistentHeaderBatch, + UnexpectedHeaderHash, + HeaderBatchOnDifferentBranch, + UnexpectedParentHeader, + InvalidHeader, + InvalidReceiptRoot, + + // Try not to use this. Instead create a new one. + Other, +} + +public static class InitiateDisconnectReasonExtension +{ + public static DisconnectReason ToDisconnectReason(this InitiateDisconnectReason initiateDisconnectReason) + { + switch (initiateDisconnectReason) + { + case InitiateDisconnectReason.TooManyPeers: + return DisconnectReason.TooManyPeers; + case InitiateDisconnectReason.SessionAlreadyExist: + case InitiateDisconnectReason.ReplacingSessionWithOppositeDirection: + case InitiateDisconnectReason.OppositeDirectionCleanup: + return DisconnectReason.AlreadyConnected; + + case InitiateDisconnectReason.SnapServerNotImplemented: + return DisconnectReason.UselessPeer; + case InitiateDisconnectReason.IncompatibleP2PVersion: + return DisconnectReason.IncompatibleP2PVersion; + case InitiateDisconnectReason.InvalidNetworkId: + return DisconnectReason.UselessPeer; + case InitiateDisconnectReason.InvalidGenesis: + case InitiateDisconnectReason.MissingForkId: + case InitiateDisconnectReason.InvalidForkId: + return DisconnectReason.BreachOfProtocol; + case InitiateDisconnectReason.ProtocolInitTimeout: + return DisconnectReason.ReceiveMessageTimeout; + case InitiateDisconnectReason.TxFlooding: + return DisconnectReason.UselessPeer; + case InitiateDisconnectReason.NoCapabilityMatched: + return DisconnectReason.UselessPeer; + + case InitiateDisconnectReason.DropWorstPeer: + return DisconnectReason.TooManyPeers; + case InitiateDisconnectReason.PeerRefreshFailed: + return DisconnectReason.DisconnectRequested; + + case InitiateDisconnectReason.ForwardSyncFailed: + return DisconnectReason.DisconnectRequested; + case InitiateDisconnectReason.GossipingInPoS: + return DisconnectReason.BreachOfProtocol; + case InitiateDisconnectReason.SessionIdAlreadyExists: + return DisconnectReason.AlreadyConnected; + case InitiateDisconnectReason.AppClosing: + return DisconnectReason.ClientQuitting; + + case InitiateDisconnectReason.InvalidTxOrUncle: + case InitiateDisconnectReason.HeaderResponseTooLong: + case InitiateDisconnectReason.InconsistentHeaderBatch: + case InitiateDisconnectReason.UnexpectedHeaderHash: + case InitiateDisconnectReason.HeaderBatchOnDifferentBranch: + case InitiateDisconnectReason.UnexpectedParentHeader: + case InitiateDisconnectReason.InvalidHeader: + case InitiateDisconnectReason.InvalidReceiptRoot: + return DisconnectReason.BreachOfProtocol; + } + + return DisconnectReason.Other; + } +} diff --git a/src/Nethermind/Nethermind.Network.Stats/Model/Node.cs b/src/Nethermind/Nethermind.Network.Stats/Model/Node.cs index da0bd43f521..ebca63b426d 100644 --- a/src/Nethermind/Nethermind.Network.Stats/Model/Node.cs +++ b/src/Nethermind/Nethermind.Network.Stats/Model/Node.cs @@ -186,10 +186,6 @@ public static NodeClientType RecognizeClientType(string clientId) { return NodeClientType.Erigon; } - else if (clientId.Contains(nameof(NodeClientType.Reth), StringComparison.OrdinalIgnoreCase)) - { - return NodeClientType.Reth; - } else if (clientId.Contains(nameof(NodeClientType.Parity), StringComparison.OrdinalIgnoreCase)) { return NodeClientType.Parity; diff --git a/src/Nethermind/Nethermind.Network.Stats/Model/NodeClientType.cs b/src/Nethermind/Nethermind.Network.Stats/Model/NodeClientType.cs index fe6978df096..be5ec95ac06 100644 --- a/src/Nethermind/Nethermind.Network.Stats/Model/NodeClientType.cs +++ b/src/Nethermind/Nethermind.Network.Stats/Model/NodeClientType.cs @@ -13,6 +13,5 @@ public enum NodeClientType OpenEthereum, Trinity, Erigon, - Reth, } } diff --git a/src/Nethermind/Nethermind.Network.Stats/NodeStatsLight.cs b/src/Nethermind/Nethermind.Network.Stats/NodeStatsLight.cs index 28c44991155..d2ed5e49073 100644 --- a/src/Nethermind/Nethermind.Network.Stats/NodeStatsLight.cs +++ b/src/Nethermind/Nethermind.Network.Stats/NodeStatsLight.cs @@ -344,13 +344,13 @@ private long CalculateSessionReputation() { rlpxReputation = (long)(rlpxReputation * 0.3); } - else if (_lastLocalDisconnect?.ToEthDisconnectReason() != EthDisconnectReason.DisconnectRequested) + else if (_lastLocalDisconnect != DisconnectReason.DisconnectRequested) { if (_lastRemoteDisconnect == DisconnectReason.TooManyPeers) { rlpxReputation = (long)(rlpxReputation * 0.3); } - else if (_lastRemoteDisconnect?.ToEthDisconnectReason() != EthDisconnectReason.DisconnectRequested) + else if (_lastRemoteDisconnect != DisconnectReason.DisconnectRequested) { rlpxReputation = (long)(rlpxReputation * 0.2); } diff --git a/src/Nethermind/Nethermind.Network.Stats/StatsParameters.cs b/src/Nethermind/Nethermind.Network.Stats/StatsParameters.cs index 2e8a530adce..4eba1b3bdbd 100644 --- a/src/Nethermind/Nethermind.Network.Stats/StatsParameters.cs +++ b/src/Nethermind/Nethermind.Network.Stats/StatsParameters.cs @@ -41,19 +41,19 @@ private StatsParameters() public int[] FailedConnectionDelays { get; } - public int[] DisconnectDelays { get; set; } + public int[] DisconnectDelays { get; } public Dictionary DelayDueToLocalDisconnect { get; } = new() { - { DisconnectReason.UselessPeer, TimeSpan.FromMinutes(15) }, - - // Its actually protocol init timeout, when status message is not received in time. - { DisconnectReason.ReceiveMessageTimeout, TimeSpan.FromMinutes(5) }, + { DisconnectReason.UselessPeer, TimeSpan.FromMinutes(5) } }; public Dictionary DelayDueToRemoteDisconnect { get; } = new() { - { DisconnectReason.ClientQuitting, TimeSpan.FromMinutes(1) }, + // Actual explicit ClientQuitting is very rare, but internally we also use this status for connection + // closed, which can happen if remote client close connection without giving any reason. + // It is unclear why we have such large number of these, but it seems that it is usually transient. + { DisconnectReason.ClientQuitting, TimeSpan.FromMinutes(1) } }; public Dictionary DelayDueToEvent { get; } = new() diff --git a/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs b/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs index 804f492e84b..ec9abcb84a0 100644 --- a/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs @@ -112,12 +112,46 @@ public void Fork_id_and_hash_as_expected_on_goerli(long head, ulong headTimestam Test(head, headTimestamp, KnownHashes.GoerliGenesis, forkHashHex, next, description, GoerliSpecProvider.Instance, "goerli.json"); } - [TestCase(0, 0ul, "0xc61a6098", 1_696_000_704ul, "Unsynced")] - [TestCase(1, 1_696_000_703ul, "0xc61a6098", 1_696_000_704ul, "Last genesis spec block")] - [TestCase(2, 1_696_000_704ul, "0xfd4f016b", 0ul, "First Shanghai block")] - public void Fork_id_and_hash_as_expected_on_holesky(long head, ulong headTimestamp, string forkHashHex, ulong next, string description) + [TestCase(0, 0ul, "0x3b8e0691", 1ul, "Unsynced, last Frontier block")] + [TestCase(1, 0ul, "0x60949295", 2ul, "First and last Homestead block")] + [TestCase(2, 0ul, "0x8bde40dd", 3ul, "First and last Tangerine block")] + [TestCase(3, 0ul, "0xcb3a64bb", 1035301ul, "First Spurious block")] + [TestCase(1_035_300L, 0ul, "0xcb3a64bb", 1_035_301ul, "Last Spurious block")] + [TestCase(1_035_301L, 0ul, "0x8d748b57", 3_660_663ul, "First Byzantium block")] + [TestCase(3_660_662L, 0ul, "0x8d748b57", 3_660_663ul, "Last Byzantium block")] + [TestCase(3_660_663L, 0ul, "0xe49cab14", 4_321_234ul, "First Constantinople block")] + [TestCase(4_321_233L, 0ul, "0xe49cab14", 4_321_234ul, "Last Constantinople block")] + [TestCase(4_321_234L, 0ul, "0xafec6b27", 5_435_345ul, "First Petersburg block")] + [TestCase(5_435_344L, 0ul, "0xafec6b27", 5_435_345ul, "Last Petersburg block")] + [TestCase(5_435_345L, 0ul, "0xcbdb8838", 8_290_928ul, "First Istanbul block")] + [TestCase(8_290_928L, 0ul, "0x6910c8bd", 8_897_988ul, "First Berlin block")] + [TestCase(8_700_000L, 0ul, "0x6910c8bd", 8_897_988ul, "Future Berlin block")] + [TestCase(8_897_988L, 0ul, "0x8E29F2F3", 0ul, "First London block")] + [TestCase(9_000_000L, 0ul, "0x8E29F2F3", 0ul, "Future London block")] + public void Fork_id_and_hash_as_expected_on_rinkeby(long head, ulong headTimestamp, string forkHashHex, ulong next, string description) { - Test(head, headTimestamp, KnownHashes.HoleskyGenesis, forkHashHex, next, description, HoleskySpecProvider.Instance, "holesky.json"); + Test(head, headTimestamp, KnownHashes.RinkebyGenesis, forkHashHex, next, description, RinkebySpecProvider.Instance, "rinkeby.json"); + } + + [TestCase(0, 0ul, "0x30c7ddbc", 10ul, " Unsynced, last Frontier, Homestead and first Tangerine block")] + [TestCase(9, 0ul, "0x30c7ddbc", 10ul, "Last Tangerine block")] + [TestCase(10, 0ul, "0x63760190", 1_700_000ul, "First Spurious block")] + [TestCase(1_699_999L, 0ul, "0x63760190", 1_700_000ul, "Last Spurious block")] + [TestCase(1_700_000L, 0ul, "0x3ea159c7", 4_230_000ul, "First Byzantium block")] + [TestCase(4_229_999L, 0ul, "0x3ea159c7", 4_230_000ul, "Last Byzantium block")] + [TestCase(4_230_000L, 0ul, "0x97b544f3", 4_939_394ul, "First Constantinople block")] + [TestCase(4_939_393L, 0ul, "0x97b544f3", 4_939_394ul, "Last Constantinople block")] + [TestCase(4_939_394L, 0ul, "0xd6e2149b", 6_485_846ul, "First Petersburg block")] + [TestCase(6_485_845L, 0ul, "0xd6e2149b", 6_485_846ul, "Last Petersburg block")] + [TestCase(6_485_846L, 0ul, "0x4bc66396", 7_117_117ul, "First Istanbul block")] + [TestCase(7_117_117L, 0ul, "0x6727ef90", 9_812_189ul, "First Muir Glacier block")] + [TestCase(9_812_189L, 0ul, "0xa157d377", 10_499_401ul, "First Berlin block")] + [TestCase(9_900_000L, 0ul, "0xa157d377", 10_499_401ul, "Future Berlin block")] + [TestCase(10_499_401L, 0ul, "0x7119B6B3", 0ul, "First London block")] + [TestCase(12_000_000, 0ul, "0x7119B6B3", 0ul, "Future London block")] + public void Fork_id_and_hash_as_expected_on_ropsten(long head, ulong headTimestamp, string forkHashHex, ulong next, string description) + { + Test(head, headTimestamp, KnownHashes.RopstenGenesis, forkHashHex, next, description, RopstenSpecProvider.Instance, "ropsten.json"); } [TestCase(0, 0ul, "0xFE3366E7", 1735371ul, "Sepolia genesis")] @@ -142,10 +176,8 @@ public void Fork_id_and_hash_as_expected_on_sepolia(long head, ulong headTimesta [TestCase(16101499, 0ul, "0xb6e6cd81", 16101500ul, "Last POSDAO Activation block")] [TestCase(16101500, 0ul, "0x069a83d9", 19040000ul, "First Berlin block")] [TestCase(19039999, 0ul, "0x069a83d9", 19040000ul, "Last Berlin block")] - [TestCase(19040000, 0ul, "0x018479d3", GnosisSpecProvider.ShanghaiTimestamp, "First London block")] - [TestCase(21735000, 0ul, "0x018479d3", GnosisSpecProvider.ShanghaiTimestamp, "First GIP-31 block")] - [TestCase(31735000, GnosisSpecProvider.ShanghaiTimestamp, "0x2efe91ba", 0ul, "First Shanghai timestamp")] - [TestCase(91735000, GnosisSpecProvider.ShanghaiTimestamp, "0x2efe91ba", 0ul, "Future Shanghai timestamp")] + [TestCase(19040000, 0ul, "0x018479d3", 0ul, "First London block")] + [TestCase(21735000, 0ul, "0x018479d3", 0ul, "First GIP-31 block")] public void Fork_id_and_hash_as_expected_on_gnosis(long head, ulong headTimestamp, string forkHashHex, ulong next, string description) { ChainSpecLoader loader = new ChainSpecLoader(new EthereumJsonSerializer()); @@ -224,6 +256,12 @@ public void Fork_id_and_hash_as_expected_on_chiado(long head, ulong headTimestam // Local is mainnet Petersburg, remote is Rinkeby Petersburg. [TestCase(7987396, 0ul, "0xafec6b27", 0ul, ValidationResult.IncompatibleOrStale)] + // 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). + [TestCase(88888888, 0ul, "0xf0afd0e3", 88888888ul, ValidationResult.IncompatibleOrStale)] + // Local is mainnet Byzantium. Remote is also in Byzantium, but announces Gopherium (non existing // fork) at block 7279999, before Petersburg. Local is incompatible. [TestCase(7279999, 0ul, "0xa00bc324", 7279999ul, ValidationResult.IncompatibleOrStale)] @@ -278,6 +316,12 @@ public void Fork_id_and_hash_as_expected_on_chiado(long head, ulong headTimestam // 0xffffffff. Local needs software update, reject. [TestCase(15_050_000, 0ul, "0x98765432", ulong.MaxValue, ValidationResult.IncompatibleOrStale, true)] + // 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). + [TestCase(888888888, 1660000000ul, "0xf0afd0e3", 1660000000ul, ValidationResult.IncompatibleOrStale)] + // 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. [TestCase(19999999, 1667999999ul, "0xf0afd0e3", 1667999999ul, ValidationResult.IncompatibleOrStale, true)] @@ -300,6 +344,12 @@ public void Fork_id_and_hash_as_expected_on_chiado(long head, ulong headTimestam // Local is mainnet Shanghai, remote is random Shanghai. [TestCase(20000000, 1_668_000_000ul, "0x12345678", 0ul, ValidationResult.IncompatibleOrStale, true)] + // Local is mainnet Shanghai, 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). + [TestCase(88888888, 8888888888ul, "0x71147644", 8888888888ul, ValidationResult.IncompatibleOrStale, true)] + public void Test_fork_id_validation_mainnet(long headNumber, ulong headTimestamp, string hash, ulong next, ValidationResult result, bool UseTimestampSpec = false) { IBlockTree blockTree = Substitute.For(); diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/DisconnectMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/DisconnectMessageSerializerTests.cs index 6314dfc3403..f9397efb92f 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/DisconnectMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/DisconnectMessageSerializerTests.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using FluentAssertions; using Nethermind.Core.Extensions; using Nethermind.Network.P2P.Messages; using Nethermind.Stats.Model; @@ -16,7 +15,7 @@ public class DisconnectMessageSerializerTests [Test] public void Can_do_roundtrip() { - DisconnectMessage msg = new(EthDisconnectReason.AlreadyConnected); + DisconnectMessage msg = new(DisconnectReason.AlreadyConnected); DisconnectMessageSerializer serializer = new(); byte[] serialized = serializer.Serialize(msg); Assert.That(serialized.ToHexString(true), Is.EqualTo("0xc105"), "bytes"); @@ -30,19 +29,17 @@ public void Can_read_single_byte_message() DisconnectMessageSerializer serializer = new(); byte[] serialized = new byte[] { 16 }; DisconnectMessage deserialized = serializer.Deserialize(serialized); - Assert.That((EthDisconnectReason)deserialized.Reason, Is.EqualTo(EthDisconnectReason.Other), "reason"); + Assert.That((DisconnectReason)deserialized.Reason, Is.EqualTo(DisconnectReason.Other), "reason"); } - [TestCase("", EthDisconnectReason.DisconnectRequested)] - [TestCase("00", EthDisconnectReason.DisconnectRequested)] - [TestCase("10", EthDisconnectReason.Other)] - [TestCase("82c104", EthDisconnectReason.TooManyPeers)] - public void Can_read_other_format_message(string hex, EthDisconnectReason expectedReason) - { - DisconnectMessageSerializer serializer = new DisconnectMessageSerializer(); - byte[] serialized = Bytes.FromHexString(hex); - DisconnectMessage deserialized = serializer.Deserialize(serialized); - deserialized.Reason.Should().Be((int)expectedReason); - } + // does this format happen more often? + // [Test] + // public void Can_read_other_format_message() + // { + // DisconnectMessageSerializer serializer = new DisconnectMessageSerializer(); + // byte[] serialized = Bytes.FromHexString("0204c108"); + // DisconnectMessage deserialized = serializer.Deserialize(serialized); + // Assert.AreEqual(DisconnectReason.Other, (DisconnectReason)deserialized.Reason, "reason"); + // } } } diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/HelloMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/HelloMessageSerializerTests.cs index e9180323380..d5ec5080a21 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/HelloMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/HelloMessageSerializerTests.cs @@ -5,6 +5,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Network.Contract.P2P; +using Nethermind.Network.P2P; using Nethermind.Network.P2P.Messages; using Nethermind.Stats.Model; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/P2PProtocolHandlerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/P2PProtocolHandlerTests.cs index c890b2d3159..8208b01c5af 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/P2PProtocolHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/P2PProtocolHandlerTests.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using System.Linq; -using System.Text.RegularExpressions; using DotNetty.Buffers; +using DotNetty.Common.Utilities; using FluentAssertions; using Nethermind.Core.Test.Builders; using Nethermind.Core.Timers; @@ -39,7 +39,6 @@ public void Setup() private IMessageSerializationService _serializer; private Node node = new(TestItem.PublicKeyA, "127.0.0.1", 30303); private INodeStatsManager _nodeStatsManager; - private Regex? _clientIdPattern; private Packet CreatePacket(T message) where T : P2PMessage { @@ -64,7 +63,6 @@ private P2PProtocolHandler CreateSession() TestItem.PublicKeyA, _nodeStatsManager, _serializer, - _clientIdPattern, LimboLogs.Instance); } @@ -117,48 +115,7 @@ public void On_hello_with_no_matching_capability() p2PProtocolHandler.HandleMessage(packet); _nodeStatsManager.GetOrAdd(node).FailedCompatibilityValidation.Should().NotBeNull(); - _session.Received(1).InitiateDisconnect(DisconnectReason.NoCapabilityMatched, Arg.Any()); - } - - [TestCase("besu", "besu/v23.4.0/linux-x86_64/openjdk-java-17", false)] - [TestCase("besu", "Geth/v1.12.1-unstable-b8d7da87-20230808/linux-amd64/go1.19.2", true)] - [TestCase("^((?!besu).)*$", "Geth/v1.12.1-unstable-b8d7da87-20230808/linux-amd64/go1.19.2", false)] - [TestCase("^((?!besu).)*$", "besu/v23.4.0/linux-x86_64/openjdk-java-17", true)] - public void On_hello_with_not_matching_client_id(string pattern, string clientId, bool shouldDisconnect) - { - _clientIdPattern = new Regex(pattern); - P2PProtocolHandler p2PProtocolHandler = CreateSession(); - - HelloMessage message = new HelloMessage() - { - Capabilities = new List() - { - new Capability(Protocol.Eth, 63) - }, - NodeId = TestItem.PublicKeyA, - ClientId = clientId, - }; - - IByteBuffer data = _serializer.ZeroSerialize(message); - // to account for adaptive packet type - data.ReadByte(); - - Packet packet = new Packet(data.ReadAllBytesAsArray()) - { - Protocol = message.Protocol, - PacketType = (byte)message.PacketType, - }; - - p2PProtocolHandler.HandleMessage(packet); - - if (shouldDisconnect) - { - _session.Received(1).InitiateDisconnect(DisconnectReason.ClientFiltered, Arg.Any()); - } - else - { - _session.DidNotReceive().InitiateDisconnect(DisconnectReason.ClientFiltered, Arg.Any()); - } + _session.Received(1).InitiateDisconnect(InitiateDisconnectReason.NoCapabilityMatched, Arg.Any()); } [Test] diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/SessionTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/SessionTests.cs index 73490d1b6f4..ed22710eeb4 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/SessionTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/SessionTests.cs @@ -194,7 +194,7 @@ public async Task Adding_protocols_when_disconnecting_will_not_cause_trouble() task.Start(); await Task.Delay(20); - session.InitiateDisconnect(DisconnectReason.Other, "test"); + session.InitiateDisconnect(InitiateDisconnectReason.Other, "test"); await Task.Delay(10); shouldStop = true; } @@ -246,7 +246,7 @@ public void Cannot_dispose_unless_disconnected() session.AddProtocolHandler(bbb); session.AddProtocolHandler(ccc); - session.InitiateDisconnect(DisconnectReason.Other, "test"); + session.InitiateDisconnect(InitiateDisconnectReason.Other, "test"); session.Dispose(); aaa.Received().DisconnectProtocol(DisconnectReason.Other, "test"); @@ -267,7 +267,7 @@ public void Raises_event_on_disconnecting() session.Handshake(TestItem.PublicKeyA); session.Init(5, _channelHandlerContext, _packetSender); - session.InitiateDisconnect(DisconnectReason.Other); + session.InitiateDisconnect(InitiateDisconnectReason.Other); Assert.True(wasCalled); } @@ -293,7 +293,7 @@ public void Disconnects_after_initiating_disconnect() session.Handshake(TestItem.PublicKeyA); session.Init(5, _channelHandlerContext, _packetSender); - session.InitiateDisconnect(DisconnectReason.Other); + session.InitiateDisconnect(InitiateDisconnectReason.Other); Assert.True(wasCalled); Assert.True(session.IsClosing); } @@ -309,7 +309,7 @@ public void Do_not_disconnects_after_initiating_disconnect_on_static_node() session.Handshake(TestItem.PublicKeyA); session.Init(5, _channelHandlerContext, _packetSender); - session.InitiateDisconnect(DisconnectReason.TooManyPeers); + session.InitiateDisconnect(InitiateDisconnectReason.TooManyPeers); Assert.False(wasCalled); Assert.False(session.IsClosing); } @@ -347,8 +347,8 @@ public void Can_disconnect_many_times() session.Handshake(TestItem.PublicKeyA); session.Init(5, _channelHandlerContext, _packetSender); - session.InitiateDisconnect(DisconnectReason.Other); - session.InitiateDisconnect(DisconnectReason.Other); + session.InitiateDisconnect(InitiateDisconnectReason.Other); + session.InitiateDisconnect(InitiateDisconnectReason.Other); session.MarkDisconnected(DisconnectReason.Other, DisconnectType.Local, "test"); session.MarkDisconnected(DisconnectReason.Other, DisconnectType.Remote, "test"); Assert.That(wasCalledTimes, Is.EqualTo(1)); @@ -397,7 +397,7 @@ public void Can_add_and_disconnect_many_handlers() session.AddProtocolHandler(aaa); session.AddProtocolHandler(bbb); session.AddProtocolHandler(ccc); - session.InitiateDisconnect(DisconnectReason.Other, "test"); + session.InitiateDisconnect(InitiateDisconnectReason.Other, "test"); aaa.Received().DisconnectProtocol(DisconnectReason.Other, "test"); bbb.Received().DisconnectProtocol(DisconnectReason.Other, "test"); ccc.Received().DisconnectProtocol(DisconnectReason.Other, "test"); @@ -491,7 +491,7 @@ public void Stops_delivering_messages_after_disconnect() IProtocolHandler p2p = BuildHandler("p2p", 10); session.AddProtocolHandler(p2p); - session.InitiateDisconnect(DisconnectReason.Other); + session.InitiateDisconnect(InitiateDisconnectReason.Other); session.DeliverMessage(PingMessage.Instance); _packetSender.DidNotReceive().Enqueue(Arg.Any()); @@ -506,7 +506,7 @@ public void Stops_receiving_messages_after_disconnect() IProtocolHandler p2p = BuildHandler("p2p", 10); session.AddProtocolHandler(p2p); - session.InitiateDisconnect(DisconnectReason.Other); + session.InitiateDisconnect(InitiateDisconnectReason.Other); session.ReceiveMessage(new Packet("p2p", 3, Array.Empty())); p2p.DidNotReceive().HandleMessage(Arg.Is(p => p.Protocol == "p2p" && p.PacketType == 3)); diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/BlockBodiesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/BlockBodiesMessageSerializerTests.cs index ced3daafb49..0e66963d2a9 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/BlockBodiesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/BlockBodiesMessageSerializerTests.cs @@ -20,7 +20,7 @@ public class BlockBodiesMessageSerializerTests [TestCaseSource(nameof(GetBlockBodyValues))] public void Should_pass_roundtrip(BlockBody[] bodies) => SerializerTester.TestZero( new BlockBodiesMessageSerializer(), - new BlockBodiesMessage(bodies), + new BlockBodiesMessage { Bodies = bodies }, additionallyExcluding: (o) => o.Excluding(c => c.Name == nameof(Transaction.SenderAddress)) .Excluding(c => c.Name == nameof(Transaction.NetworkWrapper))); @@ -30,9 +30,9 @@ public void Should_not_contain_network_form_tx_wrapper(BlockBody[] bodies) { IByteBuffer buffer = PooledByteBufferAllocator.Default.Buffer(1024 * 16); BlockBodiesMessageSerializer serializer = new(); - serializer.Serialize(buffer, new BlockBodiesMessage(bodies)); + serializer.Serialize(buffer, new BlockBodiesMessage { Bodies = bodies }); BlockBodiesMessage deserializedMessage = serializer.Deserialize(buffer); - foreach (BlockBody? body in deserializedMessage.Bodies.Bodies) + foreach (BlockBody? body in deserializedMessage.Bodies) { if (body is null) continue; foreach (Transaction tx in body.Transactions.Where(t => t.SupportsBlobs)) @@ -47,7 +47,7 @@ private static IEnumerable GetBlockBodyValues() BlockHeader header = Build.A.BlockHeader.TestObject; Transaction tx = Build.A.Transaction .WithTo(TestItem.AddressA) - .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Sepolia, LimboLogs.Instance), TestItem.PrivateKeyA) + .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Ropsten, LimboLogs.Instance), TestItem.PrivateKeyA) .TestObject; tx.SenderAddress = null; diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/BlockBodiesMessageTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/BlockBodiesMessageTests.cs index a5fb020fe45..c969bf2883b 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/BlockBodiesMessageTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/BlockBodiesMessageTests.cs @@ -14,7 +14,7 @@ public class BlockBodiesMessageTests public void Ctor_with_nulls() { var message = new BlockBodiesMessage(new[] { Build.A.Block.TestObject, null, Build.A.Block.TestObject }); - Assert.That(message.Bodies.Bodies.Length, Is.EqualTo(3)); + Assert.That(message.Bodies.Length, Is.EqualTo(3)); } [Test] diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandlerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandlerTests.cs index 81fc724dedb..2734119c9f2 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandlerTests.cs @@ -38,15 +38,14 @@ namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V62 [TestFixture, Parallelizable(ParallelScope.Self)] public class Eth62ProtocolHandlerTests { - private ISession _session = null!; - private IMessageSerializationService _svc = null!; - private ISyncServer _syncManager = null!; - private ITxPool _transactionPool = null!; - private Block _genesisBlock = null!; - private Eth62ProtocolHandler _handler = null!; - private IGossipPolicy _gossipPolicy = null!; + private ISession _session; + private IMessageSerializationService _svc; + private ISyncServer _syncManager; + private ITxPool _transactionPool; + private Block _genesisBlock; + private Eth62ProtocolHandler _handler; + private IGossipPolicy _gossipPolicy; private readonly TxDecoder _txDecoder = new(); - private ITxGossipPolicy _txGossipPolicy = null!; [SetUp] public void Setup() @@ -68,9 +67,6 @@ public void Setup() _gossipPolicy.CanGossipBlocks.Returns(true); _gossipPolicy.ShouldGossipBlock(Arg.Any()).Returns(true); _gossipPolicy.ShouldDisconnectGossipingNodes.Returns(false); - _txGossipPolicy = Substitute.For(); - _txGossipPolicy.ShouldListenToGossippedTransactions.Returns(true); - _txGossipPolicy.ShouldGossipTransaction(Arg.Any()).Returns(true); _handler = new Eth62ProtocolHandler( _session, _svc, @@ -78,8 +74,7 @@ public void Setup() _syncManager, _transactionPool, _gossipPolicy, - LimboLogs.Instance, - _txGossipPolicy); + LimboLogs.Instance); _handler.Init(); } @@ -293,7 +288,7 @@ public void Should_disconnect_peer_sending_new_block_message_in_PoS() HandleIncomingStatusMessage(); HandleZeroMessage(newBlockMessage, Eth62MessageCode.NewBlock); - _session.Received().InitiateDisconnect(DisconnectReason.GossipingInPoS, "NewBlock message received after FIRST_FINALIZED_BLOCK PoS block. Disconnecting Peer."); + _session.Received().InitiateDisconnect(InitiateDisconnectReason.GossipingInPoS, "NewBlock message received after FIRST_FINALIZED_BLOCK PoS block. Disconnecting Peer."); } [Test] @@ -332,7 +327,7 @@ public void Should_disconnect_peer_sending_new_block_hashes_in_PoS() HandleIncomingStatusMessage(); HandleZeroMessage(msg, Eth62MessageCode.NewBlockHashes); - _session.Received().InitiateDisconnect(DisconnectReason.GossipingInPoS, "NewBlock message received after FIRST_FINALIZED_BLOCK PoS block. Disconnecting Peer."); + _session.Received().InitiateDisconnect(InitiateDisconnectReason.GossipingInPoS, "NewBlock message received after FIRST_FINALIZED_BLOCK PoS block. Disconnecting Peer."); } [Test] @@ -373,23 +368,20 @@ public void Should_truncate_array_when_too_many_body(int availableBody, int expe HandleZeroMessage(msg, Eth62MessageCode.GetBlockBodies); response.Should().NotBeNull(); - BlockBody[]? bodies = response.Bodies.Bodies; - bodies.Length.Should().Be(expectedResponseSize); - foreach (BlockBody responseBody in bodies) + response.Bodies.Length.Should().Be(expectedResponseSize); + foreach (BlockBody responseBody in response.Bodies) { responseBody.Should().NotBeNull(); } } [Test] - public void Can_handle_transactions([Values(true, false)] bool canGossipTransactions) + public void Can_handle_transactions() { - _txGossipPolicy.ShouldListenToGossippedTransactions.Returns(canGossipTransactions); TransactionsMessage msg = new(new List(Build.A.Transaction.SignedAndResolved().TestObjectNTimes(3))); HandleIncomingStatusMessage(); HandleZeroMessage(msg, Eth62MessageCode.Transactions); - _transactionPool.Received(canGossipTransactions ? 3 : 0).SubmitTx(Arg.Any(), TxHandlingOptions.None); } [Test] @@ -402,42 +394,6 @@ public void Can_handle_transactions_without_filtering() HandleZeroMessage(msg, Eth62MessageCode.Transactions); } - [Test] - public async Task Can_LimitGetBlockBodiesRequestSize() - { - BlockBodiesMessage msg = new(Build.A.Block.TestObjectNTimes(3)); - Transaction signedTransaction = Build.A.Transaction.SignedAndResolved().TestObject; - Block largerBlock = Build.A.Block.WithTransactions(Enumerable.Repeat(signedTransaction, 1000).ToArray()).TestObject; - - BlockBodiesMessage largeMsg = new(Enumerable.Repeat(largerBlock, 100).ToArray()); - List requests = Enumerable.Repeat(Keccak.Zero, 1000).ToList(); - - GetBlockBodiesMessage? getMsg = null; - - _session - .When(session => session.DeliverMessage(Arg.Any())) - .Do((info => getMsg = (GetBlockBodiesMessage)info[0])); - - HandleIncomingStatusMessage(); - Task getTask = ((ISyncPeer)_handler).GetBlockBodies(requests, CancellationToken.None); - HandleZeroMessage(msg, Eth62MessageCode.BlockBodies); - await getTask; - - Assert.That(getMsg.BlockHashes.Count, Is.EqualTo(4)); - - getTask = ((ISyncPeer)_handler).GetBlockBodies(requests, CancellationToken.None); - HandleZeroMessage(largeMsg, Eth62MessageCode.BlockBodies); - await getTask; - - Assert.That(getMsg.BlockHashes.Count, Is.EqualTo(6)); - - getTask = ((ISyncPeer)_handler).GetBlockBodies(requests, CancellationToken.None); - HandleZeroMessage(msg, Eth62MessageCode.BlockBodies); - await getTask; - - Assert.That(getMsg.BlockHashes.Count, Is.EqualTo(4)); - } - [Test] public void Can_handle_block_bodies() { @@ -451,10 +407,10 @@ public void Can_handle_block_bodies() [Test] public async Task Get_block_bodies_returns_immediately_when_empty_hash_list() { - OwnedBlockBodies bodies = + BlockBody[] bodies = await ((ISyncPeer)_handler).GetBlockBodies(new List(), CancellationToken.None); - bodies.Bodies.Should().HaveCount(0); + bodies.Should().HaveCount(0); } [Test] @@ -526,7 +482,7 @@ public void should_send_txs_with_size_up_to_MaxPacketSize_in_one_TransactionsMes [TestCase(10000)] public void should_send_txs_with_size_exceeding_MaxPacketSize_in_more_than_one_TransactionsMessage(int txCount) { - int sizeOfOneTestTransaction = Build.A.Transaction.SignedAndResolved().TestObject.GetLength(); + int sizeOfOneTestTransaction = _txDecoder.GetLength(Build.A.Transaction.SignedAndResolved().TestObject); int maxNumberOfTxsInOneMsg = TransactionsMessage.MaxPacketSize / sizeOfOneTestTransaction; // it's 1055 int nonFullMsgTxsCount = txCount % maxNumberOfTxsInOneMsg; int messagesCount = txCount / maxNumberOfTxsInOneMsg + (nonFullMsgTxsCount > 0 ? 1 : 0); @@ -594,7 +550,9 @@ public void Throws_if_new_block_message_received_before_status() private void HandleIncomingStatusMessage() { - var statusMsg = new StatusMessage { GenesisHash = _genesisBlock.Hash, BestHash = _genesisBlock.Hash }; + var statusMsg = new StatusMessage(); + statusMsg.GenesisHash = _genesisBlock.Hash; + statusMsg.BestHash = _genesisBlock.Hash; IByteBuffer statusPacket = _svc.ZeroSerialize(statusMsg); statusPacket.ReadByte(); diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/TransactionsMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/TransactionsMessageSerializerTests.cs index 9c58c001545..35cf90d7221 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/TransactionsMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/TransactionsMessageSerializerTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using DotNetty.Buffers; +using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; @@ -112,7 +113,7 @@ public static IEnumerable> GetTransactions() { Build.A.Transaction .WithTo(TestItem.AddressA) - .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Sepolia, LimboLogs.Instance), TestItem.PrivateKeyA) + .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Ropsten, LimboLogs.Instance), TestItem.PrivateKeyA) .TestObject }; @@ -121,36 +122,36 @@ public static IEnumerable> GetTransactions() Build.A.Transaction .WithType(TxType.Legacy) .WithTo(TestItem.AddressA) - .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Sepolia, LimboLogs.Instance), TestItem.PrivateKeyA) + .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Ropsten, LimboLogs.Instance), TestItem.PrivateKeyA) .TestObject, Build.A.Transaction .WithTo(TestItem.AddressA) .WithShardBlobTxTypeAndFields(1) - .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Sepolia, LimboLogs.Instance), TestItem.PrivateKeyA) + .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Ropsten, LimboLogs.Instance), TestItem.PrivateKeyA) .TestObject, Build.A.Transaction .WithType(TxType.AccessList) .WithTo(TestItem.AddressA) - .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Sepolia, LimboLogs.Instance), TestItem.PrivateKeyA) + .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Ropsten, LimboLogs.Instance), TestItem.PrivateKeyA) .TestObject, Build.A.Transaction .WithTo(TestItem.AddressA) .WithShardBlobTxTypeAndFields(2) - .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Sepolia, LimboLogs.Instance), TestItem.PrivateKeyA) + .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Ropsten, LimboLogs.Instance), TestItem.PrivateKeyA) .TestObject, Build.A.Transaction .WithType(TxType.EIP1559) .WithTo(TestItem.AddressA) - .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Sepolia, LimboLogs.Instance), TestItem.PrivateKeyA) + .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Ropsten, LimboLogs.Instance), TestItem.PrivateKeyA) .TestObject, Build.A.Transaction .WithTo(TestItem.AddressA) .WithShardBlobTxTypeAndFields(3) - .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Sepolia, LimboLogs.Instance), TestItem.PrivateKeyA) + .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Ropsten, LimboLogs.Instance), TestItem.PrivateKeyA) .TestObject, Build.A.Transaction .WithType(TxType.EIP1559) - .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Sepolia, LimboLogs.Instance), TestItem.PrivateKeyA) + .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Ropsten, LimboLogs.Instance), TestItem.PrivateKeyA) .TestObject, }; @@ -160,12 +161,12 @@ public static IEnumerable> GetTransactions() Build.A.Transaction .WithTo(TestItem.AddressA) .WithShardBlobTxTypeAndFields(1) - .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Sepolia, LimboLogs.Instance), TestItem.PrivateKeyA) + .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Ropsten, LimboLogs.Instance), TestItem.PrivateKeyA) .TestObject, Build.A.Transaction .WithTo(TestItem.AddressA) .WithShardBlobTxTypeAndFields(2) - .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Sepolia, LimboLogs.Instance), TestItem.PrivateKeyA) + .SignedAndResolved(new EthereumEcdsa(BlockchainIds.Ropsten, LimboLogs.Instance), TestItem.PrivateKeyA) .TestObject }; } diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/TxFloodControllerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/TxFloodControllerTests.cs index c076d685dfc..cd15c34878c 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/TxFloodControllerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/TxFloodControllerTests.cs @@ -81,7 +81,7 @@ public void Will_only_get_disconnected_when_really_flooding() _controller.Report(false); _session.DidNotReceiveWithAnyArgs() - .InitiateDisconnect(DisconnectReason.TxFlooding, null); + .InitiateDisconnect(InitiateDisconnectReason.TxFlooding, null); for (int i = 0; i < 6000 - 601; i++) { @@ -92,7 +92,7 @@ public void Will_only_get_disconnected_when_really_flooding() _controller.Report(false); _session.Received() - .InitiateDisconnect(DisconnectReason.TxFlooding, Arg.Any()); + .InitiateDisconnect(InitiateDisconnectReason.TxFlooding, Arg.Any()); } [Test] diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/Eth63ProtocolHandlerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/Eth63ProtocolHandlerTests.cs index 204968c1073..7bad8a7f028 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/Eth63ProtocolHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/Eth63ProtocolHandlerTests.cs @@ -33,150 +33,132 @@ public class Eth63ProtocolHandlerTests public async Task Can_request_and_handle_receipts() { Context ctx = new(); - TxReceipt[][]? receipts = Enumerable.Repeat( + StatusMessageSerializer statusMessageSerializer = new(); + ReceiptsMessageSerializer receiptMessageSerializer + = new(MainnetSpecProvider.Instance); + MessageSerializationService serializationService = new(); + serializationService.Register(statusMessageSerializer); + serializationService.Register(receiptMessageSerializer); + + Eth63ProtocolHandler protocolHandler = new( + ctx.Session, + serializationService, + Substitute.For(), + Substitute.For(), + Substitute.For(), + Substitute.For(), + LimboLogs.Instance); + + var receipts = Enumerable.Repeat( Enumerable.Repeat(Build.A.Receipt.WithAllFieldsFilled.TestObject, 100).ToArray(), 1000).ToArray(); // TxReceipt[1000][100] + StatusMessage statusMessage = new(); + Packet statusPacket = + new("eth", Eth62MessageCode.Status, statusMessageSerializer.Serialize(statusMessage)); + ReceiptsMessage receiptsMsg = new(receipts); Packet receiptsPacket = - new("eth", Eth63MessageCode.Receipts, ctx._receiptMessageSerializer.Serialize(receiptsMsg)); + new("eth", Eth63MessageCode.Receipts, receiptMessageSerializer.Serialize(receiptsMsg)); - Task task = ctx.ProtocolHandler.GetReceipts( + protocolHandler.HandleMessage(statusPacket); + Task task = protocolHandler.GetReceipts( Enumerable.Repeat(Keccak.Zero, 1000).ToArray(), CancellationToken.None); - ctx.ProtocolHandler.HandleMessage(receiptsPacket); + protocolHandler.HandleMessage(receiptsPacket); var result = await task; result.Should().HaveCount(1000); } - [Test] - public async Task Limit_receipt_request() - { - Context ctx = new(); - TxReceipt[] oneBlockReceipt = Enumerable.Repeat(Build.A.Receipt.WithAllFieldsFilled.TestObject, 100).ToArray(); - Packet smallReceiptsPacket = - new("eth", Eth63MessageCode.Receipts, ctx._receiptMessageSerializer.Serialize( - new(Enumerable.Repeat(oneBlockReceipt, 10).ToArray()) - )); - Packet largeReceiptsPacket = - new("eth", Eth63MessageCode.Receipts, ctx._receiptMessageSerializer.Serialize( - new(Enumerable.Repeat(oneBlockReceipt, 1000).ToArray()) - )); - - GetReceiptsMessage? receiptsMessage = null; - - ctx.Session - .When(session => session.DeliverMessage(Arg.Any())) - .Do((info => receiptsMessage = (GetReceiptsMessage)info[0])); - - Task receiptsTask = ctx.ProtocolHandler.GetReceipts( - Enumerable.Repeat(Keccak.Zero, 1000).ToArray(), - CancellationToken.None); - - ctx.ProtocolHandler.HandleMessage(smallReceiptsPacket); - await receiptsTask; - - Assert.That(receiptsMessage?.Hashes?.Count, Is.EqualTo(8)); - - receiptsTask = ctx.ProtocolHandler.GetReceipts( - Enumerable.Repeat(Keccak.Zero, 1000).ToArray(), - CancellationToken.None); - - ctx.ProtocolHandler.HandleMessage(largeReceiptsPacket); - await receiptsTask; - - Assert.That(receiptsMessage?.Hashes?.Count, Is.EqualTo(12)); - - // Back to 10 - receiptsTask = ctx.ProtocolHandler.GetReceipts( - Enumerable.Repeat(Keccak.Zero, 1000).ToArray(), - CancellationToken.None); - - ctx.ProtocolHandler.HandleMessage(smallReceiptsPacket); - await receiptsTask; - - Assert.That(receiptsMessage?.Hashes?.Count, Is.EqualTo(8)); - } - [Test] public void Will_not_serve_receipts_requests_above_512() { Context ctx = new(); + StatusMessageSerializer statusMessageSerializer = new(); + ReceiptsMessageSerializer receiptMessageSerializer + = new(MainnetSpecProvider.Instance); + GetReceiptsMessageSerializer getReceiptMessageSerializer + = new(); + MessageSerializationService serializationService = new(); + serializationService.Register(statusMessageSerializer); + serializationService.Register(receiptMessageSerializer); + serializationService.Register(getReceiptMessageSerializer); + + ISyncServer syncServer = Substitute.For(); + Eth63ProtocolHandler protocolHandler = new( + ctx.Session, + serializationService, + Substitute.For(), + syncServer, + Substitute.For(), + Substitute.For(), + LimboLogs.Instance); + + StatusMessage statusMessage = new(); + Packet statusPacket = + new("eth", Eth62MessageCode.Status, statusMessageSerializer.Serialize(statusMessage)); + GetReceiptsMessage getReceiptsMessage = new( Enumerable.Repeat(Keccak.Zero, 513).ToArray()); Packet getReceiptsPacket = - new("eth", Eth63MessageCode.GetReceipts, ctx._getReceiptMessageSerializer.Serialize(getReceiptsMessage)); + new("eth", Eth63MessageCode.GetReceipts, getReceiptMessageSerializer.Serialize(getReceiptsMessage)); - Assert.Throws(() => ctx.ProtocolHandler.HandleMessage(getReceiptsPacket)); + protocolHandler.HandleMessage(statusPacket); + Assert.Throws(() => protocolHandler.HandleMessage(getReceiptsPacket)); } [Test] public void Will_not_send_messages_larger_than_2MB() { Context ctx = new(); - ctx.SyncServer.GetReceipts(Arg.Any()).Returns( + StatusMessageSerializer statusMessageSerializer = new(); + ReceiptsMessageSerializer receiptMessageSerializer + = new(MainnetSpecProvider.Instance); + GetReceiptsMessageSerializer getReceiptMessageSerializer + = new(); + MessageSerializationService serializationService = new(); + serializationService.Register(statusMessageSerializer); + serializationService.Register(receiptMessageSerializer); + serializationService.Register(getReceiptMessageSerializer); + + ISyncServer syncServer = Substitute.For(); + Eth63ProtocolHandler protocolHandler = new( + ctx.Session, + serializationService, + Substitute.For(), + syncServer, + Substitute.For(), + Substitute.For(), + LimboLogs.Instance); + + syncServer.GetReceipts(Arg.Any()).Returns( Enumerable.Repeat(Build.A.Receipt.WithAllFieldsFilled.TestObject, 512).ToArray()); + StatusMessage statusMessage = new(); + Packet statusPacket = + new("eth", Eth62MessageCode.Status, statusMessageSerializer.Serialize(statusMessage)); + GetReceiptsMessage getReceiptsMessage = new( Enumerable.Repeat(Keccak.Zero, 512).ToArray()); Packet getReceiptsPacket = - new("eth", Eth63MessageCode.GetReceipts, ctx._getReceiptMessageSerializer.Serialize(getReceiptsMessage)); + new("eth", Eth63MessageCode.GetReceipts, getReceiptMessageSerializer.Serialize(getReceiptsMessage)); - ctx.ProtocolHandler.HandleMessage(getReceiptsPacket); + protocolHandler.HandleMessage(statusPacket); + protocolHandler.HandleMessage(getReceiptsPacket); ctx.Session.Received().DeliverMessage(Arg.Is(r => r.TxReceipts.Length == 14)); } private class Context { - readonly MessageSerializationService _serializationService = new(); - private readonly StatusMessageSerializer _statusMessageSerializer = new(); - public readonly ReceiptsMessageSerializer _receiptMessageSerializer = new(MainnetSpecProvider.Instance); - public readonly GetReceiptsMessageSerializer _getReceiptMessageSerializer = new(); - - public ISession Session { get; } - - private ISyncServer? _syncServer; - public ISyncServer SyncServer => _syncServer ??= Substitute.For(); - - private Eth63ProtocolHandler? _protocolHandler; - public Eth63ProtocolHandler ProtocolHandler - { - get - { - if (_protocolHandler != null) - { - return _protocolHandler; - } - - _protocolHandler = new Eth63ProtocolHandler( - Session, - _serializationService, - Substitute.For(), - SyncServer, - Substitute.For(), - Substitute.For(), - LimboLogs.Instance); - - StatusMessage statusMessage = new(); - Packet statusPacket = - new("eth", Eth62MessageCode.Status, _statusMessageSerializer.Serialize(statusMessage)); - _protocolHandler.HandleMessage(statusPacket); - - return _protocolHandler; - } - } + public ISession Session { get; set; } public Context() { Session = Substitute.For(); Session.Node.Returns(new Node(TestItem.PublicKeyA, "127.0.0.1", 1000, true)); NetworkDiagTracer.IsEnabled = true; - - _serializationService.Register(_statusMessageSerializer); - _serializationService.Register(_receiptMessageSerializer); - _serializationService.Register(_getReceiptMessageSerializer); } } } diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/GetNodeDataMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/GetNodeDataMessageSerializerTests.cs index 214960c9924..70652c8c9bc 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/GetNodeDataMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/GetNodeDataMessageSerializerTests.cs @@ -4,6 +4,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P.Subprotocols.Eth.V63.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V63 diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/NodeDataMessageSeralizerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/NodeDataMessageSeralizerTests.cs index d0878927523..b256c5284e4 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/NodeDataMessageSeralizerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/NodeDataMessageSeralizerTests.cs @@ -4,6 +4,7 @@ using System; using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P.Subprotocols.Eth.V63.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V63 diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/ReceiptsMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/ReceiptsMessageSerializerTests.cs index 41265df8fc4..490dae56dcc 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/ReceiptsMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/ReceiptsMessageSerializerTests.cs @@ -20,7 +20,7 @@ public class ReceiptsMessageSerializerTests private static void Test(TxReceipt[][] txReceipts) { ReceiptsMessage message = new(txReceipts); - ReceiptsMessageSerializer serializer = new(MainnetSpecProvider.Instance); + ReceiptsMessageSerializer serializer = new(RopstenSpecProvider.Instance); var serialized = serializer.Serialize(message); ReceiptsMessage deserialized = serializer.Deserialize(serialized); @@ -61,8 +61,8 @@ private static void Test(TxReceipt[][] txReceipts) Assert.That(deserialized.TxReceipts[i][j].GasUsedTotal, Is.EqualTo(txReceipts[i][j].GasUsedTotal), $"receipts[{i}][{j}].GasUsedTotal"); if (!txReceipts[i][j].SkipStateAndStatusInRlp) { - Assert.That(deserialized.TxReceipts[i][j].StatusCode, Is.EqualTo(txReceipts[i][j].BlockNumber < MainnetSpecProvider.ByzantiumBlockNumber ? 0 : txReceipts[i][j].StatusCode), $"receipts[{i}][{j}].StatusCode"); - Assert.That(deserialized.TxReceipts[i][j].PostTransactionState, Is.EqualTo(txReceipts[i][j].BlockNumber < MainnetSpecProvider.ByzantiumBlockNumber ? txReceipts[i][j].PostTransactionState : null), $"receipts[{i}][{j}].PostTransactionState"); + Assert.That(deserialized.TxReceipts[i][j].StatusCode, Is.EqualTo(txReceipts[i][j].BlockNumber < RopstenSpecProvider.ByzantiumBlockNumber ? 0 : txReceipts[i][j].StatusCode), $"receipts[{i}][{j}].StatusCode"); + Assert.That(deserialized.TxReceipts[i][j].PostTransactionState, Is.EqualTo(txReceipts[i][j].BlockNumber < RopstenSpecProvider.ByzantiumBlockNumber ? txReceipts[i][j].PostTransactionState : null), $"receipts[{i}][{j}].PostTransactionState"); } } } @@ -92,7 +92,7 @@ public void Roundtrip_with_IgnoreOutputs() [Test] public void Roundtrip_with_eip658() { - TxReceipt[][] data = { new[] { Build.A.Receipt.WithAllFieldsFilled.TestObject, Build.A.Receipt.WithAllFieldsFilled.TestObject }, new[] { Build.A.Receipt.WithAllFieldsFilled.WithBlockNumber(MainnetSpecProvider.ConstantinopleFixBlockNumber).TestObject, Build.A.Receipt.WithAllFieldsFilled.TestObject } }; + TxReceipt[][] data = { new[] { Build.A.Receipt.WithAllFieldsFilled.TestObject, Build.A.Receipt.WithAllFieldsFilled.TestObject }, new[] { Build.A.Receipt.WithAllFieldsFilled.WithBlockNumber(RopstenSpecProvider.ConstantinopleBlockNumber).TestObject, Build.A.Receipt.WithAllFieldsFilled.TestObject } }; Test(data); } @@ -112,7 +112,7 @@ public void Roundtrip_with_nulls() [Test] public void Deserialize_empty() { - ReceiptsMessageSerializer serializer = new(MainnetSpecProvider.Instance); + ReceiptsMessageSerializer serializer = new(RopstenSpecProvider.Instance); serializer.Deserialize(new byte[0]).TxReceipts.Should().HaveCount(0); } @@ -121,7 +121,7 @@ public void Deserialize_non_empty_but_bytebuffer_starts_with_empty() { TxReceipt[][] data = { new[] { Build.A.Receipt.WithAllFieldsFilled.TestObject, Build.A.Receipt.WithAllFieldsFilled.WithBlockNumber(0).TestObject }, new[] { Build.A.Receipt.WithAllFieldsFilled.TestObject, Build.A.Receipt.WithAllFieldsFilled.TestObject } }; ReceiptsMessage message = new(data); - ReceiptsMessageSerializer serializer = new(MainnetSpecProvider.Instance); + ReceiptsMessageSerializer serializer = new(RopstenSpecProvider.Instance); IByteBuffer buffer = Unpooled.Buffer(serializer.GetLength(message, out int _) + 1); buffer.WriteByte(Rlp.OfEmptySequence[0]); @@ -137,7 +137,7 @@ public void Deserialize_non_empty_but_bytebuffer_starts_with_empty() public void Roundtrip_mainnet_sample() { byte[] bytes = Bytes.FromHexString("f9012ef9012bf90128a08ccc6709a5df7acef07f97c5681356b6c37cfac15b554aff68e986f57116df2e825208b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0"); - ReceiptsMessageSerializer serializer = new(MainnetSpecProvider.Instance); + ReceiptsMessageSerializer serializer = new(RopstenSpecProvider.Instance); ReceiptsMessage message = serializer.Deserialize(bytes); byte[] serialized = serializer.Serialize(message); Assert.That(serialized, Is.EqualTo(bytes)); diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandlerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandlerTests.cs index d5c78ca5124..8a84a1907a6 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandlerTests.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Net; -using DotNetty.Buffers; using FluentAssertions; using Nethermind.Consensus; using Nethermind.Core; @@ -15,11 +14,9 @@ using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Network.P2P; -using Nethermind.Network.P2P.Subprotocols.Eth; using Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages; using Nethermind.Network.P2P.Subprotocols.Eth.V65; using Nethermind.Network.P2P.Subprotocols.Eth.V65.Messages; -using Nethermind.Network.Rlpx; using Nethermind.Network.Test.Builders; using Nethermind.Stats; using Nethermind.Stats.Model; @@ -33,15 +30,14 @@ namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V65 [TestFixture, Parallelizable(ParallelScope.Self)] public class Eth65ProtocolHandlerTests { - private ISession _session = null!; - private IMessageSerializationService _svc = null!; - private ISyncServer _syncManager = null!; - private ITxPool _transactionPool = null!; - private IPooledTxsRequestor _pooledTxsRequestor = null!; - private ISpecProvider _specProvider = null!; - private Block _genesisBlock = null!; - private Eth65ProtocolHandler _handler = null!; - private ITxGossipPolicy _txGossipPolicy = null!; + private ISession _session; + private IMessageSerializationService _svc; + private ISyncServer _syncManager; + private ITxPool _transactionPool; + private IPooledTxsRequestor _pooledTxsRequestor; + private ISpecProvider _specProvider; + private Block _genesisBlock; + private Eth65ProtocolHandler _handler; [SetUp] public void Setup() @@ -61,9 +57,6 @@ public void Setup() _syncManager.Head.Returns(_genesisBlock.Header); _syncManager.Genesis.Returns(_genesisBlock.Header); ITimerFactory timerFactory = Substitute.For(); - _txGossipPolicy = Substitute.For(); - _txGossipPolicy.ShouldListenToGossippedTransactions.Returns(true); - _txGossipPolicy.ShouldGossipTransaction(Arg.Any()).Returns(true); _handler = new Eth65ProtocolHandler( _session, _svc, @@ -73,8 +66,7 @@ public void Setup() _pooledTxsRequestor, Policy.FullGossip, new ForkInfo(_specProvider, _genesisBlock.Header.Hash!), - LimboLogs.Instance, - _txGossipPolicy); + LimboLogs.Instance); _handler.Init(); } @@ -174,34 +166,5 @@ public void should_send_single_requested_PooledTransaction_even_if_exceed_MaxPac PooledTransactionsMessage response = _handler.FulfillPooledTransactionsRequest(request, new List()); response.Transactions.Count.Should().Be(numberOfTxsInOneMsg); } - - [Test] - public void should_handle_NewPooledTransactionHashesMessage([Values(true, false)] bool canGossipTransactions) - { - _txGossipPolicy.ShouldListenToGossippedTransactions.Returns(canGossipTransactions); - NewPooledTransactionHashesMessage msg = new(new[] { TestItem.KeccakA, TestItem.KeccakB }); - IMessageSerializationService serializationService = Build.A.SerializationService().WithEth65().TestObject; - - HandleIncomingStatusMessage(); - HandleZeroMessage(msg, Eth65MessageCode.NewPooledTransactionHashes); - - _pooledTxsRequestor.Received(canGossipTransactions ? 1 : 0).RequestTransactions(Arg.Any>(), Arg.Any>()); - } - - private void HandleZeroMessage(T msg, int messageCode) where T : MessageBase - { - IByteBuffer getBlockHeadersPacket = _svc.ZeroSerialize(msg); - getBlockHeadersPacket.ReadByte(); - _handler.HandleMessage(new ZeroPacket(getBlockHeadersPacket) { PacketType = (byte)messageCode }); - } - - private void HandleIncomingStatusMessage() - { - var statusMsg = new StatusMessage { GenesisHash = _genesisBlock.Hash, BestHash = _genesisBlock.Hash }; - - IByteBuffer statusPacket = _svc.ZeroSerialize(statusMsg); - statusPacket.ReadByte(); - _handler.HandleMessage(new ZeroPacket(statusPacket) { PacketType = 0 }); - } } } diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/GetPooledTransactionsMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/GetPooledTransactionsMessageSerializerTests.cs index 4591d96b702..611c726ad56 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/GetPooledTransactionsMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/GetPooledTransactionsMessageSerializerTests.cs @@ -4,6 +4,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P.Subprotocols.Eth.V65.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V65 diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/NewPooledTransactionHashesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/NewPooledTransactionHashesMessageSerializerTests.cs index e090c360dfc..7610292bc9f 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/NewPooledTransactionHashesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/NewPooledTransactionHashesMessageSerializerTests.cs @@ -4,6 +4,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P.Subprotocols.Eth.V65.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V65 diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/PooledTransactionsMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/PooledTransactionsMessageSerializerTests.cs index 9c0f815f3a7..d7af4f85009 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/PooledTransactionsMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/PooledTransactionsMessageSerializerTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using DotNetty.Buffers; +using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/PooledTxsRequestorTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/PooledTxsRequestorTests.cs index 0bac0287522..22f5e886fae 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/PooledTxsRequestorTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/PooledTxsRequestorTests.cs @@ -7,7 +7,7 @@ using FluentAssertions; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; -using Nethermind.Network.P2P.Subprotocols.Eth; +using Nethermind.Network.P2P.Subprotocols.Eth.V65; using Nethermind.Network.P2P.Subprotocols.Eth.V65.Messages; using Nethermind.TxPool; using NSubstitute; diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/BlockBodiesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/BlockBodiesMessageSerializerTests.cs index ff1266c2b12..f22f5aa0afc 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/BlockBodiesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/BlockBodiesMessageSerializerTests.cs @@ -65,7 +65,7 @@ public void RoundTrip() var ethMessage = new Network.P2P.Subprotocols.Eth.V62.Messages.BlockBodiesMessage { - Bodies = new(new[] { new BlockBody(new[] { tx1, tx2 }, new[] { header }) }) + Bodies = new[] { new BlockBody(new[] { tx1, tx2 }, new[] { header }) } }; BlockBodiesMessage message = new(1111, ethMessage); diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/BlockHeadersMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/BlockHeadersMessageSerializerTests.cs index c2321388032..39673e1ee76 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/BlockHeadersMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/BlockHeadersMessageSerializerTests.cs @@ -5,6 +5,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P.Subprotocols.Eth.V66.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V66 diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/Eth66ProtocolHandlerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/Eth66ProtocolHandlerTests.cs index 4598b159ba6..3fdb89f1e2e 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/Eth66ProtocolHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/Eth66ProtocolHandlerTests.cs @@ -6,6 +6,7 @@ using System.Threading; using DotNetty.Buffers; using FluentAssertions; +using Nethermind.Blockchain; using Nethermind.Blockchain.Synchronization; using Nethermind.Consensus; using Nethermind.Core; @@ -17,10 +18,8 @@ using Nethermind.Logging; using Nethermind.Network.P2P; using Nethermind.Network.P2P.Subprotocols; -using Nethermind.Network.P2P.Subprotocols.Eth; using Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages; using Nethermind.Network.P2P.Subprotocols.Eth.V65; -using Nethermind.Network.P2P.Subprotocols.Eth.V65.Messages; using Nethermind.Network.P2P.Subprotocols.Eth.V66; using Nethermind.Network.P2P.Subprotocols.Eth.V66.Messages; using Nethermind.Network.Rlpx; @@ -47,16 +46,15 @@ namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V66 [TestFixture, Parallelizable(ParallelScope.Self)] public class Eth66ProtocolHandlerTests { - private ISession _session = null!; - private IMessageSerializationService _svc = null!; - private ISyncServer _syncManager = null!; - private ITxPool _transactionPool = null!; - private IPooledTxsRequestor _pooledTxsRequestor = null!; - private IGossipPolicy _gossipPolicy = null!; - private ITimerFactory _timerFactory = null!; - private ISpecProvider _specProvider = null!; - private Block _genesisBlock = null!; - private Eth66ProtocolHandler _handler = null!; + private ISession _session; + private IMessageSerializationService _svc; + private ISyncServer _syncManager; + private ITxPool _transactionPool; + private IPooledTxsRequestor _pooledTxsRequestor; + private IGossipPolicy _gossipPolicy; + private ISpecProvider _specProvider; + private Block _genesisBlock; + private Eth66ProtocolHandler _handler; [SetUp] public void Setup() @@ -76,11 +74,11 @@ public void Setup() _genesisBlock = Build.A.Block.Genesis.TestObject; _syncManager.Head.Returns(_genesisBlock.Header); _syncManager.Genesis.Returns(_genesisBlock.Header); - _timerFactory = Substitute.For(); + ITimerFactory timerFactory = Substitute.For(); _handler = new Eth66ProtocolHandler( _session, _svc, - new NodeStatsManager(_timerFactory, LimboLogs.Instance), + new NodeStatsManager(timerFactory, LimboLogs.Instance), _syncManager, _transactionPool, _pooledTxsRequestor, @@ -287,42 +285,6 @@ public void Should_throw_when_receiving_unrequested_receipts() act.Should().Throw(); } - - [TestCase(0, 0)] - [TestCase(1, 1)] - [TestCase(256, 1)] - [TestCase(257, 2)] - [TestCase(1000, 4)] - [TestCase(10000, 40)] - public void should_request_in_GetPooledTransactionsMessage_up_to_256_txs(int numberOfTransactions, int expectedNumberOfMessages) - { - const int maxNumberOfTxsInOneMsg = 256; - - _handler = new Eth66ProtocolHandler( - _session, - _svc, - new NodeStatsManager(_timerFactory, LimboLogs.Instance), - _syncManager, - _transactionPool, - new PooledTxsRequestor(_transactionPool), - _gossipPolicy, - new ForkInfo(_specProvider, _genesisBlock.Header.Hash!), - LimboLogs.Instance); - - List hashes = new(numberOfTransactions); - - for (int i = 0; i < numberOfTransactions; i++) - { - hashes.Add(new Keccak(i.ToString("X64"))); - } - - NewPooledTransactionHashesMessage hashesMsg = new(hashes); - HandleIncomingStatusMessage(); - HandleZeroMessage(hashesMsg, Eth65MessageCode.NewPooledTransactionHashes); - - _session.Received(expectedNumberOfMessages).DeliverMessage(Arg.Is(m => m.EthMessage.Hashes.Count == maxNumberOfTxsInOneMsg || m.EthMessage.Hashes.Count == numberOfTransactions % maxNumberOfTxsInOneMsg)); - } - private void HandleZeroMessage(T msg, int messageCode) where T : MessageBase { IByteBuffer getBlockHeadersPacket = _svc.ZeroSerialize(msg); diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetBlockBodiesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetBlockBodiesMessageSerializerTests.cs index 5646f3e6389..4302fef1a04 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetBlockBodiesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetBlockBodiesMessageSerializerTests.cs @@ -3,6 +3,7 @@ using Nethermind.Core.Crypto; using Nethermind.Network.P2P.Subprotocols.Eth.V66.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V66 diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetBlockHeadersMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetBlockHeadersMessageSerializerTests.cs index e516b995911..c2d76858459 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetBlockHeadersMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetBlockHeadersMessageSerializerTests.cs @@ -3,6 +3,7 @@ using Nethermind.Core.Crypto; using Nethermind.Network.P2P.Subprotocols.Eth.V66.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V66 diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetNodeDataMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetNodeDataMessageSerializerTests.cs index 64292c93303..59ae457690a 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetNodeDataMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetNodeDataMessageSerializerTests.cs @@ -3,6 +3,7 @@ using Nethermind.Core.Crypto; using Nethermind.Network.P2P.Subprotocols.Eth.V66.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V66 diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetPooledTransactionsSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetPooledTransactionsSerializerTests.cs index ab53065a200..3b26af56ba8 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetPooledTransactionsSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetPooledTransactionsSerializerTests.cs @@ -3,6 +3,7 @@ using Nethermind.Core.Crypto; using Nethermind.Network.P2P.Subprotocols.Eth.V66.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V66 diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetReceiptsMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetReceiptsMessageSerializerTests.cs index c84560d1401..0efaab06d90 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetReceiptsMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/GetReceiptsMessageSerializerTests.cs @@ -3,6 +3,7 @@ using Nethermind.Core.Crypto; using Nethermind.Network.P2P.Subprotocols.Eth.V66.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V66 diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/NodeDataMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/NodeDataMessageSerializerTests.cs index 09afa156608..bf3740958c8 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/NodeDataMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/NodeDataMessageSerializerTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Network.P2P.Subprotocols.Eth.V66.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V66 diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/PooledTransactionsMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/PooledTransactionsMessageSerializerTests.cs index e765b0a0d8d..f2d5d152146 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/PooledTransactionsMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/PooledTransactionsMessageSerializerTests.cs @@ -4,6 +4,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Network.P2P.Subprotocols.Eth.V66.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V66 diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/ReceiptsMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/ReceiptsMessageSerializerTests.cs index 47df99c46a3..dc16ebe2e29 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/ReceiptsMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V66/ReceiptsMessageSerializerTests.cs @@ -6,6 +6,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Network.P2P.Subprotocols.Eth.V66.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using Nethermind.Specs; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V67/Eth67ProtocolHandlerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V67/Eth67ProtocolHandlerTests.cs index 2c2f2bb3ebc..8a8b57bf793 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V67/Eth67ProtocolHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V67/Eth67ProtocolHandlerTests.cs @@ -4,6 +4,7 @@ using System.Net; using DotNetty.Buffers; using FluentAssertions; +using Nethermind.Blockchain; using Nethermind.Consensus; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -13,9 +14,9 @@ using Nethermind.Logging; using Nethermind.Network.P2P; using Nethermind.Network.P2P.Subprotocols; -using Nethermind.Network.P2P.Subprotocols.Eth; using Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages; using Nethermind.Network.P2P.Subprotocols.Eth.V63.Messages; +using Nethermind.Network.P2P.Subprotocols.Eth.V65; using Nethermind.Network.P2P.Subprotocols.Eth.V66; using Nethermind.Network.P2P.Subprotocols.Eth.V67; using Nethermind.Network.Rlpx; @@ -32,15 +33,15 @@ namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V67; [TestFixture, Parallelizable(ParallelScope.Self)] public class Eth67ProtocolHandlerTests { - private ISession _session = null!; - private IMessageSerializationService _svc = null!; - private ISyncServer _syncManager = null!; - private ITxPool _transactionPool = null!; - private IPooledTxsRequestor _pooledTxsRequestor = null!; - private IGossipPolicy _gossipPolicy = null!; - private ISpecProvider _specProvider = null!; - private Block _genesisBlock = null!; - private Eth66ProtocolHandler _handler = null!; + private ISession _session; + private IMessageSerializationService _svc; + private ISyncServer _syncManager; + private ITxPool _transactionPool; + private IPooledTxsRequestor _pooledTxsRequestor; + private IGossipPolicy _gossipPolicy; + private ISpecProvider _specProvider; + private Block _genesisBlock; + private Eth66ProtocolHandler _handler; [SetUp] public void Setup() diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandlerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandlerTests.cs index a61f602f6d2..56053c08923 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandlerTests.cs @@ -16,8 +16,8 @@ using Nethermind.Logging; using Nethermind.Network.P2P; using Nethermind.Network.P2P.Subprotocols; -using Nethermind.Network.P2P.Subprotocols.Eth; using Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages; +using Nethermind.Network.P2P.Subprotocols.Eth.V65; using Nethermind.Network.P2P.Subprotocols.Eth.V66.Messages; using Nethermind.Network.P2P.Subprotocols.Eth.V68; using Nethermind.Network.P2P.Subprotocols.Eth.V68.Messages; @@ -35,17 +35,15 @@ namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V68; public class Eth68ProtocolHandlerTests { - private ISession _session = null!; - private IMessageSerializationService _svc = null!; - private ISyncServer _syncManager = null!; - private ITxPool _transactionPool = null!; - private IPooledTxsRequestor _pooledTxsRequestor = null!; - private IGossipPolicy _gossipPolicy = null!; - private ISpecProvider _specProvider = null!; - private Block _genesisBlock = null!; - private Eth68ProtocolHandler _handler = null!; - private ITxGossipPolicy _txGossipPolicy = null!; - private ITimerFactory _timerFactory = null!; + private ISession _session; + private IMessageSerializationService _svc; + private ISyncServer _syncManager; + private ITxPool _transactionPool; + private IPooledTxsRequestor _pooledTxsRequestor; + private IGossipPolicy _gossipPolicy; + private ISpecProvider _specProvider; + private Block _genesisBlock; + private Eth68ProtocolHandler _handler; [SetUp] public void Setup() @@ -65,21 +63,17 @@ public void Setup() _genesisBlock = Build.A.Block.Genesis.TestObject; _syncManager.Head.Returns(_genesisBlock.Header); _syncManager.Genesis.Returns(_genesisBlock.Header); - _timerFactory = Substitute.For(); - _txGossipPolicy = Substitute.For(); - _txGossipPolicy.ShouldListenToGossippedTransactions.Returns(true); - _txGossipPolicy.ShouldGossipTransaction(Arg.Any()).Returns(true); + ITimerFactory timerFactory = Substitute.For(); _handler = new Eth68ProtocolHandler( _session, _svc, - new NodeStatsManager(_timerFactory, LimboLogs.Instance), + new NodeStatsManager(timerFactory, LimboLogs.Instance), _syncManager, _transactionPool, _pooledTxsRequestor, _gossipPolicy, - new ForkInfo(_specProvider, _genesisBlock.Header.Hash!), - LimboLogs.Instance, - _txGossipPolicy); + new ForkInfo(_specProvider, _genesisBlock.Header.Hash), + LimboLogs.Instance); _handler.Init(); } @@ -102,20 +96,20 @@ public void Metadata_correct() _handler.HeadNumber.Should().Be(0); } - [Test] - public void Can_handle_NewPooledTransactions_message([Values(0, 1, 2, 100)] int txCount, [Values(true, false)] bool canGossipTransactions) + [TestCase(0)] + [TestCase(1)] + [TestCase(2)] + [TestCase(100)] + public void Can_handle_NewPooledTransactions_message(int txCount) { - _txGossipPolicy.ShouldListenToGossippedTransactions.Returns(canGossipTransactions); - GenerateLists(txCount, out List types, out List sizes, out List hashes); var msg = new NewPooledTransactionHashesMessage68(types, sizes, hashes); HandleIncomingStatusMessage(); HandleZeroMessage(msg, Eth68MessageCode.NewPooledTransactionHashes); - - _pooledTxsRequestor.Received(canGossipTransactions ? 1 : 0).RequestTransactionsEth68(Arg.Any>(), - Arg.Any>(), Arg.Any>()); + _pooledTxsRequestor.Received().RequestTransactionsEth66(Arg.Any>(), + Arg.Any>()); } [TestCase(true)] @@ -146,14 +140,16 @@ public void Should_process_huge_transaction() Transaction tx = Build.A.Transaction.WithType(TxType.EIP1559).WithData(new byte[2 * 1024 * 1024]) .WithHash(TestItem.KeccakA).TestObject; + TxDecoder txDecoder = new(); + var msg = new NewPooledTransactionHashesMessage68(new[] { (byte)tx.Type }, - new[] { tx.GetLength() }, new[] { tx.Hash }); + new[] { txDecoder.GetLength(tx, RlpBehaviors.None) }, new[] { tx.Hash }); HandleIncomingStatusMessage(); - HandleZeroMessage(msg, Eth68MessageCode.NewPooledTransactionHashes); - _pooledTxsRequestor.Received(1).RequestTransactionsEth68(Arg.Any>(), - Arg.Any>(), Arg.Any>()); + HandleZeroMessage(msg, Eth68MessageCode.NewPooledTransactionHashes); + _pooledTxsRequestor.Received().RequestTransactionsEth66(Arg.Any>(), + Arg.Any>()); } [TestCase(1)] @@ -193,42 +189,6 @@ public void should_send_more_than_MaxCount_hashes_in_more_than_one_NewPooledTran _session.Received(messagesCount).DeliverMessage(Arg.Is(m => m.Hashes.Count == NewPooledTransactionHashesMessage68.MaxCount || m.Hashes.Count == nonFullMsgTxsCount)); } - [Test] - public void should_divide_GetPooledTransactionsMessage_if_max_message_size_is_exceeded([Values(0, 1, 100, 10_000)] int numberOfTransactions, [Values(97, TransactionsMessage.MaxPacketSize, 200_000)] int sizeOfOneTx) - { - _handler = new Eth68ProtocolHandler( - _session, - _svc, - new NodeStatsManager(_timerFactory, LimboLogs.Instance), - _syncManager, - _transactionPool, - new PooledTxsRequestor(_transactionPool), - _gossipPolicy, - new ForkInfo(_specProvider, _genesisBlock.Header.Hash!), - LimboLogs.Instance, - _txGossipPolicy); - - int maxNumberOfTxsInOneMsg = sizeOfOneTx < TransactionsMessage.MaxPacketSize ? TransactionsMessage.MaxPacketSize / sizeOfOneTx : 1; - int messagesCount = numberOfTransactions / maxNumberOfTxsInOneMsg + (numberOfTransactions % maxNumberOfTxsInOneMsg == 0 ? 0 : 1); - - List types = new(numberOfTransactions); - List sizes = new(numberOfTransactions); - List hashes = new(numberOfTransactions); - - for (int i = 0; i < numberOfTransactions; i++) - { - types.Add(0); - sizes.Add(sizeOfOneTx); - hashes.Add(new Keccak(i.ToString("X64"))); - } - - NewPooledTransactionHashesMessage68 hashesMsg = new(types, sizes, hashes); - HandleIncomingStatusMessage(); - HandleZeroMessage(hashesMsg, Eth68MessageCode.NewPooledTransactionHashes); - - _session.Received(messagesCount).DeliverMessage(Arg.Is(m => m.EthMessage.Hashes.Count == maxNumberOfTxsInOneMsg || m.EthMessage.Hashes.Count == numberOfTransactions % maxNumberOfTxsInOneMsg)); - } - private void HandleIncomingStatusMessage() { var statusMsg = new StatusMessage(); diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/AnnounceMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/AnnounceMessageSerializerTests.cs index 8e9058e17b4..b14d899fa97 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/AnnounceMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/AnnounceMessageSerializerTests.cs @@ -3,6 +3,7 @@ using Nethermind.Core.Crypto; using Nethermind.Network.P2P.Subprotocols.Les.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Les diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/BlockBodiesSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/BlockBodiesSerializerTests.cs index 9a744bd87f1..30ecae444f8 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/BlockBodiesSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/BlockBodiesSerializerTests.cs @@ -6,6 +6,7 @@ using Nethermind.Crypto; using Nethermind.Logging; using Nethermind.Network.P2P.Subprotocols.Les.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using Nethermind.Specs; using NUnit.Framework; @@ -19,10 +20,10 @@ public void RoundTrip() { BlockHeader header = Build.A.BlockHeader.TestObject; Address to = Build.An.Address.FromNumber(1).TestObject; - Transaction tx = Build.A.Transaction.WithTo(to).SignedAndResolved(new EthereumEcdsa(MainnetSpecProvider.Instance.ChainId, LimboLogs.Instance), TestItem.PrivateKeyA).TestObject; + Transaction tx = Build.A.Transaction.WithTo(to).SignedAndResolved(new EthereumEcdsa(RopstenSpecProvider.Instance.ChainId, LimboLogs.Instance), TestItem.PrivateKeyA).TestObject; tx.SenderAddress = null; var ethMessage = new Network.P2P.Subprotocols.Eth.V62.Messages.BlockBodiesMessage(); - ethMessage.Bodies = new(new[] { new BlockBody(new[] { tx }, new[] { header }) }); + ethMessage.Bodies = new[] { new BlockBody(new[] { tx }, new[] { header }) }; BlockBodiesMessage message = new(ethMessage, 1, 1000); diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/BlockHeadersMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/BlockHeadersMessageSerializerTests.cs index 80997846e7b..cc7d805cb1d 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/BlockHeadersMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/BlockHeadersMessageSerializerTests.cs @@ -3,6 +3,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P.Subprotocols.Les.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Les diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/ContractCodesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/ContractCodesMessageSerializerTests.cs index 0cf3951977b..71d4f3a479e 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/ContractCodesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/ContractCodesMessageSerializerTests.cs @@ -3,6 +3,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P.Subprotocols.Les.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Les diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetBlockBodiesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetBlockBodiesMessageSerializerTests.cs index 444d47a032b..10d9ec020b7 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetBlockBodiesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetBlockBodiesMessageSerializerTests.cs @@ -3,6 +3,7 @@ using Nethermind.Core.Crypto; using Nethermind.Network.P2P.Subprotocols.Les.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Les diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetBlockHeadersMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetBlockHeadersMessageSerializerTests.cs index bbef9b11c24..e8d0ba35fd7 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetBlockHeadersMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetBlockHeadersMessageSerializerTests.cs @@ -3,6 +3,7 @@ using Nethermind.Core.Crypto; using Nethermind.Network.P2P.Subprotocols.Les.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Les diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetContractCodesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetContractCodesMessageSerializerTests.cs index 9dc8537ad4d..6e45cf25be4 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetContractCodesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetContractCodesMessageSerializerTests.cs @@ -4,6 +4,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P.Subprotocols.Les; using Nethermind.Network.P2P.Subprotocols.Les.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Les diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetHelperTrieProofsMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetHelperTrieProofsMessageSerializerTests.cs index 778577186e0..546f9194fe3 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetHelperTrieProofsMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetHelperTrieProofsMessageSerializerTests.cs @@ -4,6 +4,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P.Subprotocols.Les; using Nethermind.Network.P2P.Subprotocols.Les.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Les diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetReceiptsMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetReceiptsMessageSerializerTests.cs index 4b1e60d811c..d580669e221 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetReceiptsMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/GetReceiptsMessageSerializerTests.cs @@ -4,6 +4,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P.Subprotocols.Les.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Les diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/HelperTrieProofsMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/HelperTrieProofsMessageSerializerTests.cs index 0386738a5c2..abefb2aebdb 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/HelperTrieProofsMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/HelperTrieProofsMessageSerializerTests.cs @@ -3,6 +3,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P.Subprotocols.Les.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using Nethermind.Serialization.Rlp; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/ReceiptsMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/ReceiptsMessageSerializerTests.cs index 77ddc21fcdf..8d0c5be0b73 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/ReceiptsMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/ReceiptsMessageSerializerTests.cs @@ -19,7 +19,7 @@ public void RoundTrip() Network.P2P.Subprotocols.Eth.V63.Messages.ReceiptsMessage ethMessage = new(data); ReceiptsMessage receiptsMessage = new(ethMessage, 1, 2000); - ReceiptsMessageSerializer serializer = new(MainnetSpecProvider.Instance); + ReceiptsMessageSerializer serializer = new(RopstenSpecProvider.Instance); // Eth.ReceiptsMessageSerializer intentionally excludes fields when deserializing. // I think it's probably best to not copy the test logic checking for this here. diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/StatusMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/StatusMessageSerializerTests.cs index 782bde5af52..e8acd264739 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/StatusMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Les/StatusMessageSerializerTests.cs @@ -4,6 +4,7 @@ using Nethermind.Core.Crypto; using Nethermind.Network.P2P.Subprotocols.Les; using Nethermind.Network.P2P.Subprotocols.Les.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Les diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/AccountRangeMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/AccountRangeMessageSerializerTests.cs index 9d7dcc1932e..fe54e317a52 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/AccountRangeMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/AccountRangeMessageSerializerTests.cs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Microsoft.VisualStudio.TestPlatform.ObjectModel; +using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P; diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializerTests.cs index 5ec057abdf0..4acbefb704f 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializerTests.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using System.Collections.Generic; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P; diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetTrieNodesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetTrieNodesMessageSerializerTests.cs index 7dbde549b58..8d94b4d3e2f 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetTrieNodesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetTrieNodesMessageSerializerTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P; using Nethermind.Network.P2P.Subprotocols.Snap.Messages; diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/StorageRangesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/StorageRangesMessageSerializerTests.cs index beea2969c8b..3fc8f186756 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/StorageRangesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/StorageRangesMessageSerializerTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P; diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Wit/BlockWitnessHashesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Wit/BlockWitnessHashesMessageSerializerTests.cs index 5e0abf68696..c4204f28235 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Wit/BlockWitnessHashesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Wit/BlockWitnessHashesMessageSerializerTests.cs @@ -5,6 +5,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Network.P2P.Subprotocols.Wit.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Wit diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Wit/GetBlockWitnessHashesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Wit/GetBlockWitnessHashesMessageSerializerTests.cs index 025f3922706..b36d7da203a 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Wit/GetBlockWitnessHashesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Wit/GetBlockWitnessHashesMessageSerializerTests.cs @@ -6,6 +6,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Network.P2P.Subprotocols.Wit.Messages; +using Nethermind.Network.Test.P2P.Subprotocols.Eth.V62; using NUnit.Framework; namespace Nethermind.Network.Test.P2P.Subprotocols.Wit diff --git a/src/Nethermind/Nethermind.Network.Test/PeerManagerTests.cs b/src/Nethermind/Nethermind.Network.Test/PeerManagerTests.cs index 8d620e60d57..aaf662ad94b 100644 --- a/src/Nethermind/Nethermind.Network.Test/PeerManagerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/PeerManagerTests.cs @@ -10,17 +10,18 @@ using DotNetty.Transport.Channels; using FluentAssertions; using Nethermind.Config; -using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Core.Timers; using Nethermind.Crypto; using Nethermind.Logging; using Nethermind.Network.Config; +using Nethermind.Network.Discovery; using Nethermind.Network.P2P; using Nethermind.Network.P2P.Analyzers; using Nethermind.Network.P2P.EventArg; using Nethermind.Network.Rlpx; +using Nethermind.Network.StaticNodes; using Nethermind.Stats; using Nethermind.Stats.Model; using NSubstitute; @@ -84,18 +85,12 @@ public async Task Will_connect_to_a_candidate_node() [Test] public async Task Will_only_connect_up_to_max_peers() { - await using Context ctx = new(1); + await using Context ctx = new(); ctx.SetupPersistedPeers(50); ctx.PeerPool.Start(); ctx.PeerManager.Start(); - await Task.Delay(_travisDelayLong); - - int expectedConnectCount = 25; - Assert.That( - () => ctx.RlpxPeer.ConnectAsyncCallsCount, - Is - .InRange(expectedConnectCount, expectedConnectCount + 1) - .After(_travisDelay * 10, 10)); + await Task.Delay(_travisDelayLong * 10); + Assert.That(ctx.RlpxPeer.ConnectAsyncCallsCount, Is.EqualTo(25)); } [Test] @@ -266,11 +261,11 @@ public async Task Will_fill_up_on_disconnects() ctx.PeerPool.Start(); ctx.PeerManager.Start(); await Task.Delay(_travisDelayLong); - Assert.That(ctx.RlpxPeer.ConnectAsyncCallsCount, Is.AtLeast(25)); + Assert.That(ctx.RlpxPeer.ConnectAsyncCallsCount, Is.EqualTo(25)); ctx.DisconnectAllSessions(); await Task.Delay(_travisDelayLong); - Assert.That(ctx.RlpxPeer.ConnectAsyncCallsCount, Is.AtLeast(50)); + Assert.That(ctx.RlpxPeer.ConnectAsyncCallsCount, Is.EqualTo(50)); } [Test, Retry(5)] @@ -297,23 +292,21 @@ public async Task Will_fill_up_over_and_over_again_on_disconnects() TimeSpan prevConnectingDelay = StatsParameters.Instance.DelayDueToEvent[NodeStatsEventType.Connecting]; StatsParameters.Instance.DelayDueToEvent[NodeStatsEventType.Connecting] = TimeSpan.Zero; - int[] prevDisconnectDelays = StatsParameters.Instance.DisconnectDelays; - StatsParameters.Instance.DisconnectDelays = new[] { 0 }; try { + int currentCount = 0; for (int i = 0; i < 10; i++) { - Assert.That( - () => ctx.PeerPool.ActivePeers.Count(), - Is.AtLeast(25).After(_travisDelayLonger * 2, 10)); + currentCount += 25; + await Task.Delay(_travisDelayLonger); + Assert.That(ctx.RlpxPeer.ConnectAsyncCallsCount, Is.EqualTo(currentCount)); ctx.DisconnectAllSessions(); } } finally { StatsParameters.Instance.DelayDueToEvent[NodeStatsEventType.Connecting] = prevConnectingDelay; - StatsParameters.Instance.DisconnectDelays = prevDisconnectDelays; } } @@ -333,49 +326,6 @@ public async Task Will_fill_up_over_and_over_again_on_newly_discovered() } } - [Test] - public async Task Will_not_stop_trying_on_rlpx_connection_failure() - { - await using Context ctx = new(); - ctx.SetupPersistedPeers(0); - ctx.PeerPool.Start(); - ctx.PeerManager.Start(); - ctx.RlpxPeer.MakeItFail(); - - for (int i = 0; i < 10; i++) - { - ctx.DiscoverNew(25); - await Task.Delay(_travisDelay); - Assert.That(() => ctx.RlpxPeer.ConnectAsyncCallsCount, Is.EqualTo(25 * (i + 1)).After(1000, 10)); - } - } - - [Test] - public async Task Will_not_stop_trying_on_any_failure() - { - await using Context ctx = new(maxActivePeers: 110); - - ctx.Stats = Substitute.For(); - ctx.Stats - .When(it => it.ReportEvent(Arg.Any(), NodeStatsEventType.ConnectionFailed)) - .Throw(new Exception("test exception")); - - Enumerable.Range(0, 110).ForEach((idx) => - { - PublicKey key = new PrivateKeyGenerator().Generate().PublicKey; - ctx.PeerPool.GetOrAdd(new Node(key, "1.2.3.4", idx)); - }); - - ctx.CreatePeerManager(); - ctx.SetupPersistedPeers(0); - ctx.PeerPool.Start(); - ctx.PeerManager.Start(); - ctx.RlpxPeer.MakeItFail(); - - Assert.That(() => ctx.RlpxPeer.ConnectAsyncCallsCount, Is.GreaterThan(100).After(10000, 10)); - await ctx.PeerManager.StopAsync(); - } - [Test] public async Task IfPeerAdded_with_invalid_chain_then_do_not_connect() { @@ -429,7 +379,7 @@ public async Task Will_fill_up_over_and_over_again_on_disconnects_and_when_ids_k { currentCount += 25; maxCount += 50; - Assert.That(() => ctx.RlpxPeer.ConnectAsyncCallsCount, Is.InRange(currentCount, maxCount).After(_travisDelayLonger * 2, 10)); + await Task.Delay(_travisDelay); ctx.RlpxPeer.ConnectAsyncCallsCount.Should().BeInRange(currentCount, maxCount); ctx.HandshakeAllSessions(); await Task.Delay(_travisDelay); @@ -602,16 +552,16 @@ private class Context : IAsyncDisposable { public RlpxMock RlpxPeer { get; } public IDiscoveryApp DiscoveryApp { get; } - public INodeStatsManager Stats { get; set; } + public INodeStatsManager Stats { get; } public INetworkStorage Storage { get; } public NodesLoader NodesLoader { get; } - public PeerManager PeerManager { get; set; } + public PeerManager PeerManager { get; } public IPeerPool PeerPool { get; } public INetworkConfig NetworkConfig { get; } public IStaticNodesManager StaticNodesManager { get; } public List Sessions { get; } = new(); - public Context(int parallelism = 0, int maxActivePeers = 25) + public Context() { RlpxPeer = new RlpxMock(Sessions); DiscoveryApp = Substitute.For(); @@ -621,19 +571,12 @@ public Context(int parallelism = 0, int maxActivePeers = 25) Storage = new InMemoryStorage(); NodesLoader = new NodesLoader(new NetworkConfig(), Stats, Storage, RlpxPeer, LimboLogs.Instance); NetworkConfig = new NetworkConfig(); - NetworkConfig.MaxActivePeers = maxActivePeers; + NetworkConfig.MaxActivePeers = 25; NetworkConfig.PeersPersistenceInterval = 50; - NetworkConfig.NumConcurrentOutgoingConnects = parallelism; - NetworkConfig.MaxOutgoingConnectPerSec = 1000000; // no limit in unit test StaticNodesManager = Substitute.For(); StaticNodesManager.LoadInitialList().Returns(new List()); CompositeNodeSource nodeSources = new(NodesLoader, DiscoveryApp, StaticNodesManager); PeerPool = new PeerPool(nodeSources, Stats, Storage, NetworkConfig, LimboLogs.Instance); - CreatePeerManager(); - } - - public void CreatePeerManager() - { PeerManager = new PeerManager(RlpxPeer, PeerPool, Stats, NetworkConfig, LimboLogs.Instance); } @@ -711,7 +654,7 @@ public void DisconnectAllSessions() foreach (Session session in clone) { - session.MarkDisconnected(DisconnectReason.Other, DisconnectType.Remote, "test"); + session.MarkDisconnected(DisconnectReason.TooManyPeers, DisconnectType.Remote, "test"); } } @@ -744,14 +687,14 @@ public Task Init() public Task ConnectAsync(Node node) { - lock (this) + if (_isFailing) { - ConnectAsyncCallsCount++; + throw new InvalidOperationException("making it fail"); } - if (_isFailing) + lock (this) { - throw new InvalidOperationException("making it fail"); + ConnectAsyncCallsCount++; } var session = new Session(30313, node, Substitute.For(), NullDisconnectsAnalyzer.Instance, diff --git a/src/Nethermind/Nethermind.Network.Test/ProtocolsManagerTests.cs b/src/Nethermind/Nethermind.Network.Test/ProtocolsManagerTests.cs index 9b72d269f19..b84477b2fb6 100644 --- a/src/Nethermind/Nethermind.Network.Test/ProtocolsManagerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/ProtocolsManagerTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.Numerics; using System.Threading; @@ -14,14 +15,13 @@ using Nethermind.Core.Test.Builders; using Nethermind.Core.Timers; using Nethermind.Logging; -using Nethermind.Network.Config; using Nethermind.Network.P2P; using Nethermind.Network.P2P.Analyzers; using Nethermind.Network.P2P.Messages; using Nethermind.Network.P2P.ProtocolHandlers; -using Nethermind.Network.P2P.Subprotocols.Eth; using Nethermind.Network.P2P.Subprotocols.Eth.V62; using Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages; +using Nethermind.Network.P2P.Subprotocols.Eth.V65; using Nethermind.Network.Rlpx; using Nethermind.Specs; using Nethermind.Stats; @@ -113,7 +113,6 @@ public Context() _peerStorage, forkInfo, _gossipPolicy, - new NetworkConfig(), LimboLogs.Instance); _serializer.Register(new HelloMessageSerializer()); @@ -172,7 +171,7 @@ public Context VerifyDisconnected() public Context ReceiveDisconnect() { - DisconnectMessage message = new(EthDisconnectReason.Other); + DisconnectMessage message = new(DisconnectReason.Other); IByteBuffer disconnectPacket = _serializer.ZeroSerialize(message); // to account for AdaptivePacketType byte diff --git a/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/AuthEip8MessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/AuthEip8MessageSerializerTests.cs index 08c8d369783..935873b1e28 100644 --- a/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/AuthEip8MessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/AuthEip8MessageSerializerTests.cs @@ -53,7 +53,7 @@ public void Encode_decode_before_eip155(int chainId) } [TestCase(BlockchainIds.Mainnet)] - [TestCase(BlockchainIds.Sepolia)] + [TestCase(BlockchainIds.Ropsten)] [TestCase(BlockchainIds.Kovan)] public void Encode_decode_with_eip155(int chainId) { diff --git a/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/AuthMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/AuthMessageSerializerTests.cs index e334ac47b3a..6e476759807 100644 --- a/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/AuthMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/AuthMessageSerializerTests.cs @@ -57,7 +57,7 @@ public void Encode_decode_before_eip155(int chainId) } [TestCase(BlockchainIds.Mainnet)] - [TestCase(BlockchainIds.Sepolia)] + [TestCase(BlockchainIds.Ropsten)] [TestCase(BlockchainIds.Kovan)] public void Encode_decode_with_eip155(int chainId) { diff --git a/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/EncryptionHandshakeServiceTests.cs b/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/EncryptionHandshakeServiceTests.cs index 1e12458e4f5..edce9608289 100644 --- a/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/EncryptionHandshakeServiceTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/EncryptionHandshakeServiceTests.cs @@ -41,7 +41,7 @@ public void SetUp() _ack = null; } - private readonly IEthereumEcdsa _ecdsa = new EthereumEcdsa(BlockchainIds.Sepolia, LimboLogs.Instance); // TODO: separate general crypto signer from Ethereum transaction signing + private readonly IEthereumEcdsa _ecdsa = new EthereumEcdsa(BlockchainIds.Ropsten, LimboLogs.Instance); // TODO: separate general crypto signer from Ethereum transaction signing private IMessageSerializationService _messageSerializationService; diff --git a/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/NettyHandshakeHandlerTests.cs b/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/NettyHandshakeHandlerTests.cs index 3cd3cc0a49c..8379e695797 100644 --- a/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/NettyHandshakeHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/NettyHandshakeHandlerTests.cs @@ -5,6 +5,7 @@ using System.Net; using System.Threading.Tasks; using DotNetty.Buffers; +using DotNetty.Codecs; using DotNetty.Common.Concurrency; using DotNetty.Transport.Channels; using FluentAssertions; diff --git a/src/Nethermind/Nethermind.Network.Test/Rlpx/ZeroNettyP2PHandlerTests.cs b/src/Nethermind/Nethermind.Network.Test/Rlpx/ZeroNettyP2PHandlerTests.cs index 786e800f191..f90d0c690c0 100644 --- a/src/Nethermind/Nethermind.Network.Test/Rlpx/ZeroNettyP2PHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/Rlpx/ZeroNettyP2PHandlerTests.cs @@ -3,16 +3,11 @@ using System; using System.Threading.Tasks; -using DotNetty.Buffers; using DotNetty.Transport.Channels; -using FluentAssertions; using Nethermind.Core.Exceptions; -using Nethermind.Core.Extensions; using Nethermind.Logging; using Nethermind.Network.P2P; using Nethermind.Network.P2P.ProtocolHandlers; -using Nethermind.Network.Rlpx; -using Nethermind.Serialization.Rlp; using NSubstitute; using NUnit.Framework; @@ -45,32 +40,6 @@ public async Task When_internal_nethermind_exception_is_thrown__then_do_not_disc await channelHandlerContext.DidNotReceive().DisconnectAsync(); } - [Test] - public void When_not_a_snappy_encoded_data_then_pass_data_directly() - { - IChannelHandlerContext channelHandlerContext = Substitute.For(); - channelHandlerContext.Allocator.Returns(UnpooledByteBufferAllocator.Default); - - byte[] msg = Bytes.FromHexString("0x10"); - - ISession session = Substitute.For(); - session.When(s => s.ReceiveMessage(Arg.Any())) - .Do(c => - { - ZeroPacket packet = (ZeroPacket)c[0]; - packet.Content.ReadAllBytesAsArray().Should().BeEquivalentTo(msg); - }); - - ZeroNettyP2PHandler handler = new ZeroNettyP2PHandler(session, LimboLogs.Instance); - handler.EnableSnappy(); - - IByteBuffer buff = Unpooled.Buffer(2); - buff.WriteBytes(msg); - ZeroPacket packet = new ZeroPacket(buff); - - handler.ChannelRead(channelHandlerContext, packet); - } - private class TestInternalNethermindException : Exception, IInternalNethermindException { diff --git a/src/Nethermind/Nethermind.Network.Test/SnapProtocolHandlerTests.cs b/src/Nethermind/Nethermind.Network.Test/SnapProtocolHandlerTests.cs index 0d6726ad6ba..2fc4dcae8f4 100644 --- a/src/Nethermind/Nethermind.Network.Test/SnapProtocolHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/SnapProtocolHandlerTests.cs @@ -8,6 +8,7 @@ using DotNetty.Buffers; using DotNetty.Common.Utilities; using FluentAssertions; +using Nethermind.Blockchain.Synchronization; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Network/Config/INetworkConfig.cs b/src/Nethermind/Nethermind.Network/Config/INetworkConfig.cs index f187ef9ea8a..48a31f89410 100644 --- a/src/Nethermind/Nethermind.Network/Config/INetworkConfig.cs +++ b/src/Nethermind/Nethermind.Network/Config/INetworkConfig.cs @@ -86,19 +86,10 @@ public interface INetworkConfig : IConfig [ConfigItem(DefaultValue = "0", HiddenFromDocs = true, Description = "[TECHNICAL] Number of concurrent outgoing connections. Reduce this if your ISP throttles from having open too many connections. Default is 0 which means same as processor count.")] int NumConcurrentOutgoingConnects { get; set; } - [ConfigItem(DefaultValue = "20", Description = "[TECHNICAL] Max number of new outgoing connections per second. Default is 20.")] - int MaxOutgoingConnectPerSec { get; set; } - [ConfigItem(DefaultValue = "2000", HiddenFromDocs = true, Description = "[TECHNICAL] Outgoing connection timeout in ms. Default is 2 seconds.")] int ConnectTimeoutMs { get; set; } [ConfigItem(DefaultValue = "1", HiddenFromDocs = true, Description = "[TECHNICAL] Num of thread in final processing of network packet. Set to more than 1 if you have very fast internet.")] int ProcessingThreadCount { get; set; } - - [ConfigItem(DefaultValue = null, HiddenFromDocs = true, Description = "[TECHNICAL] Only allow peer with clientId matching this regex. Useful for testing. eg: 'besu' to only connect to BeSU")] - string? ClientIdMatcher { get; set; } - - [ConfigItem(DefaultValue = "false", HiddenFromDocs = true, Description = "[TECHNICAL] Disable feeding ENR DNS records to discv4 table")] - bool DisableDiscV4DnsFeeder { get; set; } } } diff --git a/src/Nethermind/Nethermind.Network/Config/NetworkConfig.cs b/src/Nethermind/Nethermind.Network/Config/NetworkConfig.cs index 82d36422a1a..1f57cad0641 100644 --- a/src/Nethermind/Nethermind.Network/Config/NetworkConfig.cs +++ b/src/Nethermind/Nethermind.Network/Config/NetworkConfig.cs @@ -35,10 +35,7 @@ public class NetworkConfig : INetworkConfig public int P2PPort { get; set; } = 30303; public long SimulateSendLatencyMs { get; set; } = 0; public int NumConcurrentOutgoingConnects { get; set; } = 0; - public int MaxOutgoingConnectPerSec { get; set; } = 20; public int ConnectTimeoutMs { get; set; } = 2000; public int ProcessingThreadCount { get; set; } = 1; - public string? ClientIdMatcher { get; set; } = null; - public bool DisableDiscV4DnsFeeder { get; set; } = false; } } diff --git a/src/Nethermind/Nethermind.Network/ForkInfo.cs b/src/Nethermind/Nethermind.Network/ForkInfo.cs index 69df07bfddd..1776b5c4183 100644 --- a/src/Nethermind/Nethermind.Network/ForkInfo.cs +++ b/src/Nethermind/Nethermind.Network/ForkInfo.cs @@ -4,12 +4,15 @@ using System; using System.Buffers.Binary; using System.Collections.Generic; +using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; using Force.Crc32; +using Nethermind.Blockchain; using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Specs; diff --git a/src/Nethermind/Nethermind.Network/IPeerManager.cs b/src/Nethermind/Nethermind.Network/IPeerManager.cs index 8a4aa451f0e..cdb8f8fbf63 100644 --- a/src/Nethermind/Nethermind.Network/IPeerManager.cs +++ b/src/Nethermind/Nethermind.Network/IPeerManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Nethermind.Config; namespace Nethermind.Network { diff --git a/src/Nethermind/Nethermind.Network/Metrics.cs b/src/Nethermind/Nethermind.Network/Metrics.cs index 722840ec98c..aed8a821093 100644 --- a/src/Nethermind/Nethermind.Network/Metrics.cs +++ b/src/Nethermind/Nethermind.Network/Metrics.cs @@ -1,25 +1,15 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Concurrent; using System.ComponentModel; using System.Runtime.Serialization; using Nethermind.Core.Attributes; -using Nethermind.Stats.Model; namespace Nethermind.Network { //TODO: consult on use of metric disabeling flags! public static class Metrics { - [KeyIsLabel("reason")] - [Description("Number of local disconnects")] - public static ConcurrentDictionary LocalDisconnectsTotal { get; } = new(); - - [KeyIsLabel("reason")] - [Description("Number of remote disconnects")] - public static ConcurrentDictionary RemoteDisconnectsTotal { get; } = new(); - [CounterMetric] [Description("Number of incoming connection.")] public static long IncomingConnections { get; set; } diff --git a/src/Nethermind/Nethermind.Network/P2P/Analyzers/MetricsDisconnectsAnalyzer.cs b/src/Nethermind/Nethermind.Network/P2P/Analyzers/MetricsDisconnectsAnalyzer.cs index 0f69e5a8261..b31ad8a889f 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Analyzers/MetricsDisconnectsAnalyzer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Analyzers/MetricsDisconnectsAnalyzer.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using Nethermind.Core.Collections; using Nethermind.Stats.Model; namespace Nethermind.Network.P2P.Analyzers @@ -10,48 +9,44 @@ public class MetricsDisconnectsAnalyzer : IDisconnectsAnalyzer { public void ReportDisconnect(DisconnectReason reason, DisconnectType type, string details) { - EthDisconnectReason ethReason = reason.ToEthDisconnectReason(); - if (type == DisconnectType.Remote) { - Metrics.RemoteDisconnectsTotal.Increment(reason); - - switch (ethReason) + switch (reason) { - case EthDisconnectReason.BreachOfProtocol: + case DisconnectReason.BreachOfProtocol: Metrics.BreachOfProtocolDisconnects++; break; - case EthDisconnectReason.UselessPeer: + case DisconnectReason.UselessPeer: Metrics.UselessPeerDisconnects++; break; - case EthDisconnectReason.TooManyPeers: + case DisconnectReason.TooManyPeers: Metrics.TooManyPeersDisconnects++; break; - case EthDisconnectReason.AlreadyConnected: + case DisconnectReason.AlreadyConnected: Metrics.AlreadyConnectedDisconnects++; break; - case EthDisconnectReason.IncompatibleP2PVersion: + case DisconnectReason.IncompatibleP2PVersion: Metrics.IncompatibleP2PDisconnects++; break; - case EthDisconnectReason.NullNodeIdentityReceived: + case DisconnectReason.NullNodeIdentityReceived: Metrics.NullNodeIdentityDisconnects++; break; - case EthDisconnectReason.ClientQuitting: + case DisconnectReason.ClientQuitting: Metrics.ClientQuittingDisconnects++; break; - case EthDisconnectReason.UnexpectedIdentity: + case DisconnectReason.UnexpectedIdentity: Metrics.UnexpectedIdentityDisconnects++; break; - case EthDisconnectReason.ReceiveMessageTimeout: + case DisconnectReason.ReceiveMessageTimeout: Metrics.ReceiveMessageTimeoutDisconnects++; break; - case EthDisconnectReason.DisconnectRequested: + case DisconnectReason.DisconnectRequested: Metrics.DisconnectRequestedDisconnects++; break; - case EthDisconnectReason.IdentitySameAsSelf: + case DisconnectReason.IdentitySameAsSelf: Metrics.SameAsSelfDisconnects++; break; - case EthDisconnectReason.TcpSubSystemError: + case DisconnectReason.TcpSubSystemError: Metrics.TcpSubsystemErrorDisconnects++; break; default: @@ -62,44 +57,42 @@ public void ReportDisconnect(DisconnectReason reason, DisconnectType type, strin if (type == DisconnectType.Local) { - Metrics.LocalDisconnectsTotal.Increment(reason); - - switch (ethReason) + switch (reason) { - case EthDisconnectReason.BreachOfProtocol: + case DisconnectReason.BreachOfProtocol: Metrics.LocalBreachOfProtocolDisconnects++; break; - case EthDisconnectReason.UselessPeer: + case DisconnectReason.UselessPeer: Metrics.LocalUselessPeerDisconnects++; break; - case EthDisconnectReason.TooManyPeers: + case DisconnectReason.TooManyPeers: Metrics.LocalTooManyPeersDisconnects++; break; - case EthDisconnectReason.AlreadyConnected: + case DisconnectReason.AlreadyConnected: Metrics.LocalAlreadyConnectedDisconnects++; break; - case EthDisconnectReason.IncompatibleP2PVersion: + case DisconnectReason.IncompatibleP2PVersion: Metrics.LocalIncompatibleP2PDisconnects++; break; - case EthDisconnectReason.NullNodeIdentityReceived: + case DisconnectReason.NullNodeIdentityReceived: Metrics.LocalNullNodeIdentityDisconnects++; break; - case EthDisconnectReason.ClientQuitting: + case DisconnectReason.ClientQuitting: Metrics.LocalClientQuittingDisconnects++; break; - case EthDisconnectReason.UnexpectedIdentity: + case DisconnectReason.UnexpectedIdentity: Metrics.LocalUnexpectedIdentityDisconnects++; break; - case EthDisconnectReason.ReceiveMessageTimeout: + case DisconnectReason.ReceiveMessageTimeout: Metrics.LocalReceiveMessageTimeoutDisconnects++; break; - case EthDisconnectReason.DisconnectRequested: + case DisconnectReason.DisconnectRequested: Metrics.LocalDisconnectRequestedDisconnects++; break; - case EthDisconnectReason.IdentitySameAsSelf: + case DisconnectReason.IdentitySameAsSelf: Metrics.LocalSameAsSelfDisconnects++; break; - case EthDisconnectReason.TcpSubSystemError: + case DisconnectReason.TcpSubSystemError: Metrics.LocalTcpSubsystemErrorDisconnects++; break; default: diff --git a/src/Nethermind/Nethermind.Network/P2P/ISession.cs b/src/Nethermind/Nethermind.Network/P2P/ISession.cs index cafddf1fa58..20223802e29 100644 --- a/src/Nethermind/Nethermind.Network/P2P/ISession.cs +++ b/src/Nethermind/Nethermind.Network/P2P/ISession.cs @@ -48,7 +48,7 @@ public interface ISession : IDisposable /// /// Starts local disconnect (triggers disconnect on each protocolHandler, down to tcp disconnect) /// - void InitiateDisconnect(DisconnectReason disconnectReason, string details); + void InitiateDisconnect(InitiateDisconnectReason disconnectReason, string details); /// /// Drop tcp connection after a delay diff --git a/src/Nethermind/Nethermind.Network/P2P/MessageDictionary.cs b/src/Nethermind/Nethermind.Network/P2P/MessageDictionary.cs index 66157d8d520..bd3fef78aef 100644 --- a/src/Nethermind/Nethermind.Network/P2P/MessageDictionary.cs +++ b/src/Nethermind/Nethermind.Network/P2P/MessageDictionary.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading.Tasks; +using Nethermind.Core.Collections; using Nethermind.Core.Exceptions; using Nethermind.Network.P2P.Messages; using Nethermind.Network.P2P.Subprotocols; diff --git a/src/Nethermind/Nethermind.Network/P2P/Messages/DisconnectMessage.cs b/src/Nethermind/Nethermind.Network/P2P/Messages/DisconnectMessage.cs index 17d52e92ff5..1eec0f7f218 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Messages/DisconnectMessage.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Messages/DisconnectMessage.cs @@ -7,7 +7,7 @@ namespace Nethermind.Network.P2P.Messages { public class DisconnectMessage : P2PMessage { - public DisconnectMessage(EthDisconnectReason reason) + public DisconnectMessage(DisconnectReason reason) { Reason = (int)reason; } diff --git a/src/Nethermind/Nethermind.Network/P2P/Messages/DisconnectMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Messages/DisconnectMessageSerializer.cs index d6693214589..7487a7d0d31 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Messages/DisconnectMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Messages/DisconnectMessageSerializer.cs @@ -3,6 +3,7 @@ using System; using DotNetty.Buffers; +using Nethermind.Core.Extensions; using Nethermind.Serialization.Rlp; using Nethermind.Stats.Model; @@ -28,26 +29,24 @@ private int GetLength(DisconnectMessage message, out int contentLength) } + private byte[] breach1 = Bytes.FromHexString("0204c104"); + private byte[] breach2 = Bytes.FromHexString("0204c180"); + public DisconnectMessage Deserialize(IByteBuffer msgBytes) { if (msgBytes.ReadableBytes == 1) { - return new DisconnectMessage((EthDisconnectReason)msgBytes.GetByte(0)); - } - - if (msgBytes.ReadableBytes == 0) - { - // Sometimes 0x00 was sent, uncompressed, which interpreted as empty buffer by snappy. - return new DisconnectMessage(EthDisconnectReason.DisconnectRequested); + return new DisconnectMessage((DisconnectReason)msgBytes.GetByte(0)); } Span msg = msgBytes.ReadAllBytesAsSpan(); - Rlp.ValueDecoderContext rlpStream = msg.AsRlpValueContext(); - if (!rlpStream.IsSequenceNext()) + if (msg.SequenceEqual(breach1) + || msg.SequenceEqual(breach2)) { - rlpStream = new Rlp.ValueDecoderContext(rlpStream.DecodeByteArraySpan()); + return new DisconnectMessage(DisconnectReason.Other); } + Rlp.ValueDecoderContext rlpStream = msg.AsRlpValueContext(); rlpStream.ReadSequenceLength(); int reason = rlpStream.DecodeInt(); DisconnectMessage disconnectMessage = new DisconnectMessage(reason); diff --git a/src/Nethermind/Nethermind.Network/P2P/PacketSender.cs b/src/Nethermind/Nethermind.Network/P2P/PacketSender.cs index 1321dc672e5..581ebcf2156 100644 --- a/src/Nethermind/Nethermind.Network/P2P/PacketSender.cs +++ b/src/Nethermind/Nethermind.Network/P2P/PacketSender.cs @@ -2,8 +2,13 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.IO; +using System.Text; +using System.Threading; using System.Threading.Tasks; using DotNetty.Buffers; +using DotNetty.Common; +using DotNetty.Common.Utilities; using DotNetty.Transport.Channels; using Nethermind.Logging; using Nethermind.Network.P2P.Messages; @@ -36,7 +41,9 @@ public int Enqueue(T message) where T : P2PMessage int length = buffer.ReadableBytes; // Running in background - _ = SendBuffer(buffer); +#pragma warning disable CS4014 + SendBuffer(buffer); +#pragma warning restore CS4014 return length; } diff --git a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/P2PProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/P2PProtocolHandler.cs index 73ef1dc32a3..33e6ee4f281 100644 --- a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/P2PProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/P2PProtocolHandler.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using FastEnumUtility; @@ -48,7 +47,6 @@ public class P2PProtocolHandler : ProtocolHandlerBase, IPingSender, IP2PProtocol public IReadOnlyList AgreedCapabilities { get { return _agreedCapabilities; } } public IReadOnlyList AvailableCapabilities { get { return _availableCapabilities; } } private readonly List SupportedCapabilities = DefaultCapabilities.ToList(); - private readonly Regex? _clientIdPattern; public int ListenPort { get; } public PublicKey LocalNodeId { get; } @@ -63,12 +61,9 @@ public P2PProtocolHandler( PublicKey localNodeId, INodeStatsManager nodeStatsManager, IMessageSerializationService serializer, - Regex? clientIdPattern, ILogManager logManager) : base(session, nodeStatsManager, serializer, logManager) { _nodeStatsManager = nodeStatsManager ?? throw new ArgumentNullException(nameof(nodeStatsManager)); - _clientIdPattern = clientIdPattern; - LocalNodeId = localNodeId; ListenPort = session.LocalPort; _agreedCapabilities = new List(); @@ -132,25 +127,15 @@ public override void HandleMessage(Packet msg) { DisconnectMessage disconnectMessage = Deserialize(msg.Data); ReportIn(disconnectMessage, size); - - EthDisconnectReason disconnectReason = - FastEnum.IsDefined((byte)disconnectMessage.Reason) - ? ((EthDisconnectReason)disconnectMessage.Reason) - : EthDisconnectReason.Other; - if (Logger.IsTrace) { - if (!FastEnum.IsDefined((byte)disconnectMessage.Reason)) - { - Logger.Trace($"{Session} unknown disconnect reason ({disconnectMessage.Reason}) on {Session.RemotePort}"); - } - else - { - Logger.Trace($"{Session} Received disconnect ({disconnectReason}) on {Session.RemotePort}"); - } + string reason = FastEnum.IsDefined((byte)disconnectMessage.Reason) + ? ((DisconnectReason)disconnectMessage.Reason).ToName() + : disconnectMessage.Reason.ToString(); + Logger.Trace($"{Session} Received disconnect ({reason}) on {Session.RemotePort}"); } - Close(disconnectReason); + Close(disconnectMessage.Reason); break; } case P2PMessageCode.Ping: @@ -242,17 +227,10 @@ private void HandleHello(HelloMessage hello) { _nodeStatsManager.ReportFailedValidation(Session.Node, CompatibilityValidationType.Capabilities); Session.InitiateDisconnect( - DisconnectReason.NoCapabilityMatched, + InitiateDisconnectReason.NoCapabilityMatched, $"capabilities: {string.Join(", ", capabilities)}"); } - if (_clientIdPattern?.IsMatch(hello.ClientId) == false) - { - Session.InitiateDisconnect( - DisconnectReason.ClientFiltered, - $"clientId: {hello.ClientId}"); - } - ReceivedProtocolInitMsg(hello); P2PProtocolInitializedEventArgs eventArgs = new(this) @@ -314,7 +292,7 @@ public override void DisconnectProtocol(DisconnectReason disconnectReason, strin { if (Logger.IsTrace) Logger.Trace($"Sending disconnect {disconnectReason} ({details}) to {Session.Node:s}"); - DisconnectMessage message = new(disconnectReason.ToEthDisconnectReason()); + DisconnectMessage message = new(disconnectReason); Send(message); if (NetworkDiagTracer.IsEnabled) NetworkDiagTracer.ReportDisconnect(Session.Node.Address, $"Local {disconnectReason} {details}"); @@ -348,21 +326,23 @@ private void HandlePing() Send(PongMessage.Instance); } - private void Close(EthDisconnectReason ethDisconnectReason) + private void Close(int disconnectReasonId) { - if (ethDisconnectReason != EthDisconnectReason.TooManyPeers && - ethDisconnectReason != EthDisconnectReason.Other && - ethDisconnectReason != EthDisconnectReason.DisconnectRequested) + DisconnectReason disconnectReason = (DisconnectReason)disconnectReasonId; + + if (disconnectReason != DisconnectReason.TooManyPeers && + disconnectReason != DisconnectReason.Other && + disconnectReason != DisconnectReason.DisconnectRequested) { - if (Logger.IsDebug) Logger.Debug($"{Session} received disconnect [{ethDisconnectReason}]"); + if (Logger.IsDebug) Logger.Debug($"{Session} received disconnect [{disconnectReason}]"); } else { - if (Logger.IsTrace) Logger.Trace($"{Session} P2P received disconnect [{ethDisconnectReason}]"); + if (Logger.IsTrace) Logger.Trace($"{Session} P2P received disconnect [{disconnectReason}]"); } // Received disconnect message, triggering direct TCP disconnection - Session.MarkDisconnected(ethDisconnectReason.ToDisconnectReason(), DisconnectType.Remote, "message"); + Session.MarkDisconnected(disconnectReason, DisconnectType.Remote, "message"); } public override string Name => Protocol.P2P; diff --git a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ProtocolHandlerBase.cs b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ProtocolHandlerBase.cs index 441f7cec327..aaa6abe98c2 100644 --- a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ProtocolHandlerBase.cs +++ b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ProtocolHandlerBase.cs @@ -98,7 +98,7 @@ protected async Task CheckProtocolInitTimeout() Logger.Trace($"Disconnecting due to timeout for protocol init message ({Name}): {Session.RemoteNodeId}"); } - Session.InitiateDisconnect(DisconnectReason.ProtocolInitTimeout, "protocol init timeout"); + Session.InitiateDisconnect(InitiateDisconnectReason.ProtocolInitTimeout, "protocol init timeout"); } else { diff --git a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/SyncPeerProtocolHandlerBase.cs b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/SyncPeerProtocolHandlerBase.cs index 5467aab98f5..fb1feb06c6a 100644 --- a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/SyncPeerProtocolHandlerBase.cs +++ b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/SyncPeerProtocolHandlerBase.cs @@ -51,25 +51,7 @@ public abstract class SyncPeerProtocolHandlerBase : ZeroProtocolHandlerBase, ISy protected readonly TxDecoder _txDecoder; protected readonly MessageQueue _headersRequests; - protected readonly MessageQueue _bodiesRequests; - - private readonly LatencyAndMessageSizeBasedRequestSizer _bodiesRequestSizer = new( - minRequestLimit: 1, - maxRequestLimit: 128, - - // In addition to the byte limit, we also try to keep the latency of the get block bodies between these two - // watermark. This reduce timeout rate, and subsequently disconnection rate. - lowerLatencyWatermark: TimeSpan.FromMilliseconds(2000), - upperLatencyWatermark: TimeSpan.FromMilliseconds(3000), - - // When the bodies message size exceed this, we try to reduce the maximum number of block for this peer. - // This is for BeSU and Reth which does not seems to use the 2MB soft limit, causing them to send 20MB of bodies - // or receipts. This is not great as large message size are harder for DotNetty to pool byte buffer, causing - // higher memory usage. Reducing this even further does seems to help with memory, but may reduce throughput. - maxResponseSize: 3_000_000, - initialRequestSize: 4 - ); - + protected readonly MessageQueue _bodiesRequests; protected LruKeyCache NotifiedTransactions { get; } = new(2 * MemoryAllowance.MemPoolSize, "notifiedTransactions"); protected SyncPeerProtocolHandlerBase(ISession session, @@ -82,30 +64,29 @@ protected SyncPeerProtocolHandlerBase(ISession session, _timestamper = Timestamper.Default; _txDecoder = new TxDecoder(); _headersRequests = new MessageQueue(Send); - _bodiesRequests = new MessageQueue(Send); - + _bodiesRequests = new MessageQueue(Send); } - public void Disconnect(DisconnectReason reason, string details) + public void Disconnect(InitiateDisconnectReason reason, string details) { if (Logger.IsTrace) Logger.Trace($"Disconnecting {Node:c} because of the {details}"); Session.InitiateDisconnect(reason, details); } - async Task ISyncPeer.GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) + async Task ISyncPeer.GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) { if (blockHashes.Count == 0) { - return new OwnedBlockBodies(Array.Empty()); + return Array.Empty(); } - OwnedBlockBodies blocks = await _bodiesRequestSizer.Run(blockHashes, async clampedBlockHashes => - await SendRequest(new GetBlockBodiesMessage(clampedBlockHashes), token)); + GetBlockBodiesMessage bodiesMsg = new(blockHashes); + BlockBody[] blocks = await SendRequest(bodiesMsg, token); return blocks; } - protected virtual async Task<(OwnedBlockBodies, long)> SendRequest(GetBlockBodiesMessage message, CancellationToken token) + protected virtual async Task SendRequest(GetBlockBodiesMessage message, CancellationToken token) { if (Logger.IsTrace) { @@ -368,7 +349,7 @@ protected void Handle(BlockHeadersMessage message, long size) protected void HandleBodies(BlockBodiesMessage blockBodiesMessage, long size) { Metrics.Eth62BlockBodiesReceived++; - _bodiesRequests.Handle((blockBodiesMessage.Bodies, size), size); + _bodiesRequests.Handle(blockBodiesMessage.Bodies, size); } protected void Handle(GetReceiptsMessage msg) diff --git a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroNettyP2PHandler.cs b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroNettyP2PHandler.cs index 4ba00d291f5..cfa86bb064e 100644 --- a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroNettyP2PHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroNettyP2PHandler.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.IO; using System.Net.Sockets; using DotNetty.Buffers; using DotNetty.Common.Utilities; @@ -64,22 +63,22 @@ protected override void ChannelRead0(IChannelHandlerContext ctx, ZeroPacket inpu try { - int length = SnappyCodec.Uncompress(content.Array, content.ArrayOffset + content.ReaderIndex, - content.ReadableBytes, output.Array, output.ArrayOffset + output.WriterIndex); + int length = SnappyCodec.Uncompress(content.Array, content.ArrayOffset + content.ReaderIndex, content.ReadableBytes, output.Array, output.ArrayOffset); output.SetWriterIndex(output.WriterIndex + length); } - catch (InvalidDataException) - { - output.SafeRelease(); - // Data is not compressed sometimes, so we pass directly. - _session.ReceiveMessage(input); - return; - } catch (Exception) { - content.SkipBytes(content.ReadableBytes); - output.SafeRelease(); - throw; + if (content.ReadableBytes == 2 && content.ReadByte() == 193) + { + // this is a Parity disconnect sent as a non-snappy-encoded message + // e.g. 0xc103 + } + else + { + content.SkipBytes(content.ReadableBytes); + output.SafeRelease(); + throw; + } } content.SkipBytes(content.ReadableBytes); diff --git a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroProtocolHandlerBase.cs b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroProtocolHandlerBase.cs index 5fa02d2969a..2073f8819db 100644 --- a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroProtocolHandlerBase.cs +++ b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroProtocolHandlerBase.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using DotNetty.Common.Utilities; using Nethermind.Logging; +using Nethermind.Network.P2P.Messages; using Nethermind.Network.Rlpx; using Nethermind.Stats; @@ -73,7 +74,7 @@ CancellationToken token if (Logger.IsTrace) Logger.Trace($"{this} speed is {request.ResponseSize}/{elapsed} = {bytesPerMillisecond}"); StatsManager.ReportTransferSpeedEvent(Session.Node, speedType, bytesPerMillisecond); - return await task; + return task.Result; } StatsManager.ReportTransferSpeedEvent(Session.Node, speedType, 0L); diff --git a/src/Nethermind/Nethermind.Network/P2P/Session.cs b/src/Nethermind/Nethermind.Network/P2P/Session.cs index 23c98419af0..563c5c427e4 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Session.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Session.cs @@ -337,28 +337,28 @@ public void Handshake(PublicKey? handshakeRemoteNodeId) HandshakeComplete?.Invoke(this, EventArgs.Empty); } - public void InitiateDisconnect(DisconnectReason disconnectReason, string? details = null) + public void InitiateDisconnect(InitiateDisconnectReason initiateDisconnectReason, string? details = null) { - EthDisconnectReason ethDisconnectReason = disconnectReason.ToEthDisconnectReason(); + DisconnectReason disconnectReason = initiateDisconnectReason.ToDisconnectReason(); bool ShouldDisconnectStaticNode() { - switch (ethDisconnectReason) + switch (disconnectReason) { - case EthDisconnectReason.DisconnectRequested: - case EthDisconnectReason.TcpSubSystemError: - case EthDisconnectReason.UselessPeer: - case EthDisconnectReason.TooManyPeers: - case EthDisconnectReason.Other: + case DisconnectReason.DisconnectRequested: + case DisconnectReason.TcpSubSystemError: + case DisconnectReason.UselessPeer: + case DisconnectReason.TooManyPeers: + case DisconnectReason.Other: return false; - case EthDisconnectReason.ReceiveMessageTimeout: - case EthDisconnectReason.BreachOfProtocol: - case EthDisconnectReason.AlreadyConnected: - case EthDisconnectReason.IncompatibleP2PVersion: - case EthDisconnectReason.NullNodeIdentityReceived: - case EthDisconnectReason.ClientQuitting: - case EthDisconnectReason.UnexpectedIdentity: - case EthDisconnectReason.IdentitySameAsSelf: + case DisconnectReason.ReceiveMessageTimeout: + case DisconnectReason.BreachOfProtocol: + case DisconnectReason.AlreadyConnected: + case DisconnectReason.IncompatibleP2PVersion: + case DisconnectReason.NullNodeIdentityReceived: + case DisconnectReason.ClientQuitting: + case DisconnectReason.UnexpectedIdentity: + case DisconnectReason.IdentitySameAsSelf: return true; default: return true; @@ -381,7 +381,7 @@ bool ShouldDisconnectStaticNode() State = SessionState.DisconnectingProtocols; } - if (_logger.IsDebug) _logger.Debug($"{this} initiating disconnect because {disconnectReason}, details: {details}"); + if (_logger.IsDebug) _logger.Debug($"{this} initiating disconnect because {initiateDisconnectReason}, details: {details}"); //Trigger disconnect on each protocol handler (if p2p is initialized it will send disconnect message to the peer) if (_protocols.Any()) { @@ -390,7 +390,7 @@ bool ShouldDisconnectStaticNode() try { if (_logger.IsTrace) - _logger.Trace($"{this} disconnecting {protocolHandler.Name} {disconnectReason} ({details})"); + _logger.Trace($"{this} disconnecting {protocolHandler.Name} {initiateDisconnectReason} ({details})"); protocolHandler.DisconnectProtocol(disconnectReason, details); } catch (Exception e) diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/PooledTxsRequestor.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/PooledTxsRequestor.cs deleted file mode 100644 index 3dd79c22bbd..00000000000 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/PooledTxsRequestor.cs +++ /dev/null @@ -1,141 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using Nethermind.Core.Caching; -using Nethermind.Core.Collections; -using Nethermind.Core.Crypto; -using Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages; -using Nethermind.Network.P2P.Subprotocols.Eth.V65.Messages; -using Nethermind.TxPool; - -namespace Nethermind.Network.P2P.Subprotocols.Eth -{ - public class PooledTxsRequestor : IPooledTxsRequestor - { - private const int MaxNumberOfTxsInOneMsg = 256; - private readonly ITxPool _txPool; - private readonly LruKeyCache _pendingHashes = new(MemoryAllowance.TxHashCacheSize, - Math.Min(1024 * 16, MemoryAllowance.TxHashCacheSize), "pending tx hashes"); - - public PooledTxsRequestor(ITxPool txPool) - { - _txPool = txPool; - } - - public void RequestTransactions(Action send, IReadOnlyList hashes) - { - using ArrayPoolList discoveredTxHashes = new(hashes.Count); - AddMarkUnknownHashes(hashes, discoveredTxHashes); - - if (discoveredTxHashes.Count != 0) - { - RequestPooledTransactions(send, discoveredTxHashes); - } - } - - public void RequestTransactionsEth66(Action send, IReadOnlyList hashes) - { - using ArrayPoolList discoveredTxHashes = new(hashes.Count); - AddMarkUnknownHashes(hashes, discoveredTxHashes); - - if (discoveredTxHashes.Count != 0) - { - if (discoveredTxHashes.Count <= MaxNumberOfTxsInOneMsg) - { - RequestPooledTransactionsEth66(send, discoveredTxHashes); - } - else - { - using ArrayPoolList hashesToRequest = new(MaxNumberOfTxsInOneMsg); - for (int i = 0; i < discoveredTxHashes.Count; i++) - { - if (hashesToRequest.Count % MaxNumberOfTxsInOneMsg == 0 && hashesToRequest.Count > 0) - { - RequestPooledTransactionsEth66(send, hashesToRequest); - hashesToRequest.Clear(); - } - - hashesToRequest.Add(discoveredTxHashes[i]); - } - - if (hashesToRequest.Count > 0) - { - RequestPooledTransactionsEth66(send, hashesToRequest); - } - } - } - } - - public void RequestTransactionsEth68(Action send, IReadOnlyList hashes, IReadOnlyList sizes) - { - using ArrayPoolList<(Keccak Hash, int Size)> discoveredTxHashesAndSizes = new(hashes.Count); - AddMarkUnknownHashesEth68(hashes, sizes, discoveredTxHashesAndSizes); - - if (discoveredTxHashesAndSizes.Count != 0) - { - int packetSizeLeft = TransactionsMessage.MaxPacketSize; - using ArrayPoolList hashesToRequest = new(discoveredTxHashesAndSizes.Count); - - for (int i = 0; i < discoveredTxHashesAndSizes.Count; i++) - { - int txSize = discoveredTxHashesAndSizes[i].Size; - - if (txSize > packetSizeLeft && hashesToRequest.Count > 0) - { - RequestPooledTransactionsEth66(send, hashesToRequest); - hashesToRequest.Clear(); - packetSizeLeft = TransactionsMessage.MaxPacketSize; - } - - hashesToRequest.Add(discoveredTxHashesAndSizes[i].Hash); - packetSizeLeft -= txSize; - } - - if (hashesToRequest.Count > 0) - { - RequestPooledTransactionsEth66(send, hashesToRequest); - } - } - } - - private void AddMarkUnknownHashes(IReadOnlyList hashes, ArrayPoolList discoveredTxHashes) - { - int count = hashes.Count; - for (int i = 0; i < count; i++) - { - Keccak hash = hashes[i]; - if (!_txPool.IsKnown(hash) && _pendingHashes.Set(hash)) - { - discoveredTxHashes.Add(hash); - } - } - } - private void AddMarkUnknownHashesEth68(IReadOnlyList hashes, IReadOnlyList sizes, ArrayPoolList<(Keccak, int)> discoveredTxHashesAndSizes) - { - int count = hashes.Count; - for (int i = 0; i < count; i++) - { - Keccak hash = hashes[i]; - if (!_txPool.IsKnown(hash) && _pendingHashes.Set(hash)) - { - discoveredTxHashesAndSizes.Add((hash, sizes[i])); - } - } - } - - private void RequestPooledTransactions(Action send, IReadOnlyList hashesToRequest) - { - send(new GetPooledTransactionsMessage(hashesToRequest)); - Metrics.Eth65GetPooledTransactionsRequested++; - } - - private void RequestPooledTransactionsEth66(Action send, IReadOnlyList hashesToRequest) - { - GetPooledTransactionsMessage msg65 = new(hashesToRequest); - send(new V66.Messages.GetPooledTransactionsMessage() { EthMessage = msg65 }); - Metrics.Eth66GetPooledTransactionsRequested++; - } - } -} diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs index 08ab26d2481..26cb6a7d2ea 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs @@ -30,23 +30,20 @@ public class Eth62ProtocolHandler : SyncPeerProtocolHandlerBase, IZeroProtocolHa private readonly TxFloodController _floodController; protected readonly ITxPool _txPool; private readonly IGossipPolicy _gossipPolicy; - private readonly ITxGossipPolicy _txGossipPolicy; private readonly LruKeyCache _lastBlockNotificationCache = new(10, "LastBlockNotificationCache"); - public Eth62ProtocolHandler(ISession session, + public Eth62ProtocolHandler( + ISession session, IMessageSerializationService serializer, INodeStatsManager statsManager, ISyncServer syncServer, ITxPool txPool, IGossipPolicy gossipPolicy, - ILogManager logManager, - ITxGossipPolicy? transactionsGossipPolicy = null) - : base(session, serializer, statsManager, syncServer, logManager) + ILogManager logManager) : base(session, serializer, statsManager, syncServer, logManager) { _floodController = new TxFloodController(this, Timestamper.Default, Logger); _txPool = txPool ?? throw new ArgumentNullException(nameof(txPool)); _gossipPolicy = gossipPolicy ?? throw new ArgumentNullException(nameof(gossipPolicy)); - _txGossipPolicy = transactionsGossipPolicy ?? TxPool.ShouldGossip.Instance; EnsureGossipPolicy(); } @@ -61,7 +58,6 @@ public void DisableTxFiltering() public override int MessageIdSpaceSize => 8; public override string Name => "eth62"; protected override TimeSpan InitTimeout => Timeouts.Eth62Status; - protected bool CanReceiveTransactions => _txGossipPolicy.ShouldListenToGossippedTransactions; public override event EventHandler? ProtocolInitialized; @@ -116,7 +112,7 @@ bool CanAcceptBlockGossip() { const string postFinalized = $"NewBlock message received after FIRST_FINALIZED_BLOCK PoS block. Disconnecting Peer."; ReportIn(postFinalized, size); - Disconnect(DisconnectReason.GossipingInPoS, postFinalized); + Disconnect(InitiateDisconnectReason.GossipingInPoS, postFinalized); return false; } @@ -157,26 +153,17 @@ bool CanAcceptBlockGossip() break; case Eth62MessageCode.Transactions: Metrics.Eth62TransactionsReceived++; - if (CanReceiveTransactions) + if (_floodController.IsAllowed()) { - if (_floodController.IsAllowed()) - { - TransactionsMessage txMsg = Deserialize(message.Content); - ReportIn(txMsg, size); - Handle(txMsg); - } - else - { - const string txFlooding = $"Ignoring {nameof(TransactionsMessage)} because of message flooding."; - ReportIn(txFlooding, size); - } + TransactionsMessage txMsg = Deserialize(message.Content); + ReportIn(txMsg, size); + Handle(txMsg); } else { - const string ignored = $"{nameof(TransactionsMessage)} ignored, syncing"; - ReportIn(ignored, size); + const string txFlooding = $"Ignoring {nameof(TransactionsMessage)} because of message flooding."; + ReportIn(txFlooding, size); } - break; case Eth62MessageCode.GetBlockHeaders: GetBlockHeadersMessage getBlockHeadersMessage diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessage.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessage.cs index 876b927ac79..93d83067e6f 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessage.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessage.cs @@ -11,28 +11,26 @@ public class BlockBodiesMessage : P2PMessage public override int PacketType { get; } = Eth62MessageCode.BlockBodies; public override string Protocol { get; } = "eth"; - public OwnedBlockBodies? Bodies { get; set; } - public BlockBodiesMessage() { } public BlockBodiesMessage(Block[] blocks) { - BlockBody[] bodies = new BlockBody[blocks.Length]; + Bodies = new BlockBody[blocks.Length]; for (int i = 0; i < blocks.Length; i++) { - bodies[i] = blocks[i]?.Body; + Bodies[i] = blocks[i]?.Body; } - - Bodies = new OwnedBlockBodies(bodies); } - public BlockBodiesMessage(BlockBody?[] bodies) + public BlockBodiesMessage(BlockBody[] bodies) { - Bodies = new OwnedBlockBodies(bodies); + Bodies = bodies; } - public override string ToString() => $"{nameof(BlockBodiesMessage)}({Bodies?.Bodies?.Length ?? 0})"; + public BlockBody?[] Bodies { get; set; } + + public override string ToString() => $"{nameof(BlockBodiesMessage)}({Bodies?.Length ?? 0})"; } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessageSerializer.cs index 3ad0d5c5cc1..546f949401e 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessageSerializer.cs @@ -4,22 +4,24 @@ using System.Linq; using DotNetty.Buffers; using Nethermind.Core; -using Nethermind.Core.Buffers; using Nethermind.Serialization.Rlp; namespace Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages { public class BlockBodiesMessageSerializer : IZeroInnerMessageSerializer { - private readonly BlockBodyDecoder _blockBodyDecoder = new BlockBodyDecoder(); + private readonly TxDecoder _txDecoder = new TxDecoder(); + private readonly HeaderDecoder _headerDecoder = new HeaderDecoder(); + private readonly WithdrawalDecoder _withdrawalDecoderDecoder = new WithdrawalDecoder(); public void Serialize(IByteBuffer byteBuffer, BlockBodiesMessage message) { + int totalLength = GetLength(message, out int contentLength); byteBuffer.EnsureWritable(totalLength, true); NettyRlpStream stream = new(byteBuffer); stream.StartSequence(contentLength); - foreach (BlockBody? body in message.Bodies.Bodies) + foreach (BlockBody? body in message.Bodies) { if (body == null) { @@ -27,73 +29,87 @@ public void Serialize(IByteBuffer byteBuffer, BlockBodiesMessage message) } else { - _blockBodyDecoder.Serialize(stream, body); + SerializeBody(stream, body); + } + } + } + + private void SerializeBody(NettyRlpStream stream, BlockBody body) + { + stream.StartSequence(GetBodyLength(body)); + stream.StartSequence(GetTxLength(body.Transactions)); + foreach (Transaction? txn in body.Transactions) + { + stream.Encode(txn); + } + + stream.StartSequence(GetUnclesLength(body.Uncles)); + foreach (BlockHeader? uncle in body.Uncles) + { + stream.Encode(uncle); + } + + if (body.Withdrawals != null) + { + stream.StartSequence(GetWithdrawalsLength(body.Withdrawals)); + foreach (Withdrawal? withdrawal in body.Withdrawals) + { + stream.Encode(withdrawal); } } } + public BlockBodiesMessage Deserialize(IByteBuffer byteBuffer) + { + NettyRlpStream rlpStream = new(byteBuffer); + return Deserialize(rlpStream); + } + public int GetLength(BlockBodiesMessage message, out int contentLength) { - contentLength = message.Bodies.Bodies.Select(b => b == null + contentLength = message.Bodies.Select(b => b == null ? Rlp.OfEmptySequence.Length - : Rlp.LengthOfSequence(_blockBodyDecoder.GetBodyLength(b)) + : Rlp.LengthOfSequence(GetBodyLength(b)) ).Sum(); return Rlp.LengthOfSequence(contentLength); } - public BlockBodiesMessage Deserialize(IByteBuffer byteBuffer) + private int GetBodyLength(BlockBody b) { - NettyBufferMemoryOwner memoryOwner = new(byteBuffer); - - Rlp.ValueDecoderContext ctx = new(memoryOwner.Memory, true); - int startingPosition = ctx.Position; - BlockBody[]? bodies = ctx.DecodeArray(_blockBodyDecoder, false); - byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startingPosition)); - - return new() { Bodies = new(bodies, memoryOwner) }; + if (b.Withdrawals != null) + { + return Rlp.LengthOfSequence(GetTxLength(b.Transactions)) + + Rlp.LengthOfSequence(GetUnclesLength(b.Uncles)) + Rlp.LengthOfSequence(GetWithdrawalsLength(b.Withdrawals)); + } + return Rlp.LengthOfSequence(GetTxLength(b.Transactions)) + + Rlp.LengthOfSequence(GetUnclesLength(b.Uncles)); } - private class BlockBodyDecoder : IRlpValueDecoder + private int GetTxLength(Transaction[] transactions) { - private readonly TxDecoder _txDecoder = new(); - private readonly HeaderDecoder _headerDecoder = new(); - private readonly WithdrawalDecoder _withdrawalDecoderDecoder = new(); - public int GetLength(BlockBody item, RlpBehaviors rlpBehaviors) - { - return Rlp.LengthOfSequence(GetBodyLength(item)); - } + return transactions.Sum(t => _txDecoder.GetLength(t, RlpBehaviors.None)); + } - public int GetBodyLength(BlockBody b) - { - if (b.Withdrawals != null) - { - return Rlp.LengthOfSequence(GetTxLength(b.Transactions)) + - Rlp.LengthOfSequence(GetUnclesLength(b.Uncles)) + Rlp.LengthOfSequence(GetWithdrawalsLength(b.Withdrawals)); - } - return Rlp.LengthOfSequence(GetTxLength(b.Transactions)) + - Rlp.LengthOfSequence(GetUnclesLength(b.Uncles)); - } + private int GetUnclesLength(BlockHeader[] headers) + { - private int GetTxLength(Transaction[] transactions) - { - return transactions.Sum(t => _txDecoder.GetLength(t, RlpBehaviors.None)); - } + return headers.Sum(t => _headerDecoder.GetLength(t, RlpBehaviors.None)); + } - private int GetUnclesLength(BlockHeader[] headers) - { - return headers.Sum(t => _headerDecoder.GetLength(t, RlpBehaviors.None)); - } + private int GetWithdrawalsLength(Withdrawal[] withdrawals) + { - private int GetWithdrawalsLength(Withdrawal[] withdrawals) - { - return withdrawals.Sum(t => _withdrawalDecoderDecoder.GetLength(t, RlpBehaviors.None)); - } + return withdrawals.Sum(t => _withdrawalDecoderDecoder.GetLength(t, RlpBehaviors.None)); + } - public BlockBody? Decode(ref Rlp.ValueDecoderContext ctx, RlpBehaviors rlpBehaviors = RlpBehaviors.None) + public static BlockBodiesMessage Deserialize(RlpStream rlpStream) + { + BlockBodiesMessage message = new(); + message.Bodies = rlpStream.DecodeArray(ctx => { - int sequenceLength = ctx.ReadSequenceLength(); - int startingPosition = ctx.Position; + int sequenceLength = rlpStream.ReadSequenceLength(); + int startingPosition = rlpStream.Position; if (sequenceLength == 0) { return null; @@ -101,41 +117,18 @@ private int GetWithdrawalsLength(Withdrawal[] withdrawals) // quite significant allocations (>0.5%) here based on a sample 3M blocks sync // (just on these delegates) - Transaction[] transactions = ctx.DecodeArray(_txDecoder); - BlockHeader[] uncles = ctx.DecodeArray(_headerDecoder); + Transaction[] transactions = rlpStream.DecodeArray(_ => Rlp.Decode(ctx)); + BlockHeader[] uncles = rlpStream.DecodeArray(_ => Rlp.Decode(ctx)); Withdrawal[]? withdrawals = null; - if (ctx.PeekNumberOfItemsRemaining(startingPosition + sequenceLength, 1) > 0) + if (rlpStream.PeekNumberOfItemsRemaining(startingPosition + sequenceLength, 1) > 0) { - withdrawals = ctx.DecodeArray(_withdrawalDecoderDecoder); + withdrawals = rlpStream.DecodeArray(_ => Rlp.Decode(ctx)); } return new BlockBody(transactions, uncles, withdrawals); - } - - public void Serialize(RlpStream stream, BlockBody body) - { - stream.StartSequence(GetBodyLength(body)); - stream.StartSequence(GetTxLength(body.Transactions)); - foreach (Transaction? txn in body.Transactions) - { - stream.Encode(txn); - } + }, false); - stream.StartSequence(GetUnclesLength(body.Uncles)); - foreach (BlockHeader? uncle in body.Uncles) - { - stream.Encode(uncle); - } - - if (body.Withdrawals != null) - { - stream.StartSequence(GetWithdrawalsLength(body.Withdrawals)); - foreach (Withdrawal? withdrawal in body.Withdrawals) - { - stream.Encode(withdrawal); - } - } - } + return message; } } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/TxFloodController.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/TxFloodController.cs index 5f0aacf4961..29ea07e3285 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/TxFloodController.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/TxFloodController.cs @@ -43,7 +43,7 @@ public void Report(bool accepted) { if (_logger.IsDebug) _logger.Debug($"Disconnecting {_protocolHandler} due to tx flooding"); _protocolHandler.Disconnect( - DisconnectReason.TxFlooding, + InitiateDisconnectReason.TxFlooding, $"tx flooding {_notAcceptedSinceLastCheck}/{_checkInterval.TotalSeconds > 100}"); } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Eth63ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Eth63ProtocolHandler.cs index 32e4d573eaf..cfca85ac686 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Eth63ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Eth63ProtocolHandler.cs @@ -24,24 +24,7 @@ public class Eth63ProtocolHandler : Eth62ProtocolHandler { private readonly MessageQueue _nodeDataRequests; - private readonly MessageQueue _receiptsRequests; - - private readonly LatencyAndMessageSizeBasedRequestSizer _receiptsRequestSizer = new( - minRequestLimit: 1, - maxRequestLimit: 128, - - // In addition to the byte limit, we also try to keep the latency of the get receipts between these two - // watermark. This reduce timeout rate, and subsequently disconnection rate. - lowerLatencyWatermark: TimeSpan.FromMilliseconds(2000), - upperLatencyWatermark: TimeSpan.FromMilliseconds(3000), - - // When the receipts message size exceed this, we try to reduce the maximum number of block for this peer. - // This is for BeSU and Reth which does not seems to use the 2MB soft limit, causing them to send 20MB of bodies - // or receipts. This is not great as large message size are harder for DotNetty to pool byte buffer, causing - // higher memory usage. Reducing this even further does seems to help with memory, but may reduce throughput. - maxResponseSize: 3_000_000, - initialRequestSize: 8 - ); + private readonly MessageQueue _receiptsRequests; public Eth63ProtocolHandler(ISession session, IMessageSerializationService serializer, @@ -49,12 +32,10 @@ public Eth63ProtocolHandler(ISession session, ISyncServer syncServer, ITxPool txPool, IGossipPolicy gossipPolicy, - ILogManager logManager, - ITxGossipPolicy? transactionsGossipPolicy = null) - : base(session, serializer, nodeStatsManager, syncServer, txPool, gossipPolicy, logManager, transactionsGossipPolicy) + ILogManager logManager) : base(session, serializer, nodeStatsManager, syncServer, txPool, gossipPolicy, logManager) { _nodeDataRequests = new MessageQueue(Send); - _receiptsRequests = new MessageQueue(Send); + _receiptsRequests = new MessageQueue(Send); } public override byte ProtocolVersion => EthVersions.Eth63; @@ -96,7 +77,7 @@ public override void HandleMessage(ZeroPacket message) protected virtual void Handle(ReceiptsMessage msg, long size) { Metrics.Eth63ReceiptsReceived++; - _receiptsRequests.Handle((msg.TxReceipts, size), size); + _receiptsRequests.Handle(msg.TxReceipts, size); } private void Handle(GetNodeDataMessage msg) @@ -149,9 +130,8 @@ public override async Task GetReceipts(IReadOnlyList bloc return Array.Empty(); } - TxReceipt[][] txReceipts = await _receiptsRequestSizer.Run(blockHashes, async clampedBlockHashes => - await SendRequest(new GetReceiptsMessage(clampedBlockHashes), token)); - + GetReceiptsMessage msg = new(blockHashes); + TxReceipt[][] txReceipts = await SendRequest(msg, token); return txReceipts; } @@ -171,7 +151,7 @@ protected virtual async Task SendRequest(GetNodeDataMessage message, C token); } - protected virtual async Task<(TxReceipt[][], long)> SendRequest(GetReceiptsMessage message, CancellationToken token) + protected virtual async Task SendRequest(GetReceiptsMessage message, CancellationToken token) { if (Logger.IsTrace) { diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Messages/ReceiptsMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Messages/ReceiptsMessageSerializer.cs index e224a50632b..4c3453116a3 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Messages/ReceiptsMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Messages/ReceiptsMessageSerializer.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Linq; using DotNetty.Buffers; using Nethermind.Core; using Nethermind.Core.Extensions; diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V64/Eth64ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V64/Eth64ProtocolHandler.cs index 1da0028cb29..3660472443b 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V64/Eth64ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V64/Eth64ProtocolHandler.cs @@ -3,8 +3,10 @@ using System; using Nethermind.Consensus; +using Nethermind.Core.Specs; using Nethermind.Logging; using Nethermind.Network.Contract.P2P; +using Nethermind.Network.P2P.Subprotocols.Eth.V62; using Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages; using Nethermind.Network.P2P.Subprotocols.Eth.V63; using Nethermind.Stats; @@ -27,9 +29,7 @@ public Eth64ProtocolHandler(ISession session, ITxPool txPool, IGossipPolicy gossipPolicy, ForkInfo forkInfo, - ILogManager logManager, - ITxGossipPolicy? transactionsGossipPolicy = null) - : base(session, serializer, nodeStatsManager, syncServer, txPool, gossipPolicy, logManager, transactionsGossipPolicy) + ILogManager logManager) : base(session, serializer, nodeStatsManager, syncServer, txPool, gossipPolicy, logManager) { _forkInfo = forkInfo ?? throw new ArgumentNullException(nameof(forkInfo)); } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs index 4ede85c04e1..01bfbcf6c1a 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs @@ -34,9 +34,8 @@ public Eth65ProtocolHandler(ISession session, IPooledTxsRequestor pooledTxsRequestor, IGossipPolicy gossipPolicy, ForkInfo forkInfo, - ILogManager logManager, - ITxGossipPolicy? transactionsGossipPolicy = null) - : base(session, serializer, nodeStatsManager, syncServer, txPool, gossipPolicy, forkInfo, logManager, transactionsGossipPolicy) + ILogManager logManager) + : base(session, serializer, nodeStatsManager, syncServer, txPool, gossipPolicy, forkInfo, logManager) { _pooledTxsRequestor = pooledTxsRequestor; } @@ -53,20 +52,11 @@ public override void HandleMessage(ZeroPacket message) switch (message.PacketType) { case Eth65MessageCode.PooledTransactions: - if (CanReceiveTransactions) - { - PooledTransactionsMessage pooledTxMsg - = Deserialize(message.Content); - Metrics.Eth65PooledTransactionsReceived++; - ReportIn(pooledTxMsg, size); - Handle(pooledTxMsg); - } - else - { - const string ignored = $"{nameof(PooledTransactionsMessage)} ignored, syncing"; - ReportIn(ignored, size); - } - + PooledTransactionsMessage pooledTxMsg + = Deserialize(message.Content); + Metrics.Eth65PooledTransactionsReceived++; + ReportIn(pooledTxMsg, size); + Handle(pooledTxMsg); break; case Eth65MessageCode.GetPooledTransactions: GetPooledTransactionsMessage getPooledTxMsg @@ -75,19 +65,10 @@ GetPooledTransactionsMessage getPooledTxMsg Handle(getPooledTxMsg); break; case Eth65MessageCode.NewPooledTransactionHashes: - if (CanReceiveTransactions) - { - NewPooledTransactionHashesMessage newPooledTxMsg = - Deserialize(message.Content); - ReportIn(newPooledTxMsg, size); - Handle(newPooledTxMsg); - } - else - { - const string ignored = $"{nameof(NewPooledTransactionHashesMessage)} ignored, syncing"; - ReportIn(ignored, size); - } - + NewPooledTransactionHashesMessage newPooledTxMsg = + Deserialize(message.Content); + ReportIn(newPooledTxMsg, size); + Handle(newPooledTxMsg); break; } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/IPooledTxsRequestor.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/IPooledTxsRequestor.cs similarity index 72% rename from src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/IPooledTxsRequestor.cs rename to src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/IPooledTxsRequestor.cs index 786186ebbf4..45af648dc84 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/IPooledTxsRequestor.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/IPooledTxsRequestor.cs @@ -6,12 +6,12 @@ using Nethermind.Core.Crypto; using Nethermind.Network.P2P.Subprotocols.Eth.V65.Messages; -namespace Nethermind.Network.P2P.Subprotocols.Eth +namespace Nethermind.Network.P2P.Subprotocols.Eth.V65 { public interface IPooledTxsRequestor { void RequestTransactions(Action send, IReadOnlyList hashes); void RequestTransactionsEth66(Action send, IReadOnlyList hashes); - void RequestTransactionsEth68(Action send, IReadOnlyList hashes, IReadOnlyList sizes); + } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/PooledTxsRequestor.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/PooledTxsRequestor.cs new file mode 100644 index 00000000000..39c46a464ac --- /dev/null +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/PooledTxsRequestor.cs @@ -0,0 +1,64 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Generic; +using Nethermind.Core; +using Nethermind.Core.Caching; +using Nethermind.Core.Collections; +using Nethermind.Core.Crypto; +using Nethermind.Network.P2P.Subprotocols.Eth.V65.Messages; +using Nethermind.TxPool; + +namespace Nethermind.Network.P2P.Subprotocols.Eth.V65 +{ + public class PooledTxsRequestor : IPooledTxsRequestor + { + private readonly ITxPool _txPool; + private readonly LruKeyCache _pendingHashes = new(MemoryAllowance.TxHashCacheSize, + Math.Min(1024 * 16, MemoryAllowance.TxHashCacheSize), "pending tx hashes"); + + public PooledTxsRequestor(ITxPool txPool) + { + _txPool = txPool; + } + + public void RequestTransactions(Action send, IReadOnlyList hashes) + { + using ArrayPoolList discoveredTxHashes = new(hashes.Count); + AddMarkUnknownHashes(hashes, discoveredTxHashes); + + if (discoveredTxHashes.Count != 0) + { + send(new GetPooledTransactionsMessage(discoveredTxHashes)); + Metrics.Eth65GetPooledTransactionsRequested++; + } + } + + public void RequestTransactionsEth66(Action send, IReadOnlyList hashes) + { + using ArrayPoolList discoveredTxHashes = new(hashes.Count); + AddMarkUnknownHashes(hashes, discoveredTxHashes); + + if (discoveredTxHashes.Count != 0) + { + GetPooledTransactionsMessage msg65 = new(discoveredTxHashes); + send(new V66.Messages.GetPooledTransactionsMessage() { EthMessage = msg65 }); + Metrics.Eth66GetPooledTransactionsRequested++; + } + } + + private void AddMarkUnknownHashes(IReadOnlyList hashes, ArrayPoolList discoveredTxHashes) + { + int count = hashes.Count; + for (int i = 0; i < count; i++) + { + Keccak hash = hashes[i]; + if (!_txPool.IsKnown(hash) && _pendingHashes.Set(hash)) + { + discoveredTxHashes.Add(hash); + } + } + } + } +} diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V66/Eth66ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V66/Eth66ProtocolHandler.cs index cc55d85827c..b43cdd9704d 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V66/Eth66ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V66/Eth66ProtocolHandler.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Nethermind.Consensus; @@ -29,9 +30,9 @@ namespace Nethermind.Network.P2P.Subprotocols.Eth.V66 public class Eth66ProtocolHandler : Eth65ProtocolHandler { private readonly MessageDictionary _headersRequests66; - private readonly MessageDictionary _bodiesRequests66; + private readonly MessageDictionary _bodiesRequests66; private readonly MessageDictionary _nodeDataRequests66; - private readonly MessageDictionary _receiptsRequests66; + private readonly MessageDictionary _receiptsRequests66; private readonly IPooledTxsRequestor _pooledTxsRequestor; private readonly Action _sendAction; @@ -43,14 +44,13 @@ public Eth66ProtocolHandler(ISession session, IPooledTxsRequestor pooledTxsRequestor, IGossipPolicy gossipPolicy, ForkInfo forkInfo, - ILogManager logManager, - ITxGossipPolicy? transactionsGossipPolicy = null) - : base(session, serializer, nodeStatsManager, syncServer, txPool, pooledTxsRequestor, gossipPolicy, forkInfo, logManager, transactionsGossipPolicy) + ILogManager logManager) + : base(session, serializer, nodeStatsManager, syncServer, txPool, pooledTxsRequestor, gossipPolicy, forkInfo, logManager) { _headersRequests66 = new MessageDictionary(Send); - _bodiesRequests66 = new MessageDictionary(Send); + _bodiesRequests66 = new MessageDictionary(Send); _nodeDataRequests66 = new MessageDictionary(Send); - _receiptsRequests66 = new MessageDictionary(Send); + _receiptsRequests66 = new MessageDictionary(Send); _pooledTxsRequestor = pooledTxsRequestor; // Capture Action once rather than per call _sendAction = Send; @@ -99,20 +99,11 @@ GetPooledTransactionsMessage getPooledTxMsg Handle(getPooledTxMsg); break; case Eth66MessageCode.PooledTransactions: - if (CanReceiveTransactions) - { - PooledTransactionsMessage pooledTxMsg - = Deserialize(message.Content); - Metrics.Eth66PooledTransactionsReceived++; - ReportIn(pooledTxMsg, size); - Handle(pooledTxMsg.EthMessage); - } - else - { - const string ignored = $"{nameof(PooledTransactionsMessage)} ignored, syncing"; - ReportIn(ignored, size); - } - + PooledTransactionsMessage pooledTxMsg + = Deserialize(message.Content); + Metrics.Eth66PooledTransactionsReceived++; + ReportIn(pooledTxMsg, size); + Handle(pooledTxMsg.EthMessage); break; case Eth66MessageCode.GetReceipts: GetReceiptsMessage getReceiptsMessage = Deserialize(message.Content); @@ -187,7 +178,7 @@ private void Handle(BlockHeadersMessage message, long size) private void HandleBodies(BlockBodiesMessage blockBodiesMessage, long size) { - _bodiesRequests66.Handle(blockBodiesMessage.RequestId, (blockBodiesMessage.EthMessage.Bodies, size), size); + _bodiesRequests66.Handle(blockBodiesMessage.RequestId, blockBodiesMessage.EthMessage.Bodies, size); } private void Handle(NodeDataMessage msg, int size) @@ -197,7 +188,7 @@ private void Handle(NodeDataMessage msg, int size) private void Handle(ReceiptsMessage msg, long size) { - _receiptsRequests66.Handle(msg.RequestId, (msg.EthMessage.TxReceipts, size), size); + _receiptsRequests66.Handle(msg.RequestId, msg.EthMessage.TxReceipts, size); } protected override void Handle(NewPooledTransactionHashesMessage msg) @@ -235,7 +226,7 @@ protected override async Task SendRequest(V62.Messages.GetBlockHe token); } - protected override async Task<(OwnedBlockBodies, long)> SendRequest(V62.Messages.GetBlockBodiesMessage message, CancellationToken token) + protected override async Task SendRequest(V62.Messages.GetBlockBodiesMessage message, CancellationToken token) { if (Logger.IsTrace) { @@ -269,7 +260,7 @@ protected override async Task SendRequest(V63.Messages.GetNodeDataMess token); } - protected override async Task<(TxReceipt[][], long)> SendRequest(V63.Messages.GetReceiptsMessage message, CancellationToken token) + protected override async Task SendRequest(V63.Messages.GetReceiptsMessage message, CancellationToken token) { if (Logger.IsTrace) { diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V67/Eth67ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V67/Eth67ProtocolHandler.cs index bc58a8014bf..ab97d51df60 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V67/Eth67ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V67/Eth67ProtocolHandler.cs @@ -2,8 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Consensus; +using Nethermind.Core.Specs; using Nethermind.Logging; using Nethermind.Network.Contract.P2P; +using Nethermind.Network.P2P.Subprotocols.Eth.V65; using Nethermind.Network.P2P.Subprotocols.Eth.V66; using Nethermind.Network.Rlpx; using Nethermind.Stats; @@ -25,9 +27,8 @@ public Eth67ProtocolHandler(ISession session, IPooledTxsRequestor pooledTxsRequestor, IGossipPolicy gossipPolicy, ForkInfo forkInfo, - ILogManager logManager, - ITxGossipPolicy? transactionsGossipPolicy = null) - : base(session, serializer, nodeStatsManager, syncServer, txPool, pooledTxsRequestor, gossipPolicy, forkInfo, logManager, transactionsGossipPolicy) + ILogManager logManager) + : base(session, serializer, nodeStatsManager, syncServer, txPool, pooledTxsRequestor, gossipPolicy, forkInfo, logManager) { } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandler.cs index 36d3547a2c9..35172064bd6 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandler.cs @@ -10,6 +10,7 @@ using Nethermind.Core.Crypto; using Nethermind.Logging; using Nethermind.Network.Contract.P2P; +using Nethermind.Network.P2P.Subprotocols.Eth.V65; using Nethermind.Network.P2P.Subprotocols.Eth.V67; using Nethermind.Network.P2P.Subprotocols.Eth.V68.Messages; using Nethermind.Network.Rlpx; @@ -37,9 +38,9 @@ public Eth68ProtocolHandler(ISession session, IPooledTxsRequestor pooledTxsRequestor, IGossipPolicy gossipPolicy, ForkInfo forkInfo, - ILogManager logManager, - ITxGossipPolicy? transactionsGossipPolicy = null) - : base(session, serializer, nodeStatsManager, syncServer, txPool, pooledTxsRequestor, gossipPolicy, forkInfo, logManager, transactionsGossipPolicy) + ILogManager logManager) + : base(session, serializer, nodeStatsManager, syncServer, txPool, pooledTxsRequestor, gossipPolicy, + forkInfo, logManager) { _pooledTxsRequestor = pooledTxsRequestor; @@ -53,19 +54,10 @@ public override void HandleMessage(ZeroPacket message) switch (message.PacketType) { case Eth68MessageCode.NewPooledTransactionHashes: - if (CanReceiveTransactions) - { - NewPooledTransactionHashesMessage68 newPooledTxHashesMsg = - Deserialize(message.Content); - ReportIn(newPooledTxHashesMsg, size); - Handle(newPooledTxHashesMsg); - } - else - { - const string ignored = $"{nameof(NewPooledTransactionHashesMessage68)} ignored, syncing"; - ReportIn(ignored, size); - } - + NewPooledTransactionHashesMessage68 newPooledTxHashesMsg = + Deserialize(message.Content); + ReportIn(newPooledTxHashesMsg, size); + Handle(newPooledTxHashesMsg); break; default: base.HandleMessage(message); @@ -93,7 +85,7 @@ private void Handle(NewPooledTransactionHashesMessage68 message) Stopwatch? stopwatch = isTrace ? Stopwatch.StartNew() : null; - _pooledTxsRequestor.RequestTransactionsEth68(_sendAction, message.Hashes, message.Sizes); + _pooledTxsRequestor.RequestTransactionsEth66(_sendAction, message.Hashes); stopwatch?.Stop(); diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Messages/NewPooledTransactionHashesMessageSerializer68.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Messages/NewPooledTransactionHashesMessageSerializer68.cs index 2d52a8841ea..83a76664665 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Messages/NewPooledTransactionHashesMessageSerializer68.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Messages/NewPooledTransactionHashesMessageSerializer68.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Linq; using DotNetty.Buffers; using Nethermind.Core.Crypto; using Nethermind.Serialization.Rlp; diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Les/LesProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Les/LesProtocolHandler.cs index 2351c3423c0..2c44d42e54d 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Les/LesProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Les/LesProtocolHandler.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain; using Nethermind.Blockchain.Synchronization; @@ -19,8 +20,10 @@ using Nethermind.Network.Rlpx; using Nethermind.Serialization.Rlp; using Nethermind.Stats; +using Nethermind.Stats.Model; using Nethermind.Synchronization; using Nethermind.Synchronization.FastSync; +using Nethermind.TxPool; using CancellationToken = System.Threading.CancellationToken; namespace Nethermind.Network.P2P.Subprotocols.Les diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Les/Messages/BlockBodiesMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Les/Messages/BlockBodiesMessageSerializer.cs index 3211a9705d0..37d66043b05 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Les/Messages/BlockBodiesMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Les/Messages/BlockBodiesMessageSerializer.cs @@ -8,8 +8,6 @@ namespace Nethermind.Network.P2P.Subprotocols.Les.Messages { public class BlockBodiesMessageSerializer : IZeroMessageSerializer { - private readonly Eth.V62.Messages.BlockBodiesMessageSerializer _baseDeserializer = new(); - public void Serialize(IByteBuffer byteBuffer, BlockBodiesMessage message) { Eth.V62.Messages.BlockBodiesMessageSerializer ethSerializer = new(); @@ -30,11 +28,16 @@ public void Serialize(IByteBuffer byteBuffer, BlockBodiesMessage message) public BlockBodiesMessage Deserialize(IByteBuffer byteBuffer) { NettyRlpStream rlpStream = new(byteBuffer); + return Deserialize(rlpStream); + } + + private static BlockBodiesMessage Deserialize(RlpStream rlpStream) + { BlockBodiesMessage blockBodiesMessage = new(); rlpStream.ReadSequenceLength(); blockBodiesMessage.RequestId = rlpStream.DecodeLong(); blockBodiesMessage.BufferValue = rlpStream.DecodeInt(); - blockBodiesMessage.EthMessage = _baseDeserializer.Deserialize(byteBuffer); + blockBodiesMessage.EthMessage = Eth.V62.Messages.BlockBodiesMessageSerializer.Deserialize(rlpStream); return blockBodiesMessage; } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/AccountRangeMessage.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/AccountRangeMessage.cs index e9684180260..281d53266ab 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/AccountRangeMessage.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/AccountRangeMessage.cs @@ -1,6 +1,10 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections; +using System.Collections.Generic; +using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.State.Snap; namespace Nethermind.Network.P2P.Subprotocols.Snap.Messages diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/AccountRangeMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/AccountRangeMessageSerializer.cs index 34fc5eb5863..353ec19315a 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/AccountRangeMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/AccountRangeMessageSerializer.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using DotNetty.Buffers; +using Nethermind.Core; using Nethermind.Serialization.Rlp; +using Nethermind.Core.Extensions; using Nethermind.State.Snap; namespace Nethermind.Network.P2P.Subprotocols.Snap.Messages diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/ByteCodesMessage.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/ByteCodesMessage.cs index 7e1516987cc..53fb3421ea8 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/ByteCodesMessage.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/ByteCodesMessage.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Core.Crypto; namespace Nethermind.Network.P2P.Subprotocols.Snap.Messages { diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetAccountRangeMessage.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetAccountRangeMessage.cs index 24be0cb7730..383fb522f68 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetAccountRangeMessage.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetAccountRangeMessage.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core.Crypto; using Nethermind.State.Snap; namespace Nethermind.Network.P2P.Subprotocols.Snap.Messages diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetByteCodesMessage.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetByteCodesMessage.cs index 4db643fffbe..113e578312e 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetByteCodesMessage.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetByteCodesMessage.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections; using System.Collections.Generic; using Nethermind.Core.Crypto; diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangeMessage.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangeMessage.cs index a03b4f4015e..169935e2fc7 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangeMessage.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangeMessage.cs @@ -1,6 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections; +using System.Collections.Generic; +using Nethermind.Core.Crypto; using Nethermind.State.Snap; namespace Nethermind.Network.P2P.Subprotocols.Snap.Messages diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializer.cs index a3b80213a0f..797e833fe41 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializer.cs @@ -3,6 +3,8 @@ using System.Linq; using DotNetty.Buffers; +using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Serialization.Rlp; using Nethermind.State.Snap; diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/SnapMessageBase.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/SnapMessageBase.cs index e54d85521ce..c382d6f150b 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/SnapMessageBase.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/SnapMessageBase.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using DotNetty.Common.Utilities; using Nethermind.Network.P2P.Messages; namespace Nethermind.Network.P2P.Subprotocols.Snap.Messages diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/StorageRangeMessage.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/StorageRangeMessage.cs index 4634d5c39b6..6b9960f7a49 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/StorageRangeMessage.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/StorageRangeMessage.cs @@ -1,6 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections; +using System.Collections.Generic; +using Nethermind.Core.Crypto; using Nethermind.State.Snap; namespace Nethermind.Network.P2P.Subprotocols.Snap.Messages diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/StorageRangesMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/StorageRangesMessageSerializer.cs index ca5fc79aada..a37a337a5d8 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/StorageRangesMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/StorageRangesMessageSerializer.cs @@ -1,8 +1,10 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using DotNetty.Buffers; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Serialization.Rlp; using Nethermind.State.Snap; diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/SnapProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/SnapProtocolHandler.cs index 069575997cd..41e2be889fb 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/SnapProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/SnapProtocolHandler.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain.Synchronization; -using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Logging; using Nethermind.Network.Contract.P2P; @@ -22,15 +22,11 @@ namespace Nethermind.Network.P2P.Subprotocols.Snap { public class SnapProtocolHandler : ZeroProtocolHandlerBase, ISnapSyncPeer { - public static TimeSpan LowerLatencyThreshold = TimeSpan.FromMilliseconds(2000); - public static TimeSpan UpperLatencyThreshold = TimeSpan.FromMilliseconds(3000); - - private readonly LatencyBasedRequestSizer _requestSizer = new( - minRequestLimit: 50000, - maxRequestLimit: 3_000_000, - lowerWatermark: LowerLatencyThreshold, - upperWatermark: UpperLatencyThreshold - ); + private const int MaxBytesLimit = 2_000_000; + private const int MinBytesLimit = 20_000; + public static readonly TimeSpan UpperLatencyThreshold = TimeSpan.FromMilliseconds(2000); + public static readonly TimeSpan LowerLatencyThreshold = TimeSpan.FromMilliseconds(1000); + private const double BytesLimitAdjustmentFactor = 2; public override string Name => "snap1"; protected override TimeSpan InitTimeout => Timeouts.Eth; @@ -47,6 +43,8 @@ public class SnapProtocolHandler : ZeroProtocolHandlerBase, ISnapSyncPeer private readonly MessageQueue _getTrieNodesRequests; private static readonly byte[] _emptyBytes = { 0 }; + private int _currentBytesLimit = MinBytesLimit; + public SnapProtocolHandler(ISession session, INodeStatsManager nodeStats, IMessageSerializationService serializer, @@ -151,28 +149,28 @@ private void Handle(TrieNodesMessage msg, long size) private void Handle(GetAccountRangeMessage msg) { Metrics.SnapGetAccountRangeReceived++; - Session.InitiateDisconnect(DisconnectReason.SnapServerNotImplemented, DisconnectMessage); + Session.InitiateDisconnect(InitiateDisconnectReason.SnapServerNotImplemented, DisconnectMessage); if (Logger.IsDebug) Logger.Debug($"Peer disconnected because of requesting Snap data (AccountRange). Peer: {Session.Node.ClientId}"); } private void Handle(GetStorageRangeMessage getStorageRangesMessage) { Metrics.SnapGetStorageRangesReceived++; - Session.InitiateDisconnect(DisconnectReason.SnapServerNotImplemented, DisconnectMessage); + Session.InitiateDisconnect(InitiateDisconnectReason.SnapServerNotImplemented, DisconnectMessage); if (Logger.IsDebug) Logger.Debug($"Peer disconnected because of requesting Snap data (StorageRange). Peer: {Session.Node.ClientId}"); } private void Handle(GetByteCodesMessage getByteCodesMessage) { Metrics.SnapGetByteCodesReceived++; - Session.InitiateDisconnect(DisconnectReason.SnapServerNotImplemented, DisconnectMessage); + Session.InitiateDisconnect(InitiateDisconnectReason.SnapServerNotImplemented, DisconnectMessage); if (Logger.IsDebug) Logger.Debug($"Peer disconnected because of requesting Snap data (ByteCodes). Peer: {Session.Node.ClientId}"); } private void Handle(GetTrieNodesMessage getTrieNodesMessage) { Metrics.SnapGetTrieNodesReceived++; - Session.InitiateDisconnect(DisconnectReason.SnapServerNotImplemented, DisconnectMessage); + Session.InitiateDisconnect(InitiateDisconnectReason.SnapServerNotImplemented, DisconnectMessage); if (Logger.IsDebug) Logger.Debug($"Peer disconnected because of requesting Snap data (TrieNodes). Peer: {Session.Node.ClientId}"); } @@ -183,12 +181,14 @@ public override void DisconnectProtocol(DisconnectReason disconnectReason, strin public async Task GetAccountRange(AccountRange range, CancellationToken token) { - AccountRangeMessage response = await _requestSizer.MeasureLatency((bytesLimit) => - SendRequest(new GetAccountRangeMessage() - { - AccountRange = range, - ResponseBytes = bytesLimit - }, _getAccountRangeRequests, token)); + var request = new GetAccountRangeMessage() + { + AccountRange = range, + ResponseBytes = _currentBytesLimit + }; + + AccountRangeMessage response = await AdjustBytesLimit(() => + SendRequest(request, _getAccountRangeRequests, token)); Metrics.SnapGetAccountRangeSent++; @@ -197,12 +197,14 @@ public async Task GetAccountRange(AccountRange range, Cancell public async Task GetStorageRange(StorageRange range, CancellationToken token) { - StorageRangeMessage response = await _requestSizer.MeasureLatency((bytesLimit) => - SendRequest(new GetStorageRangeMessage() - { - StoragetRange = range, - ResponseBytes = bytesLimit - }, _getStorageRangeRequests, token)); + var request = new GetStorageRangeMessage() + { + StoragetRange = range, + ResponseBytes = _currentBytesLimit + }; + + StorageRangeMessage response = await AdjustBytesLimit(() => + SendRequest(request, _getStorageRangeRequests, token)); Metrics.SnapGetStorageRangesSent++; @@ -211,12 +213,14 @@ public async Task GetStorageRange(StorageRange range, Cancellati public async Task GetByteCodes(IReadOnlyList codeHashes, CancellationToken token) { - ByteCodesMessage response = await _requestSizer.MeasureLatency((bytesLimit) => - SendRequest(new GetByteCodesMessage() - { - Hashes = codeHashes, - Bytes = bytesLimit, - }, _getByteCodesRequests, token)); + var request = new GetByteCodesMessage() + { + Hashes = codeHashes, + Bytes = _currentBytesLimit + }; + + ByteCodesMessage response = await AdjustBytesLimit(() => + SendRequest(request, _getByteCodesRequests, token)); Metrics.SnapGetByteCodesSent++; @@ -237,13 +241,15 @@ public async Task GetTrieNodes(GetTrieNodesRequest request, Cancellati private async Task GetTrieNodes(ValueKeccak rootHash, PathGroup[] groups, CancellationToken token) { - TrieNodesMessage response = await _requestSizer.MeasureLatency((bytesLimit) => - SendRequest(new GetTrieNodesMessage() - { - RootHash = rootHash, - Paths = groups, - Bytes = bytesLimit - }, _getTrieNodesRequests, token)); + GetTrieNodesMessage reqMsg = new() + { + RootHash = rootHash, + Paths = groups, + Bytes = _currentBytesLimit + }; + + TrieNodesMessage response = await AdjustBytesLimit(() => + SendRequest(reqMsg, _getTrieNodesRequests, token)); Metrics.SnapGetTrieNodesSent++; @@ -274,5 +280,46 @@ private async Task SendRequest(TIn msg, MessageQueue static (request) => request.ToString(), token); } + + /// + /// Adjust the _currentBytesLimit depending on the latency of the request and if the request failed. + /// + /// + /// + /// + private async Task AdjustBytesLimit(Func> func) + { + // Record bytes limit so that in case multiple concurrent request happens, we do not multiply the + // limit on top of other adjustment, so only the last adjustment will stick, which is fine. + int startingBytesLimit = _currentBytesLimit; + bool failed = false; + Stopwatch sw = Stopwatch.StartNew(); + try + { + return await func(); + } + catch (Exception) + { + failed = true; + throw; + } + finally + { + sw.Stop(); + if (failed) + { + _currentBytesLimit = MinBytesLimit; + } + else if (sw.Elapsed < LowerLatencyThreshold) + { + _currentBytesLimit = Math.Min((int)(startingBytesLimit * BytesLimitAdjustmentFactor), MaxBytesLimit); + } + else if (sw.Elapsed > UpperLatencyThreshold && startingBytesLimit > MinBytesLimit) + { + _currentBytesLimit = (int)(startingBytesLimit / BytesLimitAdjustmentFactor); + } + } + } + } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Wit/WitProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Wit/WitProtocolHandler.cs index 0e08e6147a8..8b7ab064b88 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Wit/WitProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Wit/WitProtocolHandler.cs @@ -4,6 +4,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using DotNetty.Common.Utilities; using Nethermind.Blockchain.Synchronization; using Nethermind.Core.Crypto; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Network/PeerComparer.cs b/src/Nethermind/Nethermind.Network/PeerComparer.cs index cc2c7744ec8..f8e9cb21e83 100644 --- a/src/Nethermind/Nethermind.Network/PeerComparer.cs +++ b/src/Nethermind/Nethermind.Network/PeerComparer.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using Nethermind.Stats; namespace Nethermind.Network { diff --git a/src/Nethermind/Nethermind.Network/PeerManager.cs b/src/Nethermind/Nethermind.Network/PeerManager.cs index 3160a223052..3b7d57ecf51 100644 --- a/src/Nethermind/Nethermind.Network/PeerManager.cs +++ b/src/Nethermind/Nethermind.Network/PeerManager.cs @@ -2,15 +2,15 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Buffers; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Threading; -using System.Threading.Channels; using System.Threading.Tasks; +using System.Threading.Tasks.Dataflow; using FastEnumUtility; -using Nethermind.Core; using Nethermind.Core.Attributes; using Nethermind.Core.Crypto; using Nethermind.Logging; @@ -20,6 +20,7 @@ using Nethermind.Network.Rlpx; using Nethermind.Stats; using Nethermind.Stats.Model; +using Nethermind.Synchronization.Peers; using Timer = System.Timers.Timer; namespace Nethermind.Network @@ -36,7 +37,6 @@ public class PeerManager : IPeerManager private readonly PeerComparer _peerComparer = new(); private readonly IPeerPool _peerPool; private readonly List _candidates; - private readonly RateLimiter _outgoingConnectionRateLimiter; private int _pending; private int _tryCount; @@ -51,9 +51,10 @@ public class PeerManager : IPeerManager private bool _isStarted; private int _logCounter = 1; + private Task _peerUpdateLoopTask; private readonly CancellationTokenSource _cancellationTokenSource = new(); - private readonly int _outgoingConnectParallelism; + private readonly int _parallelism; public PeerManager( IRlpxHost rlpxHost, @@ -66,12 +67,11 @@ public PeerManager( _rlpxHost = rlpxHost ?? throw new ArgumentNullException(nameof(rlpxHost)); _stats = stats ?? throw new ArgumentNullException(nameof(stats)); _networkConfig = networkConfig ?? throw new ArgumentNullException(nameof(networkConfig)); - _outgoingConnectParallelism = networkConfig.NumConcurrentOutgoingConnects; - if (_outgoingConnectParallelism == 0) + _parallelism = networkConfig.NumConcurrentOutgoingConnects; + if (_parallelism == 0) { - _outgoingConnectParallelism = Environment.ProcessorCount; + _parallelism = Environment.ProcessorCount; } - _outgoingConnectionRateLimiter = new RateLimiter(networkConfig.MaxOutgoingConnectPerSec); _peerPool = peerPool; _candidates = new List(networkConfig.MaxActivePeers * 2); @@ -122,7 +122,7 @@ private void PeerPoolOnPeerAdded(object sender, PeerEventArgs nodeEventArgs) // fire and forget - all the surrounding logic will be executed // exceptions can be lost here without issues // this for rapid connections to newly discovered peers without having to go through the UpdatePeerLoop - SetupOutgoingPeerConnection(peer, cancelIfThrottled: true); + SetupOutgoingPeerConnection(peer); } #pragma warning restore 4014 } @@ -158,7 +158,7 @@ public void Start() StartPeerUpdateLoop(); - Task.Factory.StartNew( + _peerUpdateLoopTask = Task.Factory.StartNew( RunPeerUpdateLoop, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, @@ -205,28 +205,7 @@ private class CandidateSelection private async Task RunPeerUpdateLoop() { - Channel taskChannel = Channel.CreateBounded(1); - List? tasks = Enumerable.Range(0, _outgoingConnectParallelism).Select(async (idx) => - { - await foreach (Peer peer in taskChannel.Reader.ReadAllAsync(_cancellationTokenSource.Token)) - { - try - { - await SetupOutgoingPeerConnection(peer); - } - catch (TaskCanceledException) - { - if (_logger.IsDebug) _logger.Debug($"Connect worker {idx} cancelled"); - break; - } - catch (Exception e) - { - // This is strictly speaking not related to the connection, but something outside of it. - if (_logger.IsError) _logger.Error($"Error setting up connection to {peer}, {e}"); - } - } - if (_logger.IsDebug) _logger.Debug($"Connect worker {idx} completed"); - }).ToList(); + const int TIME_WAIT = 60_000; int loopCount = 0; long previousActivePeersCount = 0; @@ -257,7 +236,7 @@ private async Task RunPeerUpdateLoop() continue; } - if (!EnsureAvailableActivePeerSlot()) + if (AvailableActivePeersCount == 0) { continue; } @@ -271,38 +250,79 @@ private async Task RunPeerUpdateLoop() List remainingCandidates = _currentSelection.Candidates; if (remainingCandidates.Count == 0) { - // Delay to prevent high CPU use. There is a shortcut path for newly discovered peer, so having - // a lower delay probably wont do much. - await Task.Delay(TimeSpan.FromSeconds(1)); continue; } if (_cancellationTokenSource.IsCancellationRequested) { - if (_logger.IsInfo) _logger.Info("Peer update loop canceled"); break; } - foreach (Peer peer in remainingCandidates) + int currentPosition = 0; + long lastMs = Environment.TickCount64; + int peersTried = 0; + while (true) { - if (!EnsureAvailableActivePeerSlot()) + if (_cancellationTokenSource.IsCancellationRequested) { - // Some new connection are in flight at this point, but statistically speaking, they - // are going to fail, so its fine. break; } - await taskChannel.Writer.WriteAsync(peer, _cancellationTokenSource.Token); + int nodesToTry = Math.Min(remainingCandidates.Count - currentPosition, AvailableActivePeersCount); + if (nodesToTry <= 0) + { + break; + } + + peersTried += nodesToTry; + ActionBlock workerBlock = new( + SetupOutgoingPeerConnection, + new ExecutionDataflowBlockOptions + { + MaxDegreeOfParallelism = _parallelism, + CancellationToken = _cancellationTokenSource.Token + }); + + for (int i = 0; i < nodesToTry; i++) + { + await workerBlock.SendAsync(remainingCandidates[currentPosition + i]); + } + + currentPosition += nodesToTry; + + workerBlock.Complete(); + + // Wait for all messages to propagate through the network. + await workerBlock.Completion; + + Interlocked.Increment(ref _connectionRounds); + + long nowMs = Environment.TickCount64; + if (peersTried > 1_000) + { + peersTried = 0; + // Wait for sockets to clear + await Task.Delay(TIME_WAIT); + } + else + { + long diffMs = nowMs - lastMs; + if (diffMs < 50) + { + await Task.Delay(50 - (int)diffMs); + } + } + lastMs = nowMs; } - if (_logger.IsTrace || (_logger.IsDebug && _logCounter % 5 == 0)) + if (_logger.IsTrace) { List>? activePeers = _peerPool.ActivePeers.ToList(); int activePeersCount = activePeers.Count; if (activePeersCount != previousActivePeersCount) { string countersLog = string.Join(", ", _currentSelection.Counters.Select(x => $"{x.Key.ToString()}: {x.Value}")); - _logger.Debug($"RunPeerUpdate | {countersLog}, Incompatible: {GetIncompatibleDesc(_currentSelection.Incompatible)}, EligibleCandidates: {_currentSelection.Candidates.Count}, " + + _logger.Trace($"RunPeerUpdate | {countersLog}, Incompatible: {GetIncompatibleDesc(_currentSelection.Incompatible)}, EligibleCandidates: {_currentSelection.Candidates.Count}, " + $"Tried: {_tryCount}, Rounds: {_connectionRounds}, Failed initial connect: {_failedInitialConnect}, Established initial connect: {_newActiveNodes}, " + $"Current candidate peers: {_peerPool.PeerCount}, Current active peers: {activePeers.Count} " + $"[InOut: {activePeers.Count(x => x.Value.OutSession is not null && x.Value.InSession is not null)} | " + @@ -320,11 +340,15 @@ private async Task RunPeerUpdateLoop() string nl = Environment.NewLine; _logger.Trace($"{nl}{nl}All active peers: {nl} {string.Join(nl, _peerPool.ActivePeers.Values.Select(x => $"{x.Node:s} | P2P: {_stats.GetOrAdd(x.Node).DidEventHappen(NodeStatsEventType.P2PInitialized)} | Eth62: {_stats.GetOrAdd(x.Node).DidEventHappen(NodeStatsEventType.Eth62Initialized)} | {_stats.GetOrAdd(x.Node).P2PNodeDetails?.ClientId} | {_stats.GetOrAdd(x.Node).ToString()}"))} {nl}{nl}"); } + + _logCounter++; } - _logCounter++; - if (EnsureAvailableActivePeerSlot()) + if (_peerPool.ActivePeerCount < MaxActivePeers) { + // We been though all the peers once, so wait TIME-WAIT additional delay before + // trying them again to avoid busy loop or exhausting sockets. + await Task.Delay(TIME_WAIT); _peerUpdateRequested.Set(); } @@ -346,7 +370,6 @@ private async Task RunPeerUpdateLoop() ++failCount; if (failCount >= 10) { - if (_logger.IsError) _logger.Error("Too much failure in peer update loop", e); break; } else @@ -357,34 +380,8 @@ private async Task RunPeerUpdateLoop() _peerUpdateTimer.Start(); } - - taskChannel.Writer.Complete(); - await Task.WhenAll(tasks); - } - - private bool EnsureAvailableActivePeerSlot() - { - if (AvailableActivePeersCount - _pending > 0) - { - return true; - } - - // Once the connection was established, the active peer count will increase, but it might - // not pass the handshake and the status check. So we wait for a bit to see if we can get - // the active peer count to go down within this time window. - DateTimeOffset deadline = DateTimeOffset.Now + Timeouts.Handshake + - TimeSpan.FromMilliseconds(_networkConfig.ConnectTimeoutMs); - while (DateTimeOffset.Now < deadline && (AvailableActivePeersCount - _pending) <= 0) - { - // The signal is not very reliable. So we just do like a simple pool. - _peerUpdateRequested.Reset(); - _peerUpdateRequested.Wait(TimeSpan.FromMilliseconds(100)); - } - - return AvailableActivePeersCount - _pending > 0; } - private static readonly IReadOnlyList _enumValues = FastEnum.GetValues(); private void SelectAndRankCandidates() @@ -620,12 +617,8 @@ public int Compare(PeerStats x, PeerStats y) #region Outgoing connection handling [Todo(Improve.MissingFunctionality, "Add cancellation support for the peer connection (so it does not wait for the 10sec timeout")] - private async Task SetupOutgoingPeerConnection(Peer peer, bool cancelIfThrottled = false) + private async Task SetupOutgoingPeerConnection(Peer peer) { - if (cancelIfThrottled && _outgoingConnectionRateLimiter.IsThrottled()) return; - - await _outgoingConnectionRateLimiter.WaitAsync(_cancellationTokenSource.Token); - // Can happen when In connection is received from the same peer and is initialized before we get here // In this case we do not initialize OUT connection if (!AddActivePeer(peer.Node.Id, peer, "upgrading candidate")) @@ -640,7 +633,6 @@ private async Task SetupOutgoingPeerConnection(Peer peer, bool cancelIfThrottled // for some time we will have a peer in active that has no session assigned - analyze this? Interlocked.Decrement(ref _pending); - _peerUpdateRequested.Set(); if (_logger.IsTrace) _logger.Trace($"Connecting to {_stats.GetCurrentReputation(peer.Node)} rep node - {result}, ACTIVE: {_peerPool.ActivePeerCount}, CAND: {_peerPool.PeerCount}"); if (!result) @@ -650,7 +642,7 @@ private async Task SetupOutgoingPeerConnection(Peer peer, bool cancelIfThrottled if (peer.OutSession is not null) { if (_logger.IsTrace) _logger.Trace($"Timeout, doing additional disconnect: {peer.Node.Id}"); - peer.OutSession?.MarkDisconnected(DisconnectReason.OutgoingConnectionFailed, DisconnectType.Local, "timeout"); + peer.OutSession?.MarkDisconnected(DisconnectReason.ReceiveMessageTimeout, DisconnectType.Local, "timeout"); } peer.IsAwaitingConnection = false; @@ -700,7 +692,7 @@ private void ProcessOutgoingConnection(ISession session) if (!_peerPool.ActivePeers.TryGetValue(id, out Peer peer)) { - session.MarkDisconnected(DisconnectReason.DuplicatedConnection, DisconnectType.Local, "peer removed"); + session.MarkDisconnected(DisconnectReason.DisconnectRequested, DisconnectType.Local, "peer removed"); return; } @@ -747,7 +739,7 @@ private void ProcessIncomingConnection(ISession session) if (initCount >= MaxActivePeers) { if (_logger.IsTrace) _logger.Trace($"Initiating disconnect with {session} {DisconnectReason.TooManyPeers} {DisconnectType.Local}"); - session.InitiateDisconnect(DisconnectReason.TooManyPeers, $"{initCount}"); + session.InitiateDisconnect(InitiateDisconnectReason.TooManyPeers, $"{initCount}"); return; } } @@ -882,7 +874,7 @@ private void AddSession(ISession session, Peer peer) if (newSessionIsIn && peerHasAnOpenInSession || newSessionIsOut && peerHasAnOpenOutSession) { if (_logger.IsDebug) _logger.Debug($"Disconnecting a {session} - already connected"); - session.InitiateDisconnect(DisconnectReason.SessionAlreadyExist, "same"); + session.InitiateDisconnect(InitiateDisconnectReason.SessionAlreadyExist, "same"); } else if (newSessionIsIn && peerHasAnOpenOutSession || newSessionIsOut && peerHasAnOpenInSession) { @@ -891,7 +883,7 @@ private void AddSession(ISession session, Peer peer) if (session.Direction != directionToKeep) { if (_logger.IsDebug) _logger.Debug($"Disconnecting a new {session} - {directionToKeep} session already connected"); - session.InitiateDisconnect(DisconnectReason.ReplacingSessionWithOppositeDirection, "same"); + session.InitiateDisconnect(InitiateDisconnectReason.ReplacingSessionWithOppositeDirection, "same"); if (newSessionIsIn) { peer.Stats.AddNodeStatsHandshakeEvent(ConnectionDirection.In); @@ -907,13 +899,13 @@ private void AddSession(ISession session, Peer peer) { peer.InSession = session; if (_logger.IsDebug) _logger.Debug($"Disconnecting an existing {session} - {directionToKeep} session to replace"); - peer.OutSession?.InitiateDisconnect(DisconnectReason.OppositeDirectionCleanup, "same"); + peer.OutSession?.InitiateDisconnect(InitiateDisconnectReason.OppositeDirectionCleanup, "same"); } else { peer.OutSession = session; if (_logger.IsDebug) _logger.Debug($"Disconnecting an existing {session} - {directionToKeep} session to replace"); - peer.InSession?.InitiateDisconnect(DisconnectReason.OppositeDirectionCleanup, "same"); + peer.InSession?.InitiateDisconnect(InitiateDisconnectReason.OppositeDirectionCleanup, "same"); } } } diff --git a/src/Nethermind/Nethermind.Network/PeerPool.cs b/src/Nethermind/Nethermind.Network/PeerPool.cs index e4958a54a24..e9d1e1e03fa 100644 --- a/src/Nethermind/Nethermind.Network/PeerPool.cs +++ b/src/Nethermind/Nethermind.Network/PeerPool.cs @@ -124,8 +124,8 @@ public bool TryRemove(PublicKey id, out Peer peer) if (Peers.TryRemove(id, out peer)) { _staticPeers.TryRemove(id, out _); - peer.InSession?.MarkDisconnected(DisconnectReason.PeerRemoved, DisconnectType.Local, "admin_removePeer"); - peer.OutSession?.MarkDisconnected(DisconnectReason.PeerRemoved, DisconnectType.Local, "admin_removePeer"); + peer.InSession?.MarkDisconnected(DisconnectReason.DisconnectRequested, DisconnectType.Local, "admin_removePeer"); + peer.OutSession?.MarkDisconnected(DisconnectReason.DisconnectRequested, DisconnectType.Local, "admin_removePeer"); peer.InSession = null; peer.OutSession = null; PeerRemoved?.Invoke(this, new PeerEventArgs(peer)); diff --git a/src/Nethermind/Nethermind.Network/ProtocolValidator.cs b/src/Nethermind/Nethermind.Network/ProtocolValidator.cs index 41e855a05d4..6c41ce3c1f4 100644 --- a/src/Nethermind/Nethermind.Network/ProtocolValidator.cs +++ b/src/Nethermind/Nethermind.Network/ProtocolValidator.cs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; +using System.Linq; using Nethermind.Blockchain; using Nethermind.Core; using Nethermind.Core.Attributes; @@ -43,7 +45,7 @@ public bool DisconnectOnInvalid(string protocol, ISession session, ProtocolIniti private bool ValidateP2PProtocol(ISession session, ProtocolInitializedEventArgs eventArgs) { P2PProtocolInitializedEventArgs args = (P2PProtocolInitializedEventArgs)eventArgs; - return ValidateP2PVersion(args.P2PVersion) || Disconnect(session, DisconnectReason.IncompatibleP2PVersion, CompatibilityValidationType.P2PVersion, $"p2p.{args.P2PVersion}"); + return ValidateP2PVersion(args.P2PVersion) || Disconnect(session, InitiateDisconnectReason.IncompatibleP2PVersion, CompatibilityValidationType.P2PVersion, $"p2p.{args.P2PVersion}"); } private bool ValidateEthProtocol(ISession session, ProtocolInitializedEventArgs eventArgs) @@ -51,30 +53,30 @@ private bool ValidateEthProtocol(ISession session, ProtocolInitializedEventArgs SyncPeerProtocolInitializedEventArgs syncPeerArgs = (SyncPeerProtocolInitializedEventArgs)eventArgs; if (!ValidateNetworkId(syncPeerArgs.NetworkId)) { - return Disconnect(session, DisconnectReason.InvalidNetworkId, CompatibilityValidationType.NetworkId, $"invalid network id - {syncPeerArgs.NetworkId}", + return Disconnect(session, InitiateDisconnectReason.InvalidNetworkId, CompatibilityValidationType.NetworkId, $"invalid network id - {syncPeerArgs.NetworkId}", _logger.IsTrace ? $", different networkId: {BlockchainIds.GetBlockchainName(syncPeerArgs.NetworkId)}, our networkId: {BlockchainIds.GetBlockchainName(_blockTree.NetworkId)}" : ""); } if (syncPeerArgs.GenesisHash != _blockTree.Genesis.Hash) { - return Disconnect(session, DisconnectReason.InvalidGenesis, CompatibilityValidationType.DifferentGenesis, "invalid genesis", + return Disconnect(session, InitiateDisconnectReason.InvalidGenesis, CompatibilityValidationType.DifferentGenesis, "invalid genesis", _logger.IsTrace ? $", different genesis hash: {syncPeerArgs.GenesisHash}, our: {_blockTree.Genesis.Hash}" : ""); } if (syncPeerArgs.ForkId == null) { - return Disconnect(session, DisconnectReason.MissingForkId, CompatibilityValidationType.MissingForkId, "missing fork id"); + return Disconnect(session, InitiateDisconnectReason.MissingForkId, CompatibilityValidationType.MissingForkId, "missing fork id"); } if (_forkInfo.ValidateForkId(syncPeerArgs.ForkId.Value, _blockTree.Head?.Header) != ValidationResult.Valid) { - return Disconnect(session, DisconnectReason.InvalidForkId, CompatibilityValidationType.InvalidForkId, "invalid fork id"); + return Disconnect(session, InitiateDisconnectReason.InvalidForkId, CompatibilityValidationType.InvalidForkId, "invalid fork id"); } return true; } - private bool Disconnect(ISession session, DisconnectReason reason, CompatibilityValidationType type, string details, string traceDetails = "") + private bool Disconnect(ISession session, InitiateDisconnectReason reason, CompatibilityValidationType type, string details, string traceDetails = "") { if (_logger.IsTrace) _logger.Trace($"Initiating disconnect with peer: {session.RemoteNodeId}, {details}{traceDetails}"); _nodeStatsManager.ReportFailedValidation(session.Node, type); diff --git a/src/Nethermind/Nethermind.Network/ProtocolsManager.cs b/src/Nethermind/Nethermind.Network/ProtocolsManager.cs index 19adae3089c..d19184c7878 100644 --- a/src/Nethermind/Nethermind.Network/ProtocolsManager.cs +++ b/src/Nethermind/Nethermind.Network/ProtocolsManager.cs @@ -5,17 +5,16 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Numerics; -using System.Text.RegularExpressions; using Nethermind.Config; using Nethermind.Consensus; +using Nethermind.Core.Specs; using Nethermind.Logging; -using Nethermind.Network.Config; using Nethermind.Network.Contract.P2P; using Nethermind.Network.P2P; using Nethermind.Network.P2P.EventArg; using Nethermind.Network.P2P.Messages; using Nethermind.Network.P2P.ProtocolHandlers; -using Nethermind.Network.P2P.Subprotocols.Eth; +using Nethermind.Network.P2P.Subprotocols.Eth.V65; using Nethermind.Network.P2P.Subprotocols.Eth.V66; using Nethermind.Network.P2P.Subprotocols.Eth.V67; using Nethermind.Network.P2P.Subprotocols.Eth.V68; @@ -28,7 +27,6 @@ using Nethermind.Synchronization; using Nethermind.Synchronization.Peers; using Nethermind.TxPool; -using ShouldGossip = Nethermind.TxPool.ShouldGossip; namespace Nethermind.Network { @@ -52,14 +50,11 @@ public class ProtocolsManager : IProtocolsManager private readonly INetworkStorage _peerStorage; private readonly ForkInfo _forkInfo; private readonly IGossipPolicy _gossipPolicy; - private readonly ITxGossipPolicy _txGossipPolicy; - private readonly INetworkConfig _networkConfig; private readonly ILogManager _logManager; private readonly ILogger _logger; private readonly IDictionary> _protocolFactories; private readonly HashSet _capabilities = new(); - private readonly Regex? _clientIdPattern; - public event EventHandler? P2PProtocolInitialized; + public event EventHandler P2PProtocolInitialized; public ProtocolsManager( ISyncPeerPool syncPeerPool, @@ -74,9 +69,7 @@ public ProtocolsManager( INetworkStorage peerStorage, ForkInfo forkInfo, IGossipPolicy gossipPolicy, - INetworkConfig networkConfig, - ILogManager logManager, - ITxGossipPolicy? transactionsGossipPolicy = null) + ILogManager logManager) { _syncPool = syncPeerPool ?? throw new ArgumentNullException(nameof(syncPeerPool)); _syncServer = syncServer ?? throw new ArgumentNullException(nameof(syncServer)); @@ -90,16 +83,9 @@ public ProtocolsManager( _peerStorage = peerStorage ?? throw new ArgumentNullException(nameof(peerStorage)); _forkInfo = forkInfo ?? throw new ArgumentNullException(nameof(forkInfo)); _gossipPolicy = gossipPolicy ?? throw new ArgumentNullException(nameof(gossipPolicy)); - _txGossipPolicy = transactionsGossipPolicy ?? ShouldGossip.Instance; _logManager = logManager ?? throw new ArgumentNullException(nameof(logManager)); - _networkConfig = networkConfig ?? throw new ArgumentNullException(nameof(networkConfig)); _logger = _logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); - if (networkConfig.ClientIdMatcher != null) - { - _clientIdPattern = new Regex(networkConfig.ClientIdMatcher, RegexOptions.Compiled); - } - _protocolFactories = GetProtocolFactories(); rlpxHost.SessionCreated += SessionCreated; } @@ -188,7 +174,7 @@ private IDictionary> GetProtocolFa { [Protocol.P2P] = (session, _) => { - P2PProtocolHandler handler = new(session, _rlpxHost.LocalNodeId, _stats, _serializer, _clientIdPattern, _logManager); + P2PProtocolHandler handler = new(session, _rlpxHost.LocalNodeId, _stats, _serializer, _logManager); session.PingSender = handler; InitP2PProtocol(session, handler); @@ -198,9 +184,9 @@ private IDictionary> GetProtocolFa { var ethHandler = version switch { - 66 => new Eth66ProtocolHandler(session, _serializer, _stats, _syncServer, _txPool, _pooledTxsRequestor, _gossipPolicy, _forkInfo, _logManager, _txGossipPolicy), - 67 => new Eth67ProtocolHandler(session, _serializer, _stats, _syncServer, _txPool, _pooledTxsRequestor, _gossipPolicy, _forkInfo, _logManager, _txGossipPolicy), - 68 => new Eth68ProtocolHandler(session, _serializer, _stats, _syncServer, _txPool, _pooledTxsRequestor, _gossipPolicy, _forkInfo, _logManager, _txGossipPolicy), + 66 => new Eth66ProtocolHandler(session, _serializer, _stats, _syncServer, _txPool, _pooledTxsRequestor, _gossipPolicy, _forkInfo, _logManager), + 67 => new Eth67ProtocolHandler(session, _serializer, _stats, _syncServer, _txPool, _pooledTxsRequestor, _gossipPolicy, _forkInfo, _logManager), + 68 => new Eth68ProtocolHandler(session, _serializer, _stats, _syncServer, _txPool, _pooledTxsRequestor, _gossipPolicy, _forkInfo, _logManager), _ => throw new NotSupportedException($"Eth protocol version {version} is not supported.") }; @@ -356,7 +342,7 @@ private void InitSyncPeerProtocol(ISession session, SyncPeerProtocolHandlerBase else { if (_logger.IsTrace) _logger.Trace($"Not able to add a sync peer on {session} for {session.Node:s}"); - session.InitiateDisconnect(DisconnectReason.SessionIdAlreadyExists, "sync peer"); + session.InitiateDisconnect(InitiateDisconnectReason.SessionIdAlreadyExists, "sync peer"); } if (_logger.IsTrace) _logger.Trace($"Finalized {handler.ProtocolCode.ToUpper()} protocol initialization on {session} - adding sync peer {session.Node:s}"); diff --git a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckEip8MessageSerializer.cs b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckEip8MessageSerializer.cs index 1151e16baca..ca0fadf37e5 100644 --- a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckEip8MessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckEip8MessageSerializer.cs @@ -3,6 +3,7 @@ using DotNetty.Buffers; using Nethermind.Core.Crypto; +using Nethermind.Network.P2P; using Nethermind.Serialization.Rlp; namespace Nethermind.Network.Rlpx.Handshake diff --git a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckMessageSerializer.cs b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckMessageSerializer.cs index 27190620f79..2805a864986 100644 --- a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckMessageSerializer.cs @@ -4,6 +4,7 @@ using System; using DotNetty.Buffers; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Serialization.Rlp; namespace Nethermind.Network.Rlpx.Handshake diff --git a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AuthEip8MessageSerializer.cs b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AuthEip8MessageSerializer.cs index 8b7f3d22d29..24f55aea56f 100644 --- a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AuthEip8MessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AuthEip8MessageSerializer.cs @@ -5,6 +5,7 @@ using DotNetty.Buffers; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Network.P2P; using Nethermind.Serialization.Rlp; namespace Nethermind.Network.Rlpx.Handshake diff --git a/src/Nethermind/Nethermind.Network/Rlpx/RlpxHost.cs b/src/Nethermind/Nethermind.Network/Rlpx/RlpxHost.cs index 92e24bc886b..dfd28ba4c6d 100644 --- a/src/Nethermind/Nethermind.Network/Rlpx/RlpxHost.cs +++ b/src/Nethermind/Nethermind.Network/Rlpx/RlpxHost.cs @@ -6,6 +6,8 @@ using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; +using DotNetty.Buffers; +using DotNetty.Codecs; using DotNetty.Common.Concurrency; using DotNetty.Handlers.Logging; using DotNetty.Transport.Bootstrapping; @@ -237,7 +239,7 @@ private void InitializeChannel(IChannel channel, ISession session) await Task.Delay(TimeSpan.FromSeconds(1)); if (_logger.IsTrace) _logger.Trace($"|NetworkTrace| {session} channel disconnected"); - session.MarkDisconnected(DisconnectReason.ConnectionClosed, DisconnectType.Remote, "channel disconnected"); + session.MarkDisconnected(DisconnectReason.TcpSubSystemError, DisconnectType.Remote, "channel disconnected"); }); } diff --git a/src/Nethermind/Nethermind.Network/Rlpx/ZeroPacket.cs b/src/Nethermind/Nethermind.Network/Rlpx/ZeroPacket.cs index 3e8bde45501..d599c1fcc1a 100644 --- a/src/Nethermind/Nethermind.Network/Rlpx/ZeroPacket.cs +++ b/src/Nethermind/Nethermind.Network/Rlpx/ZeroPacket.cs @@ -1,7 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using DotNetty.Buffers; +using DotNetty.Common.Utilities; namespace Nethermind.Network.Rlpx { diff --git a/src/Nethermind/Nethermind.Network/Rlpx/ZeroPacketSplitter.cs b/src/Nethermind/Nethermind.Network/Rlpx/ZeroPacketSplitter.cs index 66cc1cc9ce2..6d989f9bca3 100644 --- a/src/Nethermind/Nethermind.Network/Rlpx/ZeroPacketSplitter.cs +++ b/src/Nethermind/Nethermind.Network/Rlpx/ZeroPacketSplitter.cs @@ -8,6 +8,7 @@ using DotNetty.Transport.Channels; using Nethermind.Core.Attributes; using Nethermind.Logging; +using Nethermind.Network.P2P; using Nethermind.Serialization.Rlp; namespace Nethermind.Network.Rlpx diff --git a/src/Nethermind/Nethermind.Network/SnapCapabilitySwitcher.cs b/src/Nethermind/Nethermind.Network/SnapCapabilitySwitcher.cs index f53993f2e61..f4053b45c75 100644 --- a/src/Nethermind/Nethermind.Network/SnapCapabilitySwitcher.cs +++ b/src/Nethermind/Nethermind.Network/SnapCapabilitySwitcher.cs @@ -5,6 +5,7 @@ using System; using Nethermind.Logging; using Nethermind.Network.Contract.P2P; +using Nethermind.Network.P2P; using Nethermind.Stats.Model; using Nethermind.Synchronization.ParallelSync; @@ -22,7 +23,7 @@ public SnapCapabilitySwitcher(IProtocolsManager? protocolsManager, ISyncModeSele { _protocolsManager = protocolsManager ?? throw new ArgumentNullException(nameof(protocolsManager)); _syncModeSelector = syncModeSelector ?? throw new ArgumentNullException(nameof(syncModeSelector)); - _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); + _logger = logManager.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); } /// diff --git a/src/Nethermind/Nethermind.Network/ZeroMessageSerializerExtensions.cs b/src/Nethermind/Nethermind.Network/ZeroMessageSerializerExtensions.cs index a46e231ae82..0c8aef9b66b 100644 --- a/src/Nethermind/Nethermind.Network/ZeroMessageSerializerExtensions.cs +++ b/src/Nethermind/Nethermind.Network/ZeroMessageSerializerExtensions.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using DotNetty.Buffers; using DotNetty.Common.Utilities; using Nethermind.Serialization.Rlp; diff --git a/src/Nethermind/Nethermind.Overseer.Test/AuRaTest.cs b/src/Nethermind/Nethermind.Overseer.Test/AuRaTest.cs index 2687a001c84..770dae4cc7b 100644 --- a/src/Nethermind/Nethermind.Overseer.Test/AuRaTest.cs +++ b/src/Nethermind/Nethermind.Overseer.Test/AuRaTest.cs @@ -1,10 +1,17 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Globalization; using System.Linq; using System.Threading.Tasks; using FluentAssertions; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; +using Nethermind.JsonRpc.Data; +using Nethermind.JsonRpc.Modules.Eth; using Nethermind.Overseer.Test.Framework; +using Newtonsoft.Json; using NUnit.Framework; namespace Nethermind.Overseer.Test diff --git a/src/Nethermind/Nethermind.Overseer.Test/CliqueTests.cs b/src/Nethermind/Nethermind.Overseer.Test/CliqueTests.cs index 5088be5b61f..26ade3a7214 100644 --- a/src/Nethermind/Nethermind.Overseer.Test/CliqueTests.cs +++ b/src/Nethermind/Nethermind.Overseer.Test/CliqueTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading.Tasks; +using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Crypto; using Nethermind.JsonRpc.Data; diff --git a/src/Nethermind/Nethermind.Overseer.Test/Framework/ProcessBuilder.cs b/src/Nethermind/Nethermind.Overseer.Test/Framework/ProcessBuilder.cs index 03bda2e92e9..7dcfd2c6d53 100644 --- a/src/Nethermind/Nethermind.Overseer.Test/Framework/ProcessBuilder.cs +++ b/src/Nethermind/Nethermind.Overseer.Test/Framework/ProcessBuilder.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.Runtime.InteropServices; +using Nethermind.Core.Crypto; using Nethermind.Crypto; using Nethermind.Overseer.Test.JsonRpc; using NUnit.Framework; @@ -20,10 +21,10 @@ public NethermindProcessWrapper Create(string name, string workingDirectory, str process.Exited += ProcessOnExited; process.StartInfo.WorkingDirectory = workingDirectory; process.StartInfo.FileName = "dotnet"; - var arguments = $"nethermind.dll -c {config} --JsonRpc.Port {httpPort} --Network.P2PPort {p2pPort} --Network.DiscoveryPort {p2pPort} --KeyStore.TestNodeKey {nodeKey}"; + var arguments = $"Nethermind.Runner.dll --config {config} --JsonRpc.Port {httpPort} --Network.P2PPort {p2pPort} --Network.DiscoveryPort {p2pPort} --KeyStore.TestNodeKey {nodeKey}"; if (!string.IsNullOrEmpty(dbPath)) { - arguments = $"{arguments} -d {dbPath}"; + arguments = $"{arguments} --baseDbPath {dbPath}"; } if (!string.IsNullOrEmpty(bootnode)) diff --git a/src/Nethermind/Nethermind.Overseer.Test/Framework/TestBuilder.cs b/src/Nethermind/Nethermind.Overseer.Test/Framework/TestBuilder.cs index c4aa9fa8e98..efa5f1b320d 100644 --- a/src/Nethermind/Nethermind.Overseer.Test/Framework/TestBuilder.cs +++ b/src/Nethermind/Nethermind.Overseer.Test/Framework/TestBuilder.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Nethermind.Core.Extensions; using Nethermind.Overseer.Test.Framework.Steps; diff --git a/src/Nethermind/Nethermind.Overseer.Test/JsonRpc/JsonRpcClient.cs b/src/Nethermind/Nethermind.Overseer.Test/JsonRpc/JsonRpcClient.cs index 2611cf8bbb0..9c81fcb707a 100644 --- a/src/Nethermind/Nethermind.Overseer.Test/JsonRpc/JsonRpcClient.cs +++ b/src/Nethermind/Nethermind.Overseer.Test/JsonRpc/JsonRpcClient.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Net; using System.Net.Http; using System.Text; using System.Threading.Tasks; diff --git a/src/Nethermind/Nethermind.PerfTest/Program.cs b/src/Nethermind/Nethermind.PerfTest/Program.cs index 03e39859f9e..7902f163b19 100644 --- a/src/Nethermind/Nethermind.PerfTest/Program.cs +++ b/src/Nethermind/Nethermind.PerfTest/Program.cs @@ -254,7 +254,7 @@ private static async Task RunBenchmarkBlocks() /* load spec */ ChainSpecLoader loader = new ChainSpecLoader(new EthereumJsonSerializer()); - string path = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"chainspec", "goerli.json")); + string path = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"chainspec", "ropsten.json")); _logger.Info($"Loading ChainSpec from {path}"); ChainSpec chainSpec = loader.Load(File.ReadAllText(path)); _logger.Info($"ChainSpec loaded"); diff --git a/src/Nethermind/Nethermind.Precompiles.Benchmark/Blake2fBenchmark.cs b/src/Nethermind/Nethermind.Precompiles.Benchmark/Blake2fBenchmark.cs index 87c865f5d66..bdaa925af43 100644 --- a/src/Nethermind/Nethermind.Precompiles.Benchmark/Blake2fBenchmark.cs +++ b/src/Nethermind/Nethermind.Precompiles.Benchmark/Blake2fBenchmark.cs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Evm.Precompiles; namespace Nethermind.Precompiles.Benchmark diff --git a/src/Nethermind/Nethermind.Precompiles.Benchmark/KeccakBenchmark.cs b/src/Nethermind/Nethermind.Precompiles.Benchmark/KeccakBenchmark.cs index 844c4a6dde1..e65f7fa55c2 100644 --- a/src/Nethermind/Nethermind.Precompiles.Benchmark/KeccakBenchmark.cs +++ b/src/Nethermind/Nethermind.Precompiles.Benchmark/KeccakBenchmark.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Core.Crypto; namespace Nethermind.Precompiles.Benchmark diff --git a/src/Nethermind/Nethermind.Precompiles.Benchmark/ModExpBenchmark.cs b/src/Nethermind/Nethermind.Precompiles.Benchmark/ModExpBenchmark.cs index 9f60de0910f..6ce1ee5f410 100644 --- a/src/Nethermind/Nethermind.Precompiles.Benchmark/ModExpBenchmark.cs +++ b/src/Nethermind/Nethermind.Precompiles.Benchmark/ModExpBenchmark.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; using Nethermind.Evm.Precompiles; namespace Nethermind.Precompiles.Benchmark diff --git a/src/Nethermind/Nethermind.Precompiles.Benchmark/PointEvaluationBenchmark.cs b/src/Nethermind/Nethermind.Precompiles.Benchmark/PointEvaluationBenchmark.cs index 5673479be57..09b06902e91 100644 --- a/src/Nethermind/Nethermind.Precompiles.Benchmark/PointEvaluationBenchmark.cs +++ b/src/Nethermind/Nethermind.Precompiles.Benchmark/PointEvaluationBenchmark.cs @@ -2,18 +2,12 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; -using System.Threading.Tasks; -using BenchmarkDotNet.Attributes; -using Nethermind.Crypto; using Nethermind.Evm.Precompiles; namespace Nethermind.Precompiles.Benchmark; public class PointEvaluationBenchmark : PrecompileBenchmarkBase { - [GlobalSetup] - public async Task GlobalSetup() => await KzgPolynomialCommitments.InitializeAsync(); - protected override IEnumerable Precompiles => new[] { PointEvaluationPrecompile.Instance }; protected override string InputsDirectory => "point_evaluation"; } diff --git a/src/Nethermind/Nethermind.Precompiles.Benchmark/PrecompileBenchmarkBase.cs b/src/Nethermind/Nethermind.Precompiles.Benchmark/PrecompileBenchmarkBase.cs index 1e50a065d5e..63cb0501efd 100644 --- a/src/Nethermind/Nethermind.Precompiles.Benchmark/PrecompileBenchmarkBase.cs +++ b/src/Nethermind/Nethermind.Precompiles.Benchmark/PrecompileBenchmarkBase.cs @@ -10,6 +10,7 @@ using Nethermind.Core.Extensions; using Nethermind.Evm.Precompiles; using Nethermind.Serialization.Json; +using Nethermind.Specs; using Nethermind.Specs.Forks; namespace Nethermind.Precompiles.Benchmark diff --git a/src/Nethermind/Nethermind.Precompiles.Benchmark/RipEmdBenchmark.cs b/src/Nethermind/Nethermind.Precompiles.Benchmark/RipEmdBenchmark.cs index 4936e94af0f..c6b38dead86 100644 --- a/src/Nethermind/Nethermind.Precompiles.Benchmark/RipEmdBenchmark.cs +++ b/src/Nethermind/Nethermind.Precompiles.Benchmark/RipEmdBenchmark.cs @@ -2,6 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Diagnostics.Windows.Configs; +using BenchmarkDotNet.Jobs; using Nethermind.Evm.Precompiles; namespace Nethermind.Precompiles.Benchmark diff --git a/src/Nethermind/Nethermind.Precompiles.Benchmark/Sha256Benchmark.cs b/src/Nethermind/Nethermind.Precompiles.Benchmark/Sha256Benchmark.cs index c0fc5542326..c485531b939 100644 --- a/src/Nethermind/Nethermind.Precompiles.Benchmark/Sha256Benchmark.cs +++ b/src/Nethermind/Nethermind.Precompiles.Benchmark/Sha256Benchmark.cs @@ -2,6 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Diagnostics.Windows.Configs; +using BenchmarkDotNet.Jobs; using Nethermind.Evm.Precompiles; namespace Nethermind.Precompiles.Benchmark diff --git a/src/Nethermind/Nethermind.Runner.Test/ChainspecFilesTests.cs b/src/Nethermind/Nethermind.Runner.Test/ChainspecFilesTests.cs index 7ea6dd028b4..8a57400673c 100644 --- a/src/Nethermind/Nethermind.Runner.Test/ChainspecFilesTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/ChainspecFilesTests.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using Nethermind.Specs.ChainSpecStyle; using Nethermind.Serialization.Json; +using NSubstitute.ExceptionExtensions; namespace Nethermind.Runner.Test { diff --git a/src/Nethermind/Nethermind.Runner.Test/ConfigFilesTests.cs b/src/Nethermind/Nethermind.Runner.Test/ConfigFilesTests.cs index 6cb75b1de3e..92f7de461a8 100644 --- a/src/Nethermind/Nethermind.Runner.Test/ConfigFilesTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/ConfigFilesTests.cs @@ -2,17 +2,22 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; +using System.Threading.Tasks; using FluentAssertions; using Nethermind.Analytics; using Nethermind.Api; using Nethermind.Blockchain.Synchronization; using Nethermind.Config; using Nethermind.Config.Test; +using Nethermind.Core; using Nethermind.Db; using Nethermind.EthStats; +using Nethermind.Grpc; using Nethermind.JsonRpc; using Nethermind.Monitoring.Config; using Nethermind.Network.Config; @@ -20,6 +25,7 @@ using Nethermind.Db.Rocks.Config; using Nethermind.Init; using Nethermind.Logging; +using Nethermind.Merge.Plugin; using Nethermind.TxPool; using NUnit.Framework; @@ -72,12 +78,12 @@ public void Networking_is_disabled_when_needed(string configWildcard, bool isEna Test(configWildcard, c => c.NetworkingEnabled, isEnabled); } - [TestCase("sepolia", "ws://localhost:3000/api")] + [TestCase("ropsten", "ws://localhost:3000/api")] [TestCase("rinkeby", "ws://localhost:3000/api")] [TestCase("goerli", "wss://stats.goerli.net/api")] [TestCase("mainnet", "wss://ethstats.net/api")] [TestCase("poacore", "ws://localhost:3000/api")] - [TestCase("gnosis", "ws://localhost:3000/api")] + [TestCase("xdai", "ws://localhost:3000/api")] [TestCase("spaceneth", "ws://localhost:3000/api")] [TestCase("volta", "ws://localhost:3000/api")] public void Ethstats_values_are_correct(string configWildcard, string host) @@ -89,17 +95,19 @@ public void Ethstats_values_are_correct(string configWildcard, string host) } [TestCase("aura ^archive", false)] + [TestCase("ethhash", true)] [TestCase("clique", true)] public void Geth_limits_configs_are_correct(string configWildcard, bool useGethLimitsInFastSync) { Test(configWildcard, c => c.UseGethLimitsInFastBlocks, useGethLimitsInFastSync); } + [TestCase("ropsten", "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d")] [TestCase("rinkeby", "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")] [TestCase("goerli", "0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a")] [TestCase("mainnet", "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")] [TestCase("poacore", "0x39f02c003dde5b073b3f6e1700fc0b84b4877f6839bb23edadd3d2d82a488634")] - [TestCase("gnosis", "0x4f1dd23188aab3a76b463e4af801b52b1248ef073c648cbdc4c9333d3da79756")] + [TestCase("xdai", "0x4f1dd23188aab3a76b463e4af801b52b1248ef073c648cbdc4c9333d3da79756")] [TestCase("volta", "0xebd8b413ca7b7f84a8dd20d17519ce2b01954c74d94a0a739a3e416abe0e43e5")] public void Genesis_hash_is_correct(string configWildcard, string genesisHash) { @@ -120,6 +128,13 @@ public void Eth_stats_disabled_by_default(string configWildcard) Test(configWildcard, c => c.Enabled, false); } + [TestCase("^ndm", false)] + [TestCase("ndm", true)] + public void Grpc_defaults(string configWildcard, bool expectedDefault) + { + Test(configWildcard, c => c.Enabled, expectedDefault); + } + [TestCase("*")] public void Analytics_defaults(string configWildcard) { @@ -153,8 +168,10 @@ public void Cache_state_index(string configWildcard, bool expectedValue) [TestCase("goerli ^archive", 768000000)] [TestCase("rinkeby archive", 1536000000)] [TestCase("rinkeby ^archive", 1024000000)] - [TestCase("gnosis archive", 1024000000)] - [TestCase("gnosis ^archive", 768000000)] + [TestCase("ropsten archive", 1536000000)] + [TestCase("ropsten ^archive", 1024000000)] + [TestCase("xdai archive", 1024000000)] + [TestCase("xdai ^archive", 768000000)] [TestCase("poacore archive", 1024000000)] [TestCase("poacore ^archive", 768000000)] [TestCase("spaceneth.cfg", 64000000)] @@ -193,11 +210,12 @@ public void Network_diag_tracer_disabled_by_default(string configWildcard) } [TestCase("mainnet", 2048)] + [TestCase("xdai", 2048)] [TestCase("gnosis", 2048)] [TestCase("poacore", 2048)] [TestCase("energy", 2048)] [TestCase("chiado", 2048)] - [TestCase("^mainnet ^spaceneth ^volta ^energy ^poacore ^gnosis ^chiado", 1024)] + [TestCase("^mainnet ^spaceneth ^volta ^energy ^poacore ^xdai ^gnosis ^chiado", 1024)] [TestCase("spaceneth", 128)] public void Tx_pool_defaults_are_correct(string configWildcard, int poolSize) { @@ -205,12 +223,14 @@ public void Tx_pool_defaults_are_correct(string configWildcard, int poolSize) } [TestCase("spaceneth", true)] + [TestCase("ropsten", true)] [TestCase("goerli", true)] + [TestCase("xdai", true)] [TestCase("gnosis", true)] [TestCase("mainnet", true)] [TestCase("sepolia", true)] [TestCase("chiado", true)] - [TestCase("^spaceneth ^goerli ^mainnet ^gnosis ^sepolia ^chiado", false)] + [TestCase("^spaceneth ^ropsten ^goerli ^mainnet ^xdai ^gnosis ^sepolia ^chiado", false)] public void Json_defaults_are_correct(string configWildcard, bool jsonEnabled) { Test(configWildcard, c => c.Enabled, jsonEnabled); @@ -238,17 +258,19 @@ public void Fast_sync_settings_as_expected(string configWildcard, bool downloadB [TestCase("archive", false)] [TestCase("mainnet.cfg", true)] [TestCase("goerli.cfg", true)] + [TestCase("ropsten.cfg", true)] [TestCase("rinkeby.cfg", false)] [TestCase("sepolia.cfg", true)] - [TestCase("gnosis.cfg", false)] + [TestCase("xdai.cfg", false)] public void Snap_sync_settings_as_expected(string configWildcard, bool enabled) { Test(configWildcard, c => c.SnapSync, enabled); } - [TestCase("^aura ^sepolia ^goerli ^mainnet", false)] + [TestCase("^aura ^ropsten ^sepolia ^goerli ^mainnet", false)] [TestCase("aura ^archive", true)] [TestCase("^archive ^rinkeby ^spaceneth", true)] + [TestCase("ropsten ^archive", true)] [TestCase("sepolia ^archive", true)] [TestCase("goerli ^archive", true)] [TestCase("mainnet ^archive", true)] @@ -306,12 +328,13 @@ public void Clique_pivots_divide_by_30000_epoch_length(string configWildcard) Test(configWildcard, c => (int)(c.PivotNumberParsed % 30000L), (s, p) => p.Should().Be(0)); } + [TestCase("ropsten", false)] [TestCase("rinkeby", false)] [TestCase("goerli", false)] [TestCase("mainnet_archive.cfg", true)] [TestCase("mainnet.cfg", true)] [TestCase("poacore", true)] - [TestCase("gnosis", true)] + [TestCase("xdai", true)] [TestCase("volta", false)] public void Basic_configs_are_as_expected(string configWildcard, bool isProduction = false) { @@ -330,14 +353,15 @@ public void Basic_configs_are_as_expected(string configWildcard, bool isProducti } + [TestCase("ropsten")] [TestCase("rinkeby")] [TestCase("goerli", new[] { 16, 16, 16, 16 })] [TestCase("mainnet")] [TestCase("poacore.cfg", new[] { 16, 16, 16, 16 })] [TestCase("poacore_archive.cfg", new[] { 16, 16, 16, 16 })] [TestCase("poacore_validator.cfg", null, false)] - [TestCase("gnosis.cfg", new[] { 16, 16, 16 })] - [TestCase("gnosis_archive.cfg", new[] { 16, 16, 16 })] + [TestCase("xdai.cfg", new[] { 16, 16, 16 })] + [TestCase("xdai_archive.cfg", new[] { 16, 16, 16 })] [TestCase("volta")] public void Bloom_configs_are_as_expected(string configWildcard, int[] levels = null, bool index = true) { @@ -361,10 +385,11 @@ public void Arena_order_is_default(string configWildcard) [TestCase("chiado", 30_000_000L, 5ul)] [TestCase("gnosis", 30_000_000L, 5ul)] + [TestCase("xdai", 30_000_000L, 5ul)] [TestCase("goerli", 30_000_000L)] [TestCase("mainnet", 30_000_000L)] [TestCase("sepolia", 30_000_000L)] - [TestCase("^chiado ^gnosis ^goerli ^mainnet ^sepolia")] + [TestCase("^chiado ^gnosis ^xdai ^goerli ^mainnet ^sepolia")] public void Blocks_defaults_are_correct(string configWildcard, long? targetBlockGasLimit = null, ulong secondsPerSlot = 12) { Test(configWildcard, c => c.TargetBlockGasLimit, targetBlockGasLimit); @@ -413,6 +438,8 @@ public void Memory_hint_is_enough(string configWildcard) protected override IEnumerable Configs { get; } = new HashSet { + "ropsten_archive.cfg", + "ropsten.cfg", "rinkeby_archive.cfg", "rinkeby.cfg", "goerli_archive.cfg", @@ -423,6 +450,8 @@ public void Memory_hint_is_enough(string configWildcard) "mainnet.cfg", "poacore.cfg", "poacore_archive.cfg", + "xdai.cfg", + "xdai_archive.cfg", "gnosis.cfg", "gnosis_archive.cfg", "spaceneth.cfg", diff --git a/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs b/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs index 2e1f9e53fc8..0874c1ff690 100644 --- a/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs +++ b/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs @@ -15,6 +15,7 @@ using Nethermind.Consensus.Producers; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; +using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Crypto; using Nethermind.Db; @@ -28,6 +29,7 @@ using Nethermind.JsonRpc.Modules.Eth.GasPrice; using Nethermind.KeyStore; using Nethermind.Monitoring; +using Nethermind.Network.Discovery; using Nethermind.Network.Rlpx; using Nethermind.Serialization.Json; using Nethermind.Specs.ChainSpecStyle; diff --git a/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/EthereumStepsManagerTests.cs b/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/EthereumStepsManagerTests.cs index 1a058d86cfa..427ad619029 100644 --- a/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/EthereumStepsManagerTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/EthereumStepsManagerTests.cs @@ -11,8 +11,11 @@ using Nethermind.Consensus.AuRa.InitializationSteps; using Nethermind.Init.Steps; using Nethermind.Logging; +using Nethermind.Runner.Ethereum.Api; +using Nethermind.Runner.Ethereum.Steps; using Nethermind.Serialization.Json; using Nethermind.Specs.ChainSpecStyle; +using NSubstitute.ExceptionExtensions; using NUnit.Framework; namespace Nethermind.Runner.Test.Ethereum.Steps diff --git a/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/Migrations/ReceiptMigrationTests.cs b/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/Migrations/ReceiptMigrationTests.cs index 500bf7f8b79..e5ffb418b31 100644 --- a/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/Migrations/ReceiptMigrationTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/Migrations/ReceiptMigrationTests.cs @@ -2,10 +2,12 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Threading; using FluentAssertions; -using Nethermind.Blockchain; +using Nethermind.Api; using Nethermind.Blockchain.Receipts; +using Nethermind.Config; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; @@ -14,8 +16,9 @@ using Nethermind.Db; using Nethermind.Init.Steps.Migrations; using Nethermind.Logging; -using Nethermind.Serialization.Rlp; -using Nethermind.State.Repositories; +using Nethermind.Serialization.Json; +using Nethermind.Specs.ChainSpecStyle; +using Nethermind.Synchronization; using Nethermind.Synchronization.ParallelSync; using NSubstitute; using NUnit.Framework; @@ -25,98 +28,65 @@ namespace Nethermind.Runner.Test.Ethereum.Steps.Migrations [TestFixture] public class ReceiptMigrationTests { - [TestCase(null, 0, false, false, false, false)] // No change to migrate - [TestCase(5, 5, false, false, false, true)] // Explicit command and partially migrated - [TestCase(null, 5, true, false, false, true)] // Partially migrated - [TestCase(5, 0, false, false, false, true)] // Explicit command - [TestCase(null, 0, true, false, false, true)] // Force reset - [TestCase(null, 0, false, false, true, true)] // Encoding mismatch - [TestCase(null, 0, false, true, false, true)] // Encoding mismatch - [TestCase(null, 0, false, true, true, false)] // Encoding match - public void RunMigration(int? commandStartBlockNumber, long currentMigratedBlockNumber, bool forceReset, bool receiptIsCompact, bool useCompactEncoding, bool wasMigrated) + [TestCase(null)] + [TestCase(5)] + public void RunMigration(int? migratedBlockNumber) { int chainLength = 10; - IReceiptConfig receiptConfig = new ReceiptConfig() + IConfigProvider configProvider = Substitute.For(); + BlockTreeBuilder blockTreeBuilder = Core.Test.Builders.Build.A.BlockTree().OfChainLength(chainLength); + InMemoryReceiptStorage inMemoryReceiptStorage = new() { MigratedBlockNumber = migratedBlockNumber is not null ? 0 : long.MaxValue }; + InMemoryReceiptStorage outMemoryReceiptStorage = new() { MigratedBlockNumber = migratedBlockNumber is not null ? 0 : long.MaxValue }; + NethermindApi context = new(configProvider, new EthereumJsonSerializer(), LimboLogs.Instance, new ChainSpec()) { - ForceReceiptsMigration = forceReset, - StoreReceipts = true, - ReceiptsMigration = true, - CompactReceiptStore = useCompactEncoding + ReceiptStorage = new TestReceiptStorage(inMemoryReceiptStorage, outMemoryReceiptStorage), + DbProvider = Substitute.For(), + BlockTree = blockTreeBuilder.TestObject, + Synchronizer = Substitute.For(), + ChainLevelInfoRepository = blockTreeBuilder.ChainLevelInfoRepository, + SyncModeSelector = Substitute.For() }; - BlockTreeBuilder blockTreeBuilder = Core.Test.Builders.Build.A.BlockTree().OfChainLength(chainLength); - IBlockTree blockTree = blockTreeBuilder.TestObject; - ChainLevelInfoRepository chainLevelInfoRepository = blockTreeBuilder.ChainLevelInfoRepository; - - InMemoryReceiptStorage inMemoryReceiptStorage = new(true) { MigratedBlockNumber = currentMigratedBlockNumber }; - InMemoryReceiptStorage outMemoryReceiptStorage = new(true) { MigratedBlockNumber = currentMigratedBlockNumber }; - TestReceiptStorage receiptStorage = new(inMemoryReceiptStorage, outMemoryReceiptStorage); - ReceiptArrayStorageDecoder receiptArrayStorageDecoder = new(receiptIsCompact); + configProvider.GetConfig().StoreReceipts.Returns(true); + configProvider.GetConfig().ReceiptsMigration.Returns(true); + context.SyncModeSelector.Current.Returns(SyncMode.WaitingForBlock); - ISyncModeSelector syncModeSelector = Substitute.For(); - syncModeSelector.Current.Returns(SyncMode.WaitingForBlock); - - // Insert the blocks int txIndex = 0; for (int i = 1; i < chainLength; i++) { - Block block = blockTree.FindBlock(i); + Block block = context.BlockTree.FindBlock(i); inMemoryReceiptStorage.Insert(block, new[] { - Core.Test.Builders.Build.A.Receipt.WithTransactionHash(TestItem.Keccaks[txIndex++]).TestObject, - Core.Test.Builders.Build.A.Receipt.WithTransactionHash(TestItem.Keccaks[txIndex++]).TestObject - }); + Core.Test.Builders.Build.A.Receipt.WithTransactionHash(TestItem.Keccaks[txIndex++]).TestObject, + Core.Test.Builders.Build.A.Receipt.WithTransactionHash(TestItem.Keccaks[txIndex++]).TestObject + }); } - TestMemColumnsDb receiptColumnDb = new(); + ManualResetEvent guard = new(false); + Keccak lastTransaction = TestItem.Keccaks[txIndex - 1]; - // Put the last block receipt encoding - Block lastBlock = blockTree.FindBlock(chainLength - 1); - TxReceipt[] receipts = inMemoryReceiptStorage.Get(lastBlock); - using (NettyRlpStream nettyStream = receiptArrayStorageDecoder.EncodeToNewNettyStream(receipts, RlpBehaviors.Storage)) + TestReceiptColumenDb receiptColumenDb = new(); + context.DbProvider.ReceiptsDb.Returns(receiptColumenDb); + receiptColumenDb.RemoveFunc = (key) => { - receiptColumnDb.GetColumnDb(ReceiptsColumns.Blocks) - .Set(Bytes.Concat(lastBlock.Number.ToBigEndianByteArray(), lastBlock.Hash.BytesToArray()), nettyStream.AsSpan()); - } + if (Bytes.AreEqual(key, lastTransaction.Bytes)) guard.Set(); + }; - ManualResetEvent guard = new(false); - ReceiptMigration migration = new( - receiptStorage, - new DisposableStack(), - blockTree, - syncModeSelector, - chainLevelInfoRepository, - receiptConfig, - receiptColumnDb, - Substitute.For(), - LimboLogs.Instance - ); - - if (commandStartBlockNumber.HasValue) + ReceiptMigration migration = new(context); + if (migratedBlockNumber.HasValue) { - _ = migration.Run(commandStartBlockNumber.Value); + _ = migration.Run(migratedBlockNumber.Value); } else { migration.Run(); } - migration._migrationTask?.Wait(); - Assert.That(() => outMemoryReceiptStorage.MigratedBlockNumber, Is.InRange(0, 1).After(1000, 10)); + guard.WaitOne(TimeSpan.FromSeconds(1)); + int txCount = ((migratedBlockNumber ?? chainLength) - 1 - 1) * 2; - if (wasMigrated) - { - int blockNum = (commandStartBlockNumber ?? chainLength) - 1 - 1; - int txCount = blockNum * 2; - receiptColumnDb - .KeyWasWritten((item => item.Item2 == null), txCount); - ((TestMemDb)receiptColumnDb.GetColumnDb(ReceiptsColumns.Blocks)).KeyWasRemoved((_ => true), blockNum); - outMemoryReceiptStorage.Count.Should().Be(txCount); - } - else - { - receiptColumnDb.KeyWasWritten((item => item.Item2 == null), 0); - } + receiptColumenDb.KeyWasRemoved(_ => true, txCount); + outMemoryReceiptStorage.Count.Should().Be(txCount); } private class TestReceiptStorage : IReceiptStorage @@ -137,7 +107,7 @@ public TestReceiptStorage(IReceiptStorage inStorage, IReceiptStorage outStorage) public TxReceipt[] Get(Keccak blockHash) => _inStorage.Get(blockHash); public bool CanGetReceiptsByHash(long blockNumber) => _inStorage.CanGetReceiptsByHash(blockNumber); - public bool TryGetReceiptsIterator(long blockNumber, Keccak blockHash, out ReceiptsIterator iterator) => _inStorage.TryGetReceiptsIterator(blockNumber, blockHash, out iterator); + public bool TryGetReceiptsIterator(long blockNumber, Keccak blockHash, out ReceiptsIterator iterator) => _outStorage.TryGetReceiptsIterator(blockNumber, blockHash, out iterator); public void Insert(Block block, TxReceipt[] txReceipts, bool ensureCanonical) => _outStorage.Insert(block, txReceipts); @@ -163,5 +133,15 @@ public void EnsureCanonical(Block block) public event EventHandler ReceiptsInserted { add { } remove { } } } + + class TestReceiptColumenDb : TestMemDb, IColumnsDb + { + public IDbWithSpan GetColumnDb(ReceiptsColumns key) + { + return this; + } + + public IEnumerable ColumnKeys { get; } + } } } diff --git a/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/RegisterRpcModulesTests.cs b/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/RegisterRpcModulesTests.cs index 7a9c32ba605..0430f7f0b3e 100644 --- a/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/RegisterRpcModulesTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/RegisterRpcModulesTests.cs @@ -10,6 +10,8 @@ using Nethermind.JsonRpc; using Nethermind.JsonRpc.Modules; using Nethermind.JsonRpc.Modules.Proof; +using Nethermind.Runner.Ethereum.Api; +using Nethermind.Runner.Ethereum.Steps; using NSubstitute; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Runner.Test/EthereumRunnerTests.cs b/src/Nethermind/Nethermind.Runner.Test/EthereumRunnerTests.cs index c10a725622c..688676774b2 100644 --- a/src/Nethermind/Nethermind.Runner.Test/EthereumRunnerTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/EthereumRunnerTests.cs @@ -5,13 +5,18 @@ using System; using System.Collections; using System.Collections.Concurrent; +using System.Collections.Generic; using System.IO; using System.IO.Abstractions; +using System.Linq; +using System.Reflection; using System.Threading; using System.Threading.Tasks; +using FluentAssertions; using Nethermind.Api; using Nethermind.Blockchain.Synchronization; using Nethermind.Config; +using Nethermind.Core; using Nethermind.Core.Test.IO; using Nethermind.Db.Rocks.Config; using Nethermind.EthStats; @@ -22,9 +27,14 @@ using Nethermind.Network.Config; using Nethermind.Runner.Ethereum; using Nethermind.Db.Blooms; +using Nethermind.Logging.NLog; using Nethermind.Runner.Ethereum.Api; using Nethermind.TxPool; +using NLog; +using NLog.Config; +using NLog.Targets; using NUnit.Framework; +using LogLevel = NLog.LogLevel; namespace Nethermind.Runner.Test { diff --git a/src/Nethermind/Nethermind.Runner.Test/MemoryHintManTests.cs b/src/Nethermind/Nethermind.Runner.Test/MemoryHintManTests.cs index f49d07d2847..d76f2c3e2e6 100755 --- a/src/Nethermind/Nethermind.Runner.Test/MemoryHintManTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/MemoryHintManTests.cs @@ -6,13 +6,11 @@ using Nethermind.Api; using Nethermind.Blockchain.Synchronization; using Nethermind.Core.Extensions; -using Nethermind.Core.Memory; using Nethermind.Db.Rocks.Config; using Nethermind.Init; using Nethermind.Logging; using Nethermind.Network.Config; using Nethermind.TxPool; -using NSubstitute; using NUnit.Framework; namespace Nethermind.Runner.Test @@ -29,7 +27,6 @@ public class MemoryHintManTests private ITxPoolConfig _txPoolConfig; private INetworkConfig _networkConfig; private MemoryHintMan _memoryHintMan; - private MallocHelper _mallocHelper; [SetUp] public void Setup() @@ -39,8 +36,7 @@ public void Setup() _initConfig = new InitConfig(); _txPoolConfig = new TxPoolConfig(); _networkConfig = new NetworkConfig(); - _mallocHelper = Substitute.For(); - _memoryHintMan = new MemoryHintMan(LimboLogs.Instance, _mallocHelper); + _memoryHintMan = new MemoryHintMan(LimboLogs.Instance); } private void SetMemoryAllowances(uint cpuCount) @@ -170,22 +166,5 @@ public void Big_value_at_memory_hint(long memoryHint) SetMemoryAllowances(1); Trie.MemoryAllowance.TrieNodeCacheCount.Should().BeGreaterThan(0); } - - [TestCase(true)] - [TestCase(false)] - public void Big_value_at_memory_hint(bool shouldSetMallocOpts) - { - _initConfig.DisableMallocOpts = !shouldSetMallocOpts; - SetMemoryAllowances(1); - - if (shouldSetMallocOpts) - { - _mallocHelper.Received().MallOpt(Arg.Any(), Arg.Any()); - } - else - { - _mallocHelper.DidNotReceive().MallOpt(Arg.Any(), Arg.Any()); - } - } } } diff --git a/src/Nethermind/Nethermind.Runner.Test/Nethermind.Runner.Test.csproj b/src/Nethermind/Nethermind.Runner.Test/Nethermind.Runner.Test.csproj index f402a828bb6..d6226ce7379 100644 --- a/src/Nethermind/Nethermind.Runner.Test/Nethermind.Runner.Test.csproj +++ b/src/Nethermind/Nethermind.Runner.Test/Nethermind.Runner.Test.csproj @@ -50,6 +50,9 @@ Chains\rinkeby.json + + Chains\ropsten.json + Chains\spaceneth.json diff --git a/src/Nethermind/Nethermind.Runner/Dockerfile b/src/Nethermind/Nethermind.Runner/Dockerfile index d70400b080f..6c27772f767 100644 --- a/src/Nethermind/Nethermind.Runner/Dockerfile +++ b/src/Nethermind/Nethermind.Runner/Dockerfile @@ -54,4 +54,4 @@ RUN dotnet publish Nethermind.Runner.csproj -c release -o /app/publish -p:UseApp FROM base AS final WORKDIR /app COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "nethermind.dll"] +ENTRYPOINT ["dotnet", "Nethermind.Runner.dll"] diff --git a/src/Nethermind/Nethermind.Runner/Ethereum/Api/ApiBuilder.cs b/src/Nethermind/Nethermind.Runner/Ethereum/Api/ApiBuilder.cs index 5b4859c293e..e81b7dc8983 100644 --- a/src/Nethermind/Nethermind.Runner/Ethereum/Api/ApiBuilder.cs +++ b/src/Nethermind/Nethermind.Runner/Ethereum/Api/ApiBuilder.cs @@ -11,7 +11,6 @@ using Nethermind.Config; using Nethermind.Consensus; using Nethermind.Core; -using Nethermind.JsonRpc.Data; using Nethermind.Logging; using Nethermind.Serialization.Json; using Nethermind.Specs.ChainSpecStyle; @@ -81,9 +80,7 @@ private ChainSpec LoadChainSpec(IJsonSerializer ethereumJsonSerializer) ThisNodeInfo.AddInfo("Chainspec :", $"{chainSpecFile}"); IChainSpecLoader loader = new ChainSpecLoader(ethereumJsonSerializer); - ChainSpec chainSpec = loader.LoadEmbeddedOrFromFile(chainSpecFile, _logger); - TransactionForRpc.DefaultChainId = chainSpec.ChainId; - return chainSpec; + return loader.LoadEmbeddedOrFromFile(chainSpecFile, _logger); } private void SetLoggerVariables(ChainSpec chainSpec) diff --git a/src/Nethermind/Nethermind.Runner/Ethereum/JsonRpcRunner.cs b/src/Nethermind/Nethermind.Runner/Ethereum/JsonRpcRunner.cs index 4d911adbd43..6bbef2b0430 100644 --- a/src/Nethermind/Nethermind.Runner/Ethereum/JsonRpcRunner.cs +++ b/src/Nethermind/Nethermind.Runner/Ethereum/JsonRpcRunner.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; diff --git a/src/Nethermind/Nethermind.Runner/Ethereum/Steps/StartRpc.cs b/src/Nethermind/Nethermind.Runner/Ethereum/Steps/StartRpc.cs index 46c2e8fdd04..f67a9e43cbd 100644 --- a/src/Nethermind/Nethermind.Runner/Ethereum/Steps/StartRpc.cs +++ b/src/Nethermind/Nethermind.Runner/Ethereum/Steps/StartRpc.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Linq; using System.Threading; using System.Threading.Tasks; diff --git a/src/Nethermind/Nethermind.Runner/JsonRpc/JsonRpcIpcRunner.cs b/src/Nethermind/Nethermind.Runner/JsonRpc/JsonRpcIpcRunner.cs index 840279d49b1..9b3b53b1003 100644 --- a/src/Nethermind/Nethermind.Runner/JsonRpc/JsonRpcIpcRunner.cs +++ b/src/Nethermind/Nethermind.Runner/JsonRpc/JsonRpcIpcRunner.cs @@ -2,11 +2,15 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.IO; using System.IO.Abstractions; +using System.Linq; using System.Net.Sockets; +using System.Text; using System.Threading; using System.Threading.Tasks; +using Nethermind.Api; using Nethermind.Config; using Nethermind.JsonRpc; using Nethermind.JsonRpc.Modules; @@ -14,6 +18,7 @@ using Nethermind.Logging; using Nethermind.Serialization.Json; using Nethermind.Sockets; +using Newtonsoft.Json; namespace Nethermind.Runner.JsonRpc { diff --git a/src/Nethermind/Nethermind.Runner/JsonRpc/Startup.cs b/src/Nethermind/Nethermind.Runner/JsonRpc/Startup.cs index 70fdec8c406..c9a08dd377f 100644 --- a/src/Nethermind/Nethermind.Runner/JsonRpc/Startup.cs +++ b/src/Nethermind/Nethermind.Runner/JsonRpc/Startup.cs @@ -4,6 +4,8 @@ using System; using System.Diagnostics; using System.IO; +using System.Linq; +using System.Net; using System.Security.Authentication; using System.Text; using System.Threading; @@ -14,6 +16,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.ResponseCompression; using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Nethermind.Api; @@ -26,6 +29,7 @@ using Nethermind.Logging; using Nethermind.Serialization.Json; using Nethermind.Sockets; +using Newtonsoft.Json; namespace Nethermind.Runner.JsonRpc { @@ -71,14 +75,10 @@ public void ConfigureServices(IServiceCollection services) public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IJsonRpcProcessor jsonRpcProcessor, IJsonRpcService jsonRpcService, IJsonRpcLocalStats jsonRpcLocalStats, IJsonSerializer jsonSerializer) { - long SerializeTimeoutException(IJsonRpcService service, Stream resultStream, JsonRpcResult result) + long SerializeTimeoutException(IJsonRpcService service, Stream resultStream) { - JsonRpcResponse response = result.SingleResponse?.Response; - return jsonSerializer.Serialize(resultStream, service.GetErrorResponse( - ErrorCodes.Timeout, - "Request was canceled due to enabled timeout.", - response?.Id, - response?.MethodName)); + JsonRpcErrorResponse? error = service.GetErrorResponse(ErrorCodes.Timeout, "Request was canceled due to enabled timeout."); + return jsonSerializer.Serialize(resultStream, error); } if (env.IsDevelopment()) @@ -194,8 +194,8 @@ long SerializeTimeoutException(IJsonRpcService service, Stream resultStream, Jso } first = false; - responseSize += jsonSerializer.SerializeWaitForEnumeration(resultStream, entry.Response); - _ = jsonRpcLocalStats.ReportCall(entry.Report); + responseSize += jsonSerializer.Serialize(resultStream, entry.Response); + jsonRpcLocalStats.ReportCall(entry.Report); // We reached the limit and don't want to responded to more request in the batch if (!jsonRpcContext.IsAuthenticated && responseSize > jsonRpcConfig.MaxBatchResponseBodySize) @@ -218,7 +218,7 @@ long SerializeTimeoutException(IJsonRpcService service, Stream resultStream, Jso { using (result.Response) { - jsonSerializer.SerializeWaitForEnumeration(resultStream, result.Response); + jsonSerializer.Serialize(resultStream, result.Response); } } @@ -231,11 +231,11 @@ long SerializeTimeoutException(IJsonRpcService service, Stream resultStream, Jso } catch (Exception e) when (e.InnerException is OperationCanceledException) { - responseSize = SerializeTimeoutException(jsonRpcService, resultStream, result); + responseSize = SerializeTimeoutException(jsonRpcService, resultStream); } catch (OperationCanceledException) { - responseSize = SerializeTimeoutException(jsonRpcService, resultStream, result); + responseSize = SerializeTimeoutException(jsonRpcService, resultStream); } finally { @@ -248,7 +248,7 @@ long SerializeTimeoutException(IJsonRpcService service, Stream resultStream, Jso } long handlingTimeMicroseconds = stopwatch.ElapsedMicroseconds(); - _ = jsonRpcLocalStats.ReportCall(result.IsCollection + jsonRpcLocalStats.ReportCall(result.IsCollection ? new RpcReport("# collection serialization #", handlingTimeMicroseconds, true) : result.Report.Value, handlingTimeMicroseconds, responseSize); @@ -278,16 +278,15 @@ private static int GetStatusCode(JsonRpcResult result) } else { - return IsResourceUnavailableError(result.Response) + return ModuleTimeout(result.Response) ? StatusCodes.Status503ServiceUnavailable : StatusCodes.Status200OK; } } - private static bool IsResourceUnavailableError(JsonRpcResponse? response) + private static bool ModuleTimeout(JsonRpcResponse? response) { - return response is JsonRpcErrorResponse { Error.Code: ErrorCodes.ModuleTimeout } - or JsonRpcErrorResponse { Error.Code: ErrorCodes.LimitExceeded }; + return response is JsonRpcErrorResponse { Error.Code: ErrorCodes.ModuleTimeout }; } } } diff --git a/src/Nethermind/Nethermind.Runner/Logging/NLogConfigurator.cs b/src/Nethermind/Nethermind.Runner/Logging/NLogConfigurator.cs index ac0fa79ca1b..4c82688d5f6 100644 --- a/src/Nethermind/Nethermind.Runner/Logging/NLogConfigurator.cs +++ b/src/Nethermind/Nethermind.Runner/Logging/NLogConfigurator.cs @@ -69,17 +69,8 @@ public static void ConfigureLogLevels(CommandOption logLevelOverride) Console.WriteLine($"Enabling log level override: {logLevel.ToUpperInvariant()}"); - // There are some rules for which we don't want to override the log level - // but instead preserve the original config defined in the 'NLog.config' file - string[] ignoredRuleNames = - { - "JsonWebAPI*", - "JsonWebAPI.Microsoft.Extensions.Diagnostics.HealthChecks.DefaultHealthCheckService", - }; foreach (LoggingRule rule in LogManager.Configuration.LoggingRules) { - if (ignoredRuleNames.Contains(rule.LoggerNamePattern)) { continue; } - foreach (var ruleTarget in rule.Targets) { if (ruleTarget.Name != "seq") diff --git a/src/Nethermind/Nethermind.Runner/NLog.config b/src/Nethermind/Nethermind.Runner/NLog.config index badd3125e9d..411c0df4536 100644 --- a/src/Nethermind/Nethermind.Runner/NLog.config +++ b/src/Nethermind/Nethermind.Runner/NLog.config @@ -2,88 +2,41 @@ - - - - + - + layout="${longdate}|${level:uppercase=true}|${threadid}|${message} ${exception:format=toString}" /> + + + layout="${longdate}|${message} ${exception:format=toString}"> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Nethermind/Nethermind.Runner/Nethermind.Runner.csproj b/src/Nethermind/Nethermind.Runner/Nethermind.Runner.csproj index 8532a580a4a..8574b92fa30 100644 --- a/src/Nethermind/Nethermind.Runner/Nethermind.Runner.csproj +++ b/src/Nethermind/Nethermind.Runner/Nethermind.Runner.csproj @@ -4,7 +4,6 @@ net7.0 latest annotations - nethermind true false false @@ -12,12 +11,11 @@ true true true - true Linux - -v $(OutDir)/.data:/data -p 8545:8545 -p 8551:8551 -p 30303:30303 + -v $(NETHERMIND_DATA_DIR):/data -p 8545:8545 -p 8551:8551 -p 30303:30303 03db39d0-4200-473e-9ff8-4a48d496381f @@ -33,7 +31,6 @@ - diff --git a/src/Nethermind/Nethermind.Runner/Program.cs b/src/Nethermind/Nethermind.Runner/Program.cs index d0f41737379..eaf5651c2c8 100644 --- a/src/Nethermind/Nethermind.Runner/Program.cs +++ b/src/Nethermind/Nethermind.Runner/Program.cs @@ -13,9 +13,9 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -#if !DEBUG + using DotNetty.Common; -#endif + using Microsoft.Extensions.CommandLineUtils; using Nethermind.Api; using Nethermind.Api.Extensions; @@ -40,515 +40,514 @@ using NLog.Config; using ILogger = Nethermind.Logging.ILogger; -namespace Nethermind.Runner; - -public static class Program +namespace Nethermind.Runner { - private const string FailureString = "Failure"; - private const string DefaultConfigsDirectory = "configs"; - private const string DefaultConfigFile = "configs/mainnet.cfg"; + public static class Program + { + private const string FailureString = "Failure"; + private const string DefaultConfigsDirectory = "configs"; + private const string DefaultConfigFile = "configs/mainnet.cfg"; - private static ILogger _logger = SimpleConsoleLogger.Instance; + private static ILogger _logger = SimpleConsoleLogger.Instance; - private static readonly ProcessExitSource _processExitSource = new(); - private static readonly TaskCompletionSource _cancelKeySource = new(); - private static readonly TaskCompletionSource _processExit = new(); - private static readonly TaskCompletionSource _exitSourceExit = new(); - private static readonly ManualResetEventSlim _appClosed = new(true); + private static readonly ProcessExitSource _processExitSource = new(); + private static readonly TaskCompletionSource _cancelKeySource = new(); + private static readonly TaskCompletionSource _processExit = new(); + private static readonly ManualResetEventSlim _appClosed = new(true); - public static void Main(string[] args) - { + public static void Main(string[] args) + { #if !DEBUG - ResourceLeakDetector.Level = ResourceLeakDetector.DetectionLevel.Disabled; + ResourceLeakDetector.Level = ResourceLeakDetector.DetectionLevel.Disabled; #endif - AppDomain.CurrentDomain.UnhandledException += (sender, eventArgs) => - { - ILogger logger = GetCriticalLogger(); - if (eventArgs.ExceptionObject is Exception e) + AppDomain.CurrentDomain.UnhandledException += (sender, eventArgs) => + { + ILogger logger = GetCriticalLogger(); + if (eventArgs.ExceptionObject is Exception e) + { + logger.Error(FailureString, e); + } + else + { + logger.Error(FailureString + eventArgs.ExceptionObject); + } + }; + + try { + Run(args); + } + catch (AggregateException e) + { + ILogger logger = GetCriticalLogger(); + logger.Error(FailureString, e.InnerException); + } + catch (Exception e) + { + ILogger logger = GetCriticalLogger(); logger.Error(FailureString, e); } - else + finally { - logger.Error(FailureString + eventArgs.ExceptionObject); + NLogManager.Shutdown(); } - }; - - try - { - Run(args); - } - catch (AggregateException e) - { - ILogger logger = GetCriticalLogger(); - logger.Error(FailureString, e.InnerException); } - catch (Exception e) - { - ILogger logger = GetCriticalLogger(); - logger.Error(FailureString, e); - } - finally - { - NLogManager.Shutdown(); - } - } - private static ILogger GetCriticalLogger() - { - try + private static ILogger GetCriticalLogger() { - return new NLogManager("logs.txt").GetClassLogger(); - } - catch - { - if (_logger.IsWarn) _logger.Warn("Critical file logging could not be instantiated! Sticking to console logging till config is loaded."); - return _logger; + try + { + return new NLogManager("logs.txt").GetClassLogger(); + } + catch + { + if (_logger.IsWarn) _logger.Warn("Critical file logging could not be instantiated! Sticking to console logging till config is loaded."); + return _logger; + } } - } - private static void Run(string[] args) - { - _logger.Info("Nethermind starting initialization."); - _logger.Info($"Client version: {ProductInfo.ClientId}"); - - AppDomain.CurrentDomain.ProcessExit += CurrentDomainOnProcessExit; - AssemblyLoadContext.Default.ResolvingUnmanagedDll += OnResolvingUnmanagedDll; - - GlobalDiagnosticsContext.Set("version", ProductInfo.Version); - CommandLineApplication app = new() { Name = "Nethermind.Runner" }; - _ = app.HelpOption("-?|-h|--help"); - _ = app.VersionOption("-v|--version", () => ProductInfo.Version, GetProductInfo); - - CommandOption dataDir = app.Option("-dd|--datadir ", "Data directory", CommandOptionType.SingleValue); - CommandOption configFile = app.Option("-c|--config ", "Config file path", CommandOptionType.SingleValue); - CommandOption dbBasePath = app.Option("-d|--baseDbPath ", "Base db path", CommandOptionType.SingleValue); - CommandOption logLevelOverride = app.Option("-l|--log ", "Log level override. Possible values: OFF|TRACE|DEBUG|INFO|WARN|ERROR", CommandOptionType.SingleValue); - CommandOption configsDirectory = app.Option("-cd|--configsDirectory ", "Configs directory", CommandOptionType.SingleValue); - CommandOption loggerConfigSource = app.Option("-lcs|--loggerConfigSource ", "Path to the NLog config file", CommandOptionType.SingleValue); - _ = app.Option("-pd|--pluginsDirectory ", "plugins directory", CommandOptionType.SingleValue); - - IFileSystem fileSystem = new FileSystem(); - - string pluginsDirectoryPath = LoadPluginsDirectory(args); - PluginLoader pluginLoader = new(pluginsDirectoryPath, fileSystem, - typeof(AuRaPlugin), - typeof(CliquePlugin), - typeof(EthashPlugin), - typeof(NethDevPlugin), - typeof(HivePlugin), - typeof(UPnPPlugin) - ); - - // leaving here as an example of adding Debug plugin - // IPluginLoader mevLoader = SinglePluginLoader.Instance; - // CompositePluginLoader pluginLoader = new (pluginLoader, mevLoader); - pluginLoader.Load(SimpleConsoleLogManager.Instance); - TypeDiscovery.Initialize(typeof(INethermindPlugin)); - - BuildOptionsFromConfigFiles(app); - - app.OnExecute(async () => + private static void Run(string[] args) { - IConfigProvider configProvider = BuildConfigProvider(app, loggerConfigSource, logLevelOverride, configsDirectory, configFile); - IInitConfig initConfig = configProvider.GetConfig(); - IKeyStoreConfig keyStoreConfig = configProvider.GetConfig(); - IPluginConfig pluginConfig = configProvider.GetConfig(); + _logger.Info("Nethermind starting initialization."); + _logger.Info($"Client version: {ProductInfo.ClientId}"); + + AppDomain.CurrentDomain.ProcessExit += CurrentDomainOnProcessExit; + AssemblyLoadContext.Default.ResolvingUnmanagedDll += OnResolvingUnmanagedDll; + + GlobalDiagnosticsContext.Set("version", ProductInfo.Version); + CommandLineApplication app = new() { Name = "Nethermind.Runner" }; + _ = app.HelpOption("-?|-h|--help"); + _ = app.VersionOption("-v|--version", () => ProductInfo.Version, GetProductInfo); - pluginLoader.OrderPlugins(pluginConfig); - Console.Title = initConfig.LogFileName; - Console.CancelKeyPress += ConsoleOnCancelKeyPress; + CommandOption dataDir = app.Option("-dd|--datadir ", "Data directory", CommandOptionType.SingleValue); + CommandOption configFile = app.Option("-c|--config ", "Config file path", CommandOptionType.SingleValue); + CommandOption dbBasePath = app.Option("-d|--baseDbPath ", "Base db path", CommandOptionType.SingleValue); + CommandOption logLevelOverride = app.Option("-l|--log ", "Log level override. Possible values: OFF|TRACE|DEBUG|INFO|WARN|ERROR", CommandOptionType.SingleValue); + CommandOption configsDirectory = app.Option("-cd|--configsDirectory ", "Configs directory", CommandOptionType.SingleValue); + CommandOption loggerConfigSource = app.Option("-lcs|--loggerConfigSource ", "Path to the NLog config file", CommandOptionType.SingleValue); + _ = app.Option("-pd|--pluginsDirectory ", "plugins directory", CommandOptionType.SingleValue); - SetFinalDataDirectory(dataDir.HasValue() ? dataDir.Value() : null, initConfig, keyStoreConfig); - NLogManager logManager = new(initConfig.LogFileName, initConfig.LogDirectory, initConfig.LogRules); + IFileSystem fileSystem = new FileSystem(); - _logger = logManager.GetClassLogger(); - ConfigureSeqLogger(configProvider); - SetFinalDbPath(dbBasePath.HasValue() ? dbBasePath.Value() : null, initConfig); - LogMemoryConfiguration(); + string pluginsDirectoryPath = LoadPluginsDirectory(args); + PluginLoader pluginLoader = new(pluginsDirectoryPath, fileSystem, + typeof(AuRaPlugin), + typeof(CliquePlugin), + typeof(EthashPlugin), + typeof(NethDevPlugin), + typeof(HivePlugin), + typeof(UPnPPlugin) + ); - EthereumJsonSerializer serializer = new(); - if (_logger.IsDebug) _logger.Debug($"Nethermind config:{Environment.NewLine}{serializer.Serialize(initConfig, true)}{Environment.NewLine}"); - if (_logger.IsInfo) _logger.Info($"RocksDb Version: {DbOnTheRocks.GetRocksDbVersion()}"); + // leaving here as an example of adding Debug plugin + // IPluginLoader mevLoader = SinglePluginLoader.Instance; + // CompositePluginLoader pluginLoader = new (pluginLoader, mevLoader); + pluginLoader.Load(SimpleConsoleLogManager.Instance); - ApiBuilder apiBuilder = new(configProvider, logManager); + BuildOptionsFromConfigFiles(app); - IList plugins = new List(); - foreach (Type pluginType in pluginLoader.PluginTypes) + app.OnExecute(async () => { - try + IConfigProvider configProvider = BuildConfigProvider(app, loggerConfigSource, logLevelOverride, configsDirectory, configFile); + IInitConfig initConfig = configProvider.GetConfig(); + IKeyStoreConfig keyStoreConfig = configProvider.GetConfig(); + IPluginConfig pluginConfig = configProvider.GetConfig(); + + pluginLoader.OrderPlugins(pluginConfig); + Console.Title = initConfig.LogFileName; + Console.CancelKeyPress += ConsoleOnCancelKeyPress; + + SetFinalDataDirectory(dataDir.HasValue() ? dataDir.Value() : null, initConfig, keyStoreConfig); + NLogManager logManager = new(initConfig.LogFileName, initConfig.LogDirectory, initConfig.LogRules); + + _logger = logManager.GetClassLogger(); + ConfigureSeqLogger(configProvider); + SetFinalDbPath(dbBasePath.HasValue() ? dbBasePath.Value() : null, initConfig); + LogMemoryConfiguration(); + + EthereumJsonSerializer serializer = new(); + if (_logger.IsDebug) _logger.Debug($"Nethermind config:{Environment.NewLine}{serializer.Serialize(initConfig, true)}{Environment.NewLine}"); + if (_logger.IsInfo) _logger.Info($"RocksDb Version: {DbOnTheRocks.GetRocksDbVersion()}"); + + ApiBuilder apiBuilder = new(configProvider, logManager); + + IList plugins = new List(); + foreach (Type pluginType in pluginLoader.PluginTypes) { - if (Activator.CreateInstance(pluginType) is INethermindPlugin plugin) + try + { + if (Activator.CreateInstance(pluginType) is INethermindPlugin plugin) + { + plugins.Add(plugin); + } + } + catch (Exception e) { - plugins.Add(plugin); + if (_logger.IsError) _logger.Error($"Failed to create plugin {pluginType.FullName}", e); } } + + INethermindApi nethermindApi = apiBuilder.Create(plugins.OfType()); + ((List)nethermindApi.Plugins).AddRange(plugins); + nethermindApi.ProcessExit = _processExitSource; + + _appClosed.Reset(); + EthereumRunner ethereumRunner = new(nethermindApi); + try + { + await ethereumRunner.Start(_processExitSource.Token); + + _ = await Task.WhenAny(_cancelKeySource.Task, _processExit.Task); + } + catch (TaskCanceledException) + { + if (_logger.IsTrace) _logger.Trace("Runner Task was canceled"); + } + catch (OperationCanceledException) + { + if (_logger.IsTrace) _logger.Trace("Runner operation was canceled"); + } catch (Exception e) { - if (_logger.IsError) _logger.Error($"Failed to create plugin {pluginType.FullName}", e); + if (_logger.IsError) _logger.Error("Error during ethereum runner start", e); + _processExitSource.Exit(e is IExceptionWithExitCode withExit ? withExit.ExitCode : ExitCodes.GeneralError); } - } - INethermindApi nethermindApi = apiBuilder.Create(plugins.OfType()); - ((List)nethermindApi.Plugins).AddRange(plugins); - nethermindApi.ProcessExit = _processExitSource; + _logger.Info("Closing, please wait until all functions are stopped properly..."); + await ethereumRunner.StopAsync(); + _logger.Info("All done, goodbye!"); + _appClosed.Set(); - _appClosed.Reset(); - EthereumRunner ethereumRunner = new(nethermindApi); - try - { - await ethereumRunner.Start(_processExitSource.Token); + return _processExitSource.ExitCode; + }); - _ = await Task.WhenAny(_cancelKeySource.Task, _processExit.Task, _processExitSource.ExitTask); - } - catch (TaskCanceledException) - { - if (_logger.IsTrace) _logger.Trace("Runner Task was canceled"); - } - catch (OperationCanceledException) + try { - if (_logger.IsTrace) _logger.Trace("Runner operation was canceled"); + Environment.ExitCode = app.Execute(args); } catch (Exception e) { - if (_logger.IsError) _logger.Error("Error during ethereum runner start", e); - _processExitSource.Exit(e is IExceptionWithExitCode withExit ? withExit.ExitCode : ExitCodes.GeneralError); - } - - _logger.Info("Closing, please wait until all functions are stopped properly..."); - await ethereumRunner.StopAsync(); - _logger.Info("All done, goodbye!"); - _appClosed.Set(); - - return _processExitSource.ExitCode; - }); - - try - { - Environment.ExitCode = app.Execute(args); - } - catch (Exception e) - { - if (e is IExceptionWithExitCode withExit) - { - Environment.ExitCode = withExit.ExitCode; + if (e is IExceptionWithExitCode withExit) + { + Environment.ExitCode = withExit.ExitCode; + } + else + { + Environment.ExitCode = ExitCodes.GeneralError; + } + throw; } - else + finally { - Environment.ExitCode = ExitCodes.GeneralError; + _appClosed.Wait(); } - throw; } - finally + + private static IntPtr OnResolvingUnmanagedDll(Assembly _, string nativeLibraryName) { - _appClosed.Wait(); + const string MacosSnappyPath = "/opt/homebrew/Cellar/snappy"; + var alternativePath = nativeLibraryName switch + { + "libdl" => "libdl.so.2", + "libsnappy" or "snappy" => Directory.Exists(MacosSnappyPath) ? + Directory.EnumerateFiles(MacosSnappyPath, "libsnappy.dylib", SearchOption.AllDirectories).FirstOrDefault() : "libsnappy.so.1", + _ => null + }; + + return alternativePath is null ? IntPtr.Zero : NativeLibrary.Load(alternativePath); } - } - private static IntPtr OnResolvingUnmanagedDll(Assembly _, string nativeLibraryName) - { - const string macosSnappyPath = "/opt/homebrew/Cellar/snappy"; - var alternativePath = nativeLibraryName switch + private static void BuildOptionsFromConfigFiles(CommandLineApplication app) { - "libdl" => "libdl.so.2", - "libsnappy" or "snappy" => Directory.Exists(macosSnappyPath) ? - Directory.EnumerateFiles(macosSnappyPath, "libsnappy.dylib", SearchOption.AllDirectories).FirstOrDefault() : "libsnappy.so.1", - _ => null - }; + Type configurationType = typeof(IConfig); + IEnumerable configTypes = TypeDiscovery.FindNethermindTypes(configurationType) + .Where(ct => ct.IsInterface); - return alternativePath is null ? IntPtr.Zero : NativeLibrary.Load(alternativePath); - } + foreach (Type configType in configTypes.Where(ct => !ct.IsAssignableTo(typeof(INoCategoryConfig))).OrderBy(c => c.Name)) + { + if (configType is null) + { + continue; + } - private static void BuildOptionsFromConfigFiles(CommandLineApplication app) - { - Type configurationType = typeof(IConfig); - IEnumerable configTypes = TypeDiscovery.FindNethermindBasedTypes(configurationType) - .Where(ct => ct.IsInterface); + ConfigCategoryAttribute? typeLevel = configType.GetCustomAttribute(); - foreach (Type configType in configTypes.Where(ct => !ct.IsAssignableTo(typeof(INoCategoryConfig))).OrderBy(c => c.Name)) - { - if (configType is null) - { - continue; - } + if (typeLevel is not null && (typeLevel?.DisabledForCli ?? true)) + { + continue; + } - ConfigCategoryAttribute? typeLevel = configType.GetCustomAttribute(); + foreach (PropertyInfo propertyInfo in configType + .GetProperties(BindingFlags.Public | BindingFlags.Instance) + .OrderBy(p => p.Name)) + { + ConfigItemAttribute? configItemAttribute = propertyInfo.GetCustomAttribute(); + if (!(configItemAttribute?.DisabledForCli ?? false)) + { + _ = app.Option($"--{configType.Name[1..].Replace("Config", string.Empty)}.{propertyInfo.Name}", $"{(configItemAttribute is null ? "" : configItemAttribute.Description + $" (DEFAULT: {configItemAttribute.DefaultValue})" ?? "")}", CommandOptionType.SingleValue); - if (typeLevel is not null && (typeLevel?.DisabledForCli ?? true)) - { - continue; + } + } } - foreach (PropertyInfo propertyInfo in configType - .GetProperties(BindingFlags.Public | BindingFlags.Instance) - .OrderBy(p => p.Name)) + // Create Help Text for environment variables + Type noCategoryConfig = configTypes.FirstOrDefault(ct => ct.IsAssignableTo(typeof(INoCategoryConfig))); + if (noCategoryConfig is not null) { - ConfigItemAttribute? configItemAttribute = propertyInfo.GetCustomAttribute(); - if (!(configItemAttribute?.DisabledForCli ?? false)) + StringBuilder sb = new(); + sb.AppendLine(); + sb.AppendLine("Configurable Environment Variables:"); + foreach (PropertyInfo propertyInfo in noCategoryConfig.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(p => p.Name)) { - _ = app.Option($"--{configType.Name[1..].Replace("Config", string.Empty)}.{propertyInfo.Name}", $"{(configItemAttribute is null ? "" : configItemAttribute.Description + $" (DEFAULT: {configItemAttribute.DefaultValue})" ?? "")}", CommandOptionType.SingleValue); - + ConfigItemAttribute? configItemAttribute = propertyInfo.GetCustomAttribute(); + if (configItemAttribute is not null && !(string.IsNullOrEmpty(configItemAttribute?.EnvironmentVariable))) + { + sb.AppendLine($"{configItemAttribute.EnvironmentVariable} - {(string.IsNullOrEmpty(configItemAttribute.Description) ? "" : configItemAttribute.Description)} (DEFAULT: {configItemAttribute.DefaultValue})"); + } } + + app.ExtendedHelpText = sb.ToString(); } } - // Create Help Text for environment variables - Type noCategoryConfig = configTypes.FirstOrDefault(ct => ct.IsAssignableTo(typeof(INoCategoryConfig))); - if (noCategoryConfig is not null) + private static string LoadPluginsDirectory(string[] args) { - StringBuilder sb = new(); - sb.AppendLine(); - sb.AppendLine("Configurable Environment Variables:"); - foreach (PropertyInfo propertyInfo in noCategoryConfig.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(p => p.Name)) + string shortCommand = "-pd"; + string longCommand = "--pluginsDirectory"; + + string[] GetPluginArgs() { - ConfigItemAttribute? configItemAttribute = propertyInfo.GetCustomAttribute(); - if (configItemAttribute is not null && !(string.IsNullOrEmpty(configItemAttribute?.EnvironmentVariable))) + for (int i = 0; i < args.Length; i++) { - sb.AppendLine($"{configItemAttribute.EnvironmentVariable} - {(string.IsNullOrEmpty(configItemAttribute.Description) ? "" : configItemAttribute.Description)} (DEFAULT: {configItemAttribute.DefaultValue})"); + string arg = args[i]; + if (arg == shortCommand || arg == longCommand) + { + return i == args.Length - 1 ? new[] { arg } : new[] { arg, args[i + 1] }; + } } + + return Array.Empty(); } - app.ExtendedHelpText = sb.ToString(); - } - } + CommandLineApplication pluginsApp = new() { Name = "Nethermind.Runner.Plugins" }; + CommandOption pluginsAppDirectory = pluginsApp.Option($"{shortCommand}|{longCommand} ", "plugins directory", CommandOptionType.SingleValue); + string pluginDirectory = "plugins"; + pluginsApp.OnExecute(() => + { + if (pluginsAppDirectory.HasValue()) + { + pluginDirectory = pluginsAppDirectory.Value(); + } - private static string LoadPluginsDirectory(string[] args) - { - string shortCommand = "-pd"; - string longCommand = "--pluginsDirectory"; + return 0; + }); + pluginsApp.Execute(GetPluginArgs()); + return pluginDirectory; + } - string[] GetPluginArgs() + private static IConfigProvider BuildConfigProvider( + CommandLineApplication app, + CommandOption loggerConfigSource, + CommandOption logLevelOverride, + CommandOption configsDirectory, + CommandOption configFile) { - for (int i = 0; i < args.Length; i++) + if (loggerConfigSource.HasValue()) { - string arg = args[i]; - if (arg == shortCommand || arg == longCommand) + string nLogPath = loggerConfigSource.Value(); + _logger.Info($"Loading NLog configuration file from {nLogPath}."); + + try + { + LogManager.Configuration = new XmlLoggingConfiguration(nLogPath); + } + catch (Exception e) { - return i == args.Length - 1 ? new[] { arg } : new[] { arg, args[i + 1] }; + _logger.Info($"Failed to load NLog configuration from {nLogPath}. {e}"); } } + else + { + _logger.Info($"Loading standard NLog.config file from {"NLog.config".GetApplicationResourcePath()}."); + Stopwatch stopwatch = Stopwatch.StartNew(); + LogManager.Configuration = new XmlLoggingConfiguration("NLog.config".GetApplicationResourcePath()); + stopwatch.Stop(); - return Array.Empty(); - } + _logger.Info($"NLog.config loaded in {stopwatch.ElapsedMilliseconds}ms."); + } - CommandLineApplication pluginsApp = new() { Name = "Nethermind.Runner.Plugins" }; - CommandOption pluginsAppDirectory = pluginsApp.Option($"{shortCommand}|{longCommand} ", "plugins directory", CommandOptionType.SingleValue); - string pluginDirectory = "plugins"; - pluginsApp.OnExecute(() => - { - if (pluginsAppDirectory.HasValue()) + // TODO: dynamically switch log levels from CLI! + if (logLevelOverride.HasValue()) { - pluginDirectory = pluginsAppDirectory.Value(); + NLogConfigurator.ConfigureLogLevels(logLevelOverride); } - return 0; - }); - pluginsApp.Execute(GetPluginArgs()); - return pluginDirectory; - } + ConfigProvider configProvider = new(); + Dictionary configArgs = new(); + foreach (CommandOption commandOption in app.Options) + { + if (commandOption.HasValue()) + { + configArgs.Add(commandOption.LongName, commandOption.Value()); + } + } - private static IConfigProvider BuildConfigProvider( - CommandLineApplication app, - CommandOption loggerConfigSource, - CommandOption logLevelOverride, - CommandOption configsDirectory, - CommandOption configFile) - { - if (loggerConfigSource.HasValue()) - { - string nLogPath = loggerConfigSource.Value(); - _logger.Info($"Loading NLog configuration file from {nLogPath}."); + IConfigSource argsSource = new ArgsConfigSource(configArgs); + configProvider.AddSource(argsSource); + configProvider.AddSource(new EnvConfigSource()); - try + string configDir = configsDirectory.HasValue() ? configsDirectory.Value() : DefaultConfigsDirectory; + string configFilePath = configFile.HasValue() ? configFile.Value() : DefaultConfigFile; + string? configPathVariable = Environment.GetEnvironmentVariable("NETHERMIND_CONFIG"); + if (!string.IsNullOrWhiteSpace(configPathVariable)) { - LogManager.Configuration = new XmlLoggingConfiguration(nLogPath); + configFilePath = configPathVariable; } - catch (Exception e) + + if (!PathUtils.IsExplicitlyRelative(configFilePath)) { - _logger.Info($"Failed to load NLog configuration from {nLogPath}. {e}"); + configFilePath = configDir == DefaultConfigsDirectory + ? configFilePath.GetApplicationResourcePath() + : Path.Combine(configDir, string.Concat(configFilePath)); } - } - else - { - _logger.Info($"Loading standard NLog.config file from {"NLog.config".GetApplicationResourcePath()}."); - Stopwatch stopwatch = Stopwatch.StartNew(); - LogManager.Configuration = new XmlLoggingConfiguration("NLog.config".GetApplicationResourcePath()); - stopwatch.Stop(); - - _logger.Info($"NLog.config loaded in {stopwatch.ElapsedMilliseconds}ms."); - } - // TODO: dynamically switch log levels from CLI! - if (logLevelOverride.HasValue()) - { - NLogConfigurator.ConfigureLogLevels(logLevelOverride); - } + if (!Path.HasExtension(configFilePath) && !configFilePath.Contains(Path.DirectorySeparatorChar)) + { + string redirectedConfigPath = Path.Combine(configDir, string.Concat(configFilePath, ".cfg")); + configFilePath = redirectedConfigPath; + if (!File.Exists(configFilePath)) + { + throw new InvalidOperationException($"Configuration: {configFilePath} was not found."); + } + } - ConfigProvider configProvider = new(); - Dictionary configArgs = new(); - foreach (CommandOption commandOption in app.Options) - { - if (commandOption.HasValue()) + if (!Path.HasExtension(configFilePath)) { - configArgs.Add(commandOption.LongName, commandOption.Value()); + configFilePath = string.Concat(configFilePath, ".cfg"); } - } - IConfigSource argsSource = new ArgsConfigSource(configArgs); - configProvider.AddSource(argsSource); - configProvider.AddSource(new EnvConfigSource()); + // Fallback to "{executingDirectory}/configs/{configFile}" if "configs" catalog was not specified. + if (!File.Exists(configFilePath)) + { + string configName = Path.GetFileName(configFilePath); + string? configDirectory = Path.GetDirectoryName(configFilePath); + string redirectedConfigPath = Path.Combine(configDirectory ?? string.Empty, configDir, configName); + configFilePath = redirectedConfigPath; + if (!File.Exists(configFilePath)) + { + throw new InvalidOperationException($"Configuration: {configFilePath} was not found."); + } + } - string configDir = configsDirectory.HasValue() ? configsDirectory.Value() : DefaultConfigsDirectory; - string configFilePath = configFile.HasValue() ? configFile.Value() : DefaultConfigFile; - string? configPathVariable = Environment.GetEnvironmentVariable("NETHERMIND_CONFIG"); - if (!string.IsNullOrWhiteSpace(configPathVariable)) - { - configFilePath = configPathVariable; - } + _logger.Info($"Reading config file from {configFilePath}"); + configProvider.AddSource(new JsonConfigSource(configFilePath)); + configProvider.Initialize(); + var incorrectSettings = configProvider.FindIncorrectSettings(); + if (incorrectSettings.Errors.Count > 0) + { + _logger.Warn($"Incorrect config settings found:{Environment.NewLine}{incorrectSettings.ErrorMsg}"); + } - if (!PathUtils.IsExplicitlyRelative(configFilePath)) - { - configFilePath = configDir == DefaultConfigsDirectory - ? configFilePath.GetApplicationResourcePath() - : Path.Combine(configDir, string.Concat(configFilePath)); + _logger.Info("Configuration initialized."); + return configProvider; } - if (!Path.HasExtension(configFilePath) && !configFilePath.Contains(Path.DirectorySeparatorChar)) + private static void CurrentDomainOnProcessExit(object? sender, EventArgs e) { - string redirectedConfigPath = Path.Combine(configDir, string.Concat(configFilePath, ".cfg")); - configFilePath = redirectedConfigPath; - if (!File.Exists(configFilePath)) - { - throw new InvalidOperationException($"Configuration: {configFilePath} was not found."); - } + _processExitSource.Exit(ExitCodes.Ok); + _processExit.SetResult(null); + _appClosed.Wait(); } - if (!Path.HasExtension(configFilePath)) + private static void LogMemoryConfiguration() { - configFilePath = string.Concat(configFilePath, ".cfg"); + if (_logger.IsDebug) + _logger.Debug($"Server GC : {System.Runtime.GCSettings.IsServerGC}"); + if (_logger.IsDebug) + _logger.Debug($"GC latency mode : {System.Runtime.GCSettings.LatencyMode}"); + if (_logger.IsDebug) + _logger.Debug($"LOH compaction mode : {System.Runtime.GCSettings.LargeObjectHeapCompactionMode}"); } - // Fallback to "{executingDirectory}/configs/{configFile}" if "configs" catalog was not specified. - if (!File.Exists(configFilePath)) + private static void SetFinalDbPath(string? baseDbPath, IInitConfig initConfig) { - string configName = Path.GetFileName(configFilePath); - string? configDirectory = Path.GetDirectoryName(configFilePath); - string redirectedConfigPath = Path.Combine(configDirectory ?? string.Empty, configDir, configName); - configFilePath = redirectedConfigPath; - if (!File.Exists(configFilePath)) + if (!string.IsNullOrWhiteSpace(baseDbPath)) + { + string newDbPath = initConfig.BaseDbPath.GetApplicationResourcePath(baseDbPath); + if (_logger.IsDebug) _logger.Debug($"Adding prefix to baseDbPath, new value: {newDbPath}, old value: {initConfig.BaseDbPath}"); + initConfig.BaseDbPath = newDbPath; + } + else { - throw new InvalidOperationException($"Configuration: {configFilePath} was not found."); + initConfig.BaseDbPath ??= string.Empty.GetApplicationResourcePath("db"); } } - _logger.Info($"Reading config file from {configFilePath}"); - configProvider.AddSource(new JsonConfigSource(configFilePath)); - configProvider.Initialize(); - var incorrectSettings = configProvider.FindIncorrectSettings(); - if (incorrectSettings.Errors.Count > 0) + private static void SetFinalDataDirectory(string? dataDir, IInitConfig initConfig, IKeyStoreConfig keyStoreConfig) { - _logger.Warn($"Incorrect config settings found:{Environment.NewLine}{incorrectSettings.ErrorMsg}"); - } - - _logger.Info("Configuration initialized."); - return configProvider; - } - - private static void CurrentDomainOnProcessExit(object? sender, EventArgs e) - { - _processExitSource.Exit(ExitCodes.Ok); - _processExit.SetResult(null); - _appClosed.Wait(); - } + if (!string.IsNullOrWhiteSpace(dataDir)) + { + string newDbPath = initConfig.BaseDbPath.GetApplicationResourcePath(dataDir); + string newKeyStorePath = keyStoreConfig.KeyStoreDirectory.GetApplicationResourcePath(dataDir); + string newLogDirectory = initConfig.LogDirectory.GetApplicationResourcePath(dataDir); - private static void LogMemoryConfiguration() - { - if (_logger.IsDebug) - _logger.Debug($"Server GC : {System.Runtime.GCSettings.IsServerGC}"); - if (_logger.IsDebug) - _logger.Debug($"GC latency mode : {System.Runtime.GCSettings.LatencyMode}"); - if (_logger.IsDebug) - _logger.Debug($"LOH compaction mode : {System.Runtime.GCSettings.LargeObjectHeapCompactionMode}"); - } + if (_logger.IsInfo) + { + _logger.Info($"Setting BaseDbPath to: {newDbPath}, from: {initConfig.BaseDbPath}"); + _logger.Info($"Setting KeyStoreDirectory to: {newKeyStorePath}, from: {keyStoreConfig.KeyStoreDirectory}"); + _logger.Info($"Setting LogDirectory to: {newLogDirectory}, from: {initConfig.LogDirectory}"); + } - private static void SetFinalDbPath(string? baseDbPath, IInitConfig initConfig) - { - if (!string.IsNullOrWhiteSpace(baseDbPath)) - { - string newDbPath = initConfig.BaseDbPath.GetApplicationResourcePath(baseDbPath); - if (_logger.IsDebug) _logger.Debug($"Adding prefix to baseDbPath, new value: {newDbPath}, old value: {initConfig.BaseDbPath}"); - initConfig.BaseDbPath = newDbPath; + initConfig.BaseDbPath = newDbPath; + keyStoreConfig.KeyStoreDirectory = newKeyStorePath; + initConfig.LogDirectory = newLogDirectory; + } + else + { + initConfig.BaseDbPath ??= string.Empty.GetApplicationResourcePath("db"); + keyStoreConfig.KeyStoreDirectory ??= string.Empty.GetApplicationResourcePath("keystore"); + initConfig.LogDirectory ??= string.Empty.GetApplicationResourcePath("logs"); + } } - else + + private static void ConsoleOnCancelKeyPress(object? sender, ConsoleCancelEventArgs e) { - initConfig.BaseDbPath ??= string.Empty.GetApplicationResourcePath("db"); + _processExitSource.Exit(ExitCodes.Ok); + _ = _cancelKeySource.TrySetResult(null); + e.Cancel = true; } - } - private static void SetFinalDataDirectory(string? dataDir, IInitConfig initConfig, IKeyStoreConfig keyStoreConfig) - { - if (!string.IsNullOrWhiteSpace(dataDir)) + private static void ConfigureSeqLogger(IConfigProvider configProvider) { - string newDbPath = initConfig.BaseDbPath.GetApplicationResourcePath(dataDir); - string newKeyStorePath = keyStoreConfig.KeyStoreDirectory.GetApplicationResourcePath(dataDir); - string newLogDirectory = initConfig.LogDirectory.GetApplicationResourcePath(dataDir); - - if (_logger.IsInfo) + ISeqConfig seqConfig = configProvider.GetConfig(); + if (seqConfig.MinLevel != "Off") { - _logger.Info($"Setting BaseDbPath to: {newDbPath}, from: {initConfig.BaseDbPath}"); - _logger.Info($"Setting KeyStoreDirectory to: {newKeyStorePath}, from: {keyStoreConfig.KeyStoreDirectory}"); - _logger.Info($"Setting LogDirectory to: {newLogDirectory}, from: {initConfig.LogDirectory}"); + if (_logger.IsInfo) + _logger.Info($"Seq Logging enabled on host: {seqConfig.ServerUrl} with level: {seqConfig.MinLevel}"); + NLogConfigurator.ConfigureSeqBufferTarget(seqConfig.ServerUrl, seqConfig.ApiKey, seqConfig.MinLevel); + } + else + { + // Clear it up, otherwise internally it will keep requesting to localhost as `all` target include this. + NLogConfigurator.ClearSeqTarget(); } - - initConfig.BaseDbPath = newDbPath; - keyStoreConfig.KeyStoreDirectory = newKeyStorePath; - initConfig.LogDirectory = newLogDirectory; } - else + + private static string GetProductInfo() { - initConfig.BaseDbPath ??= string.Empty.GetApplicationResourcePath("db"); - keyStoreConfig.KeyStoreDirectory ??= string.Empty.GetApplicationResourcePath("keystore"); - initConfig.LogDirectory ??= string.Empty.GetApplicationResourcePath("logs"); - } - } + var info = new StringBuilder(); - private static void ConsoleOnCancelKeyPress(object? sender, ConsoleCancelEventArgs e) - { - _processExitSource.Exit(ExitCodes.Ok); - _ = _cancelKeySource.TrySetResult(null); - e.Cancel = true; - } + info + .Append("Version: ").AppendLine(ProductInfo.Version) + .Append("Commit: ").AppendLine(ProductInfo.Commit) + .Append("Build Date: ").AppendLine(ProductInfo.BuildTimestamp.ToString("u")) + .Append("OS: ") + .Append(ProductInfo.OS) + .Append(' ') + .AppendLine(ProductInfo.OSArchitecture) + .Append("Runtime: ").AppendLine(ProductInfo.Runtime); - private static void ConfigureSeqLogger(IConfigProvider configProvider) - { - ISeqConfig seqConfig = configProvider.GetConfig(); - if (seqConfig.MinLevel != "Off") - { - if (_logger.IsInfo) - _logger.Info($"Seq Logging enabled on host: {seqConfig.ServerUrl} with level: {seqConfig.MinLevel}"); - NLogConfigurator.ConfigureSeqBufferTarget(seqConfig.ServerUrl, seqConfig.ApiKey, seqConfig.MinLevel); - } - else - { - // Clear it up, otherwise internally it will keep requesting to localhost as `all` target include this. - NLogConfigurator.ClearSeqTarget(); + return info.ToString(); } } - - private static string GetProductInfo() - { - var info = new StringBuilder(); - - info - .Append("Version: ").AppendLine(ProductInfo.Version) - .Append("Commit: ").AppendLine(ProductInfo.Commit) - .Append("Build Date: ").AppendLine(ProductInfo.BuildTimestamp.ToString("u")) - .Append("OS: ") - .Append(ProductInfo.OS) - .Append(' ') - .AppendLine(ProductInfo.OSArchitecture) - .Append("Runtime: ").AppendLine(ProductInfo.Runtime); - - return info.ToString(); - } } diff --git a/src/Nethermind/Nethermind.Runner/Properties/launchSettings.json b/src/Nethermind/Nethermind.Runner/Properties/launchSettings.json index 3776aefe1b3..1c393b255df 100644 --- a/src/Nethermind/Nethermind.Runner/Properties/launchSettings.json +++ b/src/Nethermind/Nethermind.Runner/Properties/launchSettings.json @@ -2,133 +2,119 @@ "profiles": { "Chiado": { "commandName": "Project", - "commandLineArgs": "-c chiado -dd .data", + "commandLineArgs": "-c chiado -dd %NETHERMIND_DATA_DIR%", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Chiado (archive)": { "commandName": "Project", - "commandLineArgs": "-c chiado_archive -dd .data", + "commandLineArgs": "-c chiado_archive -dd %NETHERMIND_DATA_DIR%", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "EIP-4844 local trace": { "commandName": "Project", - "commandLineArgs": "-c eip4844_local -dd .data --log TRACE", + "commandLineArgs": "-c eip4844_local -dd %NETHERMIND_DATA_DIR% --log TRACE", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Energy Web": { "commandName": "Project", - "commandLineArgs": "-c energyweb -dd .data --JsonRpc.Enabled true", + "commandLineArgs": "-c energyweb -dd %NETHERMIND_DATA_DIR% --JsonRpc.Enabled true", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Gnosis": { "commandName": "Project", - "commandLineArgs": "-c gnosis -dd .data", + "commandLineArgs": "-c gnosis -dd %NETHERMIND_DATA_DIR%", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Gnosis (archive)": { "commandName": "Project", - "commandLineArgs": "-c gnosis_archive -dd .data", + "commandLineArgs": "-c gnosis_archive -dd %NETHERMIND_DATA_DIR%", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Goerli": { "commandName": "Project", - "commandLineArgs": "-c goerli -dd .data", + "commandLineArgs": "-c goerli -dd %NETHERMIND_DATA_DIR%", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Goerli (archive)": { "commandName": "Project", - "commandLineArgs": "-c goerli_archive -dd .data", + "commandLineArgs": "-c goerli_archive -dd %NETHERMIND_DATA_DIR%", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Hive": { "commandName": "Project", - "commandLineArgs": "-c hive -dd .data --Init.DiagnosticMode MemDb", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "Holesky": { - "commandName": "Project", - "commandLineArgs": "-c holesky -dd .data", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "Holesky (archive)": { - "commandName": "Project", - "commandLineArgs": "-c holesky_archive -dd .data", + "commandLineArgs": "-c hive -dd %NETHERMIND_DATA_DIR% --Init.DiagnosticMode MemDb", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Kovan": { "commandName": "Project", - "commandLineArgs": "-c kovan -dd .data --JsonRpc.Enabled true", + "commandLineArgs": "-c kovan -dd %NETHERMIND_DATA_DIR% --JsonRpc.Enabled true", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Mainnet": { "commandName": "Project", - "commandLineArgs": "-c mainnet -dd .data", + "commandLineArgs": "-c mainnet -dd %NETHERMIND_DATA_DIR%", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Mainnet (archive)": { "commandName": "Project", - "commandLineArgs": "-c mainnet_archive -dd .data", + "commandLineArgs": "-c mainnet_archive -dd %NETHERMIND_DATA_DIR%", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "POA Core": { "commandName": "Project", - "commandLineArgs": "-c poacore -dd .data --JsonRpc.Enabled true", + "commandLineArgs": "-c poacore -dd %NETHERMIND_DATA_DIR% --JsonRpc.Enabled true", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Sepolia": { "commandName": "Project", - "commandLineArgs": "-c sepolia -dd .data", + "commandLineArgs": "-c sepolia -dd %NETHERMIND_DATA_DIR%", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Sepolia (archive)": { "commandName": "Project", - "commandLineArgs": "-c sepolia_archive -dd .data", + "commandLineArgs": "-c sepolia_archive -dd %NETHERMIND_DATA_DIR%", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Spaceneth": { "commandName": "Project", - "commandLineArgs": "-c spaceneth -dd .data", + "commandLineArgs": "-c spaceneth -dd %NETHERMIND_DATA_DIR%", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Volta": { "commandName": "Project", - "commandLineArgs": "-c volta -dd .data --JsonRpc.Enabled true", + "commandLineArgs": "-c volta -dd %NETHERMIND_DATA_DIR% --JsonRpc.Enabled true", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.cfg b/src/Nethermind/Nethermind.Runner/configs/chiado.cfg index b71ef3a2d26..1ab6e4ffd16 100644 --- a/src/Nethermind/Nethermind.Runner/configs/chiado.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/chiado.cfg @@ -13,8 +13,8 @@ "Sync": { "FastSync": true, "FastBlocks": true, - "PivotNumber": 6310000, - "PivotHash": "0xdb60c645fa2f288eb91d889fd0b8819c6e37bee0f69d2d0763179e649b85c09a", + "PivotNumber": 4380000, + "PivotHash": "0xef55b022bd93c51c11325bafe7919f740e360b82515188b660f04dfc12d26b97", "PivotTotalDifficulty": "231708131825107706987652208063906496124457284", "FastSyncCatchUpHeightDelta": "10000000000", "UseGethLimitsInFastBlocks": false diff --git a/src/Nethermind/Nethermind.Runner/configs/eip4844_local.cfg b/src/Nethermind/Nethermind.Runner/configs/eip4844_local.cfg new file mode 100644 index 00000000000..a021f5a7f40 --- /dev/null +++ b/src/Nethermind/Nethermind.Runner/configs/eip4844_local.cfg @@ -0,0 +1,44 @@ +{ + "Init": { + "ChainSpecPath": "chainspec/eip4844_local.json", + "GenesisHash": "0x033931fc47c599fae7058806e8fd0e131e0bf73b2e026cded18267578b09cf2e", + "LogFileName": "eip4844_local.logs.txt", + "MemoryHint": 1024000000 + }, + "TxPool": { + "Size": 1024 + }, + "Metrics": { + "NodeName": "Etho" + }, + "Pruning": { + "Mode": "Hybrid" + }, + "Sync": { + "FastSync": true, + "SnapSync": true, + "FastBlocks": true, + "FastSyncCatchUpHeightDelta": "128" + }, + "Discovery": { + "Bootnodes": "enode://c97e956a20f0214b8304bf42e723b2b8f723bbf1064e981d4267c37c326c77503b383b607dd785ddea04112c855f360ac3d4fca999aa26306a02a2c048256879@127.0.0.1:30304" + }, + "JsonRpc": { + "Enabled": true, + "EnabledModules": ["Admin","Eth","Subscribe","Engine","Trace","TxPool","Web3","Personal","Proof","Net","Parity","Health","Debug"], + "Host": "0.0.0.0", + "UnsecureDevNoRpcAuthentication": true, + "Port": 8547, + "AdditionalRpcUrls": [ + "http://0.0.0.0:8551|http;ws|net;eth;subscribe;engine;web3;client;health" + ] + }, + "Merge": { + "Enabled": true, + "SecondsPerSlot": 6 + }, + "HealthChecks": { + "Enabled": true, + "UIEnabled": true + } +} diff --git a/src/Nethermind/Nethermind.Runner/configs/energyweb.cfg b/src/Nethermind/Nethermind.Runner/configs/energyweb.cfg index 171bfb07952..46d2eb0b660 100644 --- a/src/Nethermind/Nethermind.Runner/configs/energyweb.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/energyweb.cfg @@ -8,9 +8,9 @@ }, "Sync": { "FastSync": true, - "PivotNumber": 26270000, - "PivotHash": "0xf2dc4d73f0d6f790a7eeb4edd1a2f63b8a61edbe36998feef49065cc7cb8fdf6", - "PivotTotalDifficulty": "8939217779013053435182850937232550914583767819", + "PivotNumber": 24480000, + "PivotHash": "0xcdfcaaa3bf507433194509bbd205ef637ef0e6956a363fda5b723ca109307f07", + "PivotTotalDifficulty": "8330112342224573585583410389929685816081252042", "FastBlocks": true, "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 diff --git a/src/Nethermind/Nethermind.Runner/configs/exosama.cfg b/src/Nethermind/Nethermind.Runner/configs/exosama.cfg index d11fe9ad6a2..c90eb64ff4c 100644 --- a/src/Nethermind/Nethermind.Runner/configs/exosama.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/exosama.cfg @@ -8,9 +8,9 @@ }, "Sync": { "FastSync": true, - "PivotNumber": 5930000, - "PivotHash": "0x7c10e55a4c3c0fa900d0989879e389a2b86398a03b90e75a22ac5109a6e6b3b9", - "PivotTotalDifficulty": "2017874435841165088337811422070385493589073289", + "PivotNumber": 4000000, + "PivotHash": "0x3133356c599c48e906e6477e19291d140970c187bb64e690d37f0e27567a48e9", + "PivotTotalDifficulty": "1361129467683753853853498429727072845482853378", "FastBlocks": true, "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 diff --git a/src/Nethermind/Nethermind.Runner/configs/gnosis.cfg b/src/Nethermind/Nethermind.Runner/configs/gnosis.cfg index b32ed29cdba..a22b3802002 100644 --- a/src/Nethermind/Nethermind.Runner/configs/gnosis.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/gnosis.cfg @@ -12,8 +12,8 @@ }, "Sync": { "FastSync": true, - "PivotNumber": 30220000, - "PivotHash": "0x23a088814d684a96780ae26e640c3d4dee8e6c18699706597a5a6b704b43a20f", + "PivotNumber": 28380000, + "PivotHash": "0x59ccc82039e67a33aefbba3710c12d2252c6ac9ce3184161ebe2e6687410e395", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "FastBlocks": true, "UseGethLimitsInFastBlocks": false, diff --git a/src/Nethermind/Nethermind.Runner/configs/goerli.cfg b/src/Nethermind/Nethermind.Runner/configs/goerli.cfg index 43c3e7f38e6..24f3a2d710a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/goerli.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/goerli.cfg @@ -15,8 +15,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 9750000, - "PivotHash": "0xfd773896e9913d63b264ac23c5feb6e930b904ab944339523f792a147f63fbe9", + "PivotNumber": 9120000, + "PivotHash": "0x64b4b8c62191b20f7dd3995ebf8e52b06cc5ddfd283c7e6d1782a73c2e61a00a", "PivotTotalDifficulty": "10790000", "FastBlocks": true, "UseGethLimitsInFastBlocks": true, diff --git a/src/Nethermind/Nethermind.Runner/configs/holesky.cfg b/src/Nethermind/Nethermind.Runner/configs/holesky.cfg deleted file mode 100644 index a66c834aeda..00000000000 --- a/src/Nethermind/Nethermind.Runner/configs/holesky.cfg +++ /dev/null @@ -1,32 +0,0 @@ -{ - "Init": { - "ChainSpecPath": "chainspec/holesky.json", - "GenesisHash": "0xb5f7f912443c940f21fd611f12828d75b534364ed9e95ca4e307729a4661bde4", - "BaseDbPath": "nethermind_db/holesky", - "LogFileName": "holesky.logs.txt" - }, - "Sync": { - "FastSync": true, - "SnapSync": true, - "FastBlocks": true - }, - "Metrics": { - "NodeName": "Holesky" - }, - "Blocks": { - "TargetBlockGasLimit": 30000000 - }, - "JsonRpc": { - "Enabled": true, - "Timeout": 20000, - "Host": "127.0.0.1", - "Port": 8545, - "EngineHost": "127.0.0.1", - "EnginePort": 8551, - "EngineEnabledModules": "net,eth,subscribe,engine,web3,client" - }, - "Merge": { - "Enabled": true, - "FinalTotalDifficulty": "0" - } -} diff --git a/src/Nethermind/Nethermind.Runner/configs/holesky_archive.cfg b/src/Nethermind/Nethermind.Runner/configs/holesky_archive.cfg deleted file mode 100644 index ebd9b36add2..00000000000 --- a/src/Nethermind/Nethermind.Runner/configs/holesky_archive.cfg +++ /dev/null @@ -1,33 +0,0 @@ -{ - "Init": { - "ChainSpecPath": "chainspec/holesky.json", - "GenesisHash": "0xb5f7f912443c940f21fd611f12828d75b534364ed9e95ca4e307729a4661bde4", - "BaseDbPath": "nethermind_db/holesky_archive", - "LogFileName": "holesky_archive.logs.txt" - }, - "Metrics": { - "NodeName": "Holesky Archive" - }, - "Blocks": { - "TargetBlockGasLimit": 30000000 - }, - "Receipt": { - "TxLookupLimit": 0 - }, - "Pruning": { - "Mode": "None" - }, - "JsonRpc": { - "Enabled": true, - "Timeout": 20000, - "Host": "127.0.0.1", - "Port": 8545, - "EngineHost": "127.0.0.1", - "EnginePort": 8551, - "EngineEnabledModules": "net,eth,subscribe,engine,web3,client" - }, - "Merge": { - "Enabled": true, - "FinalTotalDifficulty": "0" - } -} diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg b/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg index fb2696cf3e5..89fa841c557 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg @@ -12,8 +12,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 18250000, - "PivotHash": "0x031f40971a52212af60463cd5042138d6a4c4b7eb9b23765b731da057ea5a9e1", + "PivotNumber": 17452000, + "PivotHash": "0x77ab15efcef6450d780c495ade7683ca2805bf5c629ffca6869cd69835f087bf", "PivotTotalDifficulty": "58750003716598352816469", "FastBlocks": true, "AncientBodiesBarrier": 11052984, diff --git a/src/Nethermind/Nethermind.Runner/configs/ropsten.cfg b/src/Nethermind/Nethermind.Runner/configs/ropsten.cfg new file mode 100644 index 00000000000..845f0e0558e --- /dev/null +++ b/src/Nethermind/Nethermind.Runner/configs/ropsten.cfg @@ -0,0 +1,52 @@ +{ + "Init": { + "ChainSpecPath": "chainspec/ropsten.json", + "GenesisHash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "BaseDbPath": "nethermind_db/ropsten", + "LogFileName": "ropsten.logs.txt", + "MemoryHint": 1024000000 + }, + "TxPool": { + "Size": 1024 + }, + "Sync": { + "FastSync": true, + "SnapSync": true, + "FastBlocks": true, + "UseGethLimitsInFastBlocks": true, + "PivotNumber": 13070000, + "PivotHash": "0x1b3bd0a74ae9df08574c6696ff3ce60a31cce51de8eb4ceb34fb2d05f78b46c6", + "PivotTotalDifficulty": "50000820485795157", + "FastSyncCatchUpHeightDelta": "10000000000" + }, + "EthStats": { + "Server": "ws://localhost:3000/api" + }, + "Metrics": { + "NodeName": "Ropsten" + }, + "JsonRpc": { + "Enabled": true, + "Timeout": 20000, + "Host": "127.0.0.1", + "Port": 8545, + "EnabledModules": [ + "Eth", + "Subscribe", + "Trace", + "TxPool", + "Web3", + "Personal", + "Proof", + "Net", + "Parity", + "Health" + ], + "AdditionalRpcUrls": [ + "http://localhost:8551|http;ws|net;eth;subscribe;engine;web3;client" + ] + }, + "Merge": { + "Enabled": true + } +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/ropsten_archive.cfg b/src/Nethermind/Nethermind.Runner/configs/ropsten_archive.cfg new file mode 100644 index 00000000000..d9afbee32f0 --- /dev/null +++ b/src/Nethermind/Nethermind.Runner/configs/ropsten_archive.cfg @@ -0,0 +1,35 @@ +{ + "Init": { + "ChainSpecPath": "chainspec/ropsten.json", + "GenesisHash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "BaseDbPath": "nethermind_db/ropsten_archive", + "LogFileName": "ropsten_archive.logs.txt", + "MemoryHint": 1536000000 + }, + "TxPool": { + "Size": 1024 + }, + "EthStats": { + "Server": "ws://localhost:3000/api" + }, + "Metrics": { + "NodeName": "Ropsten Archive" + }, + "Receipt": { + "TxLookupLimit": 0 + }, + "Pruning": { + "Mode": "None" + }, + "JsonRpc": { + "Enabled": true, + "Timeout": 20000, + "Host": "127.0.0.1", + "Port": 8545, + "EnabledModules": ["Eth", "Subscribe", "Trace", "TxPool", "Web3", "Personal", "Proof", "Net", "Parity", "Health"], + "AdditionalRpcUrls": ["http://localhost:8551|http;ws|net;eth;subscribe;engine;web3;client"] + }, + "Merge": { + "Enabled": true + } +} diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.cfg b/src/Nethermind/Nethermind.Runner/configs/sepolia.cfg index 2cf6a784a80..0190ee6a17a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia.cfg @@ -18,8 +18,8 @@ "FastBlocks": true, "SnapSync": true, "UseGethLimitsInFastBlocks": true, - "PivotNumber": 4397000, - "PivotHash": "0xa6320283e0831ad392e4b339eb0d8b5e99725a3b849ff40a678ebd70799b6e49", + "PivotNumber": 3664000, + "PivotHash": "0x758b7be085029db19a86afdc8d8b8a3b5077517ecde673d58b8f858be76f339c", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": "10000000000" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/volta.cfg b/src/Nethermind/Nethermind.Runner/configs/volta.cfg index 1b8d36bc3b7..e94f0411d12 100644 --- a/src/Nethermind/Nethermind.Runner/configs/volta.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/volta.cfg @@ -12,9 +12,9 @@ }, "Sync": { "FastSync": true, - "PivotNumber": 24910000, - "PivotHash": "0xc2c29e9469c4c30b8fca15e43613d9522f3f2adc3b7b39a94ba94af4a80e03e2", - "PivotTotalDifficulty": "8476433760000577124872661471125346147004978933", + "PivotNumber": 23370000, + "PivotHash": "0x263e9f1ca462c2363ed160e8ede889abfd7857baafa992bf2b24e57d503169dd", + "PivotTotalDifficulty": "7952398914942331891139064575680423101366204125", "FastBlocks": true, "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 diff --git a/src/Nethermind/Nethermind.Runner/configs/wit.cfg b/src/Nethermind/Nethermind.Runner/configs/wit.cfg new file mode 100644 index 00000000000..f7f7a0841c0 --- /dev/null +++ b/src/Nethermind/Nethermind.Runner/configs/wit.cfg @@ -0,0 +1,22 @@ +{ + "Init": { + "ChainSpecPath": "chainspec/wit.json", + "GenesisHash": "0x14a2603062751658538211f50bc7bac02572f16fd3d7e4f29257dac34165a61a", + "BaseDbPath": "nethermind_db/wit", + "LogFileName": "wit.logs.txt", + "DiagnosticMode": "None", + "MemoryHint": 768000000 + }, + "TxPool": { + "Size": 1024 + }, + "EthStats": { + "Server": "wss://stats.goerli.net/api" + }, + "Metrics": { + "NodeName": "wit" + }, + "Bloom": { + "IndexLevelBucketSizes" : [16, 16, 16, 16] + } +} diff --git a/src/Nethermind/Nethermind.Runner/configs/xdai.cfg b/src/Nethermind/Nethermind.Runner/configs/xdai.cfg new file mode 100644 index 00000000000..f44d5b97a5e --- /dev/null +++ b/src/Nethermind/Nethermind.Runner/configs/xdai.cfg @@ -0,0 +1,42 @@ +{ + "Init": { + "ChainSpecPath": "chainspec/gnosis.json", + "GenesisHash": "0x4f1dd23188aab3a76b463e4af801b52b1248ef073c648cbdc4c9333d3da79756", + "BaseDbPath": "nethermind_db/xdai", + "LogFileName": "xdai.logs.txt", + "MemoryHint": 768000000 + }, + "JsonRpc": { + "Enabled": true, + "EnginePort": 8551 + }, + "Sync": { + "FastSync": true, + "PivotNumber": 28380000, + "PivotHash": "0x59ccc82039e67a33aefbba3710c12d2252c6ac9ce3184161ebe2e6687410e395", + "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", + "FastBlocks": true, + "UseGethLimitsInFastBlocks": false, + "FastSyncCatchUpHeightDelta": 10000000000 + }, + "Blocks": { + "SecondsPerSlot": 5, + "TargetBlockGasLimit": 30000000 + }, + "Mining": { + "MinGasPrice": "1000000000" + }, + "EthStats": { + "Name": "Nethermind xDai" + }, + "Metrics": { + "NodeName": "xDai" + }, + "Bloom": { + "IndexLevelBucketSizes": [ + 16, + 16, + 16 + ] + } +} \ No newline at end of file diff --git a/src/Nethermind/Nethermind.Runner/configs/xdai_archive.cfg b/src/Nethermind/Nethermind.Runner/configs/xdai_archive.cfg new file mode 100644 index 00000000000..fa3c8a9678e --- /dev/null +++ b/src/Nethermind/Nethermind.Runner/configs/xdai_archive.cfg @@ -0,0 +1,36 @@ +{ + "Init": { + "ChainSpecPath": "chainspec/gnosis.json", + "GenesisHash": "0x4f1dd23188aab3a76b463e4af801b52b1248ef073c648cbdc4c9333d3da79756", + "BaseDbPath": "nethermind_db/xdai_archive", + "LogFileName": "xdai_archive.logs.txt", + "MemoryHint": 1024000000 + }, + "JsonRpc": { + "Enabled": true, + "EnginePort": 8551 + }, + "Mining": { + "MinGasPrice": "1000000000" + }, + "Blocks": { + "SecondsPerSlot": 5, + "TargetBlockGasLimit": 30000000 + }, + "Receipt": { + "TxLookupLimit": 0 + }, + "EthStats": { + "Name": "Nethermind xDai" + }, + "Metrics": { + "NodeName": "xDai Archive" + }, + "Bloom": + { + "IndexLevelBucketSizes" : [16, 16, 16] + }, + "Pruning": { + "Mode": "None" + } +} diff --git a/src/Nethermind/Nethermind.Seq/Config/SeqConfig.cs b/src/Nethermind/Nethermind.Seq/Config/SeqConfig.cs index a41870df626..02d0586caba 100644 --- a/src/Nethermind/Nethermind.Seq/Config/SeqConfig.cs +++ b/src/Nethermind/Nethermind.Seq/Config/SeqConfig.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; + namespace Nethermind.Seq.Config { public class SeqConfig : ISeqConfig diff --git a/src/Nethermind/Nethermind.Serialization.Json/ULongConverter.cs b/src/Nethermind/Nethermind.Serialization.Json/ULongConverter.cs index b88725e7afe..4f1517f27f3 100644 --- a/src/Nethermind/Nethermind.Serialization.Json/ULongConverter.cs +++ b/src/Nethermind/Nethermind.Serialization.Json/ULongConverter.cs @@ -6,72 +6,73 @@ using Nethermind.Core.Extensions; using Newtonsoft.Json; -namespace Nethermind.Serialization.Json; - -public class ULongConverter : JsonConverter +namespace Nethermind.Serialization.Json { - private readonly NumberConversion _conversion; - - public ULongConverter() - : this(NumberConversion.Hex) + public class ULongConverter : JsonConverter { - } + private readonly NumberConversion _conversion; - public ULongConverter(NumberConversion conversion) - { - _conversion = conversion; - } - - public override void WriteJson(JsonWriter writer, ulong value, JsonSerializer serializer) - { - switch (_conversion) + public ULongConverter() + : this(NumberConversion.Hex) { - case NumberConversion.Hex: - writer.WriteValue(value.ToHexString(true)); - break; - case NumberConversion.Decimal: - writer.WriteValue(value == 0 ? "0" : value.ToString()); - break; - case NumberConversion.Raw: - writer.WriteValue(value); - break; - default: - throw new NotSupportedException(); } - } - public override ulong ReadJson(JsonReader reader, Type objectType, ulong existingValue, bool hasExistingValue, JsonSerializer serializer) - { - return reader.Value is ulong || reader.Value is int - ? (ulong)reader.Value - : FromString(reader.Value?.ToString()); - } - - public static ulong FromString(string s) - { - if (s is null) + public ULongConverter(NumberConversion conversion) { - throw new JsonException("null cannot be assigned to long"); + _conversion = conversion; } - if (s == "0x0") + public override void WriteJson(JsonWriter writer, ulong value, JsonSerializer serializer) { - return 0UL; + switch (_conversion) + { + case NumberConversion.Hex: + writer.WriteValue(value == 0UL ? "0x0" : value.ToHexString(true)); + break; + case NumberConversion.Decimal: + writer.WriteValue(value == 0 ? "0" : value.ToString()); + break; + case NumberConversion.Raw: + writer.WriteValue(value); + break; + default: + throw new NotSupportedException(); + } } - if (s.StartsWith("0x0")) + public override ulong ReadJson(JsonReader reader, Type objectType, ulong existingValue, bool hasExistingValue, JsonSerializer serializer) { - return ulong.Parse(s.AsSpan(2), NumberStyles.AllowHexSpecifier); + return reader.Value is ulong || reader.Value is int + ? (ulong)reader.Value + : FromString(reader.Value?.ToString()); } - if (s.StartsWith("0x")) + public static ulong FromString(string s) { - Span withZero = new(new char[s.Length - 1]); - withZero[0] = '0'; - s.AsSpan(2).CopyTo(withZero.Slice(1)); - return ulong.Parse(withZero, NumberStyles.AllowHexSpecifier); - } + if (s is null) + { + throw new JsonException("null cannot be assigned to long"); + } - return ulong.Parse(s, NumberStyles.Integer); + if (s == "0x0") + { + return 0UL; + } + + if (s.StartsWith("0x0")) + { + return ulong.Parse(s.AsSpan(2), NumberStyles.AllowHexSpecifier); + } + + if (s.StartsWith("0x")) + { + Span withZero = new(new char[s.Length - 1]); + withZero[0] = '0'; + s.AsSpan(2).CopyTo(withZero.Slice(1)); + return ulong.Parse(withZero, NumberStyles.AllowHexSpecifier); + } + + return ulong.Parse(s, NumberStyles.Integer); + } } } diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/AccountDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/AccountDecoder.cs index aedaa50df13..c4c860ea8d7 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/AccountDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/AccountDecoder.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/BlockDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/BlockDecoder.cs index fc1f0226567..01d826db691 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/BlockDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/BlockDecoder.cs @@ -4,6 +4,7 @@ using System; using System.Buffers; using System.Collections.Generic; +using System.Linq; using Nethermind.Core; namespace Nethermind.Serialization.Rlp diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/BlockInfoDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/BlockInfoDecoder.cs index 52ee69d05c3..c15f52acb0f 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/BlockInfoDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/BlockInfoDecoder.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/ByteArrayExtensions.cs b/src/Nethermind/Nethermind.Serialization.Rlp/ByteArrayExtensions.cs index aff78b367c5..4c39add0a90 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/ByteArrayExtensions.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/ByteArrayExtensions.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using Nethermind.Core.Buffers; namespace Nethermind.Serialization.Rlp { @@ -13,11 +12,6 @@ public static RlpStream AsRlpStream(this byte[]? bytes) return new(bytes ?? Array.Empty()); } - public static RlpStream AsRlpStream(this CappedArray bytes) - { - return new(bytes.Array ?? Array.Empty()); - } - public static Rlp.ValueDecoderContext AsRlpValueContext(this byte[]? bytes) { return new(bytes ?? Array.Empty()); diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/ChainLevelDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/ChainLevelDecoder.cs index c29daf71e00..85e2af8b498 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/ChainLevelDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/ChainLevelDecoder.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Cryptography; using Nethermind.Core; namespace Nethermind.Serialization.Rlp diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/CompactLogEntryDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/CompactLogEntryDecoder.cs index abcc5e0669c..d96c0ba959a 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/CompactLogEntryDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/CompactLogEntryDecoder.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Linq; using Nethermind.Core; using Nethermind.Core.Collections; diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/Eip2930/AccessListDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/Eip2930/AccessListDecoder.cs index bd3a668cc2a..db6bd5048d9 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/Eip2930/AccessListDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/Eip2930/AccessListDecoder.cs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; -using System.Linq; +using System.IO; using Nethermind.Core; using Nethermind.Core.Eip2930; using Nethermind.Int256; @@ -29,7 +29,7 @@ public class AccessListDecoder : IRlpStreamDecoder, IRlpValueDecode int length = rlpStream.ReadSequenceLength(); int check = rlpStream.Position + length; - AccessList.Builder accessListBuilder = new(); + AccessListBuilder accessListBuilder = new(); while (rlpStream.Position < check) { int accessListItemLength = rlpStream.ReadSequenceLength(); @@ -72,7 +72,7 @@ public class AccessListDecoder : IRlpStreamDecoder, IRlpValueDecode rlpStream.Check(check); } - return accessListBuilder.Build(); + return accessListBuilder.ToAccessList(); } /// @@ -94,7 +94,7 @@ public class AccessListDecoder : IRlpStreamDecoder, IRlpValueDecode int length = decoderContext.ReadSequenceLength(); int check = decoderContext.Position + length; - AccessList.Builder accessListBuilder = new(); + AccessListBuilder accessListBuilder = new(); while (decoderContext.Position < check) { int accessListItemLength = decoderContext.ReadSequenceLength(); @@ -137,7 +137,20 @@ public class AccessListDecoder : IRlpStreamDecoder, IRlpValueDecode decoderContext.Check(check); } - return accessListBuilder.Build(); + return accessListBuilder.ToAccessList(); + } + + private readonly struct AccessListItem + { + public AccessListItem(Address address, List indexes) + { + Address = address; + Indexes = indexes; + } + + public Address Address { get; } + + public List Indexes { get; } } public void Encode(RlpStream stream, AccessList? item, RlpBehaviors rlpBehaviors = RlpBehaviors.None) @@ -145,44 +158,86 @@ public void Encode(RlpStream stream, AccessList? item, RlpBehaviors rlpBehaviors if (item is null) { stream.WriteByte(Rlp.NullObjectByte); - return; } - - int contentLength = GetContentLength(item); - stream.StartSequence(contentLength); - foreach ((Address? address, AccessList.StorageKeysEnumerable storageKeys) in item) + else { - // {} brackets applied to show the content structure - // Address - // Index1 - // Index2 - // ... - // IndexN - AccessItemLengths lengths = new(storageKeys.Count()); - stream.StartSequence(lengths.ContentLength); + int contentLength = GetContentLength(item); + stream.StartSequence(contentLength); + + if (!item.IsNormalized) { - stream.Encode(address); - stream.StartSequence(lengths.IndexesContentLength); + AccessListItem? currentItem = default; + + void SerializeCurrent() { - foreach (UInt256 index in storageKeys) + if (currentItem is not null) { - // storage indices are encoded as 32 bytes data arrays - stream.Encode(index, 32); + AccessListItem toEncode = currentItem.Value; + EncodeListItem(stream, toEncode.Address, toEncode.Indexes, toEncode.Indexes.Count); + } + } + + foreach (object accessListEntry in item.OrderQueue!) + { + if (accessListEntry is Address address) + { + // serialize any element that is not the last + SerializeCurrent(); + currentItem = new AccessListItem(address, new List()); + } + else + { + if (currentItem is null) + { + throw new InvalidDataException( + $"{nameof(AccessList)} order looks corrupted - processing index ahead of address"); + } + + currentItem.Value.Indexes.Add((UInt256)accessListEntry); } } + + // serialize the last element + SerializeCurrent(); + } + else + { + foreach ((Address address, IReadOnlySet indexes) in item.Data) + { + EncodeListItem(stream, address, indexes, indexes.Count); + } } } } - public int GetLength(AccessList? accessList, RlpBehaviors rlpBehaviors) + /// + /// Spend some time trying to find some base interface like ICountableEnumerable, none of such in .NET Core + /// + private static void EncodeListItem( + RlpStream stream, + Address address, + IEnumerable indexes, + int indexesCount) { - if (accessList is null) + // {} brackets applied to show the content structure + // Address + // Index1 + // Index2 + // ... + // IndexN + AccessItemLengths lengths = new(indexesCount); + stream.StartSequence(lengths.ContentLength); { - return 1; + stream.Encode(address); + stream.StartSequence(lengths.IndexesContentLength); + { + foreach (UInt256 index in indexes) + { + // storage indices are encoded as 32 bytes data arrays + stream.Encode(index, 32); + } + } } - - int contentLength = GetContentLength(accessList); - return Rlp.LengthOfSequence(contentLength); } /// @@ -206,9 +261,64 @@ public AccessItemLengths(int indexesCount) private static int GetContentLength(AccessList accessList) { - return accessList - .Select(entry => new AccessItemLengths(entry.StorageKeys.Count())) - .Sum(lengths => lengths.SequenceLength); + int contentLength = 0; + if (accessList.IsNormalized) + { + foreach ((_, IReadOnlySet indexes) in accessList.Data) + { + contentLength += new AccessItemLengths(indexes.Count).SequenceLength; + } + } + else + { + IReadOnlyCollection orderQueue = accessList.OrderQueue; + bool isOpen = false; + int indexCounter = 0; + foreach (object accessListEntry in orderQueue!) + { + if (accessListEntry is Address) + { + if (isOpen) + { + contentLength += new AccessItemLengths(indexCounter).SequenceLength; + indexCounter = 0; + } + else + { + isOpen = true; + } + } + else + { + indexCounter++; + } + } + + if (isOpen) + { + contentLength += new AccessItemLengths(indexCounter).SequenceLength; + } + } + + return contentLength; + } + + public int GetLength(AccessList? accessList, RlpBehaviors rlpBehaviors) + { + if (accessList is null) + { + return 1; + } + + int contentLength = GetContentLength(accessList); + return Rlp.LengthOfSequence(contentLength); + } + + public Rlp Encode(AccessList? accessList, RlpBehaviors rlpBehaviors = RlpBehaviors.None) + { + RlpStream rlpStream = new(GetLength(accessList, rlpBehaviors)); + Encode(rlpStream, accessList, rlpBehaviors); + return new Rlp(rlpStream.Data); } } } diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs index 5cc4cb4187e..d6d1ef9fa62 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only using System; @@ -71,25 +71,19 @@ public class HeaderDecoder : IRlpValueDecoder, IRlpStreamDecoder 0 && decoderContext.PeekPrefixAndContentLength().ContentLength == Keccak.Size) { blockHeader.WithdrawalsRoot = decoderContext.DecodeKeccak(); - if (itemsRemaining >= 3 && decoderContext.Position != headerCheck) + if (itemsRemaining == 3 && decoderContext.Position != headerCheck) { - blockHeader.BlobGasUsed = decoderContext.DecodeULong(allowLeadingZeroBytes: false); - blockHeader.ExcessBlobGas = decoderContext.DecodeULong(allowLeadingZeroBytes: false); - } - - if (itemsRemaining == 4 && decoderContext.Position != headerCheck) - { - blockHeader.ParentBeaconBlockRoot = decoderContext.DecodeKeccak(); + blockHeader.DataGasUsed = decoderContext.DecodeULong(); + blockHeader.ExcessDataGas = decoderContext.DecodeULong(); } } - if ((rlpBehaviors & RlpBehaviors.AllowExtraBytes) != RlpBehaviors.AllowExtraBytes) { decoderContext.Check(headerCheck); @@ -158,21 +152,16 @@ public class HeaderDecoder : IRlpValueDecoder, IRlpStreamDecoder 0 && rlpStream.PeekPrefixAndContentLength().ContentLength == Keccak.Size) { blockHeader.WithdrawalsRoot = rlpStream.DecodeKeccak(); - if (itemsRemaining >= 3 && rlpStream.Position != headerCheck) - { - blockHeader.BlobGasUsed = rlpStream.DecodeUlong(allowLeadingZeroBytes: false); - blockHeader.ExcessBlobGas = rlpStream.DecodeUlong(allowLeadingZeroBytes: false); - } - - if (itemsRemaining == 4 && rlpStream.Position != headerCheck) + if (itemsRemaining == 3 && rlpStream.Position != headerCheck) { - blockHeader.ParentBeaconBlockRoot = rlpStream.DecodeKeccak(); + blockHeader.DataGasUsed = rlpStream.DecodeUlong(allowLeadingZeroBytes: false); + blockHeader.ExcessDataGas = rlpStream.DecodeUlong(allowLeadingZeroBytes: false); } } @@ -228,20 +217,15 @@ public void Encode(RlpStream rlpStream, BlockHeader? header, RlpBehaviors rlpBeh rlpStream.Encode(header.BaseFeePerGas); } - if (header.WithdrawalsRoot is not null || header.ExcessBlobGas is not null || header.BlobGasUsed is not null || header.ParentBeaconBlockRoot is not null) + if (header.WithdrawalsRoot is not null || header.ExcessDataGas is not null || header.DataGasUsed is not null) { rlpStream.Encode(header.WithdrawalsRoot ?? Keccak.Zero); } - if (header.BlobGasUsed is not null || header.ExcessBlobGas is not null || header.ParentBeaconBlockRoot is not null) - { - rlpStream.Encode(header.BlobGasUsed.GetValueOrDefault()); - rlpStream.Encode(header.ExcessBlobGas.GetValueOrDefault()); - } - - if (header.ParentBeaconBlockRoot is not null) + if (header.DataGasUsed is not null || header.ExcessDataGas is not null) { - rlpStream.Encode(header.ParentBeaconBlockRoot); + rlpStream.Encode(header.DataGasUsed.GetValueOrDefault()); + rlpStream.Encode(header.ExcessDataGas.GetValueOrDefault()); } } @@ -281,10 +265,9 @@ private static int GetContentLength(BlockHeader? item, RlpBehaviors rlpBehaviors + Rlp.LengthOf(item.Timestamp) + Rlp.LengthOf(item.ExtraData) + (item.BaseFeePerGas.IsZero ? 0 : Rlp.LengthOf(item.BaseFeePerGas)) - + (item.WithdrawalsRoot is null && item.BlobGasUsed is null && item.ExcessBlobGas is null ? 0 : Rlp.LengthOfKeccakRlp) - + (item.ParentBeaconBlockRoot is null ? 0 : Rlp.LengthOfKeccakRlp) - + (item.BlobGasUsed is null ? 0 : Rlp.LengthOf(item.BlobGasUsed.Value)) - + (item.ExcessBlobGas is null ? 0 : Rlp.LengthOf(item.ExcessBlobGas.Value)); + + (item.WithdrawalsRoot is null && item.DataGasUsed is null && item.ExcessDataGas is null ? 0 : Rlp.LengthOfKeccakRlp) + + (item.DataGasUsed is null ? 0 : Rlp.LengthOf(item.DataGasUsed.Value)) + + (item.ExcessDataGas is null ? 0 : Rlp.LengthOf(item.ExcessDataGas.Value)); if (notForSealing) { diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/NettyBufferMemoryOwner.cs b/src/Nethermind/Nethermind.Serialization.Rlp/NettyBufferMemoryOwner.cs deleted file mode 100644 index 4ff463456ab..00000000000 --- a/src/Nethermind/Nethermind.Serialization.Rlp/NettyBufferMemoryOwner.cs +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Buffers; -using DotNetty.Buffers; - -namespace Nethermind.Core.Buffers; - -/// -/// A wrapper around IByteBuffer to expose standard Memory. -/// Internally, IByteBuffer is already a standard array, so no need for a MemoryManager. -/// Technically, IByteBuffer may be several IByteBuffer concatenated together, but we never use it like that. -/// -public class NettyBufferMemoryOwner : IMemoryOwner -{ - private readonly IByteBuffer _byteBuffer; - private bool _disposed = false; - - public NettyBufferMemoryOwner(IByteBuffer byteBuffer) - { - _byteBuffer = byteBuffer; - _byteBuffer.Retain(); - } - - ~NettyBufferMemoryOwner() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool isDisposing) - { - if (!_disposed) - { - _disposed = true; - _byteBuffer.Release(); - } - } - - public Memory Memory => _byteBuffer - .Array - .AsMemory() - .Slice(_byteBuffer.ArrayOffset + _byteBuffer.ReaderIndex, _byteBuffer.ReadableBytes); -} diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/NettyRlpStream.cs b/src/Nethermind/Nethermind.Serialization.Rlp/NettyRlpStream.cs index 66f21af06c3..706d1206459 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/NettyRlpStream.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/NettyRlpStream.cs @@ -70,12 +70,6 @@ public override Span Read(int length) return span; } - public override Span Peek(int offset, int length) - { - Span span = _buffer.Array.AsSpan(_buffer.ArrayOffset + _buffer.ReaderIndex + offset, length); - return span; - } - public override byte PeekByte() { byte result = _buffer.ReadByte(); diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/OwnedBlockBodies.cs b/src/Nethermind/Nethermind.Serialization.Rlp/OwnedBlockBodies.cs deleted file mode 100644 index c2bc6fcb383..00000000000 --- a/src/Nethermind/Nethermind.Serialization.Rlp/OwnedBlockBodies.cs +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Buffers; -using Nethermind.Core.Crypto; -using Nethermind.Serialization.Rlp; - -namespace Nethermind.Core; - -/// -/// A holder for BlockBody[] that must be explicitly disposed or there will be memory leak. May uses netty's buffer directly. -/// BlockBody may contain `Memory` that is explicitly managed. Reusing `BlockBody` from this object after Dispose -/// is likely to cause corrupted `BlockBody`. -/// -public class OwnedBlockBodies : IDisposable -{ - private BlockBody?[]? _rawBodies = null; - - private IMemoryOwner? _memoryOwner = null; - - public OwnedBlockBodies(BlockBody?[]? bodies, IMemoryOwner? memoryOwner = null) - { - _rawBodies = bodies; - _memoryOwner = memoryOwner; - } - - public BlockBody?[]? Bodies => _rawBodies; - - /// - /// Disown the `BlockBody`, copying any `Memory` so that it does not depend on the `_memoryOwner.` - /// - public void Disown() - { - if (_memoryOwner == null) return; - - foreach (BlockBody? blockBody in Bodies) - { - if (blockBody == null) continue; - foreach (Transaction tx in blockBody.Transactions) - { - Keccak? _ = tx.Hash; // Just need to trigger hash calculation - if (tx.Data != null) - { - tx.Data = tx.Data.Value.ToArray(); - } - } - } - - _memoryOwner?.Dispose(); - _memoryOwner = null; - } - - public void Dispose() - { - if (_memoryOwner == null) return; - - foreach (BlockBody? blockBody in Bodies) - { - if (blockBody == null) continue; - foreach (Transaction tx in blockBody.Transactions) - { - TxDecoder.TxObjectPool.Return(tx); - } - } - - _memoryOwner?.Dispose(); - _memoryOwner = null; - } -} diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs b/src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs index b8dc2c3bebb..ddf9239e7cf 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs @@ -479,7 +479,7 @@ public static Rlp Encode(Keccak? keccak) return new Rlp(result); } - public static int StartSequence(Span buffer, int position, int sequenceLength) + public static int StartSequence(byte[] buffer, int position, int sequenceLength) { byte prefix; int beforeLength = position + 1; @@ -568,8 +568,6 @@ public ValueDecoderContext(Memory memory, bool sliceMemory = false) public int Length => Data.Length; - public bool ShouldSliceMemory => _sliceMemory; - public bool IsSequenceNext() { return Data[Position] >= 192; @@ -1405,36 +1403,6 @@ internal byte[][] DecodeByteArrays() return result; } - - public T[] DecodeArray(IRlpValueDecoder? decoder = null, bool checkPositions = true, - T defaultElement = default) - { - if (decoder == null) - { - decoder = GetValueDecoder(); - if (decoder == null) - { - throw new RlpException($"{nameof(Rlp)} does not support length of {nameof(T)}"); - } - } - int positionCheck = ReadSequenceLength() + Position; - int count = PeekNumberOfItemsRemaining(checkPositions ? positionCheck : (int?)null); - T[] result = new T[count]; - for (int i = 0; i < result.Length; i++) - { - if (PeekByte() == Rlp.OfEmptySequence[0]) - { - result[i] = defaultElement; - Position++; - } - else - { - result[i] = decoder.Decode(ref this); - } - } - - return result; - } } public override bool Equals(object? other) diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/RlpDecoderExtensions.cs b/src/Nethermind/Nethermind.Serialization.Rlp/RlpDecoderExtensions.cs index 83edad25ef0..0a0cf494604 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/RlpDecoderExtensions.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/RlpDecoderExtensions.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using DotNetty.Buffers; -using Nethermind.Core.Buffers; namespace Nethermind.Serialization.Rlp { @@ -93,22 +92,6 @@ public static NettyRlpStream EncodeToNewNettyStream(this IRlpStreamDecoder return rlpStream; } - public static CappedArray EncodeToCappedArray(this IRlpStreamDecoder decoder, T? item, RlpBehaviors rlpBehaviors = RlpBehaviors.None, ICappedArrayPool? bufferPool = null) - { - int size = decoder.GetLength(item, rlpBehaviors); - CappedArray buffer = bufferPool.SafeRentBuffer(size); - decoder.Encode(buffer.AsRlpStream(), item, rlpBehaviors); - - return buffer; - } - - public static CappedArray EncodeToCappedArray(this int item, ICappedArrayPool? bufferPool = null) - { - CappedArray buffer = bufferPool.SafeRentBuffer(Rlp.LengthOf(item)); - buffer.AsRlpStream().Encode(item); - return buffer; - } - public static Rlp Encode(this IRlpObjectDecoder decoder, IReadOnlyCollection? items, RlpBehaviors behaviors = RlpBehaviors.None) { if (items is null) diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs b/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs index 640a17aaf84..f96be91df79 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs @@ -146,7 +146,7 @@ private void WriteEncodedLength(int value) public virtual void WriteByte(byte byteToWrite) { - Data[_position++] = byteToWrite; + Data[Position++] = byteToWrite; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -157,15 +157,15 @@ public void Write(byte[] bytesToWrite) public virtual void Write(ReadOnlySpan bytesToWrite) { - bytesToWrite.CopyTo(Data.AsSpan(_position, bytesToWrite.Length)); - _position += bytesToWrite.Length; + bytesToWrite.CopyTo(Data.AsSpan(Position, bytesToWrite.Length)); + Position += bytesToWrite.Length; } public virtual void Write(IReadOnlyList bytesToWrite) { for (int i = 0; i < bytesToWrite.Count; ++i) { - Data![_position + i] = bytesToWrite[i]; + Data![Position + i] = bytesToWrite[i]; } Position += bytesToWrite.Count; } @@ -175,19 +175,7 @@ public virtual void Write(IReadOnlyList bytesToWrite) public byte[]? Data { get; } - private int _position = 0; - - public virtual int Position - { - get - { - return _position; - } - set - { - _position = value; - } - } + public virtual int Position { get; set; } public virtual int Length => Data!.Length; @@ -683,16 +671,9 @@ public int PeekNextRlpLength() } public (int PrefixLength, int ContentLength) ReadPrefixAndContentLength() - { - (int prefixLength, int contentLength) result = PeekPrefixAndContentLength(); - Position += result.prefixLength; - return result; - } - - public (int PrefixLength, int ContentLength) PeekPrefixAndContentLength() { (int prefixLength, int contentLength) result; - int prefix = PeekByte(); + int prefix = ReadByte(); if (prefix <= 128) { result = (0, 1); @@ -710,7 +691,7 @@ public int PeekNextRlpLength() throw new RlpException("Expected length of length less or equal 4"); } - int length = PeekDeserializeLength(1, lengthOfLength); + int length = DeserializeLength(lengthOfLength); if (length < 56) { throw new RlpException($"Expected length greater or equal 56 and was {length}"); @@ -725,7 +706,7 @@ public int PeekNextRlpLength() else { int lengthOfContentLength = prefix - 247; - int contentLength = PeekDeserializeLength(1, lengthOfContentLength); + int contentLength = DeserializeLength(lengthOfContentLength); if (contentLength < 56) { throw new RlpException($"Expected length greater or equal 56 and got {contentLength}"); @@ -738,6 +719,15 @@ public int PeekNextRlpLength() return result; } + public (int PrefixLength, int ContentLength) PeekPrefixAndContentLength() + { + int memorizedPosition = Position; + (int PrefixLength, int ContentLength) result = ReadPrefixAndContentLength(); + + Position = memorizedPosition; + return result; + } + public int ReadSequenceLength() { int prefix = ReadByte(); @@ -774,26 +764,6 @@ private int DeserializeLength(int lengthOfLength) // additional bounds checking from BinaryPrimitives.ReadUInt16BigEndian etc ref byte firstElement = ref MemoryMarshal.GetReference(Read(lengthOfLength)); - return DeserializeLengthRef(ref firstElement, lengthOfLength); - } - - private int PeekDeserializeLength(int offset, int lengthOfLength) - { - if (lengthOfLength == 0 || (uint)lengthOfLength > 4) - { - ThrowArgumentOutOfRangeException(lengthOfLength); - } - - // Will use Unsafe.ReadUnaligned as we know the length of the span is same - // as what we asked for and then explicitly check lengths, so can skip the - // additional bounds checking from BinaryPrimitives.ReadUInt16BigEndian etc - ref byte firstElement = ref MemoryMarshal.GetReference(Peek(offset, lengthOfLength)); - - return DeserializeLengthRef(ref firstElement, lengthOfLength); - } - - private static int DeserializeLengthRef(ref byte firstElement, int lengthOfLength) - { int result = firstElement; if (result == 0) { @@ -848,38 +818,38 @@ static void ThrowInvalidData() { throw new RlpException("Length starts with 0"); } - } - [DoesNotReturn] - static void ThrowArgumentOutOfRangeException(int lengthOfLength) - { - throw new InvalidOperationException($"Invalid length of length = {lengthOfLength}"); + [DoesNotReturn] + static void ThrowArgumentOutOfRangeException(int lengthOfLength) + { + throw new InvalidOperationException($"Invalid length of length = {lengthOfLength}"); + } } public virtual byte ReadByte() { - return Data![_position++]; + return Data![Position++]; } public virtual byte PeekByte() { - return Data![_position]; + return Data![Position]; } protected virtual byte PeekByte(int offset) { - return Data![_position + offset]; + return Data![Position + offset]; } protected virtual void SkipBytes(int length) { - _position += length; + Position += length; } public virtual Span Read(int length) { - Span data = Data.AsSpan(_position, length); - _position += length; + Span data = Data.AsSpan(Position, length); + Position += length; return data; } @@ -1059,12 +1029,9 @@ public Span PeekNextItem() public Span Peek(int length) { - return Peek(0, length); - } - - public virtual Span Peek(int offset, int length) - { - return Data.AsSpan(_position + offset, length); + Span item = Read(length); + Position -= item.Length; + return item; } public bool IsNextItemEmptyArray() diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoder.cs index 1cebed2715e..17b22a02628 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoder.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using Microsoft.Extensions.ObjectPool; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; @@ -10,12 +9,11 @@ namespace Nethermind.Serialization.Rlp { - public class TxDecoder : TxDecoder + public class TxDecoder : TxDecoder, ITransactionSizeCalculator { public const int MaxDelayedHashTxnSize = 32768; public static TxDecoder Instance = new TxDecoder(); public static TxDecoder InstanceWithoutLazyHash = new TxDecoder(false); - public static ObjectPool TxObjectPool = new DefaultObjectPool(new Transaction.PoolPolicy(), Environment.ProcessorCount * 4); public TxDecoder() : base(true) // Rlp will try to find empty constructor. { @@ -25,9 +23,9 @@ public TxDecoder(bool lazyHash) : base(lazyHash) { } - protected override Transaction NewTx() + public int GetLength(Transaction tx) { - return TxObjectPool.Get(); + return GetLength(tx, RlpBehaviors.None); } } public class SystemTxDecoder : TxDecoder { } @@ -46,11 +44,6 @@ protected TxDecoder(bool lazyHash = true) _lazyHash = lazyHash; } - protected virtual T NewTx() - { - return new(); - } - public T? Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { if (rlpStream.IsNextItemNull()) @@ -61,7 +54,7 @@ protected virtual T NewTx() Span transactionSequence = rlpStream.PeekNextItem(); - T transaction = NewTx(); + T transaction = new(); if ((rlpBehaviors & RlpBehaviors.SkipTypedWrapping) == RlpBehaviors.SkipTypedWrapping) { byte firstByte = rlpStream.PeekByte(); @@ -138,7 +131,7 @@ protected virtual T NewTx() else if (transactionSequence.Length <= TxDecoder.MaxDelayedHashTxnSize && _lazyHash) { // Delay hash generation, as may be filtered as having too low gas etc - transaction.SetPreHashNoLock(transactionSequence); + transaction.SetPreHash(transactionSequence); } else { @@ -205,7 +198,7 @@ private void DecodeShardBlobPayloadWithoutSig(T transaction, RlpStream rlpStream transaction.Value = rlpStream.DecodeUInt256(allowLeadingZeroBytes: false); transaction.Data = rlpStream.DecodeByteArray(); transaction.AccessList = _accessListDecoder.Decode(rlpStream, rlpBehaviors); - transaction.MaxFeePerBlobGas = rlpStream.DecodeUInt256(allowLeadingZeroBytes: false); + transaction.MaxFeePerDataGas = rlpStream.DecodeUInt256(allowLeadingZeroBytes: false); transaction.BlobVersionedHashes = rlpStream.DecodeByteArrays(); } @@ -263,7 +256,7 @@ private void DecodeShardBlobPayloadWithoutSig(T transaction, ref Rlp.ValueDecode transaction.Value = decoderContext.DecodeUInt256(allowLeadingZeroBytes: false); transaction.Data = decoderContext.DecodeByteArray(); transaction.AccessList = _accessListDecoder.Decode(ref decoderContext, rlpBehaviors); - transaction.MaxFeePerBlobGas = decoderContext.DecodeUInt256(allowLeadingZeroBytes: false); + transaction.MaxFeePerDataGas = decoderContext.DecodeUInt256(allowLeadingZeroBytes: false); transaction.BlobVersionedHashes = decoderContext.DecodeByteArrays(); } @@ -321,7 +314,7 @@ private void EncodeShardBlobPayloadWithoutPayload(T item, RlpStream stream, RlpB stream.Encode(item.Value); stream.Encode(item.Data); _accessListDecoder.Encode(stream, item.AccessList, rlpBehaviors); - stream.Encode(item.MaxFeePerBlobGas.Value); + stream.Encode(item.MaxFeePerDataGas.Value); stream.Encode(item.BlobVersionedHashes); } @@ -351,19 +344,16 @@ public void Decode(ref Rlp.ValueDecoderContext decoderContext, ref T? transactio if (transaction == null) { - transaction = NewTx(); + transaction = new(); } transaction.Type = TxType.Legacy; - int txSequenceStart = decoderContext.Position; Span transactionSequence = decoderContext.PeekNextItem(); - if ((rlpBehaviors & RlpBehaviors.SkipTypedWrapping) == RlpBehaviors.SkipTypedWrapping) { byte firstByte = decoderContext.PeekByte(); if (firstByte <= 0x7f) // it is typed transactions { - txSequenceStart = decoderContext.Position; transactionSequence = decoderContext.Peek(decoderContext.Length); transaction.Type = (TxType)decoderContext.ReadByte(); } @@ -374,7 +364,6 @@ public void Decode(ref Rlp.ValueDecoderContext decoderContext, ref T? transactio { (int PrefixLength, int ContentLength) prefixAndContentLength = decoderContext.ReadPrefixAndContentLength(); - txSequenceStart = decoderContext.Position; transactionSequence = decoderContext.Peek(prefixAndContentLength.ContentLength); transaction.Type = (TxType)decoderContext.ReadByte(); } @@ -386,7 +375,6 @@ public void Decode(ref Rlp.ValueDecoderContext decoderContext, ref T? transactio int networkWrapperLength = decoderContext.ReadSequenceLength(); networkWrapperCheck = decoderContext.Position + networkWrapperLength; int rlpRength = decoderContext.PeekNextRlpLength(); - txSequenceStart = decoderContext.Position; transactionSequence = decoderContext.Peek(rlpRength); } @@ -438,18 +426,7 @@ public void Decode(ref Rlp.ValueDecoderContext decoderContext, ref T? transactio else if (transactionSequence.Length <= TxDecoder.MaxDelayedHashTxnSize && _lazyHash) { // Delay hash generation, as may be filtered as having too low gas etc - if (decoderContext.ShouldSliceMemory) - { - // Do not copy the memory in this case. - int currentPosition = decoderContext.Position; - decoderContext.Position = txSequenceStart; - transaction.SetPreHashMemoryNoLock(decoderContext.ReadMemory(transactionSequence.Length)); - decoderContext.Position = currentPosition; - } - else - { - transaction.SetPreHashNoLock(transactionSequence); - } + transaction.SetPreHash(transactionSequence); } else { @@ -693,11 +670,11 @@ private int GetShardBlobContentLength(T item) + Rlp.LengthOf(item.Data) + Rlp.LengthOf(item.ChainId ?? 0) + _accessListDecoder.GetLength(item.AccessList, RlpBehaviors.None) - + Rlp.LengthOf(item.MaxFeePerBlobGas) + + (item.MaxFeePerDataGas.Value == 42_000_000_000 ? Rlp.LengthOfSequence(33) : Rlp.LengthOf(item.MaxFeePerDataGas)) + Rlp.LengthOf(item.BlobVersionedHashes); } - private int GetShardBlobNetworkWrapperContentLength(T item, int txContentLength) + private int GetShardBlobNetwrokWrapperContentLength(T item, int txContentLength) { ShardBlobNetworkWrapper networkWrapper = item.NetworkWrapper as ShardBlobNetworkWrapper; return Rlp.LengthOfSequence(txContentLength) @@ -749,7 +726,7 @@ private int GetContentLength(T item, bool forSigning, bool isEip155Enabled = fal switch (item.Type) { case TxType.Blob: - contentLength = GetShardBlobNetworkWrapperContentLength(item, contentLength); + contentLength = GetShardBlobNetwrokWrapperContentLength(item, contentLength); break; } } diff --git a/src/Nethermind/Nethermind.Serialization.Ssz.Test/BitArrayTests.cs b/src/Nethermind/Nethermind.Serialization.Ssz.Test/BitArrayTests.cs index 3e850d02bff..c1edd3bcdff 100644 --- a/src/Nethermind/Nethermind.Serialization.Ssz.Test/BitArrayTests.cs +++ b/src/Nethermind/Nethermind.Serialization.Ssz.Test/BitArrayTests.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections; using System.Collections.Generic; using System.Linq; diff --git a/src/Nethermind/Nethermind.Serialization.Ssz.Test/HashTreeRootTests.cs b/src/Nethermind/Nethermind.Serialization.Ssz.Test/HashTreeRootTests.cs index 5d99dafc40a..6ddcf721c86 100644 --- a/src/Nethermind/Nethermind.Serialization.Ssz.Test/HashTreeRootTests.cs +++ b/src/Nethermind/Nethermind.Serialization.Ssz.Test/HashTreeRootTests.cs @@ -2,9 +2,11 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using Nethermind.Core; +using Nethermind.Core.Extensions; //using Nethermind.Core2.Containers; //using Nethermind.Core2.Crypto; //using Nethermind.Core2.Types; diff --git a/src/Nethermind/Nethermind.Sockets.Test/WebSocketExtensionsTests.cs b/src/Nethermind/Nethermind.Sockets.Test/WebSocketExtensionsTests.cs index 3fc100f4d26..442eecb453a 100644 --- a/src/Nethermind/Nethermind.Sockets.Test/WebSocketExtensionsTests.cs +++ b/src/Nethermind/Nethermind.Sockets.Test/WebSocketExtensionsTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Net.WebSockets; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using Nethermind.Core.Extensions; @@ -16,6 +17,7 @@ using NSubstitute; using NSubstitute.Extensions; using NUnit.Framework; +using NUnit.Framework.Constraints; namespace Nethermind.Sockets.Test { @@ -151,8 +153,8 @@ public async Task Updates_Metrics_And_Stats_Successfully() Assert.That(Metrics.JsonRpcBytesReceivedWebSockets, Is.EqualTo(1024)); Assert.That(Metrics.JsonRpcBytesSentWebSockets, Is.EqualTo(400)); - await localStats.Received(1).ReportCall(Arg.Any(), Arg.Any(), 100); - await localStats.Received(1).ReportCall(Arg.Any(), Arg.Any(), 300); + localStats.Received(1).ReportCall(Arg.Any(), Arg.Any(), 100); + localStats.Received(1).ReportCall(Arg.Any(), Arg.Any(), 300); } [Test] diff --git a/src/Nethermind/Nethermind.Sockets/CounterStream.cs b/src/Nethermind/Nethermind.Sockets/CounterStream.cs deleted file mode 100644 index c8fc360bb13..00000000000 --- a/src/Nethermind/Nethermind.Sockets/CounterStream.cs +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.IO; - -namespace Nethermind.Sockets; - -public class CounterStream : Stream -{ - private readonly Stream _stream; - - public CounterStream(Stream stream) - { - _stream = stream ?? throw new ArgumentNullException(nameof(stream)); - } - - public long WrittenBytes { get; private set; } - - public override void Flush() => _stream.Flush(); - - public override int Read(byte[] buffer, int offset, int count) => _stream.Read(buffer, offset, count); - - public override long Seek(long offset, SeekOrigin origin) => _stream.Seek(offset, origin); - - public override void SetLength(long value) => _stream.SetLength(value); - - public override void Write(byte[] buffer, int offset, int count) - { - _stream.Write(buffer, offset, count); - WrittenBytes += count; - } - - public override bool CanRead - { - get => _stream.CanRead; - } - - public override bool CanSeek - { - get => _stream.CanSeek; - } - - public override bool CanWrite - { - get => _stream.CanWrite; - } - - public override long Length - { - get => _stream.Length; - } - - public override bool CanTimeout - { - get => _stream.CanTimeout; - } - - public override long Position - { - get => _stream.Position; - set => _stream.Position = value; - } -} diff --git a/src/Nethermind/Nethermind.Sockets/ISocketHandler.cs b/src/Nethermind/Nethermind.Sockets/ISocketHandler.cs index 65bd867128a..ddfcb55132e 100644 --- a/src/Nethermind/Nethermind.Sockets/ISocketHandler.cs +++ b/src/Nethermind/Nethermind.Sockets/ISocketHandler.cs @@ -2,7 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.IO; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace Nethermind.Sockets @@ -16,6 +17,5 @@ public interface ISocketHandler : IDisposable Task SendRawAsync(ArraySegment data, bool endMessage = true); Task GetReceiveResult(ArraySegment buffer); Task CloseAsync(ReceiveResult? result); - Stream SendUsingStream(); } } diff --git a/src/Nethermind/Nethermind.Sockets/IWebSocketsModule.cs b/src/Nethermind/Nethermind.Sockets/IWebSocketsModule.cs index 619a650db5c..1a76555826b 100644 --- a/src/Nethermind/Nethermind.Sockets/IWebSocketsModule.cs +++ b/src/Nethermind/Nethermind.Sockets/IWebSocketsModule.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Net.WebSockets; +using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; diff --git a/src/Nethermind/Nethermind.Sockets/IpcSocketsHandler.cs b/src/Nethermind/Nethermind.Sockets/IpcSocketsHandler.cs index 1bfe41c6bde..5cbcc744e93 100644 --- a/src/Nethermind/Nethermind.Sockets/IpcSocketsHandler.cs +++ b/src/Nethermind/Nethermind.Sockets/IpcSocketsHandler.cs @@ -2,8 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.IO; +using System.Collections.Generic; +using System.Linq; using System.Net.Sockets; +using System.Text; using System.Threading.Tasks; namespace Nethermind.Sockets @@ -45,14 +47,9 @@ public Task CloseAsync(ReceiveResult? result) return Task.Factory.StartNew(_socket.Close); } - public Stream SendUsingStream() - { - return new NetworkStream(_socket, FileAccess.Write, ownsSocket: false); - } - public void Dispose() { - _socket.Dispose(); + _socket?.Dispose(); } } } diff --git a/src/Nethermind/Nethermind.Sockets/ReceiveResult.cs b/src/Nethermind/Nethermind.Sockets/ReceiveResult.cs index 2fc5ac1ab8f..69baf861d15 100644 --- a/src/Nethermind/Nethermind.Sockets/ReceiveResult.cs +++ b/src/Nethermind/Nethermind.Sockets/ReceiveResult.cs @@ -1,6 +1,10 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; + namespace Nethermind.Sockets { public class ReceiveResult diff --git a/src/Nethermind/Nethermind.Sockets/SocketClient.cs b/src/Nethermind/Nethermind.Sockets/SocketClient.cs index 76770815dd5..579fd86b7f5 100644 --- a/src/Nethermind/Nethermind.Sockets/SocketClient.cs +++ b/src/Nethermind/Nethermind.Sockets/SocketClient.cs @@ -3,7 +3,12 @@ using System; using System.Buffers; +using System.Collections.Generic; +using System.Diagnostics; using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; using System.Threading.Tasks; using Nethermind.Serialization.Json; diff --git a/src/Nethermind/Nethermind.Sockets/WebSocketHandler.cs b/src/Nethermind/Nethermind.Sockets/WebSocketHandler.cs index fd07cdc2c93..1ca93c0744a 100644 --- a/src/Nethermind/Nethermind.Sockets/WebSocketHandler.cs +++ b/src/Nethermind/Nethermind.Sockets/WebSocketHandler.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.IO; using System.Net.Sockets; using System.Net.WebSockets; using System.Threading; @@ -19,7 +18,7 @@ public class WebSocketHandler : ISocketHandler public WebSocketHandler(WebSocket webSocket, ILogManager logManager) { _webSocket = webSocket; - _logger = logManager.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); + _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); } public Task SendRawAsync(ArraySegment data, bool endOfMessage = true) => @@ -109,14 +108,9 @@ public Task CloseAsync(ReceiveResult? result) return Task.CompletedTask; } - public Stream SendUsingStream() - { - return new WebSocketStream(_webSocket, WebSocketMessageType.Text); - } - public void Dispose() { - _webSocket.Dispose(); + _webSocket?.Dispose(); } } } diff --git a/src/Nethermind/Nethermind.Sockets/WebSocketStream.cs b/src/Nethermind/Nethermind.Sockets/WebSocketStream.cs deleted file mode 100644 index c2d36755256..00000000000 --- a/src/Nethermind/Nethermind.Sockets/WebSocketStream.cs +++ /dev/null @@ -1,108 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.IO; -using System.Net.WebSockets; -using System.Threading; -using System.Threading.Tasks; - -namespace Nethermind.Sockets; - -public class WebSocketStream : Stream -{ - private WebSocket? _socket; - private readonly WebSocketMessageType _messageType; - - public WebSocketStream(WebSocket socket, WebSocketMessageType messageType) - { - _socket = socket; - _messageType = messageType; - } - - public override bool CanRead => true; - public override bool CanSeek => false; - public override bool CanWrite => true; - public override long Length => throw new NotSupportedException(); - - public override long Position - { - get => throw new NotSupportedException(); - set => throw new NotSupportedException(); - } - - public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - ThrowIfDisposed(); - _ = _socket ?? throw new InvalidOperationException($"The underlying {nameof(WebSocket)} is null"); - - if (_socket.State is WebSocketState.Closed or WebSocketState.CloseReceived or WebSocketState.CloseSent) - { - return 0; - } - - ArraySegment segment = new(buffer, offset, count); - WebSocketReceiveResult result = await _socket.ReceiveAsync(segment, cancellationToken); - - if (result.MessageType == WebSocketMessageType.Close) - { - await _socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Remote close", cancellationToken); - return 0; - } - - return result.Count; - } - - public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - ThrowIfDisposed(); - _ = _socket ?? throw new ArgumentNullException(nameof(_socket)); - if (_socket.State != WebSocketState.Open) { throw new IOException($"WebSocket not open ({_socket.State})"); } - - ArraySegment segment = new(buffer, offset, count); - await _socket.SendAsync(segment, _messageType, false, cancellationToken); - } - - public override void Flush() { } - - public override int Read(byte[] buffer, int offset, int count) - { - return ReadAsync(buffer, offset, count).GetAwaiter().GetResult(); - } - - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException(); - } - - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - public override void Write(byte[] buffer, int offset, int count) - { - WriteAsync(buffer, offset, count).GetAwaiter().GetResult(); - } - - protected override void Dispose(bool disposing) - { - try - { - if (disposing) - { - _socket?.SendAsync(ReadOnlyMemory.Empty, WebSocketMessageType.Text, true, CancellationToken.None); - } - } - finally - { - _socket = null; - base.Dispose(disposing); - } - } - - private void ThrowIfDisposed() - { - if (_socket == null) throw new ObjectDisposedException(nameof(_socket)); - } -} diff --git a/src/Nethermind/Nethermind.Sockets/WebSocketsReceiveResult.cs b/src/Nethermind/Nethermind.Sockets/WebSocketsReceiveResult.cs index e25848ba02f..56f99e2c4f3 100644 --- a/src/Nethermind/Nethermind.Sockets/WebSocketsReceiveResult.cs +++ b/src/Nethermind/Nethermind.Sockets/WebSocketsReceiveResult.cs @@ -1,6 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; using System.Net.WebSockets; namespace Nethermind.Sockets diff --git a/src/Nethermind/Nethermind.Specs.Test/ChainParametersTests.cs b/src/Nethermind/Nethermind.Specs.Test/ChainParametersTests.cs deleted file mode 100644 index 18c8948698b..00000000000 --- a/src/Nethermind/Nethermind.Specs.Test/ChainParametersTests.cs +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using System.Linq; -using Nethermind.Specs.ChainSpecStyle; -using Nethermind.Specs.ChainSpecStyle.Json; -using NUnit.Framework; - -namespace Nethermind.Specs.Test; - -public class ChainParametersTests -{ - [Test] - public void ChainParameters_should_have_same_properties_as_chainSpecParamsJson() - { - string[] chainParametersExceptions = { - "Registrar" - }; - string[] chainSpecParamsJsonExceptions = { - "ChainId", "EnsRegistrar", "NetworkId" - }; - IEnumerable chainParametersProperties = typeof(ChainParameters).GetProperties() - .Where(x => !chainParametersExceptions.Contains(x.Name)) - .Select(x => x.Name); - IEnumerable chainSpecParamsJsonProperties = typeof(ChainSpecParamsJson).GetProperties() - .Where(x => !chainSpecParamsJsonExceptions.Contains(x.Name)). - Select(x => x.Name); - - Assert.That(chainParametersProperties, Is.EquivalentTo(chainSpecParamsJsonProperties)); - } -} diff --git a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs index b5180ea82c6..84b64b91bae 100644 --- a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs +++ b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs @@ -22,8 +22,6 @@ namespace Nethermind.Specs.Test.ChainSpecStyle; [TestFixture] public class ChainSpecBasedSpecProviderTests { - private const double GnosisBlockTime = 5; - [TestCase(0, null, false)] [TestCase(0, 0ul, false)] [TestCase(0, 4660ul, false)] @@ -119,7 +117,11 @@ public void Logs_warning_when_timestampActivation_happens_before_blockActivation [Test] public void Sepolia_loads_properly() { - ChainSpec chainSpec = LoadChainSpecFromChainFolder("sepolia"); + ChainSpecLoader loader = new(new EthereumJsonSerializer()); + string path = Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../Chains/sepolia.json"); + ChainSpec chainSpec = loader.Load(File.ReadAllText(path)); + chainSpec.Parameters.Eip2537Transition.Should().BeNull(); + ChainSpecBasedSpecProvider provider = new(chainSpec); SepoliaSpecProvider sepolia = SepoliaSpecProvider.Instance; @@ -138,37 +140,6 @@ public void Sepolia_loads_properly() Assert.That(provider.GenesisSpec.DifficultyBombDelay, Is.EqualTo(long.MaxValue)); Assert.That(provider.ChainId, Is.EqualTo(BlockchainIds.Sepolia)); Assert.That(provider.NetworkId, Is.EqualTo(BlockchainIds.Sepolia)); - - GetTransitionTimestamps(chainSpec.Parameters).Should().AllSatisfy( - t => ValidateSlotByTimestamp(t, SepoliaSpecProvider.BeaconChainGenesisTimestamp).Should().BeTrue()); - } - - [Test] - public void Holesky_loads_properly() - { - ChainSpec chainSpec = LoadChainSpecFromChainFolder("holesky"); - ChainSpecBasedSpecProvider provider = new(chainSpec); - ISpecProvider hardCodedSpec = HoleskySpecProvider.Instance; - - List forkActivationsToTest = new() - { - new ForkActivation(0, HoleskySpecProvider.GenesisTimestamp), - new ForkActivation(1, HoleskySpecProvider.ShanghaiTimestamp), - new ForkActivation(3, HoleskySpecProvider.ShanghaiTimestamp + 24), - //new ForkActivation(4, HoleskySpecProvider.CancunTimestamp), - //new ForkActivation(5, HoleskySpecProvider.CancunTimestamp + 12), - }; - - CompareSpecProviders(hardCodedSpec, provider, forkActivationsToTest); - Assert.That(provider.TerminalTotalDifficulty, Is.EqualTo(hardCodedSpec.TerminalTotalDifficulty)); - Assert.That(provider.GenesisSpec.Eip1559TransitionBlock, Is.EqualTo(0)); - Assert.That(provider.GenesisSpec.DifficultyBombDelay, Is.EqualTo(0)); - Assert.That(provider.ChainId, Is.EqualTo(BlockchainIds.Holesky)); - Assert.That(provider.NetworkId, Is.EqualTo(BlockchainIds.Holesky)); - - // because genesis time for holesky is set 5 minutes before the launch of the chain. this test fails. - //GetTransitionTimestamps(chainSpec.Parameters).Should().AllSatisfy( - // t => ValidateSlotByTimestamp(t, HoleskySpecProvider.GenesisTimestamp).Should().BeTrue()); } [Test] @@ -203,7 +174,11 @@ public void Rinkeby_loads_properly() [Test] public void Goerli_loads_properly() { - ChainSpec chainSpec = LoadChainSpecFromChainFolder("goerli"); + ChainSpecLoader loader = new(new EthereumJsonSerializer()); + string path = Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../Chains/goerli.json"); + ChainSpec chainSpec = loader.Load(File.ReadAllText(path)); + chainSpec.Parameters.Eip2537Transition.Should().BeNull(); + ChainSpecBasedSpecProvider provider = new(chainSpec); GoerliSpecProvider goerli = GoerliSpecProvider.Instance; @@ -226,22 +201,22 @@ public void Goerli_loads_properly() Assert.That(provider.TerminalTotalDifficulty, Is.EqualTo(GoerliSpecProvider.Instance.TerminalTotalDifficulty)); Assert.That(provider.ChainId, Is.EqualTo(BlockchainIds.Goerli)); Assert.That(provider.NetworkId, Is.EqualTo(BlockchainIds.Goerli)); - - GetTransitionTimestamps(chainSpec.Parameters).Should().AllSatisfy( - t => ValidateSlotByTimestamp(t, GoerliSpecProvider.BeaconChainGenesisTimestamp).Should().BeTrue()); } [Test] public void Chiado_loads_properly() { - ChainSpec chainSpec = LoadChainSpecFromChainFolder("chiado"); + ChainSpecLoader loader = new(new EthereumJsonSerializer()); + string path = Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../Chains/chiado.json"); + ChainSpec chainSpec = loader.Load(File.ReadAllText(path)); + ChainSpecBasedSpecProvider provider = new(chainSpec); ChiadoSpecProvider chiado = ChiadoSpecProvider.Instance; List forkActivationsToTest = new() { (ForkActivation)0, - (ForkActivation)(1, 20), + //(ForkActivation)1, (1, ChiadoSpecProvider.ShanghaiTimestamp - 1), (1, ChiadoSpecProvider.ShanghaiTimestamp), (999_999_999, 999_999_999) // far in the future @@ -252,18 +227,18 @@ public void Chiado_loads_properly() Assert.That(provider.ChainId, Is.EqualTo(BlockchainIds.Chiado)); Assert.That(provider.NetworkId, Is.EqualTo(BlockchainIds.Chiado)); - IReleaseSpec? preShanghaiSpec = provider.GetSpec((1, ChiadoSpecProvider.ShanghaiTimestamp - 1)); - IReleaseSpec? postShanghaiSpec = provider.GetSpec((1, ChiadoSpecProvider.ShanghaiTimestamp)); - - VerifyGnosisShanghaiExceptions(preShanghaiSpec, postShanghaiSpec); - GetTransitionTimestamps(chainSpec.Parameters).Should().AllSatisfy( - t => ValidateSlotByTimestamp(t, ChiadoSpecProvider.BeaconChainGenesisTimestamp, GnosisBlockTime).Should().BeTrue()); + provider.GetSpec((1, ChiadoSpecProvider.ShanghaiTimestamp - 1)).MaxCodeSize.Should().Be(long.MaxValue); + provider.GetSpec((1, ChiadoSpecProvider.ShanghaiTimestamp)).MaxCodeSize.Should().Be(24576L); + provider.GetSpec((1, ChiadoSpecProvider.ShanghaiTimestamp)).MaxInitCodeSize.Should().Be(2 * 24576L); } [Test] public void Gnosis_loads_properly() { - ChainSpec chainSpec = LoadChainSpecFromChainFolder("gnosis"); + ChainSpecLoader loader = new(new EthereumJsonSerializer()); + string path = Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../Chains/gnosis.json"); + ChainSpec chainSpec = loader.Load(File.ReadAllText(path)); + ChainSpecBasedSpecProvider provider = new(chainSpec); GnosisSpecProvider gnosisSpecProvider = GnosisSpecProvider.Instance; @@ -291,51 +266,22 @@ public void Gnosis_loads_properly() Assert.That(provider.ChainId, Is.EqualTo(BlockchainIds.Gnosis)); Assert.That(provider.NetworkId, Is.EqualTo(BlockchainIds.Gnosis)); - VerifyGnosisPreShanghaiExceptions(provider); + provider.GetSpec((1, GnosisSpecProvider.ShanghaiTimestamp - 1)).MaxCodeSize.Should().Be(long.MaxValue); - IReleaseSpec? preShanghaiSpec = provider.GetSpec((GnosisSpecProvider.LondonBlockNumber + 1, - GnosisSpecProvider.ShanghaiTimestamp - 1)); - IReleaseSpec? postShanghaiSpec = provider.GetSpec((GnosisSpecProvider.LondonBlockNumber + 1, - GnosisSpecProvider.ShanghaiTimestamp)); - - VerifyGnosisShanghaiExceptions(preShanghaiSpec, postShanghaiSpec); - GetTransitionTimestamps(chainSpec.Parameters).Should().AllSatisfy( - t => ValidateSlotByTimestamp(t, GnosisSpecProvider.BeaconChainGenesisTimestamp, GnosisBlockTime).Should().BeTrue()); - } - - private void VerifyGnosisShanghaiExceptions(IReleaseSpec preShanghaiSpec, IReleaseSpec postShanghaiSpec) - { - preShanghaiSpec.MaxCodeSize.Should().Be(long.MaxValue); - postShanghaiSpec.MaxCodeSize.Should().Be(24576L); - - preShanghaiSpec.MaxInitCodeSize.Should().Be(-2L); // doesn't have meaningful value before EIP3860 - postShanghaiSpec.MaxInitCodeSize.Should().Be(2 * 24576L); - - preShanghaiSpec.LimitCodeSize.Should().Be(false); - postShanghaiSpec.LimitCodeSize.Should().Be(true); - - preShanghaiSpec.IsEip170Enabled.Should().Be(false); - postShanghaiSpec.IsEip170Enabled.Should().Be(true); - } - - private void VerifyGnosisPreShanghaiExceptions(ISpecProvider specProvider) - { - specProvider.GenesisSpec.MaximumUncleCount.Should().Be(0); - specProvider.GetSpec((ForkActivation)(GnosisSpecProvider.ConstantinopoleBlockNumber - (1))).IsEip1283Enabled.Should() - .BeFalse(); - specProvider.GetSpec((ForkActivation)GnosisSpecProvider.ConstantinopoleBlockNumber).IsEip1283Enabled.Should() - .BeTrue(); - specProvider.GetSpec((ForkActivation)(GnosisSpecProvider.ConstantinopoleBlockNumber - 1)).UseConstantinopleNetGasMetering.Should() - .BeFalse(); - specProvider.GetSpec((ForkActivation)GnosisSpecProvider.ConstantinopoleBlockNumber).UseConstantinopleNetGasMetering.Should() - .BeTrue(); + /* ToDo uncomment when we have gnosis shapella timestamp + provider.GetSpec((1, GnosisSpecProvider.ShanghaiTimestamp)).MaxCodeSize.Should().Be(24576L); + provider.GetSpec((1, GnosisSpecProvider.ShanghaiTimestamp)).MaxInitCodeSize.Should().Be(2 * 24576L);*/ } [Test] public void Mainnet_loads_properly() { - ChainSpec chainSpec = LoadChainSpecFromChainFolder("foundation"); + ChainSpecLoader loader = new(new EthereumJsonSerializer()); + string path = Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../Chains/foundation.json"); + ChainSpec chainSpec = loader.Load(File.ReadAllText(path)); + chainSpec.Parameters.Eip2537Transition.Should().BeNull(); + ChainSpecBasedSpecProvider provider = new(chainSpec); MainnetSpecProvider mainnet = MainnetSpecProvider.Instance; @@ -375,7 +321,6 @@ public void Mainnet_loads_properly() provider.GetSpec((MainnetSpecProvider.SpuriousDragonBlockNumber, null)).MaxCodeSize.Should().Be(24576L); provider.GetSpec((MainnetSpecProvider.SpuriousDragonBlockNumber, null)).MaxInitCodeSize.Should().Be(2 * 24576L); - provider.GetSpec((ForkActivation)(long.MaxValue - 1)).IsEip2537Enabled.Should().BeFalse(); Assert.That(provider.GenesisSpec.Eip1559TransitionBlock, Is.EqualTo(MainnetSpecProvider.LondonBlockNumber)); Assert.That(provider.GetSpec((ForkActivation)4_369_999).DifficultyBombDelay, Is.EqualTo(0_000_000)); Assert.That(provider.GetSpec((ForkActivation)4_370_000).DifficultyBombDelay, Is.EqualTo(3_000_000)); @@ -395,9 +340,6 @@ public void Mainnet_loads_properly() Assert.That(provider.TerminalTotalDifficulty, Is.EqualTo(MainnetSpecProvider.Instance.TerminalTotalDifficulty)); Assert.That(provider.ChainId, Is.EqualTo(BlockchainIds.Mainnet)); Assert.That(provider.NetworkId, Is.EqualTo(BlockchainIds.Mainnet)); - - GetTransitionTimestamps(chainSpec.Parameters).Should().AllSatisfy( - t => ValidateSlotByTimestamp(t, MainnetSpecProvider.BeaconChainGenesisTimestamp).Should().BeTrue()); } [Flags] @@ -467,11 +409,41 @@ private static void CompareSpecs(IReleaseSpec expectedSpec, IReleaseSpec actualS } } - private ChainSpec LoadChainSpecFromChainFolder(string chain) + [Test] + public void Ropsten_loads_properly() { ChainSpecLoader loader = new(new EthereumJsonSerializer()); - string path = Path.Combine(TestContext.CurrentContext.WorkDirectory, $"../../../../Chains/{chain}.json"); - return loader.Load(File.ReadAllText(path)); + string path = Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../Chains/ropsten.json"); + ChainSpec chainSpec = loader.Load(File.ReadAllText(path)); + chainSpec.Parameters.Eip2537Transition.Should().BeNull(); + + ChainSpecBasedSpecProvider provider = new(chainSpec); + RopstenSpecProvider ropsten = RopstenSpecProvider.Instance; + + List forkActivationsToTest = new() + { + (ForkActivation)0, + (ForkActivation)1, + (ForkActivation)(RopstenSpecProvider.SpuriousDragonBlockNumber - 1), + (ForkActivation)RopstenSpecProvider.SpuriousDragonBlockNumber, + (ForkActivation)(RopstenSpecProvider.ByzantiumBlockNumber - 1), + (ForkActivation)RopstenSpecProvider.ByzantiumBlockNumber, + (ForkActivation)(RopstenSpecProvider.ConstantinopleFixBlockNumber - 1), + (ForkActivation)RopstenSpecProvider.ConstantinopleFixBlockNumber, + (ForkActivation)(RopstenSpecProvider.IstanbulBlockNumber - 1), + (ForkActivation)RopstenSpecProvider.IstanbulBlockNumber, + (ForkActivation)(RopstenSpecProvider.MuirGlacierBlockNumber - 1), + (ForkActivation)RopstenSpecProvider.MuirGlacierBlockNumber, + (ForkActivation)(RopstenSpecProvider.BerlinBlockNumber - 1), + (ForkActivation)RopstenSpecProvider.BerlinBlockNumber, + (ForkActivation)(RopstenSpecProvider.LondonBlockNumber - 1), + (ForkActivation)RopstenSpecProvider.LondonBlockNumber, + (ForkActivation)999_999_999, // far in the future + }; + + CompareSpecProviders(ropsten, provider, forkActivationsToTest, CompareSpecsOptions.CheckDifficultyBomb); + Assert.That(provider.TerminalTotalDifficulty, Is.EqualTo(RopstenSpecProvider.Instance.TerminalTotalDifficulty)); + Assert.That(provider.GenesisSpec.Eip1559TransitionBlock, Is.EqualTo(RopstenSpecProvider.LondonBlockNumber)); } [Test] @@ -708,6 +680,7 @@ public void Eip_transitions_loaded_correctly() Eip2028Transition = 20280L, Eip2200Transition = 22000L, Eip2315Transition = 23150L, + Eip2537Transition = 25370L, Eip2565Transition = 25650L, Eip2929Transition = 29290L, Eip2930Transition = 29300L, @@ -727,7 +700,6 @@ public void Eip_transitions_loaded_correctly() Eip3855TransitionTimestamp = 1000000012, Eip3860TransitionTimestamp = 1000000012, Eip1153TransitionTimestamp = 1000000024, - Eip2537TransitionTimestamp = 1000000024 } }; @@ -791,13 +763,11 @@ void TestTransitions(ForkActivation activation, Action changes) TestTransitions((ForkActivation)22000L, r => { r.IsEip2200Enabled = true; }); TestTransitions((ForkActivation)23000L, r => { r.IsEip1283Enabled = r.IsEip1344Enabled = true; }); TestTransitions((ForkActivation)24000L, r => { r.IsEip2315Enabled = r.ValidateChainId = r.ValidateReceipts = true; }); - TestTransitions((ForkActivation)29290L, r => { r.IsEip2929Enabled = r.IsEip2565Enabled = true; }); + TestTransitions((ForkActivation)29290L, r => { r.IsEip2929Enabled = r.IsEip2537Enabled = r.IsEip2565Enabled = true; }); TestTransitions((ForkActivation)29300L, r => { r.IsEip2930Enabled = true; }); TestTransitions((ForkActivation)31980L, r => { r.IsEip3198Enabled = true; }); TestTransitions((ForkActivation)35290L, r => { r.IsEip3529Enabled = true; }); TestTransitions((ForkActivation)35410L, r => { r.IsEip3541Enabled = true; }); - TestTransitions((ForkActivation)35410L, r => { r.IsEip3541Enabled = true; }); - TestTransitions((41000L, 1000000012), r => { @@ -805,25 +775,6 @@ void TestTransitions(ForkActivation activation, Action changes) r.IsEip3855Enabled = true; r.IsEip3860Enabled = true; }); - TestTransitions((40001L, 1000000024), r => { r.IsEip1153Enabled = r.IsEip2537Enabled = true; }); + TestTransitions((40001L, 1000000024), r => { r.IsEip1153Enabled = true; }); } - - private static IEnumerable GetTransitionTimestamps(ChainParameters parameters) => parameters.GetType() - .Properties() - .Where(p => p.Name.EndsWith("TransitionTimestamp", StringComparison.Ordinal)) - .Select(p => (ulong?)p.GetValue(parameters)) - .Where(t => t is not null) - .Select(t => t!.Value); - - /// - /// Validates the timestamp specified by making sure the resulting slot is a multiple of 8192. - /// - /// The timestamp to validate - /// The network's genesis timestamp - /// The network's block time in seconds - /// true if the timestamp is valid; otherwise, false. - private static bool ValidateSlotByTimestamp(ulong timestamp, ulong genesisTimestamp, double blockTime = 12) => - timestamp > genesisTimestamp && - Math.Round((timestamp - genesisTimestamp) / blockTime) % 0x2000 == 0 && - Math.Ceiling((timestamp - genesisTimestamp) / blockTime) % 0x2000 == 0; } diff --git a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecLoaderTests.cs b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecLoaderTests.cs index 6891b0681e0..e61ea183e66 100644 --- a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecLoaderTests.cs +++ b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecLoaderTests.cs @@ -118,6 +118,65 @@ private static ChainSpec LoadChainSpec(string path) return chainSpec; } + [Test] + public void Can_load_ropsten() + { + string path = Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../", "Chains/ropsten.json"); + ChainSpec chainSpec = LoadChainSpec(path); + + Assert.That(chainSpec.NetworkId, Is.EqualTo(3), $"{nameof(chainSpec.NetworkId)}"); + Assert.That(chainSpec.Name, Is.EqualTo("Ropsten Testnet"), $"{nameof(chainSpec.Name)}"); + Assert.NotNull(chainSpec.Genesis, $"{nameof(ChainSpec.Genesis)}"); + + Assert.That(chainSpec.Parameters.Eip1559BaseFeeInitialValue, Is.EqualTo(1.GWei()), $"fork base fee"); + Assert.That(chainSpec.Genesis.Header.Nonce, Is.EqualTo(0x0000000000000042UL), $"genesis {nameof(BlockHeader.Nonce)}"); + Assert.That(chainSpec.Genesis.Header.MixHash, Is.EqualTo(Keccak.Zero), $"genesis {nameof(BlockHeader.MixHash)}"); + Assert.That((long)chainSpec.Genesis.Header.Difficulty, Is.EqualTo(0x100000L), $"genesis {nameof(BlockHeader.Difficulty)}"); + Assert.That(chainSpec.Genesis.Header.Beneficiary, Is.EqualTo(Address.Zero), $"genesis {nameof(BlockHeader.Beneficiary)}"); + Assert.That((long)chainSpec.Genesis.Header.Timestamp, Is.EqualTo(0x00L), $"genesis {nameof(BlockHeader.Timestamp)}"); + Assert.That(chainSpec.Genesis.Header.ParentHash, Is.EqualTo(Keccak.Zero), $"genesis {nameof(BlockHeader.ParentHash)}"); + Assert.That( + chainSpec.Genesis.Header.ExtraData, Is.EqualTo(Bytes.FromHexString("0x3535353535353535353535353535353535353535353535353535353535353535")), + $"genesis {nameof(BlockHeader.ExtraData)}"); + Assert.That(chainSpec.Genesis.Header.GasLimit, Is.EqualTo(0x1000000L), $"genesis {nameof(BlockHeader.GasLimit)}"); + + Assert.NotNull(chainSpec.Allocations, $"{nameof(ChainSpec.Allocations)}"); + Assert.That(chainSpec.Allocations.Count, Is.EqualTo(257), $"allocations count"); + Assert.That( + chainSpec.Allocations[new Address("0000000000000000000000000000000000000018")].Balance, Is.EqualTo(UInt256.Zero), + "account 0000000000000000000000000000000000000018"); + Assert.That( + chainSpec.Allocations[new Address("0000000000000000000000000000000000000001")].Balance, Is.EqualTo(UInt256.One), + "account 0000000000000000000000000000000000000001"); + + Assert.That( + chainSpec.Allocations[new Address("874b54a8bd152966d63f706bae1ffeb0411921e5")].Balance, Is.EqualTo(UInt256.Parse("1000000000000000000000000000000")), + "account 874b54a8bd152966d63f706bae1ffeb0411921e5"); + + Assert.That(chainSpec.SealEngineType, Is.EqualTo(SealEngineType.Ethash), "engine"); + + Assert.That(chainSpec.HomesteadBlockNumber, Is.EqualTo((long?)0), "homestead no"); + Assert.That(chainSpec.DaoForkBlockNumber, Is.EqualTo(null), "dao no"); + Assert.That(chainSpec.TangerineWhistleBlockNumber, Is.EqualTo((long?)0), "tw no"); + Assert.That(chainSpec.SpuriousDragonBlockNumber, Is.EqualTo((long?)10), "sd no"); + Assert.That(chainSpec.ByzantiumBlockNumber, Is.EqualTo((long?)1700000), "byzantium no"); + Assert.That(chainSpec.ConstantinopleBlockNumber, Is.EqualTo((long?)4230000), "constantinople no"); + Assert.That(chainSpec.ConstantinopleFixBlockNumber, Is.EqualTo((long?)0x4b5e82), "constantinople fix no"); + Assert.That(chainSpec.IstanbulBlockNumber, Is.EqualTo((long?)0x62F756), "istanbul no"); + + chainSpec.HomesteadBlockNumber.Should().Be(0L); + chainSpec.DaoForkBlockNumber.Should().Be(null); + chainSpec.TangerineWhistleBlockNumber.Should().Be(0L); + chainSpec.SpuriousDragonBlockNumber.Should().Be(RopstenSpecProvider.SpuriousDragonBlockNumber); + chainSpec.ByzantiumBlockNumber.Should().Be(RopstenSpecProvider.ByzantiumBlockNumber); + chainSpec.ConstantinopleBlockNumber.Should().Be(RopstenSpecProvider.ConstantinopleBlockNumber); + chainSpec.ConstantinopleFixBlockNumber.Should().Be(RopstenSpecProvider.ConstantinopleFixBlockNumber); + chainSpec.IstanbulBlockNumber.Should().Be(RopstenSpecProvider.IstanbulBlockNumber); + chainSpec.MuirGlacierNumber.Should().Be(RopstenSpecProvider.MuirGlacierBlockNumber); + chainSpec.BerlinBlockNumber.Should().Be(RopstenSpecProvider.BerlinBlockNumber); + chainSpec.LondonBlockNumber.Should().Be(RopstenSpecProvider.LondonBlockNumber); + } + [Test] public void Can_load_goerli() { @@ -288,31 +347,6 @@ public void Can_load_sepolia() chainSpec.ShanghaiTimestamp.Should().Be(1677557088); } - [Test] - public void Can_load_holesky() - { - string path = Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../", "Chains/holesky.json"); - ChainSpec chainSpec = LoadChainSpec(path); - - Assert.That(chainSpec.NetworkId, Is.EqualTo(17000), $"{nameof(chainSpec.NetworkId)}"); - Assert.That(chainSpec.Name, Is.EqualTo("Holesky Testnet"), $"{nameof(chainSpec.Name)}"); - Assert.That(chainSpec.DataDir, Is.EqualTo("holesky"), $"{nameof(chainSpec.DataDir)}"); - Assert.That(chainSpec.SealEngineType, Is.EqualTo(SealEngineType.Ethash), "engine"); - - chainSpec.DaoForkBlockNumber.Should().Be(null); - chainSpec.TangerineWhistleBlockNumber.Should().Be(0); - chainSpec.SpuriousDragonBlockNumber.Should().Be(0); - chainSpec.ByzantiumBlockNumber.Should().Be(0); - chainSpec.ConstantinopleBlockNumber.Should().Be(0); - chainSpec.ConstantinopleFixBlockNumber.Should().Be(0); - chainSpec.IstanbulBlockNumber.Should().Be(0); - chainSpec.BerlinBlockNumber.Should().Be(0); - chainSpec.LondonBlockNumber.Should().Be(0); - chainSpec.ShanghaiTimestamp.Should().Be(HoleskySpecProvider.ShanghaiTimestamp); - chainSpec.ShanghaiTimestamp.Should().Be(HoleskySpecProvider.Instance.TimestampFork); - // chainSpec.CancunTimestamp.Should().Be(HoleskySpecProvider.CancunTimestamp); - } - [Test] public void Can_load_posdao_with_openethereum_pricing_transitions() { diff --git a/src/Nethermind/Nethermind.Specs.Test/GoerliSpecProviderTests.cs b/src/Nethermind/Nethermind.Specs.Test/GoerliSpecProviderTests.cs index 29af41d1b07..b64d3e3dfdb 100644 --- a/src/Nethermind/Nethermind.Specs.Test/GoerliSpecProviderTests.cs +++ b/src/Nethermind/Nethermind.Specs.Test/GoerliSpecProviderTests.cs @@ -3,6 +3,7 @@ using FluentAssertions; using Nethermind.Core.Specs; +using Nethermind.Specs.Forks; using NUnit.Framework; namespace Nethermind.Specs.Test diff --git a/src/Nethermind/Nethermind.Specs.Test/MainnetSpecProviderTests.cs b/src/Nethermind/Nethermind.Specs.Test/MainnetSpecProviderTests.cs index 79f33a03507..247f1361ebf 100644 --- a/src/Nethermind/Nethermind.Specs.Test/MainnetSpecProviderTests.cs +++ b/src/Nethermind/Nethermind.Specs.Test/MainnetSpecProviderTests.cs @@ -45,16 +45,6 @@ public void Cancun_eips(long blockNumber, ulong timestamp, bool isEnabled) { _specProvider.GetSpec(new ForkActivation(blockNumber, timestamp)).IsEip1153Enabled.Should().Be(isEnabled); _specProvider.GetSpec(new ForkActivation(blockNumber, timestamp)).IsEip4844Enabled.Should().Be(isEnabled); - _specProvider.GetSpec(new ForkActivation(blockNumber, timestamp)).IsEip5656Enabled.Should().Be(isEnabled); - _specProvider.GetSpec(new ForkActivation(blockNumber, timestamp)).IsEip4788Enabled.Should().Be(isEnabled); - if (isEnabled) - { - _specProvider.GetSpec(new ForkActivation(blockNumber, timestamp)).Eip4788ContractAddress.Should().NotBeNull(); - } - else - { - _specProvider.GetSpec(new ForkActivation(blockNumber, timestamp)).Eip4788ContractAddress.Should().BeNull(); - } } [Test] diff --git a/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs b/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs index 225168c5b1d..fde167d5f5e 100644 --- a/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs @@ -153,9 +153,5 @@ public ulong Eip4844TransitionTimestamp public bool IsEip3860Enabled => _spec.IsEip3860Enabled; public bool IsEip4895Enabled => _spec.IsEip4895Enabled; public ulong WithdrawalTimestamp => _spec.WithdrawalTimestamp; - public bool IsEip5656Enabled => _spec.IsEip5656Enabled; - public bool IsEip6780Enabled => _spec.IsEip6780Enabled; - public bool IsEip4788Enabled => _spec.IsEip4788Enabled; - public Address Eip4788ContractAddress => _spec.Eip4788ContractAddress; } } diff --git a/src/Nethermind/Nethermind.Specs.Test/OverridableSpecProvider.cs b/src/Nethermind/Nethermind.Specs.Test/OverridableSpecProvider.cs index 817d91feb34..2e7a1de3311 100644 --- a/src/Nethermind/Nethermind.Specs.Test/OverridableSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs.Test/OverridableSpecProvider.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Specs.Test/RinkebySpecProviderTests.cs b/src/Nethermind/Nethermind.Specs.Test/RinkebySpecProviderTests.cs index e8074607f7b..89c65e18183 100644 --- a/src/Nethermind/Nethermind.Specs.Test/RinkebySpecProviderTests.cs +++ b/src/Nethermind/Nethermind.Specs.Test/RinkebySpecProviderTests.cs @@ -3,6 +3,7 @@ using FluentAssertions; using Nethermind.Core.Specs; +using Nethermind.Specs.Forks; using NUnit.Framework; namespace Nethermind.Specs.Test diff --git a/src/Nethermind/Nethermind.Specs.Test/RopstenSpecProviderTests.cs b/src/Nethermind/Nethermind.Specs.Test/RopstenSpecProviderTests.cs new file mode 100644 index 00000000000..542f917ee0f --- /dev/null +++ b/src/Nethermind/Nethermind.Specs.Test/RopstenSpecProviderTests.cs @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using FluentAssertions; +using Nethermind.Core.Specs; +using Nethermind.Specs.Forks; +using NUnit.Framework; + +namespace Nethermind.Specs.Test +{ + [TestFixture] + public class RopstenSpecProviderTests + { + private readonly ISpecProvider _specProvider = RopstenSpecProvider.Instance; + + [TestCase(9_812_188, false)] + [TestCase(9_812_189, true)] + public void Berlin_eips(long blockNumber, bool isEnabled) + { + _specProvider.GetSpec((ForkActivation)blockNumber).IsEip2315Enabled.Should().Be(false); + _specProvider.GetSpec((ForkActivation)blockNumber).IsEip2537Enabled.Should().Be(false); + _specProvider.GetSpec((ForkActivation)blockNumber).IsEip2565Enabled.Should().Be(isEnabled); + _specProvider.GetSpec((ForkActivation)blockNumber).IsEip2929Enabled.Should().Be(isEnabled); + _specProvider.GetSpec((ForkActivation)blockNumber).IsEip2930Enabled.Should().Be(isEnabled); + } + + [TestCase(10_499_400, false)] + [TestCase(10_499_401, true)] + public void London_eips(long blockNumber, bool isEnabled) + { + if (isEnabled) + _specProvider.GetSpec((ForkActivation)blockNumber).DifficultyBombDelay.Should().Be(London.Instance.DifficultyBombDelay); + else + _specProvider.GetSpec((ForkActivation)blockNumber).DifficultyBombDelay.Should().Be(Berlin.Instance.DifficultyBombDelay); + + _specProvider.GetSpec((ForkActivation)blockNumber).IsEip1559Enabled.Should().Be(isEnabled); + _specProvider.GetSpec((ForkActivation)blockNumber).IsEip3198Enabled.Should().Be(isEnabled); + _specProvider.GetSpec((ForkActivation)blockNumber).IsEip3529Enabled.Should().Be(isEnabled); + _specProvider.GetSpec((ForkActivation)blockNumber).IsEip3541Enabled.Should().Be(isEnabled); + } + + [Test] + public void Dao_block_number_is_null() + { + _specProvider.DaoBlockNumber.Should().BeNull(); + } + } +} diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainParameters.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainParameters.cs index fca58477f4c..807f845281f 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainParameters.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainParameters.cs @@ -104,18 +104,24 @@ public class ChainParameters public long? MergeForkIdTransition { get; set; } - public long? TerminalPoWBlockNumber { get; set; } + public long? TerminalPowBlockNumber { get; set; } public UInt256? TerminalTotalDifficulty { get; set; } + + /// + /// this field will indicate the timestamp at which this EIP1153 will be enabled. + /// + public ulong? Eip1153TransitionTimestamp { get; set; } + + /// + /// this field will indicate the timestamp at which this EIP3651 will be enabled. + /// public ulong? Eip3651TransitionTimestamp { get; set; } public ulong? Eip3855TransitionTimestamp { get; set; } public ulong? Eip3860TransitionTimestamp { get; set; } + public ulong? Eip4895TransitionTimestamp { get; set; } + public ulong? Eip4844TransitionTimestamp { get; set; } - public ulong? Eip1153TransitionTimestamp { get; set; } - public ulong? Eip5656TransitionTimestamp { get; set; } - public ulong? Eip6780TransitionTimestamp { get; set; } - public ulong? Eip4788TransitionTimestamp { get; set; } - public Address Eip4788ContractAddress { get; set; } } } diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs index 85d8226e2d4..bacd27adf5c 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs @@ -97,9 +97,9 @@ static void Add(SortedSet transitions, T value, T? minValueExclusive) _transitions = CreateTransitions(_chainSpec, transitionBlockNumbers, transitionTimestamps); _firstTimestampActivation = TransitionActivations.FirstOrDefault(t => t.Timestamp is not null); - if (_chainSpec.Parameters.TerminalPoWBlockNumber is not null) + if (_chainSpec.Parameters.TerminalPowBlockNumber is not null) { - MergeBlockNumber = (ForkActivation)(_chainSpec.Parameters.TerminalPoWBlockNumber + 1); + MergeBlockNumber = (ForkActivation)(_chainSpec.Parameters.TerminalPowBlockNumber + 1); } TerminalTotalDifficulty = _chainSpec.Parameters.TerminalTotalDifficulty; @@ -236,10 +236,6 @@ private static ReleaseSpec CreateReleaseSpec(ChainSpec chainSpec, long releaseSt releaseSpec.IsEip4844Enabled = (chainSpec.Parameters.Eip4844TransitionTimestamp ?? ulong.MaxValue) <= releaseStartTimestamp; releaseSpec.Eip4844TransitionTimestamp = chainSpec.Parameters.Eip4844TransitionTimestamp ?? ulong.MaxValue; - releaseSpec.IsEip5656Enabled = (chainSpec.Parameters.Eip5656TransitionTimestamp ?? ulong.MaxValue) <= releaseStartTimestamp; - releaseSpec.IsEip6780Enabled = (chainSpec.Parameters.Eip6780TransitionTimestamp ?? ulong.MaxValue) <= releaseStartTimestamp; - releaseSpec.IsEip4788Enabled = (chainSpec.Parameters.Eip4788TransitionTimestamp ?? ulong.MaxValue) <= releaseStartTimestamp; - releaseSpec.Eip4788ContractAddress = chainSpec.Parameters.Eip4788ContractAddress; return releaseSpec; } diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs index 2d02d64ca2d..360e1cada75 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs @@ -139,11 +139,6 @@ private void LoadParameters(ChainSpecJson chainSpecJson, ChainSpec chainSpec) Eip3860TransitionTimestamp = chainSpecJson.Params.Eip3860TransitionTimestamp, Eip4895TransitionTimestamp = chainSpecJson.Params.Eip4895TransitionTimestamp, Eip4844TransitionTimestamp = chainSpecJson.Params.Eip4844TransitionTimestamp, - Eip2537TransitionTimestamp = chainSpecJson.Params.Eip2537TransitionTimestamp, - Eip5656TransitionTimestamp = chainSpecJson.Params.Eip5656TransitionTimestamp, - Eip6780TransitionTimestamp = chainSpecJson.Params.Eip6780TransitionTimestamp, - Eip4788TransitionTimestamp = chainSpecJson.Params.Eip4788TransitionTimestamp, - Eip4788ContractAddress = chainSpecJson.Params.Eip4788ContractAddress, TransactionPermissionContract = chainSpecJson.Params.TransactionPermissionContract, TransactionPermissionContractTransition = chainSpecJson.Params.TransactionPermissionContractTransition, ValidateChainIdTransition = chainSpecJson.Params.ValidateChainIdTransition, @@ -158,7 +153,7 @@ private void LoadParameters(ChainSpecJson chainSpecJson, ChainSpec chainSpec) Eip1559BaseFeeMinValue = chainSpecJson.Params.Eip1559BaseFeeMinValue, MergeForkIdTransition = chainSpecJson.Params.MergeForkIdTransition, TerminalTotalDifficulty = chainSpecJson.Params.TerminalTotalDifficulty, - TerminalPoWBlockNumber = chainSpecJson.Params.TerminalPoWBlockNumber + TerminalPowBlockNumber = chainSpecJson.Params.TerminalPoWBlockNumber }; chainSpec.Parameters.Eip152Transition ??= GetTransitionForExpectedPricing("blake2_f", "price.blake2_f.gas_per_round", 1); @@ -224,7 +219,7 @@ chainSpec.Parameters.Eip1283DisableTransition is null // TheMerge parameters chainSpec.MergeForkIdBlockNumber = chainSpec.Parameters.MergeForkIdTransition; - chainSpec.TerminalPoWBlockNumber = chainSpec.Parameters.TerminalPoWBlockNumber; + chainSpec.TerminalPoWBlockNumber = chainSpec.Parameters.TerminalPowBlockNumber; chainSpec.TerminalTotalDifficulty = chainSpec.Parameters.TerminalTotalDifficulty; } @@ -386,14 +381,8 @@ private static void LoadGenesis(ChainSpecJson chainSpecJson, ChainSpec chainSpec bool isEip4844Enabled = chainSpecJson.Params.Eip4844TransitionTimestamp != null && genesisHeader.Timestamp >= chainSpecJson.Params.Eip4844TransitionTimestamp; if (isEip4844Enabled) { - genesisHeader.BlobGasUsed = chainSpecJson.Genesis.BlobGasUsed; - genesisHeader.ExcessBlobGas = chainSpecJson.Genesis.ExcessBlobGas; - } - - bool isEip4788Enabled = chainSpecJson.Params.Eip4788TransitionTimestamp != null && genesisHeader.Timestamp >= chainSpecJson.Params.Eip4788TransitionTimestamp; - if (isEip4788Enabled) - { - genesisHeader.ParentBeaconBlockRoot = Keccak.Zero; + genesisHeader.DataGasUsed = chainSpecJson.Genesis.DataGasUsed; + genesisHeader.ExcessDataGas = chainSpecJson.Genesis.ExcessDataGas; } genesisHeader.AuRaStep = step; diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoaderExtensions.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoaderExtensions.cs index 33aa367760d..97dbc200da2 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoaderExtensions.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoaderExtensions.cs @@ -3,8 +3,10 @@ using System; using System.IO; +using System.Linq; using System.Reflection; using System.Text; +using Microsoft.Extensions.Primitives; using Nethermind.Config; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs index 52190d8a622..36b80f2e38d 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs @@ -23,8 +23,7 @@ internal class ChainSpecGenesisJson public Keccak StateRoot { get; set; } - public ulong? BlobGasUsed { get; set; } - public ulong? ExcessBlobGas { get; set; } - public Keccak ParentBeaconBlockRoot { get; set; } + public ulong? DataGasUsed { get; set; } + public ulong? ExcessDataGas { get; set; } } } diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecParamsJson.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecParamsJson.cs index 7917a2b1ebe..c29def202d8 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecParamsJson.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecParamsJson.cs @@ -1,14 +1,13 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Int256; using Newtonsoft.Json; -[assembly: InternalsVisibleTo("Nethermind.Specs.Test")] namespace Nethermind.Specs.ChainSpecStyle.Json { [SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Global")] @@ -23,6 +22,8 @@ internal class ChainSpecParamsJson public long? GasLimitBoundDivisor { get; set; } + public UInt256? AccountStartNonce { get; set; } + public long? MaximumExtraDataSize { get; set; } public long? MinGasLimit { get; set; } @@ -134,15 +135,12 @@ internal class ChainSpecParamsJson public long? TerminalPoWBlockNumber { get; set; } public ulong? Eip1153TransitionTimestamp { get; set; } + public ulong? Eip3651TransitionTimestamp { get; set; } public ulong? Eip3855TransitionTimestamp { get; set; } public ulong? Eip3860TransitionTimestamp { get; set; } public ulong? Eip4895TransitionTimestamp { get; set; } + public ulong? Eip4844TransitionTimestamp { get; set; } - public ulong? Eip2537TransitionTimestamp { get; set; } - public ulong? Eip5656TransitionTimestamp { get; set; } - public ulong? Eip6780TransitionTimestamp { get; set; } - public ulong? Eip4788TransitionTimestamp { get; set; } - public Address Eip4788ContractAddress { get; set; } } } diff --git a/src/Nethermind/Nethermind.Specs/ChiadoSpecProvider.cs b/src/Nethermind/Nethermind.Specs/ChiadoSpecProvider.cs index dade428b89e..f614cb8ddbf 100644 --- a/src/Nethermind/Nethermind.Specs/ChiadoSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/ChiadoSpecProvider.cs @@ -10,8 +10,7 @@ namespace Nethermind.Specs; public class ChiadoSpecProvider : ISpecProvider { - public const ulong BeaconChainGenesisTimestamp = 0x6343ee4c; - public const ulong ShanghaiTimestamp = 0x646e0e4c; + public const ulong ShanghaiTimestamp = 0x646e0e4cUL; private ChiadoSpecProvider() { } diff --git a/src/Nethermind/Nethermind.Specs/Forks/01_Frontier.cs b/src/Nethermind/Nethermind.Specs/Forks/01_Frontier.cs index 7a5d15fce3a..210703601d3 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/01_Frontier.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/01_Frontier.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; +using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Int256; namespace Nethermind.Specs.Forks { diff --git a/src/Nethermind/Nethermind.Specs/Forks/02_Homestead.cs b/src/Nethermind/Nethermind.Specs/Forks/02_Homestead.cs index 678cffdfaac..e2045f71c27 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/02_Homestead.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/02_Homestead.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; +using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Int256; namespace Nethermind.Specs.Forks { diff --git a/src/Nethermind/Nethermind.Specs/Forks/03_Dao.cs b/src/Nethermind/Nethermind.Specs/Forks/03_Dao.cs index 1c8740bd88f..5e2b9956135 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/03_Dao.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/03_Dao.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; +using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Int256; namespace Nethermind.Specs.Forks { diff --git a/src/Nethermind/Nethermind.Specs/Forks/04_TangerineWhistle.cs b/src/Nethermind/Nethermind.Specs/Forks/04_TangerineWhistle.cs index dc9db1de076..f8529e1932c 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/04_TangerineWhistle.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/04_TangerineWhistle.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; +using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Int256; namespace Nethermind.Specs.Forks { diff --git a/src/Nethermind/Nethermind.Specs/Forks/05_SpuriousDragon.cs b/src/Nethermind/Nethermind.Specs/Forks/05_SpuriousDragon.cs index 79c2b687799..a90615cec64 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/05_SpuriousDragon.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/05_SpuriousDragon.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; +using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Int256; namespace Nethermind.Specs.Forks { diff --git a/src/Nethermind/Nethermind.Specs/Forks/06_Byzantium.cs b/src/Nethermind/Nethermind.Specs/Forks/06_Byzantium.cs index fd2d1d94cab..ebb96bc4381 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/06_Byzantium.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/06_Byzantium.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; +using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Specs/Forks/07_Constantinople.cs b/src/Nethermind/Nethermind.Specs/Forks/07_Constantinople.cs index 77f43f8ffa2..4be2bb8ee53 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/07_Constantinople.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/07_Constantinople.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; +using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Specs/Forks/08_ConstantinopleFix.cs b/src/Nethermind/Nethermind.Specs/Forks/08_ConstantinopleFix.cs index af93bdcead5..e67c1b9f529 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/08_ConstantinopleFix.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/08_ConstantinopleFix.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; +using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Int256; namespace Nethermind.Specs.Forks { diff --git a/src/Nethermind/Nethermind.Specs/Forks/09_Istanbul.cs b/src/Nethermind/Nethermind.Specs/Forks/09_Istanbul.cs index 7bcc8bd20f2..6c6a6881e67 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/09_Istanbul.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/09_Istanbul.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; +using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Int256; namespace Nethermind.Specs.Forks { diff --git a/src/Nethermind/Nethermind.Specs/Forks/10_MuirGlacier.cs b/src/Nethermind/Nethermind.Specs/Forks/10_MuirGlacier.cs index 71d955332c4..88f687d432f 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/10_MuirGlacier.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/10_MuirGlacier.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; +using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Int256; namespace Nethermind.Specs.Forks { diff --git a/src/Nethermind/Nethermind.Specs/Forks/11_Berlin.cs b/src/Nethermind/Nethermind.Specs/Forks/11_Berlin.cs index 949a6437273..eff6d51a0a6 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/11_Berlin.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/11_Berlin.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; +using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Int256; namespace Nethermind.Specs.Forks { diff --git a/src/Nethermind/Nethermind.Specs/Forks/12_London.cs b/src/Nethermind/Nethermind.Specs/Forks/12_London.cs index 9a924df0c86..1c88c8c60b3 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/12_London.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/12_London.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; +using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Int256; namespace Nethermind.Specs.Forks { diff --git a/src/Nethermind/Nethermind.Specs/Forks/13_ArrowGlacier.cs b/src/Nethermind/Nethermind.Specs/Forks/13_ArrowGlacier.cs index d9847bd3112..7a14514c1ff 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/13_ArrowGlacier.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/13_ArrowGlacier.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; +using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Int256; namespace Nethermind.Specs.Forks { diff --git a/src/Nethermind/Nethermind.Specs/Forks/14_GrayGlacier.cs b/src/Nethermind/Nethermind.Specs/Forks/14_GrayGlacier.cs index 0090eabfa90..c63f0dbcad3 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/14_GrayGlacier.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/14_GrayGlacier.cs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; +using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Int256; namespace Nethermind.Specs.Forks { diff --git a/src/Nethermind/Nethermind.Specs/Forks/16_Cancun.cs b/src/Nethermind/Nethermind.Specs/Forks/16_Cancun.cs index 4131684f0a5..a110de27f0d 100644 --- a/src/Nethermind/Nethermind.Specs/Forks/16_Cancun.cs +++ b/src/Nethermind/Nethermind.Specs/Forks/16_Cancun.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Threading; -using Nethermind.Core; using Nethermind.Core.Specs; namespace Nethermind.Specs.Forks @@ -15,11 +14,7 @@ protected Cancun() { Name = "Cancun"; IsEip1153Enabled = true; - IsEip5656Enabled = true; IsEip4844Enabled = true; - IsEip6780Enabled = true; - IsEip4788Enabled = true; - Eip4788ContractAddress = Address.FromNumber(0x0b); } public new static IReleaseSpec Instance => LazyInitializer.EnsureInitialized(ref _instance, () => new Cancun()); diff --git a/src/Nethermind/Nethermind.Specs/FrontierSpecProvider.cs b/src/Nethermind/Nethermind.Specs/FrontierSpecProvider.cs index e8eaff7efd0..847771b687e 100644 --- a/src/Nethermind/Nethermind.Specs/FrontierSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/FrontierSpecProvider.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs b/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs index a3fccaffb44..935f8c77d28 100644 --- a/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs @@ -10,14 +10,6 @@ namespace Nethermind.Specs; public class GnosisSpecProvider : ISpecProvider { - public const long ConstantinopoleBlockNumber = 1_604_400; - public const long ConstantinopoleFixBlockNumber = 2_508_800; - public const long IstanbulBlockNumber = 7_298_030; - public const long BerlinBlockNumber = 16_101_500; - public const long LondonBlockNumber = 19_040_000; - public const ulong BeaconChainGenesisTimestamp = 0x61b10dbc; - public const ulong ShanghaiTimestamp = 0x64c8edbc; - private GnosisSpecProvider() { } public IReleaseSpec GetSpec(ForkActivation forkActivation) @@ -55,5 +47,12 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD public ulong ChainId => BlockchainIds.Gnosis; public ForkActivation[] TransitionActivations { get; } + public const long ConstantinopoleBlockNumber = 1_604_400; + public const long ConstantinopoleFixBlockNumber = 2_508_800; + public const long IstanbulBlockNumber = 7_298_030; + public const long BerlinBlockNumber = 16_101_500; + public const long LondonBlockNumber = 19_040_000; + public const ulong ShanghaiTimestamp = long.MaxValue; + public static GnosisSpecProvider Instance { get; } = new(); } diff --git a/src/Nethermind/Nethermind.Specs/GoerliSpecProvider.cs b/src/Nethermind/Nethermind.Specs/GoerliSpecProvider.cs index 5defde805f0..255cd982144 100644 --- a/src/Nethermind/Nethermind.Specs/GoerliSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/GoerliSpecProvider.cs @@ -1,60 +1,64 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Linq; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; using Nethermind.Specs.Forks; -namespace Nethermind.Specs; - -public class GoerliSpecProvider : ISpecProvider +namespace Nethermind.Specs { - public const long IstanbulBlockNumber = 1_561_651; - public const long BerlinBlockNumber = 4_460_644; - public const long LondonBlockNumber = 5_062_605; - public const ulong BeaconChainGenesisTimestamp = 0x6059f460; - public const ulong ShanghaiTimestamp = 0x6410f460; + public class GoerliSpecProvider : ISpecProvider + { + public static readonly GoerliSpecProvider Instance = new(); + private GoerliSpecProvider() { } - private GoerliSpecProvider() { } + private ForkActivation? _theMergeBlock = null; + private UInt256? _terminalTotalDifficulty = 10790000; - public IReleaseSpec GetSpec(ForkActivation forkActivation) - { - return forkActivation.BlockNumber switch + public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) { - < IstanbulBlockNumber => GenesisSpec, - < BerlinBlockNumber => Istanbul.Instance, - < LondonBlockNumber => Berlin.Instance, - _ => forkActivation.Timestamp switch - { - null or < ShanghaiTimestamp => London.Instance, - _ => Shanghai.Instance - } - }; - } + if (blockNumber is not null) + _theMergeBlock = (ForkActivation)blockNumber; + if (terminalTotalDifficulty is not null) + _terminalTotalDifficulty = terminalTotalDifficulty; + } - public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) - { - if (blockNumber is not null) - MergeBlockNumber = (ForkActivation)blockNumber; - if (terminalTotalDifficulty is not null) - TerminalTotalDifficulty = terminalTotalDifficulty; - } + public ForkActivation? MergeBlockNumber => _theMergeBlock; + public ulong TimestampFork => ShanghaiTimestamp; + public UInt256? TerminalTotalDifficulty => _terminalTotalDifficulty; + public IReleaseSpec GenesisSpec { get; } = ConstantinopleFix.Instance; - public ulong NetworkId => BlockchainIds.Goerli; - public ulong ChainId => NetworkId; - public long? DaoBlockNumber => null; - public ForkActivation? MergeBlockNumber { get; private set; } = null; - public ulong TimestampFork => ShanghaiTimestamp; - public UInt256? TerminalTotalDifficulty { get; private set; } = 10790000; - public IReleaseSpec GenesisSpec { get; } = ConstantinopleFix.Instance; - public ForkActivation[] TransitionActivations { get; } = - { - (ForkActivation)IstanbulBlockNumber, - (ForkActivation)BerlinBlockNumber, - (ForkActivation)LondonBlockNumber, - (LondonBlockNumber, ShanghaiTimestamp) - }; + public IReleaseSpec GetSpec(ForkActivation forkActivation) + { + return forkActivation.BlockNumber switch + { + < IstanbulBlockNumber => GenesisSpec, + < BerlinBlockNumber => Istanbul.Instance, + < LondonBlockNumber => Berlin.Instance, + _ => forkActivation.Timestamp switch + { + null or < ShanghaiTimestamp => London.Instance, + _ => Shanghai.Instance + } + }; + } + + public long? DaoBlockNumber => null; + public const long IstanbulBlockNumber = 1_561_651; + public const long BerlinBlockNumber = 4_460_644; + public const long LondonBlockNumber = 5_062_605; + public const ulong ShanghaiTimestamp = 1678832736; + public ulong NetworkId => BlockchainIds.Goerli; + public ulong ChainId => NetworkId; - public static readonly GoerliSpecProvider Instance = new(); + public ForkActivation[] TransitionActivations { get; } = + { + (ForkActivation)IstanbulBlockNumber, + (ForkActivation)BerlinBlockNumber, + (ForkActivation)LondonBlockNumber, + (LondonBlockNumber, ShanghaiTimestamp) + }; + } } diff --git a/src/Nethermind/Nethermind.Specs/HoleskySpecProvider.cs b/src/Nethermind/Nethermind.Specs/HoleskySpecProvider.cs deleted file mode 100644 index 006460e0490..00000000000 --- a/src/Nethermind/Nethermind.Specs/HoleskySpecProvider.cs +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core; -using Nethermind.Core.Specs; -using Nethermind.Int256; -using Nethermind.Specs.Forks; - -namespace Nethermind.Specs; - -public class HoleskySpecProvider : ISpecProvider -{ - public const ulong GenesisTimestamp = 0x65156994; - public const ulong ShanghaiTimestamp = 0x6516eac0; - // public const ulong CancunTimestamp = 0x77359400; - - private HoleskySpecProvider() { } - - public IReleaseSpec GetSpec(ForkActivation forkActivation) - { - return forkActivation.Timestamp switch - { - null or < ShanghaiTimestamp => GenesisSpec, - // < CancunTimestamp => Shanghai.Instance, - _ => Shanghai.Instance - }; - } - - public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) - { - if (blockNumber is not null) - MergeBlockNumber = (ForkActivation)blockNumber; - if (terminalTotalDifficulty is not null) - TerminalTotalDifficulty = terminalTotalDifficulty; - } - - public ulong NetworkId => BlockchainIds.Holesky; - public ulong ChainId => NetworkId; - public long? DaoBlockNumber => null; - public ForkActivation? MergeBlockNumber { get; private set; } = (0, GenesisTimestamp); - public ulong TimestampFork => ShanghaiTimestamp; - public UInt256? TerminalTotalDifficulty { get; private set; } = 0; - public IReleaseSpec GenesisSpec { get; } = London.Instance; - public ForkActivation[] TransitionActivations { get; } = - { - (1, ShanghaiTimestamp), - // (2, CancunTimestamp) - }; - - public static readonly HoleskySpecProvider Instance = new(); -} diff --git a/src/Nethermind/Nethermind.Specs/KnownHashes.cs b/src/Nethermind/Nethermind.Specs/KnownHashes.cs index 437fe89fdcc..ecea487bd0d 100644 --- a/src/Nethermind/Nethermind.Specs/KnownHashes.cs +++ b/src/Nethermind/Nethermind.Specs/KnownHashes.cs @@ -10,9 +10,9 @@ public static class KnownHashes public static readonly Keccak MainnetGenesis = new("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"); public static readonly Keccak GoerliGenesis = new("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a"); public static readonly Keccak RinkebyGenesis = new("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177"); + public static readonly Keccak RopstenGenesis = new("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"); public static readonly Keccak SepoliaGenesis = new("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9"); public static readonly Keccak GnosisGenesis = new("0x4f1dd23188aab3a76b463e4af801b52b1248ef073c648cbdc4c9333d3da79756"); public static readonly Keccak ChiadoGenesis = new("0xada44fd8d2ecab8b08f256af07ad3e777f17fb434f8f8e678b312f576212ba9a"); - public static readonly Keccak HoleskyGenesis = new("0xb5f7f912443c940f21fd611f12828d75b534364ed9e95ca4e307729a4661bde4"); } } diff --git a/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs b/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs index 1670bde6c46..d810b27ce2e 100644 --- a/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/MainnetSpecProvider.cs @@ -5,88 +5,81 @@ using Nethermind.Int256; using Nethermind.Specs.Forks; -namespace Nethermind.Specs; - -public class MainnetSpecProvider : ISpecProvider +namespace Nethermind.Specs { - public const long HomesteadBlockNumber = 1_150_000; - public const long DaoBlockNumberConst = 1_920_000; - public const long TangerineWhistleBlockNumber = 2_463_000; - public const long SpuriousDragonBlockNumber = 2_675_000; - public const long ByzantiumBlockNumber = 4_370_000; - public const long ConstantinopleFixBlockNumber = 7_280_000; - public const long IstanbulBlockNumber = 9_069_000; - public const long MuirGlacierBlockNumber = 9_200_000; - public const long BerlinBlockNumber = 12_244_000; - public const long LondonBlockNumber = 12_965_000; - public const long ArrowGlacierBlockNumber = 13_773_000; - public const long GrayGlacierBlockNumber = 15_050_000; - public const ulong GenesisBlockTimestamp = 0x55ba4215; - public const ulong BeaconChainGenesisTimestamp = 0x5fc63057; - public const ulong ShanghaiBlockTimestamp = 0x64373057; - public const ulong CancunBlockTimestamp = ulong.MaxValue - 3; - public const ulong PragueBlockTimestamp = ulong.MaxValue - 2; - public const ulong OsakaBlockTimestamp = ulong.MaxValue - 1; + public class MainnetSpecProvider : ISpecProvider + { + private ForkActivation? _theMergeBlock = null; + private UInt256? _terminalTotalDifficulty = UInt256.Parse("58750000000000000000000"); - public IReleaseSpec GetSpec(ForkActivation forkActivation) => - forkActivation switch + public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) { - { BlockNumber: < HomesteadBlockNumber } => Frontier.Instance, - { BlockNumber: < DaoBlockNumberConst } => Homestead.Instance, - { BlockNumber: < TangerineWhistleBlockNumber } => Dao.Instance, - { BlockNumber: < SpuriousDragonBlockNumber } => TangerineWhistle.Instance, - { BlockNumber: < ByzantiumBlockNumber } => SpuriousDragon.Instance, - { BlockNumber: < ConstantinopleFixBlockNumber } => Byzantium.Instance, - { BlockNumber: < IstanbulBlockNumber } => ConstantinopleFix.Instance, - { BlockNumber: < MuirGlacierBlockNumber } => Istanbul.Instance, - { BlockNumber: < BerlinBlockNumber } => MuirGlacier.Instance, - { BlockNumber: < LondonBlockNumber } => Berlin.Instance, - { BlockNumber: < ArrowGlacierBlockNumber } => London.Instance, - { BlockNumber: < GrayGlacierBlockNumber } => ArrowGlacier.Instance, - { Timestamp: null } or { Timestamp: < ShanghaiBlockTimestamp } => GrayGlacier.Instance, - { Timestamp: < CancunBlockTimestamp } => Shanghai.Instance, - _ => Cancun.Instance - }; + if (blockNumber is not null) + _theMergeBlock = (ForkActivation)blockNumber; + if (terminalTotalDifficulty is not null) + _terminalTotalDifficulty = terminalTotalDifficulty; + } - public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) - { - if (blockNumber is not null) - MergeBlockNumber = (ForkActivation)blockNumber; + public ForkActivation? MergeBlockNumber => _theMergeBlock; + public ulong TimestampFork => ShanghaiBlockTimestamp; + public UInt256? TerminalTotalDifficulty => _terminalTotalDifficulty; + public IReleaseSpec GenesisSpec => Frontier.Instance; - if (terminalTotalDifficulty is not null) - TerminalTotalDifficulty = terminalTotalDifficulty; - } + public IReleaseSpec GetSpec(ForkActivation forkActivation) => + forkActivation switch + { + { BlockNumber: < HomesteadBlockNumber } => Frontier.Instance, + { BlockNumber: < DaoBlockNumberConst } => Homestead.Instance, + { BlockNumber: < TangerineWhistleBlockNumber } => Dao.Instance, + { BlockNumber: < SpuriousDragonBlockNumber } => TangerineWhistle.Instance, + { BlockNumber: < ByzantiumBlockNumber } => SpuriousDragon.Instance, + { BlockNumber: < ConstantinopleFixBlockNumber } => Byzantium.Instance, + { BlockNumber: < IstanbulBlockNumber } => ConstantinopleFix.Instance, + { BlockNumber: < MuirGlacierBlockNumber } => Istanbul.Instance, + { BlockNumber: < BerlinBlockNumber } => MuirGlacier.Instance, + { BlockNumber: < LondonBlockNumber } => Berlin.Instance, + { BlockNumber: < ArrowGlacierBlockNumber } => London.Instance, + { BlockNumber: < GrayGlacierBlockNumber } => ArrowGlacier.Instance, + { Timestamp: null } or { Timestamp: < ShanghaiBlockTimestamp } => GrayGlacier.Instance, + { Timestamp: < CancunBlockTimestamp } => Shanghai.Instance, + _ => Cancun.Instance + }; - public ulong NetworkId { get; } = Core.BlockchainIds.Mainnet; - public ulong ChainId => NetworkId; - public long? DaoBlockNumber => DaoBlockNumberConst; - public ForkActivation? MergeBlockNumber { get; private set; } = null; - public ulong TimestampFork { get; } = ShanghaiBlockTimestamp; - public UInt256? TerminalTotalDifficulty { get; private set; } = UInt256.Parse("58750000000000000000000"); - public IReleaseSpec GenesisSpec => Frontier.Instance; - public static ForkActivation ShanghaiActivation { get; } = (15_050_001, ShanghaiBlockTimestamp); - public static ForkActivation CancunActivation { get; } = (15_050_002, CancunBlockTimestamp); - public static ForkActivation PragueActivation { get; } = (15_050_003, PragueBlockTimestamp); - public static ForkActivation OsakaActivation { get; } = (15_050_004, OsakaBlockTimestamp); - public ForkActivation[] TransitionActivations { get; } = - { - (ForkActivation)HomesteadBlockNumber, - (ForkActivation)DaoBlockNumberConst, - (ForkActivation)TangerineWhistleBlockNumber, - (ForkActivation)SpuriousDragonBlockNumber, - (ForkActivation)ByzantiumBlockNumber, - (ForkActivation)ConstantinopleFixBlockNumber, - (ForkActivation)IstanbulBlockNumber, - (ForkActivation)MuirGlacierBlockNumber, - (ForkActivation)BerlinBlockNumber, - (ForkActivation)LondonBlockNumber, - (ForkActivation)ArrowGlacierBlockNumber, - (ForkActivation)GrayGlacierBlockNumber, - ShanghaiActivation, - CancunActivation, - //PragueActivation, - //OsakaActivation - }; + public const long HomesteadBlockNumber = 1_150_000; + public long? DaoBlockNumber => DaoBlockNumberConst; + public const long DaoBlockNumberConst = 1_920_000; + public const long TangerineWhistleBlockNumber = 2_463_000; + public const long SpuriousDragonBlockNumber = 2_675_000; + public const long ByzantiumBlockNumber = 4_370_000; + public const long ConstantinopleFixBlockNumber = 7_280_000; + public const long IstanbulBlockNumber = 9_069_000; + public const long MuirGlacierBlockNumber = 9_200_000; + public const long BerlinBlockNumber = 12_244_000; + public const long LondonBlockNumber = 12_965_000; + public const long ArrowGlacierBlockNumber = 13_773_000; + public const long GrayGlacierBlockNumber = 15_050_000; + public const ulong GenesisBlockTimestamp = 1_438_269_973; + public const ulong ShanghaiBlockTimestamp = 1_681_338_455; + public const ulong CancunBlockTimestamp = ulong.MaxValue - 3; + public const ulong PragueBlockTimestamp = ulong.MaxValue - 2; + public const ulong OsakaBlockTimestamp = ulong.MaxValue - 1; + public static ForkActivation ShanghaiActivation = (15_050_001, ShanghaiBlockTimestamp); + public static ForkActivation CancunActivation = (15_050_002, CancunBlockTimestamp); + public static ForkActivation PragueActivation = (15_050_003, PragueBlockTimestamp); + public static ForkActivation OsakaActivation = (15_050_004, OsakaBlockTimestamp); - public static MainnetSpecProvider Instance { get; } = new(); + public ulong NetworkId => Core.BlockchainIds.Mainnet; + public ulong ChainId => NetworkId; + + public ForkActivation[] TransitionActivations { get; } = + { + (ForkActivation)HomesteadBlockNumber, (ForkActivation)DaoBlockNumberConst, (ForkActivation)TangerineWhistleBlockNumber, (ForkActivation)SpuriousDragonBlockNumber, + (ForkActivation)ByzantiumBlockNumber, (ForkActivation)ConstantinopleFixBlockNumber, (ForkActivation)IstanbulBlockNumber, (ForkActivation)MuirGlacierBlockNumber, + (ForkActivation)BerlinBlockNumber, (ForkActivation)LondonBlockNumber, (ForkActivation)ArrowGlacierBlockNumber, (ForkActivation)GrayGlacierBlockNumber, + ShanghaiActivation, CancunActivation, + //PragueActivation, OsakaActivation + }; + + public static readonly MainnetSpecProvider Instance = new(); + } } diff --git a/src/Nethermind/Nethermind.Specs/OlympicSpecProvider.cs b/src/Nethermind/Nethermind.Specs/OlympicSpecProvider.cs index 54967e746c2..94513327899 100644 --- a/src/Nethermind/Nethermind.Specs/OlympicSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/OlympicSpecProvider.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; using Nethermind.Specs.Forks; diff --git a/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs b/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs index fa886f82fa6..9cb46d7439c 100644 --- a/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; @@ -78,15 +79,5 @@ public ReleaseSpec Clone() public bool IsEip3860Enabled { get; set; } public bool IsEip4895Enabled { get; set; } public bool IsEip4844Enabled { get; set; } - public bool IsEip5656Enabled { get; set; } - public bool IsEip6780Enabled { get; set; } - public bool IsEip4788Enabled { get; set; } - - private Address _eip4788ContractAddress; - public Address Eip4788ContractAddress - { - get => IsEip4788Enabled ? _eip4788ContractAddress : null; - set => _eip4788ContractAddress = value; - } } } diff --git a/src/Nethermind/Nethermind.Specs/RinkebySpecProvider.cs b/src/Nethermind/Nethermind.Specs/RinkebySpecProvider.cs index 39c40dc7361..bf07dfe9db0 100644 --- a/src/Nethermind/Nethermind.Specs/RinkebySpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/RinkebySpecProvider.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; using Nethermind.Specs.Forks; diff --git a/src/Nethermind/Nethermind.Specs/RopstenSpecProvider.cs b/src/Nethermind/Nethermind.Specs/RopstenSpecProvider.cs new file mode 100644 index 00000000000..ddd9ef053ed --- /dev/null +++ b/src/Nethermind/Nethermind.Specs/RopstenSpecProvider.cs @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core; +using Nethermind.Core.Specs; +using Nethermind.Int256; +using Nethermind.Specs.Forks; + +namespace Nethermind.Specs +{ + public class RopstenSpecProvider : ISpecProvider + { + private ForkActivation? _theMergeBlock; + private UInt256? _terminalTotalDifficulty = 50000000000000000; + + public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) + { + if (blockNumber is not null) + _theMergeBlock = (ForkActivation)blockNumber; + if (terminalTotalDifficulty is not null) + _terminalTotalDifficulty = terminalTotalDifficulty; + } + + public ForkActivation? MergeBlockNumber => _theMergeBlock; + public ulong TimestampFork => ISpecProvider.TimestampForkNever; + public UInt256? TerminalTotalDifficulty => _terminalTotalDifficulty; + public IReleaseSpec GenesisSpec => TangerineWhistle.Instance; + + public IReleaseSpec GetSpec(ForkActivation forkActivation) => + forkActivation.BlockNumber switch + { + < SpuriousDragonBlockNumber => TangerineWhistle.Instance, + < ByzantiumBlockNumber => SpuriousDragon.Instance, + < ConstantinopleBlockNumber => Byzantium.Instance, + < ConstantinopleFixBlockNumber => Constantinople.Instance, + < IstanbulBlockNumber => ConstantinopleFix.Instance, + < MuirGlacierBlockNumber => Istanbul.Instance, + < BerlinBlockNumber => MuirGlacier.Instance, + < LondonBlockNumber => Berlin.Instance, + _ => London.Instance + }; + + public long? DaoBlockNumber => null; + public const long SpuriousDragonBlockNumber = 10; + public const long ByzantiumBlockNumber = 1_700_000; + public const long ConstantinopleBlockNumber = 4_230_000; + public const long ConstantinopleFixBlockNumber = 4_939_394; + public const long IstanbulBlockNumber = 6_485_846; + public const long MuirGlacierBlockNumber = 7_117_117; + public const long BerlinBlockNumber = 9_812_189; + public const long LondonBlockNumber = 10_499_401; + + public ulong NetworkId => Core.BlockchainIds.Ropsten; + public ulong ChainId => NetworkId; + public ForkActivation[] TransitionActivations => new ForkActivation[] + { + (ForkActivation)SpuriousDragonBlockNumber, + (ForkActivation)ByzantiumBlockNumber, + (ForkActivation)ConstantinopleBlockNumber, + (ForkActivation)ConstantinopleFixBlockNumber, + (ForkActivation)IstanbulBlockNumber, + (ForkActivation)MuirGlacierBlockNumber, + (ForkActivation)BerlinBlockNumber, + (ForkActivation)LondonBlockNumber + }; + + public RopstenSpecProvider() { } + + public static readonly RopstenSpecProvider Instance = new(); + } +} diff --git a/src/Nethermind/Nethermind.Specs/SepoliaSpecProvider.cs b/src/Nethermind/Nethermind.Specs/SepoliaSpecProvider.cs index 8a5976ca816..6049cdd8ac6 100644 --- a/src/Nethermind/Nethermind.Specs/SepoliaSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/SepoliaSpecProvider.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; using Nethermind.Specs.Forks; @@ -9,10 +11,23 @@ namespace Nethermind.Specs; public class SepoliaSpecProvider : ISpecProvider { - public const ulong BeaconChainGenesisTimestamp = 0x62b07d60; - public const ulong ShanghaiBlockTimestamp = 0x63fd7d60; + private ForkActivation? _theMergeBlock = null; + private UInt256? _terminalTotalDifficulty = 17000000000000000; - private SepoliaSpecProvider() { } + public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) + { + if (blockNumber is not null) + _theMergeBlock = (ForkActivation)blockNumber; + if (terminalTotalDifficulty is not null) + _terminalTotalDifficulty = terminalTotalDifficulty; + } + + public ForkActivation? MergeBlockNumber => _theMergeBlock; + public ulong TimestampFork => ISpecProvider.TimestampForkNever; + public UInt256? TerminalTotalDifficulty => _terminalTotalDifficulty; + public IReleaseSpec GenesisSpec => London.Instance; + + public const ulong ShanghaiBlockTimestamp = 1677557088; public IReleaseSpec GetSpec(ForkActivation forkActivation) => forkActivation switch @@ -21,26 +36,15 @@ public IReleaseSpec GetSpec(ForkActivation forkActivation) => _ => Shanghai.Instance }; - public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalDifficulty = null) - { - if (blockNumber is not null) - MergeBlockNumber = (ForkActivation)blockNumber; - if (terminalTotalDifficulty is not null) - TerminalTotalDifficulty = terminalTotalDifficulty; - } + public long? DaoBlockNumber => null; + public ulong NetworkId => Core.BlockchainIds.Rinkeby; public ulong ChainId => NetworkId; - public long? DaoBlockNumber => null; - public ForkActivation? MergeBlockNumber { get; private set; } = null; - public ulong TimestampFork => ISpecProvider.TimestampForkNever; - public UInt256? TerminalTotalDifficulty { get; private set; } = 17000000000000000; - public IReleaseSpec GenesisSpec => London.Instance; - public ForkActivation[] TransitionActivations { get; } = - { - (ForkActivation)1735371, - (1735371, 1677557088) - }; - public static SepoliaSpecProvider Instance { get; } = new(); + public ForkActivation[] TransitionActivations { get; } = { (ForkActivation)1735371, new ForkActivation(1735371, 1677557088) }; + + private SepoliaSpecProvider() { } + + public static readonly SepoliaSpecProvider Instance = new(); } diff --git a/src/Nethermind/Nethermind.Specs/SystemTransactionReleaseSpec.cs b/src/Nethermind/Nethermind.Specs/SystemTransactionReleaseSpec.cs index b4c0c4d29e8..1dd493212d3 100644 --- a/src/Nethermind/Nethermind.Specs/SystemTransactionReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Specs/SystemTransactionReleaseSpec.cs @@ -126,9 +126,5 @@ public bool IsEip158IgnoredAccount(Address address) public bool IsEip3855Enabled => _spec.IsEip3855Enabled; public bool IsEip3860Enabled => _spec.IsEip3860Enabled; public bool IsEip4895Enabled => _spec.IsEip4895Enabled; - public bool IsEip5656Enabled => _spec.IsEip5656Enabled; - public bool IsEip6780Enabled => _spec.IsEip6780Enabled; - public bool IsEip4788Enabled => _spec.IsEip4788Enabled; - public Address Eip4788ContractAddress => _spec.Eip4788ContractAddress; } } diff --git a/src/Nethermind/Nethermind.State.Test.Runner/StateTestTxTracer.cs b/src/Nethermind/Nethermind.State.Test.Runner/StateTestTxTracer.cs index 34aa1ff54b3..92cdb19e917 100644 --- a/src/Nethermind/Nethermind.State.Test.Runner/StateTestTxTracer.cs +++ b/src/Nethermind/Nethermind.State.Test.Runner/StateTestTxTracer.cs @@ -10,240 +10,242 @@ using Nethermind.Int256; using Nethermind.Evm; using Nethermind.Evm.Tracing; +using Nethermind.State.Tracing; -namespace Nethermind.State.Test.Runner; - -public class StateTestTxTracer : ITxTracer +namespace Nethermind.State.Test.Runner { - private StateTestTxTraceEntry _traceEntry; - private StateTestTxTrace _trace = new(); - private bool _gasAlreadySetForCurrentOp; - - public bool IsTracingReceipt => true; - public bool IsTracingActions => false; - public bool IsTracingOpLevelStorage => true; - public bool IsTracingMemory => true; - public bool IsTracingDetailedMemory { get; set; } = true; - public bool IsTracingInstructions => true; - public bool IsTracingRefunds { get; } = false; - public bool IsTracingCode => false; - public bool IsTracingStack { get; set; } = true; - public bool IsTracingState => false; - public bool IsTracingStorage => false; - public bool IsTracingBlockHash { get; } = false; - public bool IsTracingAccess { get; } = false; - public bool IsTracingFees => false; - public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; - - - public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak stateRoot = null) - { - _trace.Result.Output = output; - _trace.Result.GasUsed = gasSpent; - } + public class StateTestTxTracer : ITxTracer + { + private StateTestTxTraceEntry _traceEntry; + private StateTestTxTrace _trace = new(); + private bool _gasAlreadySetForCurrentOp; + + public bool IsTracingReceipt => true; + public bool IsTracingActions => false; + public bool IsTracingOpLevelStorage => true; + public bool IsTracingMemory => true; + public bool IsTracingDetailedMemory { get; set; } = true; + public bool IsTracingInstructions => true; + public bool IsTracingRefunds { get; } = false; + public bool IsTracingCode => false; + public bool IsTracingStack { get; set; } = true; + public bool IsTracingState => false; + public bool IsTracingStorage => false; + public bool IsTracingBlockHash { get; } = false; + public bool IsTracingAccess { get; } = false; + public bool IsTracingFees => false; + public bool IsTracing => IsTracingReceipt || IsTracingActions || IsTracingOpLevelStorage || IsTracingMemory || IsTracingInstructions || IsTracingRefunds || IsTracingCode || IsTracingStack || IsTracingBlockHash || IsTracingAccess || IsTracingFees; + + + public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEntry[] logs, Keccak stateRoot = null) + { + _trace.Result.Output = output; + _trace.Result.GasUsed = gasSpent; + } - public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak stateRoot = null) - { - _trace.Result.Error = _traceEntry?.Error ?? error; - _trace.Result.Output = output ?? Bytes.Empty; - _trace.Result.GasUsed = gasSpent; - } + public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string error, Keccak stateRoot = null) + { + _trace.Result.Error = _traceEntry?.Error ?? error; + _trace.Result.Output = output ?? Bytes.Empty; + _trace.Result.GasUsed = gasSpent; + } - public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) - { - _gasAlreadySetForCurrentOp = false; - _traceEntry = new StateTestTxTraceEntry(); - _traceEntry.Pc = pc; - _traceEntry.Operation = (byte)opcode; - _traceEntry.OperationName = opcode.GetName(isPostMerge); - _traceEntry.Gas = gas; - _traceEntry.Depth = depth; - _trace.Entries.Add(_traceEntry); - } + public void StartOperation(int depth, long gas, Instruction opcode, int pc, bool isPostMerge = false) + { + _gasAlreadySetForCurrentOp = false; + _traceEntry = new StateTestTxTraceEntry(); + _traceEntry.Pc = pc; + _traceEntry.Operation = (byte)opcode; + _traceEntry.OperationName = opcode.GetName(isPostMerge); + _traceEntry.Gas = gas; + _traceEntry.Depth = depth; + _trace.Entries.Add(_traceEntry); + } - public void ReportOperationError(EvmExceptionType error) - { - _traceEntry.Error = GetErrorDescription(error); - } + public void ReportOperationError(EvmExceptionType error) + { + _traceEntry.Error = GetErrorDescription(error); + } - private static string? GetErrorDescription(EvmExceptionType evmExceptionType) - { - return evmExceptionType switch - { - EvmExceptionType.None => null, - EvmExceptionType.BadInstruction => "BadInstruction", - EvmExceptionType.StackOverflow => "StackOverflow", - EvmExceptionType.StackUnderflow => "StackUnderflow", - EvmExceptionType.OutOfGas => "OutOfGas", - EvmExceptionType.InvalidJumpDestination => "BadJumpDestination", - EvmExceptionType.AccessViolation => "AccessViolation", - EvmExceptionType.StaticCallViolation => "StaticCallViolation", - _ => "Error" - }; - } + private static string? GetErrorDescription(EvmExceptionType evmExceptionType) + { + return evmExceptionType switch + { + EvmExceptionType.None => null, + EvmExceptionType.BadInstruction => "BadInstruction", + EvmExceptionType.StackOverflow => "StackOverflow", + EvmExceptionType.StackUnderflow => "StackUnderflow", + EvmExceptionType.OutOfGas => "OutOfGas", + EvmExceptionType.InvalidJumpDestination => "BadJumpDestination", + EvmExceptionType.AccessViolation => "AccessViolation", + EvmExceptionType.StaticCallViolation => "StaticCallViolation", + _ => "Error" + }; + } - public void ReportOperationRemainingGas(long gas) - { - if (!_gasAlreadySetForCurrentOp) + public void ReportOperationRemainingGas(long gas) { - _gasAlreadySetForCurrentOp = true; - _traceEntry.GasCost = _traceEntry.Gas - gas; + if (!_gasAlreadySetForCurrentOp) + { + _gasAlreadySetForCurrentOp = true; + _traceEntry.GasCost = _traceEntry.Gas - gas; + } } - } - public void SetOperationMemorySize(ulong newSize) - { - _traceEntry.UpdateMemorySize((int)newSize); - if (IsTracingDetailedMemory) + public void SetOperationMemorySize(ulong newSize) { - int diff = _traceEntry.MemSize * 2 - (_traceEntry.Memory.Length - 2); - if (diff > 0) + _traceEntry.UpdateMemorySize((int)newSize); + if (IsTracingDetailedMemory) { - _traceEntry.Memory += new string('0', diff); + int diff = _traceEntry.MemSize * 2 - (_traceEntry.Memory.Length - 2); + if (diff > 0) + { + _traceEntry.Memory += new string('0', diff); + } } } - } - public void ReportMemoryChange(long offset, in ReadOnlySpan data) - { - } + public void ReportMemoryChange(long offset, in ReadOnlySpan data) + { + } - public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) - { - } + public void ReportStorageChange(in ReadOnlySpan key, in ReadOnlySpan value) + { + } - public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) - { - } + public void SetOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan newValue, ReadOnlySpan currentValue) + { + } - public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) - { - } + public void LoadOperationStorage(Address address, UInt256 storageIndex, ReadOnlySpan value) + { + } - public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) - { - throw new NotSupportedException(); - } + public void ReportSelfDestruct(Address address, UInt256 balance, Address refundAddress) + { + throw new NotSupportedException(); + } - public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) - { - throw new NotSupportedException(); - } + public void ReportBalanceChange(Address address, UInt256? before, UInt256? after) + { + throw new NotSupportedException(); + } - public void ReportCodeChange(Address address, byte[] before, byte[] after) - { - throw new NotSupportedException(); - } + public void ReportCodeChange(Address address, byte[] before, byte[] after) + { + throw new NotSupportedException(); + } - public void ReportNonceChange(Address address, UInt256? before, UInt256? after) - { - throw new NotSupportedException(); - } + public void ReportNonceChange(Address address, UInt256? before, UInt256? after) + { + throw new NotSupportedException(); + } - public void ReportAccountRead(Address address) - { - throw new NotImplementedException(); - } + public void ReportAccountRead(Address address) + { + throw new NotImplementedException(); + } - public void ReportStorageChange(in StorageCell storageAddress, byte[] before, byte[] after) - { - throw new NotSupportedException(); - } + public void ReportStorageChange(in StorageCell storageAddress, byte[] before, byte[] after) + { + throw new NotSupportedException(); + } - public void ReportStorageRead(in StorageCell storageCell) - { - throw new NotImplementedException(); - } + public void ReportStorageRead(in StorageCell storageCell) + { + throw new NotImplementedException(); + } - public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) - { - throw new NotSupportedException(); - } + public void ReportAction(long gas, UInt256 value, Address @from, Address to, ReadOnlyMemory input, ExecutionType callType, bool isPrecompileCall = false) + { + throw new NotSupportedException(); + } - public void ReportActionEnd(long gas, ReadOnlyMemory output) - { - throw new NotSupportedException(); - } + public void ReportActionEnd(long gas, ReadOnlyMemory output) + { + throw new NotSupportedException(); + } - public void ReportActionError(EvmExceptionType exceptionType) - { - throw new NotSupportedException(); - } + public void ReportActionError(EvmExceptionType exceptionType) + { + throw new NotSupportedException(); + } - public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) - { - throw new NotSupportedException(); - } + public void ReportActionEnd(long gas, Address deploymentAddress, ReadOnlyMemory deployedCode) + { + throw new NotSupportedException(); + } - public void ReportBlockHash(Keccak blockHash) - { - throw new NotImplementedException(); - } + public void ReportBlockHash(Keccak blockHash) + { + throw new NotImplementedException(); + } - public void ReportByteCode(byte[] byteCode) - { - throw new NotSupportedException(); - } + public void ReportByteCode(byte[] byteCode) + { + throw new NotSupportedException(); + } - public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) - { - } + public void ReportGasUpdateForVmTrace(long refund, long gasAvailable) + { + } - public void ReportRefundForVmTrace(long refund, long gasAvailable) - { - } + public void ReportRefundForVmTrace(long refund, long gasAvailable) + { + } - public void ReportRefund(long refund) - { - _traceEntry.Refund = (int)refund; - } + public void ReportRefund(long refund) + { + _traceEntry.Refund = (int)refund; + } - public void ReportExtraGasPressure(long extraGasPressure) - { - throw new NotImplementedException(); - } + public void ReportExtraGasPressure(long extraGasPressure) + { + throw new NotImplementedException(); + } - public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) - { - throw new NotImplementedException(); - } + public void ReportAccess(IReadOnlySet
accessedAddresses, IReadOnlySet accessedStorageCells) + { + throw new NotImplementedException(); + } - public void SetOperationStack(List stackTrace) - { - _traceEntry.Stack = new List(); - foreach (string s in stackTrace) + public void SetOperationStack(List stackTrace) { - ReadOnlySpan inProgress = s.AsSpan(); - if (s.StartsWith("0x")) + _traceEntry.Stack = new List(); + foreach (string s in stackTrace) { - inProgress = inProgress.Slice(2); - } + ReadOnlySpan inProgress = s.AsSpan(); + if (s.StartsWith("0x")) + { + inProgress = inProgress.Slice(2); + } - inProgress = inProgress.TrimStart('0'); + inProgress = inProgress.TrimStart('0'); - _traceEntry.Stack.Add(inProgress.Length == 0 ? "0x0" : "0x" + inProgress.ToString()); + _traceEntry.Stack.Add(inProgress.Length == 0 ? "0x0" : "0x" + inProgress.ToString()); + } } - } - public void ReportStackPush(in ReadOnlySpan stackItem) - { - } + public void ReportStackPush(in ReadOnlySpan stackItem) + { + } - public void SetOperationMemory(IEnumerable memoryTrace) - { - if (IsTracingDetailedMemory) + public void SetOperationMemory(List memoryTrace) { - _traceEntry.Memory = string.Concat("0x", string.Join("", memoryTrace.Select(mt => mt.Replace("0x", string.Empty)))); + if (IsTracingDetailedMemory) + { + _traceEntry.Memory = string.Concat("0x", string.Join("", memoryTrace.Select(mt => mt.Replace("0x", string.Empty)))); + } } - } - public StateTestTxTrace BuildResult() - { - return _trace; - } + public StateTestTxTrace BuildResult() + { + return _trace; + } - public void ReportFees(UInt256 fees, UInt256 burntFees) - { - throw new NotImplementedException(); + public void ReportFees(UInt256 fees, UInt256 burntFees) + { + throw new NotImplementedException(); + } } } diff --git a/src/Nethermind/Nethermind.State.Test/CachingStoreTests.cs b/src/Nethermind/Nethermind.State.Test/CachingStoreTests.cs index d3d32a15b3b..0a6e106e629 100644 --- a/src/Nethermind/Nethermind.State.Test/CachingStoreTests.cs +++ b/src/Nethermind/Nethermind.State.Test/CachingStoreTests.cs @@ -1,9 +1,12 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Test; +using Nethermind.Db; using Nethermind.Trie; +using NSubstitute; using NUnit.Framework; namespace Nethermind.Store.Test diff --git a/src/Nethermind/Nethermind.State.Test/NodeTests.cs b/src/Nethermind/Nethermind.State.Test/NodeTests.cs index c0148a241c2..f9b8a05d625 100644 --- a/src/Nethermind/Nethermind.State.Test/NodeTests.cs +++ b/src/Nethermind/Nethermind.State.Test/NodeTests.cs @@ -1,10 +1,11 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using Nethermind.Core.Buffers; using Nethermind.Core.Test.Builders; using Nethermind.Db; using Nethermind.Logging; +using Nethermind.Serialization.Rlp; +using Nethermind.State; using Nethermind.Trie; using Nethermind.Trie.Pruning; using NUnit.Framework; @@ -134,11 +135,11 @@ public void Child_and_value_store_encode() private static ITrieNodeResolver BuildATreeFromNode(TrieNode node) { TrieNode.AllowBranchValues = true; - CappedArray rlp = node.RlpEncode(null); + byte[] rlp = node.RlpEncode(null); node.ResolveKey(null, true); MemDb memDb = new(); - memDb[node.Keccak.Bytes] = rlp.ToArray(); + memDb[node.Keccak.Bytes] = rlp; // ITrieNodeResolver tree = new PatriciaTree(memDb, node.Keccak, false, true); return new TrieStore(memDb, NullLogManager.Instance); diff --git a/src/Nethermind/Nethermind.State.Test/Proofs/AccountProofCollectorTests.cs b/src/Nethermind/Nethermind.State.Test/Proofs/AccountProofCollectorTests.cs index f0b67a02798..b2f6699748e 100644 --- a/src/Nethermind/Nethermind.State.Test/Proofs/AccountProofCollectorTests.cs +++ b/src/Nethermind/Nethermind.State.Test/Proofs/AccountProofCollectorTests.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using FluentAssertions; using Nethermind.Core; -using Nethermind.Core.Buffers; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; @@ -747,7 +747,7 @@ public void Chaotic_test() } } - node.Value.ToArray().Should().BeEquivalentTo(new byte[] { 1 }); + node.Value.Should().BeEquivalentTo(new byte[] { 1 }); } } } diff --git a/src/Nethermind/Nethermind.State.Test/SnapSync/RecreateStateFromAccountRangesTests.cs b/src/Nethermind/Nethermind.State.Test/SnapSync/RecreateStateFromAccountRangesTests.cs index dddaea98b0d..60cfcd8bafa 100644 --- a/src/Nethermind/Nethermind.State.Test/SnapSync/RecreateStateFromAccountRangesTests.cs +++ b/src/Nethermind/Nethermind.State.Test/SnapSync/RecreateStateFromAccountRangesTests.cs @@ -3,14 +3,20 @@ #nullable disable +using System; using System.Collections.Generic; using System.Linq; +using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Db; +using Nethermind.Int256; using Nethermind.Logging; +using Nethermind.Serialization.Rlp; using Nethermind.State; using Nethermind.State.Proofs; +using Nethermind.State.Snap; using Nethermind.Synchronization.SnapSync; using Nethermind.Trie; using Nethermind.Trie.Pruning; diff --git a/src/Nethermind/Nethermind.State.Test/SnapSync/RecreateStateFromStorageRangesTests.cs b/src/Nethermind/Nethermind.State.Test/SnapSync/RecreateStateFromStorageRangesTests.cs index e2c683fc6d1..42bb388f234 100644 --- a/src/Nethermind/Nethermind.State.Test/SnapSync/RecreateStateFromStorageRangesTests.cs +++ b/src/Nethermind/Nethermind.State.Test/SnapSync/RecreateStateFromStorageRangesTests.cs @@ -3,14 +3,23 @@ #nullable disable +using System; +using System.Collections.Generic; using System.Linq; +using Nethermind.Blockchain; +using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Db; +using Nethermind.Int256; using Nethermind.Logging; +using Nethermind.Serialization.Rlp; using Nethermind.State; using Nethermind.State.Proofs; +using Nethermind.State.Snap; using Nethermind.Synchronization.SnapSync; +using Nethermind.Trie; using Nethermind.Trie.Pruning; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.State.Test/StateReaderTests.cs b/src/Nethermind/Nethermind.State.Test/StateReaderTests.cs index fa2f67226ce..079f03fecdd 100644 --- a/src/Nethermind/Nethermind.State.Test/StateReaderTests.cs +++ b/src/Nethermind/Nethermind.State.Test/StateReaderTests.cs @@ -5,6 +5,7 @@ using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Db; using Nethermind.Specs; @@ -15,6 +16,7 @@ using Nethermind.Trie.Pruning; using NSubstitute; using NUnit.Framework; +using Metrics = Nethermind.Trie.Pruning.Metrics; namespace Nethermind.Store.Test { diff --git a/src/Nethermind/Nethermind.State.Test/Witnesses/WitnessCollectorTests.cs b/src/Nethermind/Nethermind.State.Test/Witnesses/WitnessCollectorTests.cs index a95eebe7ed4..82bf950ac75 100644 --- a/src/Nethermind/Nethermind.State.Test/Witnesses/WitnessCollectorTests.cs +++ b/src/Nethermind/Nethermind.State.Test/Witnesses/WitnessCollectorTests.cs @@ -9,6 +9,7 @@ using Nethermind.Db; using Nethermind.Logging; using Nethermind.State.Witnesses; +using Nethermind.Trie; using NUnit.Framework; namespace Nethermind.Store.Test.Witnesses diff --git a/src/Nethermind/Nethermind.State.Test/Witnesses/WitnessingStoreTests.cs b/src/Nethermind/Nethermind.State.Test/Witnesses/WitnessingStoreTests.cs index 75188210096..c26ad366b57 100644 --- a/src/Nethermind/Nethermind.State.Test/Witnesses/WitnessingStoreTests.cs +++ b/src/Nethermind/Nethermind.State.Test/Witnesses/WitnessingStoreTests.cs @@ -3,6 +3,7 @@ using System; using FluentAssertions; +using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; @@ -11,6 +12,7 @@ using Nethermind.State; using Nethermind.State.Witnesses; using Nethermind.Trie; +using NSubstitute; using NUnit.Framework; namespace Nethermind.Store.Test.Witnesses diff --git a/src/Nethermind/Nethermind.State/IStorageTreeFactory.cs b/src/Nethermind/Nethermind.State/IStorageTreeFactory.cs deleted file mode 100644 index 7a78cc6e4a6..00000000000 --- a/src/Nethermind/Nethermind.State/IStorageTreeFactory.cs +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Logging; -using Nethermind.Trie.Pruning; - -namespace Nethermind.State; - -public interface IStorageTreeFactory -{ - StorageTree Create(Address address, ITrieStore trieStore, Keccak storageRoot, Keccak stateRoot, ILogManager? logManager); -} diff --git a/src/Nethermind/Nethermind.State/IWorldState.cs b/src/Nethermind/Nethermind.State/IWorldState.cs index 51f56ed43bc..cea4e411e11 100644 --- a/src/Nethermind/Nethermind.State/IWorldState.cs +++ b/src/Nethermind/Nethermind.State/IWorldState.cs @@ -80,15 +80,14 @@ public interface IWorldState : IJournal, IReadOnlyStateProvider void DeleteAccount(Address address); - void CreateAccount(Address address, in UInt256 balance, in UInt256 nonce = default); - void CreateAccountIfNotExists(Address address, in UInt256 balance, in UInt256 nonce = default); + void CreateAccount(Address address, in UInt256 balance); + + void CreateAccount(Address address, in UInt256 balance, in UInt256 nonce); void InsertCode(Address address, ReadOnlyMemory code, IReleaseSpec spec, bool isGenesis = false); void AddToBalance(Address address, in UInt256 balanceChange, IReleaseSpec spec); - void AddToBalanceAndCreateIfNotExists(Address address, in UInt256 balanceChange, IReleaseSpec spec); - void SubtractFromBalance(Address address, in UInt256 balanceChange, IReleaseSpec spec); void UpdateStorageRoot(Address address, Keccak storageRoot); diff --git a/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs b/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs index 31801e41096..0f496cf0a13 100644 --- a/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs +++ b/src/Nethermind/Nethermind.State/PersistentStorageProvider.cs @@ -23,27 +23,21 @@ internal class PersistentStorageProvider : PartialStorageProviderBase private readonly ITrieStore _trieStore; private readonly StateProvider _stateProvider; private readonly ILogManager? _logManager; - internal readonly IStorageTreeFactory _storageTreeFactory; private readonly ResettableDictionary _storages = new(); - /// /// EIP-1283 /// private readonly ResettableDictionary _originalValues = new(); - private readonly ResettableHashSet _committedThisRound = new(); - public PersistentStorageProvider(ITrieStore? trieStore, StateProvider? stateProvider, ILogManager? logManager, IStorageTreeFactory? storageTreeFactory = null) + public PersistentStorageProvider(ITrieStore? trieStore, StateProvider? stateProvider, ILogManager? logManager) : base(logManager) { _trieStore = trieStore ?? throw new ArgumentNullException(nameof(trieStore)); _stateProvider = stateProvider ?? throw new ArgumentNullException(nameof(stateProvider)); _logManager = logManager ?? throw new ArgumentNullException(nameof(logManager)); - _storageTreeFactory = storageTreeFactory ?? new StorageTreeFactory(); } - public Keccak StateRoot { get; set; } = null!; - /// /// Reset the storage state /// @@ -226,7 +220,7 @@ private StorageTree GetOrCreateStorage(Address address) { if (!_storages.ContainsKey(address)) { - StorageTree storageTree = _storageTreeFactory.Create(address, _trieStore, _stateProvider.GetStorageRoot(address), StateRoot, _logManager); + StorageTree storageTree = new(_trieStore, _stateProvider.GetStorageRoot(address), _logManager); return _storages[address] = storageTree; } @@ -287,11 +281,5 @@ public override void ClearStorage(Address address) // TODO: how does it work with pruning? _storages[address] = new StorageTree(_trieStore, Keccak.EmptyTreeHash, _logManager); } - - private class StorageTreeFactory : IStorageTreeFactory - { - public StorageTree Create(Address address, ITrieStore trieStore, Keccak storageRoot, Keccak stateRoot, ILogManager? logManager) - => new(trieStore, storageRoot, logManager); - } } } diff --git a/src/Nethermind/Nethermind.State/Proofs/AccountProofCollector.cs b/src/Nethermind/Nethermind.State/Proofs/AccountProofCollector.cs index 510be44f649..e493a541764 100644 --- a/src/Nethermind/Nethermind.State/Proofs/AccountProofCollector.cs +++ b/src/Nethermind/Nethermind.State/Proofs/AccountProofCollector.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using Nethermind.Core; -using Nethermind.Core.Buffers; using Nethermind.Core.Crypto; using Nethermind.Int256; using Nethermind.Serialization.Rlp; @@ -242,13 +241,13 @@ private void AddProofItem(TrieNode node, TrieVisitContext trieVisitContext) { foreach (int storageIndex in value.StorageIndices) { - _storageProofItems[storageIndex].Add(node.FullRlp.ToArray()); + _storageProofItems[storageIndex].Add(node.FullRlp); } } } else { - _accountProofItems.Add(node.FullRlp.ToArray()); + _accountProofItems.Add(node.FullRlp); } } @@ -283,13 +282,13 @@ public void VisitLeaf(TrieNode node, TrieVisitContext trieVisitContext, byte[] v bool isPathMatched = IsPathMatched(node, thisStoragePath); if (isPathMatched) { - _accountProof.StorageProofs[storageIndex].Value = new RlpStream(node.Value.ToArray()).DecodeByteArray(); + _accountProof.StorageProofs[storageIndex].Value = new RlpStream(node.Value).DecodeByteArray(); } } } else { - Account account = _accountDecoder.Decode(new RlpStream(node.Value.ToArray())); + Account account = _accountDecoder.Decode(new RlpStream(node.Value)); bool isPathMatched = IsPathMatched(node, _fullAccountPath); if (isPathMatched) { diff --git a/src/Nethermind/Nethermind.State/Proofs/PatriciaTrieT.cs b/src/Nethermind/Nethermind.State/Proofs/PatriciaTrieT.cs index 371535e9a96..5287eeeb44c 100644 --- a/src/Nethermind/Nethermind.State/Proofs/PatriciaTrieT.cs +++ b/src/Nethermind/Nethermind.State/Proofs/PatriciaTrieT.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Nethermind.Core.Buffers; using Nethermind.Db; using Nethermind.Logging; using Nethermind.Serialization.Rlp; @@ -24,8 +23,8 @@ public abstract class PatriciaTrie : PatriciaTree /// true to maintain an in-memory database for proof computation; /// otherwise, false. /// - public PatriciaTrie(IEnumerable? list, bool canBuildProof, ICappedArrayPool? bufferPool = null) - : base(canBuildProof ? new MemDb() : NullDb.Instance, EmptyTreeHash, false, false, NullLogManager.Instance, bufferPool: bufferPool) + public PatriciaTrie(IEnumerable? list, bool canBuildProof) + : base(canBuildProof ? new MemDb() : NullDb.Instance, EmptyTreeHash, false, false, NullLogManager.Instance) { CanBuildProof = canBuildProof; diff --git a/src/Nethermind/Nethermind.State/Proofs/ProofCollector.cs b/src/Nethermind/Nethermind.State/Proofs/ProofCollector.cs index cb1cc0076c4..416cd37f0c1 100644 --- a/src/Nethermind/Nethermind.State/Proofs/ProofCollector.cs +++ b/src/Nethermind/Nethermind.State/Proofs/ProofCollector.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using Nethermind.Core.Buffers; using Nethermind.Core.Crypto; using Nethermind.Trie; @@ -66,7 +65,7 @@ public void VisitExtension(TrieNode node, TrieVisitContext trieVisitContext) protected virtual void AddProofBits(TrieNode node) { - _proofBits.Add(node.FullRlp.ToArray()); + _proofBits.Add(node.FullRlp); } public void VisitLeaf(TrieNode node, TrieVisitContext trieVisitContext, byte[] value) diff --git a/src/Nethermind/Nethermind.State/Proofs/ProofVerifier.cs b/src/Nethermind/Nethermind.State/Proofs/ProofVerifier.cs index c55a6cf728d..314e2ad63ab 100644 --- a/src/Nethermind/Nethermind.State/Proofs/ProofVerifier.cs +++ b/src/Nethermind/Nethermind.State/Proofs/ProofVerifier.cs @@ -1,9 +1,10 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; using System.IO; using System.Linq; -using Nethermind.Core.Buffers; using Nethermind.Core.Crypto; using Nethermind.Serialization.Rlp; using Nethermind.Trie; @@ -45,7 +46,7 @@ public static class ProofVerifier TrieNode trieNode = new(NodeType.Unknown, proof.Last()); trieNode.ResolveNode(null); - return trieNode.Value.ToArray(); + return trieNode.Value; } } } diff --git a/src/Nethermind/Nethermind.State/Proofs/ReceiptTrie.cs b/src/Nethermind/Nethermind.State/Proofs/ReceiptTrie.cs index a605bc7fd9a..14296d471b0 100644 --- a/src/Nethermind/Nethermind.State/Proofs/ReceiptTrie.cs +++ b/src/Nethermind/Nethermind.State/Proofs/ReceiptTrie.cs @@ -5,14 +5,9 @@ using System.Collections.Generic; using System.Linq; using Nethermind.Core; -using Nethermind.Core.Buffers; -using Nethermind.Core.Crypto; -using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Serialization.Rlp; using Nethermind.State.Trie; -using Nethermind.Trie; -using Nethermind.Trie.Pruning; namespace Nethermind.State.Proofs; @@ -25,8 +20,8 @@ public class ReceiptTrie : PatriciaTrie /// /// The transaction receipts to build the trie of. - public ReceiptTrie(IReceiptSpec spec, IEnumerable receipts, bool canBuildProof = false, ICappedArrayPool? bufferPool = null) - : base(null, canBuildProof, bufferPool: bufferPool) + public ReceiptTrie(IReceiptSpec spec, IEnumerable receipts, bool canBuildProof = false) + : base(null, canBuildProof) { ArgumentNullException.ThrowIfNull(spec); ArgumentNullException.ThrowIfNull(receipts); @@ -40,25 +35,15 @@ public ReceiptTrie(IReceiptSpec spec, IEnumerable receipts, bool canB private void Initialize(IEnumerable receipts, IReceiptSpec spec) { - RlpBehaviors behavior = (spec.IsEip658Enabled ? RlpBehaviors.Eip658Receipts : RlpBehaviors.None) - | RlpBehaviors.SkipTypedWrapping; - int key = 0; + var behavior = (spec.IsEip658Enabled ? RlpBehaviors.Eip658Receipts : RlpBehaviors.None) + | RlpBehaviors.SkipTypedWrapping; + var key = 0; - foreach (TxReceipt? receipt in receipts) + foreach (var receipt in receipts) { - CappedArray buffer = _decoder.EncodeToCappedArray(receipt, behavior, bufferPool: _bufferPool); - CappedArray keyBuffer = (key++).EncodeToCappedArray(bufferPool: _bufferPool); - Set(keyBuffer.AsSpan(), buffer); + Set(Rlp.Encode(key++).Bytes, _decoder.EncodeNew(receipt, behavior)); } } protected override void Initialize(IEnumerable list) => throw new NotSupportedException(); - - public static Keccak CalculateRoot(IReceiptSpec receiptSpec, IList txReceipts) - { - TrackingCappedArrayPool cappedArrayPool = new(txReceipts.Count * 4); - Keccak receiptsRoot = new ReceiptTrie(receiptSpec, txReceipts, bufferPool: cappedArrayPool).RootHash; - cappedArrayPool.ReturnAll(); - return receiptsRoot; - } } diff --git a/src/Nethermind/Nethermind.State/Proofs/TxTrie.cs b/src/Nethermind/Nethermind.State/Proofs/TxTrie.cs index 5aad9928a33..6ed6b271323 100644 --- a/src/Nethermind/Nethermind.State/Proofs/TxTrie.cs +++ b/src/Nethermind/Nethermind.State/Proofs/TxTrie.cs @@ -4,12 +4,8 @@ using System; using System.Collections.Generic; using Nethermind.Core; -using Nethermind.Core.Buffers; -using Nethermind.Core.Crypto; using Nethermind.Serialization.Rlp; using Nethermind.State.Trie; -using Nethermind.Trie; -using Nethermind.Trie.Pruning; namespace Nethermind.State.Proofs; @@ -22,8 +18,8 @@ public class TxTrie : PatriciaTrie /// /// The transactions to build the trie of. - public TxTrie(IEnumerable transactions, bool canBuildProof = false, ICappedArrayPool? bufferPool = null) - : base(transactions, canBuildProof, bufferPool: bufferPool) => ArgumentNullException.ThrowIfNull(transactions); + public TxTrie(IEnumerable transactions, bool canBuildProof = false) + : base(transactions, canBuildProof) => ArgumentNullException.ThrowIfNull(transactions); protected override void Initialize(IEnumerable list) { @@ -34,18 +30,8 @@ protected override void Initialize(IEnumerable list) // a temporary trie would be a trie that exists to create a state root only and then be disposed of foreach (Transaction? transaction in list) { - CappedArray buffer = _txDecoder.EncodeToCappedArray(transaction, RlpBehaviors.SkipTypedWrapping, - bufferPool: _bufferPool); - CappedArray keyBuffer = (key++).EncodeToCappedArray(bufferPool: _bufferPool); - Set(keyBuffer.AsSpan(), buffer); + Rlp transactionRlp = _txDecoder.Encode(transaction, RlpBehaviors.SkipTypedWrapping); + Set(Rlp.Encode(key++).Bytes, transactionRlp.Bytes); } } - - public static Keccak CalculateRoot(IList transactions) - { - TrackingCappedArrayPool cappedArray = new TrackingCappedArrayPool(transactions.Count * 4); - Keccak rootHash = new TxTrie(transactions, false, bufferPool: cappedArray).RootHash; - cappedArray.ReturnAll(); - return rootHash; - } } diff --git a/src/Nethermind/Nethermind.State/Snap/AccountRange.cs b/src/Nethermind/Nethermind.State/Snap/AccountRange.cs index 5ceedb0d757..e8d8e6c3a5c 100644 --- a/src/Nethermind/Nethermind.State/Snap/AccountRange.cs +++ b/src/Nethermind/Nethermind.State/Snap/AccountRange.cs @@ -1,6 +1,11 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; using Nethermind.Core.Crypto; namespace Nethermind.State.Snap diff --git a/src/Nethermind/Nethermind.State/Snap/AccountsAndProofs.cs b/src/Nethermind/Nethermind.State/Snap/AccountsAndProofs.cs index bdad8248148..6b6452716a4 100644 --- a/src/Nethermind/Nethermind.State/Snap/AccountsAndProofs.cs +++ b/src/Nethermind/Nethermind.State/Snap/AccountsAndProofs.cs @@ -1,6 +1,12 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + namespace Nethermind.State.Snap { public class AccountsAndProofs diff --git a/src/Nethermind/Nethermind.State/Snap/AccountsToRefreshRequest.cs b/src/Nethermind/Nethermind.State/Snap/AccountsToRefreshRequest.cs index 8fc00330bca..6b0e572c2ab 100644 --- a/src/Nethermind/Nethermind.State/Snap/AccountsToRefreshRequest.cs +++ b/src/Nethermind/Nethermind.State/Snap/AccountsToRefreshRequest.cs @@ -1,7 +1,13 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; using Nethermind.Core.Crypto; +using Nethermind.State.Snap; namespace Nethermind.State.Snap { diff --git a/src/Nethermind/Nethermind.State/Snap/Constants.cs b/src/Nethermind/Nethermind.State/Snap/Constants.cs index 394923319b9..bd72a4dbca2 100644 --- a/src/Nethermind/Nethermind.State/Snap/Constants.cs +++ b/src/Nethermind/Nethermind.State/Snap/Constants.cs @@ -1,6 +1,12 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + namespace Nethermind.State.Snap { public class Constants diff --git a/src/Nethermind/Nethermind.State/Snap/GetTrieNodesRequest.cs b/src/Nethermind/Nethermind.State/Snap/GetTrieNodesRequest.cs index 018a0e79055..99d7752fe94 100644 --- a/src/Nethermind/Nethermind.State/Snap/GetTrieNodesRequest.cs +++ b/src/Nethermind/Nethermind.State/Snap/GetTrieNodesRequest.cs @@ -1,6 +1,11 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; using Nethermind.Core.Crypto; namespace Nethermind.State.Snap diff --git a/src/Nethermind/Nethermind.State/Snap/PathGroup.cs b/src/Nethermind/Nethermind.State/Snap/PathGroup.cs index d290e459162..d4ccdbf190c 100644 --- a/src/Nethermind/Nethermind.State/Snap/PathGroup.cs +++ b/src/Nethermind/Nethermind.State/Snap/PathGroup.cs @@ -1,6 +1,12 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + namespace Nethermind.State.Snap { public class PathGroup diff --git a/src/Nethermind/Nethermind.State/Snap/PathWithAccount.cs b/src/Nethermind/Nethermind.State/Snap/PathWithAccount.cs index 60d30e04e4a..6aa0132827b 100644 --- a/src/Nethermind/Nethermind.State/Snap/PathWithAccount.cs +++ b/src/Nethermind/Nethermind.State/Snap/PathWithAccount.cs @@ -1,6 +1,11 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; using Nethermind.Core; using Nethermind.Core.Crypto; diff --git a/src/Nethermind/Nethermind.State/Snap/PathWithStorageSlot.cs b/src/Nethermind/Nethermind.State/Snap/PathWithStorageSlot.cs index d118b1ea7d6..f6a826b822c 100644 --- a/src/Nethermind/Nethermind.State/Snap/PathWithStorageSlot.cs +++ b/src/Nethermind/Nethermind.State/Snap/PathWithStorageSlot.cs @@ -1,6 +1,11 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; using Nethermind.Core.Crypto; namespace Nethermind.State.Snap diff --git a/src/Nethermind/Nethermind.State/Snap/SlotsAndProofs.cs b/src/Nethermind/Nethermind.State/Snap/SlotsAndProofs.cs index 7dab28849f9..795acf36328 100644 --- a/src/Nethermind/Nethermind.State/Snap/SlotsAndProofs.cs +++ b/src/Nethermind/Nethermind.State/Snap/SlotsAndProofs.cs @@ -1,6 +1,12 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + namespace Nethermind.State.Snap { public class SlotsAndProofs diff --git a/src/Nethermind/Nethermind.State/Snap/StorageRange.cs b/src/Nethermind/Nethermind.State/Snap/StorageRange.cs index d823689868e..7272116b707 100644 --- a/src/Nethermind/Nethermind.State/Snap/StorageRange.cs +++ b/src/Nethermind/Nethermind.State/Snap/StorageRange.cs @@ -1,6 +1,11 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; using Nethermind.Core.Crypto; namespace Nethermind.State.Snap diff --git a/src/Nethermind/Nethermind.State/StateProvider.cs b/src/Nethermind/Nethermind.State/StateProvider.cs index 9569fe427a6..7d7f1a57c64 100644 --- a/src/Nethermind/Nethermind.State/StateProvider.cs +++ b/src/Nethermind/Nethermind.State/StateProvider.cs @@ -3,13 +3,11 @@ using System; using System.Collections.Generic; -using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; using Nethermind.Core; -using Nethermind.Core.Caching; using Nethermind.Core.Crypto; using Nethermind.Core.Resettables; using Nethermind.Core.Specs; -using Nethermind.Db; using Nethermind.Int256; using Nethermind.Logging; using Nethermind.State.Tracing; @@ -25,11 +23,6 @@ internal class StateProvider private const int StartCapacity = Resettable.StartCapacity; private readonly ResettableDictionary> _intraBlockCache = new(); private readonly ResettableHashSet
_committedThisRound = new(); - // Only guarding against hot duplicates so filter doesn't need to be too big - // Note: - // False negatives are fine as they will just result in a overwrite set - // False positives would be problematic as the code _must_ be persisted - private readonly LruKeyCache _codeInsertFilter = new(2048, "Code Insert Filter"); private readonly List _keptInCache = new(); private readonly ILogger _logger; @@ -39,11 +32,11 @@ internal class StateProvider private Change?[] _changes = new Change?[StartCapacity]; private int _currentPosition = Resettable.EmptyPosition; - public StateProvider(ITrieStore? trieStore, IKeyValueStore? codeDb, ILogManager? logManager, StateTree? stateTree = null) + public StateProvider(ITrieStore? trieStore, IKeyValueStore? codeDb, ILogManager? logManager) { _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); _codeDb = codeDb ?? throw new ArgumentNullException(nameof(codeDb)); - _tree = stateTree ?? new StateTree(trieStore, logManager); + _tree = new StateTree(trieStore, logManager); } public void Accept(ITreeVisitor? visitor, Keccak? stateRoot, VisitingOptions? visitingOptions = null) @@ -76,7 +69,7 @@ public Keccak StateRoot set => _tree.RootHash = value; } - internal readonly StateTree _tree; + private readonly StateTree _tree; public bool IsContract(Address address) { @@ -148,29 +141,7 @@ public void InsertCode(Address address, ReadOnlyMemory code, IReleaseSpec { _needsStateRootUpdate = true; Keccak codeHash = code.Length == 0 ? Keccak.OfAnEmptyString : Keccak.Compute(code.Span); - - // Don't reinsert if already inserted. This can be the case when the same - // code is used by multiple deployments. Either from factory contracts (e.g. LPs) - // or people copy and pasting popular contracts - if (!_codeInsertFilter.Get(codeHash)) - { - if (_codeDb is IDbWithSpan dbWithSpan) - { - dbWithSpan.PutSpan(codeHash.Bytes, code.Span); - } - else if (MemoryMarshal.TryGetArray(code, out ArraySegment codeArray) - && codeArray.Offset == 0 - && codeArray.Count == code.Length) - { - _codeDb[codeHash.Bytes] = codeArray.Array; - } - else - { - _codeDb[codeHash.Bytes] = code.ToArray(); - } - - _codeInsertFilter.Set(codeHash); - } + _codeDb[codeHash.Bytes] = code.ToArray(); Account? account = GetThroughCache(address); if (account is null) @@ -407,30 +378,21 @@ public void Restore(int snapshot) _keptInCache.Clear(); } - public void CreateAccount(Address address, in UInt256 balance, in UInt256 nonce = default) + public void CreateAccount(Address address, in UInt256 balance) { _needsStateRootUpdate = true; - if (_logger.IsTrace) _logger.Trace($"Creating account: {address} with balance {balance} and nonce {nonce}"); - Account account = (balance.IsZero && nonce.IsZero) ? Account.TotallyEmpty : new Account(nonce, balance); + if (_logger.IsTrace) _logger.Trace($"Creating account: {address} with balance {balance}"); + Account account = balance.IsZero ? Account.TotallyEmpty : new Account(balance); PushNew(address, account); } - public void CreateAccountIfNotExists(Address address, in UInt256 balance, in UInt256 nonce = default) - { - if (AccountExists(address)) return; - CreateAccount(address, balance, nonce); - } - public void AddToBalanceAndCreateIfNotExists(Address address, in UInt256 balance, IReleaseSpec spec) + public void CreateAccount(Address address, in UInt256 balance, in UInt256 nonce) { - if (AccountExists(address)) - { - AddToBalance(address, balance, spec); - } - else - { - CreateAccount(address, balance); - } + _needsStateRootUpdate = true; + if (_logger.IsTrace) _logger.Trace($"Creating account: {address} with balance {balance} and nonce {nonce}"); + Account account = (balance.IsZero && nonce.IsZero) ? Account.TotallyEmpty : new Account(nonce, balance); + PushNew(address, account); } public void Commit(IReleaseSpec releaseSpec, bool isGenesis = false) diff --git a/src/Nethermind/Nethermind.State/StateTree.cs b/src/Nethermind/Nethermind.State/StateTree.cs index b149070ead8..225a97d1b59 100644 --- a/src/Nethermind/Nethermind.State/StateTree.cs +++ b/src/Nethermind/Nethermind.State/StateTree.cs @@ -3,7 +3,6 @@ using System.Diagnostics; using Nethermind.Core; -using Nethermind.Core.Buffers; using Nethermind.Core.Crypto; using Nethermind.Db; using Nethermind.Logging; @@ -20,8 +19,8 @@ public class StateTree : PatriciaTree private static readonly Rlp EmptyAccountRlp = Rlp.Encode(Account.TotallyEmpty); [DebuggerStepThrough] - public StateTree(ICappedArrayPool? bufferPool = null) - : base(new MemDb(), Keccak.EmptyTreeHash, true, true, NullLogManager.Instance, bufferPool: bufferPool) + public StateTree() + : base(new MemDb(), Keccak.EmptyTreeHash, true, true, NullLogManager.Instance) { TrieType = TrieType.State; } @@ -37,14 +36,24 @@ public StateTree(ITrieStore? store, ILogManager? logManager) public Account? Get(Address address, Keccak? rootHash = null) { byte[]? bytes = Get(ValueKeccak.Compute(address.Bytes).BytesAsSpan, rootHash); - return bytes is null ? null : _decoder.Decode(bytes.AsRlpStream()); + if (bytes is null) + { + return null; + } + + return _decoder.Decode(bytes.AsRlpStream()); } [DebuggerStepThrough] internal Account? Get(Keccak keccak) // for testing { byte[]? bytes = Get(keccak.Bytes); - return bytes is null ? null : _decoder.Decode(bytes.AsRlpStream()); + if (bytes is null) + { + return null; + } + + return _decoder.Decode(bytes.AsRlpStream()); } public void Set(Address address, Account? account) diff --git a/src/Nethermind/Nethermind.State/Witnesses/WitnessCollector.cs b/src/Nethermind/Nethermind.State/Witnesses/WitnessCollector.cs index 61b6dca90fa..6adb42f8739 100644 --- a/src/Nethermind/Nethermind.State/Witnesses/WitnessCollector.cs +++ b/src/Nethermind/Nethermind.State/Witnesses/WitnessCollector.cs @@ -4,11 +4,13 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using Nethermind.Core; using Nethermind.Core.Caching; using Nethermind.Core.Crypto; using Nethermind.Core.Resettables; using Nethermind.Logging; +using Nethermind.Trie; namespace Nethermind.State.Witnesses { diff --git a/src/Nethermind/Nethermind.State/WorldState.cs b/src/Nethermind/Nethermind.State/WorldState.cs index 924ce51c21c..2f8da1de6b5 100644 --- a/src/Nethermind/Nethermind.State/WorldState.cs +++ b/src/Nethermind/Nethermind.State/WorldState.cs @@ -18,24 +18,19 @@ [assembly: InternalsVisibleTo("Nethermind.Benchmark")] [assembly: InternalsVisibleTo("Nethermind.Blockchain.Test")] [assembly: InternalsVisibleTo("Nethermind.Synchronization.Test")] -[assembly: InternalsVisibleTo("Nethermind.Synchronization")] namespace Nethermind.State { public class WorldState : IWorldState { - internal readonly StateProvider _stateProvider; - internal readonly PersistentStorageProvider _persistentStorageProvider; + private readonly StateProvider _stateProvider; + private readonly PersistentStorageProvider _persistentStorageProvider; private readonly TransientStorageProvider _transientStorageProvider; public Keccak StateRoot { get => _stateProvider.StateRoot; - set - { - _stateProvider.StateRoot = value; - _persistentStorageProvider.StateRoot = value; - } + set => _stateProvider.StateRoot = value; } public WorldState(ITrieStore? trieStore, IKeyValueStore? codeDb, ILogManager? logManager) @@ -44,14 +39,6 @@ public WorldState(ITrieStore? trieStore, IKeyValueStore? codeDb, ILogManager? lo _persistentStorageProvider = new PersistentStorageProvider(trieStore, _stateProvider, logManager); _transientStorageProvider = new TransientStorageProvider(logManager); } - - internal WorldState(ITrieStore? trieStore, IKeyValueStore? codeDb, ILogManager? logManager, StateTree stateTree, IStorageTreeFactory storageTreeFactory) - { - _stateProvider = new StateProvider(trieStore, codeDb, logManager, stateTree); - _persistentStorageProvider = new PersistentStorageProvider(trieStore, _stateProvider, logManager, storageTreeFactory); - _transientStorageProvider = new TransientStorageProvider(logManager); - } - public Account GetAccount(Address address) { return _stateProvider.GetAccount(address); @@ -102,7 +89,11 @@ public void DeleteAccount(Address address) { _stateProvider.DeleteAccount(address); } - public void CreateAccount(Address address, in UInt256 balance, in UInt256 nonce = default) + public void CreateAccount(Address address, in UInt256 balance) + { + _stateProvider.CreateAccount(address, balance); + } + public void CreateAccount(Address address, in UInt256 balance, in UInt256 nonce) { _stateProvider.CreateAccount(address, balance, nonce); } @@ -114,10 +105,6 @@ public void AddToBalance(Address address, in UInt256 balanceChange, IReleaseSpec { _stateProvider.AddToBalance(address, balanceChange, spec); } - public void AddToBalanceAndCreateIfNotExists(Address address, in UInt256 balanceChange, IReleaseSpec spec) - { - _stateProvider.AddToBalanceAndCreateIfNotExists(address, balanceChange, spec); - } public void SubtractFromBalance(Address address, in UInt256 balanceChange, IReleaseSpec spec) { _stateProvider.SubtractFromBalance(address, balanceChange, spec); @@ -139,7 +126,6 @@ public void CommitTree(long blockNumber) { _persistentStorageProvider.CommitTrees(blockNumber); _stateProvider.CommitTree(blockNumber); - _persistentStorageProvider.StateRoot = _stateProvider.StateRoot; } public void TouchCode(Keccak codeHash) @@ -226,10 +212,5 @@ internal void SetNonce(Address address, in UInt256 nonce) { _stateProvider.SetNonce(address, nonce); } - - public void CreateAccountIfNotExists(Address address, in UInt256 balance, in UInt256 nonce = default) - { - _stateProvider.CreateAccountIfNotExists(address, balance, nonce); - } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/AllocationStrategies/BySpeedStrategyTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/AllocationStrategies/BySpeedStrategyTests.cs index 09df2772e7b..288cbcf02f6 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/AllocationStrategies/BySpeedStrategyTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/AllocationStrategies/BySpeedStrategyTests.cs @@ -20,7 +20,7 @@ namespace Nethermind.Synchronization.Test.AllocationStrategies; public class BySpeedStrategyTests { - private static PublicKey TestPublicKey { get; } = new(Bytes.FromHexString( + private static PublicKey TestPublicKey = new(Bytes.FromHexString( "0x13a1107b6f78a4977222d2d5a4cd05a8a042b75222c8ec99129b83793eda3d214208d4e835617512fc8d148d3d1b4d89530861644f531675b1fb64b785c6c152")); [TestCase(1, 0, 0, 2)] @@ -33,7 +33,7 @@ public class BySpeedStrategyTests [TestCase(1, 0.1, 0, 2)] public void TestShouldSelectHighestSpeed(int? currentPeerIdx, decimal minDiffPercentageForSpeedSwitch, int minDiffSpeed, int expectedSelectedPeerIdx) { - long[] peerSpeeds = + long[] peerSpeeds = new long[] { 100, 90, @@ -43,16 +43,19 @@ public void TestShouldSelectHighestSpeed(int? currentPeerIdx, decimal minDiffPer INodeStatsManager nodeStatsManager = Substitute.For(); - List peers = peerSpeeds - .Select(peerSpeed => CreatePeerInfoWithSpeed(peerSpeed, nodeStatsManager)) - .ToList(); + List peers = new(); + for (int i = 0; i < peerSpeeds.Length; i++) + { + PeerInfo pInfo = CreatePeerInfoWithSpeed(peerSpeeds[i], nodeStatsManager); + peers.Add(pInfo); + } BySpeedStrategy strategy = new(TransferSpeedType.Bodies, true, minDiffPercentageForSpeedSwitch, minDiffSpeed, 0, 0); PeerInfo? currentPeer = null; if (currentPeerIdx is not null) currentPeer = peers[currentPeerIdx.Value]; - PeerInfo selectedPeer = strategy.Allocate(currentPeer, peers, nodeStatsManager, Build.A.BlockTree().TestObject)!; + PeerInfo? selectedPeer = strategy.Allocate(currentPeer, peers, nodeStatsManager, Build.A.BlockTree().TestObject); int selectedPeerIdx = peers.IndexOf(selectedPeer); selectedPeerIdx.Should().Be(expectedSelectedPeerIdx); @@ -73,13 +76,16 @@ public void TestMinimumKnownSpeed(int peerWithKnownSpeed, int peerWithUnknownSpe INodeStatsManager nodeStatsManager = Substitute.For(); - List peers = peerSpeeds - .Select(peerSpeed => CreatePeerInfoWithSpeed(peerSpeed, nodeStatsManager)) - .ToList(); + List peers = new(); + for (int i = 0; i < peerSpeeds.Length; i++) + { + PeerInfo pInfo = CreatePeerInfoWithSpeed(peerSpeeds[i], nodeStatsManager); + peers.Add(pInfo); + } BySpeedStrategy strategy = new(TransferSpeedType.Bodies, true, 0, 0, 0, desiredKnownPeer); - PeerInfo selectedPeer = strategy.Allocate(null, peers, nodeStatsManager, Build.A.BlockTree().TestObject)!; + PeerInfo? selectedPeer = strategy.Allocate(null, peers, nodeStatsManager, Build.A.BlockTree().TestObject); int selectedPeerIdx = peers.IndexOf(selectedPeer); if (pickedNewPeer) @@ -104,7 +110,7 @@ public void TestWhenSameSpeed_RandomlyTryOtherPeer() BySpeedStrategy strategy = new(TransferSpeedType.Bodies, true, 0, 0, 0, 0); - PeerInfo selectedPeer = strategy.Allocate(null, peers, nodeStatsManager, Build.A.BlockTree().TestObject)!; + PeerInfo? selectedPeer = strategy.Allocate(null, peers, nodeStatsManager, Build.A.BlockTree().TestObject); int selectedPeerIdx = peers.IndexOf(selectedPeer); selectedPeerIdx.Should().BeGreaterThan(50); } @@ -122,9 +128,12 @@ public void TestRecalculateSpeedProbability(int peerWithKnownSpeed, int peerWith INodeStatsManager nodeStatsManager = Substitute.For(); - List peers = peerSpeeds - .Select(peerSpeed => CreatePeerInfoWithSpeed(peerSpeed, nodeStatsManager)) - .ToList(); + List peers = new(); + for (int i = 0; i < peerSpeeds.Length; i++) + { + PeerInfo pInfo = CreatePeerInfoWithSpeed(peerSpeeds[i], nodeStatsManager); + peers.Add(pInfo); + } BySpeedStrategy strategy = new(TransferSpeedType.Bodies, true, 0, 0, recalculateSpeedProbability, 0); @@ -133,7 +142,7 @@ public void TestRecalculateSpeedProbability(int peerWithKnownSpeed, int peerWith for (int i = 0; i < 100; i++) { - PeerInfo selectedPeer = strategy.Allocate(null, peers, nodeStatsManager, Build.A.BlockTree().TestObject)!; + PeerInfo? selectedPeer = strategy.Allocate(null, peers, nodeStatsManager, Build.A.BlockTree().TestObject); int selectedPeerIdx = peers.IndexOf(selectedPeer); if (peerSpeeds[selectedPeerIdx] is null) { diff --git a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs index 14596b34c35..74447c505c0 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs @@ -50,14 +50,12 @@ public async Task Merge_Happy_path(long pivot, long headNumber, int options, int .InsertBeaconHeaders(4, pivot - 1) .InsertBeaconBlocks(pivot + 1, insertedBeaconBlocks, BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder.TotalDifficultyMode.Null); BlockTree syncedTree = blockTrees.SyncedTree; - PostMergeContext ctx = new() - { - BlockTreeScenario = blockTrees, - }; + PostMergeContext ctx = new(); + ctx.BlockTreeScenario = blockTrees; DownloaderOptions downloaderOptions = (DownloaderOptions)options; bool withReceipts = downloaderOptions == DownloaderOptions.WithReceipts; - ctx.MergeConfig = new MergeConfig { TerminalTotalDifficulty = "0" }; + ctx.MergeConfig = new MergeConfig() { TerminalTotalDifficulty = "0" }; ctx.BeaconPivot.EnsurePivot(blockTrees.SyncedTree.FindHeader(pivot, BlockTreeLookupOptions.None)); ctx.BeaconPivot.ProcessDestination = blockTrees.SyncedTree.FindHeader(pivot, BlockTreeLookupOptions.None); @@ -72,7 +70,7 @@ public async Task Merge_Happy_path(long pivot, long headNumber, int options, int SyncPeerMock syncPeer = new(syncedTree, withReceipts, responseOptions, 16000000); PeerInfo peerInfo = new(syncPeer); await downloader.DownloadBlocks(peerInfo, new BlocksRequest(downloaderOptions), CancellationToken.None); - ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(Math.Max(0, insertedBeaconBlocks)); + ctx.BlockTree.BestSuggestedHeader.Number.Should().Be(Math.Max(0, insertedBeaconBlocks)); ctx.BlockTree.BestKnownNumber.Should().Be(Math.Max(0, insertedBeaconBlocks)); int receiptCount = 0; @@ -99,14 +97,13 @@ public async Task Can_reach_terminal_block(long headNumber, int options, int thr .InsertBeaconPivot(16) .InsertBeaconHeaders(4, 15) .InsertBeaconBlocks(17, headNumber, BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder.TotalDifficultyMode.Null); + BlockTree notSyncedTree = blockTrees.NotSyncedTree; BlockTree syncedTree = blockTrees.SyncedTree; - PostMergeContext ctx = new() - { - BlockTreeScenario = blockTrees, - }; + PostMergeContext ctx = new(); + ctx.BlockTreeScenario = blockTrees; DownloaderOptions downloaderOptions = (DownloaderOptions)options; - ctx.MergeConfig = new MergeConfig { TerminalTotalDifficulty = $"{ttd}" }; + ctx.MergeConfig = new MergeConfig() { TerminalTotalDifficulty = $"{ttd}" }; if (withBeaconPivot) ctx.BeaconPivot.EnsurePivot(blockTrees.SyncedTree.FindHeader(16, BlockTreeLookupOptions.None)); @@ -137,13 +134,11 @@ public async Task IfNoBeaconPivot_thenStopAtPoS(long headNumber, int options, in BlockTree notSyncedTree = blockTrees.NotSyncedTree; BlockTree syncedTree = blockTrees.SyncedTree; - PostMergeContext ctx = new() - { - BlockTreeScenario = blockTrees, - }; + PostMergeContext ctx = new(); + ctx.BlockTreeScenario = blockTrees; DownloaderOptions downloaderOptions = (DownloaderOptions)options; - ctx.MergeConfig = new MergeConfig { TerminalTotalDifficulty = $"{ttd}" }; + ctx.MergeConfig = new MergeConfig() { TerminalTotalDifficulty = $"{ttd}" }; if (withBeaconPivot) ctx.BeaconPivot.EnsurePivot(blockTrees.SyncedTree.FindHeader(16, BlockTreeLookupOptions.None)); @@ -166,10 +161,8 @@ public async Task WillSkipBlocksToIgnore(long pivot, long headNumber, int blocks .InsertBeaconHeaders(4, pivot - 1); BlockTree syncedTree = blockTrees.SyncedTree; - PostMergeContext ctx = new() - { - BlockTreeScenario = blockTrees, - }; + PostMergeContext ctx = new(); + ctx.BlockTreeScenario = blockTrees; ctx.BeaconPivot.EnsurePivot(blockTrees.SyncedTree.FindHeader(pivot, BlockTreeLookupOptions.None)); ctx.BeaconPivot.ProcessDestination = blockTrees.SyncedTree.FindHeader(pivot, BlockTreeLookupOptions.None); @@ -201,13 +194,11 @@ public async Task Recalculate_header_total_difficulty() .InsertOtherChainToMain(notSyncedTree, 1, 3) // Need to have the header inserted to LRU which mean we need to move the head forward .InsertBeaconHeaders(1, 3, tdMode: BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder.TotalDifficultyMode.Null); - PostMergeContext ctx = new() - { - BlockTreeScenario = blockTrees, - MergeConfig = new MergeConfig { TerminalTotalDifficulty = $"{ttd}" }, - }; + PostMergeContext ctx = new(); + ctx.BlockTreeScenario = blockTrees; + ctx.MergeConfig = new MergeConfig() { TerminalTotalDifficulty = $"{ttd}" }; - BlockHeader lastHeader = syncedTree.FindHeader(3, BlockTreeLookupOptions.None)!; + BlockHeader lastHeader = syncedTree.FindHeader(3, BlockTreeLookupOptions.None); // Because the FindHeader recalculated the TD. lastHeader.TotalDifficulty = 0; @@ -230,14 +221,14 @@ public async Task Recalculate_header_total_difficulty() Block? lastBestSuggestedBlock = null; - notSyncedTree.NewBestSuggestedBlock += (_, args) => + notSyncedTree.NewBestSuggestedBlock += (sender, args) => { lastBestSuggestedBlock = args.Block; }; await downloader.DownloadBlocks(peerInfo, new BlocksRequest(DownloaderOptions.Process | DownloaderOptions.WithBodies | DownloaderOptions.WithReceipts), CancellationToken.None); - lastBestSuggestedBlock!.Hash.Should().Be(lastHeader.Hash!); + lastBestSuggestedBlock.Hash.Should().Be(lastHeader.Hash); lastBestSuggestedBlock.TotalDifficulty.Should().NotBeEquivalentTo(UInt256.Zero); } @@ -248,18 +239,16 @@ public async Task Does_not_deadlock_on_replace_peer() .GoesLikeThis() .WithBlockTrees(0, 4) .InsertBeaconPivot(3); - PostMergeContext ctx = new() - { - MergeConfig = new MergeConfig { TerminalTotalDifficulty = "0" }, - BlockTreeScenario = blockTrees, - }; + PostMergeContext ctx = new(); + ctx.MergeConfig = new MergeConfig() { TerminalTotalDifficulty = "0" }; + ctx.BlockTreeScenario = blockTrees; ctx.BeaconPivot.EnsurePivot(blockTrees.SyncedTree.FindHeader(3, BlockTreeLookupOptions.None)); ManualResetEventSlim chainLevelHelperBlocker = new ManualResetEventSlim(false); IChainLevelHelper chainLevelHelper = Substitute.For(); chainLevelHelper - .When(clh => clh.GetNextHeaders(Arg.Any(), Arg.Any())) - .Do(_ => + .When((clh) => clh.GetNextHeaders(Arg.Any(), Arg.Any())) + .Do((args) => { chainLevelHelperBlocker.Wait(); }); @@ -286,7 +275,7 @@ public async Task Does_not_deadlock_on_replace_peer() CancellationTokenSource cts = new CancellationTokenSource(); - Task _ = ctx.Dispatcher.Start(cts.Token); + Task ignored = ctx.Dispatcher.Start(cts.Token); await Task.Delay(TimeSpan.FromMilliseconds(100)); // Feed should activate and allocate the first peer @@ -318,7 +307,7 @@ public async Task Does_not_deadlock_on_replace_peer() } [Test] - public void No_old_bodies_and_receipts() + public async Task No_old_bodies_and_receipts() { BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder blockTrees = BlockTreeTests.BlockTreeTestScenario .GoesLikeThis() @@ -326,10 +315,8 @@ public void No_old_bodies_and_receipts() .InsertBeaconPivot(64) .InsertBeaconHeaders(4, 128); BlockTree syncedTree = blockTrees.SyncedTree; - PostMergeContext ctx = new() - { - BlockTreeScenario = blockTrees, - }; + PostMergeContext ctx = new(); + ctx.BlockTreeScenario = blockTrees; ctx.Feed = new FastSyncFeed(ctx.SyncModeSelector, new SyncConfig @@ -337,7 +324,7 @@ public void No_old_bodies_and_receipts() NonValidatorNode = true, DownloadBodiesInFastSync = false, DownloadReceiptsInFastSync = false - }, LimboLogs.Instance)!; + }, LimboLogs.Instance); ctx.BeaconPivot.EnsurePivot(blockTrees.SyncedTree.FindHeader(64, BlockTreeLookupOptions.None)); @@ -359,7 +346,7 @@ public void No_old_bodies_and_receipts() ctx.Feed.Activate(); CancellationTokenSource cts = new(); - Task _ = ctx.Dispatcher.Start(cts.Token); + ctx.Dispatcher.Start(cts.Token); Assert.That( () => ctx.BlockTree.BestKnownNumber, @@ -402,15 +389,15 @@ public async Task BlockDownloader_works_correctly_with_withdrawals(int options) .Returns(async ci => await syncPeerInternal.GetReceipts(ci.ArgAt>(0), ci.ArgAt(1))); - syncPeer.TotalDifficulty.Returns(_ => syncPeerInternal.TotalDifficulty); - syncPeer.HeadHash.Returns(_ => syncPeerInternal.HeadHash); - syncPeer.HeadNumber.Returns(_ => syncPeerInternal.HeadNumber); + syncPeer.TotalDifficulty.Returns(ci => syncPeerInternal.TotalDifficulty); + syncPeer.HeadHash.Returns(ci => syncPeerInternal.HeadHash); + syncPeer.HeadNumber.Returns(ci => syncPeerInternal.HeadNumber); PeerInfo peerInfo = new(syncPeer); int threshold = 2; await downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.None, threshold), CancellationToken.None); - ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(Math.Max(0, Math.Min(headNumber, headNumber - threshold))); + ctx.BlockTree.BestSuggestedHeader.Number.Should().Be(Math.Max(0, Math.Min(headNumber, headNumber - threshold))); syncPeerInternal.ExtendTree(chainLength * 2); Func action = async () => await downloader.DownloadBlocks(peerInfo, new BlocksRequest(downloaderOptions), CancellationToken.None); @@ -422,7 +409,7 @@ class PostMergeContext : Context { protected override ISpecProvider SpecProvider => _specProvider ??= new MainnetSpecProvider(); // PoSSwitcher changes TTD, so can't use MainnetSpecProvider.Instance - private BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder? _blockTreeScenario; + private BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder? _blockTreeScenario = null; public BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder BlockTreeScenario { @@ -434,22 +421,21 @@ public BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder BlockTreeScenario public override IBlockTree BlockTree => _blockTreeScenario?.NotSyncedTree ?? base.BlockTree; - private MemDb? _metadataDb; - private MemDb MetadataDb => (_metadataDb ?? _blockTreeScenario?.NotSyncedTreeBuilder.MetadataDb) ?? (_metadataDb ??= new MemDb()); + private MemDb? _metadataDb = null; + private MemDb MetadataDb => (_metadataDb ?? _blockTreeScenario?.NotSyncedTreeBuilder?.MetadataDb) ?? (_metadataDb ??= new MemDb()); - private MergeConfig? _mergeConfig; + private MergeConfig _mergeConfig; public MergeConfig MergeConfig { - get => _mergeConfig ??= new MergeConfig - { TerminalTotalDifficulty = "58750000000000000000000" }; // Main block downloader test assume pre-merge + get => _mergeConfig ??= new MergeConfig() { TerminalTotalDifficulty = "58750000000000000000000" }; // Main block downloader test assume pre-merge set => _mergeConfig = value; } - private BeaconPivot? _beaconPivot; + private BeaconPivot? _beaconPivot = null; public BeaconPivot BeaconPivot => _beaconPivot ??= new(new SyncConfig(), MetadataDb, BlockTree, LimboLogs.Instance); - private PoSSwitcher? _posSwitcher; + private PoSSwitcher? _posSwitcher = null; public PoSSwitcher PosSwitcher => _posSwitcher ??= new( MergeConfig, @@ -462,7 +448,7 @@ public MergeConfig MergeConfig protected override IBetterPeerStrategy BetterPeerStrategy => _betterPeerStrategy ??= new MergeBetterPeerStrategy(new TotalDifficultyBetterPeerStrategy(LimboLogs.Instance), PosSwitcher, BeaconPivot, LimboLogs.Instance); - private IChainLevelHelper? _chainLevelHelper; + private IChainLevelHelper? _chainLevelHelper = null; public IChainLevelHelper ChainLevelHelper { diff --git a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs index 37157f43f0f..f0fc4425af8 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs @@ -84,12 +84,12 @@ public async Task Happy_path(long headNumber, int options, int threshold) await downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.None, threshold), CancellationToken.None); - ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(Math.Max(0, Math.Min(headNumber, headNumber - threshold))); + ctx.BlockTree!.BestSuggestedHeader!.Number.Should().Be(Math.Max(0, Math.Min(headNumber, headNumber - threshold))); syncPeer.ExtendTree(chainLength * 2); await downloader.DownloadBlocks(peerInfo, new BlocksRequest(downloaderOptions), CancellationToken.None); - ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(Math.Max(0, peerInfo.HeadNumber)); - ctx.BlockTree.IsMainChain(ctx.BlockTree.BestSuggestedHeader!.Hash!).Should().Be(downloaderOptions != DownloaderOptions.Process); + ctx.BlockTree!.BestSuggestedHeader!.Number.Should().Be(Math.Max(0, peerInfo.HeadNumber)); + ctx.BlockTree.IsMainChain(ctx.BlockTree!.BestSuggestedHeader!.Hash!).Should().Be(downloaderOptions != DownloaderOptions.Process); int receiptCount = 0; for (int i = (int)Math.Max(0, headNumber - threshold); i < peerInfo.HeadNumber; i++) @@ -106,10 +106,8 @@ public async Task Happy_path(long headNumber, int options, int threshold) [Test] public async Task Ancestor_lookup_simple() { - Context ctx = new() - { - BlockTree = Build.A.BlockTree().OfChainLength(1024).TestObject, - }; + Context ctx = new(); + ctx.BlockTree = Build.A.BlockTree().OfChainLength(1024).TestObject; BlockDownloader downloader = ctx.BlockDownloader; Response blockResponseOptions = Response.AllCorrect; @@ -117,7 +115,7 @@ public async Task Ancestor_lookup_simple() PeerInfo peerInfo = new(syncPeer); - Block block1024 = Build.A.Block.WithParent(ctx.BlockTree.Head!).WithDifficulty(ctx.BlockTree.Head!.Difficulty + 1).TestObject; + Block block1024 = Build.A.Block.WithParent(ctx.BlockTree.Head).WithDifficulty(ctx.BlockTree.Head.Difficulty + 1).TestObject; Block block1025 = Build.A.Block.WithParent(block1024).WithDifficulty(block1024.Difficulty + 1).TestObject; Block block1026 = Build.A.Block.WithParent(block1025).WithDifficulty(block1025.Difficulty + 1).TestObject; ctx.BlockTree.SuggestBlock(block1024); @@ -126,28 +124,26 @@ public async Task Ancestor_lookup_simple() for (int i = 0; i < 1023; i++) { - Assert.That(syncPeer.BlockTree.FindBlock(i, BlockTreeLookupOptions.None)!.Hash, Is.EqualTo(ctx.BlockTree.FindBlock(i, BlockTreeLookupOptions.None)!.Hash), i.ToString()); + Assert.That(syncPeer.BlockTree.FindBlock(i, BlockTreeLookupOptions.None).Hash, Is.EqualTo(ctx.BlockTree.FindBlock(i, BlockTreeLookupOptions.None).Hash), i.ToString()); } await downloader.DownloadBlocks(peerInfo, new BlocksRequest(DownloaderOptions.WithReceipts, 0), CancellationToken.None); - ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(peerInfo.HeadNumber); + ctx.BlockTree.BestSuggestedHeader.Number.Should().Be(peerInfo.HeadNumber); ctx.BlockTree.IsMainChain(ctx.BlockTree.BestSuggestedHeader.GetOrCalculateHash()).Should().Be(true); } [Test] public async Task Ancestor_lookup_headers() { - Context ctx = new() - { - BlockTree = Build.A.BlockTree().OfChainLength(1024).TestObject, - }; + Context ctx = new(); + ctx.BlockTree = Build.A.BlockTree().OfChainLength(1024).TestObject; BlockDownloader downloader = ctx.BlockDownloader; Response responseOptions = Response.AllCorrect; SyncPeerMock syncPeer = new(2048 + 1, false, responseOptions); PeerInfo peerInfo = new(syncPeer); - Block block1024 = Build.A.Block.WithParent(ctx.BlockTree.Head!).WithDifficulty(ctx.BlockTree.Head!.Difficulty + 1).TestObject; + Block block1024 = Build.A.Block.WithParent(ctx.BlockTree.Head).WithDifficulty(ctx.BlockTree.Head.Difficulty + 1).TestObject; Block block1025 = Build.A.Block.WithParent(block1024).WithDifficulty(block1024.Difficulty + 1).TestObject; Block block1026 = Build.A.Block.WithParent(block1025).WithDifficulty(block1025.Difficulty + 1).TestObject; ctx.BlockTree.SuggestBlock(block1024); @@ -156,20 +152,18 @@ public async Task Ancestor_lookup_headers() for (int i = 0; i < 1023; i++) { - Assert.That(syncPeer.BlockTree.FindBlock(i, BlockTreeLookupOptions.None)!.Hash, Is.EqualTo(ctx.BlockTree.FindBlock(i, BlockTreeLookupOptions.None)!.Hash), i.ToString()); + Assert.That(syncPeer.BlockTree.FindBlock(i, BlockTreeLookupOptions.None).Hash, Is.EqualTo(ctx.BlockTree.FindBlock(i, BlockTreeLookupOptions.None).Hash), i.ToString()); } await downloader.DownloadHeaders(peerInfo, new BlocksRequest(), CancellationToken.None); - ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(peerInfo.HeadNumber); + ctx.BlockTree.BestSuggestedHeader.Number.Should().Be(peerInfo.HeadNumber); } [Test] public void Ancestor_failure() { - Context ctx = new() - { - BlockTree = Build.A.BlockTree().OfChainLength(2048 + 1).TestObject, - }; + Context ctx = new(); + ctx.BlockTree = Build.A.BlockTree().OfChainLength(2048 + 1).TestObject; BlockDownloader downloader = ctx.BlockDownloader; Response blockResponseOptions = Response.AllCorrect; @@ -178,16 +172,14 @@ public void Ancestor_failure() PeerInfo peerInfo = new(syncPeer); Assert.ThrowsAsync(() => downloader.DownloadHeaders(peerInfo, new BlocksRequest(), CancellationToken.None)); - ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(2048); + ctx.BlockTree.BestSuggestedHeader.Number.Should().Be(2048); } [Test] public void Ancestor_failure_blocks() { - Context ctx = new() - { - BlockTree = Build.A.BlockTree().OfChainLength(2048 + 1).TestObject, - }; + Context ctx = new(); + ctx.BlockTree = Build.A.BlockTree().OfChainLength(2048 + 1).TestObject; BlockDownloader downloader = ctx.BlockDownloader; Response responseOptions = Response.AllCorrect; @@ -196,7 +188,7 @@ public void Ancestor_failure_blocks() PeerInfo peerInfo = new(syncPeer); Assert.ThrowsAsync(() => downloader.DownloadBlocks(peerInfo, new BlocksRequest(), CancellationToken.None)); - ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(2048); + ctx.BlockTree.BestSuggestedHeader.Number.Should().Be(2048); } [TestCase(32, true)] @@ -225,12 +217,12 @@ public async Task Can_sync_with_peer_when_it_times_out_on_full_batch(int ignored PeerInfo peerInfo = new(syncPeer); - await downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.WithBodies, ignoredBlocks), CancellationToken.None).ContinueWith(_ => { }); + await downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.WithBodies, ignoredBlocks), CancellationToken.None).ContinueWith(t => { }); await downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.WithBodies, ignoredBlocks), CancellationToken.None); - Assert.That(ctx.BlockTree.BestSuggestedHeader!.Number, Is.EqualTo(Math.Max(0, peerInfo.HeadNumber - ignoredBlocks))); + Assert.That(ctx.BlockTree.BestSuggestedHeader.Number, Is.EqualTo(Math.Max(0, peerInfo.HeadNumber - ignoredBlocks))); syncPeer.HeadNumber.Returns((int)Math.Ceiling(SyncBatchSize.Max * SyncBatchSize.AdjustmentFactor) + ignoredBlocks); - await downloader.DownloadBlocks(peerInfo, new BlocksRequest(), CancellationToken.None).ContinueWith(continuationAction: _ => { }); + await downloader.DownloadBlocks(peerInfo, new BlocksRequest(), CancellationToken.None).ContinueWith(t => { }); await downloader.DownloadBlocks(peerInfo, new BlocksRequest(), CancellationToken.None); Assert.That(ctx.BlockTree.BestSuggestedHeader.Number, Is.EqualTo(Math.Max(0, peerInfo.HeadNumber))); } @@ -263,17 +255,14 @@ public async Task Can_sync_partially_when_only_some_bodies_is_available(int bloc if (blockHashes.Count == 0) { - return new OwnedBlockBodies(Array.Empty()); + return Array.Empty(); } - BlockBody?[] response = ctx.ResponseBuilder - .BuildBlocksResponse(blockHashes, Response.AllCorrect | Response.WithTransactions & ~Response.AllKnown) - .Result - .Bodies!; + BlockBody[] response = ctx.ResponseBuilder.BuildBlocksResponse(blockHashes, Response.AllCorrect | Response.WithTransactions & ~Response.AllKnown).Result; if (response.Length < minResponseLength) { - BlockBody?[] nullPaddedResponse = new BlockBody[minResponseLength]; + BlockBody[] nullPaddedResponse = new BlockBody[minResponseLength]; for (int i = 0; i < response.Length; i++) { nullPaddedResponse[i] = response[i]; @@ -281,7 +270,7 @@ public async Task Can_sync_partially_when_only_some_bodies_is_available(int bloc response = nullPaddedResponse; } - return new OwnedBlockBodies(response); + return response; }); syncPeer.TotalDifficulty.Returns(UInt256.MaxValue); @@ -289,8 +278,8 @@ public async Task Can_sync_partially_when_only_some_bodies_is_available(int bloc PeerInfo peerInfo = new(syncPeer); - ctx.BlockTree.BestSuggestedBody!.Number.Should().Be(0); - await downloader.DownloadBlocks(peerInfo, new BlocksRequest(DownloaderOptions.Process), CancellationToken.None).ContinueWith(_ => { }); + ctx.BlockTree.BestSuggestedBody.Number.Should().Be(0); + await downloader.DownloadBlocks(peerInfo, new BlocksRequest(DownloaderOptions.Process), CancellationToken.None).ContinueWith(t => { }); ctx.BlockTree.BestSuggestedBody.Number.Should().Be(availableBlock); } @@ -326,7 +315,7 @@ public async Task Peer_only_advertise_one_header() ISyncPeer syncPeer = Substitute.For(); syncPeer.GetBlockHeaders(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(_ => ctx.ResponseBuilder.BuildHeaderResponse(0, 1, Response.AllCorrect)); + .Returns(ci => ctx.ResponseBuilder.BuildHeaderResponse(0, 1, Response.AllCorrect)); PeerInfo peerInfo = new(syncPeer); syncPeer.TotalDifficulty.Returns(UInt256.MaxValue); @@ -358,7 +347,7 @@ public async Task Peer_sends_just_one_item_when_advertising_more_blocks_but_no_b Task task = downloader.DownloadBlocks(peerInfo, new BlocksRequest(), CancellationToken.None); await task.ContinueWith(t => Assert.False(t.IsFaulted)); - Assert.That(ctx.BlockTree.BestSuggestedHeader!.Number, Is.EqualTo(headNumber)); + Assert.That(ctx.BlockTree.BestSuggestedHeader.Number, Is.EqualTo(headNumber)); } [Test] @@ -393,10 +382,8 @@ public async Task Throws_on_inconsistent_batch() [Test] public async Task Throws_on_invalid_seal() { - Context ctx = new() - { - SealValidator = Always.Invalid, - }; + Context ctx = new(); + ctx.SealValidator = Always.Invalid; BlockDownloader downloader = ctx.BlockDownloader; ISyncPeer syncPeer = Substitute.For(); @@ -414,10 +401,8 @@ public async Task Throws_on_invalid_seal() [Test] public async Task Throws_on_invalid_header() { - Context ctx = new() - { - BlockValidator = Always.Invalid, - }; + Context ctx = new(); + ctx.BlockValidator = Always.Invalid; BlockDownloader downloader = ctx.BlockDownloader; ISyncPeer syncPeer = Substitute.For(); @@ -449,6 +434,11 @@ public bool ValidateSeal(BlockHeader header, bool force) private class SlowHeaderValidator : IBlockValidator { + public bool ValidateHash(BlockHeader header) + { + Thread.Sleep(1000); + return true; + } public bool Validate(BlockHeader header, BlockHeader? parent, bool isUncle) { @@ -480,23 +470,14 @@ public bool ValidateWithdrawals(Block block, out string? error) error = string.Empty; return true; } - - public bool ValidateOrphanedBlock(Block block, out string? error) - { - Thread.Sleep(1000); - error = null; - return true; - } } [Test, MaxTime(7000)] [Ignore("Fails OneLoggerLogManager Travis only")] public async Task Can_cancel_seal_validation() { - Context ctx = new() - { - SealValidator = new SlowSealValidator(), - }; + Context ctx = new(); + ctx.SealValidator = new SlowSealValidator(); BlockDownloader downloader = ctx.BlockDownloader; ISyncPeer syncPeer = Substitute.For(); @@ -515,6 +496,7 @@ public async Task Can_cancel_seal_validation() Task task = downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.WithBodies, 0), cancellation.Token); await task.ContinueWith(t => Assert.True(t.IsCanceled, $"headers {t.Status}")); + // peerInfo.HeadNumber = 2000; syncPeer.HeadNumber.Returns(2000); cancellation = new CancellationTokenSource(); cancellation.CancelAfter(1000); @@ -525,10 +507,8 @@ public async Task Can_cancel_seal_validation() [Test, MaxTime(15000)] public async Task Can_cancel_adding_headers() { - Context ctx = new() - { - BlockValidator = new SlowHeaderValidator(), - }; + Context ctx = new(); + ctx.BlockValidator = new SlowHeaderValidator(); BlockDownloader downloader = ctx.BlockDownloader; ISyncPeer syncPeer = Substitute.For(); @@ -561,10 +541,8 @@ public async Task Validate_always_the_last_seal_and_random_seal_in_the_package() { ISealValidator sealValidator = Substitute.For(); sealValidator.ValidateSeal(Arg.Any(), Arg.Any()).Returns(true); - Context ctx = new() - { - SealValidator = sealValidator, - }; + Context ctx = new(); + ctx.SealValidator = sealValidator; BlockDownloader downloader = ctx.BlockDownloader; BlockHeader[] blockHeaders = await ctx.ResponseBuilder.BuildHeaderResponse(0, 512, Response.AllCorrect); @@ -586,30 +564,29 @@ public async Task Validate_always_the_last_seal_and_random_seal_in_the_package() private class ThrowingPeer : ISyncPeer { - public ThrowingPeer(long number, UInt256? totalDiff, Keccak? headHash = null) + public ThrowingPeer(long number, UInt256 totalDiff, Keccak headHash = null) { HeadNumber = number; - TotalDifficulty = totalDiff ?? UInt256.MaxValue; + TotalDifficulty = totalDiff; HeadHash = headHash ?? Keccak.Zero; } - public string Name => "Throwing"; + public Node Node { get; } public string ClientId => "EX peer"; - public Node Node { get; } = null!; - public string ProtocolCode { get; } = null!; - public byte ProtocolVersion { get; } = default; public Keccak HeadHash { get; set; } public long HeadNumber { get; set; } - public UInt256 TotalDifficulty { get; set; } + public UInt256 TotalDifficulty { get; set; } = UInt256.MaxValue; public bool IsInitialized { get; set; } public bool IsPriority { get; set; } + public byte ProtocolVersion { get; } + public string ProtocolCode { get; } - public void Disconnect(DisconnectReason reason, string details) + public void Disconnect(InitiateDisconnectReason reason, string details) { throw new NotImplementedException(); } - public Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) + public Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) { throw new NotImplementedException(); } @@ -683,11 +660,12 @@ public async Task Throws_on_block_task_exception() ISyncPeer syncPeer = Substitute.For(); syncPeer.TotalDifficulty.Returns(UInt256.MaxValue); + Task? buildHeadersResponse = null; syncPeer.GetBlockHeaders(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(ci => ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => buildHeadersResponse = ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); syncPeer.GetBlockBodies(Arg.Any>(), Arg.Any()) - .Returns(Task.FromException(new TimeoutException())); + .Returns(Task.FromException(new TimeoutException())); syncPeer.GetReceipts(Arg.Any>(), Arg.Any()) .Returns(ci => ctx.ResponseBuilder.BuildReceiptsResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); @@ -714,11 +692,13 @@ public async Task Throws_on_receipt_task_exception_when_downloading_receipts(int ISyncPeer syncPeer = Substitute.For(); syncPeer.TotalDifficulty.Returns(UInt256.MaxValue); + Task? buildHeadersResponse = null; syncPeer.GetBlockHeaders(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(ci => ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => buildHeadersResponse = ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); + Task? buildBlocksResponse = null; syncPeer.GetBlockBodies(Arg.Any>(), Arg.Any()) - .Returns(ci => ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => buildBlocksResponse = ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); syncPeer.GetReceipts(Arg.Any>(), Arg.Any()) .Returns(Task.FromException(new TimeoutException())); @@ -728,6 +708,7 @@ public async Task Throws_on_receipt_task_exception_when_downloading_receipts(int await downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.WithBodies, 0), CancellationToken.None); syncPeer.HeadNumber.Returns(2); + // peerInfo.HeadNumber *= 2; Func action = async () => await downloader.DownloadBlocks(peerInfo, new BlocksRequest(downloaderOptions), CancellationToken.None); if (shouldThrow) @@ -777,15 +758,15 @@ public async Task Throws_on_null_receipt_downloaded(int options, bool shouldThro return receipts; }); - syncPeer.TotalDifficulty.Returns(_ => syncPeerInternal.TotalDifficulty); - syncPeer.HeadHash.Returns(_ => syncPeerInternal.HeadHash); - syncPeer.HeadNumber.Returns(_ => syncPeerInternal.HeadNumber); + syncPeer.TotalDifficulty.Returns(ci => syncPeerInternal.TotalDifficulty); + syncPeer.HeadHash.Returns(ci => syncPeerInternal.HeadHash); + syncPeer.HeadNumber.Returns(ci => syncPeerInternal.HeadNumber); PeerInfo peerInfo = new(syncPeer); int threshold = 2; await downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.None, threshold), CancellationToken.None); - ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(Math.Max(0, Math.Min(headNumber, headNumber - threshold))); + ctx.BlockTree.BestSuggestedHeader.Number.Should().Be(Math.Max(0, Math.Min(headNumber, headNumber - threshold))); syncPeerInternal.ExtendTree(chainLength * 2); Func action = async () => await downloader.DownloadBlocks(peerInfo, new BlocksRequest(downloaderOptions), CancellationToken.None); @@ -811,11 +792,13 @@ public async Task Throws_on_block_bodies_count_higher_than_receipts_list_count(i ISyncPeer syncPeer = Substitute.For(); syncPeer.TotalDifficulty.Returns(UInt256.MaxValue); + Task? buildHeadersResponse = null; syncPeer.GetBlockHeaders(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(ci => ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => buildHeadersResponse = ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); + Task? buildBlocksResponse = null; syncPeer.GetBlockBodies(Arg.Any>(), Arg.Any()) - .Returns(ci => ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => buildBlocksResponse = ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); syncPeer.GetReceipts(Arg.Any>(), Arg.Any()) .Returns(ci => ctx.ResponseBuilder.BuildReceiptsResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions).Result.Skip(1).ToArray()); @@ -839,11 +822,13 @@ public async Task Does_throw_on_transaction_count_different_than_receipts_count_ ISyncPeer syncPeer = Substitute.For(); syncPeer.TotalDifficulty.Returns(UInt256.MaxValue); + Task? buildHeadersResponse = null; syncPeer.GetBlockHeaders(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(ci => ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => buildHeadersResponse = ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); + Task? buildBlocksResponse = null; syncPeer.GetBlockBodies(Arg.Any>(), Arg.Any()) - .Returns(ci => ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => buildBlocksResponse = ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); syncPeer.GetReceipts(Arg.Any>(), Arg.Any()) .Returns(ci => ctx.ResponseBuilder.BuildReceiptsResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions) @@ -869,11 +854,13 @@ public async Task Throws_on_incorrect_receipts_root(int threshold) ISyncPeer syncPeer = Substitute.For(); syncPeer.TotalDifficulty.Returns(UInt256.MaxValue); + Task? buildHeadersResponse = null; syncPeer.GetBlockHeaders(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(ci => ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.IncorrectReceiptRoot)); + .Returns(ci => buildHeadersResponse = ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.IncorrectReceiptRoot)); + Task? buildBlocksResponse = null; syncPeer.GetBlockBodies(Arg.Any>(), Arg.Any()) - .Returns(ci => ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => buildBlocksResponse = ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); syncPeer.GetReceipts(Arg.Any>(), Arg.Any()) .Returns(ci => ctx.ResponseBuilder.BuildReceiptsResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions).Result); @@ -903,13 +890,13 @@ private enum Response private class Context { - private readonly Block _genesis = Build.A.Block.Genesis.TestObject; - private readonly MemDb _stateDb = new(); - private readonly MemDb _blockInfoDb = new(); - private readonly SyncConfig _syncConfig = new(); + private Block genesis = Build.A.Block.Genesis.TestObject; + private MemDb _stateDb = new(); + private MemDb _blockInfoDb = new(); + private SyncConfig syncConfig = new(); private IBlockTree? _blockTree { get; set; } private Dictionary TestHeaderMapping { get; } - public InMemoryReceiptStorage ReceiptStorage { get; } = new(); + public InMemoryReceiptStorage ReceiptStorage = new(); private SyncBatchSize? _syncBatchSize; @@ -929,7 +916,7 @@ public virtual IBlockTree BlockTree if (_blockTree is null) { _blockTree = new BlockTree(new MemDb(), new MemDb(), _blockInfoDb, new ChainLevelInfoRepository(_blockInfoDb), SpecProvider, NullBloomStorage.Instance, LimboLogs.Instance); - _blockTree.SuggestBlock(_genesis); + _blockTree.SuggestBlock(genesis); } return _blockTree; @@ -940,10 +927,10 @@ public virtual IBlockTree BlockTree } } - private ISyncPeerPool? _peerPool; + private ISyncPeerPool _peerPool; public ISyncPeerPool PeerPool => _peerPool ??= Substitute.For(); - private ResponseBuilder? _responseBuilder; + private ResponseBuilder? _responseBuilder = null; public ResponseBuilder ResponseBuilder => _responseBuilder ??= new ResponseBuilder(BlockTree, TestHeaderMapping); @@ -954,25 +941,25 @@ public virtual IBlockTree BlockTree private ISyncProgressResolver? _syncProgressResolver; - private ISyncProgressResolver SyncProgressResolver => _syncProgressResolver ??= + private ISyncProgressResolver? SyncProgressResolver => _syncProgressResolver ??= new SyncProgressResolver( BlockTree, ReceiptStorage, _stateDb, new TrieStore(_stateDb, LimboLogs.Instance), ProgressTracker, - _syncConfig, + syncConfig, LimboLogs.Instance); - private MultiSyncModeSelector? _syncModeSelector; + private MultiSyncModeSelector _syncModeSelector; - protected IBetterPeerStrategy? _betterPeerStrategy; + protected IBetterPeerStrategy _betterPeerStrategy; protected virtual IBetterPeerStrategy BetterPeerStrategy => _betterPeerStrategy ??= new TotalDifficultyBetterPeerStrategy(LimboLogs.Instance); public ISyncModeSelector SyncModeSelector => _syncModeSelector ??= - new MultiSyncModeSelector(SyncProgressResolver, PeerPool, _syncConfig, No.BeaconSync, BetterPeerStrategy, LimboLogs.Instance); + new MultiSyncModeSelector(SyncProgressResolver, PeerPool, syncConfig, No.BeaconSync, BetterPeerStrategy, LimboLogs.Instance); private ActivatedSyncFeed? _feed; @@ -989,14 +976,14 @@ public ISealValidator SealValidator set => _sealValidator = value; } - private IBlockValidator? _blockValidator; + private IBlockValidator _blockValidator; public IBlockValidator BlockValidator { get => _blockValidator ??= Always.Valid; set => _blockValidator = value; } - private BlockDownloader? _blockDownloader; + private BlockDownloader _blockDownloader; public virtual BlockDownloader BlockDownloader => _blockDownloader ??= new BlockDownloader( Feed, PeerPool, @@ -1011,10 +998,10 @@ public IBlockValidator BlockValidator SyncBatchSize ); - private SyncDispatcher? _dispatcher; + private SyncDispatcher _dispatcher; public SyncDispatcher Dispatcher => _dispatcher ??= new SyncDispatcher( 0, - Feed!, + Feed, BlockDownloader, PeerPool, PeerAllocationStrategy, @@ -1026,14 +1013,15 @@ public IBlockValidator BlockValidator protected virtual IPeerAllocationStrategyFactory PeerAllocationStrategy => _peerAllocationStrategy ??= new BlocksSyncPeerAllocationStrategyFactory(); - public Context() + public Context(BlockTree? blockTree = null) { - TestHeaderMapping = new Dictionary + if (blockTree != null) { - { - 0, _genesis.Hash! - }, - }; + BlockTree = blockTree; + } + + TestHeaderMapping = new Dictionary(); + TestHeaderMapping.Add(0, genesis.Hash!); } } @@ -1043,19 +1031,19 @@ private class SyncPeerMock : ISyncPeer private readonly bool _withWithdrawals; private readonly BlockHeadersMessageSerializer _headersSerializer = new(); private readonly BlockBodiesMessageSerializer _bodiesSerializer = new(); - private readonly ReceiptsMessageSerializer _receiptsSerializer = new(MainnetSpecProvider.Instance); - private readonly Response _flags; + private readonly ReceiptsMessageSerializer _receiptsSerializer = new(RopstenSpecProvider.Instance); - public BlockTree BlockTree { get; private set; } = null!; + private IDb _blockInfoDb = new MemDb(); + public BlockTree BlockTree { get; private set; } private IReceiptStorage _receiptStorage = new InMemoryReceiptStorage(); - public string Name => "Mock"; + public Response Flags { get; set; } public SyncPeerMock(long chainLength, bool withReceipts, Response flags, bool withWithdrawals = false) { _withReceipts = withReceipts; _withWithdrawals = withWithdrawals; - _flags = flags; + Flags = flags; BuildTree(chainLength, withReceipts); } @@ -1063,10 +1051,10 @@ public SyncPeerMock(BlockTree blockTree, bool withReceipts, Response flags, UInt { _withReceipts = withReceipts; _withWithdrawals = withWithdrawals; - _flags = flags; + Flags = flags; BlockTree = blockTree; - HeadNumber = BlockTree.Head!.Number; - HeadHash = BlockTree.HeadHash!; + HeadNumber = BlockTree.Head.Number; + HeadHash = BlockTree.HeadHash; TotalDifficulty = peerTotalDifficulty; } @@ -1082,8 +1070,8 @@ private void BuildTree(long chainLength, bool withReceipts) builder = builder.OfChainLength((int)chainLength, 0, 0, _withWithdrawals); BlockTree = builder.TestObject; - HeadNumber = BlockTree.Head!.Number; - HeadHash = BlockTree.HeadHash!; + HeadNumber = BlockTree.Head.Number; + HeadHash = BlockTree.HeadHash; TotalDifficulty = BlockTree.Head.TotalDifficulty ?? 0; } @@ -1092,35 +1080,47 @@ public void ExtendTree(long newLength) BuildTree(newLength, _withReceipts); } - public Node Node { get; } = null!; - public string ClientId { get; } = null!; - public byte ProtocolVersion { get; } = default; - public string ProtocolCode { get; } = null!; - public Keccak HeadHash { get; set; } = null!; - public PublicKey Id => Node.Id; + public Node Node { get; } + public string ClientId { get; } + public Keccak HeadHash { get; set; } public long HeadNumber { get; set; } public UInt256 TotalDifficulty { get; set; } public bool IsInitialized { get; set; } public bool IsPriority { get; set; } + public byte ProtocolVersion { get; } + public string ProtocolCode { get; } - public async Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) + public void Disconnect(InitiateDisconnectReason reason, string details) { + throw new NotImplementedException(); + } + + public async Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) + { + bool consistent = Flags.HasFlag(Response.Consistent); + bool justFirst = Flags.HasFlag(Response.JustFirst); + bool allKnown = Flags.HasFlag(Response.AllKnown); + bool noBody = Flags.HasFlag(Response.NoBody); + BlockBody[] headers = new BlockBody[blockHashes.Count]; int i = 0; foreach (Keccak blockHash in blockHashes) { - headers[i++] = BlockTree.FindBlock(blockHash, BlockTreeLookupOptions.None)!.Body; + headers[i++] = BlockTree.FindBlock(blockHash, BlockTreeLookupOptions.None).Body; } BlockBodiesMessage message = new(headers); byte[] messageSerialized = _bodiesSerializer.Serialize(message); - return await Task.FromResult(_bodiesSerializer.Deserialize(messageSerialized).Bodies!); + return await Task.FromResult(_bodiesSerializer.Deserialize(messageSerialized).Bodies); } public async Task GetBlockHeaders(long number, int maxBlocks, int skip, CancellationToken token) { - bool justFirst = _flags.HasFlag(Response.JustFirst); - bool timeoutOnFullBatch = _flags.HasFlag(Response.TimeoutOnFullBatch); + bool consistent = Flags.HasFlag(Response.Consistent); + bool justFirst = Flags.HasFlag(Response.JustFirst); + bool allKnown = Flags.HasFlag(Response.AllKnown); + bool timeoutOnFullBatch = Flags.HasFlag(Response.TimeoutOnFullBatch); + bool noBody = Flags.HasFlag(Response.NoBody); if (timeoutOnFullBatch && number == SyncBatchSize.Max) { @@ -1130,7 +1130,7 @@ public async Task GetBlockHeaders(long number, int maxBlocks, int BlockHeader[] headers = new BlockHeader[maxBlocks]; for (int i = 0; i < (justFirst ? 1 : maxBlocks); i++) { - headers[i] = BlockTree.FindHeader(number + i, BlockTreeLookupOptions.None)!; + headers[i] = BlockTree.FindHeader(number + i, BlockTreeLookupOptions.None); } BlockHeadersMessage message = new(headers); @@ -1138,27 +1138,6 @@ public async Task GetBlockHeaders(long number, int maxBlocks, int return await Task.FromResult(_headersSerializer.Deserialize(messageSerialized).BlockHeaders); } - public async Task GetReceipts(IReadOnlyList blockHash, CancellationToken token) - { - TxReceipt[][] receipts = new TxReceipt[blockHash.Count][]; - int i = 0; - foreach (Keccak keccak in blockHash) - { - Block? block = BlockTree.FindBlock(keccak, BlockTreeLookupOptions.None); - TxReceipt[] blockReceipts = _receiptStorage.Get(block!); - receipts[i++] = blockReceipts; - } - - ReceiptsMessage message = new(receipts); - byte[] messageSerialized = _receiptsSerializer.Serialize(message); - return await Task.FromResult(_receiptsSerializer.Deserialize(messageSerialized).TxReceipts); - } - - public void Disconnect(DisconnectReason reason, string details) - { - throw new NotImplementedException(); - } - public Task GetBlockHeaders(Keccak startHash, int maxBlocks, int skip, CancellationToken token) { throw new NotImplementedException(); @@ -1174,11 +1153,29 @@ public void NotifyOfNewBlock(Block block, SendBlockMode mode) throw new NotImplementedException(); } + public PublicKey Id => Node.Id; + public void SendNewTransactions(IEnumerable txs, bool sendFullTx) { throw new NotImplementedException(); } + public async Task GetReceipts(IReadOnlyList blockHash, CancellationToken token) + { + TxReceipt[][] receipts = new TxReceipt[blockHash.Count][]; + int i = 0; + foreach (Keccak keccak in blockHash) + { + Block? block = BlockTree.FindBlock(keccak, BlockTreeLookupOptions.None); + TxReceipt[] blockReceipts = _receiptStorage.Get(block!); + receipts[i++] = blockReceipts; + } + + ReceiptsMessage message = new(receipts); + byte[] messageSerialized = _receiptsSerializer.Serialize(message); + return await Task.FromResult(_receiptsSerializer.Deserialize(messageSerialized).TxReceipts); + } + public Task GetNodeData(IReadOnlyList hashes, CancellationToken token) { throw new NotImplementedException(); @@ -1197,7 +1194,7 @@ public bool TryGetSatelliteProtocol(string protocol, out T protocolHandler) w private class ResponseBuilder { - private readonly IBlockTree _blockTree; + private IBlockTree _blockTree; private readonly Dictionary _testHeaderMapping; public ResponseBuilder(IBlockTree blockTree, Dictionary testHeaderMapping) @@ -1219,7 +1216,7 @@ public async Task BuildHeaderResponse(long startNumber, int numbe throw new TimeoutException(); } - BlockHeader startBlock = _blockTree.FindHeader(_testHeaderMapping[startNumber], BlockTreeLookupOptions.None)!; + BlockHeader startBlock = _blockTree.FindHeader(_testHeaderMapping[startNumber], BlockTreeLookupOptions.None); BlockHeader[] headers = new BlockHeader[number]; headers[0] = startBlock; if (!justFirst) @@ -1245,13 +1242,13 @@ public async Task BuildHeaderResponse(long startNumber, int numbe _blockTree.SuggestHeader(headers[i]); } - _testHeaderMapping[startNumber + i] = headers[i].Hash!; + _testHeaderMapping[startNumber + i] = headers[i].Hash; } } foreach (BlockHeader header in headers) { - _headers[header.Hash!] = header; + _headers[header.Hash] = header; } BlockHeadersMessage message = new(headers); @@ -1261,11 +1258,12 @@ public async Task BuildHeaderResponse(long startNumber, int numbe private readonly BlockHeadersMessageSerializer _headersSerializer = new(); private readonly BlockBodiesMessageSerializer _bodiesSerializer = new(); - private readonly ReceiptsMessageSerializer _receiptsSerializer = new(MainnetSpecProvider.Instance); - private readonly Dictionary _headers = new(); - private readonly Dictionary _bodies = new(); + private readonly ReceiptsMessageSerializer _receiptsSerializer = new(RopstenSpecProvider.Instance); + + private Dictionary _headers = new(); + private Dictionary _bodies = new(); - public async Task BuildBlocksResponse(IList blockHashes, Response flags) + public async Task BuildBlocksResponse(IList blockHashes, Response flags) { bool consistent = flags.HasFlag(Response.Consistent); bool justFirst = flags.HasFlag(Response.JustFirst); @@ -1329,7 +1327,7 @@ Block BuildBlockForHeader(BlockHeader header, int txSeed) BlockBodiesMessage message = new(blockBodies); byte[] messageSerialized = _bodiesSerializer.Serialize(message); - return await Task.FromResult(_bodiesSerializer.Deserialize(messageSerialized).Bodies!); + return await Task.FromResult(_bodiesSerializer.Deserialize(messageSerialized).Bodies); } public async Task BuildReceiptsResponse(IList blockHashes, Response flags = Response.AllCorrect) @@ -1342,7 +1340,7 @@ Block BuildBlockForHeader(BlockHeader header, int txSeed) .Select(t => Build.A.Receipt .WithStatusCode(StatusCode.Success) .WithGasUsed(10) - .WithBloom(Bloom.Empty) + .WithBloom(Core.Bloom.Empty) .WithLogs(Build.A.LogEntry.WithAddress(t.SenderAddress!).WithTopics(TestItem.KeccakA).TestObject) .TestObject) .ToArray(); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/DbTuner/SyncDbTunerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/DbTuner/SyncDbTunerTests.cs index 54d7c7d401f..122f508268d 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/DbTuner/SyncDbTunerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/DbTuner/SyncDbTunerTests.cs @@ -5,6 +5,7 @@ using Nethermind.Db; using Nethermind.Synchronization.DbTuner; using Nethermind.Synchronization.FastBlocks; +using Nethermind.Synchronization.FastSync; using Nethermind.Synchronization.ParallelSync; using Nethermind.Synchronization.SnapSync; using NSubstitute; @@ -17,13 +18,14 @@ public class SyncDbTunerTests private ITunableDb.TuneType _tuneType = ITunableDb.TuneType.HeavyWrite; private ITunableDb.TuneType _blocksTuneType = ITunableDb.TuneType.AggressiveHeavyWrite; private SyncConfig _syncConfig = null!; - private ISyncFeed _snapSyncFeed = null!; - private ISyncFeed _bodiesSyncFeed = null!; - private ISyncFeed _receiptSyncFeed = null!; + private ISyncFeed? _snapSyncFeed; + private ISyncFeed? _bodiesSyncFeed; + private ISyncFeed? _receiptSyncFeed; private ITunableDb _stateDb = null!; private ITunableDb _codeDb = null!; private ITunableDb _blockDb = null!; private ITunableDb _receiptDb = null!; + private SyncDbTuner _tuner = null!; [SetUp] public void Setup() @@ -34,15 +36,15 @@ public void Setup() TuneDbMode = _tuneType, BlocksDbTuneDbMode = _blocksTuneType, }; - _snapSyncFeed = Substitute.For>(); - _bodiesSyncFeed = Substitute.For>(); - _receiptSyncFeed = Substitute.For>(); + _snapSyncFeed = Substitute.For?>(); + _bodiesSyncFeed = Substitute.For?>(); + _receiptSyncFeed = Substitute.For?>(); _stateDb = Substitute.For(); _codeDb = Substitute.For(); _blockDb = Substitute.For(); _receiptDb = Substitute.For(); - SyncDbTuner _ = new SyncDbTuner( + _tuner = new SyncDbTuner( _syncConfig, _snapSyncFeed, _bodiesSyncFeed, @@ -77,7 +79,7 @@ public void WhenReceiptsIsOn_TriggerReceiptsDbTune() TestFeedAndDbTune(_receiptSyncFeed, _receiptDb); } - private void TestFeedAndDbTune(ISyncFeed feed, ITunableDb db, ITunableDb.TuneType? tuneType = null) + public void TestFeedAndDbTune(ISyncFeed feed, ITunableDb db, ITunableDb.TuneType? tuneType = null) { feed.StateChanged += Raise.EventWith(new SyncFeedStateEventArgs(SyncFeedState.Active)); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ExitOnSyncCompleteTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/ExitOnSyncCompleteTests.cs deleted file mode 100644 index 62d0aac1aae..00000000000 --- a/src/Nethermind/Nethermind.Synchronization.Test/ExitOnSyncCompleteTests.cs +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Threading.Tasks; -using Nethermind.Config; -using Nethermind.Logging; -using Nethermind.Synchronization.ParallelSync; -using NSubstitute; -using NUnit.Framework; - -namespace Nethermind.Synchronization.Test; - -public class ExitOnSyncCompleteTests -{ - - [Test] - public async Task TestWillExit() - { - ISyncModeSelector syncMode = Substitute.For(); - IProcessExitSource exitSource = Substitute.For(); - TimeSpan exitConditionDuration = TimeSpan.FromMilliseconds(10); - - exitSource.WatchForExit(syncMode, LimboLogs.Instance, exitConditionDuration: exitConditionDuration); - - syncMode.Changed += Raise.EventWith(this, new SyncModeChangedEventArgs(SyncMode.All, SyncMode.WaitingForBlock)); - await Task.Delay(exitConditionDuration); - syncMode.Changed += Raise.EventWith(this, new SyncModeChangedEventArgs(SyncMode.All, SyncMode.WaitingForBlock)); - - exitSource.Received().Exit(0); - } - - [Test] - public async Task TestWillNotExitIfStillSyncing() - { - ISyncModeSelector syncMode = Substitute.For(); - IProcessExitSource exitSource = Substitute.For(); - TimeSpan exitConditionDuration = TimeSpan.FromMilliseconds(10); - - exitSource.WatchForExit(syncMode, LimboLogs.Instance, exitConditionDuration: exitConditionDuration); - - syncMode.Changed += Raise.EventWith(this, new SyncModeChangedEventArgs(SyncMode.All, SyncMode.WaitingForBlock)); - await Task.Delay(exitConditionDuration); - syncMode.Changed += Raise.EventWith(this, new SyncModeChangedEventArgs(SyncMode.All, SyncMode.FastBlocks)); - - exitSource.DidNotReceive().Exit(0); - } -} diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs index f0956ccf78b..34b89727bcb 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs @@ -2,10 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; using System.Linq; using System.Threading; -using System.Threading.Channels; using System.Threading.Tasks; using FluentAssertions; using Nethermind.Blockchain; @@ -38,57 +36,19 @@ public class FastHeadersSyncTests public async Task Will_fail_if_launched_without_fast_blocks_enabled() { IDbProvider memDbProvider = await TestMemDbProvider.InitAsync(); - BlockTree blockTree = new( - blockDb: memDbProvider.BlocksDb, - headerDb: memDbProvider.HeadersDb, - blockInfoDb: memDbProvider.BlockInfosDb, - chainLevelInfoRepository: new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), - specProvider: MainnetSpecProvider.Instance, - bloomStorage: NullBloomStorage.Instance, - logManager: LimboLogs.Instance); - - Assert.Throws(() => - { - HeadersSyncFeed _ = new HeadersSyncFeed( - syncModeSelector: Substitute.For(), - blockTree: blockTree, - syncPeerPool: Substitute.For(), - syncConfig: new SyncConfig(), - syncReport: Substitute.For(), - logManager: LimboLogs.Instance); - }); + BlockTree blockTree = new(memDbProvider.BlocksDb, memDbProvider.HeadersDb, memDbProvider.BlockInfosDb, new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); + Assert.Throws(() => new HeadersSyncFeed(Substitute.For(), blockTree, Substitute.For(), new SyncConfig(), Substitute.For(), LimboLogs.Instance)); } [Test] public async Task Can_prepare_3_requests_in_a_row() { IDbProvider memDbProvider = await TestMemDbProvider.InitAsync(); - BlockTree blockTree = new( - blockDb: memDbProvider.BlocksDb, - headerDb: memDbProvider.HeadersDb, - blockInfoDb: memDbProvider.BlockInfosDb, - chainLevelInfoRepository: new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), - specProvider: MainnetSpecProvider.Instance, - bloomStorage: NullBloomStorage.Instance, - logManager: LimboLogs.Instance); - HeadersSyncFeed feed = new( - syncModeSelector: Substitute.For(), - blockTree: blockTree, - syncPeerPool: Substitute.For(), - syncConfig: new SyncConfig - { - FastSync = true, - FastBlocks = true, - PivotNumber = "1000", - PivotHash = Keccak.Zero.ToString(), - PivotTotalDifficulty = "1000" - }, - syncReport: Substitute.For(), - logManager: LimboLogs.Instance); - - await feed.PrepareRequest(); - await feed.PrepareRequest(); - await feed.PrepareRequest(); + BlockTree blockTree = new(memDbProvider.BlocksDb, memDbProvider.HeadersDb, memDbProvider.BlockInfosDb, new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); + HeadersSyncFeed feed = new(Substitute.For(), blockTree, Substitute.For(), new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, Substitute.For(), LimboLogs.Instance); + HeadersSyncBatch? batch1 = await feed.PrepareRequest(); + HeadersSyncBatch? batch2 = await feed.PrepareRequest(); + HeadersSyncBatch? batch3 = await feed.PrepareRequest(); } [Test] @@ -109,19 +69,19 @@ public async Task When_next_header_hash_update_is_delayed_do_not_drop_peer() ManualResetEventSlim hangLatch = new(false); BlockHeader pivot = remoteBlockTree.FindHeader(1000, BlockTreeLookupOptions.None)!; ResettableHeaderSyncFeed feed = new( - syncModeSelector: Substitute.For(), - blockTree: blockTree, - syncPeerPool: syncPeerPool, - syncConfig: new SyncConfig + Substitute.For(), + blockTree, + syncPeerPool, + new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "1000", - PivotHash = pivot.Hash!.Bytes.ToHexString(), - PivotTotalDifficulty = pivot.TotalDifficulty.ToString()! + PivotHash = pivot.Hash.Bytes.ToHexString(), + PivotTotalDifficulty = pivot.TotalDifficulty!.ToString() }, - syncReport: syncReport, - logManager: LimboLogs.Instance, + syncReport, + LimboLogs.Instance, hangOnBlockNumberAfterInsert: 425, hangLatch: hangLatch ); @@ -136,10 +96,10 @@ void FulfillBatch(HeadersSyncBatch batch) batch.ResponseSourcePeer = peerInfo; } - HeadersSyncBatch batch1 = (await feed.PrepareRequest())!; - HeadersSyncBatch batch2 = (await feed.PrepareRequest())!; - HeadersSyncBatch batch3 = (await feed.PrepareRequest())!; - HeadersSyncBatch batch4 = (await feed.PrepareRequest())!; + HeadersSyncBatch? batch1 = await feed.PrepareRequest(); + HeadersSyncBatch? batch2 = await feed.PrepareRequest(); + HeadersSyncBatch? batch3 = await feed.PrepareRequest(); + HeadersSyncBatch? batch4 = await feed.PrepareRequest(); FulfillBatch(batch1); FulfillBatch(batch2); @@ -150,13 +110,16 @@ void FulfillBatch(HeadersSyncBatch batch) feed.HandleResponse(batch1); feed.HandleResponse(batch3); feed.HandleResponse(batch2); - Task _ = Task.Factory.StartNew(() => feed.PrepareRequest(), TaskCreationOptions.LongRunning); + Task.Factory.StartNew(() => + { + feed.PrepareRequest(); + }, TaskCreationOptions.LongRunning); await Task.Delay(TimeSpan.FromMilliseconds(100)); feed.HandleResponse(batch4); - syncPeerPool.DidNotReceive().ReportBreachOfProtocol(peerInfo, Arg.Any(), Arg.Any()); + syncPeerPool.DidNotReceive().ReportBreachOfProtocol(peerInfo, Arg.Any(), Arg.Any()); } [Test] @@ -172,21 +135,7 @@ public async Task Can_prepare_several_request_and_ignore_request_from_previous_s syncReport.HeadersInQueue.Returns(new MeasuredProgress()); BlockHeader pivot = remoteBlockTree.FindHeader(500, BlockTreeLookupOptions.None)!; - ResettableHeaderSyncFeed feed = new( - syncModeSelector: Substitute.For(), - blockTree: blockTree, - syncPeerPool: Substitute.For(), - syncConfig: new SyncConfig - { - FastSync = true, - FastBlocks = true, - PivotNumber = "500", - PivotHash = pivot.Hash!.Bytes.ToHexString(), - PivotTotalDifficulty = pivot.TotalDifficulty!.ToString()! - }, - syncReport: syncReport, - logManager: LimboLogs.Instance); - + ResettableHeaderSyncFeed feed = new(Substitute.For(), blockTree, Substitute.For(), new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "500", PivotHash = pivot.Hash.Bytes.ToHexString(), PivotTotalDifficulty = pivot.TotalDifficulty!.ToString() }, syncReport, LimboLogs.Instance); feed.InitializeFeed(); void FulfillBatch(HeadersSyncBatch batch) @@ -197,13 +146,13 @@ void FulfillBatch(HeadersSyncBatch batch) } await feed.PrepareRequest(); - HeadersSyncBatch batch1 = (await feed.PrepareRequest())!; + HeadersSyncBatch? batch1 = await feed.PrepareRequest(); FulfillBatch(batch1); feed.Reset(); await feed.PrepareRequest(); - HeadersSyncBatch batch2 = (await feed.PrepareRequest())!; + HeadersSyncBatch? batch2 = await feed.PrepareRequest(); FulfillBatch(batch2); feed.HandleResponse(batch2); @@ -216,14 +165,7 @@ public async Task Will_dispatch_when_only_partially_processed_dependency() IDbProvider memDbProvider = await TestMemDbProvider.InitAsync(); BlockTree remoteBlockTree = Build.A.BlockTree().OfHeadersOnly.OfChainLength(2001).TestObject; - BlockTree blockTree = new( - blockDb: memDbProvider.BlocksDb, - headerDb: memDbProvider.HeadersDb, - blockInfoDb: memDbProvider.BlockInfosDb, - chainLevelInfoRepository: new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), - specProvider: MainnetSpecProvider.Instance, - bloomStorage: NullBloomStorage.Instance, - logManager: LimboLogs.Instance); + BlockTree blockTree = new(memDbProvider.BlocksDb, memDbProvider.HeadersDb, memDbProvider.BlockInfosDb, new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); ISyncReport syncReport = Substitute.For(); syncReport.FastBlocksHeaders.Returns(new MeasuredProgress()); @@ -231,20 +173,19 @@ public async Task Will_dispatch_when_only_partially_processed_dependency() BlockHeader pivot = remoteBlockTree.FindHeader(2000, BlockTreeLookupOptions.None)!; HeadersSyncFeed feed = new( - syncModeSelector: Substitute.For(), - blockTree: blockTree, - syncPeerPool: Substitute.For(), - syncConfig: new SyncConfig + Substitute.For(), + blockTree, + Substitute.For(), + new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = pivot.Number.ToString(), - PivotHash = pivot.Hash!.ToString(), - PivotTotalDifficulty = pivot.TotalDifficulty.ToString()!, + PivotHash = pivot.Hash.ToString(), + PivotTotalDifficulty = pivot.TotalDifficulty.ToString(), }, - syncReport: syncReport, - logManager: LimboLogs.Instance); - + syncReport, + LimboLogs.Instance); feed.InitializeFeed(); void FulfillBatch(HeadersSyncBatch batch) @@ -255,18 +196,18 @@ void FulfillBatch(HeadersSyncBatch batch) } // First batch need to be handled first before handle dependencies can do anything - HeadersSyncBatch batch1 = (await feed.PrepareRequest())!; + HeadersSyncBatch? batch1 = await feed.PrepareRequest(); FulfillBatch(batch1); feed.HandleResponse(batch1); - HeadersSyncBatch batch2 = (await feed.PrepareRequest())!; + HeadersSyncBatch? batch2 = await feed.PrepareRequest(); FulfillBatch(batch2); int maxHeaderBatchToProcess = 4; - HeadersSyncBatch[] batches = Enumerable.Range(0, maxHeaderBatchToProcess + 1).Select(_ => + HeadersSyncBatch[] batches = Enumerable.Range(0, maxHeaderBatchToProcess + 1).Select((_) => { - HeadersSyncBatch batch = feed.PrepareRequest().Result!; + HeadersSyncBatch? batch = feed.PrepareRequest().Result; FulfillBatch(batch); return batch; }).ToArray(); @@ -281,7 +222,7 @@ void FulfillBatch(HeadersSyncBatch batch) feed.HandleResponse(batch2); // HandleDependantBatch would start from first batch in batches, stopped at second last, not processing the last one - HeadersSyncBatch newBatch = (await feed.PrepareRequest())!; + HeadersSyncBatch? newBatch = await feed.PrepareRequest(); blockTree.LowestInsertedHeader!.Number.Should().Be(batches[^2].StartNumber); // New batch would be at end of batch 5 (batch 6). @@ -294,14 +235,7 @@ public async Task Can_reset_and_not_hang_when_a_batch_is_processing() IDbProvider memDbProvider = await TestMemDbProvider.InitAsync(); BlockTree remoteBlockTree = Build.A.BlockTree().OfHeadersOnly.OfChainLength(501).TestObject; - BlockTree blockTree = new( - blockDb: memDbProvider.BlocksDb, - headerDb: memDbProvider.HeadersDb, - blockInfoDb: memDbProvider.BlockInfosDb, - chainLevelInfoRepository: new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), - specProvider: MainnetSpecProvider.Instance, - bloomStorage: NullBloomStorage.Instance, - logManager: LimboLogs.Instance); + BlockTree blockTree = new(memDbProvider.BlocksDb, memDbProvider.HeadersDb, memDbProvider.BlockInfosDb, new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); ISyncReport syncReport = Substitute.For(); syncReport.FastBlocksHeaders.Returns(new MeasuredProgress()); @@ -311,19 +245,12 @@ public async Task Can_reset_and_not_hang_when_a_batch_is_processing() BlockHeader pivot = remoteBlockTree.FindHeader(500, BlockTreeLookupOptions.None)!; ResettableHeaderSyncFeed feed = new( - syncModeSelector: Substitute.For(), - blockTree: blockTree, - syncPeerPool: Substitute.For(), - syncConfig: new SyncConfig - { - FastSync = true, - FastBlocks = true, - PivotNumber = "500", - PivotHash = pivot.Hash!.Bytes.ToHexString(), - PivotTotalDifficulty = pivot.TotalDifficulty!.ToString()! - }, - syncReport: syncReport, - logManager: LimboLogs.Instance, + Substitute.For(), + blockTree, + Substitute.For(), + new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "500", PivotHash = pivot.Hash.Bytes.ToHexString(), PivotTotalDifficulty = pivot.TotalDifficulty!.ToString() }, + syncReport, + LimboLogs.Instance, hangOnBlockNumber: 400, hangLatch: hangLatch ); @@ -337,7 +264,7 @@ void FulfillBatch(HeadersSyncBatch batch) false); } - HeadersSyncBatch batch1 = (await feed.PrepareRequest())!; + HeadersSyncBatch? batch1 = await feed.PrepareRequest(); FulfillBatch(batch1); // Initiate a process batch which should hang in the middle @@ -353,48 +280,27 @@ void FulfillBatch(HeadersSyncBatch batch) await resetTask; // A new batch is creating, starting at hang block - HeadersSyncBatch batch2 = (await feed.PrepareRequest())!; + HeadersSyncBatch? batch2 = await feed.PrepareRequest(); FulfillBatch(batch2); feed.HandleResponse(batch2); // The whole new batch should get processed instead of skipping due to concurrently modified _nextHeaderHash. - blockTree.LowestInsertedHeader!.Number.Should().Be(batch2.StartNumber); + blockTree.LowestInsertedHeader.Number.Should().Be(batch2.StartNumber); } [Test] public async Task Can_keep_returning_nulls_after_all_batches_were_prepared() { IDbProvider memDbProvider = await TestMemDbProvider.InitAsync(); - BlockTree blockTree = new( - blockDb: memDbProvider.BlocksDb, - headerDb: memDbProvider.HeadersDb, - blockInfoDb: memDbProvider.BlockInfosDb, - chainLevelInfoRepository: new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), - specProvider: MainnetSpecProvider.Instance, - bloomStorage: NullBloomStorage.Instance, - logManager: LimboLogs.Instance); - HeadersSyncFeed feed = new( - syncModeSelector: Substitute.For(), - blockTree: blockTree, - syncPeerPool: Substitute.For(), - syncConfig: new SyncConfig - { - FastSync = true, - FastBlocks = true, - PivotNumber = "1000", - PivotHash = Keccak.Zero.ToString(), - PivotTotalDifficulty = "1000" - }, - syncReport: Substitute.For(), - logManager: LimboLogs.Instance); - + BlockTree blockTree = new(memDbProvider.BlocksDb, memDbProvider.HeadersDb, memDbProvider.BlockInfosDb, new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); + HeadersSyncFeed feed = new(Substitute.For(), blockTree, Substitute.For(), new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, Substitute.For(), LimboLogs.Instance); for (int i = 0; i < 10; i++) { await feed.PrepareRequest(); } - HeadersSyncBatch? result = await feed.PrepareRequest(); + var result = await feed.PrepareRequest(); result.Should().BeNull(); } @@ -410,8 +316,7 @@ public async Task Finishes_when_all_downloaded() HeadersSyncFeed feed = new(Substitute.For(), blockTree, Substitute.For(), new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, report, LimboLogs.Instance); await feed.PrepareRequest(); blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).TestObject); - HeadersSyncBatch? result = await feed.PrepareRequest(); - + var result = await feed.PrepareRequest(); result.Should().BeNull(); feed.CurrentState.Should().Be(SyncFeedState.Finished); measuredProgress.HasEnded.Should().BeTrue(); @@ -432,90 +337,13 @@ public async Task Can_resume_downloading_from_parent_of_lowest_inserted_header() HeadersSyncFeed feed = new(Substitute.For(), blockTree, Substitute.For(), new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, report, LimboLogs.Instance); feed.InitializeFeed(); - HeadersSyncBatch? result = await feed.PrepareRequest(); - - result.Should().NotBeNull(); - result!.EndNumber.Should().Be(499); - } - - [Test] - public async Task Will_never_lose_batch_on_invalid_batch() - { - IBlockTree blockTree = Substitute.For(); - blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1000).TestObject); - ISyncReport report = Substitute.For(); - report.HeadersInQueue.Returns(new MeasuredProgress()); - MeasuredProgress measuredProgress = new(); - report.FastBlocksHeaders.Returns(measuredProgress); - HeadersSyncFeed feed = new( - Substitute.For(), - blockTree, - Substitute.For(), - new SyncConfig - { - FastSync = true, - FastBlocks = true, - PivotNumber = "1000", - PivotHash = Keccak.Zero.ToString(), - PivotTotalDifficulty = "1000" - }, report, LimboLogs.Instance); - feed.InitializeFeed(); - - List batches = new(); - while (true) - { - HeadersSyncBatch? batch = await feed.PrepareRequest(); - if (batch == null) break; - batches.Add(batch); - } - int totalBatchCount = batches.Count; - - Channel batchToProcess = Channel.CreateBounded(batches.Count); - foreach (HeadersSyncBatch headersSyncBatch in batches) - { - await batchToProcess.Writer.WriteAsync(headersSyncBatch); - } - batches.Clear(); - - Task requestTasks = Task.Run(async () => - { - for (int i = 0; i < 100000; i++) - { - HeadersSyncBatch? batch = await feed.PrepareRequest(); - if (batch == null) - { - await Task.Delay(1); - continue; - } - - await batchToProcess.Writer.WriteAsync(batch); - } - - batchToProcess.Writer.Complete(); - }); - - BlockHeader randomBlockHeader = Build.A.BlockHeader.WithNumber(999999).TestObject; - await foreach (HeadersSyncBatch headersSyncBatch in batchToProcess.Reader.ReadAllAsync()) - { - headersSyncBatch.Response = new[] { randomBlockHeader }; - feed.HandleResponse(headersSyncBatch); - } - - await requestTasks; - - while (true) - { - HeadersSyncBatch? batch = await feed.PrepareRequest(); - if (batch == null) break; - batches.Add(batch); - } - - batches.Count.Should().Be(totalBatchCount); + var result = await feed.PrepareRequest(); + result.EndNumber.Should().Be(499); } private class ResettableHeaderSyncFeed : HeadersSyncFeed { - private readonly ManualResetEventSlim? _hangLatch; + private ManualResetEventSlim? _hangLatch; private readonly long? _hangOnBlockNumber; private readonly long? _hangOnBlockNumberAfterInsert; @@ -547,15 +375,15 @@ protected override AddBlockResult InsertToBlockTree(BlockHeader header) { if (header.Number == _hangOnBlockNumber) { - _hangLatch!.Wait(); + _hangLatch.Wait(); } AddBlockResult insertOutcome = _blockTree.Insert(header); if (header.Number == _hangOnBlockNumberAfterInsert) { - _hangLatch!.Wait(); + _hangLatch.Wait(); } - if (insertOutcome is AddBlockResult.Added or AddBlockResult.AlreadyKnown) + if (insertOutcome == AddBlockResult.Added || insertOutcome == AddBlockResult.AlreadyKnown) { SetExpectedNextHeaderToParent(header); } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/SyncStatusListTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/SyncStatusListTests.cs index 24f30a52b8c..02db5270a06 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/SyncStatusListTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/SyncStatusListTests.cs @@ -4,13 +4,10 @@ using System; using System.Linq; using System.Threading.Tasks; -using FluentAssertions; -using Nethermind.Blockchain; -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Core.Test.Builders; + +using DotNetty.Codecs; + using Nethermind.Synchronization.FastBlocks; -using NSubstitute; using NUnit.Framework; namespace Nethermind.Synchronization.Test.FastBlocks @@ -38,6 +35,7 @@ public void Can_read_back_all_set_values() { const int length = 4096; + FastBlockStatusList list = CreateFastBlockStatusList(length, false); for (int i = 0; i < length; i++) { @@ -45,19 +43,6 @@ public void Can_read_back_all_set_values() } } - [Test] - public void Will_not_go_below_ancient_barrier() - { - IBlockTree blockTree = Substitute.For(); - blockTree.FindCanonicalBlockInfo(Arg.Any()).Returns(new BlockInfo(TestItem.KeccakA, 0)); - SyncStatusList syncStatusList = new SyncStatusList(blockTree, 1000, null, 900); - - BlockInfo?[] infos = new BlockInfo?[500]; - syncStatusList.GetInfosForBatch(infos); - - infos.Count((it) => it != null).Should().Be(101); - } - [Test] public void Can_read_back_all_parallel_set_values() { diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/ReceiptsSyncFeedTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/ReceiptsSyncFeedTests.cs index 794547436e3..e9f009689a7 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/ReceiptsSyncFeedTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/ReceiptsSyncFeedTests.cs @@ -36,7 +36,7 @@ public Scenario(ISpecProvider specProvider, int nonEmptyBlocks, int txPerBlock, Blocks = new Block[_pivotNumber + 1]; Blocks[0] = Build.A.Block.Genesis.TestObject; - Block parent = Blocks[0]!; + Block parent = Blocks[0]; for (int blockNumber = 1; blockNumber <= _pivotNumber; blockNumber++) { Block block = Build.A.Block @@ -56,34 +56,34 @@ public Scenario(ISpecProvider specProvider, int nonEmptyBlocks, int txPerBlock, parent = block; } - BlocksByHash = Blocks - .Where(b => b is not null) - .ToDictionary(b => b!.Hash!, b => b!); + BlocksByHash = Blocks.Where(b => b is not null).ToDictionary(b => b.Hash!, b => b); } - public Dictionary BlocksByHash { get; } - public Block?[] Blocks { get; } - public Block? LowestInsertedBody { get; } + public Dictionary BlocksByHash; + + public Block[] Blocks; + + public Block LowestInsertedBody; } - private static readonly ISpecProvider _specProvider; - private IReceiptStorage _receiptStorage = null!; - private ISyncPeerPool _syncPeerPool = null!; - private ISyncModeSelector _selector = null!; - private ReceiptsSyncFeed _feed = null!; - private ISyncConfig _syncConfig = null!; - private ISyncReport _syncReport = null!; - private IBlockTree _blockTree = null!; + private static ISpecProvider _specProvider; + private IReceiptStorage _receiptStorage; + private ISyncPeerPool _syncPeerPool; + private ISyncModeSelector _selector; + private ReceiptsSyncFeed _feed; + private ISyncConfig _syncConfig; + private ISyncReport _syncReport; + private IBlockTree _blockTree; - private static readonly long _pivotNumber = 1024; + private static long _pivotNumber = 1024; - private static readonly Scenario _1024BodiesWithOneTxEach; - private static readonly Scenario _256BodiesWithOneTxEach; - private static readonly Scenario _64BodiesWithOneTxEach; - private static readonly Scenario _64BodiesWithOneTxEachFollowedByEmpty; + private static Scenario _1024BodiesWithOneTxEach; + private static Scenario _256BodiesWithOneTxEach; + private static Scenario _64BodiesWithOneTxEach; + private static Scenario _64BodiesWithOneTxEachFollowedByEmpty; - private MeasuredProgress _measuredProgress = null!; - private MeasuredProgress _measuredProgressQueue = null!; + private MeasuredProgress _measuredProgress; + private MeasuredProgress _measuredProgressQueue; static ReceiptsSyncFeedTests() { @@ -154,7 +154,7 @@ public async Task Should_finish_on_start_when_receipts_not_stored() _syncReport, LimboLogs.Instance); - ReceiptsSyncBatch? request = await _feed.PrepareRequest(); + var request = await _feed.PrepareRequest(); request.Should().BeNull(); _feed.CurrentState.Should().Be(SyncFeedState.Finished); } @@ -181,7 +181,7 @@ public void Should_start_dormant() public void When_activating_should_emit_an_event() { SyncFeedState state = SyncFeedState.Dormant; - _feed.StateChanged += (_, e) => state = e.NewState; + _feed.StateChanged += (s, e) => state = e.NewState; _feed.Activate(); state.Should().Be(SyncFeedState.Active); } @@ -240,7 +240,7 @@ private void LoadScenario(Scenario scenario, ISyncConfig syncConfig) { _syncConfig = syncConfig; _syncConfig.PivotNumber = _pivotNumber.ToString(); - _syncConfig.PivotHash = scenario.Blocks.Last()?.Hash?.ToString(); + _syncConfig.PivotHash = scenario.Blocks.Last().Hash?.ToString(); _feed = new ReceiptsSyncFeed( _selector, @@ -252,20 +252,18 @@ private void LoadScenario(Scenario scenario, ISyncConfig syncConfig) _syncReport, LimboLogs.Instance); - _blockTree.Genesis.Returns(scenario.Blocks[0]!.Header); + _blockTree.Genesis.Returns(scenario.Blocks[0].Header); _blockTree.FindCanonicalBlockInfo(Arg.Any()).Returns( ci => { - Block? block = scenario.Blocks[ci.Arg()]; + Block block = scenario.Blocks[ci.Arg()]; if (block is null) { return null; } - BlockInfo blockInfo = new(block.Hash!, block.TotalDifficulty ?? 0) - { - BlockNumber = ci.Arg(), - }; + BlockInfo blockInfo = new(block.Hash!, block.TotalDifficulty ?? 0); + blockInfo.BlockNumber = ci.Arg(); return blockInfo; }); @@ -279,7 +277,7 @@ private void LoadScenario(Scenario scenario, ISyncConfig syncConfig) : null); _receiptStorage.LowestInsertedReceiptBlockNumber.Returns((long?)null); - _blockTree.LowestInsertedBodyNumber.Returns(scenario.LowestInsertedBody!.Number); + _blockTree.LowestInsertedBodyNumber.Returns(scenario.LowestInsertedBody.Number); } [Test] @@ -325,7 +323,7 @@ public async Task If_receipts_root_comes_invalid_then_reports_breach_of_protocol SyncResponseHandlingResult handlingResult = _feed.HandleResponse(batch); handlingResult.Should().Be(SyncResponseHandlingResult.NoProgress); - _syncPeerPool.Received().ReportBreachOfProtocol(peerInfo, DisconnectReason.InvalidReceiptRoot, Arg.Any()); + _syncPeerPool.Received().ReportBreachOfProtocol(peerInfo, InitiateDisconnectReason.InvalidReceiptRoot, Arg.Any()); } private static void FillBatchResponses(ReceiptsSyncBatch batch) diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTester.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTester.cs index f207e33df7b..779dd54c030 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTester.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTester.cs @@ -1,12 +1,17 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; using System.Threading; using System.Threading.Tasks; using Nethermind.Logging; using Nethermind.Synchronization.FastSync; using Nethermind.Synchronization.ParallelSync; using Nethermind.Synchronization.Peers; +using Nethermind.Synchronization.StateSync; namespace Nethermind.Synchronization.Test.FastSync.SnapProtocolTests { @@ -30,7 +35,7 @@ public async Task ExecuteDispatch(StateSyncBatch batch, int times) for (int i = 0; i < times; i++) { - await _downloader.Dispatch(allocation.Current!, batch, CancellationToken.None); + await _downloader.Dispatch(allocation.Current, batch, CancellationToken.None); } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTests.cs index 2eaaf9dcef4..26717fd067f 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain.Synchronization; @@ -26,13 +27,12 @@ namespace Nethermind.Synchronization.Test.FastSync.SnapProtocolTests [Parallelizable(ParallelScope.Self)] public class StateSyncDispatcherTests { - private static IBlockTree _blockTree = null!; + private static IBlockTree _blockTree; + private ILogManager _logManager; + SyncPeerPool _pool; + StateSyncDispatcherTester _dispatcher; - private ILogManager _logManager = null!; - private SyncPeerPool _pool = null!; - private StateSyncDispatcherTester _dispatcher = null!; - - private readonly PublicKey _publicKey = new("0x000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"); + private PublicKey _publicKey = new("0x000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"); private static IBlockTree BlockTree => LazyInitializer.EnsureInitialized(ref _blockTree, () => Build.A.BlockTree().OfChainLength(100).TestObject); @@ -46,7 +46,7 @@ public void Setup() _pool = new SyncPeerPool(blockTree, new NodeStatsManager(timerFactory, LimboLogs.Instance), new TotalDifficultyBetterPeerStrategy(LimboLogs.Instance), LimboLogs.Instance, 25); _pool.Start(); - ISyncFeed? feed = Substitute.For>(); + var feed = Substitute.For>(); _dispatcher = new StateSyncDispatcherTester(feed, new StateSyncDownloader(_logManager), _pool, new StateSyncAllocationStrategyFactory(), _logManager); } @@ -61,14 +61,12 @@ public async Task Eth66Peer_RunGetNodeData() peer.TotalDifficulty.Returns(new Int256.UInt256(1_000_000_000)); _pool.AddPeer(peer); - StateSyncBatch batch = new( - Keccak.OfAnEmptyString, - NodeDataType.State, - new[] { new StateSyncItem(Keccak.EmptyTreeHash, Array.Empty(), Array.Empty(), NodeDataType.State) }); + StateSyncBatch batch = new StateSyncBatch(Keccak.OfAnEmptyString, NodeDataType.State, + new StateSyncItem[] { new StateSyncItem(Keccak.EmptyTreeHash, Array.Empty(), Array.Empty(), NodeDataType.State) }); await _dispatcher.ExecuteDispatch(batch, 1); - await peer.ReceivedWithAnyArgs(1).GetNodeData(default!, default); + await peer.ReceivedWithAnyArgs(1).GetNodeData(default, default); } [Test] @@ -88,22 +86,20 @@ public async Task GroupMultipleStorageSlotsByAccount() }); _pool.AddPeer(peer); - StateSyncItem item01 = new(Keccak.EmptyTreeHash, null, new byte[] { 3 }, NodeDataType.State); - StateSyncItem item02 = new(Keccak.EmptyTreeHash, new byte[] { 11 }, new byte[] { 2 }, NodeDataType.State); - StateSyncItem item03 = new(Keccak.EmptyTreeHash, null, new byte[] { 1 }, NodeDataType.State); - StateSyncItem item04 = new(Keccak.EmptyTreeHash, new byte[] { 22 }, new byte[] { 21 }, NodeDataType.State); - StateSyncItem item05 = new(Keccak.EmptyTreeHash, new byte[] { 11 }, new byte[] { 1 }, NodeDataType.State); - StateSyncItem item06 = new(Keccak.EmptyTreeHash, new byte[] { 22 }, new byte[] { 22 }, NodeDataType.State); + var item01 = new StateSyncItem(Keccak.EmptyTreeHash, null, new byte[] { 3 }, NodeDataType.State); + var item02 = new StateSyncItem(Keccak.EmptyTreeHash, new byte[] { 11 }, new byte[] { 2 }, NodeDataType.State); + var item03 = new StateSyncItem(Keccak.EmptyTreeHash, null, new byte[] { 1 }, NodeDataType.State); + var item04 = new StateSyncItem(Keccak.EmptyTreeHash, new byte[] { 22 }, new byte[] { 21 }, NodeDataType.State); + var item05 = new StateSyncItem(Keccak.EmptyTreeHash, new byte[] { 11 }, new byte[] { 1 }, NodeDataType.State); + var item06 = new StateSyncItem(Keccak.EmptyTreeHash, new byte[] { 22 }, new byte[] { 22 }, NodeDataType.State); - StateSyncBatch batch = new( - Keccak.OfAnEmptyString, - NodeDataType.State, - new[] { item01, item02, item03, item04, item05, item06 }); + StateSyncBatch batch = new StateSyncBatch(Keccak.OfAnEmptyString, NodeDataType.State, new StateSyncItem[] { + item01, item02, item03, item04, item05, item06 + }); await _dispatcher.ExecuteDispatch(batch, 1); - batch.RequestedNodes.Should().NotBeNull(); - batch.RequestedNodes!.Count.Should().Be(6); + batch.RequestedNodes.Count().Should().Be(6); batch.RequestedNodes[0].Should().Be(item01); batch.RequestedNodes[1].Should().Be(item03); batch.RequestedNodes[2].Should().Be(item02); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedHealingTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedHealingTests.cs index 94db85ce17c..33e005b66a5 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedHealingTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedHealingTests.cs @@ -52,6 +52,8 @@ public async Task HealBigSqueezedRandomTree() int pathPoolCount = 100_000; Keccak[] pathPool = new Keccak[pathPoolCount]; SortedDictionary accounts = new(); + int updatesCount = 0; + int deletionsCount = 0; for (int i = 0; i < pathPoolCount; i++) { @@ -74,7 +76,7 @@ public async Task HealBigSqueezedRandomTree() dbContext.RemoteStateTree.Commit(0); int startingHashIndex = 0; - int endHashIndex; + int endHashIndex = 0; int blockJumps = 5; for (int blockNumber = 1; blockNumber <= blockJumps; blockNumber++) { @@ -99,11 +101,13 @@ public async Task HealBigSqueezedRandomTree() { dbContext.RemoteStateTree.Set(path, account); accounts[path] = account; + updatesCount++; } else { dbContext.RemoteStateTree.Set(path, null); accounts.Remove(path); + deletionsCount++; } @@ -155,12 +159,12 @@ private static void ProcessAccountRange(StateTree remoteStateTree, StateTree loc AccountProofCollector accountProofCollector = new(startingHash.Bytes); remoteStateTree.Accept(accountProofCollector, remoteStateTree.RootHash); - byte[][] firstProof = accountProofCollector.BuildResult().Proof!; + byte[][] firstProof = accountProofCollector.BuildResult().Proof; accountProofCollector = new(endHash.Bytes); remoteStateTree.Accept(accountProofCollector, remoteStateTree.RootHash); - byte[][] lastProof = accountProofCollector.BuildResult().Proof!; + byte[][] lastProof = accountProofCollector.BuildResult().Proof; - _ = SnapProviderHelper.AddAccountRange(localStateTree, blockNumber, rootHash, startingHash, limitHash, accounts, firstProof.Concat(lastProof).ToArray()); + (_, _, _, _) = SnapProviderHelper.AddAccountRange(localStateTree, blockNumber, rootHash, startingHash, limitHash, accounts, firstProof!.Concat(lastProof!).ToArray()); } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTests.cs index 45c12fc64bc..8c889bb1f76 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTests.cs @@ -7,7 +7,6 @@ using FluentAssertions; using Nethermind.Blockchain; using Nethermind.Blockchain.Synchronization; -using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; @@ -43,21 +42,16 @@ public StateSyncFeedTests(int peerCount, int maxNodeLatency) : base(peerCount, m [Repeat(TestRepeatCount)] public async Task Big_test((string Name, Action SetupTree) testCase) { - DbContext dbContext = new(_logger, _logManager) - { - RemoteCodeDb = - { - [Keccak.Compute(TrieScenarios.Code0).Bytes] = TrieScenarios.Code0, - [Keccak.Compute(TrieScenarios.Code1).Bytes] = TrieScenarios.Code1, - [Keccak.Compute(TrieScenarios.Code2).Bytes] = TrieScenarios.Code2, - [Keccak.Compute(TrieScenarios.Code3).Bytes] = TrieScenarios.Code3, - }, - }; + DbContext dbContext = new(_logger, _logManager); + dbContext.RemoteCodeDb[Keccak.Compute(TrieScenarios.Code0).Bytes] = TrieScenarios.Code0; + dbContext.RemoteCodeDb[Keccak.Compute(TrieScenarios.Code1).Bytes] = TrieScenarios.Code1; + dbContext.RemoteCodeDb[Keccak.Compute(TrieScenarios.Code2).Bytes] = TrieScenarios.Code2; + dbContext.RemoteCodeDb[Keccak.Compute(TrieScenarios.Code3).Bytes] = TrieScenarios.Code3; testCase.SetupTree(dbContext.RemoteStateTree, dbContext.RemoteTrieStore, dbContext.RemoteCodeDb); dbContext.CompareTrees("BEFORE FIRST SYNC", true); - SafeContext ctx = PrepareDownloader(dbContext, mock => + SafeContext ctx = PrepareDownloader(dbContext, (mock) => mock.SetFilter(((MemDb)dbContext.RemoteStateDb).Keys.Take(((MemDb)dbContext.RemoteStateDb).Keys.Count - 4).Select(k => new Keccak(k)).ToArray())); await ActivateAndWait(ctx, dbContext, 1024); @@ -96,15 +90,17 @@ public async Task Big_test((string Name, Action Setu ctx.Feed.FallAsleep(); ctx.Pool.WakeUpAll(); - foreach (SyncPeerMock mock in ctx.SyncPeerMocks) + for (int index = 0; index < ctx.SyncPeerMocks.Length; index++) { + SyncPeerMock mock = ctx.SyncPeerMocks[index]; mock.SetFilter(null); } await ActivateAndWait(ctx, dbContext, 1024); + dbContext.CompareTrees("END"); - dbContext.AssertFlushed(); + dbContext.CompareCodeDbs(); } [Test] @@ -143,14 +139,15 @@ public async Task Can_download_in_multiple_connections((string Name, Action + SafeContext ctx = PrepareDownloader(dbContext, (mock) => mock.SetFilter(new[] { dbContext.RemoteStateTree.RootHash })); await ActivateAndWait(ctx, dbContext, 1024, 1000); ctx.Pool.WakeUpAll(); - foreach (SyncPeerMock mock in ctx.SyncPeerMocks) + for (int index = 0; index < ctx.SyncPeerMocks.Length; index++) { + SyncPeerMock mock = ctx.SyncPeerMocks[index]; mock.SetFilter(null); } @@ -172,7 +169,7 @@ public async Task Can_download_when_executor_sends_shorter_responses((string Nam dbContext.CompareTrees("BEGIN"); - SafeContext ctx = PrepareDownloader(dbContext, mock => mock.MaxResponseLength = 1); + SafeContext ctx = PrepareDownloader(dbContext, (mock) => mock.MaxResponseLength = 1); await ActivateAndWait(ctx, dbContext, 1024); @@ -208,7 +205,7 @@ public async Task Can_download_with_moving_target((string Name, Action + SafeContext ctx = PrepareDownloader(dbContext, (mock) => mock.SetFilter(((MemDb)dbContext.RemoteStateDb).Keys.Take(((MemDb)dbContext.RemoteStateDb).Keys.Count - 1).Select(k => new Keccak(k)).ToArray())); await ActivateAndWait(ctx, dbContext, 1024, 1000); @@ -233,8 +230,9 @@ public async Task Can_download_with_moving_target((string Name, Action + // { + // Assert.AreEqual(0, _pool.InitializedPeers.Count(p => p.CanBeAllocated(AllocationContexts.All))); + // }); + // } + + // [Test] + // [Retry(3)] + // public async Task Silences_when_peer_sends_empty_byte_arrays() + // { + // DbContext dbContext = new DbContext(_logger, _logManager); + // SyncPeerMock mock = new SyncPeerMock(dbContext.RemoteStateDb, dbContext.RemoteCodeDb, SyncPeerMock.EmptyArraysInResponses); + // SafeContext ctx = PrepareDownloader(mock); + // _feed.SetNewStateRoot(1024, Keccak.Compute("the_peer_has_no_data")); + // _feed.Activate(); + // await Task.WhenAny(_stateSyncDispatcher.Start(CancellationToken.None), Task.Delay(1000)).Unwrap() + // .ContinueWith(t => + // { + // _pool.InitializedPeers.Count(p => p.CanBeAllocated(AllocationContexts.All)).Should().Be(0); + // }); + // } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs index dd8fe63eece..b00795cd348 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs @@ -3,15 +3,14 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; -using FluentAssertions; using Nethermind.Blockchain; using Nethermind.Blockchain.Synchronization; using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Core.Timers; using Nethermind.Db; @@ -36,11 +35,11 @@ public class StateSyncFeedTestsBase { private const int TimeoutLength = 5000; - private static IBlockTree? _blockTree; + protected static IBlockTree _blockTree; protected static IBlockTree BlockTree => LazyInitializer.EnsureInitialized(ref _blockTree, () => Build.A.BlockTree().OfChainLength(100).TestObject); - protected ILogger _logger = null!; - protected ILogManager _logManager = null!; + protected ILogger _logger; + protected ILogManager _logManager; private readonly int _defaultPeerCount; private readonly int _defaultPeerMaxRandomLatency; @@ -95,38 +94,35 @@ protected SafeContext PrepareDownloader(DbContext dbContext, Action syncPeers) + protected SafeContext PrepareDownloaderWithPeer(DbContext dbContext, params ISyncPeer[] syncPeers) { - SafeContext ctx = new(); - BlockTree blockTree = Build.A.BlockTree().OfChainLength((int)BlockTree.BestSuggestedHeader!.Number).TestObject; + SafeContext ctx = new SafeContext(); + ctx = new SafeContext(); + BlockTree blockTree = Build.A.BlockTree().OfChainLength((int)BlockTree.BestSuggestedHeader.Number).TestObject; ITimerFactory timerFactory = Substitute.For(); ctx.Pool = new SyncPeerPool(blockTree, new NodeStatsManager(timerFactory, LimboLogs.Instance), new TotalDifficultyBetterPeerStrategy(LimboLogs.Instance), LimboLogs.Instance, 25); ctx.Pool.Start(); - foreach (ISyncPeer syncPeer in syncPeers) + for (int i = 0; i < syncPeers.Length; i++) { - ctx.Pool.AddPeer(syncPeer); + ctx.Pool.AddPeer(syncPeers[i]); } + SyncConfig syncConfig = new SyncConfig(); + syncConfig.FastSync = true; ctx.SyncModeSelector = StaticSelector.StateNodesWithFastBlocks; ctx.TreeFeed = new(SyncMode.StateNodes, dbContext.LocalCodeDb, dbContext.LocalStateDb, blockTree, _logManager); ctx.Feed = new StateSyncFeed(ctx.SyncModeSelector, ctx.TreeFeed, _logManager); ctx.Downloader = new StateSyncDownloader(_logManager); - ctx.StateSyncDispatcher = new SyncDispatcher( - 0, - ctx.Feed!, - ctx.Downloader, - ctx.Pool, - new StateSyncAllocationStrategyFactory(), - _logManager); - Task _ = ctx.StateSyncDispatcher.Start(CancellationToken.None); + ctx.StateSyncDispatcher = new SyncDispatcher(0, ctx.Feed, ctx.Downloader, ctx.Pool, new StateSyncAllocationStrategyFactory(), _logManager); + ctx.StateSyncDispatcher.Start(CancellationToken.None); return ctx; } protected async Task ActivateAndWait(SafeContext safeContext, DbContext dbContext, long blockNumber, int timeout = TimeoutLength) { - DotNetty.Common.Concurrency.TaskCompletionSource dormantAgainSource = new(); - safeContext.Feed.StateChanged += (_, e) => + DotNetty.Common.Concurrency.TaskCompletionSource dormantAgainSource = new DotNetty.Common.Concurrency.TaskCompletionSource(); + safeContext.Feed.StateChanged += (s, e) => { if (e.NewState == SyncFeedState.Dormant) { @@ -136,7 +132,7 @@ protected async Task ActivateAndWait(SafeContext safeContext, DbContext dbContex safeContext.TreeFeed.ResetStateRoot(blockNumber, dbContext.RemoteStateTree.RootHash, safeContext.Feed.CurrentState); safeContext.Feed.Activate(); - + var watch = Stopwatch.StartNew(); await Task.WhenAny( dormantAgainSource.Task, Task.Delay(timeout)); @@ -144,13 +140,13 @@ await Task.WhenAny( protected class SafeContext { - public ISyncModeSelector SyncModeSelector { get; set; } = null!; - public SyncPeerMock[] SyncPeerMocks { get; set; } = null!; - public ISyncPeerPool Pool { get; set; } = null!; - public TreeSync TreeFeed { get; set; } = null!; - public StateSyncFeed Feed { get; set; } = null!; - public StateSyncDownloader Downloader { get; set; } = null!; - public SyncDispatcher StateSyncDispatcher { get; set; } = null!; + public ISyncModeSelector SyncModeSelector; + public SyncPeerMock[] SyncPeerMocks; + public ISyncPeerPool Pool; + public TreeSync TreeFeed; + public StateSyncFeed Feed; + public StateSyncDownloader Downloader; + public SyncDispatcher StateSyncDispatcher; } protected class DbContext @@ -161,10 +157,10 @@ public DbContext(ILogger logger, ILogManager logManager) { _logger = logger; RemoteDb = new MemDb(); - LocalDb = new TestMemDb(); + LocalDb = new MemDb(); RemoteStateDb = RemoteDb; LocalStateDb = LocalDb; - LocalCodeDb = new TestMemDb(); + LocalCodeDb = new MemDb(); RemoteCodeDb = new MemDb(); RemoteTrieStore = new TrieStore(RemoteStateDb, logManager); @@ -172,10 +168,10 @@ public DbContext(ILogger logger, ILogManager logManager) LocalStateTree = new StateTree(new TrieStore(LocalStateDb, logManager), logManager); } - public MemDb RemoteCodeDb { get; } - public TestMemDb LocalCodeDb { get; } + public IDb RemoteCodeDb { get; } + public IDb LocalCodeDb { get; } public MemDb RemoteDb { get; } - public TestMemDb LocalDb { get; } + public MemDb LocalDb { get; } public ITrieStore RemoteTrieStore { get; } public IDb RemoteStateDb { get; } public IDb LocalStateDb { get; } @@ -206,135 +202,165 @@ public void CompareTrees(string stage, bool skipLogs = false) Assert.That(collector.Stats.MissingNodes, Is.EqualTo(0)); Assert.That(collector.Stats.MissingCode, Is.EqualTo(0)); } + + // Assert.AreEqual(dbContext._remoteCodeDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), dbContext._localCodeDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), "keys"); + // Assert.AreEqual(dbContext._remoteCodeDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), dbContext._localCodeDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), "values"); + // + // Assert.AreEqual(dbContext._remoteDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), _localDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), "keys"); + // Assert.AreEqual(dbContext._remoteDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), _localDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), "values"); } - public void AssertFlushed() + public void CompareCodeDbs() { - LocalDb.WasFlushed.Should().BeTrue(); - LocalCodeDb.WasFlushed.Should().BeTrue(); + // Assert.AreEqual(dbContext._remoteCodeDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), dbContext._localCodeDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), "keys"); + // Assert.AreEqual(dbContext._remoteCodeDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), dbContext._localCodeDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), "values"); + + // Assert.AreEqual(dbContext._remoteDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), _localDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), "keys"); + // Assert.AreEqual(dbContext._remoteDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), _localDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), "values"); } } protected class SyncPeerMock : ISyncPeer { - public string Name => "Mock"; + public static Func, Task> NotPreimage = request => + { + var result = new byte[request.Count][]; + + int i = 0; + foreach (Keccak _ in request) result[i++] = new byte[] { 1, 2, 3 }; + + return Task.FromResult(result); + }; + + public static Func, Task> EmptyArraysInResponses = request => + { + var result = new byte[request.Count][]; + + int i = 0; + foreach (Keccak _ in request) result[i++] = new byte[0]; + + return Task.FromResult(result); + }; private readonly IDb _codeDb; private readonly IDb _stateDb; - private Keccak[]? _filter; - private readonly Func, Task>? _executorResultFunction; + private Func, Task> _executorResultFunction; + + private Keccak[] _filter; + private readonly long _maxRandomizedLatencyMs; public SyncPeerMock( IDb stateDb, IDb codeDb, - Func, Task>? executorResultFunction = null, + Func, Task> executorResultFunction = null, long? maxRandomizedLatencyMs = null, Node? node = null ) { _stateDb = stateDb; _codeDb = codeDb; - _executorResultFunction = executorResultFunction; + + if (executorResultFunction is not null) _executorResultFunction = executorResultFunction; Node = node ?? new Node(TestItem.PublicKeyA, "127.0.0.1", 30302, true) { EthDetails = "eth66" }; _maxRandomizedLatencyMs = maxRandomizedLatencyMs ?? 0; } public int MaxResponseLength { get; set; } = int.MaxValue; - public Keccak HeadHash { get; set; } = null!; - public string ProtocolCode { get; } = null!; - public byte ProtocolVersion { get; } = default; - public string ClientId => "executorMock"; + public Node Node { get; } + public string ClientId => "executorMock"; + public Keccak HeadHash { get; set; } public long HeadNumber { get; set; } public UInt256 TotalDifficulty { get; set; } public bool IsInitialized { get; set; } public bool IsPriority { get; set; } + public byte ProtocolVersion { get; } + public string ProtocolCode { get; } - public PublicKey Id => Node.Id; - - public async Task GetNodeData(IReadOnlyList hashes, CancellationToken token) + public void Disconnect(InitiateDisconnectReason reason, string details) { - if (_maxRandomizedLatencyMs != 0) - { - await Task.Delay(TimeSpan.FromMilliseconds(TestContext.CurrentContext.Random.NextLong() % _maxRandomizedLatencyMs)); - } - - if (_executorResultFunction is not null) return await _executorResultFunction(hashes); - - byte[][] responses = new byte[hashes.Count][]; - - int i = 0; - foreach (Keccak item in hashes) - { - if (i >= MaxResponseLength) break; - - if (_filter is null || _filter.Contains(item)) responses[i] = _stateDb[item.Bytes] ?? _codeDb[item.Bytes]!; - - i++; - } - - return responses; + throw new NotImplementedException(); } - public void SetFilter(Keccak[]? availableHashes) + public Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) { - _filter = availableHashes; + throw new NotImplementedException(); } - public bool TryGetSatelliteProtocol(string protocol, out T protocolHandler) where T : class + public Task GetBlockHeaders(Keccak blockHash, int maxBlocks, int skip, CancellationToken token) { - protocolHandler = null!; - return false; + throw new NotImplementedException(); } - public void RegisterSatelliteProtocol(string protocol, T protocolHandler) where T : class + public Task GetBlockHeaders(long number, int maxBlocks, int skip, CancellationToken token) { throw new NotImplementedException(); } - public void Disconnect(DisconnectReason reason, string details) + public Task GetHeadBlockHeader(Keccak? hash, CancellationToken token) { - throw new NotImplementedException(); + return Task.FromResult(BlockTree.Head?.Header); } - public Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) + public void NotifyOfNewBlock(Block block, SendBlockMode mode) { throw new NotImplementedException(); } - public Task GetBlockHeaders(Keccak blockHash, int maxBlocks, int skip, CancellationToken token) + public PublicKey Id => Node.Id; + + public void SendNewTransactions(IEnumerable txs, bool sendFullTx) { throw new NotImplementedException(); } - public Task GetBlockHeaders(long number, int maxBlocks, int skip, CancellationToken token) + public Task GetReceipts(IReadOnlyList blockHash, CancellationToken token) { throw new NotImplementedException(); } - public Task GetHeadBlockHeader(Keccak? hash, CancellationToken token) + public async Task GetNodeData(IReadOnlyList hashes, CancellationToken token) { - return Task.FromResult(BlockTree.Head?.Header); + if (_maxRandomizedLatencyMs != 0) + { + await Task.Delay(TimeSpan.FromMilliseconds(TestContext.CurrentContext.Random.NextLong() % _maxRandomizedLatencyMs)); + } + + if (_executorResultFunction is not null) return await _executorResultFunction(hashes); + + var responses = new byte[hashes.Count][]; + + int i = 0; + foreach (Keccak item in hashes) + { + if (i >= MaxResponseLength) break; + + if (_filter is null || _filter.Contains(item)) responses[i] = _stateDb[item.Bytes] ?? _codeDb[item.Bytes]; + + i++; + } + + return responses; } - public void NotifyOfNewBlock(Block block, SendBlockMode mode) + public void SetFilter(Keccak[] availableHashes) { - throw new NotImplementedException(); + _filter = availableHashes; } - public void SendNewTransactions(IEnumerable txs, bool sendFullTx) + public void RegisterSatelliteProtocol(string protocol, T protocolHandler) where T : class { throw new NotImplementedException(); } - public Task GetReceipts(IReadOnlyList blockHash, CancellationToken token) + public bool TryGetSatelliteProtocol(string protocol, out T protocolHandler) where T : class { - throw new NotImplementedException(); + protocolHandler = null!; + return false; } - } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/LatencySyncPeerMock.cs b/src/Nethermind/Nethermind.Synchronization.Test/LatencySyncPeerMock.cs new file mode 100644 index 00000000000..e6a063b3420 --- /dev/null +++ b/src/Nethermind/Nethermind.Synchronization.Test/LatencySyncPeerMock.cs @@ -0,0 +1,117 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Nethermind.Blockchain; +using Nethermind.Blockchain.Synchronization; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Test.Builders; +using Nethermind.Int256; +using Nethermind.Stats.Model; +using NUnit.Framework.Constraints; + +namespace Nethermind.Synchronization.Test +{ + /// + /// Mock of a sync peer that allows controlling concurrency issues without spawning tasks. + /// By controlling latency parameters we can test various ordering of responses, timeouts and other issues without unpredictable results from tests running on multiple threads. + /// + public class LatencySyncPeerMock : ISyncPeer + { + public IBlockTree Tree { get; } + public bool IsReported { get; set; } = false; + public long? BusyUntil { get; set; } + public int Latency { get; set; } + public static int RemoteIndex { get; set; } = 1; + + public LatencySyncPeerMock(IBlockTree tree, int latency = 5) + { + Latency = latency; + string localHost = "0.0.0.0"; + string remoteHost = $"{RemoteIndex}.{RemoteIndex}.{RemoteIndex}.{RemoteIndex}"; + + Tree = tree; + HeadNumber = Tree.Head.Number; + HeadHash = Tree.Head.Hash; + TotalDifficulty = Tree.Head.TotalDifficulty ?? 0; + + Node = new Node(TestItem.PrivateKeys[RemoteIndex].PublicKey, remoteHost, 30303); + LocalNode = new Node(TestItem.PrivateKeys[0].PublicKey, localHost, 30303); + Node.ClientId = $"remote {RemoteIndex}"; + LocalNode.ClientId = "local nethermind"; + RemoteIndex++; + } + + public Node Node { get; } + public Node LocalNode { get; } + public string ClientId => Node.ClientId; + public long HeadNumber { get; set; } + public Keccak HeadHash { get; set; } + public UInt256 TotalDifficulty { get; set; } + public bool IsInitialized { get; set; } = true; + public bool IsPriority { get; set; } + public byte ProtocolVersion { get; } + public string ProtocolCode { get; } + + public void Disconnect(InitiateDisconnectReason reason, string details) + { + throw new NotImplementedException(); + } + + public Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task GetBlockHeaders(Keccak blockHash, int maxBlocks, int skip, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task GetBlockHeaders(long number, int maxBlocks, int skip, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task GetHeadBlockHeader(Keccak? hash, CancellationToken token) + { + throw new NotImplementedException(); + } + + public void NotifyOfNewBlock(Block block, SendBlockMode mode) + { + throw new NotImplementedException(); + } + + public PublicKey Id => Node.Id; + + public void SendNewTransactions(IEnumerable txs, bool sendFullTx) + { + throw new NotImplementedException(); + } + + public Task GetReceipts(IReadOnlyList blockHash, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task GetNodeData(IReadOnlyList hashes, CancellationToken token) + { + throw new NotImplementedException(); + } + + public void RegisterSatelliteProtocol(string protocol, T protocolHandler) where T : class + { + throw new NotImplementedException(); + } + + public bool TryGetSatelliteProtocol(string protocol, out T protocolHandler) where T : class + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Nethermind/Nethermind.Synchronization.Test/MallocTrimmerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/MallocTrimmerTests.cs deleted file mode 100644 index 26c544963f6..00000000000 --- a/src/Nethermind/Nethermind.Synchronization.Test/MallocTrimmerTests.cs +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Threading.Tasks; -using Nethermind.Core.Memory; -using Nethermind.Logging; -using Nethermind.Synchronization.ParallelSync; -using NSubstitute; -using NUnit.Framework; - -namespace Nethermind.Synchronization.Test; - -public class MallocTrimmerTests -{ - [TestCase(SyncMode.None, false)] - [TestCase(SyncMode.WaitingForBlock, false)] - [TestCase(SyncMode.FastBlocks, true)] - public async Task TestTrim(SyncMode mode, bool doReceive) - { - MallocHelper helper = Substitute.For(); - - ISyncModeSelector syncModeSelector = Substitute.For(); - new MallocTrimmer(syncModeSelector, TimeSpan.FromMilliseconds(1), NullLogManager.Instance, helper); - - syncModeSelector.Changed += Raise.EventWith(null, - new SyncModeChangedEventArgs(SyncMode.FastSync, mode)); - - await Task.Delay(TimeSpan.FromMilliseconds(100)); - - syncModeSelector.Changed += Raise.EventWith(null, - new SyncModeChangedEventArgs(SyncMode.None, SyncMode.None)); - - if (doReceive) - { - helper.Received().MallocTrim(Arg.Any()); - } - else - { - helper.DidNotReceive().MallocTrim(Arg.Any()); - } - } -} diff --git a/src/Nethermind/Nethermind.Synchronization.Test/Nethermind.Synchronization.Test.csproj b/src/Nethermind/Nethermind.Synchronization.Test/Nethermind.Synchronization.Test.csproj index f6111e7e6ac..0972afd2cf9 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/Nethermind.Synchronization.Test.csproj +++ b/src/Nethermind/Nethermind.Synchronization.Test/Nethermind.Synchronization.Test.csproj @@ -4,7 +4,6 @@ net7.0 false enable - true diff --git a/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs index 03a02069fc5..06a84baba15 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs @@ -9,7 +9,6 @@ using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; -using Nethermind.Config; using Nethermind.Consensus; using Nethermind.Consensus.Validators; using Nethermind.Core; @@ -93,10 +92,9 @@ public async Task Setup() blockDownloaderFactory, pivot, syncReport, - Substitute.For(), LimboLogs.Instance); _syncServer = new SyncServer( - trieStore.AsKeyValueStore(), + trieStore, _codeDb, _blockTree, _receiptStorage, @@ -118,15 +116,15 @@ public async Task TearDown() await _synchronizer.StopAsync(); } - private IDb _stateDb = null!; - private IDb _codeDb = null!; - private IBlockTree _blockTree = null!; - private IBlockTree _remoteBlockTree = null!; - private IReceiptStorage _receiptStorage = null!; - private Block _genesisBlock = null!; - private ISyncPeerPool _pool = null!; - private ISyncServer _syncServer = null!; - private ISynchronizer _synchronizer = null!; + private IDb _stateDb; + private IDb _codeDb; + private IBlockTree _blockTree; + private IBlockTree _remoteBlockTree; + private IReceiptStorage _receiptStorage; + private Block _genesisBlock; + private ISyncPeerPool _pool; + private ISyncServer _syncServer; + private ISynchronizer _synchronizer; [Test, Ignore("travis")] public void Retrieves_missing_blocks_in_batches() @@ -135,7 +133,7 @@ public void Retrieves_missing_blocks_in_batches() ISyncPeer peer = new SyncPeerMock(_remoteBlockTree); ManualResetEvent resetEvent = new(false); - _synchronizer.SyncEvent += (_, args) => + _synchronizer.SyncEvent += (sender, args) => { if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed) resetEvent.Set(); }; @@ -144,7 +142,7 @@ public void Retrieves_missing_blocks_in_batches() _pool.AddPeer(peer); resetEvent.WaitOne(_standardTimeoutUnit); - Assert.That(_blockTree.BestSuggestedHeader!.Number, Is.EqualTo(SyncBatchSize.Max * 2 - 1)); + Assert.That((int)_blockTree.BestSuggestedHeader.Number, Is.EqualTo(SyncBatchSize.Max * 2 - 1)); } [Test] @@ -157,7 +155,7 @@ public void Syncs_with_empty_peer() _synchronizer.Start(); _pool.AddPeer(peer); - Assert.That(_blockTree.BestSuggestedHeader!.Number, Is.EqualTo(0)); + Assert.That((int)_blockTree.BestSuggestedHeader.Number, Is.EqualTo(0)); } [Test] @@ -168,13 +166,13 @@ public void Syncs_when_knows_more_blocks() ISyncPeer peer = new SyncPeerMock(_remoteBlockTree); ManualResetEvent resetEvent = new(false); - _synchronizer.SyncEvent += (_, _) => { resetEvent.Set(); }; + _synchronizer.SyncEvent += (sender, args) => { resetEvent.Set(); }; _pool.Start(); _synchronizer.Start(); _pool.AddPeer(peer); resetEvent.WaitOne(_standardTimeoutUnit); - Assert.That(_blockTree.BestSuggestedHeader!.Number, Is.EqualTo(SyncBatchSize.Max * 2 - 1)); + Assert.That((int)_blockTree.BestSuggestedHeader.Number, Is.EqualTo(SyncBatchSize.Max * 2 - 1)); } [Test] @@ -185,7 +183,7 @@ public void Can_resync_if_missed_a_block() ISyncPeer peer = new SyncPeerMock(_remoteBlockTree); SemaphoreSlim semaphore = new(0); - _synchronizer.SyncEvent += (_, args) => + _synchronizer.SyncEvent += (sender, args) => { if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed) semaphore.Release(1); }; @@ -194,24 +192,22 @@ public void Can_resync_if_missed_a_block() _pool.AddPeer(peer); BlockTreeBuilder.ExtendTree(_remoteBlockTree, SyncBatchSize.Max * 2); - _syncServer.AddNewBlock(_remoteBlockTree.RetrieveHeadBlock()!, peer); + _syncServer.AddNewBlock(_remoteBlockTree.RetrieveHeadBlock(), peer); semaphore.Wait(_standardTimeoutUnit); semaphore.Wait(_standardTimeoutUnit); - Assert.That(_blockTree.BestSuggestedHeader!.Number, Is.EqualTo(SyncBatchSize.Max * 2 - 1)); + Assert.That((int)_blockTree.BestSuggestedHeader.Number, Is.EqualTo(SyncBatchSize.Max * 2 - 1)); } [Test, Ignore("travis")] public void Can_add_new_block() { - _remoteBlockTree = Build.A - .BlockTree(_genesisBlock) - .OfChainLength(SyncBatchSize.Max).TestObject; + _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(SyncBatchSize.Max).TestObject; ISyncPeer peer = new SyncPeerMock(_remoteBlockTree); ManualResetEvent resetEvent = new(false); - _synchronizer.SyncEvent += (_, args) => + _synchronizer.SyncEvent += (sender, args) => { if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed) resetEvent.Set(); }; @@ -220,15 +216,12 @@ public void Can_add_new_block() _synchronizer.Start(); _pool.AddPeer(peer); - Block block = Build.A.Block - .WithParent(_remoteBlockTree.Head!) - .WithTotalDifficulty((_remoteBlockTree.Head!.TotalDifficulty ?? 0) + 1) - .TestObject; + Block block = Build.A.Block.WithParent(_remoteBlockTree.Head).WithTotalDifficulty((_remoteBlockTree.Head.TotalDifficulty ?? 0) + 1).TestObject; _syncServer.AddNewBlock(block, peer); resetEvent.WaitOne(_standardTimeoutUnit); - Assert.That(_blockTree.BestSuggestedHeader!.Number, Is.EqualTo(SyncBatchSize.Max - 1)); + Assert.That((int)_blockTree.BestSuggestedHeader.Number, Is.EqualTo(SyncBatchSize.Max - 1)); } [Test] @@ -238,7 +231,7 @@ public void Can_sync_on_split_of_length_1() ISyncPeer miner1 = new SyncPeerMock(miner1Tree); ManualResetEvent resetEvent = new(false); - _synchronizer.SyncEvent += (_, args) => + _synchronizer.SyncEvent += (sender, args) => { if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed) resetEvent.Set(); }; @@ -251,10 +244,7 @@ public void Can_sync_on_split_of_length_1() miner1Tree.BestSuggestedHeader.Should().BeEquivalentTo(_blockTree.BestSuggestedHeader, "client agrees with miner before split"); - Block splitBlock = Build.A.Block - .WithParent(miner1Tree.FindParent(miner1Tree.Head!, BlockTreeLookupOptions.TotalDifficultyNotNeeded)!) - .WithDifficulty(miner1Tree.Head!.Difficulty - 1) - .TestObject; + Block splitBlock = Build.A.Block.WithParent(miner1Tree.FindParent(miner1Tree.Head, BlockTreeLookupOptions.TotalDifficultyNotNeeded)).WithDifficulty(miner1Tree.Head.Difficulty - 1).TestObject; Block splitBlockChild = Build.A.Block.WithParent(splitBlock).TestObject; miner1Tree.SuggestBlock(splitBlock); @@ -270,7 +260,7 @@ public void Can_sync_on_split_of_length_1() resetEvent.WaitOne(_standardTimeoutUnit); - Assert.That(_blockTree.BestSuggestedHeader!.Hash, Is.EqualTo(miner1Tree.BestSuggestedHeader!.Hash), "client agrees with miner after split"); + Assert.That(_blockTree.BestSuggestedHeader.Hash, Is.EqualTo(miner1Tree.BestSuggestedHeader.Hash), "client agrees with miner after split"); } [Test] @@ -280,7 +270,7 @@ public void Can_sync_on_split_of_length_6() ISyncPeer miner1 = new SyncPeerMock(miner1Tree); ManualResetEvent resetEvent = new(false); - _synchronizer.SyncEvent += (_, args) => + _synchronizer.SyncEvent += (sender, args) => { if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed) resetEvent.Set(); }; @@ -291,7 +281,7 @@ public void Can_sync_on_split_of_length_6() resetEvent.WaitOne(_standardTimeoutUnit); - Assert.That(_blockTree.BestSuggestedHeader!.Hash, Is.EqualTo(miner1Tree.BestSuggestedHeader!.Hash), "client agrees with miner before split"); + Assert.That(_blockTree.BestSuggestedHeader.Hash, Is.EqualTo(miner1Tree.BestSuggestedHeader.Hash), "client agrees with miner before split"); miner1Tree.AddBranch(7, 0, 1); @@ -299,7 +289,7 @@ public void Can_sync_on_split_of_length_6() resetEvent.Reset(); - _syncServer.AddNewBlock(miner1Tree.RetrieveHeadBlock()!, miner1); + _syncServer.AddNewBlock(miner1Tree.RetrieveHeadBlock(), miner1); resetEvent.WaitOne(_standardTimeoutUnit); @@ -314,7 +304,7 @@ public async Task Does_not_do_full_sync_when_not_needed() ISyncPeer miner1 = new SyncPeerMock(minerTree); AutoResetEvent resetEvent = new(false); - _synchronizer.SyncEvent += (_, args) => + _synchronizer.SyncEvent += (sender, args) => { if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed) resetEvent.Set(); }; @@ -324,9 +314,9 @@ public async Task Does_not_do_full_sync_when_not_needed() _pool.AddPeer(miner1); resetEvent.WaitOne(_standardTimeoutUnit); - Assert.That(_blockTree.BestSuggestedHeader!.Hash, Is.EqualTo(minerTree.BestSuggestedHeader!.Hash), "client agrees with miner before split"); + Assert.That(_blockTree.BestSuggestedHeader.Hash, Is.EqualTo(minerTree.BestSuggestedHeader.Hash), "client agrees with miner before split"); - Block newBlock = Build.A.Block.WithParent(minerTree.Head!).TestObject; + Block newBlock = Build.A.Block.WithParent(minerTree.Head).TestObject; minerTree.SuggestBlock(newBlock); minerTree.UpdateMainChain(newBlock); @@ -352,7 +342,7 @@ public async Task Does_not_do_full_sync_when_not_needed_with_split() ISyncPeer miner1 = new SyncPeerMock(minerTree); AutoResetEvent resetEvent = new(false); - _synchronizer.SyncEvent += (_, args) => + _synchronizer.SyncEvent += (sender, args) => { if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed) resetEvent.Set(); }; @@ -362,9 +352,9 @@ public async Task Does_not_do_full_sync_when_not_needed_with_split() _pool.AddPeer(miner1); resetEvent.WaitOne(_standardTimeoutUnit); - Assert.That(_blockTree.BestSuggestedHeader!.Hash, Is.EqualTo(minerTree.BestSuggestedHeader!.Hash), "client agrees with miner before split"); + Assert.That(_blockTree.BestSuggestedHeader.Hash, Is.EqualTo(minerTree.BestSuggestedHeader.Hash), "client agrees with miner before split"); - Block newBlock = Build.A.Block.WithParent(minerTree.Head!).TestObject; + Block newBlock = Build.A.Block.WithParent(minerTree.Head).TestObject; minerTree.SuggestBlock(newBlock); minerTree.UpdateMainChain(newBlock); @@ -386,23 +376,21 @@ public async Task Does_not_do_full_sync_when_not_needed_with_split() public void Can_retrieve_node_values() { _stateDb.Set(TestItem.KeccakA, TestItem.RandomDataA); - byte[]?[] data = _syncServer.GetNodeData(new[] { TestItem.KeccakA, TestItem.KeccakB }); - - Assert.That(data, Is.Not.Null); - Assert.That(data.Length, Is.EqualTo(2), "data.Length"); - Assert.That(data[0], Is.EqualTo(TestItem.RandomDataA), "data[0]"); - Assert.That(data[1], Is.EqualTo(null), "data[1]"); + byte[][] values = _syncServer.GetNodeData(new[] { TestItem.KeccakA, TestItem.KeccakB }); + Assert.That(values.Length, Is.EqualTo(2), "data.Length"); + Assert.That(values[0], Is.EqualTo(TestItem.RandomDataA), "data[0]"); + Assert.That(values[1], Is.EqualTo(null), "data[1]"); } [Test] public void Can_retrieve_empty_receipts() { _blockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(2).TestObject; - Block? block0 = _blockTree.FindBlock(0, BlockTreeLookupOptions.None); - Block? block1 = _blockTree.FindBlock(1, BlockTreeLookupOptions.None); + Block block0 = _blockTree.FindBlock(0, BlockTreeLookupOptions.None); + Block block1 = _blockTree.FindBlock(1, BlockTreeLookupOptions.None); - _syncServer.GetReceipts(block0!.Hash!).Should().HaveCount(0); - _syncServer.GetReceipts(block1!.Hash!).Should().HaveCount(0); + _syncServer.GetReceipts(block0.Hash).Should().HaveCount(0); + _syncServer.GetReceipts(block1.Hash).Should().HaveCount(0); _syncServer.GetReceipts(TestItem.KeccakA).Should().HaveCount(0); } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/Extensions.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/Extensions.cs index 178e4ac54a6..2d044812c6a 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/Extensions.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/Extensions.cs @@ -1,6 +1,9 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; using Nethermind.Synchronization.ParallelSync; using NSubstitute; using static Nethermind.Synchronization.Test.ParallelSync.MultiSyncModeSelectorTestsBase; diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorFastSyncTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorFastSyncTests.cs index fdcf1180d56..e366cd6b1c0 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorFastSyncTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorFastSyncTests.cs @@ -1,8 +1,11 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.Linq; +using System.Text; +using System.Threading.Tasks; using FluentAssertions; using Nethermind.Blockchain.Synchronization; using Nethermind.Core; @@ -77,17 +80,6 @@ public void Load_from_db() .TheSyncModeShouldBe(SyncMode.DbLoad); } - [Test] - public void Load_from_without_merge_sync_pivot_resolved() - { - Scenario.GoesLikeThis(_needToWaitForHeaders) - .WhenMergeSyncPivotNotResolvedYet() - .WhateverThePeerPoolLooks() - .WhenThisNodeIsLoadingBlocksFromDb() - .ThenInAnyFastSyncConfiguration() - .TheSyncModeShouldBe(SyncMode.DbLoad | SyncMode.UpdatingPivot); - } - [Test] public void Simple_archive() { @@ -614,7 +606,7 @@ public void Switch_correctly_from_full_sync_to_state_nodes_catch_up() syncPeers.Add(syncPeer); ISyncPeerPool syncPeerPool = Substitute.For(); - IEnumerable peerInfos = syncPeers.Select(p => new PeerInfo(p)).ToArray(); + IEnumerable peerInfos = syncPeers.Select(p => new PeerInfo(p)); syncPeerPool.InitializedPeers.Returns(peerInfos); syncPeerPool.AllPeers.Returns(peerInfos); @@ -632,7 +624,7 @@ public void Switch_correctly_from_full_sync_to_state_nodes_catch_up() { long number = header.Number + i; syncPeer.HeadNumber.Returns(number); - syncPeer.TotalDifficulty.Returns(header.TotalDifficulty!.Value + i); + syncPeer.TotalDifficulty.Returns(header.TotalDifficulty.Value + i); syncProgressResolver.FindBestHeader().Returns(number); syncProgressResolver.FindBestFullBlock().Returns(number); selector.Update(); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs index eca3ae733e2..4f2ee0f0b5e 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs @@ -10,12 +10,14 @@ using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Synchronization.ParallelSync; using Nethermind.Synchronization.Peers; using NSubstitute; +using NUnit.Framework; namespace Nethermind.Synchronization.Test.ParallelSync { @@ -25,33 +27,17 @@ public static class Scenario { public const long FastSyncCatchUpHeightDelta = 64; - public static BlockHeader Pivot { get; } = Build.A.Block - .WithDifficulty(1) - .WithTotalDifficulty((UInt256)1024) - .WithNumber(1024) - .TestObject.Header; + public static BlockHeader Pivot { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty((UInt256)1024).WithNumber(1024).TestObject.Header; - public static BlockHeader MidWayToPivot { get; } = Build.A.Block - .WithDifficulty(1) - .WithTotalDifficulty((UInt256)512) - .WithNumber(512) - .TestObject.Header; + public static BlockHeader MidWayToPivot { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty((UInt256)512).WithNumber(512).TestObject.Header; - public static BlockHeader ChainHead { get; } = Build.A.Block - .WithDifficulty(1) - .WithTotalDifficulty(Pivot.TotalDifficulty + 2048) - .WithNumber(Pivot.Number + 2048) - .TestObject.Header; + public static BlockHeader ChainHead { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty(Pivot.TotalDifficulty + 2048).WithNumber(Pivot.Number + 2048).TestObject.Header; public static BlockHeader ChainHeadWrongDifficulty { get { - BlockHeader header = Build.A.Block - .WithDifficulty(1) - .WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 128) - .WithNumber(Pivot.Number + 2048) - .TestObject.Header; + BlockHeader header = Build.A.Block.WithDifficulty(1).WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 128).WithNumber(Pivot.Number + 2048).TestObject.Header; header.Hash = ChainHead.Hash; return header; } @@ -67,53 +53,21 @@ public static BlockHeader ChainHeadParentWrongDifficulty } } - public static BlockHeader FutureHead { get; } = Build.A.Block - .WithDifficulty(1) - .WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 128) - .WithNumber(Pivot.Number + 2048 + 128) - .TestObject.Header; - - public static BlockHeader SlightlyFutureHead { get; } = Build.A.Block - .WithDifficulty(1) - .WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 4) - .WithNumber(Pivot.Number + 2048 + 4) - .TestObject.Header; - - public static BlockHeader SlightlyFutureHeadWithFastSyncLag { get; } = Build.A.Block - .WithDifficulty(1) - .WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 4) - .WithNumber(ChainHead.Number + MultiSyncModeSelector.FastSyncLag + 1) - .TestObject.Header; - - public static BlockHeader MaliciousPrePivot { get; } = Build.A.Block - .WithDifficulty(1) - .WithTotalDifficulty((UInt256)1000000) - .WithNumber(512) - .TestObject.Header; - - public static BlockHeader NewBetterBranchWithLowerNumber { get; } = Build.A.Block - .WithDifficulty(1) - .WithTotalDifficulty((UInt256)1000000) - .WithNumber(ChainHead.Number - 16) - .TestObject.Header; - - public static BlockHeader ValidGenesis { get; } = Build.A.Block - .WithDifficulty(1) - .WithTotalDifficulty(UInt256.One) - .Genesis - .TestObject.Header; - - public static BlockHeader InvalidGenesis { get; } = Build.A.Block - .WithDifficulty(1) - .WithTotalDifficulty(UInt256.One) - .Genesis - .TestObject.Header; - - public static BlockHeader InvalidGenesisWithHighTotalDifficulty { get; } = Build.A.Block - .Genesis - .WithDifficulty((UInt256)1000000) - .WithTotalDifficulty((UInt256)1000000) - .TestObject.Header; + public static BlockHeader FutureHead { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 128).WithNumber(Pivot.Number + 2048 + 128).TestObject.Header; + + public static BlockHeader SlightlyFutureHead { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 4).WithNumber(Pivot.Number + 2048 + 4).TestObject.Header; + + public static BlockHeader SlightlyFutureHeadWithFastSyncLag { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 4).WithNumber(ChainHead.Number + MultiSyncModeSelector.FastSyncLag + 1).TestObject.Header; + + public static BlockHeader MaliciousPrePivot { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty((UInt256)1000000).WithNumber(512).TestObject.Header; + + public static BlockHeader NewBetterBranchWithLowerNumber { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty((UInt256)1000000).WithNumber(ChainHead.Number - 16).TestObject.Header; + + public static BlockHeader ValidGenesis { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty(UInt256.One).Genesis.TestObject.Header; + + public static BlockHeader InvalidGenesis { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty(UInt256.One).Genesis.TestObject.Header; + + public static BlockHeader InvalidGenesisWithHighTotalDifficulty { get; set; } = Build.A.Block.Genesis.WithDifficulty((UInt256)1000000).WithTotalDifficulty((UInt256)1000000).TestObject.Header; public static IEnumerable ScenarioHeaders { @@ -147,19 +101,20 @@ public class ScenarioBuilder private readonly List _peers = new(); private bool _needToWaitForHeaders; - public ISyncPeerPool SyncPeerPool { get; set; } = null!; + public ISyncPeerPool SyncPeerPool { get; set; } - public ISyncProgressResolver SyncProgressResolver { get; set; } = null!; + public ISyncProgressResolver SyncProgressResolver { get; set; } - public ISyncConfig SyncConfig { get; } = new SyncConfig(); + public ISyncConfig SyncConfig { get; set; } = new SyncConfig(); public IBeaconSyncStrategy BeaconSyncStrategy { get; set; } = No.BeaconSync; private void SetDefaults() { SyncPeerPool = Substitute.For(); - SyncPeerPool.InitializedPeers.Returns(_peers.Select(p => new PeerInfo(p))); - SyncPeerPool.AllPeers.Returns(_peers.Select(p => new PeerInfo(p))); + var peerInfos = _peers.Select(p => new PeerInfo(p)); + SyncPeerPool.InitializedPeers.Returns(peerInfos); + SyncPeerPool.AllPeers.Returns(peerInfos); SyncProgressResolver = Substitute.For(); SyncProgressResolver.ChainDifficulty.Returns(ValidGenesis.TotalDifficulty ?? 0); @@ -861,11 +816,16 @@ void Test() { foreach (Func configSetups in _configActions) { - syncProgressSetup.Invoke(); - peeringSetup.Invoke(); - configSetups.Invoke(); - + string syncProgressSetupName = syncProgressSetup.Invoke(); + string peeringSetupName = peeringSetup.Invoke(); + string configSetupName = configSetups.Invoke(); + + // Console.WriteLine("====================="); + // Console.WriteLine(syncProgressSetupName); + // Console.WriteLine(peeringSetupName); + // Console.WriteLine(configSetupName); Test(); + // Console.WriteLine("====================="); } } } @@ -876,21 +836,6 @@ public ScenarioBuilder WhenConsensusRequiresToWaitForHeaders(bool needToWaitForH _needToWaitForHeaders = needToWaitForHeaders; return this; } - - public ScenarioBuilder WhenMergeSyncPivotNotResolvedYet() - { - _syncProgressSetups.Add( - () => - { - SyncConfig.MaxAttemptsToUpdatePivot = 3; - BeaconSyncStrategy = Substitute.For(); - BeaconSyncStrategy.GetFinalizedHash().Returns(TestItem.KeccakA); - return "merge sync pivot not resolved yet"; - } - ); - - return this; - } } public static ScenarioBuilder GoesLikeThis(bool needToWaitForHeaders) => diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTestsBase.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTestsBase.cs index 91a01c85496..57bcb4ebd15 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTestsBase.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTestsBase.cs @@ -1,7 +1,20 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using Nethermind.Blockchain.Synchronization; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Test.Builders; +using Nethermind.Int256; +using Nethermind.Logging; using Nethermind.Synchronization.ParallelSync; +using Nethermind.Synchronization.Peers; +using NSubstitute; +using NUnit.Framework; namespace Nethermind.Synchronization.Test.ParallelSync { diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs index bdd075712c3..30700f5f208 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs @@ -9,6 +9,7 @@ using FluentAssertions; using Nethermind.Blockchain; using Nethermind.Blockchain.Synchronization; +using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Int256; using Nethermind.Logging; @@ -62,7 +63,7 @@ public void ReportNoSyncProgress(PeerInfo peerInfo, AllocationContexts contexts) { } - public void ReportBreachOfProtocol(PeerInfo peerInfo, DisconnectReason disconnectReason, string details) + public void ReportBreachOfProtocol(PeerInfo peerInfo, InitiateDisconnectReason initiateDisconnectReason, string details) { } @@ -106,13 +107,13 @@ public Task StopAsync() return Task.CompletedTask; } - public PeerInfo? GetPeer(Node node) + public PeerInfo GetPeer(Node node) { return null; } - public event EventHandler NotifyPeerBlock = delegate { }; - public event EventHandler PeerRefreshed = delegate { }; + public event EventHandler NotifyPeerBlock; + public event EventHandler PeerRefreshed; } private class TestBatch @@ -125,7 +126,7 @@ public TestBatch(int start, int length) public int Start { get; } public int Length { get; } - public int[]? Result { get; set; } + public int[] Result { get; set; } } private class TestDownloader : ISyncDownloader @@ -159,12 +160,15 @@ public TestSyncFeed(bool isMultiFeed = true, int max = 64) Max = max; } - public int Max { get; } - public int HighestRequested { get; private set; } + public int Max; - public readonly HashSet _results = new(); - private readonly ConcurrentQueue _returned = new(); - private readonly ManualResetEvent _responseLock = new ManualResetEvent(true); + public int HighestRequested; + + public HashSet _results = new(); + + private ConcurrentQueue _returned = new(); + + private ManualResetEvent _responseLock = new ManualResetEvent(true); public void LockResponse() { @@ -176,7 +180,7 @@ public void UnlockResponse() _responseLock.Set(); } - public override SyncResponseHandlingResult HandleResponse(TestBatch response, PeerInfo? peer = null) + public override SyncResponseHandlingResult HandleResponse(TestBatch response, PeerInfo peer = null) { _responseLock.WaitOne(); if (response.Result is null) @@ -208,7 +212,7 @@ public override SyncResponseHandlingResult HandleResponse(TestBatch response, Pe public override async Task PrepareRequest(CancellationToken token = default) { TestBatch testBatch; - if (_returned.TryDequeue(out TestBatch? returned)) + if (_returned.TryDequeue(out TestBatch returned)) { Console.WriteLine("Sending previously failed batch"); testBatch = returned; @@ -228,7 +232,7 @@ public override async Task PrepareRequest(CancellationToken token = d Finish(); } - return null!; + return null; } lock (_results) @@ -285,7 +289,7 @@ public async Task Test_release_before_processing_complete(bool isMultiSync, int new StaticPeerAllocationStrategyFactory(FirstFree.Instance), LimboLogs.Instance); - Task _ = dispatcher.Start(CancellationToken.None); + Task executorTask = dispatcher.Start(CancellationToken.None); syncFeed.Activate(); await Task.Delay(100); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncedTxGossipPolicyTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncedTxGossipPolicyTests.cs deleted file mode 100644 index d811744d16e..00000000000 --- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncedTxGossipPolicyTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Synchronization.ParallelSync; -using Nethermind.TxPool; -using NUnit.Framework; - -namespace Nethermind.Synchronization.Test.ParallelSync; - -public class SyncedTxGossipPolicyTests -{ - [TestCase(SyncMode.FastSync, ExpectedResult = false)] - [TestCase(SyncMode.SnapSync, ExpectedResult = false)] - [TestCase(SyncMode.StateNodes, ExpectedResult = false)] - [TestCase(SyncMode.FastSync | SyncMode.StateNodes, ExpectedResult = false)] - [TestCase(SyncMode.FastHeaders, ExpectedResult = false)] - [TestCase(SyncMode.BeaconHeaders, ExpectedResult = false)] - [TestCase(SyncMode.FastHeaders | SyncMode.BeaconHeaders | SyncMode.SnapSync, ExpectedResult = false)] - [TestCase(SyncMode.WaitingForBlock, ExpectedResult = true)] - [TestCase(SyncMode.FastBodies | SyncMode.WaitingForBlock, ExpectedResult = true)] - [TestCase(SyncMode.FastReceipts | SyncMode.WaitingForBlock, ExpectedResult = true)] - [TestCase(SyncMode.FastBodies | SyncMode.FastSync, ExpectedResult = false)] - [TestCase(SyncMode.Full, ExpectedResult = false)] - [TestCase(SyncMode.DbLoad, ExpectedResult = false)] - [TestCase(SyncMode.Disconnected, ExpectedResult = false)] - [TestCase(SyncMode.UpdatingPivot, ExpectedResult = false)] - public bool can_gossip(SyncMode mode) => - ((ITxGossipPolicy)new SyncedTxGossipPolicy(new StaticSelector(mode))).ShouldListenToGossippedTransactions; -} diff --git a/src/Nethermind/Nethermind.Synchronization.Test/PeerInfoAllocationTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/PeerInfoAllocationTests.cs index 126ea4e7593..0f5be760d09 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/PeerInfoAllocationTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/PeerInfoAllocationTests.cs @@ -6,6 +6,7 @@ using System.Collections; using FluentAssertions; using Nethermind.Blockchain.Synchronization; +using Nethermind.Network; using Nethermind.Stats.Model; using Nethermind.Synchronization.Peers; using NSubstitute; diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs index f702e409258..17b6b773998 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using FluentAssertions; using Nethermind.Blockchain; -using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Db; using Nethermind.Logging; @@ -22,7 +21,7 @@ public class ProgressTrackerTests public async Task Did_not_have_race_issue() { BlockTree blockTree = Build.A.BlockTree().WithBlocks(Build.A.Block.TestObject).TestObject; - ProgressTracker progressTracker = new(blockTree, new MemDb(), LimboLogs.Instance); + ProgressTracker progressTracker = new ProgressTracker(blockTree, new MemDb(), LimboLogs.Instance); progressTracker.EnqueueStorageRange(new StorageRange() { Accounts = Array.Empty(), @@ -60,79 +59,29 @@ public void Will_create_multiple_get_address_range_request() (SnapSyncBatch request, bool finished) = progressTracker.GetNextRequest(); request.AccountRangeRequest.Should().NotBeNull(); request.AccountRangeRequest!.StartingHash.Bytes[0].Should().Be(0); - request.AccountRangeRequest.LimitHash!.Value.Bytes[0].Should().Be(64); + request.AccountRangeRequest.LimitHash.Value.Bytes[0].Should().Be(64); finished.Should().BeFalse(); (request, finished) = progressTracker.GetNextRequest(); request.AccountRangeRequest.Should().NotBeNull(); request.AccountRangeRequest!.StartingHash.Bytes[0].Should().Be(64); - request.AccountRangeRequest.LimitHash!.Value.Bytes[0].Should().Be(128); + request.AccountRangeRequest.LimitHash.Value.Bytes[0].Should().Be(128); finished.Should().BeFalse(); (request, finished) = progressTracker.GetNextRequest(); request.AccountRangeRequest.Should().NotBeNull(); request.AccountRangeRequest!.StartingHash.Bytes[0].Should().Be(128); - request.AccountRangeRequest.LimitHash!.Value.Bytes[0].Should().Be(192); + request.AccountRangeRequest.LimitHash.Value.Bytes[0].Should().Be(192); finished.Should().BeFalse(); (request, finished) = progressTracker.GetNextRequest(); request.AccountRangeRequest.Should().NotBeNull(); request.AccountRangeRequest!.StartingHash.Bytes[0].Should().Be(192); - request.AccountRangeRequest.LimitHash!.Value.Bytes[0].Should().Be(255); + request.AccountRangeRequest.LimitHash.Value.Bytes[0].Should().Be(255); finished.Should().BeFalse(); (request, finished) = progressTracker.GetNextRequest(); request.Should().BeNull(); finished.Should().BeFalse(); } - - [Test] - public void Will_deque_code_request_if_high_even_if_storage_queue_is_not_empty() - { - BlockTree blockTree = Build.A.BlockTree().WithBlocks(Build.A.Block.TestObject).TestObject; - ProgressTracker progressTracker = new ProgressTracker(blockTree, new MemDb(), LimboLogs.Instance); - - for (int i = 0; i < ProgressTracker.HIGH_STORAGE_QUEUE_SIZE - 1; i++) - { - progressTracker.EnqueueAccountStorage(new PathWithAccount() - { - Path = TestItem.ValueKeccaks[0] - }); - } - - for (int i = 0; i < ProgressTracker.HIGH_CODES_QUEUE_SIZE; i++) - { - progressTracker.EnqueueCodeHashes(new[] { TestItem.ValueKeccaks[0] }); - } - - (SnapSyncBatch request, bool _) = progressTracker.GetNextRequest(); - - request.CodesRequest.Should().NotBeNull(); - request.StorageRangeRequest.Should().BeNull(); - } - - [Test] - public void Will_deque_storage_request_if_high() - { - BlockTree blockTree = Build.A.BlockTree().WithBlocks(Build.A.Block.TestObject).TestObject; - ProgressTracker progressTracker = new ProgressTracker(blockTree, new MemDb(), LimboLogs.Instance); - - for (int i = 0; i < ProgressTracker.HIGH_STORAGE_QUEUE_SIZE; i++) - { - progressTracker.EnqueueAccountStorage(new PathWithAccount() - { - Path = TestItem.ValueKeccaks[0] - }); - } - - for (int i = 0; i < ProgressTracker.HIGH_CODES_QUEUE_SIZE; i++) - { - progressTracker.EnqueueCodeHashes(new[] { TestItem.ValueKeccaks[0] }); - } - - (SnapSyncBatch request, bool _) = progressTracker.GetNextRequest(); - - request.CodesRequest.Should().BeNull(); - request.StorageRangeRequest.Should().NotBeNull(); - } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/RecreateStateFromStorageRangesTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/RecreateStateFromStorageRangesTests.cs index fae00f8deda..b974eb4bb8d 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/RecreateStateFromStorageRangesTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/RecreateStateFromStorageRangesTests.cs @@ -3,14 +3,23 @@ #nullable disable +using System; +using System.Collections.Generic; using System.Linq; +using Nethermind.Blockchain; +using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Db; +using Nethermind.Int256; using Nethermind.Logging; +using Nethermind.Serialization.Rlp; using Nethermind.State; using Nethermind.State.Proofs; +using Nethermind.State.Snap; using Nethermind.Synchronization.SnapSync; +using Nethermind.Trie; using Nethermind.Trie.Pruning; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerMock.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerMock.cs index 52018d6f79a..5ef61c22e10 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerMock.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerMock.cs @@ -18,7 +18,6 @@ namespace Nethermind.Synchronization.Test { public class SyncPeerMock : ISyncPeer { - public string Name => "Mock"; private readonly IBlockTree _remoteTree; private readonly ISyncServer? _remoteSyncServer; private readonly TaskCompletionSource _closeTaskCompletionSource = new(); @@ -64,21 +63,21 @@ private void RunQueue() public Node Node { get; } - private Node LocalNode { get; } - public byte ProtocolVersion { get; } = default; - public string ProtocolCode { get; } = null!; + public Node LocalNode { get; } public string ClientId => Node.ClientId; public Keccak HeadHash { get; set; } public long HeadNumber { get; set; } public UInt256 TotalDifficulty { get; set; } public bool IsInitialized { get; set; } public bool IsPriority { get; set; } + public byte ProtocolVersion { get; } + public string ProtocolCode { get; } - public void Disconnect(DisconnectReason reason, string details) + public void Disconnect(InitiateDisconnectReason reason, string details) { } - public Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) + public Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) { BlockBody[] result = new BlockBody[blockHashes.Count]; for (int i = 0; i < blockHashes.Count; i++) @@ -87,7 +86,7 @@ public Task GetBlockBodies(IReadOnlyList blockHashes, result[i] = new BlockBody(block?.Transactions, block?.Uncles); } - return Task.FromResult(new OwnedBlockBodies(result)); + return Task.FromResult(result); } public Task GetBlockHeaders(Keccak blockHash, int maxBlocks, int skip, CancellationToken token) diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerPoolTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerPoolTests.cs index e4450756fb8..853ca21c7de 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerPoolTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerPoolTests.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using FluentAssertions; +using Microsoft.AspNetCore.Connections; using Nethermind.Blockchain; using Nethermind.Blockchain.Synchronization; using Nethermind.Core; @@ -29,10 +30,10 @@ public class SyncPeerPoolTests { private class Context : IAsyncDisposable { - public INodeStatsManager Stats { get; } - public IBlockTree BlockTree { get; } - public IBetterPeerStrategy PeerStrategy { get; } - public SyncPeerPool Pool { get; set; } + public INodeStatsManager Stats; + public IBlockTree BlockTree; + public IBetterPeerStrategy PeerStrategy; + public SyncPeerPool Pool; public Context() { @@ -50,33 +51,32 @@ public async ValueTask DisposeAsync() private class SimpleSyncPeerMock : ISyncPeer { - public string Name => "SimpleMock"; public SimpleSyncPeerMock(PublicKey publicKey, string description = "simple mock") { Node = new Node(publicKey, "127.0.0.1", 30303); ClientId = description; } - public Keccak HeadHash { get; set; } = null!; - public byte ProtocolVersion { get; } = default; - public string ProtocolCode { get; } = null!; public Node Node { get; } public string ClientId { get; } + public Keccak HeadHash { get; set; } public long HeadNumber { get; set; } public UInt256 TotalDifficulty { get; set; } = 1; public bool IsInitialized { get; set; } public bool IsPriority { get; set; } + public byte ProtocolVersion { get; } + public string ProtocolCode { get; } - public bool DisconnectRequested { get; private set; } + public bool DisconnectRequested { get; set; } - public void Disconnect(DisconnectReason reason, string details) + public void Disconnect(InitiateDisconnectReason reason, string details) { DisconnectRequested = true; } - public Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) + public Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) { - return Task.FromResult(new OwnedBlockBodies(Array.Empty())); + return Task.FromResult(Array.Empty()); } public Task GetBlockHeaders(long number, int maxBlocks, int skip, CancellationToken token) @@ -175,7 +175,7 @@ public async Task Cannot_add_when_not_started() public async Task Will_disconnect_one_when_at_max() { await using Context ctx = new(); - SimpleSyncPeerMock[] peers = await SetupPeers(ctx, 25); + var peers = await SetupPeers(ctx, 25); await WaitForPeersInitialization(ctx); ctx.Pool.DropUselessPeers(true); Assert.True(peers.Any(p => p.DisconnectRequested)); @@ -186,10 +186,10 @@ public async Task Will_disconnect_one_when_at_max() public async Task Will_disconnect_when_refresh_exception_is_not_cancelled(bool isExceptionOperationCanceled, bool isDisconnectRequested) { await using Context ctx = new(); - SimpleSyncPeerMock[] peers = await SetupPeers(ctx, 25); - SimpleSyncPeerMock peer = peers[0]; + var peers = await SetupPeers(ctx, 25); + var peer = peers[0]; - Exception refreshException = isExceptionOperationCanceled ? new OperationCanceledException() : new Exception(); + var refreshException = isExceptionOperationCanceled ? new OperationCanceledException() : new Exception(); ctx.Pool.ReportRefreshFailed(peer, "test with cancellation", refreshException); peer.DisconnectRequested.Should().Be(isDisconnectRequested); } @@ -203,7 +203,7 @@ public async Task Will_not_disconnect_any_priority_peer_if_their_amount_is_lower const int priorityPeersMaxCount = 25; await using Context ctx = new(); ctx.Pool = new SyncPeerPool(ctx.BlockTree, ctx.Stats, ctx.PeerStrategy, LimboLogs.Instance, peersMaxCount, priorityPeersMaxCount, 50); - SimpleSyncPeerMock[] peers = await SetupPeers(ctx, peersMaxCount); + var peers = await SetupPeers(ctx, peersMaxCount); // setting priority to all peers except one - peers[number] for (int i = 0; i < priorityPeersMaxCount; i++) @@ -225,7 +225,7 @@ public async Task Can_disconnect_priority_peer_if_their_amount_is_max() const int priorityPeersMaxCount = 25; await using Context ctx = new(); ctx.Pool = new SyncPeerPool(ctx.BlockTree, ctx.Stats, ctx.PeerStrategy, LimboLogs.Instance, peersMaxCount, priorityPeersMaxCount, 50); - SimpleSyncPeerMock[] peers = await SetupPeers(ctx, peersMaxCount); + var peers = await SetupPeers(ctx, peersMaxCount); foreach (SimpleSyncPeerMock peer in peers) { @@ -364,10 +364,10 @@ public async Task Can_refresh() { await using Context ctx = new(); ctx.Pool.Start(); - ISyncPeer? syncPeer = Substitute.For(); + var syncPeer = Substitute.For(); syncPeer.Node.Returns(new Node(TestItem.PublicKeyA, "127.0.0.1", 30303)); ctx.Pool.AddPeer(syncPeer); - ctx.Pool.RefreshTotalDifficulty(syncPeer, Keccak.Zero); + ctx.Pool.RefreshTotalDifficulty(syncPeer, null); await Task.Delay(100); Assert.That(() => @@ -396,12 +396,12 @@ public async Task Can_replace_peer_with_better() ctx.Pool.Start(); ctx.Pool.AddPeer(new SimpleSyncPeerMock(TestItem.PublicKeyA, "A")); await WaitForPeersInitialization(ctx); - SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BlocksSyncPeerAllocationStrategy(null)); + var allocation = await ctx.Pool.Allocate(new BlocksSyncPeerAllocationStrategy(null)); bool replaced = false; - allocation.Replaced += (_, _) => replaced = true; + allocation.Replaced += (sender, args) => replaced = true; ctx.Pool.AddPeer(new SimpleSyncPeerMock(TestItem.PublicKeyB, "B")); - await WaitFor(() => replaced); + await WaitFor(() => replaced, "peer to get replaced"); Assert.True(replaced); } @@ -417,7 +417,7 @@ public async Task Does_not_replace_with_a_worse_peer() await WaitForPeersInitialization(ctx); SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); bool replaced = false; - allocation.Replaced += (_, _) => replaced = true; + allocation.Replaced += (sender, args) => replaced = true; ctx.Pool.AddPeer(new SimpleSyncPeerMock(TestItem.PublicKeyB)); await WaitForPeersInitialization(ctx); @@ -436,7 +436,7 @@ public async Task Does_not_replace_if_too_small_percentage_change() await WaitForPeersInitialization(ctx); SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); bool replaced = false; - allocation.Replaced += (_, _) => replaced = true; + allocation.Replaced += (sender, args) => replaced = true; ctx.Pool.AddPeer(new SimpleSyncPeerMock(TestItem.PublicKeyB)); await WaitForPeersInitialization(ctx); @@ -455,7 +455,7 @@ public async Task Does_not_replace_on_small_difference_in_low_numbers() await WaitForPeersInitialization(ctx); SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); bool replaced = false; - allocation.Replaced += (_, _) => replaced = true; + allocation.Replaced += (sender, args) => replaced = true; ctx.Pool.AddPeer(new SimpleSyncPeerMock(TestItem.PublicKeyB)); await WaitForPeersInitialization(ctx); @@ -474,7 +474,7 @@ public async Task Can_stay_when_current_is_best() await WaitForPeersInitialization(ctx); SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); bool replaced = false; - allocation.Replaced += (_, _) => replaced = true; + allocation.Replaced += (sender, args) => replaced = true; ctx.Pool.AddPeer(new SimpleSyncPeerMock(TestItem.PublicKeyB)); await WaitForPeersInitialization(ctx); Assert.False(replaced); @@ -492,9 +492,9 @@ public async Task Can_list_all_peers() public async Task Can_borrow_peer() { await using Context ctx = new(); - SimpleSyncPeerMock[] peers = await SetupPeers(ctx, 1); + var peers = await SetupPeers(ctx, 1); - SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + var allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); Assert.That(allocation.Current?.SyncPeer, Is.SameAs(peers[0])); } @@ -503,9 +503,9 @@ public async Task Can_borrow_peer() public async Task Can_borrow_return_and_borrow_again() { await using Context ctx = new(); - SimpleSyncPeerMock[] peers = await SetupPeers(ctx, 1); + var peers = await SetupPeers(ctx, 1); - SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + var allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); ctx.Pool.Free(allocation); allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); ctx.Pool.Free(allocation); @@ -588,9 +588,9 @@ public async Task Initialized_peers() public async Task Report_invalid_invokes_disconnection() { await using Context ctx = new(); - SimpleSyncPeerMock[] _ = await SetupPeers(ctx, 3); - PeerInfo peerInfo = ctx.Pool.InitializedPeers.First(); - ctx.Pool.ReportBreachOfProtocol(peerInfo, DisconnectReason.Other, "issue details"); + var peers = await SetupPeers(ctx, 3); + var peerInfo = ctx.Pool.InitializedPeers.First(); + ctx.Pool.ReportBreachOfProtocol(peerInfo, InitiateDisconnectReason.Other, "issue details"); Assert.True(((SimpleSyncPeerMock)peerInfo.SyncPeer).DisconnectRequested); } @@ -599,10 +599,10 @@ public async Task Report_invalid_invokes_disconnection() public async Task Will_not_allocate_same_peer_to_two_allocations() { await using Context ctx = new(); - SimpleSyncPeerMock[] peers = await SetupPeers(ctx, 1); + var peers = await SetupPeers(ctx, 1); - SyncPeerAllocation allocation1 = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); - SyncPeerAllocation allocation2 = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + var allocation1 = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + var allocation2 = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); Assert.That(allocation1.Current?.SyncPeer, Is.SameAs(peers[0])); Assert.Null(allocation2.Current); @@ -612,9 +612,9 @@ public async Task Will_not_allocate_same_peer_to_two_allocations() public async Task Can_remove_borrowed_peer() { await using Context ctx = new(); - SimpleSyncPeerMock[] peers = await SetupPeers(ctx, 1); + var peers = await SetupPeers(ctx, 1); - SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BlocksSyncPeerAllocationStrategy(null)); + var allocation = await ctx.Pool.Allocate(new BlocksSyncPeerAllocationStrategy(null)); ctx.Pool.RemovePeer(peers[0]); Assert.Null(allocation.Current); @@ -624,7 +624,7 @@ public async Task Can_remove_borrowed_peer() public async Task Will_remove_peer_if_times_out_on_init() { await using Context ctx = new(); - SimpleSyncPeerMock peer = new SimpleSyncPeerMock(TestItem.PublicKeyA); + var peer = new SimpleSyncPeerMock(TestItem.PublicKeyA); peer.SetHeaderResponseTime(int.MaxValue); ctx.Pool.Start(); ctx.Pool.AddPeer(peer); @@ -637,12 +637,12 @@ public async Task Will_remove_peer_if_times_out_on_init() public async Task Can_remove_during_init() { await using Context ctx = new(); - SimpleSyncPeerMock peer = new SimpleSyncPeerMock(TestItem.PublicKeyA); + var peer = new SimpleSyncPeerMock(TestItem.PublicKeyA); peer.SetHeaderResponseTime(500); ctx.Pool.Start(); ctx.Pool.AddPeer(peer); - SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + var allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); ctx.Pool.RemovePeer(peer); Assert.That(allocation.Current, Is.EqualTo(null)); @@ -653,13 +653,13 @@ public async Task Can_remove_during_init() public async Task It_is_fine_to_fail_init() { await using Context ctx = new(); - SimpleSyncPeerMock peer = new SimpleSyncPeerMock(TestItem.PublicKeyA); + var peer = new SimpleSyncPeerMock(TestItem.PublicKeyA); peer.SetHeaderFailure(true); ctx.Pool.Start(); ctx.Pool.AddPeer(peer); await WaitForPeersInitialization(ctx); - SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + var allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); ctx.Pool.RemovePeer(peer); Assert.That(allocation.Current, Is.EqualTo(null)); @@ -672,7 +672,7 @@ public async Task Can_return() await using Context ctx = new(); await SetupPeers(ctx, 1); - SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + var allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); ctx.Pool.Free(allocation); } @@ -682,7 +682,7 @@ public async Task Does_not_fail_when_receiving_a_new_block_and_allocation_has_no await using Context ctx = new(); await SetupPeers(ctx, 1); - SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + var allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); allocation.Cancel(); ctx.BlockTree.NewHeadBlock += Raise.EventWith(new object(), new BlockEventArgs(Build.A.Block.WithTotalDifficulty(1L).TestObject)); @@ -694,7 +694,7 @@ public async Task Can_borrow_async_many() await using Context ctx = new(); await SetupPeers(ctx, 2); - Task[] allocationTasks = new Task[3]; + var allocationTasks = new Task[3]; for (int i = 0; i < allocationTasks.Length; i++) { allocationTasks[i] = ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true), AllocationContexts.All, 50); @@ -702,13 +702,13 @@ public async Task Can_borrow_async_many() await Task.WhenAll(allocationTasks); - SyncPeerAllocation[] allocations = allocationTasks.Select(t => t.Result).ToArray(); - SyncPeerAllocation[] successfulAllocations = allocations.Where(r => r.Current is not null).ToArray(); + var allocations = allocationTasks.Select(t => t.Result).ToArray(); + var successfulAllocations = allocations.Where(r => r.Current is not null).ToArray(); // we had only two peers and 3 borrow calls so only two are successful Assert.That(successfulAllocations.Length, Is.EqualTo(2)); - foreach (SyncPeerAllocation allocation in successfulAllocations) + foreach (var allocation in successfulAllocations) { // free allocated peers ctx.Pool.Free(allocation); @@ -723,7 +723,7 @@ public async Task Can_borrow_async_many() private int _pendingRequests; - private readonly Random _workRandomDelay = new(42); + private Random _workRandomDelay = new(42); private async Task DoWork(string desc, SyncPeerAllocation allocation) { @@ -763,7 +763,9 @@ public async Task Try_to_break_multithreaded() Task task = DoWork(iterationsLocal.ToString(), allocation); - Task _ = task.ContinueWith(t => +#pragma warning disable 4014 + task.ContinueWith(t => +#pragma warning restore 4014 { Console.WriteLine($"{iterationsLocal} Decrement on {t.IsCompleted}"); Interlocked.Decrement(ref _pendingRequests); @@ -781,7 +783,7 @@ public async Task Try_to_break_multithreaded() private async Task SetupPeers(Context ctx, int count) { - SimpleSyncPeerMock[] peers = new SimpleSyncPeerMock[count]; + var peers = new SimpleSyncPeerMock[count]; for (int i = 0; i < count; i++) { peers[i] = new SimpleSyncPeerMock(TestItem.PublicKeys[i]); @@ -800,10 +802,10 @@ private async Task SetupPeers(Context ctx, int count) private async Task WaitForPeersInitialization(Context ctx) { - await WaitFor(() => ctx.Pool.AllPeers.All(p => p.IsInitialized)); + await WaitFor(() => ctx.Pool.AllPeers.All(p => p.IsInitialized), "peers to initialize"); } - private async Task WaitFor(Func isConditionMet) + private async Task WaitFor(Func isConditionMet, string description = "condition to be met") { const int waitInterval = 50; for (int i = 0; i < 20; i++) diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncPeersReportTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncPeersReportTests.cs index 9d342d14a10..e1d4fc4447b 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncPeersReportTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncPeersReportTests.cs @@ -38,9 +38,9 @@ public void Can_write_one_uninitialized() { ISyncPeerPool syncPeerPool = Substitute.For(); - PeerInfo syncPeer = BuildPeer(false); + var syncPeer = BuildPeer(false); - PeerInfo[] peers = { syncPeer }; + var peers = new[] { syncPeer }; syncPeerPool.PeerCount.Returns(peers.Length); SyncPeersReport report = new(syncPeerPool, Substitute.For(), NoErrorLimboLogs.Instance); @@ -52,10 +52,10 @@ public void Can_write_one_uninitialized() public void Can_write_one_uninitialized_one_initialized() { ISyncPeerPool syncPeerPool = Substitute.For(); - PeerInfo syncPeer = BuildPeer(false); - PeerInfo syncPeer2 = BuildPeer(true); + var syncPeer = BuildPeer(false); + var syncPeer2 = BuildPeer(true); - PeerInfo[] peers = { syncPeer, syncPeer2 }; + var peers = new[] { syncPeer, syncPeer2 }; syncPeerPool.PeerCount.Returns(peers.Length); @@ -70,9 +70,9 @@ public void Can_write_report_update() ISyncPeerPool syncPeerPool = Substitute.For(); (PeerInfo syncPeer, StubSyncPeer syncPeerSyncPeer) = BuildPeerWithStubSyncPeer(false); - PeerInfo syncPeer2 = BuildPeer(true); + var syncPeer2 = BuildPeer(true); - PeerInfo[] peers = { syncPeer, syncPeer2 }; + var peers = new[] { syncPeer, syncPeer2 }; syncPeerPool.PeerCount.Returns(peers.Length); @@ -130,9 +130,9 @@ public void Can_write_report_update_with_allocations() { ISyncPeerPool syncPeerPool = Substitute.For(); (PeerInfo syncPeer, StubSyncPeer syncPeerSyncPeer) = BuildPeerWithStubSyncPeer(false); - PeerInfo syncPeer2 = BuildPeer(true); + var syncPeer2 = BuildPeer(true); - PeerInfo[] peers = { syncPeer, syncPeer2 }; + var peers = new[] { syncPeer, syncPeer2 }; syncPeerPool.PeerCount.Returns(peers.Length); syncPeerPool.AllPeers.Returns(peers); @@ -148,13 +148,13 @@ public void Can_write_report_update_with_allocations() [Test] public void PeerFormatIsCorrect() { - PeerInfo syncPeer = BuildPeer(false); + var syncPeer = BuildPeer(false); syncPeer.TryAllocate(AllocationContexts.All); - PeerInfo syncPeer2 = BuildPeer(true, direction: ConnectionDirection.In); + var syncPeer2 = BuildPeer(true, direction: ConnectionDirection.In); syncPeer2.PutToSleep(AllocationContexts.All, DateTime.Now); - PeerInfo[] peers = { syncPeer, syncPeer2 }; + var peers = new[] { syncPeer, syncPeer2 }; ISyncPeerPool syncPeerPool = Substitute.For(); syncPeerPool.PeerCount.Returns(peers.Length); @@ -168,7 +168,7 @@ public void PeerFormatIsCorrect() " [ ][HBRNSW][Peer|eth99| 9999| 127.0.0.1: 3030| In][ | | | | | ][]"; SyncPeersReport report = new(syncPeerPool, Substitute.For(), NoErrorLimboLogs.Instance); - string reportStr = report.MakeReportForPeers(peers, "== Header =="); + string reportStr = report.MakeReportForPeer(peers, "== Header =="); reportStr.Should().Be(expectedResult); } @@ -188,24 +188,27 @@ public StubSyncPeer(bool initialized, string protocolVersion, ISession session, } public override string Name { get; } - public override byte ProtocolVersion { get; } = default; - public override string ProtocolCode { get; } = default!; - public override int MessageIdSpaceSize { get; } = default; - protected override TimeSpan InitTimeout { get; } = default; - public override event EventHandler ProtocolInitialized = delegate { }; - public override event EventHandler SubprotocolRequested = delegate { }; + public override byte ProtocolVersion { get; } + public override string ProtocolCode { get; } + public override int MessageIdSpaceSize { get; } public override void Init() { throw new NotImplementedException(); } + + public override event EventHandler ProtocolInitialized; + public override event EventHandler SubprotocolRequested; + protected override TimeSpan InitTimeout { get; } public override void HandleMessage(ZeroPacket message) { throw new NotImplementedException(); } + public override void NotifyOfNewBlock(Block block, SendBlockMode mode) { throw new NotImplementedException(); } + protected override void OnDisposed() { throw new NotImplementedException(); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs index 60cbc1db2f4..9a2915b5f92 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs @@ -13,7 +13,6 @@ using Nethermind.Synchronization.SnapSync; using Nethermind.Trie.Pruning; using NSubstitute; -using NSubstitute.ReturnsExtensions; using NUnit.Framework; namespace Nethermind.Synchronization.Test @@ -28,14 +27,12 @@ public void Header_block_is_0_when_no_header_was_suggested() IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new() - { - PivotNumber = "1", - }; + SyncConfig syncConfig = new(); + syncConfig.PivotNumber = "1"; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); SyncProgressResolver syncProgressResolver = new(blockTree, receiptStorage, stateDb, NullTrieNodeResolver.Instance, progressTracker, syncConfig, LimboLogs.Instance); - blockTree.BestSuggestedHeader.ReturnsNull(); + blockTree.BestSuggestedHeader.Returns((BlockHeader)null); Assert.That(syncProgressResolver.FindBestHeader(), Is.EqualTo(0)); } @@ -45,14 +42,12 @@ public void Best_block_is_0_when_no_block_was_suggested() IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new() - { - PivotNumber = "1", - }; + SyncConfig syncConfig = new(); + syncConfig.PivotNumber = "1"; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); SyncProgressResolver syncProgressResolver = new(blockTree, receiptStorage, stateDb, NullTrieNodeResolver.Instance, progressTracker, syncConfig, LimboLogs.Instance); - blockTree.BestSuggestedBody.ReturnsNull(); + blockTree.BestSuggestedBody.Returns((Block)null); Assert.That(syncProgressResolver.FindBestFullBlock(), Is.EqualTo(0)); } @@ -62,17 +57,15 @@ public void Best_state_is_head_when_there_are_no_suggested_blocks() IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new() - { - PivotNumber = "1", - }; + SyncConfig syncConfig = new(); + syncConfig.PivotNumber = "1"; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); SyncProgressResolver syncProgressResolver = new(blockTree, receiptStorage, stateDb, NullTrieNodeResolver.Instance, progressTracker, syncConfig, LimboLogs.Instance); - Block head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; + var head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; blockTree.Head.Returns(head); blockTree.BestSuggestedHeader.Returns(head.Header); - stateDb[head.StateRoot!.Bytes] = new byte[] { 1 }; + stateDb[head.StateRoot.Bytes] = new byte[] { 1 }; Assert.That(syncProgressResolver.FindBestFullState(), Is.EqualTo(head.Number)); } @@ -82,21 +75,19 @@ public void Best_state_is_suggested_if_there_is_suggested_block_with_state() IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new() - { - PivotNumber = "1", - }; + SyncConfig syncConfig = new(); + syncConfig.PivotNumber = "1"; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); SyncProgressResolver syncProgressResolver = new(blockTree, receiptStorage, stateDb, NullTrieNodeResolver.Instance, progressTracker, syncConfig, LimboLogs.Instance); - Block head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; - BlockHeader suggested = Build.A.BlockHeader.WithNumber(6).WithStateRoot(TestItem.KeccakB).TestObject; + var head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; + var suggested = Build.A.BlockHeader.WithNumber(6).WithStateRoot(TestItem.KeccakB).TestObject; blockTree.Head.Returns(head); blockTree.BestSuggestedHeader.Returns(suggested); blockTree.FindHeader(Arg.Any(), BlockTreeLookupOptions.TotalDifficultyNotNeeded).Returns(head.Header); - stateDb[head.StateRoot!.Bytes] = new byte[] { 1 }; - stateDb[suggested.StateRoot!.Bytes] = new byte[] { 1 }; + stateDb[head.StateRoot.Bytes] = new byte[] { 1 }; + stateDb[suggested.StateRoot.Bytes] = new byte[] { 1 }; Assert.That(syncProgressResolver.FindBestFullState(), Is.EqualTo(suggested.Number)); } @@ -106,20 +97,18 @@ public void Best_state_is_head_if_there_is_suggested_block_without_state() IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new() - { - PivotNumber = "1", - }; + SyncConfig syncConfig = new(); + syncConfig.PivotNumber = "1"; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); SyncProgressResolver syncProgressResolver = new(blockTree, receiptStorage, stateDb, NullTrieNodeResolver.Instance, progressTracker, syncConfig, LimboLogs.Instance); - Block head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; - BlockHeader suggested = Build.A.BlockHeader.WithNumber(6).WithStateRoot(TestItem.KeccakB).TestObject; + var head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; + var suggested = Build.A.BlockHeader.WithNumber(6).WithStateRoot(TestItem.KeccakB).TestObject; blockTree.Head.Returns(head); blockTree.BestSuggestedHeader.Returns(suggested); - blockTree.FindHeader(Arg.Any(), BlockTreeLookupOptions.TotalDifficultyNotNeeded).Returns(head.Header); - stateDb[head.StateRoot!.Bytes] = new byte[] { 1 }; - stateDb[suggested.StateRoot!.Bytes] = null; + blockTree.FindHeader(Arg.Any(), BlockTreeLookupOptions.TotalDifficultyNotNeeded).Returns(head?.Header); + stateDb[head.StateRoot.Bytes] = new byte[] { 1 }; + stateDb[suggested.StateRoot.Bytes] = null; Assert.That(syncProgressResolver.FindBestFullState(), Is.EqualTo(head.Number)); } @@ -129,11 +118,9 @@ public void Is_fast_block_finished_returns_true_when_no_fast_block_sync_is_used( IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new() - { - FastBlocks = false, - PivotNumber = "1", - }; + SyncConfig syncConfig = new(); + syncConfig.FastBlocks = false; + syncConfig.PivotNumber = "1"; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); SyncProgressResolver syncProgressResolver = new(blockTree, receiptStorage, stateDb, NullTrieNodeResolver.Instance, progressTracker, syncConfig, LimboLogs.Instance); @@ -148,14 +135,12 @@ public void Is_fast_block_headers_finished_returns_false_when_headers_not_downlo IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new() - { - FastBlocks = true, - FastSync = true, - DownloadBodiesInFastSync = true, - DownloadReceiptsInFastSync = true, - PivotNumber = "1", - }; + SyncConfig syncConfig = new(); + syncConfig.FastBlocks = true; + syncConfig.FastSync = true; + syncConfig.DownloadBodiesInFastSync = true; + syncConfig.DownloadReceiptsInFastSync = true; + syncConfig.PivotNumber = "1"; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(2).WithStateRoot(TestItem.KeccakA).TestObject); @@ -170,14 +155,12 @@ public void Is_fast_block_bodies_finished_returns_false_when_blocks_not_download IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new() - { - FastBlocks = true, - FastSync = true, - DownloadBodiesInFastSync = true, - DownloadReceiptsInFastSync = true, - PivotNumber = "1", - }; + SyncConfig syncConfig = new(); + syncConfig.FastBlocks = true; + syncConfig.FastSync = true; + syncConfig.DownloadBodiesInFastSync = true; + syncConfig.DownloadReceiptsInFastSync = true; + syncConfig.PivotNumber = "1"; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); @@ -193,14 +176,12 @@ public void Is_fast_block_receipts_finished_returns_false_when_receipts_not_down IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new() - { - FastBlocks = true, - FastSync = true, - DownloadBodiesInFastSync = true, - DownloadReceiptsInFastSync = true, - PivotNumber = "1", - }; + SyncConfig syncConfig = new(); + syncConfig.FastBlocks = true; + syncConfig.FastSync = true; + syncConfig.DownloadBodiesInFastSync = true; + syncConfig.DownloadReceiptsInFastSync = true; + syncConfig.PivotNumber = "1"; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); @@ -218,13 +199,11 @@ public void Is_fast_block_bodies_finished_returns_true_when_bodies_not_downloade IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new() - { - FastBlocks = true, - DownloadBodiesInFastSync = false, - DownloadReceiptsInFastSync = true, - PivotNumber = "1", - }; + SyncConfig syncConfig = new(); + syncConfig.FastBlocks = true; + syncConfig.DownloadBodiesInFastSync = false; + syncConfig.DownloadReceiptsInFastSync = true; + syncConfig.PivotNumber = "1"; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); @@ -241,13 +220,11 @@ public void Is_fast_block_receipts_finished_returns_true_when_receipts_not_downl IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new() - { - FastBlocks = true, - DownloadBodiesInFastSync = true, - DownloadReceiptsInFastSync = false, - PivotNumber = "1", - }; + SyncConfig syncConfig = new(); + syncConfig.FastBlocks = true; + syncConfig.DownloadBodiesInFastSync = true; + syncConfig.DownloadReceiptsInFastSync = false; + syncConfig.PivotNumber = "1"; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncReportTest.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncReportTest.cs index 3c12bcd1ae9..b543dfbadc9 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncReportTest.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncReportTest.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Threading.Tasks; using Nethermind.Blockchain.Synchronization; using Nethermind.Core.Timers; @@ -23,7 +22,7 @@ public class SyncReportTest [TestCase(true, false)] [TestCase(true, true)] [TestCase(false, false)] - public void Smoke(bool fastSync, bool fastBlocks) + public async Task Smoke(bool fastSync, bool fastBlocks) { ISyncModeSelector selector = Substitute.For(); ISyncPeerPool pool = Substitute.For(); @@ -32,22 +31,20 @@ public void Smoke(bool fastSync, bool fastBlocks) ITimer timer = Substitute.For(); timerFactory.CreateTimer(Arg.Any()).Returns(timer); - Queue syncModes = new(); - syncModes.Enqueue(SyncMode.WaitingForBlock); - syncModes.Enqueue(SyncMode.FastSync); - syncModes.Enqueue(SyncMode.Full); - syncModes.Enqueue(SyncMode.FastBlocks); - syncModes.Enqueue(SyncMode.StateNodes); - syncModes.Enqueue(SyncMode.Disconnected); + Queue _syncModes = new(); + _syncModes.Enqueue(SyncMode.WaitingForBlock); + _syncModes.Enqueue(SyncMode.FastSync); + _syncModes.Enqueue(SyncMode.Full); + _syncModes.Enqueue(SyncMode.FastBlocks); + _syncModes.Enqueue(SyncMode.StateNodes); + _syncModes.Enqueue(SyncMode.Disconnected); - SyncConfig syncConfig = new() - { - FastBlocks = fastBlocks, - FastSync = fastSync, - }; + SyncConfig syncConfig = new(); + syncConfig.FastBlocks = fastBlocks; + syncConfig.FastSync = fastSync; SyncReport syncReport = new(pool, Substitute.For(), selector, syncConfig, Substitute.For(), LimboLogs.Instance, timerFactory); - selector.Current.Returns(_ => syncModes.Count > 0 ? syncModes.Dequeue() : SyncMode.Full); + selector.Current.Returns((ci) => _syncModes.Count > 0 ? _syncModes.Dequeue() : SyncMode.Full); timer.Elapsed += Raise.Event(); syncReport.FastBlocksHeaders.MarkEnd(); syncReport.FastBlocksBodies.MarkEnd(); @@ -59,7 +56,6 @@ public void Smoke(bool fastSync, bool fastBlocks) [TestCase(true)] public void Ancient_bodies_and_receipts_are_reported_correctly(bool setBarriers) { - CultureInfo.CurrentCulture = CultureInfo.InvariantCulture; ISyncModeSelector selector = Substitute.For(); ISyncPeerPool pool = Substitute.For(); pool.InitializedPeersCount.Returns(1); @@ -71,38 +67,36 @@ public void Ancient_bodies_and_receipts_are_reported_correctly(bool setBarriers) logger.IsInfo.Returns(true); logManager.GetClassLogger().Returns(logger); - Queue syncModes = new(); - syncModes.Enqueue(SyncMode.FastHeaders); - syncModes.Enqueue(SyncMode.FastBodies); - syncModes.Enqueue(SyncMode.FastReceipts); + Queue _syncModes = new(); + _syncModes.Enqueue(SyncMode.FastHeaders); + _syncModes.Enqueue(SyncMode.FastBodies); + _syncModes.Enqueue(SyncMode.FastReceipts); - SyncConfig syncConfig = new() - { - FastBlocks = true, - FastSync = true, - PivotNumber = "100", - }; + SyncConfig syncConfig = new(); + syncConfig.FastBlocks = true; + syncConfig.FastSync = true; + syncConfig.PivotNumber = "100"; if (setBarriers) { syncConfig.AncientBodiesBarrier = 30; syncConfig.AncientReceiptsBarrier = 35; } - SyncReport _ = new(pool, Substitute.For(), selector, syncConfig, Substitute.For(), logManager, timerFactory); + SyncReport syncReport = new(pool, Substitute.For(), selector, syncConfig, Substitute.For(), logManager, timerFactory); selector.Current.Returns(_ => SyncMode.FastHeaders | SyncMode.FastBodies | SyncMode.FastReceipts); timer.Elapsed += Raise.Event(); if (setBarriers) { - logger.Received(1).Info("Old Headers 0 / 100 ( 0.00 %) | queue 0 | current 0 Blk/s | total 0 Blk/s"); - logger.Received(1).Info("Old Bodies 0 / 70 ( 0.00 %) | queue 0 | current 0 Blk/s | total 0 Blk/s"); - logger.Received(1).Info("Old Receipts 0 / 65 ( 0.00 %) | queue 0 | current 0 Blk/s | total 0 Blk/s"); + logger.Received(1).Info("Old Headers 0 / 100 | queue 0 | current 0.00bps | total 0.00bps"); + logger.Received(1).Info("Old Bodies 0 / 70 | queue 0 | current 0.00bps | total 0.00bps"); + logger.Received(1).Info("Old Receipts 0 / 65 | queue 0 | current 0.00bps | total 0.00bps"); } else { - logger.Received(1).Info("Old Headers 0 / 100 ( 0.00 %) | queue 0 | current 0 Blk/s | total 0 Blk/s"); - logger.Received(1).Info("Old Bodies 0 / 100 ( 0.00 %) | queue 0 | current 0 Blk/s | total 0 Blk/s"); - logger.Received(1).Info("Old Receipts 0 / 100 ( 0.00 %) | queue 0 | current 0 Blk/s | total 0 Blk/s"); + logger.Received(1).Info("Old Headers 0 / 100 | queue 0 | current 0.00bps | total 0.00bps"); + logger.Received(1).Info("Old Bodies 0 / 100 | queue 0 | current 0.00bps | total 0.00bps"); + logger.Received(1).Info("Old Receipts 0 / 100 | queue 0 | current 0.00bps | total 0.00bps"); } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs index ef2a31e200c..4b6f51798cd 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs @@ -45,7 +45,7 @@ public void When_finding_hash_it_does_not_load_headers() { Context ctx = new(); ctx.BlockTree.FindHash(123).Returns(TestItem.KeccakA); - Keccak result = ctx.SyncServer.FindHash(123)!; + Keccak result = ctx.SyncServer.FindHash(123); ctx.BlockTree.DidNotReceive().FindHeader(Arg.Any(), Arg.Any()); ctx.BlockTree.DidNotReceive().FindHeader(Arg.Any(), Arg.Any()); @@ -105,7 +105,7 @@ public void Can_accept_new_valid_blocks(bool sealOk, bool validationOk, bool acc MainnetSpecProvider.Instance, LimboLogs.Instance); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); if (!accepted) { @@ -148,7 +148,7 @@ public void Can_accept_blocks_that_are_fine() MainnetSpecProvider.Instance, LimboLogs.Instance); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); @@ -161,39 +161,20 @@ public void Terminal_block_with_lower_td_should_not_change_best_suggested_but_sh Context ctx = new(); BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; BlockTree localBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; - TestSpecProvider testSpecProvider = new(London.Instance) - { - TerminalTotalDifficulty = 10_000_000, - }; + TestSpecProvider testSpecProvider = new(London.Instance); + testSpecProvider.TerminalTotalDifficulty = 10_000_000; - Block newBestLocalBlock = Build.A.Block - .WithNumber(localBlockTree.Head!.Number + 1) - .WithParent(localBlockTree.Head!).WithDifficulty(10_000_002L).TestObject; + Block newBestLocalBlock = Build.A.Block.WithNumber(localBlockTree.Head!.Number + 1).WithParent(localBlockTree.Head!).WithDifficulty(10_000_002L).TestObject; localBlockTree.SuggestBlock(newBestLocalBlock); - PoSSwitcher poSSwitcher = new( - new MergeConfig - { - TerminalTotalDifficulty = $"{testSpecProvider.TerminalTotalDifficulty}" - }, - new SyncConfig(), - new MemDb(), - localBlockTree, - testSpecProvider, - LimboLogs.Instance); + PoSSwitcher poSSwitcher = new(new MergeConfig() { TerminalTotalDifficulty = $"{testSpecProvider.TerminalTotalDifficulty}" }, new SyncConfig(), new MemDb(), localBlockTree, testSpecProvider, LimboLogs.Instance); HeaderValidator headerValidator = new( localBlockTree, Always.Valid, testSpecProvider, LimboLogs.Instance); - MergeHeaderValidator mergeHeaderValidator = new( - poSSwitcher, - headerValidator, - localBlockTree, - testSpecProvider, - Always.Valid, - LimboLogs.Instance); + MergeHeaderValidator mergeHeaderValidator = new(poSSwitcher, headerValidator, localBlockTree, testSpecProvider, Always.Valid, LimboLogs.Instance); BlockValidator blockValidator = new( Always.Valid, mergeHeaderValidator, @@ -230,13 +211,13 @@ public void Fake_total_difficulty_from_peer_does_not_trick_the_node(long ttd) BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; Context ctx = CreateMergeContext(9, (UInt256)ttd); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; - block.Header.TotalDifficulty = block.Header.TotalDifficulty * 2; + Block? block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); + block!.Header.TotalDifficulty *= 2; ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); Assert.That(block.Header.Hash, Is.EqualTo(ctx.LocalBlockTree.BestSuggestedHeader!.Hash)); - Block parentBlock = remoteBlockTree.FindBlock(8, BlockTreeLookupOptions.None)!; + Block? parentBlock = remoteBlockTree.FindBlock(8, BlockTreeLookupOptions.None); Assert.That(ctx.LocalBlockTree.BestSuggestedHeader.TotalDifficulty, Is.EqualTo(parentBlock.TotalDifficulty + block.Difficulty)); } @@ -248,10 +229,10 @@ public void Can_reject_block_POW_block_after_TTD(long ttd, bool sendFakeTd) BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; Context ctx = CreateMergeContext(9, (UInt256)ttd); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); if (sendFakeTd) { - block.Header.TotalDifficulty = block.Header.TotalDifficulty * 2; + block.Header.TotalDifficulty *= 2; } Assert.Throws(() => ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock)); @@ -264,19 +245,14 @@ public void Can_reject_block_POW_block_after_TTD(long ttd, bool sendFakeTd) public void Post_merge_blocks_wont_be_accepted_by_gossip(long ttd, bool sendFakeTd) { BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; - Block postMergeBlock = Build.A.Block - .WithDifficulty(0) - .WithParent(remoteBlockTree.Head!) - .WithTotalDifficulty(remoteBlockTree.Head!.TotalDifficulty) - .WithNonce(0u) - .TestObject; + Block postMergeBlock = Build.A.Block.WithDifficulty(0).WithParent(remoteBlockTree.Head).WithTotalDifficulty(remoteBlockTree.Head.TotalDifficulty).WithNonce(0u).TestObject; remoteBlockTree.SuggestBlock(postMergeBlock); Context ctx = CreateMergeContext(9, (UInt256)ttd); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); if (sendFakeTd) { - block.Header.TotalDifficulty = block.Header.TotalDifficulty * 2; + block.Header.TotalDifficulty *= 2; } ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); @@ -291,20 +267,15 @@ public void Post_merge_blocks_wont_be_accepted_by_gossip(long ttd, bool sendFake public void Can_inject_terminal_block_with_not_higher_td_than_head(long ttd, bool sendFakeTd, long difficulty) { BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; - Block terminalBlockWithLowerDifficulty = Build.A.Block - .WithDifficulty((UInt256)difficulty) - .WithParent(remoteBlockTree.Head!) - .WithGasLimit(remoteBlockTree.Head!.GasLimit + 1) - .WithTotalDifficulty(remoteBlockTree.Head.TotalDifficulty + (UInt256)difficulty) - .TestObject; + Block terminalBlockWithLowerDifficulty = Build.A.Block.WithDifficulty((UInt256)difficulty).WithParent(remoteBlockTree.Head).WithGasLimit(remoteBlockTree.Head.GasLimit + 1).WithTotalDifficulty(remoteBlockTree.Head.TotalDifficulty + (UInt256)difficulty).TestObject; remoteBlockTree.SuggestBlock(terminalBlockWithLowerDifficulty); Context ctx = CreateMergeContext(10, (UInt256)ttd); Assert.True(terminalBlockWithLowerDifficulty.IsTerminalBlock(ctx.SpecProvider)); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); if (sendFakeTd) { - block.Header.TotalDifficulty = block.Header.TotalDifficulty * 2; + block.Header.TotalDifficulty *= 2; } ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); @@ -318,19 +289,15 @@ public void Can_inject_terminal_block_with_not_higher_td_than_head(long ttd, boo public void Can_inject_terminal_block_with_higher_td_than_head(long ttd, bool sendFakeTd) { BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; - Block terminalBlockWithHigherTotalDifficulty = Build.A.Block - .WithDifficulty(1000010) - .WithParent(remoteBlockTree.Head!) - .WithTotalDifficulty(remoteBlockTree.Head!.TotalDifficulty + 1000010) - .TestObject; + Block terminalBlockWithHigherTotalDifficulty = Build.A.Block.WithDifficulty(1000010).WithParent(remoteBlockTree.Head).WithTotalDifficulty(remoteBlockTree.Head.TotalDifficulty + 1000010).TestObject; remoteBlockTree.SuggestBlock(terminalBlockWithHigherTotalDifficulty); Context ctx = CreateMergeContext(10, (UInt256)ttd); Assert.True(terminalBlockWithHigherTotalDifficulty.IsTerminalBlock(ctx.SpecProvider)); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; + Block? block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); if (sendFakeTd) { - block.Header.TotalDifficulty = block.Header.TotalDifficulty * 2; + block.Header.TotalDifficulty *= 2; } ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); @@ -344,69 +311,40 @@ public void Can_inject_terminal_block_with_higher_td_than_head(long ttd, bool se public void PostMerge_block_from_gossip_should_not_override_main_chain(long ttd) { BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; - Block poWBlockPostMerge = Build.A.Block - .WithDifficulty(1000010) - .WithParent(remoteBlockTree.Head!) - .WithTotalDifficulty(remoteBlockTree.Head!.TotalDifficulty + 1000010) - .TestObject; + Block poWBlockPostMerge = Build.A.Block.WithDifficulty(1000010).WithParent(remoteBlockTree.Head).WithTotalDifficulty(remoteBlockTree.Head.TotalDifficulty + 1000010).TestObject; remoteBlockTree.SuggestBlock(poWBlockPostMerge); Context ctx = CreateMergeContext(10, (UInt256)ttd); - Block newPostMergeBlock = Build.A.Block - .WithDifficulty(0) - .WithParent(ctx.LocalBlockTree.Head!) - .WithTotalDifficulty(ctx.LocalBlockTree.Head!.TotalDifficulty) - .TestObject; + Block newPostMergeBlock = Build.A.Block.WithDifficulty(0).WithParent(ctx.LocalBlockTree.Head).WithTotalDifficulty(ctx.LocalBlockTree.Head.TotalDifficulty).TestObject; ctx.LocalBlockTree.SuggestBlock(newPostMergeBlock); ctx.LocalBlockTree.UpdateMainChain(new[] { newPostMergeBlock }, true, true); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); Assert.That(ctx.LocalBlockTree.BestSuggestedHeader!.Number, Is.EqualTo(10)); ctx.LocalBlockTree.FindBlock(poWBlockPostMerge.Hash!, BlockTreeLookupOptions.None).Should().NotBeNull(); ctx.LocalBlockTree.BestSuggestedHeader!.Hash.Should().Be(newPostMergeBlock.Hash!); - ctx.LocalBlockTree.FindCanonicalBlockInfo(poWBlockPostMerge.Number).BlockHash.Should().NotBe(poWBlockPostMerge.Hash!); + ctx.LocalBlockTree.FindCanonicalBlockInfo(poWBlockPostMerge.Number).BlockHash.Should().NotBe(poWBlockPostMerge.Hash); } private Context CreateMergeContext(int blockTreeChainLength, UInt256 ttd) { Context ctx = new(); - TestSpecProvider testSpecProvider = new(London.Instance) - { - TerminalTotalDifficulty = ttd, - }; + TestSpecProvider testSpecProvider = new(London.Instance); + testSpecProvider.TerminalTotalDifficulty = ttd; Block genesis = Build.A.Block.Genesis.TestObject; BlockTree localBlockTree = Build.A.BlockTree(genesis, testSpecProvider).OfChainLength(blockTreeChainLength).TestObject; - PoSSwitcher poSSwitcher = new( - new MergeConfig - { - TerminalTotalDifficulty = $"{ttd}" - }, - new SyncConfig(), - new MemDb(), - localBlockTree, - testSpecProvider, - LimboLogs.Instance); - MergeSealEngine sealEngine = new( - new SealEngine(new NethDevSealEngine(), Always.Valid), - poSSwitcher, - new MergeSealValidator(poSSwitcher, Always.Valid), - LimboLogs.Instance); + PoSSwitcher poSSwitcher = new(new MergeConfig() { TerminalTotalDifficulty = $"{ttd}" }, new SyncConfig(), new MemDb(), localBlockTree, testSpecProvider, LimboLogs.Instance); + MergeSealEngine sealEngine = new(new SealEngine(new NethDevSealEngine(), Always.Valid), poSSwitcher, new MergeSealValidator(poSSwitcher, Always.Valid), LimboLogs.Instance); HeaderValidator headerValidator = new( localBlockTree, sealEngine, testSpecProvider, LimboLogs.Instance); - MergeHeaderValidator mergeHeaderValidator = new( - poSSwitcher, - headerValidator, - localBlockTree, - testSpecProvider, - Always.Valid, - LimboLogs.Instance); + MergeHeaderValidator mergeHeaderValidator = new(poSSwitcher, headerValidator, localBlockTree, testSpecProvider, Always.Valid, LimboLogs.Instance); InvalidChainTracker invalidChainTracker = new( poSSwitcher, @@ -480,14 +418,14 @@ public void Will_not_reject_block_with_bad_total_diff_but_will_reset_diff_to_nul MainnetSpecProvider.Instance, LimboLogs.Instance); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; - block.Header.TotalDifficulty = block.Header.TotalDifficulty * 2; + Block? block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); + block!.Header!.TotalDifficulty *= 2; ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); Assert.That(block.Header.Hash, Is.EqualTo(localBlockTree.BestSuggestedHeader!.Hash)); Block? parentBlock = remoteBlockTree.FindBlock(8, BlockTreeLookupOptions.None); - Assert.That(localBlockTree.BestSuggestedHeader.TotalDifficulty, Is.EqualTo(parentBlock!.TotalDifficulty + block.Difficulty)); + Assert.That(localBlockTree.BestSuggestedHeader.TotalDifficulty, Is.EqualTo(parentBlock.TotalDifficulty + block.Difficulty)); } [Test] @@ -513,7 +451,7 @@ public void Rejects_new_old_blocks() MainnetSpecProvider.Instance, LimboLogs.Instance); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); @@ -626,7 +564,7 @@ public async Task Broadcast_NewBlock_on_arrival_to_sqrt_of_peers([Values(1, 2, 3 .When(r => r.AddNewBlock(Arg.Is(b => b.Hash == remoteBlockTree.Head!.Hash), Arg.Any())) .Do(_ => count++); PeerInfo[] peers = Enumerable.Range(0, peerCount).Take(peerCount) - .Select(_ => new PeerInfo(new SyncPeerMock(remoteBlockTree, remoteSyncServer: remoteServer))) + .Select(k => new PeerInfo(new SyncPeerMock(remoteBlockTree, remoteSyncServer: remoteServer))) .ToArray(); ctx.PeerPool.AllPeers.Returns(peers); ctx.PeerPool.PeerCount.Returns(peers.Length); @@ -645,7 +583,7 @@ public void GetNodeData_returns_cached_trie_nodes() MemDb stateDb = new(); TrieStore trieStore = new(stateDb, Prune.WhenCacheReaches(10.MB()), NoPersistence.Instance, LimboLogs.Instance); ctx.SyncServer = new SyncServer( - trieStore.AsKeyValueStore(), + trieStore, new MemDb(), localBlockTree, NullReceiptStorage.Instance, @@ -697,9 +635,9 @@ public Context() public IBlockTree BlockTree { get; } public ISyncPeerPool PeerPool { get; } public SyncServer SyncServer { get; set; } - public ISpecProvider SpecProvider { get; set; } = null!; + public ISpecProvider SpecProvider { get; set; } - public IBlockTree LocalBlockTree { get; set; } = null!; + public IBlockTree LocalBlockTree { get; set; } public ISyncPeer NodeWhoSentTheBlock { get; } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs index c1bebc53a84..a3ca85cfec9 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs @@ -15,6 +15,7 @@ using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Transactions; using Nethermind.Consensus.Validators; +using Nethermind.Consensus.Withdrawals; using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; @@ -373,10 +374,9 @@ private SyncTestContext CreateSyncManager(int index) blockDownloaderFactory, pivot, syncReport, - Substitute.For(), logManager); SyncServer syncServer = new( - trieStore.AsKeyValueStore(), + trieStore, codeDb, tree, receiptStorage, diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs index 86fff95793a..c7a3bbe1dec 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs @@ -4,15 +4,15 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; -using Nethermind.Config; +using Nethermind.Blockchain.Test.Validators; using Nethermind.Consensus; +using Nethermind.Consensus.Processing; using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -28,6 +28,7 @@ using Nethermind.Stats.Model; using Nethermind.Db.Blooms; using Nethermind.Merge.Plugin; +using Nethermind.Merge.Plugin.Handlers; using Nethermind.Merge.Plugin.InvalidChainTracker; using Nethermind.Merge.Plugin.Synchronization; using Nethermind.Merge.Plugin.Test; @@ -59,15 +60,11 @@ public SynchronizerTests(SynchronizerType synchronizerType) _synchronizerType = synchronizerType; } - private static readonly Block _genesisBlock = Build.A.Block - .Genesis - .WithDifficulty(100000) + private static Block _genesisBlock = Build.A.Block.Genesis.WithDifficulty(100000) .WithTotalDifficulty((UInt256)100000).TestObject; private class SyncPeerMock : ISyncPeer { - public string Name => "Mock"; - private readonly bool _causeTimeoutOnInit; private readonly bool _causeTimeoutOnBlocks; private readonly bool _causeTimeoutOnHeaders; @@ -77,10 +74,7 @@ private class SyncPeerMock : ISyncPeer public BlockHeader HeadHeader => HeadBlock.Header; - public SyncPeerMock( - string peerName, - bool causeTimeoutOnInit = false, - bool causeTimeoutOnBlocks = false, + public SyncPeerMock(string peerName, bool causeTimeoutOnInit = false, bool causeTimeoutOnBlocks = false, bool causeTimeoutOnHeaders = false) { _causeTimeoutOnInit = causeTimeoutOnInit; @@ -93,7 +87,7 @@ public SyncPeerMock( private void UpdateHead() { - HeadHash = HeadBlock.Hash!; + HeadHash = HeadBlock.Hash; HeadNumber = HeadBlock.Number; TotalDifficulty = HeadBlock.TotalDifficulty ?? 0; } @@ -101,25 +95,25 @@ private void UpdateHead() public Node Node { get; } = new Node(Build.A.PrivateKey.TestObject.PublicKey, "127.0.0.1", 1234); public string ClientId { get; } - public Keccak HeadHash { get; set; } = null!; - public byte ProtocolVersion { get; } = default; - public string ProtocolCode { get; } = null!; + public Keccak HeadHash { get; set; } public long HeadNumber { get; set; } public UInt256 TotalDifficulty { get; set; } public bool IsInitialized { get; set; } public bool IsPriority { get; set; } + public byte ProtocolVersion { get; } + public string ProtocolCode { get; } - public void Disconnect(DisconnectReason reason, string details) + public void Disconnect(InitiateDisconnectReason reason, string details) { Disconnected?.Invoke(this, EventArgs.Empty); } - public Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) + public Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) { if (_causeTimeoutOnBlocks) { - return Task.FromException(new TimeoutException()); + return Task.FromException(new TimeoutException()); } BlockBody[] result = new BlockBody[blockHashes.Count]; @@ -134,7 +128,7 @@ public Task GetBlockBodies(IReadOnlyList blockHashes, } } - return Task.FromResult(new OwnedBlockBodies(result)); + return Task.FromResult(result); } public Task GetBlockHeaders(long number, int maxBlocks, int skip, CancellationToken token) @@ -204,7 +198,7 @@ public void NotifyOfNewBlock(Block block, SendBlockMode mode) public ConcurrentStack ReceivedBlocks { get; } = new(); - public event EventHandler? Disconnected; + public event EventHandler Disconnected; public PublicKey Id => Node.Id; @@ -275,9 +269,9 @@ public WhenImplementation(SynchronizerType synchronizerType) public class SyncingContext { - public static ConcurrentQueue AllInstances { get; } = new(); + public static ConcurrentQueue AllInstances = new(); - private readonly Dictionary _peers = new(); + private Dictionary _peers = new(); private BlockTree BlockTree { get; } private ISyncServer SyncServer { get; } @@ -286,9 +280,10 @@ public class SyncingContext private ISyncPeerPool SyncPeerPool { get; } - readonly ILogManager _logManager = LimboLogs.Instance; + // ILogManager _logManager = LimboLogs.Instance; + ILogManager _logManager = LimboLogs.Instance; - private readonly ILogger _logger; + private ILogger _logger; public SyncingContext(SynchronizerType synchronizerType) { @@ -316,11 +311,12 @@ ISyncConfig GetSyncConfig() => ITimerFactory timerFactory = Substitute.For(); NodeStatsManager stats = new(timerFactory, _logManager); - MergeConfig mergeConfig = new(); + MergeConfig? mergeConfig = new() { }; if (WithTTD(synchronizerType)) { - mergeConfig.TerminalTotalDifficulty = UInt256.MaxValue.ToString(CultureInfo.InvariantCulture); + mergeConfig.TerminalTotalDifficulty = UInt256.MaxValue.ToString(); } + IBlockCacheService blockCacheService = new BlockCacheService(); PoSSwitcher poSSwitcher = new(mergeConfig, syncConfig, dbProvider.MetadataDb, BlockTree, new TestSingleReleaseSpecProvider(Constantinople.Instance), _logManager); IBeaconPivot beaconPivot = new BeaconPivot(syncConfig, dbProvider.MetadataDb, BlockTree, _logManager); @@ -381,7 +377,6 @@ ISyncConfig GetSyncConfig() => poSSwitcher, mergeConfig, invalidChainTracker, - Substitute.For(), _logManager, syncReport); } @@ -412,12 +407,11 @@ ISyncConfig GetSyncConfig() => blockDownloaderFactory, pivot, syncReport, - Substitute.For(), _logManager); } SyncServer = new SyncServer( - trieStore.AsKeyValueStore(), + trieStore, codeDb, BlockTree, NullReceiptStorage.Instance, @@ -446,22 +440,22 @@ public SyncingContext BestKnownNumberIs(long number) public SyncingContext BlockIsKnown() { - Assert.True(BlockTree.IsKnownBlock(_blockHeader.Number, _blockHeader.Hash!), "block is known"); + Assert.True(BlockTree.IsKnownBlock(_blockHeader.Number, _blockHeader.Hash), "block is known"); return this; } - private const int DynamicTimeout = 5000; + private const int dynamicTimeout = 5000; public SyncingContext BestSuggestedHeaderIs(BlockHeader header) { int waitTimeSoFar = 0; - _blockHeader = BlockTree.BestSuggestedHeader!; - while (header != _blockHeader && waitTimeSoFar <= DynamicTimeout) + _blockHeader = BlockTree.BestSuggestedHeader; + while (header != _blockHeader && waitTimeSoFar <= dynamicTimeout) { - _logger.Info($"ASSERTING THAT HEADER IS {header.Number} (WHEN ACTUALLY IS {_blockHeader.Number})"); + _logger.Info($"ASSERTING THAT HEADER IS {header.Number} (WHEN ACTUALLY IS {_blockHeader?.Number})"); Thread.Sleep(100); waitTimeSoFar += 100; - _blockHeader = BlockTree.BestSuggestedHeader!; + _blockHeader = BlockTree.BestSuggestedHeader; } Assert.That(_blockHeader, Is.SameAs(header), "header"); @@ -473,15 +467,15 @@ public SyncingContext BestSuggestedBlockHasNumber(long number) _logger.Info($"ASSERTING THAT NUMBER IS {number}"); int waitTimeSoFar = 0; - _blockHeader = BlockTree.BestSuggestedHeader!; - while (number != _blockHeader.Number && waitTimeSoFar <= DynamicTimeout) + _blockHeader = BlockTree.BestSuggestedHeader; + while (number != _blockHeader?.Number && waitTimeSoFar <= dynamicTimeout) { Thread.Sleep(10); waitTimeSoFar += 10; - _blockHeader = BlockTree.BestSuggestedHeader!; + _blockHeader = BlockTree.BestSuggestedHeader; } - Assert.That(_blockHeader.Number, Is.EqualTo(number), "block number"); + Assert.That(_blockHeader?.Number, Is.EqualTo(number), "block number"); return this; } @@ -491,18 +485,18 @@ public SyncingContext BlockIsSameAsGenesis() return this; } - private BlockHeader _blockHeader = null!; + private BlockHeader _blockHeader; public SyncingContext Genesis { get { - _blockHeader = BlockTree.Genesis!; + _blockHeader = BlockTree.Genesis; return this; } } - private SyncingContext Wait(int milliseconds) + public SyncingContext Wait(int milliseconds) { if (_logger.IsInfo) _logger.Info($"WAIT {milliseconds}"); Thread.Sleep(milliseconds); @@ -516,7 +510,7 @@ public SyncingContext Wait() public SyncingContext WaitUntilInitialized() { - SpinWait.SpinUntil(() => SyncPeerPool.AllPeers.All(p => p.IsInitialized), DynamicTimeout); + SpinWait.SpinUntil(() => SyncPeerPool.AllPeers.All(p => p.IsInitialized), dynamicTimeout); return this; } @@ -530,7 +524,7 @@ public SyncingContext BestSuggested { get { - _blockHeader = BlockTree.BestSuggestedHeader!; + _blockHeader = BlockTree.BestSuggestedHeader; return this; } } @@ -545,7 +539,7 @@ public SyncingContext AfterProcessingGenesis() public SyncingContext AfterPeerIsAdded(ISyncPeer syncPeer) { - ((SyncPeerMock)syncPeer).Disconnected += (_, _) => SyncPeerPool.RemovePeer(syncPeer); + ((SyncPeerMock)syncPeer).Disconnected += (s, e) => SyncPeerPool.RemovePeer(syncPeer); _logger.Info($"PEER ADDED {syncPeer.ClientId}"); _peers.TryAdd(syncPeer.ClientId, syncPeer); @@ -571,7 +565,7 @@ public SyncingContext AfterNewBlockMessage(Block block, ISyncPeer peer) public SyncingContext AfterHintBlockMessage(Block block, ISyncPeer peer) { _logger.Info($"HINT BLOCK MESSAGE {block.Number}"); - SyncServer.HintBlock(block.Hash!, block.Number, peer); + SyncServer.HintBlock(block.Hash, block.Number, peer); return this; } @@ -583,7 +577,7 @@ public SyncingContext PeerCountIs(long i) public SyncingContext PeerCountEventuallyIs(long i) { - Assert.That(() => SyncPeerPool.AllPeers.Count(), Is.EqualTo(i).After(5000, 100), "peer count"); + Assert.That(() => SyncPeerPool.AllPeers.Count(), Is.EqualTo(i).After(1000, 100), "peer count"); return this; } @@ -594,13 +588,13 @@ public SyncingContext WaitAMoment() public void Stop() { - Task task = Task.Run(async () => + Task task = new(async () => { await Synchronizer.StopAsync(); await SyncPeerPool.StopAsync(); }); - task.GetAwaiter().GetResult(); + task.RunSynchronously(); } } @@ -798,11 +792,11 @@ public void Will_inform_connecting_peer_about_the_alternative_branch_with_same_d Assert.That(peerA.HeadBlock.Hash, Is.Not.EqualTo(peerB.HeadBlock.Hash)); - Block? peerBNewBlock = null; + Block peerBNewBlock = null; SpinWait.SpinUntil(() => { bool receivedBlock = peerB.ReceivedBlocks.TryPeek(out peerBNewBlock); - return receivedBlock && peerBNewBlock!.Hash == peerA.HeadBlock.Hash; + return receivedBlock && peerBNewBlock.Hash == peerA.HeadBlock.Hash; }, WaitTime); Assert.That(peerA.HeadBlock.Hash, Is.EqualTo(peerBNewBlock?.Header.Hash!)); @@ -824,7 +818,7 @@ public void Will_not_add_same_peer_twice() .BestSuggestedBlockHasNumber(1).Stop(); } - [Test, Retry(5)] + [Test, Retry(3)] public void Will_remove_peer_when_init_fails() { SyncPeerMock peerA = new("A", true, true); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/TotalDifficultyBasedBetterPeerStrategyTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/TotalDifficultyBasedBetterPeerStrategyTests.cs index 2827b66809f..a54786f8c90 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/TotalDifficultyBasedBetterPeerStrategyTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/TotalDifficultyBasedBetterPeerStrategyTests.cs @@ -6,6 +6,7 @@ using Nethermind.Core.Test.Builders; using Nethermind.Int256; using Nethermind.Logging; +using Nethermind.Synchronization.ParallelSync; using NSubstitute; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.Synchronization.Test/Trie/HealingTreeTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/Trie/HealingTreeTests.cs deleted file mode 100644 index 2f8ec918721..00000000000 --- a/src/Nethermind/Nethermind.Synchronization.Test/Trie/HealingTreeTests.cs +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Linq.Expressions; -using System.Threading.Tasks; -using FluentAssertions; -using Nethermind.Core.Crypto; -using Nethermind.Core.Extensions; -using Nethermind.Core.Test; -using Nethermind.Core.Test.Builders; -using Nethermind.Logging; -using Nethermind.State.Snap; -using Nethermind.Synchronization.Trie; -using Nethermind.Trie; -using Nethermind.Trie.Pruning; -using NSubstitute; -using NUnit.Framework; - -namespace Nethermind.Synchronization.Test.Trie; - -[Parallelizable(ParallelScope.Fixtures)] -public class HealingTreeTests -{ - private static readonly byte[] _rlp = { 3, 4 }; - private static readonly Keccak _key = Keccak.Compute(_rlp); - - [Test] - public void get_state_tree_works() - { - HealingStateTree stateTree = new(Substitute.For(), LimboLogs.Instance); - stateTree.Get(stackalloc byte[] { 1, 2, 3 }); - } - - [Test] - public void get_storage_tree_works() - { - HealingStorageTree stateTree = new(Substitute.For(), Keccak.EmptyTreeHash, LimboLogs.Instance, TestItem.AddressA, TestItem.KeccakA, null); - stateTree.Get(stackalloc byte[] { 1, 2, 3 }); - } - - [Test] - public void recovery_works_state_trie([Values(true, false)] bool isMainThread, [Values(true, false)] bool successfullyRecovered) - { - HealingStateTree CreateHealingStateTree(ITrieStore trieStore, ITrieNodeRecovery recovery) - { - HealingStateTree stateTree = new(trieStore, LimboLogs.Instance); - stateTree.InitializeNetwork(recovery); - return stateTree; - } - - byte[] path = { 1, 2 }; - recovery_works(isMainThread, successfullyRecovered, path, CreateHealingStateTree, r => PathMatch(r, path, 0)); - } - - private static bool PathMatch(GetTrieNodesRequest r, byte[] path, int lastPathIndex) => - r.RootHash == _key - && r.AccountAndStoragePaths.Length == 1 - && r.AccountAndStoragePaths[0].Group.Length == lastPathIndex + 1 - && Bytes.AreEqual(r.AccountAndStoragePaths[0].Group[lastPathIndex], Nibbles.EncodePath(path)); - - [Test] - public void recovery_works_storage_trie([Values(true, false)] bool isMainThread, [Values(true, false)] bool successfullyRecovered) - { - HealingStorageTree CreateHealingStorageTree(ITrieStore trieStore, ITrieNodeRecovery recovery) => - new(trieStore, Keccak.EmptyTreeHash, LimboLogs.Instance, TestItem.AddressA, _key, recovery); - byte[] path = { 1, 2 }; - byte[] addressPath = ValueKeccak.Compute(TestItem.AddressA.Bytes).Bytes.ToArray(); - recovery_works(isMainThread, successfullyRecovered, path, CreateHealingStorageTree, - r => PathMatch(r, path, 1) && Bytes.AreEqual(r.AccountAndStoragePaths[0].Group[0], addressPath)); - } - - private void recovery_works( - bool isMainThread, - bool successfullyRecovered, - byte[] path, - Func, T> createTrie, - Expression> requestMatch) - where T : PatriciaTree - { - ITrieStore trieStore = Substitute.For(); - trieStore.FindCachedOrUnknown(_key).Returns( - k => throw new MissingTrieNodeException("", new TrieNodeException("", _key), path, 1), - k => new TrieNode(NodeType.Leaf) { Key = path }); - TestMemDb db = new(); - trieStore.AsKeyValueStore().Returns(db); - - ITrieNodeRecovery recovery = Substitute.For>(); - recovery.CanRecover.Returns(isMainThread); - recovery.Recover(_key, Arg.Is(requestMatch)).Returns(successfullyRecovered ? Task.FromResult(_rlp) : Task.FromResult(null)); - - T trie = createTrie(trieStore, recovery); - - Action action = () => trie.Get(stackalloc byte[] { 1, 2, 3 }, _key); - if (isMainThread && successfullyRecovered) - { - action.Should().NotThrow(); - db.KeyWasWritten(kvp => Bytes.AreEqual(kvp.Item1, ValueKeccak.Compute(_rlp).Bytes) && Bytes.AreEqual(kvp.Item2, _rlp)); - } - else - { - action.Should().Throw(); - } - } -} diff --git a/src/Nethermind/Nethermind.Synchronization.Test/Trie/HealingTrieStoreTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/Trie/HealingTrieStoreTests.cs deleted file mode 100644 index da0c7fb693b..00000000000 --- a/src/Nethermind/Nethermind.Synchronization.Test/Trie/HealingTrieStoreTests.cs +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using FluentAssertions; -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Core.Extensions; -using Nethermind.Core.Test; -using Nethermind.Core.Test.Builders; -using Nethermind.Logging; -using Nethermind.Synchronization.Trie; -using Nethermind.Trie; -using Nethermind.Trie.Pruning; -using NSubstitute; -using NUnit.Framework; - -namespace Nethermind.Synchronization.Test.Trie; - -public class HealingTrieStoreTests -{ - [Test] - public void get_works() - { - TestMemDb db = new(); - db[TestItem.KeccakA.Bytes] = new byte[] { 1, 2 }; - HealingTrieStore healingTrieStore = new(db, Nethermind.Trie.Pruning.No.Pruning, Persist.EveryBlock, LimboLogs.Instance); - healingTrieStore.LoadRlp(TestItem.KeccakA, ReadFlags.None); - } - - [Test] - public void recovery_works([Values(true, false)] bool isMainThread, [Values(true, false)] bool successfullyRecovered) - { - byte[] rlp = { 1, 2 }; - Keccak key = TestItem.KeccakA; - TestMemDb db = new(); - HealingTrieStore healingTrieStore = new(db, Nethermind.Trie.Pruning.No.Pruning, Persist.EveryBlock, LimboLogs.Instance); - ITrieNodeRecovery> recovery = Substitute.For>>(); - recovery.CanRecover.Returns(isMainThread); - recovery.Recover(key, Arg.Is>(l => l.SequenceEqual(new[] { key }))) - .Returns(successfullyRecovered ? Task.FromResult(rlp) : Task.FromResult(null)); - - healingTrieStore.InitializeNetwork(recovery); - Action action = () => healingTrieStore.LoadRlp(key, ReadFlags.None); - if (isMainThread && successfullyRecovered) - { - action.Should().NotThrow(); - db.KeyWasWritten(kvp => Bytes.AreEqual(kvp.Item1, key.Bytes) && Bytes.AreEqual(kvp.Item2, rlp)); - } - else - { - action.Should().Throw(); - } - } -} diff --git a/src/Nethermind/Nethermind.Synchronization.Test/Trie/RecoveryTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/Trie/RecoveryTests.cs deleted file mode 100644 index ddcab8cbe5e..00000000000 --- a/src/Nethermind/Nethermind.Synchronization.Test/Trie/RecoveryTests.cs +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using FluentAssertions; -using Nethermind.Blockchain.Synchronization; -using Nethermind.Core.Crypto; -using Nethermind.Logging; -using Nethermind.Network.Contract.P2P; -using Nethermind.State.Snap; -using Nethermind.Synchronization.Peers; -using Nethermind.Synchronization.Trie; -using NSubstitute; -using NUnit.Framework; - -namespace Nethermind.Synchronization.Test.Trie; - -public class RecoveryTests -{ - private byte[] _keyRlp = null!; - private byte[] _returnedRlp = null!; - private Keccak _key = null!; - private ISyncPeer _syncPeerEth66 = null!; - private PeerInfo _peerEth66 = null!; - private ISyncPeer _syncPeerEth67 = null!; - private PeerInfo _peerEth67 = null!; - private ISnapSyncPeer _snapSyncPeer = null!; - private GetTrieNodesRequest _snapRequest = null!; - private ISyncPeerPool _syncPeerPool = null!; - private SnapTrieNodeRecovery _snapRecovery = null!; - private GetNodeDataTrieNodeRecovery _nodeDataRecovery = null!; - - [SetUp] - public void SetUp() - { - _returnedRlp = _keyRlp = new byte[] { 1, 2, 3 }; - _key = Keccak.Compute(_keyRlp); - _syncPeerEth66 = Substitute.For(); - _syncPeerEth66.ProtocolVersion.Returns(EthVersions.Eth66); - _syncPeerEth66.GetNodeData(Arg.Is>(l => l.Contains(_key)), Arg.Any()) - .Returns(_ => Task.FromResult(new[] { _returnedRlp })); - _peerEth66 = new(_syncPeerEth66); - - _snapSyncPeer = Substitute.For(); - _snapSyncPeer.GetTrieNodes(Arg.Any(), Arg.Any()) - .Returns(c => Task.FromResult(new[] { _returnedRlp })); - _syncPeerEth67 = Substitute.For(); - _syncPeerEth67.ProtocolVersion.Returns(EthVersions.Eth67); - _syncPeerEth67.TryGetSatelliteProtocol(Protocol.Snap, out Arg.Any()) - .Returns(c => - { - c[1] = _snapSyncPeer; - return true; - }); - _peerEth67 = new(_syncPeerEth67); - - _snapRequest = new GetTrieNodesRequest { AccountAndStoragePaths = Array.Empty() }; - _syncPeerPool = Substitute.For(); - _snapRecovery = new SnapTrieNodeRecovery(_syncPeerPool, LimboLogs.Instance); - _nodeDataRecovery = new GetNodeDataTrieNodeRecovery(_syncPeerPool, LimboLogs.Instance); - } - - [Test] - public async Task can_recover_eth66() - { - byte[]? rlp = await Recover(_nodeDataRecovery, new List { _key }, _peerEth66); - rlp.Should().BeEquivalentTo(_keyRlp); - } - - [Test] - public async Task cannot_recover_eth66_no_peers() - { - byte[]? rlp = await Recover(_nodeDataRecovery, new List { _key }, _peerEth67); - rlp.Should().BeNull(); - } - - [Test] - public async Task cannot_recover_eth66_empty_response() - { - _syncPeerEth66.GetNodeData(Arg.Is>(l => l.Contains(_key)), Arg.Any()) - .Returns(Task.FromResult(Array.Empty())); - byte[]? rlp = await Recover(_nodeDataRecovery, new List { _key }, _peerEth66); - rlp.Should().BeNull(); - } - - [Test] - public async Task cannot_recover_eth66_invalid_rlp() - { - _returnedRlp = new byte[] { 5, 6, 7 }; - byte[]? rlp = await Recover(_nodeDataRecovery, new List { _key }, _peerEth66); - rlp.Should().BeNull(); - } - - [Test] - public async Task can_recover_eth67() - { - byte[]? rlp = await Recover(_snapRecovery, _snapRequest, _peerEth67); - rlp.Should().BeEquivalentTo(_keyRlp); - } - - [Test] - public async Task cannot_recover_eth67_no_peers() - { - byte[]? rlp = await Recover(_snapRecovery, _snapRequest, _peerEth66); - rlp.Should().BeNull(); - } - - [Test] - public async Task cannot_recover_eth67_empty_response() - { - _snapSyncPeer.GetTrieNodes(Arg.Any(), Arg.Any()) - .Returns(Task.FromResult(Array.Empty())); - byte[]? rlp = await Recover(_snapRecovery, _snapRequest, _peerEth67); - rlp.Should().BeNull(); - } - - private Task Recover(T recovery, TRequest request, params PeerInfo[] peers) where T : ITrieNodeRecovery - { - _syncPeerPool.InitializedPeers.Returns(peers); - return recovery.Recover(_key, request); - } -} diff --git a/src/Nethermind/Nethermind.Synchronization.Test/TrieScenarios.cs b/src/Nethermind/Nethermind.Synchronization.Test/TrieScenarios.cs index a826be25ee2..7d318b7076b 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/TrieScenarios.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/TrieScenarios.cs @@ -12,22 +12,21 @@ using Nethermind.Int256; using Nethermind.Logging; using Nethermind.State; +using Nethermind.Trie; using Nethermind.Trie.Pruning; namespace Nethermind.Synchronization.Test { public static class TrieScenarios { - private static bool Inited; - - public static Account Empty = null!; - public static Account AccountJustState0 = null!; - public static Account AccountJustState1 = null!; - public static Account AccountJustState2 = null!; - public static Account Account0 = null!; - public static Account Account1 = null!; - public static Account Account2 = null!; - public static Account Account3 = null!; + public static Account Empty; + public static Account AccountJustState0; + public static Account AccountJustState1; + public static Account AccountJustState2; + public static Account Account0; + public static Account Account1; + public static Account Account2; + public static Account Account3; public static readonly byte[] Code0 = { 0, 0 }; public static readonly byte[] Code1 = { 0, 1 }; @@ -37,8 +36,11 @@ public static class TrieScenarios [MethodImpl(MethodImplOptions.Synchronized)] public static void InitOnce() { - if (!Inited) + if (Empty is null) { + // _logger = new ConsoleAsyncLogger(LogLevel.Debug); + // _logManager = new OneLoggerLogManager(_logger); + // this setup is just for finding the storage root StorageTree remoteStorageTree = SetStorage(new TrieStore(new MemDb(), LimboLogs.Instance)); Keccak storageRoot = remoteStorageTree.RootHash; @@ -52,12 +54,10 @@ public static void InitOnce() AccountJustState0 = Build.An.Account.WithBalance(1).TestObject; AccountJustState1 = Build.An.Account.WithBalance(2).TestObject; AccountJustState2 = Build.An.Account.WithBalance(3).TestObject; - - Inited = true; } } - private static (string Name, Action Action)[]? _scenarios; + private static (string Name, Action Action)[] _scenarios; public static (string Name, Action Action)[] Scenarios => LazyInitializer.EnsureInitialized(ref _scenarios, InitScenarios); @@ -66,7 +66,7 @@ private static (string Name, Action Action)[] InitSc { return new (string, Action)[] { - ("empty", (tree, _, codeDb) => + ("empty", (tree, stateDb, codeDb) => { codeDb[Keccak.Compute(Code0).Bytes] = Code0; tree.Commit(0); @@ -82,7 +82,7 @@ private static (string Name, Action Action)[] InitSc }), ("storage_hash_and_code_hash_same", (tree, stateDb, codeDb) => { - byte[] code = Bytes.FromHexString("e3a120b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601"); + var code = Bytes.FromHexString("e3a120b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601"); Keccak codeHash = Keccak.Compute(code); StorageTree remoteStorageTree = new(stateDb, Keccak.EmptyTreeHash, LimboLogs.Instance); remoteStorageTree.Set((UInt256) 1, new byte[] {1}); @@ -94,7 +94,7 @@ private static (string Name, Action Action)[] InitSc }), ("storage_hash_and_code_hash_same_with_additional_account_of_same_storage_root", (tree, stateDb, codeDb) => { - byte[] code = Bytes.FromHexString("e3a120b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601"); + var code = Bytes.FromHexString("e3a120b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601"); Keccak codeHash = Keccak.Compute(code); StorageTree remoteStorageTree = new(stateDb, Keccak.EmptyTreeHash, LimboLogs.Instance); remoteStorageTree.Set((UInt256) 1, new byte[] {1}); @@ -107,7 +107,7 @@ private static (string Name, Action Action)[] InitSc }), ("storage_hash_and_code_hash_same_with_additional_account_of_same_code", (tree, stateDb, codeDb) => { - byte[] code = Bytes.FromHexString("e3a120b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601"); + var code = Bytes.FromHexString("e3a120b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601"); Keccak codeHash = Keccak.Compute(code); StorageTree remoteStorageTree = new(stateDb, Keccak.EmptyTreeHash, LimboLogs.Instance); remoteStorageTree.Set((UInt256) 1, new byte[] {1}); @@ -118,7 +118,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"), AccountJustState0.WithChangedStorageRoot(remoteStorageTree.RootHash).WithChangedCodeHash(codeHash)); tree.Commit(0); }), - ("branch_with_same_accounts_at_different_addresses", (tree, _, codeDb) => + ("branch_with_same_accounts_at_different_addresses", (tree, stateDb, codeDb) => { codeDb[Keccak.Compute(Code0).Bytes] = Code0; tree.Set(new Keccak("1baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), AccountJustState0); @@ -146,7 +146,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb1eeeeeb1"), null); tree.Commit(0); }), - ("set_3_delete_all", (tree, _, _) => + ("set_3_delete_all", (tree, stateDb, codeDb) => { // SetStorage(stateDb); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), Account0); @@ -164,9 +164,9 @@ private static (string Name, Action Action)[] InitSc codeDb[Keccak.Compute(Code1).Bytes] = Code1; tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), Account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), Account1); - Account _ = tree.Get(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"))!; + Account account = tree.Get(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111")); tree.UpdateRootHash(); - Keccak __ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), ("extension_read_missing", (tree, stateDb, codeDb) => @@ -176,9 +176,9 @@ private static (string Name, Action Action)[] InitSc codeDb[Keccak.Compute(Code1).Bytes] = Code1; tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), Account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), Account1); - Account _ = tree.Get(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddd"))!; + Account account = tree.Get(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddd")); tree.UpdateRootHash(); - Keccak __ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), ("extension_new_branch", (tree, stateDb, codeDb) => @@ -191,16 +191,16 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), Account1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddd"), Account2); tree.UpdateRootHash(); - Keccak _ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), - ("just_state", (tree, _, _) => + ("just_state", (tree, stateDb, codeDb) => { tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), AccountJustState0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), AccountJustState1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddd"), AccountJustState2); tree.UpdateRootHash(); - Keccak _ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), ("extension_delete_missing", (tree, stateDb, codeDb) => @@ -212,10 +212,10 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), Account1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeddddddddddddddddddddddddd"), null); tree.UpdateRootHash(); - Keccak _ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), - ("extension_create_new_extension", (tree, stateDb, codeDb) => + ("extenson_create_new_extension", (tree, stateDb, codeDb) => { SetStorage(stateDb); codeDb[Keccak.Compute(Code0).Bytes] = Code0; @@ -227,7 +227,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeaaaaaaaaaaaaaaaab00000000"), Account2); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeaaaaaaaaaaaaaaaab11111111"), Account3); tree.UpdateRootHash(); - Keccak _ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), ("leaf_new_value", (tree, stateDb, codeDb) => @@ -237,7 +237,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account0); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account1); tree.UpdateRootHash(); - Keccak _ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), ("leaf_no_change", (tree, stateDb, codeDb) => @@ -247,15 +247,16 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account0); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account0); tree.UpdateRootHash(); - Keccak _ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), - ("leaf_delete", (tree, _, _) => + ("leaf_delete", (tree, stateDb, codeDb) => { +// SetStorage(stateDb); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account0); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), null); tree.UpdateRootHash(); - Keccak _ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), ("leaf_delete_missing", (tree, stateDb, codeDb) => @@ -265,7 +266,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account0); tree.Set(new Keccak("1111111111111111111111111111111ddddddddddddddddddddddddddddddddd"), null); tree.UpdateRootHash(); - Keccak _ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), ("leaf_update_extension", (tree, stateDb, codeDb) => @@ -276,7 +277,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111111111111111111111111111"), Account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000000000000000000000000000"), Account1); tree.UpdateRootHash(); - Keccak _ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), ("leaf_read", (tree, stateDb, codeDb) => @@ -284,9 +285,9 @@ private static (string Name, Action Action)[] InitSc SetStorage(stateDb); codeDb[Keccak.Compute(Code0).Bytes] = Code0; tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account0); - Account _ = tree.Get(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"))!; + Account account = tree.Get(new Keccak("1111111111111111111111111111111111111111111111111111111111111111")); tree.UpdateRootHash(); - Keccak __ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), ("leaf_update_missing", (tree, stateDb, codeDb) => @@ -294,9 +295,9 @@ private static (string Name, Action Action)[] InitSc SetStorage(stateDb); codeDb[Keccak.Compute(Code0).Bytes] = Code0; tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account0); - Account _ = tree.Get(new Keccak("111111111111111111111111111111111111111111111111111111111ddddddd"))!; + Account account = tree.Get(new Keccak("111111111111111111111111111111111111111111111111111111111ddddddd")); tree.UpdateRootHash(); - Keccak __ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), ("branch_update_missing", (tree, stateDb, codeDb) => @@ -309,7 +310,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111"), Account1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb22222"), Account2); tree.UpdateRootHash(); - Keccak _ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), ("branch_read_missing", (tree, stateDb, codeDb) => @@ -319,9 +320,9 @@ private static (string Name, Action Action)[] InitSc codeDb[Keccak.Compute(Code1).Bytes] = Code1; tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000"), Account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111"), Account1); - Account _ = tree.Get(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb22222"))!; + Account account = tree.Get(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb22222")); tree.UpdateRootHash(); - Keccak __ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }), ("branch_delete_missing", (tree, stateDb, codeDb) => @@ -333,7 +334,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111"), Account1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb22222"), null); tree.UpdateRootHash(); - Keccak _ = tree.RootHash; + Keccak rootHash = tree.RootHash; tree.Commit(0); }) }; diff --git a/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs b/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs index d48dd4ff6ec..375cb96eed7 100644 --- a/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs +++ b/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain; @@ -137,7 +138,7 @@ await DownloadHeaders(bestPeer, blocksRequest, cancellation) } } - public async Task DownloadHeaders(PeerInfo? bestPeer, BlocksRequest blocksRequest, CancellationToken cancellation) + public async Task DownloadHeaders(PeerInfo bestPeer, BlocksRequest blocksRequest, CancellationToken cancellation) { if (bestPeer is null) { @@ -240,7 +241,8 @@ bool HasMoreToSync() return headersSynced; } - public virtual async Task DownloadBlocks(PeerInfo? bestPeer, BlocksRequest blocksRequest, CancellationToken cancellation) + public virtual async Task DownloadBlocks(PeerInfo? bestPeer, BlocksRequest blocksRequest, + CancellationToken cancellation) { if (bestPeer is null) { @@ -443,12 +445,9 @@ protected async Task RequestBodies(PeerInfo peer, CancellationToken cancellation while (offset != context.NonEmptyBlockHashes.Count) { IReadOnlyList hashesToRequest = context.GetHashesByOffset(offset, peer.MaxBodiesPerRequest()); - Task getBodiesRequest = peer.SyncPeer.GetBlockBodies(hashesToRequest, cancellation); + Task getBodiesRequest = peer.SyncPeer.GetBlockBodies(hashesToRequest, cancellation); await getBodiesRequest.ContinueWith(_ => DownloadFailHandler(getBodiesRequest, "bodies"), cancellation); - - using OwnedBlockBodies ownedBlockBodies = getBodiesRequest.Result; - ownedBlockBodies.Disown(); - BlockBody?[] result = ownedBlockBodies.Bodies; + BlockBody?[] result = getBodiesRequest.Result; int receivedBodies = 0; for (int i = 0; i < result.Length; i++) @@ -666,7 +665,7 @@ protected void HandleSyncRequestResult(Task task, PeerInfo? peerInfo) if (peerInfo is not null) // fix this for node data sync { - peerInfo.SyncPeer.Disconnect(DisconnectReason.ForwardSyncFailed, reason); + peerInfo.SyncPeer.Disconnect(InitiateDisconnectReason.ForwardSyncFailed, reason); // redirect sync event from block downloader here (move this one inside) InvokeEvent(new SyncEventArgs(peerInfo.SyncPeer, Synchronization.SyncEvent.Failed)); } diff --git a/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloaderLimits.cs b/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloaderLimits.cs index 82290de7028..eab7096c8ce 100644 --- a/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloaderLimits.cs +++ b/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloaderLimits.cs @@ -20,10 +20,8 @@ public static int MaxBodiesPerRequest(this PeerInfo peer) NodeClientType.Parity => ParitySyncLimits.MaxBodyFetch, NodeClientType.OpenEthereum => ParitySyncLimits.MaxBodyFetch, NodeClientType.Trinity => GethSyncLimits.MaxBodyFetch, - NodeClientType.Erigon => GethSyncLimits.MaxBodyFetch, - NodeClientType.Reth => GethSyncLimits.MaxBodyFetch, NodeClientType.Unknown => 32, - _ => throw new ArgumentOutOfRangeException(nameof(peer.PeerClientType), peer.PeerClientType, null) + _ => throw new ArgumentOutOfRangeException() }; } @@ -36,11 +34,8 @@ public static int MaxReceiptsPerRequest(this PeerInfo peer) NodeClientType.Nethermind => NethermindSyncLimits.MaxReceiptFetch, NodeClientType.Parity => ParitySyncLimits.MaxReceiptFetch, NodeClientType.OpenEthereum => ParitySyncLimits.MaxReceiptFetch, - NodeClientType.Trinity => GethSyncLimits.MaxReceiptFetch, - NodeClientType.Erigon => GethSyncLimits.MaxReceiptFetch, - NodeClientType.Reth => GethSyncLimits.MaxReceiptFetch, NodeClientType.Unknown => 128, - _ => throw new ArgumentOutOfRangeException(nameof(peer.PeerClientType), peer.PeerClientType, null) + _ => throw new ArgumentOutOfRangeException() }; } @@ -53,11 +48,8 @@ public static int MaxHeadersPerRequest(this PeerInfo peer) NodeClientType.Nethermind => NethermindSyncLimits.MaxHeaderFetch, NodeClientType.Parity => ParitySyncLimits.MaxHeaderFetch, NodeClientType.OpenEthereum => ParitySyncLimits.MaxHeaderFetch, - NodeClientType.Trinity => GethSyncLimits.MaxHeaderFetch, - NodeClientType.Erigon => GethSyncLimits.MaxHeaderFetch, - NodeClientType.Reth => GethSyncLimits.MaxHeaderFetch, NodeClientType.Unknown => 192, - _ => throw new ArgumentOutOfRangeException(nameof(peer.PeerClientType), peer.PeerClientType, null) + _ => throw new ArgumentOutOfRangeException() }; } } diff --git a/src/Nethermind/Nethermind.Synchronization/Blocks/IBlockDownloaderFactory.cs b/src/Nethermind/Nethermind.Synchronization/Blocks/IBlockDownloaderFactory.cs index b78e2da2047..91dd37531ec 100644 --- a/src/Nethermind/Nethermind.Synchronization/Blocks/IBlockDownloaderFactory.cs +++ b/src/Nethermind/Nethermind.Synchronization/Blocks/IBlockDownloaderFactory.cs @@ -4,10 +4,12 @@ using System; using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; +using Nethermind.Blockchain.Synchronization; using Nethermind.Consensus; using Nethermind.Consensus.Validators; using Nethermind.Core.Specs; using Nethermind.Logging; +using Nethermind.Stats; using Nethermind.Synchronization.ParallelSync; using Nethermind.Synchronization.Peers; using Nethermind.Synchronization.Reporting; diff --git a/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncBatch.cs b/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncBatch.cs index 214129f8cd6..a12ec7f887a 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncBatch.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncBatch.cs @@ -13,6 +13,6 @@ public BodiesSyncBatch(BlockInfo[] infos) } public BlockInfo?[] Infos { get; } - public OwnedBlockBodies? Response { get; set; } + public BlockBody?[]? Response { get; set; } } } diff --git a/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncDownloader.cs b/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncDownloader.cs index 46cfada24e6..9622fb0f4cd 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncDownloader.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncDownloader.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain.Synchronization; +using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncFeed.cs b/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncFeed.cs index 7e6f5f29635..5574785318a 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncFeed.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastBlocks/BodiesSyncFeed.cs @@ -7,7 +7,6 @@ using Nethermind.Blockchain; using Nethermind.Blockchain.Synchronization; using Nethermind.Core; -using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Logging; using Nethermind.State.Proofs; @@ -31,7 +30,7 @@ public class BodiesSyncFeed : ActivatedSyncFeed private readonly ISyncPeerPool _syncPeerPool; private long _pivotNumber; - private long _barrier; + private readonly long _barrier; private SyncStatusList _syncStatusList; @@ -58,7 +57,7 @@ public BodiesSyncFeed( } _pivotNumber = _syncConfig.PivotNumberParsed; - _barrier = _syncConfig.AncientBodiesBarrierCalc; + _barrier = _barrier = _syncConfig.AncientBodiesBarrierCalc; if (_logger.IsInfo) _logger.Info($"Using pivot {_pivotNumber} and barrier {_barrier} in bodies sync"); ResetSyncStatusList(); @@ -69,7 +68,6 @@ public override void InitializeFeed() if (_pivotNumber < _syncConfig.PivotNumberParsed) { _pivotNumber = _syncConfig.PivotNumberParsed; - _barrier = _syncConfig.AncientBodiesBarrierCalc; if (_logger.IsInfo) _logger.Info($"Changed pivot in bodies sync. Now using pivot {_pivotNumber} and barrier {_barrier}"); ResetSyncStatusList(); } @@ -82,8 +80,7 @@ private void ResetSyncStatusList() _syncStatusList = new SyncStatusList( _blockTree, _pivotNumber, - _blockTree.LowestInsertedBodyNumber, - _syncConfig.AncientBodiesBarrier); + _blockTree.LowestInsertedBodyNumber); } protected override SyncMode ActivationSyncModes { get; } = SyncMode.FastBodies & ~SyncMode.FastBlocks; @@ -155,7 +152,6 @@ public override SyncResponseHandlingResult HandleResponse(BodiesSyncBatch? batch } finally { - batch.Response?.Dispose(); batch?.MarkHandlingEnd(); } } @@ -163,8 +159,7 @@ public override SyncResponseHandlingResult HandleResponse(BodiesSyncBatch? batch private bool TryPrepareBlock(BlockInfo blockInfo, BlockBody blockBody, out Block? block) { BlockHeader header = _blockTree.FindHeader(blockInfo.BlockHash); - Keccak rootHash = TxTrie.CalculateRoot(blockBody.Transactions); - bool txRootIsValid = rootHash == header.TxRoot; + bool txRootIsValid = new TxTrie(blockBody.Transactions).RootHash == header.TxRoot; bool unclesHashIsValid = UnclesHash.Calculate(blockBody.Uncles) == header.UnclesHash; if (txRootIsValid && unclesHashIsValid) { @@ -182,14 +177,13 @@ private int InsertBodies(BodiesSyncBatch batch) { bool hasBreachedProtocol = false; int validResponsesCount = 0; - BlockBody[]? responses = batch.Response?.Bodies ?? Array.Empty(); for (int i = 0; i < batch.Infos.Length; i++) { BlockInfo? blockInfo = batch.Infos[i]; - BlockBody? body = responses.Length <= i + BlockBody? body = (batch.Response?.Length ?? 0) <= i ? null - : responses[i]; + : batch.Response![i]; // last batch if (blockInfo is null) @@ -213,7 +207,7 @@ private int InsertBodies(BodiesSyncBatch batch) if (batch.ResponseSourcePeer is not null) { - _syncPeerPool.ReportBreachOfProtocol(batch.ResponseSourcePeer, DisconnectReason.InvalidTxOrUncle, "invalid tx or uncles root"); + _syncPeerPool.ReportBreachOfProtocol(batch.ResponseSourcePeer, InitiateDisconnectReason.InvalidTxOrUncle, "invalid tx or uncles root"); } _syncStatusList.MarkPending(blockInfo); diff --git a/src/Nethermind/Nethermind.Synchronization/FastBlocks/FastHeadersSyncFeed.cs b/src/Nethermind/Nethermind.Synchronization/FastBlocks/FastHeadersSyncFeed.cs index 62f10e0735d..2ab6379b3a2 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastBlocks/FastHeadersSyncFeed.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastBlocks/FastHeadersSyncFeed.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -394,7 +395,7 @@ public override SyncResponseHandlingResult HandleResponse(HeadersSyncBatch? batc _resetLock.EnterReadLock(); try { - if (!_sent.TryRemove(batch)) + if (!_sent.Contains(batch)) { if (_logger.IsDebug) _logger.Debug("Ignoring batch not in sent record"); return SyncResponseHandlingResult.Ignored; @@ -426,6 +427,7 @@ public override SyncResponseHandlingResult HandleResponse(HeadersSyncBatch? batc finally { batch.MarkHandlingEnd(); + _sent.TryRemove(batch); } } finally @@ -480,7 +482,7 @@ protected virtual int InsertHeaders(HeadersSyncBatch batch) { _syncPeerPool.ReportBreachOfProtocol( batch.ResponseSourcePeer, - DisconnectReason.HeaderResponseTooLong, + InitiateDisconnectReason.HeaderResponseTooLong, $"response too long ({batch.Response.Length})"); } @@ -506,7 +508,7 @@ protected virtual int InsertHeaders(HeadersSyncBatch batch) { _syncPeerPool.ReportBreachOfProtocol( batch.ResponseSourcePeer, - DisconnectReason.InconsistentHeaderBatch, + InitiateDisconnectReason.InconsistentHeaderBatch, "inconsistent headers batch"); } @@ -525,7 +527,7 @@ protected virtual int InsertHeaders(HeadersSyncBatch batch) if (_logger.IsDebug) _logger.Debug($"{batch} - reporting INVALID hash"); _syncPeerPool.ReportBreachOfProtocol( batch.ResponseSourcePeer, - DisconnectReason.UnexpectedHeaderHash, + InitiateDisconnectReason.UnexpectedHeaderHash, "first hash inconsistent with request"); } @@ -546,7 +548,7 @@ protected virtual int InsertHeaders(HeadersSyncBatch batch) { _syncPeerPool.ReportBreachOfProtocol( batch.ResponseSourcePeer, - DisconnectReason.HeaderBatchOnDifferentBranch, + InitiateDisconnectReason.HeaderBatchOnDifferentBranch, "headers - different branch"); } @@ -560,7 +562,7 @@ protected virtual int InsertHeaders(HeadersSyncBatch batch) { _syncPeerPool.ReportBreachOfProtocol( batch.ResponseSourcePeer, - DisconnectReason.HeaderBatchOnDifferentBranch, + InitiateDisconnectReason.HeaderBatchOnDifferentBranch, "headers - different branch"); } @@ -603,7 +605,7 @@ protected virtual int InsertHeaders(HeadersSyncBatch batch) if (batch.ResponseSourcePeer is not null) { if (_logger.IsDebug) _logger.Debug($"{batch} - reporting INVALID inconsistent"); - _syncPeerPool.ReportBreachOfProtocol(batch.ResponseSourcePeer, DisconnectReason.UnexpectedParentHeader, "headers - response not matching request"); + _syncPeerPool.ReportBreachOfProtocol(batch.ResponseSourcePeer, InitiateDisconnectReason.UnexpectedParentHeader, "headers - response not matching request"); } break; @@ -617,7 +619,7 @@ protected virtual int InsertHeaders(HeadersSyncBatch batch) if (batch.ResponseSourcePeer is not null) { if (_logger.IsDebug) _logger.Debug($"{batch} - reporting INVALID bad block"); - _syncPeerPool.ReportBreachOfProtocol(batch.ResponseSourcePeer, DisconnectReason.InvalidHeader, $"invalid header {header.ToString(BlockHeader.Format.Short)}"); + _syncPeerPool.ReportBreachOfProtocol(batch.ResponseSourcePeer, InitiateDisconnectReason.InvalidHeader, $"invalid header {header.ToString(BlockHeader.Format.Short)}"); } break; diff --git a/src/Nethermind/Nethermind.Synchronization/FastBlocks/MemorySizeEstimator.cs b/src/Nethermind/Nethermind.Synchronization/FastBlocks/MemorySizeEstimator.cs index 51f2064a7ca..6046243c2ac 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastBlocks/MemorySizeEstimator.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastBlocks/MemorySizeEstimator.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Core; namespace Nethermind.Synchronization.FastBlocks diff --git a/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncDownloader.cs b/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncDownloader.cs index 7793249db64..364f8408e86 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncDownloader.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncDownloader.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain.Synchronization; +using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncFeed.cs b/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncFeed.cs index c16484d2b8c..b79c23e59eb 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncFeed.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastBlocks/ReceiptsSyncFeed.cs @@ -36,7 +36,7 @@ public class ReceiptsSyncFeed : ActivatedSyncFeed private SyncStatusList _syncStatusList; private long _pivotNumber; - private long _barrier; + private readonly long _barrier; private bool ShouldFinish => !_syncConfig.DownloadReceiptsInFastSync || AllReceiptsDownloaded; private bool AllReceiptsDownloaded => _receiptStorage.LowestInsertedReceiptBlockNumber <= _barrier; @@ -78,7 +78,6 @@ public override void InitializeFeed() if (_pivotNumber < _syncConfig.PivotNumberParsed) { _pivotNumber = _syncConfig.PivotNumberParsed; - _barrier = _syncConfig.AncientReceiptsBarrierCalc; if (_logger.IsInfo) _logger.Info($"Changed pivot in receipts sync. Now using pivot {_pivotNumber} and barrier {_barrier}"); ResetSyncStatusList(); } @@ -91,8 +90,7 @@ private void ResetSyncStatusList() _syncStatusList = new SyncStatusList( _blockTree, _pivotNumber, - _receiptStorage.LowestInsertedReceiptBlockNumber, - _syncConfig.AncientReceiptsBarrier); + _receiptStorage.LowestInsertedReceiptBlockNumber); } protected override SyncMode ActivationSyncModes { get; } @@ -259,7 +257,7 @@ private int InsertReceipts(ReceiptsSyncBatch batch) if (batch.ResponseSourcePeer is not null) { - _syncPeerPool.ReportBreachOfProtocol(batch.ResponseSourcePeer, DisconnectReason.InvalidReceiptRoot, "invalid tx or uncles root"); + _syncPeerPool.ReportBreachOfProtocol(batch.ResponseSourcePeer, InitiateDisconnectReason.InvalidReceiptRoot, "invalid tx or uncles root"); } _syncStatusList.MarkPending(blockInfo); diff --git a/src/Nethermind/Nethermind.Synchronization/FastBlocks/SyncStatusList.cs b/src/Nethermind/Nethermind.Synchronization/FastBlocks/SyncStatusList.cs index 373afedd1d2..42130e96c44 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastBlocks/SyncStatusList.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastBlocks/SyncStatusList.cs @@ -16,7 +16,6 @@ internal class SyncStatusList private readonly FastBlockStatusList _statuses; private readonly LruCache _cache = new(maxCapacity: 64, startCapacity: 64, "blockInfo Cache"); private long _lowestInsertWithoutGaps; - private readonly long _lowerBound; public long LowestInsertWithoutGaps { @@ -26,20 +25,19 @@ public long LowestInsertWithoutGaps public long QueueSize => _queueSize; - public SyncStatusList(IBlockTree blockTree, long pivotNumber, long? lowestInserted, long lowerBound) + public SyncStatusList(IBlockTree blockTree, long pivotNumber, long? lowestInserted) { _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); _statuses = new FastBlockStatusList(pivotNumber + 1); LowestInsertWithoutGaps = lowestInserted ?? pivotNumber; - _lowerBound = lowerBound; } public void GetInfosForBatch(BlockInfo?[] blockInfos) { int collected = 0; long currentNumber = Volatile.Read(ref _lowestInsertWithoutGaps); - while (collected < blockInfos.Length && currentNumber != 0 && currentNumber >= _lowerBound) + while (collected < blockInfos.Length && currentNumber != 0) { if (blockInfos[collected] is not null) { diff --git a/src/Nethermind/Nethermind.Synchronization/FastSync/DetailedProgress.cs b/src/Nethermind/Nethermind.Synchronization/FastSync/DetailedProgress.cs index febb468f2ad..41107f73ed5 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastSync/DetailedProgress.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastSync/DetailedProgress.cs @@ -46,7 +46,7 @@ public class DetailedProgress private readonly IChainEstimations _chainEstimations; - public DetailedProgress(ulong chainId, byte[]? serializedInitialState) + public DetailedProgress(ulong chainId, byte[] serializedInitialState) { _chainEstimations = ChainSizes.CreateChainSizeInfo(chainId); @@ -69,13 +69,13 @@ internal void DisplayProgressReport(int pendingRequestsCount, BranchProgress bra // if (_logger.IsInfo) _logger.Info($"Time {TimeSpan.FromSeconds(_secondsInSync):dd\\.hh\\:mm\\:ss} | {(decimal) _dataSize / 1000 / 1000,6:F2}MB | kBps: {savedKBytesPerSecond,5:F0} | P: {_pendingRequests.Count} | acc {_savedAccounts} | queues {StreamsDescription} | db {_averageTimeInHandler:f2}ms"); Metrics.StateSynced = DataSize; - string dataSizeInfo = $"{(decimal)DataSize / 1000 / 1000,6:F2} MB"; + string dataSizeInfo = $"{(decimal)DataSize / 1000 / 1000,6:F2}MB"; if (_chainEstimations.StateSize is not null) { decimal percentage = Math.Min(1, (decimal)DataSize / _chainEstimations.StateSize.Value); dataSizeInfo = string.Concat( $"~{percentage:P2} | ", dataSizeInfo, - $" / ~{(decimal)_chainEstimations.StateSize.Value / 1000 / 1000,6:F2} MB"); + $" / ~{(decimal)_chainEstimations.StateSize.Value / 1000 / 1000,6:F2}MB"); } if (logger.IsInfo) logger.Info( @@ -100,30 +100,28 @@ internal void DisplayProgressReport(int pendingRequestsCount, BranchProgress bra } } - private void LoadFromSerialized(byte[]? serializedData) + private void LoadFromSerialized(byte[] serializedData) { - if (serializedData == null) + if (serializedData != null) { - return; - } - - RlpStream rlpStream = new(serializedData); - rlpStream.ReadSequenceLength(); - ConsumedNodesCount = rlpStream.DecodeLong(); - SavedStorageCount = rlpStream.DecodeLong(); - SavedStateCount = rlpStream.DecodeLong(); - SavedNodesCount = rlpStream.DecodeLong(); - SavedAccounts = rlpStream.DecodeLong(); - SavedCode = rlpStream.DecodeLong(); - RequestedNodesCount = rlpStream.DecodeLong(); - DbChecks = rlpStream.DecodeLong(); - StateWasThere = rlpStream.DecodeLong(); - StateWasNotThere = rlpStream.DecodeLong(); - DataSize = rlpStream.DecodeLong(); - - if (rlpStream.Position != rlpStream.Length) - { - SecondsInSync = rlpStream.DecodeLong(); + RlpStream rlpStream = new(serializedData); + rlpStream.ReadSequenceLength(); + ConsumedNodesCount = rlpStream.DecodeLong(); + SavedStorageCount = rlpStream.DecodeLong(); + SavedStateCount = rlpStream.DecodeLong(); + SavedNodesCount = rlpStream.DecodeLong(); + SavedAccounts = rlpStream.DecodeLong(); + SavedCode = rlpStream.DecodeLong(); + RequestedNodesCount = rlpStream.DecodeLong(); + DbChecks = rlpStream.DecodeLong(); + StateWasThere = rlpStream.DecodeLong(); + StateWasNotThere = rlpStream.DecodeLong(); + DataSize = rlpStream.DecodeLong(); + + if (rlpStream.Position != rlpStream.Length) + { + SecondsInSync = rlpStream.DecodeLong(); + } } } diff --git a/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncFeed.cs b/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncFeed.cs index e22792cb7d6..79be14f0cb8 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncFeed.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncFeed.cs @@ -2,7 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Concurrent; +using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Nethermind.Logging; @@ -61,7 +64,7 @@ public StateSyncFeed( } } - public override SyncResponseHandlingResult HandleResponse(StateSyncBatch? batch, PeerInfo? peer = null) + public override SyncResponseHandlingResult HandleResponse(StateSyncBatch? batch, PeerInfo peer = null) { return _treeSync.HandleResponse(batch, peer); } diff --git a/src/Nethermind/Nethermind.Synchronization/FastSync/TreeSync.cs b/src/Nethermind/Nethermind.Synchronization/FastSync/TreeSync.cs index dab5f5f22d3..6c83c15a173 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastSync/TreeSync.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastSync/TreeSync.cs @@ -6,11 +6,11 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Text; using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain; using Nethermind.Core; -using Nethermind.Core.Buffers; using Nethermind.Core.Caching; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; @@ -694,9 +694,6 @@ private void SaveNode(StateSyncItem syncItem, byte[] data) { if (_logger.IsInfo) _logger.Info($"Saving root {syncItem.Hash} of {_branchProgress.CurrentSyncBlock}"); - _stateDb.Flush(); - _codeDb.Flush(); - Interlocked.Exchange(ref _rootSaved, 1); } @@ -874,7 +871,7 @@ private void HandleTrieNode(StateSyncItem currentStateSyncItem, byte[] currentRe { _pendingItems.MaxStateLevel = 64; DependentItem dependentItem = new(currentStateSyncItem, currentResponseItem, 2, true); - (Keccak codeHash, Keccak storageRoot) = AccountDecoder.DecodeHashesOnly(new RlpStream(trieNode.Value.ToArray())); + (Keccak codeHash, Keccak storageRoot) = AccountDecoder.DecodeHashesOnly(new RlpStream(trieNode.Value)); if (codeHash != Keccak.OfAnEmptyString) { // prepare a branch without the code DB diff --git a/src/Nethermind/Nethermind.Synchronization/IBeaconSyncStrategy.cs b/src/Nethermind/Nethermind.Synchronization/IBeaconSyncStrategy.cs index 06bc322b829..5696fef9f8a 100644 --- a/src/Nethermind/Nethermind.Synchronization/IBeaconSyncStrategy.cs +++ b/src/Nethermind/Nethermind.Synchronization/IBeaconSyncStrategy.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Configuration; using Nethermind.Core; using Nethermind.Core.Crypto; diff --git a/src/Nethermind/Nethermind.Synchronization/IProcessExitSourceExtensions.cs b/src/Nethermind/Nethermind.Synchronization/IProcessExitSourceExtensions.cs deleted file mode 100644 index 54ca859fd11..00000000000 --- a/src/Nethermind/Nethermind.Synchronization/IProcessExitSourceExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using Nethermind.Config; -using Nethermind.Logging; -using Nethermind.Synchronization.ParallelSync; - -namespace Nethermind.Synchronization; - -public static class IProcessExitSourceExtensions -{ - public static void WatchForExit( - this IProcessExitSource exitSource, - ISyncModeSelector syncMode, - ILogManager logManager, - TimeSpan? exitConditionDuration = null) - { - ILogger logger = logManager.GetClassLogger(); - - // Usually there are time where the mode changed to WaitingForBlock temporarily. So there need to be a small - // wait to make sure the sync really is completed. - exitConditionDuration ??= TimeSpan.FromSeconds(5); - - DateTime lastExitConditionTime = DateTime.MaxValue; - syncMode.Changed += ((sender, args) => - { - if (args.Current is SyncMode.WaitingForBlock or SyncMode.None) - { - if (lastExitConditionTime == DateTime.MaxValue) - { - lastExitConditionTime = DateTime.Now; - } - else if (DateTime.Now - lastExitConditionTime > exitConditionDuration) - { - logger.Info($"Sync finished. Exiting...."); - exitSource.Exit(0); - } - } - else - { - lastExitConditionTime = DateTime.MaxValue; - } - }); - } -} diff --git a/src/Nethermind/Nethermind.Synchronization/MallocTrimmer.cs b/src/Nethermind/Nethermind.Synchronization/MallocTrimmer.cs deleted file mode 100644 index 4574e37c9b9..00000000000 --- a/src/Nethermind/Nethermind.Synchronization/MallocTrimmer.cs +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Diagnostics; -using Nethermind.Core.Extensions; -using Nethermind.Core.Memory; -using Nethermind.Logging; -using Nethermind.Synchronization.ParallelSync; -using Timer = System.Timers.Timer; - -namespace Nethermind.Synchronization; - -public class MallocTrimmer -{ - private MallocHelper _mallocHelper; - private ILogger _logger; - - public MallocTrimmer( - ISyncModeSelector syncModeSelector, - TimeSpan interval, - ILogManager logManager, - MallocHelper? mallocHelper = null - ) - { - _mallocHelper = mallocHelper ?? new MallocHelper(); - _logger = logManager.GetClassLogger(); - - if (interval == TimeSpan.Zero) return; - - Timer timer = new(interval); - timer.Elapsed += (sender, args) => Trim(); - - syncModeSelector.Changed += (_, args) => - { - bool notSyncing = args.Current is SyncMode.None or SyncMode.WaitingForBlock; - timer.Enabled = !notSyncing; - }; - } - - private void Trim() - { - // Unlike a GC, this seems to be single threaded, going through each arena one by one. - // It does however, lock the arena. On 32 thread machine, 256 arena, this take between 300ms to 1 second - // in total, so about 1 to 4 ms for each arena, which is the possible hang when allocating via malloc. - // This does not apply to managed code though, so this is largely the concern of rocksdb when reading - // from uncached block. - // - // Unlike the standard free(), in addition to always clearing fastbin and consolidating chunks, this - // also MADV_DONTNEED large enough free section of the heap. This also means private/virtual memory - // does not go down, but RSS and GC load does. - long startTime = Stopwatch.GetTimestamp(); - if (_logger.IsDebug) _logger.Debug("Trimming malloc heaps"); - bool wasReleased = _mallocHelper.MallocTrim((uint)1.MiB()); - if (_logger.IsDebug) _logger.Debug($"Trimming malloc heap took {Stopwatch.GetElapsedTime(startTime)}. wasReleased: {wasReleased}"); - } -} diff --git a/src/Nethermind/Nethermind.Synchronization/ParallelSync/ISyncProgressResolver.cs b/src/Nethermind/Nethermind.Synchronization/ParallelSync/ISyncProgressResolver.cs index b794c1ac771..3608af55b45 100644 --- a/src/Nethermind/Nethermind.Synchronization/ParallelSync/ISyncProgressResolver.cs +++ b/src/Nethermind/Nethermind.Synchronization/ParallelSync/ISyncProgressResolver.cs @@ -10,8 +10,6 @@ namespace Nethermind.Synchronization.ParallelSync { public interface ISyncProgressResolver { - void UpdateBarriers(); - long FindBestFullState(); long FindBestHeader(); diff --git a/src/Nethermind/Nethermind.Synchronization/ParallelSync/MultiSyncModeSelector.cs b/src/Nethermind/Nethermind.Synchronization/ParallelSync/MultiSyncModeSelector.cs index 60530ebeb27..12dabccb235 100644 --- a/src/Nethermind/Nethermind.Synchronization/ParallelSync/MultiSyncModeSelector.cs +++ b/src/Nethermind/Nethermind.Synchronization/ParallelSync/MultiSyncModeSelector.cs @@ -33,7 +33,7 @@ namespace Nethermind.Synchronization.ParallelSync /// - Beacon modes are allied directly. /// - If no Beacon mode is applied and we have good peers on the network we apply ,. /// - public class MultiSyncModeSelector : ISyncModeSelector + public class MultiSyncModeSelector : ISyncModeSelector, IDisposable { /// /// Number of blocks before the best peer's head when we switch from fast sync to full sync @@ -134,17 +134,12 @@ public void Stop() public void Update() { _pivotNumber = _syncConfig.PivotNumberParsed; - bool shouldBeInUpdatingPivot = ShouldBeInUpdatingPivot(); SyncMode newModes; string reason = string.Empty; if (_syncProgressResolver.IsLoadingBlocksFromDb()) { newModes = SyncMode.DbLoad; - if (shouldBeInUpdatingPivot) - { - newModes |= SyncMode.UpdatingPivot; - } } else if (!_syncConfig.SynchronizationEnabled) { @@ -154,6 +149,7 @@ public void Update() else { bool inBeaconControl = _beaconSyncStrategy.ShouldBeInBeaconModeControl(); + bool shouldBeInUpdatingPivot = ShouldBeInUpdatingPivot(); (UInt256? peerDifficulty, long? peerBlock) = ReloadDataFromPeers(); // if there are no peers that we could use then we cannot sync if (peerDifficulty is null || peerBlock is null || peerBlock == 0) @@ -220,11 +216,11 @@ public void Update() CheckAddFlag(best.IsInSnapRanges, SyncMode.SnapSync, ref newModes); CheckAddFlag(best.IsInDisconnected, SyncMode.Disconnected, ref newModes); CheckAddFlag(best.IsInWaitingForBlock, SyncMode.WaitingForBlock, ref newModes); - SyncMode current = Current; - if (IsTheModeSwitchWorthMentioning(current, newModes)) + if (IsTheModeSwitchWorthMentioning(newModes)) { + string stateString = BuildStateString(best); if (_logger.IsInfo) - _logger.Info($"Changing state {current} to {newModes} at {BuildStateString(best)}"); + _logger.Info($"Changing state {Current} to {newModes} at {stateString}"); } } catch (InvalidAsynchronousStateException) @@ -254,12 +250,12 @@ private void CheckAddFlag(in bool flag, SyncMode mode, ref SyncMode resultMode) } } - private bool IsTheModeSwitchWorthMentioning(SyncMode current, SyncMode newModes) + private bool IsTheModeSwitchWorthMentioning(SyncMode newModes) { - return newModes != current && - (_logger.IsDebug || - (newModes != SyncMode.WaitingForBlock || current != SyncMode.Full) && - (newModes != SyncMode.Full || current != SyncMode.WaitingForBlock)); + return _logger.IsDebug || + newModes != Current && + (newModes != SyncMode.WaitingForBlock || Current != SyncMode.Full) && + (newModes != SyncMode.Full || Current != SyncMode.WaitingForBlock); } private void UpdateSyncModes(SyncMode newModes, string? reason = null) @@ -290,10 +286,14 @@ private void UpdateSyncModes(SyncMode newModes, string? reason = null) /// Snapshot of the best known states /// A string describing the state of sync private static string BuildStateString(Snapshot best) => - $"processed: {best.Processed} | state: {best.State} | block: {best.Block} | header: {best.Header} | target block: {best.TargetBlock} | peer block: {best.Peer.Block}"; - - private static string BuildStateStringDebug(Snapshot best) => - $"processed: {best.Processed} | state: {best.State} | block: {best.Block} | header: {best.Header} | chain difficulty: {best.ChainDifficulty} | target block: {best.TargetBlock} | peer block: {best.Peer.Block} | peer total difficulty: {best.Peer.TotalDifficulty}"; + $"processed:{best.Processed}|" + + $"state:{best.State}|" + + $"block:{best.Block}|" + + $"header:{best.Header}|" + + $"chain difficulty:{best.ChainDifficulty}|" + + $"target block:{best.TargetBlock}|" + + $"peer block:{best.Peer.Block}|" + + $"peer total difficulty:{best.Peer.TotalDifficulty}"; private bool IsInAStickyFullSyncMode(Snapshot best) { @@ -713,13 +713,13 @@ private Snapshot EnsureSnapshot(in UInt256 peerDifficulty, long peerBlock, bool if (IsSnapshotInvalid(best)) { - string stateString = BuildStateStringDebug(best); + string stateString = BuildStateString(best); if (_logger.IsWarn) _logger.Warn($"Invalid snapshot calculation: {stateString}. Recalculating progress pointers..."); _syncProgressResolver.RecalculateProgressPointers(); best = TakeSnapshot(peerDifficulty, peerBlock, inBeaconControl); if (IsSnapshotInvalid(best)) { - string recalculatedSnapshot = BuildStateStringDebug(best); + string recalculatedSnapshot = BuildStateString(best); string errorMessage = $"Cannot recalculate snapshot progress. Invalid snapshot calculation: {recalculatedSnapshot}"; if (_logger.IsError) _logger.Error(errorMessage); throw new InvalidAsynchronousStateException(errorMessage); diff --git a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncDispatcher.cs b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncDispatcher.cs index 40cca61b6ce..d20edf05dca 100644 --- a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncDispatcher.cs +++ b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncDispatcher.cs @@ -5,7 +5,6 @@ using System.Threading; using System.Threading.Tasks; using Nethermind.Core.Exceptions; -using Nethermind.Core.Extensions; using Nethermind.Logging; using Nethermind.Synchronization.Peers; @@ -70,14 +69,14 @@ public async Task Start(CancellationToken cancellationToken) if (currentStateLocal == SyncFeedState.Dormant) { - if (Logger.IsDebug) Logger.Debug($"{GetType().NameWithGenerics()} is going to sleep."); + if (Logger.IsDebug) Logger.Debug($"{GetType().Name} is going to sleep."); if (dormantTaskLocal is null) { if (Logger.IsWarn) Logger.Warn("Dormant task is NULL when trying to await it"); } await (dormantTaskLocal?.Task ?? Task.CompletedTask).WaitAsync(cancellationToken); - if (Logger.IsDebug) Logger.Debug($"{GetType().NameWithGenerics()} got activated."); + if (Logger.IsDebug) Logger.Debug($"{GetType().Name} got activated."); } else if (currentStateLocal == SyncFeedState.Active) { @@ -87,7 +86,7 @@ public async Task Start(CancellationToken cancellationToken) { if (!Feed.IsMultiFeed) { - if (Logger.IsTrace) Logger.Trace($"{Feed.GetType().NameWithGenerics()} enqueued a null request."); + if (Logger.IsTrace) Logger.Trace($"{Feed.GetType().Name} enqueued a null request."); } await Task.Delay(10, cancellationToken); @@ -107,20 +106,20 @@ public async Task Start(CancellationToken cancellationToken) if (!Feed.IsMultiFeed) { - if (Logger.IsDebug) Logger.Debug($"Awaiting single dispatch from {Feed.GetType().NameWithGenerics()} with allocated {allocatedPeer}"); + if (Logger.IsDebug) Logger.Debug($"Awaiting single dispatch from {Feed.GetType().Name} with allocated {allocatedPeer}"); await task; - if (Logger.IsDebug) Logger.Debug($"Single dispatch from {Feed.GetType().NameWithGenerics()} with allocated {allocatedPeer} has been processed"); + if (Logger.IsDebug) Logger.Debug($"Single dispatch from {Feed.GetType().Name} with allocated {allocatedPeer} has been processed"); } } else { - Logger.Debug($"DISPATCHER - {GetType().NameWithGenerics()}: peer NOT allocated"); + Logger.Debug($"DISPATCHER - {this.GetType().Name}: peer NOT allocated"); DoHandleResponse(request); } } else if (currentStateLocal == SyncFeedState.Finished) { - if (Logger.IsInfo) Logger.Info($"{GetType().NameWithGenerics()} has finished work."); + if (Logger.IsInfo) Logger.Info($"{GetType().Name} has finished work."); break; } } diff --git a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncMode.cs b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncMode.cs index b02e9a56bbd..5d5c066ff32 100644 --- a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncMode.cs +++ b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncMode.cs @@ -69,34 +69,6 @@ public enum SyncMode public static class SyncModeExtensions { - public static bool NotSyncing(this SyncMode syncMode) => syncMode is SyncMode.WaitingForBlock or SyncMode.Disconnected; - - public static bool HaveNotSyncedBodiesYet(this SyncMode syncMode) => - syncMode.HasFlag(SyncMode.FastHeaders) || - syncMode.HasFlag(SyncMode.FastBodies) || - syncMode.HasFlag(SyncMode.FastSync) || - syncMode.HasFlag(SyncMode.StateNodes) || - syncMode.HasFlag(SyncMode.SnapSync) || - syncMode.HasFlag(SyncMode.BeaconHeaders) || - syncMode.HasFlag(SyncMode.UpdatingPivot); - - public static bool HaveNotSyncedReceiptsYet(this SyncMode syncMode) => - syncMode.HasFlag(SyncMode.FastBlocks) || - syncMode.HasFlag(SyncMode.FastSync) || - syncMode.HasFlag(SyncMode.StateNodes) || - syncMode.HasFlag(SyncMode.SnapSync) || - syncMode.HasFlag(SyncMode.BeaconHeaders) || - syncMode.HasFlag(SyncMode.UpdatingPivot); - - public static bool HaveNotSyncedHeadersYet(this SyncMode syncMode) => - syncMode.HasFlag(SyncMode.FastHeaders) || - syncMode.HasFlag(SyncMode.BeaconHeaders) || - syncMode.HasFlag(SyncMode.UpdatingPivot); - - public static bool HaveNotSyncedStateYet(this SyncMode syncMode) => - syncMode.HasFlag(SyncMode.FastSync) || - syncMode.HasFlag(SyncMode.StateNodes) || - syncMode.HasFlag(SyncMode.SnapSync) || - syncMode.HasFlag(SyncMode.UpdatingPivot); + public static bool NotSyncing(this SyncMode syncMode) => syncMode == SyncMode.WaitingForBlock || syncMode == SyncMode.Disconnected; } } diff --git a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncProgressResolver.cs b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncProgressResolver.cs index 902dbb145a4..70ee82a19cb 100644 --- a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncProgressResolver.cs +++ b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncProgressResolver.cs @@ -31,10 +31,10 @@ public class SyncProgressResolver : ISyncProgressResolver private readonly ISyncConfig _syncConfig; // ReSharper disable once NotAccessedField.Local - private readonly ILogger _logger; + private ILogger _logger; - private long _bodiesBarrier; - private long _receiptsBarrier; + private readonly long _bodiesBarrier; + private readonly long _receiptsBarrier; public SyncProgressResolver(IBlockTree blockTree, IReceiptStorage receiptStorage, @@ -56,12 +56,6 @@ public SyncProgressResolver(IBlockTree blockTree, _receiptsBarrier = _syncConfig.AncientReceiptsBarrierCalc; } - public void UpdateBarriers() - { - _bodiesBarrier = _syncConfig.AncientBodiesBarrierCalc; - _receiptsBarrier = _syncConfig.AncientReceiptsBarrierCalc; - } - private bool IsFullySynced(Keccak stateRoot) { if (stateRoot == Keccak.EmptyTreeHash) diff --git a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncedTxGossipPolicy.cs b/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncedTxGossipPolicy.cs deleted file mode 100644 index 85262725560..00000000000 --- a/src/Nethermind/Nethermind.Synchronization/ParallelSync/SyncedTxGossipPolicy.cs +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.TxPool; - -namespace Nethermind.Synchronization.ParallelSync; - -public class SyncedTxGossipPolicy : ITxGossipPolicy -{ - private readonly ISyncModeSelector _syncModeSelector; - - public SyncedTxGossipPolicy(ISyncModeSelector syncModeSelector) - { - _syncModeSelector = syncModeSelector; - } - - public bool ShouldListenToGossippedTransactions => (_syncModeSelector.Current & SyncMode.WaitingForBlock) != 0; -} diff --git a/src/Nethermind/Nethermind.Synchronization/Peers/ISyncPeerPool.cs b/src/Nethermind/Nethermind.Synchronization/Peers/ISyncPeerPool.cs index e744ee79cc1..b5313c840df 100644 --- a/src/Nethermind/Nethermind.Synchronization/Peers/ISyncPeerPool.cs +++ b/src/Nethermind/Nethermind.Synchronization/Peers/ISyncPeerPool.cs @@ -19,7 +19,7 @@ public interface ISyncPeerPool : IDisposable void ReportNoSyncProgress(PeerInfo peerInfo, AllocationContexts allocationContexts); - void ReportBreachOfProtocol(PeerInfo peerInfo, DisconnectReason disconnectReason, string details); + void ReportBreachOfProtocol(PeerInfo peerInfo, InitiateDisconnectReason initiateDisconnectReason, string details); void ReportWeakPeer(PeerInfo peerInfo, AllocationContexts allocationContexts); diff --git a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerAllocation.cs b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerAllocation.cs index 4cf37a1b0e9..3b26c14b6e0 100644 --- a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerAllocation.cs +++ b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerAllocation.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using Nethermind.Blockchain; using Nethermind.Stats; using Nethermind.Synchronization.Peers.AllocationStrategies; @@ -17,12 +16,10 @@ public class SyncPeerAllocation /// /// this should be used whenever we change IsAllocated property on PeerInfo- /// - private static readonly object _allocationLock = new(); + private static object _allocationLock = new(); - private readonly IPeerAllocationStrategy _peerAllocationStrategy; + private IPeerAllocationStrategy _peerAllocationStrategy; public AllocationContexts Contexts { get; } - - [MemberNotNullWhen(true, nameof(HasPeer))] public PeerInfo? Current { get; private set; } public bool HasPeer => Current is not null; diff --git a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs index cf826d4c806..740e32876a0 100644 --- a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs +++ b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeerPool.cs @@ -15,10 +15,13 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Core.Specs; using Nethermind.Int256; using Nethermind.Logging; +using Nethermind.Specs; using Nethermind.Stats; using Nethermind.Stats.Model; +using Nethermind.Synchronization.ParallelSync; using Nethermind.Synchronization.Peers.AllocationStrategies; using Timer = System.Timers.Timer; @@ -83,7 +86,7 @@ public void ReportNoSyncProgress(PeerInfo peerInfo, AllocationContexts allocatio ReportWeakPeer(peerInfo, allocationContexts); } - public void ReportBreachOfProtocol(PeerInfo? peerInfo, DisconnectReason disconnectReason, string details) + public void ReportBreachOfProtocol(PeerInfo? peerInfo, InitiateDisconnectReason initiateDisconnectReason, string details) { /* since the allocations can have the peers dynamically changed * it may be hard for the external classes to ensure that the peerInfo is not null at the time when they report @@ -92,7 +95,7 @@ public void ReportBreachOfProtocol(PeerInfo? peerInfo, DisconnectReason disconne if (peerInfo is not null) { _stats.ReportSyncEvent(peerInfo.SyncPeer.Node, NodeStatsEventType.SyncFailed); - peerInfo.SyncPeer.Disconnect(disconnectReason, details); + peerInfo.SyncPeer.Disconnect(initiateDisconnectReason, details); } } @@ -145,7 +148,7 @@ public async Task StopAsync() _isStarted = false; _refreshLoopCancellation.Cancel(); await (_refreshLoopTask ?? Task.CompletedTask); - Parallel.ForEach(_peers, p => { p.Value.SyncPeer.Disconnect(DisconnectReason.AppClosing, "App Close"); }); + Parallel.ForEach(_peers, p => { p.Value.SyncPeer.Disconnect(InitiateDisconnectReason.AppClosing, "App Close"); }); } public PeerInfo? GetPeer(Node node) => _peers.TryGetValue(node.Id, out PeerInfo? peerInfo) ? peerInfo : null; @@ -322,9 +325,18 @@ public async Task Allocate(IPeerAllocationStrategy peerAlloc SyncPeerAllocation allocation = new(peerAllocationStrategy, allocationContexts); while (true) { - if (TryAllocateOnce(peerAllocationStrategy, allocationContexts, allocation)) + lock (_isAllocatedChecks) { - return allocation; + allocation.AllocateBestPeer(InitializedPeers.Where(p => p.CanBeAllocated(allocationContexts)), _stats, _blockTree); + if (allocation.HasPeer) + { + if (peerAllocationStrategy.CanBeReplaced) + { + _replaceableAllocations.TryAdd(allocation, null); + } + + return allocation; + } } bool timeoutReached = timeoutMilliseconds == 0 @@ -344,25 +356,6 @@ public async Task Allocate(IPeerAllocationStrategy peerAlloc } } - private bool TryAllocateOnce(IPeerAllocationStrategy peerAllocationStrategy, AllocationContexts allocationContexts, SyncPeerAllocation allocation) - { - lock (_isAllocatedChecks) - { - allocation.AllocateBestPeer(InitializedPeers.Where(p => p.CanBeAllocated(allocationContexts)), _stats, _blockTree); - if (allocation.HasPeer) - { - if (peerAllocationStrategy.CanBeReplaced) - { - _replaceableAllocations.TryAdd(allocation, null); - } - - return true; - } - } - - return false; - } - /// /// Frees the allocation space borrowed earlier for some sync consumer. /// @@ -521,7 +514,7 @@ private int DropWorstPeer() } } - worstPeer?.SyncPeer.Disconnect(DisconnectReason.DropWorstPeer, $"PEER REVIEW / {worstReason}"); + worstPeer?.SyncPeer.Disconnect(InitiateDisconnectReason.DropWorstPeer, $"PEER REVIEW / {worstReason}"); return 1; } @@ -665,7 +658,7 @@ public void ReportRefreshFailed(ISyncPeer syncPeer, string reason, Exception? ex } else { - syncPeer.Disconnect(DisconnectReason.PeerRefreshFailed, $"refresh peer info fault - {reason}"); + syncPeer.Disconnect(InitiateDisconnectReason.PeerRefreshFailed, $"refresh peer info fault - {reason}"); } } diff --git a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeersReport.cs b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeersReport.cs index 5f80e4a9699..ce1d5762ba1 100644 --- a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeersReport.cs +++ b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeersReport.cs @@ -52,7 +52,7 @@ public void WriteFullReport() RememberState(out bool _); _logger.Debug(MakeSummaryReportForPeers(_peerPool.InitializedPeers, $"Sync peers - Connected: {_currentInitializedPeerCount} | All: {_peerPool.PeerCount} | Max: {_peerPool.PeerMaxCount}")); - _logger.Debug(MakeReportForPeers(OrderedPeers, "")); + _logger.Debug(MakeReportForPeer(OrderedPeers, "")); } } @@ -71,10 +71,14 @@ public void WriteAllocatedReport() return; } + var header = $"Allocated sync peers {_currentInitializedPeerCount}({_peerPool.PeerCount})/{_peerPool.PeerMaxCount}"; if (_logger.IsDebug) { - var header = $"Allocated sync peers {_currentInitializedPeerCount}({_peerPool.PeerCount})/{_peerPool.PeerMaxCount}"; - _logger.Debug(MakeReportForPeers(OrderedPeers.Where(p => (p.AllocatedContexts & AllocationContexts.All) != AllocationContexts.None), header)); + _logger.Debug(MakeReportForPeer(OrderedPeers.Where(p => (p.AllocatedContexts & AllocationContexts.All) != AllocationContexts.None), header)); + } + else + { + _logger.Info(MakeSummaryReportForPeers(_peerPool.InitializedPeers, header)); } } } @@ -88,20 +92,6 @@ public void WriteAllocatedReport() _stringBuilder.Append(header); _stringBuilder.Append(" |"); - bool isFirst = true; - foreach (var peerGroup in peers.GroupBy(peerInfo => peerInfo.SyncPeer.Name).OrderBy(p => p.Key)) - { - if (isFirst) - { - isFirst = false; - } - else - { - _stringBuilder.Append(','); - } - _stringBuilder.Append($" {peerGroup.Key} ({peerGroup.Count() / sum,3:P0})"); - } - _stringBuilder.Append(" |"); PeersContextCounts activeContexts = new(); PeersContextCounts sleepingContexts = new(); @@ -117,7 +107,7 @@ public void WriteAllocatedReport() sleepingContexts.AppendTo(_stringBuilder, activeContexts.Total != activeContexts.None ? "None" : "All"); _stringBuilder.Append(" |"); - isFirst = true; + bool isFirst = true; foreach (var peerGroup in peerGroups.OrderByDescending(x => x.Count())) { if (isFirst) @@ -128,7 +118,7 @@ public void WriteAllocatedReport() { _stringBuilder.Append(','); } - _stringBuilder.Append($" {peerGroup.Key} ({peerGroup.Count() / sum,3:P0})"); + _stringBuilder.Append($" {peerGroup.Key} ({peerGroup.Count() / sum,6:P2})"); } string result = _stringBuilder.ToString(); @@ -155,7 +145,7 @@ static void CountContexts(AllocationContexts contexts, ref PeersContextCounts co } } - internal string MakeReportForPeers(IEnumerable peers, string header) + internal string? MakeReportForPeer(IEnumerable peers, string header) { _stringBuilder.Append(header); bool headerAdded = false; diff --git a/src/Nethermind/Nethermind.Synchronization/Reporting/SnapshotReport.cs b/src/Nethermind/Nethermind.Synchronization/Reporting/SnapshotReport.cs index a882403ea4e..48b28ee090d 100644 --- a/src/Nethermind/Nethermind.Synchronization/Reporting/SnapshotReport.cs +++ b/src/Nethermind/Nethermind.Synchronization/Reporting/SnapshotReport.cs @@ -1,6 +1,14 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Linq; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.ComponentModel; +using Microsoft.VisualBasic; +using Nethermind.Synchronization.ParallelSync; + namespace Nethermind.Synchronization.Reporting { public class SyncReportSymmary diff --git a/src/Nethermind/Nethermind.Synchronization/Reporting/SyncReport.cs b/src/Nethermind/Nethermind.Synchronization/Reporting/SyncReport.cs index 0b1eb8f4728..b2c0da67f42 100644 --- a/src/Nethermind/Nethermind.Synchronization/Reporting/SyncReport.cs +++ b/src/Nethermind/Nethermind.Synchronization/Reporting/SyncReport.cs @@ -3,6 +3,7 @@ using System; using System.Text; +using System.Timers; using Nethermind.Blockchain.Synchronization; using Nethermind.Core; using Nethermind.Core.Timers; @@ -15,7 +16,7 @@ namespace Nethermind.Synchronization.Reporting { public class SyncReport : ISyncReport { - private const int SpeedPaddingLength = 9; + private const int SpeedPaddingLength = 5; private readonly ISyncPeerPool _syncPeerPool; private readonly ISyncConfig _syncConfig; @@ -23,14 +24,14 @@ public class SyncReport : ISyncReport private readonly IPivot _pivot; private readonly ILogger _logger; - private readonly SyncPeersReport _syncPeersReport; + private SyncPeersReport _syncPeersReport; private int _reportId; private const int SyncReportFrequency = 1; private const int PeerCountFrequency = 15; private const int NoProgressStateSyncReportFrequency = 30; private const int SyncAllocatedPeersReportFrequency = 30; private const int SyncFullPeersReportFrequency = 120; - private static readonly TimeSpan _defaultReportingIntervals = TimeSpan.FromSeconds(5); + private static readonly TimeSpan _defaultReportingIntervals = TimeSpan.FromSeconds(1); public SyncReport(ISyncPeerPool syncPeerPool, INodeStatsManager nodeStatsManager, ISyncModeSelector syncModeSelector, ISyncConfig syncConfig, IPivot pivot, ILogManager logManager, ITimerFactory? timerFactory = null, double tickTime = 1000) @@ -119,13 +120,13 @@ private void TimerOnElapsed(object? sender, EventArgs e) private static string Pad(decimal value, int length) { - string valueString = $"{value:N0}"; + string valueString = $"{value:F2}"; return valueString.PadLeft(length + 3, ' '); } private static string Pad(long value, int length) { - string valueString = $"{value:N0}"; + string valueString = $"{value}"; return valueString.PadLeft(length, ' '); } @@ -134,19 +135,15 @@ private static string Pad(long value, int length) private string _paddedPivot; private string _paddedAmountOfOldBodiesToDownload; private string _paddedAmountOfOldReceiptsToDownload; - private long _amountOfBodiesToDownload; - private long _amountOfReceiptsToDownload; private void SetPaddedPivots() { _fastBlocksPivotNumber = _syncConfig.PivotNumberParsed; - _blockPaddingLength = _fastBlocksPivotNumber.ToString("N0").Length; + _blockPaddingLength = _fastBlocksPivotNumber.ToString().Length; _paddedPivot = $"{Pad(_fastBlocksPivotNumber, _blockPaddingLength)}"; long amountOfBodiesToDownload = _fastBlocksPivotNumber - _syncConfig.AncientBodiesBarrier; - _amountOfBodiesToDownload = amountOfBodiesToDownload; _paddedAmountOfOldBodiesToDownload = $"{Pad(amountOfBodiesToDownload, $"{amountOfBodiesToDownload}".Length)}"; long amountOfReceiptsToDownload = _fastBlocksPivotNumber - _syncConfig.AncientReceiptsBarrier; - _amountOfReceiptsToDownload = amountOfReceiptsToDownload; _paddedAmountOfOldReceiptsToDownload = $"{Pad(_fastBlocksPivotNumber - _syncConfig.AncientReceiptsBarrier, $"{amountOfReceiptsToDownload}".Length)}"; } @@ -177,7 +174,7 @@ private void WriteSyncReport() { if (_reportId % PeerCountFrequency == 0) { - _logger.Info(_syncPeersReport.MakeSummaryReportForPeers(_syncPeerPool.InitializedPeers, $"Peers | with best block: {_syncPeerPool.InitializedPeersCount} | all: {_syncPeerPool.PeerCount}")); + _logger.Info(_syncPeersReport.MakeSummaryReportForPeers(_syncPeerPool.InitializedPeers, $"Peers | with known best block: {_syncPeerPool.InitializedPeersCount} | all: {_syncPeerPool.PeerCount}")); } } @@ -289,7 +286,7 @@ private void WriteFullSyncReport() return; } - _logger.Info($"Downloaded {Pad(FullSyncBlocksDownloaded.CurrentValue, _blockPaddingLength)} / {Pad(FullSyncBlocksKnown, _blockPaddingLength)} ({FullSyncBlocksDownloaded.CurrentValue / (float)(FullSyncBlocksKnown + 1),8:P2}) | current {Pad(FullSyncBlocksDownloaded.CurrentPerSecond, SpeedPaddingLength)} Blk/s | total {Pad(FullSyncBlocksDownloaded.TotalPerSecond, SpeedPaddingLength)} Blk/s"); + _logger.Info($"Downloaded {Pad(FullSyncBlocksDownloaded.CurrentValue, _blockPaddingLength)} / {Pad(FullSyncBlocksKnown, _blockPaddingLength)} | current {Pad(FullSyncBlocksDownloaded.CurrentPerSecond, SpeedPaddingLength)}bps | total {Pad(FullSyncBlocksDownloaded.TotalPerSecond, SpeedPaddingLength)}bps"); FullSyncBlocksDownloaded.SetMeasuringPoint(); } @@ -297,19 +294,19 @@ private void WriteFastBlocksReport(SyncMode currentSyncMode) { if ((currentSyncMode & SyncMode.FastHeaders) == SyncMode.FastHeaders) { - _logger.Info($"Old Headers {Pad(FastBlocksHeaders.CurrentValue, _blockPaddingLength)} / {_paddedPivot} ({FastBlocksHeaders.CurrentValue / (float)(_fastBlocksPivotNumber + 1),8:P2}) | queue {Pad(HeadersInQueue.CurrentValue, SpeedPaddingLength)} | current {Pad(FastBlocksHeaders.CurrentPerSecond, SpeedPaddingLength)} Blk/s | total {Pad(FastBlocksHeaders.TotalPerSecond, SpeedPaddingLength)} Blk/s"); + _logger.Info($"Old Headers {Pad(FastBlocksHeaders.CurrentValue, _blockPaddingLength)} / {_paddedPivot} | queue {Pad(HeadersInQueue.CurrentValue, SpeedPaddingLength)} | current {Pad(FastBlocksHeaders.CurrentPerSecond, SpeedPaddingLength)}bps | total {Pad(FastBlocksHeaders.TotalPerSecond, SpeedPaddingLength)}bps"); FastBlocksHeaders.SetMeasuringPoint(); } if ((currentSyncMode & SyncMode.FastBodies) == SyncMode.FastBodies) { - _logger.Info($"Old Bodies {Pad(FastBlocksBodies.CurrentValue, _blockPaddingLength)} / {_paddedAmountOfOldBodiesToDownload} ({FastBlocksBodies.CurrentValue / (float)(_amountOfBodiesToDownload + 1),8:P2}) | queue {Pad(BodiesInQueue.CurrentValue, SpeedPaddingLength)} | current {Pad(FastBlocksBodies.CurrentPerSecond, SpeedPaddingLength)} Blk/s | total {Pad(FastBlocksBodies.TotalPerSecond, SpeedPaddingLength)} Blk/s"); + _logger.Info($"Old Bodies {Pad(FastBlocksBodies.CurrentValue, _blockPaddingLength)} / {_paddedAmountOfOldBodiesToDownload} | queue {Pad(BodiesInQueue.CurrentValue, SpeedPaddingLength)} | current {Pad(FastBlocksBodies.CurrentPerSecond, SpeedPaddingLength)}bps | total {Pad(FastBlocksBodies.TotalPerSecond, SpeedPaddingLength)}bps"); FastBlocksBodies.SetMeasuringPoint(); } if ((currentSyncMode & SyncMode.FastReceipts) == SyncMode.FastReceipts) { - _logger.Info($"Old Receipts {Pad(FastBlocksReceipts.CurrentValue, _blockPaddingLength)} / {_paddedAmountOfOldReceiptsToDownload} ({FastBlocksReceipts.CurrentValue / (float)(_amountOfReceiptsToDownload + 1),8:P2}) | queue {Pad(ReceiptsInQueue.CurrentValue, SpeedPaddingLength)} | current {Pad(FastBlocksReceipts.CurrentPerSecond, SpeedPaddingLength)} Blk/s | total {Pad(FastBlocksReceipts.TotalPerSecond, SpeedPaddingLength)} Blk/s"); + _logger.Info($"Old Receipts {Pad(FastBlocksReceipts.CurrentValue, _blockPaddingLength)} / {_paddedAmountOfOldReceiptsToDownload} | queue {Pad(ReceiptsInQueue.CurrentValue, SpeedPaddingLength)} | current {Pad(FastBlocksReceipts.CurrentPerSecond, SpeedPaddingLength)}bps | total {Pad(FastBlocksReceipts.TotalPerSecond, SpeedPaddingLength)}bps"); FastBlocksReceipts.SetMeasuringPoint(); } } @@ -317,9 +314,9 @@ private void WriteFastBlocksReport(SyncMode currentSyncMode) private void WriteBeaconSyncReport() { long numHeadersToDownload = _pivot.PivotNumber - _pivot.PivotDestinationNumber + 1; - int paddingLength = numHeadersToDownload.ToString("N0").Length; + int paddingLength = numHeadersToDownload.ToString().Length; _logger.Info($"Beacon Headers from block {_pivot.PivotDestinationNumber} to block {_pivot.PivotNumber} | " - + $"{Pad(BeaconHeaders.CurrentValue, paddingLength)} / {Pad(numHeadersToDownload, paddingLength)} | queue {Pad(BeaconHeadersInQueue.CurrentValue, SpeedPaddingLength)} | current {Pad(BeaconHeaders.CurrentPerSecond, SpeedPaddingLength)} Blk/s | total {Pad(BeaconHeaders.TotalPerSecond, SpeedPaddingLength)} Blk/s"); + + $"{Pad(BeaconHeaders.CurrentValue, paddingLength)} / {Pad(numHeadersToDownload, paddingLength)} | queue {Pad(BeaconHeadersInQueue.CurrentValue, SpeedPaddingLength)} | current {Pad(BeaconHeaders.CurrentPerSecond, SpeedPaddingLength)}bps | total {Pad(BeaconHeaders.TotalPerSecond, SpeedPaddingLength)}bps"); BeaconHeaders.SetMeasuringPoint(); } diff --git a/src/Nethermind/Nethermind.Synchronization/SnapSync/AddRangeResult.cs b/src/Nethermind/Nethermind.Synchronization/SnapSync/AddRangeResult.cs index 37fe611029c..76b4f9da0db 100644 --- a/src/Nethermind/Nethermind.Synchronization/SnapSync/AddRangeResult.cs +++ b/src/Nethermind/Nethermind.Synchronization/SnapSync/AddRangeResult.cs @@ -1,6 +1,12 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + namespace Nethermind.Synchronization.SnapSync { public enum AddRangeResult diff --git a/src/Nethermind/Nethermind.Synchronization/SnapSync/ISnapProvider.cs b/src/Nethermind/Nethermind.Synchronization/SnapSync/ISnapProvider.cs index 3baac9d94d4..32b555d6e8a 100644 --- a/src/Nethermind/Nethermind.Synchronization/SnapSync/ISnapProvider.cs +++ b/src/Nethermind/Nethermind.Synchronization/SnapSync/ISnapProvider.cs @@ -1,6 +1,11 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; using Nethermind.Core.Crypto; using Nethermind.State.Snap; diff --git a/src/Nethermind/Nethermind.Synchronization/SnapSync/Pivot.cs b/src/Nethermind/Nethermind.Synchronization/SnapSync/Pivot.cs index 136933d70e0..cbb4cd46fea 100644 --- a/src/Nethermind/Nethermind.Synchronization/SnapSync/Pivot.cs +++ b/src/Nethermind/Nethermind.Synchronization/SnapSync/Pivot.cs @@ -2,6 +2,10 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; using Nethermind.Blockchain; using Nethermind.Core; using Nethermind.Logging; @@ -51,7 +55,7 @@ public BlockHeader GetPivotHeader() private void LogPivotChanged(string msg) { - _logger.Info($"Snap - {msg} - Pivot changed from {_bestHeader?.Number} to {_blockTree.BestSuggestedHeader?.Number}"); + _logger.Info($"SNAP - {msg} - Pivot changed from {_bestHeader?.Number} to {_blockTree.BestSuggestedHeader?.Number}"); } public void UpdateHeaderForcefully() diff --git a/src/Nethermind/Nethermind.Synchronization/SnapSync/ProgressTracker.cs b/src/Nethermind/Nethermind.Synchronization/SnapSync/ProgressTracker.cs index e9152ad42d3..6da54fa603f 100644 --- a/src/Nethermind/Nethermind.Synchronization/SnapSync/ProgressTracker.cs +++ b/src/Nethermind/Nethermind.Synchronization/SnapSync/ProgressTracker.cs @@ -18,12 +18,10 @@ namespace Nethermind.Synchronization.SnapSync { public class ProgressTracker { - private const string NO_REQUEST = "Skipped Request"; + private const string NO_REQUEST = "NO REQUEST"; private const int STORAGE_BATCH_SIZE = 1_200; - public const int HIGH_STORAGE_QUEUE_SIZE = STORAGE_BATCH_SIZE * 100; private const int CODES_BATCH_SIZE = 1_000; - public const int HIGH_CODES_QUEUE_SIZE = CODES_BATCH_SIZE * 5; private readonly byte[] ACC_PROGRESS_KEY = Encoding.ASCII.GetBytes("AccountProgressKey"); // This does not need to be a lot as it spawn other requests. In fact 8 is probably too much. It is severely @@ -122,7 +120,7 @@ public bool CanSync() return false; } - if (_logger.IsInfo) _logger.Info($"Starting the Snap data sync from the {header.ToString(BlockHeader.Format.Short)} {header.StateRoot} root"); + if (_logger.IsInfo) _logger.Info($"Starting the SNAP data sync from the {header.ToString(BlockHeader.Format.Short)} {header.StateRoot} root"); return true; } @@ -144,154 +142,110 @@ public void UpdatePivot() if (!AccountsToRefresh.IsEmpty) { - return DequeAccountToRefresh(request, rootHash); - } + Interlocked.Increment(ref _activeAccRefreshRequests); - if (ShouldRequestAccountRequests() && AccountRangeReadyForRequest.TryDequeue(out AccountRangePartition partition)) - { - return CreateAccountRangeRequest(rootHash, partition, blockNumber, request); - } + LogRequest($"AccountsToRefresh:{AccountsToRefresh.Count}"); - if (TryDequeNextSlotRange(out StorageRange slotRange)) - { - return CreateNextSlowRangeRequest(slotRange, rootHash, blockNumber, request); - } + int queueLength = AccountsToRefresh.Count; + AccountWithStorageStartingHash[] paths = new AccountWithStorageStartingHash[queueLength]; - if (StoragesToRetrieve.Count >= HIGH_STORAGE_QUEUE_SIZE) - { - return DequeStorageToRetrieveRequest(rootHash, blockNumber, request); - } + for (int i = 0; i < queueLength && AccountsToRefresh.TryDequeue(out var acc); i++) + { + paths[i] = acc; + } - if (CodesToRetrieve.Count >= HIGH_CODES_QUEUE_SIZE) - { - return DequeCodeRequest(request); - } + request.AccountsToRefreshRequest = new AccountsToRefreshRequest() { RootHash = rootHash, Paths = paths }; - if (!StoragesToRetrieve.IsEmpty) - { - return DequeStorageToRetrieveRequest(rootHash, blockNumber, request); - } + return (request, false); - if (!CodesToRetrieve.IsEmpty) - { - return DequeCodeRequest(request); } - bool rangePhaseFinished = IsSnapGetRangesFinished(); - if (rangePhaseFinished) + if (ShouldRequestAccountRequests() && AccountRangeReadyForRequest.TryDequeue(out AccountRangePartition partition)) { - _logger.Info($"Snap - State Ranges (Phase 1) finished."); - FinishRangePhase(); - } + Interlocked.Increment(ref _activeAccountRequests); - LogRequest(NO_REQUEST); + AccountRange range = new( + rootHash, + partition.NextAccountPath, + partition.AccountPathLimit, + blockNumber); - return (null, IsSnapGetRangesFinished()); - } + LogRequest("AccountRange"); - private (SnapSyncBatch request, bool finished) DequeCodeRequest(SnapSyncBatch request) - { - Interlocked.Increment(ref _activeCodeRequests); + request.AccountRangeRequest = range; - // TODO: optimize this - List codesToQuery = new(CODES_BATCH_SIZE); - for (int i = 0; i < CODES_BATCH_SIZE && CodesToRetrieve.TryDequeue(out ValueKeccak codeHash); i++) - { - codesToQuery.Add(codeHash); + return (request, false); } + else if (TryDequeNextSlotRange(out StorageRange slotRange)) + { + slotRange.RootHash = rootHash; + slotRange.BlockNumber = blockNumber; - codesToQuery.Sort(); - - LogRequest($"CodesToRetrieve:{codesToQuery.Count}"); - - request.CodesRequest = codesToQuery.ToArray(); + LogRequest($"NextSlotRange:{slotRange.Accounts.Length}"); - return (request, false); - } + request.StorageRangeRequest = slotRange; - private (SnapSyncBatch request, bool finished) DequeStorageToRetrieveRequest(Keccak rootHash, long blockNumber, - SnapSyncBatch request) - { - Interlocked.Increment(ref _activeStorageRequests); - - // TODO: optimize this - List storagesToQuery = new(STORAGE_BATCH_SIZE); - for (int i = 0; i < STORAGE_BATCH_SIZE && StoragesToRetrieve.TryDequeue(out PathWithAccount storage); i++) - { - storagesToQuery.Add(storage); + return (request, false); } - - StorageRange storageRange = new() + else if (!StoragesToRetrieve.IsEmpty) { - RootHash = rootHash, - Accounts = storagesToQuery.ToArray(), - StartingHash = ValueKeccak.Zero, - BlockNumber = blockNumber - }; - - LogRequest($"StoragesToRetrieve:{storagesToQuery.Count}"); - - request.StorageRangeRequest = storageRange; - - return (request, false); - } + Interlocked.Increment(ref _activeStorageRequests); - private (SnapSyncBatch request, bool finished) CreateNextSlowRangeRequest(StorageRange slotRange, Keccak rootHash, - long blockNumber, SnapSyncBatch request) - { - slotRange.RootHash = rootHash; - slotRange.BlockNumber = blockNumber; - - LogRequest($"NextSlotRange:{slotRange.Accounts.Length}"); - - request.StorageRangeRequest = slotRange; - - return (request, false); - } + // TODO: optimize this + List storagesToQuery = new(STORAGE_BATCH_SIZE); + for (int i = 0; i < STORAGE_BATCH_SIZE && StoragesToRetrieve.TryDequeue(out PathWithAccount storage); i++) + { + storagesToQuery.Add(storage); + } - private (SnapSyncBatch request, bool finished) CreateAccountRangeRequest(Keccak rootHash, - AccountRangePartition partition, long blockNumber, SnapSyncBatch request) - { - Interlocked.Increment(ref _activeAccountRequests); + StorageRange storageRange = new() + { + RootHash = rootHash, + Accounts = storagesToQuery.ToArray(), + StartingHash = ValueKeccak.Zero, + BlockNumber = blockNumber + }; - AccountRange range = new( - rootHash, - partition.NextAccountPath, - partition.AccountPathLimit, - blockNumber); + LogRequest($"StoragesToRetrieve:{storagesToQuery.Count}"); - LogRequest("AccountRange"); + request.StorageRangeRequest = storageRange; - request.AccountRangeRequest = range; + return (request, false); + } + else if (!CodesToRetrieve.IsEmpty) + { + Interlocked.Increment(ref _activeCodeRequests); - return (request, false); - } + // TODO: optimize this + List codesToQuery = new(CODES_BATCH_SIZE); + for (int i = 0; i < CODES_BATCH_SIZE && CodesToRetrieve.TryDequeue(out ValueKeccak codeHash); i++) + { + codesToQuery.Add(codeHash); + } + codesToQuery.Sort(); - private (SnapSyncBatch request, bool finished) DequeAccountToRefresh(SnapSyncBatch request, Keccak rootHash) - { - Interlocked.Increment(ref _activeAccRefreshRequests); + LogRequest($"CodesToRetrieve:{codesToQuery.Count}"); - LogRequest($"AccountsToRefresh: {AccountsToRefresh.Count}"); + request.CodesRequest = codesToQuery.ToArray(); - int queueLength = AccountsToRefresh.Count; - AccountWithStorageStartingHash[] paths = new AccountWithStorageStartingHash[queueLength]; + return (request, false); + } - for (int i = 0; i < queueLength && AccountsToRefresh.TryDequeue(out var acc); i++) + bool rangePhaseFinished = IsSnapGetRangesFinished(); + if (rangePhaseFinished) { - paths[i] = acc; + _logger.Info($"SNAP - State Ranges (Phase 1) finished."); + FinishRangePhase(); } - request.AccountsToRefreshRequest = new AccountsToRefreshRequest() { RootHash = rootHash, Paths = paths }; + LogRequest(NO_REQUEST); - return (request, false); + return (null, IsSnapGetRangesFinished()); } private bool ShouldRequestAccountRequests() { - return _activeAccountRequests < _accountRangePartitionCount - && NextSlotRange.Count < 10 - && StoragesToRetrieve.Count < HIGH_STORAGE_QUEUE_SIZE - && CodesToRetrieve.Count < HIGH_CODES_QUEUE_SIZE; + return _activeAccountRequests < _accountRangePartitionCount && NextSlotRange.Count < 10 && StoragesToRetrieve.Count < 5 * STORAGE_BATCH_SIZE && CodesToRetrieve.Count < 5 * CODES_BATCH_SIZE; } public void EnqueueCodeHashes(ReadOnlySpan codeHashes) @@ -400,7 +354,7 @@ private void GetSyncProgress() if (path == ValueKeccak.MaxValue) { - _logger.Info($"Snap - State Ranges (Phase 1) is finished."); + _logger.Info($"SNAP - State Ranges (Phase 1) is finished."); foreach (KeyValuePair partition in AccountRangePartitions) { partition.Value.MoreAccountsToRight = false; @@ -409,7 +363,7 @@ private void GetSyncProgress() } else { - _logger.Info($"Snap - State Ranges (Phase 1) progress loaded from DB:{path}"); + _logger.Info($"SNAP - State Ranges (Phase 1) progress loaded from DB:{path}"); } } } @@ -432,9 +386,9 @@ private void LogRequest(string reqType) totalPathProgress += nextAccount - startAccount; } - float progress = (float)(totalPathProgress / (double)(256 * 256)); + double progress = 100 * totalPathProgress / (double)(256 * 256); - if (_logger.IsInfo) _logger.Info($"Snap State Ranges (Phase 1): ({progress,8:P2}) [{new string('*', (int)(progress * 71))}{new string(' ', 71 - (int)(progress * 71))}]"); + if (_logger.IsInfo) _logger.Info($"SNAP - progress of State Ranges (Phase 1): {progress:f3}% [{new string('*', (int)progress / 10)}{new string(' ', 10 - (int)progress / 10)}]"); } if (_logger.IsTrace || _reqCount % 1000 == 0) @@ -442,7 +396,7 @@ private void LogRequest(string reqType) int moreAccountCount = AccountRangePartitions.Count(kv => kv.Value.MoreAccountsToRight); _logger.Info( - $"Snap - ({reqType}, diff: {_pivot.Diff}) {moreAccountCount} - Requests Account: {_activeAccountRequests} | Storage: {_activeStorageRequests} | Code: {_activeCodeRequests} | Refresh: {_activeAccRefreshRequests} - Queues Slots: {NextSlotRange.Count} | Storages: {StoragesToRetrieve.Count} | Codes: {CodesToRetrieve.Count} | Refresh: {AccountsToRefresh.Count}"); + $"SNAP - ({reqType}, diff:{_pivot.Diff}) {moreAccountCount} - Requests Account:{_activeAccountRequests} | Storage:{_activeStorageRequests} | Code:{_activeCodeRequests} | Refresh:{_activeAccRefreshRequests} - Queues Slots:{NextSlotRange.Count} | Storages:{StoragesToRetrieve.Count} | Codes:{CodesToRetrieve.Count} | Refresh:{AccountsToRefresh.Count}"); } } diff --git a/src/Nethermind/Nethermind.Synchronization/SnapSync/SnapProvider.cs b/src/Nethermind/Nethermind.Synchronization/SnapSync/SnapProvider.cs index 37f21f09525..1943ae47a3a 100644 --- a/src/Nethermind/Nethermind.Synchronization/SnapSync/SnapProvider.cs +++ b/src/Nethermind/Nethermind.Synchronization/SnapSync/SnapProvider.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using Microsoft.Extensions.ObjectPool; @@ -217,7 +218,7 @@ public void RefreshAccounts(AccountsToRefreshRequest request, byte[][] response) if (nodeData.Length == 0) { RetryAccountRefresh(requestedPath); - _logger.Trace($"SNAP - Empty Account Refresh: {requestedPath.PathAndAccount.Path}"); + _logger.Trace($"SNAP - Empty Account Refresh:{requestedPath.PathAndAccount.Path}"); continue; } @@ -335,7 +336,7 @@ public ITrieStore Create() { return new TrieStore( _stateDb, - Nethermind.Trie.Pruning.No.Pruning, + Trie.Pruning.No.Pruning, Persist.EveryBlock, _logManager); } diff --git a/src/Nethermind/Nethermind.Synchronization/StateSync/PeerInfoExtensions.cs b/src/Nethermind/Nethermind.Synchronization/StateSync/PeerInfoExtensions.cs index e9ab2b1bb25..88f16d24532 100644 --- a/src/Nethermind/Nethermind.Synchronization/StateSync/PeerInfoExtensions.cs +++ b/src/Nethermind/Nethermind.Synchronization/StateSync/PeerInfoExtensions.cs @@ -1,21 +1,20 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using Nethermind.Blockchain.Synchronization; using Nethermind.Network.Contract.P2P; -using Nethermind.Stats.Model; using Nethermind.Synchronization.Peers; namespace Nethermind.Synchronization.StateSync; public static class PeerInfoExtensions { - public static bool CanGetNodeData(this PeerInfo peerInfo) => peerInfo.SyncPeer.CanGetNodeData(); + public static bool CanGetNodeData(this PeerInfo peerInfo) + { + return peerInfo.SyncPeer.ProtocolVersion < EthVersions.Eth67; + } - public static bool CanGetNodeData(this ISyncPeer peer) => peer.ProtocolVersion < EthVersions.Eth67; - - public static bool CanGetSnapData(this PeerInfo peerInfo) => peerInfo.SyncPeer.CanGetSnapData(); - - public static bool CanGetSnapData(this ISyncPeer peer) => - peer.ClientType != NodeClientType.Nethermind && peer.TryGetSatelliteProtocol(Protocol.Snap, out _); + public static bool CanGetSnapData(this PeerInfo peerInfo) + { + return peerInfo.SyncPeer.TryGetSatelliteProtocol(Protocol.Snap, out _); + } } diff --git a/src/Nethermind/Nethermind.Synchronization/StateSync/StateSyncDownloader.cs b/src/Nethermind/Nethermind.Synchronization/StateSync/StateSyncDownloader.cs index 5e391d93a7a..8c5f1970058 100644 --- a/src/Nethermind/Nethermind.Synchronization/StateSync/StateSyncDownloader.cs +++ b/src/Nethermind/Nethermind.Synchronization/StateSync/StateSyncDownloader.cs @@ -111,7 +111,7 @@ private GetTrieNodesRequest GetGroupedRequest(StateSyncBatch batch) for (; accountPathIndex < accountTreePaths.Count; accountPathIndex++) { (byte[] path, StateSyncItem syncItem) accountPath = accountTreePaths[accountPathIndex]; - request.AccountAndStoragePaths[accountPathIndex] = new PathGroup() { Group = new[] { Nibbles.EncodePath(accountPath.path) } }; + request.AccountAndStoragePaths[accountPathIndex] = new PathGroup() { Group = new[] { EncodePath(accountPath.path) } }; // We validate the order of the response later and it has to be the same as RequestedNodes batch.RequestedNodes[requestedNodeIndex] = accountPath.syncItem; @@ -122,12 +122,12 @@ private GetTrieNodesRequest GetGroupedRequest(StateSyncBatch batch) foreach (var kvp in itemsGroupedByAccount) { byte[][] group = new byte[kvp.Value.Count + 1][]; - group[0] = Nibbles.EncodePath(kvp.Key); + group[0] = EncodePath(kvp.Key); for (int groupIndex = 1; groupIndex < group.Length; groupIndex++) { (byte[] path, StateSyncItem syncItem) storagePath = kvp.Value[groupIndex - 1]; - group[groupIndex] = Nibbles.EncodePath(storagePath.path); + group[groupIndex] = EncodePath(storagePath.path); // We validate the order of the response later and it has to be the same as RequestedNodes batch.RequestedNodes[requestedNodeIndex] = storagePath.syncItem; @@ -148,6 +148,8 @@ private GetTrieNodesRequest GetGroupedRequest(StateSyncBatch batch) return request; } + private static byte[] EncodePath(byte[] input) => input.Length == 64 ? Nibbles.ToBytes(input) : Nibbles.ToCompactHexEncoding(input); + /// /// Present an array of StateSyncItem[] as IReadOnlyList to avoid allocating secondary array /// Also Rent and Return cache for single item to try and avoid allocating the HashList in common case diff --git a/src/Nethermind/Nethermind.Synchronization/SyncServer.cs b/src/Nethermind/Nethermind.Synchronization/SyncServer.cs index b2f82e378d2..88683580e34 100644 --- a/src/Nethermind/Nethermind.Synchronization/SyncServer.cs +++ b/src/Nethermind/Nethermind.Synchronization/SyncServer.cs @@ -17,6 +17,7 @@ using Nethermind.Core.Caching; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Db; using Nethermind.Int256; using Nethermind.Logging; using Nethermind.State; diff --git a/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs b/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs index 3dbf33d4ba2..d9bf542fa51 100644 --- a/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs +++ b/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs @@ -7,7 +7,6 @@ using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; using Nethermind.Blockchain.Synchronization; -using Nethermind.Config; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Db; @@ -58,7 +57,6 @@ public class Synchronizer : ISynchronizer private HeadersSyncFeed? _headersFeed; private BodiesSyncFeed? _bodiesFeed; private ReceiptsSyncFeed? _receiptsFeed; - private IProcessExitSource _exitSource; public Synchronizer( IDbProvider dbProvider, @@ -73,7 +71,6 @@ public Synchronizer( IBlockDownloaderFactory blockDownloaderFactory, IPivot pivot, ISyncReport syncReport, - IProcessExitSource processExitSource, ILogManager logManager) { _dbProvider = dbProvider ?? throw new ArgumentNullException(nameof(dbProvider)); @@ -88,11 +85,8 @@ public Synchronizer( _pivot = pivot ?? throw new ArgumentNullException(nameof(pivot)); _syncPeerPool = peerPool ?? throw new ArgumentNullException(nameof(peerPool)); _nodeStatsManager = nodeStatsManager ?? throw new ArgumentNullException(nameof(nodeStatsManager)); - _exitSource = processExitSource ?? throw new ArgumentNullException(nameof(processExitSource)); _logManager = logManager ?? throw new ArgumentNullException(nameof(logManager)); _syncReport = syncReport ?? throw new ArgumentNullException(nameof(syncReport)); - - new MallocTrimmer(syncModeSelector, TimeSpan.FromSeconds(syncConfig.MallocTrimIntervalSec), _logManager); } public virtual void Start() @@ -121,15 +115,10 @@ public virtual void Start() StartStateSyncComponents(); } - if (_syncConfig.TuneDbMode != ITunableDb.TuneType.Default || _syncConfig.BlocksDbTuneDbMode != ITunableDb.TuneType.Default) + if (_syncConfig.TuneDbMode != ITunableDb.TuneType.Default) { SetupDbOptimizer(); } - - if (_syncConfig.ExitOnSynced) - { - _exitSource.WatchForExit(_syncMode, _logManager, TimeSpan.FromSeconds(_syncConfig.ExitOnSyncedWaitTimeSec)); - } } private void SetupDbOptimizer() diff --git a/src/Nethermind/Nethermind.Synchronization/Trie/GetNodeDataTrieNodeRecovery.cs b/src/Nethermind/Nethermind.Synchronization/Trie/GetNodeDataTrieNodeRecovery.cs deleted file mode 100644 index 8f061870c0c..00000000000 --- a/src/Nethermind/Nethermind.Synchronization/Trie/GetNodeDataTrieNodeRecovery.cs +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Nethermind.Blockchain.Synchronization; -using Nethermind.Core.Crypto; -using Nethermind.Logging; -using Nethermind.Synchronization.Peers; -using Nethermind.Synchronization.StateSync; - -namespace Nethermind.Synchronization.Trie; - -public class GetNodeDataTrieNodeRecovery : TrieNodeRecovery> -{ - public GetNodeDataTrieNodeRecovery(ISyncPeerPool syncPeerPool, ILogManager? logManager) : base(syncPeerPool, logManager) - { - } - - protected override string GetMissingNodes(IReadOnlyList request) => string.Join(", ", request); - - protected override bool CanAllocatePeer(ISyncPeer peer) => peer.CanGetNodeData(); - - protected override async Task RecoverRlpFromPeerBase(ValueKeccak rlpHash, ISyncPeer peer, IReadOnlyList request, CancellationTokenSource cts) - { - byte[][] rlp = await peer.GetNodeData(request, cts.Token); - if (rlp.Length == 1) - { - byte[] recoveredRlp = rlp[0]; - if (ValueKeccak.Compute(recoveredRlp) == rlpHash) - { - return recoveredRlp; - } - - if (_logger.IsDebug) _logger.Debug($"Recovered RLP from peer {peer} but the hash does not match"); - } - - return null; - } -} diff --git a/src/Nethermind/Nethermind.Synchronization/Trie/HealingStateTree.cs b/src/Nethermind/Nethermind.Synchronization/Trie/HealingStateTree.cs deleted file mode 100644 index 25280848f2c..00000000000 --- a/src/Nethermind/Nethermind.Synchronization/Trie/HealingStateTree.cs +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Diagnostics; -using Nethermind.Core.Crypto; -using Nethermind.Logging; -using Nethermind.State; -using Nethermind.State.Snap; -using Nethermind.Trie; -using Nethermind.Trie.Pruning; - -namespace Nethermind.Synchronization.Trie; - -public class HealingStateTree : StateTree -{ - private ITrieNodeRecovery? _recovery; - - [DebuggerStepThrough] - public HealingStateTree(ITrieStore? store, ILogManager? logManager) - : base(store, logManager) - { - } - - public void InitializeNetwork(ITrieNodeRecovery recovery) - { - _recovery = recovery; - } - - public override byte[]? Get(ReadOnlySpan rawKey, Keccak? rootHash = null) - { - try - { - return base.Get(rawKey, rootHash); - } - catch (MissingTrieNodeException e) - { - if (Recover(e.TrieNodeException.NodeHash, e.GetPathPart(), rootHash ?? RootHash)) - { - return base.Get(rawKey, rootHash); - } - - throw; - } - } - - public override void Set(ReadOnlySpan rawKey, byte[] value) - { - try - { - base.Set(rawKey, value); - } - catch (MissingTrieNodeException e) - { - if (Recover(e.TrieNodeException.NodeHash, e.GetPathPart(), RootHash)) - { - base.Set(rawKey, value); - } - else - { - throw; - } - } - } - - private bool Recover(in ValueKeccak rlpHash, ReadOnlySpan pathPart, Keccak rootHash) - { - if (_recovery?.CanRecover == true) - { - GetTrieNodesRequest request = new() - { - RootHash = rootHash, - AccountAndStoragePaths = new[] - { - new PathGroup - { - Group = new[] { Nibbles.EncodePath(pathPart) } - } - } - }; - - byte[]? rlp = _recovery.Recover(rlpHash, request).GetAwaiter().GetResult(); - if (rlp is not null) - { - TrieStore.AsKeyValueStore().Set(rlpHash.Bytes, rlp); - return true; - } - } - - return false; - } -} diff --git a/src/Nethermind/Nethermind.Synchronization/Trie/HealingStorageTree.cs b/src/Nethermind/Nethermind.Synchronization/Trie/HealingStorageTree.cs deleted file mode 100644 index 1ff68dcdc6b..00000000000 --- a/src/Nethermind/Nethermind.Synchronization/Trie/HealingStorageTree.cs +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Logging; -using Nethermind.State; -using Nethermind.State.Snap; -using Nethermind.Trie; -using Nethermind.Trie.Pruning; - -namespace Nethermind.Synchronization.Trie; - -public class HealingStorageTree : StorageTree -{ - private readonly Address _address; - private readonly Keccak _stateRoot; - private readonly ITrieNodeRecovery? _recovery; - - public HealingStorageTree(ITrieStore? trieStore, Keccak rootHash, ILogManager? logManager, Address address, Keccak stateRoot, ITrieNodeRecovery? recovery) - : base(trieStore, rootHash, logManager) - { - _address = address; - _stateRoot = stateRoot; - _recovery = recovery; - } - - public override byte[]? Get(ReadOnlySpan rawKey, Keccak? rootHash = null) - { - try - { - return base.Get(rawKey, rootHash); - } - catch (MissingTrieNodeException e) - { - if (Recover(e.TrieNodeException.NodeHash, e.GetPathPart())) - { - return base.Get(rawKey, rootHash); - } - - throw; - } - } - - public override void Set(ReadOnlySpan rawKey, byte[] value) - { - try - { - base.Set(rawKey, value); - } - catch (MissingTrieNodeException e) - { - if (Recover(e.TrieNodeException.NodeHash, e.GetPathPart())) - { - base.Set(rawKey, value); - } - else - { - throw; - } - } - } - - private bool Recover(in ValueKeccak rlpHash, ReadOnlySpan pathPart) - { - if (_recovery?.CanRecover == true) - { - GetTrieNodesRequest request = new() - { - RootHash = _stateRoot, - AccountAndStoragePaths = new[] - { - new PathGroup - { - Group = new[] { ValueKeccak.Compute(_address.Bytes).ToByteArray(), Nibbles.EncodePath(pathPart) } - } - } - }; - - byte[]? rlp = _recovery.Recover(rlpHash, request).GetAwaiter().GetResult(); - if (rlp is not null) - { - TrieStore.AsKeyValueStore().Set(rlpHash.Bytes, rlp); - return true; - } - } - - return false; - } -} diff --git a/src/Nethermind/Nethermind.Synchronization/Trie/HealingStorageTreeFactory.cs b/src/Nethermind/Nethermind.Synchronization/Trie/HealingStorageTreeFactory.cs deleted file mode 100644 index 615c5332b94..00000000000 --- a/src/Nethermind/Nethermind.Synchronization/Trie/HealingStorageTreeFactory.cs +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Logging; -using Nethermind.State; -using Nethermind.State.Snap; -using Nethermind.Trie.Pruning; - -namespace Nethermind.Synchronization.Trie; - -public class HealingStorageTreeFactory : IStorageTreeFactory -{ - private ITrieNodeRecovery? _recovery; - - public void InitializeNetwork(ITrieNodeRecovery recovery) - { - _recovery = recovery; - } - - public StorageTree Create(Address address, ITrieStore trieStore, Keccak storageRoot, Keccak stateRoot, ILogManager? logManager) => - new HealingStorageTree(trieStore, storageRoot, logManager, address, stateRoot, _recovery); -} diff --git a/src/Nethermind/Nethermind.Synchronization/Trie/HealingTrieStore.cs b/src/Nethermind/Nethermind.Synchronization/Trie/HealingTrieStore.cs deleted file mode 100644 index 116cdff2051..00000000000 --- a/src/Nethermind/Nethermind.Synchronization/Trie/HealingTrieStore.cs +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using Nethermind.Core; -using Nethermind.Core.Collections; -using Nethermind.Core.Crypto; -using Nethermind.Logging; -using Nethermind.Trie; -using Nethermind.Trie.Pruning; - -namespace Nethermind.Synchronization.Trie; - -/// -/// Trie store that can recover from network using eth63-eth66 protocol and GetNodeData. -/// -public class HealingTrieStore : TrieStore -{ - private ITrieNodeRecovery>? _recovery; - - public HealingTrieStore( - IKeyValueStoreWithBatching? keyValueStore, - IPruningStrategy? pruningStrategy, - IPersistenceStrategy? persistenceStrategy, - ILogManager? logManager) - : base(keyValueStore, pruningStrategy, persistenceStrategy, logManager) - { - } - - public void InitializeNetwork(ITrieNodeRecovery> recovery) - { - _recovery = recovery; - } - - public override byte[] LoadRlp(Keccak keccak, ReadFlags readFlags = ReadFlags.None) - { - try - { - return base.LoadRlp(keccak, readFlags); - } - catch (TrieNodeException) - { - if (TryRecover(keccak, out byte[] rlp)) - { - return rlp; - } - - throw; - } - } - - private bool TryRecover(Keccak rlpHash, [NotNullWhen(true)] out byte[]? rlp) - { - if (_recovery?.CanRecover == true) - { - using ArrayPoolList request = new(1) { rlpHash }; - rlp = _recovery.Recover(rlpHash, request).GetAwaiter().GetResult(); - if (rlp is not null) - { - _keyValueStore.Set(rlpHash.Bytes, rlp); - return true; - } - } - - rlp = null; - return false; - } -} diff --git a/src/Nethermind/Nethermind.Synchronization/Trie/HealingWorldState.cs b/src/Nethermind/Nethermind.Synchronization/Trie/HealingWorldState.cs deleted file mode 100644 index 6ee9035a88f..00000000000 --- a/src/Nethermind/Nethermind.Synchronization/Trie/HealingWorldState.cs +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core; -using Nethermind.Logging; -using Nethermind.State; -using Nethermind.State.Snap; -using Nethermind.Trie.Pruning; - -namespace Nethermind.Synchronization.Trie; - -public class HealingWorldState : WorldState -{ - public HealingWorldState(ITrieStore? trieStore, IKeyValueStore? codeDb, ILogManager? logManager) - : base(trieStore, codeDb, logManager, new HealingStateTree(trieStore, logManager), new HealingStorageTreeFactory()) - { - } - - public void InitializeNetwork(ITrieNodeRecovery recovery) - { - StateProviderTree.InitializeNetwork(recovery); - StorageTreeFactory.InitializeNetwork(recovery); - } - - private HealingStorageTreeFactory StorageTreeFactory => ((HealingStorageTreeFactory)_persistentStorageProvider._storageTreeFactory); - - private HealingStateTree StateProviderTree => ((HealingStateTree)_stateProvider._tree); -} diff --git a/src/Nethermind/Nethermind.Synchronization/Trie/SnapTrieNodeRecovery.cs b/src/Nethermind/Nethermind.Synchronization/Trie/SnapTrieNodeRecovery.cs deleted file mode 100644 index ad02f249666..00000000000 --- a/src/Nethermind/Nethermind.Synchronization/Trie/SnapTrieNodeRecovery.cs +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Nethermind.Blockchain.Synchronization; -using Nethermind.Core.Crypto; -using Nethermind.Core.Extensions; -using Nethermind.Logging; -using Nethermind.Network.Contract.P2P; -using Nethermind.State.Snap; -using Nethermind.Synchronization.Peers; -using Nethermind.Synchronization.StateSync; - -namespace Nethermind.Synchronization.Trie; - -public class SnapTrieNodeRecovery : TrieNodeRecovery -{ - public SnapTrieNodeRecovery(ISyncPeerPool syncPeerPool, ILogManager? logManager) : base(syncPeerPool, logManager) - { - } - - protected override string GetMissingNodes(GetTrieNodesRequest request) => - string.Join("; ", request.AccountAndStoragePaths.Select(GetMissingNodes)); - - private string GetMissingNodes(PathGroup requestAccountAndStoragePaths) => - requestAccountAndStoragePaths.Group.Length switch - { - 1 => $"Account: {requestAccountAndStoragePaths.Group[0].ToHexString()}", - > 1 => $"Account: {requestAccountAndStoragePaths.Group[0].ToHexString()}, Storage: {string.Join(", ", requestAccountAndStoragePaths.Group.Skip(1).Select(g => g.ToHexString()))}", - _ => "", - }; - - protected override bool CanAllocatePeer(ISyncPeer peer) => peer.CanGetSnapData(); - - protected override async Task RecoverRlpFromPeerBase(ValueKeccak rlpHash, ISyncPeer peer, GetTrieNodesRequest request, CancellationTokenSource cts) - { - if (peer.TryGetSatelliteProtocol(Protocol.Snap, out ISnapSyncPeer? snapPeer)) - { - byte[][] rlp = await snapPeer.GetTrieNodes(request, cts.Token); - if (rlp.Length == 1 && rlp[0]?.Length > 0 && ValueKeccak.Compute(rlp[0]) == rlpHash) - { - return rlp[0]; - } - } - - return null; - } -} diff --git a/src/Nethermind/Nethermind.Synchronization/Trie/TrieNodeRecovery.cs b/src/Nethermind/Nethermind.Synchronization/Trie/TrieNodeRecovery.cs deleted file mode 100644 index 325c5b99c6a..00000000000 --- a/src/Nethermind/Nethermind.Synchronization/Trie/TrieNodeRecovery.cs +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Nethermind.Blockchain.Synchronization; -using Nethermind.Consensus.Processing; -using Nethermind.Core.Collections; -using Nethermind.Core.Crypto; -using Nethermind.Logging; -using Nethermind.Synchronization.Peers; - -namespace Nethermind.Synchronization.Trie; - -public interface ITrieNodeRecovery -{ - bool CanRecover => BlockchainProcessor.IsMainProcessingThread; - Task Recover(ValueKeccak rlpHash, TRequest request); -} - -public abstract class TrieNodeRecovery : ITrieNodeRecovery -{ - private readonly ISyncPeerPool _syncPeerPool; - protected readonly ILogger _logger; - private const int MaxPeersForRecovery = 30; - - protected TrieNodeRecovery(ISyncPeerPool syncPeerPool, ILogManager? logManager) - { - _syncPeerPool = syncPeerPool; - _logger = logManager?.GetClassLogger>() ?? NullLogger.Instance; - } - - public async Task Recover(ValueKeccak rlpHash, TRequest request) - { - if (_logger.IsWarn) _logger.Warn($"Missing trie node {GetMissingNodes(request)}, trying to recover from network"); - using CancellationTokenSource cts = new(Timeouts.Eth); - using ArrayPoolList keyRecoveries = GenerateKeyRecoveries(rlpHash, request, cts); - return await CheckKeyRecoveriesResults(keyRecoveries, cts); - } - - protected abstract string GetMissingNodes(TRequest request); - - protected async Task CheckKeyRecoveriesResults(ArrayPoolList keyRecoveries, CancellationTokenSource cts) - { - while (keyRecoveries.Count > 0) - { - Task<(Recovery, byte[]?)> task = await Task.WhenAny(keyRecoveries.Select(kr => kr.Task!)); - (Recovery Recovery, byte[]? Data) result = await task; - if (result.Data is null) - { - if (_logger.IsDebug) _logger.Debug($"Got empty response from peer {result.Recovery.Peer}"); - keyRecoveries.Remove(result.Recovery); - } - else - { - if (_logger.IsWarn) _logger.Warn($"Successfully recovered from peer {result.Recovery.Peer} with {result.Data.Length} bytes!"); - cts.Cancel(); - return result.Data; - } - } - - if (_logger.IsWarn) _logger.Warn("Failed to recover missing trie node"); - - return null; - } - - protected ArrayPoolList GenerateKeyRecoveries(in ValueKeccak rlpHash, TRequest request, CancellationTokenSource cts) - { - ArrayPoolList keyRecoveries = AllocatePeers(); - if (_logger.IsDebug) _logger.Debug($"Allocated {keyRecoveries.Count} peers (out of {_syncPeerPool!.InitializedPeers.Count()} initialized peers)"); - foreach (Recovery keyRecovery in keyRecoveries) - { - keyRecovery.Task = RecoverRlpFromPeer(rlpHash, keyRecovery, request, cts); - } - - return keyRecoveries; - } - - private ArrayPoolList AllocatePeers() => - new(MaxPeersForRecovery, - _syncPeerPool!.InitializedPeers - .Select(p => p.SyncPeer) - .Where(CanAllocatePeer) - .OrderByDescending(p => p.HeadNumber) - .Take(MaxPeersForRecovery) - .Select(peer => new Recovery { Peer = peer }) - ); - - protected abstract bool CanAllocatePeer(ISyncPeer peer); - - private async Task<(Recovery, byte[]?)> RecoverRlpFromPeer(ValueKeccak rlpHash, Recovery recovery, TRequest request, CancellationTokenSource cts) - { - ISyncPeer peer = recovery.Peer; - - try - { - return (recovery, await RecoverRlpFromPeerBase(rlpHash, peer, request, cts)); - } - catch (OperationCanceledException) - { - if (_logger.IsTrace) _logger.Trace($"Cancelled recovering RLP from peer {peer}"); - } - catch (Exception e) - { - if (_logger.IsError) _logger.Error($"Could not recover from {peer}", e); - } - - return (recovery, null); - } - - protected abstract Task RecoverRlpFromPeerBase(ValueKeccak rlpHash, ISyncPeer peer, TRequest request, CancellationTokenSource cts); - - protected class Recovery - { - public ISyncPeer Peer { get; init; } = null!; - public Task<(Recovery, byte[]?)>? Task { get; set; } - } -} diff --git a/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs b/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs index a8cd9a3536d..7f9f63a6e56 100644 --- a/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/PruningScenariosTests.cs @@ -4,9 +4,14 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using FluentAssertions; +using FluentAssertions.Numeric; +using MathNet.Numerics.LinearAlgebra; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Extensions; +using Nethermind.Core.Test.Builders; using Nethermind.Db; using Nethermind.Int256; using Nethermind.Logging; diff --git a/src/Nethermind/Nethermind.Trie.Test/TrackingCappedArrayPoolTests.cs b/src/Nethermind/Nethermind.Trie.Test/TrackingCappedArrayPoolTests.cs deleted file mode 100644 index 3465d66f98f..00000000000 --- a/src/Nethermind/Nethermind.Trie.Test/TrackingCappedArrayPoolTests.cs +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Buffers; -using Nethermind.Core.Buffers; -using NSubstitute; -using NUnit.Framework; - -namespace Nethermind.Trie.Test; - -public class TrackingCappedArrayPoolTests -{ - [Test] - public void Test_Pooling() - { - ArrayPool? arrayPool = Substitute.For>(); - arrayPool - .Rent(Arg.Any()) - .Returns(info => new byte[(int)info[0]]); - TrackingCappedArrayPool? pool = new(0, arrayPool); - - pool.Rent(1); - pool.Rent(1); - pool.Rent(1); - CappedArray sample = pool.Rent(1); - - arrayPool.Received(4).Rent(1); - - pool.Return(sample); - arrayPool.Received(0).Return(Arg.Any()); - - pool.ReturnAll(); - arrayPool.Received(4).Return(Arg.Any()); - } -} diff --git a/src/Nethermind/Nethermind.Trie.Test/TrieNodeTests.cs b/src/Nethermind/Nethermind.Trie.Test/TrieNodeTests.cs index dea83ed4a89..ae03126a259 100644 --- a/src/Nethermind/Nethermind.Trie.Test/TrieNodeTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/TrieNodeTests.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using FluentAssertions; using Nethermind.Core; -using Nethermind.Core.Buffers; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; @@ -79,7 +79,7 @@ public void Forward_read_flags_on_resolve() public void Throws_trie_exception_on_unexpected_format() { TrieNode trieNode = new(NodeType.Unknown, new byte[42]); - Assert.Throws(() => trieNode.ResolveNode(NullTrieNodeResolver.Instance)); + Assert.Throws(() => trieNode.ResolveNode(NullTrieNodeResolver.Instance)); } [Test] @@ -153,7 +153,7 @@ public void Can_check_if_child_is_null_on_a_branch() trieNode.SetChild(j, ctx.TiniestLeaf); } - CappedArray rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); + byte[] rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); TrieNode restoredNode = new(NodeType.Branch, rlp); for (int childIndex = 0; childIndex < 16; childIndex++) @@ -179,14 +179,14 @@ public void Can_encode_decode_tiny_branch() TrieNode trieNode = new(NodeType.Branch); trieNode.SetChild(11, ctx.TiniestLeaf); - CappedArray rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); + byte[] rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); TrieNode decoded = new(NodeType.Unknown, rlp); decoded.ResolveNode(NullTrieNodeResolver.Instance); TrieNode decodedTiniest = decoded.GetChild(NullTrieNodeResolver.Instance, 11); decodedTiniest.ResolveNode(NullTrieNodeResolver.Instance); - Assert.That(decodedTiniest.Value.ToArray(), Is.EqualTo(ctx.TiniestLeaf.Value.ToArray()), "value"); + Assert.That(decodedTiniest.Value, Is.EqualTo(ctx.TiniestLeaf.Value), "value"); Assert.That(HexPrefix.ToBytes(decodedTiniest.Key!, true), Is.EqualTo(HexPrefix.ToBytes(ctx.TiniestLeaf.Key!, true)), "key"); } @@ -197,7 +197,7 @@ public void Can_encode_decode_heavy_branch() TrieNode trieNode = new(NodeType.Branch); trieNode.SetChild(11, ctx.HeavyLeaf); - CappedArray rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); + byte[] rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); TrieNode decoded = new(NodeType.Unknown, rlp); decoded.ResolveNode(NullTrieNodeResolver.Instance); @@ -214,14 +214,14 @@ public void Can_encode_decode_tiny_extension() trieNode.Key = new byte[] { 5 }; trieNode.SetChild(0, ctx.TiniestLeaf); - CappedArray rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); + byte[] rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); TrieNode decoded = new(NodeType.Unknown, rlp); decoded.ResolveNode(NullTrieNodeResolver.Instance); TrieNode? decodedTiniest = decoded.GetChild(NullTrieNodeResolver.Instance, 0); decodedTiniest?.ResolveNode(NullTrieNodeResolver.Instance); - Assert.That(decodedTiniest.Value.ToArray(), Is.EqualTo(ctx.TiniestLeaf.Value.ToArray()), "value"); + Assert.That(decodedTiniest.Value, Is.EqualTo(ctx.TiniestLeaf.Value), "value"); Assert.That(HexPrefix.ToBytes(decodedTiniest.Key!, true), Is.EqualTo(HexPrefix.ToBytes(ctx.TiniestLeaf.Key!, true)), "key"); } @@ -234,7 +234,7 @@ public void Can_encode_decode_heavy_extension() trieNode.Key = new byte[] { 5 }; trieNode.SetChild(0, ctx.HeavyLeaf); - CappedArray rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); + byte[] rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); TrieNode decoded = new(NodeType.Unknown, rlp); decoded.ResolveNode(NullTrieNodeResolver.Instance); @@ -262,7 +262,7 @@ public void Get_child_hash_works_on_hashed_child_of_a_branch() Context ctx = new(); TrieNode trieNode = new(NodeType.Branch); trieNode[11] = ctx.HeavyLeaf; - CappedArray rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); + byte[] rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); TrieNode decoded = new(NodeType.Branch, rlp); Keccak getResult = decoded.GetChildHash(11); @@ -276,7 +276,7 @@ public void Get_child_hash_works_on_inlined_child_of_a_branch() TrieNode trieNode = new(NodeType.Branch); trieNode[11] = ctx.TiniestLeaf; - CappedArray rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); + byte[] rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); TrieNode decoded = new(NodeType.Branch, rlp); Keccak getResult = decoded.GetChildHash(11); @@ -290,7 +290,7 @@ public void Get_child_hash_works_on_hashed_child_of_an_extension() TrieNode trieNode = new(NodeType.Extension); trieNode[0] = ctx.HeavyLeaf; trieNode.Key = new byte[] { 5 }; - CappedArray rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); + byte[] rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); TrieNode decoded = new(NodeType.Extension, rlp); Keccak getResult = decoded.GetChildHash(0); @@ -304,7 +304,7 @@ public void Get_child_hash_works_on_inlined_child_of_an_extension() TrieNode trieNode = new(NodeType.Extension); trieNode[0] = ctx.TiniestLeaf; trieNode.Key = new byte[] { 5 }; - CappedArray rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); + byte[] rlp = trieNode.RlpEncode(NullTrieNodeResolver.Instance); TrieNode decoded = new(NodeType.Extension, rlp); Keccak getResult = decoded.GetChildHash(0); @@ -347,7 +347,7 @@ public void Leaf_with_simple_account_can_accept_visitors() node.Accept(visitor, NullTrieNodeResolver.Instance, context); - visitor.Received().VisitLeaf(node, context, node.Value.ToArray()); + visitor.Received().VisitLeaf(node, context, node.Value); } [Test] @@ -361,7 +361,7 @@ public void Leaf_with_contract_without_storage_and_empty_code_can_accept_visitor node.Accept(visitor, NullTrieNodeResolver.Instance, context); - visitor.Received().VisitLeaf(node, context, node.Value.ToArray()); + visitor.Received().VisitLeaf(node, context, node.Value); } [Test] @@ -377,7 +377,7 @@ public void Leaf_with_contract_without_storage_and_with_code_can_accept_visitors node.Accept(visitor, NullTrieNodeResolver.Instance, context); - visitor.Received().VisitLeaf(node, context, node.Value.ToArray()); + visitor.Received().VisitLeaf(node, context, node.Value); } [Test] @@ -393,7 +393,7 @@ public void Leaf_with_contract_with_storage_and_without_code_can_accept_visitors node.Accept(visitor, NullTrieNodeResolver.Instance, context); - visitor.Received().VisitLeaf(node, context, node.Value.ToArray()); + visitor.Received().VisitLeaf(node, context, node.Value); } [Test] @@ -409,7 +409,7 @@ public void Extension_with_leaf_can_be_visited() node.Accept(visitor, NullTrieNodeResolver.Instance, context); visitor.Received().VisitExtension(node, context); - visitor.Received().VisitLeaf(ctx.AccountLeaf, context, ctx.AccountLeaf.Value.ToArray()); + visitor.Received().VisitLeaf(ctx.AccountLeaf, context, ctx.AccountLeaf.Value); } [Test] @@ -429,7 +429,7 @@ public void Branch_with_children_can_be_visited() node.Accept(visitor, NullTrieNodeResolver.Instance, context); visitor.Received().VisitBranch(node, context); - visitor.Received(16).VisitLeaf(ctx.AccountLeaf, context, ctx.AccountLeaf.Value.ToArray()); + visitor.Received(16).VisitLeaf(ctx.AccountLeaf, context, ctx.AccountLeaf.Value); } [Test] @@ -516,7 +516,7 @@ public void Can_encode_branch_with_unresolved_children() node.SetChild(i, randomTrieNode); } - CappedArray rlp = node.RlpEncode(NullTrieNodeResolver.Instance); + byte[] rlp = node.RlpEncode(NullTrieNodeResolver.Instance); TrieNode restoredNode = new(NodeType.Branch, rlp); @@ -908,13 +908,12 @@ public void Rlp_is_cloned_when_cloning() leaf2.ResolveKey(trieStore, false); leaf2.Seal(); trieStore.CommitNode(0, new NodeCommitInfo(leaf2)); - trieStore.FinishBlockCommit(TrieType.State, 0, leaf2); TrieNode trieNode = new(NodeType.Branch); trieNode.SetChild(1, leaf1); trieNode.SetChild(2, leaf2); trieNode.ResolveKey(trieStore, true); - CappedArray rlp = trieNode.FullRlp; + byte[] rlp = trieNode.FullRlp; TrieNode restoredBranch = new(NodeType.Branch, rlp); @@ -922,7 +921,7 @@ public void Rlp_is_cloned_when_cloning() var restoredLeaf1 = clone.GetChild(trieStore, 1); restoredLeaf1.Should().NotBeNull(); restoredLeaf1.ResolveNode(trieStore); - restoredLeaf1.Value.ToArray().Should().BeEquivalentTo(leaf1.Value.ToArray()); + restoredLeaf1.Value.Should().BeEquivalentTo(leaf1.Value); } [Test] @@ -937,7 +936,7 @@ public void Can_parallel_read_unresolved_children() node.SetChild(i, randomTrieNode); } - CappedArray rlp = node.RlpEncode(NullTrieNodeResolver.Instance); + byte[] rlp = node.RlpEncode(NullTrieNodeResolver.Instance); TrieNode restoredNode = new(NodeType.Branch, rlp); diff --git a/src/Nethermind/Nethermind.Trie.Test/TrieTests.cs b/src/Nethermind/Nethermind.Trie.Test/TrieTests.cs index 21b5d12f9e0..03c3639bfb6 100644 --- a/src/Nethermind/Nethermind.Trie.Test/TrieTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/TrieTests.cs @@ -9,10 +9,12 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Db; using Nethermind.Int256; using Nethermind.Logging; +using Nethermind.Serialization.Rlp; using Nethermind.Specs.Forks; using Nethermind.State; using Nethermind.Trie.Pruning; diff --git a/src/Nethermind/Nethermind.Trie/BatchedTrieVisitor.cs b/src/Nethermind/Nethermind.Trie/BatchedTrieVisitor.cs index 1cc3b330d38..14036b61ff7 100644 --- a/src/Nethermind/Nethermind.Trie/BatchedTrieVisitor.cs +++ b/src/Nethermind/Nethermind.Trie/BatchedTrieVisitor.cs @@ -83,7 +83,12 @@ public BatchedTrieVisitor( // Get estimated num of file (expected db size / 64MiB), multiplied by a reasonable num of thread we want to // confine to a file. If its too high, the overhead of looping through the stack can get a bit high at the end // of the visit. But then again its probably not much. - long maxPartitionCount = (expectedDbSize / 64.MiB()) * Math.Min(4, visitingOptions.MaxDegreeOfParallelism); + int degreeOfParallelism = visitingOptions.MaxDegreeOfParallelism; + if (degreeOfParallelism == 0) + { + degreeOfParallelism = Math.Max(Environment.ProcessorCount, 1); + } + long maxPartitionCount = (expectedDbSize / 64.MiB()) * Math.Min(4, degreeOfParallelism); if (_partitionCount > maxPartitionCount) { @@ -135,7 +140,13 @@ public void Start( try { - Task[]? tasks = Enumerable.Range(0, trieVisitContext.MaxDegreeOfParallelism) + int degreeOfParallelism = trieVisitContext.MaxDegreeOfParallelism; + if (degreeOfParallelism == 0) + { + degreeOfParallelism = Math.Max(Environment.ProcessorCount, 1); + } + + Task[]? tasks = Enumerable.Range(0, degreeOfParallelism) .Select((_) => Task.Run(BatchedThread)) .ToArray(); @@ -249,7 +260,7 @@ void QueueNextNodes(ArrayPoolList<(TrieNode, SmallTrieVisitContext)> batchResult for (int i = batchResult.Count - 1; i >= 0; i--) { (TrieNode trieNode, SmallTrieVisitContext ctx) = batchResult[i]; - if (trieNode.NodeType == NodeType.Unknown && trieNode.FullRlp.IsNotNull) + if (trieNode.NodeType == NodeType.Unknown && trieNode.FullRlp != null) { // Inline node. Seems rare, so its fine to create new list for this. Does not have a keccak // to queue, so we'll just process it inline. @@ -295,7 +306,7 @@ private void BatchedThread() SmallTrieVisitContext ctx = currentBatch[i].Item2; - if (cur.FullRlp.IsNotNull) continue; + if (cur.FullRlp != null) continue; if (cur.Keccak is null) throw new TrieException($"Unable to resolve node without Keccak. ctx: {ctx.Level}, {ctx.ExpectAccounts}, {ctx.IsStorage}, {ctx.BranchChildIndex}"); resolveOrdering.Add(i); @@ -337,7 +348,7 @@ private void BatchedThread() (TrieNode nodeToResolve, SmallTrieVisitContext ctx) = currentBatch[i]; nextToProcesses.Clear(); - if (nodeToResolve.FullRlp.IsNull) + if (nodeToResolve.FullRlp == null) { // Still need to decrement counter QueueNextNodes(nextToProcesses); diff --git a/src/Nethermind/Nethermind.Trie/MissingTrieNodeException.cs b/src/Nethermind/Nethermind.Trie/MissingTrieNodeException.cs deleted file mode 100644 index f9431ed5a8c..00000000000 --- a/src/Nethermind/Nethermind.Trie/MissingTrieNodeException.cs +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; - -namespace Nethermind.Trie; - -public class MissingTrieNodeException : TrieException -{ - public MissingTrieNodeException(string message, TrieNodeException inner, byte[] updatePath, int currentIndex) : base(message, inner) - { - UpdatePath = updatePath; - CurrentIndex = currentIndex; - TrieNodeException = inner; - } - - public TrieNodeException TrieNodeException { get; } - public byte[] UpdatePath { get; } - public int CurrentIndex { get; } - public ReadOnlySpan GetPathPart() => UpdatePath.AsSpan(0, CurrentIndex + 1); -} diff --git a/src/Nethermind/Nethermind.Trie/NibbleExtensions.cs b/src/Nethermind/Nethermind.Trie/NibbleExtensions.cs index a760a021440..c849d018e19 100644 --- a/src/Nethermind/Nethermind.Trie/NibbleExtensions.cs +++ b/src/Nethermind/Nethermind.Trie/NibbleExtensions.cs @@ -89,7 +89,7 @@ public static byte ToByte(Nibble highNibble, Nibble lowNibble) return (byte)(((byte)highNibble << 4) | (byte)lowNibble); } - public static byte[] ToBytes(ReadOnlySpan nibbles) + public static byte[] ToBytes(byte[] nibbles) { byte[] bytes = new byte[nibbles.Length / 2]; for (int i = 0; i < bytes.Length; i++) @@ -100,7 +100,7 @@ public static byte[] ToBytes(ReadOnlySpan nibbles) return bytes; } - public static byte[] ToCompactHexEncoding(ReadOnlySpan nibbles) + public static byte[] ToCompactHexEncoding(byte[] nibbles) { int oddity = nibbles.Length % 2; byte[] bytes = new byte[nibbles.Length / 2 + 1]; @@ -116,7 +116,5 @@ public static byte[] ToCompactHexEncoding(ReadOnlySpan nibbles) return bytes; } - - public static byte[] EncodePath(ReadOnlySpan input) => input.Length == 64 ? ToBytes(input) : ToCompactHexEncoding(input); } } diff --git a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs index ed4ed344fde..5774e10e6e8 100644 --- a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs +++ b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs @@ -12,7 +12,6 @@ using System.Runtime.CompilerServices; using System.Threading.Tasks; using Nethermind.Core; -using Nethermind.Core.Buffers; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Logging; @@ -34,7 +33,7 @@ public class PatriciaTree /// public static readonly Keccak EmptyTreeHash = Keccak.EmptyTreeHash; - public TrieType TrieType { get; init; } + public TrieType TrieType { get; protected set; } /// /// To save allocations this used to be static but this caused one of the hardest to reproduce issues @@ -46,8 +45,7 @@ public class PatriciaTree private readonly ConcurrentQueue? _currentCommit; - public ITrieStore TrieStore { get; } - public ICappedArrayPool? _bufferPool; + public readonly ITrieStore TrieStore; private readonly bool _parallelBranches; @@ -55,7 +53,7 @@ public class PatriciaTree private Keccak _rootHash = Keccak.EmptyTreeHash; - public TrieNode? RootRef { get; set; } + public TrieNode? RootRef; /// /// Only used in EthereumTests @@ -85,8 +83,8 @@ public PatriciaTree(IKeyValueStoreWithBatching keyValueStore) { } - public PatriciaTree(ITrieStore trieStore, ILogManager logManager, ICappedArrayPool? bufferPool = null) - : this(trieStore, EmptyTreeHash, false, true, logManager, bufferPool: bufferPool) + public PatriciaTree(ITrieStore trieStore, ILogManager logManager) + : this(trieStore, EmptyTreeHash, false, true, logManager) { } @@ -95,15 +93,13 @@ public PatriciaTree( Keccak rootHash, bool parallelBranches, bool allowCommits, - ILogManager logManager, - ICappedArrayPool? bufferPool = null) + ILogManager logManager) : this( new TrieStore(keyValueStore, logManager), rootHash, parallelBranches, allowCommits, - logManager, - bufferPool: bufferPool) + logManager) { } @@ -112,8 +108,7 @@ public PatriciaTree( Keccak rootHash, bool parallelBranches, bool allowCommits, - ILogManager? logManager, - ICappedArrayPool? bufferPool = null) + ILogManager? logManager) { _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); TrieStore = trieStore ?? throw new ArgumentNullException(nameof(trieStore)); @@ -129,8 +124,6 @@ public PatriciaTree( _currentCommit = new ConcurrentQueue(); _commitExceptions = new ConcurrentQueue(); } - - _bufferPool = bufferPool; } public void Commit(long blockNumber, bool skipRoot = false, WriteFlags writeFlags = WriteFlags.None) @@ -156,7 +149,7 @@ public void Commit(long blockNumber, bool skipRoot = false, WriteFlags writeFlag } // reset objects - RootRef!.ResolveKey(TrieStore, true, bufferPool: _bufferPool); + RootRef!.ResolveKey(TrieStore, true); SetRootHash(RootRef.Keccak!, true); } @@ -272,10 +265,10 @@ private void Commit(NodeCommitInfo nodeCommitInfo, bool skipSelf = false) } } - node.ResolveKey(TrieStore, nodeCommitInfo.IsRoot, bufferPool: _bufferPool); + node.ResolveKey(TrieStore, nodeCommitInfo.IsRoot); node.Seal(); - if (node.FullRlp.Length >= 32) + if (node.FullRlp?.Length >= 32) { if (!skipSelf) { @@ -290,7 +283,7 @@ private void Commit(NodeCommitInfo nodeCommitInfo, bool skipSelf = false) public void UpdateRootHash() { - RootRef?.ResolveKey(TrieStore, true, bufferPool: _bufferPool); + RootRef?.ResolveKey(TrieStore, true); SetRootHash(RootRef?.Keccak ?? EmptyTreeHash, false); } @@ -309,83 +302,43 @@ private void SetRootHash(Keccak? value, bool resetObjects) [SkipLocalsInit] [DebuggerStepThrough] - public virtual byte[]? Get(ReadOnlySpan rawKey, Keccak? rootHash = null) + public byte[]? Get(Span rawKey, Keccak? rootHash = null) { try { int nibblesCount = 2 * rawKey.Length; byte[] array = null; Span nibbles = (rawKey.Length <= MaxKeyStackAlloc - ? stackalloc byte[MaxKeyStackAlloc] - : array = ArrayPool.Shared.Rent(nibblesCount)) - [..nibblesCount]; // Slice to exact size; - - try - { - Nibbles.BytesToNibbleBytes(rawKey, nibbles); - return Run(nibbles, nibblesCount, new CappedArray(Array.Empty()), false, startRootHash: rootHash).ToArray(); - } - finally - { - if (array is not null) ArrayPool.Shared.Return(array); - } + ? stackalloc byte[MaxKeyStackAlloc] + : array = ArrayPool.Shared.Rent(nibblesCount)) + [..nibblesCount]; // Slice to exact size; + Nibbles.BytesToNibbleBytes(rawKey, nibbles); + var result = Run(nibbles, nibblesCount, Array.Empty(), false, startRootHash: rootHash); + if (array is not null) ArrayPool.Shared.Return(array); + return result; } catch (TrieException e) { - EnhanceException(rawKey, rootHash ?? RootHash, e); - throw; - } - } - - private static void EnhanceException(ReadOnlySpan rawKey, ValueKeccak rootHash, TrieException baseException) - { - TrieNodeException? GetTrieNodeException(TrieException? exception) => - exception switch - { - null => null, - TrieNodeException ex => ex, - _ => GetTrieNodeException(exception.InnerException as TrieException) - }; - - TrieNodeException? trieNodeException = GetTrieNodeException(baseException); - if (trieNodeException is not null) - { - trieNodeException.EnhancedMessage = trieNodeException.NodeHash == rootHash - ? $"Failed to load root hash {rootHash} while loading key {rawKey.ToHexString()}." - : $"Failed to load key {rawKey.ToHexString()} from root hash {rootHash}."; + throw new TrieException($"Failed to load key {rawKey.ToHexString()} from root hash {rootHash ?? RootHash}.", e); } } [SkipLocalsInit] [DebuggerStepThrough] - public virtual void Set(ReadOnlySpan rawKey, byte[] value) - { - Set(rawKey, new CappedArray(value)); - } - - [SkipLocalsInit] - [DebuggerStepThrough] - public virtual void Set(ReadOnlySpan rawKey, CappedArray value) + public void Set(ReadOnlySpan rawKey, byte[] value) { if (_logger.IsTrace) - _logger.Trace($"{(value.Length == 0 ? $"Deleting {rawKey.ToHexString()}" : $"Setting {rawKey.ToHexString()} = {value.AsSpan().ToHexString()}")}"); + _logger.Trace($"{(value.Length == 0 ? $"Deleting {rawKey.ToHexString()}" : $"Setting {rawKey.ToHexString()} = {value.ToHexString()}")}"); int nibblesCount = 2 * rawKey.Length; byte[] array = null; Span nibbles = (rawKey.Length <= MaxKeyStackAlloc - ? stackalloc byte[MaxKeyStackAlloc] // Fixed size stack allocation - : array = ArrayPool.Shared.Rent(nibblesCount)) + ? stackalloc byte[MaxKeyStackAlloc] // Fixed size stack allocation + : array = ArrayPool.Shared.Rent(nibblesCount)) [..nibblesCount]; // Slice to exact size - - try - { - Nibbles.BytesToNibbleBytes(rawKey, nibbles); - Run(nibbles, nibblesCount, value, true); - } - finally - { - if (array is not null) ArrayPool.Shared.Return(array); - } + Nibbles.BytesToNibbleBytes(rawKey, nibbles); + Run(nibbles, nibblesCount, value, true); + if (array is not null) ArrayPool.Shared.Return(array); } [DebuggerStepThrough] @@ -394,10 +347,10 @@ public void Set(ReadOnlySpan rawKey, Rlp? value) Set(rawKey, value is null ? Array.Empty() : value.Bytes); } - private CappedArray Run( + private byte[]? Run( Span updatePath, int nibblesCount, - CappedArray updateValue, + byte[]? updateValue, bool isUpdate, bool ignoreMissingDelete = true, Keccak? startRootHash = null) @@ -423,12 +376,12 @@ private CappedArray Run( _nodeStack.Clear(); } - CappedArray result; + byte[]? result; if (startRootHash is not null) { if (_logger.IsTrace) _logger.Trace($"Starting from {startRootHash} - {traverseContext.ToString()}"); TrieNode startNode = TrieStore.FindCachedOrUnknown(startRootHash); - ResolveNode(startNode, in traverseContext); + startNode.ResolveNode(TrieStore); result = TraverseNode(startNode, in traverseContext); } else @@ -436,7 +389,7 @@ private CappedArray Run( bool trieIsEmpty = RootRef is null; if (trieIsEmpty) { - if (traverseContext.UpdateValue.IsNotNull) + if (traverseContext.UpdateValue is not null) { if (_logger.IsTrace) _logger.Trace($"Setting new leaf node with value {traverseContext.UpdateValue}"); byte[] key = updatePath[..nibblesCount].ToArray(); @@ -448,7 +401,7 @@ private CappedArray Run( } else { - ResolveNode(RootRef, in traverseContext); + RootRef.ResolveNode(TrieStore); if (_logger.IsTrace) _logger.Trace($"{traverseContext.ToString()}"); result = TraverseNode(RootRef, in traverseContext); } @@ -457,19 +410,7 @@ private CappedArray Run( return result; } - private void ResolveNode(TrieNode node, in TraverseContext traverseContext) - { - try - { - node.ResolveNode(TrieStore); - } - catch (TrieNodeException e) - { - ThrowMissingTrieNodeException(in traverseContext, e); - } - } - - private CappedArray TraverseNode(TrieNode node, in TraverseContext traverseContext) + private byte[]? TraverseNode(TrieNode node, in TraverseContext traverseContext) { if (_logger.IsTrace) _logger.Trace( @@ -487,7 +428,7 @@ private CappedArray TraverseNode(TrieNode node, in TraverseContext travers }; } - private void ConnectNodes(TrieNode? node, in TraverseContext traverseContext) + private void ConnectNodes(TrieNode? node) { bool isRoot = _nodeStack.Count == 0; TrieNode nextNode = node; @@ -562,7 +503,7 @@ L X - - - - - - - - - - - - - - */ "Before updating branch should have had at least two non-empty children"); } - ResolveNode(childNode, in traverseContext); + childNode.ResolveNode(TrieStore); if (childNode.IsBranch) { TrieNode extensionFromBranch = @@ -708,7 +649,7 @@ L L - - - - - - - - - - - - - - */ RootRef = nextNode; } - private CappedArray TraverseBranch(TrieNode node, in TraverseContext traverseContext) + private byte[]? TraverseBranch(TrieNode node, in TraverseContext traverseContext) { if (traverseContext.RemainingUpdatePathLength == 0) { @@ -722,12 +663,12 @@ which is not possible within the Ethereum protocol which has keys of the same le if (traverseContext.IsDelete) { - if (node.Value.IsNull) + if (node.Value is null) { return null; } - ConnectNodes(null, in traverseContext); + ConnectNodes(null); } else if (Bytes.AreEqual(traverseContext.UpdateValue, node.Value)) { @@ -736,7 +677,7 @@ which is not possible within the Ethereum protocol which has keys of the same le else { TrieNode withUpdatedValue = node.CloneWithChangedValue(traverseContext.UpdateValue); - ConnectNodes(withUpdatedValue, in traverseContext); + ConnectNodes(withUpdatedValue); } return traverseContext.UpdateValue; @@ -769,18 +710,18 @@ which is not possible within the Ethereum protocol which has keys of the same le byte[] leafPath = traverseContext.UpdatePath[ currentIndex..].ToArray(); TrieNode leaf = TrieNodeFactory.CreateLeaf(leafPath, traverseContext.UpdateValue); - ConnectNodes(leaf, in traverseContext); + ConnectNodes(leaf); return traverseContext.UpdateValue; } - ResolveNode(childNode, in traverseContext); + childNode.ResolveNode(TrieStore); TrieNode nextNode = childNode; return TraverseNext(in traverseContext, 1, nextNode); } - private CappedArray TraverseLeaf(TrieNode node, in TraverseContext traverseContext) + private byte[]? TraverseLeaf(TrieNode node, in TraverseContext traverseContext) { if (node.Key is null) { @@ -801,8 +742,8 @@ private CappedArray TraverseLeaf(TrieNode node, in TraverseContext travers longerPath = remaining; } - CappedArray shorterPathValue; - CappedArray longerPathValue; + byte[] shorterPathValue; + byte[] longerPathValue; if (Bytes.AreEqual(shorterPath, node.Key)) { @@ -825,14 +766,14 @@ private CappedArray TraverseLeaf(TrieNode node, in TraverseContext travers if (traverseContext.IsDelete) { - ConnectNodes(null, in traverseContext); + ConnectNodes(null); return traverseContext.UpdateValue; } if (!Bytes.AreEqual(node.Value, traverseContext.UpdateValue)) { TrieNode withUpdatedValue = node.CloneWithChangedValue(traverseContext.UpdateValue); - ConnectNodes(withUpdatedValue, in traverseContext); + ConnectNodes(withUpdatedValue); return traverseContext.UpdateValue; } @@ -878,12 +819,12 @@ private CappedArray TraverseLeaf(TrieNode node, in TraverseContext travers leafPath.ToArray(), longerPathValue); _nodeStack.Push(new StackedNode(branch, longerPath[extensionLength])); - ConnectNodes(withUpdatedKeyAndValue, in traverseContext); + ConnectNodes(withUpdatedKeyAndValue); return traverseContext.UpdateValue; } - private CappedArray TraverseExtension(TrieNode node, in TraverseContext traverseContext) + private byte[]? TraverseExtension(TrieNode node, in TraverseContext traverseContext) { if (node.Key is null) { @@ -907,7 +848,7 @@ private CappedArray TraverseExtension(TrieNode node, in TraverseContext tr ThrowMissingChildException(node); } - ResolveNode(next, in traverseContext); + next.ResolveNode(TrieStore); return TraverseNext(in traverseContext, extensionLength, next); } @@ -966,11 +907,11 @@ TrieNode secondExtension branch.SetChild(pathBeforeUpdate[extensionLength], childNode); } - ConnectNodes(branch, in traverseContext); + ConnectNodes(branch); return traverseContext.UpdateValue; } - private CappedArray TraverseNext(in TraverseContext traverseContext, int extensionLength, TrieNode next) + private byte[] TraverseNext(in TraverseContext traverseContext, int extensionLength, TrieNode next) { // Move large struct creation out of flow so doesn't force additional stack space // in calling method even if not used @@ -992,11 +933,11 @@ private static int FindCommonPrefixLength(ReadOnlySpan shorterPath, ReadOn private readonly ref struct TraverseContext { - public CappedArray UpdateValue { get; } + public byte[]? UpdateValue { get; } public ReadOnlySpan UpdatePath { get; } public bool IsUpdate { get; } public bool IsRead => !IsUpdate; - public bool IsDelete => IsUpdate && UpdateValue.IsNull; + public bool IsDelete => IsUpdate && UpdateValue is null; public bool IgnoreMissingDelete { get; } public int CurrentIndex { get; } public int RemainingUpdatePathLength => UpdatePath.Length - CurrentIndex; @@ -1019,14 +960,14 @@ public TraverseContext(scoped in TraverseContext context, int index) public TraverseContext( Span updatePath, - CappedArray updateValue, + byte[]? updateValue, bool isUpdate, bool ignoreMissingDelete = true) { UpdatePath = updatePath; - if (updateValue.IsNotNull && updateValue.Length == 0) + if (updateValue is not null && updateValue.Length == 0) { - updateValue = new CappedArray(null); + updateValue = null; } UpdateValue = updateValue; @@ -1136,12 +1077,5 @@ private static void ThrowMissingPrefixException() { throw new InvalidDataException("An attempt to visit a node without a prefix path."); } - - [DoesNotReturn] - [StackTraceHidden] - private static void ThrowMissingTrieNodeException(in TraverseContext traverseContext, TrieNodeException e) - { - throw new MissingTrieNodeException(e.Message, e, traverseContext.UpdatePath.ToArray(), traverseContext.CurrentIndex); - } } } diff --git a/src/Nethermind/Nethermind.Trie/Pruning/ITrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/ITrieStore.cs index 282a49ea0f4..9f7a010b4ef 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/ITrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/ITrieStore.cs @@ -7,18 +7,17 @@ namespace Nethermind.Trie.Pruning { - public interface ITrieStore : ITrieNodeResolver, IDisposable + public interface ITrieStore : ITrieNodeResolver, IReadOnlyKeyValueStore, IDisposable { void CommitNode(long blockNumber, NodeCommitInfo nodeCommitInfo, WriteFlags writeFlags = WriteFlags.None); void FinishBlockCommit(TrieType trieType, long blockNumber, TrieNode? root, WriteFlags writeFlags = WriteFlags.None); + bool IsPersisted(Keccak keccak); bool IsPersisted(in ValueKeccak keccak); IReadOnlyTrieStore AsReadOnly(IKeyValueStore? keyValueStore); event EventHandler? ReorgBoundaryReached; - - IKeyValueStore AsKeyValueStore(); } } diff --git a/src/Nethermind/Nethermind.Trie/Pruning/MemoryLimit.cs b/src/Nethermind/Nethermind.Trie/Pruning/MemoryLimit.cs index 0fbd8949d25..2c8a8f597fd 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/MemoryLimit.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/MemoryLimit.cs @@ -5,7 +5,7 @@ namespace Nethermind.Trie.Pruning { - [DebuggerDisplay("{_memoryLimit/(1024*1024)} MB")] + [DebuggerDisplay("{_memoryLimit/(1024*1024)}MB")] public class MemoryLimit : IPruningStrategy { private readonly long _memoryLimit; diff --git a/src/Nethermind/Nethermind.Trie/Pruning/NullTrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/NullTrieStore.cs index 06a0d6f0552..bafc5893e81 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/NullTrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/NullTrieStore.cs @@ -19,7 +19,10 @@ public void FinishBlockCommit(TrieType trieType, long blockNumber, TrieNode? roo public void HackPersistOnShutdown() { } - public IReadOnlyTrieStore AsReadOnly(IKeyValueStore keyValueStore) => this; + public IReadOnlyTrieStore AsReadOnly(IKeyValueStore keyValueStore) + { + return this; + } public event EventHandler ReorgBoundaryReached { @@ -27,16 +30,24 @@ public event EventHandler ReorgBoundaryReached remove { } } - public IKeyValueStore AsKeyValueStore() => null!; - - public TrieNode FindCachedOrUnknown(Keccak hash) => new(NodeType.Unknown, hash); + public TrieNode FindCachedOrUnknown(Keccak hash) + { + return new(NodeType.Unknown, hash); + } - public byte[] LoadRlp(Keccak hash, ReadFlags flags = ReadFlags.None) => Array.Empty(); + public byte[] LoadRlp(Keccak hash, ReadFlags flags = ReadFlags.None) + { + return Array.Empty(); + } + public bool IsPersisted(Keccak keccak) => true; public bool IsPersisted(in ValueKeccak keccak) => true; public void Dispose() { } - public byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) => null; + public byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) + { + return null; + } } } diff --git a/src/Nethermind/Nethermind.Trie/Pruning/ReadOnlyTrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/ReadOnlyTrieStore.cs index 4d5e9676a78..0b87cf7f1e5 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/ReadOnlyTrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/ReadOnlyTrieStore.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Reflection.Metadata.Ecma335; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -14,13 +15,11 @@ public class ReadOnlyTrieStore : IReadOnlyTrieStore { private readonly TrieStore _trieStore; private readonly IKeyValueStore? _readOnlyStore; - private readonly ReadOnlyValueStore _publicStore; public ReadOnlyTrieStore(TrieStore trieStore, IKeyValueStore? readOnlyStore) { _trieStore = trieStore ?? throw new ArgumentNullException(nameof(trieStore)); _readOnlyStore = readOnlyStore; - _publicStore = new ReadOnlyValueStore(_trieStore.AsKeyValueStore()); } public TrieNode FindCachedOrUnknown(Keccak hash) => @@ -28,6 +27,7 @@ public TrieNode FindCachedOrUnknown(Keccak hash) => public byte[] LoadRlp(Keccak hash, ReadFlags flags) => _trieStore.LoadRlp(hash, _readOnlyStore, flags); + public bool IsPersisted(Keccak keccak) => _trieStore.IsPersisted(keccak); public bool IsPersisted(in ValueKeccak keccak) => _trieStore.IsPersisted(keccak); public IReadOnlyTrieStore AsReadOnly(IKeyValueStore keyValueStore) @@ -44,25 +44,10 @@ public event EventHandler ReorgBoundaryReached add { } remove { } } - - public IKeyValueStore AsKeyValueStore() => _publicStore; - public void Dispose() { } - public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteFlags.None) { } - - private class ReadOnlyValueStore : IKeyValueStore - { - private readonly IKeyValueStore _keyValueStore; + public byte[]? this[ReadOnlySpan key] => _trieStore[key]; - public ReadOnlyValueStore(IKeyValueStore keyValueStore) - { - _keyValueStore = keyValueStore; - } - - public byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) => _keyValueStore.Get(key, flags); - - public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteFlags.None) { } - } + public byte[]? Get(ReadOnlySpan key, ReadFlags flags) => _trieStore.Get(key, flags); } } diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index 19d134e63c7..f03526110d4 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -61,7 +61,7 @@ public TrieNode FromCachedRlpOrUnknown(Keccak hash) // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (_objectsCache.TryGetValue(hash, out TrieNode? trieNode)) { - if (trieNode!.FullRlp.IsNull) + if (trieNode!.FullRlp is null) { // // this happens in SyncProgressResolver // throw new InvalidAsynchronousStateException("Read only trie store is trying to read a transient node."); @@ -149,7 +149,6 @@ public TrieStore( _pruningStrategy = pruningStrategy ?? throw new ArgumentNullException(nameof(pruningStrategy)); _persistenceStrategy = persistenceStrategy ?? throw new ArgumentNullException(nameof(persistenceStrategy)); _dirtyNodes = new DirtyNodesCache(this); - _publicStore = new TrieKeyValueStore(this); } public long LastPersistedBlockNumber @@ -329,7 +328,7 @@ public byte[] LoadRlp(Keccak keccak, IKeyValueStore? keyValueStore, ReadFlags re if (rlp is null) { - throw new TrieNodeException($"Node {keccak} is missing from the DB", keccak); + throw new TrieException($"Node {keccak} is missing from the DB"); } Metrics.LoadedFromDbNodesCount++; @@ -337,7 +336,21 @@ public byte[] LoadRlp(Keccak keccak, IKeyValueStore? keyValueStore, ReadFlags re return rlp; } - public virtual byte[] LoadRlp(Keccak keccak, ReadFlags readFlags = ReadFlags.None) => LoadRlp(keccak, null, readFlags); + public byte[] LoadRlp(Keccak keccak, ReadFlags readFlags = ReadFlags.None) => LoadRlp(keccak, null, readFlags); + + public bool IsPersisted(Keccak keccak) + { + byte[]? rlp = _currentBatch?[keccak.Bytes] ?? _keyValueStore[keccak.Bytes]; + + if (rlp is null) + { + return false; + } + + Metrics.LoadedFromDbNodesCount++; + + return true; + } public bool IsPersisted(in ValueKeccak keccak) { @@ -493,7 +506,7 @@ private void PruneCurrentSet() /// private void PruneCache() { - if (_logger.IsDebug) _logger.Debug($"Pruning nodes {MemoryUsedByDirtyCache / 1.MB()} MB , last persisted block: {LastPersistedBlockNumber} current: {LatestCommittedBlockNumber}."); + if (_logger.IsDebug) _logger.Debug($"Pruning nodes {MemoryUsedByDirtyCache / 1.MB()}MB , last persisted block: {LastPersistedBlockNumber} current: {LatestCommittedBlockNumber}."); Stopwatch stopwatch = Stopwatch.StartNew(); long newMemory = 0; @@ -538,7 +551,7 @@ private void PruneCache() stopwatch.Stop(); Metrics.PruningTime = stopwatch.ElapsedMilliseconds; - if (_logger.IsDebug) _logger.Debug($"Finished pruning nodes in {stopwatch.ElapsedMilliseconds}ms {MemoryUsedByDirtyCache / 1.MB()} MB, last persisted block: {LastPersistedBlockNumber} current: {LatestCommittedBlockNumber}."); + if (_logger.IsDebug) _logger.Debug($"Finished pruning nodes in {stopwatch.ElapsedMilliseconds}ms {MemoryUsedByDirtyCache / 1.MB()}MB, last persisted block: {LastPersistedBlockNumber} current: {LatestCommittedBlockNumber}."); } /// @@ -556,9 +569,7 @@ public void Dispose() #region Private - protected readonly IKeyValueStoreWithBatching _keyValueStore; - - private readonly TrieKeyValueStore _publicStore; + private readonly IKeyValueStoreWithBatching _keyValueStore; private readonly IPruningStrategy _pruningStrategy; @@ -652,14 +663,14 @@ private void Persist(TrieNode currentNode, long blockNumber, WriteFlags writeFla // to prevent it from being removed from cache and also want to have it persisted. if (_logger.IsTrace) _logger.Trace($"Persisting {nameof(TrieNode)} {currentNode} in snapshot {blockNumber}."); - _currentBatch.Set(currentNode.Keccak.Bytes, currentNode.FullRlp.ToArray(), writeFlags); + _currentBatch.Set(currentNode.Keccak.Bytes, currentNode.FullRlp, writeFlags); currentNode.IsPersisted = true; currentNode.LastSeen = Math.Max(blockNumber, currentNode.LastSeen ?? 0); PersistedNodesCount++; } else { - Debug.Assert(currentNode.FullRlp.IsNotNull && currentNode.FullRlp.Length < 32, + Debug.Assert(currentNode.FullRlp is not null && currentNode.FullRlp.Length < 32, "We only expect persistence call without Keccak for the nodes that are kept inside the parent RLP (less than 32 bytes)."); } } @@ -795,7 +806,7 @@ void PersistNode(TrieNode n) Keccak? hash = n.Keccak; if (hash is not null) { - store[hash.Bytes] = n.FullRlp.ToArray(); + store[hash.Bytes] = n.FullRlp; int persistedNodesCount = Interlocked.Increment(ref persistedNodes); if (_logger.IsInfo && persistedNodesCount % million == 0) { @@ -818,32 +829,20 @@ void PersistNode(TrieNode n) }); } - private byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) + public byte[]? this[ReadOnlySpan key] + { + get => Get(key); + } + + public byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) { return _pruningStrategy.PruningEnabled && _dirtyNodes.AllNodes.TryGetValue(new ValueKeccak(key), out TrieNode? trieNode) && trieNode is not null && trieNode.NodeType != NodeType.Unknown - && trieNode.FullRlp.IsNotNull - ? trieNode.FullRlp.ToArray() + && trieNode.FullRlp is not null + ? trieNode.FullRlp : _currentBatch?.Get(key, flags) ?? _keyValueStore.Get(key, flags); } - - public IKeyValueStore AsKeyValueStore() => _publicStore; - - private class TrieKeyValueStore : IKeyValueStore - { - private readonly TrieStore _trieStore; - - public TrieKeyValueStore(TrieStore trieStore) - { - _trieStore = trieStore; - } - - public byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) => _trieStore.Get(key, flags); - - public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteFlags.None) - => _trieStore._keyValueStore.Set(key, value, flags); - } } } diff --git a/src/Nethermind/Nethermind.Trie/TrackingCappedArrayPool.cs b/src/Nethermind/Nethermind.Trie/TrackingCappedArrayPool.cs deleted file mode 100644 index a26edd82ad7..00000000000 --- a/src/Nethermind/Nethermind.Trie/TrackingCappedArrayPool.cs +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Buffers; -using System.Collections.Generic; -using Nethermind.Core.Buffers; -using Nethermind.Trie.Pruning; - -namespace Nethermind.Trie; - -/// -/// Track every rented CappedArray and return them all at once -/// -public class TrackingCappedArrayPool : ICappedArrayPool -{ - private List> _rentedBuffers; - private ArrayPool _arrayPool; - - public TrackingCappedArrayPool() : this(0) - { - } - - public TrackingCappedArrayPool(int initialCapacity, ArrayPool arrayPool = null) - { - _rentedBuffers = new List>(initialCapacity); - _arrayPool = arrayPool ?? ArrayPool.Shared; - } - - public CappedArray Rent(int size) - { - if (size == 0) - { - return new CappedArray(Array.Empty()); - } - - CappedArray rented = new CappedArray(_arrayPool.Rent(size), size); - rented.AsSpan().Fill(0); - _rentedBuffers.Add(rented); - return rented; - } - - public void Return(CappedArray buffer) - { - } - - public void ReturnAll() - { - foreach (CappedArray rentedBuffer in _rentedBuffers) - { - if (rentedBuffer.IsNotNull && rentedBuffer.Array.Length != 0) - _arrayPool.Return(rentedBuffer.Array); - } - _rentedBuffers.Clear(); - } -} diff --git a/src/Nethermind/Nethermind.Trie/TreeDumper.cs b/src/Nethermind/Nethermind.Trie/TreeDumper.cs index a7e020944fc..dbd4dfb9a59 100644 --- a/src/Nethermind/Nethermind.Trie/TreeDumper.cs +++ b/src/Nethermind/Nethermind.Trie/TreeDumper.cs @@ -29,7 +29,7 @@ public void VisitTree(Keccak rootHash, TrieVisitContext trieVisitContext) { if (rootHash == Keccak.EmptyTreeHash) { - _builder.AppendLine("EMPTY TREE"); + _builder.AppendLine("EMPTY TREEE"); } else { @@ -88,7 +88,7 @@ public override string ToString() private string? KeccakOrRlpStringOfNode(TrieNode node) { - return node.Keccak != null ? node.Keccak!.Bytes.ToHexString() : node.FullRlp.AsSpan().ToHexString(); + return node.Keccak != null ? node.Keccak!.Bytes.ToHexString() : node.FullRlp?.ToHexString(); } } } diff --git a/src/Nethermind/Nethermind.Trie/TrieException.cs b/src/Nethermind/Nethermind.Trie/TrieException.cs index 034e45d19bf..968b8b6638b 100644 --- a/src/Nethermind/Nethermind.Trie/TrieException.cs +++ b/src/Nethermind/Nethermind.Trie/TrieException.cs @@ -12,7 +12,11 @@ public TrieException() { } - public TrieException(string message, Exception? inner = null) : base(message, inner) + public TrieException(string message) : base(message) + { + } + + public TrieException(string message, Exception inner) : base(message, inner) { } } diff --git a/src/Nethermind/Nethermind.Trie/TrieNode.Decoder.cs b/src/Nethermind/Nethermind.Trie/TrieNode.Decoder.cs index 4676830589e..19b77aba03c 100644 --- a/src/Nethermind/Nethermind.Trie/TrieNode.Decoder.cs +++ b/src/Nethermind/Nethermind.Trie/TrieNode.Decoder.cs @@ -4,9 +4,7 @@ using System; using System.Buffers; using System.Diagnostics; -using System.Linq; using System.Runtime.CompilerServices; -using Nethermind.Core.Buffers; using Nethermind.Core.Crypto; using Nethermind.Serialization.Rlp; using Nethermind.Trie.Pruning; @@ -23,7 +21,7 @@ public partial class TrieNode private class TrieNodeDecoder { - public CappedArray Encode(ITrieNodeResolver tree, TrieNode? item, ICappedArrayPool? bufferPool) + public byte[] Encode(ITrieNodeResolver tree, TrieNode? item) { Metrics.TreeNodeRlpEncodings++; @@ -34,15 +32,15 @@ public CappedArray Encode(ITrieNodeResolver tree, TrieNode? item, ICappedA return item.NodeType switch { - NodeType.Branch => RlpEncodeBranch(tree, item, bufferPool), - NodeType.Extension => EncodeExtension(tree, item, bufferPool), - NodeType.Leaf => EncodeLeaf(item, bufferPool), + NodeType.Branch => RlpEncodeBranch(tree, item), + NodeType.Extension => EncodeExtension(tree, item), + NodeType.Leaf => EncodeLeaf(item), _ => throw new TrieException($"An attempt was made to encode a trie node of type {item.NodeType}") }; } [SkipLocalsInit] - private static CappedArray EncodeExtension(ITrieNodeResolver tree, TrieNode item, ICappedArrayPool? bufferPool) + private static byte[] EncodeExtension(ITrieNodeResolver tree, TrieNode item) { Debug.Assert(item.NodeType == NodeType.Extension, $"Node passed to {nameof(EncodeExtension)} is {item.NodeType}"); @@ -65,13 +63,11 @@ private static CappedArray EncodeExtension(ITrieNodeResolver tree, TrieNod Debug.Assert(nodeRef is not null, "Extension child is null when encoding."); - nodeRef.ResolveKey(tree, false, bufferPool: bufferPool); + nodeRef.ResolveKey(tree, false); int contentLength = Rlp.LengthOf(keyBytes) + (nodeRef.Keccak is null ? nodeRef.FullRlp.Length : Rlp.LengthOfKeccakRlp); int totalLength = Rlp.LengthOfSequence(contentLength); - - CappedArray data = bufferPool.SafeRentBuffer(totalLength); - RlpStream rlpStream = data.AsRlpStream(); + RlpStream rlpStream = new(totalLength); rlpStream.StartSequence(contentLength); rlpStream.Encode(keyBytes); if (rentedBuffer is not null) @@ -86,18 +82,18 @@ private static CappedArray EncodeExtension(ITrieNodeResolver tree, TrieNod // so E - - - - - - - - - - - - - - - // so | // so | - rlpStream.Write(nodeRef.FullRlp.AsSpan()); + rlpStream.Write(nodeRef.FullRlp); } else { rlpStream.Encode(nodeRef.Keccak); } - return data; + return rlpStream.Data; } [SkipLocalsInit] - private static CappedArray EncodeLeaf(TrieNode node, ICappedArrayPool? pool) + private static byte[] EncodeLeaf(TrieNode node) { if (node.Key is null) { @@ -115,44 +111,42 @@ private static CappedArray EncodeLeaf(TrieNode node, ICappedArrayPool? poo : rentedBuffer)[..hexLength]; HexPrefix.CopyToSpan(hexPrefix, isLeaf: true, keyBytes); - int contentLength = Rlp.LengthOf(keyBytes) + Rlp.LengthOf(node.Value.AsSpan()); + int contentLength = Rlp.LengthOf(keyBytes) + Rlp.LengthOf(node.Value); int totalLength = Rlp.LengthOfSequence(contentLength); - - CappedArray data = pool.SafeRentBuffer(totalLength); - RlpStream rlpStream = data.AsRlpStream(); + RlpStream rlpStream = new(totalLength); rlpStream.StartSequence(contentLength); rlpStream.Encode(keyBytes); if (rentedBuffer is not null) { ArrayPool.Shared.Return(rentedBuffer); } - rlpStream.Encode(node.Value.AsSpan()); - return data; + rlpStream.Encode(node.Value); + return rlpStream.Data; } - private static CappedArray RlpEncodeBranch(ITrieNodeResolver tree, TrieNode item, ICappedArrayPool? pool) + private static byte[] RlpEncodeBranch(ITrieNodeResolver tree, TrieNode item) { - int valueRlpLength = AllowBranchValues ? Rlp.LengthOf(item.Value.AsSpan()) : 1; - int contentLength = valueRlpLength + GetChildrenRlpLength(tree, item, pool); + int valueRlpLength = AllowBranchValues ? Rlp.LengthOf(item.Value) : 1; + int contentLength = valueRlpLength + GetChildrenRlpLength(tree, item); int sequenceLength = Rlp.LengthOfSequence(contentLength); - CappedArray result = pool.SafeRentBuffer(sequenceLength); + byte[] result = new byte[sequenceLength]; Span resultSpan = result.AsSpan(); - int position = Rlp.StartSequence(resultSpan, 0, contentLength); - WriteChildrenRlp(tree, item, resultSpan.Slice(position, contentLength - valueRlpLength), pool); + int position = Rlp.StartSequence(result, 0, contentLength); + WriteChildrenRlp(tree, item, resultSpan.Slice(position, contentLength - valueRlpLength)); position = sequenceLength - valueRlpLength; if (AllowBranchValues) { - Rlp.Encode(resultSpan, position, item.Value); + Rlp.Encode(result, position, item.Value); } else { - result.AsSpan()[position] = 128; + result[position] = 128; } return result; } - private static int GetChildrenRlpLength(ITrieNodeResolver tree, TrieNode item, ICappedArrayPool? bufferPool) + private static int GetChildrenRlpLength(ITrieNodeResolver tree, TrieNode item) { int totalLength = 0; item.InitData(); @@ -177,8 +171,8 @@ private static int GetChildrenRlpLength(ITrieNodeResolver tree, TrieNode item, I else { TrieNode childNode = (TrieNode)item._data[i]; - childNode!.ResolveKey(tree, false, bufferPool: bufferPool); - totalLength += childNode.Keccak is null ? childNode.FullRlp.Length : Rlp.LengthOfKeccakRlp; + childNode!.ResolveKey(tree, false); + totalLength += childNode.Keccak is null ? childNode.FullRlp!.Length : Rlp.LengthOfKeccakRlp; } } @@ -188,7 +182,7 @@ private static int GetChildrenRlpLength(ITrieNodeResolver tree, TrieNode item, I return totalLength; } - private static void WriteChildrenRlp(ITrieNodeResolver tree, TrieNode item, Span destination, ICappedArrayPool? bufferPool) + private static void WriteChildrenRlp(ITrieNodeResolver tree, TrieNode item, Span destination) { int position = 0; RlpStream rlpStream = item._rlpStream; @@ -218,10 +212,10 @@ private static void WriteChildrenRlp(ITrieNodeResolver tree, TrieNode item, Span else { TrieNode childNode = (TrieNode)item._data[i]; - childNode!.ResolveKey(tree, false, bufferPool: bufferPool); + childNode!.ResolveKey(tree, false); if (childNode.Keccak is null) { - Span fullRlp = childNode.FullRlp!.AsSpan(); + Span fullRlp = childNode.FullRlp.AsSpan(); fullRlp.CopyTo(destination.Slice(position, fullRlp.Length)); position += fullRlp.Length; } diff --git a/src/Nethermind/Nethermind.Trie/TrieNode.Visitor.cs b/src/Nethermind/Nethermind.Trie/TrieNode.Visitor.cs index 2fd7fcc6a0c..eb5564ccca3 100644 --- a/src/Nethermind/Nethermind.Trie/TrieNode.Visitor.cs +++ b/src/Nethermind/Nethermind.Trie/TrieNode.Visitor.cs @@ -1,12 +1,14 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Runtime.CompilerServices; +using System.Threading; using System.Threading.Tasks; using Nethermind.Core; -using Nethermind.Core.Buffers; using Nethermind.Serialization.Rlp; using Nethermind.Trie.Pruning; @@ -85,7 +87,7 @@ internal void AcceptResolvedNode(ITreeVisitor visitor, ITrieNodeResolver nodeRes case NodeType.Leaf: { - visitor.VisitLeaf(this, trieVisitContext.ToVisitContext(), Value.ToArray()); + visitor.VisitLeaf(this, trieVisitContext.ToVisitContext(), Value); if (!trieVisitContext.IsStorage && trieVisitContext.ExpectAccounts) // can combine these conditions { @@ -246,7 +248,7 @@ void VisitMultiThread(ITreeVisitor treeVisitor, ITrieNodeResolver trieNodeResolv case NodeType.Leaf: { - visitor.VisitLeaf(this, trieVisitContext, Value.ToArray()); + visitor.VisitLeaf(this, trieVisitContext, Value); trieVisitContext.AddVisited(); if (!trieVisitContext.IsStorage && trieVisitContext.ExpectAccounts) // can combine these conditions { diff --git a/src/Nethermind/Nethermind.Trie/TrieNode.cs b/src/Nethermind/Nethermind.Trie/TrieNode.cs index 92616812300..d21dbcb1522 100644 --- a/src/Nethermind/Nethermind.Trie/TrieNode.cs +++ b/src/Nethermind/Nethermind.Trie/TrieNode.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; +using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using Nethermind.Core; -using Nethermind.Core.Buffers; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Logging; @@ -54,7 +54,7 @@ public partial class TrieNode public Keccak? Keccak { get; internal set; } - public CappedArray FullRlp { get; internal set; } + public byte[]? FullRlp { get; internal set; } public NodeType NodeType { get; private set; } @@ -86,58 +86,36 @@ internal set /// /// Highly optimized /// - public CappedArray Value + public byte[]? Value { get { InitData(); - object? obj; - if (IsLeaf) { - obj = _data![1]; - - if (obj is null) - { - return new CappedArray(null); - } - - if (obj is byte[] asBytes) - { - return new CappedArray(asBytes); - } - - return (CappedArray)obj; + return (byte[])_data![1]; } if (!AllowBranchValues) { // branches that we use for state will never have value set as all the keys are equal length - return new CappedArray(Array.Empty()); + return Array.Empty(); } - obj = _data![BranchesCount]; - if (obj is null) + if (_data![BranchesCount] is null) { if (_rlpStream is null) { _data[BranchesCount] = Array.Empty(); - return new CappedArray(Array.Empty()); } else { SeekChild(BranchesCount); - byte[]? bArr = _rlpStream!.DecodeByteArray(); - _data![BranchesCount] = bArr; - return new CappedArray(bArr); + _data![BranchesCount] = _rlpStream!.DecodeByteArray(); } } - if (obj is byte[] asBytes2) - { - return new CappedArray(asBytes2); - } - return (CappedArray)obj; + return (byte[])_data[BranchesCount]; } set @@ -156,19 +134,6 @@ public CappedArray Value throw new TrieException("Optimized Patricia Trie does not support setting values on branches."); } - if (value.IsNull) - { - _data![IsLeaf ? 1 : BranchesCount] = null; - return; - } - - if (value.IsUncapped) - { - // Store array directly if possible to reduce memory - _data![IsLeaf ? 1 : BranchesCount] = value.Array; - return; - } - _data![IsLeaf ? 1 : BranchesCount] = value; } } @@ -193,7 +158,7 @@ public bool IsValidWithOneNodeLess if (AllowBranchValues) { - nonEmptyNodes += Value.Length > 0 ? 1 : 0; + nonEmptyNodes += (Value?.Length ?? 0) > 0 ? 1 : 0; } return nonEmptyNodes > 2; @@ -216,7 +181,7 @@ public TrieNode(NodeType nodeType, Keccak keccak) } } - public TrieNode(NodeType nodeType, CappedArray rlp, bool isDirty = false) + public TrieNode(NodeType nodeType, byte[] rlp, bool isDirty = false) { NodeType = nodeType; FullRlp = rlp; @@ -225,16 +190,12 @@ public TrieNode(NodeType nodeType, CappedArray rlp, bool isDirty = false) _rlpStream = rlp.AsRlpStream(); } - public TrieNode(NodeType nodeType, byte[]? rlp, bool isDirty = false) : this(nodeType, new CappedArray(rlp), isDirty) - { - } - public TrieNode(NodeType nodeType, Keccak keccak, ReadOnlySpan rlp) - : this(nodeType, keccak, new CappedArray(rlp.ToArray())) + : this(nodeType, keccak, rlp.ToArray()) { } - public TrieNode(NodeType nodeType, Keccak keccak, CappedArray rlp) + public TrieNode(NodeType nodeType, Keccak keccak, byte[] rlp) : this(nodeType, rlp) { Keccak = keccak; @@ -248,10 +209,10 @@ public override string ToString() { #if DEBUG return - $"[{NodeType}({FullRlp.Length}){(FullRlp.IsNotNull && FullRlp.Length < 32 ? $"{FullRlp.AsSpan().ToHexString()}" : "")}" + + $"[{NodeType}({FullRlp?.Length}){(FullRlp is not null && FullRlp?.Length < 32 ? $"{FullRlp.ToHexString()}" : "")}" + $"|{Id}|{Keccak}|{LastSeen}|D:{IsDirty}|S:{IsSealed}|P:{IsPersisted}|"; #else - return $"[{NodeType}({FullRlp.Length})|{Keccak?.ToShortString()}|{LastSeen}|D:{IsDirty}|S:{IsSealed}|P:{IsPersisted}|"; + return $"[{NodeType}({FullRlp?.Length})|{Keccak?.ToShortString()}|{LastSeen}|D:{IsDirty}|S:{IsSealed}|P:{IsPersisted}|"; #endif } @@ -271,13 +232,13 @@ public void Seal() /// /// Highly optimized /// - public void ResolveNode(ITrieNodeResolver tree, ReadFlags readFlags = ReadFlags.None, ICappedArrayPool? bufferPool = null) + public void ResolveNode(ITrieNodeResolver tree, ReadFlags readFlags = ReadFlags.None) { try { if (NodeType == NodeType.Unknown) { - if (FullRlp.IsNull) + if (FullRlp is null) { if (Keccak is null) { @@ -287,7 +248,7 @@ public void ResolveNode(ITrieNodeResolver tree, ReadFlags readFlags = ReadFlags. FullRlp = tree.LoadRlp(Keccak, readFlags); IsPersisted = true; - if (FullRlp.IsNull) + if (FullRlp is null) { throw new TrieException($"Trie returned a NULL RLP for node {Keccak}"); } @@ -327,11 +288,7 @@ public void ResolveNode(ITrieNodeResolver tree, ReadFlags readFlags = ReadFlags. { NodeType = NodeType.Leaf; Key = key; - - ReadOnlySpan valueSpan = _rlpStream.DecodeByteArraySpan(); - CappedArray buffer = bufferPool.SafeRentBuffer(valueSpan.Length); - valueSpan.CopyTo(buffer.AsSpan()); - Value = buffer; + Value = _rlpStream.DecodeByteArray(); } else { @@ -343,16 +300,16 @@ public void ResolveNode(ITrieNodeResolver tree, ReadFlags readFlags = ReadFlags. } else { - throw new TrieNodeException($"Unexpected number of items = {numberOfItems} when decoding a node from RLP ({FullRlp.AsSpan().ToHexString()})", Keccak ?? Keccak.Zero); + throw new TrieException($"Unexpected number of items = {numberOfItems} when decoding a node from RLP ({FullRlp?.ToHexString()})"); } } catch (RlpException rlpException) { - throw new TrieNodeException($"Error when decoding node {Keccak}", Keccak ?? Keccak.Zero, rlpException); + throw new TrieException($"Error when decoding node {Keccak}", rlpException); } } - public void ResolveKey(ITrieNodeResolver tree, bool isRoot, ICappedArrayPool? bufferPool = null) + public void ResolveKey(ITrieNodeResolver tree, bool isRoot) { if (Keccak is not null) { @@ -361,10 +318,10 @@ public void ResolveKey(ITrieNodeResolver tree, bool isRoot, ICappedArrayPool? bu return; } - Keccak = GenerateKey(tree, isRoot, bufferPool); + Keccak = GenerateKey(tree, isRoot); } - public Keccak? GenerateKey(ITrieNodeResolver tree, bool isRoot, ICappedArrayPool? bufferPool = null) + public Keccak? GenerateKey(ITrieNodeResolver tree, bool isRoot) { Keccak? keccak = Keccak; if (keccak is not null) @@ -372,14 +329,9 @@ public void ResolveKey(ITrieNodeResolver tree, bool isRoot, ICappedArrayPool? bu return keccak; } - if (FullRlp.IsNull || IsDirty) + if (FullRlp is null || IsDirty) { - CappedArray oldRlp = FullRlp; - FullRlp = RlpEncode(tree, bufferPool); - if (oldRlp.IsNotNull) - { - bufferPool.SafeReturnBuffer(oldRlp); - } + FullRlp = RlpEncode(tree); _rlpStream = FullRlp.AsRlpStream(); } @@ -389,7 +341,7 @@ public void ResolveKey(ITrieNodeResolver tree, bool isRoot, ICappedArrayPool? bu if (FullRlp.Length >= 32 || isRoot) { Metrics.TreeNodeHashCalculations++; - return Keccak.Compute(FullRlp.AsSpan()); + return Keccak.Compute(FullRlp); } return null; @@ -418,9 +370,9 @@ public bool TryResolveStorageRootHash(ITrieNodeResolver resolver, out Keccak? st return false; } - internal CappedArray RlpEncode(ITrieNodeResolver tree, ICappedArrayPool? bufferPool = null) + internal byte[] RlpEncode(ITrieNodeResolver tree) { - CappedArray rlp = _nodeDecoder.Encode(tree, this, bufferPool); + byte[] rlp = _nodeDecoder.Encode(tree, this); // just included here to improve the class reading // after some analysis I believe that any non-test Ethereum cases of a trie ever have nodes with RLP shorter than 32 bytes // if (rlp.Bytes.Length < 32) @@ -544,8 +496,8 @@ public TrieNode? this[int i] { // we expect this to happen as a Trie traversal error (please see the stack trace above) // we need to investigate this case when it happens again - bool isKeccakCalculated = Keccak is not null && FullRlp.IsNotNull; - bool isKeccakCorrect = isKeccakCalculated && Keccak == Keccak.Compute(FullRlp.AsSpan()); + bool isKeccakCalculated = Keccak is not null && FullRlp is not null; + bool isKeccakCorrect = isKeccakCalculated && Keccak == Keccak.Compute(FullRlp); throw new TrieException($"Unexpected type found at position {childIndex} of {this} with {nameof(_data)} of length {_data?.Length}. Expected a {nameof(TrieNode)} or {nameof(Keccak)} but found {childOrRef?.GetType()} with a value of {childOrRef}. Keccak calculated? : {isKeccakCalculated}; Keccak correct? : {isKeccakCorrect}"); } @@ -592,10 +544,10 @@ Keccak is null : MemorySizes.RefSize + Keccak.MemorySize; long fullRlpSize = MemorySizes.RefSize + - (FullRlp.IsNull ? 0 : MemorySizes.Align(FullRlp.Array.Length + MemorySizes.ArrayOverhead)); + (FullRlp is null ? 0 : MemorySizes.Align(FullRlp.Length + MemorySizes.ArrayOverhead)); long rlpStreamSize = MemorySizes.RefSize + (_rlpStream?.MemorySize ?? 0) - - (FullRlp.IsNull ? 0 : MemorySizes.Align(FullRlp.Array.Length + MemorySizes.ArrayOverhead)); + - (FullRlp is null ? 0 : MemorySizes.Align(FullRlp.Length + MemorySizes.ArrayOverhead)); long dataSize = MemorySizes.RefSize + (_data is null @@ -623,11 +575,6 @@ Keccak is null dataSize += MemorySizes.ArrayOverhead + array.Length; } - if (_data![i] is CappedArray cappedArray) - { - dataSize += MemorySizes.ArrayOverhead + (cappedArray.Array?.Length ?? 0) + MemorySizes.SmallObjectOverhead; - } - if (recursive) { if (_data![i] is TrieNode node) @@ -667,7 +614,7 @@ public TrieNode Clone() } } - if (FullRlp.IsNotNull) + if (FullRlp is not null) { trieNode.FullRlp = FullRlp; trieNode._rlpStream = FullRlp.AsRlpStream(); @@ -676,14 +623,14 @@ public TrieNode Clone() return trieNode; } - public TrieNode CloneWithChangedValue(CappedArray changedValue) + public TrieNode CloneWithChangedValue(byte[]? changedValue) { TrieNode trieNode = Clone(); trieNode.Value = changedValue; return trieNode; } - public TrieNode CloneWithChangedKeyAndValue(byte[] key, CappedArray changedValue) + public TrieNode CloneWithChangedKeyAndValue(byte[] key, byte[]? changedValue) { TrieNode trieNode = Clone(); trieNode.Key = key; @@ -816,7 +763,7 @@ private bool TryResolveStorageRoot(ITrieNodeResolver resolver, out TrieNode? sto { hasStorage = true; } - else if (Value.Length > 64) // if not a storage leaf + else if (Value?.Length > 64) // if not a storage leaf { Keccak storageRootKey = _accountDecoder.DecodeStorageRootOnly(Value.AsRlpStream()); if (storageRootKey != Keccak.EmptyTreeHash) diff --git a/src/Nethermind/Nethermind.Trie/TrieNodeException.cs b/src/Nethermind/Nethermind.Trie/TrieNodeException.cs deleted file mode 100644 index 4fe6e870880..00000000000 --- a/src/Nethermind/Nethermind.Trie/TrieNodeException.cs +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using Nethermind.Core.Crypto; - -namespace Nethermind.Trie; - -public class TrieNodeException : TrieException -{ - public ValueKeccak NodeHash { get; private set; } - public string? EnhancedMessage { get; set; } - public override string Message => EnhancedMessage is null ? base.Message : EnhancedMessage + Environment.NewLine + base.Message; - - public TrieNodeException(string message, Keccak keccak, Exception? inner = null) : base(message, inner) - { - NodeHash = keccak; - } -} diff --git a/src/Nethermind/Nethermind.Trie/TrieNodeFactory.cs b/src/Nethermind/Nethermind.Trie/TrieNodeFactory.cs index 7d9fbc72d44..0819cc22b88 100644 --- a/src/Nethermind/Nethermind.Trie/TrieNodeFactory.cs +++ b/src/Nethermind/Nethermind.Trie/TrieNodeFactory.cs @@ -1,7 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using Nethermind.Core.Buffers; +using System.Diagnostics; +using System.Xml.XPath; namespace Nethermind.Trie { @@ -13,7 +14,7 @@ public static TrieNode CreateBranch() return node; } - public static TrieNode CreateLeaf(byte[] path, CappedArray value) + public static TrieNode CreateLeaf(byte[] path, byte[]? value) { TrieNode node = new(NodeType.Leaf); node.Key = path; diff --git a/src/Nethermind/Nethermind.Trie/TrieStats.cs b/src/Nethermind/Nethermind.Trie/TrieStats.cs index adaf65d57cf..88e280d662f 100644 --- a/src/Nethermind/Nethermind.Trie/TrieStats.cs +++ b/src/Nethermind/Nethermind.Trie/TrieStats.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Linq; using System.Text; namespace Nethermind.Trie diff --git a/src/Nethermind/Nethermind.Trie/TrieStatsCollector.cs b/src/Nethermind/Nethermind.Trie/TrieStatsCollector.cs index 3158f68ee9a..0ed1c52f121 100644 --- a/src/Nethermind/Nethermind.Trie/TrieStatsCollector.cs +++ b/src/Nethermind/Nethermind.Trie/TrieStatsCollector.cs @@ -51,12 +51,12 @@ public void VisitBranch(TrieNode node, TrieVisitContext trieVisitContext) { if (trieVisitContext.IsStorage) { - Interlocked.Add(ref Stats._storageSize, node.FullRlp.Length); + Interlocked.Add(ref Stats._storageSize, node.FullRlp?.Length ?? 0); Interlocked.Increment(ref Stats._storageBranchCount); } else { - Interlocked.Add(ref Stats._stateSize, node.FullRlp.Length); + Interlocked.Add(ref Stats._stateSize, node.FullRlp?.Length ?? 0); Interlocked.Increment(ref Stats._stateBranchCount); } @@ -67,12 +67,12 @@ public void VisitExtension(TrieNode node, TrieVisitContext trieVisitContext) { if (trieVisitContext.IsStorage) { - Interlocked.Add(ref Stats._storageSize, node.FullRlp.Length); + Interlocked.Add(ref Stats._storageSize, node.FullRlp?.Length ?? 0); Interlocked.Increment(ref Stats._storageExtensionCount); } else { - Interlocked.Add(ref Stats._stateSize, node.FullRlp.Length); + Interlocked.Add(ref Stats._stateSize, node.FullRlp?.Length ?? 0); Interlocked.Increment(ref Stats._stateExtensionCount); } @@ -89,12 +89,12 @@ public void VisitLeaf(TrieNode node, TrieVisitContext trieVisitContext, byte[] v if (trieVisitContext.IsStorage) { - Interlocked.Add(ref Stats._storageSize, node.FullRlp.Length); + Interlocked.Add(ref Stats._storageSize, node.FullRlp?.Length ?? 0); Interlocked.Increment(ref Stats._storageLeafCount); } else { - Interlocked.Add(ref Stats._stateSize, node.FullRlp.Length); + Interlocked.Add(ref Stats._stateSize, node.FullRlp?.Length ?? 0); Interlocked.Increment(ref Stats._accountCount); } diff --git a/src/Nethermind/Nethermind.Trie/VisitContext.cs b/src/Nethermind/Nethermind.Trie/VisitContext.cs index cfe6655398d..7bbfb14b5c3 100644 --- a/src/Nethermind/Nethermind.Trie/VisitContext.cs +++ b/src/Nethermind/Nethermind.Trie/VisitContext.cs @@ -22,7 +22,7 @@ public class TrieVisitContext : IDisposable public int MaxDegreeOfParallelism { get => _maxDegreeOfParallelism; - internal init => _maxDegreeOfParallelism = VisitingOptions.AdjustMaxDegreeOfParallelism(value); + internal init => _maxDegreeOfParallelism = value == 0 ? Environment.ProcessorCount : value; } public SemaphoreSlim Semaphore diff --git a/src/Nethermind/Nethermind.Trie/VisitingOptions.cs b/src/Nethermind/Nethermind.Trie/VisitingOptions.cs index 7b5ff8a0da5..a8c00648b55 100644 --- a/src/Nethermind/Nethermind.Trie/VisitingOptions.cs +++ b/src/Nethermind/Nethermind.Trie/VisitingOptions.cs @@ -11,7 +11,6 @@ namespace Nethermind.Trie public class VisitingOptions { public static readonly VisitingOptions Default = new(); - private readonly int _maxDegreeOfParallelism = 1; /// /// Should visit accounts. @@ -21,14 +20,7 @@ public class VisitingOptions /// /// Maximum number of threads that will be used to visit the trie. /// - public int MaxDegreeOfParallelism - { - get => _maxDegreeOfParallelism; - init - { - _maxDegreeOfParallelism = AdjustMaxDegreeOfParallelism(value); - } - } + public int MaxDegreeOfParallelism { get; init; } = 1; /// /// Specify memory budget to run a batched trie visitor. Significantly reduce read iops as memory budget @@ -38,14 +30,5 @@ public int MaxDegreeOfParallelism /// with slower SSD. Set to 0 to disable batched trie visitor. /// public long FullScanMemoryBudget { get; set; } - - public static int AdjustMaxDegreeOfParallelism(int rawMaxDegreeOfParallelism) - { - if (rawMaxDegreeOfParallelism == 0) - return Math.Max(Environment.ProcessorCount / 4, 1); - if (rawMaxDegreeOfParallelism <= -1) - return Environment.ProcessorCount; - return rawMaxDegreeOfParallelism; - } } } diff --git a/src/Nethermind/Nethermind.TxPool.Test/NonceManagerTests.cs b/src/Nethermind/Nethermind.TxPool.Test/NonceManagerTests.cs index 45455ced528..4d52ea18552 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/NonceManagerTests.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/NonceManagerTests.cs @@ -33,7 +33,7 @@ public class NonceManagerTests public void Setup() { ILogManager logManager = LimboLogs.Instance; - _specProvider = MainnetSpecProvider.Instance; + _specProvider = RopstenSpecProvider.Instance; var trieStore = new TrieStore(new MemDb(), logManager); var codeDb = new MemDb(); _stateProvider = new WorldState(trieStore, codeDb, logManager); diff --git a/src/Nethermind/Nethermind.TxPool.Test/ReceiptStorageTests.cs b/src/Nethermind/Nethermind.TxPool.Test/ReceiptStorageTests.cs index 51fd3449f06..7729c797877 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/ReceiptStorageTests.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/ReceiptStorageTests.cs @@ -39,7 +39,7 @@ public ReceiptStorageTests(bool useEip2718) [SetUp] public void Setup() { - _specProvider = MainnetSpecProvider.Instance; + _specProvider = RopstenSpecProvider.Instance; _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId, LimboLogs.Instance); _blockTree = Build.A.BlockTree() .WithBlocks(Build.A.Block.TestObject) diff --git a/src/Nethermind/Nethermind.TxPool.Test/TxBroadcasterTests.cs b/src/Nethermind/Nethermind.TxPool.Test/TxBroadcasterTests.cs index 7d911711971..581e0cd55b3 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/TxBroadcasterTests.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/TxBroadcasterTests.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; using FluentAssertions; @@ -21,8 +20,8 @@ using Nethermind.Logging; using Nethermind.Network; using Nethermind.Network.P2P; -using Nethermind.Network.P2P.Subprotocols.Eth; using Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages; +using Nethermind.Network.P2P.Subprotocols.Eth.V65; using Nethermind.Network.P2P.Subprotocols.Eth.V65.Messages; using Nethermind.Network.P2P.Subprotocols.Eth.V67; using Nethermind.Network.P2P.Subprotocols.Eth.V68; @@ -54,7 +53,7 @@ public class TxBroadcasterTests public void Setup() { _logManager = LimboLogs.Instance; - _specProvider = MainnetSpecProvider.Instance; + _specProvider = RopstenSpecProvider.Instance; _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId, _logManager); _blockTree = Substitute.For(); _comparer = new TransactionComparerProvider(_specProvider, _blockTree).GetDefaultComparer(); @@ -244,7 +243,7 @@ public void should_not_pick_txs_with_GasPrice_lower_than_CurrentBaseFee(int thre const int currentBaseFeeInGwei = 250; _headInfo.CurrentBaseFee.Returns(currentBaseFeeInGwei.GWei()); Block headBlock = Build.A.Block - .WithNumber(MainnetSpecProvider.LondonBlockNumber) + .WithNumber(RopstenSpecProvider.LondonBlockNumber) .WithBaseFeePerGas(currentBaseFeeInGwei.GWei()) .TestObject; _blockTree.Head.Returns(headBlock); @@ -293,7 +292,7 @@ public void should_not_pick_1559_txs_with_MaxFeePerGas_lower_than_CurrentBaseFee const int currentBaseFeeInGwei = 250; _headInfo.CurrentBaseFee.Returns(currentBaseFeeInGwei.GWei()); Block headBlock = Build.A.Block - .WithNumber(MainnetSpecProvider.LondonBlockNumber) + .WithNumber(RopstenSpecProvider.LondonBlockNumber) .WithBaseFeePerGas(currentBaseFeeInGwei.GWei()) .TestObject; _blockTree.Head.Returns(headBlock); @@ -452,9 +451,7 @@ public void should_broadcast_hash_of_blob_local_tx_to_eth68_peers_immediately_af } [TestCase(1_000, true)] - [TestCase(4 * 1024, true)] - [TestCase(4 * 1024 + 1, false)] - [TestCase(128 * 1024, false)] + [TestCase(128 * 1024, true)] [TestCase(128 * 1024 + 1, false)] [TestCase(1_000_000, false)] public void should_broadcast_full_local_tx_up_to_max_size_and_only_announce_if_larger(int txSize, bool shouldBroadcastFullTx) @@ -502,62 +499,4 @@ public void should_broadcast_full_local_tx_up_to_max_size_and_only_announce_if_l } session68.DidNotReceive().DeliverMessage(Arg.Any()); } - - [TestCase(true, true, 1)] - [TestCase(false, true, 0)] - [TestCase(true, false, 0)] - [TestCase(false, false, 0)] - public void should_check_tx_policy_for_broadcast(bool canGossipTransactions, bool shouldGossipTransaction, int received) - { - ITxGossipPolicy txGossipPolicy = Substitute.For(); - _broadcaster = new TxBroadcaster(_comparer, TimerFactory.Default, _txPoolConfig, _headInfo, _logManager, txGossipPolicy); - _headInfo.CurrentBaseFee.Returns(0.GWei()); - - ISession session = Substitute.For(); - session.Node.Returns(new Node(TestItem.PublicKeyA, TestItem.IPEndPointA)); - ITxPoolPeer eth68Handler = new Eth68ProtocolHandler(session, - Substitute.For(), - Substitute.For(), - Substitute.For(), - Substitute.For(), - Substitute.For(), - Substitute.For(), - new ForkInfo(_specProvider, Keccak.Zero), - Substitute.For()); - _broadcaster.AddPeer(eth68Handler); - - Transaction localTx = Build.A.Transaction - .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA) - .TestObject; - - txGossipPolicy.CanGossipTransactions.Returns(canGossipTransactions); - txGossipPolicy.ShouldGossipTransaction(localTx).Returns(shouldGossipTransaction); - - _broadcaster.Broadcast(localTx, true); - - session.Received(received).DeliverMessage(Arg.Any()); - } - - [Test] - public void should_rebroadcast_all_persistent_transactions_if_PeerNotificationThreshold_is_100([Values(true, false)] bool shouldBroadcastAll) - { - _txPoolConfig = new TxPoolConfig() { Size = 100, PeerNotificationThreshold = shouldBroadcastAll ? 100 : 5 }; - _broadcaster = new TxBroadcaster(_comparer, TimerFactory.Default, _txPoolConfig, _headInfo, _logManager); - - for (int i = 0; i < _txPoolConfig.Size; i++) - { - Transaction tx = Build.A.Transaction - .WithNonce((UInt256)i) - .SignedAndResolved(TestItem.PrivateKeyA).TestObject; - _broadcaster.Broadcast(tx, true); - } - - Transaction[] pickedTxs = _broadcaster.GetPersistentTxsToSend().TransactionsToSend.ToArray(); - pickedTxs.Length.Should().Be(shouldBroadcastAll ? 100 : 1); - - for (int i = 0; i < pickedTxs.Length; i++) - { - pickedTxs[i].Nonce.Should().Be((UInt256)i); - } - } } diff --git a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs index 3a1b0936813..049ae8e8279 100644 --- a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs +++ b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -50,7 +51,7 @@ public class TxPoolTests public void Setup() { _logManager = LimboLogs.Instance; - _specProvider = MainnetSpecProvider.Instance; + _specProvider = RopstenSpecProvider.Instance; _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId, _logManager); var trieStore = new TrieStore(new MemDb(), _logManager); var codeDb = new MemDb(); @@ -93,8 +94,8 @@ public void should_delete_peers() [Test] public void should_ignore_transactions_with_different_chain_id() { - _txPool = CreatePool(null, new TestSpecProvider(Shanghai.Instance)); - EthereumEcdsa ecdsa = new(BlockchainIds.Sepolia, _logManager); // default is mainnet, we're passing sepolia + _txPool = CreatePool(); + EthereumEcdsa ecdsa = new(TestBlockchainIds.ChainId, _logManager); Transaction tx = Build.A.Transaction.SignedAndResolved(ecdsa, TestItem.PrivateKeyA).TestObject; AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast); _txPool.GetPendingTransactions().Length.Should().Be(0); @@ -579,7 +580,8 @@ public void should_not_count_txs_with_stale_nonces_when_calculating_cumulative_c } [Test] - public void should_add_tx_if_cost_of_executing_all_txs_in_bucket_exceeds_balance_but_these_with_lower_nonces_doesnt() + public void + should_add_tx_if_cost_of_executing_all_txs_in_bucket_exceeds_balance_but_these_with_lower_nonces_doesnt() { const int gasPrice = 10; const int value = 1; @@ -604,15 +606,9 @@ public void should_add_tx_if_cost_of_executing_all_txs_in_bucket_exceeds_balance } } - _txPool.GetPendingTransactions().Length.Should().Be(8); // nonces 0-6 and 8 - _txPool.GetPendingTransactions().Last().Nonce.Should().Be(8); - - _txPool.SubmitTx(transactions[8], TxHandlingOptions.PersistentBroadcast).Should().Be(AcceptTxResult.AlreadyKnown); - _txPool.SubmitTx(transactions[7], TxHandlingOptions.PersistentBroadcast).Should().Be(AcceptTxResult.Accepted); - - _txPool.GetPendingTransactions().Length.Should().Be(8); // nonces 0-7 - 8 was removed because of not enough balance - _txPool.GetPendingTransactions().Last().Nonce.Should().Be(7); - _txPool.GetPendingTransactions().Should().BeEquivalentTo(transactions.SkipLast(2)); + _txPool.GetPendingTransactions().Length.Should().Be(8); + _txPool.SubmitTx(transactions[7], TxHandlingOptions.PersistentBroadcast); + _txPool.GetPendingTransactions().Length.Should().Be(9); } [Test] @@ -1113,10 +1109,10 @@ public void should_accept_access_list_transactions_only_when_eip2930_enabled([Va { if (!eip2930Enabled) { - _blockTree.FindBestSuggestedHeader().Returns(Build.A.BlockHeader.WithNumber(MainnetSpecProvider.BerlinBlockNumber - 1).TestObject); + _blockTree.FindBestSuggestedHeader().Returns(Build.A.BlockHeader.WithNumber(RopstenSpecProvider.BerlinBlockNumber - 1).TestObject); } - _txPool = CreatePool(null, new TestSpecProvider(eip2930Enabled ? Berlin.Instance : Istanbul.Instance)); + _txPool = CreatePool(); Transaction tx = Build.A.Transaction .WithType(TxType.AccessList) .WithChainId(TestBlockchainIds.ChainId) @@ -1550,58 +1546,6 @@ public void Should_not_replace_better_txs_by_worse_ones() _txPool.GetPendingTransactionsCount().Should().Be(txPoolConfig.Size); } - [Test] - public void Should_not_replace_ready_txs_by_nonce_gap_ones() - { - TxPoolConfig txPoolConfig = new() { Size = 128 }; - _txPool = CreatePool(txPoolConfig); - - // send (size - 1) standard txs from different senders - for (int i = 0; i < txPoolConfig.Size - 1; i++) - { - Transaction tx = Build.A.Transaction - .WithNonce(0) - .WithGasPrice(10) - .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeys[i]).TestObject; - - EnsureSenderBalance(TestItem.PrivateKeys[i].Address, UInt256.MaxValue); - _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast).Should().Be(AcceptTxResult.Accepted); - } - - _txPool.GetPendingTransactionsCount().Should().Be(txPoolConfig.Size - 1); - _txPool.GetPendingTransactionsBySender().Keys.Count.Should().Be(txPoolConfig.Size - 1); - - const int nonceGap = 100; - // send 1 expensive nonce-gap tx from sender X - PrivateKey privateKeyOfAttacker = TestItem.PrivateKeys[txPoolConfig.Size]; - Transaction nonceGapTx = Build.A.Transaction - .WithNonce(nonceGap) - .WithGasPrice(1000) - .SignedAndResolved(_ethereumEcdsa, privateKeyOfAttacker).TestObject; - - EnsureSenderBalance(privateKeyOfAttacker.Address, UInt256.MaxValue); - _txPool.SubmitTx(nonceGapTx, TxHandlingOptions.PersistentBroadcast).Should().Be(AcceptTxResult.Accepted); - - _txPool.GetPendingTransactionsCount().Should().Be(txPoolConfig.Size); - _txPool.GetPendingTransactionsBySender().Keys.Count.Should().Be(txPoolConfig.Size); - - // send (size - 1) expensive txs from sender X with consecutive nonces - for (int i = 0; i < txPoolConfig.Size - 1; i++) - { - Transaction tx = Build.A.Transaction - .WithNonce((UInt256)(i + 1 + nonceGap)) - .WithGasPrice(1000) - .SignedAndResolved(_ethereumEcdsa, privateKeyOfAttacker).TestObject; - - _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast).Should().Be(AcceptTxResult.FeeTooLowToCompete); - - // newly coming txs should evict themselves - _txPool.GetPendingTransactionsBySender().Keys.Count.Should().Be(txPoolConfig.Size); - } - - _txPool.GetPendingTransactionsCount().Should().Be(txPoolConfig.Size); - } - [TestCase(9, false)] [TestCase(11, true)] public void Should_not_add_underpaid_tx_even_if_lower_nonces_are_expensive(int gasPrice, bool expectedResult) @@ -1649,22 +1593,6 @@ public void Should_not_add_underpaid_tx_even_if_lower_nonces_are_expensive(int g result.Should().Be(expectedResult ? AcceptTxResult.Accepted : AcceptTxResult.FeeTooLowToCompete); } - [TestCase(0, 97)] - [TestCase(1, 131320)] - [TestCase(2, 262530)] - [TestCase(3, 393737)] - [TestCase(4, 524944)] - [TestCase(5, 656152)] - [TestCase(6, 787361)] - public void should_calculate_size_of_blob_tx_correctly(int numberOfBlobs, int expectedLength) - { - Transaction blobTx = Build.A.Transaction - .WithShardBlobTxTypeAndFields(numberOfBlobs) - .SignedAndResolved() - .TestObject; - blobTx.GetLength().Should().Be(expectedLength); - } - private IDictionary GetPeers(int limit = 100) { var peers = new Dictionary(); @@ -1686,7 +1614,7 @@ private TxPool CreatePool( IIncomingTxFilter incomingTxFilter = null, bool thereIsPriorityContract = false) { - specProvider ??= MainnetSpecProvider.Instance; + specProvider ??= RopstenSpecProvider.Instance; ITransactionComparerProvider transactionComparerProvider = new TransactionComparerProvider(specProvider, _blockTree); @@ -1700,7 +1628,6 @@ private TxPool CreatePool( new TxValidator(_specProvider.ChainId), _logManager, transactionComparerProvider.GetDefaultComparer(), - ShouldGossip.Instance, incomingTxFilter, thereIsPriorityContract); } diff --git a/src/Nethermind/Nethermind.TxPool/Comparison/ByHashTxComparer.cs b/src/Nethermind/Nethermind.TxPool/Comparison/ByHashTxComparer.cs index f972b8f813b..c7ef35ed43f 100644 --- a/src/Nethermind/Nethermind.TxPool/Comparison/ByHashTxComparer.cs +++ b/src/Nethermind/Nethermind.TxPool/Comparison/ByHashTxComparer.cs @@ -15,16 +15,16 @@ public class ByHashTxComparer : IComparer, IEqualityComparer Compare(x, y) == TxComparisonResult.NotDecided; + public bool Equals(Transaction? x, Transaction? y) => Compare(x, y) == 0; public int GetHashCode(Transaction obj) => obj.Hash?.GetHashCode() ?? 0; } diff --git a/src/Nethermind/Nethermind.TxPool/Comparison/CompareReplacedTxByFee.cs b/src/Nethermind/Nethermind.TxPool/Comparison/CompareReplacedTxByFee.cs index f44bcf92462..1982ac4574e 100644 --- a/src/Nethermind/Nethermind.TxPool/Comparison/CompareReplacedTxByFee.cs +++ b/src/Nethermind/Nethermind.TxPool/Comparison/CompareReplacedTxByFee.cs @@ -20,38 +20,34 @@ private CompareReplacedTxByFee() { } // It is required to avoid acceptance and propagation of transaction with almost the same fee as replaced one. private const int PartOfFeeRequiredToIncrease = 10; - public int Compare(Transaction? newTx, Transaction? oldTx) + public int Compare(Transaction? x, Transaction? y) { - if (ReferenceEquals(newTx, oldTx)) return TxComparisonResult.NotDecided; - if (ReferenceEquals(null, oldTx)) return TxComparisonResult.KeepOld; - if (ReferenceEquals(null, newTx)) return TxComparisonResult.TakeNew; + if (ReferenceEquals(x, y)) return 0; + if (ReferenceEquals(null, y)) return 1; + if (ReferenceEquals(null, x)) return -1; // always allow replacement of zero fee txs (in legacy txs MaxFeePerGas equals GasPrice) - if (oldTx.MaxFeePerGas.IsZero) return TxComparisonResult.TakeNew; + if (y.MaxFeePerGas.IsZero) return -1; - if (!newTx.Supports1559 && !oldTx.Supports1559) + if (!x.Supports1559 && !y.Supports1559) { - oldTx.GasPrice.Divide(PartOfFeeRequiredToIncrease, out UInt256 bumpGasPrice); - int gasPriceResult = (oldTx.GasPrice + bumpGasPrice).CompareTo(newTx.GasPrice); - // return TakeNew if fee bump is exactly by PartOfFeeRequiredToIncrease - // never return NotDecided - it's allowed or not - return gasPriceResult != 0 ? gasPriceResult : bumpGasPrice > 0 - ? TxComparisonResult.TakeNew - : TxComparisonResult.KeepOld; + y.GasPrice.Divide(PartOfFeeRequiredToIncrease, out UInt256 bumpGasPrice); + int gasPriceResult = (y.GasPrice + bumpGasPrice).CompareTo(x.GasPrice); + // return -1 (replacement accepted) if fee bump is exactly by PartOfFeeRequiredToIncrease + // never return 0 - it's allowed or not + return gasPriceResult != 0 ? gasPriceResult : bumpGasPrice > 0 ? -1 : 1; } /* MaxFeePerGas for legacy will be GasPrice and MaxPriorityFeePerGas will be GasPrice too so we can compare legacy txs without any problems */ - oldTx.MaxFeePerGas.Divide(PartOfFeeRequiredToIncrease, out UInt256 bumpMaxFeePerGas); - if (oldTx.MaxFeePerGas + bumpMaxFeePerGas > newTx.MaxFeePerGas) return TxComparisonResult.KeepOld; - - oldTx.MaxPriorityFeePerGas.Divide(PartOfFeeRequiredToIncrease, out UInt256 bumpMaxPriorityFeePerGas); - int result = (oldTx.MaxPriorityFeePerGas + bumpMaxPriorityFeePerGas).CompareTo(newTx.MaxPriorityFeePerGas); - // return TakeNew if fee bump is exactly by PartOfFeeRequiredToIncrease - // never return NotDecided - it's allowed or not - return result != 0 ? result : (bumpMaxFeePerGas > 0 && bumpMaxPriorityFeePerGas > 0) - ? TxComparisonResult.TakeNew - : TxComparisonResult.KeepOld; + y.MaxFeePerGas.Divide(PartOfFeeRequiredToIncrease, out UInt256 bumpMaxFeePerGas); + if (y.MaxFeePerGas + bumpMaxFeePerGas > x.MaxFeePerGas) return 1; + + y.MaxPriorityFeePerGas.Divide(PartOfFeeRequiredToIncrease, out UInt256 bumpMaxPriorityFeePerGas); + int result = (y.MaxPriorityFeePerGas + bumpMaxPriorityFeePerGas).CompareTo(x.MaxPriorityFeePerGas); + // return -1 (replacement accepted) if fee bump is exactly by PartOfFeeRequiredToIncrease + // never return 0 - it's allowed or not + return result != 0 ? result : (bumpMaxFeePerGas > 0 && bumpMaxPriorityFeePerGas > 0) ? -1 : 1; } } diff --git a/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByGasLimit.cs b/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByGasLimit.cs index 5d06e4dde03..9d8a3949546 100644 --- a/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByGasLimit.cs +++ b/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByGasLimit.cs @@ -15,14 +15,14 @@ public class CompareTxByGasLimit : IComparer private CompareTxByGasLimit() { } - public int Compare(Transaction? newTx, Transaction? oldTx) + public int Compare(Transaction? x, Transaction? y) { - if (ReferenceEquals(newTx, oldTx)) return TxComparisonResult.NotDecided; - if (ReferenceEquals(null, oldTx)) return TxComparisonResult.KeepOld; - if (ReferenceEquals(null, newTx)) return TxComparisonResult.TakeNew; + if (ReferenceEquals(x, y)) return 0; + if (ReferenceEquals(null, y)) return 1; + if (ReferenceEquals(null, x)) return -1; // then by gas limit ascending - return newTx.GasLimit.CompareTo(oldTx.GasLimit); + return x.GasLimit.CompareTo(y.GasLimit); } } } diff --git a/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByNonce.cs b/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByNonce.cs index fd2b7228df5..e2785b450a6 100644 --- a/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByNonce.cs +++ b/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByNonce.cs @@ -15,14 +15,14 @@ public class CompareTxByNonce : IComparer private CompareTxByNonce() { } - public int Compare(Transaction? newTx, Transaction? oldTx) + public int Compare(Transaction? x, Transaction? y) { - if (ReferenceEquals(newTx, oldTx)) return TxComparisonResult.NotDecided; - if (ReferenceEquals(null, oldTx)) return TxComparisonResult.KeepOld; - if (ReferenceEquals(null, newTx)) return TxComparisonResult.TakeNew; + if (ReferenceEquals(x, y)) return 0; + if (ReferenceEquals(null, y)) return 1; + if (ReferenceEquals(null, x)) return -1; // compare by nonce ascending - return newTx.Nonce.CompareTo(oldTx.Nonce); + return x.Nonce.CompareTo(y.Nonce); } } } diff --git a/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByPoolIndex.cs b/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByPoolIndex.cs index d9874d327e6..313e85c73ec 100644 --- a/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByPoolIndex.cs +++ b/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByPoolIndex.cs @@ -15,13 +15,13 @@ public class CompareTxByPoolIndex : IComparer private CompareTxByPoolIndex() { } - public int Compare(Transaction? newTx, Transaction? oldTx) + public int Compare(Transaction? x, Transaction? y) { - if (ReferenceEquals(newTx, oldTx)) return TxComparisonResult.NotDecided; - if (ReferenceEquals(null, oldTx)) return TxComparisonResult.KeepOld; - if (ReferenceEquals(null, newTx)) return TxComparisonResult.TakeNew; + if (ReferenceEquals(x, y)) return 0; + if (ReferenceEquals(null, y)) return 1; + if (ReferenceEquals(null, x)) return -1; - return newTx.PoolIndex.CompareTo(oldTx.PoolIndex); + return x.PoolIndex.CompareTo(y.PoolIndex); } } } diff --git a/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByTimestamp.cs b/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByTimestamp.cs index 12cd4ae309a..9ba9166398c 100644 --- a/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByTimestamp.cs +++ b/src/Nethermind/Nethermind.TxPool/Comparison/CompareTxByTimestamp.cs @@ -15,13 +15,13 @@ public class CompareTxByTimestamp : IComparer private CompareTxByTimestamp() { } - public int Compare(Transaction? newTx, Transaction? oldTx) + public int Compare(Transaction? x, Transaction? y) { - if (ReferenceEquals(newTx, oldTx)) return TxComparisonResult.NotDecided; - if (ReferenceEquals(null, oldTx)) return TxComparisonResult.KeepOld; - if (ReferenceEquals(null, newTx)) return TxComparisonResult.TakeNew; + if (ReferenceEquals(x, y)) return 0; + if (ReferenceEquals(null, y)) return 1; + if (ReferenceEquals(null, x)) return -1; - return newTx.Timestamp.CompareTo(oldTx.Timestamp); + return x.Timestamp.CompareTo(y.Timestamp); } } } diff --git a/src/Nethermind/Nethermind.TxPool/Comparison/CompetingTransactionEqualityComparer.cs b/src/Nethermind/Nethermind.TxPool/Comparison/CompetingTransactionEqualityComparer.cs index 954418e802a..5f9c5289907 100644 --- a/src/Nethermind/Nethermind.TxPool/Comparison/CompetingTransactionEqualityComparer.cs +++ b/src/Nethermind/Nethermind.TxPool/Comparison/CompetingTransactionEqualityComparer.cs @@ -9,7 +9,7 @@ namespace Nethermind.TxPool.Comparison { /// /// Comparer to check if two pending s compete with each other. - /// s compete with each other if they have same and . In that case only one transaction can go into chain. + /// s compete with each other if they have same and . In that case only one transaction can go into chain. /// public class CompetingTransactionEqualityComparer : IEqualityComparer { @@ -17,8 +17,8 @@ public class CompetingTransactionEqualityComparer : IEqualityComparer - ReferenceEquals(newTx, oldTx) || !ReferenceEquals(newTx, null) && !ReferenceEquals(oldTx, null) && newTx.SenderAddress == oldTx.SenderAddress && newTx.Nonce == oldTx.Nonce; + public bool Equals(Transaction? x, Transaction? y) => + ReferenceEquals(x, y) || !ReferenceEquals(x, null) && !ReferenceEquals(y, null) && x.SenderAddress == y.SenderAddress && x.Nonce == y.Nonce; public int GetHashCode(Transaction? obj) => HashCode.Combine(obj?.SenderAddress, obj?.Nonce); } diff --git a/src/Nethermind/Nethermind.TxPool/Comparison/TxComparisonResult.cs b/src/Nethermind/Nethermind.TxPool/Comparison/TxComparisonResult.cs deleted file mode 100644 index 84896e596fa..00000000000 --- a/src/Nethermind/Nethermind.TxPool/Comparison/TxComparisonResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.TxPool.Comparison; - -public readonly struct TxComparisonResult -{ - public const int NotDecided = 0; - public const int KeepOld = 1; - public const int TakeNew = -1; -} diff --git a/src/Nethermind/Nethermind.TxPool/Filters/BalanceTooLowFilter.cs b/src/Nethermind/Nethermind.TxPool/Filters/BalanceTooLowFilter.cs index 1266c8c9af4..4d6806f3f67 100644 --- a/src/Nethermind/Nethermind.TxPool/Filters/BalanceTooLowFilter.cs +++ b/src/Nethermind/Nethermind.TxPool/Filters/BalanceTooLowFilter.cs @@ -46,7 +46,9 @@ public AcceptTxResult Accept(Transaction tx, TxFilteringState state, TxHandlingO if (otherTx.Nonce < tx.Nonce) { - overflow |= otherTx.IsOverflowWhenAddingTxCostToCumulative(cumulativeCost, out cumulativeCost); + overflow |= UInt256.MultiplyOverflow(otherTx.MaxFeePerGas, (UInt256)otherTx.GasLimit, out UInt256 maxTxCost); + overflow |= UInt256.AddOverflow(cumulativeCost, maxTxCost, out cumulativeCost); + overflow |= UInt256.AddOverflow(cumulativeCost, otherTx.Value, out cumulativeCost); } else { @@ -54,8 +56,9 @@ public AcceptTxResult Accept(Transaction tx, TxFilteringState state, TxHandlingO } } - overflow |= tx.IsOverflowWhenAddingTxCostToCumulative(cumulativeCost, out cumulativeCost); - + overflow |= UInt256.MultiplyOverflow(tx.MaxFeePerGas, (UInt256)tx.GasLimit, out UInt256 cost); + overflow |= UInt256.AddOverflow(cost, tx.Value, out cost); + overflow |= UInt256.AddOverflow(cost, cumulativeCost, out cumulativeCost); if (overflow) { if (_logger.IsTrace) diff --git a/src/Nethermind/Nethermind.TxPool/INonceManager.cs b/src/Nethermind/Nethermind.TxPool/INonceManager.cs index 4056ed54c48..3803e87e76a 100644 --- a/src/Nethermind/Nethermind.TxPool/INonceManager.cs +++ b/src/Nethermind/Nethermind.TxPool/INonceManager.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Core; using Nethermind.Int256; diff --git a/src/Nethermind/Nethermind.TxPool/ITxGossipPolicy.cs b/src/Nethermind/Nethermind.TxPool/ITxGossipPolicy.cs deleted file mode 100644 index 336747ce4b5..00000000000 --- a/src/Nethermind/Nethermind.TxPool/ITxGossipPolicy.cs +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Collections.Generic; -using System.Linq; -using Nethermind.Core; - -namespace Nethermind.TxPool; - -public interface ITxGossipPolicy -{ - bool ShouldListenToGossippedTransactions => true; - bool CanGossipTransactions => true; - bool ShouldGossipTransaction(Transaction tx) => true; -} - -public class CompositeTxGossipPolicy : ITxGossipPolicy -{ - public List Policies { get; } = new(); - public bool ShouldListenToGossippedTransactions => Policies.All(static p => p.ShouldListenToGossippedTransactions); - public bool CanGossipTransactions => Policies.All(static p => p.CanGossipTransactions); - public bool ShouldGossipTransaction(Transaction tx) => Policies.All(p => p.ShouldGossipTransaction(tx)); -} - -public class ShouldGossip : ITxGossipPolicy -{ - public static readonly ShouldGossip Instance = new(); -} diff --git a/src/Nethermind/Nethermind.TxPool/ITxPoolConfig.cs b/src/Nethermind/Nethermind.TxPool/ITxPoolConfig.cs index aec0917217c..e46f9bc79d4 100644 --- a/src/Nethermind/Nethermind.TxPool/ITxPoolConfig.cs +++ b/src/Nethermind/Nethermind.TxPool/ITxPoolConfig.cs @@ -7,7 +7,7 @@ namespace Nethermind.TxPool { public interface ITxPoolConfig : IConfig { - [ConfigItem(DefaultValue = "5", Description = "Defines average percent of tx hashes from persistent broadcast send to peer together with hashes of last added txs. Set this value to 100 if you want to broadcast all transactions.")] + [ConfigItem(DefaultValue = "5", Description = "Defines average percent of tx hashes from persistent broadcast send to peer together with hashes of last added txs.")] int PeerNotificationThreshold { get; set; } [ConfigItem(DefaultValue = "2048", Description = "Max number of transactions held in mempool (more transactions in mempool mean more memory used")] diff --git a/src/Nethermind/Nethermind.TxPool/ITxPoolInfoProvider.cs b/src/Nethermind/Nethermind.TxPool/ITxPoolInfoProvider.cs index 1b4321a6967..b358814560d 100644 --- a/src/Nethermind/Nethermind.TxPool/ITxPoolInfoProvider.cs +++ b/src/Nethermind/Nethermind.TxPool/ITxPoolInfoProvider.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using Nethermind.Core; + namespace Nethermind.TxPool { public interface ITxPoolInfoProvider diff --git a/src/Nethermind/Nethermind.TxPool/NetworkTransactionSizeCalculator.cs b/src/Nethermind/Nethermind.TxPool/NetworkTransactionSizeCalculator.cs deleted file mode 100644 index 42a8cf0e3b9..00000000000 --- a/src/Nethermind/Nethermind.TxPool/NetworkTransactionSizeCalculator.cs +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core; -using Nethermind.Serialization.Rlp; - -namespace Nethermind.TxPool; - -public class NetworkTransactionSizeCalculator : ITransactionSizeCalculator -{ - private readonly TxDecoder _txDecoder; - - public NetworkTransactionSizeCalculator(TxDecoder txDecoder) - { - _txDecoder = txDecoder; - } - - public int GetLength(Transaction tx) - { - return _txDecoder.GetLength(tx, RlpBehaviors.InMempoolForm | RlpBehaviors.SkipTypedWrapping); - } -} diff --git a/src/Nethermind/Nethermind.TxPool/NonceLocker.cs b/src/Nethermind/Nethermind.TxPool/NonceLocker.cs index 391c8f81f81..f97139295cf 100644 --- a/src/Nethermind/Nethermind.TxPool/NonceLocker.cs +++ b/src/Nethermind/Nethermind.TxPool/NonceLocker.cs @@ -3,6 +3,7 @@ using System; using System.Threading; +using Nethermind.Int256; namespace Nethermind.TxPool; diff --git a/src/Nethermind/Nethermind.TxPool/NonceManager.cs b/src/Nethermind/Nethermind.TxPool/NonceManager.cs index 180edbe9336..709f2a8f605 100644 --- a/src/Nethermind/Nethermind.TxPool/NonceManager.cs +++ b/src/Nethermind/Nethermind.TxPool/NonceManager.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; diff --git a/src/Nethermind/Nethermind.TxPool/TransactionExtensions.cs b/src/Nethermind/Nethermind.TxPool/TransactionExtensions.cs index b6888c71d0e..2c1ee5cfbcf 100644 --- a/src/Nethermind/Nethermind.TxPool/TransactionExtensions.cs +++ b/src/Nethermind/Nethermind.TxPool/TransactionExtensions.cs @@ -13,8 +13,8 @@ namespace Nethermind.TxPool { public static class TransactionExtensions { - private static readonly long MaxSizeOfTxForBroadcast = 4.KiB(); //4KB, as in Geth https://github.com/ethereum/go-ethereum/pull/27618 - private static readonly ITransactionSizeCalculator _transactionSizeCalculator = new NetworkTransactionSizeCalculator(new TxDecoder()); + private static readonly long MaxSizeOfTxForBroadcast = 128.KiB(); //128KB, as proposed in https://eips.ethereum.org/EIPS/eip-5793 + private static readonly ITransactionSizeCalculator _transactionSizeCalculator = new TxDecoder(); public static int GetLength(this Transaction tx) { @@ -62,19 +62,5 @@ internal static UInt256 CalculateAffordableGasPrice(this Transaction tx, bool ei return balance <= tx.Value ? default : tx.GasPrice; } - - internal static bool CheckForNotEnoughBalance(this Transaction tx, UInt256 currentCost, UInt256 balance, out UInt256 cumulativeCost) - => tx.IsOverflowWhenAddingTxCostToCumulative(currentCost, out cumulativeCost) || balance < cumulativeCost; - - internal static bool IsOverflowWhenAddingTxCostToCumulative(this Transaction tx, UInt256 currentCost, out UInt256 cumulativeCost) - { - bool overflow = false; - - overflow |= UInt256.MultiplyOverflow(tx.MaxFeePerGas, (UInt256)tx.GasLimit, out UInt256 maxTxCost); - overflow |= UInt256.AddOverflow(currentCost, maxTxCost, out cumulativeCost); - overflow |= UInt256.AddOverflow(cumulativeCost, tx.Value, out cumulativeCost); - - return overflow; - } } } diff --git a/src/Nethermind/Nethermind.TxPool/TxBroadcaster.cs b/src/Nethermind/Nethermind.TxPool/TxBroadcaster.cs index 7702f0e4ed9..469fa15170a 100644 --- a/src/Nethermind/Nethermind.TxPool/TxBroadcaster.cs +++ b/src/Nethermind/Nethermind.TxPool/TxBroadcaster.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using Nethermind.Core; @@ -24,7 +23,17 @@ internal class TxBroadcaster : IDisposable { private readonly ITxPoolConfig _txPoolConfig; private readonly IChainHeadInfoProvider _headInfo; - private readonly ITxGossipPolicy _txGossipPolicy; + + /// + /// Notification threshold randomizer seed + /// + private static int _seed = Environment.TickCount; + + /// + /// Random number generator for peer notification threshold - no need to be securely random. + /// + private static readonly ThreadLocal Random = + new(() => new Random(Interlocked.Increment(ref _seed))); /// /// Timer for rebroadcasting pending own transactions. @@ -64,12 +73,10 @@ public TxBroadcaster(IComparer comparer, ITimerFactory timerFactory, ITxPoolConfig txPoolConfig, IChainHeadInfoProvider chainHeadInfoProvider, - ILogManager? logManager, - ITxGossipPolicy? transactionsGossipPolicy = null) + ILogManager? logManager) { _txPoolConfig = txPoolConfig; _headInfo = chainHeadInfoProvider; - _txGossipPolicy = transactionsGossipPolicy ?? ShouldGossip.Instance; _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); _persistentTxs = new TxDistinctSortedPool(MemoryAllowance.MemPoolSize, comparer, logManager); _accumulatedTemporaryTxs = new ResettableList(512, 4); @@ -99,9 +106,7 @@ private void StartBroadcast(Transaction tx) { NotifyPeersAboutLocalTx(tx); if (tx.Hash is not null) - { _persistentTxs.TryInsert(tx.Hash, tx); - } } private void BroadcastOnce(Transaction tx) @@ -178,12 +183,7 @@ public void BroadcastPersistentTxs() List? persistentTxsToSend = null; List? persistentHashesToSend = null; - bool broadcastAllTxs = _txPoolConfig.PeerNotificationThreshold == 100; - IEnumerable txsToPickFrom = broadcastAllTxs - ? _persistentTxs.GetSnapshot() - : _persistentTxs.GetFirsts(); - - foreach (Transaction tx in txsToPickFrom) + foreach (Transaction tx in _persistentTxs.GetFirsts()) { if (numberOfPersistentTxsToBroadcast > 0) { @@ -259,25 +259,19 @@ void NotifyPeers() private void Notify(ITxPoolPeer peer, IEnumerable txs, bool sendFullTx) { - if (_txGossipPolicy.CanGossipTransactions) + try { - try - { - - peer.SendNewTransactions(txs.Where(t => _txGossipPolicy.ShouldGossipTransaction(t)), sendFullTx); - if (_logger.IsTrace) _logger.Trace($"Notified {peer} about transactions."); - } - catch (Exception e) - { - if (_logger.IsError) _logger.Error($"Failed to notify {peer} about transactions.", e); - } + peer.SendNewTransactions(txs, sendFullTx); + if (_logger.IsTrace) _logger.Trace($"Notified {peer} about transactions."); + } + catch (Exception e) + { + if (_logger.IsError) _logger.Error($"Failed to notify {peer} about transactions.", e); } } private void NotifyPeersAboutLocalTx(Transaction tx) { - if (!_txGossipPolicy.CanGossipTransactions || !_txGossipPolicy.ShouldGossipTransaction(tx)) return; - if (_logger.IsDebug) _logger.Debug($"Broadcasting new local transaction {tx.Hash} to all peers"); foreach ((_, ITxPoolPeer peer) in _peers) diff --git a/src/Nethermind/Nethermind.TxPool/TxPool.cs b/src/Nethermind/Nethermind.TxPool/TxPool.cs index 56f7012c876..65a2713c0fe 100644 --- a/src/Nethermind/Nethermind.TxPool/TxPool.cs +++ b/src/Nethermind/Nethermind.TxPool/TxPool.cs @@ -65,23 +65,22 @@ public class TxPool : ITxPool, IDisposable /// This class stores all known pending transactions that can be used for block production /// (by miners or validators) or simply informing other nodes about known pending transactions (broadcasting). /// + /// Tx storage used to reject known transactions. /// Used to recover sender addresses from transaction signatures. /// /// /// /// /// - /// /// /// - /// Tx storage used to reject known transactions. - public TxPool(IEthereumEcdsa ecdsa, + public TxPool( + IEthereumEcdsa ecdsa, IChainHeadInfoProvider chainHeadInfoProvider, ITxPoolConfig txPoolConfig, ITxValidator validator, ILogManager? logManager, IComparer comparer, - ITxGossipPolicy? transactionsGossipPolicy = null, IIncomingTxFilter? incomingTxFilter = null, bool thereIsPriorityContract = false) { @@ -95,7 +94,7 @@ public TxPool(IEthereumEcdsa ecdsa, AddNodeInfoEntryForTxPool(); _transactions = new TxDistinctSortedPool(MemoryAllowance.MemPoolSize, comparer, logManager); - _broadcaster = new TxBroadcaster(comparer, TimerFactory.Default, txPoolConfig, chainHeadInfoProvider, logManager, transactionsGossipPolicy); + _broadcaster = new TxBroadcaster(comparer, TimerFactory.Default, txPoolConfig, chainHeadInfoProvider, logManager); _headInfo.HeadChanged += OnHeadChange; @@ -155,6 +154,7 @@ public Transaction[] GetPendingTransactionsBySender(Address address) => private void OnHeadChange(object? sender, BlockReplacementEventArgs e) { + // TODO: I think this is dangerous if many blocks are processed one after another try { // Clear snapshot @@ -414,7 +414,6 @@ private AcceptTxResult AddCore(Transaction tx, TxFilteringState state, bool isPe { UInt256? previousTxBottleneck = null; int i = 0; - UInt256 cumulativeCost = 0; foreach (Transaction tx in transactions) { @@ -435,13 +434,6 @@ private AcceptTxResult AddCore(Transaction tx, TxFilteringState state, bool isPe UInt256 effectiveGasPrice = tx.CalculateEffectiveGasPrice(_specProvider.GetCurrentHeadSpec().IsEip1559Enabled, _headInfo.CurrentBaseFee); - - if (tx.CheckForNotEnoughBalance(cumulativeCost, balance, out cumulativeCost)) - { - // balance too low, remove tx from the pool - _broadcaster.StopBroadcast(tx.Hash!); - yield return (tx, null); - } gasBottleneck = UInt256.Min(effectiveGasPrice, previousTxBottleneck ?? 0); } @@ -628,7 +620,7 @@ public void Dispose() private static void AddNodeInfoEntryForTxPool() { ThisNodeInfo.AddInfo("Mem est tx :", - $"{(LruCache.CalculateMemorySize(32, MemoryAllowance.TxHashCacheSize) + LruCache.CalculateMemorySize(4096, MemoryAllowance.MemPoolSize)) / 1000 / 1000} MB" + $"{(LruCache.CalculateMemorySize(32, MemoryAllowance.TxHashCacheSize) + LruCache.CalculateMemorySize(4096, MemoryAllowance.MemPoolSize)) / 1000 / 1000}MB" .PadLeft(8)); } diff --git a/src/Nethermind/Nethermind.Wallet/NodeKeyManager.cs b/src/Nethermind/Nethermind.Wallet/NodeKeyManager.cs index 69e671dfb5c..ae7f962094d 100644 --- a/src/Nethermind/Nethermind.Wallet/NodeKeyManager.cs +++ b/src/Nethermind/Nethermind.Wallet/NodeKeyManager.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.IO; using System.IO.Abstractions; using System.Security; using Nethermind.Core; diff --git a/src/tests b/src/tests index 661356317ac..be07adc7436 160000 --- a/src/tests +++ b/src/tests @@ -1 +1 @@ -Subproject commit 661356317ac6df52208d54187e692472a25a01f8 +Subproject commit be07adc743652812dff63f424366c78db99e3420 diff --git a/tools/Nethermind.Tools.Kute/Application.cs b/tools/Nethermind.Tools.Kute/Application.cs deleted file mode 100644 index d5d51c8ce4f..00000000000 --- a/tools/Nethermind.Tools.Kute/Application.cs +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Tools.Kute.Extensions; -using Nethermind.Tools.Kute.MessageProvider; -using Nethermind.Tools.Kute.JsonRpcMethodFilter; -using Nethermind.Tools.Kute.JsonRpcSubmitter; -using Nethermind.Tools.Kute.MetricsConsumer; -using Nethermind.Tools.Kute.ProgressReporter; - -namespace Nethermind.Tools.Kute; - -class Application -{ - private readonly Metrics _metrics = new(); - - private readonly IMessageProvider _msgProvider; - private readonly IJsonRpcSubmitter _submitter; - private readonly IProgressReporter _progressReporter; - private readonly IMetricsConsumer _metricsConsumer; - private readonly IJsonRpcMethodFilter _methodFilter; - - public Application( - IMessageProvider msgProvider, - IJsonRpcSubmitter submitter, - IProgressReporter progressReporter, - IMetricsConsumer metricsConsumer, - IJsonRpcMethodFilter methodFilter - ) - { - _msgProvider = msgProvider; - _submitter = submitter; - _progressReporter = progressReporter; - _metricsConsumer = metricsConsumer; - _methodFilter = methodFilter; - } - - public async Task Run() - { - _progressReporter.ReportStart(); - - using (_metrics.TimeTotal()) - { - await foreach (var (jsonRpc, n) in _msgProvider.Messages.Indexed(startingFrom: 1)) - { - _metrics.TickMessages(); - - switch (jsonRpc) - { - case null: - _metrics.TickFailed(); - - break; - - case JsonRpc.BatchJsonRpc batch: - using (_metrics.TimeBatch()) - { - await _submitter.Submit(batch); - } - - break; - - case JsonRpc.SingleJsonRpc single: - if (single.IsResponse) - { - _metrics.TickResponses(); - continue; - } - - if (single.MethodName is null) - { - _metrics.TickFailed(); - continue; - } - - if (_methodFilter.ShouldIgnore(single.MethodName)) - { - _metrics.TickIgnoredRequests(); - continue; - } - - using (_metrics.TimeMethod(single.MethodName)) - { - await _submitter.Submit(single); - } - - break; - - default: - throw new ArgumentOutOfRangeException(nameof(jsonRpc)); - } - - _progressReporter.ReportProgress(n); - } - } - - _progressReporter.ReportComplete(); - await _metricsConsumer.ConsumeMetrics(_metrics); - } -} diff --git a/tools/Nethermind.Tools.Kute/Auth/IAuth.cs b/tools/Nethermind.Tools.Kute/Auth/IAuth.cs deleted file mode 100644 index 08ce8908da9..00000000000 --- a/tools/Nethermind.Tools.Kute/Auth/IAuth.cs +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Tools.Kute.Auth; - -interface IAuth -{ - string AuthToken { get; } -} diff --git a/tools/Nethermind.Tools.Kute/Auth/JwtAuth.cs b/tools/Nethermind.Tools.Kute/Auth/JwtAuth.cs deleted file mode 100644 index feb05054faa..00000000000 --- a/tools/Nethermind.Tools.Kute/Auth/JwtAuth.cs +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.IdentityModel.Tokens.Jwt; -using System.Security.Claims; -using Microsoft.IdentityModel.Tokens; -using Nethermind.Tools.Kute.SecretProvider; -using Nethermind.Tools.Kute.SystemClock; - -namespace Nethermind.Tools.Kute.Auth; - -class JwtAuth : IAuth -{ - private readonly byte[] _secret; - private readonly ISystemClock _clock; - - public string AuthToken - { - get => GenerateAuthToken(); - } - - public JwtAuth(ISystemClock clock, ISecretProvider secretProvider) - { - _clock = clock; - - var hexSecret = secretProvider.Secret; - _secret = Enumerable.Range(0, hexSecret.Length) - .Where(x => x % 2 == 0) - .Select(x => Convert.ToByte(hexSecret.Substring(x, 2), 16)) - .ToArray(); - } - - private string GenerateAuthToken() - { - var signingKey = new SymmetricSecurityKey(_secret); - var credentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); - var claims = new[] { new Claim("iat", _clock.UtcNow.ToUnixTimeSeconds().ToString()) }; - var token = new JwtSecurityToken(claims: claims, signingCredentials: credentials); - var handler = new JwtSecurityTokenHandler(); - - return handler.WriteToken(token); - } -} diff --git a/tools/Nethermind.Tools.Kute/Auth/TtlAuth.cs b/tools/Nethermind.Tools.Kute/Auth/TtlAuth.cs deleted file mode 100644 index a6099879206..00000000000 --- a/tools/Nethermind.Tools.Kute/Auth/TtlAuth.cs +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Tools.Kute.SystemClock; - -namespace Nethermind.Tools.Kute.Auth; - -class TtlAuth : IAuth -{ - private readonly IAuth _auth; - private readonly ISystemClock _clock; - private readonly int _ttl; - - private LastAuth? _lastAuth; - - public TtlAuth(IAuth auth, ISystemClock clock, int ttl) - { - _auth = auth; - _clock = clock; - _ttl = ttl; - } - - public string AuthToken - { - get - { - long currentTime = _clock.UtcNow.ToUnixTimeSeconds(); - if (_lastAuth is null || Math.Abs(_lastAuth.GeneratedAt - currentTime) >= _ttl) - { - _lastAuth = new(currentTime, _auth.AuthToken); - } - - return _lastAuth.Token; - } - } - - private record LastAuth(long GeneratedAt, string Token); -} diff --git a/tools/Nethermind.Tools.Kute/Config.cs b/tools/Nethermind.Tools.Kute/Config.cs deleted file mode 100644 index 87c0876ac21..00000000000 --- a/tools/Nethermind.Tools.Kute/Config.cs +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using CommandLine; -using Nethermind.Tools.Kute.MetricsConsumer; - -namespace Nethermind.Tools.Kute; - -public class Config -{ - [Option( - shortName: 'i', - longName: "input", - Required = true, - HelpText = "Path to a Folder or a File containing JSON RPC messages" - )] - public string MessagesFilePath { get; } - - [Option( - shortName: 'a', - longName: "address", - Required = false, - Default = "http://localhost:8551", - HelpText = "Address where to send JSON RPC calls" - )] - public string HostAddress { get; } - - [Option( - shortName: 's', - longName: "secret", - Required = true, - HelpText = "Path to file with hex encoded secret for JWT authentication" - )] - public string JwtSecretFilePath { get; } - - [Option( - shortName: 't', - longName: "ttl", - Required = false, - Default = 60, - HelpText = "Authentication time to live (ttl) in seconds" - )] - public int AuthTtl { get; } - - [Option( - shortName: 'd', - longName: "dry", - Required = false, - Default = false, - HelpText = "Only log into console" - )] - public bool DryRun { get; } - - [Option( - shortName: 'p', - longName: "progress", - Required = false, - Default = false, - HelpText = "Show progress" - )] - public bool ShowProgress { get; } - - [Option( - shortName: 'o', - longName: "output", - Required = false, - Default = MetricsOutputFormatter.Report, - HelpText = "Strategy to report metrics" - )] - public MetricsOutputFormatter MetricsOutputFormatter { get; } - - [Option( - shortName: 'f', - longName: "filters", - Separator = ',', - Required = false, - Default = new string[] { }, - HelpText = "A comma separated List of regexes of methods to be executed" - )] - public IEnumerable MethodFilters { get; } - - public Config( - string messagesFilePath, - string hostAddress, - string jwtSecretFilePath, - int authTtl, - bool dryRun, - bool showProgress, - MetricsOutputFormatter metricsOutputFormatter, - IEnumerable methodFilters - ) - { - MessagesFilePath = messagesFilePath; - HostAddress = hostAddress; - JwtSecretFilePath = jwtSecretFilePath; - AuthTtl = authTtl; - DryRun = dryRun; - ShowProgress = showProgress; - MetricsOutputFormatter = metricsOutputFormatter; - MethodFilters = methodFilters; - ShowProgress = showProgress; - } -} diff --git a/tools/Nethermind.Tools.Kute/Extensions/AsyncEnumerableExtensions.cs b/tools/Nethermind.Tools.Kute/Extensions/AsyncEnumerableExtensions.cs deleted file mode 100644 index b06b5fc327f..00000000000 --- a/tools/Nethermind.Tools.Kute/Extensions/AsyncEnumerableExtensions.cs +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Tools.Kute.Extensions; - -public static class AsyncEnumerableExtensions -{ - public static IAsyncEnumerable<(TSource, int)> Indexed(this IAsyncEnumerable source, int startingFrom = 0) - { - return source.Select((t, idx) => (t, startingFrom + idx)); - } -} diff --git a/tools/Nethermind.Tools.Kute/JsonRpc.cs b/tools/Nethermind.Tools.Kute/JsonRpc.cs deleted file mode 100644 index 438cdae9c3a..00000000000 --- a/tools/Nethermind.Tools.Kute/JsonRpc.cs +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Text.Json; - -namespace Nethermind.Tools.Kute; - -public abstract record JsonRpc -{ - private readonly JsonDocument _document; - - private JsonRpc(JsonDocument document) - { - _document = document; - } - - public string ToJsonString() => _document.RootElement.ToString(); - - public record BatchJsonRpc : JsonRpc - { - public BatchJsonRpc(JsonDocument document) : base(document) { } - - public override string ToString() => $"{nameof(BatchJsonRpc)} {ToJsonString()}"; - } - - public record SingleJsonRpc : JsonRpc - { - private readonly Lazy _isResponse; - private readonly Lazy _methodName; - - public SingleJsonRpc(JsonDocument document) : base(document) - { - _isResponse = new(() => - _document.RootElement.TryGetProperty("response", out _) - ); - _methodName = new(() => - { - if (_document.RootElement.TryGetProperty("method", out var jsonMethodField)) - { - return jsonMethodField.GetString(); - } - - return null; - }); - } - - public bool IsResponse { get => _isResponse.Value; } - public string? MethodName { get => _methodName.Value; } - - public override string ToString() => $"{nameof(SingleJsonRpc)} {ToJsonString()}"; - } -} diff --git a/tools/Nethermind.Tools.Kute/JsonRpcMethodFilter/ComposedJsonRpcMethodFilter.cs b/tools/Nethermind.Tools.Kute/JsonRpcMethodFilter/ComposedJsonRpcMethodFilter.cs deleted file mode 100644 index 9f5d4b0a8fb..00000000000 --- a/tools/Nethermind.Tools.Kute/JsonRpcMethodFilter/ComposedJsonRpcMethodFilter.cs +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Microsoft.IdentityModel.Tokens; - -namespace Nethermind.Tools.Kute.JsonRpcMethodFilter; - -class ComposedJsonRpcMethodFilter : IJsonRpcMethodFilter -{ - private readonly IEnumerable _filters; - - public ComposedJsonRpcMethodFilter(IEnumerable filters) - { - _filters = filters; - } - - public bool ShouldSubmit(string methodName) => - _filters.IsNullOrEmpty() || - _filters.Any(f => f.ShouldSubmit(methodName)); -} diff --git a/tools/Nethermind.Tools.Kute/JsonRpcMethodFilter/IJsonRpcMethodFilter.cs b/tools/Nethermind.Tools.Kute/JsonRpcMethodFilter/IJsonRpcMethodFilter.cs deleted file mode 100644 index 1c290649f0d..00000000000 --- a/tools/Nethermind.Tools.Kute/JsonRpcMethodFilter/IJsonRpcMethodFilter.cs +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Tools.Kute.JsonRpcMethodFilter; - -interface IJsonRpcMethodFilter -{ - bool ShouldSubmit(string methodName); - - bool ShouldIgnore(string methodName) => !ShouldSubmit(methodName); -} diff --git a/tools/Nethermind.Tools.Kute/JsonRpcMethodFilter/PatternJsonRpcMethodFilter.cs b/tools/Nethermind.Tools.Kute/JsonRpcMethodFilter/PatternJsonRpcMethodFilter.cs deleted file mode 100644 index 324301214a8..00000000000 --- a/tools/Nethermind.Tools.Kute/JsonRpcMethodFilter/PatternJsonRpcMethodFilter.cs +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Text.RegularExpressions; - -namespace Nethermind.Tools.Kute.JsonRpcMethodFilter; - -class PatternJsonRpcMethodFilter : IJsonRpcMethodFilter -{ - private readonly Regex _pattern; - - public PatternJsonRpcMethodFilter(string pattern) - { - _pattern = new Regex(pattern); - } - - public bool ShouldSubmit(string methodName) => _pattern.IsMatch(methodName); -} diff --git a/tools/Nethermind.Tools.Kute/JsonRpcSubmitter/HttpJsonRpcSubmitter.cs b/tools/Nethermind.Tools.Kute/JsonRpcSubmitter/HttpJsonRpcSubmitter.cs deleted file mode 100644 index 9fd1774ac3f..00000000000 --- a/tools/Nethermind.Tools.Kute/JsonRpcSubmitter/HttpJsonRpcSubmitter.cs +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Net; -using System.Net.Http.Headers; -using System.Net.Mime; -using System.Text; -using Nethermind.Tools.Kute.Auth; - -namespace Nethermind.Tools.Kute.JsonRpcSubmitter; - -class HttpJsonRpcSubmitter : IJsonRpcSubmitter -{ - private readonly Uri _uri; - private readonly HttpClient _httpClient; - private readonly IAuth _auth; - - public HttpJsonRpcSubmitter(HttpClient httpClient, IAuth auth, string hostAddress) - { - _httpClient = httpClient; - _auth = auth; - _uri = new Uri(hostAddress); - } - - public async Task Submit(JsonRpc rpc) - { - var request = new HttpRequestMessage(HttpMethod.Post, _uri) - { - Headers = { Authorization = new AuthenticationHeaderValue("Bearer", _auth.AuthToken) }, - Content = new StringContent(rpc.ToJsonString(), Encoding.UTF8, MediaTypeNames.Application.Json), - }; - var response = await _httpClient.SendAsync(request); - if (response.StatusCode != HttpStatusCode.OK) - { - throw new HttpRequestException($"Expected {HttpStatusCode.OK}, got {response.StatusCode}"); - } - } -} diff --git a/tools/Nethermind.Tools.Kute/JsonRpcSubmitter/IJsonRpcSubmitter.cs b/tools/Nethermind.Tools.Kute/JsonRpcSubmitter/IJsonRpcSubmitter.cs deleted file mode 100644 index bb9f5038829..00000000000 --- a/tools/Nethermind.Tools.Kute/JsonRpcSubmitter/IJsonRpcSubmitter.cs +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Tools.Kute.JsonRpcSubmitter; - -interface IJsonRpcSubmitter -{ - Task Submit(JsonRpc rpc); -} diff --git a/tools/Nethermind.Tools.Kute/JsonRpcSubmitter/NullJsonRpcSubmitter.cs b/tools/Nethermind.Tools.Kute/JsonRpcSubmitter/NullJsonRpcSubmitter.cs deleted file mode 100644 index d38cc4d410f..00000000000 --- a/tools/Nethermind.Tools.Kute/JsonRpcSubmitter/NullJsonRpcSubmitter.cs +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Tools.Kute.Auth; - -namespace Nethermind.Tools.Kute.JsonRpcSubmitter; - -class NullJsonRpcSubmitter : IJsonRpcSubmitter -{ - private readonly IAuth _auth; - - public NullJsonRpcSubmitter(IAuth auth) - { - _auth = auth; - } - - public Task Submit(JsonRpc rpc) - { - _ = _auth.AuthToken; - return Task.CompletedTask; - } -} diff --git a/tools/Nethermind.Tools.Kute/MessageProvider/FileMessageProvider.cs b/tools/Nethermind.Tools.Kute/MessageProvider/FileMessageProvider.cs deleted file mode 100644 index bba7c997f08..00000000000 --- a/tools/Nethermind.Tools.Kute/MessageProvider/FileMessageProvider.cs +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Tools.Kute.MessageProvider; - -public class FileMessageProvider : IMessageProvider -{ - private readonly string _filePath; - - public FileMessageProvider(string filePath) - { - _filePath = filePath; - } - - - public IAsyncEnumerable Messages - { - get - { - var pathInfo = new FileInfo(_filePath); - if (pathInfo.Attributes.HasFlag(FileAttributes.Directory)) - { - return Directory.GetFiles(_filePath) - .Select(filePath => new FileInfo(filePath)) - .OrderBy(info => info.LastWriteTime) - .ToAsyncEnumerable() - .SelectMany(info => File.ReadLinesAsync(info.FullName)); - } - - if (pathInfo.Attributes.HasFlag(FileAttributes.Normal)) - { - return File.ReadLinesAsync(_filePath); - } - - throw new ArgumentException("Path is neither a Folder or a File", nameof(_filePath)); - } - } -} diff --git a/tools/Nethermind.Tools.Kute/MessageProvider/IMessageProvider.cs b/tools/Nethermind.Tools.Kute/MessageProvider/IMessageProvider.cs deleted file mode 100644 index 7fbe4a21b88..00000000000 --- a/tools/Nethermind.Tools.Kute/MessageProvider/IMessageProvider.cs +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Tools.Kute.MessageProvider; - -public interface IMessageProvider -{ - IAsyncEnumerable Messages { get; } -} diff --git a/tools/Nethermind.Tools.Kute/MessageProvider/JsonRpcMessageProvider.cs b/tools/Nethermind.Tools.Kute/MessageProvider/JsonRpcMessageProvider.cs deleted file mode 100644 index 63da7637aeb..00000000000 --- a/tools/Nethermind.Tools.Kute/MessageProvider/JsonRpcMessageProvider.cs +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Text.Json; - -namespace Nethermind.Tools.Kute.MessageProvider; - -public class JsonRpcMessageProvider : IMessageProvider -{ - private readonly IMessageProvider _provider; - - - public JsonRpcMessageProvider(IMessageProvider provider) - { - _provider = provider; - } - - public IAsyncEnumerable Messages { get => MessagesImpl(); } - - private async IAsyncEnumerable MessagesImpl() - { - await foreach (var msg in _provider.Messages) - { - var jsonDoc = JsonSerializer.Deserialize(msg); - - yield return jsonDoc?.RootElement.ValueKind switch - { - JsonValueKind.Object => new JsonRpc.SingleJsonRpc(jsonDoc), - JsonValueKind.Array => new JsonRpc.BatchJsonRpc(jsonDoc), - _ => null - }; - } - } -} diff --git a/tools/Nethermind.Tools.Kute/Metrics.cs b/tools/Nethermind.Tools.Kute/Metrics.cs deleted file mode 100644 index f3038506d8b..00000000000 --- a/tools/Nethermind.Tools.Kute/Metrics.cs +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using App.Metrics; -using App.Metrics.Counter; -using App.Metrics.Timer; - -namespace Nethermind.Tools.Kute; - -public class Metrics -{ - private readonly IMetrics _metrics; - - private readonly TimerOptions _totalRunningTime = new() - { - Name = "Total Running Time", DurationUnit = TimeUnit.Milliseconds, - }; - private readonly CounterOptions _messages = new() - { - Name = "Messages", MeasurementUnit = Unit.Items, - }; - private readonly CounterOptions _failed = new() - { - Name = "Failed", MeasurementUnit = Unit.Items, - }; - private readonly CounterOptions _ignoredRequests = new() - { - Name = "Ignored Requests", MeasurementUnit = Unit.Items - }; - private readonly CounterOptions _responses = new() - { - Name = "Responses", MeasurementUnit = Unit.Items - }; - private readonly TimerOptions _batches = new() - { - Name = "Batches", DurationUnit = TimeUnit.Milliseconds - }; - private readonly IDictionary _processedRequests = new Dictionary(); - - public Metrics() - { - _metrics = new MetricsBuilder().Build(); - } - - public MetricsDataValueSource Snapshot => _metrics.Snapshot.Get(); - - public void TickMessages() => _metrics.Measure.Counter.Increment(_messages); - public void TickFailed() => _metrics.Measure.Counter.Increment(_failed); - public void TickIgnoredRequests() => _metrics.Measure.Counter.Increment(_ignoredRequests); - public void TickResponses() => _metrics.Measure.Counter.Increment(_responses); - - public TimerContext TimeTotal() => _metrics.Measure.Timer.Time(_totalRunningTime); - public TimerContext TimeBatch() => _metrics.Measure.Timer.Time(_batches); - public TimerContext TimeMethod(string methodName) - { - if (!_processedRequests.ContainsKey(methodName)) - { - _processedRequests[methodName] = new TimerOptions - { - Name = methodName, MeasurementUnit = Unit.Requests, DurationUnit = TimeUnit.Milliseconds, RateUnit = TimeUnit.Milliseconds - }; - } - return _metrics.Measure.Timer.Time(_processedRequests[methodName]); - } -} diff --git a/tools/Nethermind.Tools.Kute/MetricsConsumer/ConsoleMetricsConsumer.cs b/tools/Nethermind.Tools.Kute/MetricsConsumer/ConsoleMetricsConsumer.cs deleted file mode 100644 index 8ba52e996ad..00000000000 --- a/tools/Nethermind.Tools.Kute/MetricsConsumer/ConsoleMetricsConsumer.cs +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using App.Metrics.Formatters; - -namespace Nethermind.Tools.Kute.MetricsConsumer; - -public class ConsoleMetricsConsumer : IMetricsConsumer -{ - - private readonly IMetricsOutputFormatter _formatter; - - public ConsoleMetricsConsumer(IMetricsOutputFormatter formatter) - { - _formatter = formatter; - } - - public async Task ConsumeMetrics(Metrics metrics) - { - var snapshot = metrics.Snapshot; - using (var stream = Console.OpenStandardOutput()) - { - await _formatter.WriteAsync(stream, snapshot); - } - } -} diff --git a/tools/Nethermind.Tools.Kute/MetricsConsumer/IMetricsConsumer.cs b/tools/Nethermind.Tools.Kute/MetricsConsumer/IMetricsConsumer.cs deleted file mode 100644 index 3e5d0a78e48..00000000000 --- a/tools/Nethermind.Tools.Kute/MetricsConsumer/IMetricsConsumer.cs +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Tools.Kute.MetricsConsumer; - -public interface IMetricsConsumer -{ - Task ConsumeMetrics(Metrics metrics); -} - -public enum MetricsOutputFormatter -{ - Report, Json, -} diff --git a/tools/Nethermind.Tools.Kute/Nethermind.Tools.Kute.csproj b/tools/Nethermind.Tools.Kute/Nethermind.Tools.Kute.csproj deleted file mode 100644 index d9c201b6ea8..00000000000 --- a/tools/Nethermind.Tools.Kute/Nethermind.Tools.Kute.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - Exe - net7.0 - enable - enable - - - - - - - - - - - diff --git a/tools/Nethermind.Tools.Kute/Program.cs b/tools/Nethermind.Tools.Kute/Program.cs deleted file mode 100644 index 61f7f37b92f..00000000000 --- a/tools/Nethermind.Tools.Kute/Program.cs +++ /dev/null @@ -1,89 +0,0 @@ -using App.Metrics.Formatters; -using App.Metrics.Formatters.Ascii; -using App.Metrics.Formatters.Json; -using CommandLine; -using Microsoft.Extensions.DependencyInjection; -using Nethermind.Tools.Kute.Auth; -using Nethermind.Tools.Kute.JsonRpcMethodFilter; -using Nethermind.Tools.Kute.JsonRpcSubmitter; -using Nethermind.Tools.Kute.MessageProvider; -using Nethermind.Tools.Kute.MetricsConsumer; -using Nethermind.Tools.Kute.ProgressReporter; -using Nethermind.Tools.Kute.SecretProvider; -using Nethermind.Tools.Kute.SystemClock; - -namespace Nethermind.Tools.Kute; - -static class Program -{ - public static async Task Main(string[] args) - { - await Parser.Default.ParseArguments(args).WithParsedAsync(async config => - { - IServiceProvider serviceProvider = BuildServiceProvider(config); - Application app = serviceProvider.GetService()!; - - await app.Run(); - }); - } - - static IServiceProvider BuildServiceProvider(Config config) - { - IServiceCollection collection = new ServiceCollection(); - - collection.AddSingleton(); - collection.AddSingleton(); - collection.AddSingleton(); - collection.AddSingleton(new FileSecretProvider(config.JwtSecretFilePath)); - collection.AddSingleton(provider => - new TtlAuth( - new JwtAuth( - provider.GetRequiredService(), - provider.GetRequiredService() - ), - provider.GetRequiredService(), - config.AuthTtl - ) - ); - collection.AddSingleton>(new FileMessageProvider(config.MessagesFilePath)); - collection.AddSingleton, JsonRpcMessageProvider>(); - collection.AddSingleton( - new ComposedJsonRpcMethodFilter(config.MethodFilters.Select(pattern => - new PatternJsonRpcMethodFilter(pattern))) - ); - collection.AddSingleton(provider => - config.DryRun - ? new NullJsonRpcSubmitter(provider.GetRequiredService()) - : new HttpJsonRpcSubmitter( - provider.GetRequiredService(), - provider.GetRequiredService(), - config.HostAddress - )); - collection.AddSingleton(provider => - { - if (config.ShowProgress) - { - // TODO: - // Terrible, terrible hack since it forces a double enumeration: - // - A first one to count the number of messages. - // - A second one to actually process each message. - // We can reduce the cost by not parsing each message on the first enumeration - // At the same time, this optimization relies on implementation details. - var messagesProvider = provider.GetRequiredService>(); - var totalMessages = messagesProvider.Messages.ToEnumerable().Count(); - return new ConsoleProgressReporter(totalMessages); - } - - return new NullProgressReporter(); - }); - collection.AddSingleton(); - collection.AddSingleton(_ => config.MetricsOutputFormatter switch - { - MetricsOutputFormatter.Report => new MetricsTextOutputFormatter(), - MetricsOutputFormatter.Json => new MetricsJsonOutputFormatter(), - _ => throw new ArgumentOutOfRangeException(), - }); - - return collection.BuildServiceProvider(); - } -} diff --git a/tools/Nethermind.Tools.Kute/ProgressReporter/ConsoleProgressReporter.cs b/tools/Nethermind.Tools.Kute/ProgressReporter/ConsoleProgressReporter.cs deleted file mode 100644 index 7b2d4c24642..00000000000 --- a/tools/Nethermind.Tools.Kute/ProgressReporter/ConsoleProgressReporter.cs +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System.Text; - -namespace Nethermind.Tools.Kute.ProgressReporter; - -public class ConsoleProgressReporter : IProgressReporter -{ - private readonly string _suffix; - - private int _lastN; - - public ConsoleProgressReporter(int total) - { - _suffix = $"/{total}"; - } - - public void ReportStart() - { - Console.Write($"Progress: 0{_suffix}"); - } - - public void ReportProgress(int n) - { - var sb = new StringBuilder(); - - sb.Append('\b', _lastN.ToString().Length + _suffix.Length); - sb.Append(n); - sb.Append(_suffix); - - Console.Write(sb); - _lastN = n; - } - - public void ReportComplete() - { - Console.Write('\n'); - } -} diff --git a/tools/Nethermind.Tools.Kute/ProgressReporter/IProgressReporter.cs b/tools/Nethermind.Tools.Kute/ProgressReporter/IProgressReporter.cs deleted file mode 100644 index 017d33c4d6d..00000000000 --- a/tools/Nethermind.Tools.Kute/ProgressReporter/IProgressReporter.cs +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Tools.Kute.ProgressReporter; - -public interface IProgressReporter -{ - public void ReportStart(); - public void ReportProgress(int n); - public void ReportComplete(); -} diff --git a/tools/Nethermind.Tools.Kute/ProgressReporter/NullProgressReporter.cs b/tools/Nethermind.Tools.Kute/ProgressReporter/NullProgressReporter.cs deleted file mode 100644 index 27ad202f279..00000000000 --- a/tools/Nethermind.Tools.Kute/ProgressReporter/NullProgressReporter.cs +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Tools.Kute.ProgressReporter; - -public class NullProgressReporter : IProgressReporter -{ - - public void ReportStart() - { - } - public void ReportProgress(int n) - { - } - public void ReportComplete() - { - } -} diff --git a/tools/Nethermind.Tools.Kute/README.md b/tools/Nethermind.Tools.Kute/README.md deleted file mode 100644 index 68c3937981b..00000000000 --- a/tools/Nethermind.Tools.Kute/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# Kute - -Kute - /kjuːt/ - is a benchmarking tool developed at Nethermind to simulate an Ethereum Consensus Layer, expected to be used together with the Nethermind Client. The tool sends JSON-RPC messages to the Client and measures its performance. - -## Prerequisites - -This is a C# project and as such, it requires the [dotnet 7](https://dotnet.microsoft.com/en-us/download) SDK. Once installed, just run: - -``` -dotnet build [-c Release] -``` - -## Get JSON-RPC messages - -To get real JSON-RPC messages, run the Nethermind Client using the `RpcRecorderState` state feature flag (see [JsonRpc module](https://docs.nethermind.io/nethermind/ethereum-client/configuration/jsonrpc)). The minimum required value is `Request` (`All` is also valid); this usually involves adding `--JsonRpc.RpcRecorderState ` to your execution flags. - -## Run - -> We'll assume that the JWT secret used by the Nethermind Client is stored in `keystore/jwt-secret`. - -Kute includes a built in help that can be accessed by the options `-h | --help`. - -Some typical usages are as follow: - -### Use all messages in the folder `/rpc-logs` - -``` --i /rpc-logs -s keystore/jwt-secret -``` - -### Use a single messages file and emit results as JSON - -``` --i /rpc-logs -s keystore/jwt-secret -o Json -``` - -### Use a single message file, using only `engine_*` and `eth_*` methods - -``` --i /rpc.0 -s keystore/jwt-secret -f engine_*, eth_* -``` - -### Connect to a Nethermind Client running in a specific address and TTL - -``` --i /rpc.0 -s keystore/jwt-secret -a http://192.168.1.100:8551 --ttl 30 -``` - -### Run in "dry" mode (no communication with the Nethermind Client) - -``` --i /rpc.0 -s keystore/jwt-secret -d -``` - -### A note on "progress" - -Kute supports a `-p|--progress` flag which will show how many messages have been processed so far. This feature comes with a **big performance hit during startup** (it will not interfere with metrics though), so it's suggested to **not use it** unless it's required (ex. do not use it in automated environments like CI pipelines). - -### TODO - -There are some features that we might add in the future, if they end up being required: - -- Validate the responses from the Nethermind Client (a "pedantic" mode) -- Other report outputs (ex. CSV) diff --git a/tools/Nethermind.Tools.Kute/SecretProvider/FileSecretProvider.cs b/tools/Nethermind.Tools.Kute/SecretProvider/FileSecretProvider.cs deleted file mode 100644 index c3445dd6d99..00000000000 --- a/tools/Nethermind.Tools.Kute/SecretProvider/FileSecretProvider.cs +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Tools.Kute.SecretProvider; - -public class FileSecretProvider : ISecretProvider -{ - private readonly string _filePath; - - public FileSecretProvider(string filePath) - { - _filePath = filePath; - } - - private bool IsHex(char c) => - c is >= '0' and <= '9' - or >= 'a' and <= 'f' - or >= 'A' and <= 'F'; - - public string Secret - { - get - { - var content = File.ReadAllText(_filePath).Trim(); - if (!content.All(IsHex)) - { - throw new ArgumentException($"{content} is not a Hex string"); - } - - return content; - } - } -} diff --git a/tools/Nethermind.Tools.Kute/SecretProvider/ISecretProvider.cs b/tools/Nethermind.Tools.Kute/SecretProvider/ISecretProvider.cs deleted file mode 100644 index a47438dc695..00000000000 --- a/tools/Nethermind.Tools.Kute/SecretProvider/ISecretProvider.cs +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Tools.Kute.SecretProvider; - -public interface ISecretProvider -{ - string Secret { get; } -} diff --git a/tools/Nethermind.Tools.Kute/SystemClock/ISystemClock.cs b/tools/Nethermind.Tools.Kute/SystemClock/ISystemClock.cs deleted file mode 100644 index 5ed0792dd49..00000000000 --- a/tools/Nethermind.Tools.Kute/SystemClock/ISystemClock.cs +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Tools.Kute.SystemClock; - -interface ISystemClock -{ - DateTimeOffset UtcNow { get; } -} diff --git a/tools/Nethermind.Tools.Kute/SystemClock/RealSystemClock.cs b/tools/Nethermind.Tools.Kute/SystemClock/RealSystemClock.cs deleted file mode 100644 index 6039b2df7a3..00000000000 --- a/tools/Nethermind.Tools.Kute/SystemClock/RealSystemClock.cs +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -namespace Nethermind.Tools.Kute.SystemClock; - -class RealSystemClock : ISystemClock -{ - public DateTimeOffset UtcNow => DateTimeOffset.UtcNow; -} diff --git a/tools/SendBlobs/Dockerfile b/tools/SendBlobs/Dockerfile new file mode 100644 index 00000000000..7de7ce1717b --- /dev/null +++ b/tools/SendBlobs/Dockerfile @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +# SPDX-License-Identifier: LGPL-3.0-only + +FROM mcr.microsoft.com/dotnet/sdk:7.0-jammy AS build +COPY . . +RUN dotnet publish ./tools/SendBlobs/SendBlobs.csproj --sc -o out + + +FROM mcr.microsoft.com/dotnet/runtime:7.0 +RUN apt-get update && apt-get -y install libsnappy-dev libc6-dev libc6 +WORKDIR /nethermind +COPY --from=build /out/SendBlobs . +ENTRYPOINT ["./SendBlobs"] diff --git a/tools/SendBlobs/FundsDistributor.cs b/tools/SendBlobs/FundsDistributor.cs new file mode 100644 index 00000000000..1b93d17c0d7 --- /dev/null +++ b/tools/SendBlobs/FundsDistributor.cs @@ -0,0 +1,197 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Text; +using Nethermind.Cli; +using Nethermind.Consensus; +using Nethermind.Core; +using Nethermind.Core.Extensions; +using Nethermind.Crypto; +using Nethermind.Evm; +using Nethermind.Int256; +using Nethermind.Logging; +using Nethermind.Serialization.Rlp; +using Org.BouncyCastle.Utilities.Encoders; + +namespace SendBlobs; +internal class FundsDistributor +{ + public static IEnumerable ReadKeysFromFile(string path) + { + return File.ReadAllLines(path).Select(l => new PrivateKey(l)); + } + + /// + /// Distribute the available funds from an address to a number of newly generated private keys. + /// + /// + /// + /// + /// + /// Path to a file + /// containing all the executed tx hashes. + /// + public async static Task> DitributeFunds(INodeManager nodeManager, ulong chainId, Signer distributeFrom, uint keysToMake, string keyFilePath, UInt256 maxFee, UInt256 maxPriorityFee) + { + string? balanceString = await nodeManager.Post("eth_getBalance", distributeFrom.Address, "latest"); + if (balanceString is null) + throw new Exception($"Unable to get balance for {distributeFrom.Address}"); + string? nonceString = await nodeManager.Post("eth_getTransactionCount", distributeFrom.Address, "latest"); + if (nonceString is null) + throw new Exception($"Unable to get nonce for {distributeFrom.Address}"); + + string? gasPriceRes = await nodeManager.Post("eth_gasPrice") ?? "1"; + UInt256 gasPrice = (UInt256)Convert.ToUInt64(gasPriceRes, gasPriceRes.StartsWith("0x") ? 16 : 10); + + string? maxPriorityFeePerGasRes; + UInt256 maxPriorityFeePerGas = maxPriorityFee; + if (maxPriorityFee == 0) + { + maxPriorityFeePerGasRes = await nodeManager.Post("eth_maxPriorityFeePerGas") ?? "1"; + maxPriorityFeePerGas = (UInt256)Convert.ToUInt64(maxPriorityFeePerGasRes, maxPriorityFeePerGasRes.StartsWith("0x") ? 16 : 10); + } + + UInt256 balance = new UInt256(Bytes.FromHexString(balanceString)); + + if (balance == 0) + throw new Exception($"Balance on provided signer {distributeFrom.Address} is 0."); + + ulong nonce = Convert.ToUInt64(nonceString, nonceString.StartsWith("0x") ? 16 : 10); + + UInt256 approxGasFee = (gasPrice + maxPriorityFeePerGas) * GasCostOf.Transaction; + + //Leave 10% of the balance as buffer in case of gas spikes + UInt256 balanceMinusBuffer = (balance * 900) / 1000; + UInt256 totalFee = approxGasFee * keysToMake; + + if (balanceMinusBuffer <= totalFee) + throw new Exception($"Not enough balance on {distributeFrom.Address} to distribute to {keysToMake} addresses"); + + UInt256 balanceToDistribute = balanceMinusBuffer - totalFee; + + UInt256 perKeyToSend = balanceToDistribute / keysToMake; + + using PrivateKeyGenerator generator = new(); + IEnumerable privateKeys = Enumerable.Range(1, (int)keysToMake).Select(i => generator.Generate()).ToArray(); + + List txHash = new List(); + + TxDecoder txDecoder = new(); + + foreach (PrivateKey key in privateKeys) + { + if (maxFee == 0) + { + gasPriceRes = await nodeManager.Post("eth_gasPrice") ?? "1"; + gasPrice = (UInt256)Convert.ToUInt64(gasPriceRes, gasPriceRes.StartsWith("0x") ? 16 : 10); + + maxPriorityFeePerGasRes = await nodeManager.Post("eth_maxPriorityFeePerGas") ?? "1"; + maxPriorityFeePerGas = (UInt256)Convert.ToUInt64(maxPriorityFeePerGasRes, maxPriorityFeePerGasRes.StartsWith("0x") ? 16 : 10); + } + + Transaction tx = CreateTx(chainId, + key.Address, + maxFee != 0 ? maxFee : gasPrice + maxPriorityFeePerGas, + nonce, + maxPriorityFeePerGas, + perKeyToSend); + + await distributeFrom.Sign(tx); + + string txRlp = Hex.ToHexString(txDecoder + .Encode(tx, RlpBehaviors.SkipTypedWrapping | RlpBehaviors.InMempoolForm).Bytes); + + string? result = await nodeManager.Post("eth_sendRawTransaction", "0x" + txRlp); + if (result != null) + txHash.Add(result); + nonce++; + } + if (!string.IsNullOrWhiteSpace(keyFilePath)) + File.WriteAllLines(keyFilePath, privateKeys.Select(k => k.ToString()), Encoding.ASCII); + + return txHash; + } + /// + /// Send all available funds from a list of private keys contained in to . + /// + /// + /// + /// + /// + /// + /// containing all the executed tx hashes. + public async static Task> ReclaimFunds(INodeManager nodeManager, ulong chainId, Address beneficiary, string keyFilePath, ILogManager logManager, UInt256 maxFee, UInt256 maxPriorityFee) + { + IEnumerable privateSigners = + File.ReadAllLines(keyFilePath, Encoding.ASCII) + .Select(k => new Signer(chainId, new PrivateKey(k), logManager)); + + ILogger log = logManager.GetClassLogger(); + List txHashes = new List(); + foreach (var signer in privateSigners) + { + string? balanceString = await nodeManager.Post("eth_getBalance", signer.Address, "latest"); + if (balanceString is null) + continue; + string? nonceString = await nodeManager.Post("eth_getTransactionCount", signer.Address, "latest"); + if (nonceString is null) + continue; + + UInt256 balance = new UInt256(Bytes.FromHexString(balanceString)); + + ulong nonce = Convert.ToUInt64(nonceString, nonceString.StartsWith("0x") ? 16 : 10); + + string? gasPriceRes = await nodeManager.Post("eth_gasPrice") ?? "1"; + UInt256 gasPrice = (UInt256)Convert.ToUInt64(gasPriceRes, gasPriceRes.StartsWith("0x") ? 16 : 10); + + UInt256 maxPriorityFeePerGas = maxPriorityFee; + if (maxPriorityFee == 0) + { + string? maxPriorityFeePerGasRes = await nodeManager.Post("eth_maxPriorityFeePerGas") ?? "1"; + maxPriorityFeePerGas = (UInt256)Convert.ToUInt64(maxPriorityFeePerGasRes, maxPriorityFeePerGasRes.StartsWith("0x") ? 16 : 10); + } + + UInt256 approxGasFee = (gasPrice + maxPriorityFeePerGas) * GasCostOf.Transaction; + + if (balance < approxGasFee) + { + log.Info($"Not enough funds on {signer.Address} to pay for gas"); + continue; + } + + UInt256 toSend = balance - approxGasFee; + + TxDecoder txDecoder = new(); + Transaction tx = CreateTx(chainId, + beneficiary, + maxFee != 0 ? maxFee : gasPrice + maxPriorityFeePerGas, + nonce, + maxPriorityFeePerGas, + toSend); + await signer.Sign(tx); + + string txRlp = Hex.ToHexString(txDecoder + .Encode(tx, RlpBehaviors.SkipTypedWrapping | RlpBehaviors.InMempoolForm).Bytes); + + string? result = await nodeManager.Post("eth_sendRawTransaction", "0x" + txRlp); + if (result != null) + txHashes.Add(result); + } + return txHashes; + } + + private static Transaction CreateTx(ulong chainId, Address beneficiary, UInt256 maxFee, ulong nonce, UInt256 maxPriorityFeePerGas, UInt256 toSend) + { + return new() + { + Type = TxType.EIP1559, + ChainId = chainId, + Nonce = nonce, + GasLimit = GasCostOf.Transaction, + GasPrice = maxPriorityFeePerGas, + DecodedMaxFeePerGas = maxFee, + Value = toSend, + To = beneficiary, + }; + } +} diff --git a/tools/SendBlobs/Program.cs b/tools/SendBlobs/Program.cs new file mode 100644 index 00000000000..b1968e02bb0 --- /dev/null +++ b/tools/SendBlobs/Program.cs @@ -0,0 +1,395 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Microsoft.Extensions.CommandLineUtils; +using Nethermind.Cli; +using Nethermind.Cli.Console; +using Nethermind.Consensus; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Crypto; +using Nethermind.Evm; +using Nethermind.Facade.Proxy.Models; +using Nethermind.Int256; +using Nethermind.Logging; +using Nethermind.Serialization.Json; +using Nethermind.Serialization.Rlp; +using Org.BouncyCastle.Utilities.Encoders; +using SendBlobs; + +// send-blobs +// send-blobs http://localhost:8545 5 0x0000000000000000000000000000000000000000000000000000000000000000 0x000000000000000000000000000000000000f1c1 100 100 +// 1 = 0 blobs +// 2 = 1st blob is of wrong size +// 3 = 7 blobs +// 4 = 1st blob's wrong proof +// 5 = 1st blob's wrong commitment +// 6 = 1st blob with a modulo correct, but > modulo value +// 7 = max fee per blob gas = max value +// 8 = max fee per blob gas > max value +// 9 = 1st proof removed +// 10 = 1st commitment removed +// 11 = max fee per blob gas = max value / blobgasperblob + 1 +// 14 = 100 blobs +// 15 = 1000 blobs + +CommandLineApplication app = new() { Name = "SendBlobs" }; + +SetupExecute(app); +SetupDistributeCommand(app); +SetupReclaimCommand(app); + +try +{ + app.Execute(args); +} +catch (CommandParsingException ex) +{ + Console.WriteLine(ex.Message); + app.ShowHelp(); +} + +static void SetupExecute(CommandLineApplication app) +{ + app.HelpOption("--help"); + + CommandOption rpcUrlOption = app.Option("--rpcurl ", "Url of the Json RPC.", CommandOptionType.SingleValue); + CommandOption blobTxOption = app.Option("--bloboptions ", "Options in format '10x1-2', '2x5-5' etc. for the blobs.", CommandOptionType.MultipleValue); + CommandOption privateKeyOption = app.Option("--privatekey ", "The key to use for sending blobs.", CommandOptionType.SingleValue); + CommandOption privateKeyFileOption = app.Option("--keyfile ", "File containing private keys that each blob tx will be send from.", CommandOptionType.SingleValue); + CommandOption receiverOption = app.Option("--receiveraddress ", "Receiver address of the blobs.", CommandOptionType.SingleValue); + CommandOption maxFeePerDataGasOption = app.Option("--maxfeeperdatagas ", "(Optional) Set the maximum fee per blob data.", CommandOptionType.SingleValue); + CommandOption feeMultiplierOption = app.Option("--feemultiplier ", "(Optional) A multiplier to use for gas fees.", CommandOptionType.SingleValue); + CommandOption maxPriorityFeeGasOption = app.Option("--maxpriorityfee ", "(Optional) The maximum priority fee for each transaction.", CommandOptionType.SingleValue); + + app.OnExecute(async () => + { + string rpcUrl = rpcUrlOption.Value(); + (int count, int blobCount, string @break)[] blobTxCounts = blobTxOption.Value().Split(',') + .Select(x => + { + string @break = ""; + if (x.Contains("-")) + { + @break = x.Split("-")[1]; + x = x.Split("-")[0]; + } + return x.Contains("x") ? + (int.Parse(x.Split('x')[0]), int.Parse(x.Split('x')[1]), @break) + : (int.Parse(x), 1, @break); + }) + .ToArray(); + + PrivateKey[] privateKeys; + + if (privateKeyFileOption.HasValue()) + privateKeys = File.ReadAllLines(privateKeyFileOption.Value(), System.Text.Encoding.ASCII).Select(k => new PrivateKey(k)).ToArray(); + else if (privateKeyOption.HasValue()) + privateKeys = new[] { new PrivateKey(privateKeyOption.Value()) }; + else + { + Console.WriteLine("Missing private key argument."); + app.ShowHelp(); + return 1; + } + + string receiver = receiverOption.Value(); + + UInt256 maxFeePerDataGas = 1000; + if (maxFeePerDataGasOption.HasValue()) + { + ulong.TryParse(maxFeePerDataGasOption.Value(), out ulong shortMaxFeePerDataGas); + maxFeePerDataGas = shortMaxFeePerDataGas; + } + + ulong feeMultiplier = 4; + if (feeMultiplierOption.HasValue()) + ulong.TryParse(feeMultiplierOption.Value(), out feeMultiplier); + + UInt256 maxPriorityFeeGasArgs = 0; + if (maxPriorityFeeGasOption.HasValue()) UInt256.TryParse(maxPriorityFeeGasOption.Value(), out maxPriorityFeeGasArgs); + + await SendBlobs( + rpcUrl, + blobTxCounts, + privateKeys, + receiver, + maxFeePerDataGas, + feeMultiplier, + maxPriorityFeeGasArgs); + + return 0; + }); +} + +async static Task SendBlobs( + string rpcUrl, + (int count, int blobCount, string @break)[] blobTxCounts, + PrivateKey[] privateKeys, + string receiver, + UInt256 maxFeePerDataGas, + ulong feeMultiplier, + UInt256 maxPriorityFeeGasArgs) +{ + await KzgPolynomialCommitments.InitializeAsync(); + + ILogger logger = SimpleConsoleLogManager.Instance.GetLogger("send blobs"); + INodeManager nodeManager = InitNodeManager(rpcUrl, logger); + + List<(Signer, ulong)> signers = new List<(Signer, ulong)>(); + + bool isNodeSynced = await nodeManager.Post("eth_syncing") is bool; + + string? chainIdString = await nodeManager.Post("eth_chainId") ?? "1"; + ulong chainId = Convert.ToUInt64(chainIdString, chainIdString.StartsWith("0x") ? 16 : 10); + + OneLoggerLogManager logManager = new(logger); + + foreach (PrivateKey privateKey in privateKeys) + { + string? nonceString = await nodeManager.Post("eth_getTransactionCount", privateKey.Address, "latest"); + if (nonceString is null) + { + logger.Error("Unable to get nonce"); + return; + } + ulong nonce = Convert.ToUInt64(nonceString, nonceString.StartsWith("0x") ? 16 : 10); + + signers.Add(new(new Signer(chainId, privateKey, logManager), nonce)); + } + + TxDecoder txDecoder = new(); + int signerIndex = -1; + + foreach ((int txCount, int blobCount, string @break) txs in blobTxCounts) + { + int txCount = txs.txCount; + int blobCount = txs.blobCount; + string @break = txs.@break; + bool waitForBlock = false; + + while (txCount > 0) + { + txCount--; + + signerIndex++; + if (signerIndex >= signers.Count) + signerIndex = 0; + + Signer signer = signers[signerIndex].Item1; + ulong nonce = signers[signerIndex].Item2; + + switch (@break) + { + case "1": blobCount = 0; break; + case "2": blobCount = 7; break; + case "14": blobCount = 100; break; + case "15": blobCount = 1000; break; + case "wait": + waitForBlock = isNodeSynced; + if (!isNodeSynced) Console.WriteLine($"Will not wait for blob inclusion since selected node at {rpcUrl} is still syncing"); + break; + } + + byte[][] blobs = new byte[blobCount][]; + byte[][] commitments = new byte[blobCount][]; + byte[][] proofs = new byte[blobCount][]; + byte[][] blobhashes = new byte[blobCount][]; + + for (int blobIndex = 0; blobIndex < blobCount; blobIndex++) + { + blobs[blobIndex] = new byte[Ckzg.Ckzg.BytesPerBlob]; + new Random().NextBytes(blobs[blobIndex]); + for (int i = 0; i < Ckzg.Ckzg.BytesPerBlob; i += 32) + { + blobs[blobIndex][i] = 0; + } + + if (@break == "6" && blobIndex == 0) + { + Array.Fill(blobs[blobIndex], (byte)0, 0, 31); + blobs[blobIndex][31] = 1; + } + + commitments[blobIndex] = new byte[Ckzg.Ckzg.BytesPerCommitment]; + proofs[blobIndex] = new byte[Ckzg.Ckzg.BytesPerProof]; + blobhashes[blobIndex] = new byte[32]; + + KzgPolynomialCommitments.KzgifyBlob( + blobs[blobIndex].AsSpan(), + commitments[blobIndex].AsSpan(), + proofs[blobIndex].AsSpan(), + blobhashes[blobIndex].AsSpan()); + } + + string? gasPriceRes = await nodeManager.Post("eth_gasPrice") ?? "1"; + UInt256 gasPrice = (UInt256)Convert.ToUInt64(gasPriceRes, gasPriceRes.StartsWith("0x") ? 16 : 10); + + string? maxPriorityFeePerGasRes = await nodeManager.Post("eth_maxPriorityFeePerGas") ?? "1"; + UInt256 maxPriorityFeePerGas = (UInt256)Convert.ToUInt64(maxPriorityFeePerGasRes, maxPriorityFeePerGasRes.StartsWith("0x") ? 16 : 10); + + Console.WriteLine($"Nonce: {nonce}, GasPrice: {gasPrice}, MaxPriorityFeePerGas: {maxPriorityFeePerGas}"); + + switch (@break) + { + case "3": blobs[0] = blobs[0].Take(blobs.Length - 2).ToArray(); break; + case "4": proofs[0][2] = (byte)~proofs[0][2]; break; + case "5": commitments[0][2] = (byte)~commitments[0][2]; break; + case "6": + Array.Copy(KzgPolynomialCommitments.BlsModulus.ToBigEndian(), blobs[0], 32); + blobs[0][31] += 1; + break; + case "7": maxFeePerDataGas = UInt256.MaxValue; break; + //case "8": maxFeePerDataGas = 42_000_000_000; break; + case "9": proofs = proofs.Skip(1).ToArray(); break; + case "10": commitments = commitments.Skip(1).ToArray(); break; + case "11": maxFeePerDataGas = UInt256.MaxValue / Eip4844Constants.DataGasPerBlob + 1; break; + } + + UInt256 adjustedMaxPriorityFeePerGas = maxPriorityFeeGasArgs == 0 ? maxPriorityFeePerGas : maxPriorityFeeGasArgs; + Transaction tx = new() + { + Type = TxType.Blob, + ChainId = chainId, + Nonce = nonce, + GasLimit = GasCostOf.Transaction, + GasPrice = adjustedMaxPriorityFeePerGas * feeMultiplier, + DecodedMaxFeePerGas = gasPrice * feeMultiplier, + MaxFeePerDataGas = maxFeePerDataGas, + Value = 0, + To = new Address(receiver), + BlobVersionedHashes = blobhashes, + NetworkWrapper = new ShardBlobNetworkWrapper(blobs, commitments, proofs), + }; + + await signer.Sign(tx); + + string txRlp = Hex.ToHexString(txDecoder + .Encode(tx, RlpBehaviors.InMempoolForm | RlpBehaviors.SkipTypedWrapping).Bytes); + + BlockModel? blockResult = null; + if (waitForBlock) + blockResult = await nodeManager.Post>("eth_getBlockByNumber", "latest", false); + + string? result = await nodeManager.Post("eth_sendRawTransaction", "0x" + txRlp); + + Console.WriteLine("Result:" + result); + + signers[signerIndex] = new(signer, nonce + 1); + + if (blockResult != null && waitForBlock) + await WaitForBlobInclusion(nodeManager, tx.CalculateHash(), blockResult.Number); + } + } +} + +async static Task WaitForBlobInclusion(INodeManager nodeManager, Keccak txHash, UInt256 lastBlockNumber) +{ + Console.WriteLine("Waiting for blob transaction to be included in a block"); + int waitInMs = 2000; + //Retry for about 5 slots worth of time + int retryCount = (12 * 5 * 1000) / waitInMs; + while (true) + { + var blockResult = await nodeManager.Post>("eth_getBlockByNumber", lastBlockNumber, false); + if (blockResult != null) + { + lastBlockNumber++; + + if (blockResult.Transactions.Contains(txHash)) + { + string? receipt = await nodeManager.Post("eth_getTransactionByHash", txHash.ToString(), true); + + Console.WriteLine($"Found blob transaction in block {blockResult.Number}"); + return; + } + } + else + { + await Task.Delay(waitInMs); + } + + retryCount--; + if (retryCount == 0) break; + } +} + +static void SetupDistributeCommand(CommandLineApplication app) +{ + app.Command("distribute", (command) => + { + command.Description = "Distribute funds from an address to a number of new addresses."; + command.HelpOption("--help"); + + CommandOption rpcUrlOption = command.Option("--rpcurl ", "Url of the Json RPC.", CommandOptionType.SingleValue); + CommandOption privateKeyOption = command.Option("--privatekey ", "The private key to distribute funds from.", CommandOptionType.SingleValue); + CommandOption keyNumberOption = command.Option("--number ", "The number of new addresses/keys to make.", CommandOptionType.SingleValue); + CommandOption keyFileOption = command.Option("--keyfile ", "File where the newly generated keys are written.", CommandOptionType.SingleValue); + CommandOption maxPriorityFeeGasOption = command.Option("--maxpriorityfee ", "(Optional) The maximum priority fee for each transaction.", CommandOptionType.SingleValue); + CommandOption maxFeeOption = command.Option("--maxfee ", "(Optional) The maxFeePerGas fee paid for each transaction.", CommandOptionType.SingleValue); + + command.OnExecute(async () => + { + uint keysToMake = uint.Parse(keyNumberOption.Value()); + PrivateKey privateKey = new(privateKeyOption.Value()); + + ILogger logger = SimpleConsoleLogManager.Instance.GetLogger("distribute funds"); + INodeManager nodeManager = InitNodeManager(rpcUrlOption.Value(), logger); + + string? chainIdString = await nodeManager.Post("eth_chainId") ?? "1"; + ulong chainId = Convert.ToUInt64(chainIdString, chainIdString.StartsWith("0x") ? 16 : 10); + + Signer signer = new Signer(chainId, privateKey, new OneLoggerLogManager(logger)); + UInt256 maxFee = maxFeeOption.HasValue() ? UInt256.Parse(maxFeeOption.Value()) : 0; + UInt256 maxPriorityFee = maxPriorityFeeGasOption.HasValue() ? UInt256.Parse(maxPriorityFeeGasOption.Value()) : 0; + + IEnumerable hashes = await FundsDistributor.DitributeFunds(nodeManager, chainId, signer, keysToMake, keyFileOption.Value(), maxFee, maxPriorityFee); + + return 0; + }); + }); +} + +static void SetupReclaimCommand(CommandLineApplication app) +{ + app.Command("reclaim", (command) => + { + command.Description = "Reclaim funds distributed from the 'distribute' command."; + command.HelpOption("--help"); + + CommandOption rpcUrlOption = command.Option("--rpcurl ", "Url of the Json RPC.", CommandOptionType.SingleValue); + CommandOption receiverOption = command.Option("--receiveraddress ", "The address to send the funds to.", CommandOptionType.SingleValue); + CommandOption keyFileOption = command.Option("--keyfile ", "File of the private keys to reclaim from.", CommandOptionType.SingleValue); + CommandOption maxPriorityFeeGasOption = command.Option("--maxpriorityfee ", "(Optional) The maximum priority fee for each transaction.", CommandOptionType.SingleValue); + CommandOption maxFeeOption = command.Option("--maxfee ", "(Optional) The maxFeePerGas paid for each transaction.", CommandOptionType.SingleValue); + + command.OnExecute(async () => + { + ILogger logger = SimpleConsoleLogManager.Instance.GetLogger("reclaim funds"); + INodeManager nodeManager = InitNodeManager(rpcUrlOption.Value(), logger); + + string? chainIdString = await nodeManager.Post("eth_chainId") ?? "1"; + ulong chainId = Convert.ToUInt64(chainIdString, chainIdString.StartsWith("0x") ? 16 : 10); + + Address beneficiary = new Address(receiverOption.Value()); + + UInt256 maxFee = maxFeeOption.HasValue() ? UInt256.Parse(maxFeeOption.Value()) : 0; + UInt256 maxPriorityFee = maxPriorityFeeGasOption.HasValue() ? UInt256.Parse(maxPriorityFeeGasOption.Value()) : 0; + + IEnumerable hashes = await FundsDistributor.ReclaimFunds(nodeManager, chainId, beneficiary, keyFileOption.Value(), new OneLoggerLogManager(logger), maxFee, maxPriorityFee); + + return 0; + }); + }); +} + +static INodeManager InitNodeManager(string rpcUrl, ILogger logger) +{ + ICliConsole cliConsole = new CliConsole(); + IJsonSerializer serializer = new EthereumJsonSerializer(); + OneLoggerLogManager logManager = new OneLoggerLogManager(logger); + ICliEngine engine = new CliEngine(cliConsole); + INodeManager nodeManager = new NodeManager(engine, serializer, cliConsole, logManager); + nodeManager.SwitchUri(new Uri(rpcUrl)); + return nodeManager; +} diff --git a/tools/SendBlobs/Properties/launchSettings.json b/tools/SendBlobs/Properties/launchSettings.json new file mode 100644 index 00000000000..166f9df5443 --- /dev/null +++ b/tools/SendBlobs/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "SendBlobs": { + "commandName": "Project", + "commandLineArgs": "http://localhost:8545 1-8 c2b36204cdfc90550383c3d96b8f95ede48d8447d03ec1c27c07b089a6dd67c1 0x000000000000000000000000000000000000f1c1 4" + } + } +} diff --git a/tools/SendBlobs/README.md b/tools/SendBlobs/README.md new file mode 100644 index 00000000000..494e97007af --- /dev/null +++ b/tools/SendBlobs/README.md @@ -0,0 +1,136 @@ +# Send Blobs tool + +## Run using docker + +``` +docker run ghcr.io/flcl42/send-blobs:latest --rpcurl http://localhost:8545 --bloboptions 5 --privatekey 0x0000000000000000000000000000000000000000000000000000000000000000 --receiveraddress 0x000000000000000000000000000000000000f1c1 +docker run ghcr.io/flcl42/send-blobs:latest --rpcurl http://localhost:8545 --bloboptions 5x6 --privatekey 0x0000000000000000000000000000000000000000000000000000000000000000 --receiveraddress 0x000000000000000000000000000000000000f1c1 --maxfeeperdatagas 10000 --feemultiplier 4 +``` + +## Usage + +``` +Usage: SendBlobs [options] [command] + +Options: + --help Show help information + --rpcurl Url of the Json RPC. + --bloboptions Options in format '10x1-2', '2x5-5' etc. for the blobs. + --privatekey The key to use for sending blobs. + --keyfile File containing private keys that each blob tx will be send from. + --receiveraddress Receiver address of the blobs. + --maxfeeperdatagas (Optional) Set the maximum fee per blob data. + --feemultiplier (Optional) A multiplier to use for gas fees. + --maxpriorityfee (Optional) The maximum priority fee for each transaction. + +Commands: + distribute Distribute funds from an address to a number of new addresses. + reclaim Reclaim funds distributed from the 'distribute' command. + + +Use "SendBlobs [command] --help" for more information about a command. + +Usage: SendBlobs __distribute__ [options] + +Options: + --help Show help information + --rpcurl Url of the Json RPC. + --privatekey The private key to distribute funds from. + --number The number of new addresses/keys to make. + --keyfile File where the newly generated keys are written. + --maxpriorityfee (Optional) The maximum priority fee for each transaction. + --maxfee (Optional) The maxFeePerGas fee paid for each transaction. + + +Usage: SendBlobs __reclaim__ [options] + +Options: + --help Show help information + --rpcurl Url of the Json RPC. + --receiveraddress The address to send the funds to. + --keyfile File of the private keys to reclaim from. + --maxpriorityfee (Optional) The maximum priority fee for each transaction. + --maxfee (Optional) The maxFeePerGas paid for each transaction. + +sh +./SendBlobs --rpcurl http://localhost:8545 # url-that-does-not-require-auth-in-header + --bloboptions 1000,5x6,100x2 # transaction count: just a number or a list of tx-count x blob-count + --privatekey 0x0000..0000 # secret-key + --receiveraddress 0x0000..0042 # receiver-address + --maxfeeperdatagas 10000 # data gas price limit, 1000 by default + --feemultiplier 4 # fee multiplier to compete with other txs in the pool, 4 by default + +# send 5 transactions, 1 blob each +./SendBlobs --rpcurl http://localhost:8545 --bloboptions 5 \ + 0x0000000000000000000000000000000000000000000000000000000000000000 \ + 0x000000000000000000000000000000000000f1c1 10000 4 + +# send several transactions with 1 blob, with 6 blobs and than with 2 blobs +./SendBlobs --rpcurl http://localhost:8545 + --bloboptions 10x1,10x6,10x2 \ + --privatekey 0x0000000000000000000000000000000000000000000000000000000000000000 \ + --receiveraddress 0x000000000000000000000000000000000000f1c1 \ + --maxfeeperdatagas 10000 \ + --feemultiplier 4 + +#send a couple of transactions + +./SendBlobs --rpcurl http://localhost:8545 \ + --bloboptions 2x4-1 \ + --privatekey 0x0000000000000000000000000000000000000000000000000000000000000000 \ + --receiveraddress 0x0000000000000000000000000000000000000001 \ + --maxfeeperdatagas 10000 \ + --feemultiplier 4 +``` +## Blob options +``` +< modulo value + 7 = max fee per blob gas = max value + + 9 = 1st proof removed + 10 = 1st commitment removed + 11 = max fee per blob gas = max value / blobgasperblob + 1 + 14 = 100 blobs + 15 = 1000 blobs + wait = wait for each transaction to be included in a block before posting the next + +Syntax: + + 2x3-4 + ^ tx count + ^ blobs in every tx (optional, default to 1) + ^ how it's broken (optional, tx is correct by default) or write true + +BrokenTxs +``` + +## Debug + +``` +For funding the private key used in the project launch settings, the address is: +0x428a95ceb38b706fbfe74fa0144701cfc1c25ef7 +``` + +## Build + +```sh +apt install libsnappy-dev dotnet-sdk-7.0 -y +cd ./tools/SendBlobs +dotnet publish --sc -o . +./SendBlobs +``` + +or via docker + +```sh +cd ./nethermind/ # repository root +docker build . -f ./tools/SendBlobs/Dockerfile -t send-blobs +docker run send-blobs ... # args samples above +``` diff --git a/tools/SendBlobs/SendBlobs.csproj b/tools/SendBlobs/SendBlobs.csproj new file mode 100644 index 00000000000..7472fe35928 --- /dev/null +++ b/tools/SendBlobs/SendBlobs.csproj @@ -0,0 +1,23 @@ + + + + + Exe + net7.0 + enable + enable + true + true + *.pdb + + + + + + + + + + + + diff --git a/tools/SendBlobs/SendBlobs.sln b/tools/SendBlobs/SendBlobs.sln new file mode 100644 index 00000000000..04c2b860a9b --- /dev/null +++ b/tools/SendBlobs/SendBlobs.sln @@ -0,0 +1,163 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34031.279 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SendBlobs", "SendBlobs.csproj", "{B84CDBC5-A386-4DFD-89B8-2A34C4230D4E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nethermind.Cli", "..\..\src\Nethermind\Nethermind.Cli\Nethermind.Cli.csproj", "{2439617F-FB19-4BB2-A87F-51138C081334}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Crypto", "..\..\src\Nethermind\Nethermind.Crypto\Nethermind.Crypto.csproj", "{C1FF9907-6C3A-4563-8F67-10C1EBD23F0A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.JsonRpc", "..\..\src\Nethermind\Nethermind.JsonRpc\Nethermind.JsonRpc.csproj", "{A5C9C005-7501-4A30-8927-DFA99B935F36}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Core", "..\..\src\Nethermind\Nethermind.Core\Nethermind.Core.csproj", "{DDD7D989-CF6B-48A3-B752-0703293D4323}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Logging", "..\..\src\Nethermind\Nethermind.Logging\Nethermind.Logging.csproj", "{AB916D73-36AD-4B3C-9242-A1B44E511CC2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Abi", "..\..\src\Nethermind\Nethermind.Abi\Nethermind.Abi.csproj", "{C22AEF7D-66E4-440A-956E-FEFFD2225206}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Blockchain", "..\..\src\Nethermind\Nethermind.Blockchain\Nethermind.Blockchain.csproj", "{0334B0DA-F231-4999-A3AE-8C41FA7C3F45}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Config", "..\..\src\Nethermind\Nethermind.Config\Nethermind.Config.csproj", "{29002E08-290A-4505-8277-6575EFE37B91}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Consensus", "..\..\src\Nethermind\Nethermind.Consensus\Nethermind.Consensus.csproj", "{DEF43E13-D17B-4808-8F2A-2F571B7E6728}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Evm", "..\..\src\Nethermind\Nethermind.Evm\Nethermind.Evm.csproj", "{94563FE7-0D77-404F-AA80-18837D16748E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Facade", "..\..\src\Nethermind\Nethermind.Facade\Nethermind.Facade.csproj", "{E68AB892-CD21-48C4-88E6-A2DDC2EE2C0C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Monitoring", "..\..\src\Nethermind\Nethermind.Monitoring\Nethermind.Monitoring.csproj", "{A3DD53A4-1C8A-4D76-951F-CDE683A21DA7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Network", "..\..\src\Nethermind\Nethermind.Network\Nethermind.Network.csproj", "{A8A4F872-6B2E-483A-B4AB-67778820DB43}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Wallet", "..\..\src\Nethermind\Nethermind.Wallet\Nethermind.Wallet.csproj", "{5689E79D-D637-47D5-9620-BADB9EC5CC88}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Sockets", "..\..\src\Nethermind\Nethermind.Sockets\Nethermind.Sockets.csproj", "{15EAD678-1767-46BA-A54E-35B06B2FAE03}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Synchronization", "..\..\src\Nethermind\Nethermind.Synchronization\Nethermind.Synchronization.csproj", "{BAE96316-C30A-4C23-8B54-E10B1A153CA8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Db", "..\..\src\Nethermind\Nethermind.Db\Nethermind.Db.csproj", "{B19757AE-BB75-4045-AE50-435C45AE538F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Network.Stats", "..\..\src\Nethermind\Nethermind.Network.Stats\Nethermind.Network.Stats.csproj", "{DC9AF895-24B5-4E8D-82BD-2E7890B166F0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Specs", "..\..\src\Nethermind\Nethermind.Specs\Nethermind.Specs.csproj", "{129E6D35-1F55-4366-A961-C6D048E0D068}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.State", "..\..\src\Nethermind\Nethermind.State\Nethermind.State.csproj", "{09BDC967-8792-44AF-925E-2D77091A1460}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.TxPool", "..\..\src\Nethermind\Nethermind.TxPool\Nethermind.TxPool.csproj", "{E1D9FC55-A2B4-4A53-B1C0-7DCD62A29C2F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.Serialization.Rlp", "..\..\src\Nethermind\Nethermind.Serialization.Rlp\Nethermind.Serialization.Rlp.csproj", "{4CEA776F-3D7B-4F29-A24A-E2BCBBEDE93B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nethermind.KeyStore", "..\..\src\Nethermind\Nethermind.KeyStore\Nethermind.KeyStore.csproj", "{2DFA339F-52E5-4931-9EB2-C4F726D18FD2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B84CDBC5-A386-4DFD-89B8-2A34C4230D4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B84CDBC5-A386-4DFD-89B8-2A34C4230D4E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B84CDBC5-A386-4DFD-89B8-2A34C4230D4E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B84CDBC5-A386-4DFD-89B8-2A34C4230D4E}.Release|Any CPU.Build.0 = Release|Any CPU + {2439617F-FB19-4BB2-A87F-51138C081334}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2439617F-FB19-4BB2-A87F-51138C081334}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2439617F-FB19-4BB2-A87F-51138C081334}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2439617F-FB19-4BB2-A87F-51138C081334}.Release|Any CPU.Build.0 = Release|Any CPU + {C1FF9907-6C3A-4563-8F67-10C1EBD23F0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C1FF9907-6C3A-4563-8F67-10C1EBD23F0A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C1FF9907-6C3A-4563-8F67-10C1EBD23F0A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C1FF9907-6C3A-4563-8F67-10C1EBD23F0A}.Release|Any CPU.Build.0 = Release|Any CPU + {A5C9C005-7501-4A30-8927-DFA99B935F36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A5C9C005-7501-4A30-8927-DFA99B935F36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A5C9C005-7501-4A30-8927-DFA99B935F36}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A5C9C005-7501-4A30-8927-DFA99B935F36}.Release|Any CPU.Build.0 = Release|Any CPU + {DDD7D989-CF6B-48A3-B752-0703293D4323}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DDD7D989-CF6B-48A3-B752-0703293D4323}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DDD7D989-CF6B-48A3-B752-0703293D4323}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DDD7D989-CF6B-48A3-B752-0703293D4323}.Release|Any CPU.Build.0 = Release|Any CPU + {AB916D73-36AD-4B3C-9242-A1B44E511CC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB916D73-36AD-4B3C-9242-A1B44E511CC2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB916D73-36AD-4B3C-9242-A1B44E511CC2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB916D73-36AD-4B3C-9242-A1B44E511CC2}.Release|Any CPU.Build.0 = Release|Any CPU + {C22AEF7D-66E4-440A-956E-FEFFD2225206}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C22AEF7D-66E4-440A-956E-FEFFD2225206}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C22AEF7D-66E4-440A-956E-FEFFD2225206}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C22AEF7D-66E4-440A-956E-FEFFD2225206}.Release|Any CPU.Build.0 = Release|Any CPU + {0334B0DA-F231-4999-A3AE-8C41FA7C3F45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0334B0DA-F231-4999-A3AE-8C41FA7C3F45}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0334B0DA-F231-4999-A3AE-8C41FA7C3F45}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0334B0DA-F231-4999-A3AE-8C41FA7C3F45}.Release|Any CPU.Build.0 = Release|Any CPU + {29002E08-290A-4505-8277-6575EFE37B91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {29002E08-290A-4505-8277-6575EFE37B91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {29002E08-290A-4505-8277-6575EFE37B91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {29002E08-290A-4505-8277-6575EFE37B91}.Release|Any CPU.Build.0 = Release|Any CPU + {DEF43E13-D17B-4808-8F2A-2F571B7E6728}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DEF43E13-D17B-4808-8F2A-2F571B7E6728}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DEF43E13-D17B-4808-8F2A-2F571B7E6728}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DEF43E13-D17B-4808-8F2A-2F571B7E6728}.Release|Any CPU.Build.0 = Release|Any CPU + {94563FE7-0D77-404F-AA80-18837D16748E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {94563FE7-0D77-404F-AA80-18837D16748E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {94563FE7-0D77-404F-AA80-18837D16748E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {94563FE7-0D77-404F-AA80-18837D16748E}.Release|Any CPU.Build.0 = Release|Any CPU + {E68AB892-CD21-48C4-88E6-A2DDC2EE2C0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E68AB892-CD21-48C4-88E6-A2DDC2EE2C0C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E68AB892-CD21-48C4-88E6-A2DDC2EE2C0C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E68AB892-CD21-48C4-88E6-A2DDC2EE2C0C}.Release|Any CPU.Build.0 = Release|Any CPU + {A3DD53A4-1C8A-4D76-951F-CDE683A21DA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A3DD53A4-1C8A-4D76-951F-CDE683A21DA7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A3DD53A4-1C8A-4D76-951F-CDE683A21DA7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3DD53A4-1C8A-4D76-951F-CDE683A21DA7}.Release|Any CPU.Build.0 = Release|Any CPU + {A8A4F872-6B2E-483A-B4AB-67778820DB43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A8A4F872-6B2E-483A-B4AB-67778820DB43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A8A4F872-6B2E-483A-B4AB-67778820DB43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A8A4F872-6B2E-483A-B4AB-67778820DB43}.Release|Any CPU.Build.0 = Release|Any CPU + {5689E79D-D637-47D5-9620-BADB9EC5CC88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5689E79D-D637-47D5-9620-BADB9EC5CC88}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5689E79D-D637-47D5-9620-BADB9EC5CC88}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5689E79D-D637-47D5-9620-BADB9EC5CC88}.Release|Any CPU.Build.0 = Release|Any CPU + {15EAD678-1767-46BA-A54E-35B06B2FAE03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {15EAD678-1767-46BA-A54E-35B06B2FAE03}.Debug|Any CPU.Build.0 = Debug|Any CPU + {15EAD678-1767-46BA-A54E-35B06B2FAE03}.Release|Any CPU.ActiveCfg = Release|Any CPU + {15EAD678-1767-46BA-A54E-35B06B2FAE03}.Release|Any CPU.Build.0 = Release|Any CPU + {BAE96316-C30A-4C23-8B54-E10B1A153CA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BAE96316-C30A-4C23-8B54-E10B1A153CA8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BAE96316-C30A-4C23-8B54-E10B1A153CA8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BAE96316-C30A-4C23-8B54-E10B1A153CA8}.Release|Any CPU.Build.0 = Release|Any CPU + {B19757AE-BB75-4045-AE50-435C45AE538F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B19757AE-BB75-4045-AE50-435C45AE538F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B19757AE-BB75-4045-AE50-435C45AE538F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B19757AE-BB75-4045-AE50-435C45AE538F}.Release|Any CPU.Build.0 = Release|Any CPU + {DC9AF895-24B5-4E8D-82BD-2E7890B166F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DC9AF895-24B5-4E8D-82BD-2E7890B166F0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DC9AF895-24B5-4E8D-82BD-2E7890B166F0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DC9AF895-24B5-4E8D-82BD-2E7890B166F0}.Release|Any CPU.Build.0 = Release|Any CPU + {129E6D35-1F55-4366-A961-C6D048E0D068}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {129E6D35-1F55-4366-A961-C6D048E0D068}.Debug|Any CPU.Build.0 = Debug|Any CPU + {129E6D35-1F55-4366-A961-C6D048E0D068}.Release|Any CPU.ActiveCfg = Release|Any CPU + {129E6D35-1F55-4366-A961-C6D048E0D068}.Release|Any CPU.Build.0 = Release|Any CPU + {09BDC967-8792-44AF-925E-2D77091A1460}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09BDC967-8792-44AF-925E-2D77091A1460}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09BDC967-8792-44AF-925E-2D77091A1460}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09BDC967-8792-44AF-925E-2D77091A1460}.Release|Any CPU.Build.0 = Release|Any CPU + {E1D9FC55-A2B4-4A53-B1C0-7DCD62A29C2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E1D9FC55-A2B4-4A53-B1C0-7DCD62A29C2F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E1D9FC55-A2B4-4A53-B1C0-7DCD62A29C2F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E1D9FC55-A2B4-4A53-B1C0-7DCD62A29C2F}.Release|Any CPU.Build.0 = Release|Any CPU + {4CEA776F-3D7B-4F29-A24A-E2BCBBEDE93B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4CEA776F-3D7B-4F29-A24A-E2BCBBEDE93B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4CEA776F-3D7B-4F29-A24A-E2BCBBEDE93B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4CEA776F-3D7B-4F29-A24A-E2BCBBEDE93B}.Release|Any CPU.Build.0 = Release|Any CPU + {2DFA339F-52E5-4931-9EB2-C4F726D18FD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2DFA339F-52E5-4931-9EB2-C4F726D18FD2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2DFA339F-52E5-4931-9EB2-C4F726D18FD2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DFA339F-52E5-4931-9EB2-C4F726D18FD2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4EAAD22A-5D92-4DEB-A423-5A522A843D70} + EndGlobalSection +EndGlobal