diff --git a/.github/workflows/build-solution.yml b/.github/workflows/build-solution.yml index 05b705d005e..893be079443 100644 --- a/.github/workflows/build-solution.yml +++ b/.github/workflows/build-solution.yml @@ -9,17 +9,21 @@ on: defaults: run: working-directory: src/Nethermind - + +env: + BUILD_CONFIG: release + jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: + fetch-depth: 0 submodules: recursive - name: Setup .NET - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v2 with: dotnet-version: 6.0.x @@ -31,6 +35,6 @@ jobs: - name: Build run: | - dotnet build --configuration Release --no-restore Baseline.sln - dotnet build --configuration Release --no-restore Cortex.sln - dotnet build --configuration Release --no-restore Benchmarks.sln + dotnet build Baseline.sln -c ${{ env.BUILD_CONFIG }} --no-restore + dotnet build Cortex.sln -c ${{ env.BUILD_CONFIG }} --no-restore + dotnet build Benchmarks.sln -c ${{ env.BUILD_CONFIG }} --no-restore diff --git a/.github/workflows/release-nethermind.yml b/.github/workflows/release-nethermind.yml index f3f890e5d30..e5200d561c7 100644 --- a/.github/workflows/release-nethermind.yml +++ b/.github/workflows/release-nethermind.yml @@ -4,9 +4,8 @@ on: workflow_dispatch: inputs: tag: - description: 'The TAG of the version you want to release.' - required: false - default: 'master' + description: 'The TAG of the version you want to release' + required: true permissions: deployments: write @@ -29,39 +28,48 @@ jobs: WIN10: win10-x64 LINUX_ARM64: linux-arm64 OSX_ARM64: osx-arm64 + outputs: + COMMIT_HASH: ${{ steps.build-runner.outputs.COMMIT_HASH }} + BUILD_TIMESTAMP: ${{ steps.build-runner.outputs.BUILD_TIMESTAMP }} steps: - name: Checking out Nethermind repository - uses: actions/checkout@master + uses: actions/checkout@v3 with: submodules: recursive path: nethermind ref: ${{ github.event.inputs.tag }} - fetch-depth: 0 - name: Checking out Nethermind Launcher repository - uses: actions/checkout@master + uses: actions/checkout@v3 with: repository: NethermindEth/nethermind.launcher path: launcher - name: Setting up Node.js - uses: actions/setup-node@master + uses: actions/setup-node@v3 with: node-version: "14" - name: Setting up Build Environment run: | npm i pkg @vercel/ncc -g - - name: Setting up dotnet - uses: actions/setup-dotnet@v1 + - name: Setting up .NET + uses: actions/setup-dotnet@v2 with: - dotnet-version: '6.0.x' + dotnet-version: 6.0.x - name: Setting up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Setting up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Setting up Packages run: ./nethermind/scripts/deployment/setup-packages.sh - name: Building Runner - run: ./nethermind/scripts/deployment/build-runner.sh + id: build-runner + run: | + cd nethermind/ + build_timestamp=$(date '+%s') + commit_hash=$(git describe --always --exclude=* --abbrev=40) + echo "::set-output name=BUILD_TIMESTAMP::$build_timestamp" + echo "::set-output name=COMMIT_HASH::$commit_hash" + ./scripts/deployment/build-runner.sh ${{ github.event.inputs.tag }} $commit_hash $build_timestamp - name: Building Cli run: ./nethermind/scripts/deployment/build-cli.sh - name: Building Launcher @@ -73,38 +81,33 @@ jobs: docker run --platform=linux/arm64 -v $PWD:/opt/mount --rm tmp-launcher bash -c "cp /nethermind/Nethermind.Launcher /opt/mount/" mv Nethermind.Launcher ${{ env.RELEASE_DIRECTORY }}/${{ env.LIN_ARM64_RELEASE }}/Nethermind.Launcher - name: Archiving packages - run: ./nethermind/scripts/deployment/archive-packages.sh - - uses: actions/upload-artifact@master + run: ./nethermind/scripts/deployment/archive-packages.sh ${{ github.event.inputs.tag }} ${{ steps.build-runner.outputs.COMMIT_HASH }} ${{ steps.build-runner.outputs.BUILD_TIMESTAMP}} + - uses: actions/upload-artifact@v3 name: Uploading Nethermind darwin package with: name: nethermind-darwin-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.OSX_RELEASE }}/nethermind-darwin-amd64-* - - uses: actions/upload-artifact@master + - uses: actions/upload-artifact@v3 name: Uploading Nethermind linux package with: name: nethermind-linux-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.LIN_RELEASE }}/nethermind-linux-amd64-* - - uses: actions/upload-artifact@master + - uses: actions/upload-artifact@v3 name: Uploading Nethermind windows package with: name: nethermind-windows-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.WIN_RELEASE }}/nethermind-windows-amd64-* - - uses: actions/upload-artifact@master + - uses: actions/upload-artifact@v3 name: Uploading Nethermind linux arm64 package with: name: nethermind-linux-arm64-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.LIN_ARM64_RELEASE }}/nethermind-linux-arm64-* - - uses: actions/upload-artifact@master + - uses: actions/upload-artifact@v3 name: Uploading Nethermind darwin arm64 package with: name: nethermind-darwin-arm64-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.OSX_ARM64_RELEASE }}/nethermind-darwin-arm64-* - - uses: actions/upload-artifact@master - name: Uploading git-hash files - with: - name: nethermind-git-hash - path: ${{ env.RELEASE_DIRECTORY }}/git-* - - uses: actions/upload-artifact@master + - uses: actions/upload-artifact@v3 name: Uploading update-homebrew.sh with: name: update-homebrew-sh @@ -117,30 +120,28 @@ jobs: env: OSX_RELEASE: nethermind-osx-x64 OSX_ARM64_RELEASE: nethermind-osx-arm64 - RELEASE_DIRECTORY: /home/runner/work/nethermind/nethermind + RELEASE_DIRECTORY: /home/runner/work/nethermind/nethermind + VERSION: ${{ github.event.inputs.tag }} + TIMESTAMP: ${{needs.build-nethermind.outputs.BUILD_TIMESTAMP}} + HASH: ${{needs.build-nethermind.outputs.COMMIT_HASH}} steps: - name: Downloading Nethermind darwin package - uses: actions/download-artifact@master + uses: actions/download-artifact@v3 with: name: nethermind-darwin-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.OSX_RELEASE }}/ - name: Downloading Nethermind darwin arm64 package - uses: actions/download-artifact@master + uses: actions/download-artifact@v3 with: name: nethermind-darwin-arm64-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.OSX_ARM64_RELEASE }}/ - - name: Downloading git-hash files - uses: actions/download-artifact@master - with: - name: nethermind-git-hash - path: ${{ env.RELEASE_DIRECTORY }}/ - name: Downloading update-homebrew script - uses: actions/download-artifact@master + uses: actions/download-artifact@v3 with: name: update-homebrew-sh path: ${{ env.RELEASE_DIRECTORY }}/ - name: Checkout repository - uses: actions/checkout@master + uses: actions/checkout@v3 with: repository: NethermindEth/homebrew-nethermind path: homebrew-nethermind @@ -183,32 +184,32 @@ jobs: OSX_ARM64_RELEASE: nethermind-osx-arm64 steps: - name: Checking out Nethermind repository - uses: actions/checkout@master + uses: actions/checkout@v3 with: ref: ${{ github.event.inputs.tag }} path: nethermind fetch-depth: 0 - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v3 name: Downloading Nethermind darwin package with: name: nethermind-darwin-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.OSX_RELEASE }}/ - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v3 name: Downloading Nethermind linux package with: name: nethermind-linux-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.LIN_RELEASE }}/ - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v3 name: Downloading Nethermind windows package with: name: nethermind-windows-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.WIN_RELEASE }}/ - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v3 name: Downloading Nethermind linux arm64 package with: name: nethermind-linux-arm64-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.LIN_ARM64_RELEASE }}/ - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v3 name: Downloading Nethermind darwin arm64 package with: name: nethermind-darwin-arm64-package @@ -232,31 +233,31 @@ jobs: OSX_ARM64_RELEASE: nethermind-osx-arm64 steps: - name: Checking out Nethermind repository - uses: actions/checkout@master + uses: actions/checkout@v3 with: ref: ${{ github.event.inputs.tag }} path: nethermind - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v3 name: Downloading Nethermind darwin package with: name: nethermind-darwin-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.OSX_RELEASE }}/ - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v3 name: Downloading Nethermind linux package with: name: nethermind-linux-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.LIN_RELEASE }}/ - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v3 name: Downloading Nethermind windows package with: name: nethermind-windows-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.WIN_RELEASE }}/ - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v3 name: Downloading Nethermind linux arm64 package with: name: nethermind-linux-arm64-package path: ${{ env.RELEASE_DIRECTORY }}/${{ env.LIN_ARM64_RELEASE }}/ - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v3 name: Downloading Nethermind darwin arm64 package with: name: nethermind-darwin-arm64-package @@ -279,7 +280,7 @@ jobs: needs: trigger-publish steps: - name: Checking out Nethermind repository - uses: actions/checkout@master + uses: actions/checkout@v3 with: ref: ${{ github.event.inputs.tag }} fetch-depth: 0 @@ -290,10 +291,10 @@ jobs: echo ::set-output name=docker_username::${{ secrets.DOCKER_USERNAME }} echo ::set-output name=docker_image::nethermind/nethermind - name: Setting up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Setting up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Logging to Docker Hub if: success() env: @@ -338,7 +339,7 @@ jobs: - name: Install dependencies for PPA run: sudo apt update > /dev/null 2>&1 && sudo apt install debhelper devscripts -y > /dev/null 2>&1 - name: Checking out Nethermind repository - uses: actions/checkout@master + uses: actions/checkout@v3 with: path: nethermind - name: Run publish PPA script diff --git a/.github/workflows/run-nethermind-tests.yml b/.github/workflows/run-nethermind-tests.yml index 589c417652c..cf5c3b64c31 100644 --- a/.github/workflows/run-nethermind-tests.yml +++ b/.github/workflows/run-nethermind-tests.yml @@ -11,323 +11,325 @@ on: pull_request: workflow_dispatch: +env: + BUILD_CONFIG: release jobs: neth-tests: name: Running Nethermind Tests 1 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true - - name: Setting up dotnet - uses: actions/setup-dotnet@v1 + - name: Setting up .NET + uses: actions/setup-dotnet@v2 with: - dotnet-version: '6.0.x' + dotnet-version: 6.0.x - name: Installing Linux packages run: | sudo apt-get update sudo apt-get install libsnappy-dev libc6-dev libc6 - name: Nethermind.Blockchain.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Blockchain.Test + dotnet test src/Nethermind/Nethermind.Blockchain.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Abi.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Abi.Test; + dotnet test src/Nethermind/Nethermind.Abi.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Api.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Api.Test; + dotnet test src/Nethermind/Nethermind.Api.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.AuRa.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.AuRa.Test + dotnet test src/Nethermind/Nethermind.AuRa.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.AccountAbstraction.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.AccountAbstraction.Test + dotnet test src/Nethermind/Nethermind.AccountAbstraction.Test -c ${{ env.BUILD_CONFIG }} neth-tests2: name: Running Nethermind Tests 2 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true - - name: Setting up dotnet - uses: actions/setup-dotnet@v1 + - name: Setting up .NET + uses: actions/setup-dotnet@v2 with: - dotnet-version: '6.0.x' + dotnet-version: 6.0.x - name: Installing Linux packages run: | sudo apt-get update sudo apt-get install libsnappy-dev libc6-dev libc6 - name: Nethermind.Clique.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Clique.Test + dotnet test src/Nethermind/Nethermind.Clique.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Config.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Config.Test + dotnet test src/Nethermind/Nethermind.Config.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Consensus.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Consensus.Test + dotnet test src/Nethermind/Nethermind.Consensus.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Core.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Core.Test + dotnet test src/Nethermind/Nethermind.Core.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Cryptography.Bls.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Cryptography.Bls.Test + dotnet test src/Nethermind/Nethermind.Cryptography.Bls.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Network.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Network.Test + dotnet test src/Nethermind/Nethermind.Network.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Network.Discovery.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Network.Discovery.Test + dotnet test src/Nethermind/Nethermind.Network.Discovery.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Network.Dns.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Network.Dns.Test + dotnet test src/Nethermind/Nethermind.Network.Dns.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Network.Enr.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Network.Enr.Test + dotnet test src/Nethermind/Nethermind.Network.Enr.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Facade.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Facade.Test + dotnet test src/Nethermind/Nethermind.Facade.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Logging.NLog.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Logging.NLog.Test + dotnet test src/Nethermind/Nethermind.Logging.NLog.Test -c ${{ env.BUILD_CONFIG }} neth-tests3: name: Running Nethermind Tests 3 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true - - name: Setting up dotnet - uses: actions/setup-dotnet@v1 + - name: Setting up .NET + uses: actions/setup-dotnet@v2 with: - dotnet-version: '6.0.x' + dotnet-version: 6.0.x - name: Installing Linux packages run: | sudo apt-get update sudo apt-get install libsnappy-dev libc6-dev libc6 - name: Nethermind.HealthChecks.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.HealthChecks.Test + dotnet test src/Nethermind/Nethermind.HealthChecks.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.HonestValidator.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.HonestValidator.Test + dotnet test src/Nethermind/Nethermind.HonestValidator.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Evm.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Evm.Test + dotnet test src/Nethermind/Nethermind.Evm.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Ethash.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Ethash.Test + dotnet test src/Nethermind/Nethermind.Ethash.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.EthStats.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.EthStats.Test + dotnet test src/Nethermind/Nethermind.EthStats.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.JsonRpc.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.JsonRpc.Test + dotnet test src/Nethermind/Nethermind.JsonRpc.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Merge.Plugin.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Merge.Plugin.Test + dotnet test src/Nethermind/Nethermind.Merge.Plugin.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Merge.AuRa.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Merge.AuRa.Test + dotnet test src/Nethermind/Nethermind.Merge.AuRa.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Mev.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Mev.Test + dotnet test src/Nethermind/Nethermind.Mev.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Specs.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Specs.Test + dotnet test src/Nethermind/Nethermind.Specs.Test -c ${{ env.BUILD_CONFIG }} neth-tests4: name: Running Nethermind Tests 4 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true - - name: Setting up dotnet - uses: actions/setup-dotnet@v1 + - name: Setting up .NET + uses: actions/setup-dotnet@v2 with: - dotnet-version: '6.0.x' + dotnet-version: 6.0.x - name: Installing Linux packages run: | sudo apt-get update sudo apt-get install libsnappy-dev libc6-dev libc6 - name: Nethermind.Secp256k1.Test.Linux run: | - dotnet test -c Release src/Nethermind/Nethermind.Secp256k1.Test + dotnet test src/Nethermind/Nethermind.Secp256k1.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Synchronization.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Synchronization.Test + dotnet test src/Nethermind/Nethermind.Synchronization.Test -c ${{ env.BUILD_CONFIG }} neth-tests5: name: Running Nethermind Tests 5 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true - - name: Setting up dotnet - uses: actions/setup-dotnet@v1 + - name: Setting up .NET + uses: actions/setup-dotnet@v2 with: - dotnet-version: '6.0.x' + dotnet-version: 6.0.x - name: Installing Linux packages run: | sudo apt-get update sudo apt-get install libsnappy-dev libc6-dev libc6 - name: Nethermind.TxPool.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.TxPool.Test + dotnet test src/Nethermind/Nethermind.TxPool.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Trie.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Trie.Test + dotnet test src/Nethermind/Nethermind.Trie.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Sockets.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Sockets.Test + dotnet test src/Nethermind/Nethermind.Sockets.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Wallet.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Wallet.Test + dotnet test src/Nethermind/Nethermind.Wallet.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Baseline.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Baseline.Test + dotnet test src/Nethermind/Nethermind.Baseline.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Mining.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Mining.Test + dotnet test src/Nethermind/Nethermind.Mining.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.State.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.State.Test + dotnet test src/Nethermind/Nethermind.State.Test -c ${{ env.BUILD_CONFIG }} neth-tests-cortex: name: Running Cortex Tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true - - name: Setting up dotnet - uses: actions/setup-dotnet@v1 + - name: Setting up .NET + uses: actions/setup-dotnet@v2 with: - dotnet-version: '6.0.x' + dotnet-version: 6.0.x - name: Installing Linux packages run: | sudo apt-get update sudo apt-get install libsnappy-dev libc6-dev libc6 - name: Nethermind.BeaconNode.Eth1Bridge.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.BeaconNode.Eth1Bridge.Test + dotnet test src/Nethermind/Nethermind.BeaconNode.Eth1Bridge.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.BeaconNode.Peering.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.BeaconNode.Peering.Test + dotnet test src/Nethermind/Nethermind.BeaconNode.Peering.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.BeaconNode.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.BeaconNode.Test + dotnet test src/Nethermind/Nethermind.BeaconNode.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Core2.Configuration.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Core2.Configuration.Test + dotnet test src/Nethermind/Nethermind.Core2.Configuration.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Core2.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Core2.Test + dotnet test src/Nethermind/Nethermind.Core2.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Ssz.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Ssz.Test + dotnet test src/Nethermind/Nethermind.Ssz.Test -c ${{ env.BUILD_CONFIG }} neth-runner: name: Nethermind Runner Tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true - - name: Setting up dotnet - uses: actions/setup-dotnet@v1 + - name: Setting up .NET + uses: actions/setup-dotnet@v2 with: - dotnet-version: '6.0.x' + dotnet-version: 6.0.x - name: Installing Linux packages run: | sudo apt-get update sudo apt-get install libsnappy-dev libc6-dev libc6 - name: Nethermind.Runner.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Runner.Test + dotnet test src/Nethermind/Nethermind.Runner.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.State.Test.Runner.Test run : | - dotnet test -c Release src/Nethermind/Nethermind.State.Test.Runner.Test + dotnet test src/Nethermind/Nethermind.State.Test.Runner.Test -c ${{ env.BUILD_CONFIG }} - name: Nethermind.Cli.Test run: | - dotnet test -c Release src/Nethermind/Nethermind.Cli.Test + dotnet test src/Nethermind/Nethermind.Cli.Test -c ${{ env.BUILD_CONFIG }} eth-tests1: name: Running Ethereum Tests 1 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true - - name: Setting up dotnet - uses: actions/setup-dotnet@v1 + - name: Setting up .NET + uses: actions/setup-dotnet@v2 with: - dotnet-version: '6.0.x' + dotnet-version: 6.0.x - name: Ethereum.Blockchain.Test run: | - dotnet test -c Release src/Nethermind/Ethereum.Blockchain.Test + dotnet test src/Nethermind/Ethereum.Blockchain.Test -c ${{ env.BUILD_CONFIG }} eth-tests2: name: Running Ethereum Tests 2 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true - - name: Setting up dotnet - uses: actions/setup-dotnet@v1 + - name: Setting up .NET + uses: actions/setup-dotnet@v2 with: - dotnet-version: '6.0.x' + dotnet-version: 6.0.x - name: Ethereum.Trie.Test run: | - dotnet test -c Release src/Nethermind/Ethereum.Trie.Test + dotnet test src/Nethermind/Ethereum.Trie.Test -c ${{ env.BUILD_CONFIG }} - name: Ethereum.VM.Test run: | - dotnet test -c Release src/Nethermind/Ethereum.VM.Test + dotnet test src/Nethermind/Ethereum.VM.Test -c ${{ env.BUILD_CONFIG }} eth-tests3: name: Running Ethereum Tests 3 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true - - name: Setting up dotnet - uses: actions/setup-dotnet@v1 + - name: Setting up .NET + uses: actions/setup-dotnet@v2 with: - dotnet-version: '6.0.x' + dotnet-version: 6.0.x - name: Ethereum.Basic.Test run: | - dotnet test -c Release src/Nethermind/Ethereum.Basic.Test + dotnet test src/Nethermind/Ethereum.Basic.Test -c ${{ env.BUILD_CONFIG }} - name: Ethereum.Blockchain.Block.Test run: | - dotnet test -c Release src/Nethermind/Ethereum.Blockchain.Block.Test + dotnet test src/Nethermind/Ethereum.Blockchain.Block.Test -c ${{ env.BUILD_CONFIG }} - name: Ethereum.Abi.Test run: | - dotnet test -c Release src/Nethermind/Ethereum.Abi.Test + dotnet test src/Nethermind/Ethereum.Abi.Test -c ${{ env.BUILD_CONFIG }} - name: Ethereum.Difficulty.Test run: | - dotnet test -c Release src/Nethermind/Ethereum.Difficulty.Test + dotnet test src/Nethermind/Ethereum.Difficulty.Test -c ${{ env.BUILD_CONFIG }} - name: Ethereum.HexPrefix.Test run: | - dotnet test -c Release src/Nethermind/Ethereum.HexPrefix.Test + dotnet test src/Nethermind/Ethereum.HexPrefix.Test -c ${{ env.BUILD_CONFIG }} - name: Ethereum.KeyAddress.Test run: | - dotnet test -c Release src/Nethermind/Ethereum.KeyAddress.Test + dotnet test src/Nethermind/Ethereum.KeyAddress.Test -c ${{ env.BUILD_CONFIG }} - name: Ethereum.PoW.Test run: | - dotnet test -c Release src/Nethermind/Ethereum.PoW.Test + dotnet test src/Nethermind/Ethereum.PoW.Test -c ${{ env.BUILD_CONFIG }} - name: Ethereum.Rlp.Test run: | - dotnet test -c Release src/Nethermind/Ethereum.Rlp.Test + dotnet test src/Nethermind/Ethereum.Rlp.Test -c ${{ env.BUILD_CONFIG }} - name: Ethereum.Transaction.Test run: | - dotnet test -c Release src/Nethermind/Ethereum.Transaction.Test + dotnet test src/Nethermind/Ethereum.Transaction.Test -c ${{ env.BUILD_CONFIG }} - name: Ethereum.Transition.Test run: | - dotnet test -c Release src/Nethermind/Ethereum.Transition.Test + dotnet test src/Nethermind/Ethereum.Transition.Test -c ${{ env.BUILD_CONFIG }} diff --git a/scripts/deployment/archive-packages.sh b/scripts/deployment/archive-packages.sh index 2eebba01aa0..71798039f62 100755 --- a/scripts/deployment/archive-packages.sh +++ b/scripts/deployment/archive-packages.sh @@ -6,15 +6,16 @@ OSX=nethermind-darwin-amd64 OSX_ARM64=nethermind-darwin-arm64 WIN=nethermind-windows-amd64 LIN_ARM64=nethermind-linux-arm64 -RELEASE_PATH=nethermind/src/Nethermind/Nethermind.Runner/bin/Release/net6.0 +RELEASE_PATH=nethermind/src/Nethermind/Nethermind.Runner/bin/release/net6.0 echo ======================================================= echo Archiving Nethermind packages echo ======================================================= cd $RELEASE_DIRECTORY -GIT_SHORT_TAG="$(tail git-tag.txt)" -GIT_HASH="$(tail git-hash.txt)" +VERSION=$1 +COMMIT_HASH=$(echo $2 | awk '{print substr($0,0,7);}') +DATE=$(date +'%Y%m%d' -d @$3) echo ======================================================= echo Copying and packing plugins @@ -26,8 +27,8 @@ mkdir -p $OSX_ARM64_RELEASE/plugins mkdir -p $WIN_RELEASE/plugins mkdir -p $LIN_ARM64_RELEASE/plugins -cd nethermind/src/Nethermind/ -dotnet build -c Release Nethermind.sln +cd nethermind/src/Nethermind/Nethermind.Runner +dotnet build -c release Nethermind.Runner.csproj cd $RELEASE_DIRECTORY @@ -37,11 +38,11 @@ cp $RELEASE_DIRECTORY/$RELEASE_PATH/Nethermind.{Api,HealthChecks,EthStats,Merge. cp $RELEASE_DIRECTORY/$RELEASE_PATH/Nethermind.{Api,HealthChecks,EthStats,Merge.Plugin,Mev}.dll $LIN_ARM64_RELEASE/plugins cp $RELEASE_DIRECTORY/$RELEASE_PATH/Nethermind.{Api,HealthChecks,EthStats,Merge.Plugin,Mev}.dll $OSX_ARM64_RELEASE/plugins -cd $LIN_RELEASE && zip -r $LIN-$GIT_SHORT_TAG-$GIT_HASH.zip . && cd .. -cd $OSX_RELEASE && zip -r $OSX-$GIT_SHORT_TAG-$GIT_HASH.zip . && cd .. -cd $WIN_RELEASE && zip -r $WIN-$GIT_SHORT_TAG-$GIT_HASH.zip . && cd .. -cd $LIN_ARM64_RELEASE && zip -r $LIN_ARM64-$GIT_SHORT_TAG-$GIT_HASH.zip . && cd .. -cd $OSX_ARM64_RELEASE && zip -r $OSX_ARM64-$GIT_SHORT_TAG-$GIT_HASH.zip . && cd .. +cd $LIN_RELEASE && zip -r $LIN-$VERSION-$COMMIT_HASH-$DATE.zip . && cd .. +cd $OSX_RELEASE && zip -r $OSX-$VERSION-$COMMIT_HASH-$DATE.zip . && cd .. +cd $WIN_RELEASE && zip -r $WIN-$VERSION-$COMMIT_HASH-$DATE.zip . && cd .. +cd $LIN_ARM64_RELEASE && zip -r $LIN_ARM64-$VERSION-$COMMIT_HASH-$DATE.zip . && cd .. +cd $OSX_ARM64_RELEASE && zip -r $OSX_ARM64-$VERSION-$COMMIT_HASH-$DATE.zip . && cd .. echo ======================================================= echo Archiving Nethermind packages completed diff --git a/scripts/deployment/build-runner.sh b/scripts/deployment/build-runner.sh index 1ba4b20cfa6..1c3aec607dc 100755 --- a/scripts/deployment/build-runner.sh +++ b/scripts/deployment/build-runner.sh @@ -8,15 +8,16 @@ OUT=out cd $RUNNER_PATH echo ======================================================= -echo Publishing Nethermind Runner for different platforms... +echo Publishing Nethermind Runner for different platforms +echo with v$1+$2 echo ======================================================= echo Nethermind Runner path: $RUNNER_PATH -dotnet publish -c release -r $LINUX --self-contained true -p:PublishSingleFile=true -p:IncludeAllContentForSelfExtract=true -o $OUT/$LIN_RELEASE -dotnet publish -c release -r $LINUX_ARM64 -p:PublishSingleFile=true -p:IncludeAllContentForSelfExtract=true -o $OUT/$LIN_ARM64_RELEASE -dotnet publish -c release -r $OSX --self-contained true -p:PublishSingleFile=true -p:IncludeAllContentForSelfExtract=true -o $OUT/$OSX_RELEASE -dotnet publish -c release -r $OSX_ARM64 --self-contained true -p:PublishSingleFile=true -p:IncludeAllContentForSelfExtract=true -o $OUT/$OSX_ARM64_RELEASE -dotnet publish -c release -r $WIN10 --self-contained true -p:PublishSingleFile=true -p:IncludeAllContentForSelfExtract=true -o $OUT/$WIN_RELEASE +dotnet publish -c release -r $LINUX --self-contained true -p:Version=$1 -p:Commit=$2 -p:BuildTimestamp=$3 -p:PublishSingleFile=true -p:IncludeAllContentForSelfExtract=true -o $OUT/$LIN_RELEASE +dotnet publish -c release -r $LINUX_ARM64 -p:PublishSingleFile=true -p:Version=$1 -p:Commit=$2 -p:BuildTimestamp=$3 -p:IncludeAllContentForSelfExtract=true -o $OUT/$LIN_ARM64_RELEASE +dotnet publish -c release -r $OSX --self-contained true -p:Version=$1 -p:Commit=$2 -p:BuildTimestamp=$3 -p:PublishSingleFile=true -p:IncludeAllContentForSelfExtract=true -o $OUT/$OSX_RELEASE +dotnet publish -c release -r $OSX_ARM64 --self-contained true -p:Version=$1 -p:Commit=$2 -p:BuildTimestamp=$3 -p:PublishSingleFile=true -p:IncludeAllContentForSelfExtract=true -o $OUT/$OSX_ARM64_RELEASE +dotnet publish -c release -r $WIN10 --self-contained true -p:Version=$1 -p:Commit=$2 -p:BuildTimestamp=$3 -p:PublishSingleFile=true -p:IncludeAllContentForSelfExtract=true -o $OUT/$WIN_RELEASE rm -rf $OUT/$LIN_RELEASE/Data rm -rf $OUT/$LIN_RELEASE/Hive diff --git a/scripts/deployment/setup-packages.sh b/scripts/deployment/setup-packages.sh index afecda4ff9f..808e6623442 100755 --- a/scripts/deployment/setup-packages.sh +++ b/scripts/deployment/setup-packages.sh @@ -5,8 +5,6 @@ echo ======================================================= echo Setting up Nethermind packages echo ======================================================= -DATE=`date +%Y%m%d` - cd $RELEASE_DIRECTORY mkdir $LIN_RELEASE mkdir $OSX_RELEASE @@ -14,27 +12,6 @@ mkdir $WIN_RELEASE mkdir $LIN_ARM64_RELEASE mkdir $OSX_ARM64_RELEASE -echo ======================================================= -echo Creating git-hash and git-tag files -echo ======================================================= - -cd $RELEASE_DIRECTORY/nethermind -GIT="$(git rev-parse --short=7 HEAD)" -GIT_TAG_SHORT="$(git describe --tags --abbrev=0)" -GIT_TAG_LONG="$(git describe --tags --long)" -cd .. -touch git-hash.txt -touch git-tag.txt -touch git-tag-long.txt - -echo $GIT-$DATE > git-hash.txt -echo ${GIT_TAG_SHORT} > git-tag.txt -echo ${GIT_TAG_LONG} > git-tag-long.txt - -echo ======================================================= -echo Success, git-hash and git-tag files have been created -echo ======================================================= - echo ======================================================= echo Setting up Nethermind packages completed echo ======================================================= \ No newline at end of file diff --git a/scripts/deployment/update-homebrew.sh b/scripts/deployment/update-homebrew.sh index 659dccecc60..5b28ceda171 100644 --- a/scripts/deployment/update-homebrew.sh +++ b/scripts/deployment/update-homebrew.sh @@ -6,28 +6,23 @@ OSX_ARM64=nethermind-darwin-arm64 HOMEBREW_PATH=$RELEASE_DIRECTORY/homebrew-nethermind cd $RELEASE_DIRECTORY -GIT_SHORT_TAG="$(tail git-tag.txt)" -GIT_HASH="$(tail git-hash.txt)" - +DATE=$(date +'%Y%m%d' -d @$TIMESTAMP) +COMMIT_HASH=$(echo $HASH | awk '{print substr($0,0,7);}') echo ======================================================= echo Updating Homebrew package echo ======================================================= cd $OSX_RELEASE -darwin_amd64_hash="$(shasum -a 256 $OSX-$GIT_SHORT_TAG-$GIT_HASH.zip | awk '{ print $1}')" -version=$(echo $OSX-$GIT_SHORT_TAG-$GIT_HASH.zip | awk -F- '{ print $4}') -commit=$(echo $OSX-$GIT_SHORT_TAG-$GIT_HASH.zip | awk -F- '{ print $5}') -date=$(echo $OSX-$GIT_SHORT_TAG-$GIT_HASH.zip | awk -F- '{ print substr($6,1,8)}') - +darwin_amd64_hash="$(shasum -a 256 $OSX-$VERSION-$COMMIT_HASH-$DATE.zip | awk '{ print $1}')" cd .. cd $OSX_ARM64_RELEASE -darwin_arm64_hash="$(shasum -a 256 $OSX_ARM64-$GIT_SHORT_TAG-$GIT_HASH.zip | awk '{ print $1}')" +darwin_arm64_hash="$(shasum -a 256 $OSX_ARM64-$VERSION-$COMMIT_HASH-$DATE.zip | awk '{ print $1}')" cd $HOMEBREW_PATH -sed -i "s/app_version =.*/app_version = '"$version"'/" nethermind.rb -sed -i "s/commit =.*/commit = '"$commit"'/" nethermind.rb -sed -i "s/date =.*/date = '"$date"'/" nethermind.rb +sed -i "s/app_version =.*/app_version = '"$VERSION"'/" nethermind.rb +sed -i "s/commit =.*/commit = '"$COMMIT_HASH"'/" nethermind.rb +sed -i "s/date =.*/date = '"$DATE"'/" nethermind.rb awk -i inplace -v n=1 '/sha256/ { if (++count == n) sub(/sha256.*/, "sha256 \"'$darwin_amd64_hash'\""); } 1' nethermind.rb awk -i inplace -v n=2 '/sha256/ { if (++count == n) sub(/sha256.*/, "sha256 \"'$darwin_arm64_hash'\""); } 1' nethermind.rb diff --git a/scripts/packaging/archive-packages.sh b/scripts/packaging/archive-packages.sh deleted file mode 100644 index cc769e952f3..00000000000 --- a/scripts/packaging/archive-packages.sh +++ /dev/null @@ -1,33 +0,0 @@ -RELEASE_DIRECTORY=nethermind-packages -LIN_RELEASE=nethermind-lin-x64 -OSX_RELEASE=nethermind-osx-x64 -WIN_RELEASE=nethermind-win-x64 -LIN=nethermind-linux-amd64 -OSX=nethermind-darwin-amd64 -WIN=nethermind-windows-amd64 -PPA=nethermind-ppa -LATEST=latest - - -echo ======================================================= -echo Archiving Nethermind packages -echo ======================================================= - -cd $RELEASE_DIRECTORY -GIT_SHORT_TAG="$(tail git-tag.txt)" -GIT_HASH="$(tail git-hash.txt)" - -cd ~/repo_pub/$RELEASE_DIRECTORY -cd $LIN_RELEASE && zip -r $LIN-$GIT_SHORT_TAG-$GIT_HASH.zip . && cd .. -cd $OSX_RELEASE && zip -r $OSX-$GIT_SHORT_TAG-$GIT_HASH.zip . && cd .. -cd $WIN_RELEASE && zip -r $WIN-$GIT_SHORT_TAG-$GIT_HASH.zip . && cd .. - -mkdir $PPA -cd $PPA -mv $LIN_RELEASE/$LIN-$GIT_SHORT_TAG-$GIT_HASH.zip . -mv $LIN-$GIT_SHORT_TAG-$GIT_HASH.zip $PPA-$LATEST.zip - -echo ======================================================= -echo Archiving Nethermind packages completed -echo ======================================================= - diff --git a/scripts/packaging/azure-upload.sh b/scripts/packaging/azure-upload.sh deleted file mode 100644 index ad3e524e29d..00000000000 --- a/scripts/packaging/azure-upload.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -DATE=`date +%Y%m%d` -GIT_RC="$(tail -c 8 ./nethermind-packages/git-tag.txt | tr "." "-")" -export container_name=$GIT_RC-$DATE-public -export linux_folder=~/repo_pub/nethermind-packages/nethermind-lin-x64/nethermind-* -export ppa_folder=~/repo_pub/nethermind-packages/nethermind-ppa/nethermind-* -export windows_folder=~/repo_pub/nethermind-packages/nethermind-win-x64/nethermind-* -export darwin_folder=~/repo_pub/nethermind-packages/nethermind-osx-x64/nethermind-* - -echo "Creating the container..." -az storage container create --name $container_name - -echo "Uploading linux package..." -az storage blob upload --container-name $container_name --file $linux_folder --name $(basename $linux_folder) - -echo "Uploading the ppa package" -az storage blob upload --container-name $container_name --file $ppa_folder --name $(basename $ppa_folder) - -echo "Uploading windows package..." -az storage blob upload --container-name $container_name --file $windows_folder --name $(basename $windows_folder) - -echo "Uploading darwin package..." -az storage blob upload --container-name $container_name --file $darwin_folder --name $(basename $darwin_folder) - -echo "Listing the blobs..." -az storage blob list --container-name $container_name --output table - -echo "Done" diff --git a/scripts/packaging/build-cli.sh b/scripts/packaging/build-cli.sh deleted file mode 100644 index 3879a31c101..00000000000 --- a/scripts/packaging/build-cli.sh +++ /dev/null @@ -1,47 +0,0 @@ -RELEASE_DIRECTORY=../../../../nethermind-packages -CLI_PATH=nethermind/src/Nethermind/Nethermind.Cli -LINUX=linux-x64 -OSX=osx-x64 -WIN10=win10-x64 -PUBLISH_PATH=bin/release/netcoreapp3.1 -EXEC=Nethermind.Cli -ZIP=$EXEC.zip -OUT=out -LIN_RELEASE=nethermind-lin-x64 -OSX_RELEASE=nethermind-osx-x64 -WIN_RELEASE=nethermind-win-x64 - -cd $CLI_PATH - -echo ======================================================= -echo Publishing Nethermind Cli for different platforms... -echo ======================================================= -echo Nethermind Cli path: $CLI_PATH - -dotnet publish -c release -r $LINUX -dotnet publish -c release -r $OSX -dotnet publish -c release -r $WIN10 - -rm -rf $OUT && mkdir $OUT $OUT/$LINUX $OUT/$OSX $OUT/$WIN10 - -echo ======================================================= -echo Packing Nethermind Cli for different platforms... -echo ======================================================= - -/usr/local/bin/warp-packer --arch linux-x64 --input_dir $PUBLISH_PATH/$LINUX/publish --exec $EXEC --output $OUT/$LINUX/$EXEC -/usr/local/bin/warp-packer --arch macos-x64 --input_dir $PUBLISH_PATH/$OSX/publish --exec $EXEC --output $OUT/$OSX/$EXEC -/usr/local/bin/warp-packer --arch windows-x64 --input_dir $PUBLISH_PATH/$WIN10/publish --exec $EXEC.exe --output $OUT/$WIN10/$EXEC.exe - -mkdir -p $RELEASE_DIRECTORY/$LIN_RELEASE -mkdir -p $RELEASE_DIRECTORY/$OSX_RELEASE -mkdir -p $RELEASE_DIRECTORY/$WIN_RELEASE - -mv $OUT/$LINUX/$EXEC $RELEASE_DIRECTORY/$LIN_RELEASE -mv $OUT/$OSX/$EXEC $RELEASE_DIRECTORY/$OSX_RELEASE -mv $OUT/$WIN10/$EXEC.exe $RELEASE_DIRECTORY/$WIN_RELEASE - -rm -rf $OUT - -echo ======================================================= -echo Building Nethermind Cli completed -echo ======================================================= diff --git a/scripts/packaging/build-launcher-ico.sh b/scripts/packaging/build-launcher-ico.sh deleted file mode 100755 index 00a4a17fb72..00000000000 --- a/scripts/packaging/build-launcher-ico.sh +++ /dev/null @@ -1,20 +0,0 @@ -RELEASE_DIRECTORY=nethermind-packages -LAUNCHER_PATH=nethermind.launcher -APP_NAME=Nethermind.Launcher -LIN_RELEASE=nethermind-lin-x64 -OSX_RELEASE=nethermind-osx-x64 -WIN_RELEASE=nethermind-win-x64 - -echo ======================================================= -echo Building Nethermind Launcher -echo ======================================================= - -cd $LAUNCHER_PATH - -nexe -t linux-x64-10.0.0 -o $APP_NAME && mv $APP_NAME ../$RELEASE_DIRECTORY/$LIN_RELEASE -nexe -t darwin-x64-10.0.0 -o $APP_NAME && mv $APP_NAME ../$RELEASE_DIRECTORY/$OSX_RELEASE -nexe -b true -t windows-x64-10.0.0 --ico neth.ico -o $APP_NAME.exe && mv $APP_NAME.exe ../$RELEASE_DIRECTORY/$WIN_RELEASE - -echo ======================================================= -echo Building Nethermind Launcher completed -echo ======================================================= diff --git a/scripts/packaging/build-launcher.sh b/scripts/packaging/build-launcher.sh deleted file mode 100644 index 633d8636457..00000000000 --- a/scripts/packaging/build-launcher.sh +++ /dev/null @@ -1,20 +0,0 @@ -RELEASE_DIRECTORY=nethermind-packages -LAUNCHER_PATH=nethermind.launcher -APP_NAME=Nethermind.Launcher -LIN_RELEASE=nethermind-lin-x64 -OSX_RELEASE=nethermind-osx-x64 -WIN_RELEASE=nethermind-win-x64 - -echo ======================================================= -echo Building Nethermind Launcher -echo ======================================================= - -cd $LAUNCHER_PATH -npm i -pkg index.js -t node12-linux -o $APP_NAME && mv $APP_NAME ../$RELEASE_DIRECTORY/$LIN_RELEASE -pkg index.js -t node12-osx -o $APP_NAME && mv $APP_NAME ../$RELEASE_DIRECTORY/$OSX_RELEASE -pkg index.js -t node12-win -o $APP_NAME.exe && mv $APP_NAME.exe ../$RELEASE_DIRECTORY/$WIN_RELEASE - -echo ======================================================= -echo Building Nethermind Launcher completed -echo ======================================================= diff --git a/scripts/packaging/build-packages.sh b/scripts/packaging/build-packages.sh deleted file mode 100644 index c2214cd61c1..00000000000 --- a/scripts/packaging/build-packages.sh +++ /dev/null @@ -1,13 +0,0 @@ -echo ======================================================= -echo Building Nethermind packages -echo ======================================================= - -if [ "$1" != "" ]; then - ./clone-all.sh $1 && ./setup-packages.sh && ./build-runner.sh && ./build-cli.sh && ./build-launcher.sh && ./archive-packages.sh && ./azure-upload.sh && ./slack-poster.sh -else - ./clone-all.sh && ./setup-packages.sh && ./build-runner.sh && ./build-cli.sh && ./build-launcher.sh && ./archive-packages.sh && ./azure-upload.sh && ./slack-poster.sh -fi - -echo ======================================================= -echo Building Nethermind completed -echo ======================================================= diff --git a/scripts/packaging/build-runner.sh b/scripts/packaging/build-runner.sh deleted file mode 100644 index 506e3bb891b..00000000000 --- a/scripts/packaging/build-runner.sh +++ /dev/null @@ -1,61 +0,0 @@ -RELEASE_DIRECTORY=../../../../nethermind-packages -RUNNER_PATH=nethermind/src/Nethermind/Nethermind.Runner -LINUX=linux-x64 -OSX=osx-x64 -WIN10=win10-x64 -PUBLISH_PATH=bin/release/netcoreapp3.1 -OUT=out -LIN_RELEASE=nethermind-lin-x64 -OSX_RELEASE=nethermind-osx-x64 -WIN_RELEASE=nethermind-win-x64 - -cd $RUNNER_PATH - -echo ======================================================= -echo Publishing Nethermind Runner for different platforms... -echo ======================================================= -echo Nethermind Runner path: $RUNNER_PATH - -rm -rf $OUT - -dotnet publish -c release -r $LINUX /p:PublishSingleFile=true -o $OUT/$LIN_RELEASE -dotnet publish -c release -r $OSX /p:PublishSingleFile=true -o $OUT/$OSX_RELEASE -dotnet publish -c release -r $WIN10 /p:PublishSingleFile=true -o $OUT/$WIN_RELEASE - -rm -rf $OUT/$LIN_RELEASE/Data -rm -rf $OUT/$LIN_RELEASE/Hive -rm $OUT/$LIN_RELEASE/Nethermind.Runner.pdb -rm $OUT/$LIN_RELEASE/web.config -cp -r configs $OUT/$LIN_RELEASE -cp -r ../Chains $OUT/$LIN_RELEASE/chainspec -mkdir $OUT/$LIN_RELEASE/Data -cp Data/static-nodes.json $OUT/$LIN_RELEASE/Data - -rm -rf $OUT/$OSX_RELEASE/Data -rm -rf $OUT/$OSX_RELEASE/Hive -rm $OUT/$OSX_RELEASE/Nethermind.Runner.pdb -rm $OUT/$OSX_RELEASE/web.config -cp -r configs $OUT/$OSX_RELEASE -cp -r ../Chains $OUT/$OSX_RELEASE/chainspec -mkdir $OUT/$OSX_RELEASE/Data -cp Data/static-nodes.json $OUT/$OSX_RELEASE/Data - -rm -rf $OUT/$WIN_RELEASE/Data -rm -rf $OUT/$WIN_RELEASE/Hive -rm $OUT/$WIN_RELEASE/Nethermind.Runner.pdb -rm $OUT/$WIN_RELEASE/web.config -cp -r configs $OUT/$WIN_RELEASE -cp -r ../Chains $OUT/$WIN_RELEASE/chainspec -mkdir $OUT/$WIN_RELEASE/Data -cp Data/static-nodes.json $OUT/$WIN_RELEASE/Data - -mv $OUT/$LIN_RELEASE $RELEASE_DIRECTORY -mv $OUT/$OSX_RELEASE $RELEASE_DIRECTORY -mv $OUT/$WIN_RELEASE $RELEASE_DIRECTORY - - -rm -rf $OUT - -echo ======================================================= -echo Building Nethermind Runner completed -echo ======================================================= diff --git a/scripts/packaging/clone-all.sh b/scripts/packaging/clone-all.sh deleted file mode 100644 index 60bc00b8c5b..00000000000 --- a/scripts/packaging/clone-all.sh +++ /dev/null @@ -1,15 +0,0 @@ -echo ======================================================= -echo Cloning Nethermind sources -echo ======================================================= - -if [ "$1" != "" ]; then - ./clone-runner.sh $1 - ./clone-launcher.sh -else - ./clone-runner.sh - ./clone-launcher.sh -fi - -echo ======================================================= -echo Cloning Nethermind sources completed -echo ======================================================= diff --git a/scripts/packaging/clone-launcher.sh b/scripts/packaging/clone-launcher.sh deleted file mode 100644 index a351724bcee..00000000000 --- a/scripts/packaging/clone-launcher.sh +++ /dev/null @@ -1,3 +0,0 @@ -echo Cloning Launcher -rm -rf nethermind.launcher -GIT_SSH_COMMAND='ssh -i ~/.ssh/id_rsa_nethermind' git clone git@github.com:NethermindEth/nethermind.launcher.git diff --git a/scripts/packaging/clone-runner.sh b/scripts/packaging/clone-runner.sh deleted file mode 100644 index 2f61975db9a..00000000000 --- a/scripts/packaging/clone-runner.sh +++ /dev/null @@ -1,7 +0,0 @@ -echo Cloning Runner -rm -rf nethermind -if [ "$1" != "" ]; then - GIT_SSH_COMMAND='ssh -i ~/.ssh/id_rsa_nethermind' git clone --branch $1 git@github.com:NethermindEth/nethermind.git --recursive -else - GIT_SSH_COMMAND='ssh -i ~/.ssh/id_rsa_nethermind' git clone git@github.com:NethermindEth/nethermind.git --recursive -fi diff --git a/scripts/packaging/setup-packages.sh b/scripts/packaging/setup-packages.sh deleted file mode 100644 index a5faf2143db..00000000000 --- a/scripts/packaging/setup-packages.sh +++ /dev/null @@ -1,39 +0,0 @@ -RELEASE_DIRECTORY=nethermind-packages -LIN_RELEASE=nethermind-lin-x64 -OSX_RELEASE=nethermind-osx-x64 -WIN_RELEASE=nethermind-win-x64 - -echo ======================================================= -echo Setting up Nethermind packages -echo ======================================================= - -DATE=`date +%Y%m%d` - -rm -rf $RELEASE_DIRECTORY -mkdir $RELEASE_DIRECTORY - -echo ======================================================= -echo Creating git-hash and git-tag files -echo ======================================================= -cd .. -cd ~/repo_pub/nethermind -GIT="$(git rev-parse --short=7 HEAD)" -GIT_TAG="$(git describe --tags)" -GIT_SHORT_TAG="$(echo $GIT_TAG | cut -d- -f1)" -GIT_TAG_LONG="$(git describe --tags --long)" -cd ~/repo_pub/$RELEASE_DIRECTORY -touch git-hash.txt -touch git-tag.txt -touch git-tag-long.txt -echo $GIT-$DATE> git-hash.txt -echo ${GIT_SHORT_TAG} > git-tag.txt -echo ${GIT_TAG_LONG} > git-tag-long.txt - -echo ======================================================= -echo Success, git-hash and git-tag files have been created -echo ======================================================= - -echo ======================================================= -echo Setting up Nethermind packages completed -echo ======================================================= - diff --git a/scripts/packaging/slack-poster.sh b/scripts/packaging/slack-poster.sh deleted file mode 100644 index 00f8a3482b3..00000000000 --- a/scripts/packaging/slack-poster.sh +++ /dev/null @@ -1,4 +0,0 @@ -GIT_HASH="$(tail ./nethermind-packages/git-hash.txt)" -GIT_TAG="$(tail ./nethermind-packages/git-tag.txt)" -# change title link to Azure containers endpoint -curl -X POST -H 'Content-type: application/json' --data '{"attachments":[{"color":"#36a64f","pretext":"Building and uploading packages has been finished.","title":"Azure Storage","title_link":"{{ Place link to Azure containers }}","fields":[{"title":"version","value":"'$GIT_TAG-$GIT_HASH'","short":false},{"title":"repo","value":"Public","short":false}]}]}' $PRIVATE_WEBHOOK_URL diff --git a/scripts/packaging/upload-github-release-asset.sh b/scripts/packaging/upload-github-release-asset.sh deleted file mode 100644 index 0888134c276..00000000000 --- a/scripts/packaging/upload-github-release-asset.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env bash -# -# Author: Stefan Buck -# License: MIT -# https://gist.github.com/stefanbuck/ce788fee19ab6eb0b4447a85fc99f447 -# -# -# This script accepts the following parameters: -# -# * owner -# * repo -# * tag -# * filename -# * github_api_token -# -# Script to upload a release asset using the GitHub API v3. -# -# Example: -# -# upload-github-release-asset.sh github_api_token=TOKEN owner=stefanbuck repo=playground tag=v0.1.0 filename=./build.zip -# - -# Check dependencies. - -set -e -xargs=$(which gxargs || which xargs) - -# Validate settings. -[ "$TRACE" ] && set -x - -CONFIG=$@ - -for line in $CONFIG; do - eval "$line" -done - -# Define variables. -GH_API="https://api.github.com" -GH_REPO="$GH_API/repos/$owner/$repo" -GH_TAGS="$GH_REPO/releases/tags/$tag" -AUTH="Authorization: token $github_api_token" -WGET_ARGS="--content-disposition --auth-no-challenge --no-cookie" -CURL_ARGS="-LJO#" - -if [[ "$tag" == 'LATEST' ]]; then - GH_TAGS="$GH_REPO/releases/latest" -fi - -# Validate token. -curl -o /dev/null -sH "$AUTH" $GH_REPO || { echo "Error: Invalid repo, token or network issue!"; exit 1; } - -# Read asset tags. -response=$(curl -sH "$AUTH" $GH_TAGS) - -# Get ID of the asset based on given filename. -eval $(echo "$response" | grep -m 1 "id.:" | grep -w id | tr : = | tr -cd '[[:alnum:]]=') -[ "$id" ] || { echo "Error: Failed to get release id for tag: $tag"; echo "$response" | awk 'length($0)<100' >&2; exit 1; } - -# Upload asset -echo "Uploading asset... " - -# Construct url -GH_ASSET="https://uploads.github.com/repos/$owner/$repo/releases/$id/assets?name=$(basename $filename)" - -curl "$GITHUB_OAUTH_BASIC" --data-binary @"$filename" -H "Authorization: token $github_api_token" -H "Content-Type: application/octet-stream" $GH_ASSET diff --git a/src/Nethermind/Directory.Build.props b/src/Nethermind/Directory.Build.props new file mode 100644 index 00000000000..d0b5cdfd817 --- /dev/null +++ b/src/Nethermind/Directory.Build.props @@ -0,0 +1,27 @@ + + + + Debug + + + + $([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()) + Demerzel Solutions Limited + Nethermind + $(Commit.Substring(0, 8)) + + 0.0.0 + + + + + <_Parameter1>BuildTimestamp + <_Parameter2>$(BuildTimestamp) + + + <_Parameter1>Commit + <_Parameter2>$(Commit) + + + + diff --git a/src/Nethermind/Nethermind.Cli/Console/CliConsole.cs b/src/Nethermind/Nethermind.Cli/Console/CliConsole.cs index 812745d6e93..9ba063348ca 100644 --- a/src/Nethermind/Nethermind.Cli/Console/CliConsole.cs +++ b/src/Nethermind/Nethermind.Cli/Console/CliConsole.cs @@ -20,135 +20,134 @@ using System.Runtime.InteropServices; using Nethermind.Core; -namespace Nethermind.Cli.Console +namespace Nethermind.Cli.Console; + +public class CliConsole : ICliConsole { - public class CliConsole : ICliConsole + private static ColorScheme _colorScheme = DraculaColorScheme.Instance; + + private static Terminal _terminal; + + private static readonly Dictionary Terminals = new Dictionary { - private static ColorScheme _colorScheme = DraculaColorScheme.Instance; - - private static Terminal _terminal; - - private static readonly Dictionary Terminals = new Dictionary - { - ["cmd.exe"] = Terminal.Cmd, - ["cmd"] = Terminal.Cmder, - ["powershell"] = Terminal.Powershell, - ["cygwin"] = Terminal.Cygwin - }; - - public Terminal Init(ColorScheme colorScheme) - { - _colorScheme = colorScheme; - Colorful.Console.BackgroundColor = colorScheme.BackgroundColor; - Colorful.Console.ForegroundColor = colorScheme.Text; - _terminal = GetTerminal(); - if (_terminal != Terminal.Powershell) - { - Colorful.Console.ResetColor(); - } + ["cmd.exe"] = Terminal.Cmd, + ["cmd"] = Terminal.Cmder, + ["powershell"] = Terminal.Powershell, + ["cygwin"] = Terminal.Cygwin + }; - if (_terminal != Terminal.Cygwin) - { - Colorful.Console.Clear(); - } - - string version = ClientVersion.Version; - - Colorful.Console.WriteLine("**********************************************", _colorScheme.Comment); - Colorful.Console.WriteLine(); - Colorful.Console.WriteLine("Nethermind CLI {0}", GetColor(_colorScheme.Good), version); - Colorful.Console.WriteLine(" https://github.com/NethermindEth/nethermind", GetColor(_colorScheme.Interesting)); - Colorful.Console.WriteLine(" https://nethermind.readthedocs.io/en/latest/", GetColor( _colorScheme.Interesting)); - Colorful.Console.WriteLine(); - Colorful.Console.WriteLine("powered by:", _colorScheme.Text); - Colorful.Console.WriteLine(" https://github.com/sebastienros/jint", GetColor( _colorScheme.Interesting)); - Colorful.Console.WriteLine(" https://github.com/tomakita/Colorful.Console", GetColor( _colorScheme.Interesting)); - Colorful.Console.WriteLine(" https://github.com/tonerdo/readline", GetColor( _colorScheme.Interesting)); - Colorful.Console.WriteLine(); - Colorful.Console.WriteLine("**********************************************", _colorScheme.Comment); - Colorful.Console.WriteLine(); - - return _terminal; - } - - private Terminal GetTerminal() + public Terminal Init(ColorScheme colorScheme) + { + _colorScheme = colorScheme; + Colorful.Console.BackgroundColor = colorScheme.BackgroundColor; + Colorful.Console.ForegroundColor = colorScheme.Text; + _terminal = GetTerminal(); + if (_terminal != Terminal.Powershell) { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? Terminal.LinuxBash : - RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? Terminal.MacBash : Terminal.Unknown; - } - - var title = Colorful.Console.Title.ToLowerInvariant(); - foreach (var (key, value) in Terminals) - { - if (title.Contains(key)) - { - return value; - } - } - - return Terminal.Unknown; + Colorful.Console.ResetColor(); } - private Color GetColor(Color defaultColor) - { - return _terminal == Terminal.LinuxBash ? _colorScheme.Text : defaultColor; - } - - public void WriteException(Exception e) - { - Colorful.Console.WriteLine(e.ToString(), GetColor(_colorScheme.ErrorColor)); - } - - public void WriteErrorLine(string errorMessage) + if (_terminal != Terminal.Cygwin) { - Colorful.Console.WriteLine(errorMessage, GetColor(_colorScheme.ErrorColor)); + Colorful.Console.Clear(); } - public void WriteLine(object objectToWrite) - { - Colorful.Console.WriteLine(objectToWrite.ToString(), _colorScheme.Text); - } + string version = ProductInfo.Version; - public void Write(object objectToWrite) - { - Colorful.Console.Write(objectToWrite.ToString(), _colorScheme.Text); - } + Colorful.Console.WriteLine("**********************************************", _colorScheme.Comment); + Colorful.Console.WriteLine(); + Colorful.Console.WriteLine("Nethermind CLI {0}", GetColor(_colorScheme.Good), version); + Colorful.Console.WriteLine(" https://github.com/NethermindEth/nethermind", GetColor(_colorScheme.Interesting)); + Colorful.Console.WriteLine(" https://nethermind.readthedocs.io/en/latest/", GetColor( _colorScheme.Interesting)); + Colorful.Console.WriteLine(); + Colorful.Console.WriteLine("powered by:", _colorScheme.Text); + Colorful.Console.WriteLine(" https://github.com/sebastienros/jint", GetColor( _colorScheme.Interesting)); + Colorful.Console.WriteLine(" https://github.com/tomakita/Colorful.Console", GetColor( _colorScheme.Interesting)); + Colorful.Console.WriteLine(" https://github.com/tonerdo/readline", GetColor( _colorScheme.Interesting)); + Colorful.Console.WriteLine(); + Colorful.Console.WriteLine("**********************************************", _colorScheme.Comment); + Colorful.Console.WriteLine(); - public void WriteCommentLine(object objectToWrite) - { - Colorful.Console.WriteLine(objectToWrite.ToString(), _colorScheme.Comment); - } - - public void WriteLessImportant(object objectToWrite) - { - Colorful.Console.Write(objectToWrite.ToString(), GetColor(_colorScheme.LessImportant)); - } - - public void WriteKeyword(string keyword) + return _terminal; + } + + private Terminal GetTerminal() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - Colorful.Console.Write(keyword, GetColor(_colorScheme.Keyword)); + return RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? Terminal.LinuxBash : + RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? Terminal.MacBash : Terminal.Unknown; } - public void WriteInteresting(string interesting) + var title = Colorful.Console.Title.ToLowerInvariant(); + foreach (var (key, value) in Terminals) { - Colorful.Console.WriteLine(interesting, GetColor(_colorScheme.Interesting)); + if (title.Contains(key)) + { + return value; + } } - public void WriteLine() - { - Colorful.Console.WriteLine(); - } + return Terminal.Unknown; + } - public void WriteGood(string goodText) - { - Colorful.Console.WriteLine(goodText, GetColor(_colorScheme.Good)); - } + private Color GetColor(Color defaultColor) + { + return _terminal == Terminal.LinuxBash ? _colorScheme.Text : defaultColor; + } + + public void WriteException(Exception e) + { + Colorful.Console.WriteLine(e.ToString(), GetColor(_colorScheme.ErrorColor)); + } + + public void WriteErrorLine(string errorMessage) + { + Colorful.Console.WriteLine(errorMessage, GetColor(_colorScheme.ErrorColor)); + } + + public void WriteLine(object objectToWrite) + { + Colorful.Console.WriteLine(objectToWrite.ToString(), _colorScheme.Text); + } - public void WriteString(object result) - { - Colorful.Console.WriteLine(result, GetColor(_colorScheme.String)); - } + public void Write(object objectToWrite) + { + Colorful.Console.Write(objectToWrite.ToString(), _colorScheme.Text); + } + + public void WriteCommentLine(object objectToWrite) + { + Colorful.Console.WriteLine(objectToWrite.ToString(), _colorScheme.Comment); + } + + public void WriteLessImportant(object objectToWrite) + { + Colorful.Console.Write(objectToWrite.ToString(), GetColor(_colorScheme.LessImportant)); + } + + public void WriteKeyword(string keyword) + { + Colorful.Console.Write(keyword, GetColor(_colorScheme.Keyword)); + } + + public void WriteInteresting(string interesting) + { + Colorful.Console.WriteLine(interesting, GetColor(_colorScheme.Interesting)); + } + + public void WriteLine() + { + Colorful.Console.WriteLine(); + } + + public void WriteGood(string goodText) + { + Colorful.Console.WriteLine(goodText, GetColor(_colorScheme.Good)); + } + + public void WriteString(object result) + { + Colorful.Console.WriteLine(result, GetColor(_colorScheme.String)); } } diff --git a/src/Nethermind/Nethermind.Consensus.Clique/CliqueBlockProducer.cs b/src/Nethermind/Nethermind.Consensus.Clique/CliqueBlockProducer.cs index 7df1f27fc89..363608ff103 100644 --- a/src/Nethermind/Nethermind.Consensus.Clique/CliqueBlockProducer.cs +++ b/src/Nethermind/Nethermind.Consensus.Clique/CliqueBlockProducer.cs @@ -37,429 +37,428 @@ using Nethermind.State; using Nethermind.State.Proofs; -namespace Nethermind.Consensus.Clique +namespace Nethermind.Consensus.Clique; + +public class CliqueBlockProducer : ICliqueBlockProducer, IDisposable { - public class CliqueBlockProducer : ICliqueBlockProducer, IDisposable + private readonly IBlockTree _blockTree; + private readonly IStateProvider _stateProvider; + private readonly ITimestamper _timestamper; + private readonly ILogger _logger; + private readonly ICryptoRandom _cryptoRandom; + private readonly WiggleRandomizer _wiggle; + + private readonly ITxSource _txSource; + private readonly IBlockchainProcessor _processor; + private readonly ISealer _sealer; + private readonly IGasLimitCalculator _gasLimitCalculator; + private readonly ISpecProvider _specProvider; + private readonly ISnapshotManager _snapshotManager; + private readonly ICliqueConfig _config; + + private readonly ConcurrentDictionary _proposals = new(); + + private readonly CancellationTokenSource _cancellationTokenSource = new(); + private readonly System.Timers.Timer _timer = new(); + private DateTime _lastProducedBlock; + + public CliqueBlockProducer( + ITxSource txSource, + IBlockchainProcessor blockchainProcessor, + IStateProvider stateProvider, + IBlockTree blockTree, + ITimestamper timestamper, + ICryptoRandom cryptoRandom, + ISnapshotManager snapshotManager, + ISealer cliqueSealer, + IGasLimitCalculator gasLimitCalculator, + ISpecProvider? specProvider, + ICliqueConfig config, + ILogManager logManager) { - private readonly IBlockTree _blockTree; - private readonly IStateProvider _stateProvider; - private readonly ITimestamper _timestamper; - private readonly ILogger _logger; - private readonly ICryptoRandom _cryptoRandom; - private readonly WiggleRandomizer _wiggle; - - private readonly ITxSource _txSource; - private readonly IBlockchainProcessor _processor; - private readonly ISealer _sealer; - private readonly IGasLimitCalculator _gasLimitCalculator; - private readonly ISpecProvider _specProvider; - private readonly ISnapshotManager _snapshotManager; - private readonly ICliqueConfig _config; - - private readonly ConcurrentDictionary _proposals = new(); - - private readonly CancellationTokenSource _cancellationTokenSource = new(); - private readonly System.Timers.Timer _timer = new(); - private DateTime _lastProducedBlock; - - public CliqueBlockProducer( - ITxSource txSource, - IBlockchainProcessor blockchainProcessor, - IStateProvider stateProvider, - IBlockTree blockTree, - ITimestamper timestamper, - ICryptoRandom cryptoRandom, - ISnapshotManager snapshotManager, - ISealer cliqueSealer, - IGasLimitCalculator gasLimitCalculator, - ISpecProvider? specProvider, - ICliqueConfig config, - ILogManager logManager) - { - _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); - _txSource = txSource ?? throw new ArgumentNullException(nameof(txSource)); - _processor = blockchainProcessor ?? throw new ArgumentNullException(nameof(blockchainProcessor)); - _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); - _stateProvider = stateProvider ?? throw new ArgumentNullException(nameof(stateProvider)); - _timestamper = timestamper ?? throw new ArgumentNullException(nameof(timestamper)); - _cryptoRandom = cryptoRandom ?? throw new ArgumentNullException(nameof(cryptoRandom)); - _sealer = cliqueSealer ?? throw new ArgumentNullException(nameof(cliqueSealer)); - _gasLimitCalculator = gasLimitCalculator ?? throw new ArgumentNullException(nameof(gasLimitCalculator)); - _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); - _snapshotManager = snapshotManager ?? throw new ArgumentNullException(nameof(snapshotManager)); - _config = config ?? throw new ArgumentNullException(nameof(config)); - _wiggle = new WiggleRandomizer(_cryptoRandom, _snapshotManager); - - _timer.AutoReset = false; - _timer.Elapsed += TimerOnElapsed; - _timer.Interval = 100; - _timer.Start(); - } + _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); + _txSource = txSource ?? throw new ArgumentNullException(nameof(txSource)); + _processor = blockchainProcessor ?? throw new ArgumentNullException(nameof(blockchainProcessor)); + _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); + _stateProvider = stateProvider ?? throw new ArgumentNullException(nameof(stateProvider)); + _timestamper = timestamper ?? throw new ArgumentNullException(nameof(timestamper)); + _cryptoRandom = cryptoRandom ?? throw new ArgumentNullException(nameof(cryptoRandom)); + _sealer = cliqueSealer ?? throw new ArgumentNullException(nameof(cliqueSealer)); + _gasLimitCalculator = gasLimitCalculator ?? throw new ArgumentNullException(nameof(gasLimitCalculator)); + _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); + _snapshotManager = snapshotManager ?? throw new ArgumentNullException(nameof(snapshotManager)); + _config = config ?? throw new ArgumentNullException(nameof(config)); + _wiggle = new WiggleRandomizer(_cryptoRandom, _snapshotManager); + + _timer.AutoReset = false; + _timer.Elapsed += TimerOnElapsed; + _timer.Interval = 100; + _timer.Start(); + } - private readonly BlockingCollection _signalsQueue = - new(new ConcurrentQueue()); + private readonly BlockingCollection _signalsQueue = + new(new ConcurrentQueue()); - private Block? _scheduledBlock; + private Block? _scheduledBlock; - public void CastVote(Address signer, bool vote) + public void CastVote(Address signer, bool vote) + { + bool success = _proposals.TryAdd(signer, vote); + if (!success) { - bool success = _proposals.TryAdd(signer, vote); - if (!success) - { - throw new InvalidOperationException($"A vote for {signer} has already been cast."); - } - - if (_logger.IsWarn) _logger.Warn($"Added Clique vote for {signer} - {vote}"); + throw new InvalidOperationException($"A vote for {signer} has already been cast."); } - public void UncastVote(Address signer) - { - bool success = _proposals.TryRemove(signer, out _); - if (!success) - { - throw new InvalidOperationException("Cannot uncast vote"); - } - - if (_logger.IsWarn) _logger.Warn($"Removed Clique vote for {signer}"); - } + if (_logger.IsWarn) _logger.Warn($"Added Clique vote for {signer} - {vote}"); + } - public void ProduceOnTopOf(Keccak hash) + public void UncastVote(Address signer) + { + bool success = _proposals.TryRemove(signer, out _); + if (!success) { - _signalsQueue.Add(_blockTree.FindBlock(hash, BlockTreeLookupOptions.None)); + throw new InvalidOperationException("Cannot uncast vote"); } - private void TimerOnElapsed(object sender, ElapsedEventArgs e) + if (_logger.IsWarn) _logger.Warn($"Removed Clique vote for {signer}"); + } + + public void ProduceOnTopOf(Keccak hash) + { + _signalsQueue.Add(_blockTree.FindBlock(hash, BlockTreeLookupOptions.None)); + } + + private void TimerOnElapsed(object sender, ElapsedEventArgs e) + { + try { - try + if (_blockTree.Head == null) { - if (_blockTree.Head == null) - { - _timer.Enabled = true; - return; - } + _timer.Enabled = true; + return; + } - Block? scheduledBlock = _scheduledBlock; - if (scheduledBlock == null) + Block? scheduledBlock = _scheduledBlock; + if (scheduledBlock == null) + { + if (_blockTree.Head.Timestamp + _config.BlockPeriod < _timestamper.UnixTime.Seconds) { - if (_blockTree.Head.Timestamp + _config.BlockPeriod < _timestamper.UnixTime.Seconds) - { - _signalsQueue.Add(_blockTree.FindBlock(_blockTree.Head.Hash, BlockTreeLookupOptions.None)); - } - - _timer.Enabled = true; - return; + _signalsQueue.Add(_blockTree.FindBlock(_blockTree.Head.Hash, BlockTreeLookupOptions.None)); } - string turnDescription = scheduledBlock.IsInTurn() ? "IN TURN" : "OUT OF TURN"; + _timer.Enabled = true; + return; + } - int wiggle = _wiggle.WiggleFor(scheduledBlock.Header); - if (scheduledBlock.Timestamp * 1000 + (UInt256)wiggle < _timestamper.UnixTime.Milliseconds) + string turnDescription = scheduledBlock.IsInTurn() ? "IN TURN" : "OUT OF TURN"; + + int wiggle = _wiggle.WiggleFor(scheduledBlock.Header); + if (scheduledBlock.Timestamp * 1000 + (UInt256)wiggle < _timestamper.UnixTime.Milliseconds) + { + if (scheduledBlock.TotalDifficulty > _blockTree.Head.TotalDifficulty) { - if (scheduledBlock.TotalDifficulty > _blockTree.Head.TotalDifficulty) + if (ReferenceEquals(scheduledBlock, _scheduledBlock)) { - if (ReferenceEquals(scheduledBlock, _scheduledBlock)) - { - BlockHeader parent = _blockTree.FindParentHeader(scheduledBlock.Header, - BlockTreeLookupOptions.TotalDifficultyNotNeeded); - Address parentSigner = _snapshotManager.GetBlockSealer(parent); + BlockHeader parent = _blockTree.FindParentHeader(scheduledBlock.Header, + BlockTreeLookupOptions.TotalDifficultyNotNeeded); + Address parentSigner = _snapshotManager.GetBlockSealer(parent); - string parentTurnDescription = parent.IsInTurn() ? "IN TURN" : "OUT OF TURN"; - string parentDetails = - $"{parentTurnDescription} {parent.TimestampDate:HH:mm:ss} {parent.ToString(BlockHeader.Format.Short)} sealed by {KnownAddresses.GetDescription(parentSigner)}"; + string parentTurnDescription = parent.IsInTurn() ? "IN TURN" : "OUT OF TURN"; + string parentDetails = + $"{parentTurnDescription} {parent.TimestampDate:HH:mm:ss} {parent.ToString(BlockHeader.Format.Short)} sealed by {KnownAddresses.GetDescription(parentSigner)}"; - if (_logger.IsInfo) - _logger.Info( - $"Suggesting own {turnDescription} {_scheduledBlock.TimestampDate:HH:mm:ss} {scheduledBlock.ToString(Block.Format.HashNumberDiffAndTx)} based on {parentDetails} after the delay of {wiggle}"); - BlockProduced?.Invoke(this, new BlockEventArgs(scheduledBlock)); - } - } - else - { if (_logger.IsInfo) _logger.Info( - $"Dropping a losing block {scheduledBlock.ToString(Block.Format.HashNumberDiffAndTx)}"); - } - - if (ReferenceEquals(scheduledBlock, _scheduledBlock)) - { - _scheduledBlock = null; + $"Suggesting own {turnDescription} {_scheduledBlock.TimestampDate:HH:mm:ss} {scheduledBlock.ToString(Block.Format.HashNumberDiffAndTx)} based on {parentDetails} after the delay of {wiggle}"); + BlockProduced?.Invoke(this, new BlockEventArgs(scheduledBlock)); } } else { - if (_logger.IsTrace) - _logger.Trace($"Not yet {scheduledBlock.ToString(Block.Format.HashNumberDiffAndTx)}"); + if (_logger.IsInfo) + _logger.Info( + $"Dropping a losing block {scheduledBlock.ToString(Block.Format.HashNumberDiffAndTx)}"); } - _timer.Enabled = true; + if (ReferenceEquals(scheduledBlock, _scheduledBlock)) + { + _scheduledBlock = null; + } } - catch (Exception exception) + else { - if (_logger.IsError) _logger.Error("Clique block producer failure", exception); + if (_logger.IsTrace) + _logger.Trace($"Not yet {scheduledBlock.ToString(Block.Format.HashNumberDiffAndTx)}"); } + + _timer.Enabled = true; + } + catch (Exception exception) + { + if (_logger.IsError) _logger.Error("Clique block producer failure", exception); } + } - private Task? _producerTask; + private Task? _producerTask; - public Task Start() + public Task Start() + { + _blockTree.NewHeadBlock += BlockTreeOnNewHeadBlock; + _producerTask = Task.Factory.StartNew( + ConsumeSignal, + _cancellationTokenSource.Token, + TaskCreationOptions.LongRunning, + TaskScheduler.Default).ContinueWith(t => { - _blockTree.NewHeadBlock += BlockTreeOnNewHeadBlock; - _producerTask = Task.Factory.StartNew( - ConsumeSignal, - _cancellationTokenSource.Token, - TaskCreationOptions.LongRunning, - TaskScheduler.Default).ContinueWith(t => + if (t.IsFaulted) { - if (t.IsFaulted) - { - if (_logger.IsError) _logger.Error("Clique block producer encountered an exception.", t.Exception); - } - else if (t.IsCanceled) - { - if (_logger.IsDebug) _logger.Debug("Clique block producer stopped."); - } - else if (t.IsCompleted) - { - if (_logger.IsDebug) _logger.Debug("Clique block producer complete."); - } - }); - return Task.CompletedTask; - } + if (_logger.IsError) _logger.Error("Clique block producer encountered an exception.", t.Exception); + } + else if (t.IsCanceled) + { + if (_logger.IsDebug) _logger.Debug("Clique block producer stopped."); + } + else if (t.IsCompleted) + { + if (_logger.IsDebug) _logger.Debug("Clique block producer complete."); + } + }); + return Task.CompletedTask; + } - private void BlockTreeOnNewHeadBlock(object? sender, BlockEventArgs e) - { - _signalsQueue.Add(e.Block); - } + private void BlockTreeOnNewHeadBlock(object? sender, BlockEventArgs e) + { + _signalsQueue.Add(e.Block); + } - private void ConsumeSignal() + private void ConsumeSignal() + { + _lastProducedBlock = DateTime.UtcNow; + foreach (Block signal in _signalsQueue.GetConsumingEnumerable(_cancellationTokenSource.Token)) { - _lastProducedBlock = DateTime.UtcNow; - foreach (Block signal in _signalsQueue.GetConsumingEnumerable(_cancellationTokenSource.Token)) + Block parentBlock = signal; + while (_signalsQueue.TryTake(out Block? nextSignal)) { - Block parentBlock = signal; - while (_signalsQueue.TryTake(out Block? nextSignal)) + if (parentBlock.Number <= nextSignal.Number) { - if (parentBlock.Number <= nextSignal.Number) - { - parentBlock = nextSignal; - } + parentBlock = nextSignal; } + } - try + try + { + Block? block = PrepareBlock(parentBlock); + if (block is null) { - Block? block = PrepareBlock(parentBlock); - if (block is null) - { - if (_logger.IsTrace) _logger.Trace("Skipping block production or block production failed"); - Metrics.FailedBlockSeals++; - continue; - } + if (_logger.IsTrace) _logger.Trace("Skipping block production or block production failed"); + Metrics.FailedBlockSeals++; + continue; + } - if (_logger.IsInfo) _logger.Info($"Processing prepared block {block.Number}"); - Block? processedBlock = _processor.Process( - block, - ProcessingOptions.ProducingBlock, - NullBlockTracer.Instance); - if (processedBlock is null) - { - if (_logger.IsInfo) _logger.Info($"Prepared block has lost the race"); - Metrics.FailedBlockSeals++; - continue; - } + if (_logger.IsInfo) _logger.Info($"Processing prepared block {block.Number}"); + Block? processedBlock = _processor.Process( + block, + ProcessingOptions.ProducingBlock, + NullBlockTracer.Instance); + if (processedBlock is null) + { + if (_logger.IsInfo) _logger.Info($"Prepared block has lost the race"); + Metrics.FailedBlockSeals++; + continue; + } - if (_logger.IsDebug) _logger.Debug($"Sealing prepared block {processedBlock.Number}"); + if (_logger.IsDebug) _logger.Debug($"Sealing prepared block {processedBlock.Number}"); - _sealer.SealBlock(processedBlock, _cancellationTokenSource.Token).ContinueWith(t => + _sealer.SealBlock(processedBlock, _cancellationTokenSource.Token).ContinueWith(t => + { + if (t.IsCompletedSuccessfully) { - if (t.IsCompletedSuccessfully) - { - if (t.Result != null) - { - if (_logger.IsInfo) - _logger.Info($"Sealed block {t.Result.ToString(Block.Format.HashNumberDiffAndTx)}"); - _scheduledBlock = t.Result; - _lastProducedBlock = DateTime.UtcNow; - Metrics.BlocksSealed++; - } - else - { - if (_logger.IsInfo) - _logger.Info( - $"Failed to seal block {processedBlock.ToString(Block.Format.HashNumberDiffAndTx)} (null seal)"); - Metrics.FailedBlockSeals++; - } - } - else if (t.IsFaulted) + if (t.Result != null) { - if (_logger.IsError) _logger.Error("Mining failed", t.Exception); - Metrics.FailedBlockSeals++; + if (_logger.IsInfo) + _logger.Info($"Sealed block {t.Result.ToString(Block.Format.HashNumberDiffAndTx)}"); + _scheduledBlock = t.Result; + _lastProducedBlock = DateTime.UtcNow; + Metrics.BlocksSealed++; } - else if (t.IsCanceled) + else { - if (_logger.IsInfo) _logger.Info($"Sealing block {processedBlock.Number} cancelled"); + if (_logger.IsInfo) + _logger.Info( + $"Failed to seal block {processedBlock.ToString(Block.Format.HashNumberDiffAndTx)} (null seal)"); Metrics.FailedBlockSeals++; } - }, _cancellationTokenSource.Token); - } - catch (Exception e) - { - if (_logger.IsError) - _logger.Error( - $"Block producer could not produce block on top of {parentBlock.ToString(Block.Format.Short)}", - e); - Metrics.FailedBlockSeals++; - } + } + else if (t.IsFaulted) + { + if (_logger.IsError) _logger.Error("Mining failed", t.Exception); + Metrics.FailedBlockSeals++; + } + else if (t.IsCanceled) + { + if (_logger.IsInfo) _logger.Info($"Sealing block {processedBlock.Number} cancelled"); + Metrics.FailedBlockSeals++; + } + }, _cancellationTokenSource.Token); + } + catch (Exception e) + { + if (_logger.IsError) + _logger.Error( + $"Block producer could not produce block on top of {parentBlock.ToString(Block.Format.Short)}", + e); + Metrics.FailedBlockSeals++; } } + } - public async Task StopAsync() - { - _blockTree.NewHeadBlock -= BlockTreeOnNewHeadBlock; - _cancellationTokenSource?.Cancel(); - await (_producerTask ?? Task.CompletedTask); - } + public async Task StopAsync() + { + _blockTree.NewHeadBlock -= BlockTreeOnNewHeadBlock; + _cancellationTokenSource?.Cancel(); + await (_producerTask ?? Task.CompletedTask); + } - bool IBlockProducer.IsProducingBlocks(ulong? maxProducingInterval) - { - if (_producerTask == null || _producerTask.IsCompleted) - return false; - if (maxProducingInterval != null) - return _lastProducedBlock.AddSeconds(maxProducingInterval.Value) > DateTime.UtcNow; - else - return true; - } + bool IBlockProducer.IsProducingBlocks(ulong? maxProducingInterval) + { + if (_producerTask == null || _producerTask.IsCompleted) + return false; + if (maxProducingInterval != null) + return _lastProducedBlock.AddSeconds(maxProducingInterval.Value) > DateTime.UtcNow; + else + return true; + } - public event EventHandler? BlockProduced; + public event EventHandler? BlockProduced; - private Keccak? _recentNotAllowedParent; + private Keccak? _recentNotAllowedParent; - private Block? PrepareBlock(Block parentBlock) + private Block? PrepareBlock(Block parentBlock) + { + BlockHeader parentHeader = parentBlock.Header; + if (parentHeader.Hash == null) { - BlockHeader parentHeader = parentBlock.Header; - if (parentHeader.Hash == null) - { - if (_logger.IsError) _logger.Error( - $"Preparing new block on top of {parentHeader.ToString(BlockHeader.Format.Short)} - parent header hash is null"); - return null; - } + if (_logger.IsError) _logger.Error( + $"Preparing new block on top of {parentHeader.ToString(BlockHeader.Format.Short)} - parent header hash is null"); + return null; + } - if (_recentNotAllowedParent == parentBlock.Hash) - { - return null; - } + if (_recentNotAllowedParent == parentBlock.Hash) + { + return null; + } - if (!_sealer.CanSeal(parentHeader.Number + 1, parentHeader.Hash)) - { - if (_logger.IsTrace) _logger.Trace($"Not allowed to sign block ({parentBlock.Number + 1})"); - _recentNotAllowedParent = parentHeader.Hash; - return null; - } + if (!_sealer.CanSeal(parentHeader.Number + 1, parentHeader.Hash)) + { + if (_logger.IsTrace) _logger.Trace($"Not allowed to sign block ({parentBlock.Number + 1})"); + _recentNotAllowedParent = parentHeader.Hash; + return null; + } - if (_logger.IsInfo) - _logger.Info($"Preparing new block on top of {parentBlock.ToString(Block.Format.Short)}"); - - UInt256 timestamp = _timestamper.UnixTime.Seconds; - IReleaseSpec spec = _specProvider.GetSpec(parentHeader.Number + 1); - - BlockHeader header = new ( - parentHeader.Hash, - Keccak.OfAnEmptySequenceRlp, - Address.Zero, - 1, - parentBlock.Number + 1, - _gasLimitCalculator.GetGasLimit(parentBlock.Header), - timestamp > parentBlock.Timestamp ? timestamp : parentBlock.Timestamp + 1, - Array.Empty()); - - // If the block isn't a checkpoint, cast a random vote (good enough for now) - long number = header.Number; - // Assemble the voting snapshot to check which votes make sense - Snapshot snapshot = _snapshotManager.GetOrCreateSnapshot(number - 1, parentHeader.Hash); - bool isEpochBlock = (ulong)number % 30000 == 0; - if (!isEpochBlock && _proposals.Any()) + if (_logger.IsInfo) + _logger.Info($"Preparing new block on top of {parentBlock.ToString(Block.Format.Short)}"); + + UInt256 timestamp = _timestamper.UnixTime.Seconds; + IReleaseSpec spec = _specProvider.GetSpec(parentHeader.Number + 1); + + BlockHeader header = new ( + parentHeader.Hash, + Keccak.OfAnEmptySequenceRlp, + Address.Zero, + 1, + parentBlock.Number + 1, + _gasLimitCalculator.GetGasLimit(parentBlock.Header), + timestamp > parentBlock.Timestamp ? timestamp : parentBlock.Timestamp + 1, + Array.Empty()); + + // If the block isn't a checkpoint, cast a random vote (good enough for now) + long number = header.Number; + // Assemble the voting snapshot to check which votes make sense + Snapshot snapshot = _snapshotManager.GetOrCreateSnapshot(number - 1, parentHeader.Hash); + bool isEpochBlock = (ulong)number % 30000 == 0; + if (!isEpochBlock && _proposals.Any()) + { + // Gather all the proposals that make sense voting on + List
addresses = new(); + foreach ((Address address, bool authorize) in _proposals) { - // Gather all the proposals that make sense voting on - List
addresses = new(); - foreach ((Address address, bool authorize) in _proposals) + if (_snapshotManager.IsValidVote(snapshot, address, authorize)) { - if (_snapshotManager.IsValidVote(snapshot, address, authorize)) - { - addresses.Add(address); - } - } - - // If there's pending proposals, cast a vote on them - if (addresses.Count > 0) - { - header.Beneficiary = addresses[_cryptoRandom.NextInt(addresses.Count)]; - if (_proposals.TryGetValue(header.Beneficiary!, out bool proposal)) - { - header.Nonce = proposal ? Clique.NonceAuthVote : Clique.NonceDropVote; - } + addresses.Add(address); } } - // Set the correct difficulty - header.BaseFeePerGas = BaseFeeCalculator.Calculate(parentHeader, _specProvider.GetSpec(header.Number)); - header.Difficulty = CalculateDifficulty(snapshot, _sealer.Address); - header.TotalDifficulty = parentBlock.TotalDifficulty + header.Difficulty; - if (_logger.IsDebug) - _logger.Debug($"Setting total difficulty to {parentBlock.TotalDifficulty} + {header.Difficulty}."); - - // Set extra data - int mainBytesLength = Clique.ExtraVanityLength + Clique.ExtraSealLength; - int signerBytesLength = isEpochBlock ? 20 * snapshot.Signers.Count : 0; - int extraDataLength = mainBytesLength + signerBytesLength; - header.ExtraData = new byte[extraDataLength]; - header.Bloom = Bloom.Empty; - - byte[] clientName = Encoding.UTF8.GetBytes("Nethermind " + ClientVersion.Version); - Array.Copy(clientName, header.ExtraData, clientName.Length); - - if (isEpochBlock) + // If there's pending proposals, cast a vote on them + if (addresses.Count > 0) { - for (int i = 0; i < snapshot.Signers.Keys.Count; i++) + header.Beneficiary = addresses[_cryptoRandom.NextInt(addresses.Count)]; + if (_proposals.TryGetValue(header.Beneficiary!, out bool proposal)) { - Address signer = snapshot.Signers.Keys[i]; - int index = Clique.ExtraVanityLength + 20 * i; - Array.Copy(signer.Bytes, 0, header.ExtraData, index, signer.Bytes.Length); + header.Nonce = proposal ? Clique.NonceAuthVote : Clique.NonceDropVote; } } + } - // Mix digest is reserved for now, set to empty - header.MixHash = Keccak.Zero; - // Ensure the timestamp has the correct delay - header.Timestamp = parentBlock.Timestamp + _config.BlockPeriod; - if (header.Timestamp < _timestamper.UnixTime.Seconds) - { - header.Timestamp = new UInt256(_timestamper.UnixTime.Seconds); - } + // Set the correct difficulty + header.BaseFeePerGas = BaseFeeCalculator.Calculate(parentHeader, _specProvider.GetSpec(header.Number)); + header.Difficulty = CalculateDifficulty(snapshot, _sealer.Address); + header.TotalDifficulty = parentBlock.TotalDifficulty + header.Difficulty; + if (_logger.IsDebug) + _logger.Debug($"Setting total difficulty to {parentBlock.TotalDifficulty} + {header.Difficulty}."); - _stateProvider.StateRoot = parentHeader.StateRoot!; - - IEnumerable selectedTxs = _txSource.GetTransactions(parentBlock.Header, header.GasLimit); - Block block = new BlockToProduce(header, selectedTxs, Array.Empty()); - header.TxRoot = new TxTrie(block.Transactions).RootHash; - block.Header.Author = _sealer.Address; - return block; - } + // Set extra data + int mainBytesLength = Clique.ExtraVanityLength + Clique.ExtraSealLength; + int signerBytesLength = isEpochBlock ? 20 * snapshot.Signers.Count : 0; + int extraDataLength = mainBytesLength + signerBytesLength; + header.ExtraData = new byte[extraDataLength]; + header.Bloom = Bloom.Empty; - private UInt256 CalculateDifficulty(Snapshot snapshot, Address signer) + byte[] clientName = Encoding.UTF8.GetBytes($"{ProductInfo.Name} {ProductInfo.Version}"); + Array.Copy(clientName, header.ExtraData, clientName.Length); + + if (isEpochBlock) { - if (_snapshotManager.IsInTurn(snapshot, snapshot.Number + 1, signer)) + for (int i = 0; i < snapshot.Signers.Keys.Count; i++) { - if (_logger.IsInfo) _logger.Info("Producing in turn block"); - return Clique.DifficultyInTurn; + Address signer = snapshot.Signers.Keys[i]; + int index = Clique.ExtraVanityLength + 20 * i; + Array.Copy(signer.Bytes, 0, header.ExtraData, index, signer.Bytes.Length); } + } - if (_logger.IsInfo) _logger.Info("Producing out of turn block"); - return Clique.DifficultyNoTurn; + // Mix digest is reserved for now, set to empty + header.MixHash = Keccak.Zero; + // Ensure the timestamp has the correct delay + header.Timestamp = parentBlock.Timestamp + _config.BlockPeriod; + if (header.Timestamp < _timestamper.UnixTime.Seconds) + { + header.Timestamp = new UInt256(_timestamper.UnixTime.Seconds); } - public void Dispose() + _stateProvider.StateRoot = parentHeader.StateRoot!; + + IEnumerable selectedTxs = _txSource.GetTransactions(parentBlock.Header, header.GasLimit); + Block block = new BlockToProduce(header, selectedTxs, Array.Empty()); + header.TxRoot = new TxTrie(block.Transactions).RootHash; + block.Header.Author = _sealer.Address; + return block; + } + + private UInt256 CalculateDifficulty(Snapshot snapshot, Address signer) + { + if (_snapshotManager.IsInTurn(snapshot, snapshot.Number + 1, signer)) { - _cancellationTokenSource?.Dispose(); - _timer?.Dispose(); + if (_logger.IsInfo) _logger.Info("Producing in turn block"); + return Clique.DifficultyInTurn; } + + if (_logger.IsInfo) _logger.Info("Producing out of turn block"); + return Clique.DifficultyNoTurn; + } + + public void Dispose() + { + _cancellationTokenSource?.Dispose(); + _timer?.Dispose(); } } diff --git a/src/Nethermind/Nethermind.Core/ClientVersion.cs b/src/Nethermind/Nethermind.Core/ClientVersion.cs deleted file mode 100644 index 441566a7426..00000000000 --- a/src/Nethermind/Nethermind.Core/ClientVersion.cs +++ /dev/null @@ -1,41 +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 System; -using System.IO; -using System.Runtime.InteropServices; - -namespace Nethermind.Core -{ - public static class ClientVersion - { - private static readonly string _gitTag; - - private static readonly string _date; - - static ClientVersion() - { - _date = DateTime.UtcNow.ToString("yyyyMMdd"); - _gitTag = File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory!, "git-hash")) ? File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory!, "git-hash")).Trim().Replace("g", string.Empty) : string.Empty; - - Description = $"Nethermind/v{Version}/{RuntimeInformation.OSArchitecture}-{Platform.GetPlatformName()}/{RuntimeInformation.FrameworkDescription.Trim().Replace(".NET ", string.Empty).Replace(" ", string.Empty)}"; - } - - public static string Version => $"{_gitTag}-{_date}"; - - public static string Description { get; } - } -} diff --git a/src/Nethermind/Nethermind.Core/ProductInfo.cs b/src/Nethermind/Nethermind.Core/ProductInfo.cs new file mode 100644 index 00000000000..9c93c864dca --- /dev/null +++ b/src/Nethermind/Nethermind.Core/ProductInfo.cs @@ -0,0 +1,63 @@ +// 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 System; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace Nethermind.Core; + +public static class ProductInfo +{ + static ProductInfo() + { + var assembly = Assembly.GetEntryAssembly(); + var infoAttr = assembly?.GetCustomAttribute(); + var metadataAttrs = assembly?.GetCustomAttributes(); + var productAttr = assembly?.GetCustomAttribute(); + var commit = metadataAttrs?.FirstOrDefault(a => a.Key.Equals("Commit", StringComparison.Ordinal))?.Value; + var timestamp = metadataAttrs?.FirstOrDefault(a => a.Key.Equals("BuildTimestamp", StringComparison.Ordinal))?.Value; + + BuildTimestamp = long.TryParse(timestamp, out var t) + ? DateTimeOffset.FromUnixTimeSeconds(t) + : DateTimeOffset.MinValue; + Commit = commit ?? string.Empty; + Name = productAttr?.Product ?? "Nethermind"; + OS = Platform.GetPlatformName(); + OSArchitecture = RuntimeInformation.OSArchitecture.ToString().ToLowerInvariant(); + Runtime = RuntimeInformation.FrameworkDescription; + Version = infoAttr?.InformationalVersion ?? string.Empty; + + ClientId = $"{Name}/v{Version}/{OS.ToLowerInvariant()}-{OSArchitecture}/dotnet{Runtime[5..]}"; + } + + public static DateTimeOffset BuildTimestamp { get; } + + public static string ClientId { get; } + + public static string Commit { get; } + + public static string Name { get; } + + public static string OS { get; } + + public static string OSArchitecture { get; } + + public static string Runtime { get; } + + public static string Version { get; } +} diff --git a/src/Nethermind/Nethermind.EthStats/EthStatsPlugin.cs b/src/Nethermind/Nethermind.EthStats/EthStatsPlugin.cs index edf1fa21bfb..dabc57cd753 100644 --- a/src/Nethermind/Nethermind.EthStats/EthStatsPlugin.cs +++ b/src/Nethermind/Nethermind.EthStats/EthStatsPlugin.cs @@ -28,108 +28,107 @@ using Nethermind.Network.P2P; using ILogger = Nethermind.Logging.ILogger; -namespace Nethermind.EthStats +namespace Nethermind.EthStats; + +public class EthStatsPlugin : INethermindPlugin { - public class EthStatsPlugin : INethermindPlugin + private IEthStatsConfig _ethStatsConfig = null!; + private IEthStatsClient _ethStatsClient = null!; + private IEthStatsIntegration _ethStatsIntegration = null!; + private INethermindApi _api = null!; + private ILogger _logger = null!; + + private bool _isOn; + + public string Name => "EthStats"; + public string Description => "Ethereum Statistics"; + public string Author => "Nethermind"; + + public ValueTask DisposeAsync() { - private IEthStatsConfig _ethStatsConfig = null!; - private IEthStatsClient _ethStatsClient = null!; - private IEthStatsIntegration _ethStatsIntegration = null!; - private INethermindApi _api = null!; - private ILogger _logger = null!; + _ethStatsIntegration?.Dispose(); + return ValueTask.CompletedTask; + } - private bool _isOn; + public Task Init(INethermindApi nethermindApi) + { + _api = nethermindApi; + var (getFromAPi, _) = _api.ForInit; + _ethStatsConfig = getFromAPi.Config(); - public string Name => "EthStats"; - public string Description => "Ethereum Statistics"; - public string Author => "Nethermind"; + IInitConfig initConfig = getFromAPi.Config(); + _isOn = _ethStatsConfig.Enabled; + _logger = getFromAPi.LogManager.GetClassLogger(); - public ValueTask DisposeAsync() + if (!_isOn) { - _ethStatsIntegration?.Dispose(); - return ValueTask.CompletedTask; + + if (!initConfig.WebSocketsEnabled) + { + _logger.Warn($"{nameof(EthStatsPlugin)} disabled due to {nameof(initConfig.WebSocketsEnabled)} set to false"); + } + else + { + _logger.Warn($"{nameof(EthStatsPlugin)} plugin disabled due to {nameof(EthStatsConfig)} settings set to false"); + } } - public Task Init(INethermindApi nethermindApi) - { - _api = nethermindApi; - var (getFromAPi, _) = _api.ForInit; - _ethStatsConfig = getFromAPi.Config(); + return Task.CompletedTask; + } - IInitConfig initConfig = getFromAPi.Config(); - _isOn = _ethStatsConfig.Enabled; - _logger = getFromAPi.LogManager.GetClassLogger(); + public async Task InitNetworkProtocol() + { + var (getFromAPi, _) = _api.ForNetwork; + INetworkConfig networkConfig = _api.Config(); + IInitConfig initConfig = _api.Config(); - if (!_isOn) + if (_isOn) + { + string instanceId = $"{_ethStatsConfig.Name}-{Keccak.Compute(getFromAPi.Enode!.Info)}"; + if (_logger.IsInfo) { - - if (!initConfig.WebSocketsEnabled) - { - _logger.Warn($"{nameof(EthStatsPlugin)} disabled due to {nameof(initConfig.WebSocketsEnabled)} set to false"); - } - else - { - _logger.Warn($"{nameof(EthStatsPlugin)} plugin disabled due to {nameof(EthStatsConfig)} settings set to false"); - } + _logger.Info($"Initializing ETH Stats for the instance: {instanceId}, server: {_ethStatsConfig.Server}"); } + MessageSender sender = new(instanceId, _api.LogManager); + const int reconnectionInterval = 5000; + const string api = "no"; + const string client = "0.1.1"; + const bool canUpdateHistory = false; + string node = ProductInfo.ClientId; + int port = networkConfig.P2PPort; + string network = _api.SpecProvider!.ChainId.ToString(); + string protocol = $"{P2PProtocolInfoProvider.DefaultCapabilitiesToString()}"; - return Task.CompletedTask; - } + _ethStatsClient = new EthStatsClient( + _ethStatsConfig.Server, + reconnectionInterval, + sender, + _api.LogManager); - public async Task InitNetworkProtocol() - { - var (getFromAPi, _) = _api.ForNetwork; - INetworkConfig networkConfig = _api.Config(); - IInitConfig initConfig = _api.Config(); + _ethStatsIntegration = new EthStatsIntegration( + _ethStatsConfig.Name!, + node, + port, + network, + protocol, + api, + client, + _ethStatsConfig.Contact!, + canUpdateHistory, + _ethStatsConfig.Secret!, + _ethStatsClient, + sender, + getFromAPi.TxPool, + getFromAPi.BlockTree, + getFromAPi.PeerManager, + getFromAPi.GasPriceOracle, + getFromAPi.EthSyncingInfo!, + initConfig.IsMining, + getFromAPi.LogManager); - if (_isOn) - { - string instanceId = $"{_ethStatsConfig.Name}-{Keccak.Compute(getFromAPi.Enode!.Info)}"; - if (_logger.IsInfo) - { - _logger.Info($"Initializing ETH Stats for the instance: {instanceId}, server: {_ethStatsConfig.Server}"); - } - MessageSender sender = new(instanceId, _api.LogManager); - const int reconnectionInterval = 5000; - const string api = "no"; - const string client = "0.1.1"; - const bool canUpdateHistory = false; - string node = ClientVersion.Description; - int port = networkConfig.P2PPort; - string network = _api.SpecProvider!.ChainId.ToString(); - string protocol = $"{P2PProtocolInfoProvider.DefaultCapabilitiesToString()}"; - - _ethStatsClient = new EthStatsClient( - _ethStatsConfig.Server, - reconnectionInterval, - sender, - _api.LogManager); - - _ethStatsIntegration = new EthStatsIntegration( - _ethStatsConfig.Name!, - node, - port, - network, - protocol, - api, - client, - _ethStatsConfig.Contact!, - canUpdateHistory, - _ethStatsConfig.Secret!, - _ethStatsClient, - sender, - getFromAPi.TxPool, - getFromAPi.BlockTree, - getFromAPi.PeerManager, - getFromAPi.GasPriceOracle, - getFromAPi.EthSyncingInfo!, - initConfig.IsMining, - getFromAPi.LogManager); - - await _ethStatsIntegration.InitAsync(); - } + await _ethStatsIntegration.InitAsync(); } - - public Task InitRpcModules() => Task.CompletedTask; } + + public Task InitRpcModules() => Task.CompletedTask; } diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs index 1e5d1a42072..2d406052b5f 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeNetwork.cs @@ -52,510 +52,509 @@ using Nethermind.Synchronization.Reporting; using Nethermind.Synchronization.SnapSync; -namespace Nethermind.Init.Steps +namespace Nethermind.Init.Steps; + +public static class NettyMemoryEstimator { - public static class NettyMemoryEstimator + // Environment.SetEnvironmentVariable("io.netty.allocator.pageSize", "8192"); + private const uint PageSize = 8192; + + public static long Estimate(uint cpuCount, int arenaOrder) { - // Environment.SetEnvironmentVariable("io.netty.allocator.pageSize", "8192"); - private const uint PageSize = 8192; + // do not remember why there is 2 in front + return 2L * cpuCount * (1L << arenaOrder) * PageSize; + } +} - public static long Estimate(uint cpuCount, int arenaOrder) - { - // do not remember why there is 2 in front - return 2L * cpuCount * (1L << arenaOrder) * PageSize; - } +[RunnerStepDependencies( + typeof(LoadGenesisBlock), + typeof(UpdateDiscoveryConfig), + typeof(SetupKeyStore), + typeof(InitializeNodeStats), + typeof(ResolveIps), + typeof(InitializePlugins), + typeof(InitializeBlockchain))] +public class InitializeNetwork : IStep +{ + private const string DiscoveryNodesDbPath = "discoveryNodes"; + private const string PeersDbPath = "peers"; + + protected readonly IApiWithNetwork _api; + private readonly ILogger _logger; + private readonly INetworkConfig _networkConfig; + protected readonly ISyncConfig _syncConfig; + + public InitializeNetwork(INethermindApi api) + { + _api = api; + _logger = _api.LogManager.GetClassLogger(); + _networkConfig = _api.Config(); + _syncConfig = _api.Config(); } - [RunnerStepDependencies( - typeof(LoadGenesisBlock), - typeof(UpdateDiscoveryConfig), - typeof(SetupKeyStore), - typeof(InitializeNodeStats), - typeof(ResolveIps), - typeof(InitializePlugins), - typeof(InitializeBlockchain))] - public class InitializeNetwork : IStep + public async Task Execute(CancellationToken cancellationToken) { - private const string DiscoveryNodesDbPath = "discoveryNodes"; - private const string PeersDbPath = "peers"; + await Initialize(cancellationToken); + } - protected readonly IApiWithNetwork _api; - private readonly ILogger _logger; - private readonly INetworkConfig _networkConfig; - protected readonly ISyncConfig _syncConfig; + private async Task Initialize(CancellationToken cancellationToken) + { + if (_api.DbProvider == null) throw new StepDependencyException(nameof(_api.DbProvider)); - public InitializeNetwork(INethermindApi api) + if (_networkConfig.DiagTracerEnabled) { - _api = api; - _logger = _api.LogManager.GetClassLogger(); - _networkConfig = _api.Config(); - _syncConfig = _api.Config(); + NetworkDiagTracer.IsEnabled = true; } - public async Task Execute(CancellationToken cancellationToken) + if (NetworkDiagTracer.IsEnabled) { - await Initialize(cancellationToken); + NetworkDiagTracer.Start(_api.LogManager); } - private async Task Initialize(CancellationToken cancellationToken) + Environment.SetEnvironmentVariable("io.netty.allocator.maxOrder", _networkConfig.NettyArenaOrder.ToString()); + CanonicalHashTrie cht = new CanonicalHashTrie(_api.DbProvider!.ChtDb); + + ProgressTracker progressTracker = new(_api.BlockTree!, _api.DbProvider.StateDb, _api.LogManager); + _api.SnapProvider = new SnapProvider(progressTracker, _api.DbProvider, _api.LogManager); + + SyncProgressResolver syncProgressResolver = new( + _api.BlockTree!, + _api.ReceiptStorage!, + _api.DbProvider.StateDb, + _api.ReadOnlyTrieStore!, + progressTracker, + _syncConfig, + _api.LogManager); + + _api.SyncProgressResolver = syncProgressResolver; + _api.BetterPeerStrategy = new TotalDifficultyBetterPeerStrategy(_api.LogManager); + + int maxPeersCount = _networkConfig.ActivePeersMaxCount; + int maxPriorityPeersCount = _networkConfig.PriorityPeersMaxCount; + SyncPeerPool apiSyncPeerPool = new(_api.BlockTree!, _api.NodeStatsManager!, _api.BetterPeerStrategy, maxPeersCount, maxPriorityPeersCount, SyncPeerPool.DefaultUpgradeIntervalInMs, _api.LogManager); + _api.SyncPeerPool = apiSyncPeerPool; + _api.PeerDifficultyRefreshPool = apiSyncPeerPool; + _api.DisposeStack.Push(_api.SyncPeerPool); + + IEnumerable synchronizationPlugins = _api.GetSynchronizationPlugins(); + foreach (ISynchronizationPlugin plugin in synchronizationPlugins) { - if (_api.DbProvider == null) throw new StepDependencyException(nameof(_api.DbProvider)); - - if (_networkConfig.DiagTracerEnabled) - { - NetworkDiagTracer.IsEnabled = true; - } + await plugin.InitSynchronization(); + } - if (NetworkDiagTracer.IsEnabled) - { - NetworkDiagTracer.Start(_api.LogManager); - } + _api.SyncModeSelector ??= CreateMultiSyncModeSelector(syncProgressResolver); + _api.DisposeStack.Push(_api.SyncModeSelector); - Environment.SetEnvironmentVariable("io.netty.allocator.maxOrder", _networkConfig.NettyArenaOrder.ToString()); - CanonicalHashTrie cht = new CanonicalHashTrie(_api.DbProvider!.ChtDb); + _api.Pivot ??= new Pivot(_syncConfig); - ProgressTracker progressTracker = new(_api.BlockTree!, _api.DbProvider.StateDb, _api.LogManager); - _api.SnapProvider = new SnapProvider(progressTracker, _api.DbProvider, _api.LogManager); + if (_api.BlockDownloaderFactory is null || _api.Synchronizer is null) + { + SyncReport syncReport = new(_api.SyncPeerPool!, _api.NodeStatsManager!, _api.SyncModeSelector, _syncConfig, _api.Pivot, _api.LogManager); - SyncProgressResolver syncProgressResolver = new( + _api.BlockDownloaderFactory ??= new BlockDownloaderFactory(_api.SpecProvider!, _api.BlockTree!, _api.ReceiptStorage!, - _api.DbProvider.StateDb, - _api.ReadOnlyTrieStore!, - progressTracker, - _syncConfig, + _api.BlockValidator!, + _api.SealValidator!, + _api.SyncPeerPool!, + _api.BetterPeerStrategy!, + syncReport, _api.LogManager); - - _api.SyncProgressResolver = syncProgressResolver; - _api.BetterPeerStrategy = new TotalDifficultyBetterPeerStrategy(_api.LogManager); - - int maxPeersCount = _networkConfig.ActivePeersMaxCount; - int maxPriorityPeersCount = _networkConfig.PriorityPeersMaxCount; - SyncPeerPool apiSyncPeerPool = new(_api.BlockTree!, _api.NodeStatsManager!, _api.BetterPeerStrategy, maxPeersCount, maxPriorityPeersCount, SyncPeerPool.DefaultUpgradeIntervalInMs, _api.LogManager); - _api.SyncPeerPool = apiSyncPeerPool; - _api.PeerDifficultyRefreshPool = apiSyncPeerPool; - _api.DisposeStack.Push(_api.SyncPeerPool); - - IEnumerable synchronizationPlugins = _api.GetSynchronizationPlugins(); - foreach (ISynchronizationPlugin plugin in synchronizationPlugins) - { - await plugin.InitSynchronization(); - } - - _api.SyncModeSelector ??= CreateMultiSyncModeSelector(syncProgressResolver); - _api.DisposeStack.Push(_api.SyncModeSelector); - - _api.Pivot ??= new Pivot(_syncConfig); - - if (_api.BlockDownloaderFactory is null || _api.Synchronizer is null) - { - SyncReport syncReport = new(_api.SyncPeerPool!, _api.NodeStatsManager!, _api.SyncModeSelector, _syncConfig, _api.Pivot, _api.LogManager); - - _api.BlockDownloaderFactory ??= new BlockDownloaderFactory(_api.SpecProvider!, - _api.BlockTree!, - _api.ReceiptStorage!, - _api.BlockValidator!, - _api.SealValidator!, - _api.SyncPeerPool!, - _api.BetterPeerStrategy!, - syncReport, - _api.LogManager); - _api.Synchronizer ??= new Synchronizer( - _api.DbProvider, - _api.SpecProvider!, - _api.BlockTree!, - _api.ReceiptStorage!, - _api.SyncPeerPool, - _api.NodeStatsManager!, - _api.SyncModeSelector, - _syncConfig, - _api.SnapProvider, - _api.BlockDownloaderFactory, - _api.Pivot, - syncReport, - _api.LogManager); - } - - _api.DisposeStack.Push(_api.Synchronizer); - - _api.SyncServer = new SyncServer( - _api.TrieStore!, - _api.DbProvider.CodeDb, + _api.Synchronizer ??= new Synchronizer( + _api.DbProvider, + _api.SpecProvider!, _api.BlockTree!, _api.ReceiptStorage!, - _api.BlockValidator!, - _api.SealValidator!, _api.SyncPeerPool, + _api.NodeStatsManager!, _api.SyncModeSelector, - _api.Config(), - _api.WitnessRepository, - _api.GossipPolicy, - _api.SpecProvider!, - _api.LogManager, - cht); - - _ = _api.SyncServer.BuildCHT(); - _api.DisposeStack.Push(_api.SyncServer); - - InitDiscovery(); - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await InitPeer().ContinueWith(initPeerTask => - { - if (initPeerTask.IsFaulted) - { - _logger.Error("Unable to init the peer manager.", initPeerTask.Exception); - } - }); - - if (_syncConfig.SnapSync) - { - SnapCapabilitySwitcher snapCapabilitySwitcher = new(_api.ProtocolsManager, progressTracker); - snapCapabilitySwitcher.EnableSnapCapabilityUntilSynced(); - } - - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await StartSync().ContinueWith(initNetTask => - { - if (initNetTask.IsFaulted) - { - _logger.Error("Unable to start the synchronizer.", initNetTask.Exception); - } - }); - - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await StartDiscovery().ContinueWith(initDiscoveryTask => - { - if (initDiscoveryTask.IsFaulted) - { - _logger.Error("Unable to start the discovery protocol.", initDiscoveryTask.Exception); - } - }); - - try - { - if (cancellationToken.IsCancellationRequested) - { - return; - } + _syncConfig, + _api.SnapProvider, + _api.BlockDownloaderFactory, + _api.Pivot, + syncReport, + _api.LogManager); + } - StartPeer(); - } - catch (Exception e) - { - _logger.Error("Unable to start the peer manager.", e); - } + _api.DisposeStack.Push(_api.Synchronizer); + + _api.SyncServer = new SyncServer( + _api.TrieStore!, + _api.DbProvider.CodeDb, + _api.BlockTree!, + _api.ReceiptStorage!, + _api.BlockValidator!, + _api.SealValidator!, + _api.SyncPeerPool, + _api.SyncModeSelector, + _api.Config(), + _api.WitnessRepository, + _api.GossipPolicy, + _api.SpecProvider!, + _api.LogManager, + cht); + + _ = _api.SyncServer.BuildCHT(); + _api.DisposeStack.Push(_api.SyncServer); + + InitDiscovery(); + if (cancellationToken.IsCancellationRequested) + { + return; + } - if (_api.Enode == null) + await InitPeer().ContinueWith(initPeerTask => + { + if (initPeerTask.IsFaulted) { - throw new InvalidOperationException("Cannot initialize network without knowing own enode"); + _logger.Error("Unable to init the peer manager.", initPeerTask.Exception); } + }); - ThisNodeInfo.AddInfo("Ethereum :", $"tcp://{_api.Enode.HostIp}:{_api.Enode.Port}"); - ThisNodeInfo.AddInfo("Version :", $"{ClientVersion.Description.Replace("Nethermind/v", string.Empty)}"); - ThisNodeInfo.AddInfo("This node :", $"{_api.Enode.Info}"); - ThisNodeInfo.AddInfo("Node address :", $"{_api.Enode.Address} (do not use as an account)"); + if (_syncConfig.SnapSync) + { + SnapCapabilitySwitcher snapCapabilitySwitcher = new(_api.ProtocolsManager, progressTracker); + snapCapabilitySwitcher.EnableSnapCapabilityUntilSynced(); } - protected virtual MultiSyncModeSelector CreateMultiSyncModeSelector(SyncProgressResolver syncProgressResolver) - => new(syncProgressResolver, _api.SyncPeerPool!, _syncConfig, No.BeaconSync, _api.BetterPeerStrategy!, _api.LogManager, _api.ChainSpec?.SealEngineType == SealEngineType.Clique); - - private Task StartDiscovery() + if (cancellationToken.IsCancellationRequested) { - if (_api.DiscoveryApp == null) throw new StepDependencyException(nameof(_api.DiscoveryApp)); + return; + } - if (!_api.Config().DiscoveryEnabled) + await StartSync().ContinueWith(initNetTask => + { + if (initNetTask.IsFaulted) { - if (_logger.IsWarn) _logger.Warn($"Skipping discovery init due to {nameof(IInitConfig.DiscoveryEnabled)} set to false"); - return Task.CompletedTask; + _logger.Error("Unable to start the synchronizer.", initNetTask.Exception); } + }); - if (_logger.IsDebug) _logger.Debug("Starting discovery process."); - _api.DiscoveryApp.Start(); - if (_logger.IsDebug) _logger.Debug("Discovery process started."); - return Task.CompletedTask; + if (cancellationToken.IsCancellationRequested) + { + return; } - private void StartPeer() + await StartDiscovery().ContinueWith(initDiscoveryTask => { - if (_api.PeerManager == null) throw new StepDependencyException(nameof(_api.PeerManager)); - if (_api.SessionMonitor == null) throw new StepDependencyException(nameof(_api.SessionMonitor)); - if (_api.PeerPool == null) throw new StepDependencyException(nameof(_api.PeerPool)); - - if (!_api.Config().PeerManagerEnabled) + if (initDiscoveryTask.IsFaulted) { - if (_logger.IsWarn) _logger.Warn($"Skipping peer manager init due to {nameof(IInitConfig.PeerManagerEnabled)} set to false"); + _logger.Error("Unable to start the discovery protocol.", initDiscoveryTask.Exception); } + }); - if (_logger.IsDebug) _logger.Debug("Initializing peer manager"); - _api.PeerPool.Start(); - _api.PeerManager.Start(); - _api.SessionMonitor.Start(); - if (_logger.IsDebug) _logger.Debug("Peer manager initialization completed"); - } - - private void InitDiscovery() + try { - if (_api.NodeStatsManager == null) throw new StepDependencyException(nameof(_api.NodeStatsManager)); - if (_api.Timestamper == null) throw new StepDependencyException(nameof(_api.Timestamper)); - if (_api.NodeKey == null) throw new StepDependencyException(nameof(_api.NodeKey)); - if (_api.CryptoRandom == null) throw new StepDependencyException(nameof(_api.CryptoRandom)); - if (_api.EthereumEcdsa == null) throw new StepDependencyException(nameof(_api.EthereumEcdsa)); - - if (!_api.Config().DiscoveryEnabled) + if (cancellationToken.IsCancellationRequested) { - _api.DiscoveryApp = new NullDiscoveryApp(); return; } - IDiscoveryConfig discoveryConfig = _api.Config(); + StartPeer(); + } + catch (Exception e) + { + _logger.Error("Unable to start the peer manager.", e); + } - SameKeyGenerator privateKeyProvider = new(_api.NodeKey.Unprotect()); - NodeIdResolver nodeIdResolver = new(_api.EthereumEcdsa); + if (_api.Enode == null) + { + throw new InvalidOperationException("Cannot initialize network without knowing own enode"); + } - NodeRecord selfNodeRecord = PrepareNodeRecord(privateKeyProvider); - IDiscoveryMsgSerializersProvider msgSerializersProvider = new DiscoveryMsgSerializersProvider( - _api.MessageSerializationService, - _api.EthereumEcdsa, - privateKeyProvider, - nodeIdResolver); + ThisNodeInfo.AddInfo("Ethereum :", $"tcp://{_api.Enode.HostIp}:{_api.Enode.Port}"); + ThisNodeInfo.AddInfo("Client id :", ProductInfo.ClientId); + ThisNodeInfo.AddInfo("This node :", $"{_api.Enode.Info}"); + ThisNodeInfo.AddInfo("Node address :", $"{_api.Enode.Address} (do not use as an account)"); + } - msgSerializersProvider.RegisterDiscoverySerializers(); + protected virtual MultiSyncModeSelector CreateMultiSyncModeSelector(SyncProgressResolver syncProgressResolver) + => new(syncProgressResolver, _api.SyncPeerPool!, _syncConfig, No.BeaconSync, _api.BetterPeerStrategy!, _api.LogManager, _api.ChainSpec?.SealEngineType == SealEngineType.Clique); - NodeDistanceCalculator nodeDistanceCalculator = new(discoveryConfig); + private Task StartDiscovery() + { + if (_api.DiscoveryApp == null) throw new StepDependencyException(nameof(_api.DiscoveryApp)); - NodeTable nodeTable = new(nodeDistanceCalculator, discoveryConfig, _networkConfig, _api.LogManager); - EvictionManager evictionManager = new(nodeTable, _api.LogManager); + if (!_api.Config().DiscoveryEnabled) + { + if (_logger.IsWarn) _logger.Warn($"Skipping discovery init due to {nameof(IInitConfig.DiscoveryEnabled)} set to false"); + return Task.CompletedTask; + } - NodeLifecycleManagerFactory nodeLifeCycleFactory = new( - nodeTable, - evictionManager, - _api.NodeStatsManager, - selfNodeRecord, - discoveryConfig, - _api.Timestamper, - _api.LogManager); + if (_logger.IsDebug) _logger.Debug("Starting discovery process."); + _api.DiscoveryApp.Start(); + if (_logger.IsDebug) _logger.Debug("Discovery process started."); + return Task.CompletedTask; + } - // ToDo: DiscoveryDB is registered outside dbProvider - bad - SimpleFilePublicKeyDb discoveryDb = new( - "DiscoveryDB", - DiscoveryNodesDbPath.GetApplicationResourcePath(_api.Config().BaseDbPath), - _api.LogManager); + private void StartPeer() + { + if (_api.PeerManager == null) throw new StepDependencyException(nameof(_api.PeerManager)); + if (_api.SessionMonitor == null) throw new StepDependencyException(nameof(_api.SessionMonitor)); + if (_api.PeerPool == null) throw new StepDependencyException(nameof(_api.PeerPool)); - NetworkStorage discoveryStorage = new( - discoveryDb, - _api.LogManager); + if (!_api.Config().PeerManagerEnabled) + { + if (_logger.IsWarn) _logger.Warn($"Skipping peer manager init due to {nameof(IInitConfig.PeerManagerEnabled)} set to false"); + } - DiscoveryManager discoveryManager = new( - nodeLifeCycleFactory, - nodeTable, - discoveryStorage, - discoveryConfig, - _api.LogManager - ); - - NodesLocator nodesLocator = new( - nodeTable, - discoveryManager, - discoveryConfig, - _api.LogManager); + if (_logger.IsDebug) _logger.Debug("Initializing peer manager"); + _api.PeerPool.Start(); + _api.PeerManager.Start(); + _api.SessionMonitor.Start(); + if (_logger.IsDebug) _logger.Debug("Peer manager initialization completed"); + } - _api.DiscoveryApp = new DiscoveryApp( - nodesLocator, - discoveryManager, - nodeTable, - _api.MessageSerializationService, - _api.CryptoRandom, - discoveryStorage, - _networkConfig, - discoveryConfig, - _api.Timestamper, - _api.LogManager); + private void InitDiscovery() + { + if (_api.NodeStatsManager == null) throw new StepDependencyException(nameof(_api.NodeStatsManager)); + if (_api.Timestamper == null) throw new StepDependencyException(nameof(_api.Timestamper)); + if (_api.NodeKey == null) throw new StepDependencyException(nameof(_api.NodeKey)); + if (_api.CryptoRandom == null) throw new StepDependencyException(nameof(_api.CryptoRandom)); + if (_api.EthereumEcdsa == null) throw new StepDependencyException(nameof(_api.EthereumEcdsa)); - _api.DiscoveryApp.Initialize(_api.NodeKey.PublicKey); + if (!_api.Config().DiscoveryEnabled) + { + _api.DiscoveryApp = new NullDiscoveryApp(); + return; } - private NodeRecord PrepareNodeRecord(SameKeyGenerator privateKeyProvider) - { - NodeRecord selfNodeRecord = new(); - selfNodeRecord.SetEntry(IdEntry.Instance); - selfNodeRecord.SetEntry(new IpEntry(_api.IpResolver!.ExternalIp)); - selfNodeRecord.SetEntry(new TcpEntry(_networkConfig.P2PPort)); - selfNodeRecord.SetEntry(new UdpEntry(_networkConfig.DiscoveryPort)); - selfNodeRecord.SetEntry(new Secp256K1Entry(_api.NodeKey!.CompressedPublicKey)); - selfNodeRecord.EnrSequence = 1; - NodeRecordSigner enrSigner = new(_api.EthereumEcdsa, privateKeyProvider.Generate()); - enrSigner.Sign(selfNodeRecord); - if (!enrSigner.Verify(selfNodeRecord)) - { - throw new NetworkingException("Self ENR initialization failed", NetworkExceptionType.Discovery); - } + IDiscoveryConfig discoveryConfig = _api.Config(); + + SameKeyGenerator privateKeyProvider = new(_api.NodeKey.Unprotect()); + NodeIdResolver nodeIdResolver = new(_api.EthereumEcdsa); + + NodeRecord selfNodeRecord = PrepareNodeRecord(privateKeyProvider); + IDiscoveryMsgSerializersProvider msgSerializersProvider = new DiscoveryMsgSerializersProvider( + _api.MessageSerializationService, + _api.EthereumEcdsa, + privateKeyProvider, + nodeIdResolver); + + msgSerializersProvider.RegisterDiscoverySerializers(); + + NodeDistanceCalculator nodeDistanceCalculator = new(discoveryConfig); + + NodeTable nodeTable = new(nodeDistanceCalculator, discoveryConfig, _networkConfig, _api.LogManager); + EvictionManager evictionManager = new(nodeTable, _api.LogManager); + + NodeLifecycleManagerFactory nodeLifeCycleFactory = new( + nodeTable, + evictionManager, + _api.NodeStatsManager, + selfNodeRecord, + discoveryConfig, + _api.Timestamper, + _api.LogManager); + + // ToDo: DiscoveryDB is registered outside dbProvider - bad + SimpleFilePublicKeyDb discoveryDb = new( + "DiscoveryDB", + DiscoveryNodesDbPath.GetApplicationResourcePath(_api.Config().BaseDbPath), + _api.LogManager); + + NetworkStorage discoveryStorage = new( + discoveryDb, + _api.LogManager); + + DiscoveryManager discoveryManager = new( + nodeLifeCycleFactory, + nodeTable, + discoveryStorage, + discoveryConfig, + _api.LogManager + ); + + NodesLocator nodesLocator = new( + nodeTable, + discoveryManager, + discoveryConfig, + _api.LogManager); + + _api.DiscoveryApp = new DiscoveryApp( + nodesLocator, + discoveryManager, + nodeTable, + _api.MessageSerializationService, + _api.CryptoRandom, + discoveryStorage, + _networkConfig, + discoveryConfig, + _api.Timestamper, + _api.LogManager); + + _api.DiscoveryApp.Initialize(_api.NodeKey.PublicKey); + } - return selfNodeRecord; + private NodeRecord PrepareNodeRecord(SameKeyGenerator privateKeyProvider) + { + NodeRecord selfNodeRecord = new(); + selfNodeRecord.SetEntry(IdEntry.Instance); + selfNodeRecord.SetEntry(new IpEntry(_api.IpResolver!.ExternalIp)); + selfNodeRecord.SetEntry(new TcpEntry(_networkConfig.P2PPort)); + selfNodeRecord.SetEntry(new UdpEntry(_networkConfig.DiscoveryPort)); + selfNodeRecord.SetEntry(new Secp256K1Entry(_api.NodeKey!.CompressedPublicKey)); + selfNodeRecord.EnrSequence = 1; + NodeRecordSigner enrSigner = new(_api.EthereumEcdsa, privateKeyProvider.Generate()); + enrSigner.Sign(selfNodeRecord); + if (!enrSigner.Verify(selfNodeRecord)) + { + throw new NetworkingException("Self ENR initialization failed", NetworkExceptionType.Discovery); } - private Task StartSync() + return selfNodeRecord; + } + + private Task StartSync() + { + if (_api.SyncPeerPool == null) throw new StepDependencyException(nameof(_api.SyncPeerPool)); + if (_api.Synchronizer == null) throw new StepDependencyException(nameof(_api.Synchronizer)); + if (_api.BlockTree == null) throw new StepDependencyException(nameof(_api.BlockTree)); + + ISyncConfig syncConfig = _api.Config(); + if (syncConfig.NetworkingEnabled) { - if (_api.SyncPeerPool == null) throw new StepDependencyException(nameof(_api.SyncPeerPool)); - if (_api.Synchronizer == null) throw new StepDependencyException(nameof(_api.Synchronizer)); - if (_api.BlockTree == null) throw new StepDependencyException(nameof(_api.BlockTree)); + _api.SyncPeerPool!.Start(); - ISyncConfig syncConfig = _api.Config(); - if (syncConfig.NetworkingEnabled) + if (syncConfig.SynchronizationEnabled) { - _api.SyncPeerPool!.Start(); - - if (syncConfig.SynchronizationEnabled) - { - if (_logger.IsDebug) _logger.Debug($"Starting synchronization from block {_api.BlockTree.Head?.Header.ToString(BlockHeader.Format.Short)}."); - _api.Synchronizer!.Start(); - } - else - { - if (_logger.IsWarn) _logger.Warn($"Skipping blockchain synchronization init due to {nameof(ISyncConfig.SynchronizationEnabled)} set to false"); - } + if (_logger.IsDebug) _logger.Debug($"Starting synchronization from block {_api.BlockTree.Head?.Header.ToString(BlockHeader.Format.Short)}."); + _api.Synchronizer!.Start(); + } + else + { + if (_logger.IsWarn) _logger.Warn($"Skipping blockchain synchronization init due to {nameof(ISyncConfig.SynchronizationEnabled)} set to false"); } - else if (_logger.IsWarn) _logger.Warn($"Skipping connecting to peers due to {nameof(ISyncConfig.NetworkingEnabled)} set to false"); - - - return Task.CompletedTask; } + else if (_logger.IsWarn) _logger.Warn($"Skipping connecting to peers due to {nameof(ISyncConfig.NetworkingEnabled)} set to false"); - private async Task InitPeer() - { - if (_api.DbProvider == null) throw new StepDependencyException(nameof(_api.DbProvider)); - if (_api.BlockTree == null) throw new StepDependencyException(nameof(_api.BlockTree)); - if (_api.ReceiptStorage == null) throw new StepDependencyException(nameof(_api.ReceiptStorage)); - if (_api.BlockValidator == null) throw new StepDependencyException(nameof(_api.BlockValidator)); - if (_api.SyncPeerPool == null) throw new StepDependencyException(nameof(_api.SyncPeerPool)); - if (_api.Synchronizer == null) throw new StepDependencyException(nameof(_api.Synchronizer)); - if (_api.Enode == null) throw new StepDependencyException(nameof(_api.Enode)); - if (_api.NodeKey == null) throw new StepDependencyException(nameof(_api.NodeKey)); - if (_api.MainBlockProcessor == null) throw new StepDependencyException(nameof(_api.MainBlockProcessor)); - if (_api.NodeStatsManager == null) throw new StepDependencyException(nameof(_api.NodeStatsManager)); - if (_api.KeyStore == null) throw new StepDependencyException(nameof(_api.KeyStore)); - if (_api.Wallet == null) throw new StepDependencyException(nameof(_api.Wallet)); - if (_api.EthereumEcdsa == null) throw new StepDependencyException(nameof(_api.EthereumEcdsa)); - if (_api.SpecProvider == null) throw new StepDependencyException(nameof(_api.SpecProvider)); - if (_api.TxPool == null) throw new StepDependencyException(nameof(_api.TxPool)); - if (_api.TxSender == null) throw new StepDependencyException(nameof(_api.TxSender)); - if (_api.EthereumJsonSerializer == null) throw new StepDependencyException(nameof(_api.EthereumJsonSerializer)); - if (_api.DiscoveryApp == null) throw new StepDependencyException(nameof(_api.DiscoveryApp)); - - /* rlpx */ - EciesCipher eciesCipher = new(_api.CryptoRandom); - Eip8MessagePad eip8Pad = new(_api.CryptoRandom); - _api.MessageSerializationService.Register(new AuthEip8MessageSerializer(eip8Pad)); - _api.MessageSerializationService.Register(new AckEip8MessageSerializer(eip8Pad)); - _api.MessageSerializationService.Register(Assembly.GetAssembly(typeof(HelloMessageSerializer))!); - ReceiptsMessageSerializer receiptsMessageSerializer = new(_api.SpecProvider); - _api.MessageSerializationService.Register(receiptsMessageSerializer); - _api.MessageSerializationService.Register(new Network.P2P.Subprotocols.Eth.V66.Messages.ReceiptsMessageSerializer(receiptsMessageSerializer)); - - HandshakeService encryptionHandshakeServiceA = new( - _api.MessageSerializationService, - eciesCipher, - _api.CryptoRandom, - _api.EthereumEcdsa, - _api.NodeKey.Unprotect(), - _api.LogManager); - - IDiscoveryConfig discoveryConfig = _api.Config(); - // TODO: hack, but changing it in all the documentation would be a nightmare - _networkConfig.Bootnodes = discoveryConfig.Bootnodes; - - IInitConfig initConfig = _api.Config(); - - _api.DisconnectsAnalyzer = new MetricsDisconnectsAnalyzer(); - _api.SessionMonitor = new SessionMonitor(_networkConfig, _api.LogManager); - _api.RlpxPeer = new RlpxHost( - _api.MessageSerializationService, - _api.NodeKey.PublicKey, - _networkConfig.P2PPort, - encryptionHandshakeServiceA, - _api.SessionMonitor, - _api.DisconnectsAnalyzer, - _api.LogManager); - - await _api.RlpxPeer.Init(); - _api.StaticNodesManager = new StaticNodesManager(initConfig.StaticNodesPath, _api.LogManager); - await _api.StaticNodesManager.InitAsync(); + return Task.CompletedTask; + } - // ToDo: PeersDB is register outside dbProvider - bad - string dbName = "PeersDB"; - IFullDb peersDb = initConfig.DiagnosticMode == DiagnosticMode.MemDb - ? new MemDb(dbName) - : new SimpleFilePublicKeyDb(dbName, PeersDbPath.GetApplicationResourcePath(initConfig.BaseDbPath), - _api.LogManager); + private async Task InitPeer() + { + if (_api.DbProvider == null) throw new StepDependencyException(nameof(_api.DbProvider)); + if (_api.BlockTree == null) throw new StepDependencyException(nameof(_api.BlockTree)); + if (_api.ReceiptStorage == null) throw new StepDependencyException(nameof(_api.ReceiptStorage)); + if (_api.BlockValidator == null) throw new StepDependencyException(nameof(_api.BlockValidator)); + if (_api.SyncPeerPool == null) throw new StepDependencyException(nameof(_api.SyncPeerPool)); + if (_api.Synchronizer == null) throw new StepDependencyException(nameof(_api.Synchronizer)); + if (_api.Enode == null) throw new StepDependencyException(nameof(_api.Enode)); + if (_api.NodeKey == null) throw new StepDependencyException(nameof(_api.NodeKey)); + if (_api.MainBlockProcessor == null) throw new StepDependencyException(nameof(_api.MainBlockProcessor)); + if (_api.NodeStatsManager == null) throw new StepDependencyException(nameof(_api.NodeStatsManager)); + if (_api.KeyStore == null) throw new StepDependencyException(nameof(_api.KeyStore)); + if (_api.Wallet == null) throw new StepDependencyException(nameof(_api.Wallet)); + if (_api.EthereumEcdsa == null) throw new StepDependencyException(nameof(_api.EthereumEcdsa)); + if (_api.SpecProvider == null) throw new StepDependencyException(nameof(_api.SpecProvider)); + if (_api.TxPool == null) throw new StepDependencyException(nameof(_api.TxPool)); + if (_api.TxSender == null) throw new StepDependencyException(nameof(_api.TxSender)); + if (_api.EthereumJsonSerializer == null) throw new StepDependencyException(nameof(_api.EthereumJsonSerializer)); + if (_api.DiscoveryApp == null) throw new StepDependencyException(nameof(_api.DiscoveryApp)); + + /* rlpx */ + EciesCipher eciesCipher = new(_api.CryptoRandom); + Eip8MessagePad eip8Pad = new(_api.CryptoRandom); + _api.MessageSerializationService.Register(new AuthEip8MessageSerializer(eip8Pad)); + _api.MessageSerializationService.Register(new AckEip8MessageSerializer(eip8Pad)); + _api.MessageSerializationService.Register(Assembly.GetAssembly(typeof(HelloMessageSerializer))!); + ReceiptsMessageSerializer receiptsMessageSerializer = new(_api.SpecProvider); + _api.MessageSerializationService.Register(receiptsMessageSerializer); + _api.MessageSerializationService.Register(new Network.P2P.Subprotocols.Eth.V66.Messages.ReceiptsMessageSerializer(receiptsMessageSerializer)); + + HandshakeService encryptionHandshakeServiceA = new( + _api.MessageSerializationService, + eciesCipher, + _api.CryptoRandom, + _api.EthereumEcdsa, + _api.NodeKey.Unprotect(), + _api.LogManager); + + IDiscoveryConfig discoveryConfig = _api.Config(); + // TODO: hack, but changing it in all the documentation would be a nightmare + _networkConfig.Bootnodes = discoveryConfig.Bootnodes; + + IInitConfig initConfig = _api.Config(); + + _api.DisconnectsAnalyzer = new MetricsDisconnectsAnalyzer(); + _api.SessionMonitor = new SessionMonitor(_networkConfig, _api.LogManager); + _api.RlpxPeer = new RlpxHost( + _api.MessageSerializationService, + _api.NodeKey.PublicKey, + _networkConfig.P2PPort, + encryptionHandshakeServiceA, + _api.SessionMonitor, + _api.DisconnectsAnalyzer, + _api.LogManager); + + await _api.RlpxPeer.Init(); + + _api.StaticNodesManager = new StaticNodesManager(initConfig.StaticNodesPath, _api.LogManager); + await _api.StaticNodesManager.InitAsync(); + + // ToDo: PeersDB is register outside dbProvider - bad + string dbName = "PeersDB"; + IFullDb peersDb = initConfig.DiagnosticMode == DiagnosticMode.MemDb + ? new MemDb(dbName) + : new SimpleFilePublicKeyDb(dbName, PeersDbPath.GetApplicationResourcePath(initConfig.BaseDbPath), + _api.LogManager); - NetworkStorage peerStorage = new(peersDb, _api.LogManager); + NetworkStorage peerStorage = new(peersDb, _api.LogManager); + + ProtocolValidator protocolValidator = new(_api.NodeStatsManager!, _api.BlockTree!, _api.LogManager); + PooledTxsRequestor pooledTxsRequestor = new(_api.TxPool!); + _api.ProtocolsManager = new ProtocolsManager( + _api.SyncPeerPool!, + _api.SyncServer!, + _api.TxPool, + pooledTxsRequestor, + _api.DiscoveryApp!, + _api.MessageSerializationService, + _api.RlpxPeer, + _api.NodeStatsManager, + protocolValidator, + peerStorage, + _api.SpecProvider!, + _api.GossipPolicy, + _api.LogManager); + + if (_syncConfig.WitnessProtocolEnabled) + { + _api.ProtocolsManager.AddSupportedCapability(new Capability(Protocol.Wit, 0)); + } - ProtocolValidator protocolValidator = new(_api.NodeStatsManager!, _api.BlockTree!, _api.LogManager); - PooledTxsRequestor pooledTxsRequestor = new(_api.TxPool!); - _api.ProtocolsManager = new ProtocolsManager( - _api.SyncPeerPool!, - _api.SyncServer!, - _api.TxPool, - pooledTxsRequestor, - _api.DiscoveryApp!, - _api.MessageSerializationService, - _api.RlpxPeer, - _api.NodeStatsManager, - protocolValidator, - peerStorage, - _api.SpecProvider!, - _api.GossipPolicy, - _api.LogManager); + _api.ProtocolValidator = protocolValidator; - if (_syncConfig.WitnessProtocolEnabled) - { - _api.ProtocolsManager.AddSupportedCapability(new Capability(Protocol.Wit, 0)); - } + NodesLoader nodesLoader = new(_networkConfig, _api.NodeStatsManager, peerStorage, _api.RlpxPeer, _api.LogManager); - _api.ProtocolValidator = protocolValidator; - - NodesLoader nodesLoader = new(_networkConfig, _api.NodeStatsManager, peerStorage, _api.RlpxPeer, _api.LogManager); - - // I do not use the key here -> API is broken - no sense to use the node signer here - NodeRecordSigner nodeRecordSigner = new(_api.EthereumEcdsa, new PrivateKeyGenerator().Generate()); - EnrRecordParser enrRecordParser = new(nodeRecordSigner); - EnrDiscovery enrDiscovery = new(enrRecordParser, _api.LogManager); // initialize with a proper network - CompositeNodeSource nodeSources = new(_api.StaticNodesManager, nodesLoader, enrDiscovery, _api.DiscoveryApp); - _api.PeerPool = new PeerPool(nodeSources, _api.NodeStatsManager, peerStorage, _networkConfig, _api.LogManager); - _api.PeerManager = new PeerManager( - _api.RlpxPeer, - _api.PeerPool, - _api.NodeStatsManager, - _networkConfig, - _api.LogManager); + // I do not use the key here -> API is broken - no sense to use the node signer here + NodeRecordSigner nodeRecordSigner = new(_api.EthereumEcdsa, new PrivateKeyGenerator().Generate()); + EnrRecordParser enrRecordParser = new(nodeRecordSigner); + EnrDiscovery enrDiscovery = new(enrRecordParser, _api.LogManager); // initialize with a proper network + CompositeNodeSource nodeSources = new(_api.StaticNodesManager, nodesLoader, enrDiscovery, _api.DiscoveryApp); + _api.PeerPool = new PeerPool(nodeSources, _api.NodeStatsManager, peerStorage, _networkConfig, _api.LogManager); + _api.PeerManager = new PeerManager( + _api.RlpxPeer, + _api.PeerPool, + _api.NodeStatsManager, + _networkConfig, + _api.LogManager); - string chainName = ChainId.GetChainName(_api.ChainSpec!.ChainId).ToLowerInvariant(); + string chainName = ChainId.GetChainName(_api.ChainSpec!.ChainId).ToLowerInvariant(); #pragma warning disable CS4014 - enrDiscovery.SearchTree($"all.{chainName}.ethdisco.net").ContinueWith(t => + enrDiscovery.SearchTree($"all.{chainName}.ethdisco.net").ContinueWith(t => #pragma warning restore CS4014 + { + if (t.IsFaulted) { - if (t.IsFaulted) - { - _logger.Error($"ENR discovery failed: {t.Exception}"); - } - }); - - foreach (INethermindPlugin plugin in _api.Plugins) - { - await plugin.InitNetworkProtocol(); + _logger.Error($"ENR discovery failed: {t.Exception}"); } + }); + + foreach (INethermindPlugin plugin in _api.Plugins) + { + await plugin.InitNetworkProtocol(); } } } diff --git a/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs b/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs index 9e00dbe4048..fe199d4b33b 100644 --- a/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs +++ b/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs @@ -26,53 +26,52 @@ using Nethermind.Monitoring.Config; using Nethermind.Monitoring.Metrics; -namespace Nethermind.Init.Steps +namespace Nethermind.Init.Steps; + +[RunnerStepDependencies(typeof(InitializeNetwork))] +public class StartMonitoring : IStep { - [RunnerStepDependencies(typeof(InitializeNetwork))] - public class StartMonitoring : IStep + private readonly IApiWithNetwork _api; + + public StartMonitoring(INethermindApi api) { - private readonly IApiWithNetwork _api; + _api = api; + } - public StartMonitoring(INethermindApi api) + public async Task Execute(CancellationToken cancellationToken) + { + IMetricsConfig metricsConfig = _api.Config(); + ILogger logger = _api.LogManager.GetClassLogger(); + + // hacky + if (!string.IsNullOrEmpty(metricsConfig.NodeName)) { - _api = api; + _api.LogManager.SetGlobalVariable("nodeName", metricsConfig.NodeName); } - - public async Task Execute(CancellationToken cancellationToken) + + if (metricsConfig.Enabled) { - IMetricsConfig metricsConfig = _api.Config(); - ILogger logger = _api.LogManager.GetClassLogger(); - - // hacky - if (!string.IsNullOrEmpty(metricsConfig.NodeName)) + Metrics.Version = VersionToMetrics.ConvertToNumber(ProductInfo.Version); + MetricsUpdater metricsUpdater = new MetricsUpdater(metricsConfig); + _api.MonitoringService = new MonitoringService(metricsUpdater, metricsConfig, _api.LogManager); + IEnumerable metrics = new TypeDiscovery().FindNethermindTypes(nameof(Metrics)); + foreach (Type metric in metrics) { - _api.LogManager.SetGlobalVariable("nodeName", metricsConfig.NodeName); + _api.MonitoringService.RegisterMetrics(metric); } - - if (metricsConfig.Enabled) - { - Metrics.Version = VersionToMetrics.ConvertToNumber(ClientVersion.Version); - MetricsUpdater metricsUpdater = new MetricsUpdater(metricsConfig); - _api.MonitoringService = new MonitoringService(metricsUpdater, metricsConfig, _api.LogManager); - IEnumerable metrics = new TypeDiscovery().FindNethermindTypes(nameof(Metrics)); - foreach (Type metric in metrics) - { - _api.MonitoringService.RegisterMetrics(metric); - } - 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(() => _api.MonitoringService.StopAsync())); // do not await - } - else + await _api.MonitoringService.StartAsync().ContinueWith(x => { - if (logger.IsInfo) - logger.Info("Grafana / Prometheus metrics are disabled in configuration"); - } + if (x.IsFaulted && logger.IsError) + logger.Error("Error during starting a monitoring.", x.Exception); + }, cancellationToken); + + _api.DisposeStack.Push(new Reactive.AnonymousDisposable(() => _api.MonitoringService.StopAsync())); // do not await + } + else + { + if (logger.IsInfo) + logger.Info("Grafana / Prometheus metrics are disabled in configuration"); } } } diff --git a/src/Nethermind/Nethermind.Init/VersionToMetrics.cs b/src/Nethermind/Nethermind.Init/VersionToMetrics.cs index 53f8a9dd456..1307c21e5a6 100644 --- a/src/Nethermind/Nethermind.Init/VersionToMetrics.cs +++ b/src/Nethermind/Nethermind.Init/VersionToMetrics.cs @@ -15,29 +15,33 @@ // along with the Nethermind. If not, see . using System; +using System.Linq; -namespace Nethermind.Init +namespace Nethermind.Init; + +public static class VersionToMetrics { - public static class VersionToMetrics + public static int ConvertToNumber(string version) { - public static int ConvertToNumber(string version) + try + { + var index = version.IndexOfAny(new[] { '-', '+' }); + + if (index != -1) + version = version[..index]; + + var versions = version + .Split('.') + .Select(v => int.Parse(v)) + .ToArray(); + + return versions.Length == 3 + ? versions[0] * 100_000 + versions[1] * 1_000 + versions[2] + : throw new ArgumentException("Invalid version format"); + } + catch (Exception) { - try - { - int indexOfDash = version.IndexOf('-'); - indexOfDash = indexOfDash == -1 ? version.Length : indexOfDash; - int prefixLength = version.StartsWith('v') ? 1 : 0; - string numberString = version.AsSpan(prefixLength, indexOfDash - prefixLength).ToString(); - string[] versionParts = numberString.Split("."); - int result = 100_000 * int.Parse(versionParts[0]); - result += 1000 * int.Parse(versionParts[1]); - result += 1 * int.Parse(versionParts[2]); - return result; - } - catch (Exception) - { - return 0; - } + return 0; } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs index d4b101d3f50..25c3b979e39 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/AdminModuleTests.cs @@ -34,89 +34,88 @@ using NSubstitute; using NUnit.Framework; -namespace Nethermind.JsonRpc.Test.Modules +namespace Nethermind.JsonRpc.Test.Modules; + +[Parallelizable(ParallelScope.Self)] +[TestFixture] +public class AdminModuleTests { - [Parallelizable(ParallelScope.Self)] - [TestFixture] - public class AdminModuleTests + private IAdminRpcModule _adminRpcModule; + private EthereumJsonSerializer _serializer; + private NetworkConfig _networkConfig; + private IBlockTree _blockTree; + private const string _enodeString = "enode://e1b7e0dc09aae610c9dec8a0bee62bab9946cc27ebdd2f9e3571ed6d444628f99e91e43f4a14d42d498217608bb3e1d1bc8ec2aa27d7f7e423413b851bae02bc@127.0.0.1:30303"; + private const string _exampleDataDir = "/example/dbdir"; + + [SetUp] + public void Setup() { - private IAdminRpcModule _adminRpcModule; - private EthereumJsonSerializer _serializer; - private NetworkConfig _networkConfig; - private IBlockTree _blockTree; - private const string _enodeString = "enode://e1b7e0dc09aae610c9dec8a0bee62bab9946cc27ebdd2f9e3571ed6d444628f99e91e43f4a14d42d498217608bb3e1d1bc8ec2aa27d7f7e423413b851bae02bc@127.0.0.1:30303"; - private const string _exampleDataDir = "/example/dbdir"; - - [SetUp] - public void Setup() - { - _blockTree = Build.A.BlockTree().OfChainLength(5).TestObject; - _networkConfig = new NetworkConfig(); - IPeerPool peerPool = Substitute.For(); - ConcurrentDictionary dict = new(); - dict.TryAdd(TestItem.PublicKeyA, new Peer(new Node(TestItem.PublicKeyA, "127.0.0.1", 30303, true))); - peerPool.ActivePeers.Returns(dict); - - IStaticNodesManager staticNodesManager = Substitute.For(); - Enode enode = new(_enodeString); - _adminRpcModule = new AdminRpcModule( - _blockTree, - _networkConfig, - peerPool, - staticNodesManager, - enode, - _exampleDataDir, - new ManualPruningTrigger()); - - _serializer = new EthereumJsonSerializer(); - } - - [Test] - public void Test_node_info() - { - string serialized = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_nodeInfo"); - JsonRpcSuccessResponse response = _serializer.Deserialize(serialized); - JsonSerializerSettings settings = new(); - settings.Converters = EthereumJsonSerializer.CommonConverters.ToList(); - - NodeInfo nodeInfo = ((JObject) response.Result).ToObject(JsonSerializer.Create(settings)); - nodeInfo.Enode.Should().Be(_enodeString); - nodeInfo.Id.Should().Be("ae3623ef35c06ab49e9ae4b9f5a2b0f1983c28f85de1ccc98e2174333fdbdf1f"); - nodeInfo.Ip.Should().Be("127.0.0.1"); - nodeInfo.Name.Should().Be(ClientVersion.Description); - nodeInfo.ListenAddress.Should().Be("127.0.0.1:30303"); - nodeInfo.Ports.Discovery.Should().Be(_networkConfig.DiscoveryPort); - nodeInfo.Ports.Listener.Should().Be(_networkConfig.P2PPort); - - nodeInfo.Protocols.Should().HaveCount(1); - nodeInfo.Protocols["eth"].Difficulty.Should().Be(_blockTree.Head.TotalDifficulty ?? 0); - nodeInfo.Protocols["eth"].HeadHash.Should().Be(_blockTree.HeadHash); - nodeInfo.Protocols["eth"].GenesisHash.Should().Be(_blockTree.GenesisHash); - nodeInfo.Protocols["eth"].ChainId.Should().Be(_blockTree.ChainId); - } + _blockTree = Build.A.BlockTree().OfChainLength(5).TestObject; + _networkConfig = new NetworkConfig(); + IPeerPool peerPool = Substitute.For(); + ConcurrentDictionary dict = new(); + dict.TryAdd(TestItem.PublicKeyA, new Peer(new Node(TestItem.PublicKeyA, "127.0.0.1", 30303, true))); + peerPool.ActivePeers.Returns(dict); - [Test] - public void Test_data_dir() - { - string serialized = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_dataDir"); - JsonRpcSuccessResponse response = _serializer.Deserialize(serialized); - response.Result.Should().Be(_exampleDataDir); - } + IStaticNodesManager staticNodesManager = Substitute.For(); + Enode enode = new(_enodeString); + _adminRpcModule = new AdminRpcModule( + _blockTree, + _networkConfig, + peerPool, + staticNodesManager, + enode, + _exampleDataDir, + new ManualPruningTrigger()); - [Test] - public void Smoke_solc() - { - string serialized = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_setSolc"); - } + _serializer = new EthereumJsonSerializer(); + } + + [Test] + public void Test_node_info() + { + string serialized = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_nodeInfo"); + JsonRpcSuccessResponse response = _serializer.Deserialize(serialized); + JsonSerializerSettings settings = new(); + settings.Converters = EthereumJsonSerializer.CommonConverters.ToList(); - [Test] - public void Smoke_test_peers() - { - string serialized0 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_addPeer", _enodeString); - string serialized1 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_removePeer", _enodeString); - string serialized2 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_addPeer", _enodeString, "true"); - string serialized3 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_removePeer", _enodeString, "true"); - string serialized4 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_peers"); - } + NodeInfo nodeInfo = ((JObject) response.Result).ToObject(JsonSerializer.Create(settings)); + nodeInfo.Enode.Should().Be(_enodeString); + nodeInfo.Id.Should().Be("ae3623ef35c06ab49e9ae4b9f5a2b0f1983c28f85de1ccc98e2174333fdbdf1f"); + nodeInfo.Ip.Should().Be("127.0.0.1"); + nodeInfo.Name.Should().Be(ProductInfo.ClientId); + nodeInfo.ListenAddress.Should().Be("127.0.0.1:30303"); + nodeInfo.Ports.Discovery.Should().Be(_networkConfig.DiscoveryPort); + nodeInfo.Ports.Listener.Should().Be(_networkConfig.P2PPort); + + nodeInfo.Protocols.Should().HaveCount(1); + nodeInfo.Protocols["eth"].Difficulty.Should().Be(_blockTree.Head.TotalDifficulty ?? 0); + nodeInfo.Protocols["eth"].HeadHash.Should().Be(_blockTree.HeadHash); + nodeInfo.Protocols["eth"].GenesisHash.Should().Be(_blockTree.GenesisHash); + nodeInfo.Protocols["eth"].ChainId.Should().Be(_blockTree.ChainId); + } + + [Test] + public void Test_data_dir() + { + string serialized = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_dataDir"); + JsonRpcSuccessResponse response = _serializer.Deserialize(serialized); + response.Result.Should().Be(_exampleDataDir); + } + + [Test] + public void Smoke_solc() + { + string serialized = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_setSolc"); + } + + [Test] + public void Smoke_test_peers() + { + string serialized0 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_addPeer", _enodeString); + string serialized1 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_removePeer", _enodeString); + string serialized2 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_addPeer", _enodeString, "true"); + string serialized3 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_removePeer", _enodeString, "true"); + string serialized4 = RpcTest.TestSerializedRequest(_adminRpcModule, "admin_peers"); } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/AdminRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/AdminRpcModule.cs index b843db2fad1..2361a478f81 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/AdminRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Admin/AdminRpcModule.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Demerzel Solutions Limited +// 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 @@ -26,120 +26,119 @@ using Nethermind.Network.Config; using Nethermind.Stats.Model; -namespace Nethermind.JsonRpc.Modules.Admin +namespace Nethermind.JsonRpc.Modules.Admin; + +public class AdminRpcModule : IAdminRpcModule { - public class AdminRpcModule : IAdminRpcModule + private readonly IBlockTree _blockTree; + private readonly INetworkConfig _networkConfig; + private readonly IPeerPool _peerPool; + private readonly IStaticNodesManager _staticNodesManager; + private readonly IEnode _enode; + private readonly string _dataDir; + private readonly ManualPruningTrigger _pruningTrigger; + private NodeInfo _nodeInfo = null!; + + public AdminRpcModule( + IBlockTree blockTree, + INetworkConfig networkConfig, + IPeerPool peerPool, + IStaticNodesManager staticNodesManager, + IEnode enode, + string dataDir, + ManualPruningTrigger pruningTrigger) { - private readonly IBlockTree _blockTree; - private readonly INetworkConfig _networkConfig; - private readonly IPeerPool _peerPool; - private readonly IStaticNodesManager _staticNodesManager; - private readonly IEnode _enode; - private readonly string _dataDir; - private readonly ManualPruningTrigger _pruningTrigger; - private NodeInfo _nodeInfo = null!; + _enode = enode ?? throw new ArgumentNullException(nameof(enode)); + _dataDir = dataDir ?? throw new ArgumentNullException(nameof(dataDir)); + _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); + _peerPool = peerPool ?? throw new ArgumentNullException(nameof(peerPool)); + _networkConfig = networkConfig ?? throw new ArgumentNullException(nameof(networkConfig)); + _staticNodesManager = staticNodesManager ?? throw new ArgumentNullException(nameof(staticNodesManager)); + _pruningTrigger = pruningTrigger; - public AdminRpcModule( - IBlockTree blockTree, - INetworkConfig networkConfig, - IPeerPool peerPool, - IStaticNodesManager staticNodesManager, - IEnode enode, - string dataDir, - ManualPruningTrigger pruningTrigger) - { - _enode = enode ?? throw new ArgumentNullException(nameof(enode)); - _dataDir = dataDir ?? throw new ArgumentNullException(nameof(dataDir)); - _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); - _peerPool = peerPool ?? throw new ArgumentNullException(nameof(peerPool)); - _networkConfig = networkConfig ?? throw new ArgumentNullException(nameof(networkConfig)); - _staticNodesManager = staticNodesManager ?? throw new ArgumentNullException(nameof(staticNodesManager)); - _pruningTrigger = pruningTrigger; + BuildNodeInfo(); + } - BuildNodeInfo(); - } + private void BuildNodeInfo() + { + _nodeInfo = new NodeInfo(); + _nodeInfo.Name = ProductInfo.ClientId; + _nodeInfo.Enode = _enode.Info; + byte[] publicKeyBytes = _enode.PublicKey?.Bytes; + _nodeInfo.Id = (publicKeyBytes == null ? Keccak.Zero : Keccak.Compute(publicKeyBytes)).ToString(false); + _nodeInfo.Ip = _enode.HostIp?.ToString(); + _nodeInfo.ListenAddress = $"{_enode.HostIp}:{_enode.Port}"; + _nodeInfo.Ports.Discovery = _networkConfig.DiscoveryPort; + _nodeInfo.Ports.Listener = _networkConfig.P2PPort; + UpdateEthProtocolInfo(); + } - private void BuildNodeInfo() + private void UpdateEthProtocolInfo() + { + _nodeInfo.Protocols["eth"].Difficulty = _blockTree.Head?.TotalDifficulty ?? 0; + _nodeInfo.Protocols["eth"].ChainId = _blockTree.ChainId; + _nodeInfo.Protocols["eth"].HeadHash = _blockTree.HeadHash; + _nodeInfo.Protocols["eth"].GenesisHash = _blockTree.GenesisHash; + } + + public async Task> admin_addPeer(string enode, bool addToStaticNodes = false) + { + bool added; + if (addToStaticNodes) { - _nodeInfo = new NodeInfo(); - _nodeInfo.Name = ClientVersion.Description; - _nodeInfo.Enode = _enode.Info; - byte[] publicKeyBytes = _enode.PublicKey?.Bytes; - _nodeInfo.Id = (publicKeyBytes == null ? Keccak.Zero : Keccak.Compute(publicKeyBytes)).ToString(false); - _nodeInfo.Ip = _enode.HostIp?.ToString(); - _nodeInfo.ListenAddress = $"{_enode.HostIp}:{_enode.Port}"; - _nodeInfo.Ports.Discovery = _networkConfig.DiscoveryPort; - _nodeInfo.Ports.Listener = _networkConfig.P2PPort; - UpdateEthProtocolInfo(); + added = await _staticNodesManager.AddAsync(enode); } - - private void UpdateEthProtocolInfo() + else { - _nodeInfo.Protocols["eth"].Difficulty = _blockTree.Head?.TotalDifficulty ?? 0; - _nodeInfo.Protocols["eth"].ChainId = _blockTree.ChainId; - _nodeInfo.Protocols["eth"].HeadHash = _blockTree.HeadHash; - _nodeInfo.Protocols["eth"].GenesisHash = _blockTree.GenesisHash; + NetworkNode networkNode = new(enode); + _peerPool.GetOrAdd(new Node(networkNode)); + added = true; } - public async Task> admin_addPeer(string enode, bool addToStaticNodes = false) - { - bool added; - if (addToStaticNodes) - { - added = await _staticNodesManager.AddAsync(enode); - } - else - { - NetworkNode networkNode = new(enode); - _peerPool.GetOrAdd(new Node(networkNode)); - added = true; - } + return added + ? ResultWrapper.Success(enode) + : ResultWrapper.Fail("Failed to add peer."); + } - return added - ? ResultWrapper.Success(enode) - : ResultWrapper.Fail("Failed to add peer."); + public async Task> admin_removePeer(string enode, bool removeFromStaticNodes = false) + { + bool removed; + if (removeFromStaticNodes) + { + removed = await _staticNodesManager.RemoveAsync(enode); } - - public async Task> admin_removePeer(string enode, bool removeFromStaticNodes = false) + else { - bool removed; - if (removeFromStaticNodes) - { - removed = await _staticNodesManager.RemoveAsync(enode); - } - else - { - removed = _peerPool.TryRemove(new NetworkNode(enode).NodeId, out Peer _); - } - - return removed - ? ResultWrapper.Success(enode) - : ResultWrapper.Fail("Failed to remove peer."); + removed = _peerPool.TryRemove(new NetworkNode(enode).NodeId, out Peer _); } - public ResultWrapper admin_peers(bool includeDetails = false) - => ResultWrapper.Success( - _peerPool.ActivePeers.Select(p => new PeerInfo(p.Value, includeDetails)).ToArray()); + return removed + ? ResultWrapper.Success(enode) + : ResultWrapper.Fail("Failed to remove peer."); + } + + public ResultWrapper admin_peers(bool includeDetails = false) + => ResultWrapper.Success( + _peerPool.ActivePeers.Select(p => new PeerInfo(p.Value, includeDetails)).ToArray()); - public ResultWrapper admin_nodeInfo() - { - UpdateEthProtocolInfo(); - return ResultWrapper.Success(_nodeInfo); - } + public ResultWrapper admin_nodeInfo() + { + UpdateEthProtocolInfo(); + return ResultWrapper.Success(_nodeInfo); + } - public ResultWrapper admin_dataDir() - { - return ResultWrapper.Success(_dataDir); - } + public ResultWrapper admin_dataDir() + { + return ResultWrapper.Success(_dataDir); + } - public ResultWrapper admin_setSolc() - { - return ResultWrapper.Success(true); - } + public ResultWrapper admin_setSolc() + { + return ResultWrapper.Success(true); + } - public ResultWrapper admin_prune() - { - return ResultWrapper.Success(_pruningTrigger.Trigger()); - } + public ResultWrapper admin_prune() + { + return ResultWrapper.Success(_pruningTrigger.Trigger()); } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Web3/Web3RpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Web3/Web3RpcModule.cs index 329b71e4e7a..558ff707210 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Web3/Web3RpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Web3/Web3RpcModule.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Demerzel Solutions Limited +// 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 @@ -18,24 +18,19 @@ using Nethermind.Core.Crypto; using Nethermind.Logging; -namespace Nethermind.JsonRpc.Modules.Web3 +namespace Nethermind.JsonRpc.Modules.Web3; + +public class Web3RpcModule : IWeb3RpcModule { - public class Web3RpcModule : IWeb3RpcModule + public Web3RpcModule(ILogManager logManager) { - public Web3RpcModule(ILogManager logManager) - { - } + } - public ResultWrapper web3_clientVersion() - { - var clientVersion = ClientVersion.Description; - return ResultWrapper.Success(clientVersion); - } + public ResultWrapper web3_clientVersion() => ResultWrapper.Success(ProductInfo.ClientId); - public ResultWrapper web3_sha3(byte[] data) - { - Keccak keccak = Keccak.Compute(data); - return ResultWrapper.Success(keccak); - } + public ResultWrapper web3_sha3(byte[] data) + { + Keccak keccak = Keccak.Compute(data); + return ResultWrapper.Success(keccak); } } diff --git a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/P2PProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/P2PProtocolHandler.cs index c67eb6af30d..a1056186719 100644 --- a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/P2PProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/P2PProtocolHandler.cs @@ -31,344 +31,343 @@ using Nethermind.Stats; using Nethermind.Stats.Model; -namespace Nethermind.Network.P2P.ProtocolHandlers -{ - public class P2PProtocolHandler : ProtocolHandlerBase, IPingSender, IP2PProtocolHandler - { - private TaskCompletionSource _pongCompletionSource; - private readonly INodeStatsManager _nodeStatsManager; - private bool _sentHello; - private List _agreedCapabilities { get; } - private List _availableCapabilities { get; set; } - - private byte _protocolVersion = 5; - - public override byte ProtocolVersion => _protocolVersion; +namespace Nethermind.Network.P2P.ProtocolHandlers; - public override string ProtocolCode => Protocol.P2P; +public class P2PProtocolHandler : ProtocolHandlerBase, IPingSender, IP2PProtocolHandler +{ + private TaskCompletionSource _pongCompletionSource; + private readonly INodeStatsManager _nodeStatsManager; + private bool _sentHello; + private List _agreedCapabilities { get; } + private List _availableCapabilities { get; set; } - public override int MessageIdSpaceSize => 0x10; + private byte _protocolVersion = 5; - protected override TimeSpan InitTimeout => Timeouts.P2PHello; + public override byte ProtocolVersion => _protocolVersion; - public static readonly IEnumerable DefaultCapabilities = new Capability[] - { - new(Protocol.Eth, 62), - new(Protocol.Eth, 63), - new(Protocol.Eth, 64), - new(Protocol.Eth, 65), - new(Protocol.Eth, 66), - // new Capability(Protocol.Les, 3) - }; + public override string ProtocolCode => Protocol.P2P; - public IReadOnlyList AgreedCapabilities { get { return _agreedCapabilities; } } - public IReadOnlyList AvailableCapabilities { get { return _availableCapabilities; } } - private readonly List SupportedCapabilities = DefaultCapabilities.ToList(); + public override int MessageIdSpaceSize => 0x10; - public int ListenPort { get; } - public PublicKey LocalNodeId { get; } - public string RemoteClientId { get; private set; } + protected override TimeSpan InitTimeout => Timeouts.P2PHello; - public override event EventHandler ProtocolInitialized; - - public override event EventHandler SubprotocolRequested; + public static readonly IEnumerable DefaultCapabilities = new Capability[] + { + new(Protocol.Eth, 62), + new(Protocol.Eth, 63), + new(Protocol.Eth, 64), + new(Protocol.Eth, 65), + new(Protocol.Eth, 66), + // new Capability(Protocol.Les, 3) + }; + + public IReadOnlyList AgreedCapabilities { get { return _agreedCapabilities; } } + public IReadOnlyList AvailableCapabilities { get { return _availableCapabilities; } } + private readonly List SupportedCapabilities = DefaultCapabilities.ToList(); + + public int ListenPort { get; } + public PublicKey LocalNodeId { get; } + public string RemoteClientId { get; private set; } + + public override event EventHandler ProtocolInitialized; + + public override event EventHandler SubprotocolRequested; + + public P2PProtocolHandler( + ISession session, + PublicKey localNodeId, + INodeStatsManager nodeStatsManager, + IMessageSerializationService serializer, + ILogManager logManager) : base(session, nodeStatsManager, serializer, logManager) + { + _nodeStatsManager = nodeStatsManager ?? throw new ArgumentNullException(nameof(nodeStatsManager)); + LocalNodeId = localNodeId; + ListenPort = session.LocalPort; + _agreedCapabilities = new List(); + _availableCapabilities = new List(); + } - public P2PProtocolHandler( - ISession session, - PublicKey localNodeId, - INodeStatsManager nodeStatsManager, - IMessageSerializationService serializer, - ILogManager logManager) : base(session, nodeStatsManager, serializer, logManager) + public bool HasAvailableCapability(Capability capability) => _availableCapabilities.Contains(capability); + public bool HasAgreedCapability(Capability capability) => _agreedCapabilities.Contains(capability); + public void AddSupportedCapability(Capability capability) + { + if (SupportedCapabilities.Contains(capability)) { - _nodeStatsManager = nodeStatsManager ?? throw new ArgumentNullException(nameof(nodeStatsManager)); - LocalNodeId = localNodeId; - ListenPort = session.LocalPort; - _agreedCapabilities = new List(); - _availableCapabilities = new List(); + return; } - public bool HasAvailableCapability(Capability capability) => _availableCapabilities.Contains(capability); - public bool HasAgreedCapability(Capability capability) => _agreedCapabilities.Contains(capability); - public void AddSupportedCapability(Capability capability) + SupportedCapabilities.Add(capability); + } + + public override void Init() + { + SendHello(); + + // We are expecting to receive Hello message anytime from the handshake completion, + // irrespective of sending Hello from our side + CheckProtocolInitTimeout().ContinueWith(x => { - if (SupportedCapabilities.Contains(capability)) + if (x.IsFaulted && Logger.IsError) { - return; + Logger.Error("Error during p2pProtocol handler timeout logic", x.Exception); } + }); + } - SupportedCapabilities.Add(capability); - } - - public override void Init() + public override void HandleMessage(Packet msg) + { + switch (msg.PacketType) { - SendHello(); - - // We are expecting to receive Hello message anytime from the handshake completion, - // irrespective of sending Hello from our side - CheckProtocolInitTimeout().ContinueWith(x => + case P2PMessageCode.Hello: { - if (x.IsFaulted && Logger.IsError) + Metrics.HellosReceived++; + HandleHello(Deserialize(msg.Data)); + + // We need to initialize subprotocols in alphabetical order. Protocols are using AdaptiveId, + // which should be constant for the whole session. Some protocols (like Eth) are sending messages + // on initialization and we need to avoid changing theirs AdaptiveId by initializing protocols, + // which are alphabetically before already initialized ones. + foreach (Capability capability in + _agreedCapabilities.GroupBy(c => c.ProtocolCode).Select(c => c.OrderBy(v => v.Version).Last()).OrderBy(c => c.ProtocolCode)) { - Logger.Error("Error during p2pProtocol handler timeout logic", x.Exception); + if (Logger.IsTrace) Logger.Trace($"{Session} Starting protocolHandler for {capability.ProtocolCode} v{capability.Version} on {Session.RemotePort}"); + SubprotocolRequested?.Invoke(this, new ProtocolEventArgs(capability.ProtocolCode, capability.Version)); } - }); - } - public override void HandleMessage(Packet msg) - { - switch (msg.PacketType) + break; + } + case P2PMessageCode.Disconnect: { - case P2PMessageCode.Hello: + DisconnectMessage disconnectMessage = Deserialize(msg.Data); + ReportIn(disconnectMessage); + if (Logger.IsTrace) { - Metrics.HellosReceived++; - HandleHello(Deserialize(msg.Data)); - - // We need to initialize subprotocols in alphabetical order. Protocols are using AdaptiveId, - // which should be constant for the whole session. Some protocols (like Eth) are sending messages - // on initialization and we need to avoid changing theirs AdaptiveId by initializing protocols, - // which are alphabetically before already initialized ones. - foreach (Capability capability in - _agreedCapabilities.GroupBy(c => c.ProtocolCode).Select(c => c.OrderBy(v => v.Version).Last()).OrderBy(c => c.ProtocolCode)) - { - if (Logger.IsTrace) Logger.Trace($"{Session} Starting protocolHandler for {capability.ProtocolCode} v{capability.Version} on {Session.RemotePort}"); - SubprotocolRequested?.Invoke(this, new ProtocolEventArgs(capability.ProtocolCode, capability.Version)); - } - - break; + string reason = FastEnum.IsDefined((byte) disconnectMessage.Reason) + ? ((DisconnectReason) disconnectMessage.Reason).ToName() + : disconnectMessage.Reason.ToString(); + Logger.Trace($"{Session} Received disconnect ({reason}) on {Session.RemotePort}"); } - case P2PMessageCode.Disconnect: - { - DisconnectMessage disconnectMessage = Deserialize(msg.Data); - ReportIn(disconnectMessage); - if (Logger.IsTrace) - { - string reason = FastEnum.IsDefined((byte) disconnectMessage.Reason) - ? ((DisconnectReason) disconnectMessage.Reason).ToName() - : disconnectMessage.Reason.ToString(); - Logger.Trace($"{Session} Received disconnect ({reason}) on {Session.RemotePort}"); - } - - Close(disconnectMessage.Reason); - break; - } - case P2PMessageCode.Ping: - { - if (Logger.IsTrace) Logger.Trace($"{Session} Received PING on {Session.RemotePort}"); - HandlePing(); - break; - } - case P2PMessageCode.Pong: - { - if (Logger.IsTrace) Logger.Trace($"{Session} Received PONG on {Session.RemotePort}"); - HandlePong(msg); - break; - } - case P2PMessageCode.AddCapability: - { - AddCapabilityMessage message = Deserialize(msg.Data); - Capability capability = message.Capability; - _agreedCapabilities.Add(message.Capability); - SupportedCapabilities.Add(message.Capability); - if (Logger.IsTrace) - Logger.Trace($"{Session.RemoteNodeId} Starting handler for {capability} on {Session.RemotePort}"); - SubprotocolRequested?.Invoke(this, new ProtocolEventArgs(capability.ProtocolCode, capability.Version)); - break; - } - default: - Logger.Error($"{Session.RemoteNodeId} Unhandled packet type: {msg.PacketType}"); - break; - } - } - - private void HandleHello(HelloMessage hello) - { - ReportIn(hello); - bool isInbound = !_sentHello; - - if (Logger.IsTrace) Logger.Trace($"{Session} P2P received hello."); - if (!hello.NodeId.Equals(Session.RemoteNodeId)) + Close(disconnectMessage.Reason); + break; + } + case P2PMessageCode.Ping: { - if (Logger.IsDebug) - Logger.Debug($"Inconsistent Node ID details - expected {Session.RemoteNodeId}, " + - $"received hello with {hello.NodeId} " + - $"on {(isInbound ? "IN connection" : "OUT connection")}"); - // it does not really matter if there is mismatch - we do not use it anywhere -// throw new NodeDetailsMismatchException(); + if (Logger.IsTrace) Logger.Trace($"{Session} Received PING on {Session.RemotePort}"); + HandlePing(); + break; } - - RemoteClientId = hello.ClientId; - Session.Node.ClientId = hello.ClientId; - - if(Logger.IsTrace) Logger.Trace(!_sentHello - ? $"{Session.RemoteNodeId} P2P initiating inbound {hello.Protocol}.{hello.P2PVersion} " + - $"on {hello.ListenPort} ({hello.ClientId})" - : $"{Session.RemoteNodeId} P2P initiating outbound {hello.Protocol}.{hello.P2PVersion} " + - $"on {hello.ListenPort} ({hello.ClientId})"); - - // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-8.md - // Clients implementing a newer version simply send a packet with higher version and possibly additional list elements. - // * If such a packet is received by a node with lower version, - // it will blindly assume that the remote end is backwards-compatible and respond with the old handshake. - // * If the packet is received by a node with equal version, - // new features of the protocol can be used. - // * If the packet is received by a node with higher version, - // it can enable backwards-compatibility logic or drop the connection. - - _protocolVersion = hello.P2PVersion; - - List capabilities = hello.Capabilities; - _availableCapabilities = new List(capabilities); - foreach (Capability theirCapability in capabilities) + case P2PMessageCode.Pong: { - if (SupportedCapabilities.Contains(theirCapability)) - { - if (Logger.IsTrace) - Logger.Trace($"{Session.RemoteNodeId} Agreed on {theirCapability.ProtocolCode} v{theirCapability.Version}"); - _agreedCapabilities.Add(theirCapability); - } - else - { - if (Logger.IsTrace) - Logger.Trace($"{Session.RemoteNodeId} Capability not supported " + - $"{theirCapability.ProtocolCode} v{theirCapability.Version}"); - } + if (Logger.IsTrace) Logger.Trace($"{Session} Received PONG on {Session.RemotePort}"); + HandlePong(msg); + break; } - - if (_agreedCapabilities.Count == 0) + case P2PMessageCode.AddCapability: { - Session.InitiateDisconnect( - DisconnectReason.UselessPeer, - $"capabilities: {string.Join(", ", capabilities)}"); + AddCapabilityMessage message = Deserialize(msg.Data); + Capability capability = message.Capability; + _agreedCapabilities.Add(message.Capability); + SupportedCapabilities.Add(message.Capability); + if (Logger.IsTrace) + Logger.Trace($"{Session.RemoteNodeId} Starting handler for {capability} on {Session.RemotePort}"); + SubprotocolRequested?.Invoke(this, new ProtocolEventArgs(capability.ProtocolCode, capability.Version)); + break; } + default: + Logger.Error($"{Session.RemoteNodeId} Unhandled packet type: {msg.PacketType}"); + break; + } + } - ReceivedProtocolInitMsg(hello); + private void HandleHello(HelloMessage hello) + { + ReportIn(hello); + bool isInbound = !_sentHello; - P2PProtocolInitializedEventArgs eventArgs = new(this) - { - P2PVersion = ProtocolVersion, - ClientId = RemoteClientId, - Capabilities = capabilities, - ListenPort = hello.ListenPort - }; - - ProtocolInitialized?.Invoke(this, eventArgs); + if (Logger.IsTrace) Logger.Trace($"{Session} P2P received hello."); + + if (!hello.NodeId.Equals(Session.RemoteNodeId)) + { + if (Logger.IsDebug) + Logger.Debug($"Inconsistent Node ID details - expected {Session.RemoteNodeId}, " + + $"received hello with {hello.NodeId} " + + $"on {(isInbound ? "IN connection" : "OUT connection")}"); + // it does not really matter if there is mismatch - we do not use it anywhere +// throw new NodeDetailsMismatchException(); } - [SuppressMessage("ReSharper", "HeuristicUnreachableCode")] - public async Task SendPing() + RemoteClientId = hello.ClientId; + Session.Node.ClientId = hello.ClientId; + + if(Logger.IsTrace) Logger.Trace(!_sentHello + ? $"{Session.RemoteNodeId} P2P initiating inbound {hello.Protocol}.{hello.P2PVersion} " + + $"on {hello.ListenPort} ({hello.ClientId})" + : $"{Session.RemoteNodeId} P2P initiating outbound {hello.Protocol}.{hello.P2PVersion} " + + $"on {hello.ListenPort} ({hello.ClientId})"); + + // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-8.md + // Clients implementing a newer version simply send a packet with higher version and possibly additional list elements. + // * If such a packet is received by a node with lower version, + // it will blindly assume that the remote end is backwards-compatible and respond with the old handshake. + // * If the packet is received by a node with equal version, + // new features of the protocol can be used. + // * If the packet is received by a node with higher version, + // it can enable backwards-compatibility logic or drop the connection. + + _protocolVersion = hello.P2PVersion; + + List capabilities = hello.Capabilities; + _availableCapabilities = new List(capabilities); + foreach (Capability theirCapability in capabilities) { - // ReSharper disable once AssignNullToNotNullAttribute - TaskCompletionSource previousSource = - Interlocked.CompareExchange(ref _pongCompletionSource, new TaskCompletionSource(), null); - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - if (previousSource != null) + if (SupportedCapabilities.Contains(theirCapability)) { - if (Logger.IsWarn) Logger.Warn($"Another ping request in process: {Session.Node:c}"); - return true; + if (Logger.IsTrace) + Logger.Trace($"{Session.RemoteNodeId} Agreed on {theirCapability.ProtocolCode} v{theirCapability.Version}"); + _agreedCapabilities.Add(theirCapability); } - - Task pongTask = _pongCompletionSource.Task; - - if (Logger.IsTrace) Logger.Trace($"{Session} P2P sending ping on {Session.RemotePort} ({RemoteClientId})"); - Send(PingMessage.Instance); - _nodeStatsManager.ReportEvent(Session.Node, NodeStatsEventType.P2PPingOut); - Stopwatch stopwatch = Stopwatch.StartNew(); - - CancellationTokenSource delayCancellation = new(); - try - { - Task firstTask = await Task.WhenAny(pongTask, Task.Delay(Timeouts.P2PPing, delayCancellation.Token)); - if (firstTask != pongTask) - { - _nodeStatsManager.ReportTransferSpeedEvent( - Session.Node, - TransferSpeedType.Latency, - (long) Timeouts.P2PPing.TotalMilliseconds); - return false; - } - - long latency = stopwatch.ElapsedMilliseconds; - _nodeStatsManager.ReportTransferSpeedEvent(Session.Node, TransferSpeedType.Latency, latency); - return true; - } - finally + else { - delayCancellation?.Cancel(); // do not remove ? -> ReSharper issue - _pongCompletionSource = null; + if (Logger.IsTrace) + Logger.Trace($"{Session.RemoteNodeId} Capability not supported " + + $"{theirCapability.ProtocolCode} v{theirCapability.Version}"); } } - public override void DisconnectProtocol(DisconnectReason disconnectReason, string details) + if (_agreedCapabilities.Count == 0) + { + Session.InitiateDisconnect( + DisconnectReason.UselessPeer, + $"capabilities: {string.Join(", ", capabilities)}"); + } + + ReceivedProtocolInitMsg(hello); + + P2PProtocolInitializedEventArgs eventArgs = new(this) { - if (Logger.IsTrace) - Logger.Trace($"Sending disconnect {disconnectReason} ({details}) to {Session.Node:s}"); - DisconnectMessage message = new(disconnectReason); - Send(message); - if(NetworkDiagTracer.IsEnabled) - NetworkDiagTracer.ReportDisconnect(Session.Node.Address, $"Local {disconnectReason} {details}"); + P2PVersion = ProtocolVersion, + ClientId = RemoteClientId, + Capabilities = capabilities, + ListenPort = hello.ListenPort + }; + + ProtocolInitialized?.Invoke(this, eventArgs); + } + + [SuppressMessage("ReSharper", "HeuristicUnreachableCode")] + public async Task SendPing() + { + // ReSharper disable once AssignNullToNotNullAttribute + TaskCompletionSource previousSource = + Interlocked.CompareExchange(ref _pongCompletionSource, new TaskCompletionSource(), null); + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + if (previousSource != null) + { + if (Logger.IsWarn) Logger.Warn($"Another ping request in process: {Session.Node:c}"); + return true; } - private void SendHello() + Task pongTask = _pongCompletionSource.Task; + + if (Logger.IsTrace) Logger.Trace($"{Session} P2P sending ping on {Session.RemotePort} ({RemoteClientId})"); + Send(PingMessage.Instance); + _nodeStatsManager.ReportEvent(Session.Node, NodeStatsEventType.P2PPingOut); + Stopwatch stopwatch = Stopwatch.StartNew(); + + CancellationTokenSource delayCancellation = new(); + try { - if (Logger.IsTrace) + Task firstTask = await Task.WhenAny(pongTask, Task.Delay(Timeouts.P2PPing, delayCancellation.Token)); + if (firstTask != pongTask) { - Logger.Trace($"{Session} {Name} sending hello with Client ID {ClientVersion.Description}, " + - $"protocol {Name}, listen port {ListenPort}"); + _nodeStatsManager.ReportTransferSpeedEvent( + Session.Node, + TransferSpeedType.Latency, + (long) Timeouts.P2PPing.TotalMilliseconds); + return false; } - HelloMessage helloMessage = new() - { - Capabilities = SupportedCapabilities, - ClientId = ClientVersion.Description, - NodeId = LocalNodeId, - ListenPort = ListenPort, - P2PVersion = ProtocolVersion - }; - - _sentHello = true; - Send(helloMessage); - Metrics.HellosSent++; + long latency = stopwatch.ElapsedMilliseconds; + _nodeStatsManager.ReportTransferSpeedEvent(Session.Node, TransferSpeedType.Latency, latency); + return true; + } + finally + { + delayCancellation?.Cancel(); // do not remove ? -> ReSharper issue + _pongCompletionSource = null; } + } - private void HandlePing() + public override void DisconnectProtocol(DisconnectReason disconnectReason, string details) + { + if (Logger.IsTrace) + Logger.Trace($"Sending disconnect {disconnectReason} ({details}) to {Session.Node:s}"); + DisconnectMessage message = new(disconnectReason); + Send(message); + if(NetworkDiagTracer.IsEnabled) + NetworkDiagTracer.ReportDisconnect(Session.Node.Address, $"Local {disconnectReason} {details}"); + } + + private void SendHello() + { + if (Logger.IsTrace) { - ReportIn("Ping"); - if (Logger.IsTrace) Logger.Trace($"{Session} P2P responding to ping"); - Send(PongMessage.Instance); + Logger.Trace($"{Session} {Name} sending hello with Client ID {ProductInfo.ClientId}, " + + $"protocol {Name}, listen port {ListenPort}"); } - private void Close(int disconnectReasonId) + HelloMessage helloMessage = new() { - DisconnectReason disconnectReason = (DisconnectReason) disconnectReasonId; + Capabilities = SupportedCapabilities, + ClientId = ProductInfo.ClientId, + NodeId = LocalNodeId, + ListenPort = ListenPort, + P2PVersion = ProtocolVersion + }; - if (disconnectReason != DisconnectReason.TooManyPeers && - disconnectReason != DisconnectReason.Other && - disconnectReason != DisconnectReason.DisconnectRequested) - { - if (Logger.IsDebug) Logger.Debug($"{Session} received disconnect [{disconnectReason}]"); - } - else - { - if (Logger.IsTrace) Logger.Trace($"{Session} P2P received disconnect [{disconnectReason}]"); - } + _sentHello = true; + Send(helloMessage); + Metrics.HellosSent++; + } - // Received disconnect message, triggering direct TCP disconnection - Session.MarkDisconnected(disconnectReason, DisconnectType.Remote, "message"); - } + private void HandlePing() + { + ReportIn("Ping"); + if (Logger.IsTrace) Logger.Trace($"{Session} P2P responding to ping"); + Send(PongMessage.Instance); + } - public override string Name => Protocol.P2P; - - private void HandlePong(Packet msg) + private void Close(int disconnectReasonId) + { + DisconnectReason disconnectReason = (DisconnectReason) disconnectReasonId; + + if (disconnectReason != DisconnectReason.TooManyPeers && + disconnectReason != DisconnectReason.Other && + disconnectReason != DisconnectReason.DisconnectRequested) { - ReportIn("Pong"); - if (Logger.IsTrace) Logger.Trace($"{Session} sending P2P pong"); - _nodeStatsManager.ReportEvent(Session.Node, NodeStatsEventType.P2PPingIn); - _pongCompletionSource?.TrySetResult(msg); + if (Logger.IsDebug) Logger.Debug($"{Session} received disconnect [{disconnectReason}]"); } - - public override void Dispose() + else { + if (Logger.IsTrace) Logger.Trace($"{Session} P2P received disconnect [{disconnectReason}]"); } + + // Received disconnect message, triggering direct TCP disconnection + Session.MarkDisconnected(disconnectReason, DisconnectType.Remote, "message"); + } + + public override string Name => Protocol.P2P; + + private void HandlePong(Packet msg) + { + ReportIn("Pong"); + if (Logger.IsTrace) Logger.Trace($"{Session} sending P2P pong"); + _nodeStatsManager.ReportEvent(Session.Node, NodeStatsEventType.P2PPingIn); + _pongCompletionSource?.TrySetResult(msg); + } + + public override void Dispose() + { } } diff --git a/src/Nethermind/Nethermind.Runner.Test/VersionToMetricsTests.cs b/src/Nethermind/Nethermind.Runner.Test/VersionToMetricsTests.cs index 582dc27d76e..a7854b6ace9 100644 --- a/src/Nethermind/Nethermind.Runner.Test/VersionToMetricsTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/VersionToMetricsTests.cs @@ -18,47 +18,42 @@ using Nethermind.Init; using NUnit.Framework; -namespace Nethermind.Runner.Test +namespace Nethermind.Runner.Test; + +[Parallelizable(ParallelScope.All)] +[TestFixture] +public class VersionToMetricsTests { - [Parallelizable(ParallelScope.All)] - [TestFixture] - public class VersionToMetricsTests + [TestCase("1", 0)] + [TestCase("1.2", 0)] + [TestCase("1.2.3.4", 0)] + [TestCase("v1.2.3", 0)] + [TestCase("11.22.333", 1122333)] + [TestCase("11.22.33", 1122033)] + [TestCase("11.22.3", 1122003)] + [TestCase("11.2.3", 1102003)] + [TestCase("1.2.3", 102003)] + [TestCase("0.2.3", 2003)] + [TestCase("0.0.3", 3)] + [TestCase("0.0.0", 0)] + [TestCase("11.22.333-prerelease+build", 1122333)] + [TestCase("11.22.33-prerelease+build", 1122033)] + [TestCase("11.22.3-prerelease+build", 1122003)] + [TestCase("11.2.3-prerelease+build", 1102003)] + [TestCase("1.2.3-prerelease+build", 102003)] + [TestCase("0.2.3-prerelease+build", 2003)] + [TestCase("0.0.3-prerelease+build", 3)] + [TestCase("0.0.0-prerelease+build", 0)] + [TestCase("11.22.333-prerelease", 1122333)] + [TestCase("11.22.33-prerelease", 1122033)] + [TestCase("11.22.3-prerelease", 1122003)] + [TestCase("11.2.3-prerelease", 1102003)] + [TestCase("1.2.3-prerelease", 102003)] + [TestCase("0.2.3-prerelease", 2003)] + [TestCase("0.0.3-prerelease", 3)] + [TestCase("0.0.0-prerelease", 0)] + public void Converts_all_formats(string versionString, int versionNumber) { - [TestCase("v11.22.333", 1122333)] - [TestCase("v11.22.33", 1122033)] - [TestCase("v11.22.3", 1122003)] - [TestCase("v11.2.3", 1102003)] - [TestCase("v1.2.3", 102003)] - [TestCase("v0.2.3", 2003)] - [TestCase("v0.0.3", 3)] - [TestCase("v0.0.0", 0)] - [TestCase("11.22.333", 1122333)] - [TestCase("11.22.33", 1122033)] - [TestCase("11.22.3", 1122003)] - [TestCase("11.2.3", 1102003)] - [TestCase("1.2.3", 102003)] - [TestCase("0.2.3", 2003)] - [TestCase("0.0.3", 3)] - [TestCase("0.0.0", 0)] - [TestCase("v11.22.333-description", 1122333)] - [TestCase("v11.22.33-description", 1122033)] - [TestCase("v11.22.3-description", 1122003)] - [TestCase("v11.2.3-description", 1102003)] - [TestCase("v1.2.3-description", 102003)] - [TestCase("v0.2.3-description", 2003)] - [TestCase("v0.0.3-description", 3)] - [TestCase("v0.0.0-description", 0)] - [TestCase("11.22.333-description", 1122333)] - [TestCase("11.22.33-description", 1122033)] - [TestCase("11.22.3-description", 1122003)] - [TestCase("11.2.3-description", 1102003)] - [TestCase("1.2.3-description", 102003)] - [TestCase("0.2.3-description", 2003)] - [TestCase("0.0.3-description", 3)] - [TestCase("0.0.0-description", 0)] - public void Converts_all_formats(string versionString, int versionNumber) - { - VersionToMetrics.ConvertToNumber(versionString).Should().Be(versionNumber); - } + VersionToMetrics.ConvertToNumber(versionString).Should().Be(versionNumber); } } diff --git a/src/Nethermind/Nethermind.Runner/Nethermind.Runner.csproj b/src/Nethermind/Nethermind.Runner/Nethermind.Runner.csproj index a10c9fee8b1..6b7b87d355f 100644 --- a/src/Nethermind/Nethermind.Runner/Nethermind.Runner.csproj +++ b/src/Nethermind/Nethermind.Runner/Nethermind.Runner.csproj @@ -79,9 +79,6 @@ - - PreserveNewest - PreserveNewest @@ -111,25 +108,10 @@ - - - <_ContentIncludedByDefault Remove="Contracts\EntryPoint.json" /> - - - - - - - - - - - - @@ -147,4 +129,26 @@ + + + + + + + + + + + + + $(Commit.Substring(0, 8)) + + + + <_Parameter1>Commit + <_Parameter2>$(Commit) + + + + diff --git a/src/Nethermind/Nethermind.Runner/Program.cs b/src/Nethermind/Nethermind.Runner/Program.cs index 8a02267bf7d..96266ec39c6 100644 --- a/src/Nethermind/Nethermind.Runner/Program.cs +++ b/src/Nethermind/Nethermind.Runner/Program.cs @@ -103,10 +103,10 @@ private static void Run(string[] args) AppDomain.CurrentDomain.ProcessExit += CurrentDomainOnProcessExit; - GlobalDiagnosticsContext.Set("version", ClientVersion.Version); + GlobalDiagnosticsContext.Set("version", ProductInfo.Version); CommandLineApplication app = new() { Name = "Nethermind.Runner" }; _ = app.HelpOption("-?|-h|--help"); - _ = app.VersionOption("-v|--version", () => ClientVersion.Version, () => ClientVersion.Description); + _ = 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); @@ -145,7 +145,7 @@ private static void Run(string[] args) NLogManager logManager = new(initConfig.LogFileName, initConfig.LogDirectory, initConfig.LogRules); _logger = logManager.GetClassLogger(); - if (_logger.IsDebug) _logger.Debug($"Nethermind version: {ClientVersion.Description}"); + if (_logger.IsDebug) _logger.Debug(ProductInfo.ClientId); ConfigureSeqLogger(configProvider); SetFinalDbPath(dbBasePath.HasValue() ? dbBasePath.Value() : null, initConfig); @@ -253,7 +253,7 @@ private static string LoadPluginsDirectory(string[] args) { string shortCommand = "-pd"; string longCommand = "--pluginsDirectory"; - + string[] GetPluginArgs() { for (int i = 0; i < args.Length; i++) @@ -261,14 +261,14 @@ string[] GetPluginArgs() string arg = args[i]; if (arg == shortCommand || arg == longCommand) { - return i == args.Length - 1 ? new[] {arg} : new[] {arg, args[i + 1]}; + return i == args.Length - 1 ? new[] { arg } : new[] { arg, args[i + 1] }; } } return Array.Empty(); } - - CommandLineApplication pluginsApp = new() {Name = "Nethermind.Runner.Plugins"}; + + CommandLineApplication pluginsApp = new() { Name = "Nethermind.Runner.Plugins" }; CommandOption pluginsAppDirectory = pluginsApp.Option($"{shortCommand}|{longCommand} ", "plugins directory", CommandOptionType.SingleValue); string pluginDirectory = "plugins"; pluginsApp.OnExecute(() => @@ -383,7 +383,7 @@ private static IConfigProvider BuildConfigProvider( configProvider.AddSource(new JsonConfigSource(configFilePath)); configProvider.Initialize(); var incorrectSettings = configProvider.FindIncorrectSettings(); - if(incorrectSettings.Errors.Count() > 0) + if (incorrectSettings.Errors.Count() > 0) { logger.Warn($"Incorrect config settings found:{Environment.NewLine}{incorrectSettings.ErrorMsg}"); } @@ -462,10 +462,27 @@ private static void ConfigureSeqLogger(IConfigProvider configProvider) ISeqConfig seqConfig = configProvider.GetConfig(); if (seqConfig.MinLevel != "Off") { - if (_logger.IsInfo) + if (_logger.IsInfo) _logger.Info($"Seq Logging enabled on host: {seqConfig.ServerUrl} with level: {seqConfig.MinLevel}"); NLogConfigurator.ConfigureSeqBufferTarget(seqConfig.ServerUrl, seqConfig.ApiKey, seqConfig.MinLevel); } } + + 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(); + } } }