diff --git a/.circleci/config.yml b/.circleci/config.yml index a0f220dfd7d..c044ed85083 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,34 +1,53 @@ --- version: 2.1 orbs: - win: circleci/windows@2.2.0 + win: circleci/windows@5.0 executors: + besu_executor_small: + docker: + - image: cimg/openjdk:17.0 + resource_class: small + working_directory: ~/project + environment: + GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.workers.max=2 + besu_executor_med: # 2cpu, 4G ram docker: - - image: circleci/openjdk:11.0.8-jdk-buster - auth: - username: $DOCKER_USER_RO - password: $DOCKER_PASSWORD_RO + - image: cimg/openjdk:17.0 resource_class: medium working_directory: ~/project environment: + architecture: "amd64" + GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.workers.max=2 + + besu_arm64_executor_med: # 2cpu, 8G ram + machine: #https://circleci.com/developer/machine/image/ubuntu-2204 + image: ubuntu-2204:2022.10.2 + resource_class: arm.medium + working_directory: ~/project + environment: + architecture: "arm64" GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.workers.max=2 besu_executor_xl: # 8cpu, 16G ram docker: - - image: circleci/openjdk:11.0.8-jdk-buster - auth: - username: $DOCKER_USER_RO - password: $DOCKER_PASSWORD_RO + - image: cimg/openjdk:17.0 resource_class: xlarge working_directory: ~/project environment: GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.workers.max=4 -notify: - webhooks: - - url: $HUBOT_URL + xl_machine_executor: + machine: #https://circleci.com/developer/machine/image/ubuntu-2204 + image: ubuntu-2204:2022.10.2 + resource_class: xlarge + + trivy_executor: + docker: + - image: docker:stable-git + resource_class: small + working_directory: ~/project commands: prepare: @@ -36,10 +55,16 @@ commands: steps: - checkout - run: - name: Install Packages - LibSodium + name: Install Packages - LibSodium, nssdb command: | sudo apt-get update - sudo apt-get install -y libsodium23 libsodium-dev apt-transport-https + sudo apt-get install -y libsodium23 libsodium-dev libjemalloc-dev apt-transport-https haveged libnss3-tools + sudo service haveged restart + java --version + - restore_gradle_cache + restore_gradle_cache: + description: "Restore Gradle cache" + steps: - restore_cache: name: Restore cached gradle dependencies keys: @@ -50,6 +75,10 @@ commands: capture_test_results: description: "Capture test results" steps: + - run: + name: Jacoco + command: | + ./gradlew --no-daemon jacocoTestReport - run: name: Gather test results when: always @@ -64,6 +93,8 @@ commands: done - store_test_results: path: build/test-results + - store_artifacts: + path: besu/build/reports/jacoco capture_test_logs: description: "Capture test logs" @@ -79,14 +110,10 @@ jobs: executor: besu_executor_xl steps: - prepare - - run: - name: DCO check - command: | - ./scripts/dco_check.sh - run: name: Assemble command: | - ./gradlew --no-daemon clean spotlessCheck compileJava compileTestJava assemble + ./gradlew --no-daemon clean compileJava compileTestJava assemble - save_cache: name: Caching gradle dependencies key: deps-{{ checksum "gradle/versions.gradle" }}-{{ .Branch }}-{{ .Revision }} @@ -99,9 +126,10 @@ jobs: - ./ - store_artifacts: name: Distribution artifacts - path: build/distributions + path: build/distributions destination: distributions when: always + testWindows: executor: win/default steps: @@ -122,6 +150,31 @@ jobs: build\distributions\besu\bin\besu.bat --help build\distributions\besu\bin\besu.bat --version + dockerScan: + executor: trivy_executor + steps: + - checkout + - restore_gradle_cache + - setup_remote_docker: + docker_layer_caching: true + - run: + name: Install trivy + command: | + apk add --update-cache --upgrade curl bash + curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin + - run: + name: Scan with trivy + shell: /bin/sh + command: | + for FILE in $(ls docker) + do + if [[ $FILE == "test.sh" || $FILE == "tests" ]]; then + continue + fi + docker pull -q "hyperledger/besu:develop-$FILE" + trivy -q image --exit-code 1 --no-progress --severity HIGH,CRITICAL "hyperledger/besu:develop-$FILE" + done + unitTests: executor: besu_executor_xl steps: @@ -136,7 +189,7 @@ jobs: - capture_test_results integrationTests: - executor: besu_executor_xl + executor: xl_machine_executor steps: - prepare - attach_workspace: @@ -145,10 +198,6 @@ jobs: name: IntegrationTests command: | ./gradlew --no-daemon integrationTest - - run: - name: Javadoc - command: | - ./gradlew --no-daemon javadoc - run: name: CompileJmh command: | @@ -163,22 +212,88 @@ jobs: at: ~/project - run: name: ReferenceTests - no_output_timeout: 20m + no_output_timeout: 30m command: | git submodule update --init --recursive ./gradlew --no-daemon referenceTest - capture_test_results acceptanceTests: - parallelism: 8 - executor: besu_executor_xl + parallelism: 4 + executor: xl_machine_executor + steps: + - prepare + - attach_workspace: + at: ~/project + - run: + name: AcceptanceTests (Mainnet) + no_output_timeout: 20m + command: | + CLASSNAMES=$(circleci tests glob "acceptance-tests/tests/src/test/java/**/*.java" \ + | sed 's@.*/src/test/java/@@' \ + | sed 's@/@.@g' \ + | sed 's/.\{5\}$//' \ + | circleci tests split --split-by=timings --timings-type=classname) + # Format the arguments to "./gradlew test" + GRADLE_ARGS=$(echo $CLASSNAMES | awk '{for (i=1; i<=NF; i++) print "--tests",$i}') + ./gradlew --no-daemon acceptanceTestMainnet $GRADLE_ARGS + - capture_test_results + - capture_test_logs + + acceptanceTestsCliqueBft: + parallelism: 6 + executor: xl_machine_executor + steps: + - prepare + - attach_workspace: + at: ~/project + - run: + name: AcceptanceTests (Non-Mainnet) + no_output_timeout: 20m + command: | + CLASSNAMES=$(circleci tests glob "acceptance-tests/tests/src/test/java/**/*.java" \ + | sed 's@.*/src/test/java/@@' \ + | sed 's@/@.@g' \ + | sed 's/.\{5\}$//' \ + | circleci tests split --split-by=timings --timings-type=classname) + # Format the arguments to "./gradlew test" + GRADLE_ARGS=$(echo $CLASSNAMES | awk '{for (i=1; i<=NF; i++) print "--tests",$i}') + ./gradlew --no-daemon acceptanceTestCliqueBft $GRADLE_ARGS + - capture_test_results + - capture_test_logs + + acceptanceTestsPrivacy: + parallelism: 6 + executor: xl_machine_executor + steps: + - prepare + - attach_workspace: + at: ~/project + - run: + name: AcceptanceTests (Non-Mainnet) + no_output_timeout: 20m + command: | + CLASSNAMES=$(circleci tests glob "acceptance-tests/tests/src/test/java/**/*.java" \ + | sed 's@.*/src/test/java/@@' \ + | sed 's@/@.@g' \ + | sed 's/.\{5\}$//' \ + | circleci tests split --split-by=timings --timings-type=classname) + # Format the arguments to "./gradlew test" + GRADLE_ARGS=$(echo $CLASSNAMES | awk '{for (i=1; i<=NF; i++) print "--tests",$i}') + ./gradlew --no-daemon acceptanceTestPrivacy $GRADLE_ARGS + - capture_test_results + - capture_test_logs + + acceptanceTestsPermissioning: + parallelism: 6 + executor: xl_machine_executor steps: - prepare - attach_workspace: at: ~/project - run: - name: AcceptanceTests - no_output_timeout: 40m + name: AcceptanceTests (Non-Mainnet) + no_output_timeout: 20m command: | CLASSNAMES=$(circleci tests glob "acceptance-tests/tests/src/test/java/**/*.java" \ | sed 's@.*/src/test/java/@@' \ @@ -187,7 +302,7 @@ jobs: | circleci tests split --split-by=timings --timings-type=classname) # Format the arguments to "./gradlew test" GRADLE_ARGS=$(echo $CLASSNAMES | awk '{for (i=1; i<=NF; i++) print "--tests",$i}') - ./gradlew --no-daemon acceptanceTest $GRADLE_ARGS + ./gradlew --no-daemon acceptanceTestPermissioning $GRADLE_ARGS - capture_test_results - capture_test_logs @@ -199,9 +314,13 @@ jobs: at: ~/project - setup_remote_docker - run: - name: hadoLint_openjdk_11 + name: hadoLint_openjdk_17 + command: | + docker run --rm -i hadolint/hadolint < docker/openjdk-17/Dockerfile + - run: + name: hadoLint_openjdk_17_debug command: | - docker run --rm -i hadolint/hadolint < docker/openjdk-11/Dockerfile + docker run --rm -i hadolint/hadolint < docker/openjdk-17-debug/Dockerfile - run: name: hadoLint_openjdk_latest command: | @@ -221,6 +340,40 @@ jobs: curl -L https://github.com/aelsabbahy/goss/releases/download/v0.3.9/goss-linux-amd64 -o ./docker/tests/goss-linux-amd64 ./gradlew --no-daemon testDocker + buildArm64Docker: + executor: besu_arm64_executor_med + steps: + - prepare + - attach_workspace: + at: ~/project + - run: + name: hadoLint_openjdk_17 + command: | + docker run --rm -i hadolint/hadolint < docker/openjdk-17/Dockerfile + - run: + name: hadoLint_openjdk_latest + command: | + docker run --rm -i hadolint/hadolint < docker/openjdk-latest/Dockerfile + - run: + name: hadoLint_graalvm + command: | + docker run --rm -i hadolint/hadolint < docker/graalvm/Dockerfile + - run: + name: Java_17 + command: | + sudo apt install -q --assume-yes openjdk-17-jre-headless openjdk-17-jdk-headless + sudo update-java-alternatives -a + - run: + name: build image + command: | + ./gradlew --no-daemon distDocker + - run: + name: test image + command: | + mkdir -p docker/reports + curl -L https://github.com/aelsabbahy/goss/releases/download/v0.3.9/goss-linux-arm -o ./docker/tests/goss-linux-arm64 + ./gradlew --no-daemon testDocker + publish: executor: besu_executor_med steps: @@ -230,7 +383,7 @@ jobs: - run: name: Publish command: | - ./gradlew --no-daemon bintrayUpload + ./gradlew --no-daemon artifactoryPublish publishDocker: executor: besu_executor_med @@ -243,72 +396,132 @@ jobs: name: Publish Docker command: | docker login --username "${DOCKER_USER_RW}" --password "${DOCKER_PASSWORD_RW}" - # temporarily commented out because AWS credentials are broken - # docker login "${ACR_REPO}" --username "${ACR_USER_RW}" --password "${ACR_PASSWORD_RW}" ./gradlew --no-daemon "-Pbranch=${CIRCLE_BRANCH}" dockerUpload + publishArm64Docker: + executor: besu_arm64_executor_med + steps: + - prepare + - attach_workspace: + at: ~/project + - run: + name: Java_17 + command: | + sudo apt install -q --assume-yes openjdk-17-jre-headless openjdk-17-jdk-headless + sudo update-java-alternatives -a + - run: + name: Publish Docker + command: | + docker login --username "${DOCKER_USER_RW}" --password "${DOCKER_PASSWORD_RW}" + ./gradlew --no-daemon "-Pbranch=${CIRCLE_BRANCH}" dockerUpload + manifestDocker: + executor: besu_executor_med + steps: + - prepare + - setup_remote_docker + - run: + name: Create and publish docker manifest + command: | + docker login --username "${DOCKER_USER_RW}" --password "${DOCKER_PASSWORD_RW}" + ./gradlew --no-daemon "-Pbranch=${CIRCLE_BRANCH}" --parallel manifestDocker + workflows: version: 2 default: jobs: - assemble - unitTests: - requires: + requires: - assemble - context: - - besu-dockerhub-ro - testWindows: requires: - assemble - referenceTests: requires: - assemble - context: - - besu-dockerhub-ro - integrationTests: requires: - assemble - context: - - besu-dockerhub-ro - acceptanceTests: requires: - assemble - context: - - besu-dockerhub-ro + - acceptanceTestsCliqueBft: + requires: + - assemble + - acceptanceTestsPrivacy: + requires: + - assemble + - acceptanceTestsPermissioning: + requires: + - assemble - buildDocker: requires: - - unitTests - context: - - besu-dockerhub-ro + - assemble + - buildArm64Docker: + requires: + - assemble - publish: filters: branches: only: - - master + - main - /^release-.*/ requires: + - assemble - integrationTests - unitTests - acceptanceTests - referenceTests - buildDocker - - buildDocker - context: - - besu-dockerhub-ro - publishDocker: filters: branches: only: - - master + - main - /^release-.*/ requires: + - assemble - integrationTests - unitTests - acceptanceTests - referenceTests - buildDocker context: - - besu-dockerhub-ro - besu-dockerhub-rw - - besu-acr-rw + - publishArm64Docker: + filters: + branches: + only: + - main + - /^release-.*/ + requires: + - integrationTests + - unitTests + - acceptanceTests + - referenceTests + - buildArm64Docker + context: + - besu-dockerhub-rw + - manifestDocker: + filters: + branches: + only: + - main + - /^release-.*/ + requires: + - publishDocker + - publishArm64Docker + context: + - besu-dockerhub-rw + nightly: + triggers: + - schedule: + cron: "0 19 * * *" + filters: + branches: + only: + - main + jobs: + - assemble + - dockerScan diff --git a/.gitattributes b/.gitattributes index 09c9fcd2387..79522fa32e7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14,5 +14,7 @@ *.ico binary *.ttf binary *.woff binary +*.p12 binary +*.db binary *.woff2 binary goss-linux-amd64 binary diff --git a/.github/issue_template.md b/.github/issue_template.md index c1bb6a45fc7..cfae3400266 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,9 +1,9 @@ - + - + @@ -24,6 +24,9 @@ As an [Actor], I want [feature] so that [why]. **Frequency:** [What percentage of the time does it occur?] +### Logs (if a bug) +Please post relevant logs from Besu (and the consensus client, if running proof of stake) from before and after the issue. + ### Versions (Add all that apply) * Software version: [`besu --version`] * Java version: [`java -version`] @@ -32,6 +35,14 @@ As an [Actor], I want [feature] so that [why]. * Virtual Machine software & version: [`vmware -v`] * Docker Version: [`docker version`] * Cloud VM, type, size: [Amazon Web Services I3-large] +* Consensus Client & Version if using Proof of Stake: [e.g. Teku, Lighthouse, Prysm, Nimbus, Lodestar] -### Additional Information +### Smart contract information (If you're reporting an issue arising from deploying or calling a smart contract, please supply related information) +* Solidity version [`solc --version`] +* Repo with minimal set of deployable/reproducible contract code - please provide a link +* Please include specifics on how you are deploying/calling the contract +* Have you reproduced the issue on other eth clients +### Additional Information (Add any of the following or anything else that may be relevant) +* Besu setup info - genesis file, config options +* System info - memory, CPU diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 6e5e1fa16b9..11bac0fb923 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,12 +1,8 @@ - + ## PR description ## Fixed Issue(s) - - -## Changelog - -- [ ] I thought about the changelog and included a [changelog update if required](https://wiki.hyperledger.org/display/BESU/Changelog). \ No newline at end of file + \ No newline at end of file diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml new file mode 100644 index 00000000000..c72331b84e8 --- /dev/null +++ b/.github/workflows/checks.yml @@ -0,0 +1,36 @@ +name: checks +on: + push: + branches: [ main ] + pull_request: + workflow_dispatch: + +jobs: + spotless: + runs-on: [besu,Linux,self-hosted,X64,nodocker] + if: ${{ github.actor != 'dependabot[bot]' }} + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + - name: Set up Java + uses: actions/setup-java@v3 + with: + distribution: adopt + java-version: 17 + cache: gradle + - name: spotless + run: ./gradlew --no-daemon --parallel clean spotlessCheck + javadoc_17: + runs-on: [besu,Linux,self-hosted,X64,nodocker] + if: ${{ github.actor != 'dependabot[bot]' }} + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + - name: Set up Java 17 + uses: actions/setup-java@v3 + with: + distribution: adopt + java-version: 17 + cache: gradle + - name: javadoc (JDK 17) + run: ./gradlew --no-daemon clean javadoc diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000000..0e170cfb288 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,66 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + paths-ignore: + - '**/*.json' + - '**/*.md' + - '**/*.properties' + - '**/*.txt' +jobs: + analyze: + name: Analyze + runs-on: [besu,Linux,self-hosted,X64,nodocker] + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'java' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Java + uses: actions/setup-java@v3 + with: + distribution: adopt + java-version: 17 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + queries: security-and-quality,security-extended + + # Autobuild failed (OOM) + # Hence, supply memory args for gradle build + - run: | + JAVA_OPTS="-Xmx1000M" ./gradlew --no-scan compileJava + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/dco-merge-group.yml b/.github/workflows/dco-merge-group.yml new file mode 100644 index 00000000000..f93170b1c24 --- /dev/null +++ b/.github/workflows/dco-merge-group.yml @@ -0,0 +1,10 @@ +name: dco +on: + merge_group: + +jobs: + dco: + runs-on: [besu,Linux,self-hosted,nodocker] + if: ${{ github.actor != 'dependabot[bot]' }} + steps: + - run: echo "This DCO job runs on merge_queue event and doesn't check PR contents" \ No newline at end of file diff --git a/.github/workflows/dco.yml b/.github/workflows/dco.yml new file mode 100644 index 00000000000..341e1d38776 --- /dev/null +++ b/.github/workflows/dco.yml @@ -0,0 +1,20 @@ +name: dco +on: + pull_request: + workflow_dispatch: + +jobs: + dco: + runs-on: [besu,Linux,self-hosted,nodocker] + if: ${{ github.actor != 'dependabot[bot]' }} + steps: + - run: echo "This DCO job runs on pull_request event and workflow_dispatch" + - name: Get PR Commits + id: 'get-pr-commits' + uses: tim-actions/get-pr-commits@v1.2.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: DCO Check + uses: tim-actions/dco@v1.1.0 + with: + commits: ${{ steps.get-pr-commits.outputs.commits }} \ No newline at end of file diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml new file mode 100644 index 00000000000..bb0feddd1e8 --- /dev/null +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 +name: "Validate Gradle Wrapper" +on: [push, pull_request] + +jobs: + validation: + name: "Gradle Wrapper Validation" + runs-on: [besu,Linux,self-hosted,nodocker] + steps: + - uses: actions/checkout@v3 + - uses: gradle/wrapper-validation-action@v1 diff --git a/.github/workflows/pr-checklist-on-open.yml b/.github/workflows/pr-checklist-on-open.yml new file mode 100644 index 00000000000..d89748a9437 --- /dev/null +++ b/.github/workflows/pr-checklist-on-open.yml @@ -0,0 +1,20 @@ +name: "comment on pr with checklist" +on: + pull_request_target: + types: [ opened ] + branches: [ main ] +jobs: + checklist: + name: "add checklist as a comment on newly opened PRs" + runs-on: [besu,Linux,self-hosted,nodocker] + steps: + - uses: actions/github-script@v5 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: '- [ ] I thought about documentation and added the `doc-change-required` label to this PR if [updates are required](https://wiki.hyperledger.org/display/BESU/Documentation).\n- [ ] I thought about the changelog and included a [changelog update if required](https://wiki.hyperledger.org/display/BESU/Changelog).\n- [ ] If my PR includes database changes (e.g. KeyValueSegmentIdentifier) I have thought about compatibility and performed forwards and backwards compatibility tests' + }) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000000..36ea3ab50fe --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,21 @@ +name: release besu +on: + release: + types: released +jobs: + dockerPromoteX64: + runs-on: [besu,Linux,self-hosted,nodocker] + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '17' + - name: Login to DockerHub + run: echo '${{ secrets.DOCKER_PASSWORD_RW }}' | docker login -u '${{ secrets.DOCKER_USER_RW }}' --password-stdin + - name: Setup Gradle + uses: gradle/gradle-build-action@v2 + - name: Docker upload + run: ./gradlew "-Prelease.releaseVersion=${{ github.ref_name }}" "-PdockerOrgName=${{ secrets.DOCKER_ORG }}" dockerUploadRelease + - name: Docker manifest + run: ./gradlew "-Prelease.releaseVersion=${{ github.ref_name }}" "-PdockerOrgName=${{ secrets.DOCKER_ORG }}" manifestDockerRelease diff --git a/.github/workflows/repolinter.yml b/.github/workflows/repolinter.yml new file mode 100644 index 00000000000..39b0d6cab39 --- /dev/null +++ b/.github/workflows/repolinter.yml @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: Apache-2.0 +# Hyperledger Repolinter Action +name: Repolinter + +on: + workflow_dispatch: + push: + branches: + - master + - main + pull_request: + branches: + - master + - main + +jobs: + build: + runs-on: [besu,Linux,self-hosted,X64,docker] + container: ghcr.io/todogroup/repolinter:v0.10.1 + steps: + - name: Checkout Code + uses: actions/checkout@v3 + - name: Lint Repo + run: bundle exec /app/bin/repolinter.js --rulesetUrl https://raw.githubusercontent.com/hyperledger-labs/hyperledger-community-management-tools/main/repo_structure/repolint.json --format markdown diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml new file mode 100644 index 00000000000..e3a6e088e06 --- /dev/null +++ b/.github/workflows/sonarcloud.yml @@ -0,0 +1,42 @@ + +name: SonarCloud analysis + +on: + workflow_dispatch: + schedule: + # * is a special character in YAML so you have to quote this string + # expression evaluates to midnight on Tuesdays UTC + - cron: '0 0 * * 2' + +permissions: + pull-requests: read # allows SonarCloud to decorate PRs with analysis results + +jobs: + Analysis: + runs-on: ubuntu-latest + if: github.repository == 'hyperledger/besu' + steps: + - name: checkout + uses: actions/checkout@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + - name: Cache SonarCloud packages + uses: actions/cache@v3 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + - name: Cache Gradle packages + uses: actions/cache@v3 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: ${{ runner.os }}-gradle + - name: Build and analyze + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: ./gradlew build sonarqube --continue --info diff --git a/.gitignore b/.gitignore index 76ab7d30876..0465ea5e30f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ *~.nib *.iml *.launch -*.swp *.log .classpath .DS_Store @@ -29,3 +28,5 @@ site/ /kubernetes/reports/ /kubernetes/besu-*.tar.gz **/src/*/generated +jitpack.yml +/ethereum/eth/src/test/resources/tx.csv.gz diff --git a/.gitmodules b/.gitmodules index 0efd88e0991..97132b17c6d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "eth-ref-tests"] - path = ethereum/referencetests/src/test/resources + path = ethereum/referencetests/src/reference-test/external-resources url = https://github.com/ethereum/tests.git ignore = all diff --git a/.lgtm.yml b/.lgtm.yml new file mode 100644 index 00000000000..6edcbd6b2a9 --- /dev/null +++ b/.lgtm.yml @@ -0,0 +1,5 @@ +extraction: + java: + index: + java_version: "17" + build_command: JAVA_OPTS="-Xmx1000M" ./gradlew -Dorg.gradle.java.home=/usr/lib/jvm/java-11-openjdk-amd64 --no-scan compileJava diff --git a/CHANGELOG.md b/CHANGELOG.md index e2b0979bf19..54a4ae5c926 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,1480 @@ # Changelog +## 23.4.5 + +### Breaking Changes + +### Additions and Improvements +- EvmTool now executes the `execution-spec-tests` via the `t8n` and `b11r`. See the [README](ethereum/evmtool/README.md) in EvmTool for more instructions. +- Improve lifecycle management of the transaction pool [#5634](https://github.com/hyperledger/besu/pull/5634) + +### Bug Fixes +- Use the node's configuration to determine if DNS enode URLs are allowed in calls to `admin_addPeer` and `admin_removePeer` [#5584](https://github.com/hyperledger/besu/pull/5584) +- Align the implementation of Eth/68 `NewPooledTransactionHashes` to other clients, using unsigned int for encoding size. [#5640](https://github.com/hyperledger/besu/pull/5640) +- Failure at startup when enabling layered txpool before initial sync done [#5636](https://github.com/hyperledger/besu/issues/5636) + +### Download Links + +--- + +## 23.4.4 + +### Breaking Changes +- Move blockchain related variables in a dedicated storage, to pave the way to future optimizations [#5471](https://github.com/hyperledger/besu/pull/5471). The migration is performed automatically at startup, +and in case a rollback is needed, before installing a previous version, the migration can be reverted, using the subcommand `storage revert-variables` with the same configuration use to run Besu. +- Remove deprecated Rinkeby named network. [#5540](https://github.com/hyperledger/besu/pull/5540) +- Use BlobDB for blockchain storage to reduce initial sync time and write amplification (PR #5475). This PR reduces sync time by 14 hours on m6a.xlarge VM (1 day 8 hours 27 minutes instead of 1 day 22 hours 4 minutes). +### Additions and Improvements +- Allow Ethstats connection url to specify ws:// or wss:// scheme. [#5494](https://github.com/hyperledger/besu/issues/5494) +- Add support for Shanghai changes to the GraphQL service [#5496](https://github.com/hyperledger/besu/pull/5496) +- Unite the tx-pool CLI options under the same Tx Pool Options group in UX. [#5466](https://github.com/hyperledger/besu/issues/5466) +- Tidy DEBUG logs by moving engine API full logging to TRACE [#5529](https://github.com/hyperledger/besu/pull/5529) +- Remove PoW validation if merge is enabled as it is not needed any more [#5538](https://github.com/hyperledger/besu/pull/5538) +- Use BlobDB for blockchain storage to reduce initial sync time and write amplification [#5475](https://github.com/hyperledger/besu/pull/5475) +- Add healing flat db mechanism with early access CLI options `--Xsnapsync-synchronizer-flat-db-healing-enabled=true` [#5319](https://github.com/hyperledger/besu/pull/5319) +- Add debug_getRawTransaction method to the DEBUG suite [#5635](https://github.com/hyperledger/besu/pull/5635) + +### Bug Fixes +- Fix backwards sync bug where chain is rolled back too far, especially when restarting Nimbus [#5497](https://github.com/hyperledger/besu/pull/5497) +- Check to ensure storage and transactions are not closed prior to reading/writing [#5527](https://github.com/hyperledger/besu/pull/5527) +- Fix the unavailability of account code and storage on GraphQL/Bonsai [#5548](https://github.com/hyperledger/besu/pull/5548) + +### Download Links +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/23.4.4/besu-23.4.4.tar.gz / sha256: bd476d235b6fe1f236a62bc709f41c87deb68b72c47bb5b58e56b9d9283af2c4 +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/23.4.4/besu-23.4.4.zip / sha256: 4575000f4fd21d318e7b77340c9281d496bc800bee5b45a13684319e6f28bf27 + +## 23.4.3 + +- Was not released (failed burn-in test) + +- ## 23.4.2 + +- Was not released (failed burn-in test) + +## 23.4.1 + +### Breaking Changes +- Add request content length limit for the JSON-RPC API (5MB) [#5467](https://github.com/hyperledger/besu/pull/5467) +- `min-block-occupancy-ratio` options is now ignored on PoS networks [#5491](https://github.com/hyperledger/besu/pull/5491) + +### Additions and Improvements +- Set the retention policy for RocksDB log files to maintain only the logs from the last week [#5428](https://github.com/hyperledger/besu/pull/5428) +- "Big-EOF" (the EOF version initially slotted for Shanghai) has been moved from Cancun to FutureEIPs [#5429](https://github.com/hyperledger/besu/pull/5429) +- EIP-4844: Zero blob transactions are invalid [#5425](https://github.com/hyperledger/besu/pull/5425) +- Transaction pool flag to disable specific behaviors for locally submitted transactions [#5418](https://github.com/hyperledger/besu/pull/5418) +- Added In-Protocol Deposit prototype (EIP-6110) in the experimental eip. [#5005](https://github.com/hyperledger/besu/pull/5055) [#5295](https://github.com/hyperledger/besu/pull/5295) +- New optional feature to save the txpool content to file on shutdown and reloading it on startup [#5434](https://github.com/hyperledger/besu/pull/5434) +- New option to send SNI header in TLS ClientHello message [#5439](https://github.com/hyperledger/besu/pull/5439) +- Early access - layered transaction pool implementation [#5290](https://github.com/hyperledger/besu/pull/5290) +- New RPC method `debug_getRawReceipts` [#5476](https://github.com/hyperledger/besu/pull/5476) +- Add TrieLogFactory plugin support [#5440](https://github.com/hyperledger/besu/pull/5440) +- Ignore `min-block-occupancy-ratio` option when on PoS networks, since in some cases, it prevents to have full blocks even if enough transactions are present [#5491](https://github.com/hyperledger/besu/pull/5491) + +### Bug Fixes +- Fix eth_feeHistory response for the case in which blockCount is higher than highestBlock requested. [#5397](https://github.com/hyperledger/besu/pull/5397) +- Fix Besu Docker image failing to start due to NoClassDefFoundError with org.xerial.snappy.Snappy library. [#5462](https://github.com/hyperledger/besu/pull/5462) + +### Download Links + +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.4.1/besu-23.4.1.tar.gz / sha256: 49d3a7a069cae307497093d834f873ce7804a46dd59207d5e8321459532d318e +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.4.1/besu-23.4.1.zip / sha256: 1d82ed83a816968aa9366d9310b275ca6438100f5d3eb1ec03d3474b2a5f5e76 + +## 23.4.0 + +### Breaking Changes +- In `evmtool` (an offline EVM executor tool principally used for reference tests), the `--prestate` and `--genesis` options no longer parse genesis files containing IBFT, QBFT, and Clique network definitions. The same genesis files will work with those json entries removed. [#5192](https://github.com/hyperledger/besu/pull/5192) +- In `--ethstats`, if the port is not specified in the URI, it will default to 443 and 80 for ssl and non-ssl connections respectively instead of 3000. [#5301](https://github.com/hyperledger/besu/pull/5301) +- Remove IBFT 1.0 feature [#5302](https://github.com/hyperledger/besu/pull/5302) +- Remove GoQuorum-compatible privacy feature [#5303](https://github.com/hyperledger/besu/pull/5303) +- Remove launcher command line utility [#5355](https://github.com/hyperledger/besu/pull/5355) +- Remove deprecated `tx-pool-future-max-by-account` option, see instead: `tx-pool-limit-by-account-percentage` [#5361](https://github.com/hyperledger/besu/pull/5361) +- Default configuration for the deprecated ECIP-1049 network has been removed from the CLI network list [#5371](https://github.com/hyperledger/besu/pull/5371) +- Besu now requires glibc 2.32 or later to run. Ubuntu 20.04 users will need to update to a newer version of Ubuntu, 22.04 or later to run Besu + +### Additions and Improvements +- An alternate build target for the EVM using GraalVM AOT compilation was added. [#5192](https://github.com/hyperledger/besu/pull/5192) +- To generate the binary install and use GraalVM 23.3.r17 or higher and run `./gradlew nativeCompile`. The binary will be located in `ethereum/evmtool/build/native/nativeCompile` +- Upgrade RocksDB version from 7.7.3 to 8.0.0. Besu Team [contributed](https://github.com/facebook/rocksdb/pull/11099) to this release to make disabling checksum verification work. +- Log an error with stacktrace when RPC responds with internal error [#5288](https://github.com/hyperledger/besu/pull/5288) +- `--ethstats-cacert` to specify root CA of ethstats server (useful for non-production environments). [#5301](https://github.com/hyperledger/besu/pull/5301) +- Update most dependencies to latest version [#5269](https://github.com/hyperledger/besu/pull/5269) +- If jemalloc is used, print its version in the configuration overview [#4738](https://github.com/hyperledger/besu/pull/4738) +- Add metrics for accounts and storage reads (Flat database vs Merkle Patricia Trie) [#5315](https://github.com/hyperledger/besu/pull/5315) +- Offload LogBloom cache generation to computation executor, to avoid interfere with other scheduled tasks [#4530](https://github.com/hyperledger/besu/pull/4530) +- Reference tests are upgraded to use v12.1 of the ethereum tests [#5343](https://github.com/hyperledger/besu/pull/5343) +- Add new sepolia bootnodes, which should improve peering in the testnet. [#5352](https://github.com/hyperledger/besu/pull/5352) +- Renamed --bonsai-maximum-back-layers-to-load option to --bonsai-historical-block-limit for clarity. Removed --Xbonsai-use-snapshots option as it is no longer functional [#5337](https://github.com/hyperledger/besu/pull/5337) +- Change Forest to use TransactionDB instead of OptimisticTransactionDB [#5328](https://github.com/hyperledger/besu/pull/5328) +- Performance: Reduced usage of UInt256 in EVM operations [#5331](https://github.com/hyperledger/besu/pull/5331) +- Changed wrong error message "Invalid params" when private tx is reverted to "Execution reverted" with correct revert reason in data. [#5369](https://github.com/hyperledger/besu/pull/5369) +- Changes to the way gas is estimated to provide an exact gas estimate [#5142](https://github.com/hyperledger/besu/pull/5142) +- Add zero reads to Bonsai TrieLogs [#5317](https://github.com/hyperledger/besu/pull/5317) +- Bonsai TrieLog serialization interface and default implementation [#5372](https://github.com/hyperledger/besu/pull/5372) + +### Bug Fixes +- Fix eth_getBlockByNumber cache error for latest block when called during syncing [#5292](https://github.com/hyperledger/besu/pull/5292) +- Fix QBFT and IBFT unable to propose blocks on London when zeroBaseFee is used [#5276](https://github.com/hyperledger/besu/pull/5276) +- Make QBFT validator smart contract mode work with london fork [#5249](https://github.com/hyperledger/besu/issues/5249) +- Try to connect to EthStats server by default with ssl followed by non-ssl. [#5301](https://github.com/hyperledger/besu/pull/5301) +- Allow --miner-extra-data to be used in Proof-of-Stake block production [#5291](https://github.com/hyperledger/besu/pull/5291) +- Add withdrawals to payloadId calculation to avoid collisions [#5321](https://github.com/hyperledger/besu/pull/5321) +- Re-implement trace_block, trace_filter and trace_replayBlockTransactions RPC endpoints to fix memory issues and improve performance [#5131](https://github.com/hyperledger/besu/pull/5131) + +### Download Links +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.4.0/besu-23.4.0.zip / sha256: 023a267ee07ed6e069cb15020c1c0262efc5ea0a3e32adc6596068cff7fd0be5 +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.4.0/besu-23.4.0.tar.gz / sha256: 821695b3255c9f646f4d527e374219c96416f498231520f2eec2bebedc53f5a0 + +## 23.1.3 - Nimbus Hotfix +This update is strongly recommended for anyone running Nimbus with Besu. Due to the way Nimbus send request data, this can lead to a missed block proposal in certain circumstances. + +### Bug Fixes +Add withdrawals to payloadId calculation to avoid collisions #5321 +Download Links +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.1.3/besu-23.1.3.tar.gz / sha256: 36898932a7535c4d126c1980443b33c9a4971f9354112992a18ee134c1777aa3 +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.1.3/besu-23.1.3.zip / sha256: adb3b17e45217f86a56f07f09faba2e5d8a0eb8a585ad5307696d6cc58ee2f73 + +## 23.1.2 +This update is a mainnet-compatible Shanghai/Capella upgrade and is recommended for all Mainnet users. + +### Breaking Changes + +### Additions and Improvements +- Schedule Shanghai (Shapella) fork for Mainnet [#5230](https://github.com/hyperledger/besu/pull/5230) +- Increase default from 1000 to 5000 for `--rpc-max-logs-range` [#5209](https://github.com/hyperledger/besu/pull/5209) +- Bonsai-safe refactor [#5123](https://github.com/hyperledger/besu/pull/5123) +- Safe tracing [#5197](https://github.com/hyperledger/besu/pull/5197) + +### Bug Fixes +- Persist backward sync status to support resuming across restarts [#5182](https://github.com/hyperledger/besu/pull/5182) + +### Download Links +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.1.2/besu-23.1.2.tar.gz / sha256: 3d3a709a3aab993a0801b412a4719d74e319f942ddc13fb0f30b3c4a54d12538 +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.1.2/besu-23.1.2.zip / sha256: 2a9ff091cb4349fc23625a52089400bb6529a831eb22d15d0221cb27039ab203 + +## 23.1.1 +This update is required for the Goerli Shanghai/Capella upgrade and recommended for all Mainnet users. If you use Besu on Goerli, update to 23.1.1. If you previously used 23.1.1-RC1, update to test 23.1.1 on Goerli. + +### Breaking Changes + +### Additions and Improvements +- Add support for Shanghai in Sepolia https://github.com/hyperledger/besu/pull/5088 +- Add implementation for engine_getPayloadBodiesByRangeV1 and engine_getPayloadBodiesByHashV1 https://github.com/hyperledger/besu/pull/4980 +- If a PoS block creation repetition takes less than a configurable duration, then waits before next repetition https://github.com/hyperledger/besu/pull/5048 +- Allow other users to read the /opt/besu dir when using docker https://github.com/hyperledger/besu/pull/5092 +- Invalid params - add some error detail #5066 +- Added the option --kzg-trusted-setup to pass a custom setup file for custom networks or to override the default one for named networks [#5084](https://github.com/hyperledger/besu/pull/5084) +- Gas accounting for EIP-4844 [#4992](https://github.com/hyperledger/besu/pull/4992) +- Goerli configs for shapella [#5151](https://github.com/hyperledger/besu/pull/5151) + +### Bug Fixes +- Fix engine_getPayloadV2 block value calculation [#5040](https://github.com/hyperledger/besu/issues/5040) +- Moves check for init code length before balance check [#5077](https://github.com/hyperledger/besu/pull/5077) +- Address concurrency problems with eth_call [#5179](https://github.com/hyperledger/besu/pull/5179) + +### Download Links +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.1.1/besu-23.1.1.tar.gz / sha256: 11c3e5cdbc06df16a690e7ee9f98eefa46848f9fa280824b6e4c896d88f6b975 +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.1.1/besu-23.1.1.zip / sha256: afcf852f193adb8e82d187aa4f02e4669f12cc680270624d37101b94cf37adec + +## 23.1.1-RC1 +### Sepolia Shanghai Release aka Sepolia Shapella aka Shapolia + +This update is **not recommended for mainnet users**. + +Besu 23.1.1-RC1 is a **required update for Sepolia users** + +Sepolia Shanghai hardfork scheduled for: **Tue Feb 28 2023 04:04:48 UTC** + +--- + +This release has everything from [23.1.0](https://github.com/hyperledger/besu/releases/tag/23.1.0) and in addition the following: + +### Additions and Improvements +- Add support for Shanghai in Sepolia https://github.com/hyperledger/besu/pull/5088 +- Add implementation for engine_getPayloadBodiesByRangeV1 and engine_getPayloadBodiesByHashV1 https://github.com/hyperledger/besu/pull/4980 +- If a PoS block creation repetition takes less than a configurable duration, then waits before next repetition https://github.com/hyperledger/besu/pull/5048 +- Allow other users to read the /opt/besu dir when using docker https://github.com/hyperledger/besu/pull/5092 +- Invalid params - add some error detail [#5066](https://github.com/hyperledger/besu/pull/5066) + +### Bug fixes +- Fix engine_getPayloadV2 block value calculation https://github.com/hyperledger/besu/issues/5040 +- Moves check for init code length before balance check https://github.com/hyperledger/besu/pull/5077 + +### Download Links +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.1.1-RC1/besu-23.1.1-RC1.tar.gz / sha256: 82cff41f3eace02006b0e670605848e0e77e045892f8fa9aad66cbd84a88221e +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.1.1-RC1/besu-23.1.1-RC1.zip / sha256: 469c8d6a8ca9d78ee111ff1128d00bf3bcddacbf5b800ef6047717a2da0cc21d + +## 23.1.0 +Besu 23.1.0 is a recommended update for Mainnet users. Thank you all for your patience as we crafted this quarterly release. + +This is a rather large release with some breaking changes, so please be sure to read these notes carefully before you upgrade any Besu instances. We are including a move to Java 17 LTS. To build and run Besu, please make sure you have Java 17 on the host machine. Additionally, there are a host of spec compliance changes that change existing formats, so please check the specific RPC updates. Lastly, this release formalizes a deprecation notice for GoQuorum privacy modes and IBFT1.0 in Besu. These will be removed in the 23.4 series, unless otherwise stated. + +From the improvements and fixes side, we have a host of execution performance improvements and fixes for defects with bonsai storage. We have also included an error detection and auto-heal capability for nodes that encounter state issues. This should keep nodes online and validating that may have previously required a resync. + +One final note. 23.1.0 is not a Shanghai ready release. If you intend to test Besu on the long-lived testnets like Zhejiang, please [follow the instructions here](https://notes.ethereum.org/@launchpad/zhejiang). We will have more to share on our official Shanghai releases soon. + +### Breaking Changes +- Change JsonRpc http service to return the error -32602 (Invalid params) with a 200 http status code +- Besu requires minimum Java 17 and up to build and run [#3320](https://github.com/hyperledger/besu/issues/3320) +- PKCS11 with nss module (PKCS11 based HSM can be used in DevP2P TLS and QBFT PKI) does not work with RSA keys + in Java 17. SoftHSM is tested manually and working. (Other PKCS11 HSM are not tested). The relevant unit and acceptance + tests are updated to use EC private keys instead of RSA keys. +- Change eth_feeHistory parameter `blockCount` to accept hexadecimal string (was accepting plain integer) [#5047](https://github.com/hyperledger/besu/pull/5047) +- Default configurations for the deprecated Ropsten, Kiln, Shandong, and Astor networks have been removed from the CLI network list. These networks can currently be accessed but will require a user-provided genesis configuration. [#4869](https://github.com/hyperledger/besu/pull/4869) +- GoQuorum-compatible privacy is deprecated and will be removed in 23.4 +- IBFT 1.0 is deprecated and will be removed in 23.4 +- Optimize SSTORE Operation execution time (memoize current and original value) [#4836](https://github.com/hyperledger/besu/pull/4836) + +### Additions and Improvements +- Default rpc batch request to 1024 [#5104](https://github.com/hyperledger/besu/pull/5104) [#5108](https://github.com/hyperledger/besu/pull/5108) +- Add a new CLI option to limit the number of requests in a single RPC batch request. [#4965](https://github.com/hyperledger/besu/pull/4965) +- Support for new DATAHASH opcode as part of EIP-4844 [#4823](https://github.com/hyperledger/besu/issues/4823) +- Send only hash announcement for blob transaction type [#4940](https://github.com/hyperledger/besu/pull/4940) +- Add `excess_data_gas` field to block header [#4958](https://github.com/hyperledger/besu/pull/4958) +- Add `max_fee_per_data_gas` field to transaction [#4970](https://github.com/hyperledger/besu/pull/4970) +- Added option to evm CLI tool to allow code execution at specific forks [#4913](https://github.com/hyperledger/besu/pull/4913) +- Improve get account performance by using the world state updater cache [#4897](https://github.com/hyperledger/besu/pull/4897) +- Add new KZG precompile and option to override the trusted setup being used [#4822](https://github.com/hyperledger/besu/issues/4822) +- Add implementation for eth_createAccessList RPC method [#4942](https://github.com/hyperledger/besu/pull/4942) +- Updated reference tests to v11.3 [#4996](https://github.com/hyperledger/besu/pull/4996) +- Add DebugGetRawBlock and DebugGetRawHeader RPC methods [#5011](https://github.com/hyperledger/besu/pull/5011) +- Besu requires minimum Java 17 and up to build and run [#3320](https://github.com/hyperledger/besu/issues/3320) +- Add worldstate auto-heal mechanism [#5059](https://github.com/hyperledger/besu/pull/5059) +- Support for EIP-4895 - Withdrawals for Shanghai fork +- Improve SLOAD and SSTORE performance by caching empty slots [#4874](https://github.com/hyperledger/besu/pull/4874) +- RPC methods that lookup block by hash will now return an error response if no block found [#4582](https://github.com/hyperledger/besu/pull/4582) +- Added support for `safe` and `finalized` strings for the RPC methods using defaultBlock parameter [#4902](https://github.com/hyperledger/besu/pull/4902) +- Added post-execution state logging option to EVM Tool [#4709](https://github.com/hyperledger/besu/pull/4709) +- Add access list to Transaction Call Object [#4802](https://github.com/hyperledger/besu/issues/4801) +- Add timestamp fork support, including shanghaiTime and cancunTime forks [#4743](https://github.com/hyperledger/besu/pull/4743) +- Optimization: Memoize transaction size and hash at the same time [#4812](https://github.com/hyperledger/besu/pull/4812) +- Add chain data pruning feature with three experimental CLI options: `--Xchain-pruning-enabled`, `--Xchain-pruning-blocks-retained` and `--Xchain-pruning-frequency` [#4686](https://github.com/hyperledger/besu/pull/4686) + - Note that chain pruning is hidden and disabled by default. Once you choose to enable chain pruning, a new column family will be added to the db and you cannot roll back to a previous versi + on of Besu. + +### Bug Fixes +- Mitigation fix for stale bonsai code storage leading to log rolling issues on contract recreates [#4906](https://github.com/hyperledger/besu/pull/4906) +- Ensure latest cached layered worldstate is subscribed to storage, fix problem with RPC calls using 'latest' [#5076](https://github.com/hyperledger/besu/pull/5076) +- Fix for segmentation faults on worldstate truncation, snap-sync starts [#4786](https://github.com/hyperledger/besu/pull/4786) +- Fix for worldstate mismatch on failed forkchoiceUpdate [#4862](https://github.com/hyperledger/besu/pull/4862) + +Download Links +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.1.0/besu-23.1.0.tar.gz / sha256: 9081da04d47c3ff0a6ecc2256d353c7a02212f9b46f2c867a9365e18026c3a6e +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.1.0/besu-23.1.0.zip / sha256: e037f5c8f976150af40403311d1c81018f4c3dfbef0ad33324d8c3e708d1fdca + +## 23.1.0-RC1 + +### Breaking Changes +- Default configurations for the deprecated Ropsten, Kiln, Shandong, and Astor networks have been removed from the CLI network list. These networks can currently be accessed but will require a user-provided genesis configuration. [#4869](https://github.com/hyperledger/besu/pull/4869) + +### Additions and Improvements + +- Improve SLOAD and SSTORE performance by caching empty slots [#4874](https://github.com/hyperledger/besu/pull/4874) +- RPC methods that lookup block by hash will now return an error response if no block found [#4582](https://github.com/hyperledger/besu/pull/4582) +- Added support for `safe` and `finalized` strings for the RPC methods using defaultBlock parameter [#4902](https://github.com/hyperledger/besu/pull/4902) + +### Bug Fixes + +### Download Links +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.1.0-RC1/besu-23.1.0-RC1.tar.gz / sha256: 30906891e528b3b4e3ce8e2313550a1da066b31ea10b05456dd0ad026792b46d +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.1.0-RC1/besu-23.1.0-RC1.zip / sha256: 9067d1929079ae4a7c165e6f1e2bae08834939ed191f976d26544dc93352c306 + +## 23.1.0-beta + +### Breaking Changes +- GoQuorum-compatible privacy is deprecated and will be removed in 23.4 +- IBFT 1.0 is deprecated and will be removed in 23.4 +- Optimize SSTORE Operation execution time (memoize current and original value) [#4836](https://github.com/hyperledger/besu/pull/4836) + +### Additions and Improvements +- Added post-execution state logging option to EVM Tool [#4709](https://github.com/hyperledger/besu/pull/4709) +- Add access list to Transaction Call Object [#4802](https://github.com/hyperledger/besu/issues/4801) +- Add timestamp fork support, including shanghaiTime and cancunTime forks [#4743](https://github.com/hyperledger/besu/pull/4743) +- Optimization: Memoize transaction size and hash at the same time [#4812](https://github.com/hyperledger/besu/pull/4812) +- Add chain data pruning feature with three experimental CLI options: `--Xchain-pruning-enabled`, `--Xchain-pruning-blocks-retained` and `--Xchain-pruning-frequency` [#4686](https://github.com/hyperledger/besu/pull/4686) + - Note that chain pruning is hidden and disabled by default. Once you choose to enable chain pruning, a new column family will be added to the db and you cannot roll back to a previous version of Besu. + +### Bug Fixes +- Fix for segmentation faults on worldstate truncation, snap-sync starts [#4786](https://github.com/hyperledger/besu/pull/4786) +- Fix for worldstate mismatch on failed forkchoiceUpdate [#4862](https://github.com/hyperledger/besu/pull/4862) + +### Download Links + +## 22.10.3 + +### Breaking Changes +- Added `--rpc-max-logs-range` CLI option to allow limiting the number of blocks queried by `eth_getLogs` RPC API. Default value: 1000 [#4597](https://github.com/hyperledger/besu/pull/4597) +- The `graalvm` docker variant no longer meets the performance requirements for Ethereum Mainnet. The `openjdk-11` and `openjdk-latest` variants are recommended in its place. + +### Additions and Improvements +- Implement Eth/68 sub-protocol [#4715](https://github.com/hyperledger/besu/issues/4715) +- Increase the speed of modexp gas execution and execution. [#4780](https://github.com/hyperledger/besu/pull/4780) +- Added experimental CLI options `--Xeth-capability-max` and `--Xeth-capability-min` to specify a range of capabilities to be supported by the Eth protocol. [#4752](https://github.com/hyperledger/besu/pull/4752) +- Set the default curve in the EVMTool, like is done in production operations [#4790](https://github.com/hyperledger/besu/pull/4790) + +### Bug Fixes +- Fix storage key format for eth_getProof so that it follows the EIP-1474 spec [#4564](https://github.com/hyperledger/besu/pull/4564) + +### Download Links +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.10.3/besu-22.10.3.tar.gz / sha256: 7213f9445a84a196e94ae1877c6fdb1e51d37bfb19615da02ef5121d4f40e38c +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.10.3/besu-22.10.3.zip / sha256: 0bf6bc98e01b0c1045f1b7d841a390c575bc5203c2a4e543d922fbc1ea0d3d5d + +## 22.10.2 +This is a hotfix release to resolve a race condition that results in segfaults, introduced in 22.10.1 release. + +### Bug Fixes +- bugfix for async operations on Snapshot worldstates [#4767](https://github.com/hyperledger/besu/pull/4767) + +### Download Links +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.10.2/besu-22.10.2.tar.gz / sha256: cdb36141e3cba6379d35016e0a2de2edba579d4786124b5f7257b1e4a68867a2 +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.10.2/besu-22.10.2.zip / sha256: 4c9208f684762670cb4f2c6ebfb6930e05e339a7c3c586fe8caa9f26462830aa + + +## 22.10.1 + +### Breaking Changes +- Fields `publicKey` and `raw` removed from RPC API `Transaction` result object [#4575](https://github.com/hyperledger/besu/pull/4575) + +### Additions and Improvements +- Explain and improve price validation for London and local transactions during block proposal selection [#4602](https://github.com/hyperledger/besu/pull/4602) +- Support for ephemeral testnet Shandong, for EOF testing. [#4599](https://github.com/hyperledger/besu/pull/4599) +- Improve performance of block processing by parallelizing some parts during the "commit" step [#4635](https://github.com/hyperledger/besu/pull/4635) +- Upgrade RocksDB version from 7.6.0 to 7.7.3 +- Added new RPC endpoints `debug_setHead` & `debug_replayBlock [#4580](https://github.com/hyperledger/besu/pull/4580) +- Upgrade OpenTelemetry to version 1.19.0 [#3675](https://github.com/hyperledger/besu/pull/3675) +- Implement Eth/67 sub-protocol [#4596](https://github.com/hyperledger/besu/issues/4596) +- Backward sync log UX improvements [#4655](https://github.com/hyperledger/besu/pull/4655) +- Enable RocksDB Bloom filters to improve read performance [#4682](https://github.com/hyperledger/besu/pull/4682) +- Backward sync: use retry switching peer when fetching data from peers [#4656](https://github.com/hyperledger/besu/pull/4656) +- Shanghai implementation of EIP-3651 Warm coinbase [#4620](https://github.com/hyperledger/besu/pull/4620) +- Shanghai implementation of EIP-3855 Push0 [#4660](https://github.com/hyperledger/besu/pull/4660) +- Shanghai implementation of EIP-3540 and EIP-3670 Ethereum Object Format and Code Validation [#4644](https://github.com/hyperledger/besu/pull/4644) +- Remove some log statements that are keeping some objects live in heap for a long time, to reduce the amount of memory required during initial sync [#4705](https://github.com/hyperledger/besu/pull/4705) +- Add field `type` to Transaction receipt object (eth_getTransactionReceipt) [#4505](https://github.com/hyperledger/besu/issues/4505) +- Print an overview of configuration and system information at startup [#4451](https://github.com/hyperledger/besu/pull/4451) +- Do not send new payloads to backward sync if initial sync is in progress [#4720](https://github.com/hyperledger/besu/issues/4720) +- Improve the way transaction fee cap validation is done on London fee market to not depend on transient network conditions [#4598](https://github.com/hyperledger/besu/pull/4598) +- Preload and cache account and storage data from RocksDB to improve performance [#4737](https://github.com/hyperledger/besu/issues/4737) + +### Bug Fixes +- Restore updating chain head and finalized block during backward sync [#4718](https://github.com/hyperledger/besu/pull/4718) + +### Download Links +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.10.1/besu-22.10.1.tar.gz / sha256: b6757b9fc69b782cdabb95b1e784d31b1effcc2e25c6b198b2f9d6b3786c7a8a +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.10.1/besu-22.10.1.zip / sha256: 0dbee534620c7cc0fac0596e6df0c7f8a74be9df9cecd9d4f1407016f30fb9a1 + +## 22.10.0 + +### Breaking Changes +- Internal and interface APIs relating to storage have migrated from `UInt256` to `Bytes32` [#4562](https://github.com/hyperledger/besu/pull/4562) +- Flexible Privacy Groups (early access) support to Tessera's EC encryptor (contracts modified) [#4282](https://github.com/hyperledger/besu/pull/4282) + * Before this change, the `bytes32` type was used for the enclave public keys, just supporting encryptors with public keys of that length (like the default NaCl) + * For the EC encryptor, the encoded public key length is 91 +- `--tx-pool-hashes-max-size` option removed (deprecated in 22.1.3) +- `--Xmerge-support` option removed (deprecated in 22.4.2) [#4518](https://github.com/hyperledger/besu/pull/4518) +- Breaking API changes in the `OperationTracer` interface to enable performance work. + * The `traceExecution` method has been replaced with `tracePreExecution` and `tracePostExecution` methods, called just before and just after operation execution. + * See `DebugOperationTracer` and `StandardJsonTracer` for migration examples. + +### Additions and Improvements +- Updated jackson-databind library to version 2.13.4.2 addressing [CVE-2022-42003](https://nvd.nist.gov/vuln/detail/CVE-2022-42003) +- Update snapsync feature to avoid restarting the download of the world state from scratch when restarting Besu [#4381](https://github.com/hyperledger/besu/pull/4381) +- Added worldstate snapshot isolation to improve the stability of bonsai (`--Xbonsai-use-snapshots=true`) [#4351](https://github.com/hyperledger/besu/pull/4531) +- Reduce the number of runtime exceptions (SecurityModuleException) and unnecessary executions during ECIES handshake, by trying to decrypt EIP-8 formatted messages first [#4508](https://github.com/hyperledger/besu/pull/4508). +- Improved RLP processing of zero-length string as 0x80 [#4283](https://github.com/hyperledger/besu/pull/4283) [#4388](https://github.com/hyperledger/besu/issues/4388) +- Increased level of detail in JSON-RPC parameter error log messages [#4510](https://github.com/hyperledger/besu/pull/4510) +- New unstable configuration options to set the maximum time, in milliseconds, a PoS block creation jobs is allowed to run [#4519](https://github.com/hyperledger/besu/pull/4519) +- Tune EthScheduler thread pools to avoid recreating too many threads [#4529](https://github.com/hyperledger/besu/pull/4529) +- RocksDB snapshot based worldstate and plugin-api addition of Snapshot interfaces [#4409](https://github.com/hyperledger/besu/pull/4409) +- Continuously try to build better block proposals until timeout or GetPayload is called [#4516](https://github.com/hyperledger/besu/pull/4516) +- Upgrade RocksDB database version from 6.29.5 to 7.6.0 [#4517](https://github.com/hyperledger/besu/pull/4517) +- Avoid connecting to self when using static-nodes [#4521](https://github.com/hyperledger/besu/pull/4521) +- EVM performance has increased 20%-100% depending on the particulars of the contract. [#4540](https://github.com/hyperledger/besu/pull/4540) +- Improve calculateRootHash method performance during Block processing [#4568](https://github.com/hyperledger/besu/pull/4568) +- Bring GraphQL into compliance with execution-api specs [#4112](https://github.com/hyperledger/besu/pull/4112) +- Refactor unverified forkchoice event [#4487](https://github.com/hyperledger/besu/pull/4487) +- Improve UX of initial sync logs, pushing not relevant logs to debug level [#4486](https://github.com/hyperledger/besu/pull/4486) +- Optimize pivot block selector on PoS networks [#4488](https://github.com/hyperledger/besu/pull/4488) +- Optimize Snap sync on PoS networks [#4462](https://github.com/hyperledger/besu/pull/4462) + +### Bug Fixes +- Fixed default fromBlock value and improved parameter interpretation in eth_getLogs RPC handler [#4513](https://github.com/hyperledger/besu/pull/4513) +- Fix for NoSuchElementException for missing invalid reason when rejecting a local sent transaction [#4569](https://github.com/hyperledger/besu/pull/4569) +- Corrects treating a block as bad on internal error during either validation or processing [#4512](https://github.com/hyperledger/besu/issues/4512) +- Corrects emission of blockadded events when rewinding during a re-org. Fix for [#4495](https://github.com/hyperledger/besu/issues/4495) +- Always return a transaction type for pending transactions [#4364](https://github.com/hyperledger/besu/pull/4364) +- Avoid a cyclic reference while printing EngineExchangeTransitionConfigurationParameter [#4357](https://github.com/hyperledger/besu/pull/4357) +- Corrects treating a block as bad on internal error [#4512](https://github.com/hyperledger/besu/issues/4512) +- In GraphQL update scalar parsing to be variable friendly [#4522](https://github.com/hyperledger/besu/pull/4522) +- Initiate connection to maintained peers soon after startup. [#4469](https://github.com/hyperledger/besu/pull/4469) +- Update apache-commons-text to 1.10.0 to address CVE-2022-42889 [#4542](https://github.com/hyperledger/besu/pull/4542) + +### Download Links + +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.10.0/besu-22.10.0.tar.gz / sha256: 88fb5df567e4ec3547d7d2970cfef00debbd020c0da66b19166d43779b3b2b85 +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.10.0/besu-22.10.0.zip / sha256: c8e39f7c879409cb9b47f4d3de5e9c521249083830a8c9a45e8a14a319fe195d + +## 22.10.0-RC2 + +### Breaking Changes +- Flexible Privacy Groups (early access) support to Tessera's EC encryptor (contracts modified) [#4282](https://github.com/hyperledger/besu/pull/4282) + * Before this change, the `bytes32` type was used for the enclave public keys, just supporting encryptors with public keys of that length (like the default NaCl) + * For the EC encryptor, the encoded public key length is 91 +- `--tx-pool-hashes-max-size` option removed (deprecated in 22.1.3) +- `--Xmerge-support` option remove (deprecated in 22.4.2) [#4518](https://github.com/hyperledger/besu/pull/4518) +- Breaking API changes in the `OperationTracer` interface to enable performance work. + * The `traceExecution` method has been replaced with `tracePreExecution` and `tracePostExecution` methods, called just before and just after operation execution. + * See `DebugOperationTracer` and `StandardJsonTracer` for migration examples. + +### Additions and Improvements +- Reduce the number of runtime exceptions (SecurityModuleException) and unnecessary executions during ECIES handshake, by trying to decrypt EIP-8 formatted messages first [#4508](https://github.com/hyperledger/besu/pull/4508). +- Improved RLP processing of zero-length string as 0x80 [#4283](https://github.com/hyperledger/besu/pull/4283) [#4388](https://github.com/hyperledger/besu/issues/4388) +- Increased level of detail in JSON-RPC parameter error log messages [#4510](https://github.com/hyperledger/besu/pull/4510) +- New experimental configuration options to set the maximum time, in milliseconds, a PoS block creation jobs is allowed to run [#4519](https://github.com/hyperledger/besu/pull/4519) +- Tune EthScheduler thread pools to avoid recreating too many threads [#4529](https://github.com/hyperledger/besu/pull/4529) +- RocksDB snapshot based worldstate and plugin-api addition of Snapshot interfaces [#4409](https://github.com/hyperledger/besu/pull/4409) +- Continuously try to build better block proposals until timeout or GetPayload is called [#4516](https://github.com/hyperledger/besu/pull/4516) +- Upgrade RocksDB database version from 6.29.5 to 7.6.0 [#4517](https://github.com/hyperledger/besu/pull/4517) +- Avoid connecting to self when using static-nodes [#4521](https://github.com/hyperledger/besu/pull/4521) +- EVM performance has increased 20%-100% depending on the particulars of the contract. [#4540](https://github.com/hyperledger/besu/pull/4540) +- Improve calculateRootHash method performance during Block processing [#4568](https://github.com/hyperledger/besu/pull/4568) + +### Bug Fixes +- Corrects emission of blockadded events when rewinding during a re-org. Fix for [#4495](https://github.com/hyperledger/besu/issues/4495) +- Always return a transaction type for pending transactions [#4364](https://github.com/hyperledger/besu/pull/4364) +- Avoid a cyclic reference while printing EngineExchangeTransitionConfigurationParameter [#4357](https://github.com/hyperledger/besu/pull/4357) +- Corrects treating a block as bad on internal error [#4512](https://github.com/hyperledger/besu/issues/4512) +- In GraphQL update scalar parsing to be variable friendly [#4522](https://github.com/hyperledger/besu/pull/4522) +- Initiate connection to maintained peers soon after startup. [#4469](https://github.com/hyperledger/besu/pull/4469) +- Update apache-commons-text to 1.10.0 to address CVE-2022-42889 [#4542](https://github.com/hyperledger/besu/pull/4542) + +### Download Links + + +## 22.10.0-RC1 + +### Additions and Improvements +- Bring GraphQL into compliance with execution-api specs [#4112](https://github.com/hyperledger/besu/pull/4112) +- Refactor unverified forkchoice event [#4487](https://github.com/hyperledger/besu/pull/4487) +- Improve UX of initial sync logs, pushing not relevant logs to debug level [#4486](https://github.com/hyperledger/besu/pull/4486) +- Optimize pivot block selector on PoS networks [#4488](https://github.com/hyperledger/besu/pull/4488) +- Optimize Snap sync on PoS networks [#4462](https://github.com/hyperledger/besu/pull/4462) + +### Bug Fixes + +### Download Links +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.10.0-RC1/besu-22.10.0-RC1.zip / sha256: 16fd47533aa2986491143e5f4a052c0aa4866ebfa415abbf3ca868e4fbeac6ce +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.10.0-RC1/besu-22.10.0-RC1.tar.gz / sha256: 48fd3480e4380580ed9187302be987e9eca2b445935ec6a509e7269898d8a4a8 + +## 22.7.7 + +### Additions and Improvements +- Tune EthScheduler thread pools to avoid recreating too many threads [#4529](https://github.com/hyperledger/besu/issues/4529) +- Reduce the number of runtime exceptions (SecurityModuleException) and unnecessary executions during ECIES handshake, by trying to decrypt EIP-8 formatted messages first [#4508](https://github.com/hyperledger/besu/pull/4508). +- The block variable was keeping too much memory while waiting for future to finish [#4489](https://github.com/hyperledger/besu/issues/4489) + +### Bug Fixes +- Corrects treating a block as bad on internal error [#4512](https://github.com/hyperledger/besu/issues/4512) +- update appache-commons-text to 1.10.0 to address CVE-2022-42889 [#4542](https://github.com/hyperledger/besu/pull/4542) +- In GraphQL update scalar parsing to be variable friendly [#4522](https://github.com/hyperledger/besu/pull/4522) + +### Download Links +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.7.7/besu-22.7.7.zip / sha256: 79b2b1518605603d8268f873f2576617ca8340d89c045e0eda6896f40defea0d +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.7.7/besu-22.7.7.tar.gz / sha256: 161c52ba9be8508767e80dbce796b4ad2cc5b649f7ed15387c6359d1e15753f6 + +## 22.7.6 +Hotfix release of the 22.7.x series to address [#4495](https://github.com/hyperledger/besu/issues/4495) which could result in failed block proposals on merge networks. + +### Additions and Improvements +- Bring GraphQL into compliance with execution-api specs [#4112](https://github.com/hyperledger/besu/pull/4112) + +### Bug Fixes +- Corrects emission of blockadded events when rewinding during a re-org. [#4497](https://github.com/hyperledger/besu/issues/4497) + +### Download Links +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.7.6/besu-22.7.6.zip / sha256: ae05040027b96ba458a08cfee8577dafe1d85a3afce793f00f798cedb3ab547d +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.7.6/besu-22.7.6.tar.gz / sha256: 9e538852f16fd39b884c4c342beaad813e33ab24890634c01eee3d37dc1da893 + +## 22.7.5 + +### Additions and Improvements +- Avoid sending added block events to transaction pool, and processing incoming transactions during initial sync [#4457](https://github.com/hyperledger/besu/pull/4457) +- When building a new proposal, keep the best block built until now instead of the last one [#4455](https://github.com/hyperledger/besu/pull/4455) +- Add Mainnet to merged networks [#4463](https://github.com/hyperledger/besu/pull/4463) + +### Bug Fixes +- Fixed logIndex value returned by eth_getLogs RPC call [#4355](https://github.com/hyperledger/besu/pull/4355) + +### Download Links +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.7.5/besu-22.7.5.zip / sha256: b5d7b255b249beea0f46ec397122823c75f2373083a71a9f7b4c98b2b0f94997 +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.7.5/besu-22.7.5.tar.gz / sha256: 91e3cbc16c46c53f7bf55bdd968553d0fb4087bff1e244cb03ac175ac54cf718 + + +## 22.7.4 + +### Bug Fixes +- Remove records that track transactions by sender when they are empty to same memory in the transaction pool [#4415](https://github.com/hyperledger/besu/pull/4415) +- Add Toml configuration file support for _--Xplugin-rocksdb-high-spec-enabled_ flag [#4438](https://github.com/hyperledger/besu/pull/4438) + +### Download Links +- https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.7.4/besu-22.7.4.zip / sha256: 4f2a0c20bee7f266ec1dcb45fa90ae1ca42f4b22e9b21a601b7705357259aea9 +- https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.7.4/besu-22.7.4.tar.gz / sha256: a60efc4d515ac94710bbc6d61a24f409b03fcfc02323bee2a2d75c883fc99dce + +## 22.7.3 + +### Additions and Improvements +- Allow free gas networks in the London fee market [#4061](https://github.com/hyperledger/besu/issues/4061) +- Upgrade besu-native to 0.6.0 and use Blake2bf native implementation if available by default [#4264](https://github.com/hyperledger/besu/pull/4264) +- Resets engine QoS timer with every call to the engine API instead of only when ExchangeTransitionConfiguration is called [#4411](https://github.com/hyperledger/besu/issues/4411) +- ExchangeTransitionConfiguration mismatch will only submit a debug log not a warning anymore [#4411](https://github.com/hyperledger/besu/issues/4411) +- Upgrade besu-native to 0.6.1 and include linux arm64 build of bls12-381 [#4416](https://github.com/hyperledger/besu/pull/4416) +- Create a new flag on RocksDB (_--Xplugin-rocksdb-high-spec-enabled_) for high spec hardware to boost performance +- Transaction pool improvements to avoid filling the pool with not executable transactions, that could result in empty or semi-empty block proposals [#4425](https://github.com/hyperledger/besu/pull/4425) +- Limit Transaction pool consumption by sender to a configurable percentage of the pool size [#4417](https://github.com/hyperledger/besu/pull/4417) + +### Bug Fixes +- Retry block creation if there is a transient error and we still have time, to mitigate empty block issue [#4407](https://github.com/hyperledger/besu/pull/4407) +- Fix StacklessClosedChannelException in Besu and resulted timeout errors in CL clients ([#4398](https://github.com/hyperledger/besu/issues/4398), [#4400](https://github.com/hyperledger/besu/issues/4400)) +- Return JSON-RPC error code instead of INVALID in engine api when certain storage exceptions are encountered ([#4349](https://github.com/hyperledger/besu/issues/4349)) + +### Download links +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.7.3/besu-22.7.3.tar.gz / sha256: `b0863fe2406cab57caf8a02f2bf02632cc5198622ac48b69bc63c128703bbd79` +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.7.3/besu-22.7.3.zip / sha256: `368c6cb86119f8fe30bb12ab8c63b4d95a0fd8baf9c9414307a0a4033756b709` + +## 22.7.2 +### Besu 22.7.2 is a recommended release for the Merge and Mainnet users. 22.7.1 remains Merge-ready. This release provides additional robustness before the Merge with some fixes and improvements in sync, peering, and logging. + +### Additions and Improvements +- Better management of jemalloc presence/absence in startup script [#4237](https://github.com/hyperledger/besu/pull/4237) +- Retry mechanism when getting a broadcasted block fail on all peers [#4271](https://github.com/hyperledger/besu/pull/4271) +- Filter out disconnected peers when fetching available peers [#4269](https://github.com/hyperledger/besu/pull/4269) +- Updated the default value of fast-sync-min-peers post merge [#4298](https://github.com/hyperledger/besu/pull/4298) +- Log imported block info post merge [#4310](https://github.com/hyperledger/besu/pull/4310) +- Transaction pool eviction by sender from tail of transaction list [#4327](https://github.com/hyperledger/besu/pull/4327) +- Transaction pool sender future nonce limits [#4336](https://github.com/hyperledger/besu/pull/4336) +- Pandas! Pandas now appear in 3 phases: The black bear and polar bear that are preparing? Those will appear when +your client has TTD configured (which is setup by default for mainnet), is in sync, and processing Proof of Work blocks. In the second phase you will see them powering up when the Terminal Total Difficulty block is added to the blockchain. +The final form of the Ethereum Panda will appear when the first finalized block is received from the Consensus Layer. + +### Bug Fixes +- Accept wit/80 from Nethermind [#4279](https://github.com/hyperledger/besu/pull/4279) +- Properly shutdown the miner executor, to avoid waiting 30 seconds when stopping [#4353](https://github.com/hyperledger/besu/pull/4353) + +### Download links +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.7.2/besu-22.7.2.tar.gz / sha256: `8030a48f824c7bbc138b38a9e84e5531950bc16f6d21cda8b215232cce334214` +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.7.2/besu-22.7.2.zip / sha256: `72653171b1ddd910e705fc6f616d7f1f4c120ef0d91718f0376f3ee5f2982c11` + + +## 22.7.1 +### Merge Ready Release. Required update for The Merge on ethereum mainnet! +### Additions and Improvements +- Introduce a cap to reputation score increase [#4230](https://github.com/hyperledger/besu/pull/4230) +- Add experimental CLI option for `--Xp2p-peer-lower-bound` [#4200](https://github.com/hyperledger/besu/pull/4200) +- Improve pending blocks retrieval mechanism [#4227](https://github.com/hyperledger/besu/pull/4227) +- Set mainnet terminal total difficulty [#4260](https://github.com/hyperledger/besu/pull/4260) + +### Bug Fixes +- Fixes off-by-one error for mainnet TTD fallback [#4223](https://github.com/hyperledger/besu/pull/4223) +- Fix off-by-one error in AbstractRetryingPeerTask [#4254](https://github.com/hyperledger/besu/pull/4254) +- Refactor and fix retrying get block switching peer [#4256](https://github.com/hyperledger/besu/pull/4256) +- Fix encoding of key (short hex) in eth_getProof [#4261](https://github.com/hyperledger/besu/pull/4261) +- Fix for post-merge networks fast-sync [#4224](https://github.com/hyperledger/besu/pull/4224), [#4276](https://github.com/hyperledger/besu/pull/4276) + +### Download links +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.7.1/besu-22.7.1.tar.gz / sha256: `7cca4c11e1d7525c172f2af9fbf456d134ada60e970d8b6abcfcd6c623b5dd36` +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.7.1/besu-22.7.1.zip / sha256: `ba6e0b9b65ac36d041a5072392f119ff76e8e9f53a3d7b1e1a658ef1e4705d7a` + + + +## 22.7.0 + +### Additions and Improvements +- Deprecation warning for Ropsten, Rinkeby, Kiln [#4173](https://github.com/hyperledger/besu/pull/4173) + +### Bug Fixes + +- Fixes previous known issue [#3890](https://github.com/hyperledger/besu/issues/3890)from RC3 requiring a restart post-merge to continue correct transaction handling. +- Stop producing stack traces when a get headers response only contains the range start header [#4189](https://github.com/hyperledger/besu/pull/4189) +- Upgrade Spotless to 6.8.0 [#4195](https://github.com/hyperledger/besu/pull/4195) +- Upgrade Gradle to 7.5 [#4196](https://github.com/hyperledger/besu/pull/4196) + +### Download links +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.7.0/besu-22.7.0.tar.gz / sha256: `af21104a880c37706b660aa816e1c38b2b3f603a97420ddcbc889324b71aa50e` +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.7.0/besu-22.7.0.zip / sha256: `5b1586362e6e739c206c25224bb753a372bad70c0b22dbe091f9253024ebdc45` + +## 22.7.0-RC3 + +### Known/Outstanding issues: +- Besu requires a restart post-merge to re-enable remote transaction processing [#3890](https://github.com/hyperledger/besu/issues/3890) + +### Additions and Improvements +- Engine API: Change expiration time for JWT tokens to 60s [#4168](https://github.com/hyperledger/besu/pull/4168) +- Sepolia mergeNetSplit block [#4158](https://github.com/hyperledger/besu/pull/4158) +- Goerli TTD [#4160](https://github.com/hyperledger/besu/pull/4160) +- Several logging improvements + +### Bug Fixes +- Allow to set any value for baseFeePerGas in the genesis file [#4177](https://github.com/hyperledger/besu/pull/4177) +- Fix for stack overflow when searching for TTD block [#4169](https://github.com/hyperledger/besu/pull/4169) +- Fix for chain stuck issue [#4175](https://github.com/hyperledger/besu/pull/4175) + +### Download links +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.7.0-RC3/besu-22.7.0-RC3.tar.gz / sha256: `6a1ee89c82db9fa782d34733d8a8c726670378bcb71befe013da48d7928490a6` +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.7.0-RC3/besu-22.7.0-RC3.zip / sha256: `5de22445ab2a270cf33e1850cd28f1946442b7104738f0d1ac253a009c53414e` + +## 22.7.0-RC2 + +### Additions and Improvements +- Add a block to the bad blocks if it did not descend from the terminal block [#4080](https://github.com/hyperledger/besu/pull/4080) +- Backward sync exception improvements [#4092](https://github.com/hyperledger/besu/pull/4092) +- Remove block header checks during backward sync, since they will be always performed during block import phase [#4098](https://github.com/hyperledger/besu/pull/4098) +- Optimize the backward sync retry strategy [#4095](https://github.com/hyperledger/besu/pull/4095) +- Add support for jemalloc library to better handle rocksdb memory consumption [#4126](https://github.com/hyperledger/besu/pull/4126) +- RocksDB configuration changes to improve performance. [#4132](https://github.com/hyperledger/besu/pull/4132) + +### Bug Fixes +- Changed max message size in the p2p layer to 16.7MB from 10MB to improve peering performance [#4120](https://github.com/hyperledger/besu/pull/4120) +- Fixes for parent stateroot mismatch when using Bonsai storage mode (please report if you encounter this bug on this version) [#4094](https://github.com/hyperledger/besu/pull/4094) +- Above Bonsai related fixes have addressed situations where the event log was not indexed properly [#3921](https://github.com/hyperledger/besu/pull/3921) +- Fixes related to backward sync and reorgs [#4097](https://github.com/hyperledger/besu/pull/4097) +- Checkpoint sync with more merge friendly checkpoint blocks [#4085](https://github.com/hyperledger/besu/pull/4085) +- Fixes around RocksDB performance and memory usage [#4128](https://github.com/hyperledger/besu/pull/4128) +- Fix for RPC performance parallelization to improve RPC performance under heavy load [#3959](https://github.com/hyperledger/besu/pull/3959) +- Fix for post-Merge peering after PoW is removed in our logic for weighting peers [#4116](https://github.com/hyperledger/besu/pull/4116) +- Various logging changes to improve UX- Return the correct latest valid hash in case of bad block when calling engine methods [#4056](https://github.com/hyperledger/besu/pull/4056) +- Add a PoS block header rule to check that the current block is more recent than its parent [#4066](https://github.com/hyperledger/besu/pull/4066) +- Fixed a trie log layer issue on bonsai during reorg [#4069](https://github.com/hyperledger/besu/pull/4069) +- Fix transition protocol schedule to return the pre Merge schedule when reorg pre TTD [#4078](https://github.com/hyperledger/besu/pull/4078) +- Remove hash to sync from the queue only if the sync step succeeds [#4105](https://github.com/hyperledger/besu/pull/4105) +- The build process runs successfully even though the system language is not English [#4102](https://github.com/hyperledger/besu/pull/4102) +- Avoid starting or stopping the BlockPropagationManager more than once [#4122](https://github.com/hyperledger/besu/pull/4122) + +### Download links +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.7.0-RC2/besu-22.7.0-RC2.tar.gz / sha256: `befe15b893820c9c6451a74fd87b41f555ff28561494b3bebadd5da5c7ce25d3` +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.7.0-RC2/besu-22.7.0-RC2.zip / sha256: `d56c340f5982b882fbecca2697ca72a5bbefe0e978d2d4504211f012e2242a81` + +## 22.7.0-RC1 + +### Additions and Improvements +- Do not require a minimum block height when downloading headers or blocks [#3911](https://github.com/hyperledger/besu/pull/3911) +- When on PoS the head can be only be updated by ForkchoiceUpdate [#3994](https://github.com/hyperledger/besu/pull/3994) +- Version information available in metrics [#3997](https://github.com/hyperledger/besu/pull/3997) +- Add TTD and DNS to Sepolia config [#4024](https://github.com/hyperledger/besu/pull/4024) +- Return `type` with value `0x0` when serializing legacy transactions [#4027](https://github.com/hyperledger/besu/pull/4027) +- Ignore `ForkchoiceUpdate` if `newHead` is an ancestor of the chain head [#4055](https://github.com/hyperledger/besu/pull/4055) + +### Bug Fixes +- Fixed a snapsync issue that can sometimes block the healing step [#3920](https://github.com/hyperledger/besu/pull/3920) +- Support free gas networks in the London fee market [#4003](https://github.com/hyperledger/besu/pull/4003) +- Limit the size of outgoing eth subprotocol messages. [#4034](https://github.com/hyperledger/besu/pull/4034) +- Fixed a state root mismatch issue on bonsai that may appear occasionally [#4041](https://github.com/hyperledger/besu/pull/4041) + +### Download links +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.7.0-RC1/besu-22.7.0-RC1.tar.gz / sha256: `60ad8b53402beb62c24ad791799d9cfe444623a58f6f6cf1d0728459cb641e63` +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.7.0-RC1/besu-22.7.0-RC1.zip / sha256: `7acfb3a73382bf70f6337e83cb7e9e472b4e5a9da88c5ed2fbd9e82fcf2046dc` + +## 22.4.3 + +### Additions and Improvements +- \[EXPERIMENTAL\] Add checkpoint sync `--sync-mode="X_CHECKPOINT"` [#3849](https://github.com/hyperledger/besu/pull/3849) +- Support `finalized` and `safe` as tags for the block parameter in RPC APIs [#3950](https://github.com/hyperledger/besu/pull/3950) +- Added verification of payload attributes in ForkchoiceUpdated [#3837](https://github.com/hyperledger/besu/pull/3837) +- Add support for Gray Glacier hardfork [#3961](https://github.com/hyperledger/besu/issues/3961) + +### Bug Fixes +- alias engine-rpc-port parameter with the former rpc param name [#3958](https://github.com/hyperledger/besu/pull/3958) + +## 22.4.2 + +### Additions and Improvements +- Engine API Update: Replace deprecated INVALID_TERMINAL_BLOCK with INVALID last valid hash 0x0 [#3882](https://github.com/hyperledger/besu/pull/3882) +- Deprecate experimental merge flag and engine-rpc-enabled flag [#3875](https://github.com/hyperledger/besu/pull/3875) +- Update besu-native dependencies to 0.5.0 for linux arm64 support +- Update ropsten TTD to 100000000000000000000000 + +### Bug Fixes +- Stop backward sync if genesis block has been reached [#3869](https://github.com/hyperledger/besu/pull/3869) +- Allow to backward sync to request headers back to last finalized block if present or genesis [#3888](https://github.com/hyperledger/besu/pull/3888) + +### Download link +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.4.2/besu-22.4.2.zip / sha256: `e8e9eb7e3f544ecefeec863712fb8d3f6a569c9d70825a4ed2581c596db8fd45` +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.4.2/besu-22.4.2.tar.gz / sha256: `9db0c37440cb56bcf671b8de13e0ecb6235171a497bdad91020b8c4a9dac2a27` + +## 22.4.1 + +### Additions and Improvements +- GraphQL - allow null log topics in queries which match any topic [#3662](https://github.com/hyperledger/besu/pull/3662) +- multi-arch docker builds for amd64 and arm64 [#2954](https://github.com/hyperledger/besu/pull/2954) +- Filter Netty native lib errors likewise the pure Java implementation [#3807](https://github.com/hyperledger/besu/pull/3807) +- Add ropsten terminal total difficulty config [#3871](https://github.com/hyperledger/besu/pull/3871) + +### Bug Fixes +- Stop the BlockPropagationManager when it receives the TTD reached event [#3809](https://github.com/hyperledger/besu/pull/3809) +- Correct getMixHashOrPrevRandao to return the value present in the block header [#3839](https://github.com/hyperledger/besu/pull/3839) + +## 22.4.0 + +### Breaking Changes +- Version 22.4.x will be the last series to support Java 11. Version 22.7.0 will require Java 17 to build and run. +- In the Besu EVM Library all references to SHA3 have been renamed to the more accurate name Keccak256, including class names and comment. [#3749](https://github.com/hyperledger/besu/pull/3749) +- Removed the Gas object and replaced it with a primitive long [#3674](https://github.com/hyperledger/besu/pull/3674) +- Column family added for backward sync [#3638](https://github.com/hyperledger/besu/pull/3638) + - Note that this added column family makes this a one-way upgrade. That is, once you upgrade your db to this version, you cannot roll back to a previous version of Besu. + +### Bug Fixes +- Fix nullpointer on snapsync [#3773](https://github.com/hyperledger/besu/pull/3773) +- Introduce RocksDbSegmentIdentifier to avoid changing the storage plugin [#3755](https://github.com/hyperledger/besu/pull/3755) + +## Download Links +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.4.0/besu-22.4.0.zip / SHA256 d89e102a1941e70be31c176a6dd65cd5f3d69c4c +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.4.0/besu-22.4.0.tar.gz / SHA256 868e38749dd40debe028624f8267f1fce7587010 + +## 22.4.0-RC2 + +### Breaking Changes +- In the Besu EVM Library all references to SHA3 have been renamed to the more accurate name Kecack256, including class names and comment. [#3749](https://github.com/hyperledger/besu/pull/3749) + +### Additions and Improvements +- Onchain node permissioning + - Log the enodeURL that was previously only throwing an IllegalStateException during the isPermitted check [#3697](https://github.com/hyperledger/besu/pull/3697), + - Fail startup if node permissioning smart contract version does not match [#3765](https://github.com/hyperledger/besu/pull/3765) +- \[EXPERIMENTAL\] Add snapsync `--sync-mode="X_SNAP"` (only as client) [#3710](https://github.com/hyperledger/besu/pull/3710) +- Adapt Fast sync, and Snap sync, to use finalized block, from consensus layer, as pivot after the Merge [#3506](https://github.com/hyperledger/besu/issues/3506) +- Add IPC JSON-RPC interface (BSD/MacOS and Linux only) [#3695](https://github.com/hyperledger/besu/pull/3695) +- Column family added for backward sync [#3638](https://github.com/hyperledger/besu/pull/3638) + - Note that this added column family makes this a one-way upgrade. That is, once you upgrade your db to this version, you cannot roll back to a previous version of Besu. + +## Download Links +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.4.0-RC2/besu-22.4.0-RC2.zip / SHA256 5fa7f927c6717ebf503291c058815cd0c5fcfab13245d3b6beb66eb20cf7ac24 +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.4.0-RC2/besu-22.4.0-RC2.tar.gz / SHA256 1c4ecd17552cf5ebf120fc35dad753f45cb951ea0f817381feb2477ec0fff9c9 + +## 22.4.0-RC1 + +### Additions and Improvements +- Unit tests are now executed with JUnit5 [#3620](https://github.com/hyperledger/besu/pull/3620) +- Removed the Gas object and replaced it with a primitive long [#3674] + +### Bug Fixes +- Flexible Privacy Precompile handles null payload ID [#3664](https://github.com/hyperledger/besu/pull/3664) +- Subcommand blocks import throws exception [#3646](https://github.com/hyperledger/besu/pull/3646) + +## Download Links +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.4.0-RC1/besu-22.4.0-RC1.zip / SHA256 0779082acc20a98eb810eb08778e0c0e1431046c07bc89019a2761fd1baa4c25 +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.4.0-RC1/besu-22.4.0-RC1.tar.gz / SHA256 15d8b0e335f962f95da46864109db9f28ed4f7bc351995b2b8db477c12b94860 + +## 22.1.3 + +### Breaking Changes +- Remove the experimental flag for bonsai tries CLI options `--data-storage-format` and `--bonsai-maximum-back-layers-to-load` [#3578](https://github.com/hyperledger/besu/pull/3578) +- Column family added for backward sync [#3532](https://github.com/hyperledger/besu/pull/3532) + - Note that this added column family makes this a one-way upgrade. That is, once you upgrade your db to this version, you cannot roll back to a previous version of Besu. + +### Deprecations +- `--tx-pool-hashes-max-size` is now deprecated and has no more effect, and it will be removed in a future release. + +### Additions and Improvements +- Tune transaction synchronization parameter to adapt to mainnet traffic [#3610](https://github.com/hyperledger/besu/pull/3610) +- Improve eth/66 support [#3616](https://github.com/hyperledger/besu/pull/3616) +- Avoid reprocessing remote transactions already seen [#3626](https://github.com/hyperledger/besu/pull/3626) +- Upgraded jackson-databind dependency version [#3647](https://github.com/hyperledger/besu/pull/3647) + +## Download Links +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.1.3/besu-22.1.3.zip / SHA256 9dafb80f2ec9ce8d732fd9e9894ca2455dd02418971c89cd6ccee94c53354d5d +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.1.3/besu-22.1.3.tar.gz / SHA256 f9f8d37353aa4b5d12e87c08dd86328c1cffc591c6fc9e076c0f85a1d4663dfe + +## 22.1.2 + +### Additions and Improvements +- Execution layer (The Merge): + - Execution specific RPC endpoint [#3378](https://github.com/hyperledger/besu/issues/3378) + - Adds JWT authentication to Engine APIs + - Supports kiln V2.1 spec +- Tracing APIs + - new API methods: trace_rawTransaction, trace_get, trace_callMany + - added revertReason to trace APIs including: trace_transaction, trace_get, trace_call, trace_callMany, and trace_rawTransaction +- Allow mining beneficiary to transition at specific blocks for ibft2 and qbft consensus mechanisms. [#3115](https://github.com/hyperledger/besu/issues/3115) +- Return richer information from the PrecompiledContract interface. [\#3546](https://github.com/hyperledger/besu/pull/3546) + +### Bug Fixes +- Reject locally-sourced transactions below the minimum gas price when not mining. [#3397](https://github.com/hyperledger/besu/pull/3397) +- Fixed bug with contract address supplied to `debug_accountAt` [#3518](https://github.com/hyperledger/besu/pull/3518) + +## Download Links +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.1.2/besu-22.1.2.zip / SHA256 1b26e3f8982c3a9dbabc72171f83f1cfe89eef84ead45b184ee9101f411c1251 +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.1.2/besu-22.1.2.tar.gz / SHA256 1eca9abddf351eaaf4e6eaa1b9536b8b4fd7d30a81d39f9d44ffeb198627ee7a + +## 22.1.1 + +### Additions and Improvements +- Allow optional RPC methods that bypass authentication [#3382](https://github.com/hyperledger/besu/pull/3382) +- Execution layer (The Merge): + - Extend block creation and mining to support The Merge [#3412](https://github.com/hyperledger/besu/pull/3412) + - Backward sync [#3410](https://github.com/hyperledger/besu/pull/3410) + - Extend validateAndProcessBlock to return an error message in case of failure, so it can be returned to the caller of ExecutePayload API [#3411](https://github.com/hyperledger/besu/pull/3411) + - Persist latest finalized block [#2913](https://github.com/hyperledger/besu/issues/2913) + - Add PostMergeContext, and stop syncing after the switch to PoS [#3453](https://github.com/hyperledger/besu/pull/3453) + - Add header validation rules needed to validate The Merge blocks [#3454](https://github.com/hyperledger/besu/pull/3454) + - Add core components: controller builder, protocol scheduler, coordinator, block creator and processor. [#3461](https://github.com/hyperledger/besu/pull/3461) + - Execution specific RPC endpoint [#2914](https://github.com/hyperledger/besu/issues/2914), [#3350](https://github.com/hyperledger/besu/pull/3350) +- QBFT consensus algorithm is production ready + +## Download Links +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.1.1/besu-22.1.1.zip / SHA256 cfff79e19e5f9a184d0b62886990698b77d019a0745ea63b5f9373870518173e +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.1.1/besu-22.1.1.tar.gz / SHA256 51cc9d35215f977ac7338e5c611c60f225fd6a8c1c26f188e661624a039e83f3 + +## 22.1.0 + +### Breaking Changes +- Plugin API: BlockHeader.getBaseFee() method now returns an optional Wei instead of an optional Long [#3065](https://github.com/hyperledger/besu/issues/3065) +- Removed deprecated hash variable `protected volatile Hash hash;` which was used for private transactions [#3110](https://github.com/hyperledger/besu/pull/3110) + +### Additions and Improvements +- Add support for additional JWT authentication algorithms [#3017](https://github.com/hyperledger/besu/pull/3017) +- Represent baseFee as Wei instead of long accordingly to the spec [#2785](https://github.com/hyperledger/besu/issues/2785) +- Implements [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399) to repurpose DIFFICULTY opcode after the merge as a source of entropy from the Beacon chain. [#3081](https://github.com/hyperledger/besu/issues/3081) +- Re-order external services (e.g JsonRpcHttpService) to start before blocks start processing [#3118](https://github.com/hyperledger/besu/pull/3118) +- Stream JSON RPC responses to avoid creating big JSON strings in memory [#3076](https://github.com/hyperledger/besu/pull/3076) +- Ethereum Classic Mystique Hard Fork [#3256](https://github.com/hyperledger/besu/pull/3256) +- Genesis file parameter `blockperiodseconds` is validated as a positive integer on startup to prevent unexpected runtime behaviour [#3186](https://github.com/hyperledger/besu/pull/3186) +- Add option to require replay protection for locally submitted transactions [\#1975](https://github.com/hyperledger/besu/issues/1975) +- Update to block header validation for IBFT and QBFT to support London fork EIP-1559 [#3251](https://github.com/hyperledger/besu/pull/3251) +- Move into SLF4J as logging facade [#3285](https://github.com/hyperledger/besu/pull/3285) +- Changing the order in which we traverse the word state tree during fast sync. This should improve fast sync during subsequent pivot changes.[#3202](https://github.com/hyperledger/besu/pull/3202) +- Updated besu-native to version 0.4.3 [#3331](https://github.com/hyperledger/besu/pull/3331) +- Refactor synchronizer to asynchronously retrieve blocks from peers, and to change peer when retrying to get a block. [#3326](https://github.com/hyperledger/besu/pull/3326) +- Disable RocksDB TTL compactions [#3356](https://github.com/hyperledger/besu/pull/3356) +- add a websocket frame size configuration CLI parameter [#3386](https://github.com/hyperledger/besu/pull/3386) +- Add `--ec-curve` parameter to export/export-address public-key subcommands [#3333](https://github.com/hyperledger/besu/pull/3333) + +### Bug Fixes +- Change the base docker image from Debian Buster to Ubuntu 20.04 [#3171](https://github.com/hyperledger/besu/issues/3171) fixes [#3045](https://github.com/hyperledger/besu/issues/3045) +- Make 'to' field optional in eth_call method according to the spec [#3177](https://github.com/hyperledger/besu/pull/3177) +- Update to log4j 2.17.1. Resolves potential vulnerability only exploitable when using custom log4j configurations that are writable by untrusted users. +- Fix regression on cors-origin star value +- Fix for ethFeeHistory accepting hex values for blockCount +- Fix a sync issue, when the chain downloader incorrectly shutdown when a task in the pipeline is cancelled. [#3319](https://github.com/hyperledger/besu/pull/3319) +- add a websocket frame size configuration CLI parameter [3368][https://github.com/hyperledger/besu/pull/3379] +- Prevent node from peering to itself [#3342](https://github.com/hyperledger/besu/pull/3342) +- Fix an `IndexOutOfBoundsException` exception when getting block from peers. [#3304](https://github.com/hyperledger/besu/issues/3304) +- Handle legacy eth64 without throwing null pointer exceptions [#3343](https://github.com/hyperledger/besu/pull/3343) + +### Download Links +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.1.0/besu-22.1.0.tar.gz \ SHA256 232bd7f274691ca14c26289fdc289d3fcdf69426dd96e2fa1601f4d079645c2f +- https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/22.1.0/besu-22.1.0.zip \ SHA256 1b701ff5b647b64aff3d73d6f1fe3fdf73f14adbe31504011eff1660ab56ad2b + +## 21.10.9 + +### Bug Fixes +- Fix regression on cors-origin star value +- Fix for ethFeeHistory accepting hex values for blockCount + + **Full Changelog**: https://github.com/hyperledger/besu/compare/21.10.8...21.10.9 + +[besu-21.10.9.tar.gz](https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.10.9/besu-21.10.9.tar.gz) a4b85ba72ee73017303e4b2f0fdde84a87d376c2c17fdcebfa4e34680f52fc71 +[besu-21.10.9.zip](https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.10.9/besu-21.10.9.zip) c3ba3f07340fa80064ba7c06f2c0ec081184e000f9a925d132084352d0665ef9 + +## 21.10.8 + +### Additions and Improvements +- Ethereum Classic Mystique Hard Fork [#3256](https://github.com/hyperledger/besu/pull/3256) + +### Download Links +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.10.8/besu-21.10.8.tar.gz \ SHA256 d325e2e36bc38a707a9eebf92068f5021606a8c6b6464bb4b4d59008ef8014fc +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.10.8/besu-21.10.8.zip \ SHA256 a91da1e82fb378e16437327bba56dd299aafdb0614ba528167a1dae85440c5af + +## 21.10.7 + +### Bug Fixes +- Update dependencies (including vert.x, kubernetes client-java, okhttp, commons-codec) + +### Additions and Improvements +- Add support for additional JWT authentication algorithms [#3017](https://github.com/hyperledger/besu/pull/3017) +- Remove Orion ATs + +### Download Links +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.10.7/besu-21.10.7.tar.gz \ SHA256 94cee804fcaea366c9575380ef0e30ed04bf2fc7451190a94887f14c07f301ff +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.10.7/besu-21.10.7.zip \ SHA256 faf1ebfb20aa6171aa6ea98d7653339272567c318711d11e350471b5bba62c00 + +## 21.10.6 + +### Bug Fixes +- Update log4j to 2.17.1 + +### Download Links +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.10.6/besu-21.10.6.tar.gz \ SHA256 ef579490031dd4eb3704b4041e352cfb2e7e787fcff7506b69ef88843d4e1220 +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.10.6/besu-21.10.6.zip \ SHA256 0fdda65bc993905daa14824840724d0b74e3f16f771f5726f5307f6d9575a719 + +## 21.10.5 + +### Bug Fixes +- Update log4j to 2.17.0 + +### Download Links +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.10.5/besu-21.10.5.tar.gz \ SHA256 0d1b6ed8f3e1325ad0d4acabad63c192385e6dcbefe40dc6b647e8ad106445a8 +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.10.5/besu-21.10.5.zip \ SHA256 a1689a8a65c4c6f633b686983a6a1653e7ac86e742ad2ec6351176482d6e0c57 + +## 21.10.4 + +### Bug Fixes +- Update log4j to 2.16.0. +- Change the base docker image from Debian Buster to Ubuntu 20.04 [#3171](https://github.com/hyperledger/besu/issues/3171) fixes [#3045](https://github.com/hyperledger/besu/issues/3045) + +### Download links +This release is not recommended for production use. + +## 21.10.3 + +### Additions and Improvements +- Updated log4j to 2.15.0 and disabled JNDI message format lookups to improve security. +- Represent baseFee as Wei instead of long accordingly to the spec [#2785](https://github.com/hyperledger/besu/issues/2785) +- Adding support of the NO_COLOR environment variable as described in the [NO_COLOR](https://no-color.org/) standard [#3085](https://github.com/hyperledger/besu/pull/3085) +- Add `privx_findFlexiblePrivacyGroup` RPC Method, `privx_findOnchainPrivacyGroup` will be removed in a future release [#3075](https://github.com/hyperledger/besu/pull/3075) +- The invalid value is now shown when `--bootnodes` cannot parse an item to make it easier to identify which option is invalid. +- Adding two new options to be able to specify desired TLS protocol version and Java cipher suites [#3105](https://github.com/hyperledger/besu/pull/3105) +- Implements [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399) to repurpose DIFFICULTY opcode after the merge as a source of entropy from the Beacon chain. [#3081](https://github.com/hyperledger/besu/issues/3081) + +### Bug Fixes +- Change the base docker image from Debian Buster to Ubuntu 20.04 [#3171](https://github.com/hyperledger/besu/issues/3171) fixes [#3045](https://github.com/hyperledger/besu/issues/3045) + +### Download Link +This release is not recommended for production use. + +## 21.10.2 + +### Additions and Improvements +- Add discovery options to genesis file [#2944](https://github.com/hyperledger/besu/pull/2944) +- Add validate-config subcommand to perform basic syntax validation of TOML config [#2994](https://github.com/hyperledger/besu/pull/2994) +- Updated Sepolia Nodes [#3034](https://github.com/hyperledger/besu/pull/3034) [#3035](https://github.com/hyperledger/besu/pull/3035) + +### Bug Fixes +- Reduce shift calculations to shifts that may have an actual result. [#3039](https://github.com/hyperledger/besu/pull/3039) +- DNS Discovery daemon wasn't started [#3033](https://github.com/hyperledger/besu/pull/3033) + +### Download Link +This release is not recommended for production use. + +## 21.10.1 + +### Additions and Improvements +- Add CLI autocomplete scripts. [#2854](https://github.com/hyperledger/besu/pull/2854) +- Add support for PKCS11 keystore on PKI Block Creation. [#2865](https://github.com/hyperledger/besu/pull/2865) +- Optimize EVM Memory for MLOAD Operations [#2917](https://github.com/hyperledger/besu/pull/2917) +- Upgrade CircleCI OpenJDK docker image to version 11.0.12. [#2928](https://github.com/hyperledger/besu/pull/2928) +- Update JDK 11 to latest version in Besu Docker images. [#2925](https://github.com/hyperledger/besu/pull/2925) +- Add Sepolia proof-of-work testnet configurations [#2920](https://github.com/hyperledger/besu/pull/2920) +- Allow block period to be configured for IBFT2 and QBFT using transitions [#2902](https://github.com/hyperledger/besu/pull/2902) +- Add support for binary messages (0x02) for websocket. [#2980](https://github.com/hyperledger/besu/pull/2980) + +### Bug Fixes +- Do not change the sender balance, but set gas fee to zero, when simulating a transaction without enforcing balance checks. [#2454](https://github.com/hyperledger/besu/pull/2454) +- Ensure genesis block has the default base fee if london is at block 0 [#2920](https://github.com/hyperledger/besu/pull/2920) +- Fixes the exit condition for loading a BonsaiPersistedWorldState for a sibling block of the last one persisted [#2967](https://github.com/hyperledger/besu/pull/2967) + +### Early Access Features +- Enable plugins to expose custom JSON-RPC / WebSocket methods [#1317](https://github.com/hyperledger/besu/issues/1317) + +### Download Link +This release is not recommended for production use. + +## 21.10.0 + +### Additions and Improvements +- The EVM has been factored out into a standalone module, suitable for inclusion as a library. [#2790](https://github.com/hyperledger/besu/pull/2790) +- Low level performance improvements changes to cut worst-case EVM performance in half. [#2796](https://github.com/hyperledger/besu/pull/2796) +- Migrate `ExceptionalHaltReason` from an enum to an interface to allow downstream users of the EVM to add new exceptional halt reasons. [#2810](https://github.com/hyperledger/besu/pull/2810) +- reduces need for JUMPDEST analysis via caching [#2607](https://github.com/hyperledger/besu/pull/2821) +- Add support for custom private key file for public-key export and public-key export-address commands [#2801](https://github.com/hyperledger/besu/pull/2801) +- Add CLI autocomplete scripts. [#2854](https://github.com/hyperledger/besu/pull/2854) +- Added support for PKCS11 keystore on PKI Block Creation. [#2865](https://github.com/hyperledger/besu/pull/2865) +- add support for ArrowGlacier hardfork [#2943](https://github.com/hyperledger/besu/issues/2943) + +### Bug Fixes +- Allow BESU_CONFIG_FILE environment to specify TOML file [#2455](https://github.com/hyperledger/besu/issues/2455) +- Fix bug with private contracts not able to call public contracts that call public contracts [#2816](https://github.com/hyperledger/besu/pull/2816) +- Fixes the exit condition for loading a BonsaiPersistedWorldState for a sibling block of the last one persisted [#2967](https://github.com/hyperledger/besu/pull/2967) +- Fixes bonsai getMutable regression affecting fast-sync [#2934](https://github.com/hyperledger/besu/pull/2934) +- Regression in RC1 involving LogOperation and frame memory overwrites [#2908](https://github.com/hyperledger/besu/pull/2908) +- Allow `eth_call` and `eth_estimateGas` to accept contract address as sender. [#2891](https://github.com/hyperledger/besu/pull/2891) + +### Early Access Features +- Enable plugins to expose custom JSON-RPC / WebSocket methods [#1317](https://github.com/hyperledger/besu/issues/1317) + +### Download Link +This release is not recommended for production use. \ +SHA256: 71374454753c2ee595f4f34dc6913f731818d50150accbc98088aace313c6935 + +## 21.10.0-RC4 + +### Additions and Improvements + +### Bug Fixes +- Fixes the exit condition for loading a BonsaiPersistedWorldState for a sibling block of the last one persisted [#2967](https://github.com/hyperledger/besu/pull/2967) +- Fixes bonsai getMutable regression affecting fast-sync [#2934](https://github.com/hyperledger/besu/pull/2934) + +### Early Access Features +### Download Link +This release is not recommended for production use. \ +SHA256: b16e15764b8bc06c5c3f9f19bc8b99fa48e7894aa5a6ccdad65da49bbf564793 + +## 21.10.0-RC3 + +### Bug Fixes +- Regression in RC1 involving LogOperation and frame memory overwrites [#2908](https://github.com/hyperledger/besu/pull/2908) +- Allow `eth_call` and `eth_estimateGas` to accept contract address as sender. [#2891](https://github.com/hyperledger/besu/pull/2891) +- Fix Concurrency issues in Ethpeers. [#2896](https://github.com/hyperledger/besu/pull/2896) + +### Download +This release is not recommended for production use. \ +SHA256: 3d4857589336717bf5e4e5ef711b9a7f3bc46b49e1cf5b3b6574a00ccc6eda94 + +## 21.10.0-RC1/RC2 +### Additions and Improvements +- The EVM has been factored out into a standalone module, suitable for inclusion as a library. [#2790](https://github.com/hyperledger/besu/pull/2790) +- Low level performance improvements changes to cut worst-case EVM performance in half. [#2796](https://github.com/hyperledger/besu/pull/2796) +- Migrate `ExceptionalHaltReason` from an enum to an interface to allow downstream users of the EVM to add new exceptional halt reasons. [#2810](https://github.com/hyperledger/besu/pull/2810) +- reduces need for JUMPDEST analysis via caching [#2607](https://github.com/hyperledger/besu/pull/2821) +- Add support for custom private key file for public-key export and public-key export-address commands [#2801](https://github.com/hyperledger/besu/pull/2801) + +### Bug Fixes +- Allow BESU_CONFIG_FILE environment to specify TOML file [#2455](https://github.com/hyperledger/besu/issues/2455) +- Fix bug with private contracts not able to call public contracts that call public contracts [#2816](https://github.com/hyperledger/besu/pull/2816) + +### Early Access Features + +### Download +This release is not recommended for production use. \ +SHA256: 536612e5e4d7a5e7a582f729f01ba591ba68cc389e8379fea3571ed85322ff51 + + +## 21.7.4 +### Additions and Improvements +- Upgrade Gradle to 7.2, which supports building with Java 17 [#2761](https://github.com/hyperledger/besu/pull/2376) + +### Bug Fixes +- Set an idle timeout for metrics connections, to clean up ports when no longer used [\#2748](https://github.com/hyperledger/besu/pull/2748) +- Onchain privacy groups can be unlocked after being locked without having to add a participant [\#2693](https://github.com/hyperledger/besu/pull/2693) +- Update Gas Schedule for Ethereum Classic [#2746](https://github.com/hyperledger/besu/pull/2746) + +### Early Access Features +- \[EXPERIMENTAL\] Added support for QBFT with PKI-backed Block Creation. [#2647](https://github.com/hyperledger/besu/issues/2647) +- \[EXPERIMENTAL\] Added support for QBFT to use retrieve validators from a smart contract [#2574](https://github.com/hyperledger/besu/pull/2574) + +### Download Link +https://hyperledger.jfrog.io/native/besu-binaries/besu/21.7.4/besu-21.7.4.zip \ +SHA256: 778d3c42851db11fec9171f77b22662f2baeb9b2ce913d7cfaaf1042ec19b7f9 + +## 21.7.3 +### Additions and Improvements +- Migration to Apache Tuweni 2.0 [\#2376](https://github.com/hyperledger/besu/pull/2376) +- \[EXPERIMENTAL\] Added support for DevP2P-over-TLS [#2536](https://github.com/hyperledger/besu/pull/2536) +- `eth_getWork`, `eth_submitWork` support over the Stratum port [#2581](https://github.com/hyperledger/besu/pull/2581) +- Stratum metrics [#2583](https://github.com/hyperledger/besu/pull/2583) +- Support for mining ommers [#2576](https://github.com/hyperledger/besu/pull/2576) +- Updated onchain permissioning to validate permissions on transaction submission [\#2595](https://github.com/hyperledger/besu/pull/2595) +- Removed deprecated CLI option `--privacy-precompiled-address` [#2605](https://github.com/hyperledger/besu/pull/2605) +- Removed code supporting EIP-1702. [#2657](https://github.com/hyperledger/besu/pull/2657) +- A native library was added for the alternative signature algorithm secp256r1, which will be used by default [#2630](https://github.com/hyperledger/besu/pull/2630) +- The command line option --Xsecp-native-enabled was added as an alias for --Xsecp256k1-native-enabled [#2630](https://github.com/hyperledger/besu/pull/2630) +- Added Labelled gauges for metrics [#2646](https://github.com/hyperledger/besu/pull/2646) +- support for `eth/66` networking protocol [#2365](https://github.com/hyperledger/besu/pull/2365) +- update RPC methods for post london 1559 transaction [#2535](https://github.com/hyperledger/besu/pull/2535) +- \[EXPERIMENTAL\] Added support for using DNS host name in place of IP address in onchain node permissioning rules [#2667](https://github.com/hyperledger/besu/pull/2667) +- Implement EIP-3607 Reject transactions from senders with deployed code. [#2676](https://github.com/hyperledger/besu/pull/2676) +- Ignore all unknown fields when supplied to eth_estimateGas or eth_call. [\#2690](https://github.com/hyperledger/besu/pull/2690) + +### Bug Fixes +- Consider effective price and effective priority fee in transaction replacement rules [\#2529](https://github.com/hyperledger/besu/issues/2529) +- GetTransactionCount should return the latest transaction count if it is greater than the transaction pool [\#2633](https://github.com/hyperledger/besu/pull/2633) + +### Early Access Features + +## 21.7.2 + +### Additions and Improvements +This release contains improvements and bugfixes for optimum compatibility with other London client versions. + +## Bug Fixes +- hotfix for private transaction identification for mainnet transactions [#2609](https://github.com/hyperledger/besu/pull/2609) + +## Download Link +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.7.2/besu-21.7.2.zip \ +db47fd9ba33b36436ed6798d2474f7621c733353fd04f49d6defffd12e3b6e14 + + +## 21.7.1 + +### Additions and Improvements +- `priv_call` now uses NO_TRACING OperationTracer implementation which improves memory usage [\#2482](https://github.com/hyperledger/besu/pull/2482) +- Ping and Pong messages now support ENR encoding as scalars or bytes [\#2512](https://github.com/hyperledger/besu/pull/2512) + +### Download Link +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.7.1/besu-21.7.1.zip \ +sha256sum 83fc44e39a710a95d8b6cbbbf04010dea76122bafcc633a993cd15304905a402 + +## 21.7.0 + +### Additions and Improvements +This release contains the activation blocks for London across all supported testnets. They are: + * Ropsten 10_499_401 (24 Jun 2021) + * Goerli 5_062_605 (30 Jun 2021) + * Rinkeby 8_897_988 (7 Jul 2021) + * Mainnet 12_965_000 (4 Aug 2021) +- eip-1559 changes: accept transactions which have maxFeePerGas below current baseFee [\#2374](https://github.com/hyperledger/besu/pull/2374) +- Introduced transitions for IBFT2 block rewards [\#1977](https://github.com/hyperledger/besu/pull/1977) +- Change Ethstats's status from experimental feature to stable. [\#2405](https://github.com/hyperledger/besu/pull/2405) +- Fixed disabling of native libraries for secp256k1 and altBn128. [\#2163](https://github.com/hyperledger/besu/pull/2163) +- eth_feeHistory API for wallet providers [\#2466](https://github.com/hyperledger/besu/pull/2466) + +### Bug Fixes +- Ibft2 could create invalid RoundChange messages in some circumstances containing duplicate prepares [\#2449](https://github.com/hyperledger/besu/pull/2449) +- Updated `eth_sendRawTransaction` to return an error when maxPriorityFeePerGas exceeds maxFeePerGas [\#2424](https://github.com/hyperledger/besu/pull/2424) +- Fixed NoSuchElementException with EIP1559 transaction receipts when using eth_getTransactionReceipt [\#2477](https://github.com/hyperledger/besu/pull/2477) + +### Early Access Features +- QBFT is a Byzantine Fault Tolerant consensus algorithm, building on the capabilities of IBFT and IBFT 2.0. It aims to provide performance improvements in cases of excess round change, and provides interoperability with other EEA compliant clients, such as GoQuorum. + - Note: QBFT currently only supports new networks. Existing networks using IBFT2.0 cannot migrate to QBFT. This will become available in a future release. + - Note: QBFT is an early access feature pending community feedback. Please make use of QBFT in new development networks and reach out in case of issues or concerns +- GoQuorum-compatible privacy. This mode uses Tessera and is interoperable with GoQuorum. + - Note: GoQuorum-compatible privacy is an early access feature pending community feedback. + +### Download Link +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.7.0/besu-21.7.0.zip +sha256sum 389465fdcc2cc5e5007a02dc2b8a2c43d577198867316bc5cc4392803ed71034 + +## 21.7.0-RC2 + +### Additions and Improvements +- eth_feeHistory API for wallet providers [\#2466](https://github.com/hyperledger/besu/pull/2466) +### Bug Fixes +- Ibft2 could create invalid RoundChange messages in some circumstances containing duplicate prepares [\#2449](https://github.com/hyperledger/besu/pull/2449) + +## Download Link +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.7.0-RC2/besu-21.7.0-RC2.zip +sha256sum 7bc97c359386cad84d449f786dc0a8ed8728616b6704ce473c63f1d94af3a9ef + + +## 21.7.0-RC1 + +### Additions and Improvements +- eip-1559 changes: accept transactions which have maxFeePerGas below current baseFee [\#2374](https://github.com/hyperledger/besu/pull/2374) +- Introduced transitions for IBFT2 block rewards [\#1977](https://github.com/hyperledger/besu/pull/1977) +- Change Ethstats's status from experimental feature to stable. [\#2405](https://github.com/hyperledger/besu/pull/2405) +- Fixed disabling of native libraries for secp256k1 and altBn128. [\#2163](https://github.com/hyperledger/besu/pull/2163) + + +### Bug Fixes + +- Updated `eth_sendRawTransaction` to return an error when maxPriorityFeePerGas exceeds maxFeePerGas [\#2424](https://github.com/hyperledger/besu/pull/2424) + +### Early Access Features +This release contains the activation blocks for London across all supported testnets. They are: + * Ropsten 10_499_401 (24 Jun 2021) + * Goerli 5_062_605 (30 Jun 2021) + * Rinkeby 8_897_988 (7 Jul 2021) + +## Download Link +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.7.0-RC1/besu-21.7.0-RC1.zip +sha256sum fc959646af65a0e267fc4d695e0af7e87331d774e6e8e890f5cc391549ed175a + +## 21.1.7 + +## Privacy users - Orion Project Deprecation +Tessera is now the recommended Private Transaction Manager for Hyperledger Besu. + +Now that all primary Orion functionality has been merged into Tessera, Orion is being deprecated. +We encourage all users with active projects to use the provided migration instructions, +documented [here](https://docs.orion.consensys.net/en/latest/Tutorials/Migrating-from-Orion-to-Tessera/). + +We will continue to support Orion users until 30th November 2021. If you have any questions or +concerns, please reach out to the ConsenSys protocol engineering team in the +[#orion channel on Discord](https://discord.gg/hYpHRjK) or by [email](mailto:quorum@consensys.net). + + +### Additions and Improvements +* Upgrade OpenTelemetry to 1.2.0. [\#2313](https://github.com/hyperledger/besu/pull/2313) + +* Ethereum Classic Magneto Hard Fork [\#2315](https://github.com/hyperledger/besu/pull/2315) + +* Added support for the upcoming CALAVERAS ephemeral testnet and removed the configuration for the deprecated BAIKAL ephemeral testnet. [\#2343](https://github.com/hyperledger/besu/pull/2343) + +### Bug Fixes +* Fix invalid transfer values with the tracing API specifically for CALL operation [\#2319](https://github.com/hyperledger/besu/pull/2319) + +### Early Access Features + +#### Previously identified known issues + +- Fixed issue in discv5 where nonce was incorrectly reused. [\#2075](https://github.com/hyperledger/besu/pull/2075) +- Fixed issues in debug_standardTraceBadBlockToFile and debug_standardTraceBlockToFile. [\#2120](https://github.com/hyperledger/besu/pull/2120) +- Fixed invalid error code in several JSON RPC methods when the requested block is not in the range. [\#2138](https://github.com/hyperledger/besu/pull/2138) + +## Download Link +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.1.7/besu-21.1.7.zip + +sha256: f415c9b67d26819caeb9940324b2b1b9ce6e872c9181052739438545e84e2531 + + +## 21.1.6 + +### Additions and Improvements + +* Added support for the upcoming BAIKAL ephemeral testnet and removed the configuration for the deprecated YOLOv3 ephemeral testnet. [\#2237](https://github.com/hyperledger/besu/pull/2237) +* Implemented [EIP-3541](https://eips.ethereum.org/EIPS/eip-3541): Reject new contracts starting with the 0xEF byte [\#2243](https://github.com/hyperledger/besu/pull/2243) +* Implemented [EIP-3529](https://eips.ethereum.org/EIPS/eip-3529): Reduction in refunds [\#2238](https://github.com/hyperledger/besu/pull/2238) +* Implemented [EIP-3554](https://eips.ethereum.org/EIPS/eip-3554): Difficulty Bomb Delay [\#2289](https://github.com/hyperledger/besu/pull/2289) +* \[EXPERIMENTAL\] Added support for secp256r1 keys. [#2008](https://github.com/hyperledger/besu/pull/2008) + +### Bug Fixes + +- Added ACCESS_LIST transactions to the list of transactions using legacy gas pricing for 1559 [\#2239](https://github.com/hyperledger/besu/pull/2239) +- Reduced logging level of public key decoding failure of malformed packets. [\#2143](https://github.com/hyperledger/besu/pull/2143) +- Add 1559 parameters to json-rpc responses. [\#2222](https://github.com/hyperledger/besu/pull/2222) + +### Early Access Features + +#### Previously identified known issues + +- Fixed issue in discv5 where nonce was incorrectly reused. [\#2075](https://github.com/hyperledger/besu/pull/2075) +- Fixed issues in debug_standardTraceBadBlockToFile and debug_standardTraceBlockToFile. [\#2120](https://github.com/hyperledger/besu/pull/2120) +- Fixed invalid error code in several JSON RPC methods when the requested block is not in the range. [\#2138](https://github.com/hyperledger/besu/pull/2138) + +## Download Link +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.1.6/besu-21.1.6.zip + +sha256: 3952c69a32bb390ec84ccf4c2c3eb600ea3696af9a05914985d10e1632ef8488 + +## 21.1.5 + +### Additions and Improvements + +- Ignore `nonce` when supplied to eth_estimateGas or eth_call. [\#2133](https://github.com/hyperledger/besu/pull/2133) +- Ignore `privateFor` for tx estimation. [\#2160](https://github.com/hyperledger/besu/pull/2160) + +### Bug Fixes + +- Fixed `NullPointerException` when crossing network upgrade blocks when peer discovery is disabled. [\#2140](https://github.com/hyperledger/besu/pull/2140) + +### Early Access Features + +#### Previously identified known issues + +- Fixed issue in discv5 where nonce was incorrectly reused. [\#2075](https://github.com/hyperledger/besu/pull/2075) +- Fixed issues in debug_standardTraceBadBlockToFile and debug_standardTraceBlockToFile. [\#2120](https://github.com/hyperledger/besu/pull/2120) + +## Download Link +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.1.5/besu-21.1.5.zip + +sha256: edd78fcc772cfa97d11d8ee7b5766e6fac4b31b582f940838a292f2aeb204777 + +## 21.1.4 + +### Additions and Improvements + +- Adds `--discovery-dns-url` CLI command [\#2088](https://github.com/hyperledger/besu/pull/2088) + +### Bug Fixes + +- Fixed issue in discv5 where nonce was incorrectly reused. [\#2075](https://github.com/hyperledger/besu/pull/2075) +- Fixed issues in debug_standardTraceBadBlockToFile and debug_standardTraceBlockToFile. [\#2120](https://github.com/hyperledger/besu/pull/2120) + +### Early Access Features + +#### Previously identified known issues + +- [Fast sync when running Besu on cloud providers](KNOWN_ISSUES.md#fast-sync-when-running-besu-on-cloud-providers) +- [Privacy users with private transactions created using v1.3.4 or earlier](KNOWN_ISSUES.md#privacy-users-with-private-transactions-created-using-v134-or-earlier) + +## Download Link +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.1.4/besu-21.1.4.zip +58ae55b492680d92aeccfbed477e8b9c25ccc1a97cca71895e27448d754a7d8b + +## 21.1.3 + +### Additions and Improvements +* Increase node diversity when downloading blocks [\#2033](https://github.com/hyperledger/besu/pull/2033) + +### Bug Fixes +* Ethereum Node Records are now dynamically recalculated when we pass network upgrade blocks. This allows for better peering through transitions without needing to restart the node. [\#1998](https://github.com/hyperledger/besu/pull/1998) + + +### Early Access Features + +#### Previously identified known issues + +- [Fast sync when running Besu on cloud providers](KNOWN_ISSUES.md#fast-sync-when-running-besu-on-cloud-providers) +- [Privacy users with private transactions created using v1.3.4 or earlier](KNOWN_ISSUES.md#privacy-users-with-private-transactions-created-using-v134-or-earlier) + +### Download link +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.1.3/besu-21.1.3.zip +38893cae225e5c53036d06adbeccc30aeb86ef08c543fb742941a8c618485c8a + +## 21.1.2 + +### Berlin Network Upgrade + +### Important note: the 21.1.1 release contains an outdated version of the Berlin network upgrade. If you are using Besu on public Ethereum networks, you must upgrade to 21.1.2. + +This release contains the activation blocks for Berlin across all supported testnets and the Ethereum mainnet. They are: + * Ropsten 9_812_189 (10 Mar 2021) + * Goerli 4_460_644 (17 Mar 2021) + * Rinkeby 8_290_928 (24 Mar 2021) + * Ethereum 12_244_000 (14 Apr 2021) + + +### Additions and Improvements +- Added option to set a limit for JSON-RPC connections + * HTTP connections `--rpc-http-max-active-connections` [\#1996](https://github.com/hyperledger/besu/pull/1996) + * WS connections `--rpc-ws-max-active-connections` [\#2006](https://github.com/hyperledger/besu/pull/2006) +- Added ASTOR testnet ETC support [\#2017](https://github.com/hyperledger/besu/pull/2017) +### Bug Fixes +* Don't Register BLS12 precompiles for Berlin [\#2015](https://github.com/hyperledger/besu/pull/2015) + +#### Previously identified known issues + +- [Fast sync when running Besu on cloud providers](KNOWN_ISSUES.md#fast-sync-when-running-besu-on-cloud-providers) +- [Privacy users with private transactions created using v1.3.4 or earlier](KNOWN_ISSUES.md#privacy-users-with-private-transactions-created-using-v134-or-earlier) + +### Download link +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.1.2/besu-21.1.2.zip +02f4b6622756b77fed814d8c1bbf986c6178d8f5adb9d61076e061124c3d12aa + +## 21.1.1 + +### Berlin Network Upgrade + +### Important note: this release contains an outdated version of the Berlin network upgrade. If you are using Besu on public Ethereum networks, you must upgrade to 21.1.2. + +This release contains the activation blocks for Berlin across all supported testnets and the Ethereum mainnet. They are: + * Ropsten 9_812_189 (10 Mar 2021) + * Goerli 4_460_644 (17 Mar 2021) + * Rinkeby 8_290_928 (24 Mar 2021) + * Ethereum 12_244_000 (14 Apr 2021) + +### Additions and Improvements +* Removed EIP-2315 from the Berlin network upgrade [\#1983](https://github.com/hyperledger/besu/pull/1983) +* Added `besu_transaction_pool_transactions` to the reported metrics, counting the mempool size [\#1869](https://github.com/hyperledger/besu/pull/1869) +* Distributions and maven artifacts have been moved off of bintray [\#1886](https://github.com/hyperledger/besu/pull/1886) +* admin_peers json RPC response now includes the remote nodes enode URL +* add support for keccak mining and a ecip1049_dev network [\#1882](https://github.com/hyperledger/besu/pull/1882) +### Bug Fixes +* Fixed incorrect `groupId` in published maven pom files. +* Fixed GraphQL response for missing account, return empty account instead [\#1946](https://github.com/hyperledger/besu/issues/1946) + +### Early Access Features + +#### Previously identified known issues + +- [Fast sync when running Besu on cloud providers](KNOWN_ISSUES.md#fast-sync-when-running-besu-on-cloud-providers) +- [Privacy users with private transactions created using v1.3.4 or earlier](KNOWN_ISSUES.md#privacy-users-with-private-transactions-created-using-v134-or-earlier) + +### Download link +sha256: `c22a80a54e9fed864734b9fbd69a0a46840fd27ca5211648a3eaf8a955417218 ` + + +## 21.1.0 + +### Important note: this release contains an outdated version of the Berlin network upgrade, which was changed on March 5, 2021 ([link](https://github.com/ethereum/pm/issues/263#issuecomment-791473406)). If you are using Besu on public Ethereum networks, you must upgrade to 21.1.2. + +## 21.1.0 Features + +Features added between 20.10.0 to 21.1.0 include: +* Berlin Network Upgrade: this release contains the activation blocks for Berlin across all supported testnets and the Ethereum mainnet. They are: + * Ropsten 9_812_189 (10 Mar 2021) + * Goerli 4_460_644 (17 Mar 2021) + * Rinkeby 8_290_928 (24 Mar 2021) + * Ethereum 12_244_000 (14 Apr 2021) +* Besu Launcher: Besu now has support for the [Quorum Mainnet Launcher](https://github.com/ConsenSys/quorum-mainnet-launcher) which makes it easy for users to configure and launch Besu on the Ethereum mainnet. +* Bonsai Tries: A new database format which reduces storage requirements and improves performance for access to recent state. _Note: only full sync is currently supported._ +* Miner Data JSON-RPC: The `eth_getMinerDataByBlockHash` and `eth_getMinerDataByBlockNumber` endpoints return miner rewards and coinbase address for a given block. +* EIP-1898 support: [The EIP](https://eips.ethereum.org/EIPS/eip-1898) adds `blockHash` to JSON-RPC methods which accept a default block parameter. + +### Early Access Features +* Bonsai Tries: A new database format which reduces storage requirements and improves performance for access to recent state. _Note: only full sync is currently supported._ +* QBFT: A new consensus algorithm to support interoperability with other Enterprise Ethereum Alliance compatible clients. + +### 21.1.0 Breaking Changes +* `--skip-pow-validation-enabled` is now an error with `block import --format JSON`. This is because the JSON format doesn't include the nonce so the proof of work must be calculated. +* `eth_call` will not return a JSON-RPC result if the call fails, but will return an error instead. If it was for a revert the revert reason will be included. +* `eth_call` will not fail for account balance issues by default. An parameter `"strict": true` can be added to the call parameters (with `to` and `from`) to enforce balance checks. + +### Additions and Improvements +* Added `besu_transaction_pool_transactions` to the reported metrics, counting the mempool size [\#1869](https://github.com/hyperledger/besu/pull/1869) +* Added activation blocks for Berlin Network Upgrade [\#1929](https://github.com/hyperledger/besu/pull/1929) + +### Bug Fixes +* Fixed representation of access list for access list transactions in JSON-RPC results. + +#### Previously identified known issues + +- [Fast sync when running Besu on cloud providers](KNOWN_ISSUES.md#fast-sync-when-running-besu-on-cloud-providers) +- [Privacy users with private transactions created using v1.3.4 or earlier](KNOWN_ISSUES.md#privacy-users-with-private-transactions-created-using-v134-or-earlier) + +### Download link +sha256: `e4c8fe4007e3e5f7f2528cbf1eeb5457caf06536c974a6ff4305035ff5724476` + +## 21.1.0-RC2 +### Additions and Improvements +* Support for the Berlin Network Upgrade, although the block number must be set manually with `--override-genesis-config=berlinBlock=`. This is because the block numbers haven't been determined yet. The next release will include the number in the genesis file so it will support Berlin with no intervention. [\#1898](https://github.com/hyperledger/besu/pull/1898) + +## 21.1.0-RC1 + +### 21.1.0 Breaking Changes +* `--skip-pow-validation-enabled` is now an error with `block import --format JSON`. This is because the JSON format doesn't include the nonce so the proof of work must be calculated. +* `eth_call` will not return a JSON-RPC result if the call fails, but will return an error instead. If it was for a revert the revert reason will be included. +* `eth_call` will not fail for account balance issues by default. An parameter `"strict": true` can be added to the call parameters (with `to` and `from`) to enforce balance checks. + +### Additions and Improvements +* Removed unused flags in default genesis configs [\#1812](https://github.com/hyperledger/besu/pull/1812) +* `--skip-pow-validation-enabled` is now an error with `block import --format JSON`. This is because the JSON format doesn't include the nonce so the proof of work must be calculated. [\#1815](https://github.com/hyperledger/besu/pull/1815) +* Added a new CLI option `--Xlauncher` to start a mainnet launcher. It will help to configure Besu easily. +* Return the revert reason from `eth_call` JSON-RPC api calls when the contract causes a revert. [\#1829](https://github.com/hyperledger/besu/pull/1829) +* Added `chainId`, `publicKey`, and `raw` to JSON-RPC api calls returning detailed transaction results. [\#1835](https://github.com/hyperledger/besu/pull/1835) + +### Bug Fixes +* Ethereum classic heights will no longer be reported in mainnet metrics. Issue [\#1751](https://github.com/hyperledger/besu/pull/1751) Fix [\#1820](https://github.com/hyperledger/besu/pull/1820) +* Don't enforce balance checks in `eth_call` unless explicitly requested. Issue [\#502](https://github.com/hyperledger/besu/pull/502) Fix [\#1834](https://github.com/hyperledger/besu/pull/1834) + +### Early Access Features + +#### Previously identified known issues + +- [Fast sync when running Besu on cloud providers](KNOWN_ISSUES.md#fast-sync-when-running-besu-on-cloud-providers) +- [Privacy users with private transactions created using v1.3.4 or earlier](KNOWN_ISSUES.md#privacy-users-with-private-transactions-created-using-v134-or-earlier) + + +### Download link + +Link removed because this release contains an outdated version of the Berlin network upgrade, which was changed on March 5, 2021 ([link](https://github.com/ethereum/pm/issues/263#issuecomment-791473406)). If you are using Besu on public Ethereum networks, you must upgrade to 21.1.1. sha256 hash left for reference. + +sha256: `b0fe3942052b8fd43fc3025a298a6c701f9edae2e100f0c563a1c5a4ceef71f1` + +## 20.10.4 + +### Additions and Improvements +* Implemented [EIP-778](https://eips.ethereum.org/EIPS/eip-778): Ethereum Node Records (ENR) [\#1680](https://github.com/hyperledger/besu/pull/1680) +* Implemented [EIP-868](https://eips.ethereum.org/EIPS/eip-868): Node Discovery v4 ENR Extension [\#1721](https://github.com/hyperledger/besu/pull/1721) +* Added revert reason to eth_estimateGas RPC call. [\#1730](https://github.com/hyperledger/besu/pull/1730) +* Added command line option --static-nodes-file. [#1644](https://github.com/hyperledger/besu/pull/1644) +* Implemented [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898): Add `blockHash` to JSON-RPC methods which accept a default block parameter [\#1757](https://github.com/hyperledger/besu/pull/1757) + +### Bug Fixes +* Accept locally-sourced transactions below the minimum gas price. [#1480](https://github.com/hyperledger/besu/issues/1480) [#1743](https://github.com/hyperledger/besu/pull/1743) + +#### Previously identified known issues + +- [Fast sync when running Besu on cloud providers](KNOWN_ISSUES.md#fast-sync-when-running-besu-on-cloud-providers) +- [Privacy users with private transactions created using v1.3.4 or earlier](KNOWN_ISSUES.md#privacy-users-with-private-transactions-created-using-v134-or-earlier) + +### Download link +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/20.10.4/besu-20.10.4.zip +sha256: f15cd5243b809659bba1706c1745aecafc012d3fc44a91419522da925493537c + ## 20.10.3 ### Additions and Improvements * Added `memory` as an option to `--key-value-storage`. This ephemeral storage is intended for sync testing and debugging. [\#1617](https://github.com/hyperledger/besu/pull/1617) * Fixed gasPrice parameter not always respected when passed to `eth_estimateGas` endpoint [\#1636](https://github.com/hyperledger/besu/pull/1636) * Enabled eth65 by default [\#1682](https://github.com/hyperledger/besu/pull/1682) +* Warn that bootnodes will be ignored if specified with discovery disabled [\#1717](https://github.com/hyperledger/besu/pull/1717) ### Bug Fixes * Accept to use default port values if not in use. [#1673](https://github.com/hyperledger/besu/pull/1673) @@ -17,6 +1486,10 @@ - [Fast sync when running Besu on cloud providers](KNOWN_ISSUES.md#fast-sync-when-running-besu-on-cloud-providers) - [Privacy users with private transactions created using v1.3.4 or earlier](KNOWN_ISSUES.md#privacy-users-with-private-transactions-created-using-v134-or-earlier) +### Download link +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/20.10.3/besu-20.10.3.zip +sha256: `b5f46d945754dedcbbb1e5dd96bf2bfd13272ff09c6a66c0150b979a578f4389` + ## 20.10.2 ### Additions and Improvements @@ -38,7 +1511,7 @@ ### Download Link -https://dl.bintray.com/hyperledger-org/besu-repo/besu-20.10.2.zip +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/20.10.2/besu-20.10.2.zip sha256: `710aed228dcbe9b8103aef39e4431b0c63e73c3a708ce88bcd1ecfa1722ad307` ## 20.10.1 @@ -65,7 +1538,7 @@ sha256: `710aed228dcbe9b8103aef39e4431b0c63e73c3a708ce88bcd1ecfa1722ad307` * Removed duplicate files from zip and tar.gz distributions. [\#1566](https://github.com/hyperledger/besu/pull/1566) * Add a more rational value to eth_gasPrice, based on a configurable percentile of prior block's transactions (default: median of last 100 blocks). [\#1563](https://github.com/hyperledger/besu/pull/1563) -## Deprecated +## Deprecated ### --privacy-precompiled-address (Scheduled for removal in _Next_ Release) Deprecated in 1.5.1 @@ -73,7 +1546,7 @@ Deprecated in 1.5.1 ### Besu Sample Network repository -The [Besu Sample Networks repository](https://github.com/ConsenSys/besu-sample-networks) has been replaced by the [Quorum Developer Quickstart](https://besu.hyperledger.org/en/latest/Tutorials/Developer-Quickstart). +The [Besu Sample Networks repository](https://github.com/ConsenSys/besu-sample-networks) has been replaced by the [Quorum Developer Quickstart](https://besu.hyperledger.org/en/latest/Tutorials/Developer-Quickstart). #### Previously identified known issues @@ -83,14 +1556,14 @@ The [Besu Sample Networks repository](https://github.com/ConsenSys/besu-sample-n ### Download Link -https://dl.bintray.com/hyperledger-org/besu-repo/besu-20.10.1.zip +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/20.10.1/besu-20.10.1.zip sha256: `ac4fae310957c176564396f73c0f03c60c41129d43d078560d0dab533a69fd2a` ## 20.10.0 ## Release format -Hyperledger Besu is moving its versioning scheme to [CalVer](https://calver.org/) starting with the 20.10.0 (formerly 1.6.0) release. More information about the specific version of CalVer Besu is using can be found on the [wiki](https://wiki.hyperledger.org/display/BESU/Using+CalVer+for+Besu+Releases). +Hyperledger Besu is moving its versioning scheme to [CalVer](https://calver.org/) starting with the 20.10.0 (formerly 1.6.0) release. More information about the specific version of CalVer Besu is using can be found on the [wiki](https://wiki.hyperledger.org/display/BESU/Using+CalVer+for+Besu+Releases). ## 20.10 Breaking Changes @@ -102,9 +1575,9 @@ Prior versions of Besu would set the HTTP Status 400 Bad Request for JSON-RPC re In Besu version 20.10, properly formatted requests that have valid parameters (count and content) will return a HTTP Status 200 OK, with an error field if an error occurred. For example, requesting an account that does not exist in the chain, or a block by hash that Besu does not have, will now return HTTP 200 OK responses. Unparsable requests, improperly formatted requests, or requests with invalid parameters will continue to return HTTP 400 Bad Request. -Users of Web3J should note that many calls will now return a result with the error field containing the message whereas before a call would throw an exception with the error message as the exception message. +Users of Web3J should note that many calls will now return a result with the error field containing the message whereas before a call would throw an exception with the error message as the exception message. -## 20.10.0 Additions and Improvements +## 20.10.0 Additions and Improvements * Added support for ECIP-1099 / Classic Thanos Fork: Calibrate Epoch Duration. [\#1421](https://github.com/hyperledger/besu/pull/1421) [\#1441](https://github.com/hyperledger/besu/pull/1441) [\#1462](https://github.com/hyperledger/besu/pull/1462) * Added the Open Telemetry Java agent to report traces to a remote backend. Added an example to showcase the trace reporting capabilities. @@ -112,9 +1585,9 @@ Users of Web3J should note that many calls will now return a result with the err * Added support for the upcoming YOLOv2 ephemeral testnet and removed the flag for the deprecated YOLOv1 ephemeral testnet. [#1386](https://github.com/hyperledger/besu/pull/1386) * Added `debug_standardTraceBlockToFile` JSON-RPC API. This API accepts a block hash and will replay the block. It returns a list of files containing the result of the trace (one file per transaction). [\#1392](https://github.com/hyperledger/besu/pull/1392) * Added `debug_standardTraceBadBlockToFile` JSON-RPC API. This API is similar to `debug_standardTraceBlockToFile`, but can be used to obtain info about a block which has been rejected as invalid. [\#1403](https://github.com/hyperledger/besu/pull/1403) -* Added support for EIP-2929 to YOLOv2. [#1387](https://github.com/hyperledger/besu/pull/1387) +* Added support for EIP-2929 to YOLOv2. [#1387](https://github.com/hyperledger/besu/pull/1387) * Added `--start-block` and `--end-block` to the `blocks import` subcommand [\#1399](https://github.com/hyperledger/besu/pull/1399) -* Added support for multi-tenancy when using the early access feature of [onchain privacy group management](https://besu.hyperledger.org/en/stable/Concepts/Privacy/Onchain-PrivacyGroups/) +* Added support for multi-tenancy when using the early access feature of [onchain privacy group management](https://besu.hyperledger.org/en/stable/Concepts/Privacy/Onchain-PrivacyGroups/) * \[Reverted\] Fixed memory leak in eth/65 subprotocol behavior. It is now enabled by default. [\#1420](https://github.com/hyperledger/besu/pull/1420), [#1348](https://github.com/hyperledger/besu/pull/1348), [#1321](https://github.com/hyperledger/besu/pull/1321) ### Bug Fixes @@ -136,7 +1609,7 @@ Deprecated in 1.5.1 on `--privacy-onchain-groups-enabled`. [\#1222](https://github.com/hyperledger/besu/pull/1222) ### Download link -https://dl.bintray.com/hyperledger-org/besu-repo/besu-20.10.0.zip +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/20.10.0/besu-20.10.0.zip sha256sum: `2b50a375aae64b838a2cd9d43747006492cae573f1be11745b7f643646fd5a01` @@ -147,7 +1620,7 @@ sha256sum: `2b50a375aae64b838a2cd9d43747006492cae573f1be11745b7f643646fd5a01` ### Bug Fixes * Added `debug_getBadBlocks` JSON-RPC API to analyze and detect consensus flaws. Even if a block is rejected it will be returned by this method [\#1378](https://github.com/hyperledger/besu/pull/1378) -* Fix logs queries missing results against chain head [\#1351](https://github.com/hyperledger/besu/pull/1351) and [\#1381](https://github.com/hyperledger/besu/pull/1381) +* Fix logs queries missing results against chain head [\#1351](https://github.com/hyperledger/besu/pull/1351) and [\#1381](https://github.com/hyperledger/besu/pull/1381) #### Previously identified known issues @@ -158,7 +1631,7 @@ sha256sum: `2b50a375aae64b838a2cd9d43747006492cae573f1be11745b7f643646fd5a01` ### Download link -https://dl.bintray.com/hyperledger-org/besu-repo/besu-1.5.5.zip +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/1.5.5/besu-1.5.5.zip sha256sum: `e67b0a899dc4421054eaa9a8112cb89e1e5f6a56f0d8aa1b0c5111c53dfad2ad` @@ -185,7 +1658,7 @@ sha256sum: `e67b0a899dc4421054eaa9a8112cb89e1e5f6a56f0d8aa1b0c5111c53dfad2ad` - [Changes not saved to database correctly causing inconsistent private states](KNOWN_ISSUES.md#Changes-not-saved-to-database-correctly-causing-inconsistent-private-states) ### Download link -https://dl.bintray.com/hyperledger-org/besu-repo/besu-1.5.4.zip +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/1.5.4/besu-1.5.4.zip sha256sum: `1f4df8e1c5e3b5b3abf6289ccfe70f302aa7c29a652b2eb713ffbdc507670420` @@ -220,10 +1693,10 @@ To enhance control over permissions on the privacy group management contract: the privacy group. In the default onchain privacy group management contract implementation, only the owner can add and remove participants, and upgrade the management contract. -The onchain privacy support in the current version of the web3js-eea library (v0.9) will not be compatible with Besu v1.5.3. We are actively working on an upgrade to webj3-eea that will support these changes. +The onchain privacy support in the current version of the web3js-eea library (v0.9) will not be compatible with Besu v1.5.3. We are actively working on an upgrade to webj3-eea that will support these changes. ### Download link -https://dl.bintray.com/hyperledger-org/besu-repo/besu-1.5.3.zip +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/1.5.3/besu-1.5.3.zip sha256sum: `735cd511e1dae1590f2829d9535cb383aa8c526f059b3451859e5fcfccc48985` @@ -241,7 +1714,7 @@ sha256sum: `735cd511e1dae1590f2829d9535cb383aa8c526f059b3451859e5fcfccc48985` * New docker images are being generated to use the latest version of OpenJDK (currently 14.0.1) with the tag suffix of `-openjdk-latest`, for example `1.5.2-openjdk-latest`. * New docker images are being generated to use [GraalVM](https://www.graalvm.org/) with the tag suffix of `-graalvm`, for example `1.5.2-graalvm`. -* The existing images based on Java 11 are also being tagged with the suffix `-openjdk-11`, for example `1.5.2-openjdk-11`, as well as `1.5.2`. +* The existing images based on Java 11 are also being tagged with the suffix `-openjdk-11`, for example `1.5.2-openjdk-11`, as well as `1.5.2`. The intent is that the major Java VM version or Java VM type shipped with the default docker images (`latest`, `1.5.x`, etc.) may be changed during future quarterly releases but will remain consistent within quarterly releases. @@ -265,7 +1738,7 @@ The intent is that the major Java VM version or Java VM type shipped with the de - [Edward Evans](https://github.com/hyperledger/besu/commits?author=EdJoJob) voluntarily moved to [emeritus status](https://github.com/hyperledger/besu/pull/1270). ### Download link -https://dl.bintray.com/hyperledger-org/besu-repo/besu-1.5.2.zip +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/1.5.2/besu-1.5.2.zip sha256sum: `629f44e230a635b09f8d82f2196d70d31193233718118a46412f11c50772dc85` @@ -306,7 +1779,7 @@ Known issues are open issues categorized as [Very High or High impact](https://w - [Restarts caused by insufficient memory can cause inconsistent private state](KNOWN_ISSUES.md#Restart-caused-by-insufficient-memory-can-cause-inconsistent-private-state) ### Download link -https://dl.bintray.com/hyperledger-org/besu-repo/besu-1.5.1.zip +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/1.5.1/besu-1.5.1.zip sha256sum: `c17f49b6b8686822417184952487fc135772f0be03514085926a6984fd955b88` @@ -396,18 +1869,18 @@ Workaround - Do not use permissioning on K8S. Workaround - Ensure you allocate enough memory for the Java Runtime Environment that the node does not run out of memory. #### Previously identified known issues - + - [Scope of logs query causing Besu to hang](KNOWN_ISSUES.md#scope-of-logs-query-causing-besu-to-hang) - [Eth/65 loses peers](KNOWN_ISSUES.md#eth65-loses-peers) - [Fast sync when running Besu on cloud providers](KNOWN_ISSUES.md#fast-sync-when-running-besu-on-cloud-providers) - [Privacy users with private transactions created using v1.3.4 or earlier](KNOWN_ISSUES.md#privacy-users-with-private-transactions-created-using-v134-or-earlier) ### Download link -https://dl.bintray.com/hyperledger-org/besu-repo/besu-1.5.0.zip +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/1.5.0/besu-1.5.0.zip sha256sum: `56929d6a71cc681688351041c919e9630ab6df7de37dd0c4ae9e19a4f44460b2` -**For download links of releases prior to 1.5.0, please visit https://dl.bintray.com/hyperledger-org/besu-repo/** +**For download links of releases prior to 1.5.0, please visit https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/** ## 1.4.6 @@ -489,7 +1962,7 @@ Workaround - Limit the number of blocks queried by each `eth_getLogs` call. a fix is completed for the [eth/65 known issue](KNOWN_ISSUES.md). [\#741](https://github.com/hyperledger/besu/pull/741) - Resolve crashing NAT detectors on GKE. [\#731](https://github.com/hyperledger/besu/pull/731) fixes [\#507](https://github.com/hyperledger/besu/issues/507). [Besu-Kubernetes Readme](https://github.com/PegaSysEng/besu-kubernetes/blob/master/README.md#network-topology-and-high-availability-requirements) -updated to reflect changes. +updated to reflect changes. - Deal with quick service start failures [\#714](https://github.com/hyperledger/besu/pull/714) fixes [\#662](https://github.com/hyperledger/besu/issues/662) ### Known Issues @@ -518,7 +1991,7 @@ The `eth/65` change is not [backwards compatible](https://github.com/hyperledger This has the following impact: * In a private network, nodes using the 1.4.3 client cannot interact with nodes using 1.4.2 or earlier clients. -* On mainnet, synchronizing eventually stalls. +* On mainnet, synchronizing eventually stalls. Workaround -> revert to v1.4.2. @@ -543,7 +2016,7 @@ in 1.5.0 release. [\#639](https://github.com/hyperledger/besu/pull/639) ### Known Issues -#### Fast sync when running Besu on cloud providers +#### Fast sync when running Besu on cloud providers A known [RocksDB issue](https://github.com/facebook/rocksdb/issues/6435) causes fast sync to fail when running Besu on certain cloud providers. The following error is displayed repeatedly: @@ -722,7 +2195,7 @@ If you have existing private transactions, see [migration details](docs/Private- * Added [`priv_call`](https://besu.hyperledger.org/en/latest/Reference/API-Methods/#priv_call) which invokes a private contract function locally and does not change the private state. -* Besu has moved from an internal Bytes library to the [Apache Tuweni](https://tuweni.apache.org/) Bytes library. +* Besu has moved from an internal Bytes library to the [Apache Tuweni](https://tuweni.apache.org/) Bytes library. This includes using the library in the Plugins API interfaces. [#295](https://github.com/hyperledger/besu/pull/295) and [#215](https://github.com/hyperledger/besu/pull/215) ### Early Access Features @@ -1054,7 +2527,7 @@ For compatibility with ETC Agharta upgrade, use 1.3.7 or later. - Add `--target-gas-limit` command line option. [\#24](https://github.com/hyperledger/besu/pull/24)(thanks to new contributor [cfelde](https://github.com/cfelde)) - Allow private contracts to access public state. [\#9](https://github.com/hyperledger/besu/pull/9) - Documentation updates include: - - Added [sample load balancer configurations](https://besu.hyperledger.org/en/latest/HowTo/Configure/Configure-HA/Sample-Configuration/) + - Added [sample load balancer configurations](https://besu.hyperledger.org/en/latest/HowTo/Configure/Configure-HA/Sample-Configuration/) - Added [`retesteth`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Subcommands/#retesteth) subcommand - Added [`debug_accountRange`](https://besu.hyperledger.org/en/latest/Reference/API-Methods/#debug_accountrange) JSON-RPC API method - Clarified purpose of [static nodes](https://besu.hyperledger.org/en/latest/HowTo/Find-and-Connect/Managing-Peers/#static-nodes) @@ -1138,7 +2611,7 @@ For compatibility with ETC Agharta upgrade, use 1.3.7 or later. - [Added Responsible Disclosure policy](https://docs.pantheon.pegasys.tech/en/latest/Reference/Responsible-Disclosure/) - [Added `blocks export` subcommand](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Subcommands/#export) -### Technical Improvements +### Technical Improvements - Update the `pantheon blocks export` command usage [\#1887](https://github.com/PegaSysEng/pantheon/pull/1887) (thanks to [matkt](https://github.com/matkt)) - Stop Returning null for 'pending' RPC calls [\#1883](https://github.com/PegaSysEng/pantheon/pull/1883) - Blake validation errors are hard errors [\#1882](https://github.com/PegaSysEng/pantheon/pull/1882) @@ -1328,7 +2801,7 @@ For compatibility with ETC Agharta upgrade, use 1.3.7 or later. - Added content on [creating and managing privacy groups](https://besu.hyperledger.org/en/latest/Reference/web3js-eea-Methods/#createprivacygroup) - Added content on [accessing private and privacy marker transactions](https://besu.hyperledger.org/en/latest/HowTo/Use-Privacy/Access-Private-Transactions/) - Added content on [system requirements](https://besu.hyperledger.org/en/latest/HowTo/Get-Started/System-Requirements/) - - Added reference to [Besu role on Galaxy to deploy using Ansible](https://besu.hyperledger.org/en/latest/HowTo/Deploy/Ansible/). + - Added reference to [Besu role on Galaxy to deploy using Ansible](https://besu.hyperledger.org/en/latest/HowTo/Deploy/Ansible/). ### Technical Improvements @@ -1553,11 +3026,11 @@ Documentation updates include: - Added Genesis file support for specifying the maximum stack size. [\#1431](https://github.com/PegaSysEng/pantheon/pull/1431) - Included transaction details when subscribed to Pending transactions [\#1410](https://github.com/PegaSysEng/pantheon/pull/1410) - Documentation updates include: - - [Added configuration items specified in the genesis file](https://besu.hyperledger.org/en/latest/Reference/Config-Items/#configuration-items) + - [Added configuration items specified in the genesis file](https://besu.hyperledger.org/en/latest/Reference/Config-Items/#configuration-items) - [Added pending transaction details subscription](https://besu.hyperledger.org/en/latest/HowTo/Interact/APIs/RPC-PubSub/#pending-transactionss) - [Added Troubleshooting content](https://besu.hyperledger.org/en/latest/HowTo/Troubleshoot/Troubleshooting/) - - [Added Privacy Quickstart](https://besu.hyperledger.org/en/latest/Tutorials/Quickstarts/Privacy-Quickstart/) - - [Added privacy roadmap](https://github.com/hyperledger/besu/blob/master/ROADMAP.md) + - [Added Privacy Quickstart](https://besu.hyperledger.org/en/latest/Tutorials/Quickstarts/Privacy-Quickstart/) + - [Added privacy roadmap](https://github.com/hyperledger/besu/blob/master/ROADMAP.md) ### Technical Improvements @@ -1726,15 +3199,15 @@ Documentation updates include: - Notify of dropped messages [\#1156](https://github.com/PegaSysEng/pantheon/pull/1156) - Documentation updates include: - Added [Permissioning Overview](https://besu.hyperledger.org/en/latest/Concepts/Permissioning/Permissioning-Overview/) - - Added content on [Network vs Node Configuration](https://besu.hyperledger.org/en/latest/HowTo/Configure/Using-Configuration-File/) - - Updated [RAM requirements](https://besu.hyperledger.org/en/latest/HowTo/Get-Started/System-Requirements/#ram) + - Added content on [Network vs Node Configuration](https://besu.hyperledger.org/en/latest/HowTo/Configure/Using-Configuration-File/) + - Updated [RAM requirements](https://besu.hyperledger.org/en/latest/HowTo/Get-Started/System-Requirements/#ram) - Added [Privacy Overview](https://besu.hyperledger.org/en/latest/Concepts/Privacy/Privacy-Overview/) and [Processing Private Transactions](https://besu.hyperledger.org/en/latest/Concepts/Privacy/Private-Transaction-Processing/) - Renaming of Ethstats Lite Explorer to [Ethereum Lite Explorer](https://besu.hyperledger.org/en/latest/HowTo/Deploy/Lite-Block-Explorer/#lite-block-explorer-documentation) (thanks to [tzapu](https://github.com/tzapu)) - Added content on using [Truffle with Besu](https://besu.hyperledger.org/en/latest/HowTo/Develop-Dapps/Truffle/) - Added [`droppedPendingTransactions` RPC Pub/Sub subscription](https://besu.hyperledger.org/en/latest/HowTo/Interact/APIs/RPC-PubSub/#dropped-transactions) - - Added [`eea_*` JSON-RPC API methods](https://besu.hyperledger.org/en/latest/Reference/API-Methods/#eea-methods) + - Added [`eea_*` JSON-RPC API methods](https://besu.hyperledger.org/en/latest/Reference/API-Methods/#eea-methods) - Added [architecture diagram](https://besu.hyperledger.org/en/latest/Concepts/ArchitectureOverview/) - - Updated [permissioning CLI options](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#permissions-accounts-config-file-enabled) and [permissioned network tutorial](https://besu.hyperledger.org/en/stable/) + - Updated [permissioning CLI options](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#permissions-accounts-config-file-enabled) and [permissioned network tutorial](https://besu.hyperledger.org/en/stable/) ### Technical Improvements @@ -1801,18 +3274,18 @@ Documentation updates include: - Added [Azure quickstart tutorial](https://besu.hyperledger.org/en/latest/Tutorials/Quickstarts/Azure-Private-Network-Quickstart/) - Enabled copy button in code blocks - Added [IBFT 1.0](https://besu.hyperledger.org/en/latest/HowTo/Configure/Consensus-Protocols/QuorumIBFT/) - - Added section on using [Geth attach with Besu](https://besu.hyperledger.org/en/latest/HowTo/Interact/APIs/Using-JSON-RPC-API/#geth-console) + - Added section on using [Geth attach with Besu](https://besu.hyperledger.org/en/latest/HowTo/Interact/APIs/Using-JSON-RPC-API/#geth-console) - Enabled the edit link doc site to ease external doc contributions - Added [EthStats docs](https://besu.hyperledger.org/HowTo/Deploy/Lite-Network-Monitor/) (thanks to [baxy](https://github.com/baxy)) - - Updated [Postman collection](https://besu.hyperledger.org/en/latest/HowTo/Interact/APIs/Authentication/#postman) + - Updated [Postman collection](https://besu.hyperledger.org/en/latest/HowTo/Interact/APIs/Authentication/#postman) - Added [`metrics-category` CLI option](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#metrics-category) - Added information on [block time and timeout settings](https://besu.hyperledger.org/en/latest/HowTo/Configure/Consensus-Protocols/IBFT/#block-time) for IBFT 2.0 - Added [`admin_nodeInfo`](https://besu.hyperledger.org/en/latest/Reference/API-Methods/#admin_nodeinfo) - Added [permissions images](https://besu.hyperledger.org/en/latest/Concepts/Permissioning/Permissioning-Overview/) - Added permissioning blog to [Resources](https://besu.hyperledger.org/en/latest/Reference/Resources/) - Updated [Create Permissioned Network](https://besu.hyperledger.org/en/latest/Tutorials/Permissioning/Create-Permissioned-Network/) tutorial to use `export-address` - - Updated [Clique](https://besu.hyperledger.org/en/latest/HowTo/Configure/Consensus-Protocols/Clique/) and [IBFT 2.0](https://besu.hyperledger.org/en/latest/HowTo/Configure/Consensus-Protocols/IBFT/) docs to include complete genesis file - - Updated [Clique tutorial](https://besu.hyperledger.org/en/latest/Tutorials/Private-Network/Create-Private-Clique-Network/) to use `export-address` subcommand + - Updated [Clique](https://besu.hyperledger.org/en/latest/HowTo/Configure/Consensus-Protocols/Clique/) and [IBFT 2.0](https://besu.hyperledger.org/en/latest/HowTo/Configure/Consensus-Protocols/IBFT/) docs to include complete genesis file + - Updated [Clique tutorial](https://besu.hyperledger.org/en/latest/Tutorials/Private-Network/Create-Private-Clique-Network/) to use `export-address` subcommand - Added IBFT 2.0 [future message configuration options](https://besu.hyperledger.org/en/latest/HowTo/Configure/Consensus-Protocols/IBFT/#optional-configuration-options) ### Technical Improvements @@ -1972,9 +3445,9 @@ Public key address export subcommand was missing in 1.0 release. - Added rebind mitigation for Websockets. [\#905](https://github.com/PegaSysEng/pantheon/pull/905) - Support genesis contract code [\#749](https://github.com/PegaSysEng/pantheon/pull/749) (thanks to [kziemianek](https://github.com/kziemianek)). - Documentation updates include: - - Added details on [port configuration](https://besu.hyperledger.org/en/latest/HowTo/Find-and-Connect/Configuring-Ports/) + - Added details on [port configuration](https://besu.hyperledger.org/en/latest/HowTo/Find-and-Connect/Configuring-Ports/) - Added [Resources page](https://besu.hyperledger.org/en/latest/Reference/Resources/) linking to Besu blog posts and webinars - - Added [JSON-RPC Authentication](https://besu.hyperledger.org/en/latest/HowTo/Interact/APIs/Authentication/) + - Added [JSON-RPC Authentication](https://besu.hyperledger.org/en/latest/HowTo/Interact/APIs/Authentication/) - Added [tutorial to create permissioned network](https://besu.hyperledger.org/en/latest/Tutorials/Permissioning/Create-Permissioned-Network/) - Added [Permissioning](https://besu.hyperledger.org/en/latest/Concepts/Permissioning/Permissioning-Overview/) content - Added [Permissioning API methods](https://besu.hyperledger.org/en/latest/Reference/API-Methods/#permissioning-methods) @@ -2153,7 +3626,7 @@ The [documentation](https://docs.pantheon.pegasys.tech/en/latest/) has been upda | `--datadir` | [`--data-path`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#data-path) | Renamed | | `--dev-mode` | [`--network=dev`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#network) | Replaced by `--network` option | | `--genesis` | [`--genesis-file`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#genesis-file) | Renamed | -| `--goerli` | [`--network=goerli`]((https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#network) | Replaced by `--network` option | +| `--goerli` | [`--network=goerli`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#network) | Replaced by `--network` option | | `--metrics-listen=` | [`--metrics-host=`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#metrics-host) and [`--metrics-port=`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#metrics-port) | Split into host and port options | | `--miner-extraData` | [`--miner-extra-data`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#miner-extra-data) | Renamed | | `--miner-minTransactionGasPriceWei` | [`--min-gas-price`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#min-gas-price) | Renamed | @@ -2161,8 +3634,8 @@ The [documentation](https://docs.pantheon.pegasys.tech/en/latest/) has been upda | `--node-private-key` | [`--node-private-key-file`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#node-private-key-file) | Renamed | | `--ottoman` | N/A | Removed | | `--p2p-listen=` | [`--p2p-host=`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#p2p-hostt) and [`--p2p-port=`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#p2p-port) | Split into host and port options | -| `--rinkeby` | [`--network=rinkeby`]((https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#network) | Replaced by `--network` option | -| `--ropsten` | [`--network=ropsten`]((https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#network) | Replaced by `--network` option | +| `--rinkeby` | [`--network=rinkeby`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#network) | Replaced by `--network` option | +| `--ropsten` | [`--network=ropsten`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#network) | Replaced by `--network` option | | `--rpc-enabled` | [` --rpc-http-enabled`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#rpc-http-enabled)| Renamed| | `--rpc-listen=` | [`--rpc-http-host=`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#rpc-http-host) and [`--rpc-http-port=`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#rpc-http-port) | Split into host and port options | | `--rpc-api` | [`--rpc-http-api`](https://besu.hyperledger.org/en/latest/Reference/CLI/CLI-Syntax/#rpc-http-api)| Renamed | @@ -2303,12 +3776,12 @@ To recover the node key and data directory from the Docker container: Where `container` is the name or ID of the Docker container containing the Besu node. The container can be running or stopped when you copy the key and data directory. If your node was -fully synchronized to MainNet, the data directory will be ~2TB. +fully synchronized to MainNet, the data directory will be ~2TB. When restarting your node with the v0.8.4 Docker image: * Save the node key in the [`key` file](https://besu.hyperledger.org/en/latest/Concepts/Node-Keys/#node-private-key) in the data - directory or specify the location using the [`--node-private-key` option](https://besu.hyperledger.org/en/stable/). + directory or specify the location using the [`--node-private-key` option](https://besu.hyperledger.org/en/stable/). * Specify the ` + ## Active Maintainers - + | Name | Github | LFID | | ---------------- | ---------------- | ---------------- | -| Abdel Bakhta | abdelhamidbakhta | abdelhamidbakhta | +| Ameziane Hamlat | ahamlat | ahamlat | | Adrian Sutton | ajsutton | ajsutton | +| Antony Denyer | antonydenyer | antonydenyer | | Antoine Toulme | atoulme | atoulme | -| Byron Gravenorst | bgravenorst | bgravenorst | -| Chris Hare | CjHare | cjhare | -| David Mechler | davemec | davemec | -| Edward Mack | edwardmack | mackcom | -| Ivaylo Kirilov | iikirilov | iikirilov | +| Daniel Lehrner | daniellehrner | daniellehrner | +| Diego López León | diega | diega | +| Fabio Di Fabio | fab-10 | fab-10 | +| Gary Schulte | garyschulte | GarySchulte | +| Gabriel Trintinalia | gabriel-trintinalia | gabrieltrintinalia | +| Jiri Peinlich | gezero | JiriPeinlich | +| Gabriel Fukushima| gfukushima | gfukushima | +| Justin Florentine| jflo | RoboCopsGoneMad | | Jason Frame | jframe | jframe | | Joshua Fernandes | joshuafernandes | joshuafernandes | | Lucas Saldanha | lucassaldanha | lucassaldanha | | Sally MacFarlane | macfarla | macfarla | -| Madeline Murray | MadelineMurray | madelinemurray | | Mark Terry | mark-terry | m.terry | | Karim Taam | matkt | matkt | | Meredith Baxter | mbaxter | mbaxter | -| Nicolas Massart | NicolasMassart | NicolasMassart | | Stefan Pingel | pinges | pinges | -| Trent Mohay | rain-on | trent.mohay | -| Rai Sur | RatanRSur | ratanraisur | -| Rob Dawson | rojotek | RobDawson | | Danno Ferrin | shemnon | shemnon | -| Tim Beiko | timbeiko | timbeiko | +| Simon Dudley | siladu | siladu | | Usman Saleem | usmansaleem | usmansaleem | +| Zhenyang Shi | wcgcyx | wcgcyx | + ## Emeritus Maintainers -| Name | Github | LFID | -|--------------|---------|---------| -| Edward Evans | EdJoJob | EdJoJob | +| Name | Github | LFID | +|------------------|------------------|------------------| +| Abdel Bakhta | abdelhamidbakhta | abdelhamidbakhta | +| Byron Gravenorst | bgravenorst | bgravenorst | +| Chris Hare | CjHare | cjhare | +| David Mechler | davemec | davemec | +| Edward Evans | EdJoJob | EdJoJob | +| Edward Mack | edwardmack | mackcom | +| Frank Li | frankisawesome | frankliawesome | +| Ivaylo Kirilov | iikirilov | iikirilov | +| Madeline Murray | MadelineMurray | madelinemurray | +| Nicolas Massart | NicolasMassart | NicolasMassart | +| Trent Mohay | rain-on | trent.mohay | +| Rai Sur | RatanRSur | ratanraisur | +| Rob Dawson | rojotek | RobDawson | +| Sajida Zouarhi | sajz | SajidaZ | +| Taccat Isid | taccatisid | taccatisid | +| Tim Beiko | timbeiko | timbeiko | +| Vijay Michalik | vmichalik | VijayMichalik | ## Becoming a Maintainer -Besu welcomes community contribution. Community members may progress to become a -maintainer. To become a maintainer the following steps occur, roughly in order. +Besu welcomes community contribution. +Each community member may progress to become a maintainer. + +How to become a maintainer: + +- Contribute significantly to the code in this repository. + +### Maintainers contribution requirement + +The requirement to be able to be proposed as a maintainer is: + +- 5 significant changes on code have been authored in this repos by the proposed maintainer and accepted (merged PRs). + +### Maintainers approval process + +The following steps must occur for a contributor to be "upgraded" as a maintainer: -- 5 significant changes have been authored by the proposed maintainer and - accepted. - The proposed maintainer has the sponsorship of at least one other maintainer. - - This sponsoring maintainer will create a PR modifying the list of - maintainers. + - This sponsoring maintainer will create a proposal PR modifying the list of + maintainers. (see [proposal PR template](#proposal-pr-template).) - The proposed maintainer accepts the nomination and expresses a willingness - to be a long-term (more than 6 month) committer. - - This would be a comment in the above PR. - - This PR will be communicated in all appropriate communication channels. It - should be mentioned in any maintainer/community call. It should also be - posted to the appropriate mailing list or chat channels if they exist. + to be a long-term (more than 6 month) committer by adding a comment in the proposal PR. + - The PR will be communicated in all appropriate communication channels + including at least [besu-contributors channel on Hyperledger Discord](https://discord.gg/hyperledger), + the [mailing list](https://lists.hyperledger.org/g/besu) + and any maintainer/community call. - Approval by at least 3 current maintainers within two weeks of the proposal or - an absolute majority of current maintainers. - - These votes will be recorded in the PR modifying the list of maintainers. -- No veto by another maintainer within two weeks of proposal are recorded. + an absolute majority (half the total + 1) of current maintainers. + - Maintainers will vote by approving the proposal PR. +- No veto raised by another maintainer within the voting timeframe. - All vetoes must be accompanied by a public explanation as a comment in the - PR for adding this maintainer - - The explanation of the veto must be reasonable. - - A veto can be retracted, in that case the approval/veto timeframe is reset. + proposal PR. + - The explanation of the veto must be reasonable and follow the [Besu code of conduct](https://wiki.hyperledger.org/display/BESU/Code+of+Conduct). + - A veto can be retracted, in that case the voting timeframe is reset and all approvals are removed. - It is bad form to veto, retract, and veto again. -- The proposed maintainer becomes a maintainer - - Either two weeks have passed since the third approval, - - Or an absolute majority of maintainers approve. - - In either case, no maintainer presents a veto. + +The proposed maintainer becomes a maintainer either: + + - when two weeks have passed without veto since the third approval of the proposal PR, + - or an absolute majority of maintainers approved the proposal PR. + +In either case, no maintainer raised and stood by a veto. ## Removing Maintainers -Being a maintainer is not a status symbol or a title to be maintained -indefinitely. It will occasionally be necessary and appropriate to move a -maintainer to emeritus status. This can occur in the following situations: +Being a maintainer is not a status symbol or a title to be maintained indefinitely. + +It will occasionally be necessary and appropriate to move a maintainer to emeritus status. + +This can occur in the following situations: - Resignation of a maintainer. - Violation of the Code of Conduct warranting removal. - Inactivity. - A general measure of inactivity will be no commits or code review comments - for one reporting quarter, although this will not be strictly enforced if + for two reporting quarters, although this will not be strictly enforced if the maintainer expresses a reasonable intent to continue contributing. - Reasonable exceptions to inactivity will be granted for known long term leave such as parental leave and medical leave. - Other unspecified circumstances. -Like adding a maintainer the record and governance process for moving a -maintainer to emeritus status is recorded in the github PR making that change. +As for adding a maintainer, the record and governance process for moving a +maintainer to emeritus status is recorded using review approval in the PR making that change. Returning to active status from emeritus status uses the same steps as adding a -new maintainer. Note that the emeritus maintainer already has the 5 required -significant changes as there is no contribution time horizon for those. +new maintainer. + +Note that the emeritus maintainer always already has the required significant contributions. +There is no contribution prescription delay. + +## Proposal PR template + +```markdown +I propose to add [maintainer github handle] as a Besu project maintainer. + +[maintainer github handle] contributed with many high quality commits: + +- [list significant achievements] + +Here are [their past contributions on Besu project](https://github.com/hyperledger/besu/commits?author=[user github handle]). + +Voting ends two weeks from today. + +For more information on this process see the Becoming a Maintainer section in the MAINTAINERS.md file. +``` diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index edfac2bb41a..00000000000 --- a/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,39 +0,0 @@ -## Status -**READY/IN DEVELOPMENT/HOLD** - -## Description -A few sentences describing the overall goals of the pull request's commits. - -## Related PRs -List related PRs against other branches: - -branch | PR ------- | ------ -other_pr_production | [link]() -other_pr_master | [link]() - - -## Todos -- [ ] Tests -- [ ] Documentation - - -## Deploy Notes -Notes regarding deployment the contained body of work. These should note any -db migrations, etc. - -## Steps to Test or Reproduce -Outline the steps to test or reproduce the PR here. - -```sh -git pull --prune -git checkout -bundle; script/server -``` - -1. - -## Impacted Areas in Application -List general components of the application that this PR will affect: - -* \ No newline at end of file diff --git a/README.md b/README.md index 28d18498be7..98560c66ed6 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,11 @@ # Besu Ethereum Client - [![CircleCI](https://circleci.com/gh/hyperledger/besu/tree/master.svg?style=svg)](https://circleci.com/gh/hyperledger/besu/tree/master) - [![Total alerts](https://img.shields.io/lgtm/alerts/g/hyperledger/besu.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/hyperledger/besu/alerts/) - [![Language grade: Java](https://img.shields.io/lgtm/grade/java/g/hyperledger/besu.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/hyperledger/besu/context:java) + [![CircleCI](https://circleci.com/gh/hyperledger/besu/tree/main.svg?style=svg)](https://circleci.com/gh/hyperledger/besu/tree/main) [![Documentation Status](https://readthedocs.org/projects/hyperledger-besu/badge/?version=latest)](https://besu.hyperledger.org/en/latest/?badge=latest) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/3174/badge)](https://bestpractices.coreinfrastructure.org/projects/3174) - [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/PegasysEng/besu/blob/master/LICENSE) - [ ![Download](https://api.bintray.com/packages/hyperledger-org/besu-repo/besu/images/download.svg) ](https://bintray.com/hyperledger-org/besu-repo/besu/_latestVersion) - [![RocketChat chat](https://open.rocket.chat/images/join-chat.svg)](https://chat.hyperledger.org/channel/besu) + [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/hyperledger/besu/blob/main/LICENSE) + [![Discord](https://img.shields.io/discord/905194001349627914?logo=Hyperledger&style=plastic)](https://discord.gg/hyperledger) +[Download](https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/) Besu is an Apache 2.0 licensed, MainNet compatible, Ethereum client written in Java. @@ -25,7 +23,7 @@ Besu is an Apache 2.0 licensed, MainNet compatible, Ethereum client written in J Besu issues are tracked [in the github issues tab][Besu Issues]. See our [guidelines](https://wiki.hyperledger.org/display/BESU/Issues) for more details on searching and creating issues. -If you have any questions, queries or comments, [RocketChat] is the place to find us. +If you have any questions, queries or comments, [Besu channel on Hyperledger Discord] is the place to find us. ## Besu Users @@ -69,5 +67,5 @@ and YourKit YouMonitor. [Besu Issues]: https://github.com/hyperledger/besu/issues [Besu User Documentation]: https://besu.hyperledger.org -[RocketChat]: https://chat.hyperledger.org/ -[Contributing Guidelines]: CONTRIBUTING.md \ No newline at end of file +[Besu channel on Hyperledger Discord]: https://discord.gg/hyperledger +[Contributing Guidelines]: CONTRIBUTING.md diff --git a/SECURITY.md b/SECURITY.md index 4727d240345..9a328164b95 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -7,13 +7,15 @@ hear from you. We will take all security bugs seriously and if confirmed upon in patch it within a reasonable amount of time and release a public security bulletin discussing the impact and credit the discoverer. -There are two ways to report a security bug. The easiest is to email a description of the flaw and -any related information (e.g. reproduction steps, version) to -[security at hyperledger dot org](mailto:security@hyperledger.org). - -The other way is to file a confidential security bug in our -[JIRA bug tracking system](https://jira.hyperledger.org). Be sure to set the “Security Level” to -“Security issue”. +There are two email addresses where Hyperledger Besu accepts security bugs. The +first, [security "dash" besu at lists dot hyperledger dot org](mailto:security-besu@lists.hyperledger.org) +is limited to a subset of Hyperledger Besu maintainers and Hyperledger staff. For highly sensitive +bugs this is a preferred address. The second email +address [security at hyperledger dot org](mailto:security@hyperledger.org) is limited to a subset of +maintainers and staff of all Hyperledger projects, and may be viewed by maintainers outside of +Hyperledger Besu. When sending information to either of these emails please be sure to include a +description of the flaw and any related information (e.g. reproduction steps, version, known active +use). The process by which the Hyperledger Security Team handles security bugs is documented further in our [Defect Response page](https://wiki.hyperledger.org/display/SEC/Defect+Response) on our diff --git a/SUPPORT.md b/SUPPORT.md index bf5b9459362..16a9bccd6ae 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -2,17 +2,17 @@ Welcome to the Besu repository! The following links are a set of guidelines for contributing to this repo and its packages. These are mostly guidelines, not rules. Use your best judgement, and feel free to propose changes to this document in a pull request. Contributions come in the form of code submissions, writing documentation, raising issues, helping others in chat, and any other actions that help develop Besu. -### LF/Github Accounts +### Github/Discord/LF Accounts -Having Linux Foundation and Github accounts is necessary for obtaining support for Besu through the rocket chat, wiki and issue management. +Having Github, Discord, and Linux Foundation accounts is necessary for obtaining support for Besu through the community channels, wiki and issue management. * If you want to raise an issue, you can do so [on the github issue tab](https://github.com/hyperledger/besu/issues). -* Our Rocket Chat requires a [Linux Foundation (LF) account]. +* Hyperledger Discord requires a [Discord account]. * The Hyperlegder wiki also requires a [Linux Foundation (LF) account] in order to edit pages. ### Useful support links * [Besu User Documentation] -* [RocketChat] +* [Besu channel on Hyperledger Discord] * [I just have a quick question](https://wiki.hyperledger.org/display/BESU/I+just+have+a+quick+question) * [Did you find a bug?](https://wiki.hyperledger.org/display/BESU/Reporting+Bugs) * [Issues](https://wiki.hyperledger.org/display/BESU/Issues) @@ -20,5 +20,5 @@ Having Linux Foundation and Github accounts is necessary for obtaining support f [Besu User Documentation]: https://besu.hyperledger.org -[RocketChat]: https://chat.hyperledger.org/ -[Contributing Guidelines]: CONTRIBUTING.md \ No newline at end of file +[Besu channel on Hyperledger Discord]: https://discord.gg/hyperledger +[Contributing Guidelines]: CONTRIBUTING.md diff --git a/acceptance-tests/dsl/build.gradle b/acceptance-tests/dsl/build.gradle index b71b32cbc63..d65de08b954 100644 --- a/acceptance-tests/dsl/build.gradle +++ b/acceptance-tests/dsl/build.gradle @@ -2,8 +2,10 @@ dependencies { implementation project(':besu') implementation project(':config') implementation project(':consensus:clique') + implementation project(':consensus:common') implementation project(':consensus:ibft') - implementation project(':crypto') + implementation project(':consensus:qbft') + implementation project(':crypto:services') implementation project(':enclave') implementation project(':ethereum:api') implementation project(':ethereum:blockcreation') @@ -11,9 +13,13 @@ dependencies { implementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts') implementation project(':ethereum:eth') implementation project(':ethereum:p2p') + implementation project(':evm') + implementation project(':datatypes') implementation project(':ethereum:permissioning') implementation project(':ethereum:rlp') implementation project(':metrics:core') + implementation project(':pki') + implementation project(path: ':pki', configuration: 'testArtifacts') implementation project(':plugin-api') implementation project(':plugins:rocksdb') implementation project(':services:kvstore') @@ -22,25 +28,23 @@ dependencies { implementation 'com.github.tomakehurst:wiremock-jre8' implementation 'com.google.guava:guava' + implementation 'com.google.dagger:dagger' + annotationProcessor 'com.google.dagger:dagger-compiler' implementation 'com.squareup.okhttp3:okhttp' implementation 'info.picocli:picocli' implementation 'io.reactivex.rxjava2:rxjava' implementation 'io.vertx:vertx-core' implementation 'junit:junit' - implementation 'net.consensys:orion' - implementation 'org.apache.logging.log4j:log4j-api' - implementation 'org.apache.logging.log4j:log4j-core' - implementation 'org.apache.logging.log4j:log4j-slf4j-impl' - implementation 'org.apache.tuweni:bytes' - implementation 'org.apache.tuweni:io' - implementation 'org.apache.tuweni:units' + implementation 'io.opentelemetry:opentelemetry-api' + implementation 'org.apache.tuweni:tuweni-bytes' + implementation 'org.apache.tuweni:tuweni-io' + implementation 'org.apache.tuweni:tuweni-units' implementation 'org.assertj:assertj-core' implementation 'org.awaitility:awaitility' implementation 'org.java-websocket:Java-WebSocket' implementation 'org.web3j:abi' implementation 'org.web3j:besu' implementation 'org.web3j:crypto' - implementation 'tech.pegasys.ethsigner.internal:core' - implementation 'tech.pegasys.ethsigner.internal:file-based' - implementation 'tech.pegasys.ethsigner.internal:signing-api' + + implementation 'org.testcontainers:testcontainers' } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBase.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBase.java index 83ea3eecce7..617e0e534cb 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBase.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBase.java @@ -20,9 +20,9 @@ import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts; import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Blockchain; import org.hyperledger.besu.tests.acceptance.dsl.condition.admin.AdminConditions; +import org.hyperledger.besu.tests.acceptance.dsl.condition.bft.BftConditions; import org.hyperledger.besu.tests.acceptance.dsl.condition.clique.CliqueConditions; import org.hyperledger.besu.tests.acceptance.dsl.condition.eth.EthConditions; -import org.hyperledger.besu.tests.acceptance.dsl.condition.ibft2.Ibft2Conditions; import org.hyperledger.besu.tests.acceptance.dsl.condition.login.LoginConditions; import org.hyperledger.besu.tests.acceptance.dsl.condition.net.NetConditions; import org.hyperledger.besu.tests.acceptance.dsl.condition.perm.PermissioningConditions; @@ -37,10 +37,10 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.permissioning.PermissionedNodeBuilder; import org.hyperledger.besu.tests.acceptance.dsl.transaction.account.AccountTransactions; import org.hyperledger.besu.tests.acceptance.dsl.transaction.admin.AdminTransactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.bft.BftTransactions; import org.hyperledger.besu.tests.acceptance.dsl.transaction.clique.CliqueTransactions; import org.hyperledger.besu.tests.acceptance.dsl.transaction.contract.ContractTransactions; import org.hyperledger.besu.tests.acceptance.dsl.transaction.eth.EthTransactions; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2.Ibft2Transactions; import org.hyperledger.besu.tests.acceptance.dsl.transaction.miner.MinerTransactions; import org.hyperledger.besu.tests.acceptance.dsl.transaction.net.NetTransactions; import org.hyperledger.besu.tests.acceptance.dsl.transaction.perm.PermissioningTransactions; @@ -57,18 +57,18 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.ThreadContext; import org.junit.After; import org.junit.Rule; import org.junit.rules.TestName; import org.junit.rules.TestWatcher; import org.junit.runner.Description; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; public class AcceptanceTestBase { - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LoggerFactory.getLogger(AcceptanceTestBase.class); protected final Accounts accounts; protected final AccountTransactions accountTransactions; @@ -82,8 +82,8 @@ public class AcceptanceTestBase { protected final ContractTransactions contractTransactions; protected final EthConditions eth; protected final EthTransactions ethTransactions; - protected final Ibft2Transactions ibftTwoTransactions; - protected final Ibft2Conditions ibftTwo; + protected final BftTransactions bftTransactions; + protected final BftConditions bft; protected final LoginConditions login; protected final NetConditions net; protected final BesuNodeFactory besu; @@ -105,7 +105,7 @@ protected AcceptanceTestBase() { accounts = new Accounts(ethTransactions); adminTransactions = new AdminTransactions(); cliqueTransactions = new CliqueTransactions(); - ibftTwoTransactions = new Ibft2Transactions(); + bftTransactions = new BftTransactions(); accountTransactions = new AccountTransactions(accounts); permissioningTransactions = new PermissioningTransactions(); privacyTransactions = new PrivacyTransactions(); @@ -115,7 +115,7 @@ protected AcceptanceTestBase() { blockchain = new Blockchain(ethTransactions); clique = new CliqueConditions(ethTransactions, cliqueTransactions); eth = new EthConditions(ethTransactions); - ibftTwo = new Ibft2Conditions(ibftTwoTransactions); + bft = new BftConditions(bftTransactions); login = new LoginConditions(); net = new NetConditions(new NetTransactions()); cluster = new Cluster(net); @@ -179,13 +179,13 @@ private void printOutput(final Process process) { } @Rule - public TestWatcher log_eraser = + public TestWatcher logEraser = new TestWatcher() { @Override protected void starting(final Description description) { - ThreadContext.put("test", description.getMethodName()); - ThreadContext.put("class", description.getClassName()); + MDC.put("test", description.getMethodName()); + MDC.put("class", description.getClassName()); final String errorMessage = "Uncaught exception in thread \"{}\""; Thread.currentThread() @@ -201,6 +201,7 @@ protected void failed(final Throwable e, final Description description) { LOG.error( "=========================================================================================="); LOG.error("Test failed. Reported Throwable at the point of failure:", e); + LOG.error(e.getMessage()); } @Override diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/BlockUtils.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/BlockUtils.java index 076b61d90c7..6f88c3a6ead 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/BlockUtils.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/BlockUtils.java @@ -14,14 +14,16 @@ */ package org.hyperledger.besu.tests.acceptance.dsl; -import static org.hyperledger.besu.ethereum.core.Hash.fromHexString; +import static org.hyperledger.besu.datatypes.Hash.fromHexString; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; import org.hyperledger.besu.ethereum.core.Difficulty; -import org.hyperledger.besu.ethereum.core.Hash; -import org.hyperledger.besu.ethereum.core.LogsBloomFilter; +import org.hyperledger.besu.evm.log.LogsBloomFilter; + +import java.math.BigInteger; import org.apache.tuweni.bytes.Bytes; import org.web3j.protocol.core.methods.response.EthBlock.Block; @@ -50,7 +52,10 @@ public static BlockHeader createBlockHeader( Bytes.fromHexString(block.getExtraData()), null, mixHash, - block.getNonce().longValue(), + new BigInteger(block.getNonceRaw().substring(2), 16).longValue(), + null, + null, + null, blockHeaderFunctions); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/account/Account.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/account/Account.java index 3237e0e512d..6cdd53fbed6 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/account/Account.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/account/Account.java @@ -14,11 +14,13 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.account; -import org.hyperledger.besu.crypto.SECP256K1.KeyPair; -import org.hyperledger.besu.crypto.SECP256K1.PrivateKey; -import org.hyperledger.besu.crypto.SECP256K1.PublicKey; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.crypto.KeyPair; +import org.hyperledger.besu.crypto.SECPPrivateKey; +import org.hyperledger.besu.crypto.SECPPublicKey; +import org.hyperledger.besu.crypto.SignatureAlgorithm; +import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.condition.account.ExpectAccountBalance; @@ -30,6 +32,8 @@ import java.math.BigInteger; import java.util.Optional; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; import org.apache.tuweni.bytes.Bytes32; import org.web3j.crypto.Credentials; import org.web3j.utils.Convert.Unit; @@ -38,11 +42,14 @@ public class Account { private final EthTransactions eth; private final String name; - private final Optional privateKey; - private final Optional publicKey; + private final Optional privateKey; + private final Optional publicKey; private final Address address; private long nonce = 0; + private static final Supplier SIGNATURE_ALGORITHM = + Suppliers.memoize(SignatureAlgorithmFactory::getInstance); + private Account( final EthTransactions eth, final String name, @@ -68,13 +75,18 @@ public static Account create(final EthTransactions eth, final Address address) { } public static Account create(final EthTransactions eth, final String name) { - return new Account(eth, name, KeyPair.generate()); + return new Account(eth, name, SIGNATURE_ALGORITHM.get().generateKeyPair()); } static Account fromPrivateKey( final EthTransactions eth, final String name, final String privateKey) { return new Account( - eth, name, KeyPair.create(PrivateKey.create(Bytes32.fromHexString(privateKey)))); + eth, + name, + SIGNATURE_ALGORITHM + .get() + .createKeyPair( + SIGNATURE_ALGORITHM.get().createPrivateKey(Bytes32.fromHexString(privateKey)))); } public Optional web3jCredentials() { diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/account/Accounts.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/account/Accounts.java index ad3df909c6b..a219dbd27ac 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/account/Accounts.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/account/Accounts.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.account; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.transaction.eth.EthTransactions; public class Accounts { diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/blockchain/Amount.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/blockchain/Amount.java index fe1d6ae55ed..169b6f3c60d 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/blockchain/Amount.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/blockchain/Amount.java @@ -28,6 +28,8 @@ public class Amount { private final BigDecimal value; private final Unit unit; + public static Amount ZERO = new Amount(BigDecimal.ZERO, WEI); + private Amount(final BigDecimal value, final Unit unit) { this.value = value; this.unit = unit; @@ -49,20 +51,27 @@ public Unit getUnit() { return unit; } + public Amount add(final Amount other) { + final BigDecimal weiResult = + Convert.toWei(value, unit).add(Convert.toWei(other.value, other.unit)); + + final Unit denomination = getMostPreciseUnit(unit, other.unit); + final BigDecimal result = Convert.fromWei(weiResult, denomination); + + return new Amount(result, denomination); + } + public Amount subtract(final Amount subtracting) { + final BigDecimal weiResult = + Convert.toWei(value, unit).subtract(Convert.toWei(subtracting.value, subtracting.unit)); - final Unit denominator; - if (unit.getWeiFactor().compareTo(subtracting.unit.getWeiFactor()) < 0) { - denominator = unit; - } else { - denominator = subtracting.unit; - } + final Unit denomination = getMostPreciseUnit(unit, subtracting.unit); + final BigDecimal result = Convert.fromWei(weiResult, denomination); - final BigDecimal result = - Convert.fromWei( - Convert.toWei(value, unit).subtract(Convert.toWei(subtracting.value, subtracting.unit)), - denominator); + return new Amount(result, denomination); + } - return new Amount(result, denominator); + private Unit getMostPreciseUnit(final Unit a, final Unit b) { + return a.getWeiFactor().compareTo(b.getWeiFactor()) < 0 ? a : b; } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/account/ExpectAccountBalanceAtBlock.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/account/ExpectAccountBalanceAtBlock.java index 7c977aee3fa..72eba5bc2ed 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/account/ExpectAccountBalanceAtBlock.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/account/ExpectAccountBalanceAtBlock.java @@ -52,6 +52,11 @@ public void verify(final Node node) { WaitUtils.waitFor( () -> assertThat(node.execute(eth.getBalanceAtBlock(account, block))) + .withFailMessage( + () -> + String.format( + "Expected address %s at block %s to have balance %s", + account.getAddress(), block.toString(10), expectedBalance.toString(10))) .isEqualTo(expectedBalance)); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/admin/AdminConditions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/admin/AdminConditions.java index b2d9b2db047..9b270748f50 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/admin/AdminConditions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/admin/AdminConditions.java @@ -32,10 +32,17 @@ public AdminConditions(final AdminTransactions admin) { } public Condition addPeer(final Node addingPeer) { - return new ExpectPeerAdded(admin.addPeer(enodeUrl(addingPeer))); } + public Condition hasPeer(final Node peer) { + return new ExpectHasPeer(nodeId(peer), admin.listPeers()); + } + + public Condition doesNotHavePeer(final Node peer) { + return new ExpectNotHavePeer(nodeId(peer), admin.listPeers()); + } + private URI enodeUrl(final Node node) { if (!(node instanceof RunnableNode)) { fail("A RunnableNode instance is required"); @@ -43,4 +50,12 @@ private URI enodeUrl(final Node node) { return ((RunnableNode) node).enodeUrl(); } + + private String nodeId(final Node node) { + if (!(node instanceof RunnableNode)) { + fail("A RunnableNode instance is required"); + } + + return "0x" + ((RunnableNode) node).getNodeId(); + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/admin/ExpectHasPeer.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/admin/ExpectHasPeer.java new file mode 100644 index 00000000000..58f91c8e0a3 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/admin/ExpectHasPeer.java @@ -0,0 +1,41 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.tests.acceptance.dsl.condition.admin; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.admin.AdminPeersTransaction; + +import java.util.List; + +public class ExpectHasPeer implements Condition { + + private final String peer; + private final AdminPeersTransaction transaction; + + public ExpectHasPeer(final String peer, final AdminPeersTransaction transaction) { + this.peer = peer; + this.transaction = transaction; + } + + @Override + public void verify(final Node node) { + final List result = node.execute(transaction); + assertThat(result).contains(peer); + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/admin/ExpectNotHavePeer.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/admin/ExpectNotHavePeer.java new file mode 100644 index 00000000000..64f06bec4c1 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/admin/ExpectNotHavePeer.java @@ -0,0 +1,41 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.tests.acceptance.dsl.condition.admin; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.admin.AdminPeersTransaction; + +import java.util.List; + +public class ExpectNotHavePeer implements Condition { + + private final String peer; + private final AdminPeersTransaction transaction; + + public ExpectNotHavePeer(final String peer, final AdminPeersTransaction transaction) { + this.peer = peer; + this.transaction = transaction; + } + + @Override + public void verify(final Node node) { + final List result = node.execute(transaction); + assertThat(result).doesNotContain(peer); + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/ibft2/AwaitValidatorSetChange.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/bft/AwaitValidatorSetChange.java similarity index 75% rename from acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/ibft2/AwaitValidatorSetChange.java rename to acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/bft/AwaitValidatorSetChange.java index 816c3f98515..85c448eff92 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/ibft2/AwaitValidatorSetChange.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/bft/AwaitValidatorSetChange.java @@ -12,27 +12,27 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.tests.acceptance.dsl.condition.ibft2; +package org.hyperledger.besu.tests.acceptance.dsl.condition.bft; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.tests.acceptance.dsl.transaction.clique.CliqueTransactions.LATEST; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2.Ibft2Transactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.bft.BftTransactions; import java.util.List; public class AwaitValidatorSetChange implements Condition { - private final Ibft2Transactions ibft; + private final BftTransactions bft; private final List
initialSigners; - public AwaitValidatorSetChange(final List
initialSigners, final Ibft2Transactions ibft) { + public AwaitValidatorSetChange(final List
initialSigners, final BftTransactions bft) { this.initialSigners = initialSigners; - this.ibft = ibft; + this.bft = bft; } @Override @@ -40,7 +40,6 @@ public void verify(final Node node) { WaitUtils.waitFor( 60, () -> - assertThat(node.execute(ibft.createGetValidators(LATEST))) - .isNotEqualTo(initialSigners)); + assertThat(node.execute(bft.createGetValidators(LATEST))).isNotEqualTo(initialSigners)); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/bft/BftConditions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/bft/BftConditions.java new file mode 100644 index 00000000000..9df47918c0e --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/bft/BftConditions.java @@ -0,0 +1,94 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.condition.bft; + +import static org.hyperledger.besu.tests.acceptance.dsl.transaction.clique.CliqueTransactions.LATEST; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.bft.BftTransactions; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import com.google.common.collect.ImmutableMap; + +public class BftConditions { + + private final BftTransactions bft; + + public BftConditions(final BftTransactions bft) { + this.bft = bft; + } + + public List validators(final BesuNode[] nodes) { + final Comparator compareByAddress = Comparator.comparing(BesuNode::getAddress); + List besuNodes = Arrays.asList(nodes); + besuNodes.sort(compareByAddress); + return besuNodes; + } + + public ExpectValidators validatorsEqual(final BesuNode... validators) { + return new ExpectValidators(bft, validatorAddresses(validators)); + } + + private Address[] validatorAddresses(final BesuNode[] validators) { + return Arrays.stream(validators).map(BesuNode::getAddress).sorted().toArray(Address[]::new); + } + + public Condition awaitValidatorSetChange(final Node node) { + return new AwaitValidatorSetChange(node.execute(bft.createGetValidators(LATEST)), bft); + } + + public Condition noProposals() { + return new ExpectProposals(bft, ImmutableMap.of()); + } + + public PendingVotesConfig pendingVotesEqual() { + return new PendingVotesConfig(bft); + } + + public static class PendingVotesConfig { + private final Map proposals = new HashMap<>(); + private final BftTransactions bft; + + private PendingVotesConfig(final BftTransactions bft) { + this.bft = bft; + } + + public PendingVotesConfig addProposal(final BesuNode node) { + proposals.put(node, true); + return this; + } + + public PendingVotesConfig removeProposal(final BesuNode node) { + proposals.put(node, false); + return this; + } + + public Condition build() { + final Map proposalsAsAddress = + this.proposals.entrySet().stream() + .collect(Collectors.toMap(p -> p.getKey().getAddress(), Map.Entry::getValue)); + return new ExpectProposals(bft, proposalsAsAddress); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/bft/ExpectProposals.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/bft/ExpectProposals.java new file mode 100644 index 00000000000..2864e0a5393 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/bft/ExpectProposals.java @@ -0,0 +1,40 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.condition.bft; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; +import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.bft.BftTransactions; + +import java.util.Map; + +public class ExpectProposals implements Condition { + private final BftTransactions bft; + private final Map proposers; + + public ExpectProposals(final BftTransactions bft, final Map proposers) { + this.bft = bft; + this.proposers = proposers; + } + + @Override + public void verify(final Node node) { + WaitUtils.waitFor(() -> assertThat(node.execute(bft.createProposals())).isEqualTo(proposers)); + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/bft/ExpectValidators.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/bft/ExpectValidators.java new file mode 100644 index 00000000000..1e8ef463cdc --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/bft/ExpectValidators.java @@ -0,0 +1,41 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.condition.bft; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.tests.acceptance.dsl.transaction.bft.BftTransactions.LATEST; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; +import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.bft.BftTransactions; + +public class ExpectValidators implements Condition { + private final BftTransactions bft; + private final Address[] validators; + + public ExpectValidators(final BftTransactions bft, final Address... validators) { + this.bft = bft; + this.validators = validators; + } + + @Override + public void verify(final Node node) { + WaitUtils.waitFor( + () -> + assertThat(node.execute(bft.createGetValidators(LATEST))).containsExactly(validators)); + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/AwaitSignerSetChange.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/AwaitSignerSetChange.java index 6f173f371e1..f332b387c0d 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/AwaitSignerSetChange.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/AwaitSignerSetChange.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.tests.acceptance.dsl.transaction.clique.CliqueTransactions.LATEST; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/CliqueConditions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/CliqueConditions.java index a7a3ef7ed88..750e587f6e3 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/CliqueConditions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/CliqueConditions.java @@ -15,12 +15,12 @@ package org.hyperledger.besu.tests.acceptance.dsl.condition.clique; import static java.util.Collections.emptyList; -import static org.hyperledger.besu.ethereum.core.Hash.fromHexString; +import static org.hyperledger.besu.datatypes.Hash.fromHexString; import static org.hyperledger.besu.tests.acceptance.dsl.transaction.clique.CliqueTransactions.LATEST; import org.hyperledger.besu.config.CliqueConfigOptions; import org.hyperledger.besu.config.GenesisConfigFile; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.condition.blockchain.ExpectBlockNotCreated; import org.hyperledger.besu.tests.acceptance.dsl.condition.clique.ExpectNonceVote.CLIQUE_NONCE_VOTE; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectProposals.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectProposals.java index cfe2752c522..715c3501672 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectProposals.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectProposals.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectValidators.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectValidators.java index 1ffe836d505..4d25745333b 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectValidators.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectValidators.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.tests.acceptance.dsl.transaction.clique.CliqueTransactions.LATEST; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectValidatorsAtBlock.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectValidatorsAtBlock.java index 657296179fc..6482dd13e6c 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectValidatorsAtBlock.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectValidatorsAtBlock.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectValidatorsAtBlockHash.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectValidatorsAtBlockHash.java index 20152c5260c..f9d3e26289d 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectValidatorsAtBlockHash.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectValidatorsAtBlockHash.java @@ -16,8 +16,8 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectedBlockHasProposer.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectedBlockHasProposer.java index 16b3a6786cf..53b166c7149 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectedBlockHasProposer.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/ExpectedBlockHasProposer.java @@ -18,7 +18,7 @@ import org.hyperledger.besu.consensus.clique.CliqueBlockHeaderFunctions; import org.hyperledger.besu.consensus.clique.CliqueExtraData; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.tests.acceptance.dsl.BlockUtils; import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/eth/EthConditions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/eth/EthConditions.java index 0171f9dacfc..c4ee1347278 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/eth/EthConditions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/eth/EthConditions.java @@ -51,12 +51,17 @@ public Condition expectNoTransactionReceipt(final String transactionHash) { transactions.getTransactionReceipt(transactionHash)); } - public Condition sendRawTransactionExceptional( + public Condition expectEthSendRawTransactionException( final String transactionData, final String expectedMessage) { return new ExpectEthSendRawTransactionException( transactions.sendRawTransaction(transactionData), expectedMessage); } + public Condition expectSuccessfulEthRawTransaction(final String transactionData) { + return new ExpectSuccessfulEthSendRawTransaction( + transactions.sendRawTransaction(transactionData)); + } + public Condition expectSuccessfulTransactionReceiptWithReason( final String transactionHash, final String revertReason) { return new ExpectSuccessfulEthGetTransactionReceiptWithReason( diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/eth/ExpectSuccessfulEthSendRawTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/eth/ExpectSuccessfulEthSendRawTransaction.java new file mode 100644 index 00000000000..592d8e7db25 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/eth/ExpectSuccessfulEthSendRawTransaction.java @@ -0,0 +1,43 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.condition.eth; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; +import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.eth.EthSendRawTransactionTransaction; + +import org.apache.tuweni.bytes.Bytes32; + +public class ExpectSuccessfulEthSendRawTransaction implements Condition { + + private final EthSendRawTransactionTransaction transaction; + + public ExpectSuccessfulEthSendRawTransaction(final EthSendRawTransactionTransaction transaction) { + this.transaction = transaction; + } + + @Override + public void verify(final Node node) { + WaitUtils.waitFor( + 5, + () -> { + final Bytes32 txHash = Bytes32.fromHexString(node.execute(transaction)); + assertThat(txHash).isNotNull(); + }); + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/ibft2/ExpectProposals.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/ibft2/ExpectProposals.java deleted file mode 100644 index f39ec6f9eb3..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/ibft2/ExpectProposals.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.condition.ibft2; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; -import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; -import org.hyperledger.besu.tests.acceptance.dsl.node.Node; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2.Ibft2Transactions; - -import java.util.Map; - -public class ExpectProposals implements Condition { - private final Ibft2Transactions ibftTwo; - private final Map proposers; - - public ExpectProposals(final Ibft2Transactions ibftTwo, final Map proposers) { - this.ibftTwo = ibftTwo; - this.proposers = proposers; - } - - @Override - public void verify(final Node node) { - WaitUtils.waitFor( - () -> assertThat(node.execute(ibftTwo.createProposals())).isEqualTo(proposers)); - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/ibft2/ExpectValidators.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/ibft2/ExpectValidators.java deleted file mode 100644 index e4a0e7c8722..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/ibft2/ExpectValidators.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.condition.ibft2; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2.Ibft2Transactions.LATEST; - -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; -import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; -import org.hyperledger.besu.tests.acceptance.dsl.node.Node; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2.Ibft2Transactions; - -public class ExpectValidators implements Condition { - private final Ibft2Transactions ibft; - private final Address[] validators; - - public ExpectValidators(final Ibft2Transactions ibft, final Address... validators) { - this.ibft = ibft; - this.validators = validators; - } - - @Override - public void verify(final Node node) { - WaitUtils.waitFor( - () -> - assertThat(node.execute(ibft.createGetValidators(LATEST))).containsExactly(validators)); - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/ibft2/Ibft2Conditions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/ibft2/Ibft2Conditions.java deleted file mode 100644 index 583d90b74ac..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/ibft2/Ibft2Conditions.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.condition.ibft2; - -import static org.hyperledger.besu.tests.acceptance.dsl.transaction.clique.CliqueTransactions.LATEST; - -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; -import org.hyperledger.besu.tests.acceptance.dsl.node.Node; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2.Ibft2Transactions; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import com.google.common.collect.ImmutableMap; - -public class Ibft2Conditions { - - private final Ibft2Transactions ibftTwo; - - public Ibft2Conditions(final Ibft2Transactions ibftTwo) { - this.ibftTwo = ibftTwo; - } - - public List validators(final BesuNode[] nodes) { - final Comparator compareByAddress = Comparator.comparing(BesuNode::getAddress); - List besuNodes = Arrays.asList(nodes); - besuNodes.sort(compareByAddress); - return besuNodes; - } - - public ExpectValidators validatorsEqual(final BesuNode... validators) { - return new ExpectValidators(ibftTwo, validatorAddresses(validators)); - } - - private Address[] validatorAddresses(final BesuNode[] validators) { - return Arrays.stream(validators).map(BesuNode::getAddress).sorted().toArray(Address[]::new); - } - - public Condition awaitValidatorSetChange(final Node node) { - return new AwaitValidatorSetChange(node.execute(ibftTwo.createGetValidators(LATEST)), ibftTwo); - } - - public Condition noProposals() { - return new ExpectProposals(ibftTwo, ImmutableMap.of()); - } - - public PendingVotesConfig pendingVotesEqual() { - return new PendingVotesConfig(ibftTwo); - } - - public static class PendingVotesConfig { - private final Map proposals = new HashMap<>(); - private final Ibft2Transactions ibft; - - private PendingVotesConfig(final Ibft2Transactions ibft) { - this.ibft = ibft; - } - - public PendingVotesConfig addProposal(final BesuNode node) { - proposals.put(node, true); - return this; - } - - public PendingVotesConfig removeProposal(final BesuNode node) { - proposals.put(node, false); - return this; - } - - public Condition build() { - final Map proposalsAsAddress = - this.proposals.entrySet().stream() - .collect(Collectors.toMap(p -> p.getKey().getAddress(), Map.Entry::getValue)); - return new ExpectProposals(ibft, proposalsAsAddress); - } - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/net/ExpectNetServicesReturnsAllServicesAsActive.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/net/ExpectNetServicesReturnsAllServicesAsActive.java index 5c70702cd2c..79c058fc773 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/net/ExpectNetServicesReturnsAllServicesAsActive.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/net/ExpectNetServicesReturnsAllServicesAsActive.java @@ -29,6 +29,7 @@ public class ExpectNetServicesReturnsAllServicesAsActive implements Condition { private final NetServicesTransaction transaction; + private static final String JSON_RPC_CONSTANT = "jsonrpc"; public ExpectNetServicesReturnsAllServicesAsActive(final NetServicesTransaction transaction) { this.transaction = transaction; @@ -38,18 +39,18 @@ public ExpectNetServicesReturnsAllServicesAsActive(final NetServicesTransaction public void verify(final Node node) { final Map> result = node.execute(transaction); assertThat(result.keySet()) - .containsExactlyInAnyOrderElementsOf(Arrays.asList("p2p", "jsonrpc", "ws")); + .containsExactlyInAnyOrderElementsOf(Arrays.asList("p2p", JSON_RPC_CONSTANT, "ws")); assertThat(InetAddresses.isUriInetAddress(result.get("p2p").get("host"))).isTrue(); - final int p2pPort = Integer.valueOf(result.get("p2p").get("port")); + final int p2pPort = Integer.parseInt(result.get("p2p").get("port")); assertThat(NetworkUtility.isValidPort(p2pPort)).isTrue(); assertThat(InetAddresses.isUriInetAddress(result.get("ws").get("host"))).isTrue(); - final int wsPort = Integer.valueOf(result.get("ws").get("port")); + final int wsPort = Integer.parseInt(result.get("ws").get("port")); assertThat(NetworkUtility.isValidPort(wsPort)).isTrue(); - assertThat(InetAddresses.isUriInetAddress(result.get("jsonrpc").get("host"))).isTrue(); - final int jsonRpcPort = Integer.valueOf(result.get("jsonrpc").get("port")); + assertThat(InetAddresses.isUriInetAddress(result.get(JSON_RPC_CONSTANT).get("host"))).isTrue(); + final int jsonRpcPort = Integer.parseInt(result.get(JSON_RPC_CONSTANT).get("port")); assertThat(NetworkUtility.isValidPort(jsonRpcPort)).isTrue(); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/net/ExpectNetServicesReturnsOnlyJsonRpcActive.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/net/ExpectNetServicesReturnsOnlyJsonRpcActive.java index 255bf8ea1b7..cccde7b9417 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/net/ExpectNetServicesReturnsOnlyJsonRpcActive.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/net/ExpectNetServicesReturnsOnlyJsonRpcActive.java @@ -29,6 +29,7 @@ public class ExpectNetServicesReturnsOnlyJsonRpcActive implements Condition { private final NetServicesTransaction transaction; + private static final String JSON_RPC_CONSTANT = "jsonrpc"; public ExpectNetServicesReturnsOnlyJsonRpcActive(final NetServicesTransaction transaction) { this.transaction = transaction; @@ -38,10 +39,10 @@ public ExpectNetServicesReturnsOnlyJsonRpcActive(final NetServicesTransaction tr public void verify(final Node node) { final Map> result = node.execute(transaction); assertThat(result.keySet()) - .containsExactlyInAnyOrderElementsOf(Collections.singletonList("jsonrpc")); + .containsExactlyInAnyOrderElementsOf(Collections.singletonList(JSON_RPC_CONSTANT)); - assertThat(InetAddresses.isUriInetAddress(result.get("jsonrpc").get("host"))).isTrue(); - final int jsonrpcPort = Integer.valueOf(result.get("jsonrpc").get("port")); + assertThat(InetAddresses.isUriInetAddress(result.get(JSON_RPC_CONSTANT).get("host"))).isTrue(); + final int jsonrpcPort = Integer.parseInt(result.get(JSON_RPC_CONSTANT).get("port")); assertThat(NetworkUtility.isValidPort(jsonrpcPort)).isTrue(); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/perm/NodeSmartContractPermissioningV2Conditions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/perm/NodeSmartContractPermissioningV2Conditions.java index 350ff72b861..1ef293ec337 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/perm/NodeSmartContractPermissioningV2Conditions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/perm/NodeSmartContractPermissioningV2Conditions.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.condition.perm; +import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; import org.hyperledger.besu.tests.acceptance.dsl.transaction.perm.NodeSmartContractPermissioningV2Transactions; @@ -31,7 +32,15 @@ public Condition connectionIsAllowed(final String address, final Node node) { return new WaitForTrueResponse(transactions.isConnectionAllowed(address, node)); } + public Condition connectionIsAllowed(final String address, final EnodeURL enodeURL) { + return new WaitForTrueResponse(transactions.isConnectionAllowed(address, enodeURL)); + } + public Condition connectionIsForbidden(final String address, final Node node) { return new WaitForFalseResponse(transactions.isConnectionAllowed(address, node)); } + + public Condition connectionIsForbidden(final String address, final EnodeURL enodeURL) { + return new WaitForFalseResponse(transactions.isConnectionAllowed(address, enodeURL)); + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/EeaSendRawTransactionSuccess.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/EeaSendRawTransactionSuccess.java index a80cbb0007b..9aef5825ea4 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/EeaSendRawTransactionSuccess.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/EeaSendRawTransactionSuccess.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.EeaSendRawTransactionTransaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/PrivConditions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/PrivConditions.java index 43bac2df0ad..72d365cfb60 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/PrivConditions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/PrivConditions.java @@ -14,9 +14,9 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.condition.priv; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/PrivGetPrivacyPrecompileAddressSuccess.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/PrivGetPrivacyPrecompileAddressSuccess.java index 8b904965810..a3992da4327 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/PrivGetPrivacyPrecompileAddressSuccess.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/PrivGetPrivacyPrecompileAddressSuccess.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivGetPrivacyPrecompileAddressTransaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/PrivGetPrivateTransactionSuccess.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/PrivGetPrivateTransactionSuccess.java index 33383a054cf..b09b1b29bca 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/PrivGetPrivateTransactionSuccess.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/priv/PrivGetPrivateTransactionSuccess.java @@ -38,6 +38,6 @@ public PrivGetPrivateTransactionSuccess( @Override public void verify(final Node node) { final PrivateTransactionGroupResponse result = node.execute(transaction); - assertThat(result).isEqualToComparingFieldByField(privateTransaction); + assertThat(result).usingRecursiveComparison().isEqualTo(privateTransaction); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/process/ExitedWithCode.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/process/ExitedWithCode.java index abceb8ed5ba..0e28f0609ec 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/process/ExitedWithCode.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/process/ExitedWithCode.java @@ -22,12 +22,12 @@ import java.util.Optional; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ExitedWithCode implements Condition { - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LoggerFactory.getLogger(ExitedWithCode.class); private final int code; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/txpool/TxPoolConditions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/txpool/TxPoolConditions.java index da7dea8e2eb..4da3135920e 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/txpool/TxPoolConditions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/txpool/TxPoolConditions.java @@ -16,13 +16,14 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; import org.hyperledger.besu.tests.acceptance.dsl.transaction.txpool.TxPoolTransactions; import java.util.List; -import java.util.Map; +import java.util.stream.Collectors; public class TxPoolConditions { @@ -34,18 +35,16 @@ public TxPoolConditions(final TxPoolTransactions txPoolTransactions) { public Condition inTransactionPool(final Hash txHash) { return node -> - WaitUtils.waitFor( - () -> { - List> poolContents = - node.execute(txPoolTransactions.getTxPoolContents()); - boolean found = false; - for (Map txInfo : poolContents) { - if (Hash.fromHexString(txInfo.get("hash")).equals(txHash)) { - found = true; - break; - } - } - assertThat(found).isTrue(); - }); + WaitUtils.waitFor(() -> assertThat(nodeTransactionHashes(node)).contains(txHash)); + } + + public Condition notInTransactionPool(final Hash txHash) { + return node -> assertThat(nodeTransactionHashes(node)).doesNotContain(txHash); + } + + private List nodeTransactionHashes(final Node node) { + return node.execute(txPoolTransactions.getTxPoolContents()).stream() + .map((txInfo) -> Hash.fromHexString(txInfo.get("hash"))) + .collect(Collectors.toList()); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/EthSignerClient.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/EthSignerClient.java deleted file mode 100644 index f202a874b1a..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/EthSignerClient.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.ethsigner; - -import java.io.IOException; -import java.math.BigInteger; -import java.net.URI; -import java.util.Collections; -import java.util.List; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.web3j.protocol.Web3jService; -import org.web3j.protocol.core.Request; -import org.web3j.protocol.core.methods.request.Transaction; -import org.web3j.protocol.core.methods.response.EthSendTransaction; -import org.web3j.protocol.eea.Eea; -import org.web3j.protocol.http.HttpService; - -public class EthSignerClient { - private static final Logger LOG = LogManager.getLogger(); - private final Web3jService web3jService; - private final Eea web3j; - private final String from; - - public EthSignerClient(final URI ethSignerUri) throws IOException { - this.web3jService = new HttpService(ethSignerUri.toString()); - this.web3j = Eea.build(web3jService); - this.from = resolveFrom(ethSignerUri); - } - - private String resolveFrom(final URI ethSignerUri) throws IOException { - final List accounts; - try { - accounts = ethAccounts(); - return accounts.get(0); - } catch (IOException e) { - LOG.info("Failed to connect to EthSigner at {}", ethSignerUri); - throw e; - } catch (Exception e) { - LOG.info("Falling back to signing with node key"); - } - return null; - } - - public List ethAccounts() throws IOException { - return web3j.ethAccounts().send().getAccounts(); - } - - public String ethSendTransaction( - final String to, - final BigInteger gas, - final BigInteger gasPrice, - final BigInteger value, - final String data, - final BigInteger nonce) - throws IOException { - return web3j - .ethSendTransaction(new Transaction(from, nonce, gasPrice, gas, to, value, data)) - .send() - .getTransactionHash(); - } - - public String eeaSendTransaction( - final String to, - final BigInteger gas, - final BigInteger gasPrice, - final String data, - final String privateFrom, - final String privacyGroupId, - final String restriction) - throws IOException { - return eeaSendTransaction( - to, gas, gasPrice, data, null, privateFrom, privacyGroupId, restriction); - } - - public String eeaSendTransaction( - final String to, - final BigInteger gas, - final BigInteger gasPrice, - final String data, - final BigInteger nonce, - final String privateFrom, - final String privacyGroupId, - final String restriction) - throws IOException { - final PrivateTransactionRequest transaction = - new PrivateTransactionRequest( - from, - nonce, - gasPrice, - gas, - to, - BigInteger.ZERO, - data, - privateFrom, - privacyGroupId, - restriction); - - return eeaSendTransaction(transaction); - } - - public String eeaSendTransaction( - final String to, - final BigInteger gas, - final BigInteger gasPrice, - final String data, - final String privateFrom, - final List privateFor, - final String restriction) - throws IOException { - return eeaSendTransaction(to, gas, gasPrice, data, null, privateFrom, privateFor, restriction); - } - - public String eeaSendTransaction( - final String to, - final BigInteger gas, - final BigInteger gasPrice, - final String data, - final BigInteger nonce, - final String privateFrom, - final List privateFor, - final String restriction) - throws IOException { - - final PrivateTransactionRequest transaction = - new PrivateTransactionRequest( - from, - nonce, - gasPrice, - gas, - to, - BigInteger.ZERO, - data, - privateFrom, - privateFor, - restriction); - - return eeaSendTransaction(transaction); - } - - private String eeaSendTransaction(final PrivateTransactionRequest transaction) - throws IOException { - // temporary until implemented in web3j - return new Request<>( - "eea_sendTransaction", - Collections.singletonList(transaction), - web3jService, - EthSendTransaction.class) - .send() - .getTransactionHash(); - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/EthSignerClientTest.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/EthSignerClientTest.java deleted file mode 100644 index 06b33f2b6b1..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/EthSignerClientTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.ethsigner; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.post; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.tests.acceptance.dsl.ethsigner.testutil.EthSignerTestHarness; -import org.hyperledger.besu.tests.acceptance.dsl.ethsigner.testutil.EthSignerTestHarnessFactory; - -import java.io.IOException; -import java.math.BigInteger; -import java.util.Collections; -import java.util.List; - -import com.github.tomakehurst.wiremock.junit.WireMockRule; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -public class EthSignerClientTest { - @ClassRule public static final TemporaryFolder folder = new TemporaryFolder(); - - @ClassRule - public static final WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort()); - - private static final String MOCK_RESPONSE = "mock_transaction_hash"; - private static final String MOCK_SEND_TRANSACTION_RESPONSE = - "{\n" - + " \"id\":67,\n" - + " \"jsonrpc\":\"2.0\",\n" - + " \"result\": \"" - + MOCK_RESPONSE - + "\"\n" - + "}"; - private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="; - - private static EthSignerClient ethSignerClient; - - private static EthSignerTestHarness testHarness; - - @BeforeClass - public static void setUpOnce() throws Exception { - stubFor(post("/").willReturn(aResponse().withBody(MOCK_SEND_TRANSACTION_RESPONSE))); - - folder.create(); - - testHarness = - EthSignerTestHarnessFactory.create( - folder.newFolder().toPath(), - "ethSignerKey--fe3b557e8fb62b89f4916b721be55ceb828dbd73.json", - wireMockRule.port(), - 2018); - - ethSignerClient = new EthSignerClient(testHarness.getHttpListeningUrl()); - } - - @Test - public void testEthAccounts() throws IOException { - final List accounts = ethSignerClient.ethAccounts(); - assertThat(accounts).hasSize(1); - assertThat(accounts.get(0)).isEqualTo("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"); - } - - @Test - public void testEthSendTransaction() throws IOException { - final String response = - ethSignerClient.ethSendTransaction( - "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - "", - BigInteger.ZERO); - - assertThat(response).isEqualTo(MOCK_RESPONSE); - } - - @Test - public void testEeaSendTransaction() throws IOException { - final String response = - ethSignerClient.eeaSendTransaction( - "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", - BigInteger.ZERO, - BigInteger.ZERO, - "", - BigInteger.ZERO, - ENCLAVE_PUBLIC_KEY, - Collections.emptyList(), - "restricted"); - - assertThat(response).isEqualTo(MOCK_RESPONSE); - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/PrivateTransactionRequest.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/PrivateTransactionRequest.java deleted file mode 100644 index b9b21a49f27..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/PrivateTransactionRequest.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.ethsigner; - -import java.math.BigInteger; -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonInclude; -import org.web3j.utils.Numeric; - -@JsonInclude(JsonInclude.Include.NON_NULL) -public class PrivateTransactionRequest { - - private final String from; - private final BigInteger nonce; - private final BigInteger gasPrice; - private final BigInteger gas; - private final String to; - private final BigInteger value; - private final String data; - private final String privateFrom; - private List privateFor; - private String privacyGroupId; - private final String restriction; - - public PrivateTransactionRequest( - final String from, - final BigInteger nonce, - final BigInteger gasPrice, - final BigInteger gasLimit, - final String to, - final BigInteger value, - final String data, - final String privateFrom, - final List privateFor, - final String restriction) { - this.from = from; - this.to = to; - this.gas = gasLimit; - this.gasPrice = gasPrice; - this.value = value; - this.data = data == null ? null : Numeric.prependHexPrefix(data); - this.nonce = nonce; - this.privateFrom = privateFrom; - this.privateFor = privateFor; - this.restriction = restriction; - } - - public PrivateTransactionRequest( - final String from, - final BigInteger nonce, - final BigInteger gasPrice, - final BigInteger gasLimit, - final String to, - final BigInteger value, - final String data, - final String privateFrom, - final String privacyGroupId, - final String restriction) { - this.from = from; - this.to = to; - this.gas = gasLimit; - this.gasPrice = gasPrice; - this.value = value; - this.data = data == null ? null : Numeric.prependHexPrefix(data); - this.nonce = nonce; - this.privateFrom = privateFrom; - this.privacyGroupId = privacyGroupId; - this.restriction = restriction; - } - - public String getFrom() { - return from; - } - - public String getTo() { - return to; - } - - public String getGas() { - return convert(gas); - } - - public String getGasPrice() { - return convert(gasPrice); - } - - public String getValue() { - return convert(value); - } - - public String getData() { - return data; - } - - public String getNonce() { - return convert(nonce); - } - - private String convert(final BigInteger value) { - return value == null ? null : Numeric.encodeQuantity(value); - } - - public String getPrivateFrom() { - return privateFrom; - } - - public List getPrivateFor() { - return privateFor; - } - - public String getPrivacyGroupId() { - return privacyGroupId; - } - - public String getRestriction() { - return restriction; - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/testutil/EthSignerConfig.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/testutil/EthSignerConfig.java deleted file mode 100644 index a08631e8627..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/testutil/EthSignerConfig.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.ethsigner.testutil; - -import java.nio.file.Path; -import java.time.Duration; - -import org.apache.logging.log4j.Level; -import tech.pegasys.ethsigner.core.Config; -import tech.pegasys.ethsigner.core.signing.ChainIdProvider; - -public class EthSignerConfig implements Config { - private final Level logLevel; - private final String downstreamHttpHost; - private final Integer downStreamHttpPort; - private final Duration downstreamHttpRequestTimeout; - private final String httpListenHost; - private final Integer httpListenPort; - private final ChainIdProvider chainId; - private final Path dataDirectory; - - public EthSignerConfig( - final Level logLevel, - final String downstreamHttpHost, - final Integer downStreamHttpPort, - final Duration downstreamHttpRequestTimeout, - final String httpListenHost, - final Integer httpListenPort, - final ChainIdProvider chainId, - final Path dataDirectory) { - - this.logLevel = logLevel; - this.downstreamHttpHost = downstreamHttpHost; - this.downStreamHttpPort = downStreamHttpPort; - this.downstreamHttpRequestTimeout = downstreamHttpRequestTimeout; - this.httpListenHost = httpListenHost; - this.httpListenPort = httpListenPort; - this.chainId = chainId; - this.dataDirectory = dataDirectory; - } - - @Override - public Level getLogLevel() { - return logLevel; - } - - @Override - public String getDownstreamHttpHost() { - return downstreamHttpHost; - } - - @Override - public Integer getDownstreamHttpPort() { - return downStreamHttpPort; - } - - @Override - public Duration getDownstreamHttpRequestTimeout() { - return downstreamHttpRequestTimeout; - } - - @Override - public String getHttpListenHost() { - return httpListenHost; - } - - @Override - public Integer getHttpListenPort() { - return httpListenPort; - } - - @Override - public ChainIdProvider getChainId() { - return chainId; - } - - @Override - public Path getDataPath() { - return dataDirectory; - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/testutil/EthSignerTestHarness.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/testutil/EthSignerTestHarness.java deleted file mode 100644 index e4c13b7f7bc..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/testutil/EthSignerTestHarness.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.ethsigner.testutil; - -import java.net.URI; -import java.util.Properties; - -public class EthSignerTestHarness { - private final EthSignerConfig config; - private final Properties portsProperties; - - public EthSignerTestHarness(final EthSignerConfig config, final Properties properties) { - this.config = config; - this.portsProperties = properties; - } - - public URI getHttpListeningUrl() { - return URI.create( - "http://" + config.getHttpListenHost() + ":" + portsProperties.getProperty("http-jsonrpc")); - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/testutil/EthSignerTestHarnessFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/testutil/EthSignerTestHarnessFactory.java deleted file mode 100644 index 57b88d69825..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/ethsigner/testutil/EthSignerTestHarnessFactory.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.ethsigner.testutil; - -import static org.apache.tuweni.io.file.Files.copyResource; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.time.Duration; -import java.util.Properties; -import java.util.concurrent.TimeUnit; -import java.util.stream.Stream; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.awaitility.Awaitility; -import org.web3j.crypto.CipherException; -import org.web3j.crypto.WalletUtils; -import tech.pegasys.ethsigner.core.EthSigner; -import tech.pegasys.ethsigner.core.signing.ConfigurationChainId; -import tech.pegasys.ethsigner.core.signing.SingleTransactionSignerProvider; -import tech.pegasys.ethsigner.signer.filebased.CredentialTransactionSigner; - -public class EthSignerTestHarnessFactory { - - private static final Logger LOG = LogManager.getLogger(); - private static final String HOST = "127.0.0.1"; - - public static EthSignerTestHarness create( - final Path tempDir, final String keyPath, final Integer besuPort, final long chainId) - throws IOException, CipherException { - - final Path keyFilePath = copyResource(keyPath, tempDir.resolve(keyPath)); - - final EthSignerConfig config = - new EthSignerConfig( - Level.DEBUG, - HOST, - besuPort, - Duration.ofSeconds(10), - HOST, - 0, - new ConfigurationChainId(chainId), - tempDir); - - final EthSigner ethSigner = - new EthSigner( - config, - new SingleTransactionSignerProvider( - new CredentialTransactionSigner( - WalletUtils.loadCredentials("", keyFilePath.toAbsolutePath().toFile())))); - ethSigner.run(); - - waitForPortFile(tempDir); - - LOG.info("EthSigner port: {}", config.getHttpListenPort()); - - return new EthSignerTestHarness(config, loadPortsFile(tempDir)); - } - - private static Properties loadPortsFile(final Path tempDir) { - final Properties portsProperties = new Properties(); - try (final FileInputStream fis = - new FileInputStream(new File(tempDir.toFile(), "ethsigner.ports"))) { - portsProperties.load(fis); - LOG.info("Ports for ethsigner {}", portsProperties); - } catch (final IOException e) { - throw new RuntimeException("Error reading EthSigner ports file", e); - } - return portsProperties; - } - - private static void waitForPortFile(final Path tempDir) { - final File file = new File(tempDir.toFile(), "ethsigner.ports"); - Awaitility.waitAtMost(30, TimeUnit.SECONDS) - .until( - () -> { - if (file.exists()) { - try (final Stream s = Files.lines(file.toPath())) { - return s.count() > 0; - } - } else { - return false; - } - }); - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java index 5ea854b3fa5..d822a21fb18 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java @@ -15,28 +15,33 @@ package org.hyperledger.besu.tests.acceptance.dsl.node; import static java.util.Collections.unmodifiableList; -import static org.apache.logging.log4j.LogManager.getLogger; import static org.apache.tuweni.io.file.Files.copyResource; +import org.hyperledger.besu.cli.config.NetworkName; +import org.hyperledger.besu.config.MergeConfigOptions; +import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.KeyPairUtil; -import org.hyperledger.besu.crypto.SECP256K1.KeyPair; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; +import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; -import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.Util; import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; +import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; +import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.NodeConfiguration; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; import org.hyperledger.besu.tests.acceptance.dsl.transaction.admin.AdminRequestFactory; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.bft.BftRequestFactory; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.bft.ConsensusType; import org.hyperledger.besu.tests.acceptance.dsl.transaction.clique.CliqueRequestFactory; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2.Ibft2RequestFactory; import org.hyperledger.besu.tests.acceptance.dsl.transaction.login.LoginRequestFactory; import org.hyperledger.besu.tests.acceptance.dsl.transaction.miner.MinerRequestFactory; import org.hyperledger.besu.tests.acceptance.dsl.transaction.net.CustomRequestFactory; @@ -62,10 +67,11 @@ import com.google.common.base.MoreObjects; import com.google.common.io.MoreFiles; import com.google.common.io.RecursiveDeleteOption; -import org.apache.logging.log4j.Logger; import org.awaitility.Awaitility; import org.awaitility.core.ConditionTimeoutException; import org.java_websocket.exceptions.WebsocketNotConnectedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.web3j.protocol.Web3jService; import org.web3j.protocol.core.JsonRpc2_0Web3j; import org.web3j.protocol.http.HttpService; @@ -77,25 +83,33 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable { private static final String LOCALHOST = "127.0.0.1"; - private static final Logger LOG = getLogger(); + private static final Logger LOG = LoggerFactory.getLogger(BesuNode.class); + public static final String HTTP = "http://"; + public static final String WS_RPC = "ws-rpc"; + public static final String JSON_RPC = "json-rpc"; private final Path homeDirectory; - private final KeyPair keyPair; + private KeyPair keyPair; private final Properties portsProperties = new Properties(); private final Boolean p2pEnabled; + private final int p2pPort; + private final Optional tlsConfiguration; private final NetworkingConfiguration networkingConfiguration; private final boolean revertReasonEnabled; private final String name; - private final MiningParameters miningParameters; + private MiningParameters miningParameters; private final List runCommand; private PrivacyParameters privacyParameters = PrivacyParameters.DEFAULT; private final JsonRpcConfiguration jsonRpcConfiguration; + private final Optional engineRpcConfiguration; private final WebSocketConfiguration webSocketConfiguration; + private final JsonRpcIpcConfiguration jsonRpcIpcConfiguration; private final MetricsConfiguration metricsConfiguration; private Optional permissioningConfiguration; private final GenesisConfigurationProvider genesisConfigProvider; private final boolean devMode; + private final NetworkName network; private final boolean discoveryEnabled; private final List bootnodes = new ArrayList<>(); private final boolean bootnodeEligible; @@ -111,19 +125,27 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable private final List staticNodes; private boolean isDnsEnabled = false; private Optional exitCode = Optional.empty(); + private Optional pkiKeyStoreConfiguration = Optional.empty(); + private final boolean isStrictTxReplayProtectionEnabled; + private final Map environment; public BesuNode( final String name, final Optional dataPath, final MiningParameters miningParameters, final JsonRpcConfiguration jsonRpcConfiguration, + final Optional engineRpcConfiguration, final WebSocketConfiguration webSocketConfiguration, + final JsonRpcIpcConfiguration jsonRpcIpcConfiguration, final MetricsConfiguration metricsConfiguration, final Optional permissioningConfiguration, final Optional keyfilePath, final boolean devMode, + final NetworkName network, final GenesisConfigurationProvider genesisConfigProvider, final boolean p2pEnabled, + final int p2pPort, + final Optional tlsConfiguration, final NetworkingConfiguration networkingConfiguration, final boolean discoveryEnabled, final boolean bootnodeEligible, @@ -135,9 +157,14 @@ public BesuNode( final List staticNodes, final boolean isDnsEnabled, final Optional privacyParameters, - final List runCommand) + final List runCommand, + final Optional keyPair, + final Optional pkiKeyStoreConfiguration, + final boolean isStrictTxReplayProtectionEnabled, + final Map environment) throws IOException { this.homeDirectory = dataPath.orElseGet(BesuNode::createTmpDataDirectory); + this.isStrictTxReplayProtectionEnabled = isStrictTxReplayProtectionEnabled; keyfilePath.ifPresent( path -> { try { @@ -146,16 +173,26 @@ public BesuNode( LOG.error("Could not find key file \"{}\" in resources", path); } }); - this.keyPair = KeyPairUtil.loadKeyPair(homeDirectory); + keyPair.ifPresentOrElse( + existingKeyPair -> { + this.keyPair = existingKeyPair; + KeyPairUtil.storeKeyFile(existingKeyPair, homeDirectory); + }, + () -> this.keyPair = KeyPairUtil.loadKeyPair(homeDirectory)); this.name = name; this.miningParameters = miningParameters; this.jsonRpcConfiguration = jsonRpcConfiguration; + this.engineRpcConfiguration = engineRpcConfiguration; this.webSocketConfiguration = webSocketConfiguration; + this.jsonRpcIpcConfiguration = jsonRpcIpcConfiguration; this.metricsConfiguration = metricsConfiguration; this.permissioningConfiguration = permissioningConfiguration; this.genesisConfigProvider = genesisConfigProvider; this.devMode = devMode; + this.network = network; this.p2pEnabled = p2pEnabled; + this.p2pPort = p2pPort; + this.tlsConfiguration = tlsConfiguration; this.networkingConfiguration = networkingConfiguration; this.discoveryEnabled = discoveryEnabled; this.bootnodeEligible = bootnodeEligible; @@ -174,11 +211,15 @@ public BesuNode( LOG.error("Could not find plugin \"{}\" in resources", pluginName); } }); + engineRpcConfiguration.ifPresent( + config -> MergeConfigOptions.setMergeEnabled(config.isEnabled())); this.extraCLIOptions = extraCLIOptions; this.staticNodes = staticNodes; this.isDnsEnabled = isDnsEnabled; privacyParameters.ifPresent(this::setPrivacyParameters); - LOG.info("Created BesuNode {}", this.toString()); + this.pkiKeyStoreConfiguration = pkiKeyStoreConfiguration; + this.environment = environment; + LOG.info("Created BesuNode {}", this); } private static Path createTmpDataDirectory() { @@ -194,10 +235,25 @@ public boolean isJsonRpcEnabled() { return jsonRpcConfiguration().isEnabled(); } + @Override + public boolean isEngineRpcEnabled() { + return engineRpcConfiguration.isPresent() && engineRpcConfiguration.get().isEnabled(); + } + + public boolean isEngineAuthDisabled() { + return engineRpcConfiguration + .map(engineConf -> !engineConf.isAuthenticationEnabled()) + .orElse(false); + } + private boolean isWebSocketsRpcEnabled() { return webSocketConfiguration().isEnabled(); } + public boolean isJsonRpcIpcEnabled() { + return jsonRpcIpcConfiguration().isEnabled(); + } + boolean isMetricsEnabled() { return metricsConfiguration.isEnabled(); } @@ -220,10 +276,15 @@ public Optional exitCode() { @Override public URI enodeUrl() { final String discport = isDiscoveryEnabled() ? "?discport=" + getDiscoveryPort() : ""; - return URI.create("enode://" + getNodeId() + "@" + LOCALHOST + ":" + getP2pPort() + discport); + return URI.create( + "enode://" + getNodeId() + "@" + LOCALHOST + ":" + getRuntimeP2pPort() + discport); } - private String getP2pPort() { + public String getP2pPort() { + return String.valueOf(p2pPort); + } + + private String getRuntimeP2pPort() { final String port = portsProperties.getProperty("p2p"); if (port == null) { throw new IllegalStateException("Requested p2p port before ports properties was written"); @@ -240,13 +301,23 @@ private String getDiscoveryPort() { return port; } - private Optional jsonRpcBaseUrl() { + public Optional jsonRpcBaseUrl() { if (isJsonRpcEnabled()) { return Optional.of( - "http://" - + jsonRpcConfiguration.getHost() - + ":" - + portsProperties.getProperty("json-rpc")); + HTTP + jsonRpcConfiguration.getHost() + ":" + portsProperties.getProperty(JSON_RPC)); + } else { + return Optional.empty(); + } + } + + public Optional engineRpcUrl() { + if (isEngineRpcEnabled()) { + final Optional maybeEngineRpcPort = getEngineJsonRpcPort(); + if (maybeEngineRpcPort.isEmpty()) { + return Optional.empty(); + } + return Optional.of( + HTTP + engineRpcConfiguration.get().getHost() + ":" + maybeEngineRpcPort.get()); } else { return Optional.empty(); } @@ -255,7 +326,7 @@ private Optional jsonRpcBaseUrl() { private Optional wsRpcBaseUrl() { if (isWebSocketsRpcEnabled()) { return Optional.of( - "ws://" + webSocketConfiguration.getHost() + ":" + portsProperties.getProperty("ws-rpc")); + "ws://" + webSocketConfiguration.getHost() + ":" + portsProperties.getProperty(WS_RPC)); } else { return Optional.empty(); } @@ -264,10 +335,7 @@ private Optional wsRpcBaseUrl() { private Optional wsRpcBaseHttpUrl() { if (isWebSocketsRpcEnabled()) { return Optional.of( - "http://" - + webSocketConfiguration.getHost() - + ":" - + portsProperties.getProperty("ws-rpc")); + HTTP + webSocketConfiguration.getHost() + ":" + portsProperties.getProperty(WS_RPC)); } else { return Optional.empty(); } @@ -276,7 +344,7 @@ private Optional wsRpcBaseHttpUrl() { public Optional metricsHttpUrl() { if (isMetricsEnabled()) { return Optional.of( - "http://" + HTTP + metricsConfiguration.getHost() + ":" + portsProperties.getProperty("metrics") @@ -289,15 +357,25 @@ public Optional metricsHttpUrl() { @Override public Optional getJsonRpcWebSocketPort() { if (isWebSocketsRpcEnabled()) { - return Optional.of(Integer.valueOf(portsProperties.getProperty("ws-rpc"))); + return Optional.of(Integer.valueOf(portsProperties.getProperty(WS_RPC))); } else { return Optional.empty(); } } - public Optional getJsonRpcSocketPort() { - if (isWebSocketsRpcEnabled()) { - return Optional.of(Integer.valueOf(portsProperties.getProperty("json-rpc"))); + @Override + public Optional getJsonRpcPort() { + if (isJsonRpcEnabled()) { + return Optional.of(Integer.valueOf(portsProperties.getProperty(JSON_RPC))); + } else { + return Optional.empty(); + } + } + + @Override + public Optional getEngineJsonRpcPort() { + if (isEngineRpcEnabled()) { + return Optional.of(Integer.valueOf(portsProperties.getProperty("engine-json-rpc"))); } else { return Optional.empty(); } @@ -308,7 +386,7 @@ public String getHostName() { return LOCALHOST; } - private NodeRequests nodeRequests() { + public NodeRequests nodeRequests() { Optional websocketService = Optional.empty(); if (nodeRequests == null) { final Web3jService web3jService; @@ -330,20 +408,25 @@ private NodeRequests nodeRequests() { websocketService = Optional.of((WebSocketService) web3jService); } else { - web3jService = - jsonRpcBaseUrl() - .map(HttpService::new) - .orElse(new HttpService("http://" + LOCALHOST + ":" + 8545)); + final String url = jsonRpcBaseUrl().orElse(HTTP + LOCALHOST + ":" + 8545); + web3jService = new HttpService(url); if (token != null) { ((HttpService) web3jService).addHeader("Authorization", "Bearer " + token); } } + final ConsensusType bftType = + getGenesisConfig() + .map( + gc -> + gc.toLowerCase().contains("ibft") ? ConsensusType.IBFT2 : ConsensusType.QBFT) + .orElse(ConsensusType.IBFT2); + nodeRequests = new NodeRequests( new JsonRpc2_0Web3j(web3jService, 2000, Async.defaultExecutorService()), new CliqueRequestFactory(web3jService), - new Ibft2RequestFactory(web3jService), + new BftRequestFactory(web3jService, bftType), new PermissioningJsonRpcRequestFactory(web3jService), new AdminRequestFactory(web3jService), new PrivacyRequestFactory(web3jService), @@ -368,8 +451,7 @@ private LoginRequestFactory loginRequestFactory() { baseUrl = jsonRpcBaseUrl(); port = "8545"; } - loginRequestFactory = - new LoginRequestFactory(baseUrl.orElse("http://" + LOCALHOST + ":" + port)); + loginRequestFactory = new LoginRequestFactory(baseUrl.orElse(HTTP + LOCALHOST + ":" + port)); } return loginRequestFactory; } @@ -490,6 +572,10 @@ JsonRpcConfiguration jsonRpcConfiguration() { return jsonRpcConfiguration; } + Optional engineRpcConfiguration() { + return engineRpcConfiguration; + } + Optional jsonRpcListenHost() { if (isJsonRpcEnabled()) { return Optional.of(jsonRpcConfiguration().getHost()); @@ -506,6 +592,14 @@ Optional jsonRpcListenPort() { } } + Optional jsonEngineListenPort() { + if (isEngineRpcEnabled()) { + return Optional.of(engineRpcConfiguration.get().getPort()); + } else { + return Optional.empty(); + } + } + boolean wsRpcEnabled() { return isWebSocketsRpcEnabled(); } @@ -514,6 +608,10 @@ WebSocketConfiguration webSocketConfiguration() { return webSocketConfiguration; } + JsonRpcIpcConfiguration jsonRpcIpcConfiguration() { + return jsonRpcIpcConfiguration; + } + Optional wsRpcListenHost() { return Optional.of(webSocketConfiguration().getHost()); } @@ -540,6 +638,10 @@ public boolean isP2pEnabled() { return p2pEnabled; } + public Optional getTLSConfiguration() { + return tlsConfiguration; + } + public NetworkingConfiguration getNetworkingConfiguration() { return networkingConfiguration; } @@ -559,6 +661,10 @@ MiningParameters getMiningParameters() { return miningParameters; } + public void setMiningParameters(final MiningParameters miningParameters) { + this.miningParameters = miningParameters; + } + public PrivacyParameters getPrivacyParameters() { return privacyParameters; } @@ -571,6 +677,10 @@ public boolean isDevMode() { return devMode; } + public NetworkName getNetwork() { + return network; + } + public boolean isSecp256k1Native() { return secp256k1Native; } @@ -624,6 +734,14 @@ public List getRunCommand() { return runCommand; } + public Optional getPkiKeyStoreConfiguration() { + return pkiKeyStoreConfiguration; + } + + public boolean isStrictTxReplayProtectionEnabled() { + return isStrictTxReplayProtectionEnabled; + } + @Override public String toString() { return MoreObjects.toStringHelper(this) @@ -683,4 +801,9 @@ public void verify(final Condition expected) { public void setExitCode(final int exitValue) { this.exitCode = Optional.of(exitValue); } + + @Override + public Map getEnvironment() { + return environment; + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNodeRunner.java index 89512ddbdb9..fa74644ccbc 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNodeRunner.java @@ -26,13 +26,17 @@ public interface BesuNodeRunner { static BesuNodeRunner instance() { - if (Boolean.getBoolean("acctests.runBesuAsProcess")) { + if (isProcessBesuNodeRunner()) { return new ProcessBesuNodeRunner(); } else { return new ThreadBesuNodeRunner(); } } + static boolean isProcessBesuNodeRunner() { + return Boolean.getBoolean("acctests.runBesuAsProcess"); + } + void startNode(BesuNode node); void stopNode(BesuNode node); diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java index 917a44ab4f9..048e40553ba 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java @@ -18,8 +18,8 @@ import static java.nio.charset.StandardCharsets.UTF_8; import org.hyperledger.besu.cli.options.unstable.NetworkingOptions; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; +import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration; +import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.plugin.services.metrics.MetricCategory; @@ -47,15 +47,15 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.ThreadContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; public class ProcessBesuNodeRunner implements BesuNodeRunner { - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LoggerFactory.getLogger(ProcessBesuNodeRunner.class); private static final Logger PROCESS_LOG = - LogManager.getLogger("org.hyperledger.besu.SubProcessLog"); + LoggerFactory.getLogger("org.hyperledger.besu.SubProcessLog"); private final Map besuProcesses = new HashMap<>(); private final ExecutorService outputProcessorExecutor = Executors.newCachedThreadPool(); @@ -81,6 +81,9 @@ public void startNode(final BesuNode node) { if (node.isDevMode()) { params.add("--network"); params.add("DEV"); + } else if (node.getNetwork() != null) { + params.add("--network"); + params.add(node.getNetwork().name()); } params.add("--sync-mode"); @@ -93,7 +96,7 @@ public void startNode(final BesuNode node) { params.add(node.p2pListenHost()); params.add("--p2p-port"); - params.add("0"); + params.add(node.getP2pPort()); if (node.getMiningParameters().isMiningEnabled()) { params.add("--miner-enabled"); @@ -117,25 +120,33 @@ public void startNode(final BesuNode node) { if (node.getPrivacyParameters().isEnabled()) { params.add("--privacy-enabled"); + params.add("--privacy-url"); params.add(node.getPrivacyParameters().getEnclaveUri().toString()); + if (node.getPrivacyParameters().isMultiTenancyEnabled()) { params.add("--privacy-multi-tenancy-enabled"); } else { params.add("--privacy-public-key-file"); params.add(node.getPrivacyParameters().getEnclavePublicKeyFile().getAbsolutePath()); } - params.add("--privacy-marker-transaction-signing-key-file"); - params.add(node.homeDirectory().resolve("key").toString()); - if (node.getPrivacyParameters().isOnchainPrivacyGroupsEnabled()) { - params.add("--privacy-onchain-groups-enabled"); + if (!node.getExtraCLIOptions().contains("--plugin-privacy-service-signing-enabled=true")) { + params.add("--privacy-marker-transaction-signing-key-file"); + params.add(node.homeDirectory().resolve("key").toString()); + } + + if (node.getPrivacyParameters().isFlexiblePrivacyGroupsEnabled()) { + params.add("--privacy-flexible-groups-enabled"); } - } - params.add("--bootnodes"); + if (node.getPrivacyParameters().isPrivacyPluginEnabled()) { + params.add("--Xprivacy-plugin-enabled"); + } + } if (!node.getBootnodes().isEmpty()) { + params.add("--bootnodes"); params.add(node.getBootnodes().stream().map(URI::toString).collect(Collectors.joining(","))); } @@ -158,6 +169,10 @@ public void startNode(final BesuNode node) { params.add(node.jsonRpcListenPort().map(Object::toString).get()); params.add("--rpc-http-api"); params.add(apiList(node.jsonRpcConfiguration().getRpcApis())); + if (!node.jsonRpcConfiguration().getNoAuthRpcApis().isEmpty()) { + params.add("--rpc-http-api-methods-no-auth"); + params.add(apiList(node.jsonRpcConfiguration().getNoAuthRpcApis())); + } if (node.jsonRpcConfiguration().isAuthenticationEnabled()) { params.add("--rpc-http-authentication-enabled"); } @@ -169,6 +184,19 @@ public void startNode(final BesuNode node) { params.add("--rpc-http-authentication-jwt-public-key-file"); params.add(node.jsonRpcConfiguration().getAuthenticationPublicKeyFile().getAbsolutePath()); } + if (node.jsonRpcConfiguration().getAuthenticationAlgorithm() != null) { + params.add("--rpc-http-authentication-jwt-algorithm"); + params.add(node.jsonRpcConfiguration().getAuthenticationAlgorithm().toString()); + } + } + + if (node.isEngineRpcEnabled()) { + params.add("--engine-rpc-port"); + params.add(node.jsonEngineListenPort().get().toString()); + + if (node.isEngineAuthDisabled()) { + params.add("--engine-jwt-disabled"); + } } if (node.wsRpcEnabled()) { @@ -179,6 +207,10 @@ public void startNode(final BesuNode node) { params.add(node.wsRpcListenPort().map(Object::toString).get()); params.add("--rpc-ws-api"); params.add(apiList(node.webSocketConfiguration().getRpcApis())); + if (!node.webSocketConfiguration().getRpcApisNoAuth().isEmpty()) { + params.add("--rpc-ws-api-methods-no-auth"); + params.add(apiList(node.webSocketConfiguration().getRpcApisNoAuth())); + } if (node.webSocketConfiguration().isAuthenticationEnabled()) { params.add("--rpc-ws-authentication-enabled"); } @@ -191,6 +223,19 @@ public void startNode(final BesuNode node) { params.add( node.webSocketConfiguration().getAuthenticationPublicKeyFile().getAbsolutePath()); } + if (node.webSocketConfiguration().getAuthenticationAlgorithm() != null) { + params.add("--rpc-ws-authentication-jwt-algorithm"); + params.add(node.webSocketConfiguration().getAuthenticationAlgorithm().toString()); + } + } + + if (node.isJsonRpcIpcEnabled()) { + final JsonRpcIpcConfiguration ipcConfiguration = node.jsonRpcIpcConfiguration(); + params.add("--Xrpc-ipc-enabled"); + params.add("--Xrpc-ipc-path"); + params.add(ipcConfiguration.getPath().toString()); + params.add("--Xrpc-ipc-apis"); + params.add(String.join(",", ipcConfiguration.getEnabledApis())); } if (node.isMetricsEnabled()) { @@ -204,6 +249,10 @@ public void startNode(final BesuNode node) { params.add("--metrics-category"); params.add(((Enum) category).name()); } + if (node.isMetricsEnabled() || metricsConfiguration.isPushEnabled()) { + params.add("--metrics-protocol"); + params.add(metricsConfiguration.getProtocol().name()); + } if (metricsConfiguration.isPushEnabled()) { params.add("--metrics-push-enabled"); params.add("--metrics-push-host"); @@ -232,6 +281,26 @@ public void startNode(final BesuNode node) { final List networkConfigParams = NetworkingOptions.fromConfig(node.getNetworkingConfiguration()).getCLIOptions(); params.addAll(networkConfigParams); + if (node.getTLSConfiguration().isPresent()) { + final TLSConfiguration config = node.getTLSConfiguration().get(); + params.add("--Xp2p-tls-enabled"); + params.add("--Xp2p-tls-keystore-type"); + params.add(config.getKeyStoreType()); + params.add("--Xp2p-tls-keystore-file"); + params.add(config.getKeyStorePath().toAbsolutePath().toString()); + params.add("--Xp2p-tls-keystore-password-file"); + params.add(config.getKeyStorePasswordPath().toAbsolutePath().toString()); + params.add("--Xp2p-tls-crl-file"); + params.add(config.getCrlPath().toAbsolutePath().toString()); + if (null != config.getTrustStoreType()) { + params.add("--Xp2p-tls-truststore-type"); + params.add(config.getTrustStoreType()); + params.add("--Xp2p-tls-truststore-file"); + params.add(config.getTrustStorePath().toAbsolutePath().toString()); + params.add("--Xp2p-tls-truststore-password-file"); + params.add(config.getTrustStorePasswordPath().toAbsolutePath().toString()); + } + } } if (node.isRevertReasonEnabled()) { @@ -284,6 +353,34 @@ public void startNode(final BesuNode node) { String.valueOf( permissioningConfiguration.getNodeSmartContractInterfaceVersion())); }); + + node.getPkiKeyStoreConfiguration() + .ifPresent( + pkiConfig -> { + params.add("--Xpki-block-creation-enabled"); + + params.add("--Xpki-block-creation-keystore-certificate-alias"); + params.add(pkiConfig.getCertificateAlias()); + + params.add("--Xpki-block-creation-keystore-type"); + params.add(pkiConfig.getKeyStoreType()); + + params.add("--Xpki-block-creation-keystore-file"); + params.add(pkiConfig.getKeyStorePath().toAbsolutePath().toString()); + + params.add("--Xpki-block-creation-keystore-password-file"); + params.add(pkiConfig.getKeyStorePasswordPath().toAbsolutePath().toString()); + + params.add("--Xpki-block-creation-truststore-type"); + params.add(pkiConfig.getTrustStoreType()); + + params.add("--Xpki-block-creation-truststore-file"); + params.add(pkiConfig.getTrustStorePath().toAbsolutePath().toString()); + + params.add("--Xpki-block-creation-truststore-password-file"); + params.add(pkiConfig.getTrustStorePasswordPath().toAbsolutePath().toString()); + }); + params.addAll(node.getExtraCLIOptions()); params.add("--key-value-storage"); @@ -292,6 +389,9 @@ public void startNode(final BesuNode node) { params.add("--auto-log-bloom-caching-enabled"); params.add("false"); + params.add("--strict-tx-replay-protection-enabled"); + params.add(Boolean.toString(node.isStrictTxReplayProtectionEnabled())); + final String level = System.getProperty("root.log.level"); if (level != null) { params.add("--logging=" + level); @@ -319,6 +419,26 @@ public void startNode(final BesuNode node) { "JAVA_OPTS", "-Djava.security.properties=" + "acceptance-tests/tests/build/resources/test/acceptanceTesting.security"); + // add additional environment variables + processBuilder.environment().putAll(node.getEnvironment()); + + try { + int debugPort = Integer.parseInt(System.getenv("BESU_DEBUG_CHILD_PROCESS_PORT")); + LOG.warn("Waiting for debugger to attach to SUSPENDED child process"); + String debugOpts = + " -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:" + debugPort; + String prevJavaOpts = processBuilder.environment().get("JAVA_OPTS"); + if (prevJavaOpts == null) { + processBuilder.environment().put("JAVA_OPTS", debugOpts); + } else { + processBuilder.environment().put("JAVA_OPTS", prevJavaOpts + debugOpts); + } + + } catch (NumberFormatException e) { + LOG.debug( + "Child process may be attached to by exporting BESU_DEBUG_CHILD_PROCESS_PORT= to env"); + } + try { checkState( isNotAliveOrphan(node.getName()), @@ -337,7 +457,7 @@ public void startNode(final BesuNode node) { waitForFile(dataDir, "besu.ports"); waitForFile(dataDir, "besu.networks"); } - ThreadContext.remove("node"); + MDC.remove("node"); } private boolean isNotAliveOrphan(final String name) { @@ -349,7 +469,7 @@ private void printOutput(final BesuNode node, final Process process) { try (final BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream(), UTF_8))) { - ThreadContext.put("node", node.getName()); + MDC.put("node", node.getName()); String line = in.readLine(); while (line != null) { @@ -384,8 +504,8 @@ private void createStaticNodes(final BesuNode node) { StaticNodesUtils.createStaticNodesFile(node.homeDirectory(), node.getStaticNodes()); } - private String apiList(final Collection rpcApis) { - return rpcApis.stream().map(RpcApis::getValue).collect(Collectors.joining(",")); + private String apiList(final Collection rpcApis) { + return String.join(",", rpcApis); } @Override @@ -422,7 +542,7 @@ public boolean isActive(final String nodeName) { private void killBesuProcess(final String name) { final Process process = besuProcesses.remove(name); if (process == null) { - LOG.error("Process {} wasn't in our list, pid {}", name, process.pid()); + LOG.error("Process {} wasn't in our list", name); return; } if (!process.isAlive()) { diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/RunnableNode.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/RunnableNode.java index 3586dd8eea6..f729cf8b1f3 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/RunnableNode.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/RunnableNode.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.node; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.NodeConfiguration; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java index 7c68e12e5a0..29ce00b175f 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java @@ -14,73 +14,76 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.node; -import static org.hyperledger.besu.cli.config.NetworkName.DEV; import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH; import org.hyperledger.besu.Runner; import org.hyperledger.besu.RunnerBuilder; import org.hyperledger.besu.cli.config.EthNetworkConfig; +import org.hyperledger.besu.cli.config.NetworkName; +import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.consensus.qbft.pki.PkiBlockCreationConfigurationProvider; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.controller.BesuControllerBuilder; -import org.hyperledger.besu.crypto.KeyPairSecurityModule; import org.hyperledger.besu.crypto.KeyPairUtil; -import org.hyperledger.besu.crypto.NodeKey; +import org.hyperledger.besu.cryptoservices.KeyPairSecurityModule; +import org.hyperledger.besu.cryptoservices.NodeKey; +import org.hyperledger.besu.ethereum.GasLimitCalculator; import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration; -import org.hyperledger.besu.ethereum.blockcreation.GasLimitCalculator; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; +import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; -import org.hyperledger.besu.ethereum.p2p.peers.EnodeURL; -import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder; +import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.metrics.MetricsSystemFactory; import org.hyperledger.besu.metrics.ObservableMetricsSystem; +import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.plugin.services.BesuConfiguration; import org.hyperledger.besu.plugin.services.BesuEvents; import org.hyperledger.besu.plugin.services.PicoCLIOptions; import org.hyperledger.besu.plugin.services.SecurityModuleService; import org.hyperledger.besu.plugin.services.StorageService; +import org.hyperledger.besu.plugin.services.TransactionSelectionService; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin; +import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory; import org.hyperledger.besu.services.BesuConfigurationImpl; import org.hyperledger.besu.services.BesuEventsImpl; import org.hyperledger.besu.services.BesuPluginContextImpl; +import org.hyperledger.besu.services.PermissioningServiceImpl; import org.hyperledger.besu.services.PicoCLIOptionsImpl; +import org.hyperledger.besu.services.RpcEndpointServiceImpl; import org.hyperledger.besu.services.SecurityModuleServiceImpl; import org.hyperledger.besu.services.StorageServiceImpl; +import org.hyperledger.besu.services.TransactionSelectionServiceImpl; -import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.time.Clock; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; -import javax.annotation.Nonnull; +import io.opentelemetry.api.GlobalOpenTelemetry; import io.vertx.core.Vertx; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.ThreadContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; import picocli.CommandLine; import picocli.CommandLine.Model.CommandSpec; public class ThreadBesuNodeRunner implements BesuNodeRunner { - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LoggerFactory.getLogger(ThreadBesuNodeRunner.class); private final Map besuRunners = new HashMap<>(); private final Map besuPluginContextMap = new ConcurrentHashMap<>(); - private final PrintStream originalOut = System.out; - private final PrintStream originalErr = System.err; - private final ByteArrayOutputStream consoleContents = new ByteArrayOutputStream(); private BesuPluginContextImpl buildPluginContext( final BesuNode node, @@ -92,14 +95,22 @@ private BesuPluginContextImpl buildPluginContext( besuPluginContext.addService(StorageService.class, storageService); besuPluginContext.addService(SecurityModuleService.class, securityModuleService); besuPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine)); - - final Path pluginsPath = node.homeDirectory().resolve("plugins"); - final File pluginsDirFile = pluginsPath.toFile(); - if (!pluginsDirFile.isDirectory()) { - pluginsDirFile.mkdirs(); - pluginsDirFile.deleteOnExit(); + besuPluginContext.addService( + TransactionSelectionService.class, new TransactionSelectionServiceImpl()); + + final Path pluginsPath; + final String pluginDir = System.getProperty("besu.plugins.dir"); + if (pluginDir == null || pluginDir.isEmpty()) { + pluginsPath = node.homeDirectory().resolve("plugins"); + final File pluginsDirFile = pluginsPath.toFile(); + if (!pluginsDirFile.isDirectory()) { + pluginsDirFile.mkdirs(); + pluginsDirFile.deleteOnExit(); + } + System.setProperty("besu.plugins.dir", pluginsPath.toString()); + } else { + pluginsPath = Path.of(pluginDir); } - System.setProperty("besu.plugins.dir", pluginsPath.toString()); besuPluginContext.registerPlugins(pluginsPath); commandLine.parseArgs(node.getConfiguration().getExtraCLIOptions().toArray(new String[0])); @@ -115,10 +126,10 @@ private BesuPluginContextImpl buildPluginContext( @Override public void startNode(final BesuNode node) { - if (ThreadContext.containsKey("node")) { - LOG.error("ThreadContext node is already set to {}", ThreadContext.get("node")); + if (MDC.get("node") != null) { + LOG.error("ThreadContext node is already set to {}", MDC.get("node")); } - ThreadContext.put("node", node.getName()); + MDC.put("node", node.getName()); if (!node.getRunCommand().isEmpty()) { throw new UnsupportedOperationException("commands are not supported with thread runner"); @@ -136,19 +147,25 @@ public void startNode(final BesuNode node) { buildPluginContext( node, storageService, securityModuleService, commonPluginConfiguration)); + GlobalOpenTelemetry.resetForTest(); final ObservableMetricsSystem metricsSystem = MetricsSystemFactory.create(node.getMetricsConfiguration()); final List bootnodes = node.getConfiguration().getBootnodes().stream() - .map(EnodeURL::fromURI) + .map(EnodeURLImpl::fromURI) .collect(Collectors.toList()); + final NetworkName network = node.getNetwork() == null ? NetworkName.DEV : node.getNetwork(); final EthNetworkConfig.Builder networkConfigBuilder = - new EthNetworkConfig.Builder(EthNetworkConfig.getNetworkConfig(DEV)) + new EthNetworkConfig.Builder(EthNetworkConfig.getNetworkConfig(network)) .setBootNodes(bootnodes); node.getConfiguration().getGenesisConfig().ifPresent(networkConfigBuilder::setGenesisConfig); final EthNetworkConfig ethNetworkConfig = networkConfigBuilder.build(); + final SynchronizerConfiguration synchronizerConfiguration = + new SynchronizerConfiguration.Builder().build(); final BesuControllerBuilder builder = - new BesuController.Builder().fromEthNetworkConfig(ethNetworkConfig); + new BesuController.Builder() + .fromEthNetworkConfig( + ethNetworkConfig, Collections.emptyMap(), synchronizerConfiguration.getSyncMode()); final KeyValueStorageProvider storageProvider = new KeyValueStorageProviderBuilder() @@ -157,29 +174,82 @@ public void startNode(final BesuNode node) { .withMetricsSystem(metricsSystem) .build(); - final BesuController besuController = - builder - .synchronizerConfiguration(new SynchronizerConfiguration.Builder().build()) - .dataDirectory(node.homeDirectory()) - .miningParameters(node.getMiningParameters()) - .privacyParameters(node.getPrivacyParameters()) - .nodeKey(new NodeKey(new KeyPairSecurityModule(KeyPairUtil.loadKeyPair(dataDir)))) - .metricsSystem(metricsSystem) - .transactionPoolConfiguration(TransactionPoolConfiguration.DEFAULT) - .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) - .clock(Clock.systemUTC()) - .isRevertReasonEnabled(node.isRevertReasonEnabled()) - .storageProvider(storageProvider) - .gasLimitCalculator(GasLimitCalculator.constant()) + final TransactionPoolConfiguration txPoolConfig = + ImmutableTransactionPoolConfiguration.builder() + .strictTransactionReplayProtectionEnabled(node.isStrictTxReplayProtectionEnabled()) .build(); - final RunnerBuilder runnerBuilder = new RunnerBuilder(); - if (node.getPermissioningConfiguration().isPresent()) { - final PermissioningConfiguration permissioningConfiguration = - node.getPermissioningConfiguration().get(); + final int maxPeers = 25; + + final Optional transactionSelectorFactory = + getTransactionSelectorFactory(besuPluginContext); + + builder + .synchronizerConfiguration(new SynchronizerConfiguration.Builder().build()) + .dataDirectory(node.homeDirectory()) + .miningParameters(node.getMiningParameters()) + .privacyParameters(node.getPrivacyParameters()) + .nodeKey(new NodeKey(new KeyPairSecurityModule(KeyPairUtil.loadKeyPair(dataDir)))) + .metricsSystem(metricsSystem) + .transactionPoolConfiguration(txPoolConfig) + .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .clock(Clock.systemUTC()) + .isRevertReasonEnabled(node.isRevertReasonEnabled()) + .storageProvider(storageProvider) + .gasLimitCalculator(GasLimitCalculator.constant()) + .pkiBlockCreationConfiguration( + node.getPkiKeyStoreConfiguration() + .map(pkiConfig -> new PkiBlockCreationConfigurationProvider().load(pkiConfig))) + .evmConfiguration(EvmConfiguration.DEFAULT) + .maxPeers(maxPeers) + .lowerBoundPeers(maxPeers) + .maxRemotelyInitiatedPeers(15) + .networkConfiguration(node.getNetworkingConfiguration()) + .randomPeerPriority(false) + .transactionSelectorFactory(transactionSelectorFactory); + + node.getGenesisConfig() + .map(GenesisConfigFile::fromConfig) + .ifPresent(builder::genesisConfigFile); + + final BesuController besuController = builder.build(); - runnerBuilder.permissioningConfiguration(permissioningConfiguration); - } + final RunnerBuilder runnerBuilder = new RunnerBuilder(); + runnerBuilder.permissioningConfiguration(node.getPermissioningConfiguration()); + + runnerBuilder + .vertx(Vertx.vertx()) + .besuController(besuController) + .ethNetworkConfig(ethNetworkConfig) + .discovery(node.isDiscoveryEnabled()) + .p2pAdvertisedHost(node.getHostName()) + .p2pListenPort(0) + .networkingConfiguration(node.getNetworkingConfiguration()) + .jsonRpcConfiguration(node.jsonRpcConfiguration()) + .webSocketConfiguration(node.webSocketConfiguration()) + .jsonRpcIpcConfiguration(node.jsonRpcIpcConfiguration()) + .dataDir(node.homeDirectory()) + .metricsSystem(metricsSystem) + .permissioningService(new PermissioningServiceImpl()) + .metricsConfiguration(node.getMetricsConfiguration()) + .p2pEnabled(node.isP2pEnabled()) + .p2pTLSConfiguration(node.getTLSConfiguration()) + .graphQLConfiguration(GraphQLConfiguration.createDefault()) + .staticNodes( + node.getStaticNodes().stream() + .map(EnodeURLImpl::fromString) + .collect(Collectors.toList())) + .besuPluginContext(new BesuPluginContextImpl()) + .autoLogBloomCaching(false) + .storageProvider(storageProvider) + .rpcEndpointService(new RpcEndpointServiceImpl()); + node.engineRpcConfiguration().ifPresent(runnerBuilder::engineJsonRpcConfiguration); + + final Runner runner = runnerBuilder.build(); + + besuPluginContext.beforeExternalServices(); + + runner.startExternalServices(); besuPluginContext.addService( BesuEvents.class, @@ -190,37 +260,10 @@ public void startNode(final BesuNode node) { besuController.getSyncState())); besuPluginContext.startPlugins(); - final Runner runner = - runnerBuilder - .vertx(Vertx.vertx()) - .besuController(besuController) - .ethNetworkConfig(ethNetworkConfig) - .discovery(node.isDiscoveryEnabled()) - .p2pAdvertisedHost(node.getHostName()) - .p2pListenPort(0) - .maxPeers(25) - .networkingConfiguration(node.getNetworkingConfiguration()) - .jsonRpcConfiguration(node.jsonRpcConfiguration()) - .webSocketConfiguration(node.webSocketConfiguration()) - .dataDir(node.homeDirectory()) - .metricsSystem(metricsSystem) - .metricsConfiguration(node.getMetricsConfiguration()) - .p2pEnabled(node.isP2pEnabled()) - .graphQLConfiguration(GraphQLConfiguration.createDefault()) - .staticNodes( - node.getStaticNodes().stream() - .map(EnodeURL::fromString) - .collect(Collectors.toList())) - .besuPluginContext(new BesuPluginContextImpl()) - .autoLogBloomCaching(false) - .storageProvider(storageProvider) - .build(); - - System.setOut(null); - runner.start(); + runner.startEthereumMainLoop(); besuRunners.put(node.getName(), runner); - ThreadContext.remove("node"); + MDC.remove("node"); } @Override @@ -263,44 +306,20 @@ private void killRunner(final String name) { } } - static class SplittingStream extends OutputStream { - final OutputStream one; - final OutputStream two; - - SplittingStream(final OutputStream one, final OutputStream two) { - this.one = one; - this.two = two; - } - - @Override - public void write(final int b) throws IOException { - one.write(b); - two.write(b); - } - - @Override - public void write(@Nonnull final byte[] b) throws IOException { - one.write(b); - two.write(b); - } - - @Override - public void write(@Nonnull final byte[] b, final int off, final int len) throws IOException { - one.write(b, off, len); - two.write(b, off, len); - } - } - @Override public void startConsoleCapture() { - System.setOut(new PrintStream(new SplittingStream(consoleContents, originalOut))); - System.setErr(new PrintStream(new SplittingStream(consoleContents, originalErr))); + throw new RuntimeException("Console contents can only be captured in process execution"); } @Override public String getConsoleContents() { - System.setOut(originalOut); - System.setErr(originalErr); - return consoleContents.toString(StandardCharsets.UTF_8); + throw new RuntimeException("Console contents can only be captured in process execution"); + } + + private Optional getTransactionSelectorFactory( + final BesuPluginContextImpl besuPluginContext) { + final Optional txSelectionService = + besuPluginContext.getService(TransactionSelectionService.class); + return txSelectionService.isPresent() ? txSelectionService.get().get() : Optional.empty(); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/cluster/Cluster.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/cluster/Cluster.java index ced470aaff4..16a02874262 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/cluster/Cluster.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/cluster/Cluster.java @@ -33,11 +33,11 @@ import java.util.Map; import java.util.Optional; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Cluster implements AutoCloseable { - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LoggerFactory.getLogger(Cluster.class); private final Map nodes = new HashMap<>(); private final BesuNodeRunner besuNodeRunner; @@ -85,8 +85,7 @@ public void start(final List nodes) { final Optional bootnode = selectAndStartBootnode(nodes); - nodes - .parallelStream() + nodes.parallelStream() .filter( node -> { LOG.info("starting non-bootnode {}", node.getName()); @@ -153,21 +152,27 @@ public void runNodeStart(final RunnableNode node) { private void startNode(final RunnableNode node, final boolean isBootNode) { node.getConfiguration().setBootnodes(isBootNode ? emptyList() : bootnodes); - node.getConfiguration() - .getGenesisConfigProvider() - .create(originalNodes) - .ifPresent(node.getConfiguration()::setGenesisConfig); + if (node.getConfiguration().getGenesisConfig().isEmpty()) { + node.getConfiguration() + .getGenesisConfigProvider() + .create(originalNodes) + .ifPresent(node.getConfiguration()::setGenesisConfig); + } runNodeStart(node); } public void stop() { // stops nodes but do not shutdown besuNodeRunner for (final RunnableNode node : nodes.values()) { - if (node instanceof BesuNode) { - besuNodeRunner.stopNode((BesuNode) node); // besuNodeRunner.stopNode also calls node.stop - } else { - node.stop(); - } + stopNode(node); + } + } + + public void stopNode(final RunnableNode node) { + if (node instanceof BesuNode) { + besuNodeRunner.stopNode((BesuNode) node); // besuNodeRunner.stopNode also calls node.stop + } else { + node.stop(); } } @@ -185,6 +190,9 @@ public void close() { } public void verify(final Condition expected) { + if (nodes.size() == 0) { + throw new IllegalStateException("Attempt to verify an empty cluster"); + } for (final Node node : nodes.values()) { expected.verify(node); } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java index 10646daddce..91d9e24e488 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java @@ -14,17 +14,23 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.node.configuration; +import org.hyperledger.besu.cli.config.NetworkName; +import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; +import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; +import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; +import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider; import java.nio.file.Path; import java.util.List; +import java.util.Map; import java.util.Optional; public class BesuNodeConfiguration { @@ -33,13 +39,17 @@ public class BesuNodeConfiguration { private final Optional dataPath; private final MiningParameters miningParameters; private final JsonRpcConfiguration jsonRpcConfiguration; + private final Optional engineRpcConfiguration; private final WebSocketConfiguration webSocketConfiguration; + private final JsonRpcIpcConfiguration jsonRpcIpcConfiguration; private final MetricsConfiguration metricsConfiguration; private final Optional permissioningConfiguration; private final Optional keyFilePath; private final boolean devMode; private final GenesisConfigurationProvider genesisConfigProvider; private final boolean p2pEnabled; + private final int p2pPort; + private final Optional tlsConfiguration; private final NetworkingConfiguration networkingConfiguration; private final boolean discoveryEnabled; private final boolean bootnodeEligible; @@ -52,19 +62,29 @@ public class BesuNodeConfiguration { private final boolean isDnsEnabled; private final Optional privacyParameters; private final List runCommand; + private final NetworkName network; + private final Optional keyPair; + private final Optional pkiKeyStoreConfiguration; + private final boolean strictTxReplayProtectionEnabled; + private final Map environment; BesuNodeConfiguration( final String name, final Optional dataPath, final MiningParameters miningParameters, final JsonRpcConfiguration jsonRpcConfiguration, + final Optional engineRpcConfiguration, final WebSocketConfiguration webSocketConfiguration, + final JsonRpcIpcConfiguration jsonRpcIpcConfiguration, final MetricsConfiguration metricsConfiguration, final Optional permissioningConfiguration, final Optional keyFilePath, final boolean devMode, + final NetworkName network, final GenesisConfigurationProvider genesisConfigProvider, final boolean p2pEnabled, + final int p2pPort, + final Optional tlsConfiguration, final NetworkingConfiguration networkingConfiguration, final boolean discoveryEnabled, final boolean bootnodeEligible, @@ -76,18 +96,27 @@ public class BesuNodeConfiguration { final List staticNodes, final boolean isDnsEnabled, final Optional privacyParameters, - final List runCommand) { + final List runCommand, + final Optional keyPair, + final Optional pkiKeyStoreConfiguration, + final boolean strictTxReplayProtectionEnabled, + final Map environment) { this.name = name; this.miningParameters = miningParameters; this.jsonRpcConfiguration = jsonRpcConfiguration; + this.engineRpcConfiguration = engineRpcConfiguration; this.webSocketConfiguration = webSocketConfiguration; + this.jsonRpcIpcConfiguration = jsonRpcIpcConfiguration; this.metricsConfiguration = metricsConfiguration; this.permissioningConfiguration = permissioningConfiguration; this.keyFilePath = keyFilePath; this.dataPath = dataPath; this.devMode = devMode; + this.network = network; this.genesisConfigProvider = genesisConfigProvider; this.p2pEnabled = p2pEnabled; + this.p2pPort = p2pPort; + this.tlsConfiguration = tlsConfiguration; this.networkingConfiguration = networkingConfiguration; this.discoveryEnabled = discoveryEnabled; this.bootnodeEligible = bootnodeEligible; @@ -100,6 +129,10 @@ public class BesuNodeConfiguration { this.isDnsEnabled = isDnsEnabled; this.privacyParameters = privacyParameters; this.runCommand = runCommand; + this.keyPair = keyPair; + this.pkiKeyStoreConfiguration = pkiKeyStoreConfiguration; + this.strictTxReplayProtectionEnabled = strictTxReplayProtectionEnabled; + this.environment = environment; } public String getName() { @@ -114,10 +147,18 @@ public JsonRpcConfiguration getJsonRpcConfiguration() { return jsonRpcConfiguration; } + public Optional getEngineRpcConfiguration() { + return engineRpcConfiguration; + } + public WebSocketConfiguration getWebSocketConfiguration() { return webSocketConfiguration; } + public JsonRpcIpcConfiguration getJsonRpcIpcConfiguration() { + return jsonRpcIpcConfiguration; + } + public MetricsConfiguration getMetricsConfiguration() { return metricsConfiguration; } @@ -150,6 +191,14 @@ public boolean isP2pEnabled() { return p2pEnabled; } + public int getP2pPort() { + return p2pPort; + } + + public Optional getTLSConfiguration() { + return tlsConfiguration; + } + public NetworkingConfiguration getNetworkingConfiguration() { return networkingConfiguration; } @@ -193,4 +242,24 @@ public Optional getPrivacyParameters() { public List getRunCommand() { return runCommand; } + + public NetworkName getNetwork() { + return network; + } + + public Optional getKeyPair() { + return keyPair; + } + + public Optional getPkiKeyStoreConfiguration() { + return pkiKeyStoreConfiguration; + } + + public boolean isStrictTxReplayProtectionEnabled() { + return strictTxReplayProtectionEnabled; + } + + public Map getEnvironment() { + return environment; + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java index 7dd0840e3b2..4943aaf60eb 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java @@ -16,17 +16,29 @@ import static com.google.common.base.Preconditions.checkNotNull; import static java.util.Collections.singletonList; +import static org.hyperledger.besu.pki.keystore.KeyStoreWrapper.KEYSTORE_TYPE_JKS; +import static org.hyperledger.besu.pki.keystore.KeyStoreWrapper.KEYSTORE_TYPE_PKCS11; +import static org.hyperledger.besu.pki.keystore.KeyStoreWrapper.KEYSTORE_TYPE_PKCS12; +import org.hyperledger.besu.cli.config.NetworkName; +import org.hyperledger.besu.crypto.KeyPair; +import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; +import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.JwtAlgorithm; +import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; +import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider; +import org.hyperledger.besu.ethereum.core.AddressHelpers; import org.hyperledger.besu.ethereum.core.MiningParameters; -import org.hyperledger.besu.ethereum.core.MiningParametersTestBuilder; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; +import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; +import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.pki.PKCS11Utils; import java.io.File; import java.net.URISyntaxException; @@ -34,7 +46,9 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; public class BesuNodeConfigurationBuilder { @@ -42,27 +56,40 @@ public class BesuNodeConfigurationBuilder { private String name; private Optional dataPath = Optional.empty(); private MiningParameters miningParameters = - new MiningParametersTestBuilder().enabled(false).build(); + new MiningParameters.Builder() + .miningEnabled(false) + .coinbase(AddressHelpers.ofValue(1)) + .minTransactionGasPrice(Wei.of(1000)) + .build(); private JsonRpcConfiguration jsonRpcConfiguration = JsonRpcConfiguration.createDefault(); + private JsonRpcConfiguration engineRpcConfiguration = JsonRpcConfiguration.createEngineDefault(); private WebSocketConfiguration webSocketConfiguration = WebSocketConfiguration.createDefault(); + private JsonRpcIpcConfiguration jsonRpcIpcConfiguration = new JsonRpcIpcConfiguration(); private MetricsConfiguration metricsConfiguration = MetricsConfiguration.builder().build(); private Optional permissioningConfiguration = Optional.empty(); private String keyFilePath = null; private boolean devMode = true; private GenesisConfigurationProvider genesisConfigProvider = ignore -> Optional.empty(); private Boolean p2pEnabled = true; + private int p2pPort = 0; + private Optional tlsConfiguration = Optional.empty(); private final NetworkingConfiguration networkingConfiguration = NetworkingConfiguration.create(); private boolean discoveryEnabled = true; private boolean bootnodeEligible = true; private boolean revertReasonEnabled = false; - private boolean secp256K1Native = false; - private boolean altbn128Native = false; + private NetworkName network = null; + private boolean secp256K1Native = true; + private boolean altbn128Native = true; private final List plugins = new ArrayList<>(); private final List extraCLIOptions = new ArrayList<>(); private List staticNodes = new ArrayList<>(); private boolean isDnsEnabled = false; private Optional privacyParameters = Optional.empty(); private List runCommand = new ArrayList<>(); + private Optional keyPair = Optional.empty(); + private Optional pkiKeyStoreConfiguration = Optional.empty(); + private Boolean strictTxReplayProtectionEnabled = false; + private Map environment = new HashMap<>(); public BesuNodeConfigurationBuilder() { // Check connections more frequently during acceptance tests to cut down on @@ -82,14 +109,23 @@ public BesuNodeConfigurationBuilder dataPath(final Path dataPath) { } public BesuNodeConfigurationBuilder miningEnabled() { - this.miningParameters = new MiningParametersTestBuilder().enabled(true).build(); - this.jsonRpcConfiguration.addRpcApi(RpcApis.MINER); + return miningEnabled(true); + } + + public BesuNodeConfigurationBuilder miningEnabled(final boolean enabled) { + this.miningParameters = + new MiningParameters.Builder() + .miningEnabled(enabled) + .minTransactionGasPrice(Wei.of(1000)) + .coinbase(AddressHelpers.ofValue(1)) + .build(); + this.jsonRpcConfiguration.addRpcApi(RpcApis.MINER.name()); return this; } public BesuNodeConfigurationBuilder miningConfiguration(final MiningParameters miningParameters) { this.miningParameters = miningParameters; - this.jsonRpcConfiguration.addRpcApi(RpcApis.MINER); + this.jsonRpcConfiguration.addRpcApi(RpcApis.MINER.name()); return this; } @@ -99,6 +135,12 @@ public BesuNodeConfigurationBuilder jsonRpcConfiguration( return this; } + public BesuNodeConfigurationBuilder engineJsonRpcConfiguration( + final JsonRpcConfiguration engineConfig) { + this.engineRpcConfiguration = engineConfig; + return this; + } + public BesuNodeConfigurationBuilder jsonRpcEnabled() { this.jsonRpcConfiguration.setEnabled(true); this.jsonRpcConfiguration.setPort(0); @@ -107,6 +149,15 @@ public BesuNodeConfigurationBuilder jsonRpcEnabled() { return this; } + public BesuNodeConfigurationBuilder engineRpcEnabled(final boolean enabled) { + this.engineRpcConfiguration.setEnabled(enabled); + this.engineRpcConfiguration.setPort(0); + this.engineRpcConfiguration.setHostsAllowlist(singletonList("*")); + this.engineRpcConfiguration.setAuthenticationEnabled(false); + + return this; + } + public BesuNodeConfigurationBuilder metricsEnabled() { this.metricsConfiguration = MetricsConfiguration.builder() @@ -119,13 +170,23 @@ public BesuNodeConfigurationBuilder metricsEnabled() { } public BesuNodeConfigurationBuilder enablePrivateTransactions() { - this.jsonRpcConfiguration.addRpcApi(RpcApis.EEA); - this.jsonRpcConfiguration.addRpcApi(RpcApis.PRIV); + this.jsonRpcConfiguration.addRpcApi(RpcApis.EEA.name()); + this.jsonRpcConfiguration.addRpcApi(RpcApis.PRIV.name()); return this; } public BesuNodeConfigurationBuilder jsonRpcTxPool() { - this.jsonRpcConfiguration.addRpcApi(RpcApis.TX_POOL); + this.jsonRpcConfiguration.addRpcApi(RpcApis.TXPOOL.name()); + return this; + } + + public BesuNodeConfigurationBuilder jsonRpcAdmin() { + this.jsonRpcConfiguration.addRpcApi(RpcApis.ADMIN.name()); + return this; + } + + public BesuNodeConfigurationBuilder jsonRpcDebug() { + this.jsonRpcConfiguration.addRpcApi(RpcApis.DEBUG.name()); return this; } @@ -140,10 +201,21 @@ public BesuNodeConfigurationBuilder jsonRpcAuthenticationConfiguration(final Str return this; } - public BesuNodeConfigurationBuilder jsonRpcAuthenticationUsingPublicKeyEnabled() - throws URISyntaxException { + public BesuNodeConfigurationBuilder jsonRpcAuthenticationConfiguration( + final String authFile, final List noAuthApiMethods) throws URISyntaxException { + final String authTomlPath = + Paths.get(ClassLoader.getSystemResource(authFile).toURI()).toAbsolutePath().toString(); + + this.jsonRpcConfiguration.setAuthenticationEnabled(true); + this.jsonRpcConfiguration.setAuthenticationCredentialsFile(authTomlPath); + this.jsonRpcConfiguration.setNoAuthRpcApis(noAuthApiMethods); + + return this; + } + + public BesuNodeConfigurationBuilder jsonRpcAuthenticationUsingRSA() throws URISyntaxException { final File jwtPublicKey = - Paths.get(ClassLoader.getSystemResource("authentication/jwt_public_key").toURI()) + Paths.get(ClassLoader.getSystemResource("authentication/jwt_public_key_rsa").toURI()) .toAbsolutePath() .toFile(); @@ -153,18 +225,42 @@ public BesuNodeConfigurationBuilder jsonRpcAuthenticationUsingPublicKeyEnabled() return this; } + public BesuNodeConfigurationBuilder jsonRpcAuthenticationUsingECDSA() throws URISyntaxException { + final File jwtPublicKey = + Paths.get(ClassLoader.getSystemResource("authentication/jwt_public_key_ecdsa").toURI()) + .toAbsolutePath() + .toFile(); + + this.jsonRpcConfiguration.setAuthenticationEnabled(true); + this.jsonRpcConfiguration.setAuthenticationPublicKeyFile(jwtPublicKey); + this.jsonRpcConfiguration.setAuthenticationAlgorithm(JwtAlgorithm.ES256); + + return this; + } + public BesuNodeConfigurationBuilder webSocketConfiguration( final WebSocketConfiguration webSocketConfiguration) { this.webSocketConfiguration = webSocketConfiguration; return this; } + public BesuNodeConfigurationBuilder jsonRpcIpcConfiguration( + final JsonRpcIpcConfiguration jsonRpcIpcConfiguration) { + this.jsonRpcIpcConfiguration = jsonRpcIpcConfiguration; + return this; + } + public BesuNodeConfigurationBuilder metricsConfiguration( final MetricsConfiguration metricsConfiguration) { this.metricsConfiguration = metricsConfiguration; return this; } + public BesuNodeConfigurationBuilder network(final NetworkName network) { + this.network = network; + return this; + } + public BesuNodeConfigurationBuilder webSocketEnabled() { final WebSocketConfiguration config = WebSocketConfiguration.createDefault(); config.setEnabled(true); @@ -192,15 +288,43 @@ public BesuNodeConfigurationBuilder webSocketAuthenticationEnabled() throws URIS return this; } - public BesuNodeConfigurationBuilder webSocketAuthenticationUsingPublicKeyEnabled() + public BesuNodeConfigurationBuilder webSocketAuthenticationEnabledWithNoAuthMethods( + final List noAuthApiMethods) throws URISyntaxException { + final String authTomlPath = + Paths.get(ClassLoader.getSystemResource("authentication/auth.toml").toURI()) + .toAbsolutePath() + .toString(); + + this.webSocketConfiguration.setAuthenticationEnabled(true); + this.webSocketConfiguration.setAuthenticationCredentialsFile(authTomlPath); + this.webSocketConfiguration.setRpcApisNoAuth(noAuthApiMethods); + + return this; + } + + public BesuNodeConfigurationBuilder webSocketAuthenticationUsingRsaPublicKeyEnabled() + throws URISyntaxException { + final File jwtPublicKey = + Paths.get(ClassLoader.getSystemResource("authentication/jwt_public_key_rsa").toURI()) + .toAbsolutePath() + .toFile(); + + this.webSocketConfiguration.setAuthenticationEnabled(true); + this.webSocketConfiguration.setAuthenticationPublicKeyFile(jwtPublicKey); + + return this; + } + + public BesuNodeConfigurationBuilder webSocketAuthenticationUsingEcdsaPublicKeyEnabled() throws URISyntaxException { final File jwtPublicKey = - Paths.get(ClassLoader.getSystemResource("authentication/jwt_public_key").toURI()) + Paths.get(ClassLoader.getSystemResource("authentication/jwt_public_key_ecdsa").toURI()) .toAbsolutePath() .toFile(); this.webSocketConfiguration.setAuthenticationEnabled(true); this.webSocketConfiguration.setAuthenticationPublicKeyFile(jwtPublicKey); + this.webSocketConfiguration.setAuthenticationAlgorithm(JwtAlgorithm.ES256); return this; } @@ -232,6 +356,76 @@ public BesuNodeConfigurationBuilder p2pEnabled(final Boolean p2pEnabled) { return this; } + public BesuNodeConfigurationBuilder p2pPort(final int p2pPort) { + this.p2pPort = p2pPort; + return this; + } + + private static Path toPath(final String path) throws Exception { + return Path.of(BesuNodeConfigurationBuilder.class.getResource(path).toURI()); + } + + public BesuNodeConfigurationBuilder p2pTLSEnabled(final String name, final String type) { + final TLSConfiguration.Builder builder = TLSConfiguration.Builder.tlsConfiguration(); + try { + final String nsspin = "/pki-certs/%s/nsspin.txt"; + final String truststore = "/pki-certs/%s/truststore.p12"; + final String crl = "/pki-certs/crl/crl.pem"; + switch (type) { + case KEYSTORE_TYPE_JKS: + builder + .withKeyStoreType(type) + .withKeyStorePath(toPath(String.format("/pki-certs/%s/% environment) { + this.environment = environment; + return this; + } + public BesuNodeConfiguration build() { return new BesuNodeConfiguration( name, dataPath, miningParameters, jsonRpcConfiguration, + Optional.of(engineRpcConfiguration), webSocketConfiguration, + jsonRpcIpcConfiguration, metricsConfiguration, permissioningConfiguration, Optional.ofNullable(keyFilePath), devMode, + network, genesisConfigProvider, p2pEnabled, + p2pPort, + tlsConfiguration, networkingConfiguration, discoveryEnabled, bootnodeEligible, @@ -308,6 +523,10 @@ public BesuNodeConfiguration build() { staticNodes, isDnsEnabled, privacyParameters, - runCommand); + runCommand, + keyPair, + pkiKeyStoreConfiguration, + strictTxReplayProtectionEnabled, + environment); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java index 710bad5ce7c..fb6ac5f1014 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java @@ -1,13 +1,16 @@ /* * Copyright ConsenSys AG. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the * specific language governing permissions and limitations under the License. * * SPDX-License-Identifier: Apache-2.0 @@ -17,37 +20,41 @@ import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; +import org.hyperledger.besu.crypto.KeyPair; +import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.enclave.EnclaveFactory; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; +import org.hyperledger.besu.ethereum.core.AddressHelpers; import org.hyperledger.besu.ethereum.core.InMemoryPrivacyStorageProvider; import org.hyperledger.besu.ethereum.core.MiningParameters; -import org.hyperledger.besu.ethereum.core.MiningParametersTestBuilder; import org.hyperledger.besu.ethereum.core.PrivacyParameters; -import org.hyperledger.besu.ethereum.core.Wei; import org.hyperledger.besu.ethereum.permissioning.LocalPermissioningConfiguration; import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; +import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.pki.PkiKeystoreConfigurationFactory; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.function.Function; +import java.util.function.UnaryOperator; import io.vertx.core.Vertx; public class BesuNodeFactory { - private final GenesisConfigurationFactory genesis = new GenesisConfigurationFactory(); private final NodeConfigurationFactory node = new NodeConfigurationFactory(); + private final PkiKeystoreConfigurationFactory pkiKeystoreConfigurationFactory = + new PkiKeystoreConfigurationFactory(); public BesuNode create(final BesuNodeConfiguration config) throws IOException { return new BesuNode( @@ -55,13 +62,18 @@ public BesuNode create(final BesuNodeConfiguration config) throws IOException { config.getDataPath(), config.getMiningParameters(), config.getJsonRpcConfiguration(), + config.getEngineRpcConfiguration(), config.getWebSocketConfiguration(), + config.getJsonRpcIpcConfiguration(), config.getMetricsConfiguration(), config.getPermissioningConfiguration(), config.getKeyFilePath(), config.isDevMode(), + config.getNetwork(), config.getGenesisConfigProvider(), config.isP2pEnabled(), + config.getP2pPort(), + config.getTLSConfiguration(), config.getNetworkingConfiguration(), config.isDiscoveryEnabled(), config.isBootnodeEligible(), @@ -73,43 +85,80 @@ public BesuNode create(final BesuNodeConfiguration config) throws IOException { config.getStaticNodes(), config.isDnsEnabled(), config.getPrivacyParameters(), - config.getRunCommand()); + config.getRunCommand(), + config.getKeyPair(), + config.getPkiKeyStoreConfiguration(), + config.isStrictTxReplayProtectionEnabled(), + config.getEnvironment()); } - public BesuNode createMinerNode(final String name) throws IOException { - return create( + public BesuNode createMinerNode( + final String name, final UnaryOperator configModifier) + throws IOException { + BesuNodeConfigurationBuilder builder = new BesuNodeConfigurationBuilder() .name(name) .miningEnabled() .jsonRpcEnabled() - .webSocketEnabled() - .build()); + .webSocketEnabled(); + builder = configModifier.apply(builder); + final BesuNodeConfiguration config = builder.build(); + + return create(config); } - public BesuNode createMinerNodeWithRevertReasonEnabled(final String name) throws IOException { - return create( + public BesuNode createMinerNodeWithExtraCliOptions( + final String name, + final UnaryOperator configModifier, + final List extraCliOptions) + throws IOException { + BesuNodeConfigurationBuilder builder = new BesuNodeConfigurationBuilder() .name(name) .miningEnabled() .jsonRpcEnabled() .webSocketEnabled() - .revertReasonEnabled() - .build()); + .extraCLIOptions(extraCliOptions); + builder = configModifier.apply(builder); + final BesuNodeConfiguration config = builder.build(); + + return create(config); + } + + public BesuNode createMinerNode(final String name) throws IOException { + return createMinerNode(name, UnaryOperator.identity()); + } + + public BesuNode createMinerNodeWithExtraCliOptions( + final String name, final List extraCliOptions) throws IOException { + return createMinerNodeWithExtraCliOptions(name, UnaryOperator.identity(), extraCliOptions); + } + + public BesuNode createMinerNodeWithRevertReasonEnabled(final String name) throws IOException { + return createMinerNode(name, BesuNodeConfigurationBuilder::revertReasonEnabled); } public BesuNode createArchiveNode(final String name) throws IOException { - return create( + return createArchiveNode(name, UnaryOperator.identity()); + } + + public BesuNode createArchiveNode( + final String name, final UnaryOperator configModifier) + throws IOException { + BesuNodeConfigurationBuilder builder = new BesuNodeConfigurationBuilder() .name(name) .jsonRpcEnabled() .jsonRpcTxPool() - .webSocketEnabled() - .build()); + .webSocketEnabled(); + + builder = configModifier.apply(builder); + + return create(builder.build()); } public BesuNode createNode( - final String name, - final Function configModifier) + final String name, final UnaryOperator configModifier) throws IOException { final BesuNodeConfigurationBuilder configBuilder = configModifier.apply(new BesuNodeConfigurationBuilder().name(name)); @@ -173,15 +222,53 @@ public BesuNode createNodeWithAuthentication(final String name, final String aut .build()); } - public BesuNode createNodeWithAuthenticationUsingJwtPublicKey(final String name) + public BesuNode createNodeWithAuthFileAndNoAuthApi( + final String name, final String authFile, final List noAuthApiMethods) + throws URISyntaxException, IOException { + return create( + new BesuNodeConfigurationBuilder() + .name(name) + .jsonRpcEnabled() + .jsonRpcAuthenticationConfiguration(authFile, noAuthApiMethods) + .webSocketEnabled() + .webSocketAuthenticationEnabled() + .build()); + } + + public BesuNode createWsNodeWithAuthFileAndNoAuthApi( + final String name, final String authFile, final List noAuthApiMethods) + throws URISyntaxException, IOException { + return create( + new BesuNodeConfigurationBuilder() + .name(name) + .jsonRpcEnabled() + .jsonRpcAuthenticationConfiguration(authFile) + .webSocketEnabled() + .webSocketAuthenticationEnabledWithNoAuthMethods(noAuthApiMethods) + .build()); + } + + public BesuNode createNodeWithAuthenticationUsingRsaJwtPublicKey(final String name) + throws IOException, URISyntaxException { + return create( + new BesuNodeConfigurationBuilder() + .name(name) + .jsonRpcEnabled() + .jsonRpcAuthenticationUsingRSA() + .webSocketEnabled() + .webSocketAuthenticationUsingRsaPublicKeyEnabled() + .build()); + } + + public BesuNode createNodeWithAuthenticationUsingEcdsaJwtPublicKey(final String name) throws IOException, URISyntaxException { return create( new BesuNodeConfigurationBuilder() .name(name) .jsonRpcEnabled() - .jsonRpcAuthenticationUsingPublicKeyEnabled() + .jsonRpcAuthenticationUsingECDSA() .webSocketEnabled() - .webSocketAuthenticationUsingPublicKeyEnabled() + .webSocketAuthenticationUsingEcdsaPublicKeyEnabled() .build()); } @@ -199,14 +286,14 @@ public BesuNode createNodeWithMultiTenantedPrivacy( final String enclaveUrl, final String authFile, final String privTransactionSigningKey, - final boolean enableOnChainPrivacy) + final boolean enableFlexiblePrivacy) throws IOException, URISyntaxException { final PrivacyParameters.Builder privacyParametersBuilder = new PrivacyParameters.Builder(); final PrivacyParameters privacyParameters = privacyParametersBuilder .setMultiTenancyEnabled(true) .setEnabled(true) - .setOnchainPrivacyGroupsEnabled(enableOnChainPrivacy) + .setFlexiblePrivacyGroupsEnabled(enableFlexiblePrivacy) .setStorageProvider(new InMemoryPrivacyStorageProvider()) .setEnclaveFactory(new EnclaveFactory(Vertx.vertx())) .setEnclaveUrl(URI.create(enclaveUrl)) @@ -215,7 +302,11 @@ public BesuNode createNodeWithMultiTenantedPrivacy( .build(); final MiningParameters miningParameters = - new MiningParametersTestBuilder().minTransactionGasPrice(Wei.ZERO).enabled(true).build(); + new MiningParameters.Builder() + .minTransactionGasPrice(Wei.ZERO) + .coinbase(AddressHelpers.ofValue(1)) + .miningEnabled(true) + .build(); return create( new BesuNodeConfigurationBuilder() @@ -238,12 +329,14 @@ public BesuNode createPluginsNode( return create( new BesuNodeConfigurationBuilder() .name(name) + .jsonRpcConfiguration(node.createJsonRpcWithIbft2AdminEnabledConfig()) + .webSocketConfiguration(node.createWebSocketEnabledConfig()) .plugins(plugins) .extraCLIOptions(extraCLIOptions) .build()); } - public BesuNode createArchiveNodeWithRpcApis(final String name, final RpcApi... enabledRpcApis) + public BesuNode createArchiveNodeWithRpcApis(final String name, final String... enabledRpcApis) throws IOException { final JsonRpcConfiguration jsonRpcConfig = node.createJsonRpcEnabledConfig(); jsonRpcConfig.setRpcApis(asList(enabledRpcApis)); @@ -259,7 +352,12 @@ public BesuNode createArchiveNodeWithRpcApis(final String name, final RpcApi... } public BesuNode createNodeWithNoDiscovery(final String name) throws IOException { - return create(new BesuNodeConfigurationBuilder().name(name).discoveryEnabled(false).build()); + return create( + new BesuNodeConfigurationBuilder() + .name(name) + .discoveryEnabled(false) + .engineRpcEnabled(false) + .build()); } public BesuNode createCliqueNode(final String name) throws IOException { @@ -270,7 +368,7 @@ public BesuNode createCliqueNode(final String name) throws IOException { .jsonRpcConfiguration(node.createJsonRpcWithCliqueEnabledConfig()) .webSocketConfiguration(node.createWebSocketEnabledConfig()) .devMode(false) - .genesisConfigProvider(genesis::createCliqueGenesisConfig) + .genesisConfigProvider(GenesisConfigurationFactory::createCliqueGenesisConfig) .build()); } @@ -284,7 +382,8 @@ public BesuNode createIbft2NonValidatorBootnode(final String name, final String .devMode(false) .genesisConfigProvider( validators -> - genesis.createIbft2GenesisConfigFilterBootnode(validators, genesisFile)) + GenesisConfigurationFactory.createIbft2GenesisConfigFilterBootnode( + validators, genesisFile)) .bootnodeEligible(true) .build()); } @@ -310,7 +409,8 @@ public BesuNode createIbft2NodeWithLocalAccountPermissioning( .devMode(false) .genesisConfigProvider( validators -> - genesis.createIbft2GenesisConfigFilterBootnode(validators, genesisFile)) + GenesisConfigurationFactory.createIbft2GenesisConfigFilterBootnode( + validators, genesisFile)) .bootnodeEligible(false) .build()); } @@ -325,7 +425,8 @@ public BesuNode createIbft2Node(final String name, final String genesisFile) thr .devMode(false) .genesisConfigProvider( validators -> - genesis.createIbft2GenesisConfigFilterBootnode(validators, genesisFile)) + GenesisConfigurationFactory.createIbft2GenesisConfigFilterBootnode( + validators, genesisFile)) .bootnodeEligible(false) .build()); } @@ -338,7 +439,69 @@ public BesuNode createIbft2Node(final String name) throws IOException { .jsonRpcConfiguration(node.createJsonRpcWithIbft2EnabledConfig(false)) .webSocketConfiguration(node.createWebSocketEnabledConfig()) .devMode(false) - .genesisConfigProvider(genesis::createIbft2GenesisConfig) + .genesisConfigProvider(GenesisConfigurationFactory::createIbft2GenesisConfig) + .build()); + } + + public BesuNode createQbftNodeWithTLS(final String name, final String type) throws IOException { + return create( + new BesuNodeConfigurationBuilder() + .name(name) + .miningEnabled() + .p2pTLSEnabled(name, type) + .jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false)) + .webSocketConfiguration(node.createWebSocketEnabledConfig()) + .devMode(false) + .genesisConfigProvider(GenesisConfigurationFactory::createQbftGenesisConfig) + .build()); + } + + public BesuNode createQbftNodeWithTLSJKS(final String name) throws IOException { + return createQbftNodeWithTLS(name, KeyStoreWrapper.KEYSTORE_TYPE_JKS); + } + + public BesuNode createQbftNodeWithTLSPKCS12(final String name) throws IOException { + return createQbftNodeWithTLS(name, KeyStoreWrapper.KEYSTORE_TYPE_PKCS12); + } + + public BesuNode createQbftNodeWithTLSPKCS11(final String name) throws IOException { + return createQbftNodeWithTLS(name, KeyStoreWrapper.KEYSTORE_TYPE_PKCS11); + } + + public BesuNode createQbftNode(final String name) throws IOException { + return create( + new BesuNodeConfigurationBuilder() + .name(name) + .miningEnabled() + .jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false)) + .webSocketConfiguration(node.createWebSocketEnabledConfig()) + .devMode(false) + .genesisConfigProvider(GenesisConfigurationFactory::createQbftGenesisConfig) + .build()); + } + + public BesuNode createPkiQbftJKSNode(final String name) throws IOException { + return createPkiQbftNode(KeyStoreWrapper.KEYSTORE_TYPE_JKS, name); + } + + public BesuNode createPkiQbftPKCS11Node(final String name) throws IOException { + return createPkiQbftNode(KeyStoreWrapper.KEYSTORE_TYPE_PKCS11, name); + } + + public BesuNode createPkiQbftPKCS12Node(final String name) throws IOException { + return createPkiQbftNode(KeyStoreWrapper.KEYSTORE_TYPE_PKCS12, name); + } + + public BesuNode createPkiQbftNode(final String type, final String name) throws IOException { + return create( + new BesuNodeConfigurationBuilder() + .name(name) + .miningEnabled() + .jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false)) + .webSocketConfiguration(node.createWebSocketEnabledConfig()) + .devMode(false) + .genesisConfigProvider(GenesisConfigurationFactory::createQbftGenesisConfig) + .pkiBlockCreationEnabled(pkiKeystoreConfigurationFactory.createPkiConfig(type, name)) .build()); } @@ -353,7 +516,7 @@ public BesuNode createCustomGenesisNode( final boolean canBeBootnode, final boolean mining) throws IOException { - final String genesisFile = genesis.readGenesisFile(genesisPath); + final String genesisFile = GenesisConfigurationFactory.readGenesisFile(genesisPath); final BesuNodeConfigurationBuilder builder = new BesuNodeConfigurationBuilder() .name(name) @@ -370,6 +533,23 @@ public BesuNode createCustomGenesisNode( return create(builder.build()); } + public BesuNode createExecutionEngineGenesisNode(final String name, final String genesisPath) + throws IOException { + final String genesisFile = GenesisConfigurationFactory.readGenesisFile(genesisPath); + + return create( + new BesuNodeConfigurationBuilder() + .name(name) + .genesisConfigProvider((a) -> Optional.of(genesisFile)) + .devMode(false) + .bootnodeEligible(false) + .miningEnabled() + .jsonRpcEnabled() + .engineRpcEnabled(true) + .jsonRpcDebug() + .build()); + } + public BesuNode createCliqueNodeWithValidators(final String name, final String... validators) throws IOException { @@ -383,7 +563,9 @@ public BesuNode createCliqueNodeWithValidators(final String name, final String.. .genesisConfigProvider( nodes -> node.createGenesisConfigForValidators( - asList(validators), nodes, genesis::createCliqueGenesisConfig)) + asList(validators), + nodes, + GenesisConfigurationFactory::createCliqueGenesisConfig)) .build()); } @@ -400,13 +582,129 @@ public BesuNode createIbft2NodeWithValidators(final String name, final String... .genesisConfigProvider( nodes -> node.createGenesisConfigForValidators( - asList(validators), nodes, genesis::createIbft2GenesisConfig)) + asList(validators), + nodes, + GenesisConfigurationFactory::createIbft2GenesisConfig)) + .build()); + } + + public BesuNode createQbftTLSNodeWithValidators( + final String name, final String type, final String... validators) throws IOException { + + return create( + new BesuNodeConfigurationBuilder() + .name(name) + .miningEnabled() + .p2pTLSEnabled(name, type) + .jsonRpcConfiguration(node.createJsonRpcWithIbft2EnabledConfig(false)) + .webSocketConfiguration(node.createWebSocketEnabledConfig()) + .devMode(false) + .genesisConfigProvider( + nodes -> + node.createGenesisConfigForValidators( + asList(validators), + nodes, + GenesisConfigurationFactory::createIbft2GenesisConfig)) + .build()); + } + + public BesuNode createQbftTLSJKSNodeWithValidators(final String name, final String... validators) + throws IOException { + return createQbftTLSNodeWithValidators(name, KeyStoreWrapper.KEYSTORE_TYPE_JKS, validators); + } + + public BesuNode createQbftTLSPKCS12NodeWithValidators( + final String name, final String... validators) throws IOException { + return createQbftTLSNodeWithValidators(name, KeyStoreWrapper.KEYSTORE_TYPE_PKCS12, validators); + } + + public BesuNode createQbftTLSPKCS11NodeWithValidators( + final String name, final String... validators) throws IOException { + return createQbftTLSNodeWithValidators(name, KeyStoreWrapper.KEYSTORE_TYPE_PKCS11, validators); + } + + public BesuNode createQbftNodeWithValidators(final String name, final String... validators) + throws IOException { + + return create( + new BesuNodeConfigurationBuilder() + .name(name) + .miningEnabled() + .jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false)) + .webSocketConfiguration(node.createWebSocketEnabledConfig()) + .devMode(false) + .genesisConfigProvider( + nodes -> + node.createGenesisConfigForValidators( + asList(validators), + nodes, + GenesisConfigurationFactory::createQbftGenesisConfig)) + .build()); + } + + public BesuNode createQbftNodeWithContractBasedValidators( + final String name, final String... validators) throws IOException { + return create( + new BesuNodeConfigurationBuilder() + .name(name) + .miningEnabled() + .jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false)) + .webSocketConfiguration(node.createWebSocketEnabledConfig()) + .devMode(false) + .genesisConfigProvider( + nodes -> + node.createGenesisConfigForValidators( + asList(validators), + nodes, + GenesisConfigurationFactory::createQbftValidatorContractGenesisConfig)) + .build()); + } + + public BesuNode createPkiQbftJKSNodeWithValidators(final String name, final String... validators) + throws IOException { + return createPkiQbftNodeWithValidators(KeyStoreWrapper.KEYSTORE_TYPE_JKS, name, validators); + } + + public BesuNode createPkiQbftPKCS11NodeWithValidators( + final String name, final String... validators) throws IOException { + return createPkiQbftNodeWithValidators(KeyStoreWrapper.KEYSTORE_TYPE_PKCS11, name, validators); + } + + public BesuNode createPkiQbftPKCS12NodeWithValidators( + final String name, final String... validators) throws IOException { + return createPkiQbftNodeWithValidators(KeyStoreWrapper.KEYSTORE_TYPE_PKCS12, name, validators); + } + + public BesuNode createPkiQbftNodeWithValidators( + final String type, final String name, final String... validators) throws IOException { + + return create( + new BesuNodeConfigurationBuilder() + .name(name) + .miningEnabled() + .jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false)) + .webSocketConfiguration(node.createWebSocketEnabledConfig()) + .devMode(false) + .pkiBlockCreationEnabled(pkiKeystoreConfigurationFactory.createPkiConfig(type, name)) + .genesisConfigProvider( + nodes -> + node.createGenesisConfigForValidators( + asList(validators), + nodes, + GenesisConfigurationFactory::createQbftGenesisConfig)) .build()); } public BesuNode createNodeWithStaticNodes(final String name, final List staticNodes) throws IOException { + BesuNodeConfigurationBuilder builder = + createConfigurationBuilderWithStaticNodes(name, staticNodes); + return create(builder.build()); + } + + private BesuNodeConfigurationBuilder createConfigurationBuilderWithStaticNodes( + final String name, final List staticNodes) { final List staticNodesUrls = staticNodes.stream() .map(node -> (RunnableNode) node) @@ -414,15 +712,51 @@ public BesuNode createNodeWithStaticNodes(final String name, final List st .map(URI::toASCIIString) .collect(toList()); - return create( - new BesuNodeConfigurationBuilder() - .name(name) - .jsonRpcEnabled() - .webSocketEnabled() - .discoveryEnabled(false) - .staticNodes(staticNodesUrls) - .bootnodeEligible(false) - .build()); + return new BesuNodeConfigurationBuilder() + .name(name) + .jsonRpcEnabled() + .webSocketEnabled() + .discoveryEnabled(false) + .staticNodes(staticNodesUrls) + .bootnodeEligible(false); + } + + public BesuNode createNodeWithNonDefaultSignatureAlgorithm( + final String name, final String genesisPath, final KeyPair keyPair) throws IOException { + BesuNodeConfigurationBuilder builder = + createNodeConfigurationWithNonDefaultSignatureAlgorithm( + name, genesisPath, keyPair, new ArrayList<>()); + builder.miningEnabled(); + + return create(builder.build()); + } + + public BesuNode createNodeWithNonDefaultSignatureAlgorithm( + final String name, + final String genesisPath, + final KeyPair keyPair, + final List staticNodes) + throws IOException { + BesuNodeConfigurationBuilder builder = + createNodeConfigurationWithNonDefaultSignatureAlgorithm( + name, genesisPath, keyPair, staticNodes); + return create(builder.build()); + } + + public BesuNodeConfigurationBuilder createNodeConfigurationWithNonDefaultSignatureAlgorithm( + final String name, + final String genesisPath, + final KeyPair keyPair, + final List staticNodes) { + BesuNodeConfigurationBuilder builder = + createConfigurationBuilderWithStaticNodes(name, staticNodes); + + final String genesisData = GenesisConfigurationFactory.readGenesisFile(genesisPath); + + return builder + .devMode(false) + .genesisConfigProvider((nodes) -> Optional.of(genesisData)) + .keyPair(keyPair); } public BesuNode runCommand(final String command) throws IOException { diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfiguration.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfiguration.java index aecf96c064f..ce2d53cdf33 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfiguration.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfiguration.java @@ -18,6 +18,7 @@ import java.net.URI; import java.util.List; +import java.util.Map; import java.util.Optional; public interface NodeConfiguration { @@ -32,10 +33,16 @@ public interface NodeConfiguration { Optional getJsonRpcWebSocketPort(); + Optional getJsonRpcPort(); + + Optional getEngineJsonRpcPort(); + String getHostName(); boolean isJsonRpcEnabled(); + boolean isEngineRpcEnabled(); + GenesisConfigurationProvider getGenesisConfigProvider(); Optional getGenesisConfig(); @@ -53,4 +60,6 @@ public interface NodeConfiguration { boolean isRevertReasonEnabled(); List getStaticNodes(); + + Map getEnvironment(); } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfigurationFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfigurationFactory.java index e910b789c8e..f2682993f8a 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfigurationFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfigurationFactory.java @@ -16,13 +16,13 @@ import static java.util.Collections.singletonList; import static java.util.stream.Collectors.toList; -import static org.hyperledger.besu.consensus.clique.jsonrpc.CliqueRpcApis.CLIQUE; -import static org.hyperledger.besu.consensus.ibft.jsonrpc.IbftRpcApis.IBFT; import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.ADMIN; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.CLIQUE; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.IBFT; import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.MINER; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.QBFT; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider; @@ -45,17 +45,23 @@ public Optional createGenesisConfigForValidators( } public JsonRpcConfiguration createJsonRpcWithCliqueEnabledConfig() { - return createJsonRpcWithRpcApiEnabledConfig(CLIQUE); + return createJsonRpcWithRpcApiEnabledConfig(CLIQUE.name()); } public JsonRpcConfiguration createJsonRpcWithIbft2EnabledConfig(final boolean minerEnabled) { return minerEnabled - ? createJsonRpcWithRpcApiEnabledConfig(IBFT, MINER) - : createJsonRpcWithRpcApiEnabledConfig(IBFT); + ? createJsonRpcWithRpcApiEnabledConfig(IBFT.name(), MINER.name()) + : createJsonRpcWithRpcApiEnabledConfig(IBFT.name()); } public JsonRpcConfiguration createJsonRpcWithIbft2AdminEnabledConfig() { - return createJsonRpcWithRpcApiEnabledConfig(IBFT, ADMIN); + return createJsonRpcWithRpcApiEnabledConfig(IBFT.name(), ADMIN.name()); + } + + public JsonRpcConfiguration createJsonRpcWithQbftEnabledConfig(final boolean minerEnabled) { + return minerEnabled + ? createJsonRpcWithRpcApiEnabledConfig(QBFT.name(), MINER.name()) + : createJsonRpcWithRpcApiEnabledConfig(QBFT.name()); } public JsonRpcConfiguration createJsonRpcEnabledConfig() { @@ -74,12 +80,12 @@ public WebSocketConfiguration createWebSocketEnabledConfig() { } public JsonRpcConfiguration jsonRpcConfigWithAdmin() { - return createJsonRpcWithRpcApiEnabledConfig(ADMIN); + return createJsonRpcWithRpcApiEnabledConfig(ADMIN.name()); } - public JsonRpcConfiguration createJsonRpcWithRpcApiEnabledConfig(final RpcApi... rpcApi) { + public JsonRpcConfiguration createJsonRpcWithRpcApiEnabledConfig(final String... rpcApi) { final JsonRpcConfiguration jsonRpcConfig = createJsonRpcEnabledConfig(); - final List rpcApis = new ArrayList<>(jsonRpcConfig.getRpcApis()); + final List rpcApis = new ArrayList<>(jsonRpcConfig.getRpcApis()); rpcApis.addAll(Arrays.asList(rpcApi)); jsonRpcConfig.setRpcApis(rpcApis); return jsonRpcConfig; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/genesis/GenesisConfigurationFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/genesis/GenesisConfigurationFactory.java index ceab0160ad0..c52fbbba0c5 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/genesis/GenesisConfigurationFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/genesis/GenesisConfigurationFactory.java @@ -17,43 +17,53 @@ import static java.util.stream.Collectors.toList; import org.hyperledger.besu.consensus.clique.CliqueExtraData; -import org.hyperledger.besu.consensus.ibft.IbftExtraData; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.consensus.ibft.IbftExtraDataCodec; +import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode; import java.io.IOException; +import java.io.UncheckedIOException; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.Charset; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.function.Function; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.io.Resources; public class GenesisConfigurationFactory { - public Optional createCliqueGenesisConfig( + private GenesisConfigurationFactory() { + throw new IllegalStateException("Utility class"); + } + + public static Optional createCliqueGenesisConfig( final Collection validators) { final String template = readGenesisFile("/clique/clique.json"); return updateGenesisExtraData( validators, template, CliqueExtraData::createGenesisExtraDataString); } - public Optional createIbft2GenesisConfig( + public static Optional createIbft2GenesisConfig( final Collection validators) { return createIbft2GenesisConfig(validators, "/ibft/ibft.json"); } - public Optional createIbft2GenesisConfig( + public static Optional createIbft2GenesisConfig( final Collection validators, final String genesisFile) { final String template = readGenesisFile(genesisFile); return updateGenesisExtraData( - validators, template, IbftExtraData::createGenesisExtraDataString); + validators, template, IbftExtraDataCodec::createGenesisExtraDataString); } - public Optional createIbft2GenesisConfigFilterBootnode( + public static Optional createIbft2GenesisConfigFilterBootnode( final Collection validators, final String genesisFile) { final String template = readGenesisFile(genesisFile); final List filteredList = @@ -61,17 +71,63 @@ public Optional createIbft2GenesisConfigFilterBootnode( .filter(node -> !node.getConfiguration().isBootnodeEligible()) .collect(toList()); return updateGenesisExtraData( - filteredList, template, IbftExtraData::createGenesisExtraDataString); + filteredList, template, IbftExtraDataCodec::createGenesisExtraDataString); } - public Optional createPrivacyIbft2GenesisConfig( + public static Optional createPrivacyIbft2GenesisConfig( final Collection validators) { final String template = readGenesisFile("/ibft/privacy-ibft.json"); return updateGenesisExtraData( - validators, template, IbftExtraData::createGenesisExtraDataString); + validators, template, IbftExtraDataCodec::createGenesisExtraDataString); + } + + public static Optional createQbftGenesisConfig( + final Collection validators) { + final String template = readGenesisFile("/qbft/qbft.json"); + return updateGenesisExtraData( + validators, template, QbftExtraDataCodec::createGenesisExtraDataString); + } + + @SuppressWarnings("unchecked") + public static Optional createQbftValidatorContractGenesisConfig( + final Collection validators) throws UncheckedIOException { + final String template = readGenesisFile("/qbft/qbft-emptyextradata.json"); + final String contractAddress = "0x0000000000000000000000000000000000008888"; + + try { + // convert genesis json to Map for modification + final ObjectMapper objectMapper = new ObjectMapper(); + final Map genesisMap = + objectMapper.readValue(template, new TypeReference<>() {}); + + // update config/qbft to add contract address + final Map configMap = (Map) genesisMap.get("config"); + final Map qbftMap = (Map) configMap.get("qbft"); + qbftMap.put("validatorcontractaddress", contractAddress); + + // update alloc to add contract code and storage + final Map allocMap = (Map) genesisMap.get("alloc"); + final Map contractConfig = + new QbftValidatorContractConfigFactory().buildContractConfig(validators); + allocMap.put(contractAddress, contractConfig); + + // regenerate genesis json again + final String genesisJson = + objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(genesisMap); + return Optional.of(genesisJson); + } catch (final JsonProcessingException e) { + throw new UncheckedIOException(e); + } + } + + public static Optional createDevLondonGenesisConfig( + final Collection validators) { + final String template = readGenesisFile("/dev/dev_london.json"); + return updateGenesisExtraData( + validators, template, CliqueExtraData::createGenesisExtraDataString); } - private Optional updateGenesisExtraData( + private static Optional updateGenesisExtraData( final Collection validators, final String genesisTemplate, final Function, String> extraDataCreator) { @@ -83,9 +139,9 @@ private Optional updateGenesisExtraData( } @SuppressWarnings("UnstableApiUsage") - public String readGenesisFile(final String filepath) { + public static String readGenesisFile(final String filepath) { try { - final URI uri = this.getClass().getResource(filepath).toURI(); + final URI uri = GenesisConfigurationFactory.class.getResource(filepath).toURI(); return Resources.toString(uri.toURL(), Charset.defaultCharset()); } catch (final URISyntaxException | IOException e) { throw new IllegalStateException("Unable to get test genesis config " + filepath); diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/genesis/QbftValidatorContractConfigFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/genesis/QbftValidatorContractConfigFactory.java new file mode 100644 index 00000000000..1afdae90ffc --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/genesis/QbftValidatorContractConfigFactory.java @@ -0,0 +1,75 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis; + +import static java.util.stream.Collectors.toList; + +import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode; + +import java.math.BigInteger; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuweni.bytes.Bytes; + +public class QbftValidatorContractConfigFactory { + private static final String BALANCE = "0"; + // This is compiled from + // https://github.com/hyperledger/besu/blob/9deb5ea5d21c810300d5b7005bf6c3777be3f6e5/consensus/qbft/src/integration-test/resources/validator_contract.sol + // using solc --evm-version byzantium --bin-runtime validator_contract.sol", + private static final String CODE = + "608060405234801561001057600080fd5b5060043610610048576000357c010000000000000000000000000000000000000000000000000000000090048063b7ab4db51461004d575b600080fd5b61005561006b565b604051610062919061017e565b60405180910390f35b606060008054806020026020016040519081016040528092919081815260200182805480156100ef57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116100a5575b5050505050905090565b60006101058383610111565b60208301905092915050565b61011a816101d9565b82525050565b600061012b826101b0565b61013581856101c8565b9350610140836101a0565b8060005b8381101561017157815161015888826100f9565b9750610163836101bb565b925050600181019050610144565b5085935050505092915050565b600060208201905081810360008301526101988184610120565b905092915050565b6000819050602082019050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b60006101e4826101eb565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff8216905091905056fea26469706673582212206d880cf012c1677c691bf6f2f0a0e4eadf57866ffe5cd2d9833d3cfdf27b15f664736f6c63430008060033"; + // The following address location is specific to above contract. It is used to pre-initialize the + // array in the contract with validators + private static final BigInteger ARRAY_ADDR = + new BigInteger("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563", 16); + + public final Map buildContractConfig( + final Collection validators) { + Map contractAllocation = new LinkedHashMap<>(); + contractAllocation.put("balance", BALANCE); + contractAllocation.put("code", CODE); + contractAllocation.put("storage", buildContractStorageConfig(validators)); + + return contractAllocation; + } + + private Map buildContractStorageConfig( + final Collection validators) { + final List addresses = + validators.stream() + .map(RunnableNode::getAddress) + .map(Bytes::toUnprefixedHexString) + .map(hex -> (padZero(0) + hex).substring(hex.length())) + .collect(toList()); + + final Map storageValues = new LinkedHashMap<>(); + // zero location is size of array + storageValues.put(padZero(0), padZero(addresses.size())); + + // further locations are allocation of addresses to array + for (int i = 0; i < addresses.size(); i++) { + final BigInteger varStorage = ARRAY_ADDR.add(BigInteger.valueOf(i)); + storageValues.put(varStorage.toString(16), addresses.get(i)); + } + return storageValues; + } + + private String padZero(final int value) { + return String.format("%064x", value); + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/permissioning/PermissionedNodeBuilder.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/permissioning/PermissionedNodeBuilder.java index 2e81875660c..8dafc14d77f 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/permissioning/PermissionedNodeBuilder.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/permissioning/PermissionedNodeBuilder.java @@ -17,16 +17,16 @@ import static java.util.Collections.singletonList; import static java.util.stream.Collectors.toList; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.p2p.peers.EnodeURL; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.ethereum.permissioning.AllowlistPersistor; import org.hyperledger.besu.ethereum.permissioning.AllowlistPersistor.ALLOWLIST_TYPE; import org.hyperledger.besu.ethereum.permissioning.LocalPermissioningConfiguration; import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; import org.hyperledger.besu.ethereum.permissioning.SmartContractPermissioningConfiguration; +import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode; @@ -227,7 +227,9 @@ private LocalPermissioningConfiguration localConfigPermissioningConfiguration() } final List nodeAllowList = - localConfigPermittedNodes.stream().map(EnodeURL::fromURI).collect(Collectors.toList()); + localConfigPermittedNodes.stream() + .map(EnodeURLImpl::fromURI) + .collect(Collectors.toList()); initPermissioningConfigurationFile( ALLOWLIST_TYPE.NODES, @@ -294,9 +296,9 @@ private JsonRpcConfiguration jsonRpcConfigWithPermApiEnabled() { jsonRpcConfig.setPort(0); jsonRpcConfig.setHostsAllowlist(singletonList("*")); jsonRpcConfig.setCorsAllowedDomains(singletonList("*")); - final List rpcApis = new ArrayList<>(jsonRpcConfig.getRpcApis()); - rpcApis.add(RpcApis.PERM); - rpcApis.add(RpcApis.ADMIN); + final List rpcApis = new ArrayList<>(jsonRpcConfig.getRpcApis()); + rpcApis.add(RpcApis.PERM.name()); + rpcApis.add(RpcApis.ADMIN.name()); jsonRpcConfig.setRpcApis(rpcApis); return jsonRpcConfig; } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/pki/PKCS11Utils.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/pki/PKCS11Utils.java new file mode 100644 index 00000000000..7c77722c8b2 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/pki/PKCS11Utils.java @@ -0,0 +1,61 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.tests.acceptance.dsl.node.configuration.pki; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.file.Path; +import java.util.Properties; + +public class PKCS11Utils { + + public static Path initNSSConfigFile(final Path srcFilePath) { + // load nss file as Properties + final Properties nssProp = new Properties(); + try (InputStream input = new FileInputStream(srcFilePath.toFile())) { + nssProp.load(input); + String nssDbPath = srcFilePath.getParent().resolve("nssdb").toAbsolutePath().toString(); + nssProp.setProperty("nssSecmodDirectory", nssDbPath); + } catch (final IOException e) { + throw new UncheckedIOException(e); + } + + // store modified config into temporary file + final Path targetFilePath = createTemporaryFile("nsscfg"); + try (FileOutputStream outputStream = new FileOutputStream(targetFilePath.toFile())) { + nssProp.store(outputStream, null); + } catch (final IOException e) { + throw new UncheckedIOException(e); + } + + return targetFilePath; + } + + private static Path createTemporaryFile(final String suffix) { + final File tempFile; + try { + tempFile = File.createTempFile("temp", suffix); + tempFile.deleteOnExit(); + } catch (IOException e) { + throw new RuntimeException("Error creating temporary file", e); + } + return tempFile.toPath(); + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/pki/PkiKeystoreConfigurationFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/pki/PkiKeystoreConfigurationFactory.java new file mode 100644 index 00000000000..ac7f814d433 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/pki/PkiKeystoreConfigurationFactory.java @@ -0,0 +1,196 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.tests.acceptance.dsl.node.configuration.pki; + +import static org.hyperledger.besu.pki.util.TestCertificateUtils.createKeyPair; +import static org.hyperledger.besu.pki.util.TestCertificateUtils.createSelfSignedCertificate; +import static org.hyperledger.besu.pki.util.TestCertificateUtils.issueCertificate; + +import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration; +import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; +import org.hyperledger.besu.pki.util.TestCertificateUtils; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.KeyPair; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Objects; +import java.util.UUID; + +public class PkiKeystoreConfigurationFactory { + + /* + PKCS11 config files + */ + final String NSSCONFIG_PATH_STRING = "/pki-certs/%s/nss.cfg"; + final String NSSPIN_PATH_STRING = "/pki-certs/%s/nsspin.txt"; + final String TRUSTSTORE_PATH_STRING = "/pki-certs/%s/truststore.p12"; + final String CRL_PATH_STRING = "/pki-certs/crl/crl.pem"; + + /* + Software keystore config + */ + public static final String KEYSTORE_DEFAULT_PASSWORD = "password"; + + private KeyPair caKeyPair; + private X509Certificate caCertificate; + private Path trustStoreFile; + private Path passwordFile; + + public PkiKeyStoreConfiguration createPkiConfig(final String type, final String name) { + if (KeyStoreWrapper.KEYSTORE_TYPE_PKCS11.equals(type)) { + return createPKCS11PkiConfig(name); + } else { + return createSoftwareKeyStorePkiConfig(type, name); + } + } + + private PkiKeyStoreConfiguration createPKCS11PkiConfig(final String name) { + final PkiKeyStoreConfiguration.Builder pkiKeyStoreConfigBuilder = + new PkiKeyStoreConfiguration.Builder(); + + try { + pkiKeyStoreConfigBuilder + .withKeyStoreType(KeyStoreWrapper.KEYSTORE_TYPE_PKCS11) + .withKeyStorePath( + PKCS11Utils.initNSSConfigFile( + readResourceAsPath(String.format(NSSCONFIG_PATH_STRING, name)))) + .withKeyStorePasswordPath(readResourceAsPath(String.format(NSSPIN_PATH_STRING, name))) + .withTrustStoreType(KeyStoreWrapper.KEYSTORE_TYPE_PKCS12) + .withTrustStorePath(readResourceAsPath(String.format(TRUSTSTORE_PATH_STRING, name))) + .withTrustStorePasswordPath(readResourceAsPath(String.format(NSSPIN_PATH_STRING, name))) + .withCrlFilePath(readResourceAsPath(CRL_PATH_STRING)) + .withCertificateAlias(name); + + } catch (Exception e) { + throw new RuntimeException(e); + } + + return pkiKeyStoreConfigBuilder.build(); + } + + private PkiKeyStoreConfiguration createSoftwareKeyStorePkiConfig( + final String type, final String name) { + PkiKeyStoreConfiguration.Builder pkiKeyStoreConfigBuilder = + new PkiKeyStoreConfiguration.Builder(); + + pkiKeyStoreConfigBuilder.withTrustStoreType(type); + pkiKeyStoreConfigBuilder.withTrustStorePath(createTrustStore(type)); + pkiKeyStoreConfigBuilder.withTrustStorePasswordPath(passwordFile); + + pkiKeyStoreConfigBuilder.withKeyStoreType(type); + pkiKeyStoreConfigBuilder.withKeyStorePath(createKeyStore(type, name)); + pkiKeyStoreConfigBuilder.withKeyStorePasswordPath(passwordFile); + + pkiKeyStoreConfigBuilder.withCertificateAlias(name); + + return pkiKeyStoreConfigBuilder.build(); + } + + private Path createTrustStore(final String type) { + // Only create the truststore if this is the first time this method is being called + if (caKeyPair == null) { + try { + caKeyPair = createKeyPair(TestCertificateUtils.Algorithm.RSA); + caCertificate = createSelfSignedCertificate("ca", notBefore(), notAfter(), caKeyPair); + + final KeyStore truststore = KeyStore.getInstance(type); + truststore.load(null, null); + truststore.setCertificateEntry("ca", caCertificate); + + final String uniqueId = UUID.randomUUID().toString(); + trustStoreFile = writeKeyStoreFile(truststore, "truststore", uniqueId); + passwordFile = writePasswordFile(KEYSTORE_DEFAULT_PASSWORD, "password", uniqueId); + } catch (final Exception e) { + throw new RuntimeException("Error creating truststore for Acceptance Test", e); + } + } + + return trustStoreFile; + } + + private Path createKeyStore(final String type, final String alias) { + if (caKeyPair == null) { + createTrustStore(type); + } + + final KeyPair kp = createKeyPair(TestCertificateUtils.Algorithm.RSA); + final X509Certificate certificate = + issueCertificate(caCertificate, caKeyPair, "validator", notBefore(), notAfter(), kp, false); + + try { + final KeyStore keyStore = KeyStore.getInstance(type); + keyStore.load(null, null); + keyStore.setKeyEntry( + alias, + kp.getPrivate(), + KEYSTORE_DEFAULT_PASSWORD.toCharArray(), + new Certificate[] {certificate, caCertificate}); + + final String id = UUID.randomUUID().toString(); + return writeKeyStoreFile(keyStore, "keystore", id); + } catch (final Exception e) { + throw new RuntimeException("Error creating keystore for Acceptance Test", e); + } + } + + private Path writeKeyStoreFile( + final KeyStore keyStore, final String prefix, final String suffix) { + try { + final Path file = Files.createTempFile(prefix, suffix != null ? suffix : ""); + file.toFile().deleteOnExit(); + final FileOutputStream keyStoreFOS = new FileOutputStream(file.toFile()); + keyStore.store(keyStoreFOS, KEYSTORE_DEFAULT_PASSWORD.toCharArray()); + + return file; + } catch (final Exception e) { + throw new RuntimeException("Error creating keystore file", e); + } + } + + private Path writePasswordFile(final String password, final String prefix, final String suffix) { + try { + final Path file = Files.createTempFile(prefix, suffix); + file.toFile().deleteOnExit(); + Files.write(file, password.getBytes(StandardCharsets.UTF_8)); + return file; + } catch (final IOException e) { + throw new RuntimeException("Error creating password file", e); + } + } + + private Instant notBefore() { + return Instant.now().minus(1, ChronoUnit.DAYS); + } + + private Instant notAfter() { + return Instant.now().plus(10, ChronoUnit.DAYS); + } + + private Path readResourceAsPath(final String path) throws Exception { + return Path.of(Objects.requireNonNull(this.getClass().getResource(path)).toURI()); + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/privacy/PrivacyNodeConfiguration.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/privacy/PrivacyNodeConfiguration.java index 8acb6c7da21..05c989e54aa 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/privacy/PrivacyNodeConfiguration.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/privacy/PrivacyNodeConfiguration.java @@ -15,53 +15,51 @@ package org.hyperledger.besu.tests.acceptance.dsl.node.configuration.privacy; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeConfiguration; -import org.hyperledger.orion.testutil.OrionKeyConfiguration; +import org.hyperledger.enclave.testutil.EnclaveKeyConfiguration; public class PrivacyNodeConfiguration { - private final int privacyAddress; - private final boolean isOnchainPrivacyGroupEnabled; - private final BesuNodeConfiguration besuConfig; - private final OrionKeyConfiguration orionConfig; + private final boolean isFlexiblePrivacyGroupEnabled; private final boolean isMultitenancyEnabled; + private final boolean isPrivacyPluginEnabled; + private final BesuNodeConfiguration besuConfig; + private final EnclaveKeyConfiguration keyConfig; PrivacyNodeConfiguration( - final int privacyAddress, - final BesuNodeConfiguration besuConfig, - final OrionKeyConfiguration orionConfig) { - this(privacyAddress, false, false, besuConfig, orionConfig); + final BesuNodeConfiguration besuConfig, final EnclaveKeyConfiguration keyConfig) { + this(false, false, false, besuConfig, keyConfig); } - PrivacyNodeConfiguration( - final int privacyAddress, - final boolean isOnchainPrivacyGroupEnabled, + public PrivacyNodeConfiguration( + final boolean isFlexiblePrivacyGroupEnabled, final boolean isMultitenancyEnabled, + final boolean isPrivacyPluginEnabled, final BesuNodeConfiguration besuConfig, - final OrionKeyConfiguration orionConfig) { - this.privacyAddress = privacyAddress; - this.isOnchainPrivacyGroupEnabled = isOnchainPrivacyGroupEnabled; + final EnclaveKeyConfiguration keyConfig) { + this.isFlexiblePrivacyGroupEnabled = isFlexiblePrivacyGroupEnabled; this.besuConfig = besuConfig; - this.orionConfig = orionConfig; + this.keyConfig = keyConfig; this.isMultitenancyEnabled = isMultitenancyEnabled; + this.isPrivacyPluginEnabled = isPrivacyPluginEnabled; } - public int getPrivacyAddress() { - return privacyAddress; - } - - public boolean isOnchainPrivacyGroupEnabled() { - return isOnchainPrivacyGroupEnabled; + public boolean isFlexiblePrivacyGroupEnabled() { + return isFlexiblePrivacyGroupEnabled; } public boolean isMultitenancyEnabled() { return isMultitenancyEnabled; } + public boolean isPrivacyPluginEnabled() { + return isPrivacyPluginEnabled; + } + public BesuNodeConfiguration getBesuConfig() { return besuConfig; } - public OrionKeyConfiguration getOrionKeyConfig() { - return orionConfig; + public EnclaveKeyConfiguration getKeyConfig() { + return keyConfig; } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/privacy/PrivacyNodeFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/privacy/PrivacyNodeFactory.java index ca390caff40..03188db8a27 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/privacy/PrivacyNodeFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/privacy/PrivacyNodeFactory.java @@ -14,22 +14,26 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.node.configuration.privacy; -import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeConfigurationBuilder; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.NodeConfigurationFactory; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory; import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccount; -import org.hyperledger.orion.testutil.OrionKeyConfiguration; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveKeyConfiguration; +import org.hyperledger.enclave.testutil.EnclaveType; import java.io.IOException; import java.net.URISyntaxException; +import java.util.Collections; +import java.util.List; +import java.util.Optional; import io.vertx.core.Vertx; +import org.testcontainers.containers.Network; public class PrivacyNodeFactory { - private final GenesisConfigurationFactory genesis = new GenesisConfigurationFactory(); private final NodeConfigurationFactory node = new NodeConfigurationFactory(); private final Vertx vertx; @@ -37,21 +41,28 @@ public PrivacyNodeFactory(final Vertx vertx) { this.vertx = vertx; } - private PrivacyNode create(final PrivacyNodeConfiguration privacyNodeConfig) throws IOException { - return new PrivacyNode(privacyNodeConfig, vertx); - } - - public PrivacyNode createPrivateTransactionEnabledMinerNode( - final String name, final PrivacyAccount privacyAccount) throws IOException { - return createPrivateTransactionEnabledMinerNode(name, privacyAccount, Address.PRIVACY); + public PrivacyNode create( + final PrivacyNodeConfiguration privacyNodeConfig, + final EnclaveType enclaveType, + final Optional containerNetwork) + throws IOException { + return new PrivacyNode(privacyNodeConfig, vertx, enclaveType, containerNetwork); } public PrivacyNode createPrivateTransactionEnabledMinerNode( - final String name, final PrivacyAccount privacyAccount, final int privacyAddress) + final String name, + final PrivacyAccount privacyAccount, + final EnclaveType enclaveType, + final Optional containerNetwork, + final boolean isFlexiblePrivacyGroupEnabled, + final boolean isMultitenancyEnabled, + final boolean isPrivacyPluginEnabled) throws IOException { return create( new PrivacyNodeConfiguration( - privacyAddress, + isFlexiblePrivacyGroupEnabled, + isMultitenancyEnabled, + isPrivacyPluginEnabled, new BesuNodeConfigurationBuilder() .name(name) .miningEnabled() @@ -59,114 +70,225 @@ public PrivacyNode createPrivateTransactionEnabledMinerNode( .webSocketEnabled() .enablePrivateTransactions() .keyFilePath(privacyAccount.getPrivateKeyPath()) + .plugins(Collections.singletonList("testPlugins")) + .extraCLIOptions(List.of("--plugin-privacy-service-encryption-prefix=0xAA")) .build(), - new OrionKeyConfiguration( - privacyAccount.getEnclaveKeyPaths(), privacyAccount.getEnclavePrivateKeyPaths()))); + new EnclaveKeyConfiguration( + privacyAccount.getEnclaveKeyPaths(), + privacyAccount.getEnclavePrivateKeyPaths(), + privacyAccount.getEnclaveEncryptorType())), + enclaveType, + containerNetwork); } public PrivacyNode createPrivateTransactionEnabledNode( - final String name, final PrivacyAccount privacyAccount) throws IOException { - return createPrivateTransactionEnabledNode(name, privacyAccount, Address.PRIVACY); - } - - public PrivacyNode createPrivateTransactionEnabledNode( - final String name, final PrivacyAccount privacyAccount, final int privacyAddress) + final String name, + final PrivacyAccount privacyAccount, + final EnclaveType enclaveType, + final Optional containerNetwork, + final boolean isFlexiblePrivacyGroupEnabled, + final boolean isMultitenancyEnabled, + final boolean isPrivacyPluginEnabled) throws IOException { return create( new PrivacyNodeConfiguration( - privacyAddress, + isFlexiblePrivacyGroupEnabled, + isMultitenancyEnabled, + isPrivacyPluginEnabled, new BesuNodeConfigurationBuilder() .name(name) .jsonRpcEnabled() .keyFilePath(privacyAccount.getPrivateKeyPath()) .enablePrivateTransactions() .webSocketEnabled() + .plugins(Collections.singletonList("testPlugins")) + .extraCLIOptions(List.of("--plugin-privacy-service-encryption-prefix=0xBB")) .build(), - new OrionKeyConfiguration( - privacyAccount.getEnclaveKeyPaths(), privacyAccount.getEnclavePrivateKeyPaths()))); - } - - public PrivacyNode createIbft2NodePrivacyMiningEnabled( - final String name, final PrivacyAccount privacyAccount) throws IOException { - return createIbft2NodePrivacyEnabled(name, privacyAccount, Address.PRIVACY, true); + new EnclaveKeyConfiguration( + privacyAccount.getEnclaveKeyPaths(), + privacyAccount.getEnclavePrivateKeyPaths(), + privacyAccount.getEnclaveEncryptorType())), + enclaveType, + containerNetwork); } public PrivacyNode createIbft2NodePrivacyEnabled( - final String name, final PrivacyAccount privacyAccount) throws IOException { - return createIbft2NodePrivacyEnabled(name, privacyAccount, Address.PRIVACY, false); + final String name, + final PrivacyAccount privacyAccount, + final boolean minerEnabled, + final EnclaveType enclaveType, + final Optional containerNetwork, + final boolean isFlexiblePrivacyGroupEnabled, + final boolean isMultitenancyEnabled, + final boolean isPrivacyPluginEnabled, + final String unrestrictedPrefix) + throws IOException { + return create( + new PrivacyNodeConfiguration( + isFlexiblePrivacyGroupEnabled, + isMultitenancyEnabled, + isPrivacyPluginEnabled, + new BesuNodeConfigurationBuilder() + .name(name) + .miningEnabled() + .jsonRpcConfiguration(node.createJsonRpcWithIbft2EnabledConfig(minerEnabled)) + .webSocketConfiguration(node.createWebSocketEnabledConfig()) + .devMode(false) + .genesisConfigProvider(GenesisConfigurationFactory::createPrivacyIbft2GenesisConfig) + .keyFilePath(privacyAccount.getPrivateKeyPath()) + .enablePrivateTransactions() + .plugins(Collections.singletonList("testPlugins")) + .extraCLIOptions( + List.of("--plugin-privacy-service-encryption-prefix=" + unrestrictedPrefix)) + .build(), + new EnclaveKeyConfiguration( + privacyAccount.getEnclaveKeyPaths(), + privacyAccount.getEnclavePrivateKeyPaths(), + privacyAccount.getEnclaveEncryptorType())), + enclaveType, + containerNetwork); } - public PrivacyNode createIbft2NodePrivacyEnabled( + public PrivacyNode createIbft2NodePrivacyEnabledWithGenesis( final String name, final PrivacyAccount privacyAccount, - final int privacyAddress, - final boolean minerEnabled) + final boolean minerEnabled, + final EnclaveType enclaveType, + final Optional containerNetwork, + final boolean isFlexiblePrivacyGroupEnabled, + final boolean isMultitenancyEnabled, + final boolean isPrivacyPluginEnabled, + final String unrestrictedPrefix) throws IOException { return create( new PrivacyNodeConfiguration( - privacyAddress, + isFlexiblePrivacyGroupEnabled, + isMultitenancyEnabled, + isPrivacyPluginEnabled, new BesuNodeConfigurationBuilder() .name(name) .miningEnabled() .jsonRpcConfiguration(node.createJsonRpcWithIbft2EnabledConfig(minerEnabled)) .webSocketConfiguration(node.createWebSocketEnabledConfig()) .devMode(false) - .genesisConfigProvider(genesis::createPrivacyIbft2GenesisConfig) + .genesisConfigProvider(GenesisConfigurationFactory::createPrivacyIbft2GenesisConfig) + .keyFilePath(privacyAccount.getPrivateKeyPath()) + .enablePrivateTransactions() + .plugins(Collections.singletonList("testPlugins")) + .extraCLIOptions( + List.of( + "--plugin-privacy-service-encryption-prefix=" + unrestrictedPrefix, + "--plugin-privacy-service-genesis-enabled=true")) + .build(), + new EnclaveKeyConfiguration( + privacyAccount.getEnclaveKeyPaths(), + privacyAccount.getEnclavePrivateKeyPaths(), + privacyAccount.getEnclaveEncryptorType())), + enclaveType, + containerNetwork); + } + + public PrivacyNode createQbftNodePrivacyEnabled( + final String name, + final PrivacyAccount privacyAccount, + final EnclaveType enclaveType, + final Optional containerNetwork, + final boolean isFlexiblePrivacyGroupEnabled, + final boolean isMultitenancyEnabled, + final boolean isPrivacyPluginEnabled, + final String unrestrictedPrefix) + throws IOException { + return create( + new PrivacyNodeConfiguration( + isFlexiblePrivacyGroupEnabled, + isMultitenancyEnabled, + isPrivacyPluginEnabled, + new BesuNodeConfigurationBuilder() + .name(name) + .miningEnabled() + .jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false)) + .webSocketConfiguration(node.createWebSocketEnabledConfig()) + .devMode(false) + .genesisConfigProvider(GenesisConfigurationFactory::createQbftGenesisConfig) .keyFilePath(privacyAccount.getPrivateKeyPath()) .enablePrivateTransactions() + .plugins(Collections.singletonList("testPlugins")) + .extraCLIOptions( + List.of("--plugin-privacy-service-encryption-prefix=" + unrestrictedPrefix)) .build(), - new OrionKeyConfiguration( - privacyAccount.getEnclaveKeyPaths(), privacyAccount.getEnclavePrivateKeyPaths()))); + new EnclaveKeyConfiguration( + privacyAccount.getEnclaveKeyPaths(), + privacyAccount.getEnclavePrivateKeyPaths(), + privacyAccount.getEnclaveEncryptorType())), + enclaveType, + containerNetwork); } - public PrivacyNode createOnChainPrivacyGroupEnabledMinerNode( + public PrivacyNode createFlexiblePrivacyGroupEnabledMinerNode( final String name, final PrivacyAccount privacyAccount, - final int privacyAddress, - final boolean multiTenancyEnabled) + final boolean multiTenancyEnabled, + final EnclaveType enclaveType, + final Optional containerNetwork) throws IOException, URISyntaxException { final BesuNodeConfigurationBuilder besuNodeConfigurationBuilder = new BesuNodeConfigurationBuilder(); if (multiTenancyEnabled) { - besuNodeConfigurationBuilder.jsonRpcAuthenticationConfiguration( - "authentication/auth_priv.toml"); + final String authPrivTomlPath = + EnclaveEncryptorType.EC.equals(privacyAccount.getEnclaveEncryptorType()) + ? "authentication/auth_priv_ec_pubkey.toml" + : "authentication/auth_priv.toml"; + besuNodeConfigurationBuilder.jsonRpcAuthenticationConfiguration(authPrivTomlPath); } return create( new PrivacyNodeConfiguration( - privacyAddress, true, multiTenancyEnabled, + false, besuNodeConfigurationBuilder .name(name) .miningEnabled() .jsonRpcEnabled() .webSocketEnabled() .enablePrivateTransactions() + .plugins(Collections.singletonList("testPlugins")) + .extraCLIOptions(List.of("--plugin-privacy-service-genesis-enabled=true")) .keyFilePath(privacyAccount.getPrivateKeyPath()) .build(), - new OrionKeyConfiguration( - privacyAccount.getEnclaveKeyPaths(), privacyAccount.getEnclavePrivateKeyPaths()))); + new EnclaveKeyConfiguration( + privacyAccount.getEnclaveKeyPaths(), + privacyAccount.getEnclavePrivateKeyPaths(), + privacyAccount.getEnclaveEncryptorType())), + enclaveType, + containerNetwork); } - public PrivacyNode createOnChainPrivacyGroupEnabledNode( + public PrivacyNode createFlexiblePrivacyGroupEnabledNode( final String name, final PrivacyAccount privacyAccount, - final int privacyAddress, - final boolean multiTenancyEnabled) + final boolean multiTenancyEnabled, + final EnclaveType enclaveType, + final Optional containerNetwork) throws IOException { return create( new PrivacyNodeConfiguration( - privacyAddress, true, multiTenancyEnabled, + false, new BesuNodeConfigurationBuilder() .name(name) .jsonRpcEnabled() .keyFilePath(privacyAccount.getPrivateKeyPath()) .enablePrivateTransactions() + .plugins(Collections.singletonList("testPlugins")) + .extraCLIOptions(List.of("--plugin-privacy-service-genesis-enabled=true")) .webSocketEnabled() .build(), - new OrionKeyConfiguration( - privacyAccount.getEnclaveKeyPaths(), privacyAccount.getEnclavePrivateKeyPaths()))); + new EnclaveKeyConfiguration( + privacyAccount.getEnclaveKeyPaths(), + privacyAccount.getEnclavePrivateKeyPaths(), + privacyAccount.getEnclaveEncryptorType())), + enclaveType, + containerNetwork); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/ParameterizedEnclaveTestBase.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/ParameterizedEnclaveTestBase.java new file mode 100644 index 00000000000..581fd71722d --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/ParameterizedEnclaveTestBase.java @@ -0,0 +1,74 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.privacy; + +import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.EC; +import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.NACL; +import static org.hyperledger.enclave.testutil.EnclaveType.NOOP; +import static org.hyperledger.enclave.testutil.EnclaveType.TESSERA; +import static org.web3j.utils.Restriction.RESTRICTED; +import static org.web3j.utils.Restriction.UNRESTRICTED; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.PluginCreateRandomPrivacyGroupIdTransaction; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.RestrictedCreatePrivacyGroupTransaction; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.util.Arrays; +import java.util.Collection; + +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.web3j.utils.Restriction; + +@RunWith(Parameterized.class) +public abstract class ParameterizedEnclaveTestBase extends PrivacyAcceptanceTestBase { + protected final Restriction restriction; + protected final EnclaveType enclaveType; + protected final EnclaveEncryptorType enclaveEncryptorType; + + protected ParameterizedEnclaveTestBase( + final Restriction restriction, + final EnclaveType enclaveType, + final EnclaveEncryptorType enclaveEncryptorType) { + this.restriction = restriction; + this.enclaveType = enclaveType; + this.enclaveEncryptorType = enclaveEncryptorType; + } + + @Parameters(name = "{0} tx with {1} enclave and {2} encryptor type") + public static Collection params() { + return Arrays.asList( + new Object[][] { + {RESTRICTED, TESSERA, NACL}, + {RESTRICTED, TESSERA, EC}, + {UNRESTRICTED, NOOP, EnclaveEncryptorType.NOOP} + }); + } + + public Transaction createPrivacyGroup( + final String name, final String description, final PrivacyNode... nodes) { + + if (restriction == RESTRICTED) { + return new RestrictedCreatePrivacyGroupTransaction(name, description, nodes); + } else if (restriction == UNRESTRICTED) { + return new PluginCreateRandomPrivacyGroupIdTransaction(); + } else { + throw new RuntimeException("Do not know how to handle " + restriction); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyAcceptanceTestBase.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyAcceptanceTestBase.java index 84669b95b68..8e12cbc7a80 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyAcceptanceTestBase.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyAcceptanceTestBase.java @@ -21,7 +21,6 @@ import org.hyperledger.besu.tests.acceptance.dsl.condition.net.NetConditions; import org.hyperledger.besu.tests.acceptance.dsl.condition.priv.PrivConditions; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.privacy.PrivacyNodeFactory; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; import org.hyperledger.besu.tests.acceptance.dsl.privacy.condition.PrivateContractVerifier; import org.hyperledger.besu.tests.acceptance.dsl.privacy.condition.PrivateTransactionVerifier; import org.hyperledger.besu.tests.acceptance.dsl.privacy.contract.PrivateContractTransactions; @@ -40,8 +39,6 @@ public class PrivacyAcceptanceTestBase { @ClassRule public static final TemporaryFolder privacy = new TemporaryFolder(); - protected static final long POW_CHAIN_ID = 2018; - protected final PrivacyTransactions privacyTransactions; protected final PrivateContractVerifier privateContractVerifier; protected final PrivateTransactionVerifier privateTransactionVerifier; @@ -49,7 +46,6 @@ public class PrivacyAcceptanceTestBase { protected final PrivateContractTransactions privateContractTransactions; protected final PrivConditions priv; protected final PrivacyCluster privacyCluster; - protected final PrivacyAccountResolver privacyAccountResolver; protected final ContractTransactions contractTransactions; protected final NetConditions net; protected final EthTransactions ethTransactions; @@ -65,7 +61,6 @@ public PrivacyAcceptanceTestBase() { privacyBesu = new PrivacyNodeFactory(vertx); privateContractTransactions = new PrivateContractTransactions(); privacyCluster = new PrivacyCluster(net); - privacyAccountResolver = new PrivacyAccountResolver(); priv = new PrivConditions( new org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyCluster.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyCluster.java index f6c9bb526d0..3d1fc148059 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyCluster.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyCluster.java @@ -15,22 +15,26 @@ package org.hyperledger.besu.tests.acceptance.dsl.privacy; import static java.util.Collections.emptyList; +import static java.util.function.Predicate.not; import org.hyperledger.besu.tests.acceptance.dsl.condition.net.NetConditions; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNodeRunner; import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode; +import org.hyperledger.enclave.testutil.EnclaveType; +import org.hyperledger.enclave.testutil.TesseraTestHarness; +import java.net.URI; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class PrivacyCluster { - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LoggerFactory.getLogger(PrivacyCluster.class); private final NetConditions net; private final BesuNodeRunner besuNodeRunner; @@ -61,11 +65,11 @@ public void startNodes(final List nodes) { throw new IllegalArgumentException("Can't start a cluster with no nodes"); } this.nodes = nodes; - this.runnableNodes = nodes.stream().map(n -> n.getBesu()).collect(Collectors.toList()); + this.runnableNodes = nodes.stream().map(PrivacyNode::getBesu).collect(Collectors.toList()); final Optional bootNode = selectAndStartBootnode(nodes); - nodes.stream() + nodes.parallelStream() .filter(node -> bootNode.map(boot -> boot != node).orElse(true)) .forEach(this::startNode); } @@ -80,18 +84,23 @@ public void awaitPeerCount(final List nodes) { node.awaitPeerDiscovery(net.awaitPeerCount(nodes.size() - 1)); } - verifyAllOrionNetworkConnections(); + verifyAllEnclaveNetworkConnections(); } public List getNodes() { return nodes; } - /** Verify that each Orion node has connected to every other Orion */ - public void verifyAllOrionNetworkConnections() { - for (int i = 0; i < nodes.size() - 1; i++) { - nodes.get(i).testOrionConnection(nodes.subList(i + 1, nodes.size())); - } + /** Verify that each Enclave has connected to every other Enclave */ + public void verifyAllEnclaveNetworkConnections() { + nodes.forEach( + privacyNode -> { + final List otherNodes = + nodes.stream() + .filter(not(privacyNode::equals)) + .collect(Collectors.toUnmodifiableList()); + privacyNode.testEnclaveConnection(otherNodes); + }); } public void stop() { @@ -101,7 +110,7 @@ public void stop() { } public void stopNode(final PrivacyNode node) { - node.getOrion().stop(); + node.getEnclave().stop(); besuNodeRunner.stopNode(node.getBesu()); } @@ -145,7 +154,24 @@ private void startNode(final PrivacyNode node, final boolean isBootNode) { .ifPresent(node.getConfiguration()::setGenesisConfig); if (!isBootNode) { - node.addOtherEnclaveNode(bootNode.getOrion().nodeUrl()); + if (bootNode.getEnclave().getEnclaveType() == EnclaveType.TESSERA) { + final URI otherNode = bootNode.getEnclave().nodeUrl(); + try { + // Substitute IP with hostname for test container network + final URI otherNodeHostname = + new URI( + otherNode.getScheme() + + "://" + + bootNode.getName() + + ":" + + TesseraTestHarness.p2pPort); + node.addOtherEnclaveNode(otherNodeHostname); + } catch (Exception ex) { + throw new RuntimeException("Invalid node URI"); + } + } else { + node.addOtherEnclaveNode(bootNode.getEnclave().nodeUrl()); + } } LOG.info( diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java index 308440f94d5..b59ac11c6cf 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java @@ -15,14 +15,18 @@ package org.hyperledger.besu.tests.acceptance.dsl.privacy; import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH; +import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_BACKGROUND_THREAD_COUNT; +import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_CACHE_CAPACITY; +import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_IS_HIGH_SPEC; +import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_MAX_OPEN_FILES; import org.hyperledger.besu.crypto.KeyPairUtil; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.enclave.Enclave; import org.hyperledger.besu.enclave.EnclaveClientException; import org.hyperledger.besu.enclave.EnclaveFactory; import org.hyperledger.besu.enclave.EnclaveIOException; import org.hyperledger.besu.enclave.EnclaveServerException; -import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.privacy.storage.PrivacyStorageProvider; import org.hyperledger.besu.ethereum.privacy.storage.keyvalue.PrivacyKeyValueStorageProviderBuilder; @@ -41,8 +45,10 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.privacy.PrivacyNodeConfiguration; import org.hyperledger.besu.tests.acceptance.dsl.privacy.condition.PrivateCondition; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; -import org.hyperledger.orion.testutil.OrionTestHarness; -import org.hyperledger.orion.testutil.OrionTestHarnessFactory; +import org.hyperledger.enclave.testutil.EnclaveTestHarness; +import org.hyperledger.enclave.testutil.EnclaveType; +import org.hyperledger.enclave.testutil.NoopEnclaveTestHarness; +import org.hyperledger.enclave.testutil.TesseraTestHarnessFactory; import java.io.IOException; import java.net.URI; @@ -51,37 +57,43 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import io.vertx.core.Vertx; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.awaitility.Awaitility; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.Network; public class PrivacyNode implements AutoCloseable { - private static final Logger LOG = LogManager.getLogger(); - private static final int MAX_OPEN_FILES = 1024; - private static final long CACHE_CAPACITY = 8388608; - private static final int MAX_BACKGROUND_COMPACTIONS = 4; - private static final int BACKGROUND_THREAD_COUNT = 4; + private static final Logger LOG = LoggerFactory.getLogger(PrivacyNode.class); - private final OrionTestHarness orion; + private final EnclaveTestHarness enclave; private final BesuNode besu; private final Vertx vertx; - private final boolean isOnchainPrivacyEnabled; + private final boolean isFlexiblePrivacyEnabled; private final boolean isMultitenancyEnabled; + private final boolean isPrivacyPluginEnabled; - public PrivacyNode(final PrivacyNodeConfiguration privacyConfiguration, final Vertx vertx) + public PrivacyNode( + final PrivacyNodeConfiguration privacyConfiguration, + final Vertx vertx, + final EnclaveType enclaveType, + final Optional containerNetwork) throws IOException { - final Path orionDir = Files.createTempDirectory("acctest-orion"); - this.orion = OrionTestHarnessFactory.create(orionDir, privacyConfiguration.getOrionKeyConfig()); + final Path enclaveDir = Files.createTempDirectory("acctest-orion"); + final BesuNodeConfiguration config = privacyConfiguration.getBesuConfig(); + this.enclave = + selectEnclave(enclaveType, enclaveDir, config, privacyConfiguration, containerNetwork); this.vertx = vertx; - final BesuNodeConfiguration besuConfig = privacyConfiguration.getBesuConfig(); + final BesuNodeConfiguration besuConfig = config; - isOnchainPrivacyEnabled = privacyConfiguration.isOnchainPrivacyGroupEnabled(); + isFlexiblePrivacyEnabled = privacyConfiguration.isFlexiblePrivacyGroupEnabled(); isMultitenancyEnabled = privacyConfiguration.isMultitenancyEnabled(); + isPrivacyPluginEnabled = privacyConfiguration.isPrivacyPluginEnabled(); this.besu = new BesuNode( @@ -89,13 +101,18 @@ public PrivacyNode(final PrivacyNodeConfiguration privacyConfiguration, final Ve besuConfig.getDataPath(), besuConfig.getMiningParameters(), besuConfig.getJsonRpcConfiguration(), + besuConfig.getEngineRpcConfiguration(), besuConfig.getWebSocketConfiguration(), + besuConfig.getJsonRpcIpcConfiguration(), besuConfig.getMetricsConfiguration(), besuConfig.getPermissioningConfiguration(), besuConfig.getKeyFilePath(), besuConfig.isDevMode(), + besuConfig.getNetwork(), besuConfig.getGenesisConfigProvider(), besuConfig.isP2pEnabled(), + besuConfig.getP2pPort(), + besuConfig.getTLSConfiguration(), besuConfig.getNetworkingConfiguration(), besuConfig.isDiscoveryEnabled(), besuConfig.isBootnodeEligible(), @@ -107,42 +124,56 @@ public PrivacyNode(final PrivacyNodeConfiguration privacyConfiguration, final Ve Collections.emptyList(), besuConfig.isDnsEnabled(), besuConfig.getPrivacyParameters(), - List.of()); - } - - public void testOrionConnection(final List otherNodes) { - LOG.info( - String.format( - "Testing Enclave connectivity between %s (%s) and %s (%s)", - besu.getName(), - orion.nodeUrl(), - Arrays.toString(otherNodes.stream().map(node -> node.besu.getName()).toArray()), - Arrays.toString(otherNodes.stream().map(node -> node.orion.nodeUrl()).toArray()))); - final EnclaveFactory factory = new EnclaveFactory(vertx); - final Enclave enclaveClient = factory.createVertxEnclave(orion.clientUrl()); - final String payload = "SGVsbG8sIFdvcmxkIQ=="; - final List to = - otherNodes.stream() - .map(node -> node.orion.getDefaultPublicKey()) - .collect(Collectors.toList()); - - Awaitility.await() - .until( - () -> { - try { - enclaveClient.send(payload, orion.getDefaultPublicKey(), to); - return true; - } catch (final EnclaveClientException - | EnclaveIOException - | EnclaveServerException e) { - LOG.warn("Waiting for enclave connectivity"); - return false; - } - }); - } - - public OrionTestHarness getOrion() { - return orion; + List.of(), + Optional.empty(), + Optional.empty(), + besuConfig.isStrictTxReplayProtectionEnabled(), + besuConfig.getEnvironment()); + } + + public void testEnclaveConnection(final List otherNodes) { + if (this.isPrivacyPluginEnabled) { + LOG.info("Skipping test as node has no enclave (isPrivacyPluginEnabled=true)"); + return; + } + + if (!otherNodes.isEmpty()) { + LOG.debug( + String.format( + "Testing Enclave connectivity between %s (%s) and %s (%s)", + besu.getName(), + enclave.nodeUrl(), + Arrays.toString(otherNodes.stream().map(node -> node.besu.getName()).toArray()), + Arrays.toString(otherNodes.stream().map(node -> node.enclave.nodeUrl()).toArray()))); + final EnclaveFactory factory = new EnclaveFactory(vertx); + final Enclave enclaveClient = factory.createVertxEnclave(enclave.clientUrl()); + final String payload = "SGVsbG8sIFdvcmxkIQ=="; + final List to = + otherNodes.stream() + .map(node -> node.enclave.getDefaultPublicKey()) + .collect(Collectors.toList()); + + Awaitility.await() + .until( + () -> { + try { + enclaveClient.send(payload, enclave.getDefaultPublicKey(), to); + return true; + } catch (final EnclaveClientException + | EnclaveIOException + | EnclaveServerException e) { + LOG.warn( + "Waiting for enclave connectivity between {} and {}: " + e.getMessage(), + enclave.getDefaultPublicKey(), + to.get(0)); + return false; + } + }); + } + } + + public EnclaveTestHarness getEnclave() { + return enclave; } public BesuNode getBesu() { @@ -151,17 +182,17 @@ public BesuNode getBesu() { public void stop() { besu.stop(); - orion.stop(); + enclave.stop(); } @Override public void close() { besu.close(); - orion.close(); + enclave.close(); } public void start(final BesuNodeRunner runner) { - orion.start(); + enclave.start(); final PrivacyParameters privacyParameters; @@ -169,19 +200,25 @@ public void start(final BesuNodeRunner runner) { final Path dataDir = Files.createTempDirectory("acctest-privacy"); final Path dbDir = dataDir.resolve(DATABASE_PATH); - privacyParameters = + var builder = new PrivacyParameters.Builder() .setEnabled(true) - .setEnclaveUrl(orion.clientUrl()) - .setEnclavePublicKeyUsingFile(orion.getConfig().publicKeys().get(0).toFile()) + .setEnclaveUrl(enclave.clientUrl()) .setStorageProvider(createKeyValueStorageProvider(dataDir, dbDir)) .setPrivateKeyPath(KeyPairUtil.getDefaultKeyFile(besu.homeDirectory()).toPath()) .setEnclaveFactory(new EnclaveFactory(vertx)) - .setOnchainPrivacyGroupsEnabled(isOnchainPrivacyEnabled) + .setFlexiblePrivacyGroupsEnabled(isFlexiblePrivacyEnabled) .setMultiTenancyEnabled(isMultitenancyEnabled) - .build(); + .setPrivacyPluginEnabled(isPrivacyPluginEnabled); + + if (enclave.getPublicKeyPaths().size() > 0) { + builder.setPrivacyUserIdUsingFile(enclave.getPublicKeyPaths().get(0).toFile()); + } + + privacyParameters = builder.build(); + } catch (final IOException e) { - throw new RuntimeException(); + throw new RuntimeException(e); } besu.setPrivacyParameters(privacyParameters); besu.start(runner); @@ -216,7 +253,7 @@ public void verify(final PrivateCondition expected) { } public String getEnclaveKey() { - return orion.getDefaultPublicKey(); + return enclave.getDefaultPublicKey(); } public String getTransactionSigningKey() { @@ -224,7 +261,7 @@ public String getTransactionSigningKey() { } public void addOtherEnclaveNode(final URI otherNode) { - orion.addOtherNode(otherNode); + enclave.addOtherNode(otherNode); } public NodeConfiguration getConfiguration() { @@ -239,14 +276,32 @@ private PrivacyStorageProvider createKeyValueStorageProvider( new RocksDBKeyValueStorageFactory( () -> new RocksDBFactoryConfiguration( - MAX_OPEN_FILES, - MAX_BACKGROUND_COMPACTIONS, - BACKGROUND_THREAD_COUNT, - CACHE_CAPACITY), + DEFAULT_MAX_OPEN_FILES, + DEFAULT_BACKGROUND_THREAD_COUNT, + DEFAULT_CACHE_CAPACITY, + DEFAULT_IS_HIGH_SPEC), Arrays.asList(KeyValueSegmentIdentifier.values()), RocksDBMetricsFactory.PRIVATE_ROCKS_DB_METRICS))) .withCommonConfiguration(new BesuConfigurationImpl(dataLocation, dbLocation)) .withMetricsSystem(new NoOpMetricsSystem()) .build(); } + + private EnclaveTestHarness selectEnclave( + final EnclaveType enclaveType, + final Path tempDir, + final BesuNodeConfiguration config, + final PrivacyNodeConfiguration privacyConfiguration, + final Optional containerNetwork) { + + switch (enclaveType) { + case ORION: + throw new UnsupportedOperationException("The Orion tests are getting deprecated"); + case TESSERA: + return TesseraTestHarnessFactory.create( + config.getName(), tempDir, privacyConfiguration.getKeyConfig(), containerNetwork); + default: + return new NoopEnclaveTestHarness(tempDir, privacyConfiguration.getKeyConfig()); + } + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivateTransactionGroupResponse.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivateTransactionGroupResponse.java index f3a139b0ec4..3cd7ca49a49 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivateTransactionGroupResponse.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivateTransactionGroupResponse.java @@ -21,7 +21,6 @@ public class PrivateTransactionGroupResponse { private final String from; private final String gas; private final String gasPrice; - private final String hash; private final String input; private final String nonce; private final String to; @@ -52,7 +51,6 @@ public PrivateTransactionGroupResponse( this.from = from; this.gas = gas; this.gasPrice = gasPrice; - this.hash = hash; this.input = input; this.nonce = nonce; this.to = to; @@ -77,10 +75,6 @@ public String getGasPrice() { return gasPrice; } - public String getHash() { - return hash; - } - public String getInput() { return input; } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/account/PrivacyAccount.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/account/PrivacyAccount.java index 07267342d52..c246dd585a5 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/account/PrivacyAccount.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/account/PrivacyAccount.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.privacy.account; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; + import java.io.File; import java.net.URL; import java.util.Arrays; @@ -23,27 +25,38 @@ public class PrivacyAccount { private final URL privateKeyPath; private final URL[] enclaveKeyPaths; private final URL[] enclavePrivateKeyPaths; + private final EnclaveEncryptorType enclaveEncryptorType; private PrivacyAccount( final URL privateKeyPath, final URL[] enclavePublicKeyPaths, - final URL[] enclavePrivateKeyPaths) { + final URL[] enclavePrivateKeyPaths, + final EnclaveEncryptorType enclaveEncryptorType) { this.privateKeyPath = privateKeyPath; this.enclaveKeyPaths = enclavePublicKeyPaths; this.enclavePrivateKeyPaths = enclavePrivateKeyPaths; + this.enclaveEncryptorType = enclaveEncryptorType; } public static PrivacyAccount create( - final URL privateKeyPath, final URL enclavePublicKeyPath, final URL enclavePrivateKeyPath) { + final URL privateKeyPath, + final URL enclavePublicKeyPath, + final URL enclavePrivateKeyPath, + final EnclaveEncryptorType enclaveEncryptorType) { return new PrivacyAccount( - privateKeyPath, new URL[] {enclavePublicKeyPath}, new URL[] {enclavePrivateKeyPath}); + privateKeyPath, + new URL[] {enclavePublicKeyPath}, + new URL[] {enclavePrivateKeyPath}, + enclaveEncryptorType); } public static PrivacyAccount create( final URL privateKeyPath, final URL[] enclavePublicKeyPath, - final URL[] enclavePrivateKeyPath) { - return new PrivacyAccount(privateKeyPath, enclavePublicKeyPath, enclavePrivateKeyPath); + final URL[] enclavePrivateKeyPath, + final EnclaveEncryptorType enclaveEncryptorType) { + return new PrivacyAccount( + privateKeyPath, enclavePublicKeyPath, enclavePrivateKeyPath, enclaveEncryptorType); } public String getPrivateKeyPath() { @@ -62,6 +75,10 @@ public String[] getEnclavePrivateKeyPaths() { .toArray(String[]::new); } + public EnclaveEncryptorType getEnclaveEncryptorType() { + return enclaveEncryptorType; + } + private String toStringResource(final URL path) { return path.getPath().substring(path.getPath().lastIndexOf(File.separator) + 1); } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/account/PrivacyAccountResolver.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/account/PrivacyAccountResolver.java index c8003d6a481..7a6e26f7bce 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/account/PrivacyAccountResolver.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/account/PrivacyAccountResolver.java @@ -14,59 +14,88 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.privacy.account; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; + import java.net.URL; /** Supplier of known funded accounts defined in dev.json */ -public class PrivacyAccountResolver { - - public static final PrivacyAccount ALICE = - PrivacyAccount.create( +public enum PrivacyAccountResolver { + ALICE { + @Override + public PrivacyAccount resolve(final EnclaveEncryptorType enclaveEncryptorType) { + return PrivacyAccount.create( resolveResource("key"), - resolveResource("orion_key_0.pub"), - resolveResource("orion_key_0.key")); - - public static final PrivacyAccount BOB = - PrivacyAccount.create( + enclaveEncryptorType.equals(EnclaveEncryptorType.EC) + ? resolveResource("enclave_ec_key_0.pub") + : resolveResource("enclave_key_0.pub"), + enclaveEncryptorType.equals(EnclaveEncryptorType.EC) + ? resolveResource("enclave_ec_key_0.key") + : resolveResource("enclave_key_0.key"), + enclaveEncryptorType); + } + }, + BOB { + @Override + public PrivacyAccount resolve(final EnclaveEncryptorType enclaveEncryptorType) { + return PrivacyAccount.create( resolveResource("key1"), - resolveResource("orion_key_1.pub"), - resolveResource("orion_key_1.key")); - - public static final PrivacyAccount CHARLIE = - PrivacyAccount.create( + enclaveEncryptorType.equals(EnclaveEncryptorType.EC) + ? resolveResource("enclave_ec_key_1.pub") + : resolveResource("enclave_key_1.pub"), + enclaveEncryptorType.equals(EnclaveEncryptorType.EC) + ? resolveResource("enclave_ec_key_1.key") + : resolveResource("enclave_key_1.key"), + enclaveEncryptorType); + } + }, + CHARLIE { + @Override + public PrivacyAccount resolve(final EnclaveEncryptorType enclaveEncryptorType) { + return PrivacyAccount.create( resolveResource("key2"), - resolveResource("orion_key_2.pub"), - resolveResource("orion_key_2.key")); - - public static final PrivacyAccount MULTI_TENANCY = - PrivacyAccount.create( + enclaveEncryptorType.equals(EnclaveEncryptorType.EC) + ? resolveResource("enclave_ec_key_2.pub") + : resolveResource("enclave_key_2.pub"), + enclaveEncryptorType.equals(EnclaveEncryptorType.EC) + ? resolveResource("enclave_ec_key_2.key") + : resolveResource("enclave_key_2.key"), + enclaveEncryptorType); + } + }, + MULTI_TENANCY { + @Override + public PrivacyAccount resolve(final EnclaveEncryptorType enclaveEncryptorType) { + return PrivacyAccount.create( resolveResource("key"), new URL[] { - resolveResource("orion_key_0.pub"), - resolveResource("orion_key_1.pub"), - resolveResource("orion_key_2.pub") + enclaveEncryptorType.equals(EnclaveEncryptorType.EC) + ? resolveResource("enclave_ec_key_0.pub") + : resolveResource("enclave_key_0.pub"), + enclaveEncryptorType.equals(EnclaveEncryptorType.EC) + ? resolveResource("enclave_ec_key_1.pub") + : resolveResource("enclave_key_1.pub"), + enclaveEncryptorType.equals(EnclaveEncryptorType.EC) + ? resolveResource("enclave_ec_key_2.pub") + : resolveResource("enclave_key_2.pub") }, new URL[] { - resolveResource("orion_key_0.key"), - resolveResource("orion_key_1.key"), - resolveResource("orion_key_2.key") - }); - - private static URL resolveResource(final String resource) { - return PrivacyAccountResolver.class.getClassLoader().getResource(resource); - } + enclaveEncryptorType.equals(EnclaveEncryptorType.EC) + ? resolveResource("enclave_ec_key_0.key") + : resolveResource("enclave_key_0.key"), + enclaveEncryptorType.equals(EnclaveEncryptorType.EC) + ? resolveResource("enclave_ec_key_1.key") + : resolveResource("enclave_key_1.key"), + enclaveEncryptorType.equals(EnclaveEncryptorType.EC) + ? resolveResource("enclave_ec_key_2.key") + : resolveResource("enclave_key_2.key") + }, + enclaveEncryptorType); + } + }; - public PrivacyAccountResolver() {} + public abstract PrivacyAccount resolve(final EnclaveEncryptorType enclaveEncryptorType); - public PrivacyAccount resolve(final Integer account) { - switch (account) { - case 0: - return ALICE; - case 1: - return BOB; - case 2: - return CHARLIE; - default: - throw new RuntimeException("Unknown privacy account"); - } + URL resolveResource(final String resource) { + return PrivacyAccountResolver.class.getClassLoader().getResource(resource); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/condition/ExpectValidFlexiblePrivacyGroupCreated.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/condition/ExpectValidFlexiblePrivacyGroupCreated.java new file mode 100644 index 00000000000..ce9c93d23d6 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/condition/ExpectValidFlexiblePrivacyGroupCreated.java @@ -0,0 +1,53 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.privacy.condition; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.PrivacyTransactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.awaitility.Awaitility; +import org.web3j.utils.Base64String; + +public class ExpectValidFlexiblePrivacyGroupCreated implements PrivateCondition { + + private final PrivacyTransactions transactions; + private final PrivacyRequestFactory.FlexiblePrivacyGroup expected; + + public ExpectValidFlexiblePrivacyGroupCreated( + final PrivacyTransactions transactions, + final PrivacyRequestFactory.FlexiblePrivacyGroup expected) { + this.transactions = transactions; + this.expected = expected; + } + + @Override + public void verify(final PrivacyNode node) { + Awaitility.waitAtMost(20, TimeUnit.SECONDS) + .untilAsserted( + () -> { + final List groups = + node.execute( + transactions.findFlexiblePrivacyGroup( + Base64String.unwrapList(expected.getMembers()))); + assertThat(groups).contains(expected); + }); + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/condition/ExpectValidOnChainPrivacyGroupCreated.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/condition/ExpectValidOnChainPrivacyGroupCreated.java deleted file mode 100644 index 7340c49243f..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/condition/ExpectValidOnChainPrivacyGroupCreated.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.privacy.condition; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.PrivacyTransactions; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory; - -import java.util.List; - -import org.awaitility.Awaitility; -import org.web3j.utils.Base64String; - -public class ExpectValidOnChainPrivacyGroupCreated implements PrivateCondition { - - private final PrivacyTransactions transactions; - private final PrivacyRequestFactory.OnChainPrivacyGroup expected; - - public ExpectValidOnChainPrivacyGroupCreated( - final PrivacyTransactions transactions, - final PrivacyRequestFactory.OnChainPrivacyGroup expected) { - this.transactions = transactions; - this.expected = expected; - } - - @Override - public void verify(final PrivacyNode node) { - Awaitility.await() - .untilAsserted( - () -> { - final List groups = - node.execute( - transactions.findOnChainPrivacyGroup( - Base64String.unwrapList(expected.getMembers()))); - assertThat(groups).contains(expected); - }); - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/condition/ExpectValidPrivateTransactionReceipt.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/condition/ExpectValidPrivateTransactionReceipt.java index 0c0cf98de49..ff8e0c2c5f4 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/condition/ExpectValidPrivateTransactionReceipt.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/condition/ExpectValidPrivateTransactionReceipt.java @@ -25,31 +25,60 @@ public class ExpectValidPrivateTransactionReceipt implements PrivateCondition { private final PrivacyTransactions transactions; private final String transactionHash; private final PrivateTransactionReceipt expectedReceipt; + private final boolean ignoreOutput; public ExpectValidPrivateTransactionReceipt( final PrivacyTransactions transactions, final String transactionHash, final PrivateTransactionReceipt expectedReceipt) { + this(transactions, transactionHash, expectedReceipt, false); + } + + public ExpectValidPrivateTransactionReceipt( + final PrivacyTransactions transactions, + final String transactionHash, + final PrivateTransactionReceipt expectedReceipt, + final boolean ignoreOutput) { this.transactions = transactions; this.transactionHash = transactionHash; this.expectedReceipt = expectedReceipt; + this.ignoreOutput = ignoreOutput; } @Override public void verify(final PrivacyNode node) { final PrivateTransactionReceipt actualReceipt = node.execute(transactions.getPrivateTransactionReceipt(transactionHash)); - assertThat(actualReceipt) - .usingRecursiveComparison() - .ignoringFields( - "commitmentHash", "logs", "blockHash", "blockNumber", "logsBloom", "transactionIndex") - // TODO: The fields blockHash, blockNumber, logsBloom and - // transactionIndex have to be ignored as the class - // org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt does not contain these - // fields. Once web3j has been updated these ignores can be removed. - .isEqualTo(expectedReceipt); - + if (ignoreOutput) { + // output can be ignored if it is checked separately + assertThat(actualReceipt) + .usingRecursiveComparison() + .ignoringFields( + "commitmentHash", + "logs", + "blockHash", + "blockNumber", + "logsBloom", + "transactionIndex", + "output") + // TODO: The fields blockHash, blockNumber, logsBloom, transactionIndex and output have to + // be ignored as + // the class org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt does not + // contain + // these fields. Once web3j has been updated these ignores can be removed. + .isEqualTo(expectedReceipt); + } else { + assertThat(actualReceipt) + .usingRecursiveComparison() + .ignoringFields( + "commitmentHash", "logs", "blockHash", "blockNumber", "logsBloom", "transactionIndex") + // TODO: The fields blockHash, blockNumber, logsBloom and transactionIndex have to be + // ignored as the class + // org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt does not contain + // these fields. Once web3j has been updated these ignores can be removed. + .isEqualTo(expectedReceipt); + } assertThat(actualReceipt.getLogs().size()).isEqualTo(expectedReceipt.getLogs().size()); for (int i = 0; i < expectedReceipt.getLogs().size(); i++) { diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/condition/PrivateTransactionVerifier.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/condition/PrivateTransactionVerifier.java index 23b67e9704d..cfd83b65821 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/condition/PrivateTransactionVerifier.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/condition/PrivateTransactionVerifier.java @@ -16,7 +16,7 @@ import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.PrivacyTransactions; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory.OnChainPrivacyGroup; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory.FlexiblePrivacyGroup; import java.util.Arrays; import java.util.List; @@ -39,6 +39,14 @@ public ExpectValidPrivateTransactionReceipt validPrivateTransactionReceipt( return new ExpectValidPrivateTransactionReceipt(transactions, transactionHash, receipt); } + public ExpectValidPrivateTransactionReceipt validPrivateTransactionReceipt( + final String transactionHash, + final PrivateTransactionReceipt receipt, + final boolean ignoreOutput) { + return new ExpectValidPrivateTransactionReceipt( + transactions, transactionHash, receipt, ignoreOutput); + } + public ExpectExistingPrivateTransactionReceipt existingPrivateTransactionReceipt( final String transactionHash) { return new ExpectExistingPrivateTransactionReceipt(transactions, transactionHash); @@ -53,7 +61,7 @@ public ExpectValidPrivacyGroupCreated validPrivacyGroupCreated(final PrivacyGrou return new ExpectValidPrivacyGroupCreated(transactions, expected); } - public ExpectValidOnChainPrivacyGroupCreated onChainPrivacyGroupExists( + public ExpectValidFlexiblePrivacyGroupCreated flexiblePrivacyGroupExists( final String privacyGroupId, final PrivacyNode... members) { final List membersEnclaveKeys = @@ -61,16 +69,16 @@ public ExpectValidOnChainPrivacyGroupCreated onChainPrivacyGroupExists( .map(PrivacyNode::getEnclaveKey) .map(Base64String::wrap) .collect(Collectors.toList()); - return onChainPrivacyGroupExists(privacyGroupId, membersEnclaveKeys); + return flexiblePrivacyGroupExists(privacyGroupId, membersEnclaveKeys); } - public ExpectValidOnChainPrivacyGroupCreated onChainPrivacyGroupExists( + public ExpectValidFlexiblePrivacyGroupCreated flexiblePrivacyGroupExists( final String privacyGroupId, final List membersEnclaveKeys) { - final OnChainPrivacyGroup expectedGroup = - new OnChainPrivacyGroup(privacyGroupId, membersEnclaveKeys); + final FlexiblePrivacyGroup expectedGroup = + new FlexiblePrivacyGroup(privacyGroupId, membersEnclaveKeys); - return new ExpectValidOnChainPrivacyGroupCreated(transactions, expectedGroup); + return new ExpectValidFlexiblePrivacyGroupCreated(transactions, expectedGroup); } public ExpectInternalErrorPrivateTransactionReceipt internalErrorPrivateTransactionReceipt( diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/CallOnChainPermissioningPrivateSmartContractFunction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/CallOnChainPermissioningPrivateSmartContractFunction.java deleted file mode 100644 index 9fe697fc66f..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/CallOnChainPermissioningPrivateSmartContractFunction.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.privacy.contract; - -import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; - -import java.io.IOException; -import java.math.BigInteger; - -import org.web3j.crypto.Credentials; -import org.web3j.protocol.besu.Besu; -import org.web3j.tx.BesuPrivateTransactionManager; -import org.web3j.tx.PrivateTransactionManager; -import org.web3j.tx.gas.BesuPrivacyGasProvider; -import org.web3j.utils.Base64String; - -public class CallOnChainPermissioningPrivateSmartContractFunction implements Transaction { - - private static final BesuPrivacyGasProvider GAS_PROVIDER = - new BesuPrivacyGasProvider(BigInteger.valueOf(1000)); - private final String contractAddress; - private final String encodedFunction; - private final Credentials senderCredentials; - private final long chainId; - private final Base64String privateFrom; - private final Base64String privacyGroupId; - - public CallOnChainPermissioningPrivateSmartContractFunction( - final String contractAddress, - final String encodedFunction, - final String transactionSigningKey, - final long chainId, - final String privateFrom, - final String privacyGroupId) { - - this.contractAddress = contractAddress; - this.encodedFunction = encodedFunction; - this.senderCredentials = Credentials.create(transactionSigningKey); - this.chainId = chainId; - this.privateFrom = Base64String.wrap(privateFrom); - this.privacyGroupId = Base64String.wrap(privacyGroupId); - } - - @Override - public String execute(final NodeRequests node) { - final Besu besu = node.privacy().getBesuClient(); - - final PrivateTransactionManager privateTransactionManager = - new BesuPrivateTransactionManager( - besu, GAS_PROVIDER, senderCredentials, chainId, privateFrom, privacyGroupId); - - try { - return privateTransactionManager - .sendTransaction( - GAS_PROVIDER.getGasPrice(), - GAS_PROVIDER.getGasLimit(), - contractAddress, - encodedFunction, - null) - .getTransactionHash(); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/CallOnchainPermissioningPrivateSmartContractFunction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/CallOnchainPermissioningPrivateSmartContractFunction.java new file mode 100644 index 00000000000..0820d65d1d5 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/CallOnchainPermissioningPrivateSmartContractFunction.java @@ -0,0 +1,73 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.privacy.contract; + +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; +import java.math.BigInteger; + +import org.web3j.crypto.Credentials; +import org.web3j.tx.PrivateTransactionManager; +import org.web3j.tx.gas.BesuPrivacyGasProvider; +import org.web3j.utils.Base64String; +import org.web3j.utils.Restriction; + +public class CallOnchainPermissioningPrivateSmartContractFunction implements Transaction { + + private static final BesuPrivacyGasProvider GAS_PROVIDER = + new BesuPrivacyGasProvider(BigInteger.valueOf(1000)); + private final String contractAddress; + private final String encodedFunction; + private final Credentials senderCredentials; + private final Base64String privateFrom; + private final Base64String privacyGroupId; + + public CallOnchainPermissioningPrivateSmartContractFunction( + final String contractAddress, + final String encodedFunction, + final String transactionSigningKey, + final String privateFrom, + final String privacyGroupId) { + + this.contractAddress = contractAddress; + this.encodedFunction = encodedFunction; + this.senderCredentials = Credentials.create(transactionSigningKey); + this.privateFrom = Base64String.wrap(privateFrom); + this.privacyGroupId = Base64String.wrap(privacyGroupId); + } + + @Override + public String execute(final NodeRequests node) { + final PrivateTransactionManager privateTransactionManager = + node.privacy() + .getTransactionManager( + senderCredentials, privateFrom, privacyGroupId, Restriction.RESTRICTED); + + try { + return privateTransactionManager + .sendTransaction( + GAS_PROVIDER.getGasPrice(), + GAS_PROVIDER.getGasLimit(), + contractAddress, + encodedFunction, + null) + .getTransactionHash(); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/CallPrivateSmartContractFunction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/CallPrivateSmartContractFunction.java index cf483ccf08d..d3ec7989e5e 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/CallPrivateSmartContractFunction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/CallPrivateSmartContractFunction.java @@ -22,12 +22,10 @@ import java.util.List; import org.web3j.crypto.Credentials; -import org.web3j.protocol.besu.Besu; -import org.web3j.tx.BesuPrivateTransactionManager; -import org.web3j.tx.LegacyPrivateTransactionManager; import org.web3j.tx.PrivateTransactionManager; import org.web3j.tx.gas.BesuPrivacyGasProvider; import org.web3j.utils.Base64String; +import org.web3j.utils.Restriction; public class CallPrivateSmartContractFunction implements Transaction { @@ -36,7 +34,7 @@ public class CallPrivateSmartContractFunction implements Transaction { private final String contractAddress; private final String encodedFunction; private final Credentials senderCredentials; - private final long chainId; + private final Restriction restriction; private final Base64String privateFrom; private final List privateFor; private final Base64String privacyGroupId; @@ -45,14 +43,14 @@ public CallPrivateSmartContractFunction( final String contractAddress, final String encodedFunction, final String transactionSigningKey, - final long chainId, + final Restriction restriction, final String privateFrom, final List privateFor) { this( contractAddress, encodedFunction, transactionSigningKey, - chainId, + restriction, privateFrom, privateFor, null); @@ -62,14 +60,14 @@ public CallPrivateSmartContractFunction( final String contractAddress, final String encodedFunction, final String transactionSigningKey, - final long chainId, + final Restriction restriction, final String privateFrom, final String privacyGroupId) { this( contractAddress, encodedFunction, transactionSigningKey, - chainId, + restriction, privateFrom, null, privacyGroupId); @@ -79,7 +77,7 @@ private CallPrivateSmartContractFunction( final String contractAddress, final String encodedFunction, final String transactionSigningKey, - final long chainId, + final Restriction restriction, final String privateFrom, final List privateFor, final String privacyGroupId) { @@ -87,7 +85,7 @@ private CallPrivateSmartContractFunction( this.contractAddress = contractAddress; this.encodedFunction = encodedFunction; this.senderCredentials = Credentials.create(transactionSigningKey); - this.chainId = chainId; + this.restriction = restriction; this.privateFrom = Base64String.wrap(privateFrom); this.privateFor = privateFor != null ? Base64String.wrapList(privateFor) : null; this.privacyGroupId = privacyGroupId != null ? Base64String.wrap(privacyGroupId) : null; @@ -95,17 +93,16 @@ private CallPrivateSmartContractFunction( @Override public String execute(final NodeRequests node) { - final Besu besu = node.privacy().getBesuClient(); - final PrivateTransactionManager privateTransactionManager; - if (privacyGroupId != null) { + + if (privateFor != null) { privateTransactionManager = - new BesuPrivateTransactionManager( - besu, GAS_PROVIDER, senderCredentials, chainId, privateFrom, privacyGroupId); + node.privacy() + .getTransactionManager(senderCredentials, privateFrom, privateFor, restriction); } else { privateTransactionManager = - new LegacyPrivateTransactionManager( - besu, GAS_PROVIDER, senderCredentials, chainId, privateFrom, privateFor); + node.privacy() + .getTransactionManager(senderCredentials, privateFrom, privacyGroupId, restriction); } try { diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/DeployPrivateSmartContractTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/DeployPrivateSmartContractTransaction.java index a39c6866d7e..ed7ca9cd9af 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/DeployPrivateSmartContractTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/DeployPrivateSmartContractTransaction.java @@ -25,12 +25,12 @@ import org.web3j.protocol.Web3j; import org.web3j.protocol.core.RemoteCall; import org.web3j.tx.Contract; -import org.web3j.tx.LegacyPrivateTransactionManager; import org.web3j.tx.PrivateTransactionManager; import org.web3j.tx.TransactionManager; import org.web3j.tx.gas.BesuPrivacyGasProvider; import org.web3j.tx.gas.ContractGasProvider; import org.web3j.utils.Base64String; +import org.web3j.utils.Restriction; public class DeployPrivateSmartContractTransaction implements Transaction { @@ -40,33 +40,28 @@ public class DeployPrivateSmartContractTransaction implement private final Class clazz; private final Credentials senderCredentials; - private final long chainId; private final Base64String privateFrom; private final List privateFor; public DeployPrivateSmartContractTransaction( final Class clazz, final String transactionSigningKey, - final long chainId, final String privateFrom, final List privateFor) { this.clazz = clazz; this.senderCredentials = Credentials.create(transactionSigningKey); - this.chainId = chainId; this.privateFrom = Base64String.wrap(privateFrom); this.privateFor = Base64String.wrapList(privateFor); } @Override public T execute(final NodeRequests node) { + final PrivateTransactionManager privateTransactionManager = - new LegacyPrivateTransactionManager( - node.privacy().getBesuClient(), - GAS_PROVIDER, - senderCredentials, - chainId, - privateFrom, - privateFor); + node.privacy() + .getTransactionManager( + senderCredentials, privateFrom, privateFor, Restriction.RESTRICTED); + try { final Method method = clazz.getMethod( diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/DeployPrivateSmartContractWithPrivacyGroupIdTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/DeployPrivateSmartContractWithPrivacyGroupIdTransaction.java index 28771295a36..c5d0116431a 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/DeployPrivateSmartContractWithPrivacyGroupIdTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/DeployPrivateSmartContractWithPrivacyGroupIdTransaction.java @@ -23,13 +23,13 @@ import org.web3j.crypto.Credentials; import org.web3j.protocol.Web3j; import org.web3j.protocol.core.RemoteCall; -import org.web3j.tx.BesuPrivateTransactionManager; import org.web3j.tx.Contract; import org.web3j.tx.PrivateTransactionManager; import org.web3j.tx.TransactionManager; import org.web3j.tx.gas.BesuPrivacyGasProvider; import org.web3j.tx.gas.ContractGasProvider; import org.web3j.utils.Base64String; +import org.web3j.utils.Restriction; public class DeployPrivateSmartContractWithPrivacyGroupIdTransaction implements Transaction { @@ -40,33 +40,30 @@ public class DeployPrivateSmartContractWithPrivacyGroupIdTransaction clazz; private final Credentials senderCredentials; - private final long chainId; + private final Restriction restriction; private final Base64String privateFrom; private final Base64String privacyGroupId; public DeployPrivateSmartContractWithPrivacyGroupIdTransaction( final Class clazz, final String transactionSigningKey, - final long chainId, + final Restriction restriction, final String privateFrom, final String privacyGroupId) { this.clazz = clazz; this.senderCredentials = Credentials.create(transactionSigningKey); - this.chainId = chainId; + this.restriction = restriction; this.privateFrom = Base64String.wrap(privateFrom); this.privacyGroupId = Base64String.wrap(privacyGroupId); } @Override public T execute(final NodeRequests node) { + final PrivateTransactionManager privateTransactionManager = - new BesuPrivateTransactionManager( - node.privacy().getBesuClient(), - GAS_PROVIDER, - senderCredentials, - chainId, - privateFrom, - privacyGroupId); + node.privacy() + .getTransactionManager(senderCredentials, privateFrom, privacyGroupId, restriction); + try { final Method method = clazz.getMethod( diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/LoadPrivateSmartContractTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/LoadPrivateSmartContractTransaction.java index a42cb80bcdc..aac5f293f9b 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/LoadPrivateSmartContractTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/LoadPrivateSmartContractTransaction.java @@ -24,12 +24,12 @@ import org.web3j.crypto.Credentials; import org.web3j.protocol.Web3j; import org.web3j.tx.Contract; -import org.web3j.tx.LegacyPrivateTransactionManager; import org.web3j.tx.PrivateTransactionManager; import org.web3j.tx.TransactionManager; import org.web3j.tx.gas.BesuPrivacyGasProvider; import org.web3j.tx.gas.ContractGasProvider; import org.web3j.utils.Base64String; +import org.web3j.utils.Restriction; public class LoadPrivateSmartContractTransaction implements Transaction { private static final BesuPrivacyGasProvider GAS_PROVIDER = @@ -38,7 +38,6 @@ public class LoadPrivateSmartContractTransaction implements private final Class clazz; private final Credentials senderCredentials; - private final long chainId; private final Base64String privateFrom; private final List privateFor; private final String contractAddress; @@ -47,14 +46,12 @@ public LoadPrivateSmartContractTransaction( final String contractAddress, final Class clazz, final String transactionSigningKey, - final long chainId, final String privateFrom, final List privateFor) { this.contractAddress = contractAddress; this.clazz = clazz; this.senderCredentials = Credentials.create(transactionSigningKey); - this.chainId = chainId; this.privateFrom = Base64String.wrap(privateFrom); this.privateFor = Base64String.wrapList(privateFor); } @@ -63,13 +60,10 @@ public LoadPrivateSmartContractTransaction( @Override public T execute(final NodeRequests node) { final PrivateTransactionManager privateTransactionManager = - new LegacyPrivateTransactionManager( - node.privacy().getBesuClient(), - GAS_PROVIDER, - senderCredentials, - chainId, - privateFrom, - privateFor); + node.privacy() + .getTransactionManager( + senderCredentials, privateFrom, privateFor, Restriction.RESTRICTED); + try { final Method method = clazz.getMethod( diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/LoadPrivateSmartContractTransactionWithPrivacyGroupId.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/LoadPrivateSmartContractTransactionWithPrivacyGroupId.java new file mode 100644 index 00000000000..11a5045752c --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/LoadPrivateSmartContractTransactionWithPrivacyGroupId.java @@ -0,0 +1,88 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.privacy.contract; + +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.lang.reflect.Method; +import java.math.BigInteger; + +import org.web3j.crypto.Credentials; +import org.web3j.protocol.Web3j; +import org.web3j.tx.Contract; +import org.web3j.tx.PrivateTransactionManager; +import org.web3j.tx.TransactionManager; +import org.web3j.tx.gas.BesuPrivacyGasProvider; +import org.web3j.tx.gas.ContractGasProvider; +import org.web3j.utils.Base64String; +import org.web3j.utils.Restriction; + +public class LoadPrivateSmartContractTransactionWithPrivacyGroupId + implements Transaction { + + private static final BesuPrivacyGasProvider GAS_PROVIDER = + new BesuPrivacyGasProvider(BigInteger.valueOf(1000)); + private static final Object METHOD_IS_STATIC = null; + + private final Class clazz; + private final Credentials senderCredentials; + private final Base64String privateFrom; + private final Base64String privacyGroupId; + private final String contractAddress; + + public LoadPrivateSmartContractTransactionWithPrivacyGroupId( + final String contractAddress, + final Class clazz, + final String transactionSigningKey, + final String privateFrom, + final String privacyGroupId) { + + this.contractAddress = contractAddress; + this.clazz = clazz; + this.senderCredentials = Credentials.create(transactionSigningKey); + this.privateFrom = Base64String.wrap(privateFrom); + this.privacyGroupId = Base64String.wrap(privacyGroupId); + } + + @SuppressWarnings("unchecked") + @Override + public T execute(final NodeRequests node) { + final PrivateTransactionManager privateTransactionManager = + node.privacy() + .getTransactionManager( + senderCredentials, privateFrom, privacyGroupId, Restriction.RESTRICTED); + + try { + final Method method = + clazz.getMethod( + "load", + String.class, + Web3j.class, + TransactionManager.class, + ContractGasProvider.class); + + return (T) + method.invoke( + METHOD_IS_STATIC, + contractAddress, + node.privacy().getBesuClient(), + privateTransactionManager, + GAS_PROVIDER); + } catch (final Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/PrivateContractTransactions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/PrivateContractTransactions.java index e33e048c9e1..97e7e654018 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/PrivateContractTransactions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/PrivateContractTransactions.java @@ -18,6 +18,7 @@ import java.util.List; import org.web3j.tx.Contract; +import org.web3j.utils.Restriction; public class PrivateContractTransactions { @@ -26,45 +27,54 @@ public class PrivateContractTransactions { createSmartContractWithPrivacyGroupId( final Class clazz, final String transactionSigningKey, - final long chainId, + final Restriction restriction, final String privateFrom, final String privacyGroupId) { return new DeployPrivateSmartContractWithPrivacyGroupIdTransaction<>( - clazz, transactionSigningKey, chainId, privateFrom, privacyGroupId); + clazz, transactionSigningKey, restriction, privateFrom, privacyGroupId); + } + + public + DeployPrivateSmartContractWithPrivacyGroupIdTransaction + createSmartContractWithPrivacyGroupId( + final Class clazz, + final String transactionSigningKey, + final String privateFrom, + final String privacyGroupId) { + return new DeployPrivateSmartContractWithPrivacyGroupIdTransaction<>( + clazz, transactionSigningKey, Restriction.RESTRICTED, privateFrom, privacyGroupId); } public DeployPrivateSmartContractTransaction createSmartContract( final Class clazz, final String transactionSigningKey, - final long chainId, final String privateFrom, final String... privateFor) { return createSmartContract( - clazz, transactionSigningKey, chainId, privateFrom, Arrays.asList(privateFor)); + clazz, transactionSigningKey, privateFrom, Arrays.asList(privateFor)); } public DeployPrivateSmartContractTransaction createSmartContract( final Class clazz, final String transactionSigningKey, - final long chainId, final String privateFrom, final List privateFor) { return new DeployPrivateSmartContractTransaction<>( - clazz, transactionSigningKey, chainId, privateFrom, privateFor); + clazz, transactionSigningKey, privateFrom, privateFor); } public CallPrivateSmartContractFunction callSmartContract( final String contractAddress, final String encodedFunction, final String transactionSigningKey, - final long chainId, + final Restriction restriction, final String privateFrom, final String... privateFor) { return callSmartContract( contractAddress, encodedFunction, transactionSigningKey, - chainId, + restriction, privateFrom, Arrays.asList(privateFor)); } @@ -73,25 +83,30 @@ public CallPrivateSmartContractFunction callSmartContract( final String contractAddress, final String encodedFunction, final String transactionSigningKey, - final long chainId, + final Restriction restriction, final String privateFrom, final List privateFor) { return new CallPrivateSmartContractFunction( - contractAddress, encodedFunction, transactionSigningKey, chainId, privateFrom, privateFor); + contractAddress, + encodedFunction, + transactionSigningKey, + restriction, + privateFrom, + privateFor); } public CallPrivateSmartContractFunction callSmartContractWithPrivacyGroupId( final String contractAddress, final String encodedFunction, final String transactionSigningKey, - final long chainId, + final Restriction restriction, final String privateFrom, final String privacyGroupId) { return new CallPrivateSmartContractFunction( contractAddress, encodedFunction, transactionSigningKey, - chainId, + restriction, privateFrom, privacyGroupId); } @@ -100,42 +115,40 @@ public LoadPrivateSmartContractTransaction loadSmartCont final String contractAddress, final Class clazz, final String transactionSigningKey, - final long chainId, final String privateFrom, final String... privateFor) { return loadSmartContract( - contractAddress, - clazz, - transactionSigningKey, - chainId, - privateFrom, - Arrays.asList(privateFor)); + contractAddress, clazz, transactionSigningKey, privateFrom, Arrays.asList(privateFor)); } - private LoadPrivateSmartContractTransaction loadSmartContract( + public LoadPrivateSmartContractTransaction loadSmartContract( final String contractAddress, final Class clazz, final String transactionSigningKey, - final long chainId, final String privateFrom, final List privateFor) { return new LoadPrivateSmartContractTransaction<>( - contractAddress, clazz, transactionSigningKey, chainId, privateFrom, privateFor); + contractAddress, clazz, transactionSigningKey, privateFrom, privateFor); } - public CallOnChainPermissioningPrivateSmartContractFunction callOnChainPermissioningSmartContract( + public + LoadPrivateSmartContractTransactionWithPrivacyGroupId loadSmartContractWithPrivacyGroupId( + final String contractAddress, + final Class clazz, + final String transactionSigningKey, + final String privateFrom, + final String privacyGroupId) { + return new LoadPrivateSmartContractTransactionWithPrivacyGroupId<>( + contractAddress, clazz, transactionSigningKey, privateFrom, privacyGroupId); + } + + public CallOnchainPermissioningPrivateSmartContractFunction callOnchainPermissioningSmartContract( final String contractAddress, final String encodedFunction, final String transactionSigningKey, - final long chainId, final String privateFrom, final String privacyGroupId) { - return new CallOnChainPermissioningPrivateSmartContractFunction( - contractAddress, - encodedFunction, - transactionSigningKey, - chainId, - privateFrom, - privacyGroupId); + return new CallOnchainPermissioningPrivateSmartContractFunction( + contractAddress, encodedFunction, transactionSigningKey, privateFrom, privacyGroupId); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/AddToFlexiblePrivacyGroupTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/AddToFlexiblePrivacyGroupTransaction.java new file mode 100644 index 00000000000..9c879bc421c --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/AddToFlexiblePrivacyGroupTransaction.java @@ -0,0 +1,57 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.web3j.crypto.Credentials; +import org.web3j.utils.Base64String; + +public class AddToFlexiblePrivacyGroupTransaction implements Transaction { + private final Base64String privacyGroupId; + private final PrivacyNode adder; + private final List addresses; + private final Credentials signer; + + public AddToFlexiblePrivacyGroupTransaction( + final String privacyGroupId, + final PrivacyNode adder, + final Credentials signer, + final PrivacyNode... nodes) { + this.privacyGroupId = Base64String.wrap(privacyGroupId); + this.adder = adder; + this.signer = signer; + this.addresses = + Arrays.stream(nodes) + .map(n -> n.getEnclave().getDefaultPublicKey()) + .collect(Collectors.toList()); + } + + @Override + public String execute(final NodeRequests node) { + try { + return node.privacy().privxAddToPrivacyGroup(privacyGroupId, adder, signer, addresses); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/AddToOnChainPrivacyGroupTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/AddToOnChainPrivacyGroupTransaction.java deleted file mode 100644 index b802d231937..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/AddToOnChainPrivacyGroupTransaction.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; - -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; - -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import org.web3j.crypto.Credentials; -import org.web3j.utils.Base64String; - -public class AddToOnChainPrivacyGroupTransaction implements Transaction { - private final Base64String privacyGroupId; - private final PrivacyNode adder; - private final List addresses; - private final Credentials signer; - - public AddToOnChainPrivacyGroupTransaction( - final String privacyGroupId, - final PrivacyNode adder, - final Credentials signer, - final PrivacyNode... nodes) { - this.privacyGroupId = Base64String.wrap(privacyGroupId); - this.adder = adder; - this.signer = signer; - this.addresses = - Arrays.stream(nodes) - .map(n -> n.getOrion().getDefaultPublicKey()) - .collect(Collectors.toList()); - } - - @Override - public String execute(final NodeRequests node) { - try { - return node.privacy().privxAddToPrivacyGroup(privacyGroupId, adder, signer, addresses); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/CreateFlexiblePrivacyGroupTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/CreateFlexiblePrivacyGroupTransaction.java new file mode 100644 index 00000000000..bf2814a4b15 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/CreateFlexiblePrivacyGroupTransaction.java @@ -0,0 +1,46 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory.PrivxCreatePrivacyGroupResponse; + +import java.io.IOException; +import java.util.List; + +public class CreateFlexiblePrivacyGroupTransaction + implements Transaction { + private final PrivacyNode creator; + private final List addresses; + private final String privateFrom; + + CreateFlexiblePrivacyGroupTransaction( + final PrivacyNode creator, final String privateFrom, final List addresses) { + this.creator = creator; + this.addresses = addresses; + this.privateFrom = privateFrom; + } + + @Override + public PrivxCreatePrivacyGroupResponse execute(final NodeRequests node) { + try { + return node.privacy().privxCreatePrivacyGroup(creator, privateFrom, addresses); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/CreateOnChainPrivacyGroupTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/CreateOnChainPrivacyGroupTransaction.java deleted file mode 100644 index 3b09d8cfe42..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/CreateOnChainPrivacyGroupTransaction.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; - -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory.PrivxCreatePrivacyGroupResponse; - -import java.io.IOException; -import java.util.List; - -public class CreateOnChainPrivacyGroupTransaction - implements Transaction { - private final PrivacyNode creator; - private final List addresses; - private final String privateFrom; - - CreateOnChainPrivacyGroupTransaction( - final PrivacyNode creator, final String privateFrom, final List addresses) { - this.creator = creator; - this.addresses = addresses; - this.privateFrom = privateFrom; - } - - @Override - public PrivxCreatePrivacyGroupResponse execute(final NodeRequests node) { - try { - return node.privacy().privxCreatePrivacyGroup(creator, privateFrom, addresses); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/CreatePrivacyGroupTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/CreatePrivacyGroupTransaction.java deleted file mode 100644 index 34118d426d8..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/CreatePrivacyGroupTransaction.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; - -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; - -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import org.web3j.protocol.besu.Besu; -import org.web3j.protocol.besu.response.privacy.PrivCreatePrivacyGroup; -import org.web3j.utils.Base64String; - -public class CreatePrivacyGroupTransaction implements Transaction { - private final String name; - private final String description; - private final List addresses; - - public CreatePrivacyGroupTransaction( - final String name, final String description, final PrivacyNode... nodes) { - this.name = name; - this.description = description; - this.addresses = - Arrays.stream(nodes) - .map(n -> Base64String.wrap(n.getOrion().getDefaultPublicKey())) - .collect(Collectors.toList()); - } - - @Override - public String execute(final NodeRequests node) { - final Besu besu = node.privacy().getBesuClient(); - try { - final PrivCreatePrivacyGroup result = - besu.privCreatePrivacyGroup(addresses, name, description).send(); - if (result.hasError()) { - throw new RuntimeException(result.getError().getMessage()); - } else { - return result.getPrivacyGroupId().toString(); - } - } catch (final IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/FindFlexiblePrivacyGroupTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/FindFlexiblePrivacyGroupTransaction.java new file mode 100644 index 00000000000..0e8ac95b4f6 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/FindFlexiblePrivacyGroupTransaction.java @@ -0,0 +1,52 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory.PrivxFindPrivacyGroupResponse; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import org.web3j.utils.Base64String; + +public class FindFlexiblePrivacyGroupTransaction + implements Transaction> { + private final List nodes; + + public FindFlexiblePrivacyGroupTransaction(final List nodeEnclaveKeys) { + this.nodes = nodeEnclaveKeys.stream().map(Base64String::wrap).collect(Collectors.toList()); + } + + @Override + public List execute(final NodeRequests node) { + try { + PrivxFindPrivacyGroupResponse result = + node.privacy().privxFindFlexiblePrivacyGroup(nodes).send(); + assertThat(result).isNotNull(); + if (result.hasError()) { + throw new RuntimeException(result.getError().getMessage()); + } + return result.getGroups(); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/FindOnChainPrivacyGroupTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/FindOnChainPrivacyGroupTransaction.java deleted file mode 100644 index 87069b111e8..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/FindOnChainPrivacyGroupTransaction.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory.PrivxFindPrivacyGroupResponse; - -import java.io.IOException; -import java.util.List; -import java.util.stream.Collectors; - -import org.web3j.utils.Base64String; - -public class FindOnChainPrivacyGroupTransaction - implements Transaction> { - private final List nodes; - - public FindOnChainPrivacyGroupTransaction(final List nodeEnclaveKeys) { - this.nodes = nodeEnclaveKeys.stream().map(Base64String::wrap).collect(Collectors.toList()); - } - - @Override - public List execute(final NodeRequests node) { - try { - PrivxFindPrivacyGroupResponse result = - node.privacy().privxFindOnChainPrivacyGroup(nodes).send(); - assertThat(result).isNotNull(); - if (result.hasError()) { - throw new RuntimeException(result.getError().getMessage()); - } - return result.getGroups(); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/GetAllPrivacyMarkerTransactionHashes.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/GetAllPrivacyMarkerTransactionHashes.java deleted file mode 100644 index ef7e8d95443..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/GetAllPrivacyMarkerTransactionHashes.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; - -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; - -import java.io.IOException; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; - -import org.web3j.protocol.besu.Besu; -import org.web3j.protocol.core.DefaultBlockParameter; -import org.web3j.protocol.core.methods.response.EthBlock; - -public class GetAllPrivacyMarkerTransactionHashes implements Transaction> { - @Override - public List execute(final NodeRequests node) { - final Besu besu = node.privacy().getBesuClient(); - final List toReturn = new ArrayList<>(); - try { - final long blockchainHeight = besu.ethBlockNumber().send().getBlockNumber().longValueExact(); - for (int i = 0; i <= blockchainHeight; i++) { - besu.ethGetBlockByNumber(DefaultBlockParameter.valueOf(BigInteger.valueOf(i)), true) - .send() - .getBlock() - .getTransactions() - .forEach( - t -> { - if (((EthBlock.TransactionObject) t) - .getTo() - .equals(Address.DEFAULT_PRIVACY.toString())) { - toReturn.add(((EthBlock.TransactionObject) t).getHash()); - } - }); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - - return toReturn; - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/GetAllPrivateMarkerTransactionHashes.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/GetAllPrivateMarkerTransactionHashes.java new file mode 100644 index 00000000000..d0056f50b43 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/GetAllPrivateMarkerTransactionHashes.java @@ -0,0 +1,56 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; + +import static org.hyperledger.besu.ethereum.core.PrivacyParameters.DEFAULT_PRIVACY; + +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +import org.web3j.protocol.besu.Besu; +import org.web3j.protocol.core.DefaultBlockParameter; +import org.web3j.protocol.core.methods.response.EthBlock; + +public class GetAllPrivateMarkerTransactionHashes implements Transaction> { + @Override + public List execute(final NodeRequests node) { + final Besu besu = node.privacy().getBesuClient(); + final List toReturn = new ArrayList<>(); + try { + final long blockchainHeight = besu.ethBlockNumber().send().getBlockNumber().longValueExact(); + for (long i = 0; i <= blockchainHeight; i++) { + besu.ethGetBlockByNumber(DefaultBlockParameter.valueOf(BigInteger.valueOf(i)), true) + .send() + .getBlock() + .getTransactions() + .forEach( + t -> { + if (((EthBlock.TransactionObject) t).getTo().equals(DEFAULT_PRIVACY.toString())) { + toReturn.add(((EthBlock.TransactionObject) t).getHash()); + } + }); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + + return toReturn; + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/LockFlexiblePrivacyGroupTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/LockFlexiblePrivacyGroupTransaction.java new file mode 100644 index 00000000000..92ed003ad43 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/LockFlexiblePrivacyGroupTransaction.java @@ -0,0 +1,47 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; + +import org.web3j.crypto.Credentials; +import org.web3j.protocol.exceptions.TransactionException; +import org.web3j.utils.Base64String; + +public class LockFlexiblePrivacyGroupTransaction implements Transaction { + private final Base64String privacyGroupId; + private final PrivacyNode locker; + private final Credentials signer; + + public LockFlexiblePrivacyGroupTransaction( + final String privacyGroupId, final PrivacyNode locker, final Credentials signer) { + this.privacyGroupId = Base64String.wrap(privacyGroupId); + this.locker = locker; + this.signer = signer; + } + + @Override + public String execute(final NodeRequests node) { + try { + return node.privacy().privxLockPrivacyGroup(locker, privacyGroupId, signer); + } catch (final IOException | TransactionException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/LockOnChainPrivacyGroupTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/LockOnChainPrivacyGroupTransaction.java deleted file mode 100644 index f6e4e3b4761..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/LockOnChainPrivacyGroupTransaction.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; - -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; - -import java.io.IOException; - -import org.web3j.crypto.Credentials; -import org.web3j.protocol.exceptions.TransactionException; -import org.web3j.utils.Base64String; - -public class LockOnChainPrivacyGroupTransaction implements Transaction { - private final Base64String privacyGroupId; - private final PrivacyNode locker; - private final Credentials signer; - - public LockOnChainPrivacyGroupTransaction( - final String privacyGroupId, final PrivacyNode locker, final Credentials signer) { - this.privacyGroupId = Base64String.wrap(privacyGroupId); - this.locker = locker; - this.signer = signer; - } - - @Override - public String execute(final NodeRequests node) { - try { - return node.privacy().privxLockPrivacyGroup(locker, privacyGroupId, signer); - } catch (final IOException | TransactionException e) { - throw new RuntimeException(e); - } - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/PluginCreateRandomPrivacyGroupIdTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/PluginCreateRandomPrivacyGroupIdTransaction.java new file mode 100644 index 00000000000..180764449f7 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/PluginCreateRandomPrivacyGroupIdTransaction.java @@ -0,0 +1,31 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; + +import org.hyperledger.besu.crypto.SecureRandomProvider; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import org.apache.tuweni.bytes.Bytes; + +public class PluginCreateRandomPrivacyGroupIdTransaction implements Transaction { + + @Override + public String execute(final NodeRequests node) { + final byte[] bytes = new byte[32]; + SecureRandomProvider.createSecureRandom().nextBytes(bytes); + return Bytes.wrap(bytes).toBase64String(); + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/PrivacyTransactions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/PrivacyTransactions.java index 3015bae3ea5..3763e40bb7c 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/PrivacyTransactions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/PrivacyTransactions.java @@ -14,7 +14,8 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.ethereum.privacy.PrivacyGroupUtil; import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; import org.hyperledger.besu.tests.acceptance.dsl.privacy.condition.PrivGetTransactionReceiptTransaction; import org.hyperledger.besu.tests.acceptance.dsl.privacy.util.LogFilterJsonParameter; @@ -29,8 +30,12 @@ import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.filter.PrivNewFilterTransaction; import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.filter.PrivUninstallFilterTransaction; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; import org.web3j.crypto.Credentials; import org.web3j.tx.Contract; @@ -41,44 +46,49 @@ public PrivGetTransactionReceiptTransaction getPrivateTransactionReceipt( return new PrivGetTransactionReceiptTransaction(transactionHash); } - public CreatePrivacyGroupTransaction createPrivacyGroup( + public RestrictedCreatePrivacyGroupTransaction createPrivacyGroup( final String name, final String description, final PrivacyNode... nodes) { - return new CreatePrivacyGroupTransaction(name, description, nodes); + return new RestrictedCreatePrivacyGroupTransaction(name, description, nodes); } - public CreateOnChainPrivacyGroupTransaction createOnChainPrivacyGroup( + public CreateFlexiblePrivacyGroupTransaction createFlexiblePrivacyGroup( final PrivacyNode creator, final String privateFrom, final List addresses, final String token) { creator.getBesu().useAuthenticationTokenInHeaderForJsonRpc(token); - return new CreateOnChainPrivacyGroupTransaction(creator, privateFrom, addresses); + return new CreateFlexiblePrivacyGroupTransaction(creator, privateFrom, addresses); } - public CreateOnChainPrivacyGroupTransaction createOnChainPrivacyGroup( + public CreateFlexiblePrivacyGroupTransaction createFlexiblePrivacyGroup( final PrivacyNode creator, final String privateFrom, final List addresses) { - return new CreateOnChainPrivacyGroupTransaction(creator, privateFrom, addresses); + return new CreateFlexiblePrivacyGroupTransaction(creator, privateFrom, addresses); } - public AddToOnChainPrivacyGroupTransaction addToPrivacyGroup( + public AddToFlexiblePrivacyGroupTransaction addToPrivacyGroup( final String privacyGroupId, final PrivacyNode adder, final Credentials signer, final PrivacyNode... nodes) { - return new AddToOnChainPrivacyGroupTransaction(privacyGroupId, adder, signer, nodes); + return new AddToFlexiblePrivacyGroupTransaction(privacyGroupId, adder, signer, nodes); } - public LockOnChainPrivacyGroupTransaction privxLockPrivacyGroupAndCheck( + public LockFlexiblePrivacyGroupTransaction privxLockPrivacyGroupAndCheck( final String privacyGroupId, final PrivacyNode locker, final Credentials signer) { - return new LockOnChainPrivacyGroupTransaction(privacyGroupId, locker, signer); + return new LockFlexiblePrivacyGroupTransaction(privacyGroupId, locker, signer); + } + + public UnlockFlexiblePrivacyGroupTransaction privxUnlockPrivacyGroupAndCheck( + final String privacyGroupId, final PrivacyNode locker, final Credentials signer) { + return new UnlockFlexiblePrivacyGroupTransaction(privacyGroupId, locker, signer); } public FindPrivacyGroupTransaction findPrivacyGroup(final List nodes) { return new FindPrivacyGroupTransaction(nodes); } - public FindOnChainPrivacyGroupTransaction findOnChainPrivacyGroup(final List nodes) { - return new FindOnChainPrivacyGroupTransaction(nodes); + public FindFlexiblePrivacyGroupTransaction findFlexiblePrivacyGroup(final List nodes) { + return new FindFlexiblePrivacyGroupTransaction(nodes); } public PrivDistributeTransactionTransaction privDistributeTransaction( @@ -105,12 +115,12 @@ public PrivGetLogsTransaction privGetLogs( return new PrivGetLogsTransaction(privacyGroupId, filterParameter); } - public RemoveFromOnChainPrivacyGroupTransaction removeFromPrivacyGroup( + public RemoveFromFlexiblePrivacyGroupTransaction removeFromPrivacyGroup( final String privacyGroupId, final String remover, final Credentials signer, final String memberToRemove) { - return new RemoveFromOnChainPrivacyGroupTransaction( + return new RemoveFromFlexiblePrivacyGroupTransaction( privacyGroupId, remover, signer, memberToRemove); } @@ -142,4 +152,14 @@ public PrivDebugGetStateRoot debugGetStateRoot( final String privacyGroupId, final String blockParam) { return new PrivDebugGetStateRoot(privacyGroupId, blockParam); } + + public String getLegacyPrivacyGroupId(final String privateFrom, final String... privateFor) { + + final Bytes32 privacyGroupId = + PrivacyGroupUtil.calculateEeaPrivacyGroupId( + Bytes.fromBase64String(privateFrom), + Arrays.stream(privateFor).map(Bytes::fromBase64String).collect(Collectors.toList())); + + return privacyGroupId.toBase64String(); + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/RemoveFromFlexiblePrivacyGroupTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/RemoveFromFlexiblePrivacyGroupTransaction.java new file mode 100644 index 00000000000..7f2712c81dc --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/RemoveFromFlexiblePrivacyGroupTransaction.java @@ -0,0 +1,50 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; + +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; + +import org.web3j.crypto.Credentials; +import org.web3j.utils.Base64String; + +public class RemoveFromFlexiblePrivacyGroupTransaction implements Transaction { + private final Base64String privacyGroupId; + private final String remover; + private final String toRemove; + private final Credentials signer; + + public RemoveFromFlexiblePrivacyGroupTransaction( + final String privacyGroupId, + final String remover, + final Credentials signer, + final String toRemove) { + this.privacyGroupId = Base64String.wrap(privacyGroupId); + this.remover = remover; + this.signer = signer; + this.toRemove = toRemove; + } + + @Override + public String execute(final NodeRequests node) { + try { + return node.privacy().privxRemoveFromPrivacyGroup(privacyGroupId, remover, signer, toRemove); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/RemoveFromOnChainPrivacyGroupTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/RemoveFromOnChainPrivacyGroupTransaction.java deleted file mode 100644 index 4ecb18cf2ef..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/RemoveFromOnChainPrivacyGroupTransaction.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; - -import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; - -import java.io.IOException; - -import org.web3j.crypto.Credentials; -import org.web3j.utils.Base64String; - -public class RemoveFromOnChainPrivacyGroupTransaction implements Transaction { - private final Base64String privacyGroupId; - private final String remover; - private final String toRemove; - private final Credentials signer; - - public RemoveFromOnChainPrivacyGroupTransaction( - final String privacyGroupId, - final String remover, - final Credentials signer, - final String toRemove) { - this.privacyGroupId = Base64String.wrap(privacyGroupId); - this.remover = remover; - this.signer = signer; - this.toRemove = toRemove; - } - - @Override - public String execute(final NodeRequests node) { - try { - return node.privacy().privxRemoveFromPrivacyGroup(privacyGroupId, remover, signer, toRemove); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/RestrictedCreatePrivacyGroupTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/RestrictedCreatePrivacyGroupTransaction.java new file mode 100644 index 00000000000..a455076f9fb --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/RestrictedCreatePrivacyGroupTransaction.java @@ -0,0 +1,60 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.web3j.protocol.besu.Besu; +import org.web3j.protocol.besu.response.privacy.PrivCreatePrivacyGroup; +import org.web3j.utils.Base64String; + +public class RestrictedCreatePrivacyGroupTransaction implements Transaction { + private final String name; + private final String description; + private final List addresses; + + public RestrictedCreatePrivacyGroupTransaction( + final String name, final String description, final PrivacyNode... nodes) { + this.name = name; + this.description = description; + this.addresses = + Arrays.stream(nodes) + .map(n -> Base64String.wrap(n.getEnclave().getDefaultPublicKey())) + .collect(Collectors.toList()); + } + + @Override + public String execute(final NodeRequests node) { + final Besu besu = node.privacy().getBesuClient(); + try { + final PrivCreatePrivacyGroup result = + besu.privCreatePrivacyGroup(addresses, name, description).send(); + if (result.hasError()) { + throw new RuntimeException(result.getError().getMessage()); + } else { + return result.getPrivacyGroupId().toString(); + } + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/UnlockFlexiblePrivacyGroupTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/UnlockFlexiblePrivacyGroupTransaction.java new file mode 100644 index 00000000000..98b0236c32d --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/UnlockFlexiblePrivacyGroupTransaction.java @@ -0,0 +1,47 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; + +import org.web3j.crypto.Credentials; +import org.web3j.protocol.exceptions.TransactionException; +import org.web3j.utils.Base64String; + +public class UnlockFlexiblePrivacyGroupTransaction implements Transaction { + private final Base64String privacyGroupId; + private final PrivacyNode locker; + private final Credentials signer; + + public UnlockFlexiblePrivacyGroupTransaction( + final String privacyGroupId, final PrivacyNode locker, final Credentials signer) { + this.privacyGroupId = Base64String.wrap(privacyGroupId); + this.locker = locker; + this.signer = signer; + } + + @Override + public String execute(final NodeRequests node) { + try { + return node.privacy().privxUnlockPrivacyGroup(locker, privacyGroupId, signer); + } catch (final IOException | TransactionException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/pubsub/Subscription.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/pubsub/Subscription.java index 62fa168860c..6a0a734399f 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/pubsub/Subscription.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/pubsub/Subscription.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; import java.util.List; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/pubsub/WebSocketConnection.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/pubsub/WebSocketConnection.java index f83755cad87..9946139afbb 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/pubsub/WebSocketConnection.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/pubsub/WebSocketConnection.java @@ -25,15 +25,15 @@ import io.vertx.core.Vertx; import io.vertx.core.http.HttpClientOptions; -import io.vertx.core.http.RequestOptions; import io.vertx.core.http.WebSocket; +import io.vertx.core.http.WebSocketConnectOptions; import io.vertx.core.json.DecodeException; import io.vertx.core.json.Json; import org.apache.commons.lang3.exception.ExceptionUtils; public class WebSocketConnection { - private final RequestOptions options; + private final WebSocketConnectOptions options; private final ConcurrentLinkedDeque subscriptionEvents; private volatile String error; @@ -47,7 +47,7 @@ public WebSocketConnection(final Vertx vertx, final NodeConfiguration node) { "Can't start websocket connection for node with RPC disabled"); } subscriptionEvents = new ConcurrentLinkedDeque<>(); - options = new RequestOptions(); + options = new WebSocketConnectOptions(); options.setPort(node.getJsonRpcWebSocketPort().get()); options.setHost(node.getHostName()); @@ -85,30 +85,33 @@ private JsonRpcSuccessEvent send(final String json) { private void connect(final Vertx vertx) { vertx .createHttpClient(new HttpClientOptions()) - .websocket( + .webSocket( options, websocket -> { - webSocketConnection(websocket); - - websocket.handler( - data -> { - try { - final WebSocketEvent eventType = Json.decodeValue(data, WebSocketEvent.class); - - if (eventType.isSubscription()) { - success(Json.decodeValue(data, SubscriptionEvent.class)); - } else { - success(Json.decodeValue(data, JsonRpcSuccessEvent.class)); - } - - } catch (final DecodeException e) { - error( - "Data: " - + data.toString() - + "\nException: " - + ExceptionUtils.getStackTrace(e)); - } - }); + webSocketConnection(websocket.result()); + + websocket + .result() + .handler( + data -> { + try { + final WebSocketEvent eventType = + Json.decodeValue(data, WebSocketEvent.class); + + if (eventType.isSubscription()) { + success(Json.decodeValue(data, SubscriptionEvent.class)); + } else { + success(Json.decodeValue(data, JsonRpcSuccessEvent.class)); + } + + } catch (final DecodeException e) { + error( + "Data: " + + data.toString() + + "\nException: " + + ExceptionUtils.getStackTrace(e)); + } + }); }); WaitUtils.waitFor(() -> assertThat(connection).isNotNull()); diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/rpc/JsonRpcTestCase.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/rpc/JsonRpcTestCase.java new file mode 100644 index 00000000000..50dbff13f94 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/rpc/JsonRpcTestCase.java @@ -0,0 +1,47 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.rpc; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; + +public class JsonRpcTestCase { + private final JsonNode request; + private final JsonNode response; + private final int statusCode; + + @JsonCreator + public JsonRpcTestCase( + @JsonProperty("request") final JsonNode request, + @JsonProperty("response") final JsonNode response, + @JsonProperty("statusCode") final int statusCode) { + this.request = request; + this.response = response; + this.statusCode = statusCode; + } + + public JsonNode getRequest() { + return request; + } + + public JsonNode getResponse() { + return response; + } + + public int getStatusCode() { + return statusCode; + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/CallSmartContractFunction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/CallSmartContractFunction.java index ec98ac22f05..77dfa99089b 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/CallSmartContractFunction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/CallSmartContractFunction.java @@ -29,27 +29,36 @@ public class CallSmartContractFunction implements Transaction { private static final BigInteger GAS_PRICE = BigInteger.valueOf(1000); - private static final BigInteger GAS_LIMIT = BigInteger.valueOf(3000000); + private static final Credentials BENEFACTOR_ONE = Credentials.create(Accounts.GENESIS_ACCOUNT_ONE_PRIVATE_KEY); - private final String functionName; + private BigInteger gasLimit = BigInteger.valueOf(3000000); + private final String functionCall; private final String contractAddress; - public CallSmartContractFunction(final String functionName, final String contractAddress) { - this.functionName = functionName; + public CallSmartContractFunction(final String contractAddress, final String functionName) { + final Function function = + new Function(functionName, Collections.emptyList(), Collections.emptyList()); + this.contractAddress = contractAddress; + this.functionCall = FunctionEncoder.encode(function); + } + + public CallSmartContractFunction( + final String contractAddress, final String functionCall, final BigInteger gasLimit) { + this.contractAddress = contractAddress; + this.functionCall = functionCall; + this.gasLimit = gasLimit; } @Override public EthSendTransaction execute(final NodeRequests node) { - final Function function = - new Function(functionName, Collections.emptyList(), Collections.emptyList()); final RawTransactionManager transactionManager = new RawTransactionManager(node.eth(), BENEFACTOR_ONE); try { return transactionManager.sendTransaction( - GAS_PRICE, GAS_LIMIT, contractAddress, FunctionEncoder.encode(function), BigInteger.ZERO); + GAS_PRICE, gasLimit, contractAddress, functionCall, BigInteger.ZERO); } catch (IOException e) { throw new IllegalStateException(e); } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/NodeRequests.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/NodeRequests.java index 46cdf61bd01..4741e397ddc 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/NodeRequests.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/NodeRequests.java @@ -15,8 +15,8 @@ package org.hyperledger.besu.tests.acceptance.dsl.transaction; import org.hyperledger.besu.tests.acceptance.dsl.transaction.admin.AdminRequestFactory; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.bft.BftRequestFactory; import org.hyperledger.besu.tests.acceptance.dsl.transaction.clique.CliqueRequestFactory; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2.Ibft2RequestFactory; import org.hyperledger.besu.tests.acceptance.dsl.transaction.login.LoginRequestFactory; import org.hyperledger.besu.tests.acceptance.dsl.transaction.miner.MinerRequestFactory; import org.hyperledger.besu.tests.acceptance.dsl.transaction.net.CustomRequestFactory; @@ -33,7 +33,7 @@ public class NodeRequests { private final Web3j netEth; private final CliqueRequestFactory clique; - private final Ibft2RequestFactory ibft; + private final BftRequestFactory bft; private final PermissioningJsonRpcRequestFactory perm; private final AdminRequestFactory admin; private final PrivacyRequestFactory privacy; @@ -46,7 +46,7 @@ public class NodeRequests { public NodeRequests( final Web3j netEth, final CliqueRequestFactory clique, - final Ibft2RequestFactory ibft, + final BftRequestFactory bft, final PermissioningJsonRpcRequestFactory perm, final AdminRequestFactory admin, final PrivacyRequestFactory privacy, @@ -57,7 +57,7 @@ public NodeRequests( final LoginRequestFactory login) { this.netEth = netEth; this.clique = clique; - this.ibft = ibft; + this.bft = bft; this.perm = perm; this.admin = admin; this.privacy = privacy; @@ -80,8 +80,8 @@ public CliqueRequestFactory clique() { return clique; } - public Ibft2RequestFactory ibft() { - return ibft; + public BftRequestFactory bft() { + return bft; } public PermissioningJsonRpcRequestFactory perm() { diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/SignUtil.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/SignUtil.java new file mode 100644 index 00000000000..30a3d78fc04 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/SignUtil.java @@ -0,0 +1,117 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.transaction; + +import org.hyperledger.besu.crypto.SECPPrivateKey; +import org.hyperledger.besu.crypto.SECPSignature; +import org.hyperledger.besu.crypto.SignatureAlgorithm; +import org.hyperledger.besu.tests.acceptance.dsl.account.Account; + +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Optional; + +import org.apache.tuweni.bytes.Bytes32; +import org.web3j.crypto.Credentials; +import org.web3j.crypto.RawTransaction; +import org.web3j.crypto.Sign; +import org.web3j.crypto.TransactionEncoder; +import org.web3j.crypto.transaction.type.TransactionType; +import org.web3j.rlp.RlpEncoder; +import org.web3j.rlp.RlpList; +import org.web3j.rlp.RlpString; +import org.web3j.rlp.RlpType; +import org.web3j.utils.Bytes; +import org.web3j.utils.Numeric; + +public class SignUtil { + private static final int CHAIN_ID_INC = 35; + // In Ethereum transaction 27 is added to recId (v) + // See https://ethereum.github.io/yellowpaper/paper.pdf + // Appendix F. Signing Transactions (281) + private static final int LOWER_REAL_V = 27; + + private SignUtil() {} + + public static byte[] signTransaction( + final RawTransaction transaction, + final Account sender, + final SignatureAlgorithm signatureAlgorithm, + final Optional chainId) { + byte[] encodedTransaction = TransactionEncoder.encode(transaction); + + Credentials credentials = sender.web3jCredentialsOrThrow(); + SECPPrivateKey privateKey = + signatureAlgorithm.createPrivateKey(credentials.getEcKeyPair().getPrivateKey()); + + byte[] transactionHash = org.web3j.crypto.Hash.sha3(encodedTransaction); + + SECPSignature secpSignature = + signatureAlgorithm.sign( + Bytes32.wrap(transactionHash), signatureAlgorithm.createKeyPair(privateKey)); + + Sign.SignatureData signature = + new Sign.SignatureData( + calculateV(secpSignature, chainId), + secpSignature.getR().toByteArray(), + secpSignature.getS().toByteArray()); + List values = getTxRlpValues(transaction, signature, secpSignature); + RlpList rlpList = new RlpList(values); + byte[] encoded = RlpEncoder.encode(rlpList); + + if (transaction.getType().equals(TransactionType.LEGACY)) { + return encoded; + } + return ByteBuffer.allocate(encoded.length + 1) + .put(transaction.getType().getRlpType()) + .put(encoded) + .array(); + } + + private static List getTxRlpValues( + final RawTransaction transaction, + final Sign.SignatureData signature, + final SECPSignature secpSignature) { + final List values = TransactionEncoder.asRlpValues(transaction, signature); + if (!transaction.getType().equals(TransactionType.EIP1559)) { + return values; + } + + // Fix yParityField for eip1559 txs + // See outstanding fix: https://github.com/web3j/web3j/pull/1587 + final int yParityFieldIndex = values.size() - 3; + byte recId = secpSignature.getRecId(); + final byte[] yParityFieldValue = + recId == 0 ? new byte[] {} : new byte[] {secpSignature.getRecId()}; + final RlpType yParityRlpString = RlpString.create(Bytes.trimLeadingZeroes(yParityFieldValue)); + values.set(yParityFieldIndex, yParityRlpString); + return values; + } + + private static byte[] calculateV( + final SECPSignature secpSignature, final Optional maybeChainId) { + byte recId = secpSignature.getRecId(); + return maybeChainId + .map( + chainId -> { + BigInteger v = Numeric.toBigInt(new byte[] {recId}); + v = v.add(chainId.multiply(BigInteger.valueOf(2))); + v = v.add(BigInteger.valueOf(CHAIN_ID_INC)); + return v.toByteArray(); + }) + .orElseGet(() -> new byte[] {(byte) (recId + LOWER_REAL_V)}); + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/AccountTransactions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/AccountTransactions.java index a7c689ddbda..070b74d637b 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/AccountTransactions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/AccountTransactions.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.transaction.account; +import org.hyperledger.besu.crypto.SignatureAlgorithm; +import org.hyperledger.besu.plugin.data.TransactionType; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts; import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; @@ -24,6 +26,7 @@ public class AccountTransactions { + private static final Amount DEFAULT_GAS_PRICE = Amount.wei(BigInteger.valueOf(10000000000L)); private final Accounts accounts; public AccountTransactions(final Accounts accounts) { @@ -34,46 +37,87 @@ public TransferTransaction createTransfer(final Account recipient, final int amo return createTransfer(accounts.getPrimaryBenefactor(), recipient, amount); } + public TransferTransaction createTransfer( + final Account recipient, final int amount, final Amount gasPrice) { + return createFrontierBuilder(accounts.getPrimaryBenefactor(), recipient, Amount.ether(amount)) + .gasPrice(gasPrice) + .build(); + } + + public TransferTransaction createTransfer( + final Account recipient, final int amount, final SignatureAlgorithm signatureAlgorithm) { + return createFrontierBuilder(accounts.getPrimaryBenefactor(), recipient, Amount.ether(amount)) + .setSignatureAlgorithm(signatureAlgorithm) + .build(); + } + public TransferTransaction createTransfer(final Account recipient, final Amount amount) { return createTransfer(accounts.getPrimaryBenefactor(), recipient, amount); } public TransferTransaction createTransfer( final Account sender, final Account recipient, final int amount) { - return new TransferTransactionBuilder() - .sender(sender) - .recipient(recipient) - .amount(Amount.ether(amount)) - .build(); + return createFrontierBuilder(sender, recipient, Amount.ether(amount)).build(); } public TransferTransaction createTransfer( final Account sender, final Account recipient, final Amount amount) { - return new TransferTransactionBuilder() - .sender(sender) - .recipient(recipient) - .amount(amount) - .build(); + return createFrontierBuilder(sender, recipient, amount).build(); } public TransferTransaction createTransfer( final Account sender, final Account recipient, final int amount, final BigInteger nonce) { - return new TransferTransactionBuilder() - .sender(sender) - .recipient(recipient) - .amount(Amount.ether(amount)) - .nonce(nonce) + return createFrontierBuilder(sender, recipient, Amount.ether(amount)).nonce(nonce).build(); + } + + public TransferTransaction create1559Transfer( + final Account recipient, final int amount, final long chainId) { + return create1559Builder( + accounts.getPrimaryBenefactor(), recipient, Amount.ether(amount), chainId) + .build(); + } + + public TransferTransaction create1559Transfer( + final Account recipient, final int amount, final long chainId, final Amount gasPrice) { + return create1559Builder( + accounts.getPrimaryBenefactor(), recipient, Amount.ether(amount), chainId) + .gasPrice(gasPrice) .build(); } public TransferTransactionSet createIncrementalTransfers( final Account sender, final Account recipient, final int etherAmount) { + return createIncrementalTransfers(sender, recipient, etherAmount, DEFAULT_GAS_PRICE); + } + + public TransferTransactionSet createIncrementalTransfers( + final Account sender, final Account recipient, final int etherAmount, final Amount gasPrice) { + final List transfers = new ArrayList<>(); + final TransferTransactionBuilder transferOneEther = + createFrontierBuilder(sender, recipient, Amount.ether(1)).gasPrice(gasPrice); + + for (int i = 1; i <= etherAmount; i++) { + transfers.add(transferOneEther.build()); + } + + return new TransferTransactionSet(transfers); + } + + public TransferTransactionSet create1559IncrementalTransfers( + final Account sender, final Account recipient, final int etherAmount, final long chainId) { + return create1559IncrementalTransfers( + sender, recipient, etherAmount, chainId, DEFAULT_GAS_PRICE); + } + + public TransferTransactionSet create1559IncrementalTransfers( + final Account sender, + final Account recipient, + final int etherAmount, + final long chainId, + final Amount gasPrice) { final List transfers = new ArrayList<>(); final TransferTransactionBuilder transferOneEther = - new TransferTransactionBuilder() - .sender(sender) - .recipient(recipient) - .amount(Amount.ether(1)); + create1559Builder(sender, recipient, Amount.ether(1), chainId).gasPrice(gasPrice); for (int i = 1; i <= etherAmount; i++) { transfers.add(transferOneEther.build()); @@ -81,4 +125,25 @@ public TransferTransactionSet createIncrementalTransfers( return new TransferTransactionSet(transfers); } + + private TransferTransactionBuilder createFrontierBuilder( + final Account sender, final Account recipient, final Amount amount) { + return new TransferTransactionBuilder() + .sender(sender) + .recipient(recipient) + .amount(amount) + .gasPrice(DEFAULT_GAS_PRICE) + .transactionType(TransactionType.FRONTIER); + } + + private TransferTransactionBuilder create1559Builder( + final Account sender, final Account recipient, final Amount amount, final long chainId) { + return new TransferTransactionBuilder() + .sender(sender) + .recipient(recipient) + .amount(amount) + .gasPrice(DEFAULT_GAS_PRICE) + .chainId(chainId) + .transactionType(TransactionType.EIP1559); + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransaction.java index 61d3a00ae67..5a330bf27f6 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransaction.java @@ -14,12 +14,13 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.transaction.account; -import static org.web3j.utils.Numeric.toHexString; - -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.crypto.SignatureAlgorithm; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.plugin.data.TransactionType; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.SignUtil; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; import java.io.IOException; @@ -28,13 +29,14 @@ import java.util.Optional; import org.web3j.crypto.RawTransaction; -import org.web3j.crypto.TransactionEncoder; +import org.web3j.protocol.core.methods.response.EthSendTransaction; import org.web3j.utils.Convert; import org.web3j.utils.Convert.Unit; +import org.web3j.utils.Numeric; public class TransferTransaction implements Transaction { - /** Price for each for each GAS units in this transaction (wei). */ + /** Price for each GAS units in this transaction (wei). */ private static final BigInteger MINIMUM_GAS_PRICE = BigInteger.valueOf(1000); /** Number of GAS units that the transaction will cost. */ @@ -46,30 +48,35 @@ public class TransferTransaction implements Transaction { private final Unit transferUnit; private final BigInteger gasPrice; private final BigInteger nonce; + private final Optional chainId; + private final SignatureAlgorithm signatureAlgorithm; + private final TransactionType transactionType; + private byte[] signedTxData = null; public TransferTransaction( final Account sender, final Account recipient, final Amount transferAmount, final Amount gasPrice, - final BigInteger nonce) { + final BigInteger nonce, + final Optional chainId, + final SignatureAlgorithm signatureAlgorithm, + final TransactionType transactionType) { this.sender = sender; this.recipient = recipient; this.transferAmount = transferAmount.getValue(); this.transferUnit = transferAmount.getUnit(); this.gasPrice = gasPrice == null ? MINIMUM_GAS_PRICE : convertGasPriceToWei(gasPrice); this.nonce = nonce; + this.chainId = chainId; + this.signatureAlgorithm = signatureAlgorithm; + this.transactionType = transactionType; } @Override public Hash execute(final NodeRequests node) { final String signedTransactionData = signedTransactionData(); - try { - return Hash.fromHexString( - node.eth().ethSendRawTransaction(signedTransactionData).send().getTransactionHash()); - } catch (final IOException e) { - throw new RuntimeException(e); - } + return sendRawTransaction(node, signedTransactionData); } public Amount executionCost() { @@ -77,35 +84,68 @@ public Amount executionCost() { } public String signedTransactionData() { - final Optional nonce = getNonce(); - - final RawTransaction transaction = - RawTransaction.createEtherTransaction( - nonce.orElse(nonce.orElseGet(sender::getNextNonce)), - gasPrice, - INTRINSIC_GAS, - recipient.getAddress(), - Convert.toWei(transferAmount, transferUnit).toBigIntegerExact()); - - return toHexString( - TransactionEncoder.signMessage(transaction, sender.web3jCredentialsOrThrow())); + return Numeric.toHexString(createSignedTransactionData()); } - private Optional getNonce() { - return nonce == null ? Optional.empty() : Optional.of(nonce); + public String transactionHash() { + final byte[] signedTx = createSignedTransactionData(); + final byte[] txHash = org.web3j.crypto.Hash.sha3(signedTx); + return Numeric.toHexString(txHash); } - private BigInteger convertGasPriceToWei(final Amount unconverted) { - final BigInteger price = - Convert.toWei(unconverted.getValue(), unconverted.getUnit()).toBigInteger(); - - if (MINIMUM_GAS_PRICE.compareTo(price) > 0) { - throw new IllegalArgumentException( - String.format( - "Gas price: %s WEI, is below the accepted minimum: %s WEI", - price, MINIMUM_GAS_PRICE)); + private byte[] createSignedTransactionData() { + if (signedTxData == null) { + signedTxData = + SignUtil.signTransaction(createRawTransaction(), sender, signatureAlgorithm, chainId); + } + return signedTxData; + } + + private Hash sendRawTransaction(final NodeRequests node, final String signedTransactionData) { + try { + final EthSendTransaction transaction = + node.eth().ethSendRawTransaction(signedTransactionData).send(); + if (transaction.getResult() == null && transaction.getError() != null) { + throw new RuntimeException( + "Error sending transaction: " + transaction.getError().getMessage()); + } + return Hash.fromHexString(transaction.getTransactionHash()); + } catch (final IOException e) { + throw new RuntimeException(e); } + } + + private BigInteger getNonce() { + return Optional.ofNullable(nonce).orElseGet(sender::getNextNonce); + } + + private BigInteger convertGasPriceToWei(final Amount unconverted) { + return Convert.toWei(unconverted.getValue(), unconverted.getUnit()).toBigInteger(); + } + + private RawTransaction createRawTransaction() { + return transactionType == TransactionType.FRONTIER + ? createFrontierTransaction() + : create1559Transaction(chainId.orElseThrow()); + } + + private RawTransaction createFrontierTransaction() { + return RawTransaction.createEtherTransaction( + getNonce(), + gasPrice, + INTRINSIC_GAS, + recipient.getAddress(), + Convert.toWei(transferAmount, transferUnit).toBigIntegerExact()); + } - return price; + private RawTransaction create1559Transaction(final BigInteger chainId) { + return RawTransaction.createEtherTransaction( + chainId.longValueExact(), + getNonce(), + INTRINSIC_GAS, + recipient.getAddress(), + Convert.toWei(transferAmount, transferUnit).toBigIntegerExact(), + BigInteger.ZERO, + gasPrice); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransactionBuilder.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransactionBuilder.java index bf33bb916fa..b1bb3a0ad12 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransactionBuilder.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransactionBuilder.java @@ -14,10 +14,16 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.transaction.account; +import static org.testcontainers.shaded.com.google.common.base.Preconditions.checkNotNull; + +import org.hyperledger.besu.crypto.SECP256K1; +import org.hyperledger.besu.crypto.SignatureAlgorithm; +import org.hyperledger.besu.plugin.data.TransactionType; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; import java.math.BigInteger; +import java.util.Optional; public class TransferTransactionBuilder { @@ -26,6 +32,10 @@ public class TransferTransactionBuilder { private Amount transferAmount; private Amount gasPrice; private BigInteger nonce; + private Optional chainId = Optional.empty(); + private SignatureAlgorithm signatureAlgorithm = new SECP256K1(); + + private TransactionType transactionType; public TransferTransactionBuilder sender(final Account sender) { this.sender = sender; @@ -54,10 +64,41 @@ public TransferTransactionBuilder gasPrice(final Amount gasPrice) { return this; } + public TransferTransactionBuilder setSignatureAlgorithm( + final SignatureAlgorithm signatureAlgorithm) { + checkNotNull(signatureAlgorithm); + this.signatureAlgorithm = signatureAlgorithm; + return this; + } + + public TransferTransactionBuilder chainId(final BigInteger chainId) { + this.chainId = Optional.ofNullable(chainId); + return this; + } + + public TransferTransactionBuilder chainId(final Long chainId) { + checkNotNull(chainId); + return chainId(BigInteger.valueOf(chainId)); + } + + public TransferTransactionBuilder transactionType(final TransactionType transactionType) { + this.transactionType = transactionType; + return this; + } + public TransferTransaction build() { validateSender(); validateTransferAmount(); - return new TransferTransaction(sender, recipient, transferAmount, gasPrice, nonce); + validateTransactionType(); + return new TransferTransaction( + sender, + recipient, + transferAmount, + gasPrice, + nonce, + chainId, + signatureAlgorithm, + transactionType); } private void validateSender() { @@ -71,4 +112,13 @@ private void validateTransferAmount() { throw new IllegalArgumentException("NULL transferAmount is not allowed."); } } + + private void validateTransactionType() { + if (transactionType == null) { + throw new IllegalArgumentException("NULL transactionType is not allowed."); + } + if (transactionType == TransactionType.EIP1559 && chainId.isEmpty()) { + throw new IllegalStateException("Chain ID must be specified for EIP-1559 transactions"); + } + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransactionSet.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransactionSet.java index 64ab99d8829..988dcef1989 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransactionSet.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransactionSet.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.transaction.account; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/admin/AdminPeersTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/admin/AdminPeersTransaction.java new file mode 100644 index 00000000000..dffd700b93b --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/admin/AdminPeersTransaction.java @@ -0,0 +1,44 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.tests.acceptance.dsl.transaction.admin; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import org.web3j.protocol.core.methods.response.admin.AdminPeers; + +public class AdminPeersTransaction implements Transaction> { + + public AdminPeersTransaction() {} + + @Override + public List execute(final NodeRequests node) { + try { + final AdminPeers resp = node.eth().adminPeers().send(); + assertThat(resp).isNotNull(); + assertThat(resp.hasError()).isFalse(); + return resp.getResult().stream().map(AdminPeers.Peer::getId).collect(Collectors.toList()); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/admin/AdminTransactions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/admin/AdminTransactions.java index c8d73c8ea7b..c2873aca8d1 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/admin/AdminTransactions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/admin/AdminTransactions.java @@ -21,4 +21,8 @@ public class AdminTransactions { public AddPeerTransaction addPeer(final URI peer) { return new AddPeerTransaction(peer); } + + public AdminPeersTransaction listPeers() { + return new AdminPeersTransaction(); + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftDiscard.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftDiscard.java new file mode 100644 index 00000000000..bbf8a754fe9 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftDiscard.java @@ -0,0 +1,42 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.transaction.bft; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; + +public class BftDiscard implements Transaction { + private final String address; + + public BftDiscard(final String address) { + this.address = address; + } + + @Override + public Boolean execute(final NodeRequests node) { + try { + final BftRequestFactory.DiscardResponse result = node.bft().discard(address).send(); + assertThat(result).isNotNull(); + assertThat(result.hasError()).isFalse(); + return result.getResult(); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftGetValidators.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftGetValidators.java new file mode 100644 index 00000000000..7f6cc3e1e55 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftGetValidators.java @@ -0,0 +1,45 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.transaction.bft; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; +import java.util.List; + +public class BftGetValidators implements Transaction> { + private final String blockNumber; + + public BftGetValidators(final String blockNumber) { + this.blockNumber = blockNumber; + } + + @Override + public List
execute(final NodeRequests node) { + try { + final BftRequestFactory.SignersBlockResponse result = + node.bft().validatorsAtBlock(blockNumber).send(); + assertThat(result).isNotNull(); + assertThat(result.hasError()).isFalse(); + return result.getResult(); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftGetValidatorsAtHash.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftGetValidatorsAtHash.java new file mode 100644 index 00000000000..664a223b9a2 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftGetValidatorsAtHash.java @@ -0,0 +1,46 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.transaction.bft; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; +import java.util.List; + +public class BftGetValidatorsAtHash implements Transaction> { + + private final Hash hash; + + public BftGetValidatorsAtHash(final Hash hash) { + this.hash = hash; + } + + @Override + public List
execute(final NodeRequests node) { + try { + final BftRequestFactory.SignersBlockResponse result = node.bft().signersAtHash(hash).send(); + assertThat(result).isNotNull(); + assertThat(result.hasError()).isFalse(); + return result.getResult(); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftProposals.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftProposals.java new file mode 100644 index 00000000000..d91283c6421 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftProposals.java @@ -0,0 +1,40 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.transaction.bft; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.bft.BftRequestFactory.ProposalsResponse; + +import java.io.IOException; +import java.util.Map; + +public class BftProposals implements Transaction> { + + @Override + public Map execute(final NodeRequests node) { + try { + final ProposalsResponse result = node.bft().proposals().send(); + assertThat(result).isNotNull(); + assertThat(result.hasError()).isFalse(); + return result.getResult(); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftPropose.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftPropose.java new file mode 100644 index 00000000000..361d200e56b --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftPropose.java @@ -0,0 +1,44 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.transaction.bft; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; + +public class BftPropose implements Transaction { + private final String address; + private final boolean auth; + + public BftPropose(final String address, final boolean auth) { + this.address = address; + this.auth = auth; + } + + @Override + public Boolean execute(final NodeRequests node) { + try { + final BftRequestFactory.ProposeResponse result = node.bft().propose(address, auth).send(); + assertThat(result).isNotNull(); + assertThat(result.hasError()).isFalse(); + return result.getResult(); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftRequestFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftRequestFactory.java new file mode 100644 index 00000000000..33e90508cb6 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftRequestFactory.java @@ -0,0 +1,90 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.transaction.bft; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.web3j.protocol.Web3jService; +import org.web3j.protocol.core.Request; +import org.web3j.protocol.core.Response; + +public class BftRequestFactory { + + public static class ProposeResponse extends Response {} + + public static class DiscardResponse extends Response {} + + public static class SignersBlockResponse extends Response> {} + + public static class ProposalsResponse extends Response> {} + + private final Web3jService web3jService; + + private final ConsensusType bftType; + + public BftRequestFactory(final Web3jService web3jService) { + this(web3jService, ConsensusType.IBFT2); + } + + public BftRequestFactory(final Web3jService web3jService, final ConsensusType bftType) { + this.web3jService = web3jService; + this.bftType = bftType; + } + + Request propose(final String address, final Boolean auth) { + return new Request<>( + bftType.getName() + "_proposeValidatorVote", + Arrays.asList(address, auth.toString()), + web3jService, + ProposeResponse.class); + } + + Request discard(final String address) { + return new Request<>( + bftType.getName() + "_discardValidatorVote", + singletonList(address), + web3jService, + DiscardResponse.class); + } + + Request proposals() { + return new Request<>( + bftType.getName() + "_getPendingVotes", emptyList(), web3jService, ProposalsResponse.class); + } + + Request validatorsAtBlock(final String blockNumber) { + return new Request<>( + bftType.getName() + "_getValidatorsByBlockNumber", + singletonList(blockNumber), + web3jService, + SignersBlockResponse.class); + } + + Request signersAtHash(final Hash hash) { + return new Request<>( + bftType.getName() + "_getValidatorsByBlockHash", + singletonList(hash.toString()), + web3jService, + SignersBlockResponse.class); + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftTransactions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftTransactions.java new file mode 100644 index 00000000000..94c76521ac7 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/BftTransactions.java @@ -0,0 +1,50 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.transaction.bft; + +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +public class BftTransactions { + public static final String LATEST = "latest"; + + public BftPropose createRemoveProposal(final BesuNode node) { + return propose(node.getAddress().toString(), false); + } + + public BftPropose createAddProposal(final BesuNode node) { + return propose(node.getAddress().toString(), true); + } + + public BftProposals createProposals() { + return new BftProposals(); + } + + public BftGetValidators createGetValidators(final String blockNumber) { + return new BftGetValidators(blockNumber); + } + + public BftGetValidatorsAtHash createGetValidatorsAtHash(final Hash blockHash) { + return new BftGetValidatorsAtHash(blockHash); + } + + public BftDiscard createDiscardProposal(final BesuNode node) { + return new BftDiscard(node.getAddress().toString()); + } + + private BftPropose propose(final String address, final boolean auth) { + return new BftPropose(address, auth); + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/ConsensusType.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/ConsensusType.java new file mode 100644 index 00000000000..6716947e21d --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/bft/ConsensusType.java @@ -0,0 +1,30 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.transaction.bft; + +public enum ConsensusType { + QBFT("qbft"), + IBFT2("ibft"); + + private final String name; + + ConsensusType(final String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueGetSigners.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueGetSigners.java index 0405ddf8bb2..481d6bd3460 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueGetSigners.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueGetSigners.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueGetSignersAtHash.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueGetSignersAtHash.java index 0b719f7620c..31a1e8872cc 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueGetSignersAtHash.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueGetSignersAtHash.java @@ -16,8 +16,8 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueProposals.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueProposals.java index 0778d166e28..634af775be9 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueProposals.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueProposals.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueRequestFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueRequestFactory.java index 6a16d8ca526..a25b568eae0 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueRequestFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueRequestFactory.java @@ -17,8 +17,8 @@ import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import java.util.Arrays; import java.util.List; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueTransactions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueTransactions.java index e5a792c86cc..9df60f969a9 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueTransactions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/clique/CliqueTransactions.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.transaction.clique; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; public class CliqueTransactions { diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/contract/ContractTransactions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/contract/ContractTransactions.java index 360db783e68..1597c7f269c 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/contract/ContractTransactions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/contract/ContractTransactions.java @@ -17,6 +17,8 @@ import org.hyperledger.besu.tests.acceptance.dsl.transaction.CallSmartContractFunction; import org.hyperledger.besu.tests.acceptance.dsl.transaction.DeploySmartContractTransaction; +import java.math.BigInteger; + import org.web3j.tx.Contract; public class ContractTransactions { @@ -32,7 +34,12 @@ public DeploySmartContractTransaction createSmartContrac } public CallSmartContractFunction callSmartContract( - final String functionName, final String contractAddress) { - return new CallSmartContractFunction(functionName, contractAddress); + final String contractAddress, final String functionName) { + return new CallSmartContractFunction(contractAddress, functionName); + } + + public CallSmartContractFunction callSmartContract( + final String contractAddress, final String functionCall, final BigInteger gasLimit) { + return new CallSmartContractFunction(contractAddress, functionCall, gasLimit); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/eth/EthCallTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/eth/EthCallTransaction.java new file mode 100644 index 00000000000..28ea6a0206a --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/eth/EthCallTransaction.java @@ -0,0 +1,74 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.transaction.eth; + +import static org.web3j.protocol.core.DefaultBlockParameterName.LATEST; +import static org.web3j.tx.gas.DefaultGasProvider.GAS_LIMIT; + +import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; +import java.math.BigInteger; + +import org.web3j.crypto.Credentials; +import org.web3j.protocol.core.methods.response.EthCall; + +public class EthCallTransaction implements Transaction { + private final String contractAddress; + private final String functionCall; + private BigInteger gasLimit = GAS_LIMIT; + private final String benefactorOneAddress = + Credentials.create(Accounts.GENESIS_ACCOUNT_ONE_PRIVATE_KEY).getAddress(); + + public EthCallTransaction(final String contractAddress, final String functionCall) { + this.contractAddress = contractAddress; + this.functionCall = functionCall; + } + + public EthCallTransaction( + final String contractAddress, final String functionCall, final BigInteger gasLimit) { + this.contractAddress = contractAddress; + this.functionCall = functionCall; + this.gasLimit = gasLimit; + } + + @Override + public EthCall execute(final NodeRequests node) { + try { + + var transactionCount = + node.eth() + .ethGetTransactionCount(benefactorOneAddress, LATEST) + .send() + .getTransactionCount(); + + var transaction = + new org.web3j.protocol.core.methods.request.Transaction( + benefactorOneAddress, + transactionCount, + BigInteger.ZERO, + gasLimit, + contractAddress, + BigInteger.ZERO, + functionCall); + + return node.eth().ethCall(transaction, LATEST).send(); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/eth/EthEstimateGasTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/eth/EthEstimateGasTransaction.java new file mode 100644 index 00000000000..f89bf75c7d7 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/eth/EthEstimateGasTransaction.java @@ -0,0 +1,54 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.transaction.eth; + +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; +import java.math.BigInteger; + +import org.web3j.protocol.core.methods.response.EthEstimateGas; + +public class EthEstimateGasTransaction implements Transaction { + private final String contractAddress; + private final String functionCall; + private final String from = ""; + + public EthEstimateGasTransaction(final String contractAddress, final String functionCall) { + this.contractAddress = contractAddress; + this.functionCall = functionCall; + } + + @Override + public EthEstimateGas execute(final NodeRequests node) { + try { + + return node.eth() + .ethEstimateGas( + new org.web3j.protocol.core.methods.request.Transaction( + from, + BigInteger.ONE, + BigInteger.ZERO, + BigInteger.ZERO, + contractAddress, + BigInteger.ZERO, + functionCall)) + .send(); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2Discard.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2Discard.java deleted file mode 100644 index f6d1bcf2994..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2Discard.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; - -import java.io.IOException; - -public class Ibft2Discard implements Transaction { - private final String address; - - public Ibft2Discard(final String address) { - this.address = address; - } - - @Override - public Boolean execute(final NodeRequests node) { - try { - final Ibft2RequestFactory.DiscardResponse result = node.ibft().discard(address).send(); - assertThat(result).isNotNull(); - assertThat(result.hasError()).isFalse(); - return result.getResult(); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2GetValidators.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2GetValidators.java deleted file mode 100644 index c760866c496..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2GetValidators.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; - -import java.io.IOException; -import java.util.List; - -public class Ibft2GetValidators implements Transaction> { - private final String blockNumber; - - public Ibft2GetValidators(final String blockNumber) { - this.blockNumber = blockNumber; - } - - @Override - public List
execute(final NodeRequests node) { - try { - final Ibft2RequestFactory.SignersBlockResponse result = - node.ibft().validatorsAtBlock(blockNumber).send(); - assertThat(result).isNotNull(); - assertThat(result.hasError()).isFalse(); - return result.getResult(); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2GetValidatorsAtHash.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2GetValidatorsAtHash.java deleted file mode 100644 index 72e18dbdf14..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2GetValidatorsAtHash.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; - -import java.io.IOException; -import java.util.List; - -public class Ibft2GetValidatorsAtHash implements Transaction> { - - private final Hash hash; - - public Ibft2GetValidatorsAtHash(final Hash hash) { - this.hash = hash; - } - - @Override - public List
execute(final NodeRequests node) { - try { - final Ibft2RequestFactory.SignersBlockResponse result = - node.ibft().signersAtHash(hash).send(); - assertThat(result).isNotNull(); - assertThat(result.hasError()).isFalse(); - return result.getResult(); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2Proposals.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2Proposals.java deleted file mode 100644 index 86d596c73c3..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2Proposals.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; - -import java.io.IOException; -import java.util.Map; - -public class Ibft2Proposals implements Transaction> { - - @Override - public Map execute(final NodeRequests node) { - try { - final Ibft2RequestFactory.ProposalsResponse result = node.ibft().proposals().send(); - assertThat(result).isNotNull(); - assertThat(result.hasError()).isFalse(); - return result.getResult(); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2Propose.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2Propose.java deleted file mode 100644 index fad32a47c12..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2Propose.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; - -import java.io.IOException; - -public class Ibft2Propose implements Transaction { - private final String address; - private final boolean auth; - - public Ibft2Propose(final String address, final boolean auth) { - this.address = address; - this.auth = auth; - } - - @Override - public Boolean execute(final NodeRequests node) { - try { - final Ibft2RequestFactory.ProposeResponse result = node.ibft().propose(address, auth).send(); - assertThat(result).isNotNull(); - assertThat(result.hasError()).isFalse(); - return result.getResult(); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2RequestFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2RequestFactory.java deleted file mode 100644 index ac1de61844a..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2RequestFactory.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2; - -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; - -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import org.web3j.protocol.Web3jService; -import org.web3j.protocol.core.Request; -import org.web3j.protocol.core.Response; - -public class Ibft2RequestFactory { - - public static class ProposeResponse extends Response {} - - public static class DiscardResponse extends Response {} - - public static class SignersBlockResponse extends Response> {} - - public static class ProposalsResponse extends Response> {} - - private final Web3jService web3jService; - - public Ibft2RequestFactory(final Web3jService web3jService) { - this.web3jService = web3jService; - } - - Request propose(final String address, final Boolean auth) { - return new Request<>( - "ibft_proposeValidatorVote", - Arrays.asList(address, auth.toString()), - web3jService, - ProposeResponse.class); - } - - Request discard(final String address) { - return new Request<>( - "ibft_discardValidatorVote", singletonList(address), web3jService, DiscardResponse.class); - } - - Request proposals() { - return new Request<>( - "ibft_getPendingVotes", emptyList(), web3jService, ProposalsResponse.class); - } - - Request validatorsAtBlock(final String blockNumber) { - return new Request<>( - "ibft_getValidatorsByBlockNumber", - singletonList(blockNumber), - web3jService, - SignersBlockResponse.class); - } - - Request signersAtHash(final Hash hash) { - return new Request<>( - "ibft_getValidatorsByBlockHash", - singletonList(hash.toString()), - web3jService, - SignersBlockResponse.class); - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2Transactions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2Transactions.java deleted file mode 100644 index 7913c7e8d43..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/ibft2/Ibft2Transactions.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.dsl.transaction.ibft2; - -import org.hyperledger.besu.ethereum.core.Hash; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; - -public class Ibft2Transactions { - public static final String LATEST = "latest"; - - public Ibft2Propose createRemoveProposal(final BesuNode node) { - return propose(node.getAddress().toString(), false); - } - - public Ibft2Propose createAddProposal(final BesuNode node) { - return propose(node.getAddress().toString(), true); - } - - public Ibft2Proposals createProposals() { - return new Ibft2Proposals(); - } - - public Ibft2GetValidators createGetValidators(final String blockNumber) { - return new Ibft2GetValidators(blockNumber); - } - - public Ibft2GetValidatorsAtHash createGetValidatorsAtHash(final Hash blockHash) { - return new Ibft2GetValidatorsAtHash(blockHash); - } - - public Ibft2Discard createDiscardProposal(final BesuNode node) { - return new Ibft2Discard(node.getAddress().toString()); - } - - private Ibft2Propose propose(final String address, final boolean auth) { - return new Ibft2Propose(address, auth); - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/login/LoginRequestFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/login/LoginRequestFactory.java index 45904009c5f..b0a0f921964 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/login/LoginRequestFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/login/LoginRequestFactory.java @@ -74,7 +74,7 @@ String send(final String username, final String password) throws IOException { private Request loginRequest(final String username, final String password) { final RequestBody requestBody = RequestBody.create( - JSON, String.format("{\"username\":\"%s\",\"password\":\"%s\"}", username, password)); + String.format("{\"username\":\"%s\",\"password\":\"%s\"}", username, password), JSON); return new Request.Builder().post(requestBody).url(loginUri()).build(); } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningAllowAccountTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningAllowAccountTransaction.java index 26e48c18139..7b0f83b486e 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningAllowAccountTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningAllowAccountTransaction.java @@ -17,8 +17,8 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.web3j.utils.Numeric.toHexString; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningForbidAccountTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningForbidAccountTransaction.java index 964ae88e1c4..2856ec396dc 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningForbidAccountTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningForbidAccountTransaction.java @@ -17,8 +17,8 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.web3j.utils.Numeric.toHexString; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningIsAllowedTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningIsAllowedTransaction.java index 7ffb8c63952..6faa72cb0e6 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningIsAllowedTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningIsAllowedTransaction.java @@ -17,7 +17,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; import org.hyperledger.besu.crypto.Hash; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningTransactions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningTransactions.java index ffdd1276f17..86dbd900b3d 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningTransactions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/AccountSmartContractPermissioningTransactions.java @@ -14,8 +14,8 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningAllowNodeByURLV2Transaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningAllowNodeByURLV2Transaction.java new file mode 100644 index 00000000000..6cfd2af9501 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningAllowNodeByURLV2Transaction.java @@ -0,0 +1,95 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm; + +import static org.web3j.utils.Numeric.toHexString; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.plugin.data.EnodeURL; +import org.hyperledger.besu.tests.acceptance.dsl.account.Account; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Collections; +import java.util.List; + +import org.apache.tuweni.bytes.Bytes; +import org.web3j.abi.FunctionEncoder; +import org.web3j.abi.datatypes.Function; +import org.web3j.crypto.RawTransaction; +import org.web3j.crypto.TransactionEncoder; + +public class NodeSmartContractPermissioningAllowNodeByURLV2Transaction + implements Transaction { + + private final Account sender; + private final Address contractAddress; + private final EnodeURL enodeUrl; + + public NodeSmartContractPermissioningAllowNodeByURLV2Transaction( + final Account sender, final Address contractAddress, final EnodeURL enodeUrl) { + this.sender = sender; + this.contractAddress = contractAddress; + this.enodeUrl = enodeUrl; + } + + @Override + public Hash execute(final NodeRequests node) { + final String signedTransactionData = signedTransactionData(); + try { + String hash = + node.eth().ethSendRawTransaction(signedTransactionData).send().getTransactionHash(); + return Hash.fromHexString(hash); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + + private String signedTransactionData() { + final Bytes payload = createPayload(enodeUrl); + + RawTransaction transaction = + RawTransaction.createTransaction( + sender.getNextNonce(), + BigInteger.valueOf(1_000L), + BigInteger.valueOf(3_000_000L), + contractAddress.toString(), + payload.toString()); + + return toHexString( + TransactionEncoder.signMessage(transaction, sender.web3jCredentialsOrThrow())); + } + + private Bytes createPayload(final EnodeURL enodeUrl) { + try { + final String hexNodeIdString = enodeUrl.getNodeId().toUnprefixedHexString(); + final String address = enodeUrl.toURI().getHost(); + final int port = enodeUrl.getListeningPortOrZero(); + + final Function addNodeFunction = + FunctionEncoder.makeFunction( + "addEnode", + List.of("string", "string", "uint16"), + List.of(hexNodeIdString, address, port), + Collections.emptyList()); + return Bytes.fromHexString(FunctionEncoder.encode(addNodeFunction)); + } catch (Exception e) { + throw new RuntimeException("Error adding node to allowlist", e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningAllowNodeTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningAllowNodeTransaction.java index d1b672abcd6..2579dc11462 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningAllowNodeTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningAllowNodeTransaction.java @@ -17,9 +17,9 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.web3j.utils.Numeric.toHexString; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; -import org.hyperledger.besu.ethereum.p2p.peers.EnodeURL; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.ethereum.permissioning.NodeSmartContractPermissioningController; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; @@ -68,7 +68,7 @@ private String signedTransactionData() { final String enodeURL = ((RunnableNode) node).enodeUrl().toASCIIString(); final Bytes payload = NodeSmartContractPermissioningController.createPayload( - ADD_ENODE_SIGNATURE, EnodeURL.fromString(enodeURL)); + ADD_ENODE_SIGNATURE, EnodeURLImpl.fromString(enodeURL)); RawTransaction transaction = RawTransaction.createTransaction( diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningAllowNodeV2Transaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningAllowNodeV2Transaction.java index da4892a1558..6cfee3f10d4 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningAllowNodeV2Transaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningAllowNodeV2Transaction.java @@ -16,9 +16,10 @@ import static org.web3j.utils.Numeric.toHexString; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; -import org.hyperledger.besu.ethereum.p2p.peers.EnodeURL; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; +import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode; @@ -62,7 +63,7 @@ public Hash execute(final NodeRequests node) { } private String signedTransactionData() { - final EnodeURL enodeURL = EnodeURL.fromURI(((RunnableNode) node).enodeUrl()); + final EnodeURL enodeURL = EnodeURLImpl.fromURI(((RunnableNode) node).enodeUrl()); final Bytes payload = createPayload(enodeURL); RawTransaction transaction = diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningConnectionIsAllowedByURLV2Transaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningConnectionIsAllowedByURLV2Transaction.java new file mode 100644 index 00000000000..af6d753d0aa --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningConnectionIsAllowedByURLV2Transaction.java @@ -0,0 +1,80 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.ethereum.permissioning.NodeSmartContractV2PermissioningController; +import org.hyperledger.besu.plugin.data.EnodeURL; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import org.apache.tuweni.bytes.Bytes; +import org.web3j.abi.FunctionEncoder; +import org.web3j.abi.datatypes.Function; +import org.web3j.protocol.core.DefaultBlockParameterName; + +public class NodeSmartContractPermissioningConnectionIsAllowedByURLV2Transaction + implements Transaction { + + private final Address contractAddress; + private final EnodeURL enodeUrl; + + public NodeSmartContractPermissioningConnectionIsAllowedByURLV2Transaction( + final Address contractAddress, final EnodeURL enodeUrl) { + this.contractAddress = contractAddress; + this.enodeUrl = enodeUrl; + } + + @Override + public Boolean execute(final NodeRequests node) { + try { + final String value = + node.eth().ethCall(payload(), DefaultBlockParameterName.LATEST).send().getValue(); + return Bytes.fromHexString(value) + .equals(NodeSmartContractV2PermissioningController.TRUE_RESPONSE); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + + private org.web3j.protocol.core.methods.request.Transaction payload() { + final Bytes payload = createPayload(this.enodeUrl); + + return org.web3j.protocol.core.methods.request.Transaction.createFunctionCallTransaction( + null, null, null, null, contractAddress.toString(), payload.toString()); + } + + private Bytes createPayload(final EnodeURL enodeUrl) { + try { + final String hexNodeIdString = enodeUrl.getNodeId().toUnprefixedHexString(); + final String address = enodeUrl.toURI().getHost(); + final int port = enodeUrl.getListeningPortOrZero(); + + final Function connectionAllowedFunction = + FunctionEncoder.makeFunction( + "connectionAllowed", + List.of("string", "string", "uint16"), + List.of(hexNodeIdString, address, port), + Collections.emptyList()); + return Bytes.fromHexString(FunctionEncoder.encode(connectionAllowedFunction)); + } catch (Exception e) { + throw new RuntimeException("Error calling connectionAllowed", e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningConnectionIsAllowedTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningConnectionIsAllowedTransaction.java index 13b32be019b..80b08e95483 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningConnectionIsAllowedTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningConnectionIsAllowedTransaction.java @@ -18,8 +18,8 @@ import static org.hyperledger.besu.ethereum.permissioning.NodeSmartContractPermissioningController.checkTransactionResult; import org.hyperledger.besu.crypto.Hash; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.p2p.peers.EnodeURL; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.ethereum.permissioning.NodeSmartContractPermissioningController; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode; @@ -69,8 +69,8 @@ private org.web3j.protocol.core.methods.request.Transaction payload() { final Bytes payload = NodeSmartContractPermissioningController.createPayload( IS_CONNECTION_ALLOWED_SIGNATURE, - EnodeURL.fromString(sourceEnodeURL), - EnodeURL.fromString(targetEnodeURL)); + EnodeURLImpl.fromString(sourceEnodeURL), + EnodeURLImpl.fromString(targetEnodeURL)); return org.web3j.protocol.core.methods.request.Transaction.createFunctionCallTransaction( null, null, null, null, contractAddress.toString(), payload.toString()); diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningConnectionIsAllowedV2Transaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningConnectionIsAllowedV2Transaction.java index 3127a0373d3..1eeadb52a46 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningConnectionIsAllowedV2Transaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningConnectionIsAllowedV2Transaction.java @@ -14,9 +14,10 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.p2p.peers.EnodeURL; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.ethereum.permissioning.NodeSmartContractV2PermissioningController; +import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; @@ -56,7 +57,7 @@ public Boolean execute(final NodeRequests node) { } private org.web3j.protocol.core.methods.request.Transaction payload() { - final EnodeURL enodeURL = EnodeURL.fromURI(((RunnableNode) node).enodeUrl()); + final EnodeURL enodeURL = EnodeURLImpl.fromURI(((RunnableNode) node).enodeUrl()); final Bytes payload = createPayload(enodeURL); return org.web3j.protocol.core.methods.request.Transaction.createFunctionCallTransaction( diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningForbidNodeByURLV2Transaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningForbidNodeByURLV2Transaction.java new file mode 100644 index 00000000000..d36f6b69975 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningForbidNodeByURLV2Transaction.java @@ -0,0 +1,95 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm; + +import static org.web3j.utils.Numeric.toHexString; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.plugin.data.EnodeURL; +import org.hyperledger.besu.tests.acceptance.dsl.account.Account; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Collections; +import java.util.List; + +import org.apache.tuweni.bytes.Bytes; +import org.web3j.abi.FunctionEncoder; +import org.web3j.abi.datatypes.Function; +import org.web3j.crypto.RawTransaction; +import org.web3j.crypto.TransactionEncoder; + +public class NodeSmartContractPermissioningForbidNodeByURLV2Transaction + implements Transaction { + + private final Account sender; + private final Address contractAddress; + private final EnodeURL enodeUrl; + + public NodeSmartContractPermissioningForbidNodeByURLV2Transaction( + final Account sender, final Address contractAddress, final EnodeURL enodeUrl) { + this.sender = sender; + this.contractAddress = contractAddress; + this.enodeUrl = enodeUrl; + } + + @Override + public Hash execute(final NodeRequests node) { + final String signedTransactionData = signedTransactionData(); + try { + String hash = + node.eth().ethSendRawTransaction(signedTransactionData).send().getTransactionHash(); + return Hash.fromHexString(hash); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + + private String signedTransactionData() { + final Bytes payload = createPayload(this.enodeUrl); + + RawTransaction transaction = + RawTransaction.createTransaction( + sender.getNextNonce(), + BigInteger.valueOf(1000), + BigInteger.valueOf(3_000_000L), + contractAddress.toString(), + payload.toString()); + + return toHexString( + TransactionEncoder.signMessage(transaction, sender.web3jCredentialsOrThrow())); + } + + private Bytes createPayload(final EnodeURL enodeUrl) { + try { + final String hexNodeIdString = enodeUrl.getNodeId().toUnprefixedHexString(); + final String address = enodeUrl.toURI().getHost(); + final int port = enodeUrl.getListeningPortOrZero(); + + final Function removeNodeFunction = + FunctionEncoder.makeFunction( + "removeEnode", + List.of("string", "string", "uint16"), + List.of(hexNodeIdString, address, port), + Collections.emptyList()); + return Bytes.fromHexString(FunctionEncoder.encode(removeNodeFunction)); + } catch (Exception e) { + throw new RuntimeException("Error removing node from allowlist", e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningForbidNodeTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningForbidNodeTransaction.java index 1e8961fceeb..787cb9752ea 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningForbidNodeTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningForbidNodeTransaction.java @@ -17,9 +17,9 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.web3j.utils.Numeric.toHexString; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; -import org.hyperledger.besu.ethereum.p2p.peers.EnodeURL; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.ethereum.permissioning.NodeSmartContractPermissioningController; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; @@ -68,7 +68,7 @@ private String signedTransactionData() { final String enodeURL = ((RunnableNode) node).enodeUrl().toASCIIString(); final Bytes payload = NodeSmartContractPermissioningController.createPayload( - REMOVE_ENODE_SIGNATURE, EnodeURL.fromString(enodeURL)); + REMOVE_ENODE_SIGNATURE, EnodeURLImpl.fromString(enodeURL)); RawTransaction transaction = RawTransaction.createTransaction( diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningForbidNodeV2Transaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningForbidNodeV2Transaction.java index 47b316ded32..e5c39d69af4 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningForbidNodeV2Transaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningForbidNodeV2Transaction.java @@ -16,9 +16,10 @@ import static org.web3j.utils.Numeric.toHexString; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; -import org.hyperledger.besu.ethereum.p2p.peers.EnodeURL; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; +import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode; @@ -62,7 +63,7 @@ public Hash execute(final NodeRequests node) { } private String signedTransactionData() { - final EnodeURL enodeURL = EnodeURL.fromURI(((RunnableNode) node).enodeUrl()); + final EnodeURL enodeURL = EnodeURLImpl.fromURI(((RunnableNode) node).enodeUrl()); final Bytes payload = createPayload(enodeURL); RawTransaction transaction = diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningIsAllowedTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningIsAllowedTransaction.java index 8ca83e58c92..d72d6ffab8e 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningIsAllowedTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningIsAllowedTransaction.java @@ -17,8 +17,8 @@ import static java.nio.charset.StandardCharsets.UTF_8; import org.hyperledger.besu.crypto.Hash; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.p2p.peers.EnodeURL; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.ethereum.permissioning.NodeSmartContractPermissioningController; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode; @@ -84,7 +84,7 @@ private org.web3j.protocol.core.methods.request.Transaction payload() { final String sourceEnodeURL = ((RunnableNode) node).enodeUrl().toASCIIString(); final Bytes payload = NodeSmartContractPermissioningController.createPayload( - IS_NODE_ALLOWED_SIGNATURE, EnodeURL.fromString(sourceEnodeURL)); + IS_NODE_ALLOWED_SIGNATURE, EnodeURLImpl.fromString(sourceEnodeURL)); return org.web3j.protocol.core.methods.request.Transaction.createFunctionCallTransaction( null, null, null, null, contractAddress.toString(), payload.toString()); diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningTransactions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningTransactions.java index ba635cb073e..8de39e93064 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningTransactions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningTransactions.java @@ -14,8 +14,8 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningV2Transactions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningV2Transactions.java index 6a0734513c7..51d4d446643 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningV2Transactions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/NodeSmartContractPermissioningV2Transactions.java @@ -14,8 +14,9 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; @@ -33,13 +34,29 @@ public Transaction allowNode(final String contractAddress, final Node node accounts.getPrimaryBenefactor(), Address.fromHexString(contractAddress), node); } + public Transaction allowNode(final String contractAddress, final EnodeURL enodeURL) { + return new NodeSmartContractPermissioningAllowNodeByURLV2Transaction( + accounts.getPrimaryBenefactor(), Address.fromHexString(contractAddress), enodeURL); + } + public Transaction forbidNode(final String contractAddress, final Node node) { return new NodeSmartContractPermissioningForbidNodeV2Transaction( accounts.getPrimaryBenefactor(), Address.fromHexString(contractAddress), node); } + public Transaction forbidNode(final String contractAddress, final EnodeURL enodeURL) { + return new NodeSmartContractPermissioningForbidNodeByURLV2Transaction( + accounts.getPrimaryBenefactor(), Address.fromHexString(contractAddress), enodeURL); + } + public Transaction isConnectionAllowed(final String contractAddress, final Node node) { return new NodeSmartContractPermissioningConnectionIsAllowedV2Transaction( Address.fromHexString(contractAddress), node); } + + public Transaction isConnectionAllowed( + final String contractAddress, final EnodeURL enodeURL) { + return new NodeSmartContractPermissioningConnectionIsAllowedByURLV2Transaction( + Address.fromHexString(contractAddress), enodeURL); + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/PermissioningJsonRpcRequestFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/PermissioningJsonRpcRequestFactory.java index b99b2dba61f..d99915abe33 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/PermissioningJsonRpcRequestFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/perm/PermissioningJsonRpcRequestFactory.java @@ -18,7 +18,6 @@ import java.util.Collections; import java.util.List; -import org.assertj.core.util.Lists; import org.web3j.protocol.Web3jService; import org.web3j.protocol.core.Request; import org.web3j.protocol.core.Response; @@ -61,7 +60,10 @@ Request removeNodesFromWhitelist(final List enodeLis Request getNodesWhitelist() { return new Request<>( - "perm_getNodesAllowlist", Lists.emptyList(), web3jService, GetNodesWhitelistResponse.class); + "perm_getNodesAllowlist", + Collections.emptyList(), + web3jService, + GetNodesWhitelistResponse.class); } Request getAccountsWhitelist() { diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/EeaSendRawTransactionTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/EeaSendRawTransactionTransaction.java index ded0bfb1be6..5d2786ae8a6 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/EeaSendRawTransactionTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/EeaSendRawTransactionTransaction.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetCodeTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetCodeTransaction.java index 850f62379b3..dbe708f53b5 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetCodeTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetCodeTransaction.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetPrivacyPrecompileAddressTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetPrivacyPrecompileAddressTransaction.java index abbba72a7c6..cf8cd3f0656 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetPrivacyPrecompileAddressTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetPrivacyPrecompileAddressTransaction.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetPrivateTransactionTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetPrivateTransactionTransaction.java index 5c12b6c13eb..e91a83f314b 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetPrivateTransactionTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetPrivateTransactionTransaction.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivateTransactionGroupResponse; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetTransaction.java index 7ad33c9aa7a..0d6e599a1e2 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetTransaction.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetTransactionReceiptTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetTransactionReceiptTransaction.java index 2ea67b7982f..da2f6b310c6 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetTransactionReceiptTransaction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetTransactionReceiptTransaction.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivacyRequestFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivacyRequestFactory.java index f4e7c0f624e..056598a9d56 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivacyRequestFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivacyRequestFactory.java @@ -14,16 +14,16 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy; -import static com.google.common.base.Preconditions.checkArgument; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.core.PrivacyParameters.FLEXIBLE_PRIVACY_PROXY; import org.hyperledger.besu.crypto.SecureRandomProvider; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.enclave.types.PrivacyGroup; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.parameters.CreatePrivacyGroupParameter; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; -import org.hyperledger.besu.ethereum.privacy.group.OnChainGroupManagement; +import org.hyperledger.besu.ethereum.privacy.group.FlexibleGroupManagement; import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivateTransactionGroupResponse; import org.hyperledger.besu.tests.acceptance.dsl.privacy.util.LogFilterJsonParameter; @@ -40,6 +40,14 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.tuweni.bytes.Bytes; +import org.web3j.abi.FunctionEncoder; +import org.web3j.abi.TypeReference; +import org.web3j.abi.Utils; +import org.web3j.abi.datatypes.Bool; +import org.web3j.abi.datatypes.DynamicArray; +import org.web3j.abi.datatypes.DynamicBytes; +import org.web3j.abi.datatypes.Function; +import org.web3j.abi.datatypes.Type; import org.web3j.crypto.Credentials; import org.web3j.protocol.Web3jService; import org.web3j.protocol.besu.Besu; @@ -54,22 +62,53 @@ import org.web3j.protocol.eea.crypto.PrivateTransactionEncoder; import org.web3j.protocol.eea.crypto.RawPrivateTransaction; import org.web3j.protocol.exceptions.TransactionException; +import org.web3j.tx.ChainIdLong; import org.web3j.tx.Contract; +import org.web3j.tx.PrivateTransactionManager; import org.web3j.tx.response.PollingPrivateTransactionReceiptProcessor; import org.web3j.utils.Base64String; import org.web3j.utils.Numeric; +import org.web3j.utils.Restriction; public class PrivacyRequestFactory { private final SecureRandom secureRandom; + public PrivateTransactionManager getTransactionManager( + final Credentials credentials, + final Base64String privateFrom, + final List privateFor, + final Restriction restriction) { + return new PrivateTransactionManager( + getBesuClient(), + credentials, + new PollingPrivateTransactionReceiptProcessor(getBesuClient(), 1000, 60), + ChainIdLong.NONE, + privateFrom, + privateFor, + restriction); + } + + public PrivateTransactionManager getTransactionManager( + final Credentials credentials, + final Base64String privateFrom, + final Base64String privacyGroupId, + final Restriction restriction) { + return new PrivateTransactionManager( + getBesuClient(), + credentials, + new PollingPrivateTransactionReceiptProcessor(getBesuClient(), 1000, 60), + ChainIdLong.NONE, + privateFrom, + privacyGroupId, + restriction); + } + public static class GetPrivacyPrecompileAddressResponse extends Response
{} public static class GetPrivateTransactionResponse extends Response {} - public static class JsonRpcSuccessResponseResponse extends Response {} - public static class CreatePrivacyGroupResponse extends Response {} public static class DeletePrivacyGroupResponse extends Response {} @@ -151,7 +190,7 @@ public String privxAddToPrivacyGroup( nonce, BigInteger.valueOf(1000), BigInteger.valueOf(3000000), - Address.ONCHAIN_PRIVACY_PROXY.toHexString(), + FLEXIBLE_PRIVACY_PROXY.toHexString(), payload.toHexString(), Base64String.wrap(adder.getEnclaveKey()), privacyGroupId, @@ -184,7 +223,7 @@ public String privxRemoveFromPrivacyGroup( nonce, BigInteger.valueOf(1000), BigInteger.valueOf(3000000), - Address.ONCHAIN_PRIVACY_PROXY.toHexString(), + FLEXIBLE_PRIVACY_PROXY.toHexString(), payload.toHexString(), Base64String.wrap(removerTenant), privacyGroupId, @@ -198,12 +237,41 @@ public String privxRemoveFromPrivacyGroup( } private Bytes encodeRemoveFromGroupFunctionCall(final Bytes toRemove) { - return Bytes.concatenate(OnChainGroupManagement.REMOVE_PARTICIPANT_METHOD_SIGNATURE, toRemove); + final Function function = + new Function( + "removeParticipant", + Arrays.asList(new DynamicBytes(toRemove.toArrayUnsafe())), + Arrays.asList(new TypeReference() {})); + + return Bytes.fromHexString(FunctionEncoder.encode(function)); } public String privxLockPrivacyGroup( final PrivacyNode locker, final Base64String privacyGroupId, final Credentials signer) throws IOException, TransactionException { + return privxLockOrUnlockPrivacyGroup( + locker, + privacyGroupId, + signer, + FlexibleGroupManagement.LOCK_GROUP_METHOD_SIGNATURE.toHexString()); + } + + public String privxUnlockPrivacyGroup( + final PrivacyNode locker, final Base64String privacyGroupId, final Credentials signer) + throws IOException, TransactionException { + return privxLockOrUnlockPrivacyGroup( + locker, + privacyGroupId, + signer, + FlexibleGroupManagement.UNLOCK_GROUP_METHOD_SIGNATURE.toHexString()); + } + + private String privxLockOrUnlockPrivacyGroup( + final PrivacyNode locker, + final Base64String privacyGroupId, + final Credentials signer, + final String callData) + throws IOException, TransactionException { final BigInteger nonce = besuClient .privGetTransactionCount(signer.getAddress(), privacyGroupId) @@ -215,8 +283,8 @@ public String privxLockPrivacyGroup( nonce, BigInteger.valueOf(1000), BigInteger.valueOf(3000000), - Address.ONCHAIN_PRIVACY_PROXY.toHexString(), - OnChainGroupManagement.LOCK_GROUP_METHOD_SIGNATURE.toHexString(), + FLEXIBLE_PRIVACY_PROXY.toHexString(), + callData, Base64String.wrap(locker.getEnclaveKey()), privacyGroupId, org.web3j.utils.Restriction.RESTRICTED); @@ -255,7 +323,7 @@ public PrivxCreatePrivacyGroupResponse privxCreatePrivacyGroup( BigInteger.ZERO, BigInteger.valueOf(1000), BigInteger.valueOf(3000000), - Address.ONCHAIN_PRIVACY_PROXY.toHexString(), + FLEXIBLE_PRIVACY_PROXY.toHexString(), payload.toHexString(), Base64String.wrap(privateFrom), Base64String.wrap(privacyGroupId.toArrayUnsafe()), @@ -270,10 +338,10 @@ public PrivxCreatePrivacyGroupResponse privxCreatePrivacyGroup( return new PrivxCreatePrivacyGroupResponse(privacyGroupId.toBase64String(), transactionHash); } - public Request privxFindOnChainPrivacyGroup( + public Request privxFindFlexiblePrivacyGroup( final List nodes) { return new Request<>( - "privx_findOnChainPrivacyGroup", + "privx_findFlexiblePrivacyGroup", singletonList(nodes), web3jService, PrivxFindPrivacyGroupResponse.class); @@ -430,14 +498,14 @@ public Request privDebugGetStateRoot( DebugGetStateRoot.class); } - public static class PrivxFindPrivacyGroupResponse extends Response> { + public static class PrivxFindPrivacyGroupResponse extends Response> { - public List getGroups() { + public List getGroups() { return getResult(); } } - public static class OnChainPrivacyGroup { + public static class FlexiblePrivacyGroup { private final Base64String privacyGroupId; private final List members; @@ -445,11 +513,11 @@ public static class OnChainPrivacyGroup { private final String description; public enum Type { - ONCHAIN + FLEXIBLE } @JsonCreator - public OnChainPrivacyGroup( + public FlexiblePrivacyGroup( @JsonProperty(value = "privacyGroupId") final String privacyGroupId, @JsonProperty(value = "type") final Type type, @JsonProperty(value = "name") final String name, @@ -458,7 +526,7 @@ public OnChainPrivacyGroup( this(privacyGroupId, members); } - public OnChainPrivacyGroup(final String privacyGroupId, final List members) { + public FlexiblePrivacyGroup(final String privacyGroupId, final List members) { this.privacyGroupId = Base64String.wrap(privacyGroupId); this.name = ""; this.description = ""; @@ -478,7 +546,7 @@ public String getDescription() { } public Type getType() { - return Type.ONCHAIN; + return Type.FLEXIBLE; } public List getMembers() { @@ -493,7 +561,7 @@ public boolean equals(final Object o) { if (o == null || getClass() != o.getClass()) { return false; } - final OnChainPrivacyGroup that = (OnChainPrivacyGroup) o; + final FlexiblePrivacyGroup that = (FlexiblePrivacyGroup) o; return getPrivacyGroupId().equals(that.getPrivacyGroupId()) && getName().equals(that.getName()) && getDescription().equals(that.getDescription()) @@ -531,29 +599,19 @@ public String getTransactionHash() { } private Bytes encodeAddToGroupFunctionCall(final List participants) { - return Bytes.concatenate( - OnChainGroupManagement.ADD_PARTICIPANTS_METHOD_SIGNATURE, encodeList(participants)); - } - - private Bytes encodeList(final List participants) { - final Bytes dynamicParameterOffset = encodeLong(32); - final Bytes length = encodeLong(participants.size()); - return Bytes.concatenate( - dynamicParameterOffset, - length, - Bytes.fromHexString( - participants.stream() - .map(Bytes::toUnprefixedHexString) - .collect(Collectors.joining("")))); - } - - // long to uint256, 8 bytes big endian, so left padded by 24 bytes - private static Bytes encodeLong(final long l) { - checkArgument(l >= 0, "Unsigned value must be positive"); - final byte[] longBytes = new byte[8]; - for (int i = 0; i < 8; i++) { - longBytes[i] = (byte) ((l >> ((7 - i) * 8)) & 0xFF); - } - return Bytes.concatenate(Bytes.wrap(new byte[24]), Bytes.wrap(longBytes)); + final Function function = + new Function( + "addParticipants", + Arrays.asList( + new DynamicArray<>( + DynamicBytes.class, + Utils.typeMap( + participants.stream() + .map(Bytes::toArrayUnsafe) + .collect(Collectors.toList()), + DynamicBytes.class))), + Collections.emptyList()); + + return Bytes.fromHexString(FunctionEncoder.encode(function)); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivacyTransactions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivacyTransactions.java index 218368a3b7a..89a06e8b73b 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivacyTransactions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivacyTransactions.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import java.util.List; diff --git a/acceptance-tests/test-plugins/build.gradle b/acceptance-tests/test-plugins/build.gradle new file mode 100644 index 00000000000..f9e960b4944 --- /dev/null +++ b/acceptance-tests/test-plugins/build.gradle @@ -0,0 +1,37 @@ + +dependencies { + api 'org.slf4j:slf4j-api' + + implementation project(':besu') + implementation project(':crypto:algorithms') + implementation project(':datatypes') + implementation project(':ethereum:core') + implementation project(':ethereum:rlp') + implementation project(':plugin-api') + implementation 'com.google.auto.service:auto-service' + implementation 'info.picocli:picocli' + + testImplementation 'junit:junit' + testImplementation 'org.assertj:assertj-core' + testImplementation 'org.junit.jupiter:junit-jupiter' + + testRuntimeOnly 'org.junit.vintage:junit-vintage-engine' +} + +task testPluginsJar(type: Jar) { + archiveFileName = 'testPlugins.jar' + manifest { + attributes( + 'Specification-Title': archiveBaseName, + 'Specification-Version': project.version, + 'Implementation-Title': archiveBaseName, + 'Implementation-Version': calculateVersion() + ) + } + from sourceSets.main.output +} + +artifacts { testPluginsJar } + + +javadoc { enabled = false } diff --git a/besu/src/test/java/org/hyperledger/besu/plugins/BadCLIOptionsPlugin.java b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/BadCLIOptionsPlugin.java similarity index 82% rename from besu/src/test/java/org/hyperledger/besu/plugins/BadCLIOptionsPlugin.java rename to acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/BadCLIOptionsPlugin.java index ae40a95b834..a3fe06c572c 100644 --- a/besu/src/test/java/org/hyperledger/besu/plugins/BadCLIOptionsPlugin.java +++ b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/BadCLIOptionsPlugin.java @@ -13,7 +13,7 @@ * SPDX-License-Identifier: Apache-2.0 * */ -package org.hyperledger.besu.plugins; +package org.hyperledger.besu.tests.acceptance.plugins; import static java.nio.charset.StandardCharsets.UTF_8; @@ -26,13 +26,13 @@ import java.nio.file.Files; import com.google.auto.service.AutoService; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import picocli.CommandLine.Option; @AutoService(BesuPlugin.class) public class BadCLIOptionsPlugin implements BesuPlugin { - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LoggerFactory.getLogger(BadCLIOptionsPlugin.class); @Option(names = "--poorly-named-option") String poorlyNamedOption = "nothing"; @@ -45,11 +45,13 @@ public void register(final BesuContext context) { callbackDir = new File(System.getProperty("besu.plugins.dir", "plugins")); writeStatus("init"); - context - .getService(PicoCLIOptions.class) - .ifPresent( - picoCLIOptions -> - picoCLIOptions.addPicoCLIOptions("bad-cli", BadCLIOptionsPlugin.this)); + if (System.getProperty("TEST_BAD_CLI", "false").equals("true")) { + context + .getService(PicoCLIOptions.class) + .ifPresent( + picoCLIOptions -> + picoCLIOptions.addPicoCLIOptions("bad-cli", BadCLIOptionsPlugin.this)); + } writeStatus("register"); } diff --git a/besu/src/test/java/org/hyperledger/besu/plugins/TestBesuEventsPlugin.java b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestBesuEventsPlugin.java similarity index 93% rename from besu/src/test/java/org/hyperledger/besu/plugins/TestBesuEventsPlugin.java rename to acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestBesuEventsPlugin.java index 79cdd096016..44e728010cb 100644 --- a/besu/src/test/java/org/hyperledger/besu/plugins/TestBesuEventsPlugin.java +++ b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestBesuEventsPlugin.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.plugins; +package org.hyperledger.besu.tests.acceptance.plugins; import org.hyperledger.besu.plugin.BesuContext; import org.hyperledger.besu.plugin.BesuPlugin; @@ -28,12 +28,12 @@ import java.util.concurrent.atomic.AtomicInteger; import com.google.auto.service.AutoService; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @AutoService(BesuPlugin.class) public class TestBesuEventsPlugin implements BesuPlugin { - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LoggerFactory.getLogger(TestBesuEventsPlugin.class); private BesuContext context; diff --git a/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestPermissioningPlugin.java b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestPermissioningPlugin.java new file mode 100644 index 00000000000..2964e76229f --- /dev/null +++ b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestPermissioningPlugin.java @@ -0,0 +1,94 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.tests.acceptance.plugins; + +import org.hyperledger.besu.plugin.BesuContext; +import org.hyperledger.besu.plugin.BesuPlugin; +import org.hyperledger.besu.plugin.services.PermissioningService; +import org.hyperledger.besu.plugin.services.PicoCLIOptions; + +import com.google.auto.service.AutoService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import picocli.CommandLine.Option; + +@AutoService(BesuPlugin.class) +public class TestPermissioningPlugin implements BesuPlugin { + private static final Logger LOG = LoggerFactory.getLogger(TestPermissioningPlugin.class); + + private static final String aliceNode = + "09b02f8a5fddd222ade4ea4528faefc399623af3f736be3c44f03e2df22fb792f3931a4d9573d333ca74343305762a753388c3422a86d98b713fc91c1ea04842"; + + private static final String bobNode = + "af80b90d25145da28c583359beb47b21796b2fe1a23c1511e443e7a64dfdb27d7434c380f0aa4c500e220aa1a9d068514b1ff4d5019e624e7ba1efe82b340a59"; + + private static final String charlieNode = + "ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90015ea9fee96aed6d9c0fc2fbe0bd1883dee223b3200246ff1e21976bdbc9a0fc8"; + + PermissioningService service; + + @Override + public void register(final BesuContext context) { + context.getService(PicoCLIOptions.class).orElseThrow().addPicoCLIOptions("permissioning", this); + service = context.getService(PermissioningService.class).orElseThrow(); + } + + @Override + public void beforeExternalServices() { + if (enabled) { + service.registerNodePermissioningProvider( + (sourceEnode, destinationEnode) -> { + if (sourceEnode.toString().contains(bobNode) + || destinationEnode.toString().contains(bobNode)) { + + final boolean isBobTalkingToAlice = + sourceEnode.toString().contains(aliceNode) + || destinationEnode.toString().contains(aliceNode); + if (isBobTalkingToAlice) { + LOG.info("BLOCK CONNECTION from {}, to {}", sourceEnode, destinationEnode); + } else { + LOG.info("ALLOW CONNECTION from {}, to {}", sourceEnode, destinationEnode); + } + + return !isBobTalkingToAlice; + } + return true; + }); + + service.registerNodeMessagePermissioningProvider( + (destinationEnode, code) -> { + if (destinationEnode.toString().contains(charlieNode) && transactionMessage(code)) { + LOG.info("BLOCK MESSAGE to {} code {}", destinationEnode, code); + return false; + } + return true; + }); + } + } + + @Override + public void start() {} + + private boolean transactionMessage(final int code) { + return code == 0x02 || code == 0x08 || code == 0x09 || code == 0x0a; + } + + @Override + public void stop() {} + + @Option(names = "--plugin-permissioning-test-enabled") + boolean enabled = false; +} diff --git a/besu/src/test/java/org/hyperledger/besu/plugins/TestPicoCLIPlugin.java b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestPicoCLIPlugin.java similarity index 92% rename from besu/src/test/java/org/hyperledger/besu/plugins/TestPicoCLIPlugin.java rename to acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestPicoCLIPlugin.java index 37192404dab..0db5281537c 100644 --- a/besu/src/test/java/org/hyperledger/besu/plugins/TestPicoCLIPlugin.java +++ b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestPicoCLIPlugin.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.plugins; +package org.hyperledger.besu.tests.acceptance.plugins; import org.hyperledger.besu.plugin.BesuContext; import org.hyperledger.besu.plugin.BesuPlugin; @@ -24,13 +24,13 @@ import java.util.Collections; import com.google.auto.service.AutoService; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import picocli.CommandLine.Option; @AutoService(BesuPlugin.class) public class TestPicoCLIPlugin implements BesuPlugin { - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LoggerFactory.getLogger(TestPicoCLIPlugin.class); @Option( names = {"--Xplugin-test-option"}, @@ -59,8 +59,7 @@ public void register(final BesuContext context) { context .getService(PicoCLIOptions.class) - .ifPresent( - picoCLIOptions -> picoCLIOptions.addPicoCLIOptions("test", TestPicoCLIPlugin.this)); + .ifPresent(picoCLIOptions -> picoCLIOptions.addPicoCLIOptions("test", this)); callbackDir = new File(System.getProperty("besu.plugins.dir", "plugins")); writeSignal("registered"); diff --git a/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestPrivacyServicePlugin.java b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestPrivacyServicePlugin.java new file mode 100644 index 00000000000..4cdd35e8dc4 --- /dev/null +++ b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestPrivacyServicePlugin.java @@ -0,0 +1,108 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.plugins; + +import org.hyperledger.besu.plugin.BesuContext; +import org.hyperledger.besu.plugin.BesuPlugin; +import org.hyperledger.besu.plugin.services.PicoCLIOptions; +import org.hyperledger.besu.plugin.services.PrivacyPluginService; +import org.hyperledger.besu.tests.acceptance.plugins.privacy.TestPrivacyGroupGenesisProvider; +import org.hyperledger.besu.tests.acceptance.plugins.privacy.TestPrivacyPluginPayloadProvider; +import org.hyperledger.besu.tests.acceptance.plugins.privacy.TestSigningPrivateMarkerTransactionFactory; + +import com.google.auto.service.AutoService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import picocli.CommandLine.Option; + +@AutoService(BesuPlugin.class) +public class TestPrivacyServicePlugin implements BesuPlugin { + private static final Logger LOG = LoggerFactory.getLogger(TestPrivacyServicePlugin.class); + + PrivacyPluginService pluginService; + BesuContext context; + + TestPrivacyGroupGenesisProvider privacyGroupGenesisProvider = + new TestPrivacyGroupGenesisProvider(); + TestSigningPrivateMarkerTransactionFactory privateMarkerTransactionFactory = + new TestSigningPrivateMarkerTransactionFactory(); + + @Override + public void register(final BesuContext context) { + this.context = context; + + context + .getService(PicoCLIOptions.class) + .orElseThrow() + .addPicoCLIOptions("privacy-service", this); + pluginService = context.getService(PrivacyPluginService.class).orElseThrow(); + pluginService.setPrivacyGroupGenesisProvider(privacyGroupGenesisProvider); + + LOG.info("Registering Plugins with options " + this); + } + + @Override + public void beforeExternalServices() { + LOG.info("Start Plugins with options {}", this); + + TestPrivacyPluginPayloadProvider payloadProvider = new TestPrivacyPluginPayloadProvider(); + + pluginService.setPayloadProvider(payloadProvider); + payloadProvider.setPluginPayloadPrefix(prefix); + + if (genesisEnabled) { + privacyGroupGenesisProvider.setGenesisEnabled(); + } + + if (signingEnabled) { + pluginService.setPrivateMarkerTransactionFactory(privateMarkerTransactionFactory); + privateMarkerTransactionFactory.setSigningKeyEnabled(signingKey); + } + } + + @Override + public void start() {} + + @Override + public void stop() {} + + @Option(names = "--plugin-privacy-service-encryption-prefix") + String prefix; + + @Option(names = "--plugin-privacy-service-genesis-enabled") + boolean genesisEnabled = false; + + @Option(names = "--plugin-privacy-service-signing-enabled") + boolean signingEnabled = false; + + @Option(names = "--plugin-privacy-service-signing-key") + String signingKey; + + @Override + public String toString() { + return "TestPrivacyServicePlugin{" + + "prefix='" + + prefix + + '\'' + + ", signingEnabled=" + + signingEnabled + + ", genesisEnabled=" + + genesisEnabled + + ", signingKey='" + + signingKey + + '\'' + + '}'; + } +} diff --git a/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestRpcEndpointServicePlugin.java b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestRpcEndpointServicePlugin.java new file mode 100644 index 00000000000..fee061f5449 --- /dev/null +++ b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestRpcEndpointServicePlugin.java @@ -0,0 +1,75 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.plugins; + +import static com.google.common.base.Preconditions.checkArgument; + +import org.hyperledger.besu.plugin.BesuContext; +import org.hyperledger.besu.plugin.BesuPlugin; +import org.hyperledger.besu.plugin.services.RpcEndpointService; +import org.hyperledger.besu.plugin.services.rpc.PluginRpcRequest; + +import java.util.concurrent.atomic.AtomicReference; + +import com.google.auto.service.AutoService; + +@AutoService(BesuPlugin.class) +public class TestRpcEndpointServicePlugin implements BesuPlugin { + + private static final String NAMESPACE_ENABLED = "tests"; + private static final String NAMESPACE_NOT_ENABLED = "notEnabled"; + private final AtomicReference stringStorage = new AtomicReference<>("InitialValue"); + private final AtomicReference arrayStorage = new AtomicReference<>(); + + private String setValue(final PluginRpcRequest request) { + checkArgument(request.getParams().length == 1, "Only one parameter accepted"); + return stringStorage.updateAndGet(x -> request.getParams()[0].toString()); + } + + private String getValue(final PluginRpcRequest request) { + return stringStorage.get(); + } + + private Object[] replaceValueList(final PluginRpcRequest request) { + return arrayStorage.updateAndGet(x -> request.getParams()); + } + + private String throwException(final PluginRpcRequest request) { + throw new RuntimeException("Kaboom"); + } + + @Override + public void register(final BesuContext context) { + context + .getService(RpcEndpointService.class) + .ifPresent( + rpcEndpointService -> { + rpcEndpointService.registerRPCEndpoint(NAMESPACE_ENABLED, "getValue", this::getValue); + rpcEndpointService.registerRPCEndpoint(NAMESPACE_ENABLED, "setValue", this::setValue); + rpcEndpointService.registerRPCEndpoint( + NAMESPACE_ENABLED, "replaceValueList", this::replaceValueList); + rpcEndpointService.registerRPCEndpoint( + NAMESPACE_ENABLED, "throwException", this::throwException); + rpcEndpointService.registerRPCEndpoint( + NAMESPACE_NOT_ENABLED, "getValue", this::getValue); + }); + } + + @Override + public void start() {} + + @Override + public void stop() {} +} diff --git a/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/privacy/TestPrivacyGroupGenesisProvider.java b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/privacy/TestPrivacyGroupGenesisProvider.java new file mode 100644 index 00000000000..d763683ba7f --- /dev/null +++ b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/privacy/TestPrivacyGroupGenesisProvider.java @@ -0,0 +1,82 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + */ +package org.hyperledger.besu.tests.acceptance.plugins.privacy; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Quantity; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.plugin.data.PrivacyGenesis; +import org.hyperledger.besu.plugin.data.PrivacyGenesisAccount; +import org.hyperledger.besu.plugin.services.privacy.PrivacyGroupGenesisProvider; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.units.bigints.UInt256; + +public class TestPrivacyGroupGenesisProvider implements PrivacyGroupGenesisProvider { + private boolean genesisEnabled = false; + + public void setGenesisEnabled() { + this.genesisEnabled = true; + } + + @Override + public PrivacyGenesis getPrivacyGenesis(final Bytes privacyGroupId, final long blockNumber) { + if (!genesisEnabled) return Collections::emptyList; + + return () -> + List.of( + new PrivacyGenesisAccount() { + @Override + public Address getAddress() { + return org.hyperledger.besu.datatypes.Address.fromHexString( + "0x1000000000000000000000000000000000000001"); + } + + @Override + public Map getStorage() { + return Collections.emptyMap(); + } + + @Override + public Long getNonce() { + return 0L; + } + + @Override + public Quantity getBalance() { + return Wei.of(1000); + } + + // The code in the genesis file needs to be the deployed contract code, not the code + // to deploy + // the contract + // you can generate it using the solc --bin-runtime flag + // cd ./acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/ + // docker run -v $PWD:/sources ethereum/solc:0.5.0 -o /sources/output --bin-runtime + // /sources/EventEmitter.sol --overwrite + + @Override + public Bytes getCode() { + return Bytes.fromHexString( + "0x608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633fa4f2451461005c5780636057361d1461008757806367e404ce146100c2575b600080fd5b34801561006857600080fd5b50610071610119565b6040518082815260200191505060405180910390f35b34801561009357600080fd5b506100c0600480360360208110156100aa57600080fd5b8101908080359060200190929190505050610123565b005b3480156100ce57600080fd5b506100d76101d9565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600254905090565b7fc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f53382604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a18060028190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690509056fea165627a7a72305820e74360c3d08936cb1747ad641729261ff5e83b6fc0d303d136e171f15f07d7740029"); + } + }); + } +} diff --git a/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/privacy/TestPrivacyPluginPayloadProvider.java b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/privacy/TestPrivacyPluginPayloadProvider.java new file mode 100644 index 00000000000..f40d71b9c57 --- /dev/null +++ b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/privacy/TestPrivacyPluginPayloadProvider.java @@ -0,0 +1,62 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + */ +package org.hyperledger.besu.tests.acceptance.plugins.privacy; + +import static org.hyperledger.besu.ethereum.privacy.PrivateTransaction.readFrom; +import static org.hyperledger.besu.ethereum.privacy.PrivateTransaction.serialize; + +import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; +import org.hyperledger.besu.plugin.data.PrivateTransaction; +import org.hyperledger.besu.plugin.data.Transaction; +import org.hyperledger.besu.plugin.services.privacy.PrivacyPluginPayloadProvider; + +import java.util.Optional; + +import org.apache.tuweni.bytes.Bytes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestPrivacyPluginPayloadProvider implements PrivacyPluginPayloadProvider { + private static final Logger LOG = LoggerFactory.getLogger(TestPrivacyPluginPayloadProvider.class); + private String prefix; + + public void setPluginPayloadPrefix(final String prefix) { + this.prefix = prefix; + } + + @Override + public Bytes generateMarkerPayload( + final PrivateTransaction privateTransaction, final String privacyUserId) { + + return Bytes.wrap(Bytes.fromHexString(prefix), serialize(privateTransaction).encoded()); + } + + @Override + public Optional getPrivateTransactionFromPayload( + final Transaction transaction) { + + final Bytes prefixBytes = Bytes.fromHexString(prefix); + if (transaction.getPayload().slice(0, prefixBytes.size()).equals(prefixBytes)) { + LOG.info("processing payload for " + prefix); + final BytesValueRLPInput bytesValueRLPInput = + new BytesValueRLPInput(transaction.getPayload().slice(prefixBytes.size()).copy(), false); + return Optional.of(readFrom(bytesValueRLPInput)); + } else { + LOG.info("Can not process payload for " + prefix); + return Optional.empty(); + } + } +} diff --git a/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/privacy/TestSigningPrivateMarkerTransactionFactory.java b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/privacy/TestSigningPrivateMarkerTransactionFactory.java new file mode 100644 index 00000000000..3ab57a28e2c --- /dev/null +++ b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/privacy/TestSigningPrivateMarkerTransactionFactory.java @@ -0,0 +1,85 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.plugins.privacy; + +import static org.hyperledger.besu.datatypes.Address.extract; + +import org.hyperledger.besu.crypto.KeyPair; +import org.hyperledger.besu.crypto.SECPPrivateKey; +import org.hyperledger.besu.crypto.SignatureAlgorithm; +import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; +import org.hyperledger.besu.plugin.data.PrivateTransaction; +import org.hyperledger.besu.plugin.data.TransactionType; +import org.hyperledger.besu.plugin.data.UnsignedPrivateMarkerTransaction; +import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory; + +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestSigningPrivateMarkerTransactionFactory implements PrivateMarkerTransactionFactory { + + private static final Logger LOG = + LoggerFactory.getLogger(TestSigningPrivateMarkerTransactionFactory.class); + + KeyPair aliceFixedSigningKey; + Address sender; + + public void setSigningKeyEnabled(final String privateMarkerTransactionSigningKey) { + final SignatureAlgorithm algorithm = SignatureAlgorithmFactory.getInstance(); + final SECPPrivateKey privateKey = + algorithm.createPrivateKey(Bytes32.fromHexString(privateMarkerTransactionSigningKey)); + + aliceFixedSigningKey = algorithm.createKeyPair(privateKey); + sender = extract(Hash.hash(aliceFixedSigningKey.getPublicKey().getEncodedBytes())); + } + + @Override + public Bytes create( + final UnsignedPrivateMarkerTransaction unsignedPrivateMarkerTransaction, + final PrivateTransaction privateTransaction, + final String privacyUserId) { + + final Transaction transaction = + Transaction.builder() + .type(TransactionType.FRONTIER) + .nonce(unsignedPrivateMarkerTransaction.getNonce()) + .gasPrice( + unsignedPrivateMarkerTransaction.getGasPrice().map(Wei::fromQuantity).orElse(null)) + .gasLimit(unsignedPrivateMarkerTransaction.getGasLimit()) + .to(unsignedPrivateMarkerTransaction.getTo().orElseThrow()) + .value(Wei.fromQuantity(unsignedPrivateMarkerTransaction.getValue())) + .payload(unsignedPrivateMarkerTransaction.getPayload()) + .signAndBuild(aliceFixedSigningKey); + + LOG.info("Signing PMT from {}", sender); + + final BytesValueRLPOutput out = new BytesValueRLPOutput(); + transaction.writeTo(out); + return out.encoded(); + } + + @Override + public Address getSender( + final PrivateTransaction privateTransaction, final String privacyUserId) { + return sender; + } +} diff --git a/besu/src/test/java/org/hyperledger/besu/services/BesuPluginContextImplTest.java b/acceptance-tests/test-plugins/src/test/java/org/hyperledger/besu/services/BesuPluginContextImplTest.java similarity index 93% rename from besu/src/test/java/org/hyperledger/besu/services/BesuPluginContextImplTest.java rename to acceptance-tests/test-plugins/src/test/java/org/hyperledger/besu/services/BesuPluginContextImplTest.java index 234abb26ef7..5fd73b66b8f 100644 --- a/besu/src/test/java/org/hyperledger/besu/services/BesuPluginContextImplTest.java +++ b/acceptance-tests/test-plugins/src/test/java/org/hyperledger/besu/services/BesuPluginContextImplTest.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import org.hyperledger.besu.plugin.BesuPlugin; -import org.hyperledger.besu.plugins.TestPicoCLIPlugin; +import org.hyperledger.besu.tests.acceptance.plugins.TestPicoCLIPlugin; import java.io.File; import java.io.IOException; @@ -27,6 +27,7 @@ import java.util.List; import java.util.Optional; +import org.assertj.core.api.Assertions; import org.assertj.core.api.ThrowableAssert; import org.junit.After; import org.junit.BeforeClass; @@ -57,10 +58,11 @@ public void verifyEverythingGoesSmoothly() { assertThat(contextImpl.getPlugins()).isNotEmpty(); final Optional testPluginOptional = findTestPlugin(contextImpl.getPlugins()); - assertThat(testPluginOptional).isPresent(); + Assertions.assertThat(testPluginOptional).isPresent(); final TestPicoCLIPlugin testPicoCLIPlugin = testPluginOptional.get(); assertThat(testPicoCLIPlugin.getState()).isEqualTo("registered"); + contextImpl.beforeExternalServices(); contextImpl.startPlugins(); assertThat(testPicoCLIPlugin.getState()).isEqualTo("started"); @@ -77,6 +79,9 @@ public void registrationErrorsHandledSmoothly() { contextImpl.registerPlugins(new File(".").toPath()); assertThat(contextImpl.getPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class); + contextImpl.beforeExternalServices(); + assertThat(contextImpl.getPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class); + contextImpl.startPlugins(); assertThat(contextImpl.getPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class); @@ -98,6 +103,7 @@ public void startErrorsHandledSmoothly() { final TestPicoCLIPlugin testPicoCLIPlugin = testPluginOptional.get(); assertThat(testPicoCLIPlugin.getState()).isEqualTo("registered"); + contextImpl.beforeExternalServices(); contextImpl.startPlugins(); assertThat(testPicoCLIPlugin.getState()).isEqualTo("failstart"); assertThat(contextImpl.getPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class); @@ -120,6 +126,7 @@ public void stopErrorsHandledSmoothly() { final TestPicoCLIPlugin testPicoCLIPlugin = testPluginOptional.get(); assertThat(testPicoCLIPlugin.getState()).isEqualTo("registered"); + contextImpl.beforeExternalServices(); contextImpl.startPlugins(); assertThat(testPicoCLIPlugin.getState()).isEqualTo("started"); @@ -140,6 +147,7 @@ public void lifecycleExceptions() throws Throwable { assertThatExceptionOfType(IllegalStateException.class).isThrownBy(registerPlugins); assertThatExceptionOfType(IllegalStateException.class).isThrownBy(contextImpl::stopPlugins); + contextImpl.beforeExternalServices(); contextImpl.startPlugins(); assertThatExceptionOfType(IllegalStateException.class).isThrownBy(registerPlugins); assertThatExceptionOfType(IllegalStateException.class).isThrownBy(contextImpl::startPlugins); diff --git a/acceptance-tests/tests/build.gradle b/acceptance-tests/tests/build.gradle index a2502913359..8b23195361d 100644 --- a/acceptance-tests/tests/build.gradle +++ b/acceptance-tests/tests/build.gradle @@ -11,19 +11,45 @@ * specific language governing permissions and limitations under the License. */ +plugins { + id 'org.web3j' version '4.9.2' + id 'org.web3j.solidity' version '0.3.5' +} + +configurations.all { + resolutionStrategy.eachDependency { DependencyResolveDetails details -> + if (details.requested.group == 'org.web3j' && details.requested.version == '4.9.2') { + details.useVersion '4.9.4' + details.because 'Plugin version is 4.9.2 (latest), but we want it to use web3j libs version 4.9.4' + } + } +} + +web3j { generatedPackageName = 'org.hyperledger.besu.tests.web3j.generated' } + +sourceSets.main.solidity.srcDirs = ["$projectDir/contracts"] + +solidity { resolvePackages = false } + dependencies { - implementation project(':crypto') + api 'org.slf4j:slf4j-api' + + implementation project(':crypto:algorithms') testImplementation project(':acceptance-tests:dsl') + testImplementation project(':acceptance-tests:test-plugins') testImplementation project(':besu') testImplementation project(':config') testImplementation project(':consensus:clique') + testImplementation project(':datatypes') testImplementation project(':enclave') testImplementation project(':ethereum:api') testImplementation project(':ethereum:core') testImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts') + testImplementation project(':ethereum:p2p') testImplementation project(':ethereum:permissioning') testImplementation project(':ethereum:rlp') + testImplementation project(':metrics:core') testImplementation project(':plugin-api') testImplementation project(':privacy-contracts') testImplementation project(':testutil') @@ -31,16 +57,35 @@ dependencies { testImplementation 'com.github.tomakehurst:wiremock-jre8-standalone' testImplementation 'commons-io:commons-io' + testImplementation 'io.grpc:grpc-all' + testImplementation 'io.grpc:grpc-core' + testImplementation 'io.grpc:grpc-netty' + testImplementation 'io.grpc:grpc-stub' + testImplementation 'io.opentelemetry:opentelemetry-extension-trace-propagators' + testImplementation 'io.opentelemetry.instrumentation:opentelemetry-okhttp-3.0' + testImplementation 'io.netty:netty-all' + testImplementation 'io.opentelemetry:opentelemetry-api' + testImplementation 'io.opentelemetry:opentelemetry-exporter-otlp' + testImplementation 'io.opentelemetry.proto:opentelemetry-proto' + testImplementation 'io.opentelemetry:opentelemetry-sdk' + testImplementation 'io.opentelemetry:opentelemetry-sdk-trace' + testImplementation 'io.opentracing.contrib:opentracing-okhttp3' + testImplementation 'io.opentracing:opentracing-api' + testImplementation 'io.opentracing:opentracing-util' + testImplementation 'io.vertx:vertx-core' testImplementation 'junit:junit' - testImplementation 'net.consensys:orion' testImplementation 'org.apache.commons:commons-compress' - testImplementation 'org.apache.tuweni:crypto' + testImplementation 'org.apache.logging.log4j:log4j-core' + testImplementation 'org.apache.tuweni:tuweni-crypto' testImplementation 'org.assertj:assertj-core' testImplementation 'org.awaitility:awaitility' + testImplementation 'org.junit.jupiter:junit-jupiter' + testImplementation 'org.testcontainers:testcontainers' testImplementation 'org.web3j:abi' testImplementation 'org.web3j:besu' - testImplementation 'tech.pegasys.ethsigner.internal:core' - testImplementation 'tech.pegasys.ethsigner.internal:file-based' + testImplementation 'org.web3j:core' + + testRuntimeOnly 'org.junit.vintage:junit-vintage-engine' } test.enabled = false @@ -48,22 +93,81 @@ test.enabled = false sourceSets { test { resources { - srcDirs "${rootDir}/besu/build/libs" + srcDirs "${rootDir}/acceptance-tests/test-plugins/build/libs" } } } -processTestResources.dependsOn(':besu:testJar') +processTestResources.dependsOn(':acceptance-tests:test-plugins:testPluginsJar') task acceptanceTest(type: Test) { inputs.property "integration.date", LocalTime.now() // so it runs at every invocation + useJUnitPlatform {} + + dependsOn(rootProject.installDist) + setSystemProperties(test.getSystemProperties()) + systemProperty 'acctests.runBesuAsProcess', 'true' + systemProperty 'java.security.properties', "${buildDir}/resources/test/acceptanceTesting.security" + mustRunAfter rootProject.subprojects*.test + description = 'Runs ALL Besu acceptance tests (mainnet and non-mainnet).' + group = 'verification' + + jvmArgs "-XX:ErrorFile=${buildDir}/jvmErrorLogs/java_err_pid%p.log" + + testLogging { + exceptionFormat = 'full' + showStackTraces = true + showStandardStreams = Boolean.getBoolean('acctests.showStandardStreams') + showExceptions = true + showCauses = true + } + + doFirst { mkdir "${buildDir}/jvmErrorLogs" } +} +task acceptanceTestMainnet(type: Test) { + inputs.property "integration.date", LocalTime.now() // so it runs at every invocation + exclude '**/bft/**' + exclude '**/clique/**' + exclude '**/permissioning/**' + exclude '**/privacy/**' + + useJUnitPlatform {} + + dependsOn(rootProject.installDist) + setSystemProperties(test.getSystemProperties()) + systemProperty 'acctests.runBesuAsProcess', 'true' + systemProperty 'java.security.properties', "${buildDir}/resources/test/acceptanceTesting.security" + mustRunAfter rootProject.subprojects*.test + description = 'Runs MAINNET Besu acceptance tests (excluding permissioning, privacy and some other stable features).' + group = 'verification' + + jvmArgs "-XX:ErrorFile=${buildDir}/jvmErrorLogs/java_err_pid%p.log" + + testLogging { + exceptionFormat = 'full' + showStackTraces = true + showStandardStreams = Boolean.getBoolean('acctests.showStandardStreams') + showExceptions = true + showCauses = true + } + + doFirst { mkdir "${buildDir}/jvmErrorLogs" } +} + +task acceptanceTestCliqueBft(type: Test) { + inputs.property "integration.date", LocalTime.now() // so it runs at every invocation + include '**/bft/**' + include '**/clique/**' + + useJUnitPlatform {} + dependsOn(rootProject.installDist) setSystemProperties(test.getSystemProperties()) systemProperty 'acctests.runBesuAsProcess', 'true' systemProperty 'java.security.properties', "${buildDir}/resources/test/acceptanceTesting.security" mustRunAfter rootProject.subprojects*.test - description = 'Runs Besu acceptance tests.' + description = 'Runs Clique and BFT Besu acceptance tests.' group = 'verification' jvmArgs "-XX:ErrorFile=${buildDir}/jvmErrorLogs/java_err_pid%p.log" @@ -76,7 +180,59 @@ task acceptanceTest(type: Test) { showCauses = true } - doFirst { - mkdir "${buildDir}/jvmErrorLogs" + doFirst { mkdir "${buildDir}/jvmErrorLogs" } +} + +task acceptanceTestPrivacy(type: Test) { + inputs.property "integration.date", LocalTime.now() // so it runs at every invocation + include '**/privacy/**' + + useJUnitPlatform {} + + dependsOn(rootProject.installDist) + setSystemProperties(test.getSystemProperties()) + systemProperty 'acctests.runBesuAsProcess', 'true' + systemProperty 'java.security.properties', "${buildDir}/resources/test/acceptanceTesting.security" + mustRunAfter rootProject.subprojects*.test + description = 'Runs Privacy Besu acceptance tests.' + group = 'verification' + + jvmArgs "-XX:ErrorFile=${buildDir}/jvmErrorLogs/java_err_pid%p.log" + + testLogging { + exceptionFormat = 'full' + showStackTraces = true + showStandardStreams = Boolean.getBoolean('acctests.showStandardStreams') + showExceptions = true + showCauses = true + } + + doFirst { mkdir "${buildDir}/jvmErrorLogs" } +} + +task acceptanceTestPermissioning(type: Test) { + inputs.property "integration.date", LocalTime.now() // so it runs at every invocation + include '**/permissioning/**' + + useJUnitPlatform {} + + dependsOn(rootProject.installDist) + setSystemProperties(test.getSystemProperties()) + systemProperty 'acctests.runBesuAsProcess', 'true' + systemProperty 'java.security.properties', "${buildDir}/resources/test/acceptanceTesting.security" + mustRunAfter rootProject.subprojects*.test + description = 'Runs Permissioning Besu acceptance tests.' + group = 'verification' + + jvmArgs "-XX:ErrorFile=${buildDir}/jvmErrorLogs/java_err_pid%p.log" + + testLogging { + exceptionFormat = 'full' + showStackTraces = true + showStandardStreams = Boolean.getBoolean('acctests.showStandardStreams') + showExceptions = true + showCauses = true } + + doFirst { mkdir "${buildDir}/jvmErrorLogs" } } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/CrossContractReader.sol b/acceptance-tests/tests/contracts/CrossContractReader.sol similarity index 94% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/CrossContractReader.sol rename to acceptance-tests/tests/contracts/CrossContractReader.sol index 32c6836433e..e54e4c712eb 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/CrossContractReader.sol +++ b/acceptance-tests/tests/contracts/CrossContractReader.sol @@ -9,8 +9,10 @@ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 */ -pragma solidity >=0.4.0 <0.6.0; +pragma solidity >=0.7.0 <0.9.0; import "./EventEmitter.sol"; @@ -50,7 +52,7 @@ contract CrossContractReader { } function destroy() public { - selfdestruct(msg.sender); + selfdestruct(payable(msg.sender)); } function remoteDestroy(address crossAddress) public { diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/EventEmitter.sol b/acceptance-tests/tests/contracts/EventEmitter.sol similarity index 95% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/EventEmitter.sol rename to acceptance-tests/tests/contracts/EventEmitter.sol index 6053bb63c5c..22afa7a0868 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/EventEmitter.sol +++ b/acceptance-tests/tests/contracts/EventEmitter.sol @@ -12,8 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ - -pragma solidity >=0.4.0 <0.6.0; +pragma solidity >=0.7.0 <0.9.0; // compile with: // solc EventEmitter.sol --bin --abi --optimize --overwrite -o . @@ -25,7 +24,7 @@ contract EventEmitter { address _sender; uint _value; - constructor() public { + constructor() { owner = msg.sender; } diff --git a/acceptance-tests/tests/contracts/RemoteSimpleStorage.sol b/acceptance-tests/tests/contracts/RemoteSimpleStorage.sol new file mode 100644 index 00000000000..072948e035b --- /dev/null +++ b/acceptance-tests/tests/contracts/RemoteSimpleStorage.sol @@ -0,0 +1,37 @@ +/* + * Copyright contributors to Hyperledger Besu + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +pragma solidity >=0.7.0 <0.9.0; + +import "./SimpleStorage.sol"; + +// compile with: +// solc RemoteSimpleStorage.sol --bin --abi --optimize --overwrite -o . +// then create web3j wrappers with: +// web3j solidity generate -b ./generated/RemoteSimpleStorage.bin -a ./generated/RemoteSimpleStorage.abi -o ../../../../../ -p org.hyperledger.besu.tests.web3j.generated +contract RemoteSimpleStorage { + SimpleStorage public simpleStorage; + + function setRemote(SimpleStorage _simpleStorage) public { + simpleStorage = _simpleStorage; + } + + function set(uint value) public { + simpleStorage.set(value); + } + + function get() public view returns (uint) { + return simpleStorage.get(); + } +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/RevertReason.sol b/acceptance-tests/tests/contracts/RevertReason.sol similarity index 93% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/RevertReason.sol rename to acceptance-tests/tests/contracts/RevertReason.sol index b2c2d1188c2..d632910662c 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/RevertReason.sol +++ b/acceptance-tests/tests/contracts/RevertReason.sol @@ -9,8 +9,10 @@ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 */ -pragma solidity >=0.4.0 <0.6.0; +pragma solidity >=0.7.0 <0.9.0; // compile with: // solc RevertReason.sol --bin --abi --optimize --overwrite -o . diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/SimpleStorage.sol b/acceptance-tests/tests/contracts/SimpleStorage.sol similarity index 97% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/SimpleStorage.sol rename to acceptance-tests/tests/contracts/SimpleStorage.sol index eabb8d26f10..35dc7c3932f 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/SimpleStorage.sol +++ b/acceptance-tests/tests/contracts/SimpleStorage.sol @@ -12,8 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ - -pragma solidity >=0.4.0 <0.6.0; +pragma solidity >=0.7.0 <0.9.0; // compile with: // solc SimpleStorage.sol --bin --abi --optimize --overwrite -o . diff --git a/acceptance-tests/tests/contracts/TestDepth.sol b/acceptance-tests/tests/contracts/TestDepth.sol new file mode 100644 index 00000000000..ec49a1ad8bf --- /dev/null +++ b/acceptance-tests/tests/contracts/TestDepth.sol @@ -0,0 +1,32 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +pragma solidity >=0.7.0 <0.9.0; + +contract TestDepth { + uint256 public x; + + function depth(uint256 y) public { + // bool result; + if (y > 0) { + bytes memory call = abi.encodeWithSignature("depth(uint256)", --y); + (bool result,) = address(this).delegatecall(call); + require(result); + } + else { + // Save the remaining gas in storage so that we can access it later + x = gasleft(); + } + } +} \ No newline at end of file diff --git a/acceptance-tests/tests/simple-permissioning-smart-contract/migrations/1_initial_migration.js b/acceptance-tests/tests/simple-permissioning-smart-contract/migrations/1_initial_migration.js index 4d5f3f9b02e..90538d95eb3 100644 --- a/acceptance-tests/tests/simple-permissioning-smart-contract/migrations/1_initial_migration.js +++ b/acceptance-tests/tests/simple-permissioning-smart-contract/migrations/1_initial_migration.js @@ -1,3 +1,5 @@ +// Copyright ConsenSys AG. +// SPDX-License-Identifier: Apache-2.0 var Migrations = artifacts.require("./Migrations.sol"); module.exports = function(deployer) { diff --git a/acceptance-tests/tests/simple-permissioning-smart-contract/migrations/2_deploy_contracts.js b/acceptance-tests/tests/simple-permissioning-smart-contract/migrations/2_deploy_contracts.js index b23928c0a26..b3c2fbb0e03 100644 --- a/acceptance-tests/tests/simple-permissioning-smart-contract/migrations/2_deploy_contracts.js +++ b/acceptance-tests/tests/simple-permissioning-smart-contract/migrations/2_deploy_contracts.js @@ -1,3 +1,5 @@ +// Copyright ConsenSys AG. +// SPDX-License-Identifier: Apache-2.0 var SimpleNodePermissioning = artifacts.require("SimpleNodePermissioning"); var SimpleAccountPermissioning = artifacts.require("SimpleAccountPermissioning"); diff --git a/acceptance-tests/tests/simple-permissioning-smart-contract/test/test-account-permissioning.js b/acceptance-tests/tests/simple-permissioning-smart-contract/test/test-account-permissioning.js index e987b4a1482..2a23dc5dd57 100644 --- a/acceptance-tests/tests/simple-permissioning-smart-contract/test/test-account-permissioning.js +++ b/acceptance-tests/tests/simple-permissioning-smart-contract/test/test-account-permissioning.js @@ -1,3 +1,5 @@ +// Copyright ConsenSys AG. +// SPDX-License-Identifier: Apache-2.0 const TestPermissioning = artifacts.require('SimpleAccountPermissioning.sol'); var proxy; diff --git a/acceptance-tests/tests/simple-permissioning-smart-contract/test/test-node-permissioning.js b/acceptance-tests/tests/simple-permissioning-smart-contract/test/test-node-permissioning.js index 7b0b135939b..ea748ee4886 100644 --- a/acceptance-tests/tests/simple-permissioning-smart-contract/test/test-node-permissioning.js +++ b/acceptance-tests/tests/simple-permissioning-smart-contract/test/test-node-permissioning.js @@ -1,3 +1,5 @@ +// Copyright ConsenSys AG. +// SPDX-License-Identifier: Apache-2.0 const TestPermissioning = artifacts.require('SimpleNodePermissioning.sol'); var proxy; diff --git a/acceptance-tests/tests/simple-permissioning-smart-contract/truffle.js b/acceptance-tests/tests/simple-permissioning-smart-contract/truffle.js index db2718a5f88..08862e0127f 100644 --- a/acceptance-tests/tests/simple-permissioning-smart-contract/truffle.js +++ b/acceptance-tests/tests/simple-permissioning-smart-contract/truffle.js @@ -1,3 +1,5 @@ +// Copyright ConsenSys AG. +// SPDX-License-Identifier: Apache-2.0 const PrivateKeyProvider = require('truffle-hdwallet-provider'); // address 627306090abaB3A6e1400e9345bC60c78a8BEf57 diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/AbstractPreexistingNodeTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/AbstractPreexistingNodeTest.java index c05a4ab4818..5c4b58ec019 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/AbstractPreexistingNodeTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/AbstractPreexistingNodeTest.java @@ -18,7 +18,7 @@ import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; -import org.hyperledger.besu.ethereum.core.Wei; +import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeConfigurationBuilder; diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/CreateAccountAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/CreateAccountAcceptanceTest.java index caa96837956..c0af67c4942 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/CreateAccountAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/CreateAccountAcceptanceTest.java @@ -19,14 +19,14 @@ import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class CreateAccountAcceptanceTest extends AcceptanceTestBase { private Node minerNode; - @Before + @BeforeEach public void setUp() throws Exception { minerNode = besu.createMinerNode("minerNode"); cluster.start(minerNode, besu.createArchiveNode("archiveNode")); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/GossipTransactionAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/GossipTransactionAcceptanceTest.java index 32eac30de8c..1e6ca018918 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/GossipTransactionAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/GossipTransactionAcceptanceTest.java @@ -14,21 +14,21 @@ */ package org.hyperledger.besu.tests.acceptance; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; import org.hyperledger.besu.tests.acceptance.dsl.transaction.account.TransferTransaction; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class GossipTransactionAcceptanceTest extends AcceptanceTestBase { private Node archiveNode1; - @Before + @BeforeEach public void setUp() throws Exception { archiveNode1 = besu.createArchiveNode("archiveNode1"); cluster.start(archiveNode1, besu.createArchiveNode("archiveNode2")); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/LoggingTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/LoggingTest.java new file mode 100644 index 00000000000..e0276842f06 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/LoggingTest.java @@ -0,0 +1,38 @@ +/* + * Copyright contributors to Hyperledger Besu + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import java.io.IOException; + +import org.junit.Test; + +public class LoggingTest extends AcceptanceTestBase { + + @Test + public void testDefaultLoggingIsAtLeastInfo() throws IOException { + final BesuNode node = besu.createArchiveNode("logger"); + cluster.startConsoleCapture(); + cluster.runNodeStart(node); + + node.verify(net.awaitPeerCount(0)); + + assertThat(cluster.getConsoleContents()).contains("| INFO |"); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/MetricsAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/MetricsAcceptanceTest.java index 4fe6ffa3b79..2f7aee17b60 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/MetricsAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/MetricsAcceptanceTest.java @@ -26,15 +26,15 @@ import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class MetricsAcceptanceTest extends AcceptanceTestBase { private BesuNode metricsNode; private OkHttpClient client; - @Before + @BeforeEach public void setUp() throws Exception { metricsNode = besu.create( diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/OpenTelemetryAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/OpenTelemetryAcceptanceTest.java new file mode 100644 index 00000000000..79a4fdbb8cf --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/OpenTelemetryAcceptanceTest.java @@ -0,0 +1,253 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance; + +import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.metrics.MetricsProtocol; +import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeConfigurationBuilder; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.common.io.Closer; +import com.google.protobuf.ByteString; +import io.grpc.Server; +import io.grpc.Status; +import io.grpc.netty.NettyServerBuilder; +import io.grpc.stub.StreamObserver; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.extension.trace.propagation.B3Propagator; +import io.opentelemetry.instrumentation.okhttp.v3_0.OkHttpTelemetry; +import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest; +import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceResponse; +import io.opentelemetry.proto.collector.metrics.v1.MetricsServiceGrpc; +import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest; +import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse; +import io.opentelemetry.proto.collector.trace.v1.TraceServiceGrpc; +import io.opentelemetry.proto.metrics.v1.ResourceMetrics; +import io.opentelemetry.proto.trace.v1.ResourceSpans; +import io.opentelemetry.proto.trace.v1.Span; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import okhttp3.Call; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class OpenTelemetryAcceptanceTest extends AcceptanceTestBase { + + private static final class FakeCollector extends TraceServiceGrpc.TraceServiceImplBase { + private final List receivedSpans = new ArrayList<>(); + private final Status returnedStatus = Status.OK; + + @Override + public void export( + final ExportTraceServiceRequest request, + final StreamObserver responseObserver) { + receivedSpans.addAll(request.getResourceSpansList()); + responseObserver.onNext(ExportTraceServiceResponse.newBuilder().build()); + if (!returnedStatus.isOk()) { + if (returnedStatus.getCode() == Status.Code.DEADLINE_EXCEEDED) { + // Do not call onCompleted to simulate a deadline exceeded. + return; + } + responseObserver.onError(returnedStatus.asRuntimeException()); + return; + } + responseObserver.onCompleted(); + } + + List getReceivedSpans() { + return receivedSpans; + } + } + + private static final class FakeMetricsCollector + extends MetricsServiceGrpc.MetricsServiceImplBase { + private final List receivedMetrics = new ArrayList<>(); + private final Status returnedStatus = Status.OK; + + @Override + public void export( + final ExportMetricsServiceRequest request, + final StreamObserver responseObserver) { + + receivedMetrics.addAll(request.getResourceMetricsList()); + responseObserver.onNext(ExportMetricsServiceResponse.newBuilder().build()); + if (!returnedStatus.isOk()) { + if (returnedStatus.getCode() == Status.Code.DEADLINE_EXCEEDED) { + // Do not call onCompleted to simulate a deadline exceeded. + return; + } + responseObserver.onError(returnedStatus.asRuntimeException()); + return; + } + responseObserver.onCompleted(); + } + + List getReceivedMetrics() { + return receivedMetrics; + } + } + + private final FakeMetricsCollector fakeMetricsCollector = new FakeMetricsCollector(); + private final FakeCollector fakeTracesCollector = new FakeCollector(); + private final Closer closer = Closer.create(); + + private BesuNode metricsNode; + + @BeforeEach + public void setUp() throws Exception { + System.setProperty("root.log.level", "DEBUG"); + final Server server = + NettyServerBuilder.forPort(4317) + .addService(fakeTracesCollector) + .addService(fakeMetricsCollector) + .build() + .start(); + closer.register(server::shutdownNow); + + final MetricsConfiguration configuration = + MetricsConfiguration.builder() + .protocol(MetricsProtocol.OPENTELEMETRY) + .enabled(true) + .port(0) + .hostsAllowlist(singletonList("*")) + .build(); + final Map env = new HashMap<>(); + env.put("OTEL_METRIC_EXPORT_INTERVAL", "1000"); + env.put("OTEL_TRACES_SAMPLER", "always_on"); + env.put("OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4317"); + env.put("OTEL_EXPORTER_OTLP_INSECURE", "true"); + env.put("OTEL_EXPORTER_OTLP_PROTOCOL", "grpc"); + env.put("OTEL_BSP_SCHEDULE_DELAY", "1000"); + env.put("OTEL_BSP_EXPORT_TIMEOUT", "3000"); + + metricsNode = + besu.create( + new BesuNodeConfigurationBuilder() + .name("metrics-node") + .jsonRpcEnabled() + .metricsConfiguration(configuration) + .environment(env) + .build()); + cluster.start(metricsNode); + } + + @AfterEach + public void tearDown() throws Exception { + closer.close(); + } + + @Test + public void metricsReporting() { + WaitUtils.waitFor( + 30, + () -> { + final List resourceMetrics = fakeMetricsCollector.getReceivedMetrics(); + assertThat(resourceMetrics.isEmpty()).isFalse(); + }); + } + + @Test + public void traceReporting() { + // longer timeout since at 30s this test is flaky + WaitUtils.waitFor( + 60, + () -> { + // call the json RPC endpoint to generate a trace. + net.netVersion().verify(metricsNode); + final List spans = fakeTracesCollector.getReceivedSpans(); + assertThat(spans.isEmpty()).isFalse(); + final Span internalSpan = spans.get(0).getScopeSpans(0).getSpans(0); + assertThat(internalSpan.getKind()).isEqualTo(Span.SpanKind.SPAN_KIND_INTERNAL); + final ByteString parent = internalSpan.getParentSpanId(); + assertThat(parent.isEmpty()).isFalse(); + final Span serverSpan = spans.get(0).getScopeSpans(0).getSpans(1); + assertThat(serverSpan.getKind()).isEqualTo(Span.SpanKind.SPAN_KIND_SERVER); + final ByteString rootSpanId = serverSpan.getParentSpanId(); + assertThat(rootSpanId.isEmpty()).isTrue(); + }); + } + + @Test + public void traceReportingWithTraceId() { + final Duration timeout = Duration.ofSeconds(1); + WaitUtils.waitFor( + 60, + () -> { + final OpenTelemetry openTelemetry = + OpenTelemetrySdk.builder() + .setPropagators( + ContextPropagators.create( + TextMapPropagator.composite(B3Propagator.injectingSingleHeader()))) + .setTracerProvider( + SdkTracerProvider.builder().setSampler(Sampler.alwaysOn()).build()) + .build(); + final Call.Factory client = + OkHttpTelemetry.builder(openTelemetry) + .build() + .newCallFactory( + new OkHttpClient.Builder() + .connectTimeout(timeout) + .readTimeout(timeout) + .writeTimeout(timeout) + .build()); + final Request request = + new Request.Builder() + .url("http://localhost:" + metricsNode.getJsonRpcPort().get()) + .post( + RequestBody.create( + "{\"jsonrpc\":\"2.0\",\"method\":\"net_version\",\"params\":[],\"id\":255}", + MediaType.get("application/json"))) + .build(); + final Response response = client.newCall(request).execute(); + try { + assertThat(response.code()).isEqualTo(200); + final List spans = + new ArrayList<>(fakeTracesCollector.getReceivedSpans()); + assertThat(spans.isEmpty()).isFalse(); + final Span internalSpan = spans.get(0).getScopeSpans(0).getSpans(0); + assertThat(internalSpan.getKind()).isEqualTo(Span.SpanKind.SPAN_KIND_INTERNAL); + final ByteString parent = internalSpan.getParentSpanId(); + assertThat(parent.isEmpty()).isFalse(); + final Span serverSpan = spans.get(0).getScopeSpans(0).getSpans(1); + assertThat(serverSpan.getKind()).isEqualTo(Span.SpanKind.SPAN_KIND_SERVER); + final ByteString rootSpanId = serverSpan.getParentSpanId(); + assertThat(rootSpanId.isEmpty()).isFalse(); + } finally { + response.close(); + fakeTracesCollector.getReceivedSpans().clear(); + } + }); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/RpcApisTogglesAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/RpcApisTogglesAcceptanceTest.java index 6ffed6e8b9c..821d440b71c 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/RpcApisTogglesAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/RpcApisTogglesAcceptanceTest.java @@ -22,8 +22,8 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import org.java_websocket.exceptions.WebsocketNotConnectedException; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class RpcApisTogglesAcceptanceTest extends AcceptanceTestBase { @@ -31,11 +31,11 @@ public class RpcApisTogglesAcceptanceTest extends AcceptanceTestBase { private BesuNode rpcDisabledNode; private BesuNode ethApiDisabledNode; - @Before + @BeforeEach public void before() throws Exception { rpcEnabledNode = besu.createArchiveNode("rpc-enabled"); rpcDisabledNode = besu.createArchiveNodeWithRpcDisabled("rpc-disabled"); - ethApiDisabledNode = besu.createArchiveNodeWithRpcApis("eth-api-disabled", RpcApis.NET); + ethApiDisabledNode = besu.createArchiveNodeWithRpcApis("eth-api-disabled", RpcApis.NET.name()); cluster.start(rpcEnabledNode, rpcDisabledNode, ethApiDisabledNode); } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/RunHelpTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/RunHelpTest.java index eeec787cf8b..dabb277b048 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/RunHelpTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/RunHelpTest.java @@ -22,7 +22,7 @@ import java.io.IOException; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class RunHelpTest extends AcceptanceTestBase { @@ -38,6 +38,5 @@ public void testShowsHelpAndExits() throws IOException { final String consoleContents = cluster.getConsoleContents(); assertThat(consoleContents) .startsWith("Usage:\n\nbesu [OPTIONS] [COMMAND]\n\nDescription:\n\n"); - assertThat(consoleContents).endsWith("\nBesu is licensed under the Apache License 2.0\n"); } } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/backup/BackupRoundTripAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/backup/BackupRoundTripAcceptanceTest.java index f38fd093099..d2afc2e6d39 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/backup/BackupRoundTripAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/backup/BackupRoundTripAcceptanceTest.java @@ -20,8 +20,8 @@ import static org.assertj.core.api.Assertions.assertThat; import org.hyperledger.besu.config.JsonUtil; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Wei; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.tests.acceptance.AbstractPreexistingNodeTest; import org.hyperledger.besu.tests.acceptance.database.DatabaseMigrationAcceptanceTest; import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; @@ -36,10 +36,10 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; -import java.util.function.Function; +import java.util.function.UnaryOperator; +import javax.annotation.Nonnull; import com.fasterxml.jackson.databind.node.ObjectNode; -import org.jetbrains.annotations.NotNull; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -139,10 +139,7 @@ public void backupRoundtripAndBack() throws IOException { besu.createNode( "restore " + testName, configureNodeCommands( - restorePath, - "operator", - "x-restore-state", - "--backup-path=" + backupPath.toString())); + restorePath, "operator", "x-restore-state", "--backup-path=" + backupPath)); cluster.startNode(restoreNode); WaitUtils.waitFor(60, () -> restoreNode.verify(exitedSuccessfully)); @@ -185,9 +182,9 @@ public void backupRoundtripAndBack() throws IOException { assertThat(rebackupManifest).isEqualTo(backupManifest); } - @NotNull - private Function - configureNodeCommands(final Path dataPath, final String... commands) { + @Nonnull + private UnaryOperator configureNodeCommands( + final Path dataPath, final String... commands) { return nodeBuilder -> super.configureNode(nodeBuilder).dataPath(dataPath).run(commands); } } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftAcceptanceTestParameterization.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftAcceptanceTestParameterization.java new file mode 100644 index 00000000000..b7464190abe --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftAcceptanceTestParameterization.java @@ -0,0 +1,71 @@ +/* + * Copyright 2020 ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.bft; + +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeFactory; + +import java.util.ArrayList; +import java.util.List; + +public class BftAcceptanceTestParameterization { + + public static List getFactories() { + final List ret = new ArrayList<>(); + ret.addAll( + List.of( + new Object[] { + "ibft2", + new BftAcceptanceTestParameterization( + BesuNodeFactory::createIbft2Node, BesuNodeFactory::createIbft2NodeWithValidators) + }, + new Object[] { + "qbft", + new BftAcceptanceTestParameterization( + BesuNodeFactory::createQbftNode, BesuNodeFactory::createQbftNodeWithValidators) + })); + return ret; + } + + @FunctionalInterface + public interface NodeCreator { + + BesuNode create(BesuNodeFactory factory, String name) throws Exception; + } + + @FunctionalInterface + public interface NodeWithValidatorsCreator { + + BesuNode create(BesuNodeFactory factory, String name, String[] validators) throws Exception; + } + + private final NodeCreator creatorFn; + private final NodeWithValidatorsCreator createorWithValidatorFn; + + public BftAcceptanceTestParameterization( + final NodeCreator creatorFn, final NodeWithValidatorsCreator createorWithValidatorFn) { + this.creatorFn = creatorFn; + this.createorWithValidatorFn = createorWithValidatorFn; + } + + public BesuNode createNode(BesuNodeFactory factory, String name) throws Exception { + return creatorFn.create(factory, name); + } + + public BesuNode createNodeWithValidators( + BesuNodeFactory factory, String name, String[] validators) throws Exception { + return createorWithValidatorFn.create(factory, name, validators); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftBlockRewardPaymentAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftBlockRewardPaymentAcceptanceTest.java new file mode 100644 index 00000000000..4225035b7ff --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftBlockRewardPaymentAcceptanceTest.java @@ -0,0 +1,251 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.bft; + +import static java.util.Collections.singletonList; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.tests.acceptance.dsl.account.Account; +import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.Optional; +import java.util.TreeMap; + +import org.junit.Test; + +public class BftBlockRewardPaymentAcceptanceTest extends ParameterizedBftTestBase { + + private static final Amount BLOCK_REWARD = Amount.wei(new BigInteger("5000000000000000000", 10)); + + public BftBlockRewardPaymentAcceptanceTest( + final String testName, final BftAcceptanceTestParameterization nodeFactory) { + super(testName, nodeFactory); + } + + @Test + public void validatorsArePaidBlockReward() throws Exception { + final String[] validators = {"validator"}; + final BesuNode validator = nodeFactory.createNodeWithValidators(besu, "validator", validators); + final BesuNode nonValidator = + nodeFactory.createNodeWithValidators(besu, "nonValidator", validators); + cluster.start(validator, nonValidator); + final Account validator1Account = Account.create(ethTransactions, validator.getAddress()); + + final int blockRewardEth = 5; + final int blockToCheck = 2; + + cluster.verify(validator1Account.balanceAtBlockEquals(Amount.ether(0), BigInteger.ZERO)); + cluster.verify( + validator1Account.balanceAtBlockEquals( + Amount.ether(blockRewardEth * blockToCheck), BigInteger.valueOf(blockToCheck))); + } + + @Test + public void payBlockRewardToConfiguredNode() throws Exception { + final String[] validators = {"validator1"}; + final BesuNode validator1 = + nodeFactory.createNodeWithValidators(besu, "validator1", validators); + final Optional initialConfig = + validator1.getGenesisConfigProvider().create(singletonList(validator1)); + if (initialConfig.isEmpty()) { + throw new RuntimeException("Unable to generate genesis config."); + } + + final String miningBeneficiaryAddress = "0x1234567890123456789012345678901234567890"; + final Account miningBeneficiaryAccount = + Account.create(ethTransactions, Address.fromHexString(miningBeneficiaryAddress)); + + final String bftOptions = formatKeyValues("miningbeneficiary", miningBeneficiaryAddress); + final String configWithMiningBeneficiary = configureBftOptions(initialConfig.get(), bftOptions); + validator1.setGenesisConfig(configWithMiningBeneficiary); + + cluster.start(validator1); + final int blockRewardEth = 5; + final int blockToCheck = 2; + + cluster.verify(miningBeneficiaryAccount.balanceAtBlockEquals(Amount.ether(0), BigInteger.ZERO)); + cluster.verify( + miningBeneficiaryAccount.balanceAtBlockEquals( + Amount.ether(blockRewardEth * blockToCheck), BigInteger.valueOf(blockToCheck))); + } + + @Test + public void payBlockRewardAccordingToTransitions_defaultInitialMiningBeneficiary() + throws Exception { + final List
addresses = generateAddresses(2); + final Map> transitions = + Map.of( + 2L, Optional.of(addresses.get(0)), + 3L, Optional.of(addresses.get(1)), + 6L, Optional.empty(), + 8L, Optional.of(addresses.get(0))); + testMiningBeneficiaryTransitions(Optional.empty(), transitions); + } + + @Test + public void payBlockRewardAccordingToTransitions_customInitialMiningBeneficiary() + throws Exception { + final List
addresses = generateAddresses(4); + final Map> transitions = + Map.of( + 1L, Optional.of(addresses.get(1)), + 2L, Optional.of(addresses.get(2)), + 3L, Optional.of(addresses.get(3)), + 4L, Optional.empty()); + + testMiningBeneficiaryTransitions(Optional.of(addresses.get(0)), transitions); + } + + private List
generateAddresses(final int count) { + final List
addresses = new ArrayList<>(); + for (int i = 0; i < count; i++) { + addresses.add(Address.fromHexString(Integer.toString(i + 1, 16))); + } + + return addresses; + } + + private void testMiningBeneficiaryTransitions( + final Optional
initialMiningBeneficiary, + final Map> miningBeneficiaryTransitions) + throws Exception { + final String[] validators = {"validator1"}; + final BesuNode validator1 = + nodeFactory.createNodeWithValidators(besu, "validator1", validators); + final Optional initialConfig = + validator1.getGenesisConfigProvider().create(singletonList(validator1)); + if (initialConfig.isEmpty()) { + throw new RuntimeException("Unable to generate genesis config."); + } + + final String miningBeneficiary = initialMiningBeneficiary.map(Address::toHexString).orElse(""); + final String bftOptions = formatKeyValues("miningbeneficiary", miningBeneficiary); + final String configWithMiningBeneficiary = + configureBftOptions(initialConfig.get(), bftOptions, miningBeneficiaryTransitions); + validator1.setGenesisConfig(configWithMiningBeneficiary); + + cluster.start(validator1); + + // Check that expected address receive block reward at each block + final NavigableMap> orderedTransitions = + new TreeMap<>(miningBeneficiaryTransitions); + final long lastConfiguredBlock = orderedTransitions.lastKey(); + final Map accountBalances = new HashMap<>(); + for (long i = 1; i < lastConfiguredBlock + 2; i++) { + final Address beneficiaryAddress = + Optional.ofNullable(orderedTransitions.floorEntry(i)) + .flatMap(Entry::getValue) + .orElse(validator1.getAddress()); + final Account beneficiary = Account.create(ethTransactions, beneficiaryAddress); + + final Amount currentBalance = + accountBalances.computeIfAbsent(beneficiaryAddress, __ -> Amount.wei(BigInteger.ZERO)); + cluster.verify(beneficiary.balanceAtBlockEquals(currentBalance, BigInteger.valueOf(i - 1))); + final Amount newBalance = currentBalance.add(BLOCK_REWARD); + cluster.verify(beneficiary.balanceAtBlockEquals(newBalance, BigInteger.valueOf(i))); + accountBalances.put(beneficiaryAddress, newBalance); + } + } + + private String formatKeyValues(final Object... keyOrValue) { + if (keyOrValue.length % 2 == 1) { + // An odd number of strings cannot form a set of key-value pairs + throw new IllegalArgumentException("Must supply key-value pairs"); + } + final StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < keyOrValue.length; i += 2) { + if (i > 0) { + stringBuilder.append(", "); + } + final String key = keyOrValue[i].toString(); + final Object value = keyOrValue[i + 1]; + final String valueStr = value instanceof String ? quote(value) : value.toString(); + stringBuilder.append(String.format("\n%s: %s", quote(key), valueStr)); + } + return stringBuilder.toString(); + } + + private String quote(final Object value) { + return '"' + value.toString() + '"'; + } + + private String configureBftOptions(final String originalOptions, final String bftOptions) { + return configureBftOptions(originalOptions, bftOptions, Collections.emptyMap()); + } + + private String configureBftOptions( + final String originalOptions, + final String bftOptions, + final Map> transitions) { + final StringBuilder stringBuilder = + new StringBuilder() + .append(formatBftTransitionsOptions(transitions)) + .append(",\n") + .append(quote(bftType)) + .append(": {") + .append(bftOptions) + .append(","); + return originalOptions.replace(quote(bftType) + ": {", stringBuilder.toString()); + } + + private String formatBftTransitionsOptions(final Map> transitions) { + final StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder.append(quote("transitions")); + stringBuilder.append(": {\n"); + stringBuilder.append(quote(bftType)); + stringBuilder.append(": ["); + + boolean isFirst = true; + for (Long blockNumber : transitions.keySet()) { + if (!isFirst) { + stringBuilder.append(","); + } + isFirst = false; + + final Optional
miningBeneficiary = transitions.get(blockNumber); + stringBuilder.append("\n"); + stringBuilder.append(formatTransition(blockNumber, miningBeneficiary)); + } + + stringBuilder.append("\n]"); + stringBuilder.append("}\n"); + + return stringBuilder.toString(); + } + + private String formatTransition( + final long blockNumber, final Optional
miningBeneficiary) { + final StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("{"); + stringBuilder.append( + formatKeyValues( + "block", + blockNumber, + "miningbeneficiary", + miningBeneficiary.map(Address::toHexString).orElse(""))); + stringBuilder.append("}"); + return stringBuilder.toString(); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftDiscardRpcAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftDiscardRpcAcceptanceTest.java new file mode 100644 index 00000000000..40d0e881459 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftDiscardRpcAcceptanceTest.java @@ -0,0 +1,50 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.bft; + +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import org.junit.Test; + +public class BftDiscardRpcAcceptanceTest extends ParameterizedBftTestBase { + + public BftDiscardRpcAcceptanceTest( + final String testName, final BftAcceptanceTestParameterization nodeFactory) { + super(testName, nodeFactory); + } + + @Test + public void shouldDiscardVotes() throws Exception { + final String[] validators = {"validator1", "validator3"}; + final BesuNode validator1 = + nodeFactory.createNodeWithValidators(besu, "validator1", validators); + final BesuNode validator2 = + nodeFactory.createNodeWithValidators(besu, "validator2", validators); + final BesuNode validator3 = + nodeFactory.createNodeWithValidators(besu, "validator3", validators); + cluster.start(validator1, validator2, validator3); + + validator1.execute(bftTransactions.createAddProposal(validator2)); + validator1.execute(bftTransactions.createRemoveProposal(validator3)); + validator1.verify( + bft.pendingVotesEqual().addProposal(validator2).removeProposal(validator3).build()); + + validator1.execute(bftTransactions.createDiscardProposal(validator2)); + validator1.verify(bft.pendingVotesEqual().removeProposal(validator3).build()); + + validator1.execute(bftTransactions.createDiscardProposal(validator3)); + cluster.verify(bft.noProposals()); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java new file mode 100644 index 00000000000..e529268cb59 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java @@ -0,0 +1,227 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.bft; + +import org.hyperledger.besu.config.JsonUtil; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.core.AddressHelpers; +import org.hyperledger.besu.ethereum.core.MiningParameters; +import org.hyperledger.besu.tests.acceptance.dsl.account.Account; +import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import java.util.List; +import java.util.Optional; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.Test; + +public class BftMiningAcceptanceTest extends ParameterizedBftTestBase { + + public BftMiningAcceptanceTest( + final String testName, final BftAcceptanceTestParameterization nodeFactory) { + super(testName, nodeFactory); + } + + @Test + public void shouldMineOnSingleNodeWithPaidGas_Berlin() throws Exception { + final BesuNode minerNode = nodeFactory.createNode(besu, "miner1"); + cluster.start(minerNode); + + cluster.verify(blockchain.reachesHeight(minerNode, 1)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + minerNode.execute(accountTransactions.createTransfer(sender, 50)); + cluster.verify(sender.balanceEquals(50)); + + minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); + cluster.verify(receiver.balanceEquals(1)); + + minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); + cluster.verify(receiver.balanceEquals(3)); + } + + @Test + public void shouldMineOnSingleNodeWithFreeGas_Berlin() throws Exception { + final BesuNode minerNode = nodeFactory.createNode(besu, "miner1"); + final MiningParameters zeroGasMiningParams = + new MiningParameters.Builder() + .miningEnabled(true) + .minTransactionGasPrice(Wei.ZERO) + .coinbase(AddressHelpers.ofValue(1)) + .build(); + minerNode.setMiningParameters(zeroGasMiningParams); + + cluster.start(minerNode); + + cluster.verify(blockchain.reachesHeight(minerNode, 1)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + minerNode.execute(accountTransactions.createTransfer(sender, 50, Amount.ZERO)); + cluster.verify(sender.balanceEquals(50)); + + minerNode.execute( + accountTransactions.createIncrementalTransfers(sender, receiver, 1, Amount.ZERO)); + cluster.verify(receiver.balanceEquals(1)); + + minerNode.execute( + accountTransactions.createIncrementalTransfers(sender, receiver, 2, Amount.ZERO)); + cluster.verify(receiver.balanceEquals(3)); + } + + @Test + public void shouldMineOnSingleNodeWithPaidGas_London() throws Exception { + final BesuNode minerNode = nodeFactory.createNode(besu, "miner1"); + updateGenesisConfigToLondon(minerNode, false); + + cluster.start(minerNode); + + cluster.verify(blockchain.reachesHeight(minerNode, 1)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + minerNode.execute(accountTransactions.createTransfer(sender, 50)); + cluster.verify(sender.balanceEquals(50)); + + minerNode.execute(accountTransactions.create1559Transfer(sender, 50, 4)); + cluster.verify(sender.balanceEquals(100)); + + minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); + cluster.verify(receiver.balanceEquals(1)); + + minerNode.execute(accountTransactions.create1559IncrementalTransfers(sender, receiver, 2, 4)); + cluster.verify(receiver.balanceEquals(3)); + } + + @Test + public void shouldMineOnSingleNodeWithFreeGas_London() throws Exception { + final BesuNode minerNode = nodeFactory.createNode(besu, "miner1"); + updateGenesisConfigToLondon(minerNode, true); + + cluster.start(minerNode); + + cluster.verify(blockchain.reachesHeight(minerNode, 1)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + minerNode.execute(accountTransactions.createTransfer(sender, 50, Amount.ZERO)); + cluster.verify(sender.balanceEquals(50)); + + minerNode.execute(accountTransactions.create1559Transfer(sender, 50, 4, Amount.ZERO)); + cluster.verify(sender.balanceEquals(100)); + + minerNode.execute( + accountTransactions.createIncrementalTransfers(sender, receiver, 1, Amount.ZERO)); + cluster.verify(receiver.balanceEquals(1)); + + minerNode.execute( + accountTransactions.create1559IncrementalTransfers(sender, receiver, 2, 4, Amount.ZERO)); + cluster.verify(receiver.balanceEquals(3)); + } + + @Test + public void shouldMineOnMultipleNodes() throws Exception { + final BesuNode minerNode1 = nodeFactory.createNode(besu, "miner1"); + final BesuNode minerNode2 = nodeFactory.createNode(besu, "miner2"); + final BesuNode minerNode3 = nodeFactory.createNode(besu, "miner3"); + final BesuNode minerNode4 = nodeFactory.createNode(besu, "miner4"); + cluster.start(minerNode1, minerNode2, minerNode3, minerNode4); + + cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + minerNode1.execute(accountTransactions.createTransfer(sender, 50)); + cluster.verify(sender.balanceEquals(50)); + + minerNode2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); + cluster.verify(receiver.balanceEquals(1)); + + minerNode3.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); + cluster.verify(receiver.balanceEquals(3)); + + minerNode4.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 3)); + cluster.verify(receiver.balanceEquals(6)); + } + + @Test + public void shouldMineOnMultipleNodesEvenWhenClusterContainsNonValidator() throws Exception { + final String[] validators = {"validator1", "validator2", "validator3"}; + final BesuNode validator1 = + nodeFactory.createNodeWithValidators(besu, "validator1", validators); + final BesuNode validator2 = + nodeFactory.createNodeWithValidators(besu, "validator2", validators); + final BesuNode validator3 = + nodeFactory.createNodeWithValidators(besu, "validator3", validators); + final BesuNode nonValidatorNode = + nodeFactory.createNodeWithValidators(besu, "non-validator", validators); + cluster.start(validator1, validator2, validator3, nonValidatorNode); + + cluster.verify(blockchain.reachesHeight(validator1, 1, 85)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + validator1.execute(accountTransactions.createTransfer(sender, 50)); + cluster.verify(sender.balanceEquals(50)); + + validator2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); + cluster.verify(receiver.balanceEquals(1)); + + nonValidatorNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); + cluster.verify(receiver.balanceEquals(3)); + } + + @Test + public void shouldStillMineWhenANonProposerNodeFailsAndHasSufficientValidators() + throws Exception { + final BesuNode minerNode1 = nodeFactory.createNode(besu, "miner1"); + final BesuNode minerNode2 = nodeFactory.createNode(besu, "miner2"); + final BesuNode minerNode3 = nodeFactory.createNode(besu, "miner3"); + final BesuNode minerNode4 = nodeFactory.createNode(besu, "miner4"); + final List validators = + bft.validators(new BesuNode[] {minerNode1, minerNode2, minerNode3, minerNode4}); + final BesuNode nonProposerNode = validators.get(validators.size() - 1); + cluster.start(validators); + + cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85)); + + final Account receiver = accounts.createAccount("account2"); + + cluster.stopNode(nonProposerNode); + validators.get(0).execute(accountTransactions.createTransfer(receiver, 80)); + + cluster.verifyOnActiveNodes(receiver.balanceEquals(80)); + } + + private static void updateGenesisConfigToLondon( + final BesuNode minerNode, final boolean zeroBaseFeeEnabled) { + final Optional genesisConfig = + minerNode.getGenesisConfigProvider().create(List.of(minerNode)); + final ObjectNode genesisConfigNode = JsonUtil.objectNodeFromString(genesisConfig.orElseThrow()); + final ObjectNode config = (ObjectNode) genesisConfigNode.get("config"); + config.remove("berlinBlock"); + config.put("londonBlock", 0); + config.put("zeroBaseFee", zeroBaseFeeEnabled); + minerNode.setGenesisConfig(genesisConfigNode.toString()); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftProposalRpcAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftProposalRpcAcceptanceTest.java new file mode 100644 index 00000000000..7fccf33fa27 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftProposalRpcAcceptanceTest.java @@ -0,0 +1,49 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.bft; + +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import org.junit.Test; + +public class BftProposalRpcAcceptanceTest extends ParameterizedBftTestBase { + + public BftProposalRpcAcceptanceTest( + final String testName, final BftAcceptanceTestParameterization nodeFactory) { + super(testName, nodeFactory); + } + + @Test + public void shouldReturnProposals() throws Exception { + final String[] validators = {"validator1", "validator2", "validator3"}; + final BesuNode validator1 = + nodeFactory.createNodeWithValidators(besu, "validator1", validators); + final BesuNode validator2 = + nodeFactory.createNodeWithValidators(besu, "validator2", validators); + final BesuNode validator3 = + nodeFactory.createNodeWithValidators(besu, "validator3", validators); + cluster.start(validator1, validator2, validator3); + + cluster.verify(bft.noProposals()); + validator1.execute(bftTransactions.createAddProposal(validator3)); + validator1.execute(bftTransactions.createRemoveProposal(validator2)); + validator2.execute(bftTransactions.createRemoveProposal(validator3)); + + validator1.verify( + bft.pendingVotesEqual().addProposal(validator3).removeProposal(validator2).build()); + validator2.verify(bft.pendingVotesEqual().removeProposal(validator3).build()); + validator3.verify(bft.noProposals()); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftProposeRpcAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftProposeRpcAcceptanceTest.java new file mode 100644 index 00000000000..7db3d6a5b9f --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftProposeRpcAcceptanceTest.java @@ -0,0 +1,59 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.bft; + +import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import org.junit.Test; + +// These tests prove the ibft_proposeValidatorVote and ibft_getValidatorsByBlockNumber (implicitly) +// JSON RPC calls. +public class BftProposeRpcAcceptanceTest extends ParameterizedBftTestBase { + + public BftProposeRpcAcceptanceTest( + final String testName, final BftAcceptanceTestParameterization nodeFactory) { + super(testName, nodeFactory); + } + + @Test + public void validatorsCanBeAddedAndThenRemoved() throws Exception { + final String[] validators = {"validator1", "validator2", "validator3"}; + final BesuNode validator1 = + nodeFactory.createNodeWithValidators(besu, "validator1", validators); + final BesuNode validator2 = + nodeFactory.createNodeWithValidators(besu, "validator2", validators); + final BesuNode validator3 = + nodeFactory.createNodeWithValidators(besu, "validator3", validators); + final BesuNode nonValidatorNode = + nodeFactory.createNodeWithValidators(besu, "non-validator", validators); + cluster.start(validator1, validator2, validator3, nonValidatorNode); + + cluster.verify(bft.validatorsEqual(validator1, validator2, validator3)); + final Condition addedCondition = bft.awaitValidatorSetChange(validator1); + validator1.execute(bftTransactions.createAddProposal(nonValidatorNode)); + validator2.execute(bftTransactions.createAddProposal(nonValidatorNode)); + + cluster.verify(addedCondition); + cluster.verify(bft.validatorsEqual(validator1, validator2, validator3, nonValidatorNode)); + + final Condition removedCondition = bft.awaitValidatorSetChange(validator1); + validator2.execute(bftTransactions.createRemoveProposal(nonValidatorNode)); + validator3.execute(bftTransactions.createRemoveProposal(nonValidatorNode)); + nonValidatorNode.execute(bftTransactions.createRemoveProposal(nonValidatorNode)); + cluster.verify(removedCondition); + cluster.verify(bft.validatorsEqual(validator1, validator2, validator3)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftZeroValidators.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftZeroValidators.java new file mode 100644 index 00000000000..898ad47b3f8 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftZeroValidators.java @@ -0,0 +1,38 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.bft; + +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import org.junit.Test; + +public class BftZeroValidators extends ParameterizedBftTestBase { + + public BftZeroValidators( + final String testName, final BftAcceptanceTestParameterization nodeFactory) { + super(testName, nodeFactory); + } + + @Test + public void zeroValidatorsFormValidCluster() throws Exception { + final String[] validators = {}; + final BesuNode node1 = nodeFactory.createNodeWithValidators(besu, "node1", validators); + final BesuNode node2 = nodeFactory.createNodeWithValidators(besu, "node2", validators); + + cluster.start(node1, node2); + + cluster.verify(net.awaitPeerCount(1)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/ParameterizedBftTestBase.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/ParameterizedBftTestBase.java new file mode 100644 index 00000000000..e08d4a5c206 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/ParameterizedBftTestBase.java @@ -0,0 +1,43 @@ +/* + * Copyright 2020 ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.bft; + +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; + +import java.util.Collection; + +import org.junit.Ignore; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +@Ignore("This is not a test class, it offers BFT parameterization only.") +public abstract class ParameterizedBftTestBase extends AcceptanceTestBase { + + protected final String bftType; + protected final BftAcceptanceTestParameterization nodeFactory; + + @Parameters(name = "{0}") + public static Collection factoryFunctions() { + return BftAcceptanceTestParameterization.getFactories(); + } + + protected ParameterizedBftTestBase( + final String bftType, final BftAcceptanceTestParameterization input) { + this.bftType = bftType; + this.nodeFactory = input; + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/ParameterizedPkiQbftTestBase.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/ParameterizedPkiQbftTestBase.java new file mode 100644 index 00000000000..29c00b65d96 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/ParameterizedPkiQbftTestBase.java @@ -0,0 +1,41 @@ +/* + * Copyright 2020 ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.bft.pki; + +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; + +import java.util.Collection; + +import org.junit.Ignore; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +@Ignore("This is not a test class, it offers PKI QBFT parameterization only.") +public abstract class ParameterizedPkiQbftTestBase extends AcceptanceTestBase { + + protected final PkiQbftAcceptanceTestParameterization nodeFactory; + + @Parameters(name = "{0}") + public static Collection factoryFunctions() { + return PkiQbftAcceptanceTestParameterization.getFactories(); + } + + protected ParameterizedPkiQbftTestBase( + final String testName, final PkiQbftAcceptanceTestParameterization input) { + this.nodeFactory = input; + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTest.java new file mode 100644 index 00000000000..8fecb5f6779 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTest.java @@ -0,0 +1,125 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.bft.pki; + +import org.hyperledger.besu.tests.acceptance.dsl.account.Account; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import org.junit.Test; + +public class PkiQbftAcceptanceTest extends ParameterizedPkiQbftTestBase { + + public PkiQbftAcceptanceTest( + final String testName, final PkiQbftAcceptanceTestParameterization input) { + super(testName, input); + } + + @Test + public void shouldMineOnSingleNode() throws Exception { + final BesuNode minerNode = nodeFactory.createNode(besu, "miner1"); + cluster.start(minerNode); + + cluster.verify(blockchain.reachesHeight(minerNode, 1)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + minerNode.execute(accountTransactions.createTransfer(sender, 50)); + cluster.verify(sender.balanceEquals(50)); + + minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); + cluster.verify(receiver.balanceEquals(1)); + + minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); + cluster.verify(receiver.balanceEquals(3)); + } + + @Test + public void shouldMineOnMultipleNodes() throws Exception { + final BesuNode minerNode1 = nodeFactory.createNode(besu, "miner1"); + final BesuNode minerNode2 = nodeFactory.createNode(besu, "miner2"); + final BesuNode minerNode3 = nodeFactory.createNode(besu, "miner3"); + final BesuNode minerNode4 = nodeFactory.createNode(besu, "miner4"); + cluster.start(minerNode1, minerNode2, minerNode3, minerNode4); + + cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + minerNode1.execute(accountTransactions.createTransfer(sender, 50)); + cluster.verify(sender.balanceEquals(50)); + + minerNode2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); + cluster.verify(receiver.balanceEquals(1)); + + minerNode3.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); + cluster.verify(receiver.balanceEquals(3)); + + minerNode4.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 3)); + cluster.verify(receiver.balanceEquals(6)); + } + + @Test + public void shouldMineWithIgnoringANodeInCRL() throws Exception { + final BesuNode minerNode1 = nodeFactory.createNode(besu, "miner1"); + final BesuNode minerNode2 = nodeFactory.createNode(besu, "miner2"); + final BesuNode minerNode3 = nodeFactory.createNode(besu, "miner3"); + final BesuNode minerNode4 = nodeFactory.createNode(besu, "miner4"); + final BesuNode minerNode5 = nodeFactory.createNode(besu, "miner5"); + final BesuNode minerNode6 = nodeFactory.createNode(besu, "miner6"); + try { + cluster.start(minerNode1, minerNode2, minerNode3, minerNode4); + + cluster.startNode(minerNode5); + cluster.startNode(minerNode6); + + cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + minerNode1.execute(accountTransactions.createTransfer(sender, 50)); + cluster.verify(sender.balanceEquals(50)); + + minerNode2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); + cluster.verify(receiver.balanceEquals(1)); + + minerNode3.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); + cluster.verify(receiver.balanceEquals(3)); + + minerNode4.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 3)); + cluster.verify(receiver.balanceEquals(6)); + + if (minerNode1.getTLSConfiguration().isEmpty()) { + minerNode1.verify(net.awaitPeerCount(5)); + minerNode5.verify(net.awaitPeerCount(5)); + minerNode6.verify(net.awaitPeerCount(5)); + } else { + minerNode1.verify(net.awaitPeerCount(3)); + minerNode5.verify(net.awaitPeerCount(0)); + minerNode6.verify(net.awaitPeerCount(0)); + } + } finally { + cluster.stopNode(minerNode5); + cluster.stopNode(minerNode6); + minerNode5.close(); + minerNode6.close(); + } + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java new file mode 100644 index 00000000000..10d4866fef7 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java @@ -0,0 +1,123 @@ +/* + * Copyright 2020 ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See + * the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.bft.pki; + +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeFactory; + +import java.util.ArrayList; +import java.util.List; + +public class PkiQbftAcceptanceTestParameterization { + + public static List getFactories() { + final List ret = new ArrayList<>(); + + /* + BLOCK CREATION + */ + + ret.add( + new Object[] { + "qbft-pki-jks", + new PkiQbftAcceptanceTestParameterization( + BesuNodeFactory::createPkiQbftJKSNode, + BesuNodeFactory::createPkiQbftJKSNodeWithValidators) + }); + + ret.add( + new Object[] { + "qbft-pki-pkcs12", + new PkiQbftAcceptanceTestParameterization( + BesuNodeFactory::createPkiQbftPKCS12Node, + BesuNodeFactory::createPkiQbftPKCS12NodeWithValidators) + }); + + if (Boolean.getBoolean("acctests.runBesuAsProcess")) { + ret.add( + new Object[] { + "qbft-pki-pkcs11", + new PkiQbftAcceptanceTestParameterization( + BesuNodeFactory::createPkiQbftPKCS11Node, + BesuNodeFactory::createPkiQbftPKCS11NodeWithValidators) + }); + } + + /* + TLS + */ + + ret.add( + new Object[] { + "qbft-tls-jks", + new PkiQbftAcceptanceTestParameterization( + BesuNodeFactory::createQbftNodeWithTLSJKS, + BesuNodeFactory::createQbftTLSJKSNodeWithValidators) + }); + + ret.add( + new Object[] { + "qbft-tls-pkcs12", + new PkiQbftAcceptanceTestParameterization( + BesuNodeFactory::createQbftNodeWithTLSPKCS12, + BesuNodeFactory::createQbftTLSPKCS12NodeWithValidators) + }); + + if (Boolean.getBoolean("acctests.runBesuAsProcess")) { + ret.add( + new Object[] { + "qbft-tls-pkcs11", + new PkiQbftAcceptanceTestParameterization( + BesuNodeFactory::createQbftNodeWithTLSPKCS11, + BesuNodeFactory::createQbftTLSPKCS11NodeWithValidators) + }); + } + + return ret; + } + + @FunctionalInterface + public interface NodeCreator { + + BesuNode create(BesuNodeFactory factory, String name) throws Exception; + } + + @FunctionalInterface + public interface NodeWithValidatorsCreator { + + BesuNode create(BesuNodeFactory factory, String name, String[] validators) throws Exception; + } + + private final NodeCreator creatorFn; + private final NodeWithValidatorsCreator createorWithValidatorFn; + + public PkiQbftAcceptanceTestParameterization( + final NodeCreator creatorFn, final NodeWithValidatorsCreator createorWithValidatorFn) { + this.creatorFn = creatorFn; + this.createorWithValidatorFn = createorWithValidatorFn; + } + + public BesuNode createNode(BesuNodeFactory factory, String name) throws Exception { + return creatorFn.create(factory, name); + } + + public BesuNode createNodeWithValidators( + BesuNodeFactory factory, String name, String[] validators) throws Exception { + return createorWithValidatorFn.create(factory, name, validators); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/qbft/QbftContractAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/qbft/QbftContractAcceptanceTest.java new file mode 100644 index 00000000000..e3b2878b052 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/qbft/QbftContractAcceptanceTest.java @@ -0,0 +1,54 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.bft.qbft; + +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.account.Account; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import org.junit.Test; + +public class QbftContractAcceptanceTest extends AcceptanceTestBase { + + @Test + public void shouldMineOnMultipleNodesEvenWhenClusterContainsNonValidator() throws Exception { + final String[] validators = {"validator1", "validator2", "validator3"}; + final BesuNode validator1 = + besu.createQbftNodeWithContractBasedValidators("validator1", validators); + final BesuNode validator2 = + besu.createQbftNodeWithContractBasedValidators("validator2", validators); + final BesuNode validator3 = + besu.createQbftNodeWithContractBasedValidators("validator3", validators); + final BesuNode nonValidatorNode = + besu.createQbftNodeWithContractBasedValidators("non-validator", validators); + cluster.start(validator1, validator2, validator3, nonValidatorNode); + + cluster.verify(blockchain.reachesHeight(validator1, 1, 85)); + + cluster.verify(bft.validatorsEqual(validator1, validator2, validator3)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + validator1.execute(accountTransactions.createTransfer(sender, 50)); + cluster.verify(sender.balanceEquals(50)); + + validator2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); + cluster.verify(receiver.balanceEquals(1)); + + nonValidatorNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); + cluster.verify(receiver.balanceEquals(3)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ClusterAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/ClusterAcceptanceTest.java similarity index 96% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ClusterAcceptanceTest.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/ClusterAcceptanceTest.java index 3a29e7082e0..c4c9e42671c 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ClusterAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/ClusterAcceptanceTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.tests.acceptance; +package org.hyperledger.besu.tests.acceptance.bootstrap; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ClusterNoDiscoveryAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/ClusterNoDiscoveryAcceptanceTest.java similarity index 97% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ClusterNoDiscoveryAcceptanceTest.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/ClusterNoDiscoveryAcceptanceTest.java index 9328cdaae05..6c7c8127997 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ClusterNoDiscoveryAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/ClusterNoDiscoveryAcceptanceTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.tests.acceptance; +package org.hyperledger.besu.tests.acceptance.bootstrap; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ClusterThreadNodeRunnerAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/ClusterThreadNodeRunnerAcceptanceTest.java similarity index 97% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ClusterThreadNodeRunnerAcceptanceTest.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/ClusterThreadNodeRunnerAcceptanceTest.java index d4da3988cac..805749a0bf8 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ClusterThreadNodeRunnerAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/ClusterThreadNodeRunnerAcceptanceTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.tests.acceptance; +package org.hyperledger.besu.tests.acceptance.bootstrap; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/P2pDisabledAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/P2pDisabledAcceptanceTest.java similarity index 97% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/P2pDisabledAcceptanceTest.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/P2pDisabledAcceptanceTest.java index d863e1ad164..aa71839b181 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/P2pDisabledAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/P2pDisabledAcceptanceTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.tests.acceptance; +package org.hyperledger.besu.tests.acceptance.bootstrap; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/StaticNodesAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/StaticNodesAcceptanceTest.java similarity index 96% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/StaticNodesAcceptanceTest.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/StaticNodesAcceptanceTest.java index 69719d6df46..1f28a4a9f3c 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/StaticNodesAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/StaticNodesAcceptanceTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.tests.acceptance; +package org.hyperledger.besu.tests.acceptance.bootstrap; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils; diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueMiningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueMiningAcceptanceTest.java index d105b27e638..f7065b623a2 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueMiningAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueMiningAcceptanceTest.java @@ -72,6 +72,8 @@ public void shouldStallMiningWhenInsufficientValidators() throws IOException { cluster.stopNode(minerNode2); cluster.stopNode(minerNode3); minerNode1.verify(net.awaitPeerCount(0)); + minerNode1.verify(clique.blockIsCreatedByProposer(minerNode1)); + minerNode1.verify(clique.noNewBlockCreated(minerNode1)); } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/config/BootNodesGenesisSetupTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/config/BootNodesGenesisSetupTest.java new file mode 100644 index 00000000000..1ad2587ded3 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/config/BootNodesGenesisSetupTest.java @@ -0,0 +1,122 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.config; + +import org.hyperledger.besu.crypto.KeyPair; +import org.hyperledger.besu.crypto.SECPPrivateKey; +import org.hyperledger.besu.crypto.SECPPublicKey; +import org.hyperledger.besu.crypto.SignatureAlgorithm; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeConfigurationBuilder; + +import java.net.ServerSocket; +import java.util.Optional; + +import org.apache.tuweni.bytes.Bytes32; +import org.bouncycastle.asn1.sec.SECNamedCurves; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class BootNodesGenesisSetupTest extends AcceptanceTestBase { + private static final String CURVE_NAME = "secp256k1"; + private static final String ALGORITHM = SignatureAlgorithm.ALGORITHM; + + private static ECDomainParameters curve; + + private Node nodeA; + private Node nodeB; + + @BeforeClass + public static void environment() { + final X9ECParameters params = SECNamedCurves.getByName(CURVE_NAME); + curve = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH()); + } + + @Before + public void setUp() throws Exception { + int nodeAP2pBindingPort; + int nodeBP2pBindingPort; + try (ServerSocket nodeASocket = new ServerSocket(0); + ServerSocket nodeBSocket = new ServerSocket(0)) { + nodeAP2pBindingPort = nodeASocket.getLocalPort(); + nodeBP2pBindingPort = nodeBSocket.getLocalPort(); + } + final KeyPair nodeAKeyPair = + createKeyPair( + Bytes32.fromHexString( + "0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63")); + final KeyPair nodeBKeyPair = + createKeyPair( + Bytes32.fromHexString( + "0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3")); + + nodeA = + besu.createNode( + "nodeA", + nodeBuilder -> + configureNode( + nodeBuilder, + nodeAP2pBindingPort, + nodeAKeyPair, + nodeBKeyPair.getPublicKey(), + nodeBP2pBindingPort)); + nodeB = + besu.createNode( + "nodeB", + nodeBuilder -> + configureNode( + nodeBuilder, + nodeBP2pBindingPort, + nodeBKeyPair, + nodeAKeyPair.getPublicKey(), + nodeAP2pBindingPort)); + cluster.start(nodeA, nodeB); + } + + private KeyPair createKeyPair(final Bytes32 privateKey) { + return KeyPair.create(SECPPrivateKey.create(privateKey, ALGORITHM), curve, ALGORITHM); + } + + @Test + public void shouldConnectBothNodesConfiguredInGenesisFile() { + nodeA.verify(net.awaitPeerCount(1)); + nodeB.verify(net.awaitPeerCount(1)); + } + + private BesuNodeConfigurationBuilder configureNode( + final BesuNodeConfigurationBuilder nodeBuilder, + final int p2pBindingPort, + final KeyPair keyPair, + final SECPPublicKey peerPublicKey, + final int peerP2pBindingPort) { + return nodeBuilder + .devMode(false) + .keyPair(keyPair) + .p2pPort(p2pBindingPort) + .genesisConfigProvider( + (nodes) -> + Optional.of( + String.format( + "{\"config\": {\"ethash\": {}, \"discovery\": { \"bootnodes\": [\"enode://%s@127.0.0.1:%d\"]}}, \"gasLimit\": \"0x1\", \"difficulty\": \"0x1\"}", + peerPublicKey.toString().substring(2), peerP2pBindingPort))) + .bootnodeEligible(false) + .jsonRpcEnabled() + .jsonRpcAdmin(); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/crypto/SECP256R1AcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/crypto/SECP256R1AcceptanceTest.java new file mode 100644 index 00000000000..8b4ef9f864b --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/crypto/SECP256R1AcceptanceTest.java @@ -0,0 +1,102 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + */ +package org.hyperledger.besu.tests.acceptance.crypto; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assumptions.assumeThat; + +import org.hyperledger.besu.crypto.KeyPair; +import org.hyperledger.besu.crypto.SECP256R1; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.account.Account; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNodeRunner; +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; +import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster; +import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfiguration; +import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder; + +import java.util.List; + +import org.apache.tuweni.bytes.Bytes32; +import org.junit.Before; +import org.junit.Test; + +public class SECP256R1AcceptanceTest extends AcceptanceTestBase { + private Node minerNode; + private Node otherNode; + private Cluster noDiscoveryCluster; + + private static final String GENESIS_FILE = "/crypto/secp256r1.json"; + + private static final String MINER_NODE_PRIVATE_KEY = + "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63"; + private static final String OTHER_NODE_PRIVATE_KEY = + "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3"; + + private static final SECP256R1 SECP256R1_SIGNATURE_ALGORITHM = new SECP256R1(); + + @Before + public void setUp() throws Exception { + KeyPair minerNodeKeyPair = createKeyPair(MINER_NODE_PRIVATE_KEY); + KeyPair otherNodeKeyPair = createKeyPair(OTHER_NODE_PRIVATE_KEY); + + final ClusterConfiguration clusterConfiguration = + new ClusterConfigurationBuilder().awaitPeerDiscovery(false).build(); + noDiscoveryCluster = new Cluster(clusterConfiguration, net); + + minerNode = + besu.createNodeWithNonDefaultSignatureAlgorithm( + "minerNode", GENESIS_FILE, minerNodeKeyPair); + noDiscoveryCluster.start(minerNode); + + otherNode = + besu.createNodeWithNonDefaultSignatureAlgorithm( + "otherNode", GENESIS_FILE, otherNodeKeyPair, List.of(minerNode)); + noDiscoveryCluster.addNode(otherNode); + } + + @Test + public void transactionShouldBeSuccessful() { + // SignatureAlgorithmFactory.instance is static. When ThreadBesuRunner is used, we cannot change + // the signature algorithm instance to SECP256R1 as it could influence other tests running at + // the same time. So we only execute the test when ProcessBesuNodeRunner is used, as there is + // not conflict because we use separate processes. + assumeThat(BesuNodeRunner.isProcessBesuNodeRunner()).isTrue(); + + minerNode.verify(net.awaitPeerCount(1)); + otherNode.verify(net.awaitPeerCount(1)); + + final Account recipient = accounts.createAccount("recipient"); + + final Hash transactionHash = + minerNode.execute(accountTransactions.createTransfer(recipient, 5, new SECP256R1())); + assertThat(transactionHash).isNotNull(); + noDiscoveryCluster.verify(recipient.balanceEquals(5)); + } + + @Override + public void tearDownAcceptanceTestBase() { + super.tearDownAcceptanceTestBase(); + + noDiscoveryCluster.stop(); + } + + private KeyPair createKeyPair(final String privateKey) { + return SECP256R1_SIGNATURE_ALGORITHM.createKeyPair( + SECP256R1_SIGNATURE_ALGORITHM.createPrivateKey(Bytes32.fromHexString(privateKey))); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/database/DatabaseMigrationAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/database/DatabaseMigrationAcceptanceTest.java index 82ec8f5813b..d116a5cafcf 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/database/DatabaseMigrationAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/database/DatabaseMigrationAcceptanceTest.java @@ -17,8 +17,8 @@ import static java.util.Collections.singletonList; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Wei; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.tests.acceptance.AbstractPreexistingNodeTest; import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2BlockRewardPaymentAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2BlockRewardPaymentAcceptanceTest.java deleted file mode 100644 index 165728767ee..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2BlockRewardPaymentAcceptanceTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.ibft2; - -import static java.util.Collections.singletonList; - -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.account.Account; -import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; - -import java.io.IOException; -import java.math.BigInteger; -import java.util.Optional; - -import org.junit.Test; - -public class Ibft2BlockRewardPaymentAcceptanceTest extends AcceptanceTestBase { - - @Test - public void validatorsArePaidBlockReward() throws IOException { - final String[] validators = {"validator"}; - final BesuNode validator = besu.createIbft2NodeWithValidators("validator", validators); - final BesuNode nonValidator = besu.createIbft2NodeWithValidators("nonValidator", validators); - cluster.start(validator, nonValidator); - final Account validator1Account = Account.create(ethTransactions, validator.getAddress()); - - final int blockRewardEth = 5; - final int blockToCheck = 2; - - cluster.verify(validator1Account.balanceAtBlockEquals(Amount.ether(0), BigInteger.ZERO)); - cluster.verify( - validator1Account.balanceAtBlockEquals( - Amount.ether(blockRewardEth * blockToCheck), BigInteger.valueOf(blockToCheck))); - } - - @Test - public void payBlockRewardToConfiguredNode() throws IOException { - final String[] validators = {"validator1"}; - final BesuNode validator1 = besu.createIbft2NodeWithValidators("validator1", validators); - final Optional initialConfig = - validator1.getGenesisConfigProvider().create(singletonList(validator1)); - if (initialConfig.isEmpty()) { - throw new RuntimeException("Unable to generate genesis config."); - } - final String miningBeneficiaryAddress = "0x1234567890123456789012345678901234567890"; - - final String configWithMiningBeneficiary = - initialConfig - .get() - .replace( - "\"ibft2\": {", - "\"ibft2\": { \"miningbeneficiary\": \"" + miningBeneficiaryAddress + "\","); - - validator1.setGenesisConfig(configWithMiningBeneficiary); - - final Account miningBeneficiaryAccount = - Account.create(ethTransactions, Address.fromHexString(miningBeneficiaryAddress)); - - // This starts a node, without executing its configGenerator - cluster.runNodeStart(validator1); - final int blockRewardEth = 5; - final int blockToCheck = 2; - - cluster.verify(miningBeneficiaryAccount.balanceAtBlockEquals(Amount.ether(0), BigInteger.ZERO)); - cluster.verify( - miningBeneficiaryAccount.balanceAtBlockEquals( - Amount.ether(blockRewardEth * blockToCheck), BigInteger.valueOf(blockToCheck))); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2DiscardRpcAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2DiscardRpcAcceptanceTest.java deleted file mode 100644 index 8de0f984678..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2DiscardRpcAcceptanceTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.ibft2; - -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; - -import java.io.IOException; - -import org.junit.Test; - -public class Ibft2DiscardRpcAcceptanceTest extends AcceptanceTestBase { - - @Test - public void shouldDiscardVotes() throws IOException { - final String[] validators = {"validator1", "validator3"}; - final BesuNode validator1 = besu.createIbft2NodeWithValidators("validator1", validators); - final BesuNode validator2 = besu.createIbft2NodeWithValidators("validator2", validators); - final BesuNode validator3 = besu.createIbft2NodeWithValidators("validator3", validators); - cluster.start(validator1, validator2, validator3); - - validator1.execute(ibftTwoTransactions.createAddProposal(validator2)); - validator1.execute(ibftTwoTransactions.createRemoveProposal(validator3)); - validator1.verify( - ibftTwo.pendingVotesEqual().addProposal(validator2).removeProposal(validator3).build()); - - validator1.execute(ibftTwoTransactions.createDiscardProposal(validator2)); - validator1.verify(ibftTwo.pendingVotesEqual().removeProposal(validator3).build()); - - validator1.execute(ibftTwoTransactions.createDiscardProposal(validator3)); - cluster.verify(ibftTwo.noProposals()); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2MiningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2MiningAcceptanceTest.java deleted file mode 100644 index f1f8e441c63..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2MiningAcceptanceTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.ibft2; - -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.account.Account; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; - -import java.io.IOException; -import java.util.List; - -import org.junit.Test; - -public class Ibft2MiningAcceptanceTest extends AcceptanceTestBase { - - @Test - public void shouldMineOnSingleNode() throws IOException { - final BesuNode minerNode = besu.createIbft2Node("miner1"); - cluster.start(minerNode); - - cluster.verify(blockchain.reachesHeight(minerNode, 1)); - - final Account sender = accounts.createAccount("account1"); - final Account receiver = accounts.createAccount("account2"); - - minerNode.execute(accountTransactions.createTransfer(sender, 50)); - cluster.verify(sender.balanceEquals(50)); - - minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); - cluster.verify(receiver.balanceEquals(1)); - - minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); - cluster.verify(receiver.balanceEquals(3)); - } - - @Test - public void shouldMineOnMultipleNodes() throws IOException { - final BesuNode minerNode1 = besu.createIbft2Node("miner1"); - final BesuNode minerNode2 = besu.createIbft2Node("miner2"); - final BesuNode minerNode3 = besu.createIbft2Node("miner3"); - final BesuNode minerNode4 = besu.createIbft2Node("miner4"); - cluster.start(minerNode1, minerNode2, minerNode3, minerNode4); - - cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85)); - - final Account sender = accounts.createAccount("account1"); - final Account receiver = accounts.createAccount("account2"); - - minerNode1.execute(accountTransactions.createTransfer(sender, 50)); - cluster.verify(sender.balanceEquals(50)); - - minerNode2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); - cluster.verify(receiver.balanceEquals(1)); - - minerNode3.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); - cluster.verify(receiver.balanceEquals(3)); - - minerNode4.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 3)); - cluster.verify(receiver.balanceEquals(6)); - } - - @Test - public void shouldMineOnMultipleNodesEvenWhenClusterContainsNonValidator() throws IOException { - final String[] validators = {"validator1", "validator2", "validator3"}; - final BesuNode validator1 = besu.createIbft2NodeWithValidators("validator1", validators); - final BesuNode validator2 = besu.createIbft2NodeWithValidators("validator2", validators); - final BesuNode validator3 = besu.createIbft2NodeWithValidators("validator3", validators); - final BesuNode nonValidatorNode = - besu.createIbft2NodeWithValidators("non-validator", validators); - cluster.start(validator1, validator2, validator3, nonValidatorNode); - - cluster.verify(blockchain.reachesHeight(validator1, 1, 85)); - - final Account sender = accounts.createAccount("account1"); - final Account receiver = accounts.createAccount("account2"); - - validator1.execute(accountTransactions.createTransfer(sender, 50)); - cluster.verify(sender.balanceEquals(50)); - - validator2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); - cluster.verify(receiver.balanceEquals(1)); - - nonValidatorNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); - cluster.verify(receiver.balanceEquals(3)); - } - - @Test - public void shouldStillMineWhenANonProposerNodeFailsAndHasSufficientValidators() - throws IOException { - final BesuNode minerNode1 = besu.createIbft2Node("miner1"); - final BesuNode minerNode2 = besu.createIbft2Node("miner2"); - final BesuNode minerNode3 = besu.createIbft2Node("miner3"); - final BesuNode minerNode4 = besu.createIbft2Node("miner4"); - final List validators = - ibftTwo.validators(new BesuNode[] {minerNode1, minerNode2, minerNode3, minerNode4}); - final BesuNode nonProposerNode = validators.get(validators.size() - 1); - cluster.start(validators); - - cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85)); - - final Account receiver = accounts.createAccount("account2"); - - cluster.stopNode(nonProposerNode); - validators.get(0).execute(accountTransactions.createTransfer(receiver, 80)); - - cluster.verifyOnActiveNodes(receiver.balanceEquals(80)); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2ProposalRpcAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2ProposalRpcAcceptanceTest.java deleted file mode 100644 index ff0ce12629e..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2ProposalRpcAcceptanceTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.ibft2; - -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; - -import java.io.IOException; - -import org.junit.Test; - -public class Ibft2ProposalRpcAcceptanceTest extends AcceptanceTestBase { - - @Test - public void shouldReturnProposals() throws IOException { - final String[] validators = {"validator1", "validator2", "validator3"}; - final BesuNode validator1 = besu.createIbft2NodeWithValidators("validator1", validators); - final BesuNode validator2 = besu.createIbft2NodeWithValidators("validator2", validators); - final BesuNode validator3 = besu.createIbft2NodeWithValidators("validator3", validators); - cluster.start(validator1, validator2, validator3); - - cluster.verify(ibftTwo.noProposals()); - validator1.execute(ibftTwoTransactions.createAddProposal(validator3)); - validator1.execute(ibftTwoTransactions.createRemoveProposal(validator2)); - validator2.execute(ibftTwoTransactions.createRemoveProposal(validator3)); - - validator1.verify( - ibftTwo.pendingVotesEqual().addProposal(validator3).removeProposal(validator2).build()); - validator2.verify(ibftTwo.pendingVotesEqual().removeProposal(validator3).build()); - validator3.verify(ibftTwo.noProposals()); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2ProposeRpcAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2ProposeRpcAcceptanceTest.java deleted file mode 100644 index 77df0c19172..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2ProposeRpcAcceptanceTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.ibft2; - -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; - -import java.io.IOException; - -import org.junit.Test; - -// These tests prove the ibft_proposeValidatorVote and ibft_getValidatorsByBlockNumber (implicitly) -// JSON RPC calls. -public class Ibft2ProposeRpcAcceptanceTest extends AcceptanceTestBase { - - @Test - public void validatorsCanBeAddedAndThenRemoved() throws IOException { - final String[] validators = {"validator1", "validator2", "validator3"}; - final BesuNode validator1 = besu.createIbft2NodeWithValidators("validator1", validators); - final BesuNode validator2 = besu.createIbft2NodeWithValidators("validator2", validators); - final BesuNode validator3 = besu.createIbft2NodeWithValidators("validator3", validators); - final BesuNode nonValidatorNode = - besu.createIbft2NodeWithValidators("non-validator", validators); - cluster.start(validator1, validator2, validator3, nonValidatorNode); - - cluster.verify(ibftTwo.validatorsEqual(validator1, validator2, validator3)); - final Condition addedCondition = ibftTwo.awaitValidatorSetChange(validator1); - validator1.execute(ibftTwoTransactions.createAddProposal(nonValidatorNode)); - validator2.execute(ibftTwoTransactions.createAddProposal(nonValidatorNode)); - - cluster.verify(addedCondition); - cluster.verify(ibftTwo.validatorsEqual(validator1, validator2, validator3, nonValidatorNode)); - - final Condition removedCondition = ibftTwo.awaitValidatorSetChange(validator1); - validator2.execute(ibftTwoTransactions.createRemoveProposal(nonValidatorNode)); - validator3.execute(ibftTwoTransactions.createRemoveProposal(nonValidatorNode)); - nonValidatorNode.execute(ibftTwoTransactions.createRemoveProposal(nonValidatorNode)); - cluster.verify(removedCondition); - cluster.verify(ibftTwo.validatorsEqual(validator1, validator2, validator3)); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2ZeroValidators.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2ZeroValidators.java deleted file mode 100644 index 14aa20f1fb3..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ibft2/Ibft2ZeroValidators.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.ibft2; - -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; - -import java.io.IOException; - -import org.junit.Test; - -public class Ibft2ZeroValidators extends AcceptanceTestBase { - - @Test - public void zeroValidatorsFormValidCluster() throws IOException { - final String[] validators = {}; - final BesuNode node1 = besu.createIbft2NodeWithValidators("node1", validators); - final BesuNode node2 = besu.createIbft2NodeWithValidators("node2", validators); - - cluster.start(node1, node2); - - cluster.verify(net.awaitPeerCount(1)); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/AbstractJsonRpcTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/AbstractJsonRpcTest.java new file mode 100644 index 00000000000..56c43da355b --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/AbstractJsonRpcTest.java @@ -0,0 +1,122 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.jsonrpc; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.config.JsonUtil; +import org.hyperledger.besu.tests.acceptance.dsl.condition.net.NetConditions; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; +import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeFactory; +import org.hyperledger.besu.tests.acceptance.dsl.rpc.JsonRpcTestCase; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.net.NetTransactions; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import okhttp3.Call; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import org.junit.Test; + +abstract class AbstractJsonRpcTest { + private static final MediaType MEDIA_TYPE_JSON = + MediaType.parse("application/json; charset=utf-8"); + + static class JsonRpcTestsContext { + final Cluster cluster; + final BesuNode besuNode; + final OkHttpClient httpClient; + final ObjectMapper mapper; + + public JsonRpcTestsContext(final String genesisFile) throws IOException { + cluster = new Cluster(new NetConditions(new NetTransactions())); + + besuNode = + new BesuNodeFactory().createExecutionEngineGenesisNode("executionEngine", genesisFile); + cluster.start(besuNode); + httpClient = new OkHttpClient(); + + mapper = new ObjectMapper(); + } + + public void tearDown() { + cluster.close(); + } + } + + private final JsonRpcTestsContext testsContext; + private final URI testCaseFileURI; + + public AbstractJsonRpcTest( + final String ignored, final JsonRpcTestsContext testsContext, final URI testCaseFileURI) { + this.testCaseFileURI = testCaseFileURI; + this.testsContext = testsContext; + } + + @Test + public void test() throws IOException { + final JsonRpcTestCase testCase = + testsContext.mapper.readValue(testCaseFileURI.toURL(), JsonRpcTestCase.class); + + final String rpcMethod = String.valueOf(testCase.getRequest().get("method")); + + final Call testRequest = + testsContext.httpClient.newCall( + new Request.Builder() + .url(getRpcUrl(rpcMethod)) + .post(RequestBody.create(testCase.getRequest().toString(), MEDIA_TYPE_JSON)) + .build()); + final Response response = testRequest.execute(); + + assertThat(response.code()).isEqualTo(testCase.getStatusCode()); + final ObjectNode actualBody = JsonUtil.objectNodeFromString(response.body().string()); + final ObjectNode expectedBody = + JsonUtil.objectNodeFromString(testCase.getResponse().toString()); + assertThat(actualBody) + .withFailMessage( + "%s\ndid not equal\n %s", actualBody.toPrettyString(), expectedBody.toPrettyString()) + .isEqualTo(expectedBody); + } + + private String getRpcUrl(final String rpcMethod) { + if (rpcMethod.contains("eth_") || rpcMethod.contains("engine_")) { + return testsContext.besuNode.engineRpcUrl().get(); + } + + return testsContext.besuNode.jsonRpcBaseUrl().get(); + } + + public static Iterable testCases(final String testCasesPath) throws URISyntaxException { + + final File[] testCasesList = + new File(AbstractJsonRpcTest.class.getResource(testCasesPath).toURI()).listFiles(); + + return Arrays.stream(testCasesList) + .sorted() + .map(file -> new Object[] {file.getName(), file.toURI()}) + .collect(Collectors.toList()); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/DebugReplayBlockAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/DebugReplayBlockAcceptanceTest.java new file mode 100644 index 00000000000..0b6f76f4de2 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/DebugReplayBlockAcceptanceTest.java @@ -0,0 +1,51 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.jsonrpc; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class DebugReplayBlockAcceptanceTest extends AbstractJsonRpcTest { + private static final String GENESIS_FILE = "/jsonrpc/debug/replayBlock/genesis.json"; + private static final String TEST_CASE_PATH = "/jsonrpc/debug/replayBlock/test-cases/"; + + private static AbstractJsonRpcTest.JsonRpcTestsContext testsContext; + + public DebugReplayBlockAcceptanceTest(final String ignored, final URI testCaseFileURI) { + super(ignored, testsContext, testCaseFileURI); + } + + @BeforeClass + public static void init() throws IOException { + testsContext = new JsonRpcTestsContext(GENESIS_FILE); + } + + @Parameterized.Parameters(name = "{0}") + public static Iterable testCases() throws URISyntaxException { + return testCases(TEST_CASE_PATH); + } + + @AfterClass + public static void tearDown() { + testsContext.cluster.close(); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/DebugSetHeadAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/DebugSetHeadAcceptanceTest.java new file mode 100644 index 00000000000..b4db91a39aa --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/DebugSetHeadAcceptanceTest.java @@ -0,0 +1,51 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.jsonrpc; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class DebugSetHeadAcceptanceTest extends AbstractJsonRpcTest { + private static final String GENESIS_FILE = "/jsonrpc/debug/setHead/genesis.json"; + private static final String TEST_CASE_PATH = "/jsonrpc/debug/setHead/test-cases/"; + + private static JsonRpcTestsContext testsContext; + + public DebugSetHeadAcceptanceTest(final String ignored, final URI testCaseFileURI) { + super(ignored, testsContext, testCaseFileURI); + } + + @BeforeClass + public static void init() throws IOException { + testsContext = new JsonRpcTestsContext(GENESIS_FILE); + } + + @Parameterized.Parameters(name = "{0}") + public static Iterable testCases() throws URISyntaxException { + return testCases(TEST_CASE_PATH); + } + + @AfterClass + public static void tearDown() { + testsContext.cluster.close(); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/DeploySmartContractAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/DeploySmartContractAcceptanceTest.java similarity index 91% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/DeploySmartContractAcceptanceTest.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/DeploySmartContractAcceptanceTest.java index 712881f7f37..06bd5cbfda5 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/DeploySmartContractAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/DeploySmartContractAcceptanceTest.java @@ -12,20 +12,20 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.tests.web3j; +package org.hyperledger.besu.tests.acceptance.jsonrpc; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import org.hyperledger.besu.tests.web3j.generated.SimpleStorage; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class DeploySmartContractAcceptanceTest extends AcceptanceTestBase { private BesuNode minerNode; - @Before + @BeforeEach public void setUp() throws Exception { minerNode = besu.createMinerNode("miner-node"); cluster.start(minerNode); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/DeployTransactionAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/DeployTransactionAcceptanceTest.java similarity index 89% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/DeployTransactionAcceptanceTest.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/DeployTransactionAcceptanceTest.java index a81aedd67fa..909d40beb3a 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/DeployTransactionAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/DeployTransactionAcceptanceTest.java @@ -12,22 +12,22 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.tests.web3j; +package org.hyperledger.besu.tests.acceptance.jsonrpc; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class DeployTransactionAcceptanceTest extends AcceptanceTestBase { private BesuNode minerNode; private Account recipient; - @Before + @BeforeEach public void setUp() throws Exception { recipient = accounts.createAccount("recipient"); minerNode = besu.createMinerNode("node"); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EthEstimateGasAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EthEstimateGasAcceptanceTest.java new file mode 100644 index 00000000000..b8b4e2e45f4 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EthEstimateGasAcceptanceTest.java @@ -0,0 +1,124 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.jsonrpc; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.eth.EthCallTransaction; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.eth.EthEstimateGasTransaction; +import org.hyperledger.besu.tests.web3j.generated.TestDepth; + +import java.math.BigInteger; +import java.util.AbstractMap.SimpleEntry; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +public class EthEstimateGasAcceptanceTest extends AcceptanceTestBase { + + private BesuNode node; + private TestDepth testDepth; + + List> testCase = new ArrayList<>(); + + @Before + public void setUp() throws Exception { + node = + besu.createMinerNode( + "node1", + b -> + b.genesisConfigProvider(GenesisConfigurationFactory::createDevLondonGenesisConfig) + .devMode(false)); + + cluster.start(node); + testDepth = node.execute(contractTransactions.createSmartContract(TestDepth.class)); + + // taken from geth + testCase.add(new SimpleEntry<>(1, 45554L)); + testCase.add(new SimpleEntry<>(2, 47387L)); + testCase.add(new SimpleEntry<>(3, 49249L)); + testCase.add(new SimpleEntry<>(4, 51141L)); + testCase.add(new SimpleEntry<>(5, 53063L)); + testCase.add(new SimpleEntry<>(10, 63139L)); + testCase.add(new SimpleEntry<>(65, 246462L)); + } + + @Test + public void estimateGasWithDelegateCall() { + + for (var test : testCase) { + var functionCall = testDepth.depth(BigInteger.valueOf(test.getKey())).encodeFunctionCall(); + + var estimateGas = + node.execute(new EthEstimateGasTransaction(testDepth.getContractAddress(), functionCall)); + + // Sanity check our estimate is good with eth_call + var ethCall = + node.execute( + new EthCallTransaction( + testDepth.getContractAddress(), functionCall, estimateGas.getAmountUsed())); + + assertThat(ethCall.isReverted()).isEqualTo(false); + + // Sanity check our estimate is right on the edge with eth_call + var ethCallTooLow = + node.execute( + new EthCallTransaction( + testDepth.getContractAddress(), + functionCall, + estimateGas.getAmountUsed().subtract(BigInteger.ONE))); + + assertThat(ethCallTooLow.isReverted()).isEqualTo(true); + + // Sanity check our estimate is right on the edge with eth_sendRawTransaction + var transactionTooLow = + node.execute( + contractTransactions.callSmartContract( + testDepth.getContractAddress(), + functionCall, + estimateGas.getAmountUsed().subtract(BigInteger.ONE))); + + node.verify(eth.expectSuccessfulTransactionReceipt(transactionTooLow.getTransactionHash())); + + var receiptTooLow = + node.execute( + ethTransactions.getTransactionReceiptWithRevertReason( + transactionTooLow.getTransactionHash())); + + assertThat(receiptTooLow).isPresent(); + assertThat(receiptTooLow.get().isStatusOK()).isFalse(); + + // check our estimate will actually get mined successfully! + var transaction = + node.execute( + contractTransactions.callSmartContract( + testDepth.getContractAddress(), functionCall, estimateGas.getAmountUsed())); + + node.verify(eth.expectSuccessfulTransactionReceipt(transaction.getTransactionHash())); + + var receipt = + node.execute(ethTransactions.getTransactionReceipt(transaction.getTransactionHash())); + + assertThat(receipt).isPresent(); + assertThat(receipt.get().getGasUsed()).isLessThan(BigInteger.valueOf(test.getValue())); + assertThat(receipt.get().isStatusOK()).isTrue(); + } + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EthGetBlockByNumberAndHashShanghaiAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EthGetBlockByNumberAndHashShanghaiAcceptanceTest.java new file mode 100644 index 00000000000..f50e6c4a3bf --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EthGetBlockByNumberAndHashShanghaiAcceptanceTest.java @@ -0,0 +1,53 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.jsonrpc; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class EthGetBlockByNumberAndHashShanghaiAcceptanceTest extends AbstractJsonRpcTest { + private static final String TEST_RESOURCES_DIR = "/jsonrpc/eth/getBlockBy/"; + private static final String GENESIS_FILE = TEST_RESOURCES_DIR + "genesis.json"; + private static final String TEST_CASE_PATH = TEST_RESOURCES_DIR + "test-cases/"; + + private static AbstractJsonRpcTest.JsonRpcTestsContext testsContext; + + public EthGetBlockByNumberAndHashShanghaiAcceptanceTest( + final String ignored, final URI testCaseFileURI) { + super(ignored, testsContext, testCaseFileURI); + } + + @BeforeClass + public static void init() throws IOException { + testsContext = new JsonRpcTestsContext(GENESIS_FILE); + } + + @Parameterized.Parameters(name = "{0}") + public static Iterable testCases() throws URISyntaxException { + return testCases(TEST_CASE_PATH); + } + + @AfterClass + public static void tearDown() { + testsContext.cluster.close(); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EthGetWorkAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EthGetWorkAcceptanceTest.java index 2e9dd206192..c4842348aa9 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EthGetWorkAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EthGetWorkAcceptanceTest.java @@ -17,16 +17,16 @@ import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; public class EthGetWorkAcceptanceTest extends AcceptanceTestBase { private Node minerNode; private Node fullNode; - @Before + @BeforeEach public void setUp() throws Exception { minerNode = besu.createMinerNode("node1"); fullNode = besu.createArchiveNode("node2"); @@ -34,7 +34,7 @@ public void setUp() throws Exception { } @Test - @Ignore("Genuinely Flakey") + @Disabled("Genuinely Flakey") public void shouldReturnSuccessResponseWhenMining() { minerNode.verify(eth.getWork()); } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EthSendRawTransactionAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EthSendRawTransactionAcceptanceTest.java new file mode 100644 index 00000000000..4e4330da03b --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EthSendRawTransactionAcceptanceTest.java @@ -0,0 +1,126 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.jsonrpc; + +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.account.Account; +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeConfigurationBuilder; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.account.TransferTransaction; + +import java.math.BigInteger; +import java.util.function.UnaryOperator; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class EthSendRawTransactionAcceptanceTest extends AcceptanceTestBase { + private static final long CHAIN_ID = 20211; + + private Account sender; + + private Node lenientNode; + private Node strictNode; + private Node miningNode; + + @BeforeEach + public void setUp() throws Exception { + sender = accounts.getPrimaryBenefactor(); + + lenientNode = besu.createArchiveNode("lenientNode", configureNode((false))); + strictNode = besu.createArchiveNode("strictNode", configureNode((true))); + miningNode = besu.createMinerNode("strictMiningNode", configureNode((true))); + cluster.start(lenientNode, strictNode, miningNode); + } + + @Test + public void shouldSendSuccessfullyToLenientNodeWithoutChainId() { + final TransferTransaction tx = createTransactionWithoutChainId(); + final String rawTx = tx.signedTransactionData(); + final String txHash = tx.transactionHash(); + + lenientNode.verify(eth.expectSuccessfulEthRawTransaction(rawTx)); + // Tx should be included on-chain + miningNode.verify(eth.expectSuccessfulTransactionReceipt(txHash)); + } + + @Test + public void shouldFailToSendToToStrictNodeWithoutChainId() { + final TransferTransaction tx = createTransactionWithoutChainId(); + final String rawTx = tx.signedTransactionData(); + + strictNode.verify(eth.expectEthSendRawTransactionException(rawTx, "ChainId is required")); + } + + @Test + public void shouldFailToSendWithInvalidRlp() { + final String invalidRawTx = "0x5555"; + strictNode.verify(eth.expectEthSendRawTransactionException(invalidRawTx, "Invalid params")); + } + + @Test + public void shouldSendSuccessfullyWithChainId_lenientNode() { + final TransferTransaction tx = createTransactionWithChainId(); + final String rawTx = tx.signedTransactionData(); + final String txHash = tx.transactionHash(); + + lenientNode.verify(eth.expectSuccessfulEthRawTransaction(rawTx)); + // Tx should be included on-chain + miningNode.verify(eth.expectSuccessfulTransactionReceipt(txHash)); + } + + @Test + public void shouldSendSuccessfullyWithChainId_strictNode() { + final TransferTransaction tx = createTransactionWithChainId(); + final String rawTx = tx.signedTransactionData(); + final String txHash = tx.transactionHash(); + + strictNode.verify(eth.expectSuccessfulEthRawTransaction(rawTx)); + // Tx should be included on-chain + miningNode.verify(eth.expectSuccessfulTransactionReceipt(txHash)); + } + + private TransferTransaction createTransactionWithChainId() { + return createTransaction(true); + } + + private TransferTransaction createTransactionWithoutChainId() { + return createTransaction(false); + } + + private TransferTransaction createTransaction(final boolean withChainId) { + if (withChainId) { + return accountTransactions.create1559Transfer(createAccount(), 2, CHAIN_ID); + } else { + final BigInteger nonce = + miningNode.execute(ethTransactions.getTransactionCount(sender.getAddress())); + return accountTransactions.createTransfer( + accounts.getPrimaryBenefactor(), createAccount(), 1, nonce); + } + } + + private UnaryOperator configureNode( + final boolean enableStrictReplayProtection) { + return b -> + b.genesisConfigProvider(GenesisConfigurationFactory::createDevLondonGenesisConfig) + .strictTxReplayProtectionEnabled(enableStrictReplayProtection) + .devMode(false); + } + + private Account createAccount() { + return accounts.createAccount("Test account"); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/EventEmitterAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EventEmitterAcceptanceTest.java similarity index 94% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/EventEmitterAcceptanceTest.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EventEmitterAcceptanceTest.java index 91e1673c3e8..de4bfdb6464 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/EventEmitterAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EventEmitterAcceptanceTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.tests.web3j; +package org.hyperledger.besu.tests.acceptance.jsonrpc; import static org.assertj.core.api.Assertions.assertThat; @@ -26,8 +26,8 @@ import io.reactivex.Flowable; import io.reactivex.disposables.Disposable; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.web3j.protocol.core.methods.request.EthFilter; import org.web3j.protocol.core.methods.response.TransactionReceipt; @@ -38,7 +38,7 @@ public class EventEmitterAcceptanceTest extends AcceptanceTestBase { private BesuNode node; - @Before + @BeforeEach public void setUp() throws Exception { node = besu.createMinerNode("node1"); cluster.start(node); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineEip6110AcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineEip6110AcceptanceTest.java new file mode 100644 index 00000000000..d1771ac5990 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineEip6110AcceptanceTest.java @@ -0,0 +1,51 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.jsonrpc; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class ExecutionEngineEip6110AcceptanceTest extends AbstractJsonRpcTest { + private static final String GENESIS_FILE = "/jsonrpc/engine/eip6110/genesis.json"; + private static final String TEST_CASE_PATH = "/jsonrpc/engine/eip6110/test-cases/"; + + private static JsonRpcTestsContext testsContext; + + public ExecutionEngineEip6110AcceptanceTest(final String ignored, final URI testCaseFileURI) { + super(ignored, testsContext, testCaseFileURI); + } + + @BeforeClass + public static void init() throws IOException { + testsContext = new JsonRpcTestsContext(GENESIS_FILE); + } + + @Parameterized.Parameters(name = "{0}") + public static Iterable testCases() throws URISyntaxException { + return testCases(TEST_CASE_PATH); + } + + @AfterClass + public static void tearDown() { + testsContext.cluster.close(); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineParisAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineParisAcceptanceTest.java new file mode 100644 index 00000000000..c6cb8a62ea4 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineParisAcceptanceTest.java @@ -0,0 +1,51 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.jsonrpc; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class ExecutionEngineParisAcceptanceTest extends AbstractJsonRpcTest { + private static final String GENESIS_FILE = "/jsonrpc/engine/paris/genesis.json"; + private static final String TEST_CASE_PATH = "/jsonrpc/engine/paris/test-cases/"; + + private static JsonRpcTestsContext testsContext; + + public ExecutionEngineParisAcceptanceTest(final String ignored, final URI testCaseFileURI) { + super(ignored, testsContext, testCaseFileURI); + } + + @BeforeClass + public static void init() throws IOException { + testsContext = new JsonRpcTestsContext(GENESIS_FILE); + } + + @Parameterized.Parameters(name = "{0}") + public static Iterable testCases() throws URISyntaxException { + return testCases(TEST_CASE_PATH); + } + + @AfterClass + public static void tearDown() { + testsContext.cluster.close(); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineShanghaiAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineShanghaiAcceptanceTest.java new file mode 100644 index 00000000000..c676af5922b --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineShanghaiAcceptanceTest.java @@ -0,0 +1,51 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.jsonrpc; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class ExecutionEngineShanghaiAcceptanceTest extends AbstractJsonRpcTest { + private static final String GENESIS_FILE = "/jsonrpc/engine/shanghai/genesis.json"; + private static final String TEST_CASE_PATH = "/jsonrpc/engine/shanghai/test-cases/"; + + private static JsonRpcTestsContext testsContext; + + public ExecutionEngineShanghaiAcceptanceTest(final String ignored, final URI testCaseFileURI) { + super(ignored, testsContext, testCaseFileURI); + } + + @BeforeClass + public static void init() throws IOException { + testsContext = new JsonRpcTestsContext(GENESIS_FILE); + } + + @Parameterized.Parameters(name = "{0}") + public static Iterable testCases() throws URISyntaxException { + return testCases(TEST_CASE_PATH); + } + + @AfterClass + public static void tearDown() { + testsContext.cluster.close(); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/HttpServiceLoginAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/HttpServiceLoginAcceptanceTest.java deleted file mode 100644 index 605d4d2cf12..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/HttpServiceLoginAcceptanceTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.jsonrpc; - -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; -import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster; -import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfiguration; -import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder; - -import java.io.IOException; -import java.net.URISyntaxException; - -import org.junit.Before; -import org.junit.Test; - -public class HttpServiceLoginAcceptanceTest extends AcceptanceTestBase { - private Cluster authenticatedCluster; - private BesuNode nodeUsingAuthFile; - private BesuNode nodeUsingJwtPublicKey; - private static final String AUTH_FILE = "authentication/auth.toml"; - - // token with payload{"iat": 1516239022,"exp": 4729363200,"permissions": ["net:peerCount"]} - private static final String TOKEN_ALLOWING_NET_PEER_COUNT = - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsImV4cCI6NDcyOTM2MzIwMCwicGVybWl" - + "zc2lvbnMiOlsibmV0OnBlZXJDb3VudCJdfQ.Y6mNV0nvjzOdqAgMgxknFAOUTKoeRAo4aifNgNrWtuXbJJgz6-" - + "H_0GvLgjlToohPiDZbBJXJJlgb4zzLLB-sRtFnGoPaMgz_d_6z958GjFD7x_Fl0HW-WrTjRNenZNfTyD86OEAf" - + "XHy-7N3OYY2a5yeDbppTJy6nnHTq9hY-ad22-oWL1RbK3T_hnUJII_uXCZ9bJggSfu5m-NNUrm3TeqdnQzIaIz" - + "DqHlL0wNZwVPB4cFGN7zKghReBpkRJ8OFlxexQ491Q5eSpuYquhef-yGCIaMfy7GVtpDSD3Y-hjOErr7gUNCUh" - + "1wlc3Rb7ru_0qNgCWTBPJeRK32GppYotwQ"; - - @Before - public void setUp() throws IOException, URISyntaxException { - - final ClusterConfiguration clusterConfiguration = - new ClusterConfigurationBuilder().awaitPeerDiscovery(false).build(); - authenticatedCluster = new Cluster(clusterConfiguration, net); - - nodeUsingAuthFile = besu.createNodeWithAuthentication("node1", AUTH_FILE); - nodeUsingJwtPublicKey = besu.createNodeWithAuthenticationUsingJwtPublicKey("node2"); - authenticatedCluster.start(nodeUsingAuthFile, nodeUsingJwtPublicKey); - - nodeUsingAuthFile.verify(login.awaitResponse("user", "badpassword")); - nodeUsingJwtPublicKey.verify(login.awaitResponse("user", "badpassword")); - } - - @Test - public void shouldFailLoginWithWrongCredentials() { - nodeUsingAuthFile.verify(login.failure("user", "badpassword")); - } - - @Test - public void shouldSucceedLoginWithCorrectCredentials() { - nodeUsingAuthFile.verify(login.success("user", "pegasys")); - } - - @Test - public void jsonRpcMethodShouldSucceedWithAuthenticatedUserAndPermission() { - final String token = - nodeUsingAuthFile.execute( - permissioningTransactions.createSuccessfulLogin("user", "pegasys")); - nodeUsingAuthFile.useAuthenticationTokenInHeaderForJsonRpc(token); - nodeUsingAuthFile.verify(net.awaitPeerCount(1)); - } - - @Test - public void jsonRpcMethodShouldFailOnNonPermittedMethod() { - final String token = - nodeUsingAuthFile.execute( - permissioningTransactions.createSuccessfulLogin("user", "pegasys")); - nodeUsingAuthFile.useAuthenticationTokenInHeaderForJsonRpc(token); - nodeUsingAuthFile.verify(net.netVersionUnauthorized()); - nodeUsingAuthFile.verify(net.netServicesUnauthorized()); - } - - @Test - public void externalJwtPublicKeyUsedOnJsonRpcMethodShouldSucceed() { - nodeUsingJwtPublicKey.useAuthenticationTokenInHeaderForJsonRpc(TOKEN_ALLOWING_NET_PEER_COUNT); - nodeUsingJwtPublicKey.verify(net.awaitPeerCount(1)); - } - - @Test - public void externalJwtPublicKeyUsedOnJsonRpcMethodShouldFailOnNonPermittedMethod() { - nodeUsingJwtPublicKey.useAuthenticationTokenInHeaderForJsonRpc(TOKEN_ALLOWING_NET_PEER_COUNT); - nodeUsingJwtPublicKey.verify(net.netVersionUnauthorized()); - nodeUsingJwtPublicKey.verify(net.netServicesUnauthorized()); - } - - @Test - public void jsonRpcMethodShouldFailWhenThereIsNoToken() { - nodeUsingJwtPublicKey.verify(net.netVersionUnauthorized()); - nodeUsingJwtPublicKey.verify(net.netServicesUnauthorized()); - } - - @Test - public void loginShouldBeDisabledWhenUsingExternalJwtPublicKey() { - nodeUsingJwtPublicKey.verify(login.disabled()); - } - - @Override - public void tearDownAcceptanceTestBase() { - authenticatedCluster.stop(); - super.tearDownAcceptanceTestBase(); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/JsonRpcHttpAuthenticationAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/JsonRpcHttpAuthenticationAcceptanceTest.java new file mode 100644 index 00000000000..3ef383a5265 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/JsonRpcHttpAuthenticationAcceptanceTest.java @@ -0,0 +1,195 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.jsonrpc; + +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; +import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster; +import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfiguration; +import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class JsonRpcHttpAuthenticationAcceptanceTest extends AcceptanceTestBase { + private Cluster authenticatedCluster; + private BesuNode nodeUsingAuthFile; + private BesuNode nodeUsingRsaJwtPublicKey; + private BesuNode nodeUsingEcdsaJwtPublicKey; + private BesuNode nodeUsingAuthFileWithNoAuthApi; + private static final String AUTH_FILE = "authentication/auth.toml"; + + // token with payload{"iat": 1516239022,"exp": 4729363200,"permissions": ["net:peerCount"]} + private static final String RSA_TOKEN_ALLOWING_NET_PEER_COUNT = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsImV4cCI6NDcyOTM2MzIwMCwicGVybWl" + + "zc2lvbnMiOlsibmV0OnBlZXJDb3VudCJdfQ.Y6mNV0nvjzOdqAgMgxknFAOUTKoeRAo4aifNgNrWtuXbJJgz6-" + + "H_0GvLgjlToohPiDZbBJXJJlgb4zzLLB-sRtFnGoPaMgz_d_6z958GjFD7x_Fl0HW-WrTjRNenZNfTyD86OEAf" + + "XHy-7N3OYY2a5yeDbppTJy6nnHTq9hY-ad22-oWL1RbK3T_hnUJII_uXCZ9bJggSfu5m-NNUrm3TeqdnQzIaIz" + + "DqHlL0wNZwVPB4cFGN7zKghReBpkRJ8OFlxexQ491Q5eSpuYquhef-yGCIaMfy7GVtpDSD3Y-hjOErr7gUNCUh" + + "1wlc3Rb7ru_0qNgCWTBPJeRK32GppYotwQ"; + + private static final String ECDSA_TOKEN_ALLOWING_NET_PEER_COUNT = + "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsImV4cCI6NDcyOTM2MzIwMCwicGVybWlz" + + "c2lvbnMiOlsibmV0OnBlZXJDb3VudCJdfQ.pWXniN6XQ7G8b1nawy8sviPCMxrfbcI6c7UFzeXm26CMGMUEZxiC" + + "JjRntB8ueuZcsxnGlEhCHt-KngpFEmx5TA"; + + private static final List NO_AUTH_API_METHODS = Arrays.asList("net_services"); + + @BeforeEach + public void setUp() throws IOException, URISyntaxException { + + final ClusterConfiguration clusterConfiguration = + new ClusterConfigurationBuilder().awaitPeerDiscovery(false).build(); + authenticatedCluster = new Cluster(clusterConfiguration, net); + + nodeUsingAuthFile = besu.createNodeWithAuthentication("node1", AUTH_FILE); + nodeUsingRsaJwtPublicKey = besu.createNodeWithAuthenticationUsingRsaJwtPublicKey("node2"); + nodeUsingEcdsaJwtPublicKey = besu.createNodeWithAuthenticationUsingEcdsaJwtPublicKey("node3"); + nodeUsingAuthFileWithNoAuthApi = + besu.createNodeWithAuthFileAndNoAuthApi("node4", AUTH_FILE, NO_AUTH_API_METHODS); + authenticatedCluster.start( + nodeUsingAuthFile, + nodeUsingRsaJwtPublicKey, + nodeUsingEcdsaJwtPublicKey, + nodeUsingAuthFileWithNoAuthApi); + + nodeUsingAuthFile.verify(login.awaitResponse("user", "badpassword")); + nodeUsingRsaJwtPublicKey.verify(login.awaitResponse("user", "badpassword")); + nodeUsingEcdsaJwtPublicKey.verify(login.awaitResponse("user", "badpassword")); + nodeUsingAuthFileWithNoAuthApi.verify(login.awaitResponse("user", "badpassword")); + } + + @Test + public void shouldFailLoginWithWrongCredentials() { + nodeUsingAuthFile.verify(login.failure("user", "badpassword")); + nodeUsingAuthFileWithNoAuthApi.verify(login.failure("user", "badpassword")); + } + + @Test + public void shouldSucceedLoginWithCorrectCredentials() { + nodeUsingAuthFile.verify(login.success("user", "pegasys")); + nodeUsingAuthFileWithNoAuthApi.verify(login.success("user", "pegasys")); + } + + @Test + public void jsonRpcMethodShouldSucceedWithAuthenticatedUserAndPermission() { + String token = + nodeUsingAuthFile.execute( + permissioningTransactions.createSuccessfulLogin("user", "pegasys")); + nodeUsingAuthFile.useAuthenticationTokenInHeaderForJsonRpc(token); + nodeUsingAuthFile.verify(net.awaitPeerCount(3)); + + token = + nodeUsingAuthFileWithNoAuthApi.execute( + permissioningTransactions.createSuccessfulLogin("user", "pegasys")); + nodeUsingAuthFileWithNoAuthApi.useAuthenticationTokenInHeaderForJsonRpc(token); + nodeUsingAuthFileWithNoAuthApi.verify(net.awaitPeerCount(3)); + } + + @Test + public void jsonRpcMethodShouldFailOnNonPermittedMethod() { + String token = + nodeUsingAuthFile.execute( + permissioningTransactions.createSuccessfulLogin("user", "pegasys")); + nodeUsingAuthFile.useAuthenticationTokenInHeaderForJsonRpc(token); + nodeUsingAuthFile.verify(net.netVersionUnauthorized()); + nodeUsingAuthFile.verify(net.netServicesUnauthorized()); + + token = + nodeUsingAuthFileWithNoAuthApi.execute( + permissioningTransactions.createSuccessfulLogin("user", "pegasys")); + nodeUsingAuthFileWithNoAuthApi.useAuthenticationTokenInHeaderForJsonRpc(token); + nodeUsingAuthFileWithNoAuthApi.verify(net.netVersionUnauthorized()); + } + + @Test + public void jsonRpcMethodsNotIncludedInNoAuthListShouldFailWithoutToken() { + nodeUsingAuthFile.verify(net.netVersionUnauthorized()); + nodeUsingAuthFileWithNoAuthApi.verify(net.netVersionUnauthorized()); + } + + @Test + public void noAuthJsonRpcMethodShouldSucceedWithoutToken() { + nodeUsingAuthFileWithNoAuthApi.verify(net.netServicesAllActive()); + } + + @Test + public void noAuthJsonRpcConfiguredNodeShouldWorkAsIntended() { + // No token -> all methods other than specified no auth methods should fail + nodeUsingAuthFileWithNoAuthApi.verify(net.netVersionUnauthorized()); + nodeUsingAuthFileWithNoAuthApi.verify(net.netServicesAllActive()); + + // Should behave the same with valid token + String token = + nodeUsingAuthFileWithNoAuthApi.execute( + permissioningTransactions.createSuccessfulLogin("user", "pegasys")); + nodeUsingAuthFileWithNoAuthApi.useAuthenticationTokenInHeaderForJsonRpc(token); + nodeUsingAuthFileWithNoAuthApi.verify(net.netVersionUnauthorized()); + nodeUsingAuthFileWithNoAuthApi.verify(net.netServicesAllActive()); + nodeUsingAuthFileWithNoAuthApi.verify(net.awaitPeerCount(3)); + } + + @Test + public void externalRsaJwtPublicKeyUsedOnJsonRpcMethodShouldSucceed() { + nodeUsingRsaJwtPublicKey.useAuthenticationTokenInHeaderForJsonRpc( + RSA_TOKEN_ALLOWING_NET_PEER_COUNT); + nodeUsingRsaJwtPublicKey.verify(net.awaitPeerCount(3)); + } + + @Test + public void externalRsaJwtPublicKeyUsedOnJsonRpcMethodShouldFailOnNonPermittedMethod() { + nodeUsingRsaJwtPublicKey.useAuthenticationTokenInHeaderForJsonRpc( + RSA_TOKEN_ALLOWING_NET_PEER_COUNT); + nodeUsingRsaJwtPublicKey.verify(net.netVersionUnauthorized()); + nodeUsingRsaJwtPublicKey.verify(net.netServicesUnauthorized()); + } + + @Test + public void externalEcdsaJwtPublicKeyUsedOnJsonRpcMethodShouldSucceed() { + nodeUsingEcdsaJwtPublicKey.useAuthenticationTokenInHeaderForJsonRpc( + ECDSA_TOKEN_ALLOWING_NET_PEER_COUNT); + nodeUsingEcdsaJwtPublicKey.verify(net.awaitPeerCount(3)); + } + + @Test + public void externalEcdsaJwtPublicKeyUsedOnJsonRpcMethodShouldFailOnNonPermittedMethod() { + nodeUsingEcdsaJwtPublicKey.useAuthenticationTokenInHeaderForJsonRpc( + ECDSA_TOKEN_ALLOWING_NET_PEER_COUNT); + nodeUsingEcdsaJwtPublicKey.verify(net.netVersionUnauthorized()); + nodeUsingEcdsaJwtPublicKey.verify(net.netServicesUnauthorized()); + } + + @Test + public void jsonRpcMethodShouldFailWhenThereIsNoToken() { + nodeUsingRsaJwtPublicKey.verify(net.netVersionUnauthorized()); + nodeUsingRsaJwtPublicKey.verify(net.netServicesUnauthorized()); + } + + @Test + public void loginShouldBeDisabledWhenUsingExternalJwtPublicKey() { + nodeUsingRsaJwtPublicKey.verify(login.disabled()); + } + + @Override + public void tearDownAcceptanceTestBase() { + authenticatedCluster.stop(); + super.tearDownAcceptanceTestBase(); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/JsonRpcWebsocketAuthenticationAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/JsonRpcWebsocketAuthenticationAcceptanceTest.java new file mode 100644 index 00000000000..47d236e5b39 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/JsonRpcWebsocketAuthenticationAcceptanceTest.java @@ -0,0 +1,198 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.jsonrpc; + +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; +import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster; +import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfiguration; +import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class JsonRpcWebsocketAuthenticationAcceptanceTest extends AcceptanceTestBase { + private BesuNode nodeUsingAuthFile; + private BesuNode nodeUsingRsaJwtPublicKey; + private BesuNode nodeUsingEcdsaJwtPublicKey; + private BesuNode nodeUsingAuthFileWithNoAuthApi; + private Cluster authenticatedCluster; + private static final String AUTH_FILE = "authentication/auth.toml"; + + private static final List NO_AUTH_API_METHODS = Arrays.asList("net_services"); + + // token with payload{"iat": 1516239022,"exp": 4729363200,"permissions": ["net:peerCount"]} + private static final String RSA_TOKEN_ALLOWING_NET_PEER_COUNT = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsImV4cCI6NDcyOTM2MzIwMCwicGVybWl" + + "zc2lvbnMiOlsibmV0OnBlZXJDb3VudCJdfQ.Y6mNV0nvjzOdqAgMgxknFAOUTKoeRAo4aifNgNrWtuXbJJgz6-" + + "H_0GvLgjlToohPiDZbBJXJJlgb4zzLLB-sRtFnGoPaMgz_d_6z958GjFD7x_Fl0HW-WrTjRNenZNfTyD86OEAf" + + "XHy-7N3OYY2a5yeDbppTJy6nnHTq9hY-ad22-oWL1RbK3T_hnUJII_uXCZ9bJggSfu5m-NNUrm3TeqdnQzIaIz" + + "DqHlL0wNZwVPB4cFGN7zKghReBpkRJ8OFlxexQ491Q5eSpuYquhef-yGCIaMfy7GVtpDSD3Y-hjOErr7gUNCUh" + + "1wlc3Rb7ru_0qNgCWTBPJeRK32GppYotwQ"; + + private static final String ECDSA_TOKEN_ALLOWING_NET_PEER_COUNT = + "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsImV4cCI6NDcyOTM2MzIwMCwicGVybWlz" + + "c2lvbnMiOlsibmV0OnBlZXJDb3VudCJdfQ.pWXniN6XQ7G8b1nawy8sviPCMxrfbcI6c7UFzeXm26CMGMUEZxiC" + + "JjRntB8ueuZcsxnGlEhCHt-KngpFEmx5TA"; + + @BeforeEach + public void setUp() throws IOException, URISyntaxException { + final ClusterConfiguration clusterConfiguration = + new ClusterConfigurationBuilder().awaitPeerDiscovery(false).build(); + authenticatedCluster = new Cluster(clusterConfiguration, net); + + nodeUsingAuthFile = besu.createNodeWithAuthentication("node1", AUTH_FILE); + nodeUsingRsaJwtPublicKey = besu.createNodeWithAuthenticationUsingRsaJwtPublicKey("node2"); + nodeUsingEcdsaJwtPublicKey = besu.createNodeWithAuthenticationUsingEcdsaJwtPublicKey("node3"); + nodeUsingAuthFileWithNoAuthApi = + besu.createWsNodeWithAuthFileAndNoAuthApi("node4", AUTH_FILE, NO_AUTH_API_METHODS); + authenticatedCluster.start( + nodeUsingAuthFile, + nodeUsingRsaJwtPublicKey, + nodeUsingEcdsaJwtPublicKey, + nodeUsingAuthFileWithNoAuthApi); + + nodeUsingAuthFile.useWebSocketsForJsonRpc(); + nodeUsingRsaJwtPublicKey.useWebSocketsForJsonRpc(); + nodeUsingEcdsaJwtPublicKey.useWebSocketsForJsonRpc(); + nodeUsingAuthFileWithNoAuthApi.useWebSocketsForJsonRpc(); + nodeUsingAuthFile.verify(login.awaitResponse("user", "badpassword")); + nodeUsingRsaJwtPublicKey.verify(login.awaitResponse("user", "badpassword")); + nodeUsingEcdsaJwtPublicKey.verify(login.awaitResponse("user", "badpassword")); + nodeUsingAuthFileWithNoAuthApi.verify(login.awaitResponse("user", "badpassword")); + } + + @Test + public void shouldFailLoginWithWrongCredentials() { + nodeUsingAuthFile.verify(login.failure("user", "badpassword")); + nodeUsingAuthFileWithNoAuthApi.verify(login.failure("user", "badpassword")); + } + + @Test + public void shouldSucceedLoginWithCorrectCredentials() { + nodeUsingAuthFile.verify(login.success("user", "pegasys")); + nodeUsingAuthFileWithNoAuthApi.verify(login.success("user", "pegasys")); + } + + @Test + public void jsonRpcMethodShouldSucceedWithAuthenticatedUserAndPermission() { + String token = + nodeUsingAuthFile.execute( + permissioningTransactions.createSuccessfulLogin("user", "pegasys")); + nodeUsingAuthFile.useAuthenticationTokenInHeaderForJsonRpc(token); + nodeUsingAuthFile.verify(net.awaitPeerCount(3)); + + token = + nodeUsingAuthFileWithNoAuthApi.execute( + permissioningTransactions.createSuccessfulLogin("user", "pegasys")); + nodeUsingAuthFileWithNoAuthApi.useAuthenticationTokenInHeaderForJsonRpc(token); + nodeUsingAuthFileWithNoAuthApi.verify(net.awaitPeerCount(3)); + } + + @Test + public void jsonRpcMethodShouldFailOnNonPermittedMethod() { + String token = + nodeUsingAuthFile.execute( + permissioningTransactions.createSuccessfulLogin("user", "pegasys")); + nodeUsingAuthFile.useAuthenticationTokenInHeaderForJsonRpc(token); + nodeUsingAuthFile.verify(net.netVersionUnauthorized()); + nodeUsingAuthFile.verify(net.netServicesUnauthorized()); + + token = + nodeUsingAuthFileWithNoAuthApi.execute( + permissioningTransactions.createSuccessfulLogin("user", "pegasys")); + nodeUsingAuthFileWithNoAuthApi.useAuthenticationTokenInHeaderForJsonRpc(token); + nodeUsingAuthFileWithNoAuthApi.verify(net.netVersionUnauthorized()); + } + + @Test + public void jsonRpcMethodsNotIncludedInNoAuthListShouldFailWithoutToken() { + nodeUsingAuthFile.verify(net.netVersionUnauthorized()); + nodeUsingAuthFileWithNoAuthApi.verify(net.netVersionUnauthorized()); + } + + @Test + public void noAuthJsonRpcMethodShouldSucceedWithoutToken() { + nodeUsingAuthFileWithNoAuthApi.verify(net.netServicesAllActive()); + } + + @Test + public void noAuthJsonRpcConfiguredNodeShouldWorkAsIntended() { + // No token -> all methods other than specified no auth methods should fail + nodeUsingAuthFileWithNoAuthApi.verify(net.netVersionUnauthorized()); + nodeUsingAuthFileWithNoAuthApi.verify(net.netServicesAllActive()); + + // Should behave the same with valid token + String token = + nodeUsingAuthFileWithNoAuthApi.execute( + permissioningTransactions.createSuccessfulLogin("user", "pegasys")); + nodeUsingAuthFileWithNoAuthApi.useAuthenticationTokenInHeaderForJsonRpc(token); + nodeUsingAuthFileWithNoAuthApi.verify(net.netVersionUnauthorized()); + nodeUsingAuthFileWithNoAuthApi.verify(net.netServicesAllActive()); + nodeUsingAuthFileWithNoAuthApi.verify(net.awaitPeerCount(3)); + } + + @Test + public void externalRsaJwtPublicKeyUsedOnJsonRpcMethodShouldSucceed() { + nodeUsingRsaJwtPublicKey.useAuthenticationTokenInHeaderForJsonRpc( + RSA_TOKEN_ALLOWING_NET_PEER_COUNT); + nodeUsingRsaJwtPublicKey.verify(net.awaitPeerCount(3)); + } + + @Test + public void externalRsaJwtPublicKeyUsedOnJsonRpcMethodShouldFailOnNonPermittedMethod() { + nodeUsingRsaJwtPublicKey.useAuthenticationTokenInHeaderForJsonRpc( + RSA_TOKEN_ALLOWING_NET_PEER_COUNT); + nodeUsingRsaJwtPublicKey.verify(net.netVersionUnauthorized()); + nodeUsingAuthFile.verify(net.netServicesUnauthorized()); + } + + @Test + public void externalEcdsaJwtPublicKeyUsedOnJsonRpcMethodShouldSucceed() { + nodeUsingEcdsaJwtPublicKey.useAuthenticationTokenInHeaderForJsonRpc( + ECDSA_TOKEN_ALLOWING_NET_PEER_COUNT); + nodeUsingEcdsaJwtPublicKey.verify(net.awaitPeerCount(3)); + } + + @Test + public void externalEcdsaJwtPublicKeyUsedOnJsonRpcMethodShouldFailOnNonPermittedMethod() { + nodeUsingEcdsaJwtPublicKey.useAuthenticationTokenInHeaderForJsonRpc( + ECDSA_TOKEN_ALLOWING_NET_PEER_COUNT); + nodeUsingEcdsaJwtPublicKey.verify(net.netVersionUnauthorized()); + nodeUsingEcdsaJwtPublicKey.verify(net.netServicesUnauthorized()); + } + + @Test + public void jsonRpcMethodShouldFailWhenThereIsNoToken() { + nodeUsingRsaJwtPublicKey.verify(net.netVersionUnauthorized()); + nodeUsingRsaJwtPublicKey.verify(net.netServicesUnauthorized()); + } + + @Test + public void loginShouldBeDisabledWhenUsingExternalJwtPublicKey() { + nodeUsingRsaJwtPublicKey.verify(login.disabled()); + } + + @Override + public void tearDownAcceptanceTestBase() { + authenticatedCluster.stop(); + super.tearDownAcceptanceTestBase(); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/NetServicesAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/NetServicesAcceptanceTest.java index e8a337a0bd1..dbff6f151a3 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/NetServicesAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/NetServicesAcceptanceTest.java @@ -20,8 +20,9 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfiguration; import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder; -import org.junit.After; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class NetServicesAcceptanceTest extends AcceptanceTestBase { @@ -30,11 +31,15 @@ public class NetServicesAcceptanceTest extends AcceptanceTestBase { private Node nodeA; private Node nodeB; - @Test - public void shouldIndicateNetServicesEnabled() throws Exception { + @BeforeEach + public void setup() { final ClusterConfiguration clusterConfiguration = new ClusterConfigurationBuilder().awaitPeerDiscovery(false).build(); noDiscoveryCluster = new Cluster(clusterConfiguration, net); + } + + @Test + public void shouldIndicateNetServicesEnabled() throws Exception { nodeA = besu.createArchiveNodeNetServicesEnabled("nodeA"); nodeB = besu.createArchiveNodeNetServicesEnabled("nodeB"); noDiscoveryCluster.start(nodeA, nodeB); @@ -45,9 +50,6 @@ public void shouldIndicateNetServicesEnabled() throws Exception { @Test public void shouldNotDisplayDisabledServices() throws Exception { - final ClusterConfiguration clusterConfiguration = - new ClusterConfigurationBuilder().awaitPeerDiscovery(false).build(); - noDiscoveryCluster = new Cluster(clusterConfiguration, net); nodeA = besu.createArchiveNodeNetServicesDisabled("nodeA"); nodeB = besu.createArchiveNodeNetServicesDisabled("nodeB"); noDiscoveryCluster.start(nodeA, nodeB); @@ -56,7 +58,7 @@ public void shouldNotDisplayDisabledServices() throws Exception { nodeB.verify(net.netServicesOnlyJsonRpcEnabled()); } - @After + @AfterEach public void closeDown() throws Exception { noDiscoveryCluster.close(); } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/RevertReasonAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/RevertReasonAcceptanceTest.java similarity index 87% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/RevertReasonAcceptanceTest.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/RevertReasonAcceptanceTest.java index 8e59382e71d..9c8d610dc28 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/RevertReasonAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/RevertReasonAcceptanceTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.tests.web3j; +package org.hyperledger.besu.tests.acceptance.jsonrpc; import static org.hyperledger.besu.tests.web3j.generated.RevertReason.FUNC_REVERTWITHOUTREVERTREASON; import static org.hyperledger.besu.tests.web3j.generated.RevertReason.FUNC_REVERTWITHREVERTREASON; @@ -21,15 +21,15 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import org.hyperledger.besu.tests.web3j.generated.RevertReason; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.web3j.protocol.core.methods.response.EthSendTransaction; public class RevertReasonAcceptanceTest extends AcceptanceTestBase { private BesuNode minerNode; - @Before + @BeforeEach public void setUp() throws Exception { minerNode = besu.createMinerNodeWithRevertReasonEnabled("miner-node-withRevertReason"); cluster.start(minerNode); @@ -42,7 +42,7 @@ public void mustRevertWithRevertReason() { final EthSendTransaction transaction = minerNode.execute( contractTransactions.callSmartContract( - FUNC_REVERTWITHREVERTREASON, revertReasonContract.getContractAddress())); + revertReasonContract.getContractAddress(), FUNC_REVERTWITHREVERTREASON)); minerNode.verify( eth.expectSuccessfulTransactionReceiptWithReason( transaction.getTransactionHash(), "RevertReason")); @@ -55,7 +55,7 @@ public void mustRevertWithoutRevertReason() { final EthSendTransaction transaction = minerNode.execute( contractTransactions.callSmartContract( - FUNC_REVERTWITHOUTREVERTREASON, revertReasonContract.getContractAddress())); + revertReasonContract.getContractAddress(), FUNC_REVERTWITHOUTREVERTREASON)); minerNode.verify( eth.expectSuccessfulTransactionReceiptWithoutReason(transaction.getTransactionHash())); } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/Web3Sha3AcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/Web3Sha3AcceptanceTest.java index 9de4c0bf2b7..a925a276611 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/Web3Sha3AcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/Web3Sha3AcceptanceTest.java @@ -17,14 +17,14 @@ import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class Web3Sha3AcceptanceTest extends AcceptanceTestBase { private Node node; - @Before + @BeforeEach public void setUp() throws Exception { node = besu.createArchiveNode("node1"); cluster.start(node); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/WebsocketServiceLoginAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/WebsocketServiceLoginAcceptanceTest.java deleted file mode 100644 index 588a27390bc..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/WebsocketServiceLoginAcceptanceTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.jsonrpc; - -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; -import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster; -import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfiguration; -import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder; - -import java.io.IOException; -import java.net.URISyntaxException; - -import org.junit.Before; -import org.junit.Test; - -public class WebsocketServiceLoginAcceptanceTest extends AcceptanceTestBase { - private BesuNode nodeUsingAuthFile; - private BesuNode nodeUsingJwtPublicKey; - private Cluster authenticatedCluster; - private static final String AUTH_FILE = "authentication/auth.toml"; - - // token with payload{"iat": 1516239022,"exp": 4729363200,"permissions": ["net:peerCount"]} - private static final String TOKEN_ALLOWING_NET_PEER_COUNT = - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MTYyMzkwMjIsImV4cCI6NDcyOTM2MzIwMCwicGVybWl" - + "zc2lvbnMiOlsibmV0OnBlZXJDb3VudCJdfQ.Y6mNV0nvjzOdqAgMgxknFAOUTKoeRAo4aifNgNrWtuXbJJgz6-" - + "H_0GvLgjlToohPiDZbBJXJJlgb4zzLLB-sRtFnGoPaMgz_d_6z958GjFD7x_Fl0HW-WrTjRNenZNfTyD86OEAf" - + "XHy-7N3OYY2a5yeDbppTJy6nnHTq9hY-ad22-oWL1RbK3T_hnUJII_uXCZ9bJggSfu5m-NNUrm3TeqdnQzIaIz" - + "DqHlL0wNZwVPB4cFGN7zKghReBpkRJ8OFlxexQ491Q5eSpuYquhef-yGCIaMfy7GVtpDSD3Y-hjOErr7gUNCUh" - + "1wlc3Rb7ru_0qNgCWTBPJeRK32GppYotwQ"; - - @Before - public void setUp() throws IOException, URISyntaxException { - final ClusterConfiguration clusterConfiguration = - new ClusterConfigurationBuilder().awaitPeerDiscovery(false).build(); - authenticatedCluster = new Cluster(clusterConfiguration, net); - - nodeUsingAuthFile = besu.createNodeWithAuthentication("node1", AUTH_FILE); - nodeUsingJwtPublicKey = besu.createNodeWithAuthenticationUsingJwtPublicKey("node2"); - authenticatedCluster.start(nodeUsingAuthFile, nodeUsingJwtPublicKey); - - nodeUsingAuthFile.useWebSocketsForJsonRpc(); - nodeUsingJwtPublicKey.useWebSocketsForJsonRpc(); - nodeUsingAuthFile.verify(login.awaitResponse("user", "badpassword")); - nodeUsingJwtPublicKey.verify(login.awaitResponse("user", "badpassword")); - } - - @Test - public void shouldFailLoginWithWrongCredentials() { - nodeUsingAuthFile.verify(login.failure("user", "badpassword")); - } - - @Test - public void shouldSucceedLoginWithCorrectCredentials() { - nodeUsingAuthFile.verify(login.success("user", "pegasys")); - } - - @Test - public void jsonRpcMethodShouldSucceedWithAuthenticatedUserAndPermission() { - final String token = - nodeUsingAuthFile.execute( - permissioningTransactions.createSuccessfulLogin("user", "pegasys")); - nodeUsingAuthFile.useAuthenticationTokenInHeaderForJsonRpc(token); - nodeUsingAuthFile.verify(net.awaitPeerCount(1)); - } - - @Test - public void jsonRpcMethodShouldFailOnNonPermittedMethod() { - final String token = - nodeUsingAuthFile.execute( - permissioningTransactions.createSuccessfulLogin("user", "pegasys")); - nodeUsingAuthFile.useAuthenticationTokenInHeaderForJsonRpc(token); - nodeUsingAuthFile.verify(net.netVersionUnauthorized()); - nodeUsingAuthFile.verify(net.netServicesUnauthorized()); - } - - @Test - public void externalJwtPublicKeyUsedOnJsonRpcMethodShouldSucceed() { - nodeUsingJwtPublicKey.useAuthenticationTokenInHeaderForJsonRpc(TOKEN_ALLOWING_NET_PEER_COUNT); - nodeUsingJwtPublicKey.verify(net.awaitPeerCount(1)); - } - - @Test - public void externalJwtPublicKeyUsedOnJsonRpcMethodShouldFailOnNonPermittedMethod() { - nodeUsingJwtPublicKey.useAuthenticationTokenInHeaderForJsonRpc(TOKEN_ALLOWING_NET_PEER_COUNT); - nodeUsingJwtPublicKey.verify(net.netVersionUnauthorized()); - nodeUsingAuthFile.verify(net.netServicesUnauthorized()); - } - - @Test - public void jsonRpcMethodShouldFailWhenThereIsNoToken() { - nodeUsingJwtPublicKey.verify(net.netVersionUnauthorized()); - nodeUsingJwtPublicKey.verify(net.netServicesUnauthorized()); - } - - @Test - public void loginShouldBeDisabledWhenUsingExternalJwtPublicKey() { - nodeUsingJwtPublicKey.verify(login.disabled()); - } - - @Override - public void tearDownAcceptanceTestBase() { - authenticatedCluster.stop(); - super.tearDownAcceptanceTestBase(); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/admin/AdminAddPeerAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/admin/AdminAddPeerAcceptanceTest.java index cce98463846..6c1bd5813bd 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/admin/AdminAddPeerAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/admin/AdminAddPeerAcceptanceTest.java @@ -20,9 +20,9 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfiguration; import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class AdminAddPeerAcceptanceTest extends AcceptanceTestBase { private Cluster noDiscoveryCluster; @@ -30,7 +30,7 @@ public class AdminAddPeerAcceptanceTest extends AcceptanceTestBase { private Node nodeA; private Node nodeB; - @Before + @BeforeEach public void setUp() throws Exception { final ClusterConfiguration clusterConfiguration = new ClusterConfigurationBuilder().awaitPeerDiscovery(false).build(); @@ -40,7 +40,7 @@ public void setUp() throws Exception { noDiscoveryCluster.start(nodeA, nodeB); } - @After + @AfterEach public void tearDown() { noDiscoveryCluster.stop(); } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ipc/Web3JSupportAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ipc/Web3JSupportAcceptanceTest.java new file mode 100644 index 00000000000..c13c195cb33 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ipc/Web3JSupportAcceptanceTest.java @@ -0,0 +1,74 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.jsonrpc.ipc; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; +import static org.junit.Assume.assumeTrue; + +import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; +import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Locale; + +import org.junit.Before; +import org.junit.Test; +import org.web3j.protocol.Web3j; +import org.web3j.protocol.core.Request; +import org.web3j.protocol.core.methods.response.NetVersion; +import org.web3j.protocol.ipc.UnixIpcService; + +public class Web3JSupportAcceptanceTest extends AcceptanceTestBase { + + private Node node; + private Path socketPath; + + @Before + public void setUp() throws Exception { + socketPath = Files.createTempFile("besu-test-", ".ipc"); + node = + besu.createNode( + "node1", + (configurationBuilder) -> + configurationBuilder.jsonRpcIpcConfiguration( + new JsonRpcIpcConfiguration( + true, socketPath, Collections.singletonList(RpcApis.NET.name())))); + cluster.start(node); + } + + @Test + public void netVersionCall() { + final String osName = System.getProperty("os.name").toLowerCase(Locale.ENGLISH); + assumeTrue(osName.contains("mac") || osName.contains("linux")); + + final Web3j web3 = Web3j.build(new UnixIpcService(socketPath.toString())); + final Request ethBlockNumberRequest = web3.netVersion(); + node.verify( + node -> { + try { + assertThat(ethBlockNumberRequest.send().getNetVersion()) + .isEqualTo(String.valueOf(2018)); + } catch (IOException e) { + fail("Web3J net_version call failed", e); + } + }); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountLocalAndOnChainPermissioningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountLocalAndOnChainPermissioningAcceptanceTest.java deleted file mode 100644 index 418bfa9741b..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountLocalAndOnChainPermissioningAcceptanceTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.permissioning; - -import org.hyperledger.besu.tests.acceptance.dsl.account.Account; -import org.hyperledger.besu.tests.acceptance.dsl.node.Node; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.account.TransferTransaction; - -import java.math.BigInteger; -import java.util.Arrays; - -import org.junit.Before; -import org.junit.Test; - -public class AccountLocalAndOnChainPermissioningAcceptanceTest - extends AccountSmartContractPermissioningAcceptanceTestBase { - - private Account senderC; - - @Before - public void setUp() { - senderC = accounts.createAccount("Account-C"); - } - - @Test - public void testAccountCannotSendTxWhenNotOnLocalAllowList() { - // OnChain allowlist: Primary, Secondary, C - // Local allowlist: Primary, Secondary - - final Node node = - permissionedNode( - "node1", - Arrays.asList( - accounts.getPrimaryBenefactor().getAddress(), - accounts.getSecondaryBenefactor().getAddress())); - permissionedCluster.start(node); - - // ensure SenderC has got some ether available - node.execute(accountTransactions.createTransfer(senderC, 10)); - node.verify(senderC.balanceEquals(10)); - - // add accounts to onChain allowlist - node.execute(allowAccount(accounts.getPrimaryBenefactor())); - node.verify(accountIsAllowed(accounts.getPrimaryBenefactor())); - - node.execute(allowAccount(accounts.getSecondaryBenefactor())); - node.verify(accountIsAllowed(accounts.getSecondaryBenefactor())); - - node.execute(allowAccount(senderC)); - node.verify(accountIsAllowed(senderC)); - - // sender C should not be able to send Tx - verifyTransferForbidden(node, senderC, accounts.getSecondaryBenefactor()); - } - - @Test - public void testAccountCannotSendTxWhenNotOnOnChainAllowList() { - // OnChain allowlist: Primary, Secondary, Receiver - // Local allowlist: Primary, Secondary, C, Receiver - - final Account receiverAccount = accounts.createAccount("Rec-A"); - - final Node node = - permissionedNode( - "node1", - Arrays.asList( - accounts.getPrimaryBenefactor().getAddress(), - accounts.getSecondaryBenefactor().getAddress(), - senderC.getAddress(), - receiverAccount.getAddress())); - permissionedCluster.start(node); - - // ensure SenderC has got some ether available - node.execute(accountTransactions.createTransfer(senderC, 10)); - node.verify(senderC.balanceEquals(10)); - - // add accounts to onChain allowlist - node.execute(allowAccount(accounts.getPrimaryBenefactor())); - node.verify(accountIsAllowed(accounts.getPrimaryBenefactor())); - - node.execute(allowAccount(accounts.getSecondaryBenefactor())); - node.verify(accountIsAllowed(accounts.getSecondaryBenefactor())); - - node.execute(allowAccount(receiverAccount)); - node.verify(accountIsAllowed(receiverAccount)); - - // verify senderC is forbidden because it is not on OnChain allowlist - node.verify(accountIsForbidden(senderC)); - - // sender C should not be able to send Tx as well - node.execute(accountTransactions.createTransfer(senderC, receiverAccount, 1)); - node.verify(receiverAccount.balanceDoesNotChange(0)); - - // final check, other account should be able to send tx - node.execute( - accountTransactions.createTransfer(accounts.getPrimaryBenefactor(), receiverAccount, 5)); - node.verify(receiverAccount.balanceEquals(5)); - } - - private void verifyTransferForbidden( - final Node node, final Account sender, final Account beneficiary) { - BigInteger nonce = node.execute(ethTransactions.getTransactionCount(sender.getAddress())); - TransferTransaction transfer = - accountTransactions.createTransfer(sender, beneficiary, 1, nonce); - node.verify( - eth.sendRawTransactionExceptional( - transfer.signedTransactionData(), - "Sender account not authorized to send transactions")); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountLocalAndOnchainPermissioningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountLocalAndOnchainPermissioningAcceptanceTest.java new file mode 100644 index 00000000000..4b6401303be --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountLocalAndOnchainPermissioningAcceptanceTest.java @@ -0,0 +1,121 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.permissioning; + +import org.hyperledger.besu.tests.acceptance.dsl.account.Account; +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.account.TransferTransaction; + +import java.math.BigInteger; +import java.util.Arrays; + +import org.junit.Before; +import org.junit.Test; + +public class AccountLocalAndOnchainPermissioningAcceptanceTest + extends AccountSmartContractPermissioningAcceptanceTestBase { + + private Account senderC; + + @Before + public void setUp() { + senderC = accounts.createAccount("Account-C"); + } + + @Test + public void testAccountCannotSendTxWhenNotOnLocalAllowList() { + // Onchain allowlist: Primary, Secondary, C + // Local allowlist: Primary, Secondary + + final Node node = + permissionedNode( + "node1", + Arrays.asList( + accounts.getPrimaryBenefactor().getAddress(), + accounts.getSecondaryBenefactor().getAddress())); + permissionedCluster.start(node); + + // ensure SenderC has got some ether available + node.execute(accountTransactions.createTransfer(senderC, 10)); + node.verify(senderC.balanceEquals(10)); + + // add accounts to onchain allowlist + node.execute(allowAccount(accounts.getPrimaryBenefactor())); + node.verify(accountIsAllowed(accounts.getPrimaryBenefactor())); + + node.execute(allowAccount(accounts.getSecondaryBenefactor())); + node.verify(accountIsAllowed(accounts.getSecondaryBenefactor())); + + node.execute(allowAccount(senderC)); + node.verify(accountIsAllowed(senderC)); + + // sender C should not be able to send Tx + verifyTransferForbidden(node, senderC, accounts.getSecondaryBenefactor()); + } + + @Test + public void testAccountCannotSendTxWhenNotOnOnchainAllowList() { + // Onchain allowlist: Primary, Secondary, Receiver + // Local allowlist: Primary, Secondary, C, Receiver + + final Account receiverAccount = accounts.createAccount("Rec-A"); + + final Node node = + permissionedNode( + "node1", + Arrays.asList( + accounts.getPrimaryBenefactor().getAddress(), + accounts.getSecondaryBenefactor().getAddress(), + senderC.getAddress(), + receiverAccount.getAddress())); + permissionedCluster.start(node); + + // ensure SenderC has got some ether available + node.execute(accountTransactions.createTransfer(senderC, 10)); + node.verify(senderC.balanceEquals(10)); + + // add accounts to onchain allowlist + node.execute(allowAccount(accounts.getPrimaryBenefactor())); + node.verify(accountIsAllowed(accounts.getPrimaryBenefactor())); + + node.execute(allowAccount(accounts.getSecondaryBenefactor())); + node.verify(accountIsAllowed(accounts.getSecondaryBenefactor())); + + node.execute(allowAccount(receiverAccount)); + node.verify(accountIsAllowed(receiverAccount)); + + // verify senderC is forbidden because it is not on Onchain allowlist + node.verify(accountIsForbidden(senderC)); + + // sender C should not be able to send Tx + verifyTransferForbidden(node, senderC, accounts.getSecondaryBenefactor()); + + // final check, other account should be able to send tx + node.execute( + accountTransactions.createTransfer(accounts.getPrimaryBenefactor(), receiverAccount, 5)); + node.verify(receiverAccount.balanceEquals(5)); + } + + private void verifyTransferForbidden( + final Node node, final Account sender, final Account beneficiary) { + final BigInteger nonce = node.execute(ethTransactions.getTransactionCount(sender.getAddress())); + final TransferTransaction transfer = + accountTransactions.createTransfer(sender, beneficiary, 1, nonce); + node.verify( + eth.expectEthSendRawTransactionException( + transfer.signedTransactionData(), + "Sender account not authorized to send transactions")); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountLocalConfigPermissioningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountLocalConfigPermissioningAcceptanceTest.java index a90bd0133ac..78a9fee0413 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountLocalConfigPermissioningAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountLocalConfigPermissioningAcceptanceTest.java @@ -78,7 +78,7 @@ private void verifyTransferForbidden(final Account sender, final Account benefic TransferTransaction transfer = accountTransactions.createTransfer(sender, beneficiary, 1, nonce); node.verify( - eth.sendRawTransactionExceptional( + eth.expectEthSendRawTransactionException( transfer.signedTransactionData(), "Sender account not authorized to send transactions")); } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountLocalConfigPermissioningImportAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountLocalConfigPermissioningImportAcceptanceTest.java index eacbb2abfd0..4415a03f807 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountLocalConfigPermissioningImportAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountLocalConfigPermissioningImportAcceptanceTest.java @@ -74,7 +74,7 @@ public void transactionFromDeniedAccountShouldNotBreakBlockImport() throws IOExc besu.createIbft2NodeWithLocalAccountPermissioning( "nodeC", GENESIS_FILE, allowList, newPermissionsFile); - waitForBlockHeight(bootnode, 5); + waitForBlockHeight(bootnode, 2); nodeA.verify(beneficiary.balanceEquals(0)); nodeA.execute(accountTransactions.createTransfer(sender, beneficiary, 1)); @@ -82,8 +82,8 @@ public void transactionFromDeniedAccountShouldNotBreakBlockImport() throws IOExc permissionedCluster.startNode(nodeC); - waitForBlockHeight(bootnode, 10); - waitForBlockHeight(nodeC, 10); + waitForBlockHeight(bootnode, 4); + waitForBlockHeight(nodeC, 4); } private void persistAllowList(final List allowList, final Path path) throws IOException { diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountSmartContractPermissioningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountSmartContractPermissioningAcceptanceTest.java index 183b91f38ad..6d9e74e04a6 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountSmartContractPermissioningAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountSmartContractPermissioningAcceptanceTest.java @@ -16,7 +16,9 @@ import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.account.TransferTransaction; +import java.math.BigInteger; import java.util.Collections; import org.junit.Before; @@ -60,7 +62,16 @@ public void forbiddenAccountCannotTransferValue() { node.execute(forbidAccount(allowedSender)); node.verify(accountIsForbidden(allowedSender)); - node.execute(accountTransactions.createTransfer(allowedSender, otherAccount, 5)); - node.verify(otherAccount.balanceDoesNotChange(0)); + verifyTransferForbidden(allowedSender, otherAccount); + } + + private void verifyTransferForbidden(final Account sender, final Account beneficiary) { + final BigInteger nonce = node.execute(ethTransactions.getTransactionCount(sender.getAddress())); + final TransferTransaction transfer = + accountTransactions.createTransfer(sender, beneficiary, 1, nonce); + node.verify( + eth.expectEthSendRawTransactionException( + transfer.signedTransactionData(), + "Sender account not authorized to send transactions")); } } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountSmartContractPermissioningAcceptanceTestBase.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountSmartContractPermissioningAcceptanceTestBase.java index 6918e6fa02b..7cad210dd74 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountSmartContractPermissioningAcceptanceTestBase.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AccountSmartContractPermissioningAcceptanceTestBase.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.tests.acceptance.permissioning; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AllowlistPersistorAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AllowlistPersistorAcceptanceTest.java index 93c2e235de9..5a563cc5264 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AllowlistPersistorAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AllowlistPersistorAcceptanceTest.java @@ -64,7 +64,7 @@ public void setUp() throws Exception { } @Test - public void manipulatedAccountsWhitelistIsPersisted() { + public void manipulatedAccountsAllowlistIsPersisted() { node.verify( perm.expectPermissioningAllowlistFileKeyValue( ALLOWLIST_TYPE.ACCOUNTS, tempFile, senderA.getAddress())); @@ -87,7 +87,7 @@ public void manipulatedAccountsWhitelistIsPersisted() { } @Test - public void manipulatedNodesWhitelistIsPersisted() { + public void manipulatedNodesAllowlistIsPersisted() { node.verify(perm.addNodesToAllowlist(ENODE_ONE, ENODE_TWO)); node.verify( perm.expectPermissioningAllowlistFileKeyValue( @@ -104,7 +104,7 @@ public void manipulatedNodesWhitelistIsPersisted() { } @Test - public void manipulatedNodesWhitelistWithHostnameShouldNotWorkWhenDnsDisabled() { + public void manipulatedNodesAllowlistWithHostnameShouldNotWorkWhenDnsDisabled() { Assertions.assertThatThrownBy(() -> node.verify(perm.addNodesToAllowlist(ENODE_FOURTH))) .isInstanceOf(RuntimeException.class) .hasMessageContaining("Request contains an invalid node"); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AllowlistWithDnsPersistorAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AllowlistWithDnsPersistorAcceptanceTest.java index dc51fc5d0f4..88c7e783777 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AllowlistWithDnsPersistorAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/AllowlistWithDnsPersistorAcceptanceTest.java @@ -14,12 +14,18 @@ */ package org.hyperledger.besu.tests.acceptance.permissioning; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.hyperledger.besu.ethereum.permissioning.AllowlistPersistor.ALLOWLIST_TYPE; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; +import org.hyperledger.besu.ethereum.p2p.peers.ImmutableEnodeDnsConfiguration; +import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; +import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.node.Node; +import java.net.InetAddress; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -30,12 +36,13 @@ public class AllowlistWithDnsPersistorAcceptanceTest extends AcceptanceTestBase { - private static final String ENODE_ONE = - "enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@localhost:4567"; - private static final String ENODE_TWO = - "enode://5f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.10:4567"; - private static final String ENODE_THREE = - "enode://4f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.11:4567"; + public static final String ENODE_PREFIX = + "enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@"; + public static final String PORT_SUFFIX = ":4567"; + + private String ENODE_LOCALHOST_DNS; + private String ENODE_LOCALHOST_IP; + private String ENODE_TWO_IP; private Node node; private Account senderA; @@ -43,8 +50,13 @@ public class AllowlistWithDnsPersistorAcceptanceTest extends AcceptanceTestBase @Before public void setUp() throws Exception { + ENODE_LOCALHOST_DNS = ENODE_PREFIX + InetAddress.getLocalHost().getHostName() + PORT_SUFFIX; + ENODE_LOCALHOST_IP = ENODE_PREFIX + "127.0.0.1" + PORT_SUFFIX; + ENODE_TWO_IP = + "enode://5f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.10:1234"; + senderA = accounts.getPrimaryBenefactor(); - tempFile = Files.createTempFile("test", "test"); + tempFile = Files.createTempFile("test", "perm-dns-test"); this.node = permissionedNodeBuilder @@ -60,20 +72,60 @@ public void setUp() throws Exception { } @Test - public void manipulatedNodesWhitelistWithHostnameShouldWorkWhenDnsEnabled() { + public void addingEnodeWithIp_andThenAddingSameEnodeWithHostname_shouldThrow() { - node.verify(perm.addNodesToAllowlist(ENODE_ONE, ENODE_TWO)); + node.verify(perm.addNodesToAllowlist(ENODE_LOCALHOST_IP)); node.verify( perm.expectPermissioningAllowlistFileKeyValue( - ALLOWLIST_TYPE.NODES, tempFile, ENODE_ONE, ENODE_TWO)); + ALLOWLIST_TYPE.NODES, tempFile, ENODE_LOCALHOST_DNS)); + + // expect an exception when adding using hostname, since this node is already added with IP + final Condition condition = perm.addNodesToAllowlist(ENODE_LOCALHOST_DNS); + assertThatThrownBy(() -> node.verify(condition)).isInstanceOf(RuntimeException.class); + } + + @Test + public void addingEnodeWithHostname_andThenAddingSameEnodeWithIp_shouldThrow() { - node.verify(perm.removeNodesFromAllowlist(ENODE_ONE)); + node.verify(perm.addNodesToAllowlist(ENODE_LOCALHOST_DNS)); node.verify( - perm.expectPermissioningAllowlistFileKeyValue(ALLOWLIST_TYPE.NODES, tempFile, ENODE_TWO)); + perm.expectPermissioningAllowlistFileKeyValue( + ALLOWLIST_TYPE.NODES, tempFile, ENODE_LOCALHOST_DNS)); + + // expect an exception when adding using IP, since this node is already added with hostname + final Condition condition = perm.addNodesToAllowlist(ENODE_LOCALHOST_IP); + assertThatThrownBy(() -> node.verify(condition)).isInstanceOf(RuntimeException.class); + } + + @Test + public void addingEnodeWithHostNameShouldWorkWhenDnsEnabled() { + + node.verify(perm.addNodesToAllowlist(ENODE_LOCALHOST_DNS)); + + // This should just work since there is no IP address to resolve to a host name. + // With DNS enabled, the ENODE with the DNS hostname in it should remain as is. + node.verify( + perm.expectPermissioningAllowlistFileKeyValue( + ALLOWLIST_TYPE.NODES, tempFile, ENODE_LOCALHOST_DNS)); + } + + @Test + public void manipulatedNodesAllowlistWithHostnameShouldWorkWhenDnsEnabled() { + + node.verify(perm.addNodesToAllowlist(ENODE_LOCALHOST_DNS, ENODE_TWO_IP)); + // use DNS config to resolve the Enode with IP. It either resolves to a hostname or remain as is + final EnodeURL enodeURL0 = + EnodeURLImpl.fromString( + ENODE_TWO_IP, + ImmutableEnodeDnsConfiguration.builder().dnsEnabled(true).updateEnabled(true).build()); + final String enode2ResolvedToDns = enodeURL0.toString(); + node.verify( + perm.expectPermissioningAllowlistFileKeyValue( + ALLOWLIST_TYPE.NODES, tempFile, ENODE_LOCALHOST_DNS, enode2ResolvedToDns)); - node.verify(perm.addNodesToAllowlist(ENODE_ONE, ENODE_THREE)); + node.verify(perm.removeNodesFromAllowlist(ENODE_LOCALHOST_DNS)); node.verify( perm.expectPermissioningAllowlistFileKeyValue( - ALLOWLIST_TYPE.NODES, tempFile, ENODE_TWO, ENODE_ONE, ENODE_THREE)); + ALLOWLIST_TYPE.NODES, tempFile, enode2ResolvedToDns)); } } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeLocalAndOnChainPermissioningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeLocalAndOnChainPermissioningAcceptanceTest.java deleted file mode 100644 index 1247c5b5149..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeLocalAndOnChainPermissioningAcceptanceTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.permissioning; - -import org.hyperledger.besu.tests.acceptance.dsl.node.Node; - -import org.junit.Before; -import org.junit.Test; - -public class NodeLocalAndOnChainPermissioningAcceptanceTest - extends NodeSmartContractPermissioningAcceptanceTestBase { - - private Node bootnode; - private Node permissionedNode; - private Node allowedNode; - private Node forbiddenNode; - - @Before - public void setUp() { - bootnode = bootnode("bootnode"); - forbiddenNode = node("forbidden-node"); - allowedNode = node("allowed-node"); - - permissionedCluster.start(bootnode, allowedNode, forbiddenNode); - } - - @Test - public void testNodeCannotConnectWhenAllowedOnChainButNotLocally() { - - // add permissioned node after cluster start because we need enode URI for local config - permissionedNode = permissionedNode("permissioned-node", bootnode, allowedNode); - permissionedCluster.addNode(permissionedNode); - - // update OnChain smart contract with allowed nodes - permissionedNode.execute(allowNode(bootnode)); - permissionedNode.verify(nodeIsAllowed(bootnode)); - - permissionedNode.execute(allowNode(allowedNode)); - permissionedNode.verify(nodeIsAllowed(allowedNode)); - - permissionedNode.execute(allowNode(permissionedNode)); - permissionedNode.verify(nodeIsAllowed(permissionedNode)); - - permissionedNode.execute(allowNode(forbiddenNode)); - permissionedNode.verify(nodeIsAllowed(forbiddenNode)); - - permissionedNodeShouldDiscoverOnlyAllowedNodes(); - } - - @Test - public void testNodeCannotConnectWhenAllowedLocallyButNotOnChain() { - // onchain allowlist: A, B - // local allowlist: A, B, C - - // add permissioned node after cluster start because we need enode URI for local config - permissionedNode = permissionedNode("permissioned-node", bootnode, allowedNode, forbiddenNode); - permissionedCluster.addNode(permissionedNode); - - // update OnChain smart contract with allowed nodes - permissionedNode.execute(allowNode(bootnode)); - permissionedNode.verify(nodeIsAllowed(bootnode)); - - permissionedNode.execute(allowNode(allowedNode)); - permissionedNode.verify(nodeIsAllowed(allowedNode)); - - permissionedNode.execute(allowNode(permissionedNode)); - permissionedNode.verify(nodeIsAllowed(permissionedNode)); - - permissionedNodeShouldDiscoverOnlyAllowedNodes(); - } - - @Test - public void testNodesCanConnectWhenAllowedBothOnChainAndLocally() { - // add permissioned node after cluster start because we need enode URI for local config - permissionedNode = permissionedNode("permissioned-node", bootnode, allowedNode, forbiddenNode); - permissionedCluster.addNode(permissionedNode); - - // update OnChain smart contract with allowed nodes - permissionedNode.execute(allowNode(bootnode)); - permissionedNode.verify(nodeIsAllowed(bootnode)); - - permissionedNode.execute(allowNode(allowedNode)); - permissionedNode.verify(nodeIsAllowed(allowedNode)); - - permissionedNode.execute(allowNode(permissionedNode)); - permissionedNode.verify(nodeIsAllowed(permissionedNode)); - - permissionedNode.execute(allowNode(forbiddenNode)); - permissionedNode.verify(nodeIsAllowed(forbiddenNode)); - - bootnode.verify(net.awaitPeerCount(3)); - allowedNode.verify(net.awaitPeerCount(3)); - forbiddenNode.verify(net.awaitPeerCount(3)); - permissionedNode.verify(net.awaitPeerCount(3)); - } - - private void permissionedNodeShouldDiscoverOnlyAllowedNodes() { - bootnode.verify(net.awaitPeerCount(3)); - allowedNode.verify(net.awaitPeerCount(3)); - forbiddenNode.verify(net.awaitPeerCount(2)); - permissionedNode.verify(net.awaitPeerCount(2)); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeLocalAndOnchainPermissioningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeLocalAndOnchainPermissioningAcceptanceTest.java new file mode 100644 index 00000000000..6a7b8e9b35f --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeLocalAndOnchainPermissioningAcceptanceTest.java @@ -0,0 +1,115 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.permissioning; + +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; + +import org.junit.Before; +import org.junit.Test; + +public class NodeLocalAndOnchainPermissioningAcceptanceTest + extends NodeSmartContractPermissioningAcceptanceTestBase { + + private Node bootnode; + private Node permissionedNode; + private Node allowedNode; + private Node forbiddenNode; + + @Before + public void setUp() { + bootnode = bootnode("bootnode"); + forbiddenNode = node("forbidden-node"); + allowedNode = node("allowed-node"); + + permissionedCluster.start(bootnode, allowedNode, forbiddenNode); + } + + @Test + public void testNodeCannotConnectWhenAllowedOnchainButNotLocally() { + + // add permissioned node after cluster start because we need enode URI for local config + permissionedNode = permissionedNode("permissioned-node", bootnode, allowedNode); + permissionedCluster.addNode(permissionedNode); + + // update Onchain smart contract with allowed nodes + permissionedNode.execute(allowNode(bootnode)); + permissionedNode.verify(nodeIsAllowed(bootnode)); + + permissionedNode.execute(allowNode(allowedNode)); + permissionedNode.verify(nodeIsAllowed(allowedNode)); + + permissionedNode.execute(allowNode(permissionedNode)); + permissionedNode.verify(nodeIsAllowed(permissionedNode)); + + permissionedNode.execute(allowNode(forbiddenNode)); + permissionedNode.verify(nodeIsAllowed(forbiddenNode)); + + permissionedNodeShouldDiscoverOnlyAllowedNodes(); + } + + @Test + public void testNodeCannotConnectWhenAllowedLocallyButNotOnchain() { + // onchain allowlist: A, B + // local allowlist: A, B, C + + // add permissioned node after cluster start because we need enode URI for local config + permissionedNode = permissionedNode("permissioned-node", bootnode, allowedNode, forbiddenNode); + permissionedCluster.addNode(permissionedNode); + + // update Onchain smart contract with allowed nodes + permissionedNode.execute(allowNode(bootnode)); + permissionedNode.verify(nodeIsAllowed(bootnode)); + + permissionedNode.execute(allowNode(allowedNode)); + permissionedNode.verify(nodeIsAllowed(allowedNode)); + + permissionedNode.execute(allowNode(permissionedNode)); + permissionedNode.verify(nodeIsAllowed(permissionedNode)); + + permissionedNodeShouldDiscoverOnlyAllowedNodes(); + } + + @Test + public void testNodesCanConnectWhenAllowedBothOnchainAndLocally() { + // add permissioned node after cluster start because we need enode URI for local config + permissionedNode = permissionedNode("permissioned-node", bootnode, allowedNode, forbiddenNode); + permissionedCluster.addNode(permissionedNode); + + // update Onchain smart contract with allowed nodes + permissionedNode.execute(allowNode(bootnode)); + permissionedNode.verify(nodeIsAllowed(bootnode)); + + permissionedNode.execute(allowNode(allowedNode)); + permissionedNode.verify(nodeIsAllowed(allowedNode)); + + permissionedNode.execute(allowNode(permissionedNode)); + permissionedNode.verify(nodeIsAllowed(permissionedNode)); + + permissionedNode.execute(allowNode(forbiddenNode)); + permissionedNode.verify(nodeIsAllowed(forbiddenNode)); + + bootnode.verify(net.awaitPeerCount(3)); + allowedNode.verify(net.awaitPeerCount(3)); + forbiddenNode.verify(net.awaitPeerCount(3)); + permissionedNode.verify(net.awaitPeerCount(3)); + } + + private void permissionedNodeShouldDiscoverOnlyAllowedNodes() { + bootnode.verify(net.awaitPeerCount(3)); + allowedNode.verify(net.awaitPeerCount(3)); + forbiddenNode.verify(net.awaitPeerCount(2)); + permissionedNode.verify(net.awaitPeerCount(2)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningAcceptanceTest.java index 3eb746b7ae6..c5fbb693043 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningAcceptanceTest.java @@ -46,6 +46,9 @@ public void setUp() { permissionedNode.execute(allowNode(permissionedNode)); permissionedNode.verify(nodeIsAllowed(permissionedNode)); + + permissionedNode.verify(admin.addPeer(bootnode)); + permissionedNode.verify(admin.addPeer(allowedNode)); } @Test @@ -58,38 +61,18 @@ public void permissionedNodeShouldPeerOnlyWithAllowedNodes() { @Test public void permissionedNodeShouldDisconnectFromNodeNotPermittedAnymore() { - permissionedNode.verify(admin.addPeer(bootnode)); - permissionedNode.verify(admin.addPeer(allowedNode)); - permissionedNode.verify(net.awaitPeerCount(2)); - permissionedNode.execute(forbidNode(allowedNode)); permissionedNode.verify(connectionIsForbidden(permissionedNode, allowedNode)); permissionedNode.verify(net.awaitPeerCount(1)); } - @Test - public void permissionedNodeShouldConnectToNewlyPermittedNode() { - permissionedNode.verify(admin.addPeer(bootnode)); - permissionedNode.verify(admin.addPeer(allowedNode)); - permissionedNode.verify(net.awaitPeerCount(2)); - - permissionedNode.execute(allowNode(forbiddenNode)); - permissionedNode.verify(connectionIsAllowed(permissionedNode, forbiddenNode)); - permissionedNode.verify(admin.addPeer(forbiddenNode)); - - permissionedNode.verify(net.awaitPeerCount(3)); - } - @Test public void permissioningUpdatesPropagateThroughNetwork() { - permissionedNode.verify(admin.addPeer(bootnode)); - permissionedNode.verify(admin.addPeer(allowedNode)); - permissionedNode.verify(net.awaitPeerCount(2)); - - // permissioning changes in peer should propagate to permissioned node + // connection to newly permitted node is allowed allowedNode.execute(allowNode(forbiddenNode)); allowedNode.verify(connectionIsAllowed(permissionedNode, forbiddenNode)); + // permissioning changes in peer should propagate to permissioned node permissionedNode.verify(connectionIsAllowed(permissionedNode, forbiddenNode)); permissionedNode.verify(admin.addPeer(forbiddenNode)); @@ -97,7 +80,7 @@ public void permissioningUpdatesPropagateThroughNetwork() { } @Test - public void onChainPermissioningAllowlistShouldPersistAcrossRestarts() { + public void onchainPermissioningAllowlistShouldPersistAcrossRestarts() { permissionedCluster.stop(); permissionedCluster.start(bootnode, forbiddenNode, allowedNode, permissionedNode); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningAcceptanceTestBase.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningAcceptanceTestBase.java index c13fd0c9096..094dc08862b 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningAcceptanceTestBase.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningAcceptanceTestBase.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.tests.acceptance.permissioning; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.condition.perm.NodeSmartContractPermissioningConditions; diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningIbft2StallAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningIbft2StallAcceptanceTest.java new file mode 100644 index 00000000000..fc64ee13862 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningIbft2StallAcceptanceTest.java @@ -0,0 +1,78 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.permissioning; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; +import org.hyperledger.besu.ethereum.permissioning.SmartContractPermissioningConfiguration; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import java.io.IOException; +import java.util.Optional; + +import org.junit.Test; + +public class NodeSmartContractPermissioningIbft2StallAcceptanceTest + extends NodeSmartContractPermissioningAcceptanceTestBase { + + private static final String GENESIS_FILE = + "/permissioning/simple_permissioning_ibft_genesis.json"; + + @Test + public void restartedIbftClusterShouldNotStall() throws IOException { + final BesuNode bootnode = besu.createIbft2NonValidatorBootnode("bootnode", GENESIS_FILE); + final BesuNode nodeA = besu.createIbft2Node("nodeA", GENESIS_FILE); + final BesuNode nodeB = besu.createIbft2Node("nodeB", GENESIS_FILE); + + permissionedCluster.start(bootnode, nodeA, nodeB); + + // make sure we are producing blocks before sending any transactions + waitForBlockHeight(bootnode, 1); + + // allow nodes in onchain smart contract + nodeA.execute(allowNode(bootnode)); + nodeA.execute(allowNode(nodeA)); + nodeA.execute(allowNode(nodeB)); + + // verify the nodes are allowed + nodeA.verify(nodeIsAllowed(bootnode)); + nodeA.verify(nodeIsAllowed(nodeA)); + nodeA.verify(nodeIsAllowed(nodeB)); + + permissionedCluster.stop(); + + // Create permissioning config + final SmartContractPermissioningConfiguration smartContractPermissioningConfiguration = + new SmartContractPermissioningConfiguration(); + smartContractPermissioningConfiguration.setSmartContractNodeAllowlistEnabled(true); + smartContractPermissioningConfiguration.setNodeSmartContractAddress( + Address.fromHexString(CONTRACT_ADDRESS)); + final PermissioningConfiguration permissioningConfiguration = + new PermissioningConfiguration( + Optional.empty(), + Optional.of(smartContractPermissioningConfiguration), + Optional.empty()); + + // Set permissioning configurations on nodes + bootnode.setPermissioningConfiguration(permissioningConfiguration); + nodeA.setPermissioningConfiguration(permissioningConfiguration); + nodeB.setPermissioningConfiguration(permissioningConfiguration); + + permissionedCluster.start(bootnode, nodeA, nodeB); + + // Verify blockchain is progressing + permissionedCluster.verify(blockchain.reachesHeight(bootnode, 1, 120)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningIbftStallAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningIbftStallAcceptanceTest.java deleted file mode 100644 index 851ab406676..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningIbftStallAcceptanceTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.permissioning; - -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; -import org.hyperledger.besu.ethereum.permissioning.SmartContractPermissioningConfiguration; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; - -import java.io.IOException; -import java.util.Optional; - -import org.junit.Test; - -public class NodeSmartContractPermissioningIbftStallAcceptanceTest - extends NodeSmartContractPermissioningAcceptanceTestBase { - - private static final String GENESIS_FILE = - "/permissioning/simple_permissioning_ibft_genesis.json"; - - @Test - public void restartedIbftClusterShouldNotStall() throws IOException { - final BesuNode bootnode = besu.createIbft2NonValidatorBootnode("bootnode", GENESIS_FILE); - final BesuNode nodeA = besu.createIbft2Node("nodeA", GENESIS_FILE); - final BesuNode nodeB = besu.createIbft2Node("nodeB", GENESIS_FILE); - - permissionedCluster.start(bootnode, nodeA, nodeB); - - // make sure we are producing blocks before sending any transactions - waitForBlockHeight(bootnode, 1); - - // allow nodes in onchain smart contract - nodeA.execute(allowNode(bootnode)); - nodeA.execute(allowNode(nodeA)); - nodeA.execute(allowNode(nodeB)); - - // verify the nodes are allowed - nodeA.verify(nodeIsAllowed(bootnode)); - nodeA.verify(nodeIsAllowed(nodeA)); - nodeA.verify(nodeIsAllowed(nodeB)); - - permissionedCluster.stop(); - - // Create permissioning config - final SmartContractPermissioningConfiguration smartContractPermissioningConfiguration = - new SmartContractPermissioningConfiguration(); - smartContractPermissioningConfiguration.setSmartContractNodeAllowlistEnabled(true); - smartContractPermissioningConfiguration.setNodeSmartContractAddress( - Address.fromHexString(CONTRACT_ADDRESS)); - final PermissioningConfiguration permissioningConfiguration = - new PermissioningConfiguration( - Optional.empty(), - Optional.of(smartContractPermissioningConfiguration), - Optional.empty()); - - // Set permissioning configurations on nodes - bootnode.setPermissioningConfiguration(permissioningConfiguration); - nodeA.setPermissioningConfiguration(permissioningConfiguration); - nodeB.setPermissioningConfiguration(permissioningConfiguration); - - permissionedCluster.start(bootnode, nodeA, nodeB); - - // Verify blockchain is progressing - permissionedCluster.verify(blockchain.reachesHeight(bootnode, 1, 120)); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningOutOfSyncAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningOutOfSyncAcceptanceTest.java index dab55d9f32c..2f8adf43867 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningOutOfSyncAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningOutOfSyncAcceptanceTest.java @@ -33,7 +33,7 @@ public void setUp() throws InterruptedException { permissionedCluster.start(bootnode, permissionedNodeA); - // update onchain smart contract to whitelist nodes + // update onchain smart contract to allowlist nodes permissionedNodeA.execute(allowNode(bootnode)); permissionedNodeA.verify(nodeIsAllowed(bootnode)); permissionedNodeA.execute(allowNode(permissionedNodeA)); @@ -43,7 +43,7 @@ public void setUp() throws InterruptedException { @Test public void addNodeToClusterAndVerifyNonBootNodePeerConnectionWorksAfterSync() { - final long blockchainHeight = 50L; + final long blockchainHeight = 25L; waitForBlockHeight(permissionedNodeA, blockchainHeight); // Add Node B diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningV2AcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningV2AcceptanceTest.java index ffb4e48aec2..72aab9cb7e4 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningV2AcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningV2AcceptanceTest.java @@ -97,7 +97,7 @@ public void permissioningUpdatesPropagateThroughNetwork() { } @Test - public void onChainPermissioningAllowlistShouldPersistAcrossRestarts() { + public void onchainPermissioningAllowlistShouldPersistAcrossRestarts() { permissionedCluster.stop(); permissionedCluster.start(bootnode, forbiddenNode, allowedNode, permissionedNode); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningV2AcceptanceTestBase.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningV2AcceptanceTestBase.java index 61dd2215557..2cfbbf93deb 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningV2AcceptanceTestBase.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningV2AcceptanceTestBase.java @@ -14,7 +14,8 @@ */ package org.hyperledger.besu.tests.acceptance.permissioning; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.condition.perm.NodeSmartContractPermissioningV2Conditions; @@ -110,15 +111,33 @@ protected Transaction allowNode(final Node node) { return smartContractNodePermissioningV2.allowNode(CONTRACT_ADDRESS, node); } + protected Transaction allowNode(final EnodeURL enodeURL) { + return smartContractNodePermissioningV2.allowNode(CONTRACT_ADDRESS, enodeURL); + } + protected Transaction forbidNode(final Node node) { return smartContractNodePermissioningV2.forbidNode(CONTRACT_ADDRESS, node); } + protected Transaction forbidNode(final EnodeURL enodeURL) { + return smartContractNodePermissioningV2.forbidNode(CONTRACT_ADDRESS, enodeURL); + } + protected Condition connectionIsForbidden(final Node node) { return nodeSmartContractPermissioningConditionsV2.connectionIsForbidden(CONTRACT_ADDRESS, node); } + protected Condition connectionIsForbidden(final EnodeURL enodeURL) { + return nodeSmartContractPermissioningConditionsV2.connectionIsForbidden( + CONTRACT_ADDRESS, enodeURL); + } + protected Condition connectionIsAllowed(final Node node) { return nodeSmartContractPermissioningConditionsV2.connectionIsAllowed(CONTRACT_ADDRESS, node); } + + protected Condition connectionIsAllowed(final EnodeURL enodeURL) { + return nodeSmartContractPermissioningConditionsV2.connectionIsAllowed( + CONTRACT_ADDRESS, enodeURL); + } } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningV2DNSAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningV2DNSAcceptanceTest.java new file mode 100644 index 00000000000..b2ed27d7c5d --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodeSmartContractPermissioningV2DNSAcceptanceTest.java @@ -0,0 +1,111 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.permissioning; + +import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; +import org.hyperledger.besu.ethereum.p2p.peers.ImmutableEnodeDnsConfiguration; +import org.hyperledger.besu.plugin.data.EnodeURL; +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; +import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +import org.assertj.core.api.Assertions; +import org.junit.Before; +import org.junit.Test; + +public class NodeSmartContractPermissioningV2DNSAcceptanceTest + extends NodeSmartContractPermissioningV2AcceptanceTestBase { + + private Node bootnode; + private Node permissionedNode; + private Node allowedNode; + private Node forbiddenNode; + + final ImmutableEnodeDnsConfiguration enodeDnsConfiguration = + ImmutableEnodeDnsConfiguration.builder().dnsEnabled(true).updateEnabled(true).build(); + + @Before + public void setUp() { + bootnode = bootnode("bootnode"); + forbiddenNode = node("forbidden-node"); + allowedNode = node("allowed-node"); + permissionedNode = permissionedNode("permissioned-node"); + + permissionedCluster.start(bootnode, forbiddenNode, allowedNode, permissionedNode); + + // updating permissioning smart contract with allowed nodes + + permissionedNode.execute(allowNode(bootnode)); + permissionedNode.verify(connectionIsAllowed(bootnode)); + + permissionedNode.execute(allowNode(allowedNode)); + permissionedNode.verify(connectionIsAllowed(allowedNode)); + + permissionedNode.execute(allowNode(permissionedNode)); + permissionedNode.verify(connectionIsAllowed(permissionedNode)); + + // Verify initial configuration + bootnode.verify(net.awaitPeerCount(3)); + allowedNode.verify(net.awaitPeerCount(3)); + forbiddenNode.verify(net.awaitPeerCount(2)); + permissionedNode.verify(net.awaitPeerCount(2)); + } + + @Test + public void permissionedNodeShouldAddDnsRuleAndAllowNode() throws UnknownHostException { + final EnodeURL forbiddenEnodeURL = getForbiddenEnodeURL(); + Assertions.assertThat(forbiddenEnodeURL.toURI().getHost()).isEqualTo("127.0.0.1"); + final EnodeURL forbiddenDnsEnodeURL = buildDnsEnodeUrl(forbiddenEnodeURL); + Assertions.assertThat(forbiddenDnsEnodeURL.toURI().getHost()) + .isEqualTo(InetAddress.getLocalHost().getHostName()); + + permissionedNode.verify(connectionIsForbidden(forbiddenNode)); + permissionedNode.verify(connectionIsForbidden(forbiddenDnsEnodeURL)); + permissionedNode.execute(allowNode(forbiddenDnsEnodeURL)); + permissionedNode.verify(connectionIsAllowed(forbiddenDnsEnodeURL)); + permissionedNode.execute(forbidNode(forbiddenEnodeURL)); + } + + @Test + public void permissionedNodeShouldAddDNSRuleAndConnectToNewPeer() throws UnknownHostException { + final EnodeURL forbiddenEnodeURL = getForbiddenEnodeURL(); + Assertions.assertThat(forbiddenEnodeURL.toURI().getHost()).isEqualTo("127.0.0.1"); + final EnodeURL forbiddenDnsEnodeURL = buildDnsEnodeUrl(forbiddenEnodeURL); + Assertions.assertThat(forbiddenDnsEnodeURL.toURI().getHost()) + .isEqualTo(InetAddress.getLocalHost().getHostName()); + + permissionedNode.verify(net.awaitPeerCount(2)); + permissionedNode.verify(connectionIsForbidden(forbiddenNode)); + permissionedNode.verify(connectionIsForbidden(forbiddenDnsEnodeURL)); + permissionedNode.execute(allowNode(forbiddenDnsEnodeURL)); + permissionedNode.verify(connectionIsAllowed(forbiddenDnsEnodeURL)); + permissionedNode.verify(admin.addPeer(forbiddenNode)); + permissionedNode.verify(net.awaitPeerCount(3)); + permissionedNode.execute(forbidNode(forbiddenEnodeURL)); + } + + private EnodeURL getForbiddenEnodeURL() { + return EnodeURLImpl.fromURI(((RunnableNode) forbiddenNode).enodeUrl()); + } + + private EnodeURL buildDnsEnodeUrl(final EnodeURL forbiddenEnodeURL) { + return EnodeURLImpl.builder() + .configureFromEnode(forbiddenEnodeURL) + .ipAddress("localhost", enodeDnsConfiguration) + .build(); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodesSmartContractPermissioningStaticNodesAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodesSmartContractPermissioningStaticNodesAcceptanceTest.java index a6da4a02310..57253d474c2 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodesSmartContractPermissioningStaticNodesAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/permissioning/NodesSmartContractPermissioningStaticNodesAcceptanceTest.java @@ -22,8 +22,8 @@ import java.net.URI; import java.util.Arrays; import java.util.List; +import javax.annotation.Nonnull; -import org.jetbrains.annotations.NotNull; import org.junit.Before; import org.junit.Test; @@ -42,7 +42,7 @@ public void setUp() { @Test public void onlyTrustStaticNodesWhileOutOfSync() { // wait for some blocks so the permissioned node has some syncing to do - waitForBlockHeight(miner, 50); + waitForBlockHeight(miner, 25); stopMining(miner); // start permissioned node with miner node in the static nodes list @@ -51,7 +51,7 @@ public void onlyTrustStaticNodesWhileOutOfSync() { // as soon as we start the node should connect to static nodes permissionedNode.verify(net.awaitPeerCount(1)); - waitForBlockHeight(permissionedNode, 50); + waitForBlockHeight(permissionedNode, 25); // after syncing up with the network the node won't trust static nodes anymore permissionedNode.verify(net.awaitPeerCount(0)); @@ -72,7 +72,7 @@ private Node permissionedNodeWithStaticNodes(final List staticNodes) { .build(); } - @NotNull + @Nonnull private List mapNodesToEnodeURLs(final List staticNodes) { return staticNodes.stream() .map(node -> (RunnableNode) node) diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BadCLIOptionsPluginTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BadCLIOptionsPluginTest.java index 2d29d05e0ef..02299f4fdb8 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BadCLIOptionsPluginTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BadCLIOptionsPluginTest.java @@ -28,21 +28,29 @@ import java.util.stream.Stream; import org.awaitility.Awaitility; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; public class BadCLIOptionsPluginTest extends AcceptanceTestBase { private BesuNode node; - @Before + @BeforeEach public void setUp() throws Exception { + System.setProperty("TEST_BAD_CLI", "true"); + node = besu.createPluginsNode( "node1", Collections.singletonList("testPlugins"), Collections.emptyList()); cluster.start(node); } + @AfterEach + public void tearDown() { + System.setProperty("TEST_BAD_CLI", "false"); + } + @Test public void shouldNotRegister() { final Path registrationFile = node.homeDirectory().resolve("plugins/badCLIOptions.init"); @@ -60,7 +68,7 @@ public void shouldNotStart() { } @Test - @Ignore("No way to do a graceful shutdown of Besu at the moment.") + @Disabled("No way to do a graceful shutdown of Besu at the moment.") public void shouldNotStop() { cluster.stopNode(node); waitForFile(node.homeDirectory().resolve("plugins/pluginLifecycle.stopped")); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BesuEventsPluginTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BesuEventsPluginTest.java index 09deffb551b..4906193362c 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BesuEventsPluginTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BesuEventsPluginTest.java @@ -25,14 +25,14 @@ import java.util.stream.Stream; import org.awaitility.Awaitility; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class BesuEventsPluginTest extends AcceptanceTestBase { private BesuNode pluginNode; private BesuNode minerNode; - @Before + @BeforeEach public void setUp() throws Exception { minerNode = besu.createMinerNode("minerNode"); pluginNode = @@ -42,7 +42,7 @@ public void setUp() throws Exception { } @Test - public void blockIsAnnounded() { + public void blockIsAnnounced() { waitForFile(pluginNode.homeDirectory().resolve("plugins/newBlock.2")); } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/PermissioningPluginTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/PermissioningPluginTest.java new file mode 100644 index 00000000000..af6a3f7a16f --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/PermissioningPluginTest.java @@ -0,0 +1,99 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.tests.acceptance.plugins; + +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.account.Account; +import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeConfigurationBuilder; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.account.TransferTransaction; + +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class PermissioningPluginTest extends AcceptanceTestBase { + private BesuNode minerNode; + + private BesuNode aliceNode; + private BesuNode bobNode; + private BesuNode charlieNode; + + @BeforeEach + public void setUp() throws Exception { + final BesuNodeConfigurationBuilder builder = + new BesuNodeConfigurationBuilder() + .miningEnabled(false) + .plugins(List.of("testPlugins")) + .extraCLIOptions(List.of("--plugin-permissioning-test-enabled=true")) + .jsonRpcEnabled() + .jsonRpcTxPool() + .jsonRpcAdmin(); + + minerNode = besu.create(builder.name("miner").build()); + + aliceNode = besu.create(builder.name("alice").keyFilePath("key").build()); + + bobNode = besu.create(builder.name("bob").keyFilePath("key1").build()); + + charlieNode = besu.create(builder.name("charlie").keyFilePath("key2").build()); + + cluster.start(minerNode, charlieNode); + + cluster.startNode(aliceNode); + aliceNode.awaitPeerDiscovery(net.awaitPeerCount(2)); + + cluster.startNode(bobNode); + bobNode.awaitPeerDiscovery(net.awaitPeerCount(2)); + } + + @Test + public void blockedConnectionNodeCanOnlyConnectToTransactionNode() { + minerNode.verify(admin.hasPeer(aliceNode)); + minerNode.verify(admin.hasPeer(bobNode)); + minerNode.verify(admin.hasPeer(charlieNode)); + + aliceNode.verify(admin.doesNotHavePeer(bobNode)); + aliceNode.verify(admin.hasPeer(minerNode)); + aliceNode.verify(admin.hasPeer(charlieNode)); + + bobNode.verify(admin.hasPeer(minerNode)); + bobNode.verify(admin.doesNotHavePeer(aliceNode)); + bobNode.verify(admin.hasPeer(charlieNode)); + + charlieNode.verify(admin.hasPeer(minerNode)); + charlieNode.verify(admin.hasPeer(aliceNode)); + charlieNode.verify(admin.hasPeer(bobNode)); + } + + @Test + public void transactionsAreNotSendToBlockPendingTransactionsNode() { + final Account account = accounts.createAccount("account-one"); + final Amount balance = Amount.ether(20); + + final TransferTransaction tx = accountTransactions.createTransfer(account, balance); + + final Hash txHash = aliceNode.execute(tx); + + aliceNode.verify(txPoolConditions.inTransactionPool(txHash)); + bobNode.verify(txPoolConditions.inTransactionPool(txHash)); + charlieNode.verify(txPoolConditions.notInTransactionPool(txHash)); + minerNode.verify(txPoolConditions.inTransactionPool(txHash)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/PicoCLIOptionsPluginTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/PicoCLIOptionsPluginTest.java index d1a1154de69..b3a7a1ed556 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/PicoCLIOptionsPluginTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/PicoCLIOptionsPluginTest.java @@ -28,9 +28,9 @@ import java.util.stream.Stream; import org.awaitility.Awaitility; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; public class PicoCLIOptionsPluginTest extends AcceptanceTestBase { private BesuNode node; @@ -38,7 +38,7 @@ public class PicoCLIOptionsPluginTest extends AcceptanceTestBase { // context: https://en.wikipedia.org/wiki/The_Magic_Words_are_Squeamish_Ossifrage private static final String MAGIC_WORDS = "Squemish Ossifrage"; - @Before + @BeforeEach public void setUp() throws Exception { node = besu.createPluginsNode( @@ -70,7 +70,7 @@ public void shouldStart() throws IOException { } @Test - @Ignore("No way to do a graceful shutdown of Besu at the moment.") + @Disabled("No way to do a graceful shutdown of Besu at the moment.") public void shouldStop() { cluster.stopNode(node); waitForFile(node.homeDirectory().resolve("plugins/pluginLifecycle.stopped")); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/RpcEndpointServicePluginTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/RpcEndpointServicePluginTest.java new file mode 100644 index 00000000000..09da91663af --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/RpcEndpointServicePluginTest.java @@ -0,0 +1,117 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.plugins; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.config.JsonUtil; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class RpcEndpointServicePluginTest extends AcceptanceTestBase { + + private BesuNode node; + + private OkHttpClient client; + protected static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); + + @BeforeEach + public void setUp() throws Exception { + node = besu.createPluginsNode("node1", List.of("testPlugins"), List.of("--rpc-http-api=TESTS")); + cluster.start(node); + client = new OkHttpClient(); + } + + @Test + public void canUseRpcToSetValue() throws IOException { + String setValue = "secondCall"; + + ObjectNode resultJson = callTestMethod("tests_getValue", List.of()); + assertThat(resultJson.get("result").asText()).isEqualTo("InitialValue"); + + resultJson = callTestMethod("tests_setValue", List.of(setValue)); + assertThat(resultJson.get("result").asText()).isEqualTo(setValue); + + resultJson = callTestMethod("tests_getValue", List.of("ignored")); + assertThat(resultJson.get("result").asText()).isEqualTo(setValue); + } + + @Test + public void canCheckArgumentInsideSetValue() throws IOException { + ObjectNode resultJson = callTestMethod("tests_setValue", List.of("one", "two")); + assertThat(resultJson.get("error").get("message").asText()).isEqualTo("Internal error"); + } + + @Test + public void exceptionsInPluginMethodReturnError() throws IOException { + ObjectNode resultJson = callTestMethod("tests_throwException", List.of()); + assertThat(resultJson.get("error").get("message").asText()).isEqualTo("Internal error"); + } + + @Test + public void onlyEnabledMethodsReturn() throws IOException { + ObjectNode resultJson = callTestMethod("notEnabled_getValue", List.of()); + assertThat(resultJson.get("error").get("message").asText()).isEqualTo("Method not found"); + } + + @Test + public void mixedTypeArraysAreStringified() throws IOException { + ObjectNode resultJson = callTestMethod("tests_replaceValueList", List.of()); + assertThat(resultJson.get("result")).isEmpty(); + + resultJson = callTestMethod("tests_replaceValueList", List.of("One", 2, true)); + JsonNode result = resultJson.get("result"); + + assertThat(result.get(0).asText()).isEqualTo("One"); + assertThat(result.get(1).asText()).isEqualTo("2"); + assertThat(result.get(2).asText()).isEqualTo("true"); + } + + private ObjectNode callTestMethod(final String method, final List params) + throws IOException { + String format = + String.format( + "{\"jsonrpc\":\"2.0\",\"method\":\"%s\",\"params\":[%s],\"id\":42}", + method, + params.stream().map(value -> "\"" + value + "\"").collect(Collectors.joining(","))); + + RequestBody body = RequestBody.create(format, JSON); + + final String resultString = + client + .newCall( + new Request.Builder() + .post(body) + .url("http://" + node.getHostName() + ":" + node.getJsonRpcPort().get() + "/") + .build()) + .execute() + .body() + .string(); + return JsonUtil.objectNodeFromString(resultString); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/BftPrivacyClusterAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/BftPrivacyClusterAcceptanceTest.java new file mode 100644 index 00000000000..2baf1d1f5ce --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/BftPrivacyClusterAcceptanceTest.java @@ -0,0 +1,315 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.bft.ConsensusType; +import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.testcontainers.containers.Network; +import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; +import org.web3j.utils.Restriction; + +@RunWith(Parameterized.class) +public class BftPrivacyClusterAcceptanceTest extends PrivacyAcceptanceTestBase { + private final BftPrivacyType bftPrivacyType; + + public static class BftPrivacyType { + private final EnclaveType enclaveType; + private final EnclaveEncryptorType enclaveEncryptorType; + private final ConsensusType consensusType; + private final Restriction restriction; + + public BftPrivacyType( + final EnclaveType enclaveType, + final EnclaveEncryptorType enclaveEncryptorType, + final ConsensusType consensusType, + final Restriction restriction) { + this.enclaveType = enclaveType; + this.enclaveEncryptorType = enclaveEncryptorType; + this.consensusType = consensusType; + this.restriction = restriction; + } + + @Override + public String toString() { + return String.join( + ",", + enclaveType.toString(), + enclaveEncryptorType.toString(), + consensusType.toString(), + restriction.toString()); + } + } + + public BftPrivacyClusterAcceptanceTest(final BftPrivacyType bftPrivacyType) { + this.bftPrivacyType = bftPrivacyType; + } + + @Parameterized.Parameters(name = "{0}") + public static Collection bftPrivacyTypes() { + final List bftPrivacyTypes = new ArrayList<>(); + for (EnclaveType x : EnclaveType.valuesForTests()) { + for (ConsensusType consensusType : ConsensusType.values()) { + bftPrivacyTypes.add( + new BftPrivacyType( + x, EnclaveEncryptorType.NACL, consensusType, Restriction.RESTRICTED)); + bftPrivacyTypes.add( + new BftPrivacyType(x, EnclaveEncryptorType.EC, consensusType, Restriction.RESTRICTED)); + } + } + + for (ConsensusType consensusType : ConsensusType.values()) { + bftPrivacyTypes.add( + new BftPrivacyType( + EnclaveType.NOOP, + EnclaveEncryptorType.NOOP, + consensusType, + Restriction.UNRESTRICTED)); + } + + return bftPrivacyTypes; + } + + private PrivacyNode alice; + private PrivacyNode bob; + private PrivacyNode charlie; + + @Before + public void setUp() throws Exception { + final Network containerNetwork = Network.newNetwork(); + + alice = createNode(containerNetwork, "node1", 0); + bob = createNode(containerNetwork, "node2", 1); + charlie = createNode(containerNetwork, "node3", 2); + + privacyCluster.start(alice, bob, charlie); + } + + private PrivacyNode createNode( + final Network containerNetwork, final String nodeName, final int privacyAccount) + throws IOException { + if (bftPrivacyType.consensusType == ConsensusType.IBFT2) { + return privacyBesu.createIbft2NodePrivacyEnabled( + nodeName, + PrivacyAccountResolver.values()[privacyAccount].resolve( + bftPrivacyType.enclaveEncryptorType), + true, + bftPrivacyType.enclaveType, + Optional.of(containerNetwork), + false, + false, + bftPrivacyType.restriction == Restriction.UNRESTRICTED, + "0xAA"); + } else if (bftPrivacyType.consensusType == ConsensusType.QBFT) { + return privacyBesu.createQbftNodePrivacyEnabled( + nodeName, + PrivacyAccountResolver.values()[privacyAccount].resolve( + bftPrivacyType.enclaveEncryptorType), + bftPrivacyType.enclaveType, + Optional.of(containerNetwork), + false, + false, + bftPrivacyType.restriction == Restriction.UNRESTRICTED, + "0xAA"); + } else { + throw new IllegalStateException("Unknown consensus type " + bftPrivacyType.consensusType); + } + } + + @Test + public void onlyAliceAndBobCanExecuteContract() { + // Contract address is generated from sender address and transaction nonce + final String contractAddress = + EnclaveEncryptorType.EC.equals(bftPrivacyType.enclaveEncryptorType) + ? "0x3e5d325a03ad3ce5640502219833d30b89ce3ce1" + : "0xebf56429e6500e84442467292183d4d621359838"; + + final EventEmitter eventEmitter = + alice.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + privateContractVerifier + .validPrivateContractDeployed(contractAddress, alice.getAddress().toString()) + .verify(eventEmitter); + + final String transactionHash = + alice.execute( + privateContractTransactions.callSmartContract( + eventEmitter.getContractAddress(), + eventEmitter.store(BigInteger.ONE).encodeFunctionCall(), + alice.getTransactionSigningKey(), + bftPrivacyType.restriction, + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + final PrivateTransactionReceipt expectedReceipt = + alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash)); + + bob.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + transactionHash, expectedReceipt)); + + if (bftPrivacyType.restriction != Restriction.UNRESTRICTED) { + charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(transactionHash)); + } + } + + @Test + public void aliceCanDeployMultipleTimesInSingleGroup() { + final String firstDeployedAddress = + EnclaveEncryptorType.EC.equals(bftPrivacyType.enclaveEncryptorType) + ? "0x3e5d325a03ad3ce5640502219833d30b89ce3ce1" + : "0xebf56429e6500e84442467292183d4d621359838"; + + privacyCluster.stopNode(charlie); + + final EventEmitter firstEventEmitter = + alice.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + privateContractVerifier + .validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString()) + .verify(firstEventEmitter); + + final String secondDeployedAddress = + EnclaveEncryptorType.EC.equals(bftPrivacyType.enclaveEncryptorType) + ? "0x5194e214fae257530710d18c868df7a295d9d53b" + : "0x10f807f8a905da5bd319196da7523c6bd768690f"; + + final EventEmitter secondEventEmitter = + alice.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + privateContractVerifier + .validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString()) + .verify(secondEventEmitter); + } + + @Test + public void canInteractWithMultiplePrivacyGroups() { + // alice deploys contract + final String firstDeployedAddress = + EnclaveEncryptorType.EC.equals(bftPrivacyType.enclaveEncryptorType) + ? "0x760359bc605b3848f5199829bde6b382d90fb8eb" + : "0xff206d21150a8da5b83629d8a722f3135ed532b1"; + + final EventEmitter firstEventEmitter = + alice.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + bob.getEnclaveKey(), + charlie.getEnclaveKey())); + + privateContractVerifier + .validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString()) + .verify(firstEventEmitter); + + // charlie interacts with contract + final String firstTransactionHash = + charlie.execute( + privateContractTransactions.callSmartContract( + firstEventEmitter.getContractAddress(), + firstEventEmitter.store(BigInteger.ONE).encodeFunctionCall(), + charlie.getTransactionSigningKey(), + bftPrivacyType.restriction, + charlie.getEnclaveKey(), + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + // alice gets receipt from charlie's interaction + final PrivateTransactionReceipt aliceReceipt = + alice.execute(privacyTransactions.getPrivateTransactionReceipt(firstTransactionHash)); + + // verify bob and charlie have access to the same receipt + bob.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + firstTransactionHash, aliceReceipt)); + charlie.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + firstTransactionHash, aliceReceipt)); + + // alice deploys second contract + final String secondDeployedAddress = + EnclaveEncryptorType.EC.equals(bftPrivacyType.enclaveEncryptorType) + ? "0x3e5d325a03ad3ce5640502219833d30b89ce3ce1" + : "0xebf56429e6500e84442467292183d4d621359838"; + + final EventEmitter secondEventEmitter = + alice.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + privateContractVerifier + .validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString()) + .verify(secondEventEmitter); + + // bob interacts with contract + final String secondTransactionHash = + bob.execute( + privateContractTransactions.callSmartContract( + secondEventEmitter.getContractAddress(), + secondEventEmitter.store(BigInteger.ONE).encodeFunctionCall(), + bob.getTransactionSigningKey(), + bftPrivacyType.restriction, + bob.getEnclaveKey(), + alice.getEnclaveKey())); + + // alice gets receipt from bob's interaction + final PrivateTransactionReceipt secondExpectedReceipt = + alice.execute(privacyTransactions.getPrivateTransactionReceipt(secondTransactionHash)); + + bob.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + secondTransactionHash, secondExpectedReceipt)); + + // charlie cannot see the receipt + if (bftPrivacyType.restriction != Restriction.UNRESTRICTED) { + charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(secondTransactionHash)); + } + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/DeployPrivateSmartContractAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/DeployPrivateSmartContractAcceptanceTest.java new file mode 100644 index 00000000000..71aa618cdd8 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/DeployPrivateSmartContractAcceptanceTest.java @@ -0,0 +1,76 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import static org.web3j.utils.Restriction.UNRESTRICTED; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.io.IOException; +import java.util.Optional; + +import org.junit.Test; +import org.web3j.utils.Restriction; + +public class DeployPrivateSmartContractAcceptanceTest extends ParameterizedEnclaveTestBase { + + private final PrivacyNode minerNode; + + public DeployPrivateSmartContractAcceptanceTest( + final Restriction restriction, + final EnclaveType enclaveType, + final EnclaveEncryptorType enclaveEncryptorType) + throws IOException { + super(restriction, enclaveType, enclaveEncryptorType); + + minerNode = + privacyBesu.createPrivateTransactionEnabledMinerNode( + restriction + "-node", + PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType), + enclaveType, + Optional.empty(), + false, + false, + restriction == UNRESTRICTED); + + privacyCluster.start(minerNode); + } + + @Test + public void deployingMustGiveValidReceiptAndCode() throws Exception { + final String contractAddress = + EnclaveEncryptorType.EC.equals(enclaveEncryptorType) + ? "0xfeeb2367e77e28f75fc3bcc55b70a535752db058" + : "0x89ce396d0f9f937ddfa71113e29b2081c4869555"; + + final EventEmitter eventEmitter = + minerNode.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + minerNode.getTransactionSigningKey(), + minerNode.getEnclaveKey())); + + privateContractVerifier + .validPrivateContractDeployed(contractAddress, minerNode.getAddress().toString()) + .verify(eventEmitter); + + privateContractVerifier.validContractCodeProvided().verify(eventEmitter); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/EnclaveErrorAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/EnclaveErrorAcceptanceTest.java new file mode 100644 index 00000000000..7822768f140 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/EnclaveErrorAcceptanceTest.java @@ -0,0 +1,237 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.EC; +import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.NACL; +import static org.hyperledger.enclave.testutil.EnclaveType.TESSERA; + +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.KeyPairGenerator; +import java.security.spec.ECGenParameterSpec; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collection; +import java.util.Optional; + +import org.apache.tuweni.crypto.sodium.Box; +import org.assertj.core.api.Condition; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.testcontainers.containers.Network; +import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; +import org.web3j.utils.Restriction; + +@RunWith(Parameterized.class) +public class EnclaveErrorAcceptanceTest extends PrivacyAcceptanceTestBase { + + private final PrivacyNode alice; + private final PrivacyNode bob; + private final String wrongPublicKey; + + @Parameters(name = "{0} enclave type with {1} encryptor") + public static Collection enclaveParameters() { + return Arrays.asList( + new Object[][] { + {TESSERA, NACL}, + {TESSERA, EC} + }); + } + + public EnclaveErrorAcceptanceTest( + final EnclaveType enclaveType, final EnclaveEncryptorType enclaveEncryptorType) + throws IOException { + + final Network containerNetwork = Network.newNetwork(); + + alice = + privacyBesu.createIbft2NodePrivacyEnabled( + "node1", + PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType), + false, + enclaveType, + Optional.of(containerNetwork), + false, + false, + false, + "0xAA"); + bob = + privacyBesu.createIbft2NodePrivacyEnabled( + "node2", + PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType), + false, + enclaveType, + Optional.of(containerNetwork), + false, + false, + false, + "0xBB"); + privacyCluster.start(alice, bob); + + final byte[] wrongPublicKeyBytes = + EnclaveEncryptorType.EC.equals(enclaveEncryptorType) + ? getSECP256r1PublicKeyByteArray() + : Box.KeyPair.random().publicKey().bytesArray(); + + wrongPublicKey = Base64.getEncoder().encodeToString(wrongPublicKeyBytes); + } + + @Test + public void aliceCannotSendTransactionFromBobNode() { + final Throwable throwable = + catchThrowable( + () -> + alice.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + alice.getTransactionSigningKey(), + wrongPublicKey, + bob.getEnclaveKey()))); + + assertThat(throwable) + .hasMessageContaining( + JsonRpcError.PRIVATE_FROM_DOES_NOT_MATCH_ENCLAVE_PUBLIC_KEY.getMessage()); + } + + @Test + public void enclaveNoPeerUrlError() { + final Throwable throwable = + catchThrowable( + () -> + alice.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + wrongPublicKey))); + + final String tesseraMessage = JsonRpcError.TESSERA_NODE_MISSING_PEER_URL.getMessage(); + + assertThat(throwable.getMessage()).has(matchTesseraEnclaveMessage(tesseraMessage)); + } + + @Test + public void whenEnclaveIsDisconnectedGetReceiptReturnsInternalError() { + final EventEmitter eventEmitter = + alice.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + privateContractVerifier + .validPrivateContractDeployed( + eventEmitter.getContractAddress(), alice.getAddress().toString()) + .verify(eventEmitter); + + final String transactionHash = + alice.execute( + privateContractTransactions.callSmartContract( + eventEmitter.getContractAddress(), + eventEmitter.store(BigInteger.ONE).encodeFunctionCall(), + alice.getTransactionSigningKey(), + Restriction.RESTRICTED, + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + final PrivateTransactionReceipt receiptBeforeEnclaveLosesConnection = + alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash)); + + alice.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + transactionHash, receiptBeforeEnclaveLosesConnection)); + + alice.getEnclave().stop(); + + alice.verify( + privateTransactionVerifier.internalErrorPrivateTransactionReceipt(transactionHash)); + } + + @Test + @Ignore("Web3J is broken by PR #1426") + public void transactionFailsIfPartyIsOffline() { + // Contract address is generated from sender address and transaction nonce + final String contractAddress = "0xebf56429e6500e84442467292183d4d621359838"; + + final EventEmitter eventEmitter = + alice.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + privateContractVerifier + .validPrivateContractDeployed(contractAddress, alice.getAddress().toString()) + .verify(eventEmitter); + + bob.getEnclave().stop(); + + final Throwable throwable = + catchThrowable( + () -> + alice.execute( + privateContractTransactions.callSmartContract( + eventEmitter.getContractAddress(), + eventEmitter.store(BigInteger.ONE).encodeFunctionCall(), + alice.getTransactionSigningKey(), + Restriction.RESTRICTED, + alice.getEnclaveKey(), + bob.getEnclaveKey()))); + + assertThat(throwable).hasMessageContaining("NodePropagatingToAllPeers"); + } + + @Test + public void createPrivacyGroupReturnsCorrectError() { + final Throwable throwable = + catchThrowable(() -> alice.execute(privacyTransactions.createPrivacyGroup(null, null))); + final String tesseraMessage = JsonRpcError.TESSERA_CREATE_GROUP_INCLUDE_SELF.getMessage(); + + assertThat(throwable.getMessage()).has(matchTesseraEnclaveMessage(tesseraMessage)); + } + + private Condition matchTesseraEnclaveMessage(final String enclaveMessage) { + return new Condition<>( + message -> message.contains(enclaveMessage), + "Message did not match Tessera expected output"); + } + + private byte[] getSECP256r1PublicKeyByteArray() { + try { + final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC"); + final ECGenParameterSpec spec = new ECGenParameterSpec("secp256r1"); + keyGen.initialize(spec); + return keyGen.generateKeyPair().getPublic().getEncoded(); + } catch (Exception exception) { + return new byte[0]; + } + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/FlexiblePrivacyAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/FlexiblePrivacyAcceptanceTest.java new file mode 100644 index 00000000000..3f32904ba76 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/FlexiblePrivacyAcceptanceTest.java @@ -0,0 +1,638 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.hyperledger.besu.ethereum.core.PrivacyParameters.FLEXIBLE_PRIVACY_PROXY; +import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.EC; +import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.NACL; +import static org.hyperledger.enclave.testutil.EnclaveType.TESSERA; +import static org.junit.runners.Parameterized.Parameters; + +import org.hyperledger.besu.tests.acceptance.dsl.condition.eth.EthConditions; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.miner.MinerTransactions; +import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.Supplier; + +import com.google.common.collect.Lists; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.testcontainers.containers.Network; +import org.web3j.crypto.Credentials; +import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; +import org.web3j.protocol.core.methods.response.EthCall; +import org.web3j.protocol.core.methods.response.Log; +import org.web3j.protocol.core.methods.response.TransactionReceipt; +import org.web3j.tx.Contract; + +@RunWith(Parameterized.class) +public class FlexiblePrivacyAcceptanceTest extends FlexiblePrivacyAcceptanceTestBase { + + private final EnclaveType enclaveType; + private final EnclaveEncryptorType enclaveEncryptorType; + + public FlexiblePrivacyAcceptanceTest( + final EnclaveType enclaveType, final EnclaveEncryptorType enclaveEncryptorType) { + this.enclaveType = enclaveType; + this.enclaveEncryptorType = enclaveEncryptorType; + } + + @Parameters(name = "{0} enclave type with {1} encryptor") + public static Collection enclaveParameters() { + return Arrays.asList( + new Object[][] { + {TESSERA, NACL}, + {TESSERA, EC} + }); + } + + private PrivacyNode alice; + private PrivacyNode bob; + private PrivacyNode charlie; + + private final MinerTransactions minerTransactions = new MinerTransactions(); + private final EthConditions ethConditions = new EthConditions(ethTransactions); + + private static final String EXPECTED_STORE_OUTPUT_DATA = + "0x000000000000000000000000f17f52151ebef6c7334fad080c5704d77216b7320000000000000000000000000000000000000000000000000000000000000539"; + private static final String EXPECTED_STORE_EVENT_TOPIC = + "0xc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f5"; + + @Before + public void setUp() throws Exception { + final Network containerNetwork = Network.newNetwork(); + + alice = + privacyBesu.createFlexiblePrivacyGroupEnabledMinerNode( + "node1", + PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType), + false, + enclaveType, + Optional.of(containerNetwork)); + bob = + privacyBesu.createFlexiblePrivacyGroupEnabledNode( + "node2", + PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType), + false, + enclaveType, + Optional.of(containerNetwork)); + charlie = + privacyBesu.createFlexiblePrivacyGroupEnabledNode( + "node3", + PrivacyAccountResolver.CHARLIE.resolve(enclaveEncryptorType), + false, + enclaveType, + Optional.of(containerNetwork)); + privacyCluster.start(alice, bob, charlie); + } + + @Test + public void nodeCanCreatePrivacyGroup() { + final String privacyGroupId = createFlexiblePrivacyGroup(alice); + checkFlexiblePrivacyGroupExists(privacyGroupId, alice); + } + + @Test + public void deployingMustGiveValidReceipt() { + final String privacyGroupId = createFlexiblePrivacyGroup(alice, bob); + final Contract eventEmitter = deployPrivateContract(EventEmitter.class, privacyGroupId, alice); + final String commitmentHash = getContractDeploymentCommitmentHash(eventEmitter); + + alice.verify(privateTransactionVerifier.existingPrivateTransactionReceipt(commitmentHash)); + bob.verify(privateTransactionVerifier.existingPrivateTransactionReceipt(commitmentHash)); + } + + @Test + public void canAddParticipantToGroup() { + final String privacyGroupId = createFlexiblePrivacyGroup(alice, bob); + final Contract eventEmitter = deployPrivateContract(EventEmitter.class, privacyGroupId, alice); + final String commitmentHash = getContractDeploymentCommitmentHash(eventEmitter); + + charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(commitmentHash)); + + final Credentials aliceCredentials = Credentials.create(alice.getTransactionSigningKey()); + lockPrivacyGroup(privacyGroupId, alice, aliceCredentials); + addMembersToPrivacyGroup(privacyGroupId, alice, aliceCredentials, charlie); + checkFlexiblePrivacyGroupExists(privacyGroupId, alice, bob, charlie); + + charlie.verify(privateTransactionVerifier.existingPrivateTransactionReceipt(commitmentHash)); + } + + @Test + public void removedMemberCannotSendTransactionToGroup() { + final String privacyGroupId = createFlexiblePrivacyGroup(alice, bob); + + final String removeHash = + removeFromPrivacyGroup( + privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey()), bob); + + bob.verify(privateTransactionVerifier.existingPrivateTransactionReceipt(removeHash)); + + assertThatThrownBy(() -> deployPrivateContract(EventEmitter.class, privacyGroupId, bob)) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Flexible Privacy group does not exist."); + } + + @Test + public void canInteractWithPrivateGenesisPreCompile() throws Exception { + final String privacyGroupId = createFlexiblePrivacyGroup(alice, bob); + + final EventEmitter eventEmitter = + alice.execute( + privateContractTransactions.loadSmartContractWithPrivacyGroupId( + "0x1000000000000000000000000000000000000001", + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + privacyGroupId)); + + privateTransactionVerifier.existingPrivateTransactionReceipt( + eventEmitter.store(BigInteger.valueOf(42)).send().getTransactionHash()); + + final String aliceResponse = + alice + .execute( + privacyTransactions.privCall( + privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall())) + .getValue(); + + assertThat(new BigInteger(aliceResponse.substring(2), 16)) + .isEqualByComparingTo(BigInteger.valueOf(42)); + + final String bobResponse = + bob.execute( + privacyTransactions.privCall( + privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall())) + .getValue(); + + assertThat(new BigInteger(bobResponse.substring(2), 16)) + .isEqualByComparingTo(BigInteger.valueOf(42)); + + final String charlieResponse = + charlie + .execute( + privacyTransactions.privCall( + privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall())) + .getValue(); + + assertThat(charlieResponse).isEqualTo("0x"); + } + + @Test + public void memberCanBeAddedAfterBeingRemoved() { + final String privacyGroupId = createFlexiblePrivacyGroup(alice); + + checkFlexiblePrivacyGroupExists(privacyGroupId, alice); + + lockPrivacyGroup(privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey())); + addMembersToPrivacyGroup( + privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey()), bob); + + checkFlexiblePrivacyGroupExists(privacyGroupId, alice, bob); + + final EventEmitter eventEmitter = + deployPrivateContract(EventEmitter.class, privacyGroupId, alice); + + final int valueSetWhileBobWasMember = 17; + final PrivateTransactionReceipt receiptWhileBobMember = + setEventEmitterValueAndCheck( + Lists.newArrayList(alice, bob), + privacyGroupId, + eventEmitter, + valueSetWhileBobWasMember); + + removeFromPrivacyGroup( + privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey()), bob); + + checkFlexiblePrivacyGroupExists(privacyGroupId, alice); + + final int valueSetWhileBobWas_NOT_aMember = 1337; + final PrivateTransactionReceipt receiptWhileBobRemoved = + setEventEmitterValueAndCheck( + Lists.newArrayList(alice), + privacyGroupId, + eventEmitter, + valueSetWhileBobWas_NOT_aMember); + checkEmitterValue( + Lists.newArrayList(bob), + privacyGroupId, + eventEmitter, + valueSetWhileBobWasMember); // bob did not get the last transaction + + lockPrivacyGroup(privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey())); + addMembersToPrivacyGroup( + privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey()), bob); + + checkFlexiblePrivacyGroupExists(privacyGroupId, alice, bob); + + checkEmitterValue( + Lists.newArrayList(alice, bob), + privacyGroupId, + eventEmitter, + valueSetWhileBobWas_NOT_aMember); + + PrivateTransactionReceipt receipt = + bob.execute( + privacyTransactions.getPrivateTransactionReceipt( + receiptWhileBobRemoved.getcommitmentHash())); + assertThat(receipt.getStatus()).isEqualTo("0x1"); + + receipt = + bob.execute( + privacyTransactions.getPrivateTransactionReceipt( + receiptWhileBobMember.getcommitmentHash())); + assertThat(receipt.getStatus()).isEqualTo("0x1"); + } + + PrivateTransactionReceipt setEventEmitterValueAndCheck( + final List nodes, + final String privacyGroupId, + final EventEmitter eventEmitter, + final int value) { + final PrivateTransactionReceipt receiptWhileBobMember = + setEventEmitterValue(nodes, privacyGroupId, eventEmitter, value); + + checkEmitterValue(nodes, privacyGroupId, eventEmitter, value); + return receiptWhileBobMember; + } + + private PrivateTransactionReceipt setEventEmitterValue( + final List nodes, + final String privacyGroupId, + final EventEmitter eventEmitter, + final int value) { + final PrivacyNode firstNode = nodes.get(0); + final String txHash = + firstNode.execute( + privateContractTransactions.callOnchainPermissioningSmartContract( + eventEmitter.getContractAddress(), + eventEmitter.store(BigInteger.valueOf(value)).encodeFunctionCall(), + firstNode.getTransactionSigningKey(), + firstNode.getEnclaveKey(), + privacyGroupId)); + PrivateTransactionReceipt receipt = null; + for (final PrivacyNode node : nodes) { + receipt = node.execute(privacyTransactions.getPrivateTransactionReceipt(txHash)); + assertThat(receipt.getStatus()).isEqualTo("0x1"); + } + return receipt; + } + + private void checkEmitterValue( + final List nodes, + final String privacyGroupId, + final EventEmitter eventEmitter, + final int expectedValue) { + for (final PrivacyNode node : nodes) { + final EthCall response = + node.execute( + privacyTransactions.privCall( + privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall())); + + assertThat(new BigInteger(response.getValue().substring(2), 16)) + .isEqualByComparingTo(BigInteger.valueOf(expectedValue)); + } + } + + @Test + public void bobCanAddCharlieAfterBeingAddedByAlice() { + final String privacyGroupId = createFlexiblePrivacyGroup(alice); + checkFlexiblePrivacyGroupExists(privacyGroupId, alice); + final EventEmitter eventEmitter = + alice.execute( + privateContractTransactions.createSmartContractWithPrivacyGroupId( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + privacyGroupId)); + + privateContractVerifier + .validPrivateContractDeployed( + eventEmitter.getContractAddress(), alice.getAddress().toString()) + .verify(eventEmitter); + + final Credentials aliceCredentials = Credentials.create(alice.getTransactionSigningKey()); + final String aliceLockHash = + alice.execute( + privacyTransactions.privxLockPrivacyGroupAndCheck( + privacyGroupId, alice, aliceCredentials)); + + alice.execute( + privacyTransactions.addToPrivacyGroup(privacyGroupId, alice, aliceCredentials, bob)); + + checkFlexiblePrivacyGroupExists(privacyGroupId, alice, bob); + + bob.execute( + privacyTransactions.privxLockPrivacyGroupAndCheck(privacyGroupId, bob, aliceCredentials)); + + alice.execute(minerTransactions.minerStop()); + + alice.getBesu().verify(ethConditions.miningStatus(false)); + + final BigInteger pendingTransactionFilterId = + alice.execute(ethTransactions.newPendingTransactionsFilter()); + + final String callHash = + alice.execute( + privateContractTransactions.callOnchainPermissioningSmartContract( + eventEmitter.getContractAddress(), + eventEmitter.value().encodeFunctionCall(), + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + privacyGroupId)); + + final String bobAddHash = + addMembersToPrivacyGroup(privacyGroupId, bob, aliceCredentials, charlie); + + alice + .getBesu() + .verify( + ethConditions.expectNewPendingTransactions( + pendingTransactionFilterId, Arrays.asList(callHash, bobAddHash))); + + alice.execute(minerTransactions.minerStart()); + + alice.getBesu().verify(ethConditions.miningStatus(true)); + + checkFlexiblePrivacyGroupExists(privacyGroupId, alice, bob, charlie); + + final Optional aliceAddReceipt = + alice.execute(ethTransactions.getTransactionReceipt(bobAddHash)); + assertThat(aliceAddReceipt.get().getStatus()) + .isEqualTo("0x1"); // this means the PMT for the "add" succeeded which is what we expect + + final Optional alicePublicReceipt = + alice.execute(ethTransactions.getTransactionReceipt(callHash)); + if (alicePublicReceipt.isPresent()) { + assertThat(alicePublicReceipt.get().getBlockHash()) + .isEqualTo( + aliceAddReceipt + .get() + .getBlockHash()); // ensure that "add" and "call" are in the same block + assertThat(alicePublicReceipt.get().getStatus()) + .isEqualTo( + "0x1"); // this means the PMT for the "call" succeeded which is what we expect because + // it is in the same block as the "add" and there is no way to tell that this + // will happen before the block is mined + } + + final PrivateTransactionReceipt aliceReceipt = + alice.execute(privacyTransactions.getPrivateTransactionReceipt(callHash)); + assertThat(aliceReceipt.getStatus()) + .isEqualTo( + "0x0"); // this means the "call" failed which is what we expect because the group was + // locked! + final PrivateTransactionReceipt bobReceipt = + alice.execute(privacyTransactions.getPrivateTransactionReceipt(callHash)); + assertThat(bobReceipt.getStatus()) + .isEqualTo( + "0x0"); // this means the "call" failed which is what we expect because the group was + // locked! + + // assert charlie can access private transaction information from before he was added + final PrivateTransactionReceipt expectedAliceLockReceipt = + new PrivateTransactionReceipt( + null, + alice.getAddress().toHexString(), + FLEXIBLE_PRIVACY_PROXY.toHexString(), + "0x", + Collections.emptyList(), + null, + null, + alice.getEnclaveKey(), + null, + privacyGroupId, + "0x1", + null); + charlie.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + aliceLockHash, expectedAliceLockReceipt)); + + final String aliceStoreHash = + charlie.execute( + privateContractTransactions.callOnchainPermissioningSmartContract( + eventEmitter.getContractAddress(), + eventEmitter.store(BigInteger.valueOf(1337)).encodeFunctionCall(), + charlie.getTransactionSigningKey(), + charlie.getEnclaveKey(), + privacyGroupId)); + + final PrivateTransactionReceipt expectedStoreReceipt = + new PrivateTransactionReceipt( + null, + charlie.getAddress().toHexString(), + eventEmitter.getContractAddress(), + "0x", + Collections.singletonList( + new Log( + false, + "0x0", + "0x0", + aliceStoreHash, + null, + null, + eventEmitter.getContractAddress(), + EXPECTED_STORE_OUTPUT_DATA, + null, + Collections.singletonList(EXPECTED_STORE_EVENT_TOPIC))), + null, + null, + charlie.getEnclaveKey(), + null, + privacyGroupId, + "0x1", + null); + + alice.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + aliceStoreHash, expectedStoreReceipt)); + + bob.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + aliceStoreHash, expectedStoreReceipt)); + + charlie.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + aliceStoreHash, expectedStoreReceipt)); + + removeFromPrivacyGroup(privacyGroupId, bob, aliceCredentials, charlie); + + checkFlexiblePrivacyGroupExists(privacyGroupId, alice, bob); + } + + @Test + public void canOnlyCallProxyContractWhenGroupLocked() { + final String privacyGroupId = createFlexiblePrivacyGroup(alice); + checkFlexiblePrivacyGroupExists(privacyGroupId, alice); + + final EventEmitter eventEmitter = + alice.execute( + privateContractTransactions.createSmartContractWithPrivacyGroupId( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + privacyGroupId)); + + privateContractVerifier + .validPrivateContractDeployed( + eventEmitter.getContractAddress(), alice.getAddress().toString()) + .verify(eventEmitter); + + final Credentials aliceCredentials = Credentials.create(alice.getTransactionSigningKey()); + + final Supplier callContract = + () -> { + return alice.execute( + privateContractTransactions.callOnchainPermissioningSmartContract( + eventEmitter.getContractAddress(), + eventEmitter.value().encodeFunctionCall(), + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + privacyGroupId)); + }; + + final String lockHash = + alice.execute( + privacyTransactions.privxLockPrivacyGroupAndCheck( + privacyGroupId, alice, aliceCredentials)); + + final String callWhileLockedHash = callContract.get(); + + final String unlockHash = + alice.execute( + privacyTransactions.privxUnlockPrivacyGroupAndCheck( + privacyGroupId, alice, aliceCredentials)); + + final String callAfterUnlockedHash = callContract.get(); + + alice.execute(minerTransactions.minerStart()); + alice.getBesu().verify(ethConditions.miningStatus(true)); + + final BiConsumer assertThatTransactionReceiptIs = + (String hash, String expectedResult) -> { + final PrivateTransactionReceipt receipt = + alice.execute(privacyTransactions.getPrivateTransactionReceipt(hash)); + assertThat(receipt.getStatus()).isEqualTo(expectedResult); + }; + + // when locking a group succeeds ... + assertThatTransactionReceiptIs.accept(lockHash, "0x1"); + // ... calls to contracts fail ... + assertThatTransactionReceiptIs.accept(callWhileLockedHash, "0x0"); + // ... but unlock the group works ... + assertThatTransactionReceiptIs.accept(unlockHash, "0x1"); + // ... and afterwards we can call contracts again + assertThatTransactionReceiptIs.accept(callAfterUnlockedHash, "0x1"); + } + + @Test + public void addMembersToTwoGroupsInTheSameBlock() { + final String privacyGroupId1 = createFlexiblePrivacyGroup(alice); + final String privacyGroupId2 = createFlexiblePrivacyGroup(bob); + checkFlexiblePrivacyGroupExists(privacyGroupId1, alice); + checkFlexiblePrivacyGroupExists(privacyGroupId2, bob); + + lockPrivacyGroup(privacyGroupId1, alice, Credentials.create(alice.getTransactionSigningKey())); + lockPrivacyGroup(privacyGroupId2, bob, Credentials.create(bob.getTransactionSigningKey())); + + final BigInteger pendingTransactionFilterId = + alice.execute(ethTransactions.newPendingTransactionsFilter()); + + alice.execute(minerTransactions.minerStop()); + alice.getBesu().verify(ethConditions.miningStatus(false)); + + final String aliceAddHash = + addMembersToPrivacyGroup( + privacyGroupId1, alice, Credentials.create(alice.getTransactionSigningKey()), charlie); + final String bobAddHash = + addMembersToPrivacyGroup( + privacyGroupId2, bob, Credentials.create(bob.getTransactionSigningKey()), alice); + + alice + .getBesu() + .verify( + ethConditions.expectNewPendingTransactions( + pendingTransactionFilterId, Arrays.asList(aliceAddHash, bobAddHash))); + + alice.execute(minerTransactions.minerStart()); + + checkFlexiblePrivacyGroupExists(privacyGroupId1, alice, charlie); + checkFlexiblePrivacyGroupExists(privacyGroupId2, bob, alice); + } + + private T deployPrivateContract( + final Class clazz, final String privacyGroupId, final PrivacyNode sender) { + final T contract = + sender.execute( + privateContractTransactions.createSmartContractWithPrivacyGroupId( + clazz, sender.getTransactionSigningKey(), sender.getEnclaveKey(), privacyGroupId)); + + privateContractVerifier + .validPrivateContractDeployed(contract.getContractAddress(), sender.getAddress().toString()) + .verify(contract); + + return contract; + } + + private String addMembersToPrivacyGroup( + final String privacyGroupId, + final PrivacyNode nodeAddingMember, + final Credentials signer, + final PrivacyNode... newMembers) { + return nodeAddingMember.execute( + privacyTransactions.addToPrivacyGroup( + privacyGroupId, nodeAddingMember, signer, newMembers)); + } + + private String removeFromPrivacyGroup( + final String privacyGroupId, + final PrivacyNode nodeRemovingMember, + final Credentials signer, + final PrivacyNode memberBeingRemoved) { + return nodeRemovingMember.execute( + privacyTransactions.removeFromPrivacyGroup( + privacyGroupId, + nodeRemovingMember.getEnclaveKey(), + signer, + memberBeingRemoved.getEnclaveKey())); + } + + /** + * This method will send a transaction to lock the privacy group identified by the specified id. + * This also checks if the lock transaction was successful. + * + * @return the hash of the lock privacy group transaction + */ + private String lockPrivacyGroup( + final String privacyGroupId, final PrivacyNode member, final Credentials signer) { + return member.execute( + privacyTransactions.privxLockPrivacyGroupAndCheck(privacyGroupId, member, signer)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/FlexiblePrivacyAcceptanceTestBase.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/FlexiblePrivacyAcceptanceTestBase.java new file mode 100644 index 00000000000..9e4f1638dad --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/FlexiblePrivacyAcceptanceTestBase.java @@ -0,0 +1,186 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.core.PrivacyParameters.FLEXIBLE_PRIVACY_PROXY; +import static org.hyperledger.besu.ethereum.privacy.group.FlexibleGroupManagement.GET_PARTICIPANTS_METHOD_SIGNATURE; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.condition.ExpectValidFlexiblePrivacyGroupCreated; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.CreateFlexiblePrivacyGroupTransaction; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.apache.tuweni.bytes.Bytes; +import org.web3j.abi.FunctionEncoder; +import org.web3j.abi.Utils; +import org.web3j.abi.datatypes.DynamicArray; +import org.web3j.abi.datatypes.DynamicBytes; +import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; +import org.web3j.protocol.core.methods.response.TransactionReceipt; +import org.web3j.tx.Contract; +import org.web3j.utils.Base64String; + +public class FlexiblePrivacyAcceptanceTestBase extends PrivacyAcceptanceTestBase { + + protected String createFlexiblePrivacyGroup(final PrivacyNode... members) { + final List addresses = + Arrays.stream(members).map(PrivacyNode::getEnclaveKey).collect(Collectors.toList()); + return createFlexiblePrivacyGroup(members[0].getEnclaveKey(), addresses, members); + } + + /** + * Create an flexible privacy group. The privacy group id will be randomly generated. + * + *

This method also checks that each node member has successfully processed the transaction and + * has the expected list of member for the group. + * + * @param members the list of members of the privacy group. The first member of the list will be + * the creator of the group. + * @return the id of the privacy group + */ + protected String createFlexiblePrivacyGroup( + final String privateFrom, final List addresses, final PrivacyNode... members) { + + final PrivacyNode groupCreator = members[0]; + + final CreateFlexiblePrivacyGroupTransaction createTx = + privacyTransactions.createFlexiblePrivacyGroup(groupCreator, privateFrom, addresses); + + final PrivacyRequestFactory.PrivxCreatePrivacyGroupResponse createResponse = + groupCreator.execute(createTx); + final String privacyGroupId = createResponse.getPrivacyGroupId(); + + final List membersEnclaveKeys = + Arrays.stream(members) + .map(m -> Base64String.wrap(m.getEnclaveKey())) + .collect(Collectors.toList()); + + for (final PrivacyNode member : members) { + member.verify(flexiblePrivacyGroupExists(privacyGroupId, membersEnclaveKeys)); + } + + final String commitmentHash = + callGetParticipantsMethodAndReturnCommitmentHash(privacyGroupId, groupCreator, privateFrom); + final PrivateTransactionReceipt expectedReceipt = + buildExpectedAddMemberTransactionReceipt(privacyGroupId, groupCreator, addresses); + + for (final PrivacyNode member : members) { + member.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + commitmentHash, expectedReceipt)); + } + + return privacyGroupId; + } + + protected String callGetParticipantsMethodAndReturnCommitmentHash( + final String privacyGroupId, final PrivacyNode groupCreator, final String privateFrom) { + return groupCreator.execute( + privateContractTransactions.callOnchainPermissioningSmartContract( + FLEXIBLE_PRIVACY_PROXY.toHexString(), + GET_PARTICIPANTS_METHOD_SIGNATURE.toString(), + groupCreator.getTransactionSigningKey(), + privateFrom, + privacyGroupId)); + } + + protected PrivateTransactionReceipt buildExpectedAddMemberTransactionReceipt( + final String privacyGroupId, final PrivacyNode groupCreator, final List members) { + return buildExpectedAddMemberTransactionReceipt( + privacyGroupId, groupCreator, groupCreator.getEnclaveKey(), members); + } + + protected PrivateTransactionReceipt buildExpectedAddMemberTransactionReceipt( + final String privacyGroupId, + final PrivacyNode groupCreator, + final String privateFrom, + final List members) { + + final StringBuilder output = new StringBuilder(); + // hex prefix + output.append("0x"); + + final String encodedParameters = + FunctionEncoder.encode( + "", + Arrays.asList( + new DynamicArray<>( + DynamicBytes.class, + Utils.typeMap( + members.stream() + .map(Bytes::fromBase64String) + .map(Bytes::toArrayUnsafe) + .collect(Collectors.toList()), + DynamicBytes.class)))); + + output.append(encodedParameters); + + return new PrivateTransactionReceipt( + null, + groupCreator.getAddress().toHexString(), + FLEXIBLE_PRIVACY_PROXY.toHexString(), + output.toString(), + Collections.emptyList(), + null, + null, + privateFrom, + null, + privacyGroupId, + "0x1", + null); + } + + protected ExpectValidFlexiblePrivacyGroupCreated flexiblePrivacyGroupExists( + final String privacyGroupId, final List members) { + return privateTransactionVerifier.flexiblePrivacyGroupExists(privacyGroupId, members); + } + + protected String getContractDeploymentCommitmentHash(final Contract contract) { + final Optional transactionReceipt = contract.getTransactionReceipt(); + assertThat(transactionReceipt).isPresent(); + final PrivateTransactionReceipt privateTransactionReceipt = + (PrivateTransactionReceipt) transactionReceipt.get(); + return privateTransactionReceipt.getcommitmentHash(); + } + + /** + * This method will check if a privacy group with the specified id and list of members exists. + * Each one of the members node will be queried to ensure that they all have the same privacy + * group in their private state. + * + * @param privacyGroupId the id of the privacy group + * @param members the list of member in the privacy group + */ + protected void checkFlexiblePrivacyGroupExists( + final String privacyGroupId, final PrivacyNode... members) { + final List membersEnclaveKeys = + Arrays.stream(members) + .map(PrivacyNode::getEnclaveKey) + .map(Base64String::wrap) + .collect(Collectors.toList()); + + for (final PrivacyNode member : members) { + member.verify(flexiblePrivacyGroupExists(privacyGroupId, membersEnclaveKeys)); + } + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PluginPrivacySigningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PluginPrivacySigningAcceptanceTest.java new file mode 100644 index 00000000000..68d5117fd6b --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PluginPrivacySigningAcceptanceTest.java @@ -0,0 +1,135 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeConfigurationBuilder; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.privacy.PrivacyNodeConfiguration; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccount; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveKeyConfiguration; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.web3j.protocol.core.DefaultBlockParameter; +import org.web3j.protocol.core.methods.response.EthBlock.Block; +import org.web3j.protocol.core.methods.response.TransactionReceipt; + +@RunWith(Parameterized.class) +public class PluginPrivacySigningAcceptanceTest extends PrivacyAcceptanceTestBase { + private PrivacyNode minerNode; + + private final EnclaveEncryptorType enclaveEncryptorType; + + public PluginPrivacySigningAcceptanceTest(final EnclaveEncryptorType enclaveEncryptorType) { + this.enclaveEncryptorType = enclaveEncryptorType; + } + + @Parameterized.Parameters(name = "{0}") + public static Collection enclaveEncryptorTypes() { + return Arrays.stream(EnclaveEncryptorType.values()) + .filter(encryptorType -> !EnclaveEncryptorType.NOOP.equals(encryptorType)) + .collect(Collectors.toList()); + } + + @Before + public void setup() throws IOException { + final PrivacyAccount BOB = PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType); + + minerNode = + privacyBesu.create( + new PrivacyNodeConfiguration( + false, + false, + true, + new BesuNodeConfigurationBuilder() + .name("miner") + .miningEnabled() + .jsonRpcEnabled() + .webSocketEnabled() + .enablePrivateTransactions() + .keyFilePath(BOB.getPrivateKeyPath()) + .plugins(Collections.singletonList("testPlugins")) + .extraCLIOptions( + List.of( + "--plugin-privacy-service-encryption-prefix=0xAA", + "--plugin-privacy-service-signing-enabled=true", + "--plugin-privacy-service-signing-key=8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63")) + .build(), + new EnclaveKeyConfiguration( + BOB.getEnclaveKeyPaths(), + BOB.getEnclavePrivateKeyPaths(), + BOB.getEnclaveEncryptorType())), + EnclaveType.NOOP, + Optional.empty()); + + privacyCluster.start(minerNode); + } + + @Test + public void canDeployContractSignedByPlugin() throws Exception { + final String contractAddress = + EnclaveEncryptorType.EC.equals(enclaveEncryptorType) + ? "0xf01ec73d91fdeb8bb9388ec74e6a3981da86e021" + : "0xd0152772c54cecfa7684f09f7616dcc825545dff"; + + final EventEmitter eventEmitter = + minerNode.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + minerNode.getTransactionSigningKey(), + minerNode.getEnclaveKey())); + + privateContractVerifier + .validPrivateContractDeployed(contractAddress, minerNode.getAddress().toString()) + .verify(eventEmitter); + privateContractVerifier.validContractCodeProvided().verify(eventEmitter); + + final BigInteger blockNumberContractDeployed = + eventEmitter.getTransactionReceipt().get().getBlockNumber(); + final Block blockContractDeployed = + minerNode.execute( + ethTransactions.block(DefaultBlockParameter.valueOf(blockNumberContractDeployed))); + + assertThat(blockContractDeployed.getTransactions().size()).isEqualTo(1); + + final String transactionHashContractDeployed = + (String) blockContractDeployed.getTransactions().get(0).get(); + final TransactionReceipt pmtReceipt = + minerNode + .execute(ethTransactions.getTransactionReceipt(transactionHashContractDeployed)) + .get(); + + assertThat(pmtReceipt.getStatus()).isEqualTo("0x1"); + assertThat(pmtReceipt.getFrom()).isEqualTo("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivCallAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivCallAcceptanceTest.java new file mode 100644 index 00000000000..c42075d48d2 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivCallAcceptanceTest.java @@ -0,0 +1,294 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.tests.web3j.generated.RevertReason.FUNC_REVERTWITHREVERTREASON; +import static org.web3j.utils.Restriction.UNRESTRICTED; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.besu.tests.web3j.generated.RevertReason; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.io.IOException; +import java.math.BigInteger; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import javax.annotation.Nonnull; + +import org.bouncycastle.util.encoders.Hex; +import org.junit.Test; +import org.web3j.abi.FunctionEncoder; +import org.web3j.abi.TypeReference; +import org.web3j.abi.datatypes.Bool; +import org.web3j.abi.datatypes.Function; +import org.web3j.abi.datatypes.Type; +import org.web3j.abi.datatypes.generated.Uint256; +import org.web3j.protocol.core.Request; +import org.web3j.protocol.core.methods.request.Transaction; +import org.web3j.protocol.core.methods.response.EthCall; +import org.web3j.protocol.core.methods.response.TransactionReceipt; +import org.web3j.protocol.http.HttpService; +import org.web3j.tx.Contract; +import org.web3j.utils.Restriction; + +public class PrivCallAcceptanceTest extends ParameterizedEnclaveTestBase { + + private static final int VALUE = 1024; + + private final PrivacyNode minerNode; + + public PrivCallAcceptanceTest( + final Restriction restriction, + final EnclaveType enclaveType, + final EnclaveEncryptorType enclaveEncryptorType) + throws IOException { + + super(restriction, enclaveType, enclaveEncryptorType); + + minerNode = + privacyBesu.createPrivateTransactionEnabledMinerNode( + restriction + "-node", + PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType), + enclaveType, + Optional.empty(), + false, + false, + restriction == UNRESTRICTED); + + privacyCluster.start(minerNode); + } + + @Test + public void mustReturnCorrectValue() throws Exception { + + final String privacyGroupId = + minerNode.execute(createPrivacyGroup("myGroupName", "my group description", minerNode)); + + final EventEmitter eventEmitter = + minerNode.execute( + privateContractTransactions.createSmartContractWithPrivacyGroupId( + EventEmitter.class, + minerNode.getTransactionSigningKey(), + restriction, + minerNode.getEnclaveKey(), + privacyGroupId)); + + privateContractVerifier + .validPrivateContractDeployed( + eventEmitter.getContractAddress(), minerNode.getAddress().toString()) + .verify(eventEmitter); + + final Request priv_call = + privCall(privacyGroupId, eventEmitter, false, false, false); + + EthCall resp = priv_call.send(); + + String value = resp.getValue(); + assertThat(new BigInteger(value.substring(2), 16)).isEqualByComparingTo(BigInteger.ZERO); + + final TransactionReceipt receipt = eventEmitter.store(BigInteger.valueOf(VALUE)).send(); + assertThat(receipt).isNotNull(); + + resp = priv_call.send(); + value = resp.getValue(); + assertThat(new BigInteger(value.substring(2), 16)) + .isEqualByComparingTo(BigInteger.valueOf(VALUE)); + } + + @Test + public void mustRevertWithRevertReason() throws Exception { + + final String privacyGroupId = + minerNode.execute(createPrivacyGroup("myGroupName", "my group description", minerNode)); + + final RevertReason revertReasonContract = + minerNode.execute( + privateContractTransactions.createSmartContractWithPrivacyGroupId( + RevertReason.class, + minerNode.getTransactionSigningKey(), + restriction, + minerNode.getEnclaveKey(), + privacyGroupId)); + + privateContractVerifier + .validPrivateContractDeployed( + revertReasonContract.getContractAddress(), minerNode.getAddress().toString()) + .verify(revertReasonContract); + + final Request priv_call = + privCall(privacyGroupId, revertReasonContract, false, false, true); + + EthCall resp = priv_call.send(); + assertThat(resp.getRevertReason()).isEqualTo("Execution reverted"); + + byte[] bytes = Hex.decode(resp.getError().getData().substring(3, 203)); + String revertMessage = + new String(Arrays.copyOfRange(bytes, 4, bytes.length), Charset.defaultCharset()).trim(); + assertThat(revertMessage).isEqualTo("RevertReason"); + } + + @Test + public void shouldReturnEmptyResultWithNonExistingPrivacyGroup() throws IOException { + + final String privacyGroupId = + minerNode.execute(createPrivacyGroup("myGroupName", "my group description", minerNode)); + + final EventEmitter eventEmitter = + minerNode.execute( + privateContractTransactions.createSmartContractWithPrivacyGroupId( + EventEmitter.class, + minerNode.getTransactionSigningKey(), + restriction, + minerNode.getEnclaveKey(), + privacyGroupId)); + + privateContractVerifier + .validPrivateContractDeployed( + eventEmitter.getContractAddress(), minerNode.getAddress().toString()) + .verify(eventEmitter); + + final String invalidPrivacyGroup = constructInvalidString(privacyGroupId); + final Request privCall = + privCall(invalidPrivacyGroup, eventEmitter, false, false, false); + + final EthCall result = privCall.send(); + + assertThat(result.getResult()).isEqualTo("0x"); + } + + @Test + public void mustNotSucceedWithWronglyEncodedFunction() throws IOException { + + final String privacyGroupId = + minerNode.execute(createPrivacyGroup("myGroupName", "my group description", minerNode)); + + final EventEmitter eventEmitter = + minerNode.execute( + privateContractTransactions.createSmartContractWithPrivacyGroupId( + EventEmitter.class, + minerNode.getTransactionSigningKey(), + restriction, + minerNode.getEnclaveKey(), + privacyGroupId)); + + privateContractVerifier + .validPrivateContractDeployed( + eventEmitter.getContractAddress(), minerNode.getAddress().toString()) + .verify(eventEmitter); + + final Request priv_call = + privCall(privacyGroupId, eventEmitter, true, false, false); + + final String errorMessage = priv_call.send().getError().getMessage(); + assertThat(errorMessage).isEqualTo("Private transaction failed"); + } + + @Test + public void mustReturn0xUsingInvalidContractAddress() throws IOException { + + final String privacyGroupId = + minerNode.execute(createPrivacyGroup("myGroupName", "my group description", minerNode)); + + final EventEmitter eventEmitter = + minerNode.execute( + privateContractTransactions.createSmartContractWithPrivacyGroupId( + EventEmitter.class, + minerNode.getTransactionSigningKey(), + restriction, + minerNode.getEnclaveKey(), + privacyGroupId)); + + privateContractVerifier + .validPrivateContractDeployed( + eventEmitter.getContractAddress(), minerNode.getAddress().toString()) + .verify(eventEmitter); + + final Request priv_call = + privCall(privacyGroupId, eventEmitter, false, true, false); + + final EthCall result = priv_call.send(); + + assertThat(result).isNotNull(); + assertThat(result.getResult()).isEqualTo("0x"); + } + + @Nonnull + private String constructInvalidString(final String privacyGroupId) { + final char[] chars = privacyGroupId.toCharArray(); + if (chars[3] == '0') { + chars[3] = '1'; + } else { + chars[3] = '0'; + } + return String.valueOf(chars); + } + + @Nonnull + private Request privCall( + final String privacyGroupId, + final Contract contract, + final boolean useInvalidParameters, + final boolean useInvalidContractAddress, + final boolean useRevertFunction) { + + final Uint256 invalid = new Uint256(BigInteger.TEN); + + @SuppressWarnings("rawtypes") + final List inputParameters = + useInvalidParameters ? Arrays.asList(invalid) : Collections.emptyList(); + + final Function function = + useRevertFunction + ? new Function( + FUNC_REVERTWITHREVERTREASON, + inputParameters, + Arrays.>asList(new TypeReference() {})) + : new Function( + "value", + inputParameters, + Arrays.>asList(new TypeReference() {})); + + final String encoded = FunctionEncoder.encode(function); + + final HttpService httpService = + new HttpService( + "http://" + + minerNode.getBesu().getHostName() + + ":" + + minerNode.getBesu().getJsonRpcPort().get()); + + final String validContractAddress = contract.getContractAddress(); + final String invalidContractAddress = constructInvalidString(validContractAddress); + final String contractAddress = + useInvalidContractAddress ? invalidContractAddress : validContractAddress; + + final Transaction transaction = + Transaction.createEthCallTransaction(null, contractAddress, encoded); + + return new Request<>( + "priv_call", + Arrays.asList(privacyGroupId, transaction, "latest"), + httpService, + EthCall.class); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivDebugGetStateRootFlexibleGroupAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivDebugGetStateRootFlexibleGroupAcceptanceTest.java new file mode 100644 index 00000000000..59973fd00be --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivDebugGetStateRootFlexibleGroupAcceptanceTest.java @@ -0,0 +1,178 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory; +import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.io.IOException; +import java.math.BigInteger; +import java.net.URISyntaxException; +import java.util.Collection; +import java.util.Optional; + +import org.apache.tuweni.bytes.Bytes32; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.testcontainers.containers.Network; + +@RunWith(Parameterized.class) +public class PrivDebugGetStateRootFlexibleGroupAcceptanceTest + extends FlexiblePrivacyAcceptanceTestBase { + + private final EnclaveType enclaveType; + + public PrivDebugGetStateRootFlexibleGroupAcceptanceTest(final EnclaveType enclaveType) { + this.enclaveType = enclaveType; + } + + @Parameters(name = "{0}") + public static Collection enclaveTypes() { + return EnclaveType.valuesForTests(); + } + + private PrivacyNode aliceNode; + private PrivacyNode bobNode; + + @Before + public void setUp() throws IOException, URISyntaxException { + final Network containerNetwork = Network.newNetwork(); + + aliceNode = + privacyBesu.createFlexiblePrivacyGroupEnabledMinerNode( + "alice-node", + PrivacyAccountResolver.ALICE.resolve(EnclaveEncryptorType.NACL), + false, + enclaveType, + Optional.of(containerNetwork)); + bobNode = + privacyBesu.createFlexiblePrivacyGroupEnabledNode( + "bob-node", + PrivacyAccountResolver.BOB.resolve(EnclaveEncryptorType.NACL), + false, + enclaveType, + Optional.of(containerNetwork)); + + privacyCluster.start(aliceNode, bobNode); + } + + @Test + public void nodesInGroupShouldHaveSameStateRoot() { + final String privacyGroupId = createFlexiblePrivacyGroup(aliceNode, bobNode); + + final Hash aliceStateRootId = + aliceNode + .execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "latest")) + .getResult(); + + final Hash bobStateRootId = + bobNode + .execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "latest")) + .getResult(); + + assertThat(aliceStateRootId).isEqualTo(bobStateRootId); + } + + @Test + public void unknownGroupShouldReturnError() { + final PrivacyRequestFactory.DebugGetStateRoot aliceResult = + aliceNode.execute( + privacyTransactions.debugGetStateRoot( + Hash.wrap(Bytes32.random()).toBase64String(), "latest")); + + assertThat(aliceResult.getResult()).isNull(); + assertThat(aliceResult.hasError()).isTrue(); + assertThat(aliceResult.getError()).isNotNull(); + assertThat(aliceResult.getError().getMessage()).contains("Error finding privacy group"); + } + + @Test + public void blockParamShouldBeApplied() { + waitForBlockHeight(aliceNode, 2); + waitForBlockHeight(bobNode, 2); + + final String privacyGroupId = createFlexiblePrivacyGroup(aliceNode, bobNode); + + waitForBlockHeight(aliceNode, 10); + waitForBlockHeight(bobNode, 10); + + final Hash aliceResult1 = + aliceNode.execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "1")).getResult(); + final Hash bobResultInt1 = + bobNode.execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "1")).getResult(); + + assertThat(aliceResult1).isEqualTo(bobResultInt1); + + final Hash aliceResultLatest = + aliceNode + .execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "latest")) + .getResult(); + + final Hash bobResultLatest = + bobNode + .execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "latest")) + .getResult(); + + assertThat(aliceResultLatest).isEqualTo(bobResultLatest); + assertThat(aliceResult1).isNotEqualTo(aliceResultLatest); + } + + @Test + public void canInteractWithPrivateGenesisPreCompile() throws Exception { + final String privacyGroupId = createFlexiblePrivacyGroup(aliceNode, bobNode); + + final EventEmitter eventEmitter = + aliceNode.execute( + privateContractTransactions.loadSmartContractWithPrivacyGroupId( + "0x1000000000000000000000000000000000000001", + EventEmitter.class, + aliceNode.getTransactionSigningKey(), + aliceNode.getEnclaveKey(), + privacyGroupId)); + + privateTransactionVerifier.existingPrivateTransactionReceipt( + eventEmitter.store(BigInteger.valueOf(42)).send().getTransactionHash()); + + final String aliceResponse = + aliceNode + .execute( + privacyTransactions.privCall( + privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall())) + .getValue(); + + assertThat(new BigInteger(aliceResponse.substring(2), 16)) + .isEqualByComparingTo(BigInteger.valueOf(42)); + + final String bobResponse = + bobNode + .execute( + privacyTransactions.privCall( + privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall())) + .getValue(); + + assertThat(new BigInteger(bobResponse.substring(2), 16)) + .isEqualByComparingTo(BigInteger.valueOf(42)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivDebugGetStateRootOffchainGroupAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivDebugGetStateRootOffchainGroupAcceptanceTest.java index 7570bdf120d..92643446ddb 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivDebugGetStateRootOffchainGroupAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivDebugGetStateRootOffchainGroupAcceptanceTest.java @@ -15,33 +15,62 @@ package org.hyperledger.besu.tests.acceptance.privacy; import static org.assertj.core.api.Assertions.assertThat; +import static org.web3j.utils.Restriction.UNRESTRICTED; -import org.hyperledger.besu.ethereum.core.Hash; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase; import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; import java.io.IOException; -import java.net.URISyntaxException; +import java.util.Optional; import org.apache.tuweni.bytes.Bytes32; -import org.junit.Before; import org.junit.Test; +import org.testcontainers.containers.Network; +import org.web3j.utils.Restriction; -public class PrivDebugGetStateRootOffchainGroupAcceptanceTest extends PrivacyAcceptanceTestBase { +public class PrivDebugGetStateRootOffchainGroupAcceptanceTest extends ParameterizedEnclaveTestBase { - private PrivacyNode aliceNode; - private PrivacyNode bobNode; + private final PrivacyNode aliceNode; + private final PrivacyNode bobNode; + + public PrivDebugGetStateRootOffchainGroupAcceptanceTest( + final Restriction restriction, + final EnclaveType enclaveType, + final EnclaveEncryptorType enclaveEncryptorType) + throws IOException { + + super(restriction, enclaveType, enclaveEncryptorType); + + final Network containerNetwork = Network.newNetwork(); - @Before - public void setUp() throws IOException, URISyntaxException { aliceNode = - privacyBesu.createPrivateTransactionEnabledMinerNode( - "alice-node", PrivacyAccountResolver.ALICE); + privacyBesu.createIbft2NodePrivacyEnabled( + "alice-node", + PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType), + false, + enclaveType, + Optional.of(containerNetwork), + false, + false, + restriction == UNRESTRICTED, + "0xAA"); bobNode = - privacyBesu.createPrivateTransactionEnabledMinerNode( - "bob-node", PrivacyAccountResolver.BOB); + privacyBesu.createIbft2NodePrivacyEnabled( + "bob-node", + PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType), + false, + enclaveType, + Optional.of(containerNetwork), + false, + false, + restriction == UNRESTRICTED, + "0xBB"); + privacyCluster.start(aliceNode, bobNode); } @@ -49,8 +78,7 @@ public void setUp() throws IOException, URISyntaxException { public void nodesInGroupShouldHaveSameStateRoot() { final String privacyGroupId = aliceNode.execute( - privacyTransactions.createPrivacyGroup( - "testGroup", "A group for everyone", aliceNode, bobNode)); + createPrivacyGroup("testGroup", "A group for everyone", aliceNode, bobNode)); final Hash aliceStateRootId = aliceNode @@ -67,14 +95,16 @@ public void nodesInGroupShouldHaveSameStateRoot() { @Test public void unknownGroupShouldReturnError() { - final PrivacyRequestFactory.DebugGetStateRoot aliceResult = - aliceNode.execute( - privacyTransactions.debugGetStateRoot( - Hash.wrap(Bytes32.random()).toBase64String(), "latest")); + if (restriction != UNRESTRICTED) { + final PrivacyRequestFactory.DebugGetStateRoot aliceResult = + aliceNode.execute( + privacyTransactions.debugGetStateRoot( + Hash.wrap(Bytes32.random()).toBase64String(), "latest")); - assertThat(aliceResult.getResult()).isNull(); - assertThat(aliceResult.hasError()).isTrue(); - assertThat(aliceResult.getError()).isNotNull(); - assertThat(aliceResult.getError().getMessage()).contains("Error finding privacy group"); + assertThat(aliceResult.getResult()).isNull(); + assertThat(aliceResult.hasError()).isTrue(); + assertThat(aliceResult.getError()).isNotNull(); + assertThat(aliceResult.getError().getMessage()).contains("Error finding privacy group"); + } } } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivDebugGetStateRootOnchainGroupAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivDebugGetStateRootOnchainGroupAcceptanceTest.java deleted file mode 100644 index d5dfc9f2585..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivDebugGetStateRootOnchainGroupAcceptanceTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.privacy; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory; -import org.hyperledger.besu.tests.web3j.privacy.OnChainPrivacyAcceptanceTestBase; - -import java.io.IOException; -import java.net.URISyntaxException; - -import org.apache.tuweni.bytes.Bytes32; -import org.junit.Before; -import org.junit.Test; - -public class PrivDebugGetStateRootOnchainGroupAcceptanceTest - extends OnChainPrivacyAcceptanceTestBase { - - private PrivacyNode aliceNode; - private PrivacyNode bobNode; - - @Before - public void setUp() throws IOException, URISyntaxException { - aliceNode = - privacyBesu.createOnChainPrivacyGroupEnabledMinerNode( - "alice-node", PrivacyAccountResolver.ALICE, Address.PRIVACY, false); - bobNode = - privacyBesu.createOnChainPrivacyGroupEnabledMinerNode( - "bob-node", PrivacyAccountResolver.BOB, Address.PRIVACY, false); - privacyCluster.start(aliceNode, bobNode); - } - - @Test - public void nodesInGroupShouldHaveSameStateRoot() { - final String privacyGroupId = createOnChainPrivacyGroup(aliceNode, bobNode); - - final Hash aliceStateRootId = - aliceNode - .execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "latest")) - .getResult(); - - final Hash bobStateRootId = - bobNode - .execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "latest")) - .getResult(); - - assertThat(aliceStateRootId).isEqualTo(bobStateRootId); - } - - @Test - public void unknownGroupShouldReturnError() { - final PrivacyRequestFactory.DebugGetStateRoot aliceResult = - aliceNode.execute( - privacyTransactions.debugGetStateRoot( - Hash.wrap(Bytes32.random()).toBase64String(), "latest")); - - assertThat(aliceResult.getResult()).isNull(); - assertThat(aliceResult.hasError()).isTrue(); - assertThat(aliceResult.getError()).isNotNull(); - assertThat(aliceResult.getError().getMessage()).contains("Error finding privacy group"); - } - - @Test - public void blockParamShouldBeApplied() { - waitForBlockHeight(aliceNode, 2); - waitForBlockHeight(bobNode, 2); - - final String privacyGroupId = createOnChainPrivacyGroup(aliceNode, bobNode); - - waitForBlockHeight(aliceNode, 10); - waitForBlockHeight(bobNode, 10); - - final Hash aliceResult1 = - aliceNode.execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "1")).getResult(); - final Hash bobResultInt1 = - bobNode.execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "1")).getResult(); - - assertThat(aliceResult1).isEqualTo(bobResultInt1); - - final Hash aliceResultLatest = - aliceNode - .execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "latest")) - .getResult(); - - final Hash bobResultLatest = - bobNode - .execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "latest")) - .getResult(); - - assertThat(aliceResultLatest).isEqualTo(bobResultLatest); - assertThat(aliceResult1).isNotEqualTo(aliceResultLatest); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivGetCodeAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivGetCodeAcceptanceTest.java new file mode 100644 index 00000000000..c08006f694b --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivGetCodeAcceptanceTest.java @@ -0,0 +1,101 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.web3j.utils.Restriction.UNRESTRICTED; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.io.IOException; +import java.util.Optional; + +import org.apache.tuweni.bytes.Bytes; +import org.junit.Test; +import org.web3j.utils.Restriction; + +public class PrivGetCodeAcceptanceTest extends ParameterizedEnclaveTestBase { + + private final PrivacyNode alice; + + public PrivGetCodeAcceptanceTest( + final Restriction restriction, + final EnclaveType enclaveType, + final EnclaveEncryptorType enclaveEncryptorType) + throws IOException { + + super(restriction, enclaveType, enclaveEncryptorType); + + alice = + privacyBesu.createPrivateTransactionEnabledMinerNode( + restriction + "-node", + PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType), + enclaveType, + Optional.empty(), + false, + false, + restriction == UNRESTRICTED); + + privacyCluster.start(alice); + } + + @Test + public void privGetCodeReturnsDeployedContractBytecode() { + final String privacyGroupId = createPrivacyGroup(); + final EventEmitter eventEmitterContract = deployPrivateContract(privacyGroupId); + + final Bytes deployedContractCode = + alice.execute( + privacyTransactions.privGetCode( + privacyGroupId, + Address.fromHexString(eventEmitterContract.getContractAddress()), + "latest")); + + assertThat(eventEmitterContract.getContractBinary()) + .contains(deployedContractCode.toUnprefixedHexString()); + } + + private EventEmitter deployPrivateContract(final String privacyGroupId) { + final EventEmitter eventEmitter = + alice.execute( + privateContractTransactions.createSmartContractWithPrivacyGroupId( + EventEmitter.class, + alice.getTransactionSigningKey(), + restriction, + alice.getEnclaveKey(), + privacyGroupId)); + + privateContractVerifier + .validPrivateContractDeployed( + eventEmitter.getContractAddress(), alice.getAddress().toString()) + .verify(eventEmitter); + return eventEmitter; + } + + private String createPrivacyGroup() { + final String privacyGroupId = + alice.execute(createPrivacyGroup("myGroupName", "my group description", alice)); + + assertThat(privacyGroupId).isNotNull(); + + return privacyGroupId; + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivGetLogsAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivGetLogsAcceptanceTest.java similarity index 79% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivGetLogsAcceptanceTest.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivGetLogsAcceptanceTest.java index fdda78067a8..62519385a2e 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivGetLogsAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivGetLogsAcceptanceTest.java @@ -12,25 +12,31 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.tests.web3j.privacy; +package org.hyperledger.besu.tests.acceptance.privacy; import static org.assertj.core.api.Assertions.assertThat; +import static org.web3j.utils.Restriction.UNRESTRICTED; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase; import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; import org.hyperledger.besu.tests.acceptance.dsl.privacy.util.LogFilterJsonParameter; import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; +import java.io.IOException; import java.math.BigInteger; import java.util.List; +import java.util.Optional; -import org.junit.Before; import org.junit.Test; import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; import org.web3j.protocol.core.methods.response.EthLog.LogResult; +import org.web3j.utils.Restriction; @SuppressWarnings("rawtypes") -public class PrivGetLogsAcceptanceTest extends PrivacyAcceptanceTestBase { +public class PrivGetLogsAcceptanceTest extends ParameterizedEnclaveTestBase { /* This value is derived from the contract event signature @@ -38,13 +44,26 @@ public class PrivGetLogsAcceptanceTest extends PrivacyAcceptanceTestBase { private static final String EVENT_EMITTER_EVENT_TOPIC = "0xc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f5"; - private PrivacyNode node; + private final PrivacyNode node; + + public PrivGetLogsAcceptanceTest( + final Restriction restriction, + final EnclaveType enclaveType, + final EnclaveEncryptorType enclaveEncryptorType) + throws IOException { + + super(restriction, enclaveType, enclaveEncryptorType); - @Before - public void setUp() throws Exception { node = privacyBesu.createPrivateTransactionEnabledMinerNode( - "miner-node", privacyAccountResolver.resolve(0)); + restriction + "-node", + PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType), + enclaveType, + Optional.empty(), + false, + false, + restriction == UNRESTRICTED); + privacyCluster.start(node); } @@ -113,8 +132,7 @@ private LogFilterJsonParameter blockHashLogFilter( } private String createPrivacyGroup() { - return node.execute( - privacyTransactions.createPrivacyGroup("myGroupName", "my group description", node)); + return node.execute(createPrivacyGroup("myGroupName", "my group description", node)); } private EventEmitter deployEventEmitterContract(final String privacyGroupId) { @@ -123,7 +141,7 @@ private EventEmitter deployEventEmitterContract(final String privacyGroupId) { privateContractTransactions.createSmartContractWithPrivacyGroupId( EventEmitter.class, node.getTransactionSigningKey(), - POW_CHAIN_ID, + restriction, node.getEnclaveKey(), privacyGroupId)); @@ -143,7 +161,7 @@ private PrivateTransactionReceipt updateContractValue( eventEmitterContract.getContractAddress(), eventEmitterContract.store(BigInteger.valueOf(value)).encodeFunctionCall(), node.getTransactionSigningKey(), - POW_CHAIN_ID, + restriction, node.getEnclaveKey(), privacyGroupId)); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivGetPrivateTransactionAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivGetPrivateTransactionAcceptanceTest.java new file mode 100644 index 00000000000..91896761d09 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivGetPrivateTransactionAcceptanceTest.java @@ -0,0 +1,150 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import static org.web3j.utils.Restriction.RESTRICTED; +import static org.web3j.utils.Restriction.UNRESTRICTED; + +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; +import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.io.IOException; +import java.util.Optional; + +import org.apache.tuweni.bytes.Bytes; +import org.junit.Test; +import org.testcontainers.containers.Network; +import org.web3j.utils.Restriction; + +public class PrivGetPrivateTransactionAcceptanceTest extends ParameterizedEnclaveTestBase { + + private final PrivacyNode alice; + private final PrivacyNode bob; + + public PrivGetPrivateTransactionAcceptanceTest( + final Restriction restriction, + final EnclaveType enclaveType, + final EnclaveEncryptorType enclaveEncryptorType) + throws IOException { + + super(restriction, enclaveType, enclaveEncryptorType); + + final Network containerNetwork = Network.newNetwork(); + + alice = + privacyBesu.createIbft2NodePrivacyEnabled( + "node1", + PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType), + false, + enclaveType, + Optional.of(containerNetwork), + false, + false, + restriction == UNRESTRICTED, + "0xAA"); + bob = + privacyBesu.createIbft2NodePrivacyEnabled( + "node2", + PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType), + false, + enclaveType, + Optional.of(containerNetwork), + false, + false, + restriction == UNRESTRICTED, + "0xBB"); + + privacyCluster.start(alice, bob); + } + + @Test + public void returnsTransaction() { + final Transaction onlyAlice = createPrivacyGroup("Only Alice", "", alice); + + final String privacyGroupId = alice.execute(onlyAlice); + + final PrivateTransaction validSignedPrivateTransaction = + getValidSignedPrivateTransaction(alice, privacyGroupId); + final BytesValueRLPOutput rlpOutput = getRLPOutput(validSignedPrivateTransaction); + + final Hash transactionHash = + alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString())); + + alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash.toString())); + + alice + .getBesu() + .verify(priv.getPrivateTransaction(transactionHash, validSignedPrivateTransaction)); + } + + @Test + public void nonExistentHashReturnsNull() { + alice.getBesu().verify(priv.getPrivateTransactionReturnsNull(Hash.ZERO)); + } + + @Test + public void returnsNullTransactionNotInNodesPrivacyGroup() { + final Transaction onlyAlice = createPrivacyGroup("Only Alice", "", alice); + + final String privacyGroupId = alice.execute(onlyAlice); + + final PrivateTransaction validSignedPrivateTransaction = + getValidSignedPrivateTransaction(alice, privacyGroupId); + final BytesValueRLPOutput rlpOutput = getRLPOutput(validSignedPrivateTransaction); + + final Hash transactionHash = + alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString())); + + alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash.toString())); + + bob.getBesu().verify(priv.getPrivateTransactionReturnsNull(transactionHash)); + } + + private BytesValueRLPOutput getRLPOutput(final PrivateTransaction privateTransaction) { + final BytesValueRLPOutput bvrlpo = new BytesValueRLPOutput(); + privateTransaction.writeTo(bvrlpo); + return bvrlpo; + } + + private PrivateTransaction getValidSignedPrivateTransaction( + final PrivacyNode node, final String privacyGoupId) { + + org.hyperledger.besu.plugin.data.Restriction besuRestriction = + restriction == RESTRICTED + ? org.hyperledger.besu.plugin.data.Restriction.RESTRICTED + : org.hyperledger.besu.plugin.data.Restriction.UNRESTRICTED; + + return PrivateTransaction.builder() + .nonce(0) + .gasPrice(Wei.of(999999)) + .gasLimit(3000000) + .to(null) + .value(Wei.ZERO) + .payload(Bytes.wrap(new byte[] {})) + .sender(node.getAddress()) + .privateFrom(Bytes.fromBase64String(node.getEnclaveKey())) + .restriction(besuRestriction) + .privacyGroupId(Bytes.fromBase64String(privacyGoupId)) + .signAndBuild(node.getBesu().getPrivacyParameters().getSigningKeyPair().get()); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivacyClusterAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivacyClusterAcceptanceTest.java new file mode 100644 index 00000000000..1284daf917e --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivacyClusterAcceptanceTest.java @@ -0,0 +1,402 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.core.PrivacyParameters.DEFAULT_PRIVACY; +import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.EC; +import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.NACL; +import static org.hyperledger.enclave.testutil.EnclaveType.TESSERA; +import static org.web3j.utils.Restriction.RESTRICTED; + +import org.hyperledger.besu.enclave.Enclave; +import org.hyperledger.besu.enclave.EnclaveFactory; +import org.hyperledger.besu.enclave.types.ReceiveResponse; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Optional; + +import io.vertx.core.Vertx; +import org.apache.tuweni.bytes.Bytes; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.testcontainers.containers.Network; +import org.web3j.crypto.Credentials; +import org.web3j.crypto.RawTransaction; +import org.web3j.crypto.TransactionEncoder; +import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; +import org.web3j.protocol.eea.crypto.PrivateTransactionEncoder; +import org.web3j.protocol.eea.crypto.RawPrivateTransaction; +import org.web3j.utils.Base64String; +import org.web3j.utils.Numeric; + +@RunWith(Parameterized.class) +public class PrivacyClusterAcceptanceTest extends PrivacyAcceptanceTestBase { + + private final PrivacyNode alice; + private final PrivacyNode bob; + private final PrivacyNode charlie; + private final EnclaveEncryptorType enclaveEncryptorType; + private final Vertx vertx = Vertx.vertx(); + private final EnclaveFactory enclaveFactory = new EnclaveFactory(vertx); + + @Parameters(name = "{0} enclave type with {1} encryptor") + public static Collection enclaveParameters() { + return Arrays.asList( + new Object[][] { + {TESSERA, NACL}, + {TESSERA, EC} + }); + } + + public PrivacyClusterAcceptanceTest( + final EnclaveType enclaveType, final EnclaveEncryptorType enclaveEncryptorType) + throws IOException { + this.enclaveEncryptorType = enclaveEncryptorType; + final Network containerNetwork = Network.newNetwork(); + alice = + privacyBesu.createPrivateTransactionEnabledMinerNode( + "node1", + PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType), + enclaveType, + Optional.of(containerNetwork), + false, + false, + false); + bob = + privacyBesu.createPrivateTransactionEnabledNode( + "node2", + PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType), + enclaveType, + Optional.of(containerNetwork), + false, + false, + false); + charlie = + privacyBesu.createPrivateTransactionEnabledNode( + "node3", + PrivacyAccountResolver.CHARLIE.resolve(enclaveEncryptorType), + enclaveType, + Optional.of(containerNetwork), + false, + false, + false); + privacyCluster.start(alice, bob, charlie); + } + + @After + public void cleanUp() { + vertx.close(); + } + + @Test + public void onlyAliceAndBobCanExecuteContract() { + // Contract address is generated from sender address and transaction nonce + final String contractAddress = + EnclaveEncryptorType.EC.equals(enclaveEncryptorType) + ? "0x3e5d325a03ad3ce5640502219833d30b89ce3ce1" + : "0xebf56429e6500e84442467292183d4d621359838"; + + final EventEmitter eventEmitter = + alice.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + privateContractVerifier + .validPrivateContractDeployed(contractAddress, alice.getAddress().toString()) + .verify(eventEmitter); + + final String transactionHash = + alice.execute( + privateContractTransactions.callSmartContract( + eventEmitter.getContractAddress(), + eventEmitter.store(BigInteger.ONE).encodeFunctionCall(), + alice.getTransactionSigningKey(), + RESTRICTED, + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + final PrivateTransactionReceipt expectedReceipt = + alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash)); + + bob.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + transactionHash, expectedReceipt)); + + charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(transactionHash)); + + // When Alice executes a contract call in the wrong privacy group the transaction should pass + // but it should NOT return any output + final String transactionHash2 = + alice.execute( + privateContractTransactions.callSmartContract( + eventEmitter.getContractAddress(), + eventEmitter.value().encodeFunctionCall(), + alice.getTransactionSigningKey(), + RESTRICTED, + alice.getEnclaveKey(), + charlie.getEnclaveKey())); + + final PrivateTransactionReceipt expectedReceipt2 = + alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash2)); + + assertThat(expectedReceipt2.getOutput()).isEqualTo("0x"); + + charlie.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + transactionHash2, expectedReceipt2)); + } + + @Test + public void aliceCanUsePrivDistributeTransaction() { + // Contract address is generated from sender address and transaction nonce + final String contractAddress = + EnclaveEncryptorType.EC.equals(enclaveEncryptorType) + ? "0x3e5d325a03ad3ce5640502219833d30b89ce3ce1" + : "0xebf56429e6500e84442467292183d4d621359838"; + + final RawPrivateTransaction rawPrivateTransaction = + RawPrivateTransaction.createContractTransaction( + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + Numeric.prependHexPrefix(EventEmitter.BINARY), + Base64String.wrap(alice.getEnclaveKey()), + Collections.singletonList(Base64String.wrap(bob.getEnclaveKey())), + RESTRICTED); + + final String signedPrivateTransaction = + Numeric.toHexString( + PrivateTransactionEncoder.signMessage( + rawPrivateTransaction, Credentials.create(alice.getTransactionSigningKey()))); + final String transactionKey = + alice.execute(privacyTransactions.privDistributeTransaction(signedPrivateTransaction)); + + final Enclave aliceEnclave = enclaveFactory.createVertxEnclave(alice.getEnclave().clientUrl()); + final ReceiveResponse aliceRR = + aliceEnclave.receive( + Bytes.fromHexString(transactionKey).toBase64String(), alice.getEnclaveKey()); + + final Enclave bobEnclave = enclaveFactory.createVertxEnclave(bob.getEnclave().clientUrl()); + final ReceiveResponse bobRR = + bobEnclave.receive( + Bytes.fromHexString(transactionKey).toBase64String(), bob.getEnclaveKey()); + + assertThat(bobRR).usingRecursiveComparison().isEqualTo(aliceRR); + + final RawTransaction pmt = + RawTransaction.createTransaction( + BigInteger.ZERO, + BigInteger.valueOf(1000), + BigInteger.valueOf(65000), + DEFAULT_PRIVACY.toString(), + transactionKey); + + final String signedPmt = + Numeric.toHexString( + TransactionEncoder.signMessage( + pmt, Credentials.create(alice.getTransactionSigningKey()))); + + final String transactionHash = alice.execute(ethTransactions.sendRawTransaction(signedPmt)); + + final String receiptPrivateFrom = + EnclaveEncryptorType.EC.equals(enclaveEncryptorType) + ? "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAES8nC4qT/KdoAoTSF3qs/47DUsDihyVbWiRjZAiyvqp9eSDkqV1RzlM+58oOwnpFRwvWNZM+AxMVxT+MvxdsqMA==" + : "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="; + final ArrayList receiptPrivateFor = + EnclaveEncryptorType.EC.equals(enclaveEncryptorType) + ? new ArrayList<>( + Collections.singletonList( + "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXIgZqRA25V+3nN+Do6b5r0jiUunub6ubjPhqwHpPxP44uUYh9RKCQNRnsqCJ9PjeTnC8R3ieJk7HWAlycU1bug==")) + : new ArrayList<>( + Collections.singletonList("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=")); + final String receiptPrivacyGroupId = + EnclaveEncryptorType.EC.equals(enclaveEncryptorType) + ? "MjuFB4b9Hz+f8zvkWWasxZWRjHWXU4t7B2nOHo4mekA=" + : "DyAOiF/ynpc+JXa2YAGB0bCitSlOMNm+ShmB/7M6C4w="; + + final PrivateTransactionReceipt expectedReceipt = + new PrivateTransactionReceipt( + contractAddress, + "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + null, + null, // ignored in the following call, checked separately below + Collections.emptyList(), + "0x023955c49d6265c579561940287449242704d5fd239ff07ea36a3fc7aface61c", + "0x82e521ee16ff13104c5f81e8354ecaaafd5450b710b07f620204032bfe76041a", + receiptPrivateFrom, + receiptPrivateFor, + receiptPrivacyGroupId, + "0x1", + null); + + alice.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + transactionHash, expectedReceipt, true)); + + final PrivateTransactionReceipt alicePrivateTransactionReceipt = + alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash)); + assertThat(EventEmitter.BINARY) + .contains(alicePrivateTransactionReceipt.getOutput().substring(2)); + + bob.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + transactionHash, expectedReceipt, true)); + + final PrivateTransactionReceipt bobPrivateTransactionReceipt = + bob.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash)); + assertThat(EventEmitter.BINARY).contains(bobPrivateTransactionReceipt.getOutput().substring(2)); + } + + @Test + public void aliceCanDeployMultipleTimesInSingleGroup() { + final String firstDeployedAddress = + EnclaveEncryptorType.EC.equals(enclaveEncryptorType) + ? "0x3e5d325a03ad3ce5640502219833d30b89ce3ce1" + : "0xebf56429e6500e84442467292183d4d621359838"; + + final EventEmitter firstEventEmitter = + alice.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + privateContractVerifier + .validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString()) + .verify(firstEventEmitter); + + final String secondDeployedAddress = + EnclaveEncryptorType.EC.equals(enclaveEncryptorType) + ? "0x5194e214fae257530710d18c868df7a295d9d53b" + : "0x10f807f8a905da5bd319196da7523c6bd768690f"; + + final EventEmitter secondEventEmitter = + alice.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + privateContractVerifier + .validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString()) + .verify(secondEventEmitter); + } + + @Test + public void canInteractWithMultiplePrivacyGroups() { + // alice deploys contract + final String firstDeployedAddress = + EnclaveEncryptorType.EC.equals(enclaveEncryptorType) + ? "0x760359bc605b3848f5199829bde6b382d90fb8eb" + : "0xff206d21150a8da5b83629d8a722f3135ed532b1"; + + final EventEmitter firstEventEmitter = + alice.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + bob.getEnclaveKey(), + charlie.getEnclaveKey())); + + privateContractVerifier + .validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString()) + .verify(firstEventEmitter); + + // charlie interacts with contract + final String firstTransactionHash = + charlie.execute( + privateContractTransactions.callSmartContract( + firstEventEmitter.getContractAddress(), + firstEventEmitter.store(BigInteger.ONE).encodeFunctionCall(), + charlie.getTransactionSigningKey(), + RESTRICTED, + charlie.getEnclaveKey(), + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + // alice gets receipt from charlie's interaction + final PrivateTransactionReceipt firstExpectedReceipt = + alice.execute(privacyTransactions.getPrivateTransactionReceipt(firstTransactionHash)); + + // verify bob and charlie have access to the same receipt + bob.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + firstTransactionHash, firstExpectedReceipt)); + charlie.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + firstTransactionHash, firstExpectedReceipt)); + + // alice deploys second contract + final String secondDeployedAddress = + EnclaveEncryptorType.EC.equals(enclaveEncryptorType) + ? "0x3e5d325a03ad3ce5640502219833d30b89ce3ce1" + : "0xebf56429e6500e84442467292183d4d621359838"; + + final EventEmitter secondEventEmitter = + alice.execute( + privateContractTransactions.createSmartContract( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + bob.getEnclaveKey())); + + privateContractVerifier + .validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString()) + .verify(secondEventEmitter); + + // bob interacts with contract + final String secondTransactionHash = + bob.execute( + privateContractTransactions.callSmartContract( + secondEventEmitter.getContractAddress(), + secondEventEmitter.store(BigInteger.ONE).encodeFunctionCall(), + bob.getTransactionSigningKey(), + RESTRICTED, + bob.getEnclaveKey(), + alice.getEnclaveKey())); + + // alice gets receipt from bob's interaction + final PrivateTransactionReceipt secondExpectedReceipt = + alice.execute(privacyTransactions.getPrivateTransactionReceipt(secondTransactionHash)); + + bob.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + secondTransactionHash, secondExpectedReceipt)); + + // charlie cannot see the receipt + charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(secondTransactionHash)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivacyGroupAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivacyGroupAcceptanceTest.java new file mode 100644 index 00000000000..a1739b1fc8d --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivacyGroupAcceptanceTest.java @@ -0,0 +1,251 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.EC; +import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.NACL; +import static org.hyperledger.enclave.testutil.EnclaveType.TESSERA; +import static org.web3j.utils.Restriction.RESTRICTED; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.besu.util.LogConfigurator; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Collection; +import java.util.Optional; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.testcontainers.containers.Network; +import org.web3j.protocol.besu.response.privacy.PrivacyGroup; +import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; +import org.web3j.utils.Base64String; + +@RunWith(Parameterized.class) +public class PrivacyGroupAcceptanceTest extends PrivacyAcceptanceTestBase { + + private final PrivacyNode alice; + private final PrivacyNode bob; + private final PrivacyNode charlie; + + @Parameters(name = "{0} enclave type with {1} encryptor") + public static Collection enclaveParameters() { + return Arrays.asList( + new Object[][] { + {TESSERA, NACL}, + {TESSERA, EC} + }); + } + + public PrivacyGroupAcceptanceTest( + final EnclaveType enclaveType, final EnclaveEncryptorType enclaveEncryptorType) + throws IOException { + + final Network containerNetwork = Network.newNetwork(); + + alice = + privacyBesu.createPrivateTransactionEnabledMinerNode( + "node1", + PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType), + enclaveType, + Optional.of(containerNetwork), + false, + false, + false); + bob = + privacyBesu.createPrivateTransactionEnabledNode( + "node2", + PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType), + enclaveType, + Optional.of(containerNetwork), + false, + false, + false); + + charlie = + privacyBesu.createPrivateTransactionEnabledNode( + "node3", + PrivacyAccountResolver.CHARLIE.resolve(enclaveEncryptorType), + enclaveType, + Optional.of(containerNetwork), + false, + false, + false); + privacyCluster.start(alice, bob, charlie); + } + + @Test + public void nodeCanCreatePrivacyGroup() { + LogConfigurator.setLevel("", "DEBUG"); + final String privacyGroupId = + alice.execute( + privacyTransactions.createPrivacyGroup( + "myGroupName", "my group description", alice, bob)); + + assertThat(privacyGroupId).isNotNull(); + + final PrivacyGroup expected = + new PrivacyGroup( + privacyGroupId, + PrivacyGroup.Type.PANTHEON, + "myGroupName", + "my group description", + Base64String.wrapList(alice.getEnclaveKey(), bob.getEnclaveKey())); + + alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); + + bob.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); + } + + @Test + public void nodeCanCreatePrivacyGroupWithoutName() { + final String privacyGroupId = + alice.execute( + privacyTransactions.createPrivacyGroup(null, "my group description", alice, bob)); + + assertThat(privacyGroupId).isNotNull(); + + final PrivacyGroup expected = + new PrivacyGroup( + privacyGroupId, + PrivacyGroup.Type.PANTHEON, + "", + "my group description", + Base64String.wrapList(alice.getEnclaveKey(), bob.getEnclaveKey())); + + alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); + + bob.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); + } + + @Test + public void nodeCanCreatePrivacyGroupWithoutDescription() { + final String privacyGroupId = + alice.execute(privacyTransactions.createPrivacyGroup("myGroupName", null, alice, bob)); + + assertThat(privacyGroupId).isNotNull(); + + final PrivacyGroup expected = + new PrivacyGroup( + privacyGroupId, + PrivacyGroup.Type.PANTHEON, + "myGroupName", + "", + Base64String.wrapList(alice.getEnclaveKey(), bob.getEnclaveKey())); + + alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); + + bob.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); + } + + @Test + public void nodeCanCreatePrivacyGroupWithoutOptionalParams() { + final String privacyGroupId = + alice.execute(privacyTransactions.createPrivacyGroup(null, null, alice)); + + assertThat(privacyGroupId).isNotNull(); + + final PrivacyGroup expected = + new PrivacyGroup( + privacyGroupId, + PrivacyGroup.Type.PANTHEON, + "", + "", + Base64String.wrapList(alice.getEnclaveKey())); + + alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); + } + + @Test + public void canInteractWithMultiplePrivacyGroups() { + final String privacyGroupIdABC = + alice.execute(privacyTransactions.createPrivacyGroup(null, null, alice, bob, charlie)); + + final EventEmitter firstEventEmitter = + alice.execute( + privateContractTransactions.createSmartContractWithPrivacyGroupId( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + privacyGroupIdABC)); + + // charlie interacts with contract + final String firstTransactionHash = + charlie.execute( + privateContractTransactions.callSmartContractWithPrivacyGroupId( + firstEventEmitter.getContractAddress(), + firstEventEmitter.store(BigInteger.ONE).encodeFunctionCall(), + charlie.getTransactionSigningKey(), + RESTRICTED, + charlie.getEnclaveKey(), + privacyGroupIdABC)); + + // alice gets receipt from charlie's interaction + final PrivateTransactionReceipt firstExpectedReceipt = + alice.execute(privacyTransactions.getPrivateTransactionReceipt(firstTransactionHash)); + + // verify bob and charlie have access to the same receipt + bob.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + firstTransactionHash, firstExpectedReceipt)); + charlie.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + firstTransactionHash, firstExpectedReceipt)); + + // alice deploys second contract + final String privacyGroupIdAB = + alice.execute(privacyTransactions.createPrivacyGroup(null, null, alice, bob)); + + final EventEmitter secondEventEmitter = + alice.execute( + privateContractTransactions.createSmartContractWithPrivacyGroupId( + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + privacyGroupIdAB)); + + // bob interacts with contract + final String secondTransactionHash = + bob.execute( + privateContractTransactions.callSmartContractWithPrivacyGroupId( + secondEventEmitter.getContractAddress(), + secondEventEmitter.store(BigInteger.ONE).encodeFunctionCall(), + bob.getTransactionSigningKey(), + RESTRICTED, + bob.getEnclaveKey(), + privacyGroupIdAB)); + + // alice gets receipt from bob's interaction + final PrivateTransactionReceipt secondExpectedReceipt = + alice.execute(privacyTransactions.getPrivateTransactionReceipt(secondTransactionHash)); + + bob.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + secondTransactionHash, secondExpectedReceipt)); + + // charlie cannot see the receipt + charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(secondTransactionHash)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivacyReceiptAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivacyReceiptAcceptanceTest.java new file mode 100644 index 00000000000..0b45d29732a --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivacyReceiptAcceptanceTest.java @@ -0,0 +1,163 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import static java.util.Optional.empty; +import static org.web3j.utils.Restriction.RESTRICTED; +import static org.web3j.utils.Restriction.UNRESTRICTED; + +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; +import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.miner.MinerTransactions; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.io.IOException; +import java.util.Optional; + +import org.apache.tuweni.bytes.Bytes; +import org.junit.Test; +import org.web3j.utils.Restriction; + +public class PrivacyReceiptAcceptanceTest extends ParameterizedEnclaveTestBase { + final MinerTransactions minerTransactions = new MinerTransactions(); + + private final PrivacyNode alice; + + public PrivacyReceiptAcceptanceTest( + final Restriction restriction, + final EnclaveType enclaveType, + final EnclaveEncryptorType enclaveEncryptorType) + throws IOException { + super(restriction, enclaveType, enclaveEncryptorType); + + alice = + privacyBesu.createIbft2NodePrivacyEnabled( + "node1", + PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType), + false, + enclaveType, + Optional.empty(), + false, + false, + restriction == UNRESTRICTED, + "0xAA"); + privacyCluster.start(alice); + } + + @Test + public void createPrivateTransactionReceiptSuccessfulTransaction() { + final Transaction onlyAlice = createPrivacyGroup("Only Alice", "", alice); + + final String privacyGroupId = alice.execute(onlyAlice); + + final PrivateTransaction validTransaction = + createSignedTransaction(alice, privacyGroupId, empty()); + final BytesValueRLPOutput rlpOutput = getRLPOutput(validTransaction); + + final Hash transactionHash = + alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString())); + + // Successful PMT + alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash.toString())); + // Successful private transaction + alice.getBesu().verify(priv.getSuccessfulTransactionReceipt(transactionHash)); + } + + @Test + public void createPrivateTransactionReceiptFailedTransaction() { + final Transaction onlyAlice = createPrivacyGroup("Only Alice", "", alice); + + final String privacyGroupId = alice.execute(onlyAlice); + + final PrivateTransaction invalidPayloadTransaction = + createSignedTransaction( + alice, privacyGroupId, Optional.of(Bytes.fromBase64String("invalidPayload"))); + final BytesValueRLPOutput rlpOutput = getRLPOutput(invalidPayloadTransaction); + + final Hash transactionHash = + alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString())); + + // Successful PMT + alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash.toString())); + // Failed private transaction + alice.getBesu().verify(priv.getFailedTransactionReceipt(transactionHash)); + } + + @Test + public void createPrivateTransactionReceiptInvalidTransaction() { + final Transaction onlyAlice = createPrivacyGroup("Only Alice", "", alice); + + final String privacyGroupId = alice.execute(onlyAlice); + + final PrivateTransaction validTransaction = + createSignedTransaction(alice, privacyGroupId, empty()); + final BytesValueRLPOutput rlpOutput = getRLPOutput(validTransaction); + + // Stop mining, to allow adding duplicate nonce block + alice.getBesu().execute(minerTransactions.minerStop()); + + final Hash transactionHash1 = + alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString())); + final Hash transactionHash2 = + alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString())); + + // Start mining again + alice.getBesu().execute(minerTransactions.minerStart()); + + // Successful PMTs + alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash1.toString())); + alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash2.toString())); + // Successful first private transaction + alice.getBesu().verify(priv.getSuccessfulTransactionReceipt(transactionHash1)); + // Invalid second private transaction + alice.getBesu().verify(priv.getInvalidTransactionReceipt(transactionHash2)); + } + + private BytesValueRLPOutput getRLPOutput(final PrivateTransaction privateTransaction) { + final BytesValueRLPOutput bvrlpo = new BytesValueRLPOutput(); + privateTransaction.writeTo(bvrlpo); + return bvrlpo; + } + + private PrivateTransaction createSignedTransaction( + final PrivacyNode node, final String privacyGoupId, final Optional payload) { + + org.hyperledger.besu.plugin.data.Restriction besuRestriction = + restriction == RESTRICTED + ? org.hyperledger.besu.plugin.data.Restriction.RESTRICTED + : org.hyperledger.besu.plugin.data.Restriction.UNRESTRICTED; + + final Bytes defaultPayload = Bytes.wrap(new byte[] {}); + return PrivateTransaction.builder() + .nonce(0) + .gasPrice(Wei.of(999999)) + .gasLimit(3000000) + .to(null) + .value(Wei.ZERO) + .payload(payload.orElse(defaultPayload)) + .sender(node.getAddress()) + .privateFrom(Bytes.fromBase64String(node.getEnclaveKey())) + .restriction(besuRestriction) + .privacyGroupId(Bytes.fromBase64String(privacyGoupId)) + .signAndBuild(node.getBesu().getPrivacyParameters().getSigningKeyPair().get()); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivateContractPublicStateAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivateContractPublicStateAcceptanceTest.java new file mode 100644 index 00000000000..83a7ce66d8b --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivateContractPublicStateAcceptanceTest.java @@ -0,0 +1,222 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.web3j.utils.Restriction.UNRESTRICTED; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.web3j.generated.CrossContractReader; +import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.besu.tests.web3j.generated.RemoteSimpleStorage; +import org.hyperledger.besu.tests.web3j.generated.SimpleStorage; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Optional; + +import org.junit.Test; +import org.testcontainers.containers.Network; +import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; +import org.web3j.protocol.core.RemoteFunctionCall; +import org.web3j.protocol.core.methods.response.TransactionReceipt; +import org.web3j.protocol.exceptions.TransactionException; +import org.web3j.tx.exceptions.ContractCallException; +import org.web3j.utils.Restriction; + +public class PrivateContractPublicStateAcceptanceTest extends ParameterizedEnclaveTestBase { + + private final PrivacyNode transactionNode; + + public PrivateContractPublicStateAcceptanceTest( + final Restriction restriction, + final EnclaveType enclaveType, + final EnclaveEncryptorType enclaveEncryptorType) + throws IOException { + super(restriction, enclaveType, enclaveEncryptorType); + final Network containerNetwork = Network.newNetwork(); + + final PrivacyNode minerNode = + privacyBesu.createPrivateTransactionEnabledMinerNode( + restriction + "-miner-node", + PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType), + enclaveType, + Optional.of(containerNetwork), + false, + false, + restriction == UNRESTRICTED); + + transactionNode = + privacyBesu.createPrivateTransactionEnabledNode( + restriction + "-transaction-node", + PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType), + enclaveType, + Optional.of(containerNetwork), + false, + false, + restriction == UNRESTRICTED); + + privacyCluster.start(minerNode, transactionNode); + } + + @Test + public void mustAllowAccessToPublicStateFromPrivateTx() throws Exception { + final EventEmitter publicEventEmitter = + transactionNode.execute(contractTransactions.createSmartContract(EventEmitter.class)); + + final TransactionReceipt receipt = publicEventEmitter.store(BigInteger.valueOf(12)).send(); + assertThat(receipt).isNotNull(); + + final CrossContractReader reader = + transactionNode.execute( + privateContractTransactions.createSmartContract( + CrossContractReader.class, + transactionNode.getTransactionSigningKey(), + transactionNode.getEnclaveKey())); + + final RemoteFunctionCall remoteFunctionCall = + reader.read(publicEventEmitter.getContractAddress()); + final BigInteger result = remoteFunctionCall.send(); + + assertThat(result).isEqualTo(BigInteger.valueOf(12)); + } + + @Test + public void mustNotAllowAccessToPrivateStateFromPublicTx() throws Exception { + final EventEmitter privateEventEmitter = + transactionNode.execute( + (privateContractTransactions.createSmartContract( + EventEmitter.class, + transactionNode.getTransactionSigningKey(), + transactionNode.getEnclaveKey()))); + + final TransactionReceipt receipt = privateEventEmitter.store(BigInteger.valueOf(12)).send(); + assertThat(receipt).isNotNull(); + + final CrossContractReader publicReader = + transactionNode.execute( + contractTransactions.createSmartContract(CrossContractReader.class)); + final RemoteFunctionCall functionCall = + publicReader.read(privateEventEmitter.getContractAddress()); + assertThatThrownBy(functionCall::send).isInstanceOf(ContractCallException.class); + } + + @Test + public void privateContractMustNotBeAbleToCallPublicContractWhichChangesState() throws Exception { + final CrossContractReader privateReader = + transactionNode.execute( + privateContractTransactions.createSmartContract( + CrossContractReader.class, + transactionNode.getTransactionSigningKey(), + transactionNode.getEnclaveKey())); + + final CrossContractReader publicReader = + transactionNode.execute( + contractTransactions.createSmartContract(CrossContractReader.class)); + + assertThatExceptionOfType(TransactionException.class) + .isThrownBy(() -> privateReader.incrementRemote(publicReader.getContractAddress()).send()) + .returns( + "0x", e -> ((PrivateTransactionReceipt) e.getTransactionReceipt().get()).getOutput()); + } + + @Test + public void privateContractMustNotBeAbleToCallPublicContractWhichInstantiatesContract() + throws Exception { + final CrossContractReader privateReader = + transactionNode.execute( + privateContractTransactions.createSmartContract( + CrossContractReader.class, + transactionNode.getTransactionSigningKey(), + transactionNode.getEnclaveKey())); + + final CrossContractReader publicReader = + transactionNode.execute( + contractTransactions.createSmartContract(CrossContractReader.class)); + + assertThatExceptionOfType(TransactionException.class) + .isThrownBy(() -> privateReader.deployRemote(publicReader.getContractAddress()).send()) + .returns(0, e -> e.getTransactionReceipt().get().getLogs().size()); + } + + @Test + public void privateContractMustNotBeAbleToCallSelfDestructOnPublicContract() throws Exception { + final CrossContractReader privateReader = + transactionNode.execute( + privateContractTransactions.createSmartContract( + CrossContractReader.class, + transactionNode.getTransactionSigningKey(), + transactionNode.getEnclaveKey())); + + final CrossContractReader publicReader = + transactionNode + .getBesu() + .execute(contractTransactions.createSmartContract(CrossContractReader.class)); + + assertThatExceptionOfType(TransactionException.class) + .isThrownBy(() -> privateReader.remoteDestroy(publicReader.getContractAddress()).send()) + .withMessage( + "Transaction null has failed with status: 0x0. Gas used: unknown. Revert reason: '0x'.") + .returns( + "0x", e -> ((PrivateTransactionReceipt) e.getTransactionReceipt().get()).getOutput()); + } + + @Test + public void privateContractCanCallPublicContractThatCallsPublicContract() throws Exception { + final SimpleStorage simpleStorage = + transactionNode + .getBesu() + .execute(contractTransactions.createSmartContract(SimpleStorage.class)); + + final RemoteSimpleStorage remoteSimpleStorage = + transactionNode + .getBesu() + .execute(contractTransactions.createSmartContract(RemoteSimpleStorage.class)); + + remoteSimpleStorage.setRemote(simpleStorage.getContractAddress()).send(); + + final RemoteSimpleStorage reallyRemoteSimpleStorage = + transactionNode + .getBesu() + .execute(contractTransactions.createSmartContract(RemoteSimpleStorage.class)); + + reallyRemoteSimpleStorage.setRemote(remoteSimpleStorage.getContractAddress()).send(); + + simpleStorage.set(BigInteger.valueOf(42)).send(); + + assertThat(simpleStorage.get().send()).isEqualTo(BigInteger.valueOf(42)); + assertThat(remoteSimpleStorage.get().send()).isEqualTo(BigInteger.valueOf(42)); + assertThat(reallyRemoteSimpleStorage.get().send()).isEqualTo(BigInteger.valueOf(42)); + + final RemoteSimpleStorage privateRemoteSimpleStorage = + transactionNode.execute( + privateContractTransactions.createSmartContract( + RemoteSimpleStorage.class, + transactionNode.getTransactionSigningKey(), + transactionNode.getEnclaveKey())); + + privateRemoteSimpleStorage.setRemote(simpleStorage.getContractAddress()).send(); + assertThat(privateRemoteSimpleStorage.get().send()).isEqualTo(BigInteger.valueOf(42)); + + privateRemoteSimpleStorage.setRemote(reallyRemoteSimpleStorage.getContractAddress()).send(); + assertThat(privateRemoteSimpleStorage.get().send()).isEqualTo(BigInteger.valueOf(42)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivateGenesisAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivateGenesisAcceptanceTest.java new file mode 100644 index 00000000000..29d5b655e3c --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivateGenesisAcceptanceTest.java @@ -0,0 +1,99 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.web3j.utils.Restriction.RESTRICTED; +import static org.web3j.utils.Restriction.UNRESTRICTED; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Optional; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.web3j.protocol.core.methods.response.EthCall; +import org.web3j.utils.Restriction; + +@RunWith(Parameterized.class) +public class PrivateGenesisAcceptanceTest extends ParameterizedEnclaveTestBase { + private final PrivacyNode alice; + + public PrivateGenesisAcceptanceTest( + final Restriction restriction, + final EnclaveType enclaveType, + final EnclaveEncryptorType enclaveEncryptorType) + throws IOException { + + super(restriction, enclaveType, enclaveEncryptorType); + + alice = + privacyBesu.createIbft2NodePrivacyEnabledWithGenesis( + "node1", + PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType), + true, + enclaveType, + Optional.empty(), + false, + false, + restriction == UNRESTRICTED, + "AA"); + + privacyCluster.start(alice); + } + + @Test + public void canInteractWithPrivateGenesisPreCompile() throws Exception { + final String privacyGroupId = createPrivacyGroup(); + + final EventEmitter eventEmitter = + alice.execute( + privateContractTransactions.loadSmartContractWithPrivacyGroupId( + "0x1000000000000000000000000000000000000001", + EventEmitter.class, + alice.getTransactionSigningKey(), + alice.getEnclaveKey(), + privacyGroupId)); + + eventEmitter.store(BigInteger.valueOf(42)).send(); + + final EthCall response = + alice.execute( + privacyTransactions.privCall( + privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall())); + + final String value = response.getValue(); + + assertThat(new BigInteger(value.substring(2), 16)).isEqualByComparingTo(BigInteger.valueOf(42)); + } + + private String createPrivacyGroup() { + if (restriction == RESTRICTED) { + return alice.execute(privacyTransactions.createPrivacyGroup("name", "description", alice)); + } else if (restriction == UNRESTRICTED) { + return "gsvwYfGPurL7wgXKmgFtCamXarAl9fA5jaSXi8TLpJw="; + } else { + throw new RuntimeException("Do not know how to handle " + restriction); + } + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivateLogFilterAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivateLogFilterAcceptanceTest.java similarity index 79% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivateLogFilterAcceptanceTest.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivateLogFilterAcceptanceTest.java index 92ea8930496..a6837f95465 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivateLogFilterAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PrivateLogFilterAcceptanceTest.java @@ -12,34 +12,53 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.tests.web3j.privacy; +package org.hyperledger.besu.tests.acceptance.privacy; import static org.assertj.core.api.Assertions.assertThat; +import static org.web3j.utils.Restriction.UNRESTRICTED; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase; import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; import org.hyperledger.besu.tests.acceptance.dsl.privacy.util.LogFilterJsonParameter; import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; +import java.io.IOException; import java.math.BigInteger; import java.util.Collections; import java.util.List; +import java.util.Optional; -import org.junit.Before; import org.junit.Test; import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; import org.web3j.protocol.core.methods.response.EthLog.LogResult; +import org.web3j.utils.Restriction; @SuppressWarnings("rawtypes") -public class PrivateLogFilterAcceptanceTest extends PrivacyAcceptanceTestBase { +public class PrivateLogFilterAcceptanceTest extends ParameterizedEnclaveTestBase { - private PrivacyNode node; + private final PrivacyNode node; + + public PrivateLogFilterAcceptanceTest( + final Restriction restriction, + final EnclaveType enclaveType, + final EnclaveEncryptorType enclaveEncryptorType) + throws IOException { + + super(restriction, enclaveType, enclaveEncryptorType); - @Before - public void setUp() throws Exception { node = privacyBesu.createPrivateTransactionEnabledMinerNode( - "miner-node", privacyAccountResolver.resolve(0)); + restriction + "-node", + PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType), + enclaveType, + Optional.empty(), + false, + false, + restriction == UNRESTRICTED); + privacyCluster.start(node); } @@ -104,8 +123,7 @@ private LogFilterJsonParameter blockRangeLogFilter( } private String createPrivacyGroup() { - return node.execute( - privacyTransactions.createPrivacyGroup("myGroupName", "my group description", node)); + return node.execute(createPrivacyGroup("myGroupName", "my group description", node)); } private EventEmitter deployEventEmitterContract(final String privacyGroupId) { @@ -114,7 +132,7 @@ private EventEmitter deployEventEmitterContract(final String privacyGroupId) { privateContractTransactions.createSmartContractWithPrivacyGroupId( EventEmitter.class, node.getTransactionSigningKey(), - POW_CHAIN_ID, + restriction, node.getEnclaveKey(), privacyGroupId)); @@ -134,7 +152,7 @@ private PrivateTransactionReceipt updateContractValue( eventEmitterContract.getContractAddress(), eventEmitterContract.store(BigInteger.valueOf(value)).encodeFunctionCall(), node.getTransactionSigningKey(), - POW_CHAIN_ID, + restriction, node.getEnclaveKey(), privacyGroupId)); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/contracts/PrivacyGroupTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/contracts/PrivacyGroupTest.java similarity index 76% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/contracts/PrivacyGroupTest.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/contracts/PrivacyGroupTest.java index 53076db2ca6..b805fa43c4e 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/contracts/PrivacyGroupTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/contracts/PrivacyGroupTest.java @@ -12,11 +12,12 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.tests.web3j.privacy.contracts; +package org.hyperledger.besu.tests.acceptance.privacy.contracts; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; -import org.hyperledger.besu.privacy.contracts.generated.DefaultOnChainPrivacyGroupManagementContract; +import org.hyperledger.besu.privacy.contracts.generated.DefaultFlexiblePrivacyGroupManagementContract; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; @@ -24,8 +25,8 @@ import java.util.Collections; import java.util.List; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.web3j.protocol.core.RemoteFunctionCall; import org.web3j.protocol.core.methods.response.TransactionReceipt; import org.web3j.protocol.exceptions.TransactionException; @@ -40,13 +41,13 @@ public class PrivacyGroupTest extends AcceptanceTestBase { Base64String.wrap("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs="); private final Base64String thirdParticipant = Base64String.wrap("Jo2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs="); - private DefaultOnChainPrivacyGroupManagementContract defaultPrivacyGroupManagementContract; + private DefaultFlexiblePrivacyGroupManagementContract defaultPrivacyGroupManagementContract; private static final String RAW_FIRST_PARTICIPANT = "0x5aa68ac0"; private static final String RAW_ADD_PARTICIPANT = - "0xb4926e25000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000012a8d9b56a0fe9cd94d60be4413bcb721d3a7be27ed8e28b3a6346df874ee141b"; + "0x965a25ef00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000202a8d9b56a0fe9cd94d60be4413bcb721d3a7be27ed8e28b3a6346df874ee141b"; private static final String RAW_REMOVE_PARTICIPANT = - "0xfd0177972a8d9b56a0fe9cd94d60be4413bcb721d3a7be27ed8e28b3a6346df874ee141b"; + "0x1f52a8ee000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000202a8d9b56a0fe9cd94d60be4413bcb721d3a7be27ed8e28b3a6346df874ee141b"; private static final String RAW_LOCK = "0xf83d08ba"; private static final String RAW_UNLOCK = "0xa69df4b5"; private static final String RAW_CAN_EXECUTE = "0x78b90337"; @@ -54,14 +55,14 @@ public class PrivacyGroupTest extends AcceptanceTestBase { private BesuNode minerNode; - @Before + @BeforeEach public void setUp() throws Exception { minerNode = besu.createMinerNode("node"); cluster.start(minerNode); defaultPrivacyGroupManagementContract = minerNode.execute( contractTransactions.createSmartContract( - DefaultOnChainPrivacyGroupManagementContract.class)); + DefaultFlexiblePrivacyGroupManagementContract.class)); } @Test @@ -72,28 +73,28 @@ public void rlp() throws Exception { .validTransactionReceipt(contractAddress) .verify(defaultPrivacyGroupManagementContract); // 0x0b0235be - assertThat(RAW_FIRST_PARTICIPANT) - .isEqualTo(defaultPrivacyGroupManagementContract.getParticipants().encodeFunctionCall()); + assertThat(defaultPrivacyGroupManagementContract.getParticipants().encodeFunctionCall()) + .isEqualTo(RAW_FIRST_PARTICIPANT); // 0xf744b089 - assertThat(RAW_ADD_PARTICIPANT) - .isEqualTo( + assertThat( defaultPrivacyGroupManagementContract .addParticipants(Collections.singletonList(secondParticipant.raw())) - .encodeFunctionCall()); + .encodeFunctionCall()) + .isEqualTo(RAW_ADD_PARTICIPANT); // 0xf744b089 - assertThat(RAW_REMOVE_PARTICIPANT) - .isEqualTo( + assertThat( defaultPrivacyGroupManagementContract .removeParticipant(secondParticipant.raw()) - .encodeFunctionCall()); - assertThat(RAW_LOCK) - .isEqualTo(defaultPrivacyGroupManagementContract.lock().encodeFunctionCall()); - assertThat(RAW_UNLOCK) - .isEqualTo(defaultPrivacyGroupManagementContract.unlock().encodeFunctionCall()); - assertThat(RAW_CAN_EXECUTE) - .isEqualTo(defaultPrivacyGroupManagementContract.canExecute().encodeFunctionCall()); - assertThat(RAW_GET_VERSION) - .isEqualTo(defaultPrivacyGroupManagementContract.getVersion().encodeFunctionCall()); + .encodeFunctionCall()) + .isEqualTo(RAW_REMOVE_PARTICIPANT); + assertThat(defaultPrivacyGroupManagementContract.lock().encodeFunctionCall()) + .isEqualTo(RAW_LOCK); + assertThat(defaultPrivacyGroupManagementContract.unlock().encodeFunctionCall()) + .isEqualTo(RAW_UNLOCK); + assertThat(defaultPrivacyGroupManagementContract.canExecute().encodeFunctionCall()) + .isEqualTo(RAW_CAN_EXECUTE); + assertThat(defaultPrivacyGroupManagementContract.getVersion().encodeFunctionCall()) + .isEqualTo(RAW_GET_VERSION); } @Test @@ -126,15 +127,18 @@ public void canRemoveParticipant() throws Exception { assertThat(firstParticipant.raw()).isEqualTo(participantsAfterRemove.get(0)); } - @Test(expected = TransactionException.class) + @Test public void cannotAddToContractWhenNotLocked() throws Exception { defaultPrivacyGroupManagementContract .addParticipants(Collections.singletonList(thirdParticipant.raw())) .send(); - defaultPrivacyGroupManagementContract - .addParticipants(Collections.singletonList(secondParticipant.raw())) - .send(); + assertThatThrownBy( + () -> + defaultPrivacyGroupManagementContract + .addParticipants(Collections.singletonList(secondParticipant.raw())) + .send()) + .isInstanceOf(TransactionException.class); } @Test @@ -179,12 +183,13 @@ public void canAddTwiceToContractWhenCallLock() throws Exception { assertThat(secondParticipant.raw()).isEqualTo(participants.get(2)); } - @Test(expected = TransactionException.class) + @Test public void cannotLockTwice() throws Exception { defaultPrivacyGroupManagementContract .addParticipants(Collections.singletonList(thirdParticipant.raw())) .send(); defaultPrivacyGroupManagementContract.lock().send(); - defaultPrivacyGroupManagementContract.lock().send(); + assertThatThrownBy(() -> defaultPrivacyGroupManagementContract.lock().send()) + .isInstanceOf(TransactionException.class); } } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/contracts/PrivacyProxyTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/contracts/PrivacyProxyTest.java new file mode 100644 index 00000000000..931770ee321 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/contracts/PrivacyProxyTest.java @@ -0,0 +1,178 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy.contracts; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.hyperledger.besu.privacy.contracts.generated.DefaultFlexiblePrivacyGroupManagementContract; +import org.hyperledger.besu.privacy.contracts.generated.FlexiblePrivacyGroupManagementProxy; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.web3j.crypto.Credentials; +import org.web3j.protocol.Web3j; +import org.web3j.protocol.exceptions.TransactionException; +import org.web3j.protocol.http.HttpService; +import org.web3j.tx.gas.DefaultGasProvider; +import org.web3j.utils.Base64String; + +@SuppressWarnings("unchecked") +public class PrivacyProxyTest extends AcceptanceTestBase { + + private final Base64String firstParticipant = + Base64String.wrap("93Ky7lXwFkMc7+ckoFgUMku5bpr9tz4zhmWmk9RlNng="); + private final Base64String secondParticipant = + Base64String.wrap("9iaJ6OObl6TUWYjXAOyZsL0VaDPwF+tRFkMwwYSeqqw="); + private final Base64String thirdParticipant = + Base64String.wrap("Jo2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs="); + private FlexiblePrivacyGroupManagementProxy flexiblePrivacyGroupManagementProxy; + + private static final String RAW_GET_PARTICIPANTS = "0x5aa68ac0"; + private static final String RAW_ADD_PARTICIPANT = + "0x965a25ef0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020f772b2ee55f016431cefe724a05814324bb96e9afdb73e338665a693d4653678"; + + private BesuNode minerNode; + private DefaultFlexiblePrivacyGroupManagementContract + defaultFlexiblePrivacyGroupManagementContract; + + @BeforeEach + public void setUp() throws Exception { + minerNode = besu.createMinerNode("node"); + cluster.start(minerNode); + defaultFlexiblePrivacyGroupManagementContract = + minerNode.execute( + contractTransactions.createSmartContract( + DefaultFlexiblePrivacyGroupManagementContract.class)); + flexiblePrivacyGroupManagementProxy = + minerNode.execute( + contractTransactions.createSmartContract( + FlexiblePrivacyGroupManagementProxy.class, + defaultFlexiblePrivacyGroupManagementContract.getContractAddress())); + } + + @Test + public void rlp() throws Exception { + assertThat(flexiblePrivacyGroupManagementProxy.isValid()).isEqualTo(true); + contractVerifier + .validTransactionReceipt(flexiblePrivacyGroupManagementProxy.getContractAddress()) + .verify(flexiblePrivacyGroupManagementProxy); + assertThat(flexiblePrivacyGroupManagementProxy.getParticipants().encodeFunctionCall()) + .isEqualTo(RAW_GET_PARTICIPANTS); + + assertThat( + flexiblePrivacyGroupManagementProxy + .addParticipants(List.of(firstParticipant.raw())) + .encodeFunctionCall()) + .isEqualTo(RAW_ADD_PARTICIPANT); + } + + @Test + public void deploysWithNoParticipant() throws Exception { + final List participants = flexiblePrivacyGroupManagementProxy.getParticipants().send(); + assertThat(participants.size()).isEqualTo(0); + } + + @Test + public void canAddParticipants() throws Exception { + flexiblePrivacyGroupManagementProxy + .addParticipants(Arrays.asList(firstParticipant.raw(), secondParticipant.raw())) + .send(); + final List participants = flexiblePrivacyGroupManagementProxy.getParticipants().send(); + assertThat(participants.size()).isEqualTo(2); + assertThat(firstParticipant.raw()).isEqualTo(participants.get(0)); + assertThat(secondParticipant.raw()).isEqualTo(participants.get(1)); + } + + @Test + public void nonOwnerCannotUpgrade() throws Exception { + flexiblePrivacyGroupManagementProxy + .addParticipants(Arrays.asList(firstParticipant.raw(), secondParticipant.raw())) + .send(); + final List participants = flexiblePrivacyGroupManagementProxy.getParticipants().send(); + assertThat(participants.size()).isEqualTo(2); + assertThat(firstParticipant.raw()).isEqualTo(participants.get(0)); + assertThat(secondParticipant.raw()).isEqualTo(participants.get(1)); + + final DefaultFlexiblePrivacyGroupManagementContract upgradedContract = + minerNode.execute( + contractTransactions.createSmartContract( + DefaultFlexiblePrivacyGroupManagementContract.class)); + + final HttpService httpService = + new HttpService( + "http://" + minerNode.getHostName() + ":" + minerNode.getJsonRpcPort().get()); + final Web3j web3j = Web3j.build(httpService); + + // load the proxy contract, use it with another signer + final FlexiblePrivacyGroupManagementProxy proxyContractAccount2 = + FlexiblePrivacyGroupManagementProxy.load( + flexiblePrivacyGroupManagementProxy.getContractAddress(), + web3j, + Credentials.create(Accounts.GENESIS_ACCOUNT_TWO_PRIVATE_KEY), + new DefaultGasProvider()); + // contract is the proxy contract and uses genesis account 2. It should not be able to upgrade + // the contract, because it is not the owner of "upgradedContract" + assertThatThrownBy( + () -> proxyContractAccount2.upgradeTo(upgradedContract.getContractAddress()).send()) + .isInstanceOf(TransactionException.class); + } + + @Test + public void ownerCanUpgrade() throws Exception { + flexiblePrivacyGroupManagementProxy + .addParticipants(Arrays.asList(firstParticipant.raw(), secondParticipant.raw())) + .send(); + final List participants = flexiblePrivacyGroupManagementProxy.getParticipants().send(); + assertThat(participants.size()).isEqualTo(2); + assertThat(firstParticipant.raw()).isEqualTo(participants.get(0)); + assertThat(secondParticipant.raw()).isEqualTo(participants.get(1)); + + final DefaultFlexiblePrivacyGroupManagementContract upgradedContract = + minerNode.execute( + contractTransactions.createSmartContract( + DefaultFlexiblePrivacyGroupManagementContract.class)); + + flexiblePrivacyGroupManagementProxy.upgradeTo(upgradedContract.getContractAddress()).send(); + final List participantsAfterUpgrade = + flexiblePrivacyGroupManagementProxy.getParticipants().send(); + assertThat(participantsAfterUpgrade.size()).isEqualTo(2); + assertThat(firstParticipant.raw()).isEqualTo(participantsAfterUpgrade.get(0)); + assertThat(secondParticipant.raw()).isEqualTo(participantsAfterUpgrade.get(1)); + } + + @Test + public void canAddTwiceToContractWhenCallLock() throws Exception { + flexiblePrivacyGroupManagementProxy + .addParticipants(Arrays.asList(firstParticipant.raw(), thirdParticipant.raw())) + .send(); + flexiblePrivacyGroupManagementProxy.lock().send(); + flexiblePrivacyGroupManagementProxy + .addParticipants(Collections.singletonList(secondParticipant.raw())) + .send(); + final List participants = flexiblePrivacyGroupManagementProxy.getParticipants().send(); + assertThat(participants.size()).isEqualTo(3); + assertThat(firstParticipant.raw()).isEqualTo(participants.get(0)); + assertThat(thirdParticipant.raw()).isEqualTo(participants.get(1)); + assertThat(secondParticipant.raw()).isEqualTo(participants.get(2)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/FlexibleMultiTenancyAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/FlexibleMultiTenancyAcceptanceTest.java new file mode 100644 index 00000000000..da692f21ba1 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/FlexibleMultiTenancyAcceptanceTest.java @@ -0,0 +1,491 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.privacy.multitenancy; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.EC; +import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.NACL; +import static org.hyperledger.enclave.testutil.EnclaveType.TESSERA; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.contract.CallPrivateSmartContractFunction; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.CreateFlexiblePrivacyGroupTransaction; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.util.LogFilterJsonParameter; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.perm.PermissioningTransactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory; +import org.hyperledger.besu.tests.acceptance.privacy.FlexiblePrivacyAcceptanceTestBase; +import org.hyperledger.besu.tests.web3j.generated.EventEmitter; +import org.hyperledger.enclave.testutil.EnclaveEncryptorType; +import org.hyperledger.enclave.testutil.EnclaveType; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.web3j.crypto.Credentials; +import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; +import org.web3j.protocol.core.methods.response.EthCall; +import org.web3j.utils.Base64String; +import org.web3j.utils.Restriction; + +@RunWith(Parameterized.class) +public class FlexibleMultiTenancyAcceptanceTest extends FlexiblePrivacyAcceptanceTestBase { + + private final EnclaveType enclaveType; + private final EnclaveEncryptorType enclaveEncryptorType; + + public FlexibleMultiTenancyAcceptanceTest( + final EnclaveType enclaveType, final EnclaveEncryptorType enclaveEncryptorType) { + this.enclaveType = enclaveType; + this.enclaveEncryptorType = enclaveEncryptorType; + } + + @Parameterized.Parameters(name = "{0} enclave type with {1} encryptor") + public static Collection enclaveParameters() { + return Arrays.asList( + new Object[][] { + {TESSERA, NACL}, + {TESSERA, EC} + }); + } + + private static final PermissioningTransactions permissioningTransactions = + new PermissioningTransactions(); + private static final long VALUE_SET = 10L; + + private PrivacyNode alice; + private MultiTenancyPrivacyNode aliceMultiTenancyPrivacyNode; + + @Before + public void setUp() throws Exception { + alice = + privacyBesu.createFlexiblePrivacyGroupEnabledMinerNode( + "node1", + PrivacyAccountResolver.MULTI_TENANCY.resolve(enclaveEncryptorType), + true, + enclaveType, + Optional.empty()); + final BesuNode aliceBesu = alice.getBesu(); + privacyCluster.startNodes(alice); + final String alice1Token = + aliceBesu.execute(permissioningTransactions.createSuccessfulLogin("user", "pegasys")); + aliceBesu.useAuthenticationTokenInHeaderForJsonRpc(alice1Token); + final String alice2Token = + aliceBesu.execute(permissioningTransactions.createSuccessfulLogin("user2", "Password2")); + final String alice3Token = + aliceBesu.execute(permissioningTransactions.createSuccessfulLogin("user3", "Password3")); + privacyCluster.awaitPeerCount(alice); + + final String alice1EnclaveKey = alice.getEnclave().getPublicKeys().get(0); + final String alice2EnclaveKey = alice.getEnclave().getPublicKeys().get(1); + final String alice3EnclaveKey = alice.getEnclave().getPublicKeys().get(2); + + aliceMultiTenancyPrivacyNode = new MultiTenancyPrivacyNode(alice); + aliceMultiTenancyPrivacyNode + .addTenantWithToken(alice1EnclaveKey, alice1Token) + .addTenantWithToken(alice2EnclaveKey, alice2Token) + .addTenantWithToken(alice3EnclaveKey, alice3Token); + } + + @After + public void tearDown() { + privacyCluster.close(); + } + + @Test + public void createPrivacyGroup() { + createFlexiblePrivacyGroup(alice); + } + + @Test + public void createPrivacyGroupWithAllTenants() { + final MultiTenancyPrivacyGroup privacyGroup = new MultiTenancyPrivacyGroup(); + privacyGroup.addNodeWithTenants( + aliceMultiTenancyPrivacyNode, aliceMultiTenancyPrivacyNode.getTenants()); + createFlexiblePrivacyGroup(privacyGroup); + } + + @Test + public void noAccessWhenNotAMember() { + final MultiTenancyPrivacyGroup twoTenantsFromAlice = new MultiTenancyPrivacyGroup(); + final List tenants = aliceMultiTenancyPrivacyNode.getTenants(); + final String removedTenant = tenants.remove(tenants.size() - 1); + twoTenantsFromAlice.addNodeWithTenants(aliceMultiTenancyPrivacyNode, tenants); + final String privacyGroupId = createFlexiblePrivacyGroup(twoTenantsFromAlice); + + final MultiTenancyPrivacyNode multiTenancyPrivacyNode = + twoTenantsFromAlice.getPrivacyNodes().get(0); + final String tenant = tenants.get(0); + final PrivacyNode privacyNode = multiTenancyPrivacyNode.getPrivacyNode(); + final BesuNode privacyNodeBesu = privacyNode.getBesu(); + privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(tenant)); + final EventEmitter eventEmitter = + privacyNode.execute( + privateContractTransactions.createSmartContractWithPrivacyGroupId( + EventEmitter.class, + privacyNode.getTransactionSigningKey(), + tenant, + privacyGroupId)); + + final String transactionHash = getContractDeploymentCommitmentHash(eventEmitter); + + // check that a member can get the transaction receipt + privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(tenant)); + privacyNode.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + transactionHash, + (PrivateTransactionReceipt) eventEmitter.getTransactionReceipt().get())); + final String actual = + privacyNode + .execute( + privacyTransactions.privGetCode( + privacyGroupId, + Address.fromHexString(eventEmitter.getContractAddress()), + "latest")) + .toHexString(); + assertThat(EventEmitter.BINARY).contains(actual.substring(2)); + + // check that getting the transaction receipt does not work if you are not a member + privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(removedTenant)); + privacyNode.verify( + privateTransactionVerifier.noPrivateTransactionReceipt( + transactionHash)); // returning null because the RPC is using the enclave key + + // check that getting the code of the event emitter does not work when you are not a member + assertThatThrownBy( + () -> + privacyNode.execute( + privacyTransactions.privGetCode( + privacyGroupId, + Address.fromHexString(eventEmitter.getContractAddress()), + "latest"))) + .hasMessageContaining("Unauthorized"); + + final LogFilterJsonParameter filterParameter = + new LogFilterJsonParameter( + "earliest", + "latest", + List.of(eventEmitter.getContractAddress()), + Collections.emptyList(), + null); + + // create a valid filter + privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(tenant)); + final String filterId = + privacyNode.execute(privacyTransactions.newFilter(privacyGroupId, filterParameter)); + + privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(tenant)); + final CallPrivateSmartContractFunction storeTransaction = + privateContractTransactions.callSmartContractWithPrivacyGroupId( + eventEmitter.getContractAddress(), + eventEmitter.store(BigInteger.valueOf(VALUE_SET)).encodeFunctionCall(), + privacyNode.getTransactionSigningKey(), + Restriction.RESTRICTED, + tenant, + privacyGroupId); + final String storeTransactionHash = privacyNode.execute(storeTransaction); + + privacyNode.execute(privacyTransactions.getPrivateTransactionReceipt(storeTransactionHash)); + + // check that getting the filter changes works for a member + assertThat(privacyNode.execute(privacyTransactions.getFilterChanges(privacyGroupId, filterId))) + .hasSize(1); + + // check that getting the filter changes does not work if you are not a member + privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(removedTenant)); + assertThatThrownBy( + () -> + privacyNode.execute(privacyTransactions.getFilterChanges(privacyGroupId, filterId))) + .hasMessageContaining("Unauthorized"); + + // check that getting the filter logs works for a member + privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(tenant)); + assertThat(privacyNode.execute(privacyTransactions.getFilterLogs(privacyGroupId, filterId))) + .hasSize(3); // create privacy group, deploy event emitter, store on event emitter + + // check that getting the filter logs does not work if you are not a member + privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(removedTenant)); + assertThatThrownBy( + () -> privacyNode.execute(privacyTransactions.getFilterLogs(privacyGroupId, filterId))) + .hasMessageContaining("Unauthorized"); + + // check that getting the logs works for a member + privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(tenant)); + assertThat( + privacyNode.execute(privacyTransactions.privGetLogs(privacyGroupId, filterParameter))) + .hasSize(3); // create privacy group, deploy event emitter, store on event emitter + + // check that getting the logs does not work if you are not a member + privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(removedTenant)); + assertThatThrownBy( + () -> + privacyNode.execute( + privacyTransactions.privGetLogs(privacyGroupId, filterParameter))) + .hasMessageContaining("Unauthorized"); + + final List base64StringList = + tenants.stream().map(Base64String::wrap).collect(Collectors.toList()); + + // check that a member can find the on-chain privacy group + privacyNode + .getBesu() + .useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(tenant)); + final List group = + privacyNode.execute( + privacyTransactions.findFlexiblePrivacyGroup( + Base64String.unwrapList(base64StringList))); + assertThat(group.size()).isEqualTo(1); + assertThat(group.get(0).getMembers()).containsAll(base64StringList).hasSize(2); + + // check that when you are not a member you cannot find the privacy group + privacyNode + .getBesu() + .useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(removedTenant)); + assertThatThrownBy( + () -> + privacyNode.execute( + privacyTransactions.findFlexiblePrivacyGroup( + Base64String.unwrapList(base64StringList)))) + .hasMessageContaining("Error finding flexible privacy group"); + + // check that a member can do a priv_call + privacyNode + .getBesu() + .useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(tenant)); + final EthCall readValue = + privacyNode.execute( + privacyTransactions.privCall( + privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall())); + assertThat(new BigInteger(readValue.getValue().substring(2), 16)) + .isEqualByComparingTo(BigInteger.valueOf(VALUE_SET)); + + // check that when you are not a member you cannot do a priv_call + privacyNode + .getBesu() + .useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(removedTenant)); + assertThatThrownBy( + () -> + privacyNode.execute( + privacyTransactions.privCall( + privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall()))) + .hasMessageContaining("Unauthorized"); + + // check that a member can do a priv_getTransaction + privacyNode + .getBesu() + .useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(tenant)); + final PrivacyRequestFactory.GetPrivateTransactionResponse privTransaction = + privacyNode.execute(privacyTransactions.privGetTransaction(storeTransactionHash)); + assertThat(privTransaction.getResult().getPrivacyGroupId()).isEqualTo(privacyGroupId); + + // check that when you are not a member you cannot do a priv_getTransaction + privacyNode + .getBesu() + .useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(removedTenant)); + assertThatThrownBy( + () -> privacyNode.execute(privacyTransactions.privGetTransaction(storeTransactionHash))) + .hasMessageContaining( + "Expecting actual not to be null"); // TODO: returning null because the RPC is using the + // enclave key + } + + @Test + public void removedMemberCannotGetFilterChanges() { + final MultiTenancyPrivacyGroup allTenantsFromAlice = new MultiTenancyPrivacyGroup(); + final List tenants = aliceMultiTenancyPrivacyNode.getTenants(); + allTenantsFromAlice.addNodeWithTenants(aliceMultiTenancyPrivacyNode, tenants); + final String privacyGroupId = createFlexiblePrivacyGroup(allTenantsFromAlice); + final MultiTenancyPrivacyNode multiTenancyPrivacyNode = + allTenantsFromAlice.getPrivacyNodes().get(0); + final String groupCreatingTenant = allTenantsFromAlice.getGroupCreatingTenant(); + final String tenantToBeRemoved = + tenants.stream().filter(t -> !t.equals(groupCreatingTenant)).findFirst().orElseThrow(); + final PrivacyNode groupCreatingPrivacyNode = allTenantsFromAlice.getGroupCreatingPrivacyNode(); + final BesuNode groupCreatingPrivacyNodeBesu = groupCreatingPrivacyNode.getBesu(); + groupCreatingPrivacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(groupCreatingTenant)); + + final EventEmitter eventEmitter = + groupCreatingPrivacyNode.execute( + privateContractTransactions.createSmartContractWithPrivacyGroupId( + EventEmitter.class, + groupCreatingPrivacyNode.getTransactionSigningKey(), + groupCreatingTenant, + privacyGroupId)); + + final LogFilterJsonParameter filterParameter = + new LogFilterJsonParameter( + "earliest", + "latest", + List.of(eventEmitter.getContractAddress()), + Collections.emptyList(), + null); + + final String filterId = + groupCreatingPrivacyNode.execute( + privacyTransactions.newFilter(privacyGroupId, filterParameter)); + + final CallPrivateSmartContractFunction storeTransaction = + privateContractTransactions.callSmartContractWithPrivacyGroupId( + eventEmitter.getContractAddress(), + eventEmitter.store(BigInteger.valueOf(VALUE_SET)).encodeFunctionCall(), + groupCreatingPrivacyNode.getTransactionSigningKey(), + Restriction.RESTRICTED, + groupCreatingTenant, + privacyGroupId); + final String storeTransactionHash = groupCreatingPrivacyNode.execute(storeTransaction); + + groupCreatingPrivacyNode.execute( + privacyTransactions.getPrivateTransactionReceipt(storeTransactionHash)); + + // check that getting the filter changes works for a member + groupCreatingPrivacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(tenantToBeRemoved)); + + assertThat( + groupCreatingPrivacyNode.execute( + privacyTransactions.getFilterChanges(privacyGroupId, filterId))) + .hasSize(1); + + groupCreatingPrivacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(groupCreatingTenant)); + final CallPrivateSmartContractFunction store2Transaction = + privateContractTransactions.callSmartContractWithPrivacyGroupId( + eventEmitter.getContractAddress(), + eventEmitter.store(BigInteger.valueOf(VALUE_SET)).encodeFunctionCall(), + groupCreatingPrivacyNode.getTransactionSigningKey(), + Restriction.RESTRICTED, + groupCreatingTenant, + privacyGroupId); + final String store2TransactionHash = groupCreatingPrivacyNode.execute(store2Transaction); + + groupCreatingPrivacyNode.execute( + privacyTransactions.getPrivateTransactionReceipt(store2TransactionHash)); + + // now remove from privacy group + final String removeTransactionHash = + removeFromPrivacyGroup( + privacyGroupId, + groupCreatingPrivacyNode, + groupCreatingTenant, + Credentials.create(groupCreatingPrivacyNode.getTransactionSigningKey()), + tenantToBeRemoved); + groupCreatingPrivacyNode.execute( + privacyTransactions.getPrivateTransactionReceipt(removeTransactionHash)); + + // check that it does not work anymore when member has been removed + groupCreatingPrivacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( + multiTenancyPrivacyNode.getTokenForTenant(tenantToBeRemoved)); + assertThatThrownBy( + () -> + groupCreatingPrivacyNode.execute( + privacyTransactions.getFilterChanges(privacyGroupId, filterId))) + .hasMessageContaining("Unauthorized"); + } + + private String createFlexiblePrivacyGroup(final MultiTenancyPrivacyGroup group) { + final List multiTenancyPrivacyNodes = group.getPrivacyNodes(); + final MultiTenancyPrivacyNode groupCreatorMultiTenancyPrivacyNode = + multiTenancyPrivacyNodes.get(0); + final PrivacyNode groupCreatorNode = group.getGroupCreatingPrivacyNode(); + final String groupCreatorTenant = group.getGroupCreatingTenant(); + final List members = group.getTenants(); + final String token = groupCreatorMultiTenancyPrivacyNode.getTokenForTenant(groupCreatorTenant); + final CreateFlexiblePrivacyGroupTransaction createTx = + privacyTransactions.createFlexiblePrivacyGroup( + groupCreatorNode, groupCreatorTenant, members, token); + + final PrivacyRequestFactory.PrivxCreatePrivacyGroupResponse createResponse = + groupCreatorNode.execute(createTx); + final String privacyGroupId = createResponse.getPrivacyGroupId(); + + final List base64StringList = + members.stream().map(Base64String::wrap).collect(Collectors.toList()); + for (final MultiTenancyPrivacyNode mtpn : multiTenancyPrivacyNodes) { + final PrivacyNode privacyNode = mtpn.getPrivacyNode(); + for (final String tenant : mtpn.getTenants()) { + if (members.contains(tenant)) { + privacyNode + .getBesu() + .useAuthenticationTokenInHeaderForJsonRpc(mtpn.getTokenForTenant(tenant)); + privacyNode.verify(flexiblePrivacyGroupExists(privacyGroupId, base64StringList)); + } + } + } + groupCreatorNode.getBesu().useAuthenticationTokenInHeaderForJsonRpc(token); + final String commitmentHash = + callGetParticipantsMethodAndReturnCommitmentHash( + privacyGroupId, groupCreatorNode, groupCreatorTenant); + final PrivateTransactionReceipt expectedReceipt = + buildExpectedAddMemberTransactionReceipt( + privacyGroupId, groupCreatorNode, groupCreatorTenant, members); + + for (final MultiTenancyPrivacyNode mtpn : multiTenancyPrivacyNodes) { + final PrivacyNode privacyNode = mtpn.getPrivacyNode(); + for (final String tenant : mtpn.getTenants()) { + if (members.contains(tenant)) { + privacyNode + .getBesu() + .useAuthenticationTokenInHeaderForJsonRpc(mtpn.getTokenForTenant(tenant)); + privacyNode.verify( + privateTransactionVerifier.validPrivateTransactionReceipt( + commitmentHash, expectedReceipt)); + } + } + } + + return privacyGroupId; + } + + private String removeFromPrivacyGroup( + final String privacyGroupId, + final PrivacyNode node, + final String nodeRemovingMember, + final Credentials signer, + final String memberBeingRemoved) { + return node.execute( + privacyTransactions.removeFromPrivacyGroup( + privacyGroupId, nodeRemovingMember, signer, memberBeingRemoved)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/MultiTenancyAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/MultiTenancyAcceptanceTest.java index cbae10dd998..e2fdd2188b1 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/MultiTenancyAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/MultiTenancyAcceptanceTest.java @@ -21,18 +21,21 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; -import static org.hyperledger.besu.ethereum.core.Address.DEFAULT_PRIVACY; - -import org.hyperledger.besu.crypto.SECP256K1; +import static org.hyperledger.besu.ethereum.core.PrivacyParameters.DEFAULT_PRIVACY; + +import org.hyperledger.besu.crypto.KeyPair; +import org.hyperledger.besu.crypto.SignatureAlgorithm; +import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.enclave.types.PrivacyGroup; import org.hyperledger.besu.enclave.types.ReceiveResponse; import org.hyperledger.besu.enclave.types.SendResponse; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; -import org.hyperledger.besu.ethereum.core.Wei; +import org.hyperledger.besu.ethereum.privacy.PrivacyGroupUtil; import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; -import org.hyperledger.besu.ethereum.privacy.Restriction; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; +import org.hyperledger.besu.plugin.data.Restriction; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster; @@ -40,13 +43,18 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder; import java.math.BigInteger; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; import org.apache.tuweni.bytes.Bytes; -import org.apache.tuweni.io.Base64; +import org.apache.tuweni.bytes.Bytes32; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -57,20 +65,29 @@ public class MultiTenancyAcceptanceTest extends AcceptanceTestBase { private final ObjectMapper mapper = new ObjectMapper(); private Cluster multiTenancyCluster; - private static final SECP256K1.KeyPair TEST_KEY = - SECP256K1.KeyPair.create( - SECP256K1.PrivateKey.create( - new BigInteger( - "853d7f0010fd86d0d7811c1f9d968ea89a24484a8127b4a483ddf5d2cfec766d", 16))); + private static final Supplier SIGNATURE_ALGORITHM = + Suppliers.memoize(SignatureAlgorithmFactory::getInstance); + private static final KeyPair TEST_KEY = + SIGNATURE_ALGORITHM + .get() + .createKeyPair( + SIGNATURE_ALGORITHM + .get() + .createPrivateKey( + new BigInteger( + "853d7f0010fd86d0d7811c1f9d968ea89a24484a8127b4a483ddf5d2cfec766d", 16))); private static final String PRIVACY_GROUP_ID = "B1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="; private static final String PARTICIPANT_ENCLAVE_KEY0 = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="; + private static final Bytes LEAGCY_PRIVATE_FROM = Bytes.fromBase64String(PARTICIPANT_ENCLAVE_KEY0); private static final String PARTICIPANT_ENCLAVE_KEY1 = "sgFkVOyFndZe/5SAZJO5UYbrl7pezHetveriBBWWnE8="; + private static final List LEGACY_PRIVATE_FOR = + List.of(Bytes.fromBase64String(PARTICIPANT_ENCLAVE_KEY1)); private static final String PARTICIPANT_ENCLAVE_KEY2 = "R1kW75NQC9XX3kwNpyPjCBFflM29+XvnKKS9VLrUkzo="; private static final String PARTICIPANT_ENCLAVE_KEY3 = - "QzHuACXpfhoGAgrQriWJcDJ6MrUwcCvutKMoAn9KplQ="; + "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="; private final Address senderAddress = Address.wrap(Bytes.fromHexString(accounts.getPrimaryBenefactor().getAddress())); @@ -227,29 +244,37 @@ public void privGetTransactionReceiptSuccessShouldReturnTransactionReceiptAfterM public void privGetEeaTransactionCountSuccessShouldReturnExpectedTransactionCount() throws JsonProcessingException { final PrivateTransaction validSignedPrivateTransaction = - getValidSignedPrivateTransaction(senderAddress); + getValidLegacySignedPrivateTransaction(senderAddress); final String accountAddress = validSignedPrivateTransaction.getSender().toHexString(); - final String senderAddressBase64 = Base64.encode(Bytes.wrap(accountAddress.getBytes(UTF_8))); - final BytesValueRLPOutput rlpOutput = getRLPOutput(validSignedPrivateTransaction); - final List groupMembership = - List.of(testPrivacyGroup(emptyList(), PrivacyGroup.Type.LEGACY)); + final String privateTxRlp = getRLPOutput(validSignedPrivateTransaction).encoded().toHexString(); - retrievePrivacyGroupEnclaveStub(); - sendEnclaveStub(PARTICIPANT_ENCLAVE_KEY1); - receiveEnclaveStub(validSignedPrivateTransaction); - findPrivacyGroupEnclaveStub(groupMembership); + retrieveEeaPrivacyGroupEnclaveStub(validSignedPrivateTransaction); + sendEnclaveStub( + Bytes32.ZERO.toBase64String()); // can be any value, as we are stubbing the enclave + receiveEnclaveStubEea(validSignedPrivateTransaction); - node.verify(priv.getTransactionCount(accountAddress, PRIVACY_GROUP_ID, 0)); - final Hash transactionHash = - node.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString())); + final String privateFrom = validSignedPrivateTransaction.getPrivateFrom().toBase64String(); + final String[] privateFor = + validSignedPrivateTransaction.getPrivateFor().orElseThrow().stream() + .map(Bytes::toBase64String) + .toArray(String[]::new); + node.verify(priv.getEeaTransactionCount(accountAddress, privateFrom, privateFor, 0)); + + final Hash transactionHash = node.execute(privacyTransactions.sendRawTransaction(privateTxRlp)); node.verify(priv.getSuccessfulTransactionReceipt(transactionHash)); - final String privateFrom = PARTICIPANT_ENCLAVE_KEY0; - final String[] privateFor = {senderAddressBase64}; node.verify(priv.getEeaTransactionCount(accountAddress, privateFrom, privateFor, 1)); } + @Nonnull + private Bytes32 getPrivacyGroupIdFromEeaTransaction( + final PrivateTransaction validSignedPrivateTransaction) { + return PrivacyGroupUtil.calculateEeaPrivacyGroupId( + validSignedPrivateTransaction.getPrivateFrom(), + validSignedPrivateTransaction.getPrivateFor().get()); + } + private void findPrivacyGroupEnclaveStub(final List groupMembership) throws JsonProcessingException { final String findGroupResponse = mapper.writeValueAsString(groupMembership); @@ -270,7 +295,22 @@ private void deletePrivacyGroupEnclaveStub() throws JsonProcessingException { private void retrievePrivacyGroupEnclaveStub() throws JsonProcessingException { final String retrieveGroupResponse = mapper.writeValueAsString( - testPrivacyGroup(List.of(PARTICIPANT_ENCLAVE_KEY0), PrivacyGroup.Type.PANTHEON)); + testPrivacyGroup( + List.of(PARTICIPANT_ENCLAVE_KEY0, PARTICIPANT_ENCLAVE_KEY1), + PrivacyGroup.Type.PANTHEON)); + stubFor(post("/retrievePrivacyGroup").willReturn(ok(retrieveGroupResponse))); + } + + private void retrieveEeaPrivacyGroupEnclaveStub(final PrivateTransaction tx) + throws JsonProcessingException { + final ArrayList members = new ArrayList<>(); + members.add(tx.getPrivateFrom().toBase64String()); + members.addAll( + tx.getPrivateFor().orElseThrow().stream() + .map(Bytes::toBase64String) + .collect(Collectors.toList())); + final String retrieveGroupResponse = + mapper.writeValueAsString(testPrivacyGroupEea(members, PrivacyGroup.Type.LEGACY)); stubFor(post("/retrievePrivacyGroup").willReturn(ok(retrieveGroupResponse))); } @@ -289,6 +329,19 @@ private void receiveEnclaveStub(final PrivateTransaction privTx) throws JsonProc stubFor(post("/receive").willReturn(ok(receiveResponse))); } + private void receiveEnclaveStubEea(final PrivateTransaction privTx) + throws JsonProcessingException { + final BytesValueRLPOutput rlpOutput = getRLPOutputForReceiveResponse(privTx); + final String senderKey = privTx.getPrivateFrom().toBase64String(); + final String receiveResponse = + mapper.writeValueAsString( + new ReceiveResponse( + rlpOutput.encoded().toBase64String().getBytes(UTF_8), + getPrivacyGroupIdFromEeaTransaction(privTx).toBase64String(), + senderKey)); + stubFor(post("/receive").willReturn(ok(receiveResponse))); + } + private BytesValueRLPOutput getRLPOutputForReceiveResponse( final PrivateTransaction privateTransaction) { final BytesValueRLPOutput bvrlpo = new BytesValueRLPOutput(); @@ -307,6 +360,18 @@ private PrivacyGroup testPrivacyGroup( return new PrivacyGroup(PRIVACY_GROUP_ID, groupType, "test", "testGroup", groupMembers); } + private PrivacyGroup testPrivacyGroupEea( + final List groupMembers, final PrivacyGroup.Type groupType) { + final Bytes32 privacyGroupId = + PrivacyGroupUtil.calculateEeaPrivacyGroupId( + Bytes.fromBase64String(groupMembers.get(0)), + groupMembers.stream() + .map(gm -> Bytes.fromBase64String(gm)) + .collect(Collectors.toList())); + return new PrivacyGroup( + privacyGroupId.toBase64String(), groupType, "test", "testGroup", groupMembers); + } + private static PrivateTransaction getValidSignedPrivateTransaction(final Address senderAddress) { return PrivateTransaction.builder() .nonce(0) @@ -316,10 +381,27 @@ private static PrivateTransaction getValidSignedPrivateTransaction(final Address .value(Wei.ZERO) .payload(Bytes.wrap(new byte[] {})) .sender(senderAddress) - .chainId(BigInteger.valueOf(2018)) + .chainId(BigInteger.valueOf(1337)) .privateFrom(Bytes.fromBase64String(PARTICIPANT_ENCLAVE_KEY0)) .restriction(Restriction.RESTRICTED) .privacyGroupId(Bytes.fromBase64String(PRIVACY_GROUP_ID)) .signAndBuild(TEST_KEY); } + + private static PrivateTransaction getValidLegacySignedPrivateTransaction( + final Address senderAddress) { + return PrivateTransaction.builder() + .nonce(0) + .gasPrice(Wei.ZERO) + .gasLimit(3000000) + .to(null) + .value(Wei.ZERO) + .payload(Bytes.wrap(new byte[] {})) + .sender(senderAddress) + .chainId(BigInteger.valueOf(1337)) + .privateFrom(LEAGCY_PRIVATE_FROM) + .privateFor(LEGACY_PRIVATE_FOR) + .restriction(Restriction.RESTRICTED) + .signAndBuild(TEST_KEY); + } } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/MultiTenancyValidationFailAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/MultiTenancyValidationFailAcceptanceTest.java index 51d431643a1..515248347b8 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/MultiTenancyValidationFailAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/MultiTenancyValidationFailAcceptanceTest.java @@ -24,15 +24,16 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.GET_PRIVATE_TRANSACTION_NONCE_ERROR; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.PRIVATE_FROM_DOES_NOT_MATCH_ENCLAVE_PUBLIC_KEY; -import org.hyperledger.besu.crypto.SECP256K1; +import org.hyperledger.besu.crypto.SignatureAlgorithm; +import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.enclave.types.PrivacyGroup; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; -import org.hyperledger.besu.ethereum.core.Wei; import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; -import org.hyperledger.besu.ethereum.privacy.Restriction; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; +import org.hyperledger.besu.plugin.data.Restriction; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster; @@ -171,7 +172,9 @@ public void determineEeaNonceShouldFailWhenPrivateFromNotMatchEnclaveKey() { final Transaction transaction = privacyTransactions.getEeaTransactionCount( accountAddress, OTHER_ENCLAVE_PUBLIC_KEY, privateFor); - node.verify(priv.multiTenancyValidationFail(transaction, GET_PRIVATE_TRANSACTION_NONCE_ERROR)); + node.verify( + priv.multiTenancyValidationFail( + transaction, PRIVATE_FROM_DOES_NOT_MATCH_ENCLAVE_PUBLIC_KEY)); } @Test @@ -204,6 +207,9 @@ private BytesValueRLPOutput getRLPOutput(final PrivateTransaction validSignedPri private static PrivateTransaction getValidSignedPrivateTransaction( final Address senderAddress, final String privateFrom) { + + final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance(); + return PrivateTransaction.builder() .nonce(0) .gasPrice(Wei.ZERO) @@ -217,8 +223,8 @@ private static PrivateTransaction getValidSignedPrivateTransaction( .restriction(Restriction.RESTRICTED) .privacyGroupId(Bytes.fromBase64String(PRIVACY_GROUP_ID)) .signAndBuild( - SECP256K1.KeyPair.create( - SECP256K1.PrivateKey.create( + signatureAlgorithm.createKeyPair( + signatureAlgorithm.createPrivateKey( new BigInteger( "853d7f0010fd86d0d7811c1f9d968ea89a24484a8127b4a483ddf5d2cfec766d", 16)))); } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/OnChainMultiTenancyAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/OnChainMultiTenancyAcceptanceTest.java deleted file mode 100644 index 643b30a663c..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/OnChainMultiTenancyAcceptanceTest.java +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.privacy.multitenancy; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.contract.CallPrivateSmartContractFunction; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.CreateOnChainPrivacyGroupTransaction; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.util.LogFilterJsonParameter; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.perm.PermissioningTransactions; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory; -import org.hyperledger.besu.tests.web3j.generated.EventEmitter; -import org.hyperledger.besu.tests.web3j.privacy.OnChainPrivacyAcceptanceTestBase; - -import java.math.BigInteger; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.web3j.crypto.Credentials; -import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; -import org.web3j.protocol.core.methods.response.EthCall; -import org.web3j.utils.Base64String; - -public class OnChainMultiTenancyAcceptanceTest extends OnChainPrivacyAcceptanceTestBase { - - private static final String eventEmitterDeployed = - "0x6080604052600436106100565763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633fa4f245811461005b5780636057361d1461008257806367e404ce146100ae575b600080fd5b34801561006757600080fd5b506100706100ec565b60408051918252519081900360200190f35b34801561008e57600080fd5b506100ac600480360360208110156100a557600080fd5b50356100f2565b005b3480156100ba57600080fd5b506100c3610151565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b60025490565b604080513381526020810183905281517fc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f5929181900390910190a16002556001805473ffffffffffffffffffffffffffffffffffffffff191633179055565b60015473ffffffffffffffffffffffffffffffffffffffff169056fea165627a7a72305820c7f729cb24e05c221f5aa913700793994656f233fe2ce3b9fd9a505ea17e8d8a0029"; - - private static final PermissioningTransactions permissioningTransactions = - new PermissioningTransactions(); - private static final long VALUE_SET = 10L; - - private PrivacyNode alice; - private MultiTenancyPrivacyNode aliceMultiTenancyPrivacyNode; - - @Before - public void setUp() throws Exception { - alice = - privacyBesu.createOnChainPrivacyGroupEnabledMinerNode( - "node1", PrivacyAccountResolver.MULTI_TENANCY, Address.PRIVACY, true); - final BesuNode aliceBesu = alice.getBesu(); - privacyCluster.startNodes(alice); - final String alice1Token = - aliceBesu.execute(permissioningTransactions.createSuccessfulLogin("user", "pegasys")); - aliceBesu.useAuthenticationTokenInHeaderForJsonRpc(alice1Token); - final String alice2Token = - aliceBesu.execute(permissioningTransactions.createSuccessfulLogin("user2", "Password2")); - final String alice3Token = - aliceBesu.execute(permissioningTransactions.createSuccessfulLogin("user3", "Password3")); - privacyCluster.awaitPeerCount(alice); - - final String alice1EnclaveKey = alice.getOrion().getPublicKeys().get(0); - final String alice2EnclaveKey = alice.getOrion().getPublicKeys().get(1); - final String alice3EnclaveKey = alice.getOrion().getPublicKeys().get(2); - - aliceMultiTenancyPrivacyNode = new MultiTenancyPrivacyNode(alice); - aliceMultiTenancyPrivacyNode - .addTenantWithToken(alice1EnclaveKey, alice1Token) - .addTenantWithToken(alice2EnclaveKey, alice2Token) - .addTenantWithToken(alice3EnclaveKey, alice3Token); - } - - @After - public void tearDown() { - privacyCluster.close(); - } - - @Test - public void createPrivacyGroup() { - createOnChainPrivacyGroup(alice); - } - - @Test - public void createPrivacyGroupWithAllTenants() { - final MultiTenancyPrivacyGroup privacyGroup = new MultiTenancyPrivacyGroup(); - privacyGroup.addNodeWithTenants( - aliceMultiTenancyPrivacyNode, aliceMultiTenancyPrivacyNode.getTenants()); - createOnChainPrivacyGroup(privacyGroup); - } - - @Test - public void noAccessWhenNotAMember() { - final MultiTenancyPrivacyGroup twoTenantsFromAlice = new MultiTenancyPrivacyGroup(); - final List tenants = aliceMultiTenancyPrivacyNode.getTenants(); - final String removedTenant = tenants.remove(tenants.size() - 1); - twoTenantsFromAlice.addNodeWithTenants(aliceMultiTenancyPrivacyNode, tenants); - final String privacyGroupId = createOnChainPrivacyGroup(twoTenantsFromAlice); - - final MultiTenancyPrivacyNode multiTenancyPrivacyNode = - twoTenantsFromAlice.getPrivacyNodes().get(0); - final String tenant = tenants.get(0); - final PrivacyNode privacyNode = multiTenancyPrivacyNode.getPrivacyNode(); - final BesuNode privacyNodeBesu = privacyNode.getBesu(); - privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(tenant)); - final EventEmitter eventEmitter = - privacyNode.execute( - privateContractTransactions.createSmartContractWithPrivacyGroupId( - EventEmitter.class, - privacyNode.getTransactionSigningKey(), - POW_CHAIN_ID, - tenant, - privacyGroupId)); - - final String transactionHash = getContractDeploymentCommitmentHash(eventEmitter); - - // check that a member can get the transaction receipt - privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(tenant)); - privacyNode.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - transactionHash, - (PrivateTransactionReceipt) eventEmitter.getTransactionReceipt().get())); - assertThat( - privacyNode - .execute( - privacyTransactions.privGetCode( - privacyGroupId, - Address.fromHexString(eventEmitter.getContractAddress()), - "latest")) - .toHexString()) - .isEqualTo(eventEmitterDeployed); - - // check that getting the transaction receipt does not work if you are not a member - privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(removedTenant)); - privacyNode.verify( - privateTransactionVerifier.noPrivateTransactionReceipt( - transactionHash)); // returning null because the RPC is using the enclave key - - // check that getting the code of the event emitter does not work when you are not a member - assertThatThrownBy( - () -> - privacyNode.execute( - privacyTransactions.privGetCode( - privacyGroupId, - Address.fromHexString(eventEmitter.getContractAddress()), - "latest"))) - .hasMessageContaining("Unauthorized"); - - final LogFilterJsonParameter filterParameter = - new LogFilterJsonParameter( - "earliest", - "latest", - List.of(eventEmitter.getContractAddress()), - Collections.emptyList(), - null); - - // create a valid filter - privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(tenant)); - final String filterId = - privacyNode.execute(privacyTransactions.newFilter(privacyGroupId, filterParameter)); - - privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(tenant)); - final CallPrivateSmartContractFunction storeTransaction = - privateContractTransactions.callSmartContractWithPrivacyGroupId( - eventEmitter.getContractAddress(), - eventEmitter.store(BigInteger.valueOf(VALUE_SET)).encodeFunctionCall(), - privacyNode.getTransactionSigningKey(), - POW_CHAIN_ID, - tenant, - privacyGroupId); - final String storeTransactionHash = privacyNode.execute(storeTransaction); - - privacyNode.execute(privacyTransactions.getPrivateTransactionReceipt(storeTransactionHash)); - - // check that getting the filter changes works for a member - assertThat(privacyNode.execute(privacyTransactions.getFilterChanges(privacyGroupId, filterId))) - .hasSize(1); - - // check that getting the filter changes does not work if you are not a member - privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(removedTenant)); - assertThatThrownBy( - () -> - privacyNode.execute(privacyTransactions.getFilterChanges(privacyGroupId, filterId))) - .hasMessageContaining("Unauthorized"); - - // check that getting the filter logs works for a member - privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(tenant)); - assertThat(privacyNode.execute(privacyTransactions.getFilterLogs(privacyGroupId, filterId))) - .hasSize(3); // create privacy group, deploy event emitter, store on event emitter - - // check that getting the filter logs does not work if you are not a member - privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(removedTenant)); - assertThatThrownBy( - () -> privacyNode.execute(privacyTransactions.getFilterLogs(privacyGroupId, filterId))) - .hasMessageContaining("Unauthorized"); - - // check that getting the logs works for a member - privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(tenant)); - assertThat( - privacyNode.execute(privacyTransactions.privGetLogs(privacyGroupId, filterParameter))) - .hasSize(3); // create privacy group, deploy event emitter, store on event emitter - - // check that getting the logs does not work if you are not a member - privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(removedTenant)); - assertThatThrownBy( - () -> - privacyNode.execute( - privacyTransactions.privGetLogs(privacyGroupId, filterParameter))) - .hasMessageContaining("Unauthorized"); - - final List base64StringList = - tenants.stream().map(Base64String::wrap).collect(Collectors.toList()); - - // check that a member can find the on-chain privacy group - privacyNode - .getBesu() - .useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(tenant)); - final List group = - privacyNode.execute( - privacyTransactions.findOnChainPrivacyGroup(Base64String.unwrapList(base64StringList))); - assertThat(group.size()).isEqualTo(1); - assertThat(group.get(0).getMembers()).containsAll(base64StringList).hasSize(2); - - // check that when you are not a member you cannot find the privacy group - privacyNode - .getBesu() - .useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(removedTenant)); - assertThatThrownBy( - () -> - privacyNode.execute( - privacyTransactions.findOnChainPrivacyGroup( - Base64String.unwrapList(base64StringList)))) - .hasMessageContaining("Error finding onchain privacy group"); - - // check that a member can do a priv_call - privacyNode - .getBesu() - .useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(tenant)); - final EthCall readValue = - privacyNode.execute( - privacyTransactions.privCall( - privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall())); - assertThat(new BigInteger(readValue.getValue().substring(2), 16)) - .isEqualByComparingTo(BigInteger.valueOf(VALUE_SET)); - - // check that when you are not a member you cannot do a priv_call - privacyNode - .getBesu() - .useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(removedTenant)); - assertThatThrownBy( - () -> - privacyNode.execute( - privacyTransactions.privCall( - privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall()))) - .hasMessageContaining("Unauthorized"); - - // check that a member can do a priv_getTransaction - privacyNode - .getBesu() - .useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(tenant)); - final PrivacyRequestFactory.GetPrivateTransactionResponse privTransaction = - privacyNode.execute(privacyTransactions.privGetTransaction(storeTransactionHash)); - assertThat(privTransaction.getResult().getPrivacyGroupId()).isEqualTo(privacyGroupId); - - // check that when you are not a member you cannot do a priv_getTransaction - privacyNode - .getBesu() - .useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(removedTenant)); - assertThatThrownBy( - () -> privacyNode.execute(privacyTransactions.privGetTransaction(storeTransactionHash))) - .hasMessageContaining( - "Expecting actual not to be null"); // TODO: returning null because the RPC is using the - // enclave key - } - - @Test - public void removedMemberCannotGetFilterChanges() { - final MultiTenancyPrivacyGroup allTenantsFromAlice = new MultiTenancyPrivacyGroup(); - final List tenants = aliceMultiTenancyPrivacyNode.getTenants(); - allTenantsFromAlice.addNodeWithTenants(aliceMultiTenancyPrivacyNode, tenants); - final String privacyGroupId = createOnChainPrivacyGroup(allTenantsFromAlice); - final MultiTenancyPrivacyNode multiTenancyPrivacyNode = - allTenantsFromAlice.getPrivacyNodes().get(0); - final String groupCreatingTenant = allTenantsFromAlice.getGroupCreatingTenant(); - final String tenantToBeRemoved = - tenants.stream().filter(t -> !t.equals(groupCreatingTenant)).findFirst().orElseThrow(); - final PrivacyNode groupCreatingPrivacyNode = allTenantsFromAlice.getGroupCreatingPrivacyNode(); - final BesuNode groupCreatingPrivacyNodeBesu = groupCreatingPrivacyNode.getBesu(); - groupCreatingPrivacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(groupCreatingTenant)); - - final EventEmitter eventEmitter = - groupCreatingPrivacyNode.execute( - privateContractTransactions.createSmartContractWithPrivacyGroupId( - EventEmitter.class, - groupCreatingPrivacyNode.getTransactionSigningKey(), - POW_CHAIN_ID, - groupCreatingTenant, - privacyGroupId)); - - final LogFilterJsonParameter filterParameter = - new LogFilterJsonParameter( - "earliest", - "latest", - List.of(eventEmitter.getContractAddress()), - Collections.emptyList(), - null); - - final String filterId = - groupCreatingPrivacyNode.execute( - privacyTransactions.newFilter(privacyGroupId, filterParameter)); - - final CallPrivateSmartContractFunction storeTransaction = - privateContractTransactions.callSmartContractWithPrivacyGroupId( - eventEmitter.getContractAddress(), - eventEmitter.store(BigInteger.valueOf(VALUE_SET)).encodeFunctionCall(), - groupCreatingPrivacyNode.getTransactionSigningKey(), - POW_CHAIN_ID, - groupCreatingTenant, - privacyGroupId); - final String storeTransactionHash = groupCreatingPrivacyNode.execute(storeTransaction); - - groupCreatingPrivacyNode.execute( - privacyTransactions.getPrivateTransactionReceipt(storeTransactionHash)); - - // check that getting the filter changes works for a member - groupCreatingPrivacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(tenantToBeRemoved)); - - assertThat( - groupCreatingPrivacyNode.execute( - privacyTransactions.getFilterChanges(privacyGroupId, filterId))) - .hasSize(1); - - groupCreatingPrivacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(groupCreatingTenant)); - final CallPrivateSmartContractFunction store2Transaction = - privateContractTransactions.callSmartContractWithPrivacyGroupId( - eventEmitter.getContractAddress(), - eventEmitter.store(BigInteger.valueOf(VALUE_SET)).encodeFunctionCall(), - groupCreatingPrivacyNode.getTransactionSigningKey(), - POW_CHAIN_ID, - groupCreatingTenant, - privacyGroupId); - final String store2TransactionHash = groupCreatingPrivacyNode.execute(store2Transaction); - - groupCreatingPrivacyNode.execute( - privacyTransactions.getPrivateTransactionReceipt(store2TransactionHash)); - - // now remove from privacy group - final String removeTransactionHash = - removeFromPrivacyGroup( - privacyGroupId, - groupCreatingPrivacyNode, - groupCreatingTenant, - Credentials.create(groupCreatingPrivacyNode.getTransactionSigningKey()), - tenantToBeRemoved); - groupCreatingPrivacyNode.execute( - privacyTransactions.getPrivateTransactionReceipt(removeTransactionHash)); - - // check that it does not work anymore when member has been removed - groupCreatingPrivacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc( - multiTenancyPrivacyNode.getTokenForTenant(tenantToBeRemoved)); - assertThatThrownBy( - () -> - groupCreatingPrivacyNode.execute( - privacyTransactions.getFilterChanges(privacyGroupId, filterId))) - .hasMessageContaining("Unauthorized"); - } - - private String createOnChainPrivacyGroup(final MultiTenancyPrivacyGroup group) { - final List multiTenancyPrivacyNodes = group.getPrivacyNodes(); - final MultiTenancyPrivacyNode groupCreatorMultiTenancyPrivacyNode = - multiTenancyPrivacyNodes.get(0); - final PrivacyNode groupCreatorNode = group.getGroupCreatingPrivacyNode(); - final String groupCreatorTenant = group.getGroupCreatingTenant(); - final List members = group.getTenants(); - final String token = groupCreatorMultiTenancyPrivacyNode.getTokenForTenant(groupCreatorTenant); - final CreateOnChainPrivacyGroupTransaction createTx = - privacyTransactions.createOnChainPrivacyGroup( - groupCreatorNode, groupCreatorTenant, members, token); - - final PrivacyRequestFactory.PrivxCreatePrivacyGroupResponse createResponse = - groupCreatorNode.execute(createTx); - final String privacyGroupId = createResponse.getPrivacyGroupId(); - - final List base64StringList = - members.stream().map(Base64String::wrap).collect(Collectors.toList()); - for (final MultiTenancyPrivacyNode mtpn : multiTenancyPrivacyNodes) { - final PrivacyNode privacyNode = mtpn.getPrivacyNode(); - for (final String tenant : mtpn.getTenants()) { - if (members.contains(tenant)) { - privacyNode - .getBesu() - .useAuthenticationTokenInHeaderForJsonRpc(mtpn.getTokenForTenant(tenant)); - privacyNode.verify(onChainPrivacyGroupExists(privacyGroupId, base64StringList)); - } - } - } - groupCreatorNode.getBesu().useAuthenticationTokenInHeaderForJsonRpc(token); - final String commitmentHash = - callGetParticipantsMethodAndReturnCommitmentHash( - privacyGroupId, groupCreatorNode, groupCreatorTenant); - final PrivateTransactionReceipt expectedReceipt = - buildExpectedAddMemberTransactionReceipt( - privacyGroupId, groupCreatorNode, groupCreatorTenant, members.toArray(new String[] {})); - - for (final MultiTenancyPrivacyNode mtpn : multiTenancyPrivacyNodes) { - final PrivacyNode privacyNode = mtpn.getPrivacyNode(); - for (final String tenant : mtpn.getTenants()) { - if (members.contains(tenant)) { - privacyNode - .getBesu() - .useAuthenticationTokenInHeaderForJsonRpc(mtpn.getTokenForTenant(tenant)); - privacyNode.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - commitmentHash, expectedReceipt)); - } - } - } - - return privacyGroupId; - } - - private String removeFromPrivacyGroup( - final String privacyGroupId, - final PrivacyNode node, - final String nodeRemovingMember, - final Credentials signer, - final String memberBeingRemoved) { - return node.execute( - privacyTransactions.removeFromPrivacyGroup( - privacyGroupId, nodeRemovingMember, signer, memberBeingRemoved)); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/pubsub/NewPendingTransactionAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/pubsub/NewPendingTransactionAcceptanceTest.java index fb791edf608..4ae94924b25 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/pubsub/NewPendingTransactionAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/pubsub/NewPendingTransactionAcceptanceTest.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.tests.acceptance.pubsub; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; @@ -22,9 +22,9 @@ import org.hyperledger.besu.tests.acceptance.dsl.pubsub.WebSocket; import io.vertx.core.Vertx; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase { @@ -35,7 +35,7 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase { private BesuNode minerNode; private BesuNode archiveNode; - @Before + @BeforeEach public void setUp() throws Exception { vertx = Vertx.vertx(); minerNode = besu.createMinerNode("miner-node1"); @@ -46,7 +46,7 @@ public void setUp() throws Exception { archiveWebSocket = new WebSocket(vertx, archiveNode.getConfiguration()); } - @After + @AfterEach public void tearDown() { vertx.close(); } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/CrossContractReader.abi b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/CrossContractReader.abi deleted file mode 100644 index 36edfd6c590..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/CrossContractReader.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"crossAddress","type":"address"}],"name":"remoteDestroy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"crossAddress","type":"address"}],"name":"deployRemote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deploy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"destroy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"emitter_address","type":"address"}],"name":"read","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"increment","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"crossAddress","type":"address"}],"name":"incrementRemote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"contractAddress","type":"address"}],"name":"NewEventEmitter","type":"event"}] \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/CrossContractReader.bin b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/CrossContractReader.bin deleted file mode 100644 index a18bc7505c9..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/CrossContractReader.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b506104b7806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806383197ef01161005b57806383197ef0146100d8578063a087a87e146100e0578063d09de08a14610118578063e689ef8a146101205761007d565b8063305155f9146100825780635374ded2146100aa578063775c300c146100d0575b600080fd5b6100a86004803603602081101561009857600080fd5b50356001600160a01b0316610146565b005b6100a8600480360360208110156100c057600080fd5b50356001600160a01b03166101a2565b6100a86101e2565b6100a8610250565b610106600480360360208110156100f657600080fd5b50356001600160a01b0316610253565b60408051918252519081900360200190f35b6100a86102c5565b6100a86004803603602081101561013657600080fd5b50356001600160a01b03166102d0565b6000819050806001600160a01b03166383197ef06040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561018657600080fd5b505af115801561019a573d6000803e3d6000fd5b505050505050565b6000819050806001600160a01b031663775c300c6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561018657600080fd5b60006040516101f090610310565b604051809103906000f08015801561020c573d6000803e3d6000fd5b50604080516001600160a01b038316815290519192507f9ac6876e0aa40667ffeaa9b359b5ed924f4cdd0e029eb6e9c369e78c68f711fb919081900360200190a150565b33ff5b600080829050806001600160a01b0316633fa4f2456040518163ffffffff1660e01b815260040160206040518083038186803b15801561029257600080fd5b505afa1580156102a6573d6000803e3d6000fd5b505050506040513d60208110156102bc57600080fd5b50519392505050565b600080546001019055565b6000819050806001600160a01b031663d09de08a6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561018657600080fd5b6101658061031e8339019056fe608060405234801561001057600080fd5b50600080546001600160a01b03191633179055610133806100326000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fa4f2451460415780636057361d14605957806367e404ce146075575b600080fd5b60476097565b60408051918252519081900360200190f35b607360048036036020811015606d57600080fd5b5035609d565b005b607b60ef565b604080516001600160a01b039092168252519081900360200190f35b60025490565b604080513381526020810183905281517fc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f5929181900390910190a1600255600180546001600160a01b03191633179055565b6001546001600160a01b03169056fea265627a7a72305820dc1ce4d08260105d146ec5efa5274950ee9e66f81ff18994d44a40fbd33e45c064736f6c634300050a0032a265627a7a72305820d71e5a225a48fdeb043aaba4264138353b3443a28658bacec7570e108659ad2864736f6c634300050a0032 \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/CrossContractReader.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/CrossContractReader.java deleted file mode 100644 index ef87c493c50..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/CrossContractReader.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.generated; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import io.reactivex.Flowable; -import org.web3j.abi.EventEncoder; -import org.web3j.abi.TypeReference; -import org.web3j.abi.datatypes.Address; -import org.web3j.abi.datatypes.Event; -import org.web3j.abi.datatypes.Function; -import org.web3j.abi.datatypes.Type; -import org.web3j.abi.datatypes.generated.Uint256; -import org.web3j.crypto.Credentials; -import org.web3j.protocol.Web3j; -import org.web3j.protocol.core.DefaultBlockParameter; -import org.web3j.protocol.core.RemoteCall; -import org.web3j.protocol.core.RemoteFunctionCall; -import org.web3j.protocol.core.methods.request.EthFilter; -import org.web3j.protocol.core.methods.response.BaseEventResponse; -import org.web3j.protocol.core.methods.response.Log; -import org.web3j.protocol.core.methods.response.TransactionReceipt; -import org.web3j.tx.Contract; -import org.web3j.tx.TransactionManager; -import org.web3j.tx.gas.ContractGasProvider; - -/** - * Auto generated code. - * - *

Do not modify! - * - *

Please use the web3j command line tools, - * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the codegen module to update. - * - *

Generated with web3j version 4.5.0. - */ -@SuppressWarnings("rawtypes") -public class CrossContractReader extends Contract { - private static final String BINARY = - "608060405234801561001057600080fd5b506104b7806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806383197ef01161005b57806383197ef0146100d8578063a087a87e146100e0578063d09de08a14610118578063e689ef8a146101205761007d565b8063305155f9146100825780635374ded2146100aa578063775c300c146100d0575b600080fd5b6100a86004803603602081101561009857600080fd5b50356001600160a01b0316610146565b005b6100a8600480360360208110156100c057600080fd5b50356001600160a01b03166101a2565b6100a86101e2565b6100a8610250565b610106600480360360208110156100f657600080fd5b50356001600160a01b0316610253565b60408051918252519081900360200190f35b6100a86102c5565b6100a86004803603602081101561013657600080fd5b50356001600160a01b03166102d0565b6000819050806001600160a01b03166383197ef06040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561018657600080fd5b505af115801561019a573d6000803e3d6000fd5b505050505050565b6000819050806001600160a01b031663775c300c6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561018657600080fd5b60006040516101f090610310565b604051809103906000f08015801561020c573d6000803e3d6000fd5b50604080516001600160a01b038316815290519192507f9ac6876e0aa40667ffeaa9b359b5ed924f4cdd0e029eb6e9c369e78c68f711fb919081900360200190a150565b33ff5b600080829050806001600160a01b0316633fa4f2456040518163ffffffff1660e01b815260040160206040518083038186803b15801561029257600080fd5b505afa1580156102a6573d6000803e3d6000fd5b505050506040513d60208110156102bc57600080fd5b50519392505050565b600080546001019055565b6000819050806001600160a01b031663d09de08a6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561018657600080fd5b6101658061031e8339019056fe608060405234801561001057600080fd5b50600080546001600160a01b03191633179055610133806100326000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fa4f2451460415780636057361d14605957806367e404ce146075575b600080fd5b60476097565b60408051918252519081900360200190f35b607360048036036020811015606d57600080fd5b5035609d565b005b607b60ef565b604080516001600160a01b039092168252519081900360200190f35b60025490565b604080513381526020810183905281517fc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f5929181900390910190a1600255600180546001600160a01b03191633179055565b6001546001600160a01b03169056fea265627a7a72305820dc1ce4d08260105d146ec5efa5274950ee9e66f81ff18994d44a40fbd33e45c064736f6c634300050a0032a265627a7a72305820d71e5a225a48fdeb043aaba4264138353b3443a28658bacec7570e108659ad2864736f6c634300050a0032"; - - public static final String FUNC_REMOTEDESTROY = "remoteDestroy"; - - public static final String FUNC_DEPLOYREMOTE = "deployRemote"; - - public static final String FUNC_DESTROY = "destroy"; - - public static final String FUNC_READ = "read"; - - public static final String FUNC_INCREMENT = "increment"; - - public static final String FUNC_INCREMENTREMOTE = "incrementRemote"; - - public static final Event NEWEVENTEMITTER_EVENT = - new Event( - "NewEventEmitter", Arrays.>asList(new TypeReference

() {}));; - - @Deprecated - protected CrossContractReader( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final BigInteger gasPrice, - final BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected CrossContractReader( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected CrossContractReader( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final BigInteger gasPrice, - final BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected CrossContractReader( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteFunctionCall remoteDestroy(final String crossAddress) { - final Function function = - new Function( - FUNC_REMOTEDESTROY, - Arrays.asList(new org.web3j.abi.datatypes.Address(160, crossAddress)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteFunctionCall deployRemote(final String crossAddress) { - final Function function = - new Function( - FUNC_DEPLOYREMOTE, - Arrays.asList(new org.web3j.abi.datatypes.Address(160, crossAddress)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteFunctionCall deploy() { - final Function function = - new Function(FUNC_DEPLOY, Arrays.asList(), Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteFunctionCall destroy() { - final Function function = - new Function( - FUNC_DESTROY, Arrays.asList(), Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteFunctionCall read(final String emitter_address) { - final Function function = - new Function( - FUNC_READ, - Arrays.asList(new org.web3j.abi.datatypes.Address(160, emitter_address)), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - public RemoteFunctionCall increment() { - final Function function = - new Function( - FUNC_INCREMENT, Arrays.asList(), Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteFunctionCall incrementRemote(final String crossAddress) { - final Function function = - new Function( - FUNC_INCREMENTREMOTE, - Arrays.asList(new org.web3j.abi.datatypes.Address(160, crossAddress)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public List getNewEventEmitterEvents( - final TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(NEWEVENTEMITTER_EVENT, transactionReceipt); - ArrayList responses = - new ArrayList(valueList.size()); - for (Contract.EventValuesWithLog eventValues : valueList) { - NewEventEmitterEventResponse typedResponse = new NewEventEmitterEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.contractAddress = (String) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable newEventEmitterEventFlowable( - final EthFilter filter) { - return web3j - .ethLogFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public NewEventEmitterEventResponse apply(final Log log) { - Contract.EventValuesWithLog eventValues = - extractEventParametersWithLog(NEWEVENTEMITTER_EVENT, log); - NewEventEmitterEventResponse typedResponse = new NewEventEmitterEventResponse(); - typedResponse.log = log; - typedResponse.contractAddress = - (String) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - }); - } - - public Flowable newEventEmitterEventFlowable( - final DefaultBlockParameter startBlock, final DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(NEWEVENTEMITTER_EVENT)); - return newEventEmitterEventFlowable(filter); - } - - @Deprecated - public static CrossContractReader load( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return new CrossContractReader(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static CrossContractReader load( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return new CrossContractReader(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static CrossContractReader load( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final ContractGasProvider contractGasProvider) { - return new CrossContractReader(contractAddress, web3j, credentials, contractGasProvider); - } - - public static CrossContractReader load( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final ContractGasProvider contractGasProvider) { - return new CrossContractReader(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - final Web3j web3j, - final Credentials credentials, - final ContractGasProvider contractGasProvider) { - return deployRemoteCall( - CrossContractReader.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - final Web3j web3j, - final Credentials credentials, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return deployRemoteCall( - CrossContractReader.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - public static RemoteCall deploy( - final Web3j web3j, - final TransactionManager transactionManager, - final ContractGasProvider contractGasProvider) { - return deployRemoteCall( - CrossContractReader.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - final Web3j web3j, - final TransactionManager transactionManager, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return deployRemoteCall( - CrossContractReader.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } - - public static class NewEventEmitterEventResponse extends BaseEventResponse { - public String contractAddress; - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/EventEmitter.abi b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/EventEmitter.abi deleted file mode 100644 index 4f6111952ae..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/EventEmitter.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":true,"inputs":[],"name":"value","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"store","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"sender","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_to","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"stored","type":"event"}] \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/EventEmitter.bin b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/EventEmitter.bin deleted file mode 100644 index 4707225e47f..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/EventEmitter.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b5060008054600160a060020a03191633179055610199806100326000396000f3fe6080604052600436106100565763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633fa4f245811461005b5780636057361d1461008257806367e404ce146100ae575b600080fd5b34801561006757600080fd5b506100706100ec565b60408051918252519081900360200190f35b34801561008e57600080fd5b506100ac600480360360208110156100a557600080fd5b50356100f2565b005b3480156100ba57600080fd5b506100c3610151565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b60025490565b604080513381526020810183905281517fc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f5929181900390910190a16002556001805473ffffffffffffffffffffffffffffffffffffffff191633179055565b60015473ffffffffffffffffffffffffffffffffffffffff169056fea165627a7a72305820c7f729cb24e05c221f5aa913700793994656f233fe2ce3b9fd9a505ea17e8d8a0029 \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/EventEmitter.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/EventEmitter.java deleted file mode 100644 index 6153433b0b7..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/EventEmitter.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.generated; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import io.reactivex.Flowable; -import org.web3j.abi.EventEncoder; -import org.web3j.abi.TypeReference; -import org.web3j.abi.datatypes.Address; -import org.web3j.abi.datatypes.Event; -import org.web3j.abi.datatypes.Function; -import org.web3j.abi.datatypes.Type; -import org.web3j.abi.datatypes.generated.Uint256; -import org.web3j.crypto.Credentials; -import org.web3j.protocol.Web3j; -import org.web3j.protocol.core.DefaultBlockParameter; -import org.web3j.protocol.core.RemoteCall; -import org.web3j.protocol.core.RemoteFunctionCall; -import org.web3j.protocol.core.methods.request.EthFilter; -import org.web3j.protocol.core.methods.response.BaseEventResponse; -import org.web3j.protocol.core.methods.response.Log; -import org.web3j.protocol.core.methods.response.TransactionReceipt; -import org.web3j.tx.Contract; -import org.web3j.tx.TransactionManager; -import org.web3j.tx.gas.ContractGasProvider; - -/** - * Auto generated code. - * - *

Do not modify! - * - *

Please use the web3j command line tools, - * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the codegen module to update. - * - *

Generated with web3j version 4.4.1. - */ -@SuppressWarnings("rawtypes") -public class EventEmitter extends Contract { - public static final String BINARY = - "608060405234801561001057600080fd5b5060008054600160a060020a03191633179055610199806100326000396000f3fe6080604052600436106100565763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633fa4f245811461005b5780636057361d1461008257806367e404ce146100ae575b600080fd5b34801561006757600080fd5b506100706100ec565b60408051918252519081900360200190f35b34801561008e57600080fd5b506100ac600480360360208110156100a557600080fd5b50356100f2565b005b3480156100ba57600080fd5b506100c3610151565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b60025490565b604080513381526020810183905281517fc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f5929181900390910190a16002556001805473ffffffffffffffffffffffffffffffffffffffff191633179055565b60015473ffffffffffffffffffffffffffffffffffffffff169056fea165627a7a72305820c7f729cb24e05c221f5aa913700793994656f233fe2ce3b9fd9a505ea17e8d8a0029"; - - public static final String FUNC_VALUE = "value"; - - public static final String FUNC_STORE = "store"; - - public static final String FUNC_SENDER = "sender"; - - public static final Event STORED_EVENT = - new Event( - "stored", - Arrays.>asList( - new TypeReference

() {}, new TypeReference() {}));; - - @Deprecated - protected EventEmitter( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final BigInteger gasPrice, - final BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected EventEmitter( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected EventEmitter( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final BigInteger gasPrice, - final BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected EventEmitter( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteFunctionCall value() { - final Function function = - new Function( - FUNC_VALUE, - Arrays.asList(), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - public RemoteFunctionCall store(final BigInteger _amount) { - final Function function = - new Function( - FUNC_STORE, - Arrays.asList(new org.web3j.abi.datatypes.generated.Uint256(_amount)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteFunctionCall sender() { - final Function function = - new Function( - FUNC_SENDER, - Arrays.asList(), - Arrays.>asList(new TypeReference
() {})); - return executeRemoteCallSingleValueReturn(function, String.class); - } - - public List getStoredEvents(final TransactionReceipt transactionReceipt) { - List valueList = - extractEventParametersWithLog(STORED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (Contract.EventValuesWithLog eventValues : valueList) { - StoredEventResponse typedResponse = new StoredEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse._to = (String) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse._amount = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable storedEventFlowable(final EthFilter filter) { - return web3j - .ethLogFlowable(filter) - .map( - new io.reactivex.functions.Function() { - @Override - public StoredEventResponse apply(final Log log) { - Contract.EventValuesWithLog eventValues = - extractEventParametersWithLog(STORED_EVENT, log); - StoredEventResponse typedResponse = new StoredEventResponse(); - typedResponse.log = log; - typedResponse._to = (String) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse._amount = - (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - return typedResponse; - } - }); - } - - public Flowable storedEventFlowable( - final DefaultBlockParameter startBlock, final DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(STORED_EVENT)); - return storedEventFlowable(filter); - } - - @Deprecated - public static EventEmitter load( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return new EventEmitter(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static EventEmitter load( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return new EventEmitter(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static EventEmitter load( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final ContractGasProvider contractGasProvider) { - return new EventEmitter(contractAddress, web3j, credentials, contractGasProvider); - } - - public static EventEmitter load( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final ContractGasProvider contractGasProvider) { - return new EventEmitter(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - final Web3j web3j, - final Credentials credentials, - final ContractGasProvider contractGasProvider) { - return deployRemoteCall( - EventEmitter.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - public static RemoteCall deploy( - final Web3j web3j, - final TransactionManager transactionManager, - final ContractGasProvider contractGasProvider) { - return deployRemoteCall( - EventEmitter.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - final Web3j web3j, - final Credentials credentials, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return deployRemoteCall(EventEmitter.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - final Web3j web3j, - final TransactionManager transactionManager, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return deployRemoteCall( - EventEmitter.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } - - public static class StoredEventResponse extends BaseEventResponse { - public String _to; - - public BigInteger _amount; - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/RevertReason.abi b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/RevertReason.abi deleted file mode 100644 index e1bf8b04639..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/RevertReason.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":true,"inputs":[],"name":"revertWithRevertReason","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"revertWithoutRevertReason","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"}] \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/RevertReason.bin b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/RevertReason.bin deleted file mode 100644 index 1848ca10c17..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/RevertReason.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b5060d18061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806311f95f6f146037578063ff489d31146051575b600080fd5b603d6057565b604080519115158252519081900360200190f35b603d6095565b6040805162461bcd60e51b815260206004820152600c60248201526b2932bb32b93a2932b0b9b7b760a11b6044820152905160009181900360640190fd5b6000806000fdfea265627a7a723058202dd24b599e57aa54899e1beceec3fb4a5001fccb4be994e8d18aa03cc123708764736f6c634300050a0032 \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/RevertReason.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/RevertReason.java deleted file mode 100644 index 5fdea67f4bc..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/RevertReason.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.generated; - -import java.math.BigInteger; -import java.util.Arrays; - -import org.web3j.abi.TypeReference; -import org.web3j.abi.datatypes.Bool; -import org.web3j.abi.datatypes.Function; -import org.web3j.abi.datatypes.Type; -import org.web3j.crypto.Credentials; -import org.web3j.protocol.Web3j; -import org.web3j.protocol.core.RemoteCall; -import org.web3j.tx.Contract; -import org.web3j.tx.TransactionManager; -import org.web3j.tx.gas.ContractGasProvider; - -/** - * Auto generated code. - * - *

Do not modify! - * - *

Please use the web3j command line tools, - * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the codegen module to update. - * - *

Generated with web3j version 4.3.0. - */ -@SuppressWarnings("rawtypes") -public class RevertReason extends Contract { - private static final String BINARY = - "608060405234801561001057600080fd5b5060d18061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806311f95f6f146037578063ff489d31146051575b600080fd5b603d6057565b604080519115158252519081900360200190f35b603d6095565b6040805162461bcd60e51b815260206004820152600c60248201526b2932bb32b93a2932b0b9b7b760a11b6044820152905160009181900360640190fd5b6000806000fdfea265627a7a723058202dd24b599e57aa54899e1beceec3fb4a5001fccb4be994e8d18aa03cc123708764736f6c634300050a0032"; - - public static final String FUNC_REVERTWITHREVERTREASON = "revertWithRevertReason"; - - public static final String FUNC_REVERTWITHOUTREVERTREASON = "revertWithoutRevertReason"; - - @Deprecated - protected RevertReason( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final BigInteger gasPrice, - final BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected RevertReason( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected RevertReason( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final BigInteger gasPrice, - final BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected RevertReason( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteCall revertWithRevertReason() { - final Function function = - new Function( - FUNC_REVERTWITHREVERTREASON, - Arrays.asList(), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, Boolean.class); - } - - public RemoteCall revertWithoutRevertReason() { - final Function function = - new Function( - FUNC_REVERTWITHOUTREVERTREASON, - Arrays.asList(), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, Boolean.class); - } - - @Deprecated - public static RevertReason load( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return new RevertReason(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static RevertReason load( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return new RevertReason(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static RevertReason load( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final ContractGasProvider contractGasProvider) { - return new RevertReason(contractAddress, web3j, credentials, contractGasProvider); - } - - public static RevertReason load( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final ContractGasProvider contractGasProvider) { - return new RevertReason(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - final Web3j web3j, - final Credentials credentials, - final ContractGasProvider contractGasProvider) { - return deployRemoteCall( - RevertReason.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - final Web3j web3j, - final Credentials credentials, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return deployRemoteCall(RevertReason.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - public static RemoteCall deploy( - final Web3j web3j, - final TransactionManager transactionManager, - final ContractGasProvider contractGasProvider) { - return deployRemoteCall( - RevertReason.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - final Web3j web3j, - final TransactionManager transactionManager, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return deployRemoteCall( - RevertReason.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/SimpleStorage.abi b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/SimpleStorage.abi deleted file mode 100644 index 4880337f3df..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/SimpleStorage.abi +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"value","type":"uint256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/SimpleStorage.bin b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/SimpleStorage.bin deleted file mode 100644 index 60203ddfac7..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/SimpleStorage.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b5060d08061001f6000396000f3fe60806040526004361060485763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166360fe47b18114604d5780636d4ce63c146075575b600080fd5b348015605857600080fd5b50607360048036036020811015606d57600080fd5b50356099565b005b348015608057600080fd5b506087609e565b60408051918252519081900360200190f35b600055565b6000549056fea165627a7a72305820cb1d0935d14b589300b12fcd0ab849a7e9019c81da24d6daa4f6b2f003d1b0180029 \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/SimpleStorage.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/SimpleStorage.java deleted file mode 100644 index 323bfc216b9..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/generated/SimpleStorage.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.generated; - -import java.math.BigInteger; -import java.util.Arrays; -import java.util.Collections; - -import org.web3j.abi.TypeReference; -import org.web3j.abi.datatypes.Function; -import org.web3j.abi.datatypes.Type; -import org.web3j.abi.datatypes.generated.Uint256; -import org.web3j.crypto.Credentials; -import org.web3j.protocol.Web3j; -import org.web3j.protocol.core.RemoteCall; -import org.web3j.protocol.core.methods.response.TransactionReceipt; -import org.web3j.tx.Contract; -import org.web3j.tx.TransactionManager; -import org.web3j.tx.gas.ContractGasProvider; - -/** - * Auto generated code. - * - *

Do not modify! - * - *

Please use the web3j command line tools, - * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the codegen module to update. - * - *

Generated with web3j version 4.0.1. - */ -@SuppressWarnings("rawtypes") -public class SimpleStorage extends Contract { - private static final String BINARY = - "608060405234801561001057600080fd5b5060d08061001f6000396000f3fe60806040526004361060485763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166360fe47b18114604d5780636d4ce63c146075575b600080fd5b348015605857600080fd5b50607360048036036020811015606d57600080fd5b50356099565b005b348015608057600080fd5b506087609e565b60408051918252519081900360200190f35b600055565b6000549056fea165627a7a72305820cb1d0935d14b589300b12fcd0ab849a7e9019c81da24d6daa4f6b2f003d1b0180029"; - - public static final String FUNC_SET = "set"; - - public static final String FUNC_GET = "get"; - - @Deprecated - protected SimpleStorage( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final BigInteger gasPrice, - final BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - protected SimpleStorage( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, credentials, contractGasProvider); - } - - @Deprecated - protected SimpleStorage( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final BigInteger gasPrice, - final BigInteger gasLimit) { - super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - protected SimpleStorage( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final ContractGasProvider contractGasProvider) { - super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); - } - - public RemoteCall set(final BigInteger value) { - final Function function = - new Function( - FUNC_SET, - Arrays.asList(new org.web3j.abi.datatypes.generated.Uint256(value)), - Collections.>emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteCall get() { - final Function function = - new Function( - FUNC_GET, - Arrays.asList(), - Arrays.>asList(new TypeReference() {})); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - @Deprecated - public static SimpleStorage load( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return new SimpleStorage(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static SimpleStorage load( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return new SimpleStorage(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static SimpleStorage load( - final String contractAddress, - final Web3j web3j, - final Credentials credentials, - final ContractGasProvider contractGasProvider) { - return new SimpleStorage(contractAddress, web3j, credentials, contractGasProvider); - } - - public static SimpleStorage load( - final String contractAddress, - final Web3j web3j, - final TransactionManager transactionManager, - final ContractGasProvider contractGasProvider) { - return new SimpleStorage(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy( - final Web3j web3j, - final Credentials credentials, - final ContractGasProvider contractGasProvider) { - return deployRemoteCall( - SimpleStorage.class, web3j, credentials, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - final Web3j web3j, - final Credentials credentials, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return deployRemoteCall( - SimpleStorage.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); - } - - public static RemoteCall deploy( - final Web3j web3j, - final TransactionManager transactionManager, - final ContractGasProvider contractGasProvider) { - return deployRemoteCall( - SimpleStorage.class, web3j, transactionManager, contractGasProvider, BINARY, ""); - } - - @Deprecated - public static RemoteCall deploy( - final Web3j web3j, - final TransactionManager transactionManager, - final BigInteger gasPrice, - final BigInteger gasLimit) { - return deployRemoteCall( - SimpleStorage.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/DeployPrivateSmartContractAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/DeployPrivateSmartContractAcceptanceTest.java deleted file mode 100644 index 57858c423d9..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/DeployPrivateSmartContractAcceptanceTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.privacy; - -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.web3j.generated.EventEmitter; - -import org.junit.Before; -import org.junit.Test; - -public class DeployPrivateSmartContractAcceptanceTest extends PrivacyAcceptanceTestBase { - - private static final long POW_CHAIN_ID = 2018; - - private PrivacyNode minerNode; - - @Before - public void setUp() throws Exception { - minerNode = - privacyBesu.createPrivateTransactionEnabledMinerNode( - "miner-node", privacyAccountResolver.resolve(0)); - privacyCluster.start(minerNode); - } - - @Test - public void deployingMustGiveValidReceiptAndCode() throws Exception { - final String contractAddress = "0x89ce396d0f9f937ddfa71113e29b2081c4869555"; - - final EventEmitter eventEmitter = - minerNode.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - minerNode.getTransactionSigningKey(), - POW_CHAIN_ID, - minerNode.getEnclaveKey())); - - privateContractVerifier - .validPrivateContractDeployed(contractAddress, minerNode.getAddress().toString()) - .verify(eventEmitter); - - privateContractVerifier.validContractCodeProvided().verify(eventEmitter); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/EnclaveErrorAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/EnclaveErrorAcceptanceTest.java deleted file mode 100644 index 481a1e38581..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/EnclaveErrorAcceptanceTest.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.privacy; - -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.web3j.generated.EventEmitter; - -import java.math.BigInteger; -import java.util.Base64; - -import org.apache.tuweni.crypto.sodium.Box; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; - -public class EnclaveErrorAcceptanceTest extends PrivacyAcceptanceTestBase { - - private static final long IBFT2_CHAIN_ID = 4; - - private PrivacyNode alice; - private PrivacyNode bob; - private String wrongPublicKey; - - @Before - public void setUp() throws Exception { - alice = privacyBesu.createIbft2NodePrivacyEnabled("node1", privacyAccountResolver.resolve(0)); - bob = privacyBesu.createIbft2NodePrivacyEnabled("node2", privacyAccountResolver.resolve(1)); - privacyCluster.start(alice, bob); - - wrongPublicKey = - Base64.getEncoder().encodeToString(Box.KeyPair.random().publicKey().bytesArray()); - } - - @Test - public void aliceCannotSendTransactionFromBobNode() { - final Throwable throwable = - catchThrowable( - () -> - alice.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - alice.getTransactionSigningKey(), - IBFT2_CHAIN_ID, - wrongPublicKey, - bob.getEnclaveKey()))); - - assertThat(throwable) - .hasMessageContaining( - JsonRpcError.PRIVATE_FROM_DOES_NOT_MATCH_ENCLAVE_PUBLIC_KEY.getMessage()); - } - - @Test - public void enclaveNoPeerUrlError() { - final Throwable throwable = - catchThrowable( - () -> - alice.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - alice.getTransactionSigningKey(), - IBFT2_CHAIN_ID, - alice.getEnclaveKey(), - wrongPublicKey))); - - assertThat(throwable).hasMessageContaining(JsonRpcError.NODE_MISSING_PEER_URL.getMessage()); - } - - @Test - public void whenEnclaveIsDisconnectedGetReceiptReturnsInternalError() { - final EventEmitter eventEmitter = - alice.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - alice.getTransactionSigningKey(), - IBFT2_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - privateContractVerifier - .validPrivateContractDeployed( - eventEmitter.getContractAddress(), alice.getAddress().toString()) - .verify(eventEmitter); - - final String transactionHash = - alice.execute( - privateContractTransactions.callSmartContract( - eventEmitter.getContractAddress(), - eventEmitter.store(BigInteger.ONE).encodeFunctionCall(), - alice.getTransactionSigningKey(), - IBFT2_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - final PrivateTransactionReceipt receiptBeforeEnclaveLosesConnection = - alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash)); - - alice.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - transactionHash, receiptBeforeEnclaveLosesConnection)); - - alice.getOrion().stop(); - - alice.verify( - privateTransactionVerifier.internalErrorPrivateTransactionReceipt(transactionHash)); - } - - @Test - @Ignore("Web3J is broken by PR #1426") - public void transactionFailsIfPartyIsOffline() { - // Contract address is generated from sender address and transaction nonce - final String contractAddress = "0xebf56429e6500e84442467292183d4d621359838"; - - final EventEmitter eventEmitter = - alice.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - alice.getTransactionSigningKey(), - IBFT2_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - privateContractVerifier - .validPrivateContractDeployed(contractAddress, alice.getAddress().toString()) - .verify(eventEmitter); - - bob.getOrion().stop(); - - final Throwable throwable = - catchThrowable( - () -> - alice.execute( - privateContractTransactions.callSmartContract( - eventEmitter.getContractAddress(), - eventEmitter.store(BigInteger.ONE).encodeFunctionCall(), - alice.getTransactionSigningKey(), - IBFT2_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey()))); - - assertThat(throwable).hasMessageContaining("NodePropagatingToAllPeers"); - } - - @Test - public void createPrivacyGroupReturnsCorrectError() { - final Throwable throwable = - catchThrowable(() -> alice.execute(privacyTransactions.createPrivacyGroup(null, null))); - - assertThat(throwable).hasMessageContaining(JsonRpcError.CREATE_GROUP_INCLUDE_SELF.getMessage()); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/EthSignerAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/EthSignerAcceptanceTest.java deleted file mode 100644 index 0cbd711e3db..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/EthSignerAcceptanceTest.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.privacy; - -import org.hyperledger.besu.tests.acceptance.dsl.ethsigner.EthSignerClient; -import org.hyperledger.besu.tests.acceptance.dsl.ethsigner.testutil.EthSignerTestHarness; -import org.hyperledger.besu.tests.acceptance.dsl.ethsigner.testutil.EthSignerTestHarnessFactory; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.web3j.generated.EventEmitter; - -import java.io.IOException; -import java.math.BigInteger; -import java.util.Collections; - -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.web3j.protocol.besu.response.privacy.PrivacyGroup; -import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; -import org.web3j.utils.Base64String; - -public class EthSignerAcceptanceTest extends PrivacyAcceptanceTestBase { - - private PrivacyNode minerNode; - private EthSignerTestHarness ethSigner; - - private EthSignerClient ethSignerClient; - - @Before - public void setUp() throws Exception { - minerNode = - privacyBesu.createPrivateTransactionEnabledMinerNode( - "miner-node", privacyAccountResolver.resolve(0)); - privacyCluster.start(minerNode); - - ethSigner = - EthSignerTestHarnessFactory.create( - privacy.newFolder().toPath(), - "ethSignerKey--fe3b557e8fb62b89f4916b721be55ceb828dbd73.json", - minerNode.getBesu().getJsonRpcSocketPort().orElseThrow(), - 2018); - - ethSignerClient = new EthSignerClient(ethSigner.getHttpListeningUrl()); - } - - @Test - public void privateSmartContractMustDeploy() throws IOException { - final String transactionHash = - ethSignerClient.eeaSendTransaction( - null, - BigInteger.valueOf(23176), - BigInteger.valueOf(1000), - EventEmitter.BINARY, - BigInteger.valueOf(0), - minerNode.getEnclaveKey(), - Collections.emptyList(), - "restricted"); - - final PrivateTransactionReceipt receipt = - minerNode.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash)); - - minerNode.verify( - privateTransactionVerifier.validPrivateTransactionReceipt(transactionHash, receipt)); - } - - // requires ethsigner jar > 0.3.0 - // https://bintray.com/consensys/pegasys-repo/ethsigner - @Test - @Ignore - public void privateSmartContractMustDeployNoNonce() throws IOException { - final String transactionHash = - ethSignerClient.eeaSendTransaction( - null, - BigInteger.valueOf(23176), - BigInteger.valueOf(1000), - EventEmitter.BINARY, - minerNode.getEnclaveKey(), - Collections.emptyList(), - "restricted"); - - final PrivateTransactionReceipt receipt = - minerNode.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash)); - - minerNode.verify( - privateTransactionVerifier.validPrivateTransactionReceipt(transactionHash, receipt)); - } - - @Test - public void privateSmartContractMustDeployWithPrivacyGroup() throws IOException { - final String privacyGroupId = - minerNode.execute(privacyTransactions.createPrivacyGroup(null, null, minerNode)); - - minerNode.verify( - privateTransactionVerifier.validPrivacyGroupCreated( - new PrivacyGroup( - privacyGroupId, - PrivacyGroup.Type.PANTHEON, - "", - "", - Base64String.wrapList(minerNode.getEnclaveKey())))); - - final String transactionHash = - ethSignerClient.eeaSendTransaction( - null, - BigInteger.valueOf(23176), - BigInteger.valueOf(1000), - EventEmitter.BINARY, - BigInteger.valueOf(0), - minerNode.getEnclaveKey(), - privacyGroupId, - "restricted"); - - final PrivateTransactionReceipt receipt = - minerNode.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash)); - - minerNode.verify( - privateTransactionVerifier.validPrivateTransactionReceipt(transactionHash, receipt)); - } - - @Test - public void privateSmartContractMustDeployWithPrivacyGroupNoNonce() throws IOException { - final String privacyGroupId = - minerNode.execute(privacyTransactions.createPrivacyGroup(null, null, minerNode)); - - minerNode.verify( - privateTransactionVerifier.validPrivacyGroupCreated( - new PrivacyGroup( - privacyGroupId, - PrivacyGroup.Type.PANTHEON, - "", - "", - Base64String.wrapList(minerNode.getEnclaveKey())))); - - final String transactionHash = - ethSignerClient.eeaSendTransaction( - null, - BigInteger.valueOf(23176), - BigInteger.valueOf(1000), - EventEmitter.BINARY, - minerNode.getEnclaveKey(), - privacyGroupId, - "restricted"); - - final PrivateTransactionReceipt receipt = - minerNode.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash)); - - minerNode.verify( - privateTransactionVerifier.validPrivateTransactionReceipt(transactionHash, receipt)); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/Ibft2PrivacyClusterAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/Ibft2PrivacyClusterAcceptanceTest.java deleted file mode 100644 index f2d22fc6c21..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/Ibft2PrivacyClusterAcceptanceTest.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.privacy; - -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.web3j.generated.EventEmitter; - -import java.math.BigInteger; - -import org.junit.Before; -import org.junit.Test; -import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; - -public class Ibft2PrivacyClusterAcceptanceTest extends PrivacyAcceptanceTestBase { - - private static final long IBFT2_CHAIN_ID = 4; - - private PrivacyNode alice; - private PrivacyNode bob; - private PrivacyNode charlie; - - @Before - public void setUp() throws Exception { - alice = privacyBesu.createIbft2NodePrivacyEnabled("node1", privacyAccountResolver.resolve(0)); - bob = privacyBesu.createIbft2NodePrivacyEnabled("node2", privacyAccountResolver.resolve(1)); - charlie = privacyBesu.createIbft2NodePrivacyEnabled("node3", privacyAccountResolver.resolve(2)); - privacyCluster.start(alice, bob, charlie); - } - - @Test - public void onlyAliceAndBobCanExecuteContract() { - // Contract address is generated from sender address and transaction nonce - final String contractAddress = "0xebf56429e6500e84442467292183d4d621359838"; - - final EventEmitter eventEmitter = - alice.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - alice.getTransactionSigningKey(), - IBFT2_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - privateContractVerifier - .validPrivateContractDeployed(contractAddress, alice.getAddress().toString()) - .verify(eventEmitter); - - final String transactionHash = - alice.execute( - privateContractTransactions.callSmartContract( - eventEmitter.getContractAddress(), - eventEmitter.store(BigInteger.ONE).encodeFunctionCall(), - alice.getTransactionSigningKey(), - IBFT2_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - final PrivateTransactionReceipt expectedReceipt = - alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash)); - - bob.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - transactionHash, expectedReceipt)); - charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(transactionHash)); - } - - @Test - public void aliceCanDeployMultipleTimesInSingleGroup() { - final String firstDeployedAddress = "0xebf56429e6500e84442467292183d4d621359838"; - - privacyCluster.stopNode(charlie); - - final EventEmitter firstEventEmitter = - alice.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - alice.getTransactionSigningKey(), - IBFT2_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - privateContractVerifier - .validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString()) - .verify(firstEventEmitter); - - final String secondDeployedAddress = "0x10f807f8a905da5bd319196da7523c6bd768690f"; - - final EventEmitter secondEventEmitter = - alice.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - alice.getTransactionSigningKey(), - IBFT2_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - privateContractVerifier - .validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString()) - .verify(secondEventEmitter); - } - - @Test - public void canInteractWithMultiplePrivacyGroups() { - // alice deploys contract - final String firstDeployedAddress = "0xff206d21150a8da5b83629d8a722f3135ed532b1"; - - final EventEmitter firstEventEmitter = - alice.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - alice.getTransactionSigningKey(), - IBFT2_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey(), - charlie.getEnclaveKey())); - - privateContractVerifier - .validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString()) - .verify(firstEventEmitter); - - // charlie interacts with contract - final String firstTransactionHash = - charlie.execute( - privateContractTransactions.callSmartContract( - firstEventEmitter.getContractAddress(), - firstEventEmitter.store(BigInteger.ONE).encodeFunctionCall(), - charlie.getTransactionSigningKey(), - IBFT2_CHAIN_ID, - charlie.getEnclaveKey(), - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - // alice gets receipt from charlie's interaction - final PrivateTransactionReceipt aliceReceipt = - alice.execute(privacyTransactions.getPrivateTransactionReceipt(firstTransactionHash)); - - // verify bob and charlie have access to the same receipt - bob.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - firstTransactionHash, aliceReceipt)); - charlie.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - firstTransactionHash, aliceReceipt)); - - // alice deploys second contract - final String secondDeployedAddress = "0xebf56429e6500e84442467292183d4d621359838"; - - final EventEmitter secondEventEmitter = - alice.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - alice.getTransactionSigningKey(), - IBFT2_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - privateContractVerifier - .validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString()) - .verify(secondEventEmitter); - - // bob interacts with contract - final String secondTransactionHash = - bob.execute( - privateContractTransactions.callSmartContract( - secondEventEmitter.getContractAddress(), - secondEventEmitter.store(BigInteger.ONE).encodeFunctionCall(), - bob.getTransactionSigningKey(), - IBFT2_CHAIN_ID, - bob.getEnclaveKey(), - alice.getEnclaveKey())); - - // alice gets receipt from bob's interaction - final PrivateTransactionReceipt secondExpectedReceipt = - alice.execute(privacyTransactions.getPrivateTransactionReceipt(secondTransactionHash)); - - bob.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - secondTransactionHash, secondExpectedReceipt)); - - // charlie cannot see the receipt - charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(secondTransactionHash)); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/OnChainPrivacyAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/OnChainPrivacyAcceptanceTest.java deleted file mode 100644 index 25d366b0f2a..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/OnChainPrivacyAcceptanceTest.java +++ /dev/null @@ -1,492 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.privacy; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.tests.acceptance.dsl.condition.eth.EthConditions; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.miner.MinerTransactions; -import org.hyperledger.besu.tests.web3j.generated.EventEmitter; - -import java.math.BigInteger; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; - -import com.google.common.collect.Lists; -import org.junit.Before; -import org.junit.Test; -import org.web3j.crypto.Credentials; -import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; -import org.web3j.protocol.core.methods.response.EthCall; -import org.web3j.protocol.core.methods.response.Log; -import org.web3j.protocol.core.methods.response.TransactionReceipt; -import org.web3j.tx.Contract; - -public class OnChainPrivacyAcceptanceTest extends OnChainPrivacyAcceptanceTestBase { - - protected static final long POW_CHAIN_ID = 2018; - - private PrivacyNode alice; - private PrivacyNode bob; - private PrivacyNode charlie; - - private final MinerTransactions minerTransactions = new MinerTransactions(); - private final EthConditions ethConditions = new EthConditions(ethTransactions); - - private static final String EXPECTED_STORE_OUTPUT_DATA = - "0x000000000000000000000000f17f52151ebef6c7334fad080c5704d77216b7320000000000000000000000000000000000000000000000000000000000000539"; - private static final String EXPECTED_STORE_EVENT_TOPIC = - "0xc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f5"; - - @Before - public void setUp() throws Exception { - alice = - privacyBesu.createOnChainPrivacyGroupEnabledMinerNode( - "node1", privacyAccountResolver.resolve(0), Address.PRIVACY, false); - bob = - privacyBesu.createOnChainPrivacyGroupEnabledNode( - "node2", privacyAccountResolver.resolve(1), Address.PRIVACY, false); - charlie = - privacyBesu.createOnChainPrivacyGroupEnabledNode( - "node3", privacyAccountResolver.resolve(2), Address.PRIVACY, false); - privacyCluster.start(alice, bob, charlie); - } - - @Test - public void nodeCanCreatePrivacyGroup() { - final String privacyGroupId = createOnChainPrivacyGroup(alice); - checkOnChainPrivacyGroupExists(privacyGroupId, alice); - } - - @Test - public void deployingMustGiveValidReceipt() { - final String privacyGroupId = createOnChainPrivacyGroup(alice, bob); - final Contract eventEmitter = deployPrivateContract(EventEmitter.class, privacyGroupId, alice); - final String commitmentHash = getContractDeploymentCommitmentHash(eventEmitter); - - alice.verify(privateTransactionVerifier.existingPrivateTransactionReceipt(commitmentHash)); - bob.verify(privateTransactionVerifier.existingPrivateTransactionReceipt(commitmentHash)); - } - - @Test - public void canAddParticipantToGroup() { - final String privacyGroupId = createOnChainPrivacyGroup(alice, bob); - final Contract eventEmitter = deployPrivateContract(EventEmitter.class, privacyGroupId, alice); - final String commitmentHash = getContractDeploymentCommitmentHash(eventEmitter); - - charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(commitmentHash)); - - final Credentials aliceCredentials = Credentials.create(alice.getTransactionSigningKey()); - lockPrivacyGroup(privacyGroupId, alice, aliceCredentials); - addMembersToPrivacyGroup(privacyGroupId, alice, aliceCredentials, charlie); - checkOnChainPrivacyGroupExists(privacyGroupId, alice, bob, charlie); - - charlie.verify(privateTransactionVerifier.existingPrivateTransactionReceipt(commitmentHash)); - } - - @Test - public void removedMemberCannotSendTransactionToGroup() { - final String privacyGroupId = createOnChainPrivacyGroup(alice, bob); - - final String removeHash = - removeFromPrivacyGroup( - privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey()), bob); - - bob.verify(privateTransactionVerifier.existingPrivateTransactionReceipt(removeHash)); - - assertThatThrownBy(() -> deployPrivateContract(EventEmitter.class, privacyGroupId, bob)) - .isInstanceOf(RuntimeException.class) - .hasMessageContaining("Onchain Privacy group does not exist."); - } - - @Test - public void memberCanBeAddedAfterBeingRemoved() { - final String privacyGroupId = createOnChainPrivacyGroup(alice); - - checkOnChainPrivacyGroupExists(privacyGroupId, alice); - - lockPrivacyGroup(privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey())); - addMembersToPrivacyGroup( - privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey()), bob); - - checkOnChainPrivacyGroupExists(privacyGroupId, alice, bob); - - final EventEmitter eventEmitter = - deployPrivateContract(EventEmitter.class, privacyGroupId, alice); - - final int valueSetWhileBobWasMember = 17; - final PrivateTransactionReceipt receiptWhileBobMember = - setEventEmitterValueAndCheck( - Lists.newArrayList(alice, bob), - privacyGroupId, - eventEmitter, - valueSetWhileBobWasMember); - - removeFromPrivacyGroup( - privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey()), bob); - - checkOnChainPrivacyGroupExists(privacyGroupId, alice); - - final int valueSetWhileBobWas_NOT_aMember = 1337; - final PrivateTransactionReceipt receiptWhileBobRemoved = - setEventEmitterValueAndCheck( - Lists.newArrayList(alice), - privacyGroupId, - eventEmitter, - valueSetWhileBobWas_NOT_aMember); - checkEmitterValue( - Lists.newArrayList(bob), - privacyGroupId, - eventEmitter, - valueSetWhileBobWasMember); // bob did not get the last transaction - - lockPrivacyGroup(privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey())); - addMembersToPrivacyGroup( - privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey()), bob); - - checkOnChainPrivacyGroupExists(privacyGroupId, alice, bob); - - checkEmitterValue( - Lists.newArrayList(alice, bob), - privacyGroupId, - eventEmitter, - valueSetWhileBobWas_NOT_aMember); - - PrivateTransactionReceipt receipt = - bob.execute( - privacyTransactions.getPrivateTransactionReceipt( - receiptWhileBobRemoved.getcommitmentHash())); - assertThat(receipt.getStatus()).isEqualTo("0x1"); - - receipt = - bob.execute( - privacyTransactions.getPrivateTransactionReceipt( - receiptWhileBobMember.getcommitmentHash())); - assertThat(receipt.getStatus()).isEqualTo("0x1"); - } - - PrivateTransactionReceipt setEventEmitterValueAndCheck( - final List nodes, - final String privacyGroupId, - final EventEmitter eventEmitter, - final int value) { - final PrivateTransactionReceipt receiptWhileBobMember = - setEventEmitterValue(nodes, privacyGroupId, eventEmitter, value); - - checkEmitterValue(nodes, privacyGroupId, eventEmitter, value); - return receiptWhileBobMember; - } - - private PrivateTransactionReceipt setEventEmitterValue( - final List nodes, - final String privacyGroupId, - final EventEmitter eventEmitter, - final int value) { - final PrivacyNode firstNode = nodes.get(0); - final String txHash = - firstNode.execute( - privateContractTransactions.callOnChainPermissioningSmartContract( - eventEmitter.getContractAddress(), - eventEmitter.store(BigInteger.valueOf(value)).encodeFunctionCall(), - firstNode.getTransactionSigningKey(), - POW_CHAIN_ID, - firstNode.getEnclaveKey(), - privacyGroupId)); - PrivateTransactionReceipt receipt = null; - for (final PrivacyNode node : nodes) { - receipt = node.execute(privacyTransactions.getPrivateTransactionReceipt(txHash)); - assertThat(receipt.getStatus()).isEqualTo("0x1"); - } - return receipt; - } - - private void checkEmitterValue( - final List nodes, - final String privacyGroupId, - final EventEmitter eventEmitter, - final int expectedValue) { - for (final PrivacyNode node : nodes) { - final EthCall response = - node.execute( - privacyTransactions.privCall( - privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall())); - - assertThat(new BigInteger(response.getValue().substring(2), 16)) - .isEqualByComparingTo(BigInteger.valueOf(expectedValue)); - } - } - - @Test - public void bobCanAddCharlieAfterBeingAddedByAlice() { - final String privacyGroupId = createOnChainPrivacyGroup(alice); - checkOnChainPrivacyGroupExists(privacyGroupId, alice); - final EventEmitter eventEmitter = - alice.execute( - privateContractTransactions.createSmartContractWithPrivacyGroupId( - EventEmitter.class, - alice.getTransactionSigningKey(), - POW_CHAIN_ID, - alice.getEnclaveKey(), - privacyGroupId)); - - privateContractVerifier - .validPrivateContractDeployed( - eventEmitter.getContractAddress(), alice.getAddress().toString()) - .verify(eventEmitter); - - final Credentials aliceCredentials = Credentials.create(alice.getTransactionSigningKey()); - final String aliceLockHash = - alice.execute( - privacyTransactions.privxLockPrivacyGroupAndCheck( - privacyGroupId, alice, aliceCredentials)); - - alice.execute( - privacyTransactions.addToPrivacyGroup(privacyGroupId, alice, aliceCredentials, bob)); - - checkOnChainPrivacyGroupExists(privacyGroupId, alice, bob); - - bob.execute( - privacyTransactions.privxLockPrivacyGroupAndCheck(privacyGroupId, bob, aliceCredentials)); - - alice.execute(minerTransactions.minerStop()); - - alice.getBesu().verify(ethConditions.miningStatus(false)); - - final BigInteger pendingTransactionFilterId = - alice.execute(ethTransactions.newPendingTransactionsFilter()); - - final String callHash = - alice.execute( - privateContractTransactions.callOnChainPermissioningSmartContract( - eventEmitter.getContractAddress(), - eventEmitter.value().encodeFunctionCall(), - alice.getTransactionSigningKey(), - POW_CHAIN_ID, - alice.getEnclaveKey(), - privacyGroupId)); - - final String bobAddHash = - addMembersToPrivacyGroup(privacyGroupId, bob, aliceCredentials, charlie); - - alice - .getBesu() - .verify( - ethConditions.expectNewPendingTransactions( - pendingTransactionFilterId, Arrays.asList(callHash, bobAddHash))); - - alice.execute(minerTransactions.minerStart()); - - alice.getBesu().verify(ethConditions.miningStatus(true)); - - checkOnChainPrivacyGroupExists(privacyGroupId, alice, bob, charlie); - - final Optional aliceAddReceipt = - alice.execute(ethTransactions.getTransactionReceipt(bobAddHash)); - assertThat(aliceAddReceipt.get().getStatus()) - .isEqualTo("0x1"); // this means the PMT for the "add" succeeded which is what we expect - - final Optional alicePublicReceipt = - alice.execute(ethTransactions.getTransactionReceipt(callHash)); - if (alicePublicReceipt.isPresent()) { - assertThat(alicePublicReceipt.get().getBlockHash()) - .isEqualTo( - aliceAddReceipt - .get() - .getBlockHash()); // ensure that "add" and "call" are in the same block - assertThat(alicePublicReceipt.get().getStatus()) - .isEqualTo( - "0x1"); // this means the PMT for the "call" succeeded which is what we expect because - // it is in the same block as the "add" and there is no way to tell that this - // will happen before the block is mined - } - - final PrivateTransactionReceipt aliceReceipt = - alice.execute(privacyTransactions.getPrivateTransactionReceipt(callHash)); - assertThat(aliceReceipt.getStatus()) - .isEqualTo( - "0x0"); // this means the "call" failed which is what we expect because the group was - // locked! - final PrivateTransactionReceipt bobReceipt = - alice.execute(privacyTransactions.getPrivateTransactionReceipt(callHash)); - assertThat(bobReceipt.getStatus()) - .isEqualTo( - "0x0"); // this means the "call" failed which is what we expect because the group was - // locked! - - // assert charlie can access private transaction information from before he was added - final PrivateTransactionReceipt expectedAliceLockReceipt = - new PrivateTransactionReceipt( - null, - alice.getAddress().toHexString(), - Address.ONCHAIN_PRIVACY_PROXY.toHexString(), - "0x", - Collections.emptyList(), - null, - null, - alice.getEnclaveKey(), - null, - privacyGroupId, - "0x1", - null); - charlie.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - aliceLockHash, expectedAliceLockReceipt)); - - final String aliceStoreHash = - charlie.execute( - privateContractTransactions.callOnChainPermissioningSmartContract( - eventEmitter.getContractAddress(), - eventEmitter.store(BigInteger.valueOf(1337)).encodeFunctionCall(), - charlie.getTransactionSigningKey(), - POW_CHAIN_ID, - charlie.getEnclaveKey(), - privacyGroupId)); - - final PrivateTransactionReceipt expectedStoreReceipt = - new PrivateTransactionReceipt( - null, - charlie.getAddress().toHexString(), - eventEmitter.getContractAddress(), - "0x", - Collections.singletonList( - new Log( - false, - "0x0", - "0x0", - aliceStoreHash, - null, - null, - eventEmitter.getContractAddress(), - EXPECTED_STORE_OUTPUT_DATA, - null, - Collections.singletonList(EXPECTED_STORE_EVENT_TOPIC))), - null, - null, - charlie.getEnclaveKey(), - null, - privacyGroupId, - "0x1", - null); - - alice.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - aliceStoreHash, expectedStoreReceipt)); - - bob.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - aliceStoreHash, expectedStoreReceipt)); - - charlie.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - aliceStoreHash, expectedStoreReceipt)); - - removeFromPrivacyGroup(privacyGroupId, bob, aliceCredentials, charlie); - - checkOnChainPrivacyGroupExists(privacyGroupId, alice, bob); - } - - @Test - public void addMembersToTwoGroupsInTheSameBlock() { - final String privacyGroupId1 = createOnChainPrivacyGroup(alice); - final String privacyGroupId2 = createOnChainPrivacyGroup(bob); - checkOnChainPrivacyGroupExists(privacyGroupId1, alice); - checkOnChainPrivacyGroupExists(privacyGroupId2, bob); - - lockPrivacyGroup(privacyGroupId1, alice, Credentials.create(alice.getTransactionSigningKey())); - lockPrivacyGroup(privacyGroupId2, bob, Credentials.create(bob.getTransactionSigningKey())); - - final BigInteger pendingTransactionFilterId = - alice.execute(ethTransactions.newPendingTransactionsFilter()); - - alice.execute(minerTransactions.minerStop()); - alice.getBesu().verify(ethConditions.miningStatus(false)); - - final String aliceAddHash = - addMembersToPrivacyGroup( - privacyGroupId1, alice, Credentials.create(alice.getTransactionSigningKey()), charlie); - final String bobAddHash = - addMembersToPrivacyGroup( - privacyGroupId2, bob, Credentials.create(bob.getTransactionSigningKey()), alice); - - alice - .getBesu() - .verify( - ethConditions.expectNewPendingTransactions( - pendingTransactionFilterId, Arrays.asList(aliceAddHash, bobAddHash))); - - alice.execute(minerTransactions.minerStart()); - - checkOnChainPrivacyGroupExists(privacyGroupId1, alice, charlie); - checkOnChainPrivacyGroupExists(privacyGroupId2, bob, alice); - } - - private T deployPrivateContract( - final Class clazz, final String privacyGroupId, final PrivacyNode sender) { - final T contract = - sender.execute( - privateContractTransactions.createSmartContractWithPrivacyGroupId( - clazz, - sender.getTransactionSigningKey(), - POW_CHAIN_ID, - sender.getEnclaveKey(), - privacyGroupId)); - - privateContractVerifier - .validPrivateContractDeployed(contract.getContractAddress(), sender.getAddress().toString()) - .verify(contract); - - return contract; - } - - private String addMembersToPrivacyGroup( - final String privacyGroupId, - final PrivacyNode nodeAddingMember, - final Credentials signer, - final PrivacyNode... newMembers) { - return nodeAddingMember.execute( - privacyTransactions.addToPrivacyGroup( - privacyGroupId, nodeAddingMember, signer, newMembers)); - } - - private String removeFromPrivacyGroup( - final String privacyGroupId, - final PrivacyNode nodeRemovingMember, - final Credentials signer, - final PrivacyNode memberBeingRemoved) { - return nodeRemovingMember.execute( - privacyTransactions.removeFromPrivacyGroup( - privacyGroupId, - nodeRemovingMember.getEnclaveKey(), - signer, - memberBeingRemoved.getEnclaveKey())); - } - - /** - * This method will send a transaction to lock the privacy group identified by the specified id. - * This also checks if the lock transaction was successful. - * - * @return the hash of the lock privacy group transaction - */ - private String lockPrivacyGroup( - final String privacyGroupId, final PrivacyNode member, final Credentials signer) { - return member.execute( - privacyTransactions.privxLockPrivacyGroupAndCheck(privacyGroupId, member, signer)); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/OnChainPrivacyAcceptanceTestBase.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/OnChainPrivacyAcceptanceTestBase.java deleted file mode 100644 index 28c922513b6..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/OnChainPrivacyAcceptanceTestBase.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.privacy; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.ethereum.privacy.group.OnChainGroupManagement.GET_PARTICIPANTS_METHOD_SIGNATURE; - -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.condition.ExpectValidOnChainPrivacyGroupCreated; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.CreateOnChainPrivacyGroupTransaction; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -import org.apache.tuweni.bytes.Bytes; -import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; -import org.web3j.protocol.core.methods.response.TransactionReceipt; -import org.web3j.tx.Contract; -import org.web3j.utils.Base64String; - -public class OnChainPrivacyAcceptanceTestBase extends PrivacyAcceptanceTestBase { - - protected String createOnChainPrivacyGroup(final PrivacyNode... members) { - final List addresses = - Arrays.asList(members).stream().map(m -> m.getEnclaveKey()).collect(Collectors.toList()); - return createOnChainPrivacyGroup(members[0].getEnclaveKey(), addresses, members); - } - - /** - * Crete an onchain privacy group. The privacy group id will be randomly generated. - * - *

This method also checks that each node member has successfully processed the transaction and - * has the expected list of member for the group. - * - * @param members the list of members of the privacy group. The first member of the list will be - * the creator of the group. - * @return the id of the privacy group - */ - protected String createOnChainPrivacyGroup( - final String privateFrom, final List addresses, final PrivacyNode... members) { - - final PrivacyNode groupCreator = members[0]; - - final CreateOnChainPrivacyGroupTransaction createTx = - privacyTransactions.createOnChainPrivacyGroup(groupCreator, privateFrom, addresses); - - final PrivacyRequestFactory.PrivxCreatePrivacyGroupResponse createResponse = - groupCreator.execute(createTx); - final String privacyGroupId = createResponse.getPrivacyGroupId(); - - final List membersEnclaveKeys = - Arrays.stream(members) - .map(m -> Base64String.wrap(m.getEnclaveKey())) - .collect(Collectors.toList()); - - for (final PrivacyNode member : members) { - member.verify(onChainPrivacyGroupExists(privacyGroupId, membersEnclaveKeys)); - } - - final String commitmentHash = - callGetParticipantsMethodAndReturnCommitmentHash(privacyGroupId, groupCreator, privateFrom); - final PrivateTransactionReceipt expectedReceipt = - buildExpectedAddMemberTransactionReceipt( - privacyGroupId, groupCreator, addresses.toArray(new String[] {})); - - for (final PrivacyNode member : members) { - member.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - commitmentHash, expectedReceipt)); - } - - return privacyGroupId; - } - - protected String callGetParticipantsMethodAndReturnCommitmentHash( - final String privacyGroupId, final PrivacyNode groupCreator, final String privateFrom) { - return groupCreator.execute( - privateContractTransactions.callOnChainPermissioningSmartContract( - Address.ONCHAIN_PRIVACY_PROXY.toHexString(), - GET_PARTICIPANTS_METHOD_SIGNATURE.toString(), - groupCreator.getTransactionSigningKey(), - POW_CHAIN_ID, - privateFrom, - privacyGroupId)); - } - - protected PrivateTransactionReceipt buildExpectedAddMemberTransactionReceipt( - final String privacyGroupId, final PrivacyNode groupCreator, final String[] members) { - return buildExpectedAddMemberTransactionReceipt( - privacyGroupId, groupCreator, groupCreator.getEnclaveKey(), members); - } - - protected PrivateTransactionReceipt buildExpectedAddMemberTransactionReceipt( - final String privacyGroupId, - final PrivacyNode groupCreator, - final String privateFrom, - final String[] members) { - final StringBuilder output = new StringBuilder(); - // hex prefix - output.append("0x"); - // Dynamic array offset - output.append("0000000000000000000000000000000000000000000000000000000000000020"); - // Length of the array (with padded zeros to the left) - output.append(Quantity.longToPaddedHex(members.length, 32).substring(2)); - // Each member enclave key converted from Base64 to bytes - for (final String member : members) { - output.append(Bytes.fromBase64String(member).toUnprefixedHexString()); - } - - return new PrivateTransactionReceipt( - null, - groupCreator.getAddress().toHexString(), - Address.ONCHAIN_PRIVACY_PROXY.toHexString(), - output.toString(), - Collections.emptyList(), - null, - null, - privateFrom, - null, - privacyGroupId, - "0x1", - null); - } - - protected ExpectValidOnChainPrivacyGroupCreated onChainPrivacyGroupExists( - final String privacyGroupId, final List members) { - return privateTransactionVerifier.onChainPrivacyGroupExists(privacyGroupId, members); - } - - protected String getContractDeploymentCommitmentHash(final Contract contract) { - final Optional transactionReceipt = contract.getTransactionReceipt(); - assertThat(transactionReceipt).isPresent(); - final PrivateTransactionReceipt privateTransactionReceipt = - (PrivateTransactionReceipt) transactionReceipt.get(); - return privateTransactionReceipt.getcommitmentHash(); - } - - /** - * This method will check if a privacy group with the specified id and list of members exists. - * Each one of the members node will be queried to ensure that they all have the same privacy - * group in their private state. - * - * @param privacyGroupId the id of the privacy group - * @param members the list of member in the privacy group - */ - protected void checkOnChainPrivacyGroupExists( - final String privacyGroupId, final PrivacyNode... members) { - final List membersEnclaveKeys = - Arrays.stream(members) - .map(PrivacyNode::getEnclaveKey) - .map(Base64String::wrap) - .collect(Collectors.toList()); - - for (final PrivacyNode member : members) { - member.verify(onChainPrivacyGroupExists(privacyGroupId, membersEnclaveKeys)); - } - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivCallAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivCallAcceptanceTest.java deleted file mode 100644 index f381e27648e..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivCallAcceptanceTest.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.privacy; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; - -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.web3j.generated.EventEmitter; - -import java.io.IOException; -import java.math.BigInteger; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.jetbrains.annotations.NotNull; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.web3j.abi.FunctionEncoder; -import org.web3j.abi.TypeReference; -import org.web3j.abi.datatypes.Function; -import org.web3j.abi.datatypes.Type; -import org.web3j.abi.datatypes.generated.Uint256; -import org.web3j.protocol.core.Request; -import org.web3j.protocol.core.methods.request.Transaction; -import org.web3j.protocol.core.methods.response.EthCall; -import org.web3j.protocol.core.methods.response.TransactionReceipt; -import org.web3j.protocol.exceptions.ClientConnectionException; -import org.web3j.protocol.http.HttpService; -import org.web3j.tx.Contract; - -public class PrivCallAcceptanceTest extends PrivacyAcceptanceTestBase { - - private static final long POW_CHAIN_ID = 2018; - private static final int VALUE = 1024; - - private PrivacyNode minerNode; - - @Before - public void setUp() throws Exception { - minerNode = - privacyBesu.createPrivateTransactionEnabledMinerNode( - "miner-node", privacyAccountResolver.resolve(0)); - privacyCluster.start(minerNode); - } - - @Ignore - @Test - public void mustReturnCorrectValue() throws Exception { - - final String privacyGroupId = - minerNode.execute( - privacyTransactions.createPrivacyGroup( - "myGroupName", "my group description", minerNode)); - - final EventEmitter eventEmitter = - minerNode.execute( - privateContractTransactions.createSmartContractWithPrivacyGroupId( - EventEmitter.class, - minerNode.getTransactionSigningKey(), - POW_CHAIN_ID, - minerNode.getEnclaveKey(), - privacyGroupId)); - - privateContractVerifier - .validPrivateContractDeployed( - eventEmitter.getContractAddress(), minerNode.getAddress().toString()) - .verify(eventEmitter); - - final Request priv_call = privCall(privacyGroupId, eventEmitter, false, false); - - EthCall resp = priv_call.send(); - - String value = resp.getValue(); - assertThat(new BigInteger(value.substring(2), 16)).isEqualByComparingTo(BigInteger.ZERO); - - final TransactionReceipt receipt = eventEmitter.store(BigInteger.valueOf(VALUE)).send(); - assertThat(receipt).isNotNull(); - - resp = priv_call.send(); - value = resp.getValue(); - assertThat(new BigInteger(value.substring(2), 16)) - .isEqualByComparingTo(BigInteger.valueOf(VALUE)); - } - - @Ignore - @Test - public void shouldReturnEmptyResultWithNonExistingPrivacyGroup() throws IOException { - - final String privacyGroupId = - minerNode.execute( - privacyTransactions.createPrivacyGroup( - "myGroupName", "my group description", minerNode)); - - final EventEmitter eventEmitter = - minerNode.execute( - privateContractTransactions.createSmartContractWithPrivacyGroupId( - EventEmitter.class, - minerNode.getTransactionSigningKey(), - POW_CHAIN_ID, - minerNode.getEnclaveKey(), - privacyGroupId)); - - privateContractVerifier - .validPrivateContractDeployed( - eventEmitter.getContractAddress(), minerNode.getAddress().toString()) - .verify(eventEmitter); - - final String invalidPrivacyGroup = constructInvalidString(privacyGroupId); - final Request privCall = - privCall(invalidPrivacyGroup, eventEmitter, false, false); - - final EthCall result = privCall.send(); - - assertThat(result.getResult()).isEqualTo("0x"); - } - - @Ignore - @Test - public void mustNotSucceedWithWronglyEncodedFunction() { - - final String privacyGroupId = - minerNode.execute( - privacyTransactions.createPrivacyGroup( - "myGroupName", "my group description", minerNode)); - - final EventEmitter eventEmitter = - minerNode.execute( - privateContractTransactions.createSmartContractWithPrivacyGroupId( - EventEmitter.class, - minerNode.getTransactionSigningKey(), - POW_CHAIN_ID, - minerNode.getEnclaveKey(), - privacyGroupId)); - - privateContractVerifier - .validPrivateContractDeployed( - eventEmitter.getContractAddress(), minerNode.getAddress().toString()) - .verify(eventEmitter); - - final Request priv_call = privCall(privacyGroupId, eventEmitter, true, false); - - assertThatExceptionOfType(ClientConnectionException.class) - .isThrownBy(() -> priv_call.send()) - .withMessageContaining("Invalid params"); - } - - @Ignore - @Test - public void mustReturn0xUsingInvalidContractAddress() throws IOException { - - final String privacyGroupId = - minerNode.execute( - privacyTransactions.createPrivacyGroup( - "myGroupName", "my group description", minerNode)); - - final EventEmitter eventEmitter = - minerNode.execute( - privateContractTransactions.createSmartContractWithPrivacyGroupId( - EventEmitter.class, - minerNode.getTransactionSigningKey(), - POW_CHAIN_ID, - minerNode.getEnclaveKey(), - privacyGroupId)); - - privateContractVerifier - .validPrivateContractDeployed( - eventEmitter.getContractAddress(), minerNode.getAddress().toString()) - .verify(eventEmitter); - - final Request priv_call = privCall(privacyGroupId, eventEmitter, false, true); - - final EthCall result = priv_call.send(); - - assertThat(result).isNotNull(); - assertThat(result.getResult()).isEqualTo("0x"); - } - - @NotNull - private String constructInvalidString(final String privacyGroupId) { - final char[] chars = privacyGroupId.toCharArray(); - if (chars[3] == '0') { - chars[3] = '1'; - } else { - chars[3] = '0'; - } - return String.valueOf(chars); - } - - @NotNull - private Request privCall( - final String privacyGroupId, - final Contract eventEmitter, - final boolean useInvalidParameters, - final boolean useInvalidContractAddress) { - - final Uint256 invalid = new Uint256(BigInteger.TEN); - - @SuppressWarnings("rawtypes") - final List inputParameters = - useInvalidParameters ? Arrays.asList(invalid) : Collections.emptyList(); - - final Function function = - new Function( - "value", - inputParameters, - Arrays.>asList(new TypeReference() {})); - - final String encoded = FunctionEncoder.encode(function); - - final HttpService httpService = - new HttpService( - "http://" - + minerNode.getBesu().getHostName() - + ":" - + minerNode.getBesu().getJsonRpcSocketPort().get()); - - final String validContractAddress = eventEmitter.getContractAddress(); - final String invalidContractAddress = constructInvalidString(validContractAddress); - final String contractAddress = - useInvalidContractAddress ? invalidContractAddress : validContractAddress; - - final Transaction transaction = - Transaction.createEthCallTransaction(null, contractAddress, encoded); - - return new Request<>( - "priv_call", - Arrays.asList(privacyGroupId, transaction, "latest"), - httpService, - EthCall.class); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivGetCodeAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivGetCodeAcceptanceTest.java deleted file mode 100644 index e07ed2066f9..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivGetCodeAcceptanceTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.privacy; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.web3j.generated.EventEmitter; - -import org.apache.tuweni.bytes.Bytes; -import org.junit.Before; -import org.junit.Test; -import org.web3j.protocol.besu.response.privacy.PrivacyGroup; -import org.web3j.utils.Base64String; - -public class PrivGetCodeAcceptanceTest extends PrivacyAcceptanceTestBase { - - private PrivacyNode alice; - - @Before - public void setUp() throws Exception { - alice = - privacyBesu.createPrivateTransactionEnabledMinerNode( - "alice", privacyAccountResolver.resolve(0)); - privacyCluster.start(alice); - } - - @Test - public void privGetCodeReturnsDeployedContractBytecode() { - final String privacyGroupId = createPrivacyGroup(); - final EventEmitter eventEmitterContract = deployPrivateContract(privacyGroupId); - - final Bytes deployedContractCode = - alice.execute( - privacyTransactions.privGetCode( - privacyGroupId, - Address.fromHexString(eventEmitterContract.getContractAddress()), - "latest")); - - assertThat(eventEmitterContract.getContractBinary()) - .contains(deployedContractCode.toUnprefixedHexString()); - } - - private EventEmitter deployPrivateContract(final String privacyGroupId) { - final EventEmitter eventEmitter = - alice.execute( - privateContractTransactions.createSmartContractWithPrivacyGroupId( - EventEmitter.class, - alice.getTransactionSigningKey(), - POW_CHAIN_ID, - alice.getEnclaveKey(), - privacyGroupId)); - - privateContractVerifier - .validPrivateContractDeployed( - eventEmitter.getContractAddress(), alice.getAddress().toString()) - .verify(eventEmitter); - return eventEmitter; - } - - private String createPrivacyGroup() { - final String privacyGroupId = - alice.execute( - privacyTransactions.createPrivacyGroup("myGroupName", "my group description", alice)); - - assertThat(privacyGroupId).isNotNull(); - - final PrivacyGroup expected = - new PrivacyGroup( - privacyGroupId, - PrivacyGroup.Type.PANTHEON, - "myGroupName", - "my group description", - Base64String.wrapList(alice.getEnclaveKey())); - - alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); - - return privacyGroupId; - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivGetPrivateTransactionAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivGetPrivateTransactionAcceptanceTest.java deleted file mode 100644 index b318a04b6ed..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivGetPrivateTransactionAcceptanceTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.privacy; - -import org.hyperledger.besu.ethereum.core.Hash; -import org.hyperledger.besu.ethereum.core.Wei; -import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; -import org.hyperledger.besu.ethereum.privacy.Restriction; -import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.CreatePrivacyGroupTransaction; - -import org.apache.tuweni.bytes.Bytes; -import org.junit.Before; -import org.junit.Test; - -public class PrivGetPrivateTransactionAcceptanceTest extends PrivacyAcceptanceTestBase { - - private PrivacyNode alice; - private PrivacyNode bob; - - @Before - public void setUp() throws Exception { - alice = privacyBesu.createIbft2NodePrivacyEnabled("node1", privacyAccountResolver.resolve(0)); - bob = privacyBesu.createIbft2NodePrivacyEnabled("node2", privacyAccountResolver.resolve(1)); - privacyCluster.start(alice, bob); - } - - @Test - public void returnsTransaction() { - final CreatePrivacyGroupTransaction onlyAlice = - privacyTransactions.createPrivacyGroup("Only Alice", "", alice); - - final String privacyGroupId = alice.execute(onlyAlice); - - final PrivateTransaction validSignedPrivateTransaction = - getValidSignedPrivateTransaction(alice, privacyGroupId); - final BytesValueRLPOutput rlpOutput = getRLPOutput(validSignedPrivateTransaction); - - final Hash transactionHash = - alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString())); - - alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash.toString())); - - alice - .getBesu() - .verify(priv.getPrivateTransaction(transactionHash, validSignedPrivateTransaction)); - } - - @Test - public void nonExistentHashReturnsNull() { - alice.getBesu().verify(priv.getPrivateTransactionReturnsNull(Hash.ZERO)); - } - - @Test - public void returnsNullTransactionNotInNodesPrivacyGroup() { - final CreatePrivacyGroupTransaction onlyAlice = - privacyTransactions.createPrivacyGroup("Only Alice", "", alice); - - final String privacyGroupId = alice.execute(onlyAlice); - - final PrivateTransaction validSignedPrivateTransaction = - getValidSignedPrivateTransaction(alice, privacyGroupId); - final BytesValueRLPOutput rlpOutput = getRLPOutput(validSignedPrivateTransaction); - - final Hash transactionHash = - alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString())); - - alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash.toString())); - - bob.getBesu().verify(priv.getPrivateTransactionReturnsNull(transactionHash)); - } - - private BytesValueRLPOutput getRLPOutput(final PrivateTransaction privateTransaction) { - final BytesValueRLPOutput bvrlpo = new BytesValueRLPOutput(); - privateTransaction.writeTo(bvrlpo); - return bvrlpo; - } - - private static PrivateTransaction getValidSignedPrivateTransaction( - final PrivacyNode node, final String privacyGoupId) { - return PrivateTransaction.builder() - .nonce(0) - .gasPrice(Wei.of(999999)) - .gasLimit(3000000) - .to(null) - .value(Wei.ZERO) - .payload(Bytes.wrap(new byte[] {})) - .sender(node.getAddress()) - .privateFrom(Bytes.fromBase64String(node.getEnclaveKey())) - .restriction(Restriction.RESTRICTED) - .privacyGroupId(Bytes.fromBase64String(privacyGoupId)) - .signAndBuild(node.getBesu().getPrivacyParameters().getSigningKeyPair().get()); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivacyClusterAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivacyClusterAcceptanceTest.java deleted file mode 100644 index 3bd1f74b512..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivacyClusterAcceptanceTest.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.privacy; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.enclave.Enclave; -import org.hyperledger.besu.enclave.EnclaveFactory; -import org.hyperledger.besu.enclave.types.ReceiveResponse; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.web3j.generated.EventEmitter; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Collections; - -import io.vertx.core.Vertx; -import org.apache.tuweni.bytes.Bytes; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.web3j.crypto.Credentials; -import org.web3j.crypto.RawTransaction; -import org.web3j.crypto.TransactionEncoder; -import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; -import org.web3j.protocol.eea.crypto.PrivateTransactionEncoder; -import org.web3j.protocol.eea.crypto.RawPrivateTransaction; -import org.web3j.utils.Base64String; -import org.web3j.utils.Numeric; -import org.web3j.utils.Restriction; - -public class PrivacyClusterAcceptanceTest extends PrivacyAcceptanceTestBase { - - private static final long POW_CHAIN_ID = 2018; - - private static final String eventEmitterDeployed = - "0x6080604052600436106100565763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633fa4f245811461005b5780636057361d1461008257806367e404ce146100ae575b600080fd5b34801561006757600080fd5b506100706100ec565b60408051918252519081900360200190f35b34801561008e57600080fd5b506100ac600480360360208110156100a557600080fd5b50356100f2565b005b3480156100ba57600080fd5b506100c3610151565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b60025490565b604080513381526020810183905281517fc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f5929181900390910190a16002556001805473ffffffffffffffffffffffffffffffffffffffff191633179055565b60015473ffffffffffffffffffffffffffffffffffffffff169056fea165627a7a72305820c7f729cb24e05c221f5aa913700793994656f233fe2ce3b9fd9a505ea17e8d8a0029"; - - private PrivacyNode alice; - private PrivacyNode bob; - private PrivacyNode charlie; - private final Vertx vertx = Vertx.vertx(); - private final EnclaveFactory enclaveFactory = new EnclaveFactory(vertx); - - @Before - public void setUp() throws Exception { - alice = - privacyBesu.createPrivateTransactionEnabledMinerNode( - "node1", privacyAccountResolver.resolve(0)); - bob = - privacyBesu.createPrivateTransactionEnabledNode("node2", privacyAccountResolver.resolve(1)); - charlie = - privacyBesu.createPrivateTransactionEnabledNode("node3", privacyAccountResolver.resolve(2)); - privacyCluster.start(alice, bob, charlie); - } - - @After - public void cleanUp() { - vertx.close(); - } - - @Test - public void onlyAliceAndBobCanExecuteContract() { - // Contract address is generated from sender address and transaction nonce - final String contractAddress = "0xebf56429e6500e84442467292183d4d621359838"; - - final EventEmitter eventEmitter = - alice.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - alice.getTransactionSigningKey(), - POW_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - privateContractVerifier - .validPrivateContractDeployed(contractAddress, alice.getAddress().toString()) - .verify(eventEmitter); - - final String transactionHash = - alice.execute( - privateContractTransactions.callSmartContract( - eventEmitter.getContractAddress(), - eventEmitter.store(BigInteger.ONE).encodeFunctionCall(), - alice.getTransactionSigningKey(), - POW_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - final PrivateTransactionReceipt expectedReceipt = - alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash)); - - bob.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - transactionHash, expectedReceipt)); - - charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(transactionHash)); - - // When Alice executes a contract call in the wrong privacy group the transaction should pass - // but it should NOT return any output - final String transactionHash2 = - alice.execute( - privateContractTransactions.callSmartContract( - eventEmitter.getContractAddress(), - eventEmitter.value().encodeFunctionCall(), - alice.getTransactionSigningKey(), - POW_CHAIN_ID, - alice.getEnclaveKey(), - charlie.getEnclaveKey())); - - final PrivateTransactionReceipt expectedReceipt2 = - alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash2)); - - assertThat(expectedReceipt2.getOutput()).isEqualTo("0x"); - - charlie.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - transactionHash2, expectedReceipt2)); - } - - @Test - public void aliceCanUsePrivDistributeTransaction() { - // Contract address is generated from sender address and transaction nonce - final String contractAddress = "0xebf56429e6500e84442467292183d4d621359838"; - - final RawPrivateTransaction rawPrivateTransaction = - RawPrivateTransaction.createContractTransaction( - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - Numeric.prependHexPrefix(EventEmitter.BINARY), - Base64String.wrap(alice.getEnclaveKey()), - Collections.singletonList(Base64String.wrap(bob.getEnclaveKey())), - Restriction.RESTRICTED); - - final String signedPrivateTransaction = - Numeric.toHexString( - PrivateTransactionEncoder.signMessage( - rawPrivateTransaction, - POW_CHAIN_ID, - Credentials.create(alice.getTransactionSigningKey()))); - final String transactionKey = - alice.execute(privacyTransactions.privDistributeTransaction(signedPrivateTransaction)); - - final Enclave aliceEnclave = enclaveFactory.createVertxEnclave(alice.getOrion().clientUrl()); - final ReceiveResponse aliceRR = - aliceEnclave.receive( - Bytes.fromHexString(transactionKey).toBase64String(), alice.getEnclaveKey()); - - final Enclave bobEnclave = enclaveFactory.createVertxEnclave(bob.getOrion().clientUrl()); - final ReceiveResponse bobRR = - bobEnclave.receive( - Bytes.fromHexString(transactionKey).toBase64String(), bob.getEnclaveKey()); - - assertThat(bobRR).isEqualToComparingFieldByField(aliceRR); - - final RawTransaction pmt = - RawTransaction.createTransaction( - BigInteger.ZERO, - BigInteger.valueOf(1000), - BigInteger.valueOf(65000), - Address.DEFAULT_PRIVACY.toString(), - transactionKey); - - final String signedPmt = - Numeric.toHexString( - TransactionEncoder.signMessage( - pmt, POW_CHAIN_ID, Credentials.create(alice.getTransactionSigningKey()))); - - final String transactionHash = alice.execute(ethTransactions.sendRawTransaction(signedPmt)); - - final PrivateTransactionReceipt expectedReceipt = - new PrivateTransactionReceipt( - contractAddress, - "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", - null, - eventEmitterDeployed, - Collections.emptyList(), - "0x023955c49d6265c579561940287449242704d5fd239ff07ea36a3fc7aface61c", - "0x82e521ee16ff13104c5f81e8354ecaaafd5450b710b07f620204032bfe76041a", - "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=", - new ArrayList<>( - Collections.singletonList("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=")), - null, - "0x1", - null); - - alice.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - transactionHash, expectedReceipt)); - - bob.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - transactionHash, expectedReceipt)); - } - - @Test - public void aliceCanDeployMultipleTimesInSingleGroup() { - final String firstDeployedAddress = "0xebf56429e6500e84442467292183d4d621359838"; - - final EventEmitter firstEventEmitter = - alice.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - alice.getTransactionSigningKey(), - POW_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - privateContractVerifier - .validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString()) - .verify(firstEventEmitter); - - final String secondDeployedAddress = "0x10f807f8a905da5bd319196da7523c6bd768690f"; - - final EventEmitter secondEventEmitter = - alice.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - alice.getTransactionSigningKey(), - POW_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - privateContractVerifier - .validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString()) - .verify(secondEventEmitter); - } - - @Test - public void canInteractWithMultiplePrivacyGroups() { - // alice deploys contract - final String firstDeployedAddress = "0xff206d21150a8da5b83629d8a722f3135ed532b1"; - - final EventEmitter firstEventEmitter = - alice.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - alice.getTransactionSigningKey(), - POW_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey(), - charlie.getEnclaveKey())); - - privateContractVerifier - .validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString()) - .verify(firstEventEmitter); - - // charlie interacts with contract - final String firstTransactionHash = - charlie.execute( - privateContractTransactions.callSmartContract( - firstEventEmitter.getContractAddress(), - firstEventEmitter.store(BigInteger.ONE).encodeFunctionCall(), - charlie.getTransactionSigningKey(), - POW_CHAIN_ID, - charlie.getEnclaveKey(), - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - // alice gets receipt from charlie's interaction - final PrivateTransactionReceipt firstExpectedReceipt = - alice.execute(privacyTransactions.getPrivateTransactionReceipt(firstTransactionHash)); - - // verify bob and charlie have access to the same receipt - bob.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - firstTransactionHash, firstExpectedReceipt)); - charlie.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - firstTransactionHash, firstExpectedReceipt)); - - // alice deploys second contract - final String secondDeployedAddress = "0xebf56429e6500e84442467292183d4d621359838"; - - final EventEmitter secondEventEmitter = - alice.execute( - privateContractTransactions.createSmartContract( - EventEmitter.class, - alice.getTransactionSigningKey(), - POW_CHAIN_ID, - alice.getEnclaveKey(), - bob.getEnclaveKey())); - - privateContractVerifier - .validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString()) - .verify(secondEventEmitter); - - // bob interacts with contract - final String secondTransactionHash = - bob.execute( - privateContractTransactions.callSmartContract( - secondEventEmitter.getContractAddress(), - secondEventEmitter.store(BigInteger.ONE).encodeFunctionCall(), - bob.getTransactionSigningKey(), - POW_CHAIN_ID, - bob.getEnclaveKey(), - alice.getEnclaveKey())); - - // alice gets receipt from bob's interaction - final PrivateTransactionReceipt secondExpectedReceipt = - alice.execute(privacyTransactions.getPrivateTransactionReceipt(secondTransactionHash)); - - bob.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - secondTransactionHash, secondExpectedReceipt)); - - // charlie cannot see the receipt - charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(secondTransactionHash)); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivacyGroupAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivacyGroupAcceptanceTest.java deleted file mode 100644 index 4afee1e3051..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivacyGroupAcceptanceTest.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.privacy; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.web3j.generated.EventEmitter; - -import java.math.BigInteger; - -import org.junit.Before; -import org.junit.Test; -import org.web3j.protocol.besu.response.privacy.PrivacyGroup; -import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; -import org.web3j.utils.Base64String; - -public class PrivacyGroupAcceptanceTest extends PrivacyAcceptanceTestBase { - - private PrivacyNode alice; - private PrivacyNode bob; - private PrivacyNode charlie; - - @Before - public void setUp() throws Exception { - alice = - privacyBesu.createPrivateTransactionEnabledMinerNode( - "node1", privacyAccountResolver.resolve(0)); - bob = - privacyBesu.createPrivateTransactionEnabledNode("node2", privacyAccountResolver.resolve(1)); - charlie = - privacyBesu.createPrivateTransactionEnabledNode("node3", privacyAccountResolver.resolve(2)); - privacyCluster.start(alice, bob, charlie); - } - - @Test - public void nodeCanCreatePrivacyGroup() { - final String privacyGroupId = - alice.execute( - privacyTransactions.createPrivacyGroup( - "myGroupName", "my group description", alice, bob)); - - assertThat(privacyGroupId).isNotNull(); - - final PrivacyGroup expected = - new PrivacyGroup( - privacyGroupId, - PrivacyGroup.Type.PANTHEON, - "myGroupName", - "my group description", - Base64String.wrapList(alice.getEnclaveKey(), bob.getEnclaveKey())); - - alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); - - bob.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); - } - - @Test - public void nodeCanCreatePrivacyGroupWithoutName() { - final String privacyGroupId = - alice.execute( - privacyTransactions.createPrivacyGroup(null, "my group description", alice, bob)); - - assertThat(privacyGroupId).isNotNull(); - - final PrivacyGroup expected = - new PrivacyGroup( - privacyGroupId, - PrivacyGroup.Type.PANTHEON, - "", - "my group description", - Base64String.wrapList(alice.getEnclaveKey(), bob.getEnclaveKey())); - - alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); - - bob.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); - } - - @Test - public void nodeCanCreatePrivacyGroupWithoutDescription() { - final String privacyGroupId = - alice.execute(privacyTransactions.createPrivacyGroup("myGroupName", null, alice, bob)); - - assertThat(privacyGroupId).isNotNull(); - - final PrivacyGroup expected = - new PrivacyGroup( - privacyGroupId, - PrivacyGroup.Type.PANTHEON, - "myGroupName", - "", - Base64String.wrapList(alice.getEnclaveKey(), bob.getEnclaveKey())); - - alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); - - bob.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); - } - - @Test - public void nodeCanCreatePrivacyGroupWithoutOptionalParams() { - final String privacyGroupId = - alice.execute(privacyTransactions.createPrivacyGroup(null, null, alice, bob)); - - assertThat(privacyGroupId).isNotNull(); - - final PrivacyGroup expected = - new PrivacyGroup( - privacyGroupId, - PrivacyGroup.Type.PANTHEON, - "", - "", - Base64String.wrapList(alice.getEnclaveKey(), bob.getEnclaveKey())); - - alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); - - bob.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected)); - } - - @Test - public void canInteractWithMultiplePrivacyGroups() { - final String privacyGroupIdABC = - alice.execute(privacyTransactions.createPrivacyGroup(null, null, alice, bob, charlie)); - - final EventEmitter firstEventEmitter = - alice.execute( - privateContractTransactions.createSmartContractWithPrivacyGroupId( - EventEmitter.class, - alice.getTransactionSigningKey(), - POW_CHAIN_ID, - alice.getEnclaveKey(), - privacyGroupIdABC)); - - // charlie interacts with contract - final String firstTransactionHash = - charlie.execute( - privateContractTransactions.callSmartContractWithPrivacyGroupId( - firstEventEmitter.getContractAddress(), - firstEventEmitter.store(BigInteger.ONE).encodeFunctionCall(), - charlie.getTransactionSigningKey(), - POW_CHAIN_ID, - charlie.getEnclaveKey(), - privacyGroupIdABC)); - - // alice gets receipt from charlie's interaction - final PrivateTransactionReceipt firstExpectedReceipt = - alice.execute(privacyTransactions.getPrivateTransactionReceipt(firstTransactionHash)); - - // verify bob and charlie have access to the same receipt - bob.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - firstTransactionHash, firstExpectedReceipt)); - charlie.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - firstTransactionHash, firstExpectedReceipt)); - - // alice deploys second contract - final String privacyGroupIdAB = - alice.execute(privacyTransactions.createPrivacyGroup(null, null, alice, bob)); - - final EventEmitter secondEventEmitter = - alice.execute( - privateContractTransactions.createSmartContractWithPrivacyGroupId( - EventEmitter.class, - alice.getTransactionSigningKey(), - POW_CHAIN_ID, - alice.getEnclaveKey(), - privacyGroupIdAB)); - - // bob interacts with contract - final String secondTransactionHash = - bob.execute( - privateContractTransactions.callSmartContractWithPrivacyGroupId( - secondEventEmitter.getContractAddress(), - secondEventEmitter.store(BigInteger.ONE).encodeFunctionCall(), - bob.getTransactionSigningKey(), - POW_CHAIN_ID, - bob.getEnclaveKey(), - privacyGroupIdAB)); - - // alice gets receipt from bob's interaction - final PrivateTransactionReceipt secondExpectedReceipt = - alice.execute(privacyTransactions.getPrivateTransactionReceipt(secondTransactionHash)); - - bob.verify( - privateTransactionVerifier.validPrivateTransactionReceipt( - secondTransactionHash, secondExpectedReceipt)); - - // charlie cannot see the receipt - charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(secondTransactionHash)); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivacyReceiptAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivacyReceiptAcceptanceTest.java deleted file mode 100644 index a824afbaf77..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivacyReceiptAcceptanceTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.privacy; - -import static java.util.Optional.empty; - -import org.hyperledger.besu.ethereum.core.Hash; -import org.hyperledger.besu.ethereum.core.Wei; -import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; -import org.hyperledger.besu.ethereum.privacy.Restriction; -import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.CreatePrivacyGroupTransaction; -import org.hyperledger.besu.tests.acceptance.dsl.transaction.miner.MinerTransactions; - -import java.util.Optional; - -import org.apache.tuweni.bytes.Bytes; -import org.junit.Before; -import org.junit.Test; - -public class PrivacyReceiptAcceptanceTest extends PrivacyAcceptanceTestBase { - private PrivacyNode alice; - final MinerTransactions minerTransactions = new MinerTransactions(); - - @Before - public void setUp() throws Exception { - alice = - privacyBesu.createIbft2NodePrivacyMiningEnabled("node1", privacyAccountResolver.resolve(0)); - privacyCluster.start(alice); - } - - @Test - public void createPrivateTransactionReceiptSuccessfulTransaction() { - final CreatePrivacyGroupTransaction onlyAlice = - privacyTransactions.createPrivacyGroup("Only Alice", "", alice); - - final String privacyGroupId = alice.execute(onlyAlice); - - final PrivateTransaction validTransaction = - createSignedTransaction(alice, privacyGroupId, empty()); - final BytesValueRLPOutput rlpOutput = getRLPOutput(validTransaction); - - final Hash transactionHash = - alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString())); - - // Successful PMT - alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash.toString())); - // Successful private transaction - alice.getBesu().verify(priv.getSuccessfulTransactionReceipt(transactionHash)); - } - - @Test - public void createPrivateTransactionReceiptFailedTransaction() { - final CreatePrivacyGroupTransaction onlyAlice = - privacyTransactions.createPrivacyGroup("Only Alice", "", alice); - - final String privacyGroupId = alice.execute(onlyAlice); - - final PrivateTransaction invalidPayloadTransaction = - createSignedTransaction( - alice, privacyGroupId, Optional.of(Bytes.fromBase64String("invalidPayload"))); - final BytesValueRLPOutput rlpOutput = getRLPOutput(invalidPayloadTransaction); - - final Hash transactionHash = - alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString())); - - // Successful PMT - alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash.toString())); - // Failed private transaction - alice.getBesu().verify(priv.getFailedTransactionReceipt(transactionHash)); - } - - @Test - public void createPrivateTransactionReceiptInvalidTransaction() { - final CreatePrivacyGroupTransaction onlyAlice = - privacyTransactions.createPrivacyGroup("Only Alice", "", alice); - - final String privacyGroupId = alice.execute(onlyAlice); - - final PrivateTransaction validTransaction = - createSignedTransaction(alice, privacyGroupId, empty()); - final BytesValueRLPOutput rlpOutput = getRLPOutput(validTransaction); - - // Stop mining, to allow adding duplicate nonce block - alice.getBesu().execute(minerTransactions.minerStop()); - - final Hash transactionHash1 = - alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString())); - final Hash transactionHash2 = - alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString())); - - // Start mining again - alice.getBesu().execute(minerTransactions.minerStart()); - - // Successful PMTs - alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash1.toString())); - alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash2.toString())); - // Successful first private transaction - alice.getBesu().verify(priv.getSuccessfulTransactionReceipt(transactionHash1)); - // Invalid second private transaction - alice.getBesu().verify(priv.getInvalidTransactionReceipt(transactionHash2)); - } - - private BytesValueRLPOutput getRLPOutput(final PrivateTransaction privateTransaction) { - final BytesValueRLPOutput bvrlpo = new BytesValueRLPOutput(); - privateTransaction.writeTo(bvrlpo); - return bvrlpo; - } - - private static PrivateTransaction createSignedTransaction( - final PrivacyNode node, final String privacyGoupId, final Optional payload) { - final Bytes defaultPayload = Bytes.wrap(new byte[] {}); - return PrivateTransaction.builder() - .nonce(0) - .gasPrice(Wei.of(999999)) - .gasLimit(3000000) - .to(null) - .value(Wei.ZERO) - .payload(payload.orElse(defaultPayload)) - .sender(node.getAddress()) - .privateFrom(Bytes.fromBase64String(node.getEnclaveKey())) - .restriction(Restriction.RESTRICTED) - .privacyGroupId(Bytes.fromBase64String(privacyGoupId)) - .signAndBuild(node.getBesu().getPrivacyParameters().getSigningKeyPair().get()); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivateContractPublicStateAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivateContractPublicStateAcceptanceTest.java deleted file mode 100644 index bce3ae32016..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivateContractPublicStateAcceptanceTest.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.privacy; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; -import org.hyperledger.besu.tests.web3j.generated.CrossContractReader; -import org.hyperledger.besu.tests.web3j.generated.EventEmitter; - -import java.math.BigInteger; - -import org.junit.Before; -import org.junit.Test; -import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; -import org.web3j.protocol.core.methods.response.TransactionReceipt; -import org.web3j.tx.exceptions.ContractCallException; - -public class PrivateContractPublicStateAcceptanceTest extends PrivacyAcceptanceTestBase { - private static final long POW_CHAIN_ID = 2018; - - private PrivacyNode minerNode; - private PrivacyNode transactionNode; - - @Before - public void setUp() throws Exception { - minerNode = - privacyBesu.createPrivateTransactionEnabledMinerNode( - "miner-node", privacyAccountResolver.resolve(0)); - transactionNode = - privacyBesu.createPrivateTransactionEnabledNode( - "transaction-node", privacyAccountResolver.resolve(1)); - privacyCluster.start(minerNode, transactionNode); - } - - @Test - public void mustAllowAccessToPublicStateFromPrivateTx() throws Exception { - final EventEmitter publicEventEmitter = - transactionNode.execute((contractTransactions.createSmartContract(EventEmitter.class))); - - final TransactionReceipt receipt = publicEventEmitter.store(BigInteger.valueOf(12)).send(); - assertThat(receipt).isNotNull(); - - final CrossContractReader reader = - transactionNode.execute( - privateContractTransactions.createSmartContract( - CrossContractReader.class, - transactionNode.getTransactionSigningKey(), - POW_CHAIN_ID, - transactionNode.getEnclaveKey())); - - assertThat(reader.read(publicEventEmitter.getContractAddress()).send()) - .isEqualTo(BigInteger.valueOf(12)); - } - - @Test(expected = ContractCallException.class) - public void mustNotAllowAccessToPrivateStateFromPublicTx() throws Exception { - final EventEmitter privateEventEmitter = - transactionNode.execute( - (privateContractTransactions.createSmartContract( - EventEmitter.class, - transactionNode.getTransactionSigningKey(), - POW_CHAIN_ID, - transactionNode.getEnclaveKey()))); - - final TransactionReceipt receipt = privateEventEmitter.store(BigInteger.valueOf(12)).send(); - assertThat(receipt).isNotNull(); - - final CrossContractReader publicReader = - transactionNode.execute( - contractTransactions.createSmartContract(CrossContractReader.class)); - - publicReader.read(privateEventEmitter.getContractAddress()).send(); - } - - @Test - public void privateContractMustNotBeAbleToCallPublicContractWhichChangesState() throws Exception { - final CrossContractReader privateReader = - transactionNode.execute( - privateContractTransactions.createSmartContract( - CrossContractReader.class, - transactionNode.getTransactionSigningKey(), - POW_CHAIN_ID, - transactionNode.getEnclaveKey())); - - final CrossContractReader publicReader = - transactionNode.execute( - contractTransactions.createSmartContract(CrossContractReader.class)); - - final PrivateTransactionReceipt transactionReceipt = - (PrivateTransactionReceipt) - privateReader.incrementRemote(publicReader.getContractAddress()).send(); - - assertThat(transactionReceipt.getOutput()).isEqualTo("0x"); - } - - @Test - public void privateContractMustNotBeAbleToCallPublicContractWhichInstantiatesContract() - throws Exception { - final CrossContractReader privateReader = - transactionNode.execute( - privateContractTransactions.createSmartContract( - CrossContractReader.class, - transactionNode.getTransactionSigningKey(), - POW_CHAIN_ID, - transactionNode.getEnclaveKey())); - - final CrossContractReader publicReader = - transactionNode.execute( - contractTransactions.createSmartContract(CrossContractReader.class)); - - final PrivateTransactionReceipt transactionReceipt = - (PrivateTransactionReceipt) - privateReader.deployRemote(publicReader.getContractAddress()).send(); - - assertThat(transactionReceipt.getLogs().size()).isEqualTo(0); - } - - @Test - public void privateContractMustNotBeAbleToCallSelfDestructOnPublicContract() throws Exception { - final CrossContractReader privateReader = - transactionNode.execute( - privateContractTransactions.createSmartContract( - CrossContractReader.class, - transactionNode.getTransactionSigningKey(), - POW_CHAIN_ID, - transactionNode.getEnclaveKey())); - - final CrossContractReader publicReader = - transactionNode - .getBesu() - .execute(contractTransactions.createSmartContract(CrossContractReader.class)); - - final PrivateTransactionReceipt transactionReceipt = - (PrivateTransactionReceipt) - privateReader.remoteDestroy(publicReader.getContractAddress()).send(); - - assertThat(transactionReceipt.getOutput()).isEqualTo("0x"); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/contracts/PrivacyProxyTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/contracts/PrivacyProxyTest.java deleted file mode 100644 index 402d3ca80ad..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/contracts/PrivacyProxyTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.web3j.privacy.contracts; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import org.hyperledger.besu.privacy.contracts.generated.DefaultOnChainPrivacyGroupManagementContract; -import org.hyperledger.besu.privacy.contracts.generated.OnChainPrivacyGroupManagementProxy; -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; -import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.web3j.crypto.Credentials; -import org.web3j.protocol.Web3j; -import org.web3j.protocol.exceptions.TransactionException; -import org.web3j.protocol.http.HttpService; -import org.web3j.tx.gas.DefaultGasProvider; -import org.web3j.utils.Base64String; - -@SuppressWarnings("unchecked") -public class PrivacyProxyTest extends AcceptanceTestBase { - - private final Base64String firstParticipant = - Base64String.wrap("93Ky7lXwFkMc7+ckoFgUMku5bpr9tz4zhmWmk9RlNng="); - private final Base64String secondParticipant = - Base64String.wrap("9iaJ6OObl6TUWYjXAOyZsL0VaDPwF+tRFkMwwYSeqqw="); - private final Base64String thirdParticipant = - Base64String.wrap("Jo2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs="); - private OnChainPrivacyGroupManagementProxy onChainPrivacyGroupManagementProxy; - - private static final String RAW_GET_PARTICIPANTS = "0x5aa68ac0"; - private static final String RAW_ADD_PARTICIPANT = - "0xb4926e2500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000"; - - private BesuNode minerNode; - private DefaultOnChainPrivacyGroupManagementContract defaultOnChainPrivacyGroupManagementContract; - - @Before - public void setUp() throws Exception { - minerNode = besu.createMinerNode("node"); - cluster.start(minerNode); - defaultOnChainPrivacyGroupManagementContract = - minerNode.execute( - contractTransactions.createSmartContract( - DefaultOnChainPrivacyGroupManagementContract.class)); - onChainPrivacyGroupManagementProxy = - minerNode.execute( - contractTransactions.createSmartContract( - OnChainPrivacyGroupManagementProxy.class, - defaultOnChainPrivacyGroupManagementContract.getContractAddress())); - } - - @Test - public void rlp() throws Exception { - assertThat(onChainPrivacyGroupManagementProxy.isValid()).isEqualTo(true); - contractVerifier - .validTransactionReceipt(onChainPrivacyGroupManagementProxy.getContractAddress()) - .verify(onChainPrivacyGroupManagementProxy); - assertThat(RAW_GET_PARTICIPANTS) - .isEqualTo(onChainPrivacyGroupManagementProxy.getParticipants().encodeFunctionCall()); - assertThat(RAW_ADD_PARTICIPANT) - .isEqualTo( - onChainPrivacyGroupManagementProxy - .addParticipants(Collections.emptyList()) - .encodeFunctionCall()); - } - - @Ignore("return 0x which causes web3j to throw exception instead of return empty list") - @Test - public void deploysWithNoParticipant() throws Exception { - final List participants = onChainPrivacyGroupManagementProxy.getParticipants().send(); - assertThat(participants.size()).isEqualTo(0); - } - - @Test - public void canAddParticipants() throws Exception { - onChainPrivacyGroupManagementProxy - .addParticipants(Arrays.asList(firstParticipant.raw(), secondParticipant.raw())) - .send(); - final List participants = onChainPrivacyGroupManagementProxy.getParticipants().send(); - assertThat(participants.size()).isEqualTo(2); - assertThat(firstParticipant.raw()).isEqualTo(participants.get(0)); - assertThat(secondParticipant.raw()).isEqualTo(participants.get(1)); - } - - @Test - public void nonOwnerCannotUpgrade() throws Exception { - onChainPrivacyGroupManagementProxy - .addParticipants(Arrays.asList(firstParticipant.raw(), secondParticipant.raw())) - .send(); - final List participants = onChainPrivacyGroupManagementProxy.getParticipants().send(); - assertThat(participants.size()).isEqualTo(2); - assertThat(firstParticipant.raw()).isEqualTo(participants.get(0)); - assertThat(secondParticipant.raw()).isEqualTo(participants.get(1)); - - final DefaultOnChainPrivacyGroupManagementContract upgradedContract = - minerNode.execute( - contractTransactions.createSmartContract( - DefaultOnChainPrivacyGroupManagementContract.class)); - - final HttpService httpService = - new HttpService( - "http://" + minerNode.getHostName() + ":" + minerNode.getJsonRpcSocketPort().get()); - final Web3j web3j = Web3j.build(httpService); - - // load the proxy contract, use it with another signer - final OnChainPrivacyGroupManagementProxy proxyContractAccount2 = - OnChainPrivacyGroupManagementProxy.load( - onChainPrivacyGroupManagementProxy.getContractAddress(), - web3j, - Credentials.create(Accounts.GENESIS_ACCOUNT_TWO_PRIVATE_KEY), - new DefaultGasProvider()); - // contract is the proxy contract and uses genesis account 2. It should not be able to upgrade - // the contract, because it is not the owner of "upgradedContract" - assertThatThrownBy( - () -> proxyContractAccount2.upgradeTo(upgradedContract.getContractAddress()).send()) - .isInstanceOf(TransactionException.class); - } - - @Test - public void ownerCanUpgrade() throws Exception { - onChainPrivacyGroupManagementProxy - .addParticipants(Arrays.asList(firstParticipant.raw(), secondParticipant.raw())) - .send(); - final List participants = onChainPrivacyGroupManagementProxy.getParticipants().send(); - assertThat(participants.size()).isEqualTo(2); - assertThat(firstParticipant.raw()).isEqualTo(participants.get(0)); - assertThat(secondParticipant.raw()).isEqualTo(participants.get(1)); - - final DefaultOnChainPrivacyGroupManagementContract upgradedContract = - minerNode.execute( - contractTransactions.createSmartContract( - DefaultOnChainPrivacyGroupManagementContract.class)); - - onChainPrivacyGroupManagementProxy.upgradeTo(upgradedContract.getContractAddress()).send(); - final List participantsAfterUpgrade = - onChainPrivacyGroupManagementProxy.getParticipants().send(); - assertThat(participantsAfterUpgrade.size()).isEqualTo(2); - assertThat(firstParticipant.raw()).isEqualTo(participantsAfterUpgrade.get(0)); - assertThat(secondParticipant.raw()).isEqualTo(participantsAfterUpgrade.get(1)); - } - - @Test - public void canAddTwiceToContractWhenCallLock() throws Exception { - onChainPrivacyGroupManagementProxy - .addParticipants(Arrays.asList(firstParticipant.raw(), thirdParticipant.raw())) - .send(); - onChainPrivacyGroupManagementProxy.lock().send(); - onChainPrivacyGroupManagementProxy - .addParticipants(Collections.singletonList(secondParticipant.raw())) - .send(); - final List participants = onChainPrivacyGroupManagementProxy.getParticipants().send(); - assertThat(participants.size()).isEqualTo(3); - assertThat(firstParticipant.raw()).isEqualTo(participants.get(0)); - assertThat(thirdParticipant.raw()).isEqualTo(participants.get(1)); - assertThat(secondParticipant.raw()).isEqualTo(participants.get(2)); - } -} diff --git a/acceptance-tests/tests/src/test/resources/acceptanceTesting.security b/acceptance-tests/tests/src/test/resources/acceptanceTesting.security index 9eb914534a4..7c3e8a26127 100644 --- a/acceptance-tests/tests/src/test/resources/acceptanceTesting.security +++ b/acceptance-tests/tests/src/test/resources/acceptanceTesting.security @@ -1,6 +1,6 @@ ##### NOT FOR PRODUCTION USE ###### ### FOR ACCEPTANCE TESTING ONLY ### # Disable OS provided entropy -securerandom.source= +securerandom.source=file:/dev/urandom ### FOR ACCEPTANCE TESTING ONLY ### ##### NOT FOR PRODUCTION USE ###### diff --git a/acceptance-tests/tests/src/test/resources/authentication/auth_priv_ec_pubkey.toml b/acceptance-tests/tests/src/test/resources/authentication/auth_priv_ec_pubkey.toml new file mode 100644 index 00000000000..291973d7ce7 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/authentication/auth_priv_ec_pubkey.toml @@ -0,0 +1,19 @@ +[Users.user] +password = "$2a$10$l3GA7K8g6rJ/Yv.YFSygCuI9byngpEzxgWS9qEg5emYDZomQW7fGC" +permissions = ["fakePermission", "*:*"] +privacyPublicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAES8nC4qT/KdoAoTSF3qs/47DUsDihyVbWiRjZAiyvqp9eSDkqV1RzlM+58oOwnpFRwvWNZM+AxMVxT+MvxdsqMA==" + +[Users.user2] +password = "$2a$10$0ikMUcSYugKmnXilimhc1eGNnfMRvKt2PxQJPo1oCemN16QL2NNo." +permissions = ["fakePermission", "*:*"] +privacyPublicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXIgZqRA25V+3nN+Do6b5r0jiUunub6ubjPhqwHpPxP44uUYh9RKCQNRnsqCJ9PjeTnC8R3ieJk7HWAlycU1bug==" + +[Users.user3] +password = "$2a$10$Mydyzpul6CtgPRbUd6It2OpZDOfqOocpi6.UYhlyU5aphQHi1iQZq" +permissions = ["fakePermission", "*:*"] +privacyPublicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFl85WnNPyzSEX+evc774xoqUQdjSnQMTE1uIyMOve+iVwjs6dUEUwz5teiKuUUf63a/qYe4n6SGnQ7HnmtDViQ==" + +[Users.failUser] +password = "$2a$10$l3GA7K8g6rJ/Yv.YFSygCuI9byngpEzxgWS9qEg5emYDZomQW7fGC" +permissions = ["fakePermission", "*:*"] +privacyPublicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE30vyCv2v4EHwqnr0LEGaCX6GWfmYIIxLRw1PISeFsOk1tmY2hAYjEHkaZzu31SlFx0ickh10MEublBnrxCiJIA==" diff --git a/acceptance-tests/tests/src/test/resources/authentication/jwt_public_key_ecdsa b/acceptance-tests/tests/src/test/resources/authentication/jwt_public_key_ecdsa new file mode 100644 index 00000000000..65a23fa3ed7 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/authentication/jwt_public_key_ecdsa @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEy8+qE0ZFo4woPUCXfszptuDgaDpW +Sv6D5F/pbolJ2wZTVkYXoGhA3wqy1RM1RYmROp9NEPLm3mZP+kzI4TMiGg== +-----END PUBLIC KEY----- diff --git a/acceptance-tests/tests/src/test/resources/authentication/jwt_public_key b/acceptance-tests/tests/src/test/resources/authentication/jwt_public_key_rsa similarity index 100% rename from acceptance-tests/tests/src/test/resources/authentication/jwt_public_key rename to acceptance-tests/tests/src/test/resources/authentication/jwt_public_key_rsa diff --git a/acceptance-tests/tests/src/test/resources/clique/clique.json b/acceptance-tests/tests/src/test/resources/clique/clique.json index 971ccb40414..8fb3c6dc331 100644 --- a/acceptance-tests/tests/src/test/resources/clique/clique.json +++ b/acceptance-tests/tests/src/test/resources/clique/clique.json @@ -3,12 +3,10 @@ "chainId": 4, "homesteadBlock": 1, "eip150Block": 2, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 3, "eip158Block": 4, "byzantiumBlock": 5, "constantinopleBlock": 6, - "constantinopleFixBlock": 7, + "petersburgBlock": 7, "clique": { "blockperiodseconds": 10, "epochlength": 30000 diff --git a/acceptance-tests/tests/src/test/resources/crypto/secp256r1.json b/acceptance-tests/tests/src/test/resources/crypto/secp256r1.json new file mode 100644 index 00000000000..630e394c357 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/crypto/secp256r1.json @@ -0,0 +1,23 @@ +{ + "config": { + "chainId": 1981, + "ecCurve": "secp256r1", + "constantinoplefixblock": 0, + "ethash": { + "fixeddifficulty": 1000 + } + }, + "nonce": "0x0", + "timestamp": "0x58ee40ba", + "gasLimit": "0x1fffffffffffff", + "difficulty": "0x1", + "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", + "alloc": { + "91240f5b6994c7ed80f9f94b1aa847880ad3b150": { + "privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", + "info": "This genesis file uses SECP256R1 as elliptic curve. The address is only valid for this curve and invalid with the default SECP256K1 curve.", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "0xad78ebc5ac6200000" + } + } +} diff --git a/acceptance-tests/tests/src/test/resources/dev/dev_london.json b/acceptance-tests/tests/src/test/resources/dev/dev_london.json new file mode 100644 index 00000000000..709f74a3026 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/dev/dev_london.json @@ -0,0 +1,43 @@ +{ + "config":{ + "chainId":20211, + "homesteadBlock":0, + "eip150Block":0, + "eip155Block":0, + "eip158Block":0, + "byzantiumBlock":0, + "constantinopleBlock":0, + "petersburgBlock":0, + "istanbulBlock":0, + "berlinBlock":0, + "londonBlock":0, + "ethash":{ + "fixeddifficulty": 1 + } + }, + "alloc":{ + "fe3b557e8fb62b89f4916b721be55ceb828dbd73": { + "privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "0xad78ebc5ac6200000" + }, + "627306090abaB3A6e1400e9345bC60c78a8BEf57": { + "privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "90000000000000000000000" + }, + "f17f52151EbEF6C7334FAD080c5704D77216b732": { + "privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "90000000000000000000000" + } + }, + "coinbase":"0x0000000000000000000000000000000000000000", + "difficulty":"0x00001", + "extraData":"0x5365706f6c69612c20417468656e732c204174746963612c2047726565636521", + "gasLimit":"0x1c9c380", + "nonce":"0x000000000000000", + "mixhash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp":"0x6159af19" +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/ibft/ibft.json b/acceptance-tests/tests/src/test/resources/ibft/ibft.json index 01765901fd1..dddbf01b8bf 100644 --- a/acceptance-tests/tests/src/test/resources/ibft/ibft.json +++ b/acceptance-tests/tests/src/test/resources/ibft/ibft.json @@ -1,12 +1,7 @@ { "config": { "chainId": 4, - "homesteadBlock": 1, - "eip150Block": 2, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 3, - "eip158Block": 3, - "byzantiumBlock": 1035301, + "berlinBlock": 0, "ibft2": { "blockperiodseconds": 1, "epochlength": 30000, diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/genesis.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/genesis.json new file mode 100644 index 00000000000..7f41d1260a9 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/genesis.json @@ -0,0 +1,35 @@ +{ + "config": { + "chainId":1, + "homesteadBlock":0, + "eip150Block":0, + "eip155Block":0, + "eip158Block":0, + "byzantiumBlock":0, + "constantinopleBlock":0, + "petersburgBlock":0, + "istanbulBlock":0, + "muirGlacierBlock":0, + "berlinBlock":0, + "londonBlock":0, + "clique": { + "period": 5, + "epoch": 30000 + }, + "terminalTotalDifficulty":0 + }, + "nonce":"0x42", + "timestamp":"0x0", + "extraData":"0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit":"0x1C9C380", + "difficulty":"0x400000000", + "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase":"0x0000000000000000000000000000000000000000", + "alloc":{ + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b":{"balance":"0x6d6172697573766477000000"} + }, + "number":"0x0", + "gasUsed":"0x0", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas":"0x7" +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/01_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/01_prepare_payload.json new file mode 100644 index 00000000000..3ab6f968fbc --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/01_prepare_payload.json @@ -0,0 +1,32 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV1", + "params": [ + { + "headBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "safeBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "timestamp": "0x5", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "validationError": null + }, + "payloadId": "0x0065bd195a9b3bfb" + } + }, + "statusCode" : 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/02_execute_payload_1.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/02_execute_payload_1.json new file mode 100644 index 00000000000..e4c82c26d3c --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/02_execute_payload_1.json @@ -0,0 +1,35 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV1", + "params": [ + { + "parentHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x1", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x5", + "extraData": "0x", + "baseFeePerGas": "0x7", + "blockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "transactions": [] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/03_execute_payload_2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/03_execute_payload_2.json new file mode 100644 index 00000000000..b7be6df8007 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/03_execute_payload_2.json @@ -0,0 +1,35 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV1", + "params": [ + { + "parentHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x2", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x6", + "extraData": "0x", + "baseFeePerGas": "0x7", + "blockHash": "0x80732341439dd124df94271386141735f13ef8a85e12e9fba15c06bc1ad9fd73", + "transactions": [] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0x80732341439dd124df94271386141735f13ef8a85e12e9fba15c06bc1ad9fd73", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/04_update_forkchoice.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/04_update_forkchoice.json new file mode 100644 index 00000000000..d39fcc8db33 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/04_update_forkchoice.json @@ -0,0 +1,28 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV1", + "params": [ + { + "headBlockHash": "0x80732341439dd124df94271386141735f13ef8a85e12e9fba15c06bc1ad9fd73", + "safeBlockHash": "0x80732341439dd124df94271386141735f13ef8a85e12e9fba15c06bc1ad9fd73", + "finalizedBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a" + }, + null + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0x80732341439dd124df94271386141735f13ef8a85e12e9fba15c06bc1ad9fd73", + "validationError": null + }, + "payloadId": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/05_get_latest_block.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/05_get_latest_block.json new file mode 100644 index 00000000000..bbb0826a465 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/05_get_latest_block.json @@ -0,0 +1,33 @@ +{ + "request": { + "jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest", false],"id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result": { + "number": "0x2", + "hash": "0x80732341439dd124df94271386141735f13ef8a85e12e9fba15c06bc1ad9fd73", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "nonce": "0x0000000000000000", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot": "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "miner": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "difficulty": "0x0", + "totalDifficulty": "0x400000000", + "extraData": "0x", + "baseFeePerGas": "0x7", + "size": "0x1fa", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x6", + "uncles": [], + "transactions": [] + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/06_debug_replay_block.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/06_debug_replay_block.json new file mode 100644 index 00000000000..6f96b1dd57f --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/06_debug_replay_block.json @@ -0,0 +1,11 @@ +{ + "request": { + "jsonrpc":"2.0","method":"debug_replayBlock","params":["0x1"],"id":1 + }, + "response": { + "jsonrpc" : "2.0", + "id" : 1, + "result" : "Success" + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/07_get_latest_block_after_replay_block.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/07_get_latest_block_after_replay_block.json new file mode 100644 index 00000000000..5b2d2ca5db7 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/replayBlock/test-cases/07_get_latest_block_after_replay_block.json @@ -0,0 +1,33 @@ +{ + "request": { + "jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest", false],"id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result" : { + "number" : "0x1", + "hash" : "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash" : "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "nonce" : "0x0000000000000000", + "sha3Uncles" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "transactionsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "miner" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "difficulty" : "0x0", + "totalDifficulty" : "0x400000000", + "extraData" : "0x", + "baseFeePerGas" : "0x7", + "size" : "0x1fa", + "gasLimit" : "0x1c9c380", + "gasUsed" : "0x0", + "timestamp" : "0x5", + "uncles" : [ ], + "transactions" : [ ] + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/genesis.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/genesis.json new file mode 100644 index 00000000000..7f41d1260a9 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/genesis.json @@ -0,0 +1,35 @@ +{ + "config": { + "chainId":1, + "homesteadBlock":0, + "eip150Block":0, + "eip155Block":0, + "eip158Block":0, + "byzantiumBlock":0, + "constantinopleBlock":0, + "petersburgBlock":0, + "istanbulBlock":0, + "muirGlacierBlock":0, + "berlinBlock":0, + "londonBlock":0, + "clique": { + "period": 5, + "epoch": 30000 + }, + "terminalTotalDifficulty":0 + }, + "nonce":"0x42", + "timestamp":"0x0", + "extraData":"0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit":"0x1C9C380", + "difficulty":"0x400000000", + "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase":"0x0000000000000000000000000000000000000000", + "alloc":{ + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b":{"balance":"0x6d6172697573766477000000"} + }, + "number":"0x0", + "gasUsed":"0x0", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas":"0x7" +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/01_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/01_prepare_payload.json new file mode 100644 index 00000000000..3ab6f968fbc --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/01_prepare_payload.json @@ -0,0 +1,32 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV1", + "params": [ + { + "headBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "safeBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "timestamp": "0x5", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "validationError": null + }, + "payloadId": "0x0065bd195a9b3bfb" + } + }, + "statusCode" : 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/02_execute_payload_1.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/02_execute_payload_1.json new file mode 100644 index 00000000000..e4c82c26d3c --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/02_execute_payload_1.json @@ -0,0 +1,35 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV1", + "params": [ + { + "parentHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x1", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x5", + "extraData": "0x", + "baseFeePerGas": "0x7", + "blockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "transactions": [] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/03_execute_payload_2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/03_execute_payload_2.json new file mode 100644 index 00000000000..b7be6df8007 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/03_execute_payload_2.json @@ -0,0 +1,35 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV1", + "params": [ + { + "parentHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x2", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x6", + "extraData": "0x", + "baseFeePerGas": "0x7", + "blockHash": "0x80732341439dd124df94271386141735f13ef8a85e12e9fba15c06bc1ad9fd73", + "transactions": [] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0x80732341439dd124df94271386141735f13ef8a85e12e9fba15c06bc1ad9fd73", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/04_update_forkchoice.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/04_update_forkchoice.json new file mode 100644 index 00000000000..d39fcc8db33 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/04_update_forkchoice.json @@ -0,0 +1,28 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV1", + "params": [ + { + "headBlockHash": "0x80732341439dd124df94271386141735f13ef8a85e12e9fba15c06bc1ad9fd73", + "safeBlockHash": "0x80732341439dd124df94271386141735f13ef8a85e12e9fba15c06bc1ad9fd73", + "finalizedBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a" + }, + null + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0x80732341439dd124df94271386141735f13ef8a85e12e9fba15c06bc1ad9fd73", + "validationError": null + }, + "payloadId": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/05_get_latest_block.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/05_get_latest_block.json new file mode 100644 index 00000000000..bbb0826a465 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/05_get_latest_block.json @@ -0,0 +1,33 @@ +{ + "request": { + "jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest", false],"id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result": { + "number": "0x2", + "hash": "0x80732341439dd124df94271386141735f13ef8a85e12e9fba15c06bc1ad9fd73", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "nonce": "0x0000000000000000", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot": "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "miner": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "difficulty": "0x0", + "totalDifficulty": "0x400000000", + "extraData": "0x", + "baseFeePerGas": "0x7", + "size": "0x1fa", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x6", + "uncles": [], + "transactions": [] + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/06_debug_set_head.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/06_debug_set_head.json new file mode 100644 index 00000000000..18f5862b531 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/06_debug_set_head.json @@ -0,0 +1,11 @@ +{ + "request": { + "jsonrpc":"2.0","method":"debug_setHead","params":["0x1"],"id":1 + }, + "response": { + "jsonrpc" : "2.0", + "id" : 1, + "result" : "Success" + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/07_get_latest_block_after_set_head.json b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/07_get_latest_block_after_set_head.json new file mode 100644 index 00000000000..5b2d2ca5db7 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/debug/setHead/test-cases/07_get_latest_block_after_set_head.json @@ -0,0 +1,33 @@ +{ + "request": { + "jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest", false],"id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result" : { + "number" : "0x1", + "hash" : "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash" : "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "nonce" : "0x0000000000000000", + "sha3Uncles" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "transactionsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "miner" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "difficulty" : "0x0", + "totalDifficulty" : "0x400000000", + "extraData" : "0x", + "baseFeePerGas" : "0x7", + "size" : "0x1fa", + "gasLimit" : "0x1c9c380", + "gasUsed" : "0x0", + "timestamp" : "0x5", + "uncles" : [ ], + "transactions" : [ ] + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/genesis.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/genesis.json new file mode 100644 index 00000000000..b6a16b71a40 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/genesis.json @@ -0,0 +1,38 @@ +{ + "config": { + "chainId":1, + "homesteadBlock":0, + "eip150Block":0, + "eip155Block":0, + "eip158Block":0, + "byzantiumBlock":0, + "constantinopleBlock":0, + "petersburgBlock":0, + "istanbulBlock":0, + "muirGlacierBlock":0, + "berlinBlock":0, + "londonBlock":0, + "terminalTotalDifficulty":0, + "shanghaiTime":0, + "experimentalEipsTime":20, + "clique": { + "period": 5, + "epoch": 30000 + }, + "depositContractAddress": "0x00000000219ab540356cbb839cbe05303d7705fa" + }, + "nonce":"0x42", + "timestamp":"0x0", + "extraData":"0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit":"0x1C9C380", + "difficulty":"0x400000000", + "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase":"0x0000000000000000000000000000000000000000", + "alloc":{ + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b":{"balance":"0x6d6172697573766477000000"} + }, + "number":"0x0", + "gasUsed":"0x0", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas":"0x7" +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/01_shanghai_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/01_shanghai_prepare_payload.json new file mode 100644 index 00000000000..960194fcae0 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/01_shanghai_prepare_payload.json @@ -0,0 +1,46 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV2", + "params": [ + { + "headBlockHash": "0xfe950635b1bd2a416ff6283b0bbd30176e1b1125ad06fa729da9f3f4c1c61710", + "safeBlockHash": "0xfe950635b1bd2a416ff6283b0bbd30176e1b1125ad06fa729da9f3f4c1c61710", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "timestamp": "0x10", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x3" + }, + { + "index": "0x1", + "validatorIndex": "0x1", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x4" + } + ] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0xfe950635b1bd2a416ff6283b0bbd30176e1b1125ad06fa729da9f3f4c1c61710", + "validationError": null + }, + "payloadId": "0x0065bd1bbeaff359" + } + }, + "statusCode" : 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/02_shanghai_getPayloadV2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/02_shanghai_getPayloadV2.json new file mode 100644 index 00000000000..9d25e3f5e84 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/02_shanghai_getPayloadV2.json @@ -0,0 +1,49 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_getPayloadV2", + "params": [ + "0x0065bd1bbeaff359" + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "executionPayload": { + "parentHash": "0xfe950635b1bd2a416ff6283b0bbd30176e1b1125ad06fa729da9f3f4c1c61710", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xc8c8e840369eac89a610bfe2ec21fcdee4c9c43bec4876f0129fcd4b5311f6dd", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x10", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x3" + }, + { + "index": "0x1", + "validatorIndex": "0x1", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x4" + } + ], + "deposits": null, + "blockNumber": "0x1", + "blockHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + }, + "blockValue": "0x0" + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/03_shanghai_newPayloadV2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/03_shanghai_newPayloadV2.json new file mode 100644 index 00000000000..938362327ba --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/03_shanghai_newPayloadV2.json @@ -0,0 +1,49 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV2", + "params": [ + { + "parentHash": "0xfe950635b1bd2a416ff6283b0bbd30176e1b1125ad06fa729da9f3f4c1c61710", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xc8c8e840369eac89a610bfe2ec21fcdee4c9c43bec4876f0129fcd4b5311f6dd", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x10", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x3" + }, + { + "index": "0x1", + "validatorIndex": "0x1", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x4" + } + ], + "blockNumber": "0x1", + "blockHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/04_shanghai_forkchoiceUpdatedV2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/04_shanghai_forkchoiceUpdatedV2.json new file mode 100644 index 00000000000..871832b9c99 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/04_shanghai_forkchoiceUpdatedV2.json @@ -0,0 +1,28 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV2", + "params": [ + { + "headBlockHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "safeBlockHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "finalizedBlockHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13" + }, + null + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "validationError": null + }, + "payloadId": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/05_eip6110_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/05_eip6110_prepare_payload.json new file mode 100644 index 00000000000..d3d7ee37e30 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/05_eip6110_prepare_payload.json @@ -0,0 +1,46 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV2", + "params": [ + { + "headBlockHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "safeBlockHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "timestamp": "0x20", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x1" + }, + { + "index": "0x1", + "validatorIndex": "0x0", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x2" + } + ] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "validationError": null + }, + "payloadId": "0x0065bd63871ad606" + } + }, + "statusCode" : 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/06_eip6110_get_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/06_eip6110_get_payload.json new file mode 100644 index 00000000000..89b7cf65b2e --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/06_eip6110_get_payload.json @@ -0,0 +1,49 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_getPayloadV2", + "params": [ + "0x0065bd63871ad606" + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "executionPayload": { + "parentHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0x21395692fae33414143728c9ffc0aed8dcc76eb6731dd0f5a3239977478ca969", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x20", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x1" + }, + { + "index": "0x1", + "validatorIndex": "0x0", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x2" + } + ], + "deposits" : [], + "blockNumber": "0x2", + "blockHash": "0x58ea3e01b03ac17c68ed3e3d724a021408273fac8a86f42cb30a26be8e93fbe9", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + }, + "blockValue": "0x0" + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/07_eip6110_invalid_null_deposits_execute_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/07_eip6110_invalid_null_deposits_execute_payload.json new file mode 100644 index 00000000000..ebdd0ad81c2 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/07_eip6110_invalid_null_deposits_execute_payload.json @@ -0,0 +1,49 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV2", + "params": [ + { + "parentHash": "0x4f88d512a0045bc6d447ba74a18eac0ed2ebb8d9faca325f5f55b2ca84be0705", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0x1a10dba514dc4faff7ec13edd9b5ef653c1cd14eb26608bfc2b37717730a55a4", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x20", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x1" + }, + { + "index": "0x1", + "validatorIndex": "0x0", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x2" + } + ], + "deposits": null, + "blockNumber": "0x3", + "blockHash": "0x1475ca311179652e44b10b7e2d7b72f3708f3201f8d729880a83f3eb397910e8", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "error": { + "code": -32602, + "message": "Invalid params" + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/08_eip6110_execute_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/08_eip6110_execute_payload.json new file mode 100644 index 00000000000..6fe5f5a5640 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/08_eip6110_execute_payload.json @@ -0,0 +1,50 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV2", + "params": [ + { + "parentHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0x21395692fae33414143728c9ffc0aed8dcc76eb6731dd0f5a3239977478ca969", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x20", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x1" + }, + { + "index": "0x1", + "validatorIndex": "0x0", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x2" + } + ], + "deposits": [], + "blockNumber": "0x2", + "blockHash": "0xdfdf57a09e352c38bb2873c5fd7d0d199481c6e13661c4a004d116417377b2e5", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0xdfdf57a09e352c38bb2873c5fd7d0d199481c6e13661c4a004d116417377b2e5", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/genesis.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/genesis.json new file mode 100644 index 00000000000..085b69a1dd5 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/genesis.json @@ -0,0 +1,35 @@ +{ + "config": { + "chainId":1, + "homesteadBlock":0, + "eip150Block":0, + "eip155Block":0, + "eip158Block":0, + "byzantiumBlock":0, + "constantinopleBlock":0, + "petersburgBlock":0, + "istanbulBlock":0, + "muirGlacierBlock":0, + "berlinBlock":0, + "londonBlock":0, + "terminalTotalDifficulty":0, + "clique": { + "period": 5, + "epoch": 30000 + } + }, + "nonce":"0x42", + "timestamp":"0x0", + "extraData":"0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit":"0x1C9C380", + "difficulty":"0x400000000", + "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase":"0x0000000000000000000000000000000000000000", + "alloc":{ + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b":{"balance":"0x6d6172697573766477000000"} + }, + "number":"0x0", + "gasUsed":"0x0", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas":"0x7" +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/01_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/01_prepare_payload.json new file mode 100644 index 00000000000..3ab6f968fbc --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/01_prepare_payload.json @@ -0,0 +1,32 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV1", + "params": [ + { + "headBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "safeBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "timestamp": "0x5", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "validationError": null + }, + "payloadId": "0x0065bd195a9b3bfb" + } + }, + "statusCode" : 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/02_get_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/02_get_payload.json new file mode 100644 index 00000000000..e5257090527 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/02_get_payload.json @@ -0,0 +1,31 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_getPayloadV1", + "params": [ + "0x0065bd195a9b3bfb" + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "parentHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x1", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x5", + "extraData": "0x", + "baseFeePerGas": "0x7", + "blockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "transactions": [] + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/03_execute_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/03_execute_payload.json new file mode 100644 index 00000000000..e4c82c26d3c --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/03_execute_payload.json @@ -0,0 +1,35 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV1", + "params": [ + { + "parentHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x1", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x5", + "extraData": "0x", + "baseFeePerGas": "0x7", + "blockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "transactions": [] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/04_invalid_safeblock_hash.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/04_invalid_safeblock_hash.json new file mode 100644 index 00000000000..7381e94ece9 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/04_invalid_safeblock_hash.json @@ -0,0 +1,24 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV1", + "params": [ + { + "headBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "safeBlockHash": "0x00000051470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04abcdef", + "finalizedBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a" + }, + null + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "error": { + "code": -38002, + "message": "Invalid forkchoice state" + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/05_invalid_finalized_block_hash.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/05_invalid_finalized_block_hash.json new file mode 100644 index 00000000000..919553383aa --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/05_invalid_finalized_block_hash.json @@ -0,0 +1,24 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV1", + "params": [ + { + "headBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "safeBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "finalizedBlockHash": "0x00000040d288781d4aac94d3fd16809ee413bc99294a085798a589dae5abcdef" + }, + null + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "error": { + "code": -38002, + "message": "Invalid forkchoice state" + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/06_update_forkchoice_invalid_payload_attributes.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/06_update_forkchoice_invalid_payload_attributes.json new file mode 100644 index 00000000000..4014e14a6ff --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/06_update_forkchoice_invalid_payload_attributes.json @@ -0,0 +1,28 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV1", + "params": [ + { + "headBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "safeBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "finalizedBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a" + }, + { + "timestamp": "0x0", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "suggestedFeeRecipient": "0x0000000000000000000000000000000000000000" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "error": { + "code": -38003, + "message": "Invalid payload attributes" + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/07_update_forkchoice.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/07_update_forkchoice.json new file mode 100644 index 00000000000..8635adddb2b --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/07_update_forkchoice.json @@ -0,0 +1,28 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV1", + "params": [ + { + "headBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "safeBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "finalizedBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a" + }, + null + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "validationError": null + }, + "payloadId": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/08_unknown_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/08_unknown_payload.json new file mode 100644 index 00000000000..21ccd28c154 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/08_unknown_payload.json @@ -0,0 +1,19 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_getPayloadV1", + "params": [ + "0x0000000000000000" + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "error": { + "code": -32001, + "message": "Payload does not exist / is not available" + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/09_invalid_head.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/09_invalid_head.json new file mode 100644 index 00000000000..a7b699d9e96 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/09_invalid_head.json @@ -0,0 +1,32 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV1", + "params": [ + { + "headBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000001", + "safeBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "timestamp": "0x5", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "SYNCING", + "latestValidHash": null, + "validationError": null + }, + "payloadId": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/genesis.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/genesis.json new file mode 100644 index 00000000000..6b596fee607 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/genesis.json @@ -0,0 +1,51 @@ +{ + "config": { + "chainId":1, + "homesteadBlock":0, + "eip150Block":0, + "eip155Block":0, + "eip158Block":0, + "byzantiumBlock":0, + "constantinopleBlock":0, + "petersburgBlock":0, + "istanbulBlock":0, + "muirGlacierBlock":0, + "berlinBlock":0, + "londonBlock":0, + "terminalTotalDifficulty":0, + "shanghaiTime":10, + "clique": { + "period": 5, + "epoch": 30000 + } + }, + "nonce":"0x42", + "timestamp":"0x0", + "extraData":"0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit":"0x1C9C380", + "difficulty":"0x400000000", + "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase":"0x0000000000000000000000000000000000000000", + "alloc":{ + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b":{"balance":"0x6d6172697573766477000000"}, + "0x0000000000000000000000000000000000000100" : { + "balance" : "0x00", + "code" : "0x60015f55", + "nonce" : "0x00", + "storage" : { + } + }, + "0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x00", + "code" : "0x6000806000806000803560601c620186a0f160005560018055", + "nonce" : "0x00", + "storage" : { + "0x01" : "0x01" + } + } + }, + "number":"0x0", + "gasUsed":"0x0", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas":"0x7" +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/01_paris_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/01_paris_prepare_payload.json new file mode 100644 index 00000000000..314dbd2e4e4 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/01_paris_prepare_payload.json @@ -0,0 +1,32 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV1", + "params": [ + { + "headBlockHash": "0x274b386b1b268ebb5ca1f717c1279a536faf1f74dda959143dd8a779f8d8a908", + "safeBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "timestamp": "0x5", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0x274b386b1b268ebb5ca1f717c1279a536faf1f74dda959143dd8a779f8d8a908", + "validationError": null + }, + "payloadId": "0x0065bd3490dd4505" + } + }, + "statusCode" : 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/02_paris_getPayloadV1.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/02_paris_getPayloadV1.json new file mode 100644 index 00000000000..9a6d96f884a --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/02_paris_getPayloadV1.json @@ -0,0 +1,31 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_getPayloadV1", + "params": [ + "0x0065bd3490dd4505" + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "parentHash": "0x274b386b1b268ebb5ca1f717c1279a536faf1f74dda959143dd8a779f8d8a908", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xbe4b5fae64ef4f22db6639c62b4ce120f3d4adda1bc536d317d1ada680b574ef", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x1", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x5", + "extraData": "0x", + "baseFeePerGas": "0x7", + "blockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "transactions": [] + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/03_paris_newPayloadV1.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/03_paris_newPayloadV1.json new file mode 100644 index 00000000000..6f7bc724f22 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/03_paris_newPayloadV1.json @@ -0,0 +1,35 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV1", + "params": [ + { + "parentHash": "0x274b386b1b268ebb5ca1f717c1279a536faf1f74dda959143dd8a779f8d8a908", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xbe4b5fae64ef4f22db6639c62b4ce120f3d4adda1bc536d317d1ada680b574ef", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x1", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x5", + "extraData": "0x", + "baseFeePerGas": "0x7", + "blockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "transactions": [] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/04_paris_forkchoiceUpdatedV1.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/04_paris_forkchoiceUpdatedV1.json new file mode 100644 index 00000000000..1bba4a092a3 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/04_paris_forkchoiceUpdatedV1.json @@ -0,0 +1,28 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV1", + "params": [ + { + "headBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "safeBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "finalizedBlockHash": "0x274b386b1b268ebb5ca1f717c1279a536faf1f74dda959143dd8a779f8d8a908" + }, + null + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "validationError": null + }, + "payloadId": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/05_shanghai_prepare_payload_invalid_null_withdrawals.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/05_shanghai_prepare_payload_invalid_null_withdrawals.json new file mode 100644 index 00000000000..ac5947c79be --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/05_shanghai_prepare_payload_invalid_null_withdrawals.json @@ -0,0 +1,28 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV2", + "params": [ + { + "headBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "safeBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "timestamp": "0x10", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "id": 67 + }, + "response": { + "jsonrpc" : "2.0", + "id" : 67, + "error" : { + "code" : -32602, + "message" : "Invalid params" + } + }, + "statusCode" : 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/06_shanghai_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/06_shanghai_prepare_payload.json new file mode 100644 index 00000000000..456a9a74264 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/06_shanghai_prepare_payload.json @@ -0,0 +1,46 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV2", + "params": [ + { + "headBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "safeBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "timestamp": "0x10", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x3" + }, + { + "index": "0x1", + "validatorIndex": "0x1", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x4" + } + ] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "validationError": null + }, + "payloadId": "0x0065bd2db6663f59" + } + }, + "statusCode" : 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json new file mode 100644 index 00000000000..dcb022e1a62 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json @@ -0,0 +1,46 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV2", + "params": [ + { + "headBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "safeBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "timestamp": "0x10", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x1" + }, + { + "index": "0x1", + "validatorIndex": "0x1", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x2" + } + ] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "validationError": null + }, + "payloadId": "0x0065bd2db6663ed9" + } + }, + "statusCode" : 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/08_shanghai_getPayloadV2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/08_shanghai_getPayloadV2.json new file mode 100644 index 00000000000..2da9be48f4e --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/08_shanghai_getPayloadV2.json @@ -0,0 +1,49 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_getPayloadV2", + "params": [ + "0x0065bd2db6663ed9" + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "executionPayload": { + "parentHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xa61c2a422a4f7d7d7f456c1a83d5484eaf0d49e2b6b6d5716f875e782c66a9f0", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x10", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x1" + }, + { + "index": "0x1", + "validatorIndex": "0x1", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x2" + } + ], + "deposits": null, + "blockNumber": "0x2", + "blockHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + }, + "blockValue": "0x0" + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/09_shanghai_newPayloadV2_invalid_null_withdrawals.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/09_shanghai_newPayloadV2_invalid_null_withdrawals.json new file mode 100644 index 00000000000..b682b05c369 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/09_shanghai_newPayloadV2_invalid_null_withdrawals.json @@ -0,0 +1,35 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV2", + "params": [ + { + "parentHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xa61c2a422a4f7d7d7f456c1a83d5484eaf0d49e2b6b6d5716f875e782c66a9f0", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x10", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [], + "withdrawals": null, + "blockNumber": "0x2", + "blockHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "error": { + "code": -32602, + "message": "Invalid params" + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/10_shanghai_newPayloadV2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/10_shanghai_newPayloadV2.json new file mode 100644 index 00000000000..f17a98a5631 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/10_shanghai_newPayloadV2.json @@ -0,0 +1,49 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV2", + "params": [ + { + "parentHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xa61c2a422a4f7d7d7f456c1a83d5484eaf0d49e2b6b6d5716f875e782c66a9f0", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x10", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x1" + }, + { + "index": "0x1", + "validatorIndex": "0x1", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x2" + } + ], + "blockNumber": "0x2", + "blockHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/11_shanghai_forkchoiceUpdatedV2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/11_shanghai_forkchoiceUpdatedV2.json new file mode 100644 index 00000000000..938372b0ce6 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/11_shanghai_forkchoiceUpdatedV2.json @@ -0,0 +1,28 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV2", + "params": [ + { + "headBlockHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", + "safeBlockHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", + "finalizedBlockHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20" + }, + null + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", + "validationError": null + }, + "payloadId": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/12_shanghai_withdrawals_address1_latest_balance.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/12_shanghai_withdrawals_address1_latest_balance.json new file mode 100644 index 00000000000..dba627bd101 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/12_shanghai_withdrawals_address1_latest_balance.json @@ -0,0 +1,11 @@ +{ + "request": { + "jsonrpc":"2.0","method":"eth_getBalance","params":["0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b","latest"],"id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result": "0x6d61726975737664b29aca00" + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/13_shanghai_withdrawals_address2_latest_balance.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/13_shanghai_withdrawals_address2_latest_balance.json new file mode 100644 index 00000000000..7eb698ee0e3 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/13_shanghai_withdrawals_address2_latest_balance.json @@ -0,0 +1,11 @@ +{ + "request": { + "jsonrpc":"2.0","method":"eth_getBalance","params":["0xfe3b557e8fb62b89f4916b721be55ceb828dbd73","latest"],"id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result": "0x77359400" + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/14_shanghai_newPayloadV2_push0_tx.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/14_shanghai_newPayloadV2_push0_tx.json new file mode 100644 index 00000000000..788aad210b8 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/14_shanghai_newPayloadV2_push0_tx.json @@ -0,0 +1,38 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV2", + "params": [ + { + "parentHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xf8e89cc49d51d0bbbfd75fe214712e04f3b70e7c447261a2290262a8e1c4d0e1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x111f8", + "timestamp": "0x11", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [ + "0xf874800a830aae6094b94f5374fce5edbc8e2a8697c15331677e6ebf0b809400000000000000000000000000000000000001001ba040c30479d1f1f7ac729145a6e98ff0bc4882cc21930cc283db84f42f1852d9fba0567ecfa0b8daeedfd9ab8d520bcf44f06d682be47dac7d64a6865cec4ec33cef" + ], + "withdrawals": [], + "blockNumber": "0x3", + "blockHash": "0x85a4410f70b315e85382c7def115df2742348734f14c91bfbad0f2c67e9de4a2", + "receiptsRoot": "0x1668c1a230c3e0aaa4c52af3bada02571dabb4e1743ebd6eaf4bbe8008e8cc3e" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0x85a4410f70b315e85382c7def115df2742348734f14c91bfbad0f2c67e9de4a2", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/genesis.json b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/genesis.json new file mode 100644 index 00000000000..98a1201c9aa --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/genesis.json @@ -0,0 +1,36 @@ +{ + "config": { + "chainId":1, + "homesteadBlock":0, + "eip150Block":0, + "eip155Block":0, + "eip158Block":0, + "byzantiumBlock":0, + "constantinopleBlock":0, + "petersburgBlock":0, + "istanbulBlock":0, + "muirGlacierBlock":0, + "berlinBlock":0, + "londonBlock":0, + "shanghaiTime":10, + "clique": { + "period": 5, + "epoch": 30000 + }, + "terminalTotalDifficulty":0 + }, + "nonce":"0x42", + "timestamp":"0x0", + "extraData":"0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit":"0x1C9C380", + "difficulty":"0x400000000", + "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase":"0x0000000000000000000000000000000000000000", + "alloc":{ + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b":{"balance":"0x6d6172697573766477000000"} + }, + "number":"0x0", + "gasUsed":"0x0", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas":"0x7" +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/01_execute_payload_1.json b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/01_execute_payload_1.json new file mode 100644 index 00000000000..f4322b22a6b --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/01_execute_payload_1.json @@ -0,0 +1,35 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV2", + "params": [ + { + "parentHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x1", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x5", + "extraData": "0x", + "baseFeePerGas": "0x7", + "blockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "transactions": [] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/02_execute_payload_2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/02_execute_payload_2.json new file mode 100644 index 00000000000..0f160f3c39d --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/02_execute_payload_2.json @@ -0,0 +1,36 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV2", + "params": [ + { + "parentHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x2", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x10", + "extraData": "0x", + "baseFeePerGas": "0x7", + "blockHash": "0x7c2a09bedc85268606805e6df579e758af8d832ef9826927ce4b4b14452a32cf", + "transactions": [], + "withdrawals": [] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0x7c2a09bedc85268606805e6df579e758af8d832ef9826927ce4b4b14452a32cf", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/03_execute_payload_3.json b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/03_execute_payload_3.json new file mode 100644 index 00000000000..9b27bc59a26 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/03_execute_payload_3.json @@ -0,0 +1,49 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV2", + "params": [ + { + "parentHash": "0x7c2a09bedc85268606805e6df579e758af8d832ef9826927ce4b4b14452a32cf", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0x7a6f2e03f2348dc75731e6e767c97a88da50430748a030874e27f7c3fac3d49d", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x3", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x11", + "extraData": "0x", + "baseFeePerGas": "0x7", + "blockHash": "0x77edeba4adb3cb3e365fccb48393c8445a5c4c6648ec660806c2ce1e9de13fd3", + "transactions": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x1" + }, + { + "index": "0x1", + "validatorIndex": "0x0", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x2" + } + ] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0x77edeba4adb3cb3e365fccb48393c8445a5c4c6648ec660806c2ce1e9de13fd3", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/04_update_forkchoice.json b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/04_update_forkchoice.json new file mode 100644 index 00000000000..c3c234f04df --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/04_update_forkchoice.json @@ -0,0 +1,28 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV2", + "params": [ + { + "headBlockHash": "0x77edeba4adb3cb3e365fccb48393c8445a5c4c6648ec660806c2ce1e9de13fd3", + "safeBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "finalizedBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a" + }, + null + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0x77edeba4adb3cb3e365fccb48393c8445a5c4c6648ec660806c2ce1e9de13fd3", + "validationError": null + }, + "payloadId": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/05_get_genesis_block.json b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/05_get_genesis_block.json new file mode 100644 index 00000000000..4a4e8abee58 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/05_get_genesis_block.json @@ -0,0 +1,33 @@ +{ + "request": { + "jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0", false],"id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result" : { + "number" : "0x0", + "hash" : "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce" : "0x0000000000000042", + "sha3Uncles" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "transactionsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "miner" : "0x0000000000000000000000000000000000000000", + "difficulty" : "0x400000000", + "totalDifficulty" : "0x400000000", + "extraData":"0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas" : "0x7", + "size" : "0x275", + "gasLimit" : "0x1c9c380", + "gasUsed" : "0x0", + "timestamp" : "0x0", + "uncles" : [ ], + "transactions" : [ ] + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/06_get_last_paris_block.json b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/06_get_last_paris_block.json new file mode 100644 index 00000000000..f81c9b64964 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/06_get_last_paris_block.json @@ -0,0 +1,33 @@ +{ + "request": { + "jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x1", false],"id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result" : { + "number" : "0x1", + "hash" : "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash" : "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "nonce" : "0x0000000000000000", + "sha3Uncles" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "transactionsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "miner" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "difficulty" : "0x0", + "totalDifficulty" : "0x400000000", + "extraData" : "0x", + "baseFeePerGas" : "0x7", + "size" : "0x1fa", + "gasLimit" : "0x1c9c380", + "gasUsed" : "0x0", + "timestamp" : "0x5", + "uncles" : [ ], + "transactions" : [ ] + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/07_get_first_shanghai_block.json b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/07_get_first_shanghai_block.json new file mode 100644 index 00000000000..de9d681fd13 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/07_get_first_shanghai_block.json @@ -0,0 +1,35 @@ +{ + "request": { + "jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x2", false],"id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result" : { + "number" : "0x2", + "hash" : "0x7c2a09bedc85268606805e6df579e758af8d832ef9826927ce4b4b14452a32cf", + "mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash" : "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "nonce" : "0x0000000000000000", + "sha3Uncles" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "transactionsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "miner" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "difficulty" : "0x0", + "totalDifficulty" : "0x400000000", + "extraData" : "0x", + "baseFeePerGas" : "0x7", + "size" : "0x21c", + "gasLimit" : "0x1c9c380", + "gasUsed" : "0x0", + "timestamp" : "0x10", + "uncles" : [ ], + "transactions" : [ ], + "withdrawalsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "withdrawals": [ ] + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/08_get_latest_block.json b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/08_get_latest_block.json new file mode 100644 index 00000000000..dc3eaf96370 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/08_get_latest_block.json @@ -0,0 +1,48 @@ +{ + "request": { + "jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest", false],"id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result" : { + "number" : "0x3", + "hash" : "0x77edeba4adb3cb3e365fccb48393c8445a5c4c6648ec660806c2ce1e9de13fd3", + "mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash" : "0x7c2a09bedc85268606805e6df579e758af8d832ef9826927ce4b4b14452a32cf", + "nonce" : "0x0000000000000000", + "sha3Uncles" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "transactionsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0x7a6f2e03f2348dc75731e6e767c97a88da50430748a030874e27f7c3fac3d49d", + "receiptsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "miner" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "difficulty" : "0x0", + "totalDifficulty" : "0x400000000", + "extraData" : "0x", + "baseFeePerGas" : "0x7", + "size" : "0x24e", + "gasLimit" : "0x1c9c380", + "gasUsed" : "0x0", + "timestamp" : "0x11", + "uncles" : [ ], + "transactions" : [ ], + "withdrawalsRoot" : "0x18f3a249d9eb5115c5a632731a8ae4014b874bad61d4e1658a75aa190256c3b0", + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x1" + }, + { + "index": "0x1", + "validatorIndex": "0x0", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x2" + } + ] + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/09_get_last_paris_block_by_hash.json b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/09_get_last_paris_block_by_hash.json new file mode 100644 index 00000000000..a7392e9414d --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/09_get_last_paris_block_by_hash.json @@ -0,0 +1,33 @@ +{ + "request": { + "jsonrpc":"2.0","method":"eth_getBlockByHash","params":["0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", false],"id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result" : { + "number" : "0x1", + "hash" : "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash" : "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", + "nonce" : "0x0000000000000000", + "sha3Uncles" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "transactionsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "miner" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "difficulty" : "0x0", + "totalDifficulty" : "0x400000000", + "extraData" : "0x", + "baseFeePerGas" : "0x7", + "size" : "0x1fa", + "gasLimit" : "0x1c9c380", + "gasUsed" : "0x0", + "timestamp" : "0x5", + "uncles" : [ ], + "transactions" : [ ] + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/10_get_first_shanghai_block_by_hash.json b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/10_get_first_shanghai_block_by_hash.json new file mode 100644 index 00000000000..8ef5aa2095b --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/10_get_first_shanghai_block_by_hash.json @@ -0,0 +1,35 @@ +{ + "request": { + "jsonrpc":"2.0","method":"eth_getBlockByHash","params":["0x7c2a09bedc85268606805e6df579e758af8d832ef9826927ce4b4b14452a32cf", false],"id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result" : { + "number" : "0x2", + "hash" : "0x7c2a09bedc85268606805e6df579e758af8d832ef9826927ce4b4b14452a32cf", + "mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash" : "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "nonce" : "0x0000000000000000", + "sha3Uncles" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "transactionsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45", + "receiptsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "miner" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "difficulty" : "0x0", + "totalDifficulty" : "0x400000000", + "extraData" : "0x", + "baseFeePerGas" : "0x7", + "size" : "0x21c", + "gasLimit" : "0x1c9c380", + "gasUsed" : "0x0", + "timestamp" : "0x10", + "uncles" : [ ], + "transactions" : [ ], + "withdrawalsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "withdrawals": [ ] + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/11_get_latest_block_by_hash.json b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/11_get_latest_block_by_hash.json new file mode 100644 index 00000000000..8b886204742 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/eth/getBlockBy/test-cases/11_get_latest_block_by_hash.json @@ -0,0 +1,48 @@ +{ + "request": { + "jsonrpc":"2.0","method":"eth_getBlockByHash","params":["0x77edeba4adb3cb3e365fccb48393c8445a5c4c6648ec660806c2ce1e9de13fd3", false],"id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result" : { + "number" : "0x3", + "hash" : "0x77edeba4adb3cb3e365fccb48393c8445a5c4c6648ec660806c2ce1e9de13fd3", + "mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash" : "0x7c2a09bedc85268606805e6df579e758af8d832ef9826927ce4b4b14452a32cf", + "nonce" : "0x0000000000000000", + "sha3Uncles" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "transactionsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0x7a6f2e03f2348dc75731e6e767c97a88da50430748a030874e27f7c3fac3d49d", + "receiptsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "miner" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "difficulty" : "0x0", + "totalDifficulty" : "0x400000000", + "extraData" : "0x", + "baseFeePerGas" : "0x7", + "size" : "0x24e", + "gasLimit" : "0x1c9c380", + "gasUsed" : "0x0", + "timestamp" : "0x11", + "uncles" : [ ], + "transactions" : [ ], + "withdrawalsRoot" : "0x18f3a249d9eb5115c5a632731a8ae4014b874bad61d4e1658a75aa190256c3b0", + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x1" + }, + { + "index": "0x1", + "validatorIndex": "0x0", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x2" + } + ] + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/log4j2.xml b/acceptance-tests/tests/src/test/resources/log4j2.xml index af826438c13..ec7a9d96ece 100644 --- a/acceptance-tests/tests/src/test/resources/log4j2.xml +++ b/acceptance-tests/tests/src/test/resources/log4j2.xml @@ -81,8 +81,6 @@ - - diff --git a/acceptance-tests/tests/src/test/resources/permissioning/simple_permissioning_genesis.json b/acceptance-tests/tests/src/test/resources/permissioning/simple_permissioning_genesis.json index 0d8508e7b97..5aee1cc13b3 100644 --- a/acceptance-tests/tests/src/test/resources/permissioning/simple_permissioning_genesis.json +++ b/acceptance-tests/tests/src/test/resources/permissioning/simple_permissioning_genesis.json @@ -1,14 +1,7 @@ { "config": { "chainId": 999, - "homesteadBlock": 0, - "daoForkBlock": 0, - "eip150Block": 0, - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "constantinopleFixBlock": 0, + "petersburgBlock": 0, "ethash": { "fixeddifficulty": 100 } diff --git a/acceptance-tests/tests/src/test/resources/permissioning/simple_permissioning_ibft_genesis.json b/acceptance-tests/tests/src/test/resources/permissioning/simple_permissioning_ibft_genesis.json index 725161f82e7..907547b0ca9 100644 --- a/acceptance-tests/tests/src/test/resources/permissioning/simple_permissioning_ibft_genesis.json +++ b/acceptance-tests/tests/src/test/resources/permissioning/simple_permissioning_ibft_genesis.json @@ -1,14 +1,7 @@ { "config": { "chainId": 999, - "homesteadBlock": 0, - "daoForkBlock": 0, - "eip150Block": 0, - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "constantinopleFixBlock": 0, + "petersburgBlock": 0, "ibft2": { "blockperiodseconds": 5, "epochlength": 30000, diff --git a/acceptance-tests/tests/src/test/resources/permissioning/simple_permissioning_v2_genesis.json b/acceptance-tests/tests/src/test/resources/permissioning/simple_permissioning_v2_genesis.json index ce6c9d00b64..1802856c793 100644 --- a/acceptance-tests/tests/src/test/resources/permissioning/simple_permissioning_v2_genesis.json +++ b/acceptance-tests/tests/src/test/resources/permissioning/simple_permissioning_v2_genesis.json @@ -1,14 +1,7 @@ { "config": { "chainId": 999, - "homesteadBlock": 0, - "daoForkBlock": 0, - "eip150Block": 0, - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "constantinopleFixBlock": 0, + "petersburgBlock": 0, "ethash": { "fixeddifficulty": 100 } diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/README.md b/acceptance-tests/tests/src/test/resources/pki-certs/README.md new file mode 100644 index 00000000000..25b23db2031 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/README.md @@ -0,0 +1,127 @@ +See `ethereum/p2p/src/test/resources/keys/README.md` which describes the details on how the +certificates are created. The same CA are used to create miner1-miner6. + +For `PkiQbftAcceptanceTest`: +`miner1`-`miner5` are signed with `partner1_ca` and `miner6` is signed with `partner2_ca`. +`miner5` and `miner6` are revoked and added in the crl list. + +Sample shell script that can be executed to recreate the certificates +~~~ +#! /bin/sh + +names=("partner1:miner1" "partner1:miner2" "partner1:miner3" "partner1:miner4" "partner1:miner5" "partner2:miner6") +crls=("partner1:miner5" "partner2:miner6") +KEY_ALG="EC -groupname secp256r1" +#KEY_ALG="RSA -keysize 2048" + +########## +CA_CERTS_PATH=./ca_certs +ROOT_CA_KS=$CA_CERTS_PATH/root_ca.p12 +INTER_CA_KS=$CA_CERTS_PATH/inter_ca.p12 +CRL_DIR=./crl + +keytool -exportcert -keystore $ROOT_CA_KS -storepass test123 -alias root_ca -rfc -file $CA_CERTS_PATH/root_ca.pem + +echo "Generating miner keystores..." +### Generate client keystores +for name in "${names[@]}" +do + IFS=':' read -r -a array <<< "$name" + partner=${array[0]} + client=${array[1]} + + PARTNER_CA_KEYSTORE="$CA_CERTS_PATH/${partner}_ca.p12" + CLIENT_PATH="./${client}" + KEYSTORE_PATH="./$CLIENT_PATH/${client}.p12" + NSSDB_PATH="${CLIENT_PATH}/nssdb" + + echo "$PARTNER_CA_KEYSTORE" + + mkdir -p $NSSDB_PATH + + echo "Generating keystore for Partner $partner Client $client" + keytool -genkeypair -keystore $KEYSTORE_PATH -storepass test123 -alias ${client} \ + -keyalg $KEY_ALG -validity 36500 \ + -dname "CN=localhost, OU=${partner}" \ + -ext san=dns:localhost,ip:127.0.0.1 + + echo "Creating CSR for $client and signing it with ${partner}_ca" + keytool -storepass test123 -keystore $KEYSTORE_PATH -certreq -alias ${client} \ + | keytool -storepass test123 -keystore $PARTNER_CA_KEYSTORE -gencert -alias "${partner}_ca" -ext ku:c=digitalSignature,nonRepudiation,keyEncipherment -ext eku=sA,cA \ + -rfc > "${CLIENT_PATH}/${client}.pem" + + echo "Concat root_ca.pem to ${client}.pem" + cat "${CA_CERTS_PATH}/root_ca.pem" >> "${CLIENT_PATH}/${client}.pem" + + echo "Importing signed $client.pem CSR into $KEYSTORE_PATH" + keytool -keystore $KEYSTORE_PATH -importcert -alias $client \ + -storepass test123 -noprompt -file "${CLIENT_PATH}/${client}.pem" + + echo "Converting p12 to jks" + keytool -importkeystore -srckeystore $KEYSTORE_PATH -srcstoretype PKCS12 -destkeystore "$CLIENT_PATH/${client}.jks" -deststoretype JKS -srcstorepass test123 -deststorepass test123 -srcalias $client -destalias $client -srckeypass test123 -destkeypass test123 -noprompt + + echo "Initialize nss" + echo "test123" > ${CLIENT_PATH}/nsspin.txt + certutil -N -d sql:${NSSDB_PATH} -f "${CLIENT_PATH}/nsspin.txt" + # hack to make Java SunPKCS11 work with new sql version of nssdb + touch ${NSSDB_PATH}/secmod.db + + pk12util -i $KEYSTORE_PATH -d sql:${NSSDB_PATH} -k ${CLIENT_PATH}/nsspin.txt -W test123 + echo "Fixing truststores in sql:${NSSDB_PATH}" + certutil -M -n "CN=root.ca.besu.com" -t CT,C,C -d sql:"$NSSDB_PATH" -f ${CLIENT_PATH}/nsspin.txt + certutil -M -n "CN=inter.ca.besu.com" -t CT,C,C -d sql:"$NSSDB_PATH" -f ${CLIENT_PATH}/nsspin.txt + certutil -M -n "CN=${partner}.ca.besu.com" -t CT,C,C -d sql:"$NSSDB_PATH" -f ${CLIENT_PATH}/nsspin.txt + + certutil -d sql:"$NSSDB_PATH" -f nsspin.txt -L + + echo "Creating pkcs11 nss config file" + cat <${CLIENT_PATH}/nss.cfg +name = NSScrypto-${partner}-${client} +nssSecmodDirectory = ./src/test/resources/pki-certs/${client}/nssdb +nssDbMode = readOnly +nssModule = keystore +showInfo = true +EOF + + # remove pem files + rm "${CLIENT_PATH}/${client}.pem" + + # create truststore + echo "Creating truststore ..." + keytool -exportcert -keystore $ROOT_CA_KS -storepass test123 -alias root_ca -rfc | keytool -import -trustcacerts -alias root_ca -keystore "${CLIENT_PATH}/truststore.p12" -storepass test123 -noprompt + keytool -exportcert -keystore $INTER_CA_KS -storepass test123 -alias inter_ca -rfc | keytool -import -trustcacerts -alias inter_ca -keystore "${CLIENT_PATH}/truststore.p12" -storepass test123 -noprompt + keytool -exportcert -keystore $PARTNER_CA_KEYSTORE -storepass test123 -alias "${partner}_ca" -rfc | keytool -import -trustcacerts -alias "${partner}_ca" -keystore "${CLIENT_PATH}/truststore.p12" -storepass test123 -noprompt + +done +rm $CA_CERTS_PATH/root_ca.pem +echo "Keystores and nss database created" + +## create crl list +mkdir -p $CRL_DIR +rm $CRL_DIR/crl.pem + +for crl in "${crls[@]}" +do + IFS=':' read -r -a array <<< "$crl" + partner=${array[0]} + client=${array[1]} + + echo "Exporting CA certificate and private key" + openssl pkcs12 -nodes -in "$CA_CERTS_PATH/${partner}_ca.p12" -out "$CRL_DIR/${partner}_ca_key.pem" -passin pass:test123 -nocerts + openssl pkcs12 -nodes -in "$CA_CERTS_PATH/${partner}_ca.p12" -out "$CRL_DIR/${partner}_ca.pem" -passin pass:test123 -nokeys + + echo "Export $client certificate" + openssl pkcs12 -nodes -in "./${client}/${client}.p12" -out "$CRL_DIR/${client}.pem" -passin pass:test123 -nokeys + + ## On Mac, use gnutls-certtool, on Linux use certtool + echo "Creating crl" + printf '365\n\n' | gnutls-certtool --generate-crl --load-ca-privkey "$CRL_DIR/${partner}_ca_key.pem" --load-ca-certificate "$CRL_DIR/${partner}_ca.pem" \ + --load-certificate "$CRL_DIR/${client}.pem" >> $CRL_DIR/crl.pem + + rm "$CRL_DIR/${partner}_ca_key.pem" + rm "$CRL_DIR/${partner}_ca.pem" + rm "$CRL_DIR/${client}.pem" + +done + +~~~ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/ca_certs/inter_ca.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/ca_certs/inter_ca.p12 new file mode 100644 index 00000000000..a6e945c2f06 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/ca_certs/inter_ca.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/ca_certs/partner1_ca.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/ca_certs/partner1_ca.p12 new file mode 100644 index 00000000000..fc89f3e90f4 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/ca_certs/partner1_ca.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/ca_certs/partner2_ca.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/ca_certs/partner2_ca.p12 new file mode 100644 index 00000000000..c9fe7186792 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/ca_certs/partner2_ca.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/ca_certs/root_ca.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/ca_certs/root_ca.p12 new file mode 100644 index 00000000000..8fc62a23ace Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/ca_certs/root_ca.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/create.sh b/acceptance-tests/tests/src/test/resources/pki-certs/create.sh new file mode 100644 index 00000000000..c780e5e113e --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/create.sh @@ -0,0 +1,176 @@ +#! /bin/sh + +set -e + +names=("partner1:miner1" "partner1:miner2" "partner1:miner3" "partner1:miner4" "partner1:miner5" "partner2:miner6") +crls=("partner1:miner5" "partner2:miner6") +KEY_ALG="EC -groupname secp256r1" +#KEY_ALG="RSA -keysize 2048" + +########## +CA_CERTS_PATH=./ca_certs +ROOT_CA_KS=$CA_CERTS_PATH/root_ca.p12 +INTER_CA_KS=$CA_CERTS_PATH/inter_ca.p12 +PARTNER1_CA_KS=$CA_CERTS_PATH/partner1_ca.p12 +PARTNER2_CA_KS=$CA_CERTS_PATH/partner2_ca.p12 +CRL_DIR=./crl + +mkdir $CA_CERTS_PATH + +keytool -genkeypair -alias root_ca -dname "CN=root.ca.besu.com" -ext bc:c -keyalg RSA -keysize 2048 \ +-sigalg SHA256WithRSA -validity 36500 \ +-storepass test123 \ +-keystore $ROOT_CA_KS + +keytool -exportcert -keystore $ROOT_CA_KS -storepass test123 -alias root_ca -rfc -file $CA_CERTS_PATH/root_ca.pem + +keytool -genkeypair -alias inter_ca -dname "CN=inter.ca.besu.com" \ +-ext bc:c=ca:true,pathlen:1 -ext ku:c=dS,kCS,cRLs \ +-keyalg RSA -sigalg SHA256WithRSA -validity 36500 \ +-storepass test123 \ +-keystore $INTER_CA_KS + +keytool -exportcert -keystore $INTER_CA_KS -storepass test123 -alias inter_ca -rfc -file $CA_CERTS_PATH/inter_ca.pem + +keytool -genkeypair -alias partner1_ca -dname "CN=partner1.ca.besu.com" \ +-ext bc:c=ca:true,pathlen:0 -ext ku:c=dS,kCS,cRLs \ +-keyalg RSA -sigalg SHA256WithRSA -validity 36500 \ +-storepass test123 \ +-keystore $PARTNER1_CA_KS + +keytool -exportcert -keystore $PARTNER1_CA_KS -storepass test123 -alias partner1_ca -rfc -file $CA_CERTS_PATH/partner1_ca.pem + +keytool -genkeypair -alias partner2_ca -dname "CN=partner2.ca.besu.com" \ +-ext bc:c=ca:true,pathlen:0 -ext ku:c=dS,kCS,cRLs \ +-keyalg RSA -sigalg SHA256WithRSA -validity 36500 \ +-storepass test123 \ +-keystore $PARTNER2_CA_KS + +keytool -exportcert -keystore $PARTNER2_CA_KS -storepass test123 -alias partner2_ca -rfc -file $CA_CERTS_PATH/partner2_ca.pem + +keytool -storepass test123 -keystore $INTER_CA_KS -certreq -alias inter_ca \ +| keytool -storepass test123 -keystore $ROOT_CA_KS -gencert -validity 36500 -alias root_ca \ +-ext bc:c=ca:true,pathlen:1 -ext ku:c=dS,kCS,cRLs -rfc > $CA_CERTS_PATH/inter_ca.pem + +cat $CA_CERTS_PATH/root_ca.pem >> $CA_CERTS_PATH/inter_ca.pem + +keytool -keystore $INTER_CA_KS -importcert -alias inter_ca \ +-storepass test123 -noprompt -file $CA_CERTS_PATH/inter_ca.pem + +keytool -storepass test123 -keystore $PARTNER1_CA_KS -certreq -alias partner1_ca \ +| keytool -storepass test123 -keystore $INTER_CA_KS -gencert -validity 36500 -alias inter_ca \ +-ext bc:c=ca:true,pathlen:0 -ext ku:c=dS,kCS,cRLs -rfc > $CA_CERTS_PATH/partner1_ca.pem + +keytool -storepass test123 -keystore $PARTNER2_CA_KS -certreq -alias partner2_ca \ +| keytool -storepass test123 -keystore $INTER_CA_KS -gencert -validity 36500 -alias inter_ca \ +-ext bc:c=ca:true,pathlen:0 -ext ku:c=dS,kCS,cRLs -rfc > $CA_CERTS_PATH/partner2_ca.pem + +cat $CA_CERTS_PATH/inter_ca.pem >> $CA_CERTS_PATH/partner1_ca.pem +cat $CA_CERTS_PATH/inter_ca.pem >> $CA_CERTS_PATH/partner2_ca.pem + +keytool -keystore $PARTNER1_CA_KS -importcert -alias partner1_ca \ +-storepass test123 -noprompt -file $CA_CERTS_PATH/partner1_ca.pem + +keytool -keystore $PARTNER2_CA_KS -importcert -alias partner2_ca \ +-storepass test123 -noprompt -file $CA_CERTS_PATH/partner2_ca.pem + +echo "Generating miner keystores..." +### Generate client keystores +for name in "${names[@]}" +do + IFS=':' read -r -a array <<< "$name" + partner=${array[0]} + client=${array[1]} + + PARTNER_CA_KEYSTORE="$CA_CERTS_PATH/${partner}_ca.p12" + CLIENT_PATH="./${client}" + KEYSTORE_PATH="./$CLIENT_PATH/${client}.p12" + NSSDB_PATH="${CLIENT_PATH}/nssdb" + + echo "$PARTNER_CA_KEYSTORE" + + mkdir -p $NSSDB_PATH + + echo "Generating keystore for Partner $partner Client $client" + keytool -genkeypair -keystore $KEYSTORE_PATH -storepass test123 -alias ${client} \ + -keyalg $KEY_ALG -validity 36500 \ + -dname "CN=localhost, OU=${partner}" \ + -ext san=dns:localhost,ip:127.0.0.1 + + echo "Creating CSR for $client and signing it with ${partner}_ca" + keytool -storepass test123 -keystore $KEYSTORE_PATH -certreq -alias ${client} \ + | keytool -storepass test123 -keystore $PARTNER_CA_KEYSTORE -gencert -validity 36500 -alias "${partner}_ca" -ext ku:c=digitalSignature,nonRepudiation,keyEncipherment -ext eku=sA,cA \ + -rfc > "${CLIENT_PATH}/${client}.pem" + + echo "Concat root_ca.pem to ${client}.pem" + cat "${CA_CERTS_PATH}/root_ca.pem" >> "${CLIENT_PATH}/${client}.pem" + + echo "Importing signed $client.pem CSR into $KEYSTORE_PATH" + keytool -keystore $KEYSTORE_PATH -importcert -alias $client \ + -storepass test123 -noprompt -file "${CLIENT_PATH}/${client}.pem" + + echo "Converting p12 to jks" + keytool -importkeystore -srckeystore $KEYSTORE_PATH -srcstoretype PKCS12 -destkeystore "$CLIENT_PATH/${client}.jks" -deststoretype JKS -srcstorepass test123 -deststorepass test123 -srcalias $client -destalias $client -srckeypass test123 -destkeypass test123 -noprompt + + echo "Initialize nss" + echo "test123" > ${CLIENT_PATH}/nsspin.txt + certutil -N -d sql:${NSSDB_PATH} -f "${CLIENT_PATH}/nsspin.txt" + # hack to make Java SunPKCS11 work with new sql version of nssdb + touch ${NSSDB_PATH}/secmod.db + + pk12util -i $KEYSTORE_PATH -d sql:${NSSDB_PATH} -k ${CLIENT_PATH}/nsspin.txt -W test123 + echo "Fixing truststores in sql:${NSSDB_PATH}" + certutil -M -n "CN=root.ca.besu.com" -t CT,C,C -d sql:"$NSSDB_PATH" -f ${CLIENT_PATH}/nsspin.txt + certutil -M -n "CN=inter.ca.besu.com" -t u,u,u -d sql:"$NSSDB_PATH" -f ${CLIENT_PATH}/nsspin.txt + certutil -M -n "CN=${partner}.ca.besu.com" -t u,u,u -d sql:"$NSSDB_PATH" -f ${CLIENT_PATH}/nsspin.txt + + certutil -d sql:"$NSSDB_PATH" -f nsspin.txt -L + + echo "Creating pkcs11 nss config file" + cat <${CLIENT_PATH}/nss.cfg +name = NSScrypto-${partner}-${client} +nssSecmodDirectory = ./src/test/resources/pki-certs/${client}/nssdb +nssDbMode = readOnly +nssModule = keystore +showInfo = true +EOF + + # remove pem files + rm "${CLIENT_PATH}/${client}.pem" + + # create truststore + echo "Creating truststore ..." + keytool -exportcert -keystore $ROOT_CA_KS -storepass test123 -alias root_ca -rfc | keytool -import -trustcacerts -alias root_ca -keystore "${CLIENT_PATH}/truststore.p12" -storepass test123 -noprompt +## keytool -exportcert -keystore $INTER_CA_KS -storepass test123 -alias inter_ca -rfc | keytool -import -trustcacerts -alias inter_ca -keystore "${CLIENT_PATH}/truststore.p12" -storepass test123 -noprompt +## keytool -exportcert -keystore $PARTNER_CA_KEYSTORE -storepass test123 -alias "${partner}_ca" -rfc | keytool -import -trustcacerts -alias "${partner}_ca" -keystore "${CLIENT_PATH}/truststore.p12" -storepass test123 -noprompt + +done +rm $CA_CERTS_PATH/root_ca.pem +echo "Keystores and nss database created" + +## create crl list +mkdir -p $CRL_DIR +## rm $CRL_DIR/crl.pem + +for crl in "${crls[@]}" +do + IFS=':' read -r -a array <<< "$crl" + partner=${array[0]} + client=${array[1]} + + echo "Exporting CA certificate and private key" + openssl pkcs12 -nodes -in "$CA_CERTS_PATH/${partner}_ca.p12" -out "$CRL_DIR/${partner}_ca_key.pem" -passin pass:test123 -nocerts + openssl pkcs12 -nodes -in "$CA_CERTS_PATH/${partner}_ca.p12" -out "$CRL_DIR/${partner}_ca.pem" -passin pass:test123 -nokeys + + echo "Export $client certificate" + openssl pkcs12 -nodes -in "./${client}/${client}.p12" -out "$CRL_DIR/${client}.pem" -passin pass:test123 -nokeys + + ## On Mac, use gnutls-certtool, on Linux use certtool + echo "Creating crl" + printf '365\n\n' | gnutls-certtool --generate-crl --load-ca-privkey "$CRL_DIR/${partner}_ca_key.pem" --load-ca-certificate "$CRL_DIR/${partner}_ca.pem" \ + --load-certificate "$CRL_DIR/${client}.pem" >> $CRL_DIR/crl.pem + + rm "$CRL_DIR/${partner}_ca_key.pem" + rm "$CRL_DIR/${partner}_ca.pem" + rm "$CRL_DIR/${client}.pem" +done diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/crl/crl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/crl/crl.pem new file mode 100644 index 00000000000..763d01c19d4 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/crl/crl.pem @@ -0,0 +1,28 @@ +-----BEGIN X509 CRL----- +MIICGzCCAQMCAQEwDQYJKoZIhvcNAQELBQAwHzEdMBsGA1UEAxMUcGFydG5lcjEu +Y2EuYmVzdS5jb20XDTIzMDUwNDEwMTUzNVoXDTI0MDUwMzEwMTUzNVowbTAZAghF +KUAnwQI0rxcNMjMwNTA0MTAxNTM1WjAZAggBqEW2S0yD7hcNMjMwNTA0MTAxNTM1 +WjAZAghxoeavxdMy8xcNMjMwNTA0MTAxNTM1WjAaAgkAgWKzx/tKZWkXDTIzMDUw +NDEwMTUzNVqgQTA/MB8GA1UdIwQYMBaAFJcP76nbNK50KG5jmh6CvsxlAhJjMBwG +A1UdFAQVAhNkU4XHFwNbgBqsTIFexJjuzEvyMA0GCSqGSIb3DQEBCwUAA4IBAQB2 +fhAhVwRBtHdwqhGjRlgbz4i6E0CtoL/02Vazib1OiRAXCkyFJL04U3FGcrPa89Dt +ClZE0G38+Jw0Be0tEpn9A8doSbLr73w1GqW3BqNTw/qjbc6R2x28A1VIVPwV6bZH +5P59YtDV+SjSPNxqkwRMyXqGZ2WIMwUS3u47Es9vMsjChXUJWU6W+jf3LYO/dt+V +7xSchRpljhBtMB8MIoXILBq9uOSFalLmy94YzK2Rw1ZG2SVy2QZ6ZXHvZ/omLbPL +kd4oAiN7L0OLOkFVHyb9bVP6DUWfXxSxBdszbQzHCy74NEsFUC0xqq0xpxwQRRfD +codJtbEVJraSsSBkB78n +-----END X509 CRL----- +-----BEGIN X509 CRL----- +MIICGzCCAQMCAQEwDQYJKoZIhvcNAQELBQAwHzEdMBsGA1UEAxMUcGFydG5lcjIu +Y2EuYmVzdS5jb20XDTIzMDUwNDEwMTUzNVoXDTI0MDUwMzEwMTUzNVowbTAZAggF +p9b0zZl1RxcNMjMwNTA0MTAxNTM1WjAZAgh7MQ7e4x/GbRcNMjMwNTA0MTAxNTM1 +WjAZAghxoeavxdMy8xcNMjMwNTA0MTAxNTM1WjAaAgkAgWKzx/tKZWkXDTIzMDUw +NDEwMTUzNVqgQTA/MB8GA1UdIwQYMBaAFJuQMv8IsgbJS8FfPZZx+hSgj7PBMBwG +A1UdFAQVAhNkU4XHGmnm4OkmS4KBFW1nS4csMA0GCSqGSIb3DQEBCwUAA4IBAQB2 +43mCjuMmB+MXpl+Axn3b/4V2f0HmbUFhF/andWKUwzC47HoQ+WzXoTV0xisHGCgH +SYlrLdWd+pFh24H7TrKgqvmwtVmUFwm6DphXW3AHvaePWIrAy7L5ZrdOQB9TZPC1 +Ly+6x0oKoueiHodWivLQx+CJVbPAzxFEVh0JjecoFw8Tf9FGTqy8jJRdno9HgKDg +BB7w7kPGF7xoaAbukwTXFz7f1nep44oqge+leEc398tdFDxmwralXAUB0A2v/vDG +cSZTr+fyTri+zHjQzeq6//y2GF7S56KSyBXDXTJrvqtuijiVHTzQku+pbVNNrid5 +LgCJI7Phj2Q8k26z0+JJ +-----END X509 CRL----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner1/miner1.jks b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/miner1.jks new file mode 100644 index 00000000000..df9dfad4b5d Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/miner1.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner1/miner1.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/miner1.p12 new file mode 100644 index 00000000000..baba59128aa Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/miner1.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nss.cfg new file mode 100644 index 00000000000..d76bd9c163c --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nss.cfg @@ -0,0 +1,5 @@ +name = NSScrypto-partner1-miner1 +nssSecmodDirectory = ./src/test/resources/pki-certs/miner1/nssdb +nssDbMode = readOnly +nssModule = keystore +showInfo = true diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nssdb/cert9.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nssdb/cert9.db new file mode 100644 index 00000000000..33e83d02b71 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nssdb/cert9.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nssdb/key4.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nssdb/key4.db new file mode 100644 index 00000000000..03a4a5e5b86 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nssdb/key4.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nssdb/pkcs11.txt b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nssdb/pkcs11.txt new file mode 100644 index 00000000000..fe947a8221a --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nssdb/pkcs11.txt @@ -0,0 +1,5 @@ +library= +name=NSS Internal PKCS #11 Module +parameters=configdir='sql:./miner1/nssdb' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' +NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[ECC,RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30}) + diff --git a/ISSUE_TEMPLATE.md b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nssdb/secmod.db similarity index 100% rename from ISSUE_TEMPLATE.md rename to acceptance-tests/tests/src/test/resources/pki-certs/miner1/nssdb/secmod.db diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner1/truststore.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/truststore.p12 new file mode 100644 index 00000000000..ddbd8ee57be Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner1/truststore.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner2/miner2.jks b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/miner2.jks new file mode 100644 index 00000000000..2abd88e9d80 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/miner2.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner2/miner2.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/miner2.p12 new file mode 100644 index 00000000000..aeec006f0e9 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/miner2.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nss.cfg new file mode 100644 index 00000000000..995d452fc4c --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nss.cfg @@ -0,0 +1,5 @@ +name = NSScrypto-partner1-miner2 +nssSecmodDirectory = ./src/test/resources/pki-certs/miner2/nssdb +nssDbMode = readOnly +nssModule = keystore +showInfo = true diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nssdb/cert9.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nssdb/cert9.db new file mode 100644 index 00000000000..21d6ea18410 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nssdb/cert9.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nssdb/key4.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nssdb/key4.db new file mode 100644 index 00000000000..3d77b19abb4 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nssdb/key4.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nssdb/pkcs11.txt b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nssdb/pkcs11.txt new file mode 100644 index 00000000000..90b09f83b25 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nssdb/pkcs11.txt @@ -0,0 +1,5 @@ +library= +name=NSS Internal PKCS #11 Module +parameters=configdir='sql:./miner2/nssdb' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' +NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[ECC,RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30}) + diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/blockchain/.keep b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nssdb/secmod.db similarity index 100% rename from ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/blockchain/.keep rename to acceptance-tests/tests/src/test/resources/pki-certs/miner2/nssdb/secmod.db diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner2/truststore.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/truststore.p12 new file mode 100644 index 00000000000..8d9754074b7 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner2/truststore.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner3/miner3.jks b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/miner3.jks new file mode 100644 index 00000000000..79ee2cb0ecc Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/miner3.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner3/miner3.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/miner3.p12 new file mode 100644 index 00000000000..c7e42d1af69 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/miner3.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nss.cfg new file mode 100644 index 00000000000..65e04bccbfd --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nss.cfg @@ -0,0 +1,5 @@ +name = NSScrypto-partner1-miner3 +nssSecmodDirectory = ./src/test/resources/pki-certs/miner3/nssdb +nssDbMode = readOnly +nssModule = keystore +showInfo = true diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nssdb/cert9.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nssdb/cert9.db new file mode 100644 index 00000000000..5b295bcda9a Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nssdb/cert9.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nssdb/key4.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nssdb/key4.db new file mode 100644 index 00000000000..d05913b651a Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nssdb/key4.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nssdb/pkcs11.txt b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nssdb/pkcs11.txt new file mode 100644 index 00000000000..c4368a178ff --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nssdb/pkcs11.txt @@ -0,0 +1,5 @@ +library= +name=NSS Internal PKCS #11 Module +parameters=configdir='sql:./miner3/nssdb' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' +NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[ECC,RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30}) + diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/generalstate/.keep b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nssdb/secmod.db similarity index 100% rename from ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/generalstate/.keep rename to acceptance-tests/tests/src/test/resources/pki-certs/miner3/nssdb/secmod.db diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner3/truststore.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/truststore.p12 new file mode 100644 index 00000000000..028424cebdf Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner3/truststore.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner4/miner4.jks b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/miner4.jks new file mode 100644 index 00000000000..6cde7b1a0ba Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/miner4.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner4/miner4.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/miner4.p12 new file mode 100644 index 00000000000..386fe0d4b0b Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/miner4.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nss.cfg new file mode 100644 index 00000000000..29082f64b54 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nss.cfg @@ -0,0 +1,5 @@ +name = NSScrypto-partner1-miner4 +nssSecmodDirectory = ./src/test/resources/pki-certs/miner4/nssdb +nssDbMode = readOnly +nssModule = keystore +showInfo = true diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nssdb/cert9.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nssdb/cert9.db new file mode 100644 index 00000000000..fd5b048d8c9 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nssdb/cert9.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nssdb/key4.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nssdb/key4.db new file mode 100644 index 00000000000..127bbd567e9 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nssdb/key4.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nssdb/pkcs11.txt b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nssdb/pkcs11.txt new file mode 100644 index 00000000000..730c97feb8e --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nssdb/pkcs11.txt @@ -0,0 +1,5 @@ +library= +name=NSS Internal PKCS #11 Module +parameters=configdir='sql:./miner4/nssdb' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' +NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[ECC,RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30}) + diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nssdb/secmod.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nssdb/secmod.db new file mode 100644 index 00000000000..e69de29bb2d diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner4/truststore.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/truststore.p12 new file mode 100644 index 00000000000..c6c7b5decff Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner4/truststore.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner5/miner5.jks b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/miner5.jks new file mode 100644 index 00000000000..a9dc3190a97 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/miner5.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner5/miner5.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/miner5.p12 new file mode 100644 index 00000000000..7049be61bd0 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/miner5.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nss.cfg new file mode 100644 index 00000000000..063e31a2a35 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nss.cfg @@ -0,0 +1,5 @@ +name = NSScrypto-partner1-miner5 +nssSecmodDirectory = ./src/test/resources/pki-certs/miner5/nssdb +nssDbMode = readOnly +nssModule = keystore +showInfo = true diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nssdb/cert9.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nssdb/cert9.db new file mode 100644 index 00000000000..f731ba7404c Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nssdb/cert9.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nssdb/key4.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nssdb/key4.db new file mode 100644 index 00000000000..e366aa9e272 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nssdb/key4.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nssdb/pkcs11.txt b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nssdb/pkcs11.txt new file mode 100644 index 00000000000..bd574fbdc7f --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nssdb/pkcs11.txt @@ -0,0 +1,5 @@ +library= +name=NSS Internal PKCS #11 Module +parameters=configdir='sql:./miner5/nssdb' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' +NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[ECC,RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30}) + diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nssdb/secmod.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nssdb/secmod.db new file mode 100644 index 00000000000..e69de29bb2d diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner5/truststore.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/truststore.p12 new file mode 100644 index 00000000000..7d54dfe7f6d Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner5/truststore.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner6/miner6.jks b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/miner6.jks new file mode 100644 index 00000000000..b73d203e889 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/miner6.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner6/miner6.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/miner6.p12 new file mode 100644 index 00000000000..8df1575b0e3 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/miner6.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nss.cfg new file mode 100644 index 00000000000..60a2e65bc46 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nss.cfg @@ -0,0 +1,5 @@ +name = NSScrypto-partner2-miner6 +nssSecmodDirectory = ./src/test/resources/pki-certs/miner6/nssdb +nssDbMode = readOnly +nssModule = keystore +showInfo = true diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nssdb/cert9.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nssdb/cert9.db new file mode 100644 index 00000000000..8bc1ba42f15 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nssdb/cert9.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nssdb/key4.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nssdb/key4.db new file mode 100644 index 00000000000..aa078f69b7d Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nssdb/key4.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nssdb/pkcs11.txt b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nssdb/pkcs11.txt new file mode 100644 index 00000000000..a47ca829b24 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nssdb/pkcs11.txt @@ -0,0 +1,5 @@ +library= +name=NSS Internal PKCS #11 Module +parameters=configdir='sql:./miner6/nssdb' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' +NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[ECC,RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30}) + diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nssdb/secmod.db b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nssdb/secmod.db new file mode 100644 index 00000000000..e69de29bb2d diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/miner6/truststore.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/truststore.p12 new file mode 100644 index 00000000000..bb56eecd08a Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/miner6/truststore.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node1/crl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/node1/crl.pem new file mode 100644 index 00000000000..8ced006c911 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/node1/crl.pem @@ -0,0 +1,27 @@ +-----BEGIN X509 CRL----- +MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCVVMxCzAJBgNV +BAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJBgNVBAoMAk1DMQ0wCwYDVQQLDARyb290 +MRMwEQYDVQQDDApwYXJ0bmVyYWNhMSYwJAYJKoZIhvcNAQkBFhdwYXJ0bmVyYWNh +QHBhcnRuZXJhLmNvbRcNMjEwNzA5MTkxMjM1WhcNMjIwNzA5MTkxMjM1WjAnMCUC +FF9rJlU9U6JdFIeK/xRojaoxHdc5Fw0yMTA3MDkxOTEyMzVaoA4wDDAKBgNVHRQE +AwIBADANBgkqhkiG9w0BAQsFAAOCAQEAfByR//FGHSsVQbaS51d59o82XocOGnnT +p1hjceqtLGv3bhiebVrsRCOB5TsvE/r2IbB/yHYTe3+LJisIUqBxblQ6xK6IM+qA +3fY646YnPT5pvdZAPZ2BCN/xP3xqGffFKapQ9cz0/36YE3vaEoUDlC2VHK0OXI0t +4CLwAmiptUT2GW4Bk1RtokAsFiUNwNIOlRX5bywUNwkG7EuitR90QSGH3l/vyii2 +0c1Fm9He9MskwipjXpJKKb+t+m1pdpOVkSjRfjmVqi4BZwWlnQjELSLywhJ+WZG2 +Z1NgRjzPXotFKK+YD97Kx1L260A1eUZ46zSq73oUZr0EDZRnNJTr6A== +-----END X509 CRL----- +-----BEGIN X509 CRL----- +MIICLDCCARQCAQEwDQYJKoZIhvcNAQELBQAwgYExCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9v +dDETMBEGA1UEAwwKcGFydG5lcmJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmJj +YUBwYXJ0bmVyYi5jb20XDTIxMDcwOTE5MTIzNVoXDTIyMDcwOTE5MTIzNVowTjAl +AhQTZhDgbKuvX7iLRUBBTiWXBPKM1xcNMjEwNzA5MTkxMjM1WjAlAhRfayZVPVOi +XRSHiv8UaI2qMR3XORcNMjEwNzA5MTkxMjM1WqAOMAwwCgYDVR0UBAMCAQEwDQYJ +KoZIhvcNAQELBQADggEBAMIltmJ036f1BmK/baISJTZTu7PKZgSZMNORnpFT8KvC +s2GNRor5bGp5qvD6LHvsx92YVppCC6xd/beCFBtdyYifqw5xtOvqLQKuqCfxruLz +EqYjKXE/3v8VdyU71J7kFqi0U0Gy4/h/YCL92e5KNbATlmcn5ToyI2EBIEfBfV08 +mm7FBXvbHRzqhfrnCNEjBWBWz3zkJMc9Rib26eCCofYIDkY2HvYSN78YgrnMmD6O +hWOXrPoxArxvmDr5rG4vCadqbQYRkkCAOP0hBeMiB0SAcO2W2LNNAmHWXX7FvU3n +ZRZUX31WoVjhNeEQtNBb2mPYBXHQzLC66qYm1p97afc= +-----END X509 CRL----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node1/keys.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/node1/keys.p12 new file mode 100644 index 00000000000..1aeb2fec791 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/node1/keys.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node1/keystore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/node1/keystore.jks new file mode 100644 index 00000000000..3b1db9eb88b Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/node1/keystore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node1/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/node1/nss.cfg new file mode 100644 index 00000000000..320163767f8 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/node1/nss.cfg @@ -0,0 +1,6 @@ + +name = NSScrypto-node1 +nssSecmodDirectory = ./src/test/resources/pki-certs/node1/nssdb +nssDbMode = readOnly +nssModule = keystore + diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node1/nssdb/cert8.db b/acceptance-tests/tests/src/test/resources/pki-certs/node1/nssdb/cert8.db new file mode 100644 index 00000000000..a6e5cc1c572 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/node1/nssdb/cert8.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node1/nssdb/key3.db b/acceptance-tests/tests/src/test/resources/pki-certs/node1/nssdb/key3.db new file mode 100644 index 00000000000..0b103995be1 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/node1/nssdb/key3.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node1/nssdb/secmod.db b/acceptance-tests/tests/src/test/resources/pki-certs/node1/nssdb/secmod.db new file mode 100644 index 00000000000..08102e23979 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/node1/nssdb/secmod.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node1/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/node1/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/node1/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node1/ssl-ca.pem b/acceptance-tests/tests/src/test/resources/pki-certs/node1/ssl-ca.pem new file mode 100644 index 00000000000..61a8f5230ed --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/node1/ssl-ca.pem @@ -0,0 +1,70 @@ +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBEwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTExNTRaGA8y +MTIxMDYxNTE5MTE1NFowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmFjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDccGhUDD8T8m6e2x13 +B0LgCDR8F2vlfAw9FN/tXOKKU3DpagJk0CAutL6YFFYs9MXg8D6bZx+w0iXUnaN/ +6rjIC1LFs79AizpEaoFWDzcVI66ItSW1Swu3ts0I1kK7EGgAMba0TDTnssfrtuPw +rOA2TOdVX03owOE+gaaPonIQlnew5+NNGhbW+P/5ix1IQXhyuNjV/uu3VEJBGNTh +cAuMGdjvglFuz4zyFon4kNRcQvghs5ztjs2h5ZNHjEo6YtNIdJuRS/XOXII9MfPN +plcwJArWTM3yEATNBtdc5FypOSI6cO/Pl+SVEf4kKmnzJQZWOSGiDXbpm938hGVw +ByZPAgMBAAGjZjBkMB0GA1UdDgQWBBQhpkZg+Ktqh6sFCjtm9HE+9bLJ3TAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAIggdc0DCxEiNaKak +/xbc7uGiGBb+UzBTjk4BmX9kEFrZf4XEaHzsptltqcQDCVtzcbFFFxMYhv/w/1g/ +WMNuUhL0mmGIGMxfoqkg50tNyuHW6aSrBXErel9WthGXAhUSzdHgkWxl3pe2wgda +qIcSwTCFgOeVWTZRdKWqKNPHirBglJHUpMgLo0qa0Ug1hxiyOQRt2yXLpe/mH3pG +cozhrEDYQMOcDhYTpPwM2Bl+TsRPpxFaV4QDfiOyvUDFLMM0dyhl2pukjay/Xpp2 ++6Tsnaa+Ui0sDcM3A36Q07+E4Vugxjzfb9a36Eg4XE+Jg3jDA8UOqjeFg9gkK3aY +NaI0qQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node1/ssl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/node1/ssl.pem new file mode 100644 index 00000000000..291b730311c --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/node1/ssl.pem @@ -0,0 +1,126 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCw8JqVhfSxCPC+ +8UKvPAGHyZOzqrXd3SyrdYQnUKP2NkAhbXpJMNnIyk41+dVJxzjNJ9RiSr3D8hJH +3NOMLtj93UROtp7Az1PdnpPRjeHsT7kt9+79J3I4r6eEU7uhfig2UNPJBaKxqoht +MyBoGJgIYl3O8SD6grFV40cFfCFOWFgKi+Q+U7I0uMl/y+eXw1/g8DBwGPxhhw9Z +est7Ov3Qnk4x2np8Ejh6hl+dAqubojjLFdWrs2goQXrkE+qLEM2jze49L6gL5FwJ +brMkyewsaF6xVKfptMw9EK92NFzQuCUF8SXq548FzYHkiVVNweheBD7+4iCOpi0b +eiC4N6RXAgMBAAECggEABx01aeuf4fpVC6hRoRANk7MUIDYt58S7xg0MijQg04Zs +36syLn0rVHpl2J+55qR+8Si3zlfo91blS0RisRE1IkfiNjP7gA8V9SQqF1PYEJNI +A8QjNMSAQC031Ac11RFodn6bdUqntvL/VzymAelzO2sREH/7bncQwD5KHbtW73pm +un5CvnP6dHQTHX+AVDuH6yOdukuyNM+2Xn8J+PAIRsPn9yENgmvzWIW8UOvKj2Ox +4ckkT7zkihwyf8BnztNizdxSlR+ebsvP76C2gAULXoYjJlI7XxvQ1/qhma0yXhGx +I/fBBmK5rz84DabblgS0mOc2ul/nlhJI5kQSHr/PQQKBgQDVLnoJUOCa/R+s9zOn +WcUu38C8JYsj1J1PqHEOkoTim8gD3JxxCEuHLLFMSxMp4umGa3oYxut6HmgdQaym +mYPCKr0oWYDhZ8M0zwKFGTGjhGv/gkRQKdYk7IV5ASKEijRHwxfMBL9Qbc0+G0xO +/CQgJ4GsQ8neGfrDavzfsnt79wKBgQDUeqApjX0bQXTRYMyJU926N7vasyW+2kFd +KE2aUxgdEm1LG1ZDaCuPi7YZYH+J9krKISLehUJRCa4rmu6L0JjWHJAZNDQdKi2E +jNfQUWU9hoQHs3J/c8e63MmgUy7K16gt7oelRtlyL2A5NXnqvTv8U0kw7+KJkxda +et0Cke9CoQKBgBo6SJtizu9imwYNt9YsDj1xG+ZJ/C9hViVZxOcVEbJLljUbbEff +zGMKFZocVnQ9zZtTF8d6mbgBi6+lx9cLZhF6bqFLObcBrBuQKHA1pEzI2vypizwN +maIbU2SKxjNmSX5Wu1PHdb4wdCLi+uVw0gT+t055XJmtupNWU1w2OkkLAoGATdFD +SzSYdxz37Z7oCft/Hy4+TJCD6GwCuF2EXlrEYBFZmcI/S5yhJ4dhf9XJn/tl1LVi +EeD4Mrm64hlx+B7DetcnJzPpSi0iUoNKnu7Qh0H2pONhsa/znEo0RdVxM7Tb0Uak +wzE5fgo/0XP2XLRFfdn62kNg0kXerbKFsuVDnUECgYARX+jedlHmj1aY6ldhoRGf +5/RAfYAH2f0NbS4oAiRvchjydN9EjCVp8KoF7m9ToaLqPFgHP8zIjYsk7B49jXZr +DjtyMERpjMsBoRbjSKyD1glm1UQeoavgiorPz0w9QDYBstlhH/d0ejfEBCpGk5/2 +YxMs98KdYA62DUkmuaiySQ== +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIEszCCA5ugAwIBAgIUX2smVT1Tol0Uh4r/FGiNqjEd1zgwDQYJKoZIhvcNAQEL +BQAwgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw +CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwKcGFydG5lcmFjYTEm +MCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5jb20wIBcNMjEwNzA5 +MTkxMjA4WhgPMjEyMTA2MTUxOTEyMDhaMHcxCzAJBgNVBAYTAlVTMQswCQYDVQQI +DAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEO +MAwGA1UEAwwFbm9kZTExITAfBgkqhkiG9w0BCQEWEm5vZGUxQHBhcnRuZXJhLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALDwmpWF9LEI8L7xQq88 +AYfJk7Oqtd3dLKt1hCdQo/Y2QCFtekkw2cjKTjX51UnHOM0n1GJKvcPyEkfc04wu +2P3dRE62nsDPU92ek9GN4exPuS337v0ncjivp4RTu6F+KDZQ08kForGqiG0zIGgY +mAhiXc7xIPqCsVXjRwV8IU5YWAqL5D5TsjS4yX/L55fDX+DwMHAY/GGHD1l6y3s6 +/dCeTjHaenwSOHqGX50Cq5uiOMsV1auzaChBeuQT6osQzaPN7j0vqAvkXAlusyTJ +7CxoXrFUp+m0zD0Qr3Y0XNC4JQXxJernjwXNgeSJVU3B6F4EPv7iII6mLRt6ILg3 +pFcCAwEAAaOCASgwggEkMBEGCWCGSAGG+EIBAQQEAwIGwDAdBgNVHQ4EFgQUAWkS +lH1KF5emjGJvHhaERb3a7DIwCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCBeAwHQYD +VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMIG1BgNVHSMEga0wgaqAFCGmRmD4 +q2qHqwUKO2b0cT71ssndoXykejB4MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0Ex +DDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNVBAsMBHJvb3QxEDAOBgNV +BAMMB2ludGVyY2ExIDAeBgkqhkiG9w0BCQEWEWludGVyY2FAYWRtaW4uY29tghRw +BMj83j0mxnIC7JLyB9boGml0ETANBgkqhkiG9w0BAQsFAAOCAQEAWq/10HjhRI3A +OOs2JTrG5Xpzz7E8rpH45XQE0ecB1I9Zcm5bnHx+WdIo5GtxvFzGF3EtlAaxDlcM +iE1u1bfrwEF6qr0nQc8q+wHfnNdb1lqqFlXrhoerLBVrChwqkGbxILUQ+mPFhSQd +a2791g8SS/jLM3lnf9bFp7AdzJCqg7Ly0BEkIpfVsuZn0HgfYf7JG68B05RdU7/v +Hw5wGTbEmukODWZtAYRFBnKT4pq5G30heNjATjkmaWeoImJNSPgyoPzYJsYJMUNC +GYj3Ap0ueY6LbsNXst61jUGeBtCcWDa3uRg8Hl7j1dz4USPTJwBEEuSSN3CzjJuI +VGvgw1MPpQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBEwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTExNTRaGA8y +MTIxMDYxNTE5MTE1NFowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmFjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDccGhUDD8T8m6e2x13 +B0LgCDR8F2vlfAw9FN/tXOKKU3DpagJk0CAutL6YFFYs9MXg8D6bZx+w0iXUnaN/ +6rjIC1LFs79AizpEaoFWDzcVI66ItSW1Swu3ts0I1kK7EGgAMba0TDTnssfrtuPw +rOA2TOdVX03owOE+gaaPonIQlnew5+NNGhbW+P/5ix1IQXhyuNjV/uu3VEJBGNTh +cAuMGdjvglFuz4zyFon4kNRcQvghs5ztjs2h5ZNHjEo6YtNIdJuRS/XOXII9MfPN +plcwJArWTM3yEATNBtdc5FypOSI6cO/Pl+SVEf4kKmnzJQZWOSGiDXbpm938hGVw +ByZPAgMBAAGjZjBkMB0GA1UdDgQWBBQhpkZg+Ktqh6sFCjtm9HE+9bLJ3TAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAIggdc0DCxEiNaKak +/xbc7uGiGBb+UzBTjk4BmX9kEFrZf4XEaHzsptltqcQDCVtzcbFFFxMYhv/w/1g/ +WMNuUhL0mmGIGMxfoqkg50tNyuHW6aSrBXErel9WthGXAhUSzdHgkWxl3pe2wgda +qIcSwTCFgOeVWTZRdKWqKNPHirBglJHUpMgLo0qa0Ug1hxiyOQRt2yXLpe/mH3pG +cozhrEDYQMOcDhYTpPwM2Bl+TsRPpxFaV4QDfiOyvUDFLMM0dyhl2pukjay/Xpp2 ++6Tsnaa+Ui0sDcM3A36Q07+E4Vugxjzfb9a36Eg4XE+Jg3jDA8UOqjeFg9gkK3aY +NaI0qQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node1/truststore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/node1/truststore.jks new file mode 100644 index 00000000000..d707235c76a Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/node1/truststore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node2/crl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/node2/crl.pem new file mode 100644 index 00000000000..8ced006c911 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/node2/crl.pem @@ -0,0 +1,27 @@ +-----BEGIN X509 CRL----- +MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCVVMxCzAJBgNV +BAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJBgNVBAoMAk1DMQ0wCwYDVQQLDARyb290 +MRMwEQYDVQQDDApwYXJ0bmVyYWNhMSYwJAYJKoZIhvcNAQkBFhdwYXJ0bmVyYWNh +QHBhcnRuZXJhLmNvbRcNMjEwNzA5MTkxMjM1WhcNMjIwNzA5MTkxMjM1WjAnMCUC +FF9rJlU9U6JdFIeK/xRojaoxHdc5Fw0yMTA3MDkxOTEyMzVaoA4wDDAKBgNVHRQE +AwIBADANBgkqhkiG9w0BAQsFAAOCAQEAfByR//FGHSsVQbaS51d59o82XocOGnnT +p1hjceqtLGv3bhiebVrsRCOB5TsvE/r2IbB/yHYTe3+LJisIUqBxblQ6xK6IM+qA +3fY646YnPT5pvdZAPZ2BCN/xP3xqGffFKapQ9cz0/36YE3vaEoUDlC2VHK0OXI0t +4CLwAmiptUT2GW4Bk1RtokAsFiUNwNIOlRX5bywUNwkG7EuitR90QSGH3l/vyii2 +0c1Fm9He9MskwipjXpJKKb+t+m1pdpOVkSjRfjmVqi4BZwWlnQjELSLywhJ+WZG2 +Z1NgRjzPXotFKK+YD97Kx1L260A1eUZ46zSq73oUZr0EDZRnNJTr6A== +-----END X509 CRL----- +-----BEGIN X509 CRL----- +MIICLDCCARQCAQEwDQYJKoZIhvcNAQELBQAwgYExCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9v +dDETMBEGA1UEAwwKcGFydG5lcmJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmJj +YUBwYXJ0bmVyYi5jb20XDTIxMDcwOTE5MTIzNVoXDTIyMDcwOTE5MTIzNVowTjAl +AhQTZhDgbKuvX7iLRUBBTiWXBPKM1xcNMjEwNzA5MTkxMjM1WjAlAhRfayZVPVOi +XRSHiv8UaI2qMR3XORcNMjEwNzA5MTkxMjM1WqAOMAwwCgYDVR0UBAMCAQEwDQYJ +KoZIhvcNAQELBQADggEBAMIltmJ036f1BmK/baISJTZTu7PKZgSZMNORnpFT8KvC +s2GNRor5bGp5qvD6LHvsx92YVppCC6xd/beCFBtdyYifqw5xtOvqLQKuqCfxruLz +EqYjKXE/3v8VdyU71J7kFqi0U0Gy4/h/YCL92e5KNbATlmcn5ToyI2EBIEfBfV08 +mm7FBXvbHRzqhfrnCNEjBWBWz3zkJMc9Rib26eCCofYIDkY2HvYSN78YgrnMmD6O +hWOXrPoxArxvmDr5rG4vCadqbQYRkkCAOP0hBeMiB0SAcO2W2LNNAmHWXX7FvU3n +ZRZUX31WoVjhNeEQtNBb2mPYBXHQzLC66qYm1p97afc= +-----END X509 CRL----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node2/keys.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/node2/keys.p12 new file mode 100644 index 00000000000..5b3aa85caa4 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/node2/keys.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node2/keystore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/node2/keystore.jks new file mode 100644 index 00000000000..90b5e93ec75 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/node2/keystore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node2/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/node2/nss.cfg new file mode 100644 index 00000000000..a0db3bdc995 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/node2/nss.cfg @@ -0,0 +1,6 @@ + +name = NSScrypto-node2 +nssSecmodDirectory = ./src/test/resources/pki-certs/node2/nssdb +nssDbMode = readOnly +nssModule = keystore + diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node2/nssdb/cert8.db b/acceptance-tests/tests/src/test/resources/pki-certs/node2/nssdb/cert8.db new file mode 100644 index 00000000000..10555edf0d7 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/node2/nssdb/cert8.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node2/nssdb/key3.db b/acceptance-tests/tests/src/test/resources/pki-certs/node2/nssdb/key3.db new file mode 100644 index 00000000000..137e24bdb49 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/node2/nssdb/key3.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node2/nssdb/secmod.db b/acceptance-tests/tests/src/test/resources/pki-certs/node2/nssdb/secmod.db new file mode 100644 index 00000000000..ebbf2f03064 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/node2/nssdb/secmod.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node2/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/node2/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/node2/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node2/ssl-ca.pem b/acceptance-tests/tests/src/test/resources/pki-certs/node2/ssl-ca.pem new file mode 100644 index 00000000000..c0c4bf478f6 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/node2/ssl-ca.pem @@ -0,0 +1,70 @@ +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBIwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTEyMTFaGA8y +MTIxMDYxNTE5MTIxMVowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmJjYUBwYXJ0bmVyYi5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNTP8IviC0X2ozlU2+ +9+mPLL9NqJKRCsEiH7XypcXkqkzCYZv/+6nNWXGLr6HsF5qXaM/YVMJYtwiaJquw +qW1CpOKxhHA1gubNt0Fzmt69/5yP6D1zxTPzAcybNMuCy8VcLJpovYHO40+2HD6I +D91/zh3jtrgKPoEXgaW3eX4+hykQWaru3P/G4PrIvPyZXnccoCdBSRCqyZSBJUko +e5ZLnCQMlkwgDONGT3MqQyUC5lqFFMzZ75pOm2reiBe6HzP3H4wK7Ldpxds9ubGk +Acb08+QzcUT7uHvENyvLm5mbf68QurFTwIDEVg2K03dgqQWbJudSzRJAmJYSszFQ +vLZdAgMBAAGjZjBkMB0GA1UdDgQWBBR5aiJ1nA1HHi0XzbRsp4V7T8eKBjAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAsmFsG3SV1fQg6kO+ +dYvFrDKNOJzTBdVYmFhg4y4H7Qt+dwQcs/ZcOCIaAFUfMUH6CWe1AAdCymfwUHxn +l/FMeJHh/+d1cybC+Wj9wtBbz7nPsWh/PXbbg3Zi8N4+a6Y0NhZAGlNn1UgMHx+E +SkSIXk63FkGT01xM2aYtfr9ABuDdoLK/YPecduiawZoRb02WwIpZFNeEE/MS7XG6 +fX9TdUrNOal8pnWUM79K+rzdlzstpCx7uFFbACUEiiIuYiqG6X+DuypfGmQnjRXB +zbc6NsQONUxg7fnJObdpV7kKTlbpREFoECkTBdqKd7AuJwYRvGaQDWK9P1IYFr1W +Cnm4Cg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node2/ssl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/node2/ssl.pem new file mode 100644 index 00000000000..42244eb2420 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/node2/ssl.pem @@ -0,0 +1,126 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDOGeuw5pq4E18A +cZOYdLSEbyuSQMmWKtp15Blpb1buD4VEt+6xxBwQvq6BC8A24AWRFGPDM6GFkThr +9vnU64wg6xAjCQZEQYqAncO7FXKLJWagaKYE03rRTKGnNQZsH1uLEywIdEirV8j3 +31zOMgQkk8JS+Kv2tsodOZzbYTIaxvRpeTqLzzv+/eg8RQoNNr9XsqIfYrVDhvBc +tfSpnsxVuR/GAxKiqN001DFa+Yjn0sTrEjlyTbniTW8I5V5dnUOfU8awWdjXFFBL +YaDWHnOOQARlZLyg2AFdSNX6NuYhcUuNBECHFdQtBKkXNZEB6Bqx+ZHNG6AZjwYk +6JY+0kxdAgMBAAECggEAR5qn0Qj9PfC08+GBxtjdEpnRCHnrz3lJ9uVtkrz09bZ8 +tZg1nJsmqQamd/0OJcKFDJeJ5XqdplsCwDfJKpk/UPx52cI75CDlLrQhGXFlH0S6 +OAbDjy+uHuNB0mbQuWXXlyTtCm7kBGt2Te/TPWwRFmgjflIY5Jky9R5cCbfmAXj3 +5ieNPzfXtRiT7qAvLcofC+isVX7OPY6c0iMvJm1cHJ+hDwh56uPVdb5+Sa5+BFEd +cCQ8uTBPkGc1e+nUYtu7b8WnUvzCXOSHTZ+ej93/3WefMBaiTigNdmPZyzkAgO+3 +bX18hv1YBPf6XnDj3kB8MZTVpPGqTJaD96mCSDCQQQKBgQD1Ds0/sy0fJ8XZ2nwn +wJeqM6rctRbmutOA52z6xrRoqOl4ZgYEZ/MngAT0DyfenhaBu2ShD1wvlKE+TEJP +sSwiWwMoNzxqMvIFdjj4NECBNREL5oV3vokz2XGOquyk9OXaOWP7iiZIswHoHhVp +bqwC7Ga9iqVwt8Kj3l7RIf3aMQKBgQDXTdDJPj0MBXWuQp3nH3y5h49I3AKGiefW +H8G834DMA3pU3//VT7Q14qNSkQ7dvWISLG6zkXIWnMtv2w7VMJhSK3dRTYBEw3hs +67mg5DJMHz2xXLShPUM3Fcx12z0JFOLd72da/GXB5BSjYDxLEZ4KO+jZeqFHNC+o +D6GpqOPd7QKBgAiT6g9OwEeU5tIHWc0yapykjliHZjPRWlHqx9/HUM1RDEsQlylU +UiiRzJqWZTjfo74Kxyz0Eq//rd02YiPT+c2CDgw8UrsM6XfTeY8GlTNwnhYijY1x +d+/+roDl7r6fa+RFmgBWB50H1ws+8lTscMzxZW9BCSV26TM/N2ZuoCohAoGAF7Z4 +UlHKg3JufZzUq0nqgLyPaWTh2lOB9zFUMysiklWnuYVaNfIrVOv7NPLJAl8DWCEQ +qDJSsG7gcRddUNmjTRmAcLHqeKhWsRhdP30ilQOz1b7yHfgTWRPLiwd0d3WXbv4Z +EgpOYsZuB3hn65SrJVFn2dwJuz/iJ85g7cCuKBkCgYEA6C6O18FYYqa0sY2qZifs +ryW1ekJJFUhE4rluJCx4J3YvXtzpbbAXqRzfQX+BgSjosTuhKDstYR7J8C5drFpS +oU4PxqxrmoxfAgCca84prbaHRVPA1r1mj7LSHv0jAfGMa3TpKHBbk5wMwO/g1OMi +/tYajeoYLP9p39sNtgsF8HE= +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIEszCCA5ugAwIBAgIUE2YQ4Gyrr1+4i0VAQU4llwTyjNYwDQYJKoZIhvcNAQEL +BQAwgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw +CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwKcGFydG5lcmJjYTEm +MCQGCSqGSIb3DQEJARYXcGFydG5lcmJjYUBwYXJ0bmVyYi5jb20wIBcNMjEwNzA5 +MTkxMjE2WhgPMjEyMTA2MTUxOTEyMTZaMHcxCzAJBgNVBAYTAlVTMQswCQYDVQQI +DAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEO +MAwGA1UEAwwFbm9kZTIxITAfBgkqhkiG9w0BCQEWEm5vZGUyQHBhcnRuZXJiLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM4Z67DmmrgTXwBxk5h0 +tIRvK5JAyZYq2nXkGWlvVu4PhUS37rHEHBC+roELwDbgBZEUY8MzoYWROGv2+dTr +jCDrECMJBkRBioCdw7sVcoslZqBopgTTetFMoac1BmwfW4sTLAh0SKtXyPffXM4y +BCSTwlL4q/a2yh05nNthMhrG9Gl5OovPO/796DxFCg02v1eyoh9itUOG8Fy19Kme +zFW5H8YDEqKo3TTUMVr5iOfSxOsSOXJNueJNbwjlXl2dQ59TxrBZ2NcUUEthoNYe +c45ABGVkvKDYAV1I1fo25iFxS40EQIcV1C0EqRc1kQHoGrH5kc0boBmPBiTolj7S +TF0CAwEAAaOCASgwggEkMBEGCWCGSAGG+EIBAQQEAwIGwDAdBgNVHQ4EFgQUC+rE +//mis2iLbyls/S/ja/4/qtgwCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCBeAwHQYD +VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMIG1BgNVHSMEga0wgaqAFHlqInWc +DUceLRfNtGynhXtPx4oGoXykejB4MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0Ex +DDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNVBAsMBHJvb3QxEDAOBgNV +BAMMB2ludGVyY2ExIDAeBgkqhkiG9w0BCQEWEWludGVyY2FAYWRtaW4uY29tghRw +BMj83j0mxnIC7JLyB9boGml0EjANBgkqhkiG9w0BAQsFAAOCAQEApOPnX+voWhWH +cwc2ZOa2+lp8VMysh939AKQWLWvUmTUBcnPtvcN5pgTUzTW5xbsnLBvX4yBpsufa +RqqQps6/pMJudHPiyiE2cswnYDhOH1Lb735YOewqVjD+cvrm1rWiilMyb5WNmxZH +ktuyOlp6hkSIG6788SHJQyyOYcgPlenE43iAk7Mz9ESxXWnolCCawgYlYFI3qF/r +g5fJrR7Ys1+J9gbqBzjXys9cWyQlfg6y4G8Naa3xfrVmH1LhVc0sSzTIneZK1fFh +PwZ+exAhAUnbXCALp8B2Hd9Mehr13fTWzi6vfq5BB0PalB4w0Qg/7v7/W4de6sZw +4t9Yo0Vpyg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBIwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTEyMTFaGA8y +MTIxMDYxNTE5MTIxMVowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmJjYUBwYXJ0bmVyYi5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNTP8IviC0X2ozlU2+ +9+mPLL9NqJKRCsEiH7XypcXkqkzCYZv/+6nNWXGLr6HsF5qXaM/YVMJYtwiaJquw +qW1CpOKxhHA1gubNt0Fzmt69/5yP6D1zxTPzAcybNMuCy8VcLJpovYHO40+2HD6I +D91/zh3jtrgKPoEXgaW3eX4+hykQWaru3P/G4PrIvPyZXnccoCdBSRCqyZSBJUko +e5ZLnCQMlkwgDONGT3MqQyUC5lqFFMzZ75pOm2reiBe6HzP3H4wK7Ldpxds9ubGk +Acb08+QzcUT7uHvENyvLm5mbf68QurFTwIDEVg2K03dgqQWbJudSzRJAmJYSszFQ +vLZdAgMBAAGjZjBkMB0GA1UdDgQWBBR5aiJ1nA1HHi0XzbRsp4V7T8eKBjAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAsmFsG3SV1fQg6kO+ +dYvFrDKNOJzTBdVYmFhg4y4H7Qt+dwQcs/ZcOCIaAFUfMUH6CWe1AAdCymfwUHxn +l/FMeJHh/+d1cybC+Wj9wtBbz7nPsWh/PXbbg3Zi8N4+a6Y0NhZAGlNn1UgMHx+E +SkSIXk63FkGT01xM2aYtfr9ABuDdoLK/YPecduiawZoRb02WwIpZFNeEE/MS7XG6 +fX9TdUrNOal8pnWUM79K+rzdlzstpCx7uFFbACUEiiIuYiqG6X+DuypfGmQnjRXB +zbc6NsQONUxg7fnJObdpV7kKTlbpREFoECkTBdqKd7AuJwYRvGaQDWK9P1IYFr1W +Cnm4Cg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/node2/truststore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/node2/truststore.jks new file mode 100644 index 00000000000..a94ec44bc5a Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/node2/truststore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/crl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/crl.pem new file mode 100644 index 00000000000..8ced006c911 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/crl.pem @@ -0,0 +1,27 @@ +-----BEGIN X509 CRL----- +MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCVVMxCzAJBgNV +BAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJBgNVBAoMAk1DMQ0wCwYDVQQLDARyb290 +MRMwEQYDVQQDDApwYXJ0bmVyYWNhMSYwJAYJKoZIhvcNAQkBFhdwYXJ0bmVyYWNh +QHBhcnRuZXJhLmNvbRcNMjEwNzA5MTkxMjM1WhcNMjIwNzA5MTkxMjM1WjAnMCUC +FF9rJlU9U6JdFIeK/xRojaoxHdc5Fw0yMTA3MDkxOTEyMzVaoA4wDDAKBgNVHRQE +AwIBADANBgkqhkiG9w0BAQsFAAOCAQEAfByR//FGHSsVQbaS51d59o82XocOGnnT +p1hjceqtLGv3bhiebVrsRCOB5TsvE/r2IbB/yHYTe3+LJisIUqBxblQ6xK6IM+qA +3fY646YnPT5pvdZAPZ2BCN/xP3xqGffFKapQ9cz0/36YE3vaEoUDlC2VHK0OXI0t +4CLwAmiptUT2GW4Bk1RtokAsFiUNwNIOlRX5bywUNwkG7EuitR90QSGH3l/vyii2 +0c1Fm9He9MskwipjXpJKKb+t+m1pdpOVkSjRfjmVqi4BZwWlnQjELSLywhJ+WZG2 +Z1NgRjzPXotFKK+YD97Kx1L260A1eUZ46zSq73oUZr0EDZRnNJTr6A== +-----END X509 CRL----- +-----BEGIN X509 CRL----- +MIICLDCCARQCAQEwDQYJKoZIhvcNAQELBQAwgYExCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9v +dDETMBEGA1UEAwwKcGFydG5lcmJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmJj +YUBwYXJ0bmVyYi5jb20XDTIxMDcwOTE5MTIzNVoXDTIyMDcwOTE5MTIzNVowTjAl +AhQTZhDgbKuvX7iLRUBBTiWXBPKM1xcNMjEwNzA5MTkxMjM1WjAlAhRfayZVPVOi +XRSHiv8UaI2qMR3XORcNMjEwNzA5MTkxMjM1WqAOMAwwCgYDVR0UBAMCAQEwDQYJ +KoZIhvcNAQELBQADggEBAMIltmJ036f1BmK/baISJTZTu7PKZgSZMNORnpFT8KvC +s2GNRor5bGp5qvD6LHvsx92YVppCC6xd/beCFBtdyYifqw5xtOvqLQKuqCfxruLz +EqYjKXE/3v8VdyU71J7kFqi0U0Gy4/h/YCL92e5KNbATlmcn5ToyI2EBIEfBfV08 +mm7FBXvbHRzqhfrnCNEjBWBWz3zkJMc9Rib26eCCofYIDkY2HvYSN78YgrnMmD6O +hWOXrPoxArxvmDr5rG4vCadqbQYRkkCAOP0hBeMiB0SAcO2W2LNNAmHWXX7FvU3n +ZRZUX31WoVjhNeEQtNBb2mPYBXHQzLC66qYm1p97afc= +-----END X509 CRL----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/keys.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/keys.p12 new file mode 100644 index 00000000000..30115f1a0db Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/keys.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/keystore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/keystore.jks new file mode 100644 index 00000000000..310fbb591ca Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/keystore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nss.cfg new file mode 100644 index 00000000000..3615d46bd88 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nss.cfg @@ -0,0 +1,6 @@ + +name = NSScrypto-non-validator +nssSecmodDirectory = ./src/test/resources/pki-certs/non-validator/nssdb +nssDbMode = readOnly +nssModule = keystore + diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nssdb/cert8.db b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nssdb/cert8.db new file mode 100644 index 00000000000..13f76b09f90 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nssdb/cert8.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nssdb/key3.db b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nssdb/key3.db new file mode 100644 index 00000000000..9ae401fba81 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nssdb/key3.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nssdb/secmod.db b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nssdb/secmod.db new file mode 100644 index 00000000000..1320aa6f1c3 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nssdb/secmod.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/ssl-ca.pem b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/ssl-ca.pem new file mode 100644 index 00000000000..61a8f5230ed --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/ssl-ca.pem @@ -0,0 +1,70 @@ +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBEwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTExNTRaGA8y +MTIxMDYxNTE5MTE1NFowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmFjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDccGhUDD8T8m6e2x13 +B0LgCDR8F2vlfAw9FN/tXOKKU3DpagJk0CAutL6YFFYs9MXg8D6bZx+w0iXUnaN/ +6rjIC1LFs79AizpEaoFWDzcVI66ItSW1Swu3ts0I1kK7EGgAMba0TDTnssfrtuPw +rOA2TOdVX03owOE+gaaPonIQlnew5+NNGhbW+P/5ix1IQXhyuNjV/uu3VEJBGNTh +cAuMGdjvglFuz4zyFon4kNRcQvghs5ztjs2h5ZNHjEo6YtNIdJuRS/XOXII9MfPN +plcwJArWTM3yEATNBtdc5FypOSI6cO/Pl+SVEf4kKmnzJQZWOSGiDXbpm938hGVw +ByZPAgMBAAGjZjBkMB0GA1UdDgQWBBQhpkZg+Ktqh6sFCjtm9HE+9bLJ3TAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAIggdc0DCxEiNaKak +/xbc7uGiGBb+UzBTjk4BmX9kEFrZf4XEaHzsptltqcQDCVtzcbFFFxMYhv/w/1g/ +WMNuUhL0mmGIGMxfoqkg50tNyuHW6aSrBXErel9WthGXAhUSzdHgkWxl3pe2wgda +qIcSwTCFgOeVWTZRdKWqKNPHirBglJHUpMgLo0qa0Ug1hxiyOQRt2yXLpe/mH3pG +cozhrEDYQMOcDhYTpPwM2Bl+TsRPpxFaV4QDfiOyvUDFLMM0dyhl2pukjay/Xpp2 ++6Tsnaa+Ui0sDcM3A36Q07+E4Vugxjzfb9a36Eg4XE+Jg3jDA8UOqjeFg9gkK3aY +NaI0qQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/ssl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/ssl.pem new file mode 100644 index 00000000000..c885996bea1 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/ssl.pem @@ -0,0 +1,126 @@ +-----BEGIN PRIVATE KEY----- +MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDE53iE0LzazjEw +rPyUsnsn6GAwRmL8YdEQsD2SyUN59DnEV2gNuwmI446xv+eimdOcxaQTG4zjlIzN +RHpjYeV9JVrMfUV0T39/rbBVtv4mwsa2rTaC9qUyBzX7NjzYr+fEJ4G0TYlVaiGz +We8KyIRn47zlkmYPx42Hip75pE/7EcP87G0b38i6phdYkvsyAq6eIDbgTYa/otMx +z+mSejtcWgFxkShib6jXa5ycDJdxaAUlzqqUoYprvbiixgr/ga1gZs6lhB+sBO1P +hKjHFNnLNogFz+xDF8JRcYwqHPp4dCr150+mZasZcKxGRxB+a9/Ccjz2ZMlGRjGE +Vu6qwK0DAgMBAAECggEBALuBlaIcyQsweWVaBjlv8ZmiTx8JmC+w0o8q1afXozsa +WHxhpAQXTdAeqv8XuXR9Oie7ijBr9vGtv5ulj0reqdRP4zSCQsatAcRLWXV2inXM +28CQGC4ExHFsrnooPy816+Y+nORfRd2h8K/Df8BsDLKGC5cun6R9KoideCBQ2Z1C +tJYVrVC4/pPzAQAJIpE+xH6UwsrUnnBo31HdzaIl7Nh/4S/4F0RVSyrqKjZfEE4p +7Xt1ZpcQOQUo32YLOPjPwJuWGwVDM9jwaqI4fR3ckpaicMb8ihc0zlLjxQk2Cj8X +tockv6X4RdnviHp56Z9Lzfr+A/u9/dlT5Q8Sqz10K/ECgYEA6/ss5kbEEy4QjOlz +6lgJJhdTD5Tb1Zbbwu5unk8vVQrIbFCFc8o29qSQ5NCoRQ0b4BAPTlL5UsUMfwi2 ++g3iXmZScuNpR8ai9cfImEkZcxezknKBnJxLZ0nAym5eGCoF/da2dWGZ9NL/3kN2 +6e4Tz5++xp12/oQ58MoYd+eZFJkCgYEA1ZuoPPdy3NA/dgjoaJ6r0HYgNW18FMq/ +Lj7fGXT4IluCRndXhW/FBcNfqpzXcOBwRsf0PiiMuLW+LDJnT9XLr58/IqpbjS+s +I/oAtaTwkwBtcmSAR/L33O/IpZ9lh2PD0I+5JDlvAQp8ESoSS2ceD1xxyz4nyIVn +xTaRVKdnM/sCgYEAmzlUVoD0Fv21C0vA4MRZ+EFddKFhXYTnN7ko8F977f+yyHTK +49h/AQxM9wY9uXYfAOrvdoDj2cseJi2wVpltbtT1pPbr2LfTl8J7s5hZ8jgD+e/y +S/cPLnj4JPAmWtTBrjBfQqUZ5U4p2qUcAlKFm4wjrHgFvvNxPW9iWvTv3/kCgYEA +oChvgha+hpWVn3iaWSbvCAQpriWC7Uv/ADufp0Sub4RRL2h3tNLS1LliV1f1qOp/ +BHMTzC83I58REa5RC+jvKaSq/+DfeAKQfQEL2yXqQy4E4co87LVd5sfal2PmChdh +UFUSqfhuJEeqMmxq/yI3xai4oXze81gjMBjz6pcBqFUCgYEArVZbnwTSueEwSSGn +Ba9FBjwj44hrD+khAGODcpyBg0sC22hYuSJiUgpiRHb77XGNLK/Rn2i3ZUyuww03 +HfYgeXFO6DeuSy8jU7nP0FcLFmvZq7JqzFS6T46z7zepTSnIK5PSVuHAPy7nZTqC +BAHouXhT1BsH1rCY7vVH7LVXQhs= +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIExDCCA6ygAwIBAgIUX2smVT1Tol0Uh4r/FGiNqjEd1zYwDQYJKoZIhvcNAQEL +BQAwgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw +CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwKcGFydG5lcmFjYTEm +MCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5jb20wIBcNMjEwNzA5 +MTkxMjAzWhgPMjEyMTA2MTUxOTEyMDNaMIGHMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNVBAsMBHJvb3Qx +FjAUBgNVBAMMDW5vbi12YWxpZGF0b3IxKTAnBgkqhkiG9w0BCQEWGm5vbi12YWxp +ZGF0b3JAcGFydG5lcmEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAxOd4hNC82s4xMKz8lLJ7J+hgMEZi/GHRELA9kslDefQ5xFdoDbsJiOOOsb/n +opnTnMWkExuM45SMzUR6Y2HlfSVazH1FdE9/f62wVbb+JsLGtq02gvalMgc1+zY8 +2K/nxCeBtE2JVWohs1nvCsiEZ+O85ZJmD8eNh4qe+aRP+xHD/OxtG9/IuqYXWJL7 +MgKuniA24E2Gv6LTMc/pkno7XFoBcZEoYm+o12ucnAyXcWgFJc6qlKGKa724osYK +/4GtYGbOpYQfrATtT4SoxxTZyzaIBc/sQxfCUXGMKhz6eHQq9edPpmWrGXCsRkcQ +fmvfwnI89mTJRkYxhFbuqsCtAwIDAQABo4IBKDCCASQwEQYJYIZIAYb4QgEBBAQD +AgbAMB0GA1UdDgQWBBRXMoam1AQo0jGVQxCRxbHlU18FPTAJBgNVHRMEAjAAMA4G +A1UdDwEB/wQEAwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwgbUG +A1UdIwSBrTCBqoAUIaZGYPiraoerBQo7ZvRxPvWyyd2hfKR6MHgxCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsG +A1UECwwEcm9vdDEQMA4GA1UEAwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50 +ZXJjYUBhZG1pbi5jb22CFHAEyPzePSbGcgLskvIH1ugaaXQRMA0GCSqGSIb3DQEB +CwUAA4IBAQCdXem4j/D85ME7kOU6G4DpMOfFsGJEQ20oovKpEoqm0wKaEp61TGci +q9UjEQI0Istxb0x7xykqP5UAlGXk/xDXFLcz+pe2M/vKo/4sJBEvxV+yr33Cgwli +PL3XgiRqaDEXVcRXa2RcwW+HVzrBOvQz8IYdFeeqt7y+sCqw3oMkaAPKDv9H+gcL +5EI+3r9WRnQmy8VWF8FuGWZG1daDnlFC0mm/PvOctVP+YROB7mbwfs+68xtqadWe +pHdIG+rX7Bs4hZ5mXNu4Hwl+iCPRRj1uyfNkwfx3BsWnR142RksFgZjlTLaGCFCk +Qf3PEFIHpi+kiPzI5Qm8hUVLNWcJiHhO +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBEwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTExNTRaGA8y +MTIxMDYxNTE5MTE1NFowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmFjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDccGhUDD8T8m6e2x13 +B0LgCDR8F2vlfAw9FN/tXOKKU3DpagJk0CAutL6YFFYs9MXg8D6bZx+w0iXUnaN/ +6rjIC1LFs79AizpEaoFWDzcVI66ItSW1Swu3ts0I1kK7EGgAMba0TDTnssfrtuPw +rOA2TOdVX03owOE+gaaPonIQlnew5+NNGhbW+P/5ix1IQXhyuNjV/uu3VEJBGNTh +cAuMGdjvglFuz4zyFon4kNRcQvghs5ztjs2h5ZNHjEo6YtNIdJuRS/XOXII9MfPN +plcwJArWTM3yEATNBtdc5FypOSI6cO/Pl+SVEf4kKmnzJQZWOSGiDXbpm938hGVw +ByZPAgMBAAGjZjBkMB0GA1UdDgQWBBQhpkZg+Ktqh6sFCjtm9HE+9bLJ3TAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAIggdc0DCxEiNaKak +/xbc7uGiGBb+UzBTjk4BmX9kEFrZf4XEaHzsptltqcQDCVtzcbFFFxMYhv/w/1g/ +WMNuUhL0mmGIGMxfoqkg50tNyuHW6aSrBXErel9WthGXAhUSzdHgkWxl3pe2wgda +qIcSwTCFgOeVWTZRdKWqKNPHirBglJHUpMgLo0qa0Ug1hxiyOQRt2yXLpe/mH3pG +cozhrEDYQMOcDhYTpPwM2Bl+TsRPpxFaV4QDfiOyvUDFLMM0dyhl2pukjay/Xpp2 ++6Tsnaa+Ui0sDcM3A36Q07+E4Vugxjzfb9a36Eg4XE+Jg3jDA8UOqjeFg9gkK3aY +NaI0qQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/truststore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/truststore.jks new file mode 100644 index 00000000000..bac9b25c751 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/non-validator/truststore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/crl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/crl.pem new file mode 100644 index 00000000000..8ced006c911 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/crl.pem @@ -0,0 +1,27 @@ +-----BEGIN X509 CRL----- +MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCVVMxCzAJBgNV +BAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJBgNVBAoMAk1DMQ0wCwYDVQQLDARyb290 +MRMwEQYDVQQDDApwYXJ0bmVyYWNhMSYwJAYJKoZIhvcNAQkBFhdwYXJ0bmVyYWNh +QHBhcnRuZXJhLmNvbRcNMjEwNzA5MTkxMjM1WhcNMjIwNzA5MTkxMjM1WjAnMCUC +FF9rJlU9U6JdFIeK/xRojaoxHdc5Fw0yMTA3MDkxOTEyMzVaoA4wDDAKBgNVHRQE +AwIBADANBgkqhkiG9w0BAQsFAAOCAQEAfByR//FGHSsVQbaS51d59o82XocOGnnT +p1hjceqtLGv3bhiebVrsRCOB5TsvE/r2IbB/yHYTe3+LJisIUqBxblQ6xK6IM+qA +3fY646YnPT5pvdZAPZ2BCN/xP3xqGffFKapQ9cz0/36YE3vaEoUDlC2VHK0OXI0t +4CLwAmiptUT2GW4Bk1RtokAsFiUNwNIOlRX5bywUNwkG7EuitR90QSGH3l/vyii2 +0c1Fm9He9MskwipjXpJKKb+t+m1pdpOVkSjRfjmVqi4BZwWlnQjELSLywhJ+WZG2 +Z1NgRjzPXotFKK+YD97Kx1L260A1eUZ46zSq73oUZr0EDZRnNJTr6A== +-----END X509 CRL----- +-----BEGIN X509 CRL----- +MIICLDCCARQCAQEwDQYJKoZIhvcNAQELBQAwgYExCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9v +dDETMBEGA1UEAwwKcGFydG5lcmJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmJj +YUBwYXJ0bmVyYi5jb20XDTIxMDcwOTE5MTIzNVoXDTIyMDcwOTE5MTIzNVowTjAl +AhQTZhDgbKuvX7iLRUBBTiWXBPKM1xcNMjEwNzA5MTkxMjM1WjAlAhRfayZVPVOi +XRSHiv8UaI2qMR3XORcNMjEwNzA5MTkxMjM1WqAOMAwwCgYDVR0UBAMCAQEwDQYJ +KoZIhvcNAQELBQADggEBAMIltmJ036f1BmK/baISJTZTu7PKZgSZMNORnpFT8KvC +s2GNRor5bGp5qvD6LHvsx92YVppCC6xd/beCFBtdyYifqw5xtOvqLQKuqCfxruLz +EqYjKXE/3v8VdyU71J7kFqi0U0Gy4/h/YCL92e5KNbATlmcn5ToyI2EBIEfBfV08 +mm7FBXvbHRzqhfrnCNEjBWBWz3zkJMc9Rib26eCCofYIDkY2HvYSN78YgrnMmD6O +hWOXrPoxArxvmDr5rG4vCadqbQYRkkCAOP0hBeMiB0SAcO2W2LNNAmHWXX7FvU3n +ZRZUX31WoVjhNeEQtNBb2mPYBXHQzLC66qYm1p97afc= +-----END X509 CRL----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/keys.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/keys.p12 new file mode 100644 index 00000000000..0f5879ff1c0 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/keys.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/keystore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/keystore.jks new file mode 100644 index 00000000000..1adfb524170 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/keystore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nss.cfg new file mode 100644 index 00000000000..afe2f17e0f2 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nss.cfg @@ -0,0 +1,6 @@ + +name = NSScrypto-nonValidator +nssSecmodDirectory = ./src/test/resources/pki-certs/nonValidator/nssdb +nssDbMode = readOnly +nssModule = keystore + diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nssdb/cert8.db b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nssdb/cert8.db new file mode 100644 index 00000000000..3a477ba52eb Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nssdb/cert8.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nssdb/key3.db b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nssdb/key3.db new file mode 100644 index 00000000000..b6d6179cd2c Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nssdb/key3.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nssdb/secmod.db b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nssdb/secmod.db new file mode 100644 index 00000000000..1d70f9b3a97 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nssdb/secmod.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/ssl-ca.pem b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/ssl-ca.pem new file mode 100644 index 00000000000..61a8f5230ed --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/ssl-ca.pem @@ -0,0 +1,70 @@ +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBEwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTExNTRaGA8y +MTIxMDYxNTE5MTE1NFowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmFjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDccGhUDD8T8m6e2x13 +B0LgCDR8F2vlfAw9FN/tXOKKU3DpagJk0CAutL6YFFYs9MXg8D6bZx+w0iXUnaN/ +6rjIC1LFs79AizpEaoFWDzcVI66ItSW1Swu3ts0I1kK7EGgAMba0TDTnssfrtuPw +rOA2TOdVX03owOE+gaaPonIQlnew5+NNGhbW+P/5ix1IQXhyuNjV/uu3VEJBGNTh +cAuMGdjvglFuz4zyFon4kNRcQvghs5ztjs2h5ZNHjEo6YtNIdJuRS/XOXII9MfPN +plcwJArWTM3yEATNBtdc5FypOSI6cO/Pl+SVEf4kKmnzJQZWOSGiDXbpm938hGVw +ByZPAgMBAAGjZjBkMB0GA1UdDgQWBBQhpkZg+Ktqh6sFCjtm9HE+9bLJ3TAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAIggdc0DCxEiNaKak +/xbc7uGiGBb+UzBTjk4BmX9kEFrZf4XEaHzsptltqcQDCVtzcbFFFxMYhv/w/1g/ +WMNuUhL0mmGIGMxfoqkg50tNyuHW6aSrBXErel9WthGXAhUSzdHgkWxl3pe2wgda +qIcSwTCFgOeVWTZRdKWqKNPHirBglJHUpMgLo0qa0Ug1hxiyOQRt2yXLpe/mH3pG +cozhrEDYQMOcDhYTpPwM2Bl+TsRPpxFaV4QDfiOyvUDFLMM0dyhl2pukjay/Xpp2 ++6Tsnaa+Ui0sDcM3A36Q07+E4Vugxjzfb9a36Eg4XE+Jg3jDA8UOqjeFg9gkK3aY +NaI0qQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/ssl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/ssl.pem new file mode 100644 index 00000000000..5fa819c3f6d --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/ssl.pem @@ -0,0 +1,126 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD2G3cW10hPZCtX +rRYKLaa+yvxmnMNm4HijA1QbK/biD1j+6HDlbL00VVw5w3E8fc8DJD/qkL6lHy4w +u12Y1OL8EuZeBEz6+u3xp4OB5YH4LsMXc3gUcLI25wx7eqfaFcPuqSu+blGXwpJ9 +lGzwj69+lX8AYqA/+ZXufdWmyU5syTwvbWAiXF8SGnjoeNIEABYgdQ5ngy3ZLYVS +7mDwDWBoPkv1tfInZlzq9pjZFRicVNR0zfQKfMS6X2FX2M06A0R9MvWe55DJxA0s +082AHGI2+XuPomvwI+nje1b3RQhvW2SekYoHUtKnI6La4/wrLNuEEWV2UzphUa3v +fiT7aqF/AgMBAAECggEAVHC7/ZRD9SlzTZPPmhJrwc63pyVmTef6vEOqGeCNxqZp +bJyoD6+tg0U+bXtHYO/xlSxc2chsAQ+fs4y14ng4oTCC5gMnvn1WIrHNB0aNv2+b +9HHj429/ViMUP1GoQcVyAnL81UvYpu9Vf8zrS+ag2hfFCYbNYOXrsXZvVdiAFgaR +ZXh65uU7nBEODyqFj9sRtD+/ABfdoC9Vf9qs9vMaVxuIanNPtu7hHAUQ5z/WVIX/ +ZQGnfePvq5OyYDKzCHh2kWjWLLXPd/ICn6XNvjfY6k618R+3fafQ4SVyRFHNSn6H +7k7SInp4kw+QBCJXP3L47sZzZXrMEeoNslrOGMUkQQKBgQD9Vn/94JQHgAlZ8PaS +LdoNDQz53jWjBv7TZqwtZj76nHcZxGmXceSls4TZnuzZVyfk1RRxu6V4vj7sjlCB +nGnESm+158PqNcpHm2qkvuSYxZxupcx6gbnK8AWitD4Ruah2xLtIWZe75HNJPdA8 +8lew2xE9j/jo4qt1GpswCIFJzwKBgQD4sYOo5VAuNLnpV3QrXLu0svAAUZNVrQi3 +/SbYdrOg52BfmHiSPdhUy6xYgmWpcPsSPsgwl7Xr4SEMevbxNN1XvOnTVi+aTtR3 +7VmdSjpepqvx15QKXw2IekxiP3lueaJqjRgrfHNC3uv4wS+UHw4Kgx5qNL8rqoZw +nN4IjvYJUQKBgQCbzEaKa0KeGi+mEHqTC3+95vjD8dQqnnK4r7vTb73rga39Or11 +VaW4Ad8BtqsSPndaU3BvQWdSCi3IbP01uGuTO/PXeuEReGMeBoZfKsaK7Xx2z6Ag +9wa7t0C//vjtDbB82iATLoYSFzyPHmSiFqe3LAI+SfxZvIyVR/eIYrKgIQKBgHKO +6vQpNccjGKSpWWUEIZ86ch3jdfgYbhS682LxQwuSqa0/ggLzpCxjae+XmZb06WLd +MsBXkkCnAt9J4Wj5DiD1b8yfPexZ9buMxSQUZlDle/06bgJdCNHebEMxtBE0zKFC +f2jAuiOKpq5+5xjXOVOUVLVduNY3hhhn2kuc9y8RAoGAKgRwLBSk5XfOFdIkiulh +oeJ2xZHUDGxUPxteBqjXPdvMmVOJuPpLhvvV+4HwA0OXtG5GZXsl8zKhdouiVzUv +z0LXtlGX/4s1Oin+7N0qs4y+iPa4FSaypy3W5hzepwLr3HrrVnZRIjkWE0HZkBPl +MEfmbKXS0HuPCklNjx0yYio= +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIEwjCCA6qgAwIBAgIUX2smVT1Tol0Uh4r/FGiNqjEd1zUwDQYJKoZIhvcNAQEL +BQAwgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw +CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwKcGFydG5lcmFjYTEm +MCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5jb20wIBcNMjEwNzA5 +MTkxMTU5WhgPMjEyMTA2MTUxOTExNTlaMIGFMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNVBAsMBHJvb3Qx +FTATBgNVBAMMDG5vblZhbGlkYXRvcjEoMCYGCSqGSIb3DQEJARYZbm9uVmFsaWRh +dG9yQHBhcnRuZXJhLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +APYbdxbXSE9kK1etFgotpr7K/Gacw2bgeKMDVBsr9uIPWP7ocOVsvTRVXDnDcTx9 +zwMkP+qQvqUfLjC7XZjU4vwS5l4ETPr67fGng4HlgfguwxdzeBRwsjbnDHt6p9oV +w+6pK75uUZfCkn2UbPCPr36VfwBioD/5le591abJTmzJPC9tYCJcXxIaeOh40gQA +FiB1DmeDLdkthVLuYPANYGg+S/W18idmXOr2mNkVGJxU1HTN9Ap8xLpfYVfYzToD +RH0y9Z7nkMnEDSzTzYAcYjb5e4+ia/Aj6eN7VvdFCG9bZJ6RigdS0qcjotrj/Css +24QRZXZTOmFRre9+JPtqoX8CAwEAAaOCASgwggEkMBEGCWCGSAGG+EIBAQQEAwIG +wDAdBgNVHQ4EFgQUUxNHyKHVtefbfv7VxdzZLgFQd9cwCQYDVR0TBAIwADAOBgNV +HQ8BAf8EBAMCBeAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMIG1BgNV +HSMEga0wgaqAFCGmRmD4q2qHqwUKO2b0cT71ssndoXykejB4MQswCQYDVQQGEwJV +UzELMAkGA1UECAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNV +BAsMBHJvb3QxEDAOBgNVBAMMB2ludGVyY2ExIDAeBgkqhkiG9w0BCQEWEWludGVy +Y2FAYWRtaW4uY29tghRwBMj83j0mxnIC7JLyB9boGml0ETANBgkqhkiG9w0BAQsF +AAOCAQEAWMx7UZJTA7XWCSODWiGh1bJkvTCSc7XSY3h0hNjAwWOZQIvjIUAEaxtX +2sPlVWWnd2gt05mHbiiTqgcCPJuydGE9ne9PcSGU5fj11ZN7ofOP+V49Ru+R44KL +dV5zWsYN+STBjESwOE1uGa6ri1aUF9Viebp4Sg7/WZWOYO6WOop2Kc9KDnSm5NYP +ThQtcwbwZzmiNN62RodnpIlYU4QOu6B7wddNSGtzlGYvBI2aCCQuXxMpxKCfQ63t +QKznbR+DJXXPshcbKOMjXJZG9MSTYww9bPV50Ok4DtWfgP048CNAm4KYp+WsyoAj +RW8R1hN3vIf9V30mTixkLcTt7JVqBA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBEwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTExNTRaGA8y +MTIxMDYxNTE5MTE1NFowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmFjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDccGhUDD8T8m6e2x13 +B0LgCDR8F2vlfAw9FN/tXOKKU3DpagJk0CAutL6YFFYs9MXg8D6bZx+w0iXUnaN/ +6rjIC1LFs79AizpEaoFWDzcVI66ItSW1Swu3ts0I1kK7EGgAMba0TDTnssfrtuPw +rOA2TOdVX03owOE+gaaPonIQlnew5+NNGhbW+P/5ix1IQXhyuNjV/uu3VEJBGNTh +cAuMGdjvglFuz4zyFon4kNRcQvghs5ztjs2h5ZNHjEo6YtNIdJuRS/XOXII9MfPN +plcwJArWTM3yEATNBtdc5FypOSI6cO/Pl+SVEf4kKmnzJQZWOSGiDXbpm938hGVw +ByZPAgMBAAGjZjBkMB0GA1UdDgQWBBQhpkZg+Ktqh6sFCjtm9HE+9bLJ3TAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAIggdc0DCxEiNaKak +/xbc7uGiGBb+UzBTjk4BmX9kEFrZf4XEaHzsptltqcQDCVtzcbFFFxMYhv/w/1g/ +WMNuUhL0mmGIGMxfoqkg50tNyuHW6aSrBXErel9WthGXAhUSzdHgkWxl3pe2wgda +qIcSwTCFgOeVWTZRdKWqKNPHirBglJHUpMgLo0qa0Ug1hxiyOQRt2yXLpe/mH3pG +cozhrEDYQMOcDhYTpPwM2Bl+TsRPpxFaV4QDfiOyvUDFLMM0dyhl2pukjay/Xpp2 ++6Tsnaa+Ui0sDcM3A36Q07+E4Vugxjzfb9a36Eg4XE+Jg3jDA8UOqjeFg9gkK3aY +NaI0qQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/truststore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/truststore.jks new file mode 100644 index 00000000000..d50fba298f8 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/nonValidator/truststore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/truststore/truststore.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/truststore/truststore.p12 new file mode 100644 index 00000000000..33079569a10 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/truststore/truststore.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator/crl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator/crl.pem new file mode 100644 index 00000000000..8ced006c911 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator/crl.pem @@ -0,0 +1,27 @@ +-----BEGIN X509 CRL----- +MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCVVMxCzAJBgNV +BAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJBgNVBAoMAk1DMQ0wCwYDVQQLDARyb290 +MRMwEQYDVQQDDApwYXJ0bmVyYWNhMSYwJAYJKoZIhvcNAQkBFhdwYXJ0bmVyYWNh +QHBhcnRuZXJhLmNvbRcNMjEwNzA5MTkxMjM1WhcNMjIwNzA5MTkxMjM1WjAnMCUC +FF9rJlU9U6JdFIeK/xRojaoxHdc5Fw0yMTA3MDkxOTEyMzVaoA4wDDAKBgNVHRQE +AwIBADANBgkqhkiG9w0BAQsFAAOCAQEAfByR//FGHSsVQbaS51d59o82XocOGnnT +p1hjceqtLGv3bhiebVrsRCOB5TsvE/r2IbB/yHYTe3+LJisIUqBxblQ6xK6IM+qA +3fY646YnPT5pvdZAPZ2BCN/xP3xqGffFKapQ9cz0/36YE3vaEoUDlC2VHK0OXI0t +4CLwAmiptUT2GW4Bk1RtokAsFiUNwNIOlRX5bywUNwkG7EuitR90QSGH3l/vyii2 +0c1Fm9He9MskwipjXpJKKb+t+m1pdpOVkSjRfjmVqi4BZwWlnQjELSLywhJ+WZG2 +Z1NgRjzPXotFKK+YD97Kx1L260A1eUZ46zSq73oUZr0EDZRnNJTr6A== +-----END X509 CRL----- +-----BEGIN X509 CRL----- +MIICLDCCARQCAQEwDQYJKoZIhvcNAQELBQAwgYExCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9v +dDETMBEGA1UEAwwKcGFydG5lcmJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmJj +YUBwYXJ0bmVyYi5jb20XDTIxMDcwOTE5MTIzNVoXDTIyMDcwOTE5MTIzNVowTjAl +AhQTZhDgbKuvX7iLRUBBTiWXBPKM1xcNMjEwNzA5MTkxMjM1WjAlAhRfayZVPVOi +XRSHiv8UaI2qMR3XORcNMjEwNzA5MTkxMjM1WqAOMAwwCgYDVR0UBAMCAQEwDQYJ +KoZIhvcNAQELBQADggEBAMIltmJ036f1BmK/baISJTZTu7PKZgSZMNORnpFT8KvC +s2GNRor5bGp5qvD6LHvsx92YVppCC6xd/beCFBtdyYifqw5xtOvqLQKuqCfxruLz +EqYjKXE/3v8VdyU71J7kFqi0U0Gy4/h/YCL92e5KNbATlmcn5ToyI2EBIEfBfV08 +mm7FBXvbHRzqhfrnCNEjBWBWz3zkJMc9Rib26eCCofYIDkY2HvYSN78YgrnMmD6O +hWOXrPoxArxvmDr5rG4vCadqbQYRkkCAOP0hBeMiB0SAcO2W2LNNAmHWXX7FvU3n +ZRZUX31WoVjhNeEQtNBb2mPYBXHQzLC66qYm1p97afc= +-----END X509 CRL----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator/keys.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/validator/keys.p12 new file mode 100644 index 00000000000..c3be57147fe Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator/keys.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator/keystore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/validator/keystore.jks new file mode 100644 index 00000000000..4fb942a9e0f Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator/keystore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/validator/nss.cfg new file mode 100644 index 00000000000..f3849919caa --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator/nss.cfg @@ -0,0 +1,6 @@ + +name = NSScrypto-validator +nssSecmodDirectory = ./src/test/resources/pki-certs/validator/nssdb +nssDbMode = readOnly +nssModule = keystore + diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator/nssdb/cert8.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator/nssdb/cert8.db new file mode 100644 index 00000000000..f1aa64c06ca Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator/nssdb/cert8.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator/nssdb/key3.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator/nssdb/key3.db new file mode 100644 index 00000000000..cb2eb74985d Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator/nssdb/key3.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator/nssdb/secmod.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator/nssdb/secmod.db new file mode 100644 index 00000000000..c51600ebfcf Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator/nssdb/secmod.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/validator/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator/ssl-ca.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator/ssl-ca.pem new file mode 100644 index 00000000000..61a8f5230ed --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator/ssl-ca.pem @@ -0,0 +1,70 @@ +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBEwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTExNTRaGA8y +MTIxMDYxNTE5MTE1NFowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmFjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDccGhUDD8T8m6e2x13 +B0LgCDR8F2vlfAw9FN/tXOKKU3DpagJk0CAutL6YFFYs9MXg8D6bZx+w0iXUnaN/ +6rjIC1LFs79AizpEaoFWDzcVI66ItSW1Swu3ts0I1kK7EGgAMba0TDTnssfrtuPw +rOA2TOdVX03owOE+gaaPonIQlnew5+NNGhbW+P/5ix1IQXhyuNjV/uu3VEJBGNTh +cAuMGdjvglFuz4zyFon4kNRcQvghs5ztjs2h5ZNHjEo6YtNIdJuRS/XOXII9MfPN +plcwJArWTM3yEATNBtdc5FypOSI6cO/Pl+SVEf4kKmnzJQZWOSGiDXbpm938hGVw +ByZPAgMBAAGjZjBkMB0GA1UdDgQWBBQhpkZg+Ktqh6sFCjtm9HE+9bLJ3TAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAIggdc0DCxEiNaKak +/xbc7uGiGBb+UzBTjk4BmX9kEFrZf4XEaHzsptltqcQDCVtzcbFFFxMYhv/w/1g/ +WMNuUhL0mmGIGMxfoqkg50tNyuHW6aSrBXErel9WthGXAhUSzdHgkWxl3pe2wgda +qIcSwTCFgOeVWTZRdKWqKNPHirBglJHUpMgLo0qa0Ug1hxiyOQRt2yXLpe/mH3pG +cozhrEDYQMOcDhYTpPwM2Bl+TsRPpxFaV4QDfiOyvUDFLMM0dyhl2pukjay/Xpp2 ++6Tsnaa+Ui0sDcM3A36Q07+E4Vugxjzfb9a36Eg4XE+Jg3jDA8UOqjeFg9gkK3aY +NaI0qQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator/ssl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator/ssl.pem new file mode 100644 index 00000000000..a699dca2af4 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator/ssl.pem @@ -0,0 +1,126 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCoFSKbOeGCRhkr +fL6hOZ/+Nddfcep2vLcRXW/7MIN4OK26uGQx2xJr2p3Svl+m6ib4jLWx6E//tPVs +PbsipMWIazlwM6pa8rA2SHmJ7WORq/S7RRgElxqgOnRsmgxyylhffAyHvb1aOtGl +Hqzy3C3p+k6wSwleQfDhPdV1+4CLWJFJA9iHjVZzo7wr2JlOzsvnUZmlsIBeN7sb +M+Nn5ttdL9FAEbB0YtALEdbhJQrOTASzR+rK36VGn2iYQVuhCxUHb35WbZ0E/U/M +76QkMHRZs2sQ4BAluS2bOl1pXtaVW1ZSNCcNgzSBlu5gUJSoNqdaWqh5RSQDHRaU +1subXekFAgMBAAECggEAIgvd7alkx3mhgZCMIKZGhTysupWdk52YS3ksxKnIB6Mb +dbYB/aNNcPFghJ6xS2Mkr7X42+edxMMH73v1mwfbR03I3bRpbnC4RtaZX9npEEnP +kdtmCQ/+gbQ1fwYZPWtFSVocQ6aoY02Ex7iV+b+lwT5FkCoy5Jfgzg8zXOmr2Q2s +k/7wX8rj01/our7SSO7piwrlBz/uFKpRA/1NFa42R2FdYhHVTUa3nacpI2YBUSCB +TdN9tzWT7hOmVBFQm6RBnUE31sLDvyfJ2cFTpzbIogg1ZZ1DqUbY0obIwR4EBLfS +BvmsMRmCelgrRBENCDgV4CFcxN9oADH897avIy/QQQKBgQDWJnfjDAIAjSwN3f1M +Q9AzjLuNcWIg45sWdO8k0UnfUNAyPjNFlAu9GQ2nkvsUF/J5+ujATYbLo5GkzoH8 +A7aAljYU2jsErlMb0CRfQwvetQDTDwomeKSGH+6vjV54dqJ8y5/USswpy77zo5KF +ocFZPcViyZM+e3OsAKd1wSx91QKBgQDI7fyhXo4GAAFPuJDS+kVq3ObFSvxA9ahk +vDVB+Ryvuomblekm1sZT3mOgjTiWNfU3XeS4FM0EOTXAtUFRXUBEuum/G6/gNoHq +/FPpBICEHg6mKlHs3esOUWX1VENg0zA0oQYn23ZtlYel9Wm+2tqflX3TCUR10sFd +R0QqVHnmcQKBgDLcTgrpliwlWzor5/XOAUvM99pe/GxNQk8yFH4NCttz6Q6VwT2c +LLGLmrea6/DYwyj/U3ogr4v73CJlPW/qPdUKV+vZ7Lxu3qQzagAJ/260VG7MGqAK +dSC5wsmE7NP1cR/siJg174lZr49T4P/F7BLS3edZcpQbY9yNBzirWXLFAoGAUK3W +scjwyBH6dNNMO5rIgtc+RlwMm9zIB+LWk63+ScVh+bohCzpUGlsCr/XkkdQKqXen +Hg8kHx0Fq2JcXtpNswtGTjlEzoe0dPFqk/b9z47uHOSDTtPwzSf8A50ZDOjfw1Ig +0aI6lFflRssa8cqY3Fk/U5y2A4VjpRu3kDOpWtECgYEAvyJCc69wZSphrX3lRG75 +hw92hMAB0FEqLz0L0j5iM5CS7T7nte5i0AGOWkokFeL12KAk6yH7+2mJNNfCIepm +H4DuDMOqUAhXNEKjOUUcZTSzzyIa05OnLbIflHLtNXrQWcx66H64aUyolALr3HQ/ +Nzs74GQxjAgkS6nSB0xk1wE= +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIEuzCCA6OgAwIBAgIUX2smVT1Tol0Uh4r/FGiNqjEd1zQwDQYJKoZIhvcNAQEL +BQAwgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw +CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwKcGFydG5lcmFjYTEm +MCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5jb20wIBcNMjEwNzA5 +MTkxMTU2WhgPMjEyMTA2MTUxOTExNTZaMH8xCzAJBgNVBAYTAlVTMQswCQYDVQQI +DAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDES +MBAGA1UEAwwJdmFsaWRhdG9yMSUwIwYJKoZIhvcNAQkBFhZ2YWxpZGF0b3JAcGFy +dG5lcmEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqBUimznh +gkYZK3y+oTmf/jXXX3Hqdry3EV1v+zCDeDiturhkMdsSa9qd0r5fpuom+Iy1sehP +/7T1bD27IqTFiGs5cDOqWvKwNkh5ie1jkav0u0UYBJcaoDp0bJoMcspYX3wMh729 +WjrRpR6s8twt6fpOsEsJXkHw4T3VdfuAi1iRSQPYh41Wc6O8K9iZTs7L51GZpbCA +Xje7GzPjZ+bbXS/RQBGwdGLQCxHW4SUKzkwEs0fqyt+lRp9omEFboQsVB29+Vm2d +BP1PzO+kJDB0WbNrEOAQJbktmzpdaV7WlVtWUjQnDYM0gZbuYFCUqDanWlqoeUUk +Ax0WlNbLm13pBQIDAQABo4IBKDCCASQwEQYJYIZIAYb4QgEBBAQDAgbAMB0GA1Ud +DgQWBBS3AIMGNhY4RF3tSpfawFoYcyjy3jAJBgNVHRMEAjAAMA4GA1UdDwEB/wQE +AwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwgbUGA1UdIwSBrTCB +qoAUIaZGYPiraoerBQo7ZvRxPvWyyd2hfKR6MHgxCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9v +dDEQMA4GA1UEAwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1p +bi5jb22CFHAEyPzePSbGcgLskvIH1ugaaXQRMA0GCSqGSIb3DQEBCwUAA4IBAQCm +e6f/tVSVbIzdwJiqBL6yMoaC26m7nVk8pcVArQJQeHzQ6rVkyv/MWdJiYXzWjBfx +YaFoeLTLoM/hiLjjL/PtskHny/rLlYVhV8sFVpv0xsXG6OP22UZEbpoESDVU3e8D +7XPNXTvqyOdaht7VzRJNK/iv49EdDkOVTAUsK8kOukx6DZPAQGQT+5fkt2dq0sNH ++MH/Z8p5Ue/WxL1L8XLgGv1P0K1xpW7CJoSx5pa+vds4F9NuD4TThY0xK4F1hD3+ +nTtExFHquh0DhansjOG5EZPuj8HLf2Sn9cyFXErAAOedtwWKx4HjSatdHcVCysWm +jiQxcAxGeRqlG0te9oX4 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBEwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTExNTRaGA8y +MTIxMDYxNTE5MTE1NFowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmFjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDccGhUDD8T8m6e2x13 +B0LgCDR8F2vlfAw9FN/tXOKKU3DpagJk0CAutL6YFFYs9MXg8D6bZx+w0iXUnaN/ +6rjIC1LFs79AizpEaoFWDzcVI66ItSW1Swu3ts0I1kK7EGgAMba0TDTnssfrtuPw +rOA2TOdVX03owOE+gaaPonIQlnew5+NNGhbW+P/5ix1IQXhyuNjV/uu3VEJBGNTh +cAuMGdjvglFuz4zyFon4kNRcQvghs5ztjs2h5ZNHjEo6YtNIdJuRS/XOXII9MfPN +plcwJArWTM3yEATNBtdc5FypOSI6cO/Pl+SVEf4kKmnzJQZWOSGiDXbpm938hGVw +ByZPAgMBAAGjZjBkMB0GA1UdDgQWBBQhpkZg+Ktqh6sFCjtm9HE+9bLJ3TAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAIggdc0DCxEiNaKak +/xbc7uGiGBb+UzBTjk4BmX9kEFrZf4XEaHzsptltqcQDCVtzcbFFFxMYhv/w/1g/ +WMNuUhL0mmGIGMxfoqkg50tNyuHW6aSrBXErel9WthGXAhUSzdHgkWxl3pe2wgda +qIcSwTCFgOeVWTZRdKWqKNPHirBglJHUpMgLo0qa0Ug1hxiyOQRt2yXLpe/mH3pG +cozhrEDYQMOcDhYTpPwM2Bl+TsRPpxFaV4QDfiOyvUDFLMM0dyhl2pukjay/Xpp2 ++6Tsnaa+Ui0sDcM3A36Q07+E4Vugxjzfb9a36Eg4XE+Jg3jDA8UOqjeFg9gkK3aY +NaI0qQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator/truststore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/validator/truststore.jks new file mode 100644 index 00000000000..711a7b5148d Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator/truststore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator1/crl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/crl.pem new file mode 100644 index 00000000000..8ced006c911 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/crl.pem @@ -0,0 +1,27 @@ +-----BEGIN X509 CRL----- +MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCVVMxCzAJBgNV +BAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJBgNVBAoMAk1DMQ0wCwYDVQQLDARyb290 +MRMwEQYDVQQDDApwYXJ0bmVyYWNhMSYwJAYJKoZIhvcNAQkBFhdwYXJ0bmVyYWNh +QHBhcnRuZXJhLmNvbRcNMjEwNzA5MTkxMjM1WhcNMjIwNzA5MTkxMjM1WjAnMCUC +FF9rJlU9U6JdFIeK/xRojaoxHdc5Fw0yMTA3MDkxOTEyMzVaoA4wDDAKBgNVHRQE +AwIBADANBgkqhkiG9w0BAQsFAAOCAQEAfByR//FGHSsVQbaS51d59o82XocOGnnT +p1hjceqtLGv3bhiebVrsRCOB5TsvE/r2IbB/yHYTe3+LJisIUqBxblQ6xK6IM+qA +3fY646YnPT5pvdZAPZ2BCN/xP3xqGffFKapQ9cz0/36YE3vaEoUDlC2VHK0OXI0t +4CLwAmiptUT2GW4Bk1RtokAsFiUNwNIOlRX5bywUNwkG7EuitR90QSGH3l/vyii2 +0c1Fm9He9MskwipjXpJKKb+t+m1pdpOVkSjRfjmVqi4BZwWlnQjELSLywhJ+WZG2 +Z1NgRjzPXotFKK+YD97Kx1L260A1eUZ46zSq73oUZr0EDZRnNJTr6A== +-----END X509 CRL----- +-----BEGIN X509 CRL----- +MIICLDCCARQCAQEwDQYJKoZIhvcNAQELBQAwgYExCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9v +dDETMBEGA1UEAwwKcGFydG5lcmJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmJj +YUBwYXJ0bmVyYi5jb20XDTIxMDcwOTE5MTIzNVoXDTIyMDcwOTE5MTIzNVowTjAl +AhQTZhDgbKuvX7iLRUBBTiWXBPKM1xcNMjEwNzA5MTkxMjM1WjAlAhRfayZVPVOi +XRSHiv8UaI2qMR3XORcNMjEwNzA5MTkxMjM1WqAOMAwwCgYDVR0UBAMCAQEwDQYJ +KoZIhvcNAQELBQADggEBAMIltmJ036f1BmK/baISJTZTu7PKZgSZMNORnpFT8KvC +s2GNRor5bGp5qvD6LHvsx92YVppCC6xd/beCFBtdyYifqw5xtOvqLQKuqCfxruLz +EqYjKXE/3v8VdyU71J7kFqi0U0Gy4/h/YCL92e5KNbATlmcn5ToyI2EBIEfBfV08 +mm7FBXvbHRzqhfrnCNEjBWBWz3zkJMc9Rib26eCCofYIDkY2HvYSN78YgrnMmD6O +hWOXrPoxArxvmDr5rG4vCadqbQYRkkCAOP0hBeMiB0SAcO2W2LNNAmHWXX7FvU3n +ZRZUX31WoVjhNeEQtNBb2mPYBXHQzLC66qYm1p97afc= +-----END X509 CRL----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator1/keys.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/keys.p12 new file mode 100644 index 00000000000..e98020b148e Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/keys.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator1/keystore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/keystore.jks new file mode 100644 index 00000000000..2b652b862ec Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/keystore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nss.cfg new file mode 100644 index 00000000000..b908a6800f8 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nss.cfg @@ -0,0 +1,6 @@ + +name = NSScrypto-validator1 +nssSecmodDirectory = ./src/test/resources/pki-certs/validator1/nssdb +nssDbMode = readOnly +nssModule = keystore + diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nssdb/cert8.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nssdb/cert8.db new file mode 100644 index 00000000000..c9633c71418 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nssdb/cert8.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nssdb/key3.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nssdb/key3.db new file mode 100644 index 00000000000..2b98e97f3b0 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nssdb/key3.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nssdb/secmod.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nssdb/secmod.db new file mode 100644 index 00000000000..bc3748fac05 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nssdb/secmod.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator1/ssl-ca.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/ssl-ca.pem new file mode 100644 index 00000000000..61a8f5230ed --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/ssl-ca.pem @@ -0,0 +1,70 @@ +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBEwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTExNTRaGA8y +MTIxMDYxNTE5MTE1NFowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmFjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDccGhUDD8T8m6e2x13 +B0LgCDR8F2vlfAw9FN/tXOKKU3DpagJk0CAutL6YFFYs9MXg8D6bZx+w0iXUnaN/ +6rjIC1LFs79AizpEaoFWDzcVI66ItSW1Swu3ts0I1kK7EGgAMba0TDTnssfrtuPw +rOA2TOdVX03owOE+gaaPonIQlnew5+NNGhbW+P/5ix1IQXhyuNjV/uu3VEJBGNTh +cAuMGdjvglFuz4zyFon4kNRcQvghs5ztjs2h5ZNHjEo6YtNIdJuRS/XOXII9MfPN +plcwJArWTM3yEATNBtdc5FypOSI6cO/Pl+SVEf4kKmnzJQZWOSGiDXbpm938hGVw +ByZPAgMBAAGjZjBkMB0GA1UdDgQWBBQhpkZg+Ktqh6sFCjtm9HE+9bLJ3TAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAIggdc0DCxEiNaKak +/xbc7uGiGBb+UzBTjk4BmX9kEFrZf4XEaHzsptltqcQDCVtzcbFFFxMYhv/w/1g/ +WMNuUhL0mmGIGMxfoqkg50tNyuHW6aSrBXErel9WthGXAhUSzdHgkWxl3pe2wgda +qIcSwTCFgOeVWTZRdKWqKNPHirBglJHUpMgLo0qa0Ug1hxiyOQRt2yXLpe/mH3pG +cozhrEDYQMOcDhYTpPwM2Bl+TsRPpxFaV4QDfiOyvUDFLMM0dyhl2pukjay/Xpp2 ++6Tsnaa+Ui0sDcM3A36Q07+E4Vugxjzfb9a36Eg4XE+Jg3jDA8UOqjeFg9gkK3aY +NaI0qQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator1/ssl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/ssl.pem new file mode 100644 index 00000000000..696511ad10b --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/ssl.pem @@ -0,0 +1,126 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDL9plpUXsE94Ok +8bCw5GLKlh0UQEjS9UWVFpBSSxJrTuL/nCvAAVsn76XHxhgXBnbBgUHZ+eIzCKaq +jV+cIvbihF+u1uGlvQc6zDiWKv9ijQaTr0aN0ZbKvs0h40FJyEONZqNwODp4kXnU +Cptf6iIeu7xUXclUKg0WOHYGasBGxN5vx6BRHYmY6LiyBcO560gs/fLKk5nHla1j +/oxRQ47SVEdB8aDVxJJtKZC0d0a6ik69WpmnUpCLf/+zws7zYXC3sgs80uNnXDzV +iuk9ydWMKm4w2YvsCgMgzQETJu7GLFCtR1kAWPXDkpFfIicrj0J0xMyaus/VwRdl +CCV+ENSHAgMBAAECggEAXIgPqTwR93ri+l27r0StnQLlRl6zqyEi5DRMXUk5nf03 +9oa/QmhbFo8eQreYDjocfkVJvr4i5Mwz8IQasBccsj8juYo67JoJQZ+MvHPdULRy +G2YVOBmxs2FEZu9Wm0aDfw7lbu/Tdwdooc3+F1F9ETxSgGPcBpbdQQt0YAzmFjRC +b1xVIM4bC89ks5rIRcWi0dE0dMHeZG8NKryox/baTEWzb43lv2gK+vd4aQIjKsX3 +4TqqLFO4lyTv0PW4MmlHp+iEAAlS/UtSzKogVOJqain+yOeOzaVQWGASM7c/ht5Z +cdftRguBYCj31UZ/4dT1rb6OaL0Sja9AdenVhm5lQQKBgQD0/ddhyjQHF9E+99rs +xR9zh2CAXHyenflPKpHmYi7QHKZrbYB6t308oGqaSqig0Y3WWQN34LrDlb5aMJHI +WmZw+h3ejSKLdeb1Nd9GQmDIvjfMLsAWaySzP5aOFNbZB+JhUng625oV7D744HO/ +Hc+RyOG47fEPNqpBgBuwtPZfnwKBgQDVIM5Zn02P63V+utN/kxrm8JfHcq9SLNX5 +XZsun/kjY2ZK9c3Is/pxOS34pdmzv18nxcCGzMaqvELgzbVoM8ey0tPSg9WDheEC +rESUoPHSP/GpCyv00lAzJDJlvEblTRCoKdtIdF3TGc/b4GeexxGPhBI5q2Fm+3HG +l6cYypXCGQKBgE6EfF7u+zW6wGk57oQruSTBooABJD+BycFBl3kKxo4UYJHVinPK +Eu03THMesmS4RIkKBj6JW9ILT/J/1nkr3+EdiC0ndobTxq2YEnLmGza7IA7kfNOy +ixSXsJzguOrdyAQA9l+Guh+Ek7oX1YDPARNsGku2lqeVkYNkl3tOxBdpAoGAQNrt +0Dn42U3WgE0L5St3qUUXetr8XO5F4s9IVMTbhJhP3Ym1KFkUYfX7dknJ2LfolerI +bnzMC9KkK1KN3Hq9Tz52tP3nMFHCKhUP/YaIb+mDeWRr6OFDBH0EVQ8ZJ9futK2g +DAlVL9MP/KHqBlgfkOOoxCHRzwu/EKa/c3zaW6kCgYEAqdSB1tmhNOTyfZduxFUQ +W+kSHxTvXtyy88qSx9mhOqD+9Xq/liD14Y4sprplFaIBsErZaNXEPheVsEbXmdzU +PNfdu95Vqpc+gFDpsTzKHnwt0twmRqXsusQzr3ppOrs/GPdetS46ck2yrOd/r5bt +IeHhV43mdsgE4XpPLhZSWyk= +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIEvjCCA6agAwIBAgIUX2smVT1Tol0Uh4r/FGiNqjEd1zMwDQYJKoZIhvcNAQEL +BQAwgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw +CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwKcGFydG5lcmFjYTEm +MCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5jb20wIBcNMjEwNzA5 +MTkxMTU0WhgPMjEyMTA2MTUxOTExNTRaMIGBMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNVBAsMBHJvb3Qx +EzARBgNVBAMMCnZhbGlkYXRvcjExJjAkBgkqhkiG9w0BCQEWF3ZhbGlkYXRvcjFA +cGFydG5lcmEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy/aZ +aVF7BPeDpPGwsORiypYdFEBI0vVFlRaQUksSa07i/5wrwAFbJ++lx8YYFwZ2wYFB +2fniMwimqo1fnCL24oRfrtbhpb0HOsw4lir/Yo0Gk69GjdGWyr7NIeNBSchDjWaj +cDg6eJF51AqbX+oiHru8VF3JVCoNFjh2BmrARsTeb8egUR2JmOi4sgXDuetILP3y +ypOZx5WtY/6MUUOO0lRHQfGg1cSSbSmQtHdGuopOvVqZp1KQi3//s8LO82Fwt7IL +PNLjZ1w81YrpPcnVjCpuMNmL7AoDIM0BEybuxixQrUdZAFj1w5KRXyInK49CdMTM +mrrP1cEXZQglfhDUhwIDAQABo4IBKDCCASQwEQYJYIZIAYb4QgEBBAQDAgbAMB0G +A1UdDgQWBBTYucEx67wBKeANHFZjSwmx+7kSszAJBgNVHRMEAjAAMA4GA1UdDwEB +/wQEAwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwgbUGA1UdIwSB +rTCBqoAUIaZGYPiraoerBQo7ZvRxPvWyyd2hfKR6MHgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwE +cm9vdDEQMA4GA1UEAwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBh +ZG1pbi5jb22CFHAEyPzePSbGcgLskvIH1ugaaXQRMA0GCSqGSIb3DQEBCwUAA4IB +AQCo3ZgqNtVIf99TEsVOpvQQRQw0ccZCpsQSgN6vITxInYEydyg9NxGgFHVNwcSY +XpGw0r+Ghz7BS/a2AIz1PHmf0FjpkKLMJ72StaspovMLONPc4yHjMy1bUbe+7JAn +1zC8u9JyjnGX7UIA8qPnAvV+ZAI/MM5674Q3D9waQHiuToo1tV6/HlwMWQthbIy6 +iQyztsEHq+M2edWZmEOwiUk+aIgNFtpFk9gBj09RBgm93iVscmykX5vAPjxOJ8Zh +71jW0P3Q0ZTZImxZYIv7SOcseioneZBQJekdg3UDUrPQlh4WVuKY5aqVh4x2kJRG +jZI47U1/ihglkdSuDuStTS/S +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBEwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTExNTRaGA8y +MTIxMDYxNTE5MTE1NFowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmFjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmFjYUBwYXJ0bmVyYS5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDccGhUDD8T8m6e2x13 +B0LgCDR8F2vlfAw9FN/tXOKKU3DpagJk0CAutL6YFFYs9MXg8D6bZx+w0iXUnaN/ +6rjIC1LFs79AizpEaoFWDzcVI66ItSW1Swu3ts0I1kK7EGgAMba0TDTnssfrtuPw +rOA2TOdVX03owOE+gaaPonIQlnew5+NNGhbW+P/5ix1IQXhyuNjV/uu3VEJBGNTh +cAuMGdjvglFuz4zyFon4kNRcQvghs5ztjs2h5ZNHjEo6YtNIdJuRS/XOXII9MfPN +plcwJArWTM3yEATNBtdc5FypOSI6cO/Pl+SVEf4kKmnzJQZWOSGiDXbpm938hGVw +ByZPAgMBAAGjZjBkMB0GA1UdDgQWBBQhpkZg+Ktqh6sFCjtm9HE+9bLJ3TAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAIggdc0DCxEiNaKak +/xbc7uGiGBb+UzBTjk4BmX9kEFrZf4XEaHzsptltqcQDCVtzcbFFFxMYhv/w/1g/ +WMNuUhL0mmGIGMxfoqkg50tNyuHW6aSrBXErel9WthGXAhUSzdHgkWxl3pe2wgda +qIcSwTCFgOeVWTZRdKWqKNPHirBglJHUpMgLo0qa0Ug1hxiyOQRt2yXLpe/mH3pG +cozhrEDYQMOcDhYTpPwM2Bl+TsRPpxFaV4QDfiOyvUDFLMM0dyhl2pukjay/Xpp2 ++6Tsnaa+Ui0sDcM3A36Q07+E4Vugxjzfb9a36Eg4XE+Jg3jDA8UOqjeFg9gkK3aY +NaI0qQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator1/truststore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/truststore.jks new file mode 100644 index 00000000000..c6fd60f037d Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator1/truststore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator2/crl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/crl.pem new file mode 100644 index 00000000000..8ced006c911 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/crl.pem @@ -0,0 +1,27 @@ +-----BEGIN X509 CRL----- +MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCVVMxCzAJBgNV +BAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJBgNVBAoMAk1DMQ0wCwYDVQQLDARyb290 +MRMwEQYDVQQDDApwYXJ0bmVyYWNhMSYwJAYJKoZIhvcNAQkBFhdwYXJ0bmVyYWNh +QHBhcnRuZXJhLmNvbRcNMjEwNzA5MTkxMjM1WhcNMjIwNzA5MTkxMjM1WjAnMCUC +FF9rJlU9U6JdFIeK/xRojaoxHdc5Fw0yMTA3MDkxOTEyMzVaoA4wDDAKBgNVHRQE +AwIBADANBgkqhkiG9w0BAQsFAAOCAQEAfByR//FGHSsVQbaS51d59o82XocOGnnT +p1hjceqtLGv3bhiebVrsRCOB5TsvE/r2IbB/yHYTe3+LJisIUqBxblQ6xK6IM+qA +3fY646YnPT5pvdZAPZ2BCN/xP3xqGffFKapQ9cz0/36YE3vaEoUDlC2VHK0OXI0t +4CLwAmiptUT2GW4Bk1RtokAsFiUNwNIOlRX5bywUNwkG7EuitR90QSGH3l/vyii2 +0c1Fm9He9MskwipjXpJKKb+t+m1pdpOVkSjRfjmVqi4BZwWlnQjELSLywhJ+WZG2 +Z1NgRjzPXotFKK+YD97Kx1L260A1eUZ46zSq73oUZr0EDZRnNJTr6A== +-----END X509 CRL----- +-----BEGIN X509 CRL----- +MIICLDCCARQCAQEwDQYJKoZIhvcNAQELBQAwgYExCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9v +dDETMBEGA1UEAwwKcGFydG5lcmJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmJj +YUBwYXJ0bmVyYi5jb20XDTIxMDcwOTE5MTIzNVoXDTIyMDcwOTE5MTIzNVowTjAl +AhQTZhDgbKuvX7iLRUBBTiWXBPKM1xcNMjEwNzA5MTkxMjM1WjAlAhRfayZVPVOi +XRSHiv8UaI2qMR3XORcNMjEwNzA5MTkxMjM1WqAOMAwwCgYDVR0UBAMCAQEwDQYJ +KoZIhvcNAQELBQADggEBAMIltmJ036f1BmK/baISJTZTu7PKZgSZMNORnpFT8KvC +s2GNRor5bGp5qvD6LHvsx92YVppCC6xd/beCFBtdyYifqw5xtOvqLQKuqCfxruLz +EqYjKXE/3v8VdyU71J7kFqi0U0Gy4/h/YCL92e5KNbATlmcn5ToyI2EBIEfBfV08 +mm7FBXvbHRzqhfrnCNEjBWBWz3zkJMc9Rib26eCCofYIDkY2HvYSN78YgrnMmD6O +hWOXrPoxArxvmDr5rG4vCadqbQYRkkCAOP0hBeMiB0SAcO2W2LNNAmHWXX7FvU3n +ZRZUX31WoVjhNeEQtNBb2mPYBXHQzLC66qYm1p97afc= +-----END X509 CRL----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator2/keys.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/keys.p12 new file mode 100644 index 00000000000..c74b1a39873 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/keys.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator2/keystore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/keystore.jks new file mode 100644 index 00000000000..414b903e133 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/keystore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nss.cfg new file mode 100644 index 00000000000..a6725a100fe --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nss.cfg @@ -0,0 +1,6 @@ + +name = NSScrypto-validator2 +nssSecmodDirectory = ./src/test/resources/pki-certs/validator2/nssdb +nssDbMode = readOnly +nssModule = keystore + diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nssdb/cert8.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nssdb/cert8.db new file mode 100644 index 00000000000..7dd3fae7dee Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nssdb/cert8.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nssdb/key3.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nssdb/key3.db new file mode 100644 index 00000000000..3cdbd6121b4 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nssdb/key3.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nssdb/secmod.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nssdb/secmod.db new file mode 100644 index 00000000000..40f3b7e3c4d Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nssdb/secmod.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator2/ssl-ca.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/ssl-ca.pem new file mode 100644 index 00000000000..c0c4bf478f6 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/ssl-ca.pem @@ -0,0 +1,70 @@ +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBIwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTEyMTFaGA8y +MTIxMDYxNTE5MTIxMVowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmJjYUBwYXJ0bmVyYi5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNTP8IviC0X2ozlU2+ +9+mPLL9NqJKRCsEiH7XypcXkqkzCYZv/+6nNWXGLr6HsF5qXaM/YVMJYtwiaJquw +qW1CpOKxhHA1gubNt0Fzmt69/5yP6D1zxTPzAcybNMuCy8VcLJpovYHO40+2HD6I +D91/zh3jtrgKPoEXgaW3eX4+hykQWaru3P/G4PrIvPyZXnccoCdBSRCqyZSBJUko +e5ZLnCQMlkwgDONGT3MqQyUC5lqFFMzZ75pOm2reiBe6HzP3H4wK7Ldpxds9ubGk +Acb08+QzcUT7uHvENyvLm5mbf68QurFTwIDEVg2K03dgqQWbJudSzRJAmJYSszFQ +vLZdAgMBAAGjZjBkMB0GA1UdDgQWBBR5aiJ1nA1HHi0XzbRsp4V7T8eKBjAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAsmFsG3SV1fQg6kO+ +dYvFrDKNOJzTBdVYmFhg4y4H7Qt+dwQcs/ZcOCIaAFUfMUH6CWe1AAdCymfwUHxn +l/FMeJHh/+d1cybC+Wj9wtBbz7nPsWh/PXbbg3Zi8N4+a6Y0NhZAGlNn1UgMHx+E +SkSIXk63FkGT01xM2aYtfr9ABuDdoLK/YPecduiawZoRb02WwIpZFNeEE/MS7XG6 +fX9TdUrNOal8pnWUM79K+rzdlzstpCx7uFFbACUEiiIuYiqG6X+DuypfGmQnjRXB +zbc6NsQONUxg7fnJObdpV7kKTlbpREFoECkTBdqKd7AuJwYRvGaQDWK9P1IYFr1W +Cnm4Cg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator2/ssl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/ssl.pem new file mode 100644 index 00000000000..dbe6313f06c --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/ssl.pem @@ -0,0 +1,126 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDDR/V9lCYi6g49 +91p6yUVKsPmPedT4/gNS2gVOLhGrgwxNJW2cWMjv4wZG0864LxtK/gkoMR4hN4lM +BvePO73bnUBHwTmm2fAOelmoJAdLAhUkXXgbsHnok6PP7v8hgZEFMLw4+UXO+LB5 +5YbZIyNOB1FcCteac7bdVRJfswgdO5MdhlZOVcg766TMK9/8ezSthExN06exvViZ +4v/L9X5MOLmdRRPq/I1X9wCKf/fIY/FO/zJkwv2VZNhPwkW8SpiS3UevsIhxRJz6 +8zyYXfKhnUBIShDuERladJqthPkdgOp6ca0dZrTqS64MqDE7rZE6cU3xOkRLhVbd +vEbGPfTTAgMBAAECggEAXxy9RNzTdk3pgeTn/MXrKeXopyj/wgZ2N/RYgSuPD6pU +Y37HVE8qDyzT8ctX8/19nZj9fMXvlt4l0RHTob/HSR/eHxTNr6aWdXbCFFL3+mCZ +S4z64wGhXtYKA0y0lu00ZQLHqjg+9//IdJaGh1vF5ktKJTpiqKeTeVnmCRZ57UIr +j8LF8M/I1NO/ScF+CeMDHmiyecLGlFjqiEu9GtE1u9ZQNA1rmPMQ/0/nITOrmTJz +IhZK7H5xIRCdCENNuB41JGmO4Y5tMn8Bj11vJRFW+9OPF5R+lefBl2J9ZVxH3beu +yTtAdf7HDhQsVe45vHohDjkVbqEo4D2HyUShWsYiAQKBgQD8UyPPr7uqGCPXDxif +cuc7kySuWL2XbnFb8xcXsj+l6TtAod4O5ei31xcGw2hy2G8f0yGQ2U+OVKPCAXum +18rkjQNWCpPY0sRdM849bF9ZDCNrlTihD45xnPrrFdQfF5JDnPOyku7hrUs18k8R +IhPxXazJJpXmUmPJZM67z7tbMQKBgQDGIB3UGLeuuGdF/sTp9TsSHTrpAVzk1VR3 +D1PiJST3dsiCAnqnzs75agbOI8f8bdrMcWVrHUbMShuRjQWkcnRN/J9nOduCUIMr +AMTEozNfF6MQBc5nceZtvvuCGqD2TUg/bmoC3yp4q0SGIx4ZufhYUhmQ65FQvrGX +rvrNkPLHQwKBgC9IgSh1HOyl82lkic+vX4d5bmFBfd23s4RwjD5Dh8vWZeUZsBwI +l1CD/OumiJck2cYT8XFMV60rTTiYwIwmWf30MtDX0JbMAEIa6CX4ffGY5bZOUztT +R/UgXqDZCVP+PclvyvcGs78Uk0h7rLdgNG6BiFR1Z5eujsZ5nofxSIGxAoGBAJdA +jYUOGaxZOv5EsS+q952skvyu/av08La0DOXoVYBWPlyCaAET8Q6X0vosdtBPTWom +Z7aOcy4ipUlIz7Xrar7ezRKRKPMjY//AZnd34BAIi4P/6sMuQSwnUPrSOW/PMAi8 +0lG+7T2SAo4k4SXiw6UpiDsKm7V43ztdajrlHXLhAoGAXTpF0AGnc5uje11Y1Tvi +zhu3NIXfZYzbtPR8UOxCDmUvwwKiW5DkLBe6rSx2DnVuGdS6ntQLq0Us1Tamo6mW +CNhOZmJyU9kzz/XfHFzkWaen92Cq41w7Hd0oziF1T8W0UqLSk42Xq8qERorRoqlg +1rV/3EvT/wSYmTdTdPsdcsk= +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIEvjCCA6agAwIBAgIUE2YQ4Gyrr1+4i0VAQU4llwTyjNQwDQYJKoZIhvcNAQEL +BQAwgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw +CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwKcGFydG5lcmJjYTEm +MCQGCSqGSIb3DQEJARYXcGFydG5lcmJjYUBwYXJ0bmVyYi5jb20wIBcNMjEwNzA5 +MTkxMjExWhgPMjEyMTA2MTUxOTEyMTFaMIGBMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNVBAsMBHJvb3Qx +EzARBgNVBAMMCnZhbGlkYXRvcjIxJjAkBgkqhkiG9w0BCQEWF3ZhbGlkYXRvcjJA +cGFydG5lcmIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw0f1 +fZQmIuoOPfdaeslFSrD5j3nU+P4DUtoFTi4Rq4MMTSVtnFjI7+MGRtPOuC8bSv4J +KDEeITeJTAb3jzu9251AR8E5ptnwDnpZqCQHSwIVJF14G7B56JOjz+7/IYGRBTC8 +OPlFzviweeWG2SMjTgdRXArXmnO23VUSX7MIHTuTHYZWTlXIO+ukzCvf/Hs0rYRM +TdOnsb1YmeL/y/V+TDi5nUUT6vyNV/cAin/3yGPxTv8yZML9lWTYT8JFvEqYkt1H +r7CIcUSc+vM8mF3yoZ1ASEoQ7hEZWnSarYT5HYDqenGtHWa06kuuDKgxO62ROnFN +8TpES4VW3bxGxj300wIDAQABo4IBKDCCASQwEQYJYIZIAYb4QgEBBAQDAgbAMB0G +A1UdDgQWBBRvD8e/IWuuGwe8ErupvKv8q5mbcTAJBgNVHRMEAjAAMA4GA1UdDwEB +/wQEAwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwgbUGA1UdIwSB +rTCBqoAUeWoidZwNRx4tF820bKeFe0/HigahfKR6MHgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwE +cm9vdDEQMA4GA1UEAwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBh +ZG1pbi5jb22CFHAEyPzePSbGcgLskvIH1ugaaXQSMA0GCSqGSIb3DQEBCwUAA4IB +AQBOM0aMjtCa34n3o4MRUkGOSgcw8bhnKmJSHIjBKvhkiroPVJbXHC72UZTJ/yiO +/C1rrIrWES4iosAEE+qhqFqRxyHiLlrLrnRqIbNchaNVQch2Q2IZOY0vwSIv+0Vh +cnHMWGOPtMwvWRZdM7eXIiB0bjvXnvCk1erI00UjTeuXMxtQkKe5l3CVl7QYU/ns +WbihGXkt4Gzp2vtUhUVcpZOahhlAMTCxkeArrFTCi2zyX9beR2oFqqD4U78QmvSD +pSGonPFj7YxgbDx63LXvvcCRkQqVfK3SnqAlI1LkPnV0zVNxNOBol/5Fr7oZec5q +VkVF2lVfOUIwg6OXsNS21mzR +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBIwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTEyMTFaGA8y +MTIxMDYxNTE5MTIxMVowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmJjYUBwYXJ0bmVyYi5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNTP8IviC0X2ozlU2+ +9+mPLL9NqJKRCsEiH7XypcXkqkzCYZv/+6nNWXGLr6HsF5qXaM/YVMJYtwiaJquw +qW1CpOKxhHA1gubNt0Fzmt69/5yP6D1zxTPzAcybNMuCy8VcLJpovYHO40+2HD6I +D91/zh3jtrgKPoEXgaW3eX4+hykQWaru3P/G4PrIvPyZXnccoCdBSRCqyZSBJUko +e5ZLnCQMlkwgDONGT3MqQyUC5lqFFMzZ75pOm2reiBe6HzP3H4wK7Ldpxds9ubGk +Acb08+QzcUT7uHvENyvLm5mbf68QurFTwIDEVg2K03dgqQWbJudSzRJAmJYSszFQ +vLZdAgMBAAGjZjBkMB0GA1UdDgQWBBR5aiJ1nA1HHi0XzbRsp4V7T8eKBjAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAsmFsG3SV1fQg6kO+ +dYvFrDKNOJzTBdVYmFhg4y4H7Qt+dwQcs/ZcOCIaAFUfMUH6CWe1AAdCymfwUHxn +l/FMeJHh/+d1cybC+Wj9wtBbz7nPsWh/PXbbg3Zi8N4+a6Y0NhZAGlNn1UgMHx+E +SkSIXk63FkGT01xM2aYtfr9ABuDdoLK/YPecduiawZoRb02WwIpZFNeEE/MS7XG6 +fX9TdUrNOal8pnWUM79K+rzdlzstpCx7uFFbACUEiiIuYiqG6X+DuypfGmQnjRXB +zbc6NsQONUxg7fnJObdpV7kKTlbpREFoECkTBdqKd7AuJwYRvGaQDWK9P1IYFr1W +Cnm4Cg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator2/truststore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/truststore.jks new file mode 100644 index 00000000000..fb45ce73051 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator2/truststore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator3/crl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/crl.pem new file mode 100644 index 00000000000..8ced006c911 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/crl.pem @@ -0,0 +1,27 @@ +-----BEGIN X509 CRL----- +MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCVVMxCzAJBgNV +BAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJBgNVBAoMAk1DMQ0wCwYDVQQLDARyb290 +MRMwEQYDVQQDDApwYXJ0bmVyYWNhMSYwJAYJKoZIhvcNAQkBFhdwYXJ0bmVyYWNh +QHBhcnRuZXJhLmNvbRcNMjEwNzA5MTkxMjM1WhcNMjIwNzA5MTkxMjM1WjAnMCUC +FF9rJlU9U6JdFIeK/xRojaoxHdc5Fw0yMTA3MDkxOTEyMzVaoA4wDDAKBgNVHRQE +AwIBADANBgkqhkiG9w0BAQsFAAOCAQEAfByR//FGHSsVQbaS51d59o82XocOGnnT +p1hjceqtLGv3bhiebVrsRCOB5TsvE/r2IbB/yHYTe3+LJisIUqBxblQ6xK6IM+qA +3fY646YnPT5pvdZAPZ2BCN/xP3xqGffFKapQ9cz0/36YE3vaEoUDlC2VHK0OXI0t +4CLwAmiptUT2GW4Bk1RtokAsFiUNwNIOlRX5bywUNwkG7EuitR90QSGH3l/vyii2 +0c1Fm9He9MskwipjXpJKKb+t+m1pdpOVkSjRfjmVqi4BZwWlnQjELSLywhJ+WZG2 +Z1NgRjzPXotFKK+YD97Kx1L260A1eUZ46zSq73oUZr0EDZRnNJTr6A== +-----END X509 CRL----- +-----BEGIN X509 CRL----- +MIICLDCCARQCAQEwDQYJKoZIhvcNAQELBQAwgYExCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9v +dDETMBEGA1UEAwwKcGFydG5lcmJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmJj +YUBwYXJ0bmVyYi5jb20XDTIxMDcwOTE5MTIzNVoXDTIyMDcwOTE5MTIzNVowTjAl +AhQTZhDgbKuvX7iLRUBBTiWXBPKM1xcNMjEwNzA5MTkxMjM1WjAlAhRfayZVPVOi +XRSHiv8UaI2qMR3XORcNMjEwNzA5MTkxMjM1WqAOMAwwCgYDVR0UBAMCAQEwDQYJ +KoZIhvcNAQELBQADggEBAMIltmJ036f1BmK/baISJTZTu7PKZgSZMNORnpFT8KvC +s2GNRor5bGp5qvD6LHvsx92YVppCC6xd/beCFBtdyYifqw5xtOvqLQKuqCfxruLz +EqYjKXE/3v8VdyU71J7kFqi0U0Gy4/h/YCL92e5KNbATlmcn5ToyI2EBIEfBfV08 +mm7FBXvbHRzqhfrnCNEjBWBWz3zkJMc9Rib26eCCofYIDkY2HvYSN78YgrnMmD6O +hWOXrPoxArxvmDr5rG4vCadqbQYRkkCAOP0hBeMiB0SAcO2W2LNNAmHWXX7FvU3n +ZRZUX31WoVjhNeEQtNBb2mPYBXHQzLC66qYm1p97afc= +-----END X509 CRL----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator3/keys.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/keys.p12 new file mode 100644 index 00000000000..b36ede08e5a Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/keys.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator3/keystore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/keystore.jks new file mode 100644 index 00000000000..228bb46ce74 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/keystore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nss.cfg new file mode 100644 index 00000000000..d2c68dae6c4 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nss.cfg @@ -0,0 +1,6 @@ + +name = NSScrypto-validator3 +nssSecmodDirectory = ./src/test/resources/pki-certs/validator3/nssdb +nssDbMode = readOnly +nssModule = keystore + diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nssdb/cert8.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nssdb/cert8.db new file mode 100644 index 00000000000..cbfa00c240b Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nssdb/cert8.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nssdb/key3.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nssdb/key3.db new file mode 100644 index 00000000000..6414460a69c Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nssdb/key3.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nssdb/secmod.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nssdb/secmod.db new file mode 100644 index 00000000000..75bd6e3d96d Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nssdb/secmod.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator3/ssl-ca.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/ssl-ca.pem new file mode 100644 index 00000000000..a5fdc343f56 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/ssl-ca.pem @@ -0,0 +1,70 @@ +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBMwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTEyMThaGA8y +MTIxMDYxNTE5MTIxOFowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmNjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmNjYUBwYXJ0bmVyYy5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+31Xz+vdtagGGF4Zs +JPzLNkPRWUZ2aB2nB6O3GFFItRERIeKQQ809jpuWb+3nPwmHgAeu/5KDuHExXUp3 +zsq/pBhjmIxysN/tSB0ZWgnDZj0T/O1cFxmFPSIQi2YqN9ex/k1P0A/bPLYid6sp +BrMB2oDuemjG9OL8zwWxTWFstwMZgh+PUoLv4xPt3vnv8hiBvMxIRe2IjseFRvR9 +zoaxAW94oeLPngPgWanUZvU+hL0BR2h0RZbsmPciw4K7PzHKCfOnDcJN3/k32GuQ +1ETYXVqBZstMwZ/yUAZzHDUFuungfM/VyuVVqjV1Njmi1ulrZNaLj3pe+x0WwrXq +VbgfAgMBAAGjZjBkMB0GA1UdDgQWBBRoOd/JgcA/UZW816OxlkI45xhLJDAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAbIUXWJ1SU2cwnGfJ +gor9Y3QX8q3bLRBQ6nuVXUhyHtOKnecEYY+6cvTgAy4tcaEbTrmXnIwwddzWXR5c +IEgpem6t9tJqjvDZ3SMmlIf57L/rKp1rQQXmOBm2fBy86zC6RChYMshf9LQ3pCeZ +kESZ+WzHqmTDe2vpe3AaZTsGy+HucyVv5Ha5WLATFMPSMbY76sMbFDEr8viskCNm +JzDvYbqHMfZUJu4eiWiRJ8v6GY1HJ8SJrFUz2ry6WNYiizoEABHC8VrWV+Kss1Vq +MiFfAZND4wBS5TZmaKi4BQt/+cnUAX0ej6wYSug/+Atz9DSu/b+AsEZ5tXnxDMGO +vqwj8g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator3/ssl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/ssl.pem new file mode 100644 index 00000000000..474187b0e21 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/ssl.pem @@ -0,0 +1,126 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDW0t2JaCSa2iXy +7Njgdb7vpTBUxYV44tueVscVtVEAKbe9HN0iOro3cmHymmujuxmqXJA4bHK8OqeX +fsWoyhnK17aRXhRGUNHcd7OTLSsmWgLsTCQ3syfYrC1G8Dbgggdw7gp/KXDfHRLc +WZY/1H2JSH0QJwTyiNPE1Jhz7Dw2YHlTE5iOC95g02ABXI7LLiB1DvTkjwkBT9bk +Bcokx8OgX/aUScV4OJsMcog+zf2bic/lcU/SI/wPSu95EGmLB/0PER8TOCbp+GTk +Q1CiIkL1ZSjW6JtRwGhPoc3JGhKED5P+y1t6LHdE3wBbX37AfcPJqd4vMErlkn98 +1spNvckHAgMBAAECggEBALhlG5/ccr8wzS4tuyNALnqJsmixexX+tEC/f/fUQQkA +xiRf6Dh/bGQ3nHefsRFDgo5HEcw82mdTeZOCT6vIfkcszhsNRB3vNZQmc0+7j7RF +wwiNevEMqQFFGUAw5Qnk0vpOeVgZfDcnP49AnsV/YZo7TI5Wz9pXNF9ZlNq8Rhrt +NYTF92vzWfrCskQnYL2Tn29qUTWIvsqq6wt7oR0NKwTfbm4420ZGbpAKgtVWsnXN +13nRhAgB7aNEAAXn9FsRjn/aVaOLWv8rfL7AnWx/DREMOBOKNUIW7mkT4xwNFrnl +kVS4mjnMRVtMG+/xK781E9voJ+2GYXiCE3ldEY1ZhDECgYEA9I7ej9ZWYLwnf6jS +IsRDWLwqLsy5upHv88zeqGTNR/kiO8On5+GMaFT93II53TQk+gLBTdmUYR1jYdq+ +raR9nOSVjV35kE747NZIhqRGkMCJg3qLLF7haK5bvynAD60dIpme6IiDEKLjgPmr +k2CQo0rPIASed+vXpdYVYGVsaMUCgYEA4N/cLv/Mi59tAdFNUaxyIAVgFD++bG1r +RkJmhYcCqj563kIRhqd+YtWhtedeBMTrmMBztd/1p1qjUmnB/drhvl60J+4WoULR +1YSA1hLOz25iGTBEPJH05115hD4OC7o2R88NdC4TYizIqzSbyuYIw3kTLGDzO9b9 +wYaR4+TdD1sCgYEAo8a985O1uwimZw6200OeWmGA2mCODQzIpfvQLPN8qjOEooNw +AZEBx6kLbU3k1GekT63iqHEKtlLJCHJGeeELojNOmCKUC/lnKKyEW27ONwhJzzwU +0f0kdUc29/lMvvLO7Sn1yoIJS+3Z77jEF2l203Q465dMTMErZMrO/ARQKoUCgYBW +n0T0wcpsGjxmT9al2HSZyxhIlIlowPlqthdB5lDrfWfdB7wyj4CK19oT9Qztb2GF +lNS9wYiiL7LsAxscC12b9GUXYIpNEi08P29VhyctFkspgsM2Rc799K7jdvf4IoHY +RXTcRQdocPHXqUs97ECB87ikBrCLY3SaQJkgHT/eMwKBgGRqRCW3J+DHaGYVrfFh +jTtVnMAw+eNMrfEzbueav8XYFDA035lHANMaW1ImCEnGcNxTKTNHYlEI+GJGlf3j +nLyFxHt2t7t3EH+Z1TRBpTWcI9NIBA9suGSwHF6JSYYoP/XycknvHR3CKnptVqEh +2BvRskmyqDqlJ3or8iilBVG4 +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIEvjCCA6agAwIBAgIUeHwvCYkMzLzluPyGlFa5V/lmFnowDQYJKoZIhvcNAQEL +BQAwgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw +CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwKcGFydG5lcmNjYTEm +MCQGCSqGSIb3DQEJARYXcGFydG5lcmNjYUBwYXJ0bmVyYy5jb20wIBcNMjEwNzA5 +MTkxMjE4WhgPMjEyMTA2MTUxOTEyMThaMIGBMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNVBAsMBHJvb3Qx +EzARBgNVBAMMCnZhbGlkYXRvcjMxJjAkBgkqhkiG9w0BCQEWF3ZhbGlkYXRvcjNA +cGFydG5lcmMuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1tLd +iWgkmtol8uzY4HW+76UwVMWFeOLbnlbHFbVRACm3vRzdIjq6N3Jh8ppro7sZqlyQ +OGxyvDqnl37FqMoZyte2kV4URlDR3Hezky0rJloC7EwkN7Mn2KwtRvA24IIHcO4K +fylw3x0S3FmWP9R9iUh9ECcE8ojTxNSYc+w8NmB5UxOYjgveYNNgAVyOyy4gdQ70 +5I8JAU/W5AXKJMfDoF/2lEnFeDibDHKIPs39m4nP5XFP0iP8D0rveRBpiwf9DxEf +Ezgm6fhk5ENQoiJC9WUo1uibUcBoT6HNyRoShA+T/stbeix3RN8AW19+wH3Dyane +LzBK5ZJ/fNbKTb3JBwIDAQABo4IBKDCCASQwEQYJYIZIAYb4QgEBBAQDAgbAMB0G +A1UdDgQWBBSl7BsGlNKcg8bg/9K/Pt6beFmUbDAJBgNVHRMEAjAAMA4GA1UdDwEB +/wQEAwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwgbUGA1UdIwSB +rTCBqoAUaDnfyYHAP1GVvNejsZZCOOcYSyShfKR6MHgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwE +cm9vdDEQMA4GA1UEAwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBh +ZG1pbi5jb22CFHAEyPzePSbGcgLskvIH1ugaaXQTMA0GCSqGSIb3DQEBCwUAA4IB +AQAM49KuL0GR6f9O6bS8YkPNcNcOP3y5AbGzV08boCHcnL0iJmSyUoYwD4ksEj+Z +41YcBOGtPE++MR27LvpMXV6wMoJvmg4G97M1Oql+fs+eZnKyWRuQSWoCLUpsh5Cq +j9QUHv95xUyadH3HSQnDHd2Khhsu60MEqF6wuyU+EsjoNp5Ejsmk0DDWobXPwA8K +WaqyleZOjA52HeRwAeextO9Zvv4yJX/I/DeGf3LTPz8IAE0rLXROpEj31rX0CeKA +BPiBVVn0qRTeimjm9G22AUwKKBNCta2plMkbq2shHAKTXWzI72aW6kHHG35zdXWV +qnQZrcVShlqsexiZAGRfKqsb +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBMwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTEyMThaGA8y +MTIxMDYxNTE5MTIxOFowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmNjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmNjYUBwYXJ0bmVyYy5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+31Xz+vdtagGGF4Zs +JPzLNkPRWUZ2aB2nB6O3GFFItRERIeKQQ809jpuWb+3nPwmHgAeu/5KDuHExXUp3 +zsq/pBhjmIxysN/tSB0ZWgnDZj0T/O1cFxmFPSIQi2YqN9ex/k1P0A/bPLYid6sp +BrMB2oDuemjG9OL8zwWxTWFstwMZgh+PUoLv4xPt3vnv8hiBvMxIRe2IjseFRvR9 +zoaxAW94oeLPngPgWanUZvU+hL0BR2h0RZbsmPciw4K7PzHKCfOnDcJN3/k32GuQ +1ETYXVqBZstMwZ/yUAZzHDUFuungfM/VyuVVqjV1Njmi1ulrZNaLj3pe+x0WwrXq +VbgfAgMBAAGjZjBkMB0GA1UdDgQWBBRoOd/JgcA/UZW816OxlkI45xhLJDAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAbIUXWJ1SU2cwnGfJ +gor9Y3QX8q3bLRBQ6nuVXUhyHtOKnecEYY+6cvTgAy4tcaEbTrmXnIwwddzWXR5c +IEgpem6t9tJqjvDZ3SMmlIf57L/rKp1rQQXmOBm2fBy86zC6RChYMshf9LQ3pCeZ +kESZ+WzHqmTDe2vpe3AaZTsGy+HucyVv5Ha5WLATFMPSMbY76sMbFDEr8viskCNm +JzDvYbqHMfZUJu4eiWiRJ8v6GY1HJ8SJrFUz2ry6WNYiizoEABHC8VrWV+Kss1Vq +MiFfAZND4wBS5TZmaKi4BQt/+cnUAX0ej6wYSug/+Atz9DSu/b+AsEZ5tXnxDMGO +vqwj8g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator3/truststore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/truststore.jks new file mode 100644 index 00000000000..7acd9015b86 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator3/truststore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator4/crl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/crl.pem new file mode 100644 index 00000000000..8ced006c911 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/crl.pem @@ -0,0 +1,27 @@ +-----BEGIN X509 CRL----- +MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCVVMxCzAJBgNV +BAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJBgNVBAoMAk1DMQ0wCwYDVQQLDARyb290 +MRMwEQYDVQQDDApwYXJ0bmVyYWNhMSYwJAYJKoZIhvcNAQkBFhdwYXJ0bmVyYWNh +QHBhcnRuZXJhLmNvbRcNMjEwNzA5MTkxMjM1WhcNMjIwNzA5MTkxMjM1WjAnMCUC +FF9rJlU9U6JdFIeK/xRojaoxHdc5Fw0yMTA3MDkxOTEyMzVaoA4wDDAKBgNVHRQE +AwIBADANBgkqhkiG9w0BAQsFAAOCAQEAfByR//FGHSsVQbaS51d59o82XocOGnnT +p1hjceqtLGv3bhiebVrsRCOB5TsvE/r2IbB/yHYTe3+LJisIUqBxblQ6xK6IM+qA +3fY646YnPT5pvdZAPZ2BCN/xP3xqGffFKapQ9cz0/36YE3vaEoUDlC2VHK0OXI0t +4CLwAmiptUT2GW4Bk1RtokAsFiUNwNIOlRX5bywUNwkG7EuitR90QSGH3l/vyii2 +0c1Fm9He9MskwipjXpJKKb+t+m1pdpOVkSjRfjmVqi4BZwWlnQjELSLywhJ+WZG2 +Z1NgRjzPXotFKK+YD97Kx1L260A1eUZ46zSq73oUZr0EDZRnNJTr6A== +-----END X509 CRL----- +-----BEGIN X509 CRL----- +MIICLDCCARQCAQEwDQYJKoZIhvcNAQELBQAwgYExCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9v +dDETMBEGA1UEAwwKcGFydG5lcmJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmJj +YUBwYXJ0bmVyYi5jb20XDTIxMDcwOTE5MTIzNVoXDTIyMDcwOTE5MTIzNVowTjAl +AhQTZhDgbKuvX7iLRUBBTiWXBPKM1xcNMjEwNzA5MTkxMjM1WjAlAhRfayZVPVOi +XRSHiv8UaI2qMR3XORcNMjEwNzA5MTkxMjM1WqAOMAwwCgYDVR0UBAMCAQEwDQYJ +KoZIhvcNAQELBQADggEBAMIltmJ036f1BmK/baISJTZTu7PKZgSZMNORnpFT8KvC +s2GNRor5bGp5qvD6LHvsx92YVppCC6xd/beCFBtdyYifqw5xtOvqLQKuqCfxruLz +EqYjKXE/3v8VdyU71J7kFqi0U0Gy4/h/YCL92e5KNbATlmcn5ToyI2EBIEfBfV08 +mm7FBXvbHRzqhfrnCNEjBWBWz3zkJMc9Rib26eCCofYIDkY2HvYSN78YgrnMmD6O +hWOXrPoxArxvmDr5rG4vCadqbQYRkkCAOP0hBeMiB0SAcO2W2LNNAmHWXX7FvU3n +ZRZUX31WoVjhNeEQtNBb2mPYBXHQzLC66qYm1p97afc= +-----END X509 CRL----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator4/keys.p12 b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/keys.p12 new file mode 100644 index 00000000000..70373b93084 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/keys.p12 differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator4/keystore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/keystore.jks new file mode 100644 index 00000000000..ef941f664e3 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/keystore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nss.cfg b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nss.cfg new file mode 100644 index 00000000000..c114f78b09d --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nss.cfg @@ -0,0 +1,6 @@ + +name = NSScrypto-validator4 +nssSecmodDirectory = ./src/test/resources/pki-certs/validator4/nssdb +nssDbMode = readOnly +nssModule = keystore + diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nssdb/cert8.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nssdb/cert8.db new file mode 100644 index 00000000000..7c94b589ac7 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nssdb/cert8.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nssdb/key3.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nssdb/key3.db new file mode 100644 index 00000000000..0b60173dbf9 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nssdb/key3.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nssdb/secmod.db b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nssdb/secmod.db new file mode 100644 index 00000000000..346dc33e691 Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nssdb/secmod.db differ diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nsspin.txt b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nsspin.txt new file mode 100644 index 00000000000..5271a526801 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/nsspin.txt @@ -0,0 +1 @@ +test123 diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator4/ssl-ca.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/ssl-ca.pem new file mode 100644 index 00000000000..8a3ea186f1c --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/ssl-ca.pem @@ -0,0 +1,70 @@ +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBQwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTEyMjRaGA8y +MTIxMDYxNTE5MTIyNFowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmRjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmRjYUBwYXJ0bmVyZC5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbWjqued8UEhetS67V +pNCkbCBjdeSXyjZgEIxMqmPILY6oymkClkty1ktxMYkEKcDi44+oCq93MIQOAkHx +qRGlu+z9Eql/aEJzVu85gIfa+64/GJ5OgGIqfI0XOaETu1MGhZN3P7Kb38tmqX7l +ppP/lfADvdlA/C+SY21Y2OMmeXo8VUtrW5YcUZ2OHt6esFZHCanI7FGYi7A71l/R +3ZXX1BVvHYJlssY5GwBLT3Yng6sshMihhXviU4f+RBEUm1pSRG/P+0RSjQVyp3bW +EiwXHu0WD9j7Kjgesrz7J2mFTgjNEQQ6lQioN6ZCrboM6WbxWM2zzSWCPSV/ON1W +QUVTAgMBAAGjZjBkMB0GA1UdDgQWBBRdtro7rYf1BatcNzBHlkpYj4sW7jAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAJd86d928wxKO8C6+ +VksOT7G2RcYNk9ok90bcAJdj6zAhEM4h5XZPomHYibKvdmGD1IH2TlzX+P4+Z2tc +mHOkpHCa99vwGlIeb+objfR5fYrZDPlFMfYdzeesXhlmZ5j9bzxMUEAMGVCZOm99 +Gq+uHoj1+bPaLkyaFfETchhlXw6EYXoM5bkdXGZMnXvL3DWWvPauA53tUiRh++Q7 +bPCSbmT9YooVbjqyT2IGzIWXzU0O6u5H4PHMNs+DCiGcoTqvC9uZDcU0l+4g6UV7 +v83YnAhDr+Ed/WJ8EpfvbxmNFu5d/SCmmzJnv2sBn27//q4xUNxV9OaNkbxzVOwd +cQyzwQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator4/ssl.pem b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/ssl.pem new file mode 100644 index 00000000000..75a6df9ec29 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/ssl.pem @@ -0,0 +1,126 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4R9B0DJ8/0ZNm +0dOt8wv86NvtIXFggiIol5YhOeCP2uHNDZd+B5IfigMHJKNVW5lB0pxgltSM8T8v +R8zIUV1KcBkdbG0LXd6RBu8T7MtuGpIYkPG+PNXp6VNWG5e6+3IdtFp6tsg+ht6K +qgzp4n5ILjibZRQpSPSn37vw6D2v/HHH9MXOUIraMenB+RixTM+5F/eArNOrKxtn +DEXPMTA0kb5LGQsRm4S7new8opAIGaCXtGnhFgZYvmD/GlZQmYgPVw/IaRjHy69D +6/6ogtoKwrdGJoI36IUB6Obvz/VVxl1BZ0H05PPb0warAH2gmeAIYgHQs3lMjyLw +Qy04dBIhAgMBAAECggEBAIBNV8AErbekNclnm8bHqngKtFyUZTi5QgkbCWbWwhfG +YGIA7ZHMuZsF3vfRNXsPjFO8zC2fthrvOHu1tMlfhOF3zLSksgMw9u3ocvpfan+d +NkyuVfGKr7DtR51zFqATwy8VS82WhzKpejX3EYihriSZMcZXiML5zYU4C8U+HPzy +Sq0SCbpMd+3yXHu3RKJKDXtvXwF+6Iu3Pcgir7zAP8kRqpnnb/Ve3qyzkXtZhhHg +ka2+1EfEFw8YoI/VKe81Y1hS+Ra2A+a/iYgDnqpD0C1Aa2/1Yf5zBP7oXlrQyOP/ +N9Of6yOgWWQixcl+26cnJ65JN1NlyBmZc3SJTDkMvsUCgYEA4SeeyCBNOl0ehOfw +DkifuVUetFW8BsCq2TjvLoWYAK2Atc90tNfvN7z/f5Mw47s7THLoFxyhGLMnXa9W +FSkg4baSwUrHlUyMC4bQ1BK6tsfv+zbc5xoGQr1B256wZPQ4Ab5RrJ8NgnrPqAgq +CnfDiFph1YoFG93QUmeBl+5WY0MCgYEA0YaymqLi4+a5joab67SNyEdjoPVq0RBz +jyozVOHiJCL2SMaWGpTcZieDHgaq4uBrkD81mRR+XEjBWIgxT+QK+phapHHjOy5A +8f2Knr0+Pb9n5t7+Xq0V1siDZkGDokkJqOGa83nUeY/ZMju8czoOj3CMwEEb/C8q +Gm4DMX0TdMsCgYAcyG3Z85cr0N+n6eacTNhuXt1P/G3PBy5QGqEo91cZLxT3KRAo +Vjp0i6q16mEjm7nW6hGVcsl9WNm9dj6w8dMMR8S3BRJCmciFaLSlh8dqumCJYtgW +ixMl0P/sTXsLTNUkE+ppAOQ/O+fz+Sc2s1zBv5wmKkDA8ThCcIz2mTdd9QKBgBNd +WJp0HXYkt9eVV0nEiSoOdwXESNgDpjqAEvhwW/8tAAgf2nWgdnI2iqa2xQps5WQS +g3ifbUJIMx5kj/IrSFx6wj3ajL7Gepgi77HWGa+JRigPSgEkDBWquII14d2Y1Hy4 +RSLlip6ljdRXswYPQpM9OrT2D4kSLtj8e+0R+z9bAoGBAIvnrMlmScUlshKO8Z9Y +x7Xxmtwsagv/TYuaJcizTzUOZ5VcHTrZXd9oAzmaITmw0VxOsb2wbm7OvIsV/iqr +0GmAeWBMl00dHnvqLSH1fO59THpYxBuH612OIGMdJ3qYguqzSTrRPN3C1ivTH2U8 +qy4tgRxhH9uSfnZ+H6RfL5Ph +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIEvjCCA6agAwIBAgIUBBRpdaDIsULA/tPnSkiiUQ2MPqgwDQYJKoZIhvcNAQEL +BQAwgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw +CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwKcGFydG5lcmRjYTEm +MCQGCSqGSIb3DQEJARYXcGFydG5lcmRjYUBwYXJ0bmVyZC5jb20wIBcNMjEwNzA5 +MTkxMjI1WhgPMjEyMTA2MTUxOTEyMjVaMIGBMQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNVBAsMBHJvb3Qx +EzARBgNVBAMMCnZhbGlkYXRvcjQxJjAkBgkqhkiG9w0BCQEWF3ZhbGlkYXRvcjRA +cGFydG5lcmQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuEfQ +dAyfP9GTZtHTrfML/Ojb7SFxYIIiKJeWITngj9rhzQ2XfgeSH4oDBySjVVuZQdKc +YJbUjPE/L0fMyFFdSnAZHWxtC13ekQbvE+zLbhqSGJDxvjzV6elTVhuXuvtyHbRa +erbIPobeiqoM6eJ+SC44m2UUKUj0p9+78Og9r/xxx/TFzlCK2jHpwfkYsUzPuRf3 +gKzTqysbZwxFzzEwNJG+SxkLEZuEu53sPKKQCBmgl7Rp4RYGWL5g/xpWUJmID1cP +yGkYx8uvQ+v+qILaCsK3RiaCN+iFAejm78/1VcZdQWdB9OTz29MGqwB9oJngCGIB +0LN5TI8i8EMtOHQSIQIDAQABo4IBKDCCASQwEQYJYIZIAYb4QgEBBAQDAgbAMB0G +A1UdDgQWBBTiYWgjfuJswsCgAvS4hMukchm0/TAJBgNVHRMEAjAAMA4GA1UdDwEB +/wQEAwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwgbUGA1UdIwSB +rTCBqoAUXba6O62H9QWrXDcwR5ZKWI+LFu6hfKR6MHgxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwE +cm9vdDEQMA4GA1UEAwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBh +ZG1pbi5jb22CFHAEyPzePSbGcgLskvIH1ugaaXQUMA0GCSqGSIb3DQEBCwUAA4IB +AQB0yQiERMtzUId9mShNX/h09rI74S1e2YNNppGXaDv+ZAKoutYDaP/V1LLnQJ7a +aChpGIW4O66d2I0y5On8SbNTIxXhfJhqQd/vWPGEozekFw2+gaH6D3rqghQUNT4V +6gV7WRRCn5TgXZ7wDfWQua7/H1A7B+Axg19n5if9wUo3bvvwrk2q9vFj0D/jGTVd +LLoROx5dif+urxwPouwpe11rJouuolSRlkxC9kaFvWpR1ELLfrYG0fj6tFUSUNuw +p+lNisyoifUgHlzARnNCXCilAo4yq9dcYXHeY+0uB1pY1Na/xiue21GUTAVtpr4a +QvnaWDse4YykkozutA/iETLW +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID8DCCAtigAwIBAgIUcATI/N49JsZyAuyS8gfW6BppdBQwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ +KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA3MDkxOTEyMjRaGA8y +MTIxMDYxNTE5MTIyNFowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG +A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK +cGFydG5lcmRjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcmRjYUBwYXJ0bmVyZC5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbWjqued8UEhetS67V +pNCkbCBjdeSXyjZgEIxMqmPILY6oymkClkty1ktxMYkEKcDi44+oCq93MIQOAkHx +qRGlu+z9Eql/aEJzVu85gIfa+64/GJ5OgGIqfI0XOaETu1MGhZN3P7Kb38tmqX7l +ppP/lfADvdlA/C+SY21Y2OMmeXo8VUtrW5YcUZ2OHt6esFZHCanI7FGYi7A71l/R +3ZXX1BVvHYJlssY5GwBLT3Yng6sshMihhXviU4f+RBEUm1pSRG/P+0RSjQVyp3bW +EiwXHu0WD9j7Kjgesrz7J2mFTgjNEQQ6lQioN6ZCrboM6WbxWM2zzSWCPSV/ON1W +QUVTAgMBAAGjZjBkMB0GA1UdDgQWBBRdtro7rYf1BatcNzBHlkpYj4sW7jAfBgNV +HSMEGDAWgBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjASBgNVHRMBAf8ECDAGAQH/AgEA +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAJd86d928wxKO8C6+ +VksOT7G2RcYNk9ok90bcAJdj6zAhEM4h5XZPomHYibKvdmGD1IH2TlzX+P4+Z2tc +mHOkpHCa99vwGlIeb+objfR5fYrZDPlFMfYdzeesXhlmZ5j9bzxMUEAMGVCZOm99 +Gq+uHoj1+bPaLkyaFfETchhlXw6EYXoM5bkdXGZMnXvL3DWWvPauA53tUiRh++Q7 +bPCSbmT9YooVbjqyT2IGzIWXzU0O6u5H4PHMNs+DCiGcoTqvC9uZDcU0l+4g6UV7 +v83YnAhDr+Ed/WJ8EpfvbxmNFu5d/SCmmzJnv2sBn27//q4xUNxV9OaNkbxzVOwd +cQyzwQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIUYdazVD+VnI7jBu7xLaW+npfwHJIwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE +AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ8QgVwEjy3CgJFvET7tYNBw97 +4i33EHQT4ZuayGCJ+ADY3ZFpsw2M1IPlbAguqfBkcLd8TAjWNRAdsm9ubGlIcTZr +7LNle3gvc7qEP4qg0i6M7D06CDqtBaIJ1PMTJchOouGU9ntBe+h0qg8tzpiqJdIw +jIOPRWW98Hw9KgF6++2jtlcOW1IxiFSWqf0Mpc81qKukcxnsHjvdxmBp/Z1vL42E +m5xNOGXoxpjq8NygSuVDhQ/bZUnmHLmvv9MXe9Ob52rlzea/YafLpOeNGSA1aCxm +Fx0lcoXWp4xpoyJn9St7vmH3t7quBKdqt54zwcuHjhgZPSR6RikodKHtsl8TAgMB +AAGjZjBkMB0GA1UdDgQWBBTdAXu8aBbvkvxYD5Ss9/Ml5VgohjAfBgNVHSMEGDAW +gBSMsBNO3UGBteMZOTq5fDPG2aPx8DASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEA0hJCtrCI9Mf47+y3pvsTjiaT +TZwpNE0cdxHjpcCHJWX2jmGbqqA6wvQ7yy4PFarmnFOoW3hQFeiLgpz9X86YTRzF +8dj3Q2MKXf6i6/iW+Y96GFqurshKp7wV25wfzWwLXcVCiM1xYPWYSyGsZAGotu4M +c7uolVABjJu5nci9mBxVmaYV5oT1mxrvq3dCPm2AvmVFNWPNRbMSAuT5B7FUDvWG +xvd1aDFduqL0iLAcrTifMIYI3XL4pBSIlL78dgY45WL6616EF3mHhW/Y4k4PNq1I +Fz08Q3y99ilhzeAci1jv6KBVHiALZNFFtYjd10KX95qnF9SomBjCTPsQ9PTC5g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2zCCAsOgAwIBAgIUdxRGMrv1ONRI/dJXUHa3isjVXuwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ +BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x +HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNzA5MTkxMTU0 +WhgPMjEyMTA2MTUxOTExNTRaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM +MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE +AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Bqlx+ngRZfWjktX6urJ +Tpg2//n3uMW8Gp55SVq+lbpkNXuA3W0uTlom/2fsnzmMmBAJUvv/NaLcFSN++0/d +fYGVhogxjlRoyaXa4sdFPg2ocM+lCHLGhWpYuVdTWPknikTOVNbh9z94SLRfrP8N +kuxGNZNktnVm+QJmrCLmjvnPvQlcP/WqFYehFM26NaRzswOhLLRU1YK8aVlh9Vto +PGSTPtZK60XwTfyCj/zEvHqpbGbKJPp7W0rpxl7ehPQIzGQt5IMH3zKrqLm4/pt+ +XFEVqy724sstthS73bvXguWxBLOzuMze8CbI6SJpcHaH8HO5pfFMPyE5N5l2x9Co +uQIDAQABo1MwUTAdBgNVHQ4EFgQUjLATTt1BgbXjGTk6uXwzxtmj8fAwHwYDVR0j +BBgwFoAUjLATTt1BgbXjGTk6uXwzxtmj8fAwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAQEAL9/7YtxIbuTt7dgH1KOMb/y6P3Qb79fTVZTx073E2ZBj +OfSuMGUhKC30LWQXCQEsY4WpugJ4cS0NsArSYsO5XWguqgjYlWL6poOmYhGvj7ou +oi44oYqcPm6EbvLrAKdI67bkbSPLzgs+6TrxTyXHzPKFBqGBnuHaFKjgb4hGiPmd +JWKrh3fbTtuLjqSHd0Gey2uBNFql4LhPutdsCUhSOD3BibAeTbXyln70AgpTCoWT +9Qr9Ux6HYIiAHSDBzzuN8EcrlnAm9RO4zRyUVwxDsHoNsOUwybn50IM66p83HuiY +h/iX5uNjaFAADfRR4rQOwb6MLreVH2XYUSiz4M/ijg== +-----END CERTIFICATE----- diff --git a/acceptance-tests/tests/src/test/resources/pki-certs/validator4/truststore.jks b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/truststore.jks new file mode 100644 index 00000000000..0128950f21c Binary files /dev/null and b/acceptance-tests/tests/src/test/resources/pki-certs/validator4/truststore.jks differ diff --git a/acceptance-tests/tests/src/test/resources/qbft/qbft-emptyextradata.json b/acceptance-tests/tests/src/test/resources/qbft/qbft-emptyextradata.json new file mode 100644 index 00000000000..ada399d0ebc --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/qbft/qbft-emptyextradata.json @@ -0,0 +1,39 @@ +{ + "config": { + "chainid": 2017, + "byzantiumBlock": 0, + "qbft": { + "blockperiodseconds": 1, + "epochlength": 30000, + "requesttimeoutseconds": 5, + "blockreward": "5000000000000000000" + } + }, + "nonce": "0x0", + "timestamp": "0x0", + "extraData": "0xe5a00000000000000000000000000000000000000000000000000000000000000000c0c080c0", + "gasLimit": "0x29b92700", + "difficulty": "0x1", + "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "fe3b557e8fb62b89f4916b721be55ceb828dbd73": { + "privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "0xad78ebc5ac6200000" + }, + "627306090abaB3A6e1400e9345bC60c78a8BEf57": { + "privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "90000000000000000000000" + }, + "f17f52151EbEF6C7334FAD080c5704D77216b732": { + "privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "90000000000000000000000" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" +} diff --git a/acceptance-tests/tests/src/test/resources/qbft/qbft.json b/acceptance-tests/tests/src/test/resources/qbft/qbft.json new file mode 100644 index 00000000000..b614538b60f --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/qbft/qbft.json @@ -0,0 +1,39 @@ +{ + "config": { + "chainId": 4, + "berlinBlock": 0, + "qbft": { + "blockperiodseconds": 1, + "epochlength": 30000, + "requesttimeoutseconds": 5, + "blockreward": "5000000000000000000" + } + }, + "nonce": "0x0", + "timestamp": "0x58ee40ba", + "extraData": "%extraData%", + "gasLimit": "0x47b760", + "difficulty": "0x1", + "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "fe3b557e8fb62b89f4916b721be55ceb828dbd73": { + "privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "0xad78ebc5ac6200000" + }, + "627306090abaB3A6e1400e9345bC60c78a8BEf57": { + "privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "90000000000000000000000" + }, + "f17f52151EbEF6C7334FAD080c5704D77216b732": { + "privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "90000000000000000000000" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" +} diff --git a/benchmark/caliper-benchmarks/.keep b/benchmark/caliper-benchmarks/.keep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/benchmark/config/besu-keystore/key b/benchmark/config/besu-keystore/key new file mode 100644 index 00000000000..ec25faa230c --- /dev/null +++ b/benchmark/config/besu-keystore/key @@ -0,0 +1 @@ +0xa67bee5d6fb43acd42e307eb67547ab5006ad2fbb9567829e9b4b2ef3580acea diff --git a/benchmark/config/caliper-benchconfig-offchain.yaml b/benchmark/config/caliper-benchconfig-offchain.yaml new file mode 100644 index 00000000000..b8fa2f00f8d --- /dev/null +++ b/benchmark/config/caliper-benchconfig-offchain.yaml @@ -0,0 +1,69 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +--- + test: + name: Simple Storage + description: Test private transactions + workers: + type: local + number: 1 + rounds: + - label: warm-up (ignore results) + txDuration: 10 + rateControl: + type: fixed-load + opts: + startingTps: 200 + transactionLoad: 200 + workload: + module: /config/store.js + arguments: + contract: private_storage_offchain + private: legacy_group + - label: legacy private transaction (run 1) + txDuration: 10 + rateControl: + type: fixed-load + opts: + startingTps: 200 + transactionLoad: 200 + workload: + module: /config/store.js + arguments: + contract: private_storage_offchain + private: legacy_group + - label: public transaction (run 2) + txDuration: 10 + rateControl: + type: fixed-load + opts: + startingTps: 200 + transactionLoad: 200 + workload: + module: /config/store.js + arguments: + contract: public_storage + - label: legacy private transaction (run 2) + txDuration: 10 + rateControl: + type: fixed-load + opts: + startingTps: 200 + transactionLoad: 200 + workload: + module: /config/store.js + arguments: + contract: private_storage_offchain + private: legacy_group diff --git a/benchmark/config/caliper-benchconfig-onchain.yaml b/benchmark/config/caliper-benchconfig-onchain.yaml new file mode 100644 index 00000000000..ea307f689ba --- /dev/null +++ b/benchmark/config/caliper-benchconfig-onchain.yaml @@ -0,0 +1,80 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +--- + test: + name: Simple Storage + description: Test private transactions + workers: + type: local + number: 1 + rounds: + - label: warm-up (ignore results) + txDuration: 10 + rateControl: + type: fixed-load + opts: + startingTps: 200 + transactionLoad: 200 + workload: + module: /config/store.js + arguments: + contract: private_storage_onchain + private: onchain_group + - label: public transaction (run 1) + txDuration: 10 + rateControl: + type: fixed-load + opts: + startingTps: 200 + transactionLoad: 200 + workload: + module: /config/store.js + arguments: + contract: public_storage + - label: onchain private transaction (run 1) + txDuration: 10 + rateControl: + type: fixed-load + opts: + startingTps: 200 + transactionLoad: 200 + workload: + module: /config/store.js + arguments: + contract: private_storage_onchain + private: onchain_group + - label: public transaction (run 2) + txDuration: 10 + rateControl: + type: fixed-load + opts: + startingTps: 200 + transactionLoad: 200 + workload: + module: /config/store.js + arguments: + contract: public_storage + - label: onchain private transaction (run 2) + txDuration: 10 + rateControl: + type: fixed-load + opts: + startingTps: 200 + transactionLoad: 200 + workload: + module: /config/store.js + arguments: + contract: private_storage_onchain + private: onchain_group diff --git a/benchmark/config/caliper-networkconfig-offchain.json b/benchmark/config/caliper-networkconfig-offchain.json new file mode 100644 index 00000000000..c0d15ba3feb --- /dev/null +++ b/benchmark/config/caliper-networkconfig-offchain.json @@ -0,0 +1,35 @@ +{ + "caliper": { + "blockchain": "ethereum" + }, + "ethereum": { + "url": "ws://besu:8546", + "contractDeployerAddress": "0xD1cf9D73a91DE6630c2bb068Ba5fDdF9F0DEac09", + "contractDeployerAddressPrivateKey": "0x797c13f7235c627f6bd013dc17fff4c12213ab49abcf091f77c83f16db10e90b", + "fromAddressSeed": "0x3f841bf589fdf83a521e55d51afddc34fa65351161eead24f064855fc29c9580", + "transactionConfirmationBlocks": 1, + "chainId": 48122, + "privacy": { + "legacy_group": { + "groupType": "legacy", + "privateFrom": "GGilEkXLaQ9yhhtbpBT03Me9iYa7U/mWXxrJhnbl1XY=", + "privateFor": ["GGilEkXLaQ9yhhtbpBT03Me9iYa7U/mWXxrJhnbl1XY="] + } + }, + "contracts": { + "public_storage": { + "path": "/config/storage.json", + "gas": { + "update": 30000 + } + }, + "private_storage_offchain": { + "path": "/config/storage.json", + "gas": { + "update": 30000 + }, + "private": "legacy_group" + } + } + } +} diff --git a/benchmark/config/caliper-networkconfig-onchain.json b/benchmark/config/caliper-networkconfig-onchain.json new file mode 100644 index 00000000000..98076790096 --- /dev/null +++ b/benchmark/config/caliper-networkconfig-onchain.json @@ -0,0 +1,35 @@ +{ + "caliper": { + "blockchain": "ethereum" + }, + "ethereum": { + "url": "ws://besu:8546", + "contractDeployerAddress": "0xD1cf9D73a91DE6630c2bb068Ba5fDdF9F0DEac09", + "contractDeployerAddressPrivateKey": "0x797c13f7235c627f6bd013dc17fff4c12213ab49abcf091f77c83f16db10e90b", + "fromAddressSeed": "0x3f841bf589fdf83a521e55d51afddc34fa65351161eead24f064855fc29c9580", + "transactionConfirmationBlocks": 1, + "chainId": 48122, + "privacy": { + "onchain_group": { + "groupType": "onchain", + "privateFrom": "GGilEkXLaQ9yhhtbpBT03Me9iYa7U/mWXxrJhnbl1XY=", + "privateKey": "uTJGpd4ZEEtDPFSZM0+GT11xn5NFIr2KGP2Q4SdVPRM=" + } + }, + "contracts": { + "public_storage": { + "path": "/config/storage.json", + "gas": { + "update": 30000 + } + }, + "private_storage_onchain": { + "path": "/config/storage.json", + "gas": { + "update": 30000 + }, + "private": "onchain_group" + } + } + } +} diff --git a/benchmark/config/caliper-offchain.yaml b/benchmark/config/caliper-offchain.yaml new file mode 100644 index 00000000000..b31252bc102 --- /dev/null +++ b/benchmark/config/caliper-offchain.yaml @@ -0,0 +1,31 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +caliper: + report: + path: 'report-offchain.html' + benchconfig: caliper-benchconfig.yaml + networkconfig: caliper-networkconfig.json + txupdatetime: 500 + workspace: ./ + logging: + targets: + console: + target: console + enabled: true + options: + level: info + file: + target: file + enabled: false diff --git a/benchmark/config/caliper-onchain.yaml b/benchmark/config/caliper-onchain.yaml new file mode 100644 index 00000000000..dc35d7dcdda --- /dev/null +++ b/benchmark/config/caliper-onchain.yaml @@ -0,0 +1,49 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +caliper: + report: + path: 'report-onchain.html' + benchconfig: caliper-benchconfig.yaml + networkconfig: caliper-networkconfig.json + txupdatetime: 500 + workspace: ./ + logging: + template: '%timestamp%%level%%module%%message%%metadata%' + formats: + timestamp: 'YYYY.MM.DD-HH:mm:ss.SSS ZZ' + label: false + json: false + pad: true + align: false + attributeformat: + level: ' %attribute%' + module: ' [%attribute%] ' + metadata: ' (%attribute%)' + colorize: + all: true + colors: + info: green + error: red + warn: yellow + debug: grey + targets: + console: + target: console + enabled: true + options: + level: info + file: + target: file + enabled: false diff --git a/benchmark/config/genesis.json b/benchmark/config/genesis.json new file mode 100644 index 00000000000..ad32e929e46 --- /dev/null +++ b/benchmark/config/genesis.json @@ -0,0 +1,75 @@ +{ + "config": { + "chainId": 48122, + "berlinblock": 0, + "clique": { + "blockperiodseconds": 1, + "epoch": 30000 + } + }, + "nonce": "0x0", + "timestamp": "0x5ca916c6", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000c0A8e4D217eB85b812aeb1226fAb6F588943C2C20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x47b760", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0xc0A8e4D217eB85b812aeb1226fAb6F588943C2C2", + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "alloc": { + "0xc0A8e4D217eB85b812aeb1226fAb6F588943C2C2": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, + "0xD1cf9D73a91DE6630c2bb068Ba5fDdF9F0DEac09": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000", + "privatekey": "0x797c13f7235c627f6bd013dc17fff4c12213ab49abcf091f77c83f16db10e90b", + "derivation": "m/44'/60'/0'/0/0" + }, + "0xd826E703658FA2CE8D1018D42E637C08d9846A17": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000", + "privatekey": "0x4be84b298ccb944e96befc4f03b943ec13709f6a8e5b5d8595c486dfa88fd254", + "derivation": "m/44'/60'/1'/0/0" + }, + "0x247DdfA00415710E0416f8c103b5E6428782C916": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000", + "privatekey": "0xaa682edca26f3e17889d69276e6c6a4fcf1594af97e48f4dc3ac6dbb29e7924b", + "derivation": "m/44'/60'/2'/0/0" + }, + "0x500a8704F86C0d9126Dfb949fDC4dc248c228fB4": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000", + "privatekey": "0x45d09c64e4973b16422b31d5e4a1fbf57ae8fd25037566af8bc1d046022d754b", + "derivation": "m/44'/60'/3'/0/0" + }, + "0x32d9ad8F398995fFF658E74430749d65E0ee6702": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000", + "privatekey": "0x2f51f2d881e0a6f7f249139a2afe8da084424616d08aa0ce9fb1c960b49f022f", + "derivation": "m/44'/60'/4'/0/0" + }, + "0xd32d3f6dA1664C4ee7acae64fEC3661cEa6ee448": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000", + "privatekey": "0x87abeb4c0230ca6fdf42f7d2cb2baa510856e42f039ab7670b13845e45dc3245", + "derivation": "m/44'/60'/5'/0/0" + }, + "0x5F6C5F2431CE84f2Fa84deB6B27A1764DB6feB1a": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000", + "privatekey": "0x5f0ad910e681553c9407582f620d9560541fa8b8c4d03e9e2e3caed5eea6a220", + "derivation": "m/44'/60'/6'/0/0" + }, + "0x9fCDe74bf5465D5C32a09f158047803a061B3C1B": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000", + "privatekey": "0x76930906e95c96a9be735b0f182184424f450feca5ea71bf743a8c47ea6e2635", + "derivation": "m/44'/60'/7'/0/0" + }, + "0xb582703c0a0e2b598f9362A5e5c17Ab6865b0342": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000", + "privatekey": "0x32e90654e141cb4f92dd9fccef100778c112636b20b9017a9ae56be9a8c2c648", + "derivation": "m/44'/60'/8'/0/0" + }, + "0x179740E29B1E7b2C61F6004b8d5caD575D6eaa88": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000", + "privatekey": "0x028bf0ee2807cf9a8d22db99f12aea783a2e6b4897c9ddb7557e33291c7d35c5", + "derivation": "m/44'/60'/9'/0/0" + } + } +} diff --git a/benchmark/config/storage.json b/benchmark/config/storage.json new file mode 100644 index 00000000000..646d67460ac --- /dev/null +++ b/benchmark/config/storage.json @@ -0,0 +1,37 @@ +{ + "name": "storage", + "abi": [ + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "update", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "value", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b5060c38061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80633fa4f24514603757806382ab890a146053575b600080fd5b603d607e565b6040518082815260200191505060405180910390f35b607c60048036036020811015606757600080fd5b81019080803590602001909291905050506084565b005b60005481565b806000819055505056fea265627a7a72315820e8496d56b71870b96edb4d71a4fd8101b771c4c269eb0d8ee8c27c6085fa76fc64736f6c63430005110032", + "gas": 3000000 +} \ No newline at end of file diff --git a/benchmark/config/store.js b/benchmark/config/store.js new file mode 100644 index 00000000000..454ae0b81a8 --- /dev/null +++ b/benchmark/config/store.js @@ -0,0 +1,109 @@ +/* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +const { WorkloadModuleBase } = require('@hyperledger/caliper-core'); +const Web3 = require('web3'); + +class StoreWorkload extends WorkloadModuleBase { + + /** + * Initializes the parameters of the workload. + */ + constructor() { + super(); + this.txIndex = -1; + this.private = false; + this.contract = {}; + } + + /** + * Generates simple workload. + * @returns {{verb: String, args: Object[]}[]} Array of workload argument objects. + */ + _generateWorkload() { + let web3 = new Web3(this.nodeUrl); + + let workload = []; + for(let i= 0; i < this.roundArguments.txnPerBatch; i++) { + this.txIndex++; + + let value = i; + + let args = { + contract: this.roundArguments.contract, + verb: 'update', + args: [value], + readOnly: false, + } + + if (this.isPrivate) { + args.privacy = this.privacyOpts; + args.privacy.sender = web3.eth.accounts.create(); + args.privacy.sender.nonce = 0; + } + + workload.push(args); + } + + return workload; + } + + /** + * Initialize the workload module with the given parameters. + * @param {number} workerIndex The 0-based index of the worker instantiating the workload module. + * @param {number} totalWorkers The total number of workers participating in the round. + * @param {number} roundIndex The 0-based index of the currently executing round. + * @param {Object} roundArguments The user-provided arguments for the round from the benchmark configuration file. + * @param {BlockchainConnector} sutAdapter The adapter of the underlying SUT. + * @param {Object} sutContext The custom context object provided by the SUT adapter. + * @async + */ + async initializeWorkloadModule(workerIndex, totalWorkers, roundIndex, roundArguments, sutAdapter, sutContext) { + await super.initializeWorkloadModule(workerIndex, totalWorkers, roundIndex, roundArguments, sutAdapter, sutContext); + + if (!this.roundArguments.contract) { + throw new Error('store - argument "contract" missing'); + } + + this.nodeUrl = sutContext.url; + + if(this.roundArguments.private) { + this.isPrivate = true; + this.privacyOpts = sutContext.privacy[this.roundArguments.private]; + this.privacyOpts['id'] = this.roundArguments.private; + } else { + this.isPrivate = false; + } + + if(!this.roundArguments.txnPerBatch) { + this.roundArguments.txnPerBatch = 1; + } + } + + /** + * Assemble TXs for opening new accounts. + */ + async submitTransaction() { + let args = this._generateWorkload(); + await this.sutAdapter.sendRequests(args); + } +} + +function createWorkloadModule() { + return new StoreWorkload(); +} + +module.exports.createWorkloadModule = createWorkloadModule; \ No newline at end of file diff --git a/benchmark/config/tessera/config.json b/benchmark/config/tessera/config.json new file mode 100644 index 00000000000..0901b5f37b9 --- /dev/null +++ b/benchmark/config/tessera/config.json @@ -0,0 +1,48 @@ +{ + "mode": "orion", + "useWhiteList": false, + "jdbc": { + "username": "sa", + "password": "", + "url": "jdbc:h2:/data/tm/db;MODE=Oracle;TRACE_LEVEL_SYSTEM_OUT=0", + "autoCreateTables": true + }, + "serverConfigs": [ + { + "app": "ThirdParty", + "serverAddress": "http://tessera:9080", + "communicationType": "REST" + }, + { + "app": "Q2T", + "serverAddress": "http://tessera:9101", + "sslConfig": { + "tls": "OFF" + }, + "communicationType": "REST" + }, + { + "app": "P2P", + "serverAddress": "http://tessera:9000", + "sslConfig": { + "tls": "OFF" + }, + "communicationType": "REST" + } + ], + "peer": [ + { + "url": "http://tessera:9000" + } + ], + "keys": { + "passwords": [], + "keyData": [ + { + "config": {"data":{"bytes":"uTJGpd4ZEEtDPFSZM0+GT11xn5NFIr2KGP2Q4SdVPRM="},"type":"unlocked"}, + "publicKey": "GGilEkXLaQ9yhhtbpBT03Me9iYa7U/mWXxrJhnbl1XY=" + } + ] + }, + "alwaysSendTo": [] +} diff --git a/benchmark/docker-compose.yml b/benchmark/docker-compose.yml new file mode 100644 index 00000000000..a62afa7b151 --- /dev/null +++ b/benchmark/docker-compose.yml @@ -0,0 +1,109 @@ +version: '2' + +x-besu: + &besu + container_name: besu + image: "hyperledger/besu:develop" + cpuset: 4-5 + environment: + - NODE_INGRESS_CONTRACT_ADDRESS=0x0000000000000000000000000000000000009999 + - ACCOUNT_INGRESS_CONTRACT_ADDRESS=0x0000000000000000000000000000000000008888 + - BESU_NODE_PERM_ACCOUNT=D1cf9D73a91DE6630c2bb068Ba5fDdF9F0DEac09 + - BESU_NODE_PERM_KEY=797c13f7235c627f6bd013dc17fff4c12213ab49abcf091f77c83f16db10e90b + - CHAIN_ID=48122 + volumes: + - ./config:/config:ro + +x-caliper: + &caliper + container_name: caliper + # TODO: this image is build using the custom branch + # https://github.com/taccatisid/caliper/tree/besu-performance-benchmark-container. Once + # all the changes of this branch are merged into the caliper main + # branch, we should use the official caliper image here. + image: "taccatisid/caliper" + cpuset: 0-3 + entrypoint: caliper launch manager + volumes: + - ./config:/config:ro + - ./caliper-benchmarks:/hyperledger/caliper/workspace + +services: + caliper-offchain: + << : *caliper + environment: + - CALIPER_PROJECTCONFIG=/config/caliper-offchain.yaml + - CALIPER_BIND_SUT=besu:latest + - CALIPER_BENCHCONFIG=/config/caliper-benchconfig-offchain.yaml + - CALIPER_NETWORKCONFIG=/config/caliper-networkconfig-offchain.json + depends_on: + besu-offchain: + condition: service_started + tessera: + condition: service_healthy + + caliper-onchain: + << : *caliper + environment: + - CALIPER_PROJECTCONFIG=/config/caliper-onchain.yaml + - CALIPER_BIND_SUT=besu:latest + - CALIPER_BENCHCONFIG=/config/caliper-benchconfig-onchain.yaml + - CALIPER_NETWORKCONFIG=/config/caliper-networkconfig-onchain.json + depends_on: + besu-onchain: + condition: service_started + tessera: + condition: service_healthy + + besu-offchain: + << : *besu + entrypoint: + - /opt/besu/bin/besu + - --genesis-file=/config/genesis.json + - --node-private-key-file=/config/besu-keystore/key + - --min-gas-price=0 + - --revert-reason-enabled + - --rpc-ws-enabled + - --rpc-ws-apis=admin,eth,miner,web3,net,priv,eea + - --rpc-ws-host=0.0.0.0 + - --host-whitelist=* + - --graphql-http-enabled + - --discovery-enabled=false + - --privacy-enabled=true + - --privacy-url=http://tessera:9101 + - --privacy-public-key-file=/config/orion/key/orion.pub + + besu-onchain: + << : *besu + entrypoint: + - /opt/besu/bin/besu + - --genesis-file=/config/genesis.json + - --node-private-key-file=/config/besu-keystore/key + - --min-gas-price=0 + - --revert-reason-enabled + - --rpc-ws-enabled + - --rpc-ws-apis=admin,eth,miner,web3,net,priv,eea + - --rpc-ws-host=0.0.0.0 + - --host-whitelist=* + - --graphql-http-enabled + - --discovery-enabled=false + - --privacy-enabled=true + - --privacy-url=http://tessera:9101 + - --privacy-public-key-file=/config/orion/key/orion.pub + - --privacy-flexible-groups-enabled + tessera: + container_name: tessera + image: quorumengineering/tessera:latest + healthcheck: + test: ["CMD", "wget", "--spider", "--proxy", "off", "http://localhost:9000/upcheck"] + interval: 1s + timeout: 1s + retries: 10 + volumes: + - ./config/tessera:/config:ro + entrypoint: + - /bin/sh + - -c + - | + mkdir -p /data/tm/; + /tessera/bin/tessera -configfile /config/config.json diff --git a/besu/build.gradle b/besu/build.gradle index 936fce81d82..969571b565c 100644 --- a/besu/build.gradle +++ b/besu/build.gradle @@ -28,12 +28,17 @@ jar { } dependencies { + api 'org.slf4j:slf4j-api' + implementation project(':config') + implementation project(':pki') implementation project(':consensus:clique') implementation project(':consensus:common') implementation project(':consensus:ibft') - implementation project(':consensus:ibftlegacy') - implementation project(':crypto') + implementation project(':consensus:merge') + implementation project(':consensus:qbft') + implementation project(':crypto:services') + implementation project(':datatypes') implementation project(':enclave') implementation project(':ethereum:api') implementation project(':ethereum:blockcreation') @@ -46,63 +51,57 @@ dependencies { implementation project(':ethereum:trie') implementation project(':ethereum:stratum') implementation project(':ethereum:ethstats') + implementation project(':evm') implementation project(':metrics:core') implementation project(':nat') implementation project(':plugin-api') implementation project(':plugins:rocksdb') implementation project(':services:kvstore') + implementation project(':util') implementation 'com.fasterxml.jackson.core:jackson-databind' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8' + implementation 'com.github.oshi:oshi-core' implementation 'com.google.guava:guava' + implementation 'com.google.dagger:dagger' implementation 'com.graphql-java:graphql-java' implementation 'info.picocli:picocli' implementation 'io.vertx:vertx-core' implementation 'io.vertx:vertx-web' - implementation 'org.apache.logging.log4j:log4j-api' + implementation 'org.apache.commons:commons-lang3' implementation 'org.apache.logging.log4j:log4j-core' - implementation 'org.apache.tuweni:bytes' - implementation 'org.apache.tuweni:config' - implementation 'org.apache.tuweni:toml' - implementation 'org.apache.tuweni:units' + implementation 'org.apache.tuweni:tuweni-bytes' + implementation 'org.apache.tuweni:tuweni-config' + implementation 'org.apache.tuweni:tuweni-toml' + implementation 'org.apache.tuweni:tuweni-units' implementation 'org.springframework.security:spring-security-crypto' implementation 'org.xerial.snappy:snappy-java' + implementation 'tech.pegasys:jc-kzg-4844' - - runtimeOnly 'org.apache.logging.log4j:log4j-slf4j-impl' runtimeOnly 'org.apache.logging.log4j:log4j-jul' runtimeOnly 'com.splunk.logging:splunk-library-javalogging' runtimeOnly 'org.fusesource.jansi:jansi' // for color logging in windows testImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts') - testImplementation project(path: ':crypto', configuration: 'testSupportArtifacts') + testImplementation project(path: ':crypto:services', configuration: 'testSupportArtifacts') testImplementation project(':testutil') testImplementation 'com.google.auto.service:auto-service' testImplementation 'com.squareup.okhttp3:okhttp' + testImplementation 'commons-io:commons-io' + testImplementation 'io.opentelemetry:opentelemetry-api' testImplementation 'junit:junit' testImplementation 'org.apache.commons:commons-text' - testImplementation 'org.apache.tuweni:bytes' - testImplementation 'org.apache.tuweni:units' + testImplementation 'org.apache.tuweni:tuweni-bytes' + testImplementation 'org.apache.tuweni:tuweni-units' testImplementation 'org.assertj:assertj-core' testImplementation 'org.awaitility:awaitility' + testImplementation 'org.junit.jupiter:junit-jupiter' testImplementation 'org.mockito:mockito-core' -} + testImplementation 'org.mockito:mockito-junit-jupiter' + testImplementation 'org.testcontainers:testcontainers' + testImplementation 'tech.pegasys.discovery:discovery' -task testJar(type: Jar) { - archiveFileName = 'testPlugins.jar' - manifest { - attributes( - 'Specification-Title': archiveBaseName, - 'Specification-Version': project.version, - 'Implementation-Title': archiveBaseName, - 'Implementation-Version': calculateVersion() - ) - } - archiveClassifier = 'tests' - from sourceSets.test.output + testRuntimeOnly 'org.junit.vintage:junit-vintage-engine' + annotationProcessor 'com.google.dagger:dagger-compiler' } - -configurations { testArtifacts } - -artifacts { testArtifacts testJar } diff --git a/besu/src/main/java/org/hyperledger/besu/Besu.java b/besu/src/main/java/org/hyperledger/besu/Besu.java index 4760b2cc745..6bdd87d0cff 100644 --- a/besu/src/main/java/org/hyperledger/besu/Besu.java +++ b/besu/src/main/java/org/hyperledger/besu/Besu.java @@ -1,5 +1,5 @@ /* - * Copyright ConsenSys AG. + * Copyright Hyperledger Besu Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at @@ -14,48 +14,50 @@ */ package org.hyperledger.besu; -import static org.apache.logging.log4j.LogManager.getLogger; - -import org.hyperledger.besu.chainexport.RlpBlockExporter; -import org.hyperledger.besu.chainimport.JsonBlockImporter; -import org.hyperledger.besu.chainimport.RlpBlockImporter; import org.hyperledger.besu.cli.BesuCommand; import org.hyperledger.besu.cli.logging.BesuLoggingConfigurationFactory; -import org.hyperledger.besu.controller.BesuController; -import org.hyperledger.besu.services.BesuPluginContextImpl; +import org.hyperledger.besu.components.DaggerBesuComponent; import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.Log4J2LoggerFactory; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import picocli.CommandLine.RunLast; +/** Besu bootstrap class. */ public final class Besu { - private static final int SUCCESS_EXIT_CODE = 0; - private static final int ERROR_EXIT_CODE = 1; + /** + * The main entrypoint to Besu application + * + * @param args command line arguments. + */ public static void main(final String... args) { - final Logger logger = setupLogging(); - - final BesuCommand besuCommand = - new BesuCommand( - logger, - RlpBlockImporter::new, - JsonBlockImporter::new, - RlpBlockExporter::new, - new RunnerBuilder(), - new BesuController.Builder(), - new BesuPluginContextImpl(), - System.getenv()); + setupLogging(); + final BesuCommand besuCommand = DaggerBesuComponent.create().getBesuCommand(); + int exitCode = + besuCommand.parse( + new RunLast(), + besuCommand.parameterExceptionHandler(), + besuCommand.executionExceptionHandler(), + System.in, + args); - besuCommand.parse( - new RunLast().andExit(SUCCESS_EXIT_CODE), - besuCommand.exceptionHandler().andExit(ERROR_EXIT_CODE), - System.in, - args); + System.exit(exitCode); } - private static Logger setupLogging() { - InternalLoggerFactory.setDefaultFactory(Log4J2LoggerFactory.INSTANCE); + /** + * a Logger setup for handling any exceptions during the bootstrap process, to indicate to users + * their CLI configuration had problems. + */ + public static void setupLogging() { + try { + InternalLoggerFactory.setDefaultFactory(Log4J2LoggerFactory.INSTANCE); + } catch (Throwable t) { + System.out.printf( + "Could not set netty log4j logger factory: %s - %s%n", + t.getClass().getSimpleName(), t.getMessage()); + } try { System.setProperty( "vertx.logger-delegate-factory-class-name", @@ -63,21 +65,31 @@ private static Logger setupLogging() { System.setProperty( "log4j.configurationFactory", BesuLoggingConfigurationFactory.class.getName()); System.setProperty("log4j.skipJansi", String.valueOf(false)); - } catch (SecurityException e) { - System.out.println( - "Could not set logging system property as the security manager prevented it:" - + e.getMessage()); + } catch (Throwable t) { + System.out.printf( + "Could not set logging system property: %s - %s%n", + t.getClass().getSimpleName(), t.getMessage()); } - final Logger logger = getLogger(); - Thread.setDefaultUncaughtExceptionHandler(log4jExceptionHandler(logger)); - Thread.currentThread().setUncaughtExceptionHandler(log4jExceptionHandler(logger)); + } + + /** + * Returns the first logger to be created. This is used to set the default uncaught exception + * + * @return Logger + */ + public static Logger getFirstLogger() { + final Logger logger = LoggerFactory.getLogger(Besu.class); + Thread.setDefaultUncaughtExceptionHandler(slf4jExceptionHandler(logger)); + Thread.currentThread().setUncaughtExceptionHandler(slf4jExceptionHandler(logger)); return logger; } - private static Thread.UncaughtExceptionHandler log4jExceptionHandler(final Logger logger) { - return (thread, error) -> - logger.error( - () -> String.format("Uncaught exception in thread \"%s\"", thread.getName()), error); + private static Thread.UncaughtExceptionHandler slf4jExceptionHandler(final Logger logger) { + return (thread, error) -> { + if (logger.isErrorEnabled()) { + logger.error(String.format("Uncaught exception in thread \"%s\"", thread.getName()), error); + } + }; } } diff --git a/besu/src/main/java/org/hyperledger/besu/BesuInfo.java b/besu/src/main/java/org/hyperledger/besu/BesuInfo.java index 7c664ad2832..54447a59600 100644 --- a/besu/src/main/java/org/hyperledger/besu/BesuInfo.java +++ b/besu/src/main/java/org/hyperledger/besu/BesuInfo.java @@ -18,6 +18,10 @@ import java.util.Optional; +/** + * Represent Besu information such as version, OS etc. Used with --version option and during Besu + * start. + */ public final class BesuInfo { private static final String CLIENT = "besu"; private static final String VERSION = BesuInfo.class.getPackage().getImplementationVersion(); @@ -26,10 +30,31 @@ public final class BesuInfo { private BesuInfo() {} + /** + * Generate version-only Besu version + * + * @return Besu version in format such as "v23.1.0" or "v23.1.1-dev-ac23d311" + */ + public static String shortVersion() { + return VERSION; + } + + /** + * Generate full Besu version + * + * @return Besu version in format such as "besu/v23.1.1-dev-ac23d311/osx-x86_64/graalvm-java-17" + * or "besu/v23.1.0/osx-aarch_64/corretto-java-19" + */ public static String version() { return String.format("%s/v%s/%s/%s", CLIENT, VERSION, OS, VM); } + /** + * Generate node name including identity. + * + * @param maybeIdentity optional node identity to include in the version string. + * @return Version with optional identity if provided. + */ public static String nodeName(final Optional maybeIdentity) { return maybeIdentity .map(identity -> String.format("%s/%s/v%s/%s/%s", CLIENT, identity, VERSION, OS, VM)) diff --git a/besu/src/main/java/org/hyperledger/besu/Runner.java b/besu/src/main/java/org/hyperledger/besu/Runner.java index 7180d04209a..32c4a46ddeb 100644 --- a/besu/src/main/java/org/hyperledger/besu/Runner.java +++ b/besu/src/main/java/org/hyperledger/besu/Runner.java @@ -16,17 +16,20 @@ import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.ethereum.api.graphql.GraphQLHttpService; +import org.hyperledger.besu.ethereum.api.jsonrpc.EngineJsonRpcService; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcHttpService; +import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcService; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketService; import org.hyperledger.besu.ethereum.api.query.cache.AutoTransactionLogBloomCachingService; import org.hyperledger.besu.ethereum.api.query.cache.TransactionLogBloomCacher; import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolEvictionService; import org.hyperledger.besu.ethereum.p2p.network.NetworkRunner; -import org.hyperledger.besu.ethereum.p2p.peers.EnodeURL; import org.hyperledger.besu.ethereum.stratum.StratumServer; import org.hyperledger.besu.ethstats.EthStatsService; import org.hyperledger.besu.metrics.MetricsService; import org.hyperledger.besu.nat.NatService; +import org.hyperledger.besu.plugin.data.EnodeURL; import java.io.File; import java.io.FileOutputStream; @@ -45,25 +48,29 @@ import com.google.common.annotations.VisibleForTesting; import io.vertx.core.Vertx; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +/** The Runner controls various Besu services lifecycle. */ public class Runner implements AutoCloseable { - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LoggerFactory.getLogger(Runner.class); private final Vertx vertx; private final CountDownLatch vertxShutdownLatch = new CountDownLatch(1); private final CountDownLatch shutdown = new CountDownLatch(1); - private final NetworkRunner networkRunner; private final NatService natService; - private final Optional pidPath; - private final Optional jsonRpc; + private final NetworkRunner networkRunner; + private final Optional ethStatsService; private final Optional graphQLHttp; - private final Optional websocketRpc; + private final Optional jsonRpc; + private final Optional engineJsonRpc; private final Optional metrics; - private final Optional ethStatsService; + private final Optional ipcJsonRpc; + private final Optional pidPath; + private final Optional webSocketRpc; + private final TransactionPoolEvictionService transactionPoolEvictionService; private final BesuController besuController; private final Path dataDir; @@ -71,13 +78,35 @@ public class Runner implements AutoCloseable { private final Optional autoTransactionLogBloomCachingService; + /** + * Instantiates a new Runner. + * + * @param vertx the vertx + * @param networkRunner the network runner + * @param natService the nat service + * @param jsonRpc the json rpc + * @param engineJsonRpc the engine json rpc + * @param graphQLHttp the graph ql http + * @param webSocketRpc the web socket rpc + * @param ipcJsonRpc the ipc json rpc + * @param stratumServer the stratum server + * @param metrics the metrics + * @param ethStatsService the eth stats service + * @param besuController the besu controller + * @param dataDir the data dir + * @param pidPath the pid path + * @param transactionLogBloomCacher the transaction log bloom cacher + * @param blockchain the blockchain + */ Runner( final Vertx vertx, final NetworkRunner networkRunner, final NatService natService, final Optional jsonRpc, + final Optional engineJsonRpc, final Optional graphQLHttp, - final Optional websocketRpc, + final Optional webSocketRpc, + final Optional ipcJsonRpc, final Optional stratumServer, final Optional metrics, final Optional ethStatsService, @@ -92,7 +121,9 @@ public class Runner implements AutoCloseable { this.graphQLHttp = graphQLHttp; this.pidPath = pidPath; this.jsonRpc = jsonRpc; - this.websocketRpc = websocketRpc; + this.engineJsonRpc = engineJsonRpc; + this.webSocketRpc = webSocketRpc; + this.ipcJsonRpc = ipcJsonRpc; this.metrics = metrics; this.ethStatsService = ethStatsService; this.besuController = besuController; @@ -101,9 +132,36 @@ public class Runner implements AutoCloseable { this.autoTransactionLogBloomCachingService = transactionLogBloomCacher.map( cacher -> new AutoTransactionLogBloomCachingService(blockchain, cacher)); + this.transactionPoolEvictionService = + new TransactionPoolEvictionService(vertx, besuController.getTransactionPool()); + } + + /** Start external services. */ + public void startExternalServices() { + LOG.info("Starting external services ... "); + metrics.ifPresent(service -> waitForServiceToStart("metrics", service.start())); + + jsonRpc.ifPresent(service -> waitForServiceToStart("jsonRpc", service.start())); + engineJsonRpc.ifPresent(service -> waitForServiceToStart("engineJsonRpc", service.start())); + graphQLHttp.ifPresent(service -> waitForServiceToStart("graphQLHttp", service.start())); + webSocketRpc.ifPresent(service -> waitForServiceToStart("websocketRpc", service.start())); + ipcJsonRpc.ifPresent( + service -> + waitForServiceToStart( + "ipcJsonRpc", service.start().toCompletionStage().toCompletableFuture())); + stratumServer.ifPresent( + server -> + waitForServiceToStart( + "stratum", server.start().toCompletionStage().toCompletableFuture())); + autoTransactionLogBloomCachingService.ifPresent(AutoTransactionLogBloomCachingService::start); } - public void start() { + private void startExternalServicePostMainLoop() { + ethStatsService.ifPresent(EthStatsService::start); + } + + /** Start ethereum main loop. */ + public void startEthereumMainLoop() { try { LOG.info("Starting Ethereum main loop ... "); natService.start(); @@ -112,32 +170,34 @@ public void start() { besuController.getSynchronizer().start(); } besuController.getMiningCoordinator().start(); - stratumServer.ifPresent(server -> waitForServiceToStart("stratum", server.start())); - vertx.setPeriodic( - TimeUnit.MINUTES.toMillis(1), - time -> - besuController.getTransactionPool().getPendingTransactions().evictOldTransactions()); - jsonRpc.ifPresent(service -> waitForServiceToStart("jsonRpc", service.start())); - graphQLHttp.ifPresent(service -> waitForServiceToStart("graphQLHttp", service.start())); - websocketRpc.ifPresent(service -> waitForServiceToStart("websocketRpc", service.start())); - metrics.ifPresent(service -> waitForServiceToStart("metrics", service.start())); - ethStatsService.ifPresent(EthStatsService::start); + transactionPoolEvictionService.start(); + LOG.info("Ethereum main loop is up."); + // we write these values to disk to be able to access them during the acceptance tests writeBesuPortsToFile(); writeBesuNetworksToFile(); - autoTransactionLogBloomCachingService.ifPresent(AutoTransactionLogBloomCachingService::start); writePidFile(); + // start external service that depends on information from main loop + startExternalServicePostMainLoop(); } catch (final Exception ex) { - LOG.error("Startup failed", ex); - throw new IllegalStateException(ex); + LOG.error("unable to start main loop", ex); + throw new IllegalStateException("Startup failed", ex); } } + /** Stop services. */ public void stop() { + transactionPoolEvictionService.stop(); jsonRpc.ifPresent(service -> waitForServiceToStop("jsonRpc", service.stop())); + engineJsonRpc.ifPresent(service -> waitForServiceToStop("engineJsonRpc", service.stop())); graphQLHttp.ifPresent(service -> waitForServiceToStop("graphQLHttp", service.stop())); - websocketRpc.ifPresent(service -> waitForServiceToStop("websocketRpc", service.stop())); + webSocketRpc.ifPresent(service -> waitForServiceToStop("websocketRpc", service.stop())); + ipcJsonRpc.ifPresent( + service -> + waitForServiceToStop( + "ipcJsonRpc", service.stop().toCompletionStage().toCompletableFuture())); + waitForServiceToStop("Transaction Pool", besuController.getTransactionPool().setDisabled()); metrics.ifPresent(service -> waitForServiceToStop("metrics", service.stop())); ethStatsService.ifPresent(EthStatsService::stop); besuController.getMiningCoordinator().stop(); @@ -158,6 +218,7 @@ public void stop() { shutdown.countDown(); } + /** Await stop. */ public void awaitStop() { try { shutdown.await(); @@ -205,8 +266,7 @@ private void waitForServiceToStart( Thread.currentThread().interrupt(); throw new IllegalStateException("Interrupted while waiting for service to start", e); } catch (final ExecutionException e) { - LOG.error("Service " + serviceName + " failed to start", e); - throw new IllegalStateException(e); + throw new IllegalStateException("Service " + serviceName + " failed to start", e); } catch (final TimeoutException e) { LOG.warn("Service {} is taking an unusually long time to start", serviceName); } @@ -234,17 +294,25 @@ private void writeBesuPortsToFile() { }); } - if (getJsonRpcPort().isPresent()) { - properties.setProperty("json-rpc", String.valueOf(getJsonRpcPort().get())); + Optional port = getJsonRpcPort(); + if (port.isPresent()) { + properties.setProperty("json-rpc", String.valueOf(port.get())); } - if (getGraphQLHttpPort().isPresent()) { - properties.setProperty("graphql-http", String.valueOf(getGraphQLHttpPort().get())); + port = getGraphQLHttpPort(); + if (port.isPresent()) { + properties.setProperty("graphql-http", String.valueOf(port.get())); } - if (getWebsocketPort().isPresent()) { - properties.setProperty("ws-rpc", String.valueOf(getWebsocketPort().get())); + port = getWebSocketPort(); + if (port.isPresent()) { + properties.setProperty("ws-rpc", String.valueOf(port.get())); } - if (getMetricsPort().isPresent()) { - properties.setProperty("metrics", String.valueOf(getMetricsPort().get())); + port = getMetricsPort(); + if (port.isPresent()) { + properties.setProperty("metrics", String.valueOf(port.get())); + } + port = getEngineJsonRpcPort(); + if (port.isPresent()) { + properties.setProperty("engine-json-rpc", String.valueOf(port.get())); } // create besu.ports file createBesuFile( @@ -295,18 +363,47 @@ private void writePidFile() { }); } + /** + * Gets json rpc port. + * + * @return the json rpc port + */ public Optional getJsonRpcPort() { return jsonRpc.map(service -> service.socketAddress().getPort()); } + /** + * Gets engine json rpc port. + * + * @return the engine json rpc port + */ + public Optional getEngineJsonRpcPort() { + return engineJsonRpc.map(service -> service.socketAddress().getPort()); + } + + /** + * Gets GraphQl http port. + * + * @return the graph ql http port + */ public Optional getGraphQLHttpPort() { return graphQLHttp.map(service -> service.socketAddress().getPort()); } - public Optional getWebsocketPort() { - return websocketRpc.map(service -> service.socketAddress().getPort()); + /** + * Gets web socket port. + * + * @return the web socket port + */ + public Optional getWebSocketPort() { + return webSocketRpc.map(service -> service.socketAddress().getPort()); } + /** + * Gets metrics port. + * + * @return the metrics port + */ public Optional getMetricsPort() { if (metrics.isPresent()) { return metrics.get().getPort(); @@ -315,6 +412,11 @@ public Optional getMetricsPort() { } } + /** + * Gets local enode. + * + * @return the local enode + */ @VisibleForTesting Optional getLocalEnode() { return networkRunner.getNetwork().getLocalEnode(); @@ -322,6 +424,11 @@ Optional getLocalEnode() { @FunctionalInterface private interface SynchronousShutdown { + /** + * Await for shutdown. + * + * @throws InterruptedException the interrupted exception + */ void await() throws InterruptedException; } @@ -329,7 +436,6 @@ private void createBesuFile( final Properties properties, final String fileName, final String fileHeader) { final File file = new File(dataDir.toFile(), String.format("besu.%s", fileName)); file.deleteOnExit(); - try (final FileOutputStream fileOutputStream = new FileOutputStream(file)) { properties.store( fileOutputStream, diff --git a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java index a07e28df906..d54a9149429 100644 --- a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java @@ -19,29 +19,41 @@ import static java.util.function.Predicate.isEqual; import static java.util.function.Predicate.not; import static org.hyperledger.besu.controller.BesuController.CACHE_PATH; +import static org.hyperledger.besu.ethereum.core.PrivacyParameters.FLEXIBLE_PRIVACY; import org.hyperledger.besu.cli.config.EthNetworkConfig; +import org.hyperledger.besu.cli.config.NetworkName; +import org.hyperledger.besu.cli.options.stable.EthstatsOptions; import org.hyperledger.besu.controller.BesuController; -import org.hyperledger.besu.crypto.NodeKey; +import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.ApiConfiguration; import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration; -import org.hyperledger.besu.ethereum.api.graphql.GraphQLDataFetcherContextImpl; +import org.hyperledger.besu.ethereum.api.graphql.GraphQLContextType; import org.hyperledger.besu.ethereum.api.graphql.GraphQLDataFetchers; import org.hyperledger.besu.ethereum.api.graphql.GraphQLHttpService; import org.hyperledger.besu.ethereum.api.graphql.GraphQLProvider; +import org.hyperledger.besu.ethereum.api.jsonrpc.EngineJsonRpcService; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcHttpService; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; +import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.AuthenticationService; +import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.DefaultAuthenticationService; +import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.EngineAuthService; +import org.hyperledger.besu.ethereum.api.jsonrpc.execution.AuthenticatedJsonRpcProcessor; +import org.hyperledger.besu.ethereum.api.jsonrpc.execution.BaseJsonRpcProcessor; +import org.hyperledger.besu.ethereum.api.jsonrpc.execution.JsonRpcExecutor; +import org.hyperledger.besu.ethereum.api.jsonrpc.execution.JsonRpcProcessor; import org.hyperledger.besu.ethereum.api.jsonrpc.health.HealthService; import org.hyperledger.besu.ethereum.api.jsonrpc.health.LivenessCheck; import org.hyperledger.besu.ethereum.api.jsonrpc.health.ReadinessCheck; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.filter.FilterManager; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.filter.FilterManagerBuilder; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration; +import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcService; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethodsFactory; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; -import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketRequestHandler; +import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketMessageHandler; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketService; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.methods.PrivateWebSocketMethodsFactory; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.methods.WebSocketMethodsFactory; @@ -54,15 +66,16 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.PrivacyQueries; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; +import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator; import org.hyperledger.besu.ethereum.chain.Blockchain; -import org.hyperledger.besu.ethereum.core.Account; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.Synchronizer; +import org.hyperledger.besu.ethereum.eth.manager.EthPeers; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; -import org.hyperledger.besu.ethereum.mainnet.precompiles.privacy.OnChainPrivacyPrecompiledContract; +import org.hyperledger.besu.ethereum.mainnet.precompiles.privacy.FlexiblePrivacyPrecompiledContract; import org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration; import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; import org.hyperledger.besu.ethereum.p2p.config.RlpxConfiguration; @@ -74,9 +87,10 @@ import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; import org.hyperledger.besu.ethereum.p2p.network.ProtocolManager; import org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer; -import org.hyperledger.besu.ethereum.p2p.peers.EnodeURL; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration; import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissions; import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissionsDenylist; +import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.SubProtocol; import org.hyperledger.besu.ethereum.permissioning.AccountLocalConfigPermissioningController; @@ -94,7 +108,7 @@ import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethstats.EthStatsService; -import org.hyperledger.besu.ethstats.util.NetstatsUrl; +import org.hyperledger.besu.ethstats.util.EthStatsConnectOptions; import org.hyperledger.besu.metrics.MetricsService; import org.hyperledger.besu.metrics.ObservableMetricsSystem; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; @@ -107,7 +121,10 @@ import org.hyperledger.besu.nat.kubernetes.KubernetesNatManager; import org.hyperledger.besu.nat.upnp.UpnpNatManager; import org.hyperledger.besu.plugin.BesuPlugin; +import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.services.BesuPluginContextImpl; +import org.hyperledger.besu.services.PermissioningServiceImpl; +import org.hyperledger.besu.services.RpcEndpointServiceImpl; import org.hyperledger.besu.util.NetworkUtility; import java.io.IOException; @@ -119,6 +136,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -127,13 +145,16 @@ import com.google.common.base.Strings; import graphql.GraphQL; import io.vertx.core.Vertx; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import io.vertx.core.VertxOptions; import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.units.bigints.UInt256; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +/** The builder for Runner class. */ public class RunnerBuilder { - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LoggerFactory.getLogger(RunnerBuilder.class); private Vertx vertx; private BesuController besuController; @@ -141,6 +162,7 @@ public class RunnerBuilder { private NetworkingConfiguration networkingConfiguration = NetworkingConfiguration.create(); private final Collection bannedNodeIds = new ArrayList<>(); private boolean p2pEnabled = true; + private Optional p2pTLSConfiguration = Optional.empty(); private boolean discovery; private String p2pAdvertisedHost; private String p2pListenInterface = NetworkUtility.INADDR_ANY; @@ -148,14 +170,10 @@ public class RunnerBuilder { private NatMethod natMethod = NatMethod.AUTO; private String natManagerServiceName; private boolean natMethodFallbackEnabled; - private int maxPeers; - private boolean limitRemoteWireConnectionsEnabled = false; - private float fractionRemoteConnectionsAllowed; private EthNetworkConfig ethNetworkConfig; - - private String ethstatsUrl; - private String ethstatsContact; + private EthstatsOptions ethstatsOptions; private JsonRpcConfiguration jsonRpcConfiguration; + private Optional engineJsonRpcConfiguration = Optional.empty(); private GraphQLConfiguration graphQLConfiguration; private WebSocketConfiguration webSocketConfiguration; private ApiConfiguration apiConfiguration; @@ -163,184 +181,428 @@ public class RunnerBuilder { private Optional pidPath = Optional.empty(); private MetricsConfiguration metricsConfiguration; private ObservableMetricsSystem metricsSystem; + private PermissioningServiceImpl permissioningService; private Optional permissioningConfiguration = Optional.empty(); private Collection staticNodes = Collections.emptyList(); private Optional identityString = Optional.empty(); private BesuPluginContextImpl besuPluginContext; private boolean autoLogBloomCaching = true; - private boolean randomPeerPriority; private StorageProvider storageProvider; - + private RpcEndpointServiceImpl rpcEndpointServiceImpl; + private JsonRpcIpcConfiguration jsonRpcIpcConfiguration; + private boolean legacyForkIdEnabled; + private Optional rpcMaxLogsRange; + private Optional enodeDnsConfiguration; + + /** + * Add Vertx. + * + * @param vertx the vertx instance + * @return runner builder + */ public RunnerBuilder vertx(final Vertx vertx) { this.vertx = vertx; return this; } + /** + * Add Besu controller. + * + * @param besuController the besu controller + * @return the runner builder + */ public RunnerBuilder besuController(final BesuController besuController) { this.besuController = besuController; return this; } + /** + * P2p enabled. + * + * @param p2pEnabled the p 2 p enabled + * @return the runner builder + */ public RunnerBuilder p2pEnabled(final boolean p2pEnabled) { this.p2pEnabled = p2pEnabled; return this; } + /** + * TLSConfiguration p2pTLSConfiguration. + * + * @param p2pTLSConfiguration the TLSConfiguration p2pTLSConfiguration + * @return the runner builder + */ + public RunnerBuilder p2pTLSConfiguration(final TLSConfiguration p2pTLSConfiguration) { + this.p2pTLSConfiguration = Optional.of(p2pTLSConfiguration); + return this; + } + + /** + * Optional TLSConfiguration p2pTLSConfiguration. + * + * @param p2pTLSConfiguration the TLSConfiguration p2pTLSConfiguration + * @return the runner builder + */ + public RunnerBuilder p2pTLSConfiguration(final Optional p2pTLSConfiguration) { + if (null != p2pTLSConfiguration) { + this.p2pTLSConfiguration = p2pTLSConfiguration; + } + return this; + } + + /** + * Enable Discovery. + * + * @param discovery the discovery + * @return the runner builder + */ public RunnerBuilder discovery(final boolean discovery) { this.discovery = discovery; return this; } + /** + * Add Eth network config. + * + * @param ethNetworkConfig the eth network config + * @return the runner builder + */ public RunnerBuilder ethNetworkConfig(final EthNetworkConfig ethNetworkConfig) { this.ethNetworkConfig = ethNetworkConfig; return this; } + /** + * Add Networking configuration. + * + * @param networkingConfiguration the networking configuration + * @return the runner builder + */ public RunnerBuilder networkingConfiguration( final NetworkingConfiguration networkingConfiguration) { this.networkingConfiguration = networkingConfiguration; return this; } + /** + * Add P2p advertised host. + * + * @param p2pAdvertisedHost the P2P advertised host + * @return the runner builder + */ public RunnerBuilder p2pAdvertisedHost(final String p2pAdvertisedHost) { this.p2pAdvertisedHost = p2pAdvertisedHost; return this; } + /** + * Add P2P Listener interface ip/host name. + * + * @param ip the ip + * @return the runner builder + */ public RunnerBuilder p2pListenInterface(final String ip) { checkArgument(!isNull(ip), "Invalid null value supplied for p2pListenInterface"); this.p2pListenInterface = ip; return this; } + /** + * Add P2P listen port. + * + * @param p2pListenPort the p 2 p listen port + * @return the runner builder + */ public RunnerBuilder p2pListenPort(final int p2pListenPort) { this.p2pListenPort = p2pListenPort; return this; } + /** + * Add Nat method. + * + * @param natMethod the nat method + * @return the runner builder + */ public RunnerBuilder natMethod(final NatMethod natMethod) { this.natMethod = natMethod; return this; } + /** + * Add Nat manager service name. + * + * @param natManagerServiceName the nat manager service name + * @return the runner builder + */ public RunnerBuilder natManagerServiceName(final String natManagerServiceName) { this.natManagerServiceName = natManagerServiceName; return this; } + /** + * Enable Nat method fallback. + * + * @param natMethodFallbackEnabled the nat method fallback enabled + * @return the runner builder + */ public RunnerBuilder natMethodFallbackEnabled(final boolean natMethodFallbackEnabled) { this.natMethodFallbackEnabled = natMethodFallbackEnabled; return this; } - public RunnerBuilder maxPeers(final int maxPeers) { - this.maxPeers = maxPeers; - return this; - } - - public RunnerBuilder limitRemoteWireConnectionsEnabled( - final boolean limitRemoteWireConnectionsEnabled) { - this.limitRemoteWireConnectionsEnabled = limitRemoteWireConnectionsEnabled; - return this; - } - - public RunnerBuilder fractionRemoteConnectionsAllowed( - final float fractionRemoteConnectionsAllowed) { - this.fractionRemoteConnectionsAllowed = fractionRemoteConnectionsAllowed; - return this; - } - - public RunnerBuilder randomPeerPriority(final boolean randomPeerPriority) { - this.randomPeerPriority = randomPeerPriority; + /** + * Add EthStatsOptions + * + * @param ethstatsOptions the ethstats options + * @return Runner builder instance + */ + public RunnerBuilder ethstatsOptions(final EthstatsOptions ethstatsOptions) { + this.ethstatsOptions = ethstatsOptions; return this; } - public RunnerBuilder ethstatsUrl(final String ethstatsUrl) { - this.ethstatsUrl = ethstatsUrl; - return this; - } - - public RunnerBuilder ethstatsContact(final String ethstatsContact) { - this.ethstatsContact = ethstatsContact; + /** + * Add Json RPC configuration. + * + * @param jsonRpcConfiguration the json rpc configuration + * @return the runner builder + */ + public RunnerBuilder jsonRpcConfiguration(final JsonRpcConfiguration jsonRpcConfiguration) { + this.jsonRpcConfiguration = jsonRpcConfiguration; return this; } - public RunnerBuilder jsonRpcConfiguration(final JsonRpcConfiguration jsonRpcConfiguration) { - this.jsonRpcConfiguration = jsonRpcConfiguration; + /** + * Add Engine json RPC configuration. + * + * @param engineJsonRpcConfiguration the engine json rpc configuration + * @return the runner builder + */ + public RunnerBuilder engineJsonRpcConfiguration( + final JsonRpcConfiguration engineJsonRpcConfiguration) { + this.engineJsonRpcConfiguration = Optional.ofNullable(engineJsonRpcConfiguration); return this; } + /** + * Add GraphQl configuration. + * + * @param graphQLConfiguration the graph ql configuration + * @return the runner builder + */ public RunnerBuilder graphQLConfiguration(final GraphQLConfiguration graphQLConfiguration) { this.graphQLConfiguration = graphQLConfiguration; return this; } + /** + * Add Web socket configuration. + * + * @param webSocketConfiguration the web socket configuration + * @return the runner builder + */ public RunnerBuilder webSocketConfiguration(final WebSocketConfiguration webSocketConfiguration) { this.webSocketConfiguration = webSocketConfiguration; return this; } + /** + * Add Api configuration. + * + * @param apiConfiguration the api configuration + * @return the runner builder + */ public RunnerBuilder apiConfiguration(final ApiConfiguration apiConfiguration) { this.apiConfiguration = apiConfiguration; return this; } + /** + * Add Permissioning configuration. + * + * @param permissioningConfiguration the permissioning configuration + * @return the runner builder + */ public RunnerBuilder permissioningConfiguration( - final PermissioningConfiguration permissioningConfiguration) { - this.permissioningConfiguration = Optional.of(permissioningConfiguration); + final Optional permissioningConfiguration) { + this.permissioningConfiguration = permissioningConfiguration; return this; } + /** + * Add pid path. + * + * @param pidPath the pid path + * @return the runner builder + */ public RunnerBuilder pidPath(final Path pidPath) { this.pidPath = Optional.ofNullable(pidPath); return this; } + /** + * Add Data dir. + * + * @param dataDir the data dir + * @return the runner builder + */ public RunnerBuilder dataDir(final Path dataDir) { this.dataDir = dataDir; return this; } + /** + * Add list of Banned node id. + * + * @param bannedNodeIds the banned node ids + * @return the runner builder + */ public RunnerBuilder bannedNodeIds(final Collection bannedNodeIds) { this.bannedNodeIds.addAll(bannedNodeIds); return this; } + /** + * Add Metrics configuration. + * + * @param metricsConfiguration the metrics configuration + * @return the runner builder + */ public RunnerBuilder metricsConfiguration(final MetricsConfiguration metricsConfiguration) { this.metricsConfiguration = metricsConfiguration; return this; } + /** + * Add Metrics system. + * + * @param metricsSystem the metrics system + * @return the runner builder + */ public RunnerBuilder metricsSystem(final ObservableMetricsSystem metricsSystem) { this.metricsSystem = metricsSystem; return this; } + /** + * Add Permissioning service. + * + * @param permissioningService the permissioning service + * @return the runner builder + */ + public RunnerBuilder permissioningService(final PermissioningServiceImpl permissioningService) { + this.permissioningService = permissioningService; + return this; + } + + /** + * Add Static nodes collection. + * + * @param staticNodes the static nodes + * @return the runner builder + */ public RunnerBuilder staticNodes(final Collection staticNodes) { this.staticNodes = staticNodes; return this; } + /** + * Add Node identity string. + * + * @param identityString the identity string + * @return the runner builder + */ public RunnerBuilder identityString(final Optional identityString) { this.identityString = identityString; return this; } + /** + * Add Besu plugin context. + * + * @param besuPluginContext the besu plugin context + * @return the runner builder + */ public RunnerBuilder besuPluginContext(final BesuPluginContextImpl besuPluginContext) { this.besuPluginContext = besuPluginContext; return this; } + /** + * Enable Auto log bloom caching. + * + * @param autoLogBloomCaching the auto log bloom caching + * @return the runner builder + */ public RunnerBuilder autoLogBloomCaching(final boolean autoLogBloomCaching) { this.autoLogBloomCaching = autoLogBloomCaching; return this; } + /** + * Add Storage provider. + * + * @param storageProvider the storage provider + * @return the runner builder + */ public RunnerBuilder storageProvider(final StorageProvider storageProvider) { this.storageProvider = storageProvider; return this; } + /** + * Add Rpc endpoint service. + * + * @param rpcEndpointService the rpc endpoint service + * @return the runner builder + */ + public RunnerBuilder rpcEndpointService(final RpcEndpointServiceImpl rpcEndpointService) { + this.rpcEndpointServiceImpl = rpcEndpointService; + return this; + } + + /** + * Add Json Rpc Ipc configuration. + * + * @param jsonRpcIpcConfiguration the json rpc ipc configuration + * @return the runner builder + */ + public RunnerBuilder jsonRpcIpcConfiguration( + final JsonRpcIpcConfiguration jsonRpcIpcConfiguration) { + this.jsonRpcIpcConfiguration = jsonRpcIpcConfiguration; + return this; + } + + /** + * Add Rpc max logs range. + * + * @param rpcMaxLogsRange the rpc max logs range + * @return the runner builder + */ + public RunnerBuilder rpcMaxLogsRange(final Long rpcMaxLogsRange) { + this.rpcMaxLogsRange = rpcMaxLogsRange > 0 ? Optional.of(rpcMaxLogsRange) : Optional.empty(); + return this; + } + + /** + * Add enode DNS configuration + * + * @param enodeDnsConfiguration the DNS configuration for enodes + * @return the runner builder + */ + public RunnerBuilder enodeDnsConfiguration(final EnodeDnsConfiguration enodeDnsConfiguration) { + this.enodeDnsConfiguration = + enodeDnsConfiguration != null ? Optional.of(enodeDnsConfiguration) : Optional.empty(); + return this; + } + + /** + * Build Runner instance. + * + * @return the runner + */ public Runner build() { Preconditions.checkNotNull(besuController); @@ -353,12 +615,16 @@ public Runner build() { if (discovery) { final List bootstrap; if (ethNetworkConfig.getBootNodes() == null) { - bootstrap = DiscoveryConfiguration.MAINNET_BOOTSTRAP_NODES; + bootstrap = EthNetworkConfig.getNetworkConfig(NetworkName.MAINNET).getBootNodes(); } else { bootstrap = ethNetworkConfig.getBootNodes(); } discoveryConfiguration.setBootnodes(bootstrap); discoveryConfiguration.setDnsDiscoveryURL(ethNetworkConfig.getDnsDiscoveryUrl()); + discoveryConfiguration.setDiscoveryV5Enabled( + networkingConfiguration.getDiscovery().isDiscoveryV5Enabled()); + discoveryConfiguration.setFilterOnEnrForkId( + networkingConfiguration.getDiscovery().isFilterOnEnrForkIdEnabled()); } else { discoveryConfiguration.setActive(false); } @@ -382,11 +648,8 @@ public Runner build() { RlpxConfiguration.create() .setBindHost(p2pListenInterface) .setBindPort(p2pListenPort) - .setMaxPeers(maxPeers) .setSupportedProtocols(subProtocols) - .setClientId(BesuInfo.nodeName(identityString)) - .setLimitRemoteWireConnectionsEnabled(limitRemoteWireConnectionsEnabled) - .setFractionRemoteWireConnectionsAllowed(fractionRemoteConnectionsAllowed); + .setClientId(BesuInfo.nodeName(identityString)); networkingConfiguration.setRlpx(rlpxConfiguration).setDiscovery(discoveryConfiguration); final PeerPermissionsDenylist bannedNodes = PeerPermissionsDenylist.create(); @@ -414,20 +677,29 @@ public Runner build() { LOG.info("Detecting NAT service."); final boolean fallbackEnabled = natMethod == NatMethod.AUTO || natMethodFallbackEnabled; final NatService natService = new NatService(buildNatManager(natMethod), fallbackEnabled); - final NetworkBuilder inactiveNetwork = (caps) -> new NoopP2PNetwork(); + final NetworkBuilder inactiveNetwork = caps -> new NoopP2PNetwork(); final NetworkBuilder activeNetwork = - (caps) -> - DefaultP2PNetwork.builder() - .vertx(vertx) - .nodeKey(nodeKey) - .config(networkingConfiguration) - .peerPermissions(peerPermissions) - .metricsSystem(metricsSystem) - .supportedCapabilities(caps) - .natService(natService) - .randomPeerPriority(randomPeerPriority) - .storageProvider(storageProvider) - .build(); + caps -> { + final EthPeers ethPeers = besuController.getEthPeers(); + return DefaultP2PNetwork.builder() + .vertx(vertx) + .nodeKey(nodeKey) + .config(networkingConfiguration) + .legacyForkIdEnabled(legacyForkIdEnabled) + .peerPermissions(peerPermissions) + .metricsSystem(metricsSystem) + .supportedCapabilities(caps) + .natService(natService) + .storageProvider(storageProvider) + .p2pTLSConfiguration(p2pTLSConfiguration) + .blockchain(context.getBlockchain()) + .blockNumberForks(besuController.getGenesisConfigOptions().getForkBlockNumbers()) + .timestampForks(besuController.getGenesisConfigOptions().getForkBlockTimestamps()) + .allConnectionsSupplier(ethPeers::getAllConnections) + .allActiveConnectionsSupplier(ethPeers::getAllActiveConnections) + .peersLowerBound(ethPeers.getPeerLowerBound()) + .build(); + }; final NetworkRunner networkRunner = NetworkRunner.builder() @@ -437,7 +709,18 @@ public Runner build() { .metricsSystem(metricsSystem) .build(); + besuController.getEthPeers().setRlpxAgent(networkRunner.getRlpxAgent()); + final P2PNetwork network = networkRunner.getNetwork(); + // ForkId in Ethereum Node Record needs updating when we transition to a new protocol spec + context + .getBlockchain() + .observeBlockAdded( + blockAddedEvent -> { + if (protocolSchedule.isOnMilestoneBoundary(blockAddedEvent.getBlock().getHeader())) { + network.updateNodeRecord(); + } + }); nodePermissioningController.ifPresent( n -> n.setInsufficientPeersPermissioningProvider( @@ -464,27 +747,36 @@ public Runner build() { .build(); vertx.deployVerticle(filterManager); - createPrivateTransactionObserver(filterManager, privacyParameters); + createPrivateTransactionObserver( + filterManager, privacyParameters, context.getBlockchain().getGenesisBlockHeader()); final P2PNetwork peerNetwork = networkRunner.getNetwork(); final MiningParameters miningParameters = besuController.getMiningParameters(); Optional stratumServer = Optional.empty(); + if (miningParameters.isStratumMiningEnabled()) { + if (!(miningCoordinator instanceof PoWMiningCoordinator powMiningCoordinator)) { + throw new IllegalArgumentException( + "Stratum server requires an PoWMiningCoordinator not " + + ((miningCoordinator == null) ? "null" : miningCoordinator.getClass().getName())); + } stratumServer = Optional.of( new StratumServer( vertx, - miningCoordinator, + powMiningCoordinator, miningParameters.getStratumPort(), miningParameters.getStratumNetworkInterface(), - miningParameters.getStratumExtranonce())); + miningParameters.getStratumExtranonce(), + metricsSystem)); miningCoordinator.addEthHashObserver(stratumServer.get()); + LOG.debug("added ethash observer: {}", stratumServer.get()); } sanitizePeers(network, staticNodes) .map(DefaultPeer::fromEnodeURL) - .forEach(peerNetwork::addMaintainConnectionPeer); + .forEach(peerNetwork::addMaintainedConnectionPeer); final Optional nodeLocalConfigPermissioningController = nodePermissioningController.flatMap(NodePermissioningController::localConfigController); @@ -502,10 +794,12 @@ public Runner build() { AccountPermissioningController::getAccountLocalConfigPermissioningController); Optional jsonRpcHttpService = Optional.empty(); + if (jsonRpcConfiguration.isEnabled()) { - final Map jsonRpcMethods = + final Map nonEngineMethods = jsonRpcMethods( protocolSchedule, + context, besuController, peerNetwork, blockchainQueries, @@ -514,7 +808,9 @@ public Runner build() { miningCoordinator, metricsSystem, supportedCapabilities, - jsonRpcConfiguration.getRpcApis(), + jsonRpcConfiguration.getRpcApis().stream() + .filter(apiGroup -> !apiGroup.toLowerCase().startsWith("engine")) + .collect(Collectors.toList()), filterManager, accountLocalConfigPermissioningController, nodeLocalConfigPermissioningController, @@ -524,7 +820,9 @@ public Runner build() { metricsConfiguration, natService, besuPluginContext.getNamedPlugins(), - dataDir); + dataDir, + rpcEndpointServiceImpl); + jsonRpcHttpService = Optional.of( new JsonRpcHttpService( @@ -533,21 +831,86 @@ public Runner build() { jsonRpcConfiguration, metricsSystem, natService, - jsonRpcMethods, + nonEngineMethods, new HealthService(new LivenessCheck()), new HealthService(new ReadinessCheck(peerNetwork, synchronizer)))); } - Optional graphQLHttpService = Optional.empty(); - if (graphQLConfiguration.isEnabled()) { - final GraphQLDataFetchers fetchers = new GraphQLDataFetchers(supportedCapabilities); - final GraphQLDataFetcherContextImpl dataFetcherContext = - new GraphQLDataFetcherContextImpl( - blockchainQueries, + final SubscriptionManager subscriptionManager = + createSubscriptionManager(vertx, transactionPool, blockchainQueries); + + Optional engineJsonRpcService = Optional.empty(); + if (engineJsonRpcConfiguration.isPresent() && engineJsonRpcConfiguration.get().isEnabled()) { + final Map engineMethods = + jsonRpcMethods( protocolSchedule, + context, + besuController, + peerNetwork, + blockchainQueries, + synchronizer, transactionPool, miningCoordinator, - synchronizer); + metricsSystem, + supportedCapabilities, + engineJsonRpcConfiguration.get().getRpcApis(), + filterManager, + accountLocalConfigPermissioningController, + nodeLocalConfigPermissioningController, + privacyParameters, + engineJsonRpcConfiguration.get(), + webSocketConfiguration, + metricsConfiguration, + natService, + besuPluginContext.getNamedPlugins(), + dataDir, + rpcEndpointServiceImpl); + + final Optional authToUse = + engineJsonRpcConfiguration.get().isAuthenticationEnabled() + ? Optional.of( + new EngineAuthService( + vertx, + Optional.ofNullable( + engineJsonRpcConfiguration.get().getAuthenticationPublicKeyFile()), + dataDir)) + : Optional.empty(); + + final WebSocketConfiguration engineSocketConfig = + webSocketConfiguration.isEnabled() + ? webSocketConfiguration + : WebSocketConfiguration.createEngineDefault(); + + final WebSocketMethodsFactory websocketMethodsFactory = + new WebSocketMethodsFactory(subscriptionManager, engineMethods); + + engineJsonRpcService = + Optional.of( + new EngineJsonRpcService( + vertx, + dataDir, + engineJsonRpcConfiguration.orElse(JsonRpcConfiguration.createEngineDefault()), + metricsSystem, + natService, + websocketMethodsFactory.methods(), + Optional.ofNullable(engineSocketConfig), + besuController.getProtocolManager().ethContext().getScheduler(), + authToUse, + new HealthService(new LivenessCheck()), + new HealthService(new ReadinessCheck(peerNetwork, synchronizer)))); + } + + Optional graphQLHttpService = Optional.empty(); + if (graphQLConfiguration.isEnabled()) { + final GraphQLDataFetchers fetchers = new GraphQLDataFetchers(supportedCapabilities); + final Map graphQlContextMap = new ConcurrentHashMap<>(); + graphQlContextMap.putIfAbsent(GraphQLContextType.BLOCKCHAIN_QUERIES, blockchainQueries); + graphQlContextMap.putIfAbsent(GraphQLContextType.PROTOCOL_SCHEDULE, protocolSchedule); + graphQlContextMap.putIfAbsent(GraphQLContextType.TRANSACTION_POOL, transactionPool); + graphQlContextMap.putIfAbsent(GraphQLContextType.MINING_COORDINATOR, miningCoordinator); + graphQlContextMap.putIfAbsent(GraphQLContextType.SYNCHRONIZER, synchronizer); + graphQlContextMap.putIfAbsent( + GraphQLContextType.CHAIN_ID, protocolSchedule.getChainId().map(UInt256::valueOf)); final GraphQL graphQL; try { graphQL = GraphQLProvider.buildGraphQL(fetchers); @@ -562,15 +925,16 @@ public Runner build() { dataDir, graphQLConfiguration, graphQL, - dataFetcherContext, + graphQlContextMap, besuController.getProtocolManager().ethContext().getScheduler())); } Optional webSocketService = Optional.empty(); if (webSocketConfiguration.isEnabled()) { - final Map webSocketsJsonRpcMethods = + final Map nonEngineMethods = jsonRpcMethods( protocolSchedule, + context, besuController, peerNetwork, blockchainQueries, @@ -579,7 +943,9 @@ public Runner build() { miningCoordinator, metricsSystem, supportedCapabilities, - webSocketConfiguration.getRpcApis(), + webSocketConfiguration.getRpcApis().stream() + .filter(apiGroup -> !apiGroup.toLowerCase().startsWith("engine")) + .collect(Collectors.toList()), filterManager, accountLocalConfigPermissioningController, nodeLocalConfigPermissioningController, @@ -589,10 +955,8 @@ public Runner build() { metricsConfiguration, natService, besuPluginContext.getNamedPlugins(), - dataDir); - - final SubscriptionManager subscriptionManager = - createSubscriptionManager(vertx, transactionPool, blockchainQueries); + dataDir, + rpcEndpointServiceImpl); createLogsSubscriptionService( context.getBlockchain(), @@ -611,23 +975,29 @@ public Runner build() { vertx, webSocketConfiguration, subscriptionManager, - webSocketsJsonRpcMethods, + nonEngineMethods, privacyParameters, protocolSchedule, blockchainQueries, - transactionPool)); + DefaultAuthenticationService.create(vertx, webSocketConfiguration), + metricsSystem)); - createPrivateTransactionObserver(subscriptionManager, privacyParameters); + createPrivateTransactionObserver( + subscriptionManager, privacyParameters, context.getBlockchain().getGenesisBlockHeader()); } - Optional metricsService = createMetricsService(vertx, metricsConfiguration); + final Optional metricsService = + createMetricsService(vertx, metricsConfiguration); final Optional ethStatsService; - if (!Strings.isNullOrEmpty(ethstatsUrl)) { + if (isEthStatsEnabled()) { ethStatsService = Optional.of( new EthStatsService( - NetstatsUrl.fromParams(ethstatsUrl, ethstatsContact), + EthStatsConnectOptions.fromParams( + ethstatsOptions.getEthstatsUrl(), + ethstatsOptions.getEthstatsContact(), + ethstatsOptions.getEthstatsCaCert()), blockchainQueries, besuController.getProtocolManager(), transactionPool, @@ -641,13 +1011,54 @@ public Runner build() { ethStatsService = Optional.empty(); } + final Optional jsonRpcIpcService; + if (jsonRpcIpcConfiguration.isEnabled()) { + final Map ipcMethods = + jsonRpcMethods( + protocolSchedule, + context, + besuController, + peerNetwork, + blockchainQueries, + synchronizer, + transactionPool, + miningCoordinator, + metricsSystem, + supportedCapabilities, + jsonRpcIpcConfiguration.getEnabledApis().stream() + .filter(apiGroup -> !apiGroup.toLowerCase().startsWith("engine")) + .collect(Collectors.toList()), + filterManager, + accountLocalConfigPermissioningController, + nodeLocalConfigPermissioningController, + privacyParameters, + jsonRpcConfiguration, + webSocketConfiguration, + metricsConfiguration, + natService, + besuPluginContext.getNamedPlugins(), + dataDir, + rpcEndpointServiceImpl); + + jsonRpcIpcService = + Optional.of( + new JsonRpcIpcService( + vertx, + jsonRpcIpcConfiguration.getPath(), + new JsonRpcExecutor(new BaseJsonRpcProcessor(), ipcMethods))); + } else { + jsonRpcIpcService = Optional.empty(); + } + return new Runner( vertx, networkRunner, natService, jsonRpcHttpService, + engineJsonRpcService, graphQLHttpService, webSocketService, + jsonRpcIpcService, stratumServer, metricsService, ethStatsService, @@ -658,6 +1069,10 @@ public Runner build() { context.getBlockchain()); } + private boolean isEthStatsEnabled() { + return ethstatsOptions != null && !Strings.isNullOrEmpty(ethstatsOptions.getEthstatsUrl()); + } + private Stream sanitizePeers( final P2PNetwork network, final Collection enodeURLS) { if (network.getLocalEnode().isEmpty()) { @@ -687,7 +1102,23 @@ private Optional buildNodePermissioningController( localNodeId, transactionSimulator, metricsSystem, - blockchain); + blockchain, + permissioningService.getConnectionPermissioningProviders()); + + return Optional.of(nodePermissioningController); + } else if (permissioningService.getConnectionPermissioningProviders().size() > 0) { + final NodePermissioningController nodePermissioningController = + new NodePermissioningControllerFactory() + .create( + new PermissioningConfiguration( + Optional.empty(), Optional.empty(), Optional.empty()), + synchronizer, + fixedNodes, + localNodeId, + transactionSimulator, + metricsSystem, + blockchain, + permissioningService.getConnectionPermissioningProviders()); return Optional.of(nodePermissioningController); } else { @@ -738,6 +1169,13 @@ private Optional buildNatManager(final NatMethod natMethod) { } } + /** + * Gets fixed nodes. Visible for testing. + * + * @param someFixedNodes the fixed nodes + * @param moreFixedNodes nodes added to fixed nodes + * @return the fixed and more nodes combined + */ @VisibleForTesting public static Collection getFixedNodes( final Collection someFixedNodes, final Collection moreFixedNodes) { @@ -748,6 +1186,7 @@ public static Collection getFixedNodes( private Map jsonRpcMethods( final ProtocolSchedule protocolSchedule, + final ProtocolContext protocolContext, final BesuController besuController, final P2PNetwork network, final BlockchainQueries blockchainQueries, @@ -756,7 +1195,7 @@ private Map jsonRpcMethods( final MiningCoordinator miningCoordinator, final ObservableMetricsSystem metricsSystem, final Set supportedCapabilities, - final Collection jsonRpcApis, + final Collection jsonRpcApis, final FilterManager filterManager, final Optional accountAllowlistController, final Optional nodeAllowlistController, @@ -766,7 +1205,11 @@ private Map jsonRpcMethods( final MetricsConfiguration metricsConfiguration, final NatService natService, final Map namedPlugins, - final Path dataDir) { + final Path dataDir, + final RpcEndpointServiceImpl rpcEndpointServiceImpl) { + // sync vertx for engine consensus API, to process requests in FIFO order; + final Vertx consensusEngineServer = Vertx.vertx(new VertxOptions().setWorkerPoolSize(1)); + final Map methods = new JsonRpcMethodsFactory() .methods( @@ -777,6 +1220,7 @@ private Map jsonRpcMethods( blockchainQueries, synchronizer, protocolSchedule, + protocolContext, filterManager, transactionPool, miningCoordinator, @@ -792,8 +1236,22 @@ private Map jsonRpcMethods( natService, namedPlugins, dataDir, - besuController.getProtocolManager().ethContext().getEthPeers()); + besuController.getProtocolManager().ethContext().getEthPeers(), + consensusEngineServer, + rpcMaxLogsRange, + enodeDnsConfiguration); methods.putAll(besuController.getAdditionalJsonRpcMethods(jsonRpcApis)); + + final var pluginMethods = + rpcEndpointServiceImpl.getPluginMethods(jsonRpcConfiguration.getRpcApis()); + + final var overriddenMethods = + methods.keySet().stream().filter(pluginMethods::containsKey).collect(Collectors.toList()); + if (overriddenMethods.size() > 0) { + throw new RuntimeException("You can not override built in methods " + overriddenMethods); + } + + methods.putAll(pluginMethods); return methods; } @@ -845,18 +1303,20 @@ private void createLogsSubscriptionService( private void createPrivateTransactionObserver( final PrivateTransactionObserver privateTransactionObserver, - final PrivacyParameters privacyParameters) { - // register privateTransactionObserver as observer of events fired by the onchain precompile. - if (privacyParameters.isOnchainPrivacyGroupsEnabled() + final PrivacyParameters privacyParameters, + final BlockHeader genesisBlockHeader) { + // register privateTransactionObserver as observer of events fired by the flexible precompile. + if (privacyParameters.isFlexiblePrivacyGroupsEnabled() && privacyParameters.isMultiTenancyEnabled()) { - final OnChainPrivacyPrecompiledContract onchainPrivacyPrecompiledContract = - (OnChainPrivacyPrecompiledContract) + final FlexiblePrivacyPrecompiledContract flexiblePrivacyPrecompiledContract = + (FlexiblePrivacyPrecompiledContract) besuController .getProtocolSchedule() - .getByBlockNumber(1) + .getByBlockHeader(genesisBlockHeader) .getPrecompileContractRegistry() - .get(Address.ONCHAIN_PRIVACY, Account.DEFAULT_VERSION); - onchainPrivacyPrecompiledContract.addPrivateTransactionObserver(privateTransactionObserver); + .get(FLEXIBLE_PRIVACY); + + flexiblePrivacyPrecompiledContract.addPrivateTransactionObserver(privateTransactionObserver); } } @@ -883,7 +1343,8 @@ private WebSocketService createWebsocketService( final PrivacyParameters privacyParameters, final ProtocolSchedule protocolSchedule, final BlockchainQueries blockchainQueries, - final TransactionPool transactionPool) { + final Optional authenticationService, + final ObservableMetricsSystem metricsSystem) { final WebSocketMethodsFactory websocketMethodsFactory = new WebSocketMethodsFactory(subscriptionManager, jsonRpcMethods); @@ -891,27 +1352,52 @@ private WebSocketService createWebsocketService( if (privacyParameters.isEnabled()) { final PrivateWebSocketMethodsFactory privateWebSocketMethodsFactory = new PrivateWebSocketMethodsFactory( - privacyParameters, - subscriptionManager, - protocolSchedule, - blockchainQueries, - transactionPool); + privacyParameters, subscriptionManager, protocolSchedule, blockchainQueries); privateWebSocketMethodsFactory.methods().forEach(websocketMethodsFactory::addMethods); } - final WebSocketRequestHandler websocketRequestHandler = - new WebSocketRequestHandler( + rpcEndpointServiceImpl + .getPluginMethods(configuration.getRpcApis()) + .values() + .forEach(websocketMethodsFactory::addMethods); + + final JsonRpcProcessor jsonRpcProcessor; + if (authenticationService.isPresent()) { + jsonRpcProcessor = + new AuthenticatedJsonRpcProcessor( + new BaseJsonRpcProcessor(), + authenticationService.get(), + configuration.getRpcApisNoAuth()); + } else { + jsonRpcProcessor = new BaseJsonRpcProcessor(); + } + final JsonRpcExecutor jsonRpcExecutor = + new JsonRpcExecutor(jsonRpcProcessor, websocketMethodsFactory.methods()); + final WebSocketMessageHandler websocketMessageHandler = + new WebSocketMessageHandler( vertx, - websocketMethodsFactory.methods(), + jsonRpcExecutor, besuController.getProtocolManager().ethContext().getScheduler(), webSocketConfiguration.getTimeoutSec()); - return new WebSocketService(vertx, configuration, websocketRequestHandler); + return new WebSocketService( + vertx, configuration, websocketMessageHandler, authenticationService, metricsSystem); } private Optional createMetricsService( final Vertx vertx, final MetricsConfiguration configuration) { return MetricsService.create(vertx, configuration, metricsSystem); } + + /** + * Add Legacy fork id. + * + * @param legacyEth64ForkIdEnabled the legacy eth64 fork id enabled + * @return the runner builder + */ + public RunnerBuilder legacyForkId(final boolean legacyEth64ForkIdEnabled) { + this.legacyForkIdEnabled = legacyEth64ForkIdEnabled; + return this; + } } diff --git a/besu/src/main/java/org/hyperledger/besu/chainexport/BlockExporter.java b/besu/src/main/java/org/hyperledger/besu/chainexport/BlockExporter.java index e9403a2c38f..de5b058fc7b 100644 --- a/besu/src/main/java/org/hyperledger/besu/chainexport/BlockExporter.java +++ b/besu/src/main/java/org/hyperledger/besu/chainexport/BlockExporter.java @@ -25,14 +25,19 @@ import java.io.IOException; import java.util.Optional; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** Besu Block Export Util. */ public abstract class BlockExporter { - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LoggerFactory.getLogger(BlockExporter.class); private final Blockchain blockchain; + /** + * Instantiates a new Block exporter. + * + * @param blockchain the blockchain + */ protected BlockExporter(final Blockchain blockchain) { this.blockchain = blockchain; } @@ -90,6 +95,13 @@ public void exportBlocks( LOG.info("Export complete at block {}", blockNumber); } + /** + * Export block. + * + * @param outputStream The FileOutputStream where the block will be exported + * @param block The block to export + * @throws IOException In case of an error while exporting. + */ protected abstract void exportBlock(final FileOutputStream outputStream, final Block block) throws IOException; } diff --git a/besu/src/main/java/org/hyperledger/besu/chainexport/RlpBlockExporter.java b/besu/src/main/java/org/hyperledger/besu/chainexport/RlpBlockExporter.java index fcd7ec5696f..cfca4f7f9a3 100644 --- a/besu/src/main/java/org/hyperledger/besu/chainexport/RlpBlockExporter.java +++ b/besu/src/main/java/org/hyperledger/besu/chainexport/RlpBlockExporter.java @@ -23,8 +23,14 @@ import org.apache.tuweni.bytes.Bytes; +/** The Rlp block exporter. */ public class RlpBlockExporter extends BlockExporter { + /** + * Instantiates a new Rlp block exporter. + * + * @param blockchain the blockchain + */ public RlpBlockExporter(final Blockchain blockchain) { super(blockchain); } diff --git a/besu/src/main/java/org/hyperledger/besu/chainimport/JsonBlockImporter.java b/besu/src/main/java/org/hyperledger/besu/chainimport/JsonBlockImporter.java index 65a399aaf29..13c239d6d88 100644 --- a/besu/src/main/java/org/hyperledger/besu/chainimport/JsonBlockImporter.java +++ b/besu/src/main/java/org/hyperledger/besu/chainimport/JsonBlockImporter.java @@ -17,16 +17,18 @@ import org.hyperledger.besu.chainimport.internal.BlockData; import org.hyperledger.besu.chainimport.internal.ChainData; import org.hyperledger.besu.config.GenesisConfigOptions; +import org.hyperledger.besu.config.PowAlgorithm; import org.hyperledger.besu.controller.BesuController; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; -import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockImporter; -import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Transaction; -import org.hyperledger.besu.ethereum.core.WorldState; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; +import org.hyperledger.besu.evm.worldstate.WorldState; import java.io.IOException; import java.util.ArrayList; @@ -39,17 +41,22 @@ import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.apache.tuweni.bytes.Bytes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** Tool for importing blocks with transactions from human-readable json. */ public class JsonBlockImporter { - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LoggerFactory.getLogger(JsonBlockImporter.class); private final ObjectMapper mapper; private final BesuController controller; + /** + * Instantiates a new Json block importer. + * + * @param controller the controller + */ public JsonBlockImporter(final BesuController controller) { this.controller = controller; mapper = new ObjectMapper(); @@ -59,6 +66,12 @@ public JsonBlockImporter(final BesuController controller) { mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); } + /** + * Import chain. + * + * @param chainJson the chain json + * @throws IOException the io exception + */ public void importChain(final String chainJson) throws IOException { warnIfDatabaseIsNotEmpty(); @@ -84,7 +97,7 @@ private Block processBlockData(final BlockData blockData, final BlockHeader pare controller .getProtocolContext() .getWorldStateArchive() - .get(parentHeader.getStateRoot()) + .get(parentHeader.getStateRoot(), parentHeader.getHash()) .get(); final List transactions = blockData.streamTransactions(worldState).collect(Collectors.toList()); @@ -119,9 +132,9 @@ private void setOptionalFields( final BlockData blockData, final GenesisConfigOptions genesisConfig) { // Some fields can only be configured for ethash - if (genesisConfig.isEthHash()) { - // For simplicity only set these for ethash. Other consensus algorithms use these fields for - // special purposes or ignore them + if (genesisConfig.getPowAlgorithm() != PowAlgorithm.UNSUPPORTED) { + // For simplicity only set these for PoW consensus algorithms. + // Other consensus algorithms use these fields for special purposes or ignore them. miner.setCoinbase(blockData.getCoinbase().orElse(Address.ZERO)); miner.setExtraData(blockData.getExtraData().orElse(Bytes.EMPTY)); } else if (blockData.getCoinbase().isPresent() || blockData.getExtraData().isPresent()) { @@ -140,14 +153,11 @@ private void setOptionalFields( private void importBlock(final Block block) { final BlockImporter importer = - controller - .getProtocolSchedule() - .getByBlockNumber(block.getHeader().getNumber()) - .getBlockImporter(); + controller.getProtocolSchedule().getByBlockHeader(block.getHeader()).getBlockImporter(); - final boolean imported = + final BlockImportResult importResult = importer.importBlock(controller.getProtocolContext(), block, HeaderValidationMode.NONE); - if (imported) { + if (importResult.isImported()) { LOG.info( "Successfully created and imported block at height {} ({})", block.getHeader().getNumber(), @@ -219,7 +229,7 @@ private BlockHeader getParentHeader(final BlockData blockData, final List if (importedBlocks.size() > 0 && blockData.getNumber().isPresent()) { final long targetParentBlockNumber = blockData.getNumber().get() - 1L; - Optional maybeHeader = + final Optional maybeHeader = importedBlocks.stream() .map(Block::getHeader) .filter(h -> h.getNumber() == targetParentBlockNumber) @@ -229,7 +239,7 @@ private BlockHeader getParentHeader(final BlockData blockData, final List } } - long blockNumber; + final long blockNumber; if (blockData.getNumber().isPresent()) { blockNumber = blockData.getNumber().get() - 1L; } else if (importedBlocks.size() > 0) { @@ -240,7 +250,7 @@ private BlockHeader getParentHeader(final BlockData blockData, final List } if (blockNumber < BlockHeader.GENESIS_BLOCK_NUMBER) { - throw new IllegalArgumentException("Invalid block number: " + blockNumber + 1); + throw new IllegalArgumentException("Invalid block number: " + (blockNumber + 1)); } return controller diff --git a/besu/src/main/java/org/hyperledger/besu/chainimport/RlpBlockImporter.java b/besu/src/main/java/org/hyperledger/besu/chainimport/RlpBlockImporter.java index f458d2cae76..6004bf621f1 100644 --- a/besu/src/main/java/org/hyperledger/besu/chainimport/RlpBlockImporter.java +++ b/besu/src/main/java/org/hyperledger/besu/chainimport/RlpBlockImporter.java @@ -21,10 +21,12 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; import org.hyperledger.besu.ethereum.core.BlockImporter; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; @@ -41,15 +43,16 @@ import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import com.google.common.base.MoreObjects; import com.google.common.base.Stopwatch; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** Tool for importing rlp-encoded block data from files. */ public class RlpBlockImporter implements Closeable { - private static final Logger LOG = LogManager.getFormatterLogger(); + private static final Logger LOG = LoggerFactory.getLogger(RlpBlockImporter.class); private final Semaphore blockBacklog = new Semaphore(2); @@ -78,6 +81,17 @@ public RlpBlockImporter.ImportResult importBlockchain( return importBlockchain(blocks, besuController, skipPowValidation, 0L, Long.MAX_VALUE); } + /** + * Import blockchain. + * + * @param blocks the blocks + * @param besuController the besu controller + * @param skipPowValidation the skip pow validation + * @param startBlock the start block + * @param endBlock the end block + * @return the rlp block importer - import result + * @throws IOException the io exception + */ public RlpBlockImporter.ImportResult importBlockchain( final Path blocks, final BesuController besuController, @@ -89,15 +103,12 @@ public RlpBlockImporter.ImportResult importBlockchain( final ProtocolContext context = besuController.getProtocolContext(); final MutableBlockchain blockchain = context.getBlockchain(); int count = 0; - - try (final RawBlockIterator iterator = - new RawBlockIterator( - blocks, - rlp -> - BlockHeader.readFrom( - rlp, ScheduleBasedBlockHeaderFunctions.create(protocolSchedule)))) { + final BlockHeaderFunctions blockHeaderFunctions = + ScheduleBasedBlockHeaderFunctions.create(protocolSchedule); + try (final RawBlockIterator iterator = new RawBlockIterator(blocks, blockHeaderFunctions)) { BlockHeader previousHeader = null; CompletableFuture previousBlockFuture = null; + final AtomicReference threadedException = new AtomicReference<>(); while (iterator.hasNext()) { final Block block = iterator.next(); final BlockHeader header = block.getHeader(); @@ -113,7 +124,7 @@ public RlpBlockImporter.ImportResult importBlockchain( if (previousHeader == null) { previousHeader = lookupPreviousHeader(blockchain, header); } - final ProtocolSpec protocolSpec = protocolSchedule.getByBlockNumber(blockNumber); + final ProtocolSpec protocolSpec = protocolSchedule.getByBlockHeader(header); final BlockHeader lastHeader = previousHeader; final CompletableFuture validationFuture = @@ -132,7 +143,12 @@ public RlpBlockImporter.ImportResult importBlockchain( } try { - blockBacklog.acquire(); + do { + final Throwable t = (Exception) threadedException.get(); + if (t != null) { + throw new RuntimeException("Error importing block " + header.getNumber(), t); + } + } while (!blockBacklog.tryAcquire(1, SECONDS)); } catch (final InterruptedException e) { LOG.error("Interrupted adding to backlog.", e); break; @@ -142,6 +158,11 @@ public RlpBlockImporter.ImportResult importBlockchain( calculationFutures, () -> evaluateBlock(context, block, header, protocolSpec, skipPowValidation), importExecutor); + previousBlockFuture.exceptionally( + exception -> { + threadedException.set(exception); + return null; + }); ++count; previousHeader = header; @@ -196,7 +217,7 @@ private void evaluateBlock( cumulativeTimer.start(); segmentTimer.start(); final BlockImporter blockImporter = protocolSpec.getBlockImporter(); - final boolean blockImported = + final BlockImportResult blockImported = blockImporter.importBlock( context, block, @@ -204,7 +225,7 @@ private void evaluateBlock( ? HeaderValidationMode.LIGHT_SKIP_DETACHED : HeaderValidationMode.SKIP_DETACHED, skipPowValidation ? HeaderValidationMode.LIGHT : HeaderValidationMode.FULL); - if (!blockImported) { + if (!blockImported.isImported()) { throw new IllegalStateException( "Invalid block at block number " + header.getNumber() + "."); } @@ -225,7 +246,7 @@ private void logProgress(final long blockNum) { final long elapseMicros = segmentTimer.elapsed(TimeUnit.MICROSECONDS); //noinspection PlaceholderCountMatchesArgumentCount LOG.info( - "Import at block %8d / %,14d gas %,11d micros / Mgps %7.3f segment %6.3f cumulative", + "Import at block {} / {} gas {} micros / Mgps {} segment {} cumulative", blockNum, segmentGas, elapseMicros, @@ -251,6 +272,7 @@ private BlockHeader lookupPreviousHeader( public void close() { validationExecutor.shutdownNow(); try { + //noinspection ResultOfMethodCallIgnored validationExecutor.awaitTermination(5, SECONDS); } catch (final Exception e) { LOG.error("Error shutting down validatorExecutor.", e); @@ -258,18 +280,28 @@ public void close() { importExecutor.shutdownNow(); try { + //noinspection ResultOfMethodCallIgnored importExecutor.awaitTermination(5, SECONDS); } catch (final Exception e) { LOG.error("Error shutting down importExecutor", e); } } + /** The Import result. */ public static final class ImportResult { + /** The difficulty. */ public final Difficulty td; + /** The Count. */ final int count; + /** + * Instantiates a new Import result. + * + * @param td the td + * @param count the count + */ ImportResult(final Difficulty td, final int count) { this.td = td; this.count = count; diff --git a/besu/src/main/java/org/hyperledger/besu/chainimport/internal/BlockData.java b/besu/src/main/java/org/hyperledger/besu/chainimport/internal/BlockData.java index 7a10a6f490a..b8dde10a7e9 100644 --- a/besu/src/main/java/org/hyperledger/besu/chainimport/internal/BlockData.java +++ b/besu/src/main/java/org/hyperledger/besu/chainimport/internal/BlockData.java @@ -15,11 +15,11 @@ package org.hyperledger.besu.chainimport.internal; import org.hyperledger.besu.chainimport.internal.TransactionData.NonceProvider; -import org.hyperledger.besu.ethereum.core.Account; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.Transaction; -import org.hyperledger.besu.ethereum.core.WorldState; +import org.hyperledger.besu.evm.account.Account; +import org.hyperledger.besu.evm.worldstate.WorldState; import java.util.HashMap; import java.util.List; @@ -33,6 +33,9 @@ import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt256; +/** + * Represents BlockData used in ChainData. Meant to be constructed by Json serializer/deserializer. + */ @JsonIgnoreProperties("comment") public class BlockData { @@ -42,6 +45,15 @@ public class BlockData { private final Optional

coinbase; private final Optional extraData; + /** + * Constructor for BlockData + * + * @param number Block number in hex format. + * @param parentHash Parent hash in hex format. + * @param coinbase Coinbase Address in hex format. + * @param extraData Extra data in hex format. + * @param transactions list of TransactionData. + */ @JsonCreator public BlockData( @JsonProperty("number") final Optional number, @@ -56,27 +68,59 @@ public BlockData( this.transactionData = transactions; } + /** + * Gets number. + * + * @return the number + */ public Optional getNumber() { return number; } + /** + * Gets parent hash. + * + * @return the parent hash + */ public Optional getParentHash() { return parentHash; } + /** + * Gets coinbase. + * + * @return the coinbase + */ public Optional
getCoinbase() { return coinbase; } + /** + * Gets extra data. + * + * @return the extra data + */ public Optional getExtraData() { return extraData; } + /** + * Stream transactions. + * + * @param worldState the world state + * @return the stream of Transaction + */ public Stream streamTransactions(final WorldState worldState) { final NonceProvider nonceProvider = getNonceProvider(worldState); return transactionData.stream().map((tx) -> tx.getSignedTransaction(nonceProvider)); } + /** + * Gets nonce provider. + * + * @param worldState the world state + * @return the nonce provider + */ public NonceProvider getNonceProvider(final WorldState worldState) { final HashMap currentNonceValues = new HashMap<>(); return (Address address) -> diff --git a/besu/src/main/java/org/hyperledger/besu/chainimport/internal/ChainData.java b/besu/src/main/java/org/hyperledger/besu/chainimport/internal/ChainData.java index 1c525255c8c..cb9528b7e5c 100644 --- a/besu/src/main/java/org/hyperledger/besu/chainimport/internal/ChainData.java +++ b/besu/src/main/java/org/hyperledger/besu/chainimport/internal/ChainData.java @@ -20,16 +20,27 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +/** The Chain data. */ @JsonIgnoreProperties("comment") public class ChainData { private final List blocks; + /** + * Instantiates a new Chain data. + * + * @param blocks the blocks + */ @JsonCreator public ChainData(@JsonProperty("blocks") final List blocks) { this.blocks = blocks; } + /** + * Gets blocks. + * + * @return the blocks + */ public List getBlocks() { return blocks; } diff --git a/besu/src/main/java/org/hyperledger/besu/chainimport/internal/TransactionData.java b/besu/src/main/java/org/hyperledger/besu/chainimport/internal/TransactionData.java index 558efc55d83..6358021af17 100644 --- a/besu/src/main/java/org/hyperledger/besu/chainimport/internal/TransactionData.java +++ b/besu/src/main/java/org/hyperledger/besu/chainimport/internal/TransactionData.java @@ -14,21 +14,26 @@ */ package org.hyperledger.besu.chainimport.internal; -import org.hyperledger.besu.crypto.SECP256K1.KeyPair; -import org.hyperledger.besu.crypto.SECP256K1.PrivateKey; -import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.crypto.KeyPair; +import org.hyperledger.besu.crypto.SECPPrivateKey; +import org.hyperledger.besu.crypto.SignatureAlgorithm; +import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.Transaction; -import org.hyperledger.besu.ethereum.core.Wei; import java.util.Optional; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt256; +/** The Transaction data. */ @JsonIgnoreProperties("comment") public class TransactionData { @@ -37,8 +42,21 @@ public class TransactionData { private final Bytes data; private final Wei value; private final Optional
to; - private final PrivateKey privateKey; + private final SECPPrivateKey privateKey; + private static final Supplier SIGNATURE_ALGORITHM = + Suppliers.memoize(SignatureAlgorithmFactory::getInstance); + + /** + * Instantiates a new Transaction data. + * + * @param gasLimit the gas limit + * @param gasPrice the gas price + * @param data the data + * @param value the value + * @param to the to + * @param secretKey the secret key + */ @JsonCreator public TransactionData( @JsonProperty("gasLimit") final String gasLimit, @@ -52,11 +70,17 @@ public TransactionData( this.data = data.map(Bytes::fromHexString).orElse(Bytes.EMPTY); this.value = value.map(Wei::fromHexString).orElse(Wei.ZERO); this.to = to.map(Address::fromHexString); - this.privateKey = PrivateKey.create(Bytes32.fromHexString(secretKey)); + this.privateKey = SIGNATURE_ALGORITHM.get().createPrivateKey(Bytes32.fromHexString(secretKey)); } + /** + * Gets signed transaction. + * + * @param nonceProvider the nonce provider + * @return the signed transaction + */ public Transaction getSignedTransaction(final NonceProvider nonceProvider) { - final KeyPair keyPair = KeyPair.create(privateKey); + final KeyPair keyPair = SIGNATURE_ALGORITHM.get().createKeyPair(privateKey); final Address fromAddress = Address.extract(keyPair.getPublicKey()); final long nonce = nonceProvider.get(fromAddress); @@ -71,8 +95,15 @@ public Transaction getSignedTransaction(final NonceProvider nonceProvider) { .signAndBuild(keyPair); } + /** The interface Nonce provider. */ @FunctionalInterface public interface NonceProvider { + /** + * Get Nonce. + * + * @param address the address + * @return the Nonce + */ long get(final Address address); } } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 5df5a0d11e9..87fc5a545d3 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -15,18 +15,23 @@ package org.hyperledger.besu.cli; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.hyperledger.besu.cli.DefaultCommandValues.getDefaultBesuDataPath; import static org.hyperledger.besu.cli.config.NetworkName.MAINNET; import static org.hyperledger.besu.cli.util.CommandLineUtils.DEPENDENCY_WARNING_MSG; +import static org.hyperledger.besu.cli.util.CommandLineUtils.DEPRECATION_WARNING_MSG; import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH; import static org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration.DEFAULT_GRAPHQL_HTTP_PORT; +import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration.DEFAULT_ENGINE_JSON_RPC_PORT; import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration.DEFAULT_JSON_RPC_PORT; -import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_JSON_RPC_APIS; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_RPC_APIS; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.VALID_APIS; +import static org.hyperledger.besu.ethereum.api.jsonrpc.authentication.EngineAuthService.EPHEMERAL_JWT_FILE; import static org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration.DEFAULT_WEBSOCKET_PORT; -import static org.hyperledger.besu.ethereum.permissioning.QuorumPermissioningConfiguration.QIP714_DEFAULT_BLOCK; +import static org.hyperledger.besu.ethereum.permissioning.GoQuorumPermissioningConfiguration.QIP714_DEFAULT_BLOCK; import static org.hyperledger.besu.metrics.BesuMetricCategory.DEFAULT_METRIC_CATEGORIES; import static org.hyperledger.besu.metrics.MetricsProtocol.PROMETHEUS; import static org.hyperledger.besu.metrics.prometheus.MetricsConfiguration.DEFAULT_METRICS_PORT; @@ -41,22 +46,31 @@ import org.hyperledger.besu.chainimport.RlpBlockImporter; import org.hyperledger.besu.cli.config.EthNetworkConfig; import org.hyperledger.besu.cli.config.NetworkName; +import org.hyperledger.besu.cli.converter.FractionConverter; import org.hyperledger.besu.cli.converter.MetricCategoryConverter; import org.hyperledger.besu.cli.converter.PercentageConverter; -import org.hyperledger.besu.cli.converter.RpcApisConverter; import org.hyperledger.besu.cli.custom.CorsAllowedOriginsProperty; import org.hyperledger.besu.cli.custom.JsonRPCAllowlistHostsProperty; import org.hyperledger.besu.cli.custom.RpcAuthFileValidator; -import org.hyperledger.besu.cli.error.BesuExceptionHandler; -import org.hyperledger.besu.cli.options.unstable.DataStorageOptions; +import org.hyperledger.besu.cli.error.BesuExecutionExceptionHandler; +import org.hyperledger.besu.cli.error.BesuParameterExceptionHandler; +import org.hyperledger.besu.cli.options.stable.DataStorageOptions; +import org.hyperledger.besu.cli.options.stable.EthstatsOptions; +import org.hyperledger.besu.cli.options.stable.LoggingLevelOption; +import org.hyperledger.besu.cli.options.stable.NodePrivateKeyFileOption; +import org.hyperledger.besu.cli.options.stable.P2PTLSConfigOptions; +import org.hyperledger.besu.cli.options.unstable.ChainPruningOptions; import org.hyperledger.besu.cli.options.unstable.DnsOptions; import org.hyperledger.besu.cli.options.unstable.EthProtocolOptions; -import org.hyperledger.besu.cli.options.unstable.EthstatsOptions; +import org.hyperledger.besu.cli.options.unstable.EvmOptions; +import org.hyperledger.besu.cli.options.unstable.IpcOptions; import org.hyperledger.besu.cli.options.unstable.MetricsCLIOptions; import org.hyperledger.besu.cli.options.unstable.MiningOptions; import org.hyperledger.besu.cli.options.unstable.NatOptions; import org.hyperledger.besu.cli.options.unstable.NativeLibraryOptions; import org.hyperledger.besu.cli.options.unstable.NetworkingOptions; +import org.hyperledger.besu.cli.options.unstable.PkiBlockCreationOptions; +import org.hyperledger.besu.cli.options.unstable.PrivacyPluginOptions; import org.hyperledger.besu.cli.options.unstable.RPCOptions; import org.hyperledger.besu.cli.options.unstable.SynchronizerOptions; import org.hyperledger.besu.cli.options.unstable.TransactionPoolOptions; @@ -65,60 +79,76 @@ import org.hyperledger.besu.cli.subcommands.PasswordSubCommand; import org.hyperledger.besu.cli.subcommands.PublicKeySubCommand; import org.hyperledger.besu.cli.subcommands.RetestethSubCommand; +import org.hyperledger.besu.cli.subcommands.ValidateConfigSubCommand; import org.hyperledger.besu.cli.subcommands.blocks.BlocksSubCommand; import org.hyperledger.besu.cli.subcommands.operator.OperatorSubCommand; import org.hyperledger.besu.cli.subcommands.rlp.RLPSubCommand; +import org.hyperledger.besu.cli.subcommands.storage.StorageSubCommand; import org.hyperledger.besu.cli.util.BesuCommandCustomFactory; import org.hyperledger.besu.cli.util.CommandLineUtils; import org.hyperledger.besu.cli.util.ConfigOptionSearchAndRunHandler; import org.hyperledger.besu.cli.util.VersionProvider; +import org.hyperledger.besu.components.BesuComponent; +import org.hyperledger.besu.config.CheckpointConfigOptions; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.GenesisConfigOptions; -import org.hyperledger.besu.config.GoQuorumOptions; -import org.hyperledger.besu.config.experimental.ExperimentalEIPs; +import org.hyperledger.besu.config.MergeConfigOptions; +import org.hyperledger.besu.consensus.qbft.pki.PkiBlockCreationConfiguration; +import org.hyperledger.besu.consensus.qbft.pki.PkiBlockCreationConfigurationProvider; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.controller.BesuControllerBuilder; -import org.hyperledger.besu.controller.TargetingGasLimitCalculator; -import org.hyperledger.besu.crypto.KeyPairSecurityModule; +import org.hyperledger.besu.crypto.Blake2bfMessageDigest; +import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.KeyPairUtil; -import org.hyperledger.besu.crypto.NodeKey; -import org.hyperledger.besu.crypto.SECP256K1; +import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; +import org.hyperledger.besu.crypto.SignatureAlgorithmType; +import org.hyperledger.besu.cryptoservices.KeyPairSecurityModule; +import org.hyperledger.besu.cryptoservices.NodeKey; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.enclave.EnclaveFactory; +import org.hyperledger.besu.ethereum.GasLimitCalculator; import org.hyperledger.besu.ethereum.api.ApiConfiguration; import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; +import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.JwtAlgorithm; +import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; +import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider; import org.hyperledger.besu.ethereum.api.tls.TlsClientAuthConfiguration; import org.hyperledger.besu.ethereum.api.tls.TlsConfiguration; -import org.hyperledger.besu.ethereum.blockcreation.GasLimitCalculator; import org.hyperledger.besu.ethereum.chain.Blockchain; -import org.hyperledger.besu.ethereum.core.Address; -import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters; -import org.hyperledger.besu.ethereum.core.Wei; import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; -import org.hyperledger.besu.ethereum.mainnet.precompiles.AbstractAltBnPrecompiledContract; +import org.hyperledger.besu.ethereum.mainnet.FrontierTargetingGasLimitCalculator; import org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration; import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration; -import org.hyperledger.besu.ethereum.p2p.peers.EnodeURL; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.ethereum.p2p.peers.StaticNodesParser; +import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; +import org.hyperledger.besu.ethereum.permissioning.GoQuorumPermissioningConfiguration; import org.hyperledger.besu.ethereum.permissioning.LocalPermissioningConfiguration; import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; import org.hyperledger.besu.ethereum.permissioning.PermissioningConfigurationBuilder; -import org.hyperledger.besu.ethereum.permissioning.QuorumPermissioningConfiguration; import org.hyperledger.besu.ethereum.permissioning.SmartContractPermissioningConfiguration; import org.hyperledger.besu.ethereum.privacy.storage.keyvalue.PrivacyKeyValueStorageProvider; import org.hyperledger.besu.ethereum.privacy.storage.keyvalue.PrivacyKeyValueStorageProviderBuilder; +import org.hyperledger.besu.ethereum.storage.StorageProvider; +import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder; import org.hyperledger.besu.ethereum.worldstate.PrunerConfiguration; +import org.hyperledger.besu.evm.precompile.AbstractAltBnPrecompiledContract; +import org.hyperledger.besu.evm.precompile.BigIntegerModularExponentiationPrecompiledContract; +import org.hyperledger.besu.evm.precompile.KZGPointEvalPrecompiledContract; import org.hyperledger.besu.metrics.BesuMetricCategory; import org.hyperledger.besu.metrics.MetricCategoryRegistryImpl; import org.hyperledger.besu.metrics.MetricsProtocol; @@ -128,24 +158,40 @@ import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.metrics.vertx.VertxMetricsAdapterFactory; import org.hyperledger.besu.nat.NatMethod; +import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.plugin.services.BesuConfiguration; import org.hyperledger.besu.plugin.services.BesuEvents; +import org.hyperledger.besu.plugin.services.BlockchainService; import org.hyperledger.besu.plugin.services.MetricsSystem; +import org.hyperledger.besu.plugin.services.PermissioningService; import org.hyperledger.besu.plugin.services.PicoCLIOptions; +import org.hyperledger.besu.plugin.services.PrivacyPluginService; +import org.hyperledger.besu.plugin.services.RpcEndpointService; import org.hyperledger.besu.plugin.services.SecurityModuleService; import org.hyperledger.besu.plugin.services.StorageService; +import org.hyperledger.besu.plugin.services.TraceService; +import org.hyperledger.besu.plugin.services.TransactionSelectionService; import org.hyperledger.besu.plugin.services.exception.StorageException; import org.hyperledger.besu.plugin.services.metrics.MetricCategory; import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry; import org.hyperledger.besu.plugin.services.securitymodule.SecurityModule; import org.hyperledger.besu.plugin.services.storage.PrivacyKeyValueStorageFactory; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin; +import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory; import org.hyperledger.besu.services.BesuEventsImpl; import org.hyperledger.besu.services.BesuPluginContextImpl; +import org.hyperledger.besu.services.BlockchainServiceImpl; +import org.hyperledger.besu.services.PermissioningServiceImpl; import org.hyperledger.besu.services.PicoCLIOptionsImpl; +import org.hyperledger.besu.services.PrivacyPluginServiceImpl; +import org.hyperledger.besu.services.RpcEndpointServiceImpl; import org.hyperledger.besu.services.SecurityModuleServiceImpl; import org.hyperledger.besu.services.StorageServiceImpl; +import org.hyperledger.besu.services.TraceServiceImpl; +import org.hyperledger.besu.services.TransactionSelectionServiceImpl; import org.hyperledger.besu.services.kvstore.InMemoryStoragePlugin; +import org.hyperledger.besu.util.InvalidConfigurationException; +import org.hyperledger.besu.util.LogConfigurator; import org.hyperledger.besu.util.NetworkUtility; import org.hyperledger.besu.util.PermissioningConfigurationValidator; import org.hyperledger.besu.util.number.Fraction; @@ -161,8 +207,11 @@ import java.net.URI; import java.net.UnknownHostException; import java.nio.file.Path; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; import java.time.Clock; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -174,8 +223,11 @@ import java.util.Set; import java.util.TreeMap; import java.util.function.Function; +import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; @@ -186,19 +238,20 @@ import io.vertx.core.VertxOptions; import io.vertx.core.json.DecodeException; import io.vertx.core.metrics.MetricsOptions; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.core.config.Configurator; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.units.bigints.UInt256; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import picocli.AutoComplete; import picocli.CommandLine; -import picocli.CommandLine.AbstractParseResultHandler; import picocli.CommandLine.Command; import picocli.CommandLine.ExecutionException; +import picocli.CommandLine.IExecutionStrategy; +import picocli.CommandLine.Mixin; import picocli.CommandLine.Option; import picocli.CommandLine.ParameterException; +/** Represents the main Besu CLI command that runs the Besu Ethereum client full node. */ @SuppressWarnings("FieldCanBeLocal") // because Picocli injected fields report false positives @Command( description = "This command runs the Besu Ethereum client full node.", @@ -206,10 +259,10 @@ name = "besu", mixinStandardHelpOptions = true, versionProvider = VersionProvider.class, - header = "Usage:", + header = "@|bold,fg(cyan) Usage:|@", synopsisHeading = "%n", - descriptionHeading = "%nDescription:%n%n", - optionListHeading = "%nOptions:%n", + descriptionHeading = "%n@|bold,fg(cyan) Description:|@%n%n", + optionListHeading = "%n@|bold,fg(cyan) Options:|@%n", footerHeading = "%n", footer = "Besu is licensed under the Apache License 2.0") public class BesuCommand implements DefaultCommandValues, Runnable { @@ -230,31 +283,49 @@ public class BesuCommand implements DefaultCommandValues, Runnable { final EthProtocolOptions unstableEthProtocolOptions = EthProtocolOptions.create(); final MetricsCLIOptions unstableMetricsCLIOptions = MetricsCLIOptions.create(); final TransactionPoolOptions unstableTransactionPoolOptions = TransactionPoolOptions.create(); - private final EthstatsOptions unstableEthstatsOptions = EthstatsOptions.create(); - private final DataStorageOptions unstableDataStorageOptions = DataStorageOptions.create(); private final DnsOptions unstableDnsOptions = DnsOptions.create(); private final MiningOptions unstableMiningOptions = MiningOptions.create(); private final NatOptions unstableNatOptions = NatOptions.create(); private final NativeLibraryOptions unstableNativeLibraryOptions = NativeLibraryOptions.create(); private final RPCOptions unstableRPCOptions = RPCOptions.create(); + private final PrivacyPluginOptions unstablePrivacyPluginOptions = PrivacyPluginOptions.create(); + private final EvmOptions unstableEvmOptions = EvmOptions.create(); + private final IpcOptions unstableIpcOptions = IpcOptions.create(); + private final ChainPruningOptions unstableChainPruningOptions = ChainPruningOptions.create(); + + // stable CLI options + private final DataStorageOptions dataStorageOptions = DataStorageOptions.create(); + private final EthstatsOptions ethstatsOptions = EthstatsOptions.create(); + private final NodePrivateKeyFileOption nodePrivateKeyFileOption = + NodePrivateKeyFileOption.create(); + private final LoggingLevelOption loggingLevelOption = LoggingLevelOption.create(); private final RunnerBuilder runnerBuilder; private final BesuController.Builder controllerBuilderFactory; private final BesuPluginContextImpl besuPluginContext; private final StorageServiceImpl storageService; private final SecurityModuleServiceImpl securityModuleService; + private final PermissioningServiceImpl permissioningService; + private final PrivacyPluginServiceImpl privacyPluginService; + private final RpcEndpointServiceImpl rpcEndpointServiceImpl; + private final Map environment; private final MetricCategoryRegistryImpl metricCategoryRegistry = new MetricCategoryRegistryImpl(); private final MetricCategoryConverter metricCategoryConverter = new MetricCategoryConverter(); - // Public IP stored to prevent having to research it each time we need it. - private InetAddress autoDiscoveredDefaultIP = null; - private final PreSynchronizationTaskRunner preSynchronizationTaskRunner = new PreSynchronizationTaskRunner(); private final Set allocatedPorts = new HashSet<>(); + private final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider; + private GenesisConfigOptions genesisConfigOptions; + + private RocksDBPlugin rocksDBPlugin; + + private int maxPeers; + private int maxRemoteInitiatedPeers; + private int peersLowerBound; // CLI options defined by user at runtime. // Options parsing is done with CLI library Picocli https://picocli.info/ @@ -286,110 +357,155 @@ public class BesuCommand implements DefaultCommandValues, Runnable { "Genesis file. Setting this option makes --network option ignored and requires --network-id to be set.") private final File genesisFile = null; - @CommandLine.Option( - names = {"--node-private-key-file"}, - paramLabel = MANDATORY_PATH_FORMAT_HELP, - description = - "The node's private key file (default: a file named \"key\" in the Besu data folder)") - private final File nodePrivateKeyFile = null; - @Option( names = "--identity", paramLabel = "", description = "Identification for this node in the Client ID", arity = "1") private final Optional identityString = Optional.empty(); + // P2P Discovery Option Group + @CommandLine.ArgGroup(validate = false, heading = "@|bold P2P Discovery Options|@%n") + P2PDiscoveryOptionGroup p2PDiscoveryOptionGroup = new P2PDiscoveryOptionGroup(); + + private final TransactionSelectionServiceImpl transactionSelectionServiceImpl; + + static class P2PDiscoveryOptionGroup { + + // Public IP stored to prevent having to research it each time we need it. + private InetAddress autoDiscoveredDefaultIP = null; + + // Completely disables P2P within Besu. + @Option( + names = {"--p2p-enabled"}, + description = "Enable P2P functionality (default: ${DEFAULT-VALUE})", + arity = "1") + private final Boolean p2pEnabled = true; + + // Boolean option to indicate if peers should NOT be discovered, default to + // false indicates that + // the peers should be discovered by default. + // + // This negative option is required because of the nature of the option that is + // true when + // added on the command line. You can't do --option=false, so false is set as + // default + // and you have not to set the option at all if you want it false. + // This seems to be the only way it works with Picocli. + // Also many other software use the same negative option scheme for false + // defaults + // meaning that it's probably the right way to handle disabling options. + @Option( + names = {"--discovery-enabled"}, + description = "Enable P2P discovery (default: ${DEFAULT-VALUE})", + arity = "1") + private final Boolean peerDiscoveryEnabled = true; + + // A list of bootstrap nodes can be passed + // and a hardcoded list will be used otherwise by the Runner. + // NOTE: we have no control over default value here. + @Option( + names = {"--bootnodes"}, + paramLabel = "", + description = + "Comma separated enode URLs for P2P discovery bootstrap. " + + "Default is a predefined list.", + split = ",", + arity = "0..*") + private final List bootNodes = null; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @Option( + names = {"--p2p-host"}, + paramLabel = MANDATORY_HOST_FORMAT_HELP, + description = "IP address this node advertises to its peers (default: ${DEFAULT-VALUE})", + arity = "1") + private String p2pHost = autoDiscoverDefaultIP().getHostAddress(); + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @Option( + names = {"--p2p-interface"}, + paramLabel = MANDATORY_HOST_FORMAT_HELP, + description = + "The network interface address on which this node listens for P2P communication (default: ${DEFAULT-VALUE})", + arity = "1") + private String p2pInterface = NetworkUtility.INADDR_ANY; + + @Option( + names = {"--p2p-port"}, + paramLabel = MANDATORY_PORT_FORMAT_HELP, + description = "Port on which to listen for P2P communication (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer p2pPort = EnodeURLImpl.DEFAULT_LISTENING_PORT; + + @Option( + names = {"--max-peers", "--p2p-peer-upper-bound"}, + paramLabel = MANDATORY_INTEGER_FORMAT_HELP, + description = "Maximum P2P connections that can be established (default: ${DEFAULT-VALUE})") + private final Integer maxPeers = DEFAULT_MAX_PEERS; + + @Option( + names = {"--remote-connections-limit-enabled"}, + description = + "Whether to limit the number of P2P connections initiated remotely. (default: ${DEFAULT-VALUE})") + private final Boolean isLimitRemoteWireConnectionsEnabled = true; + + @Option( + names = {"--remote-connections-max-percentage"}, + paramLabel = MANDATORY_DOUBLE_FORMAT_HELP, + description = + "The maximum percentage of P2P connections that can be initiated remotely. Must be between 0 and 100 inclusive. (default: ${DEFAULT-VALUE})", + arity = "1", + converter = PercentageConverter.class) + private final Integer maxRemoteConnectionsPercentage = + Fraction.fromFloat(DEFAULT_FRACTION_REMOTE_WIRE_CONNECTIONS_ALLOWED) + .toPercentage() + .getValue(); + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @CommandLine.Option( + names = {"--discovery-dns-url"}, + description = "Specifies the URL to use for DNS discovery") + private String discoveryDnsUrl = null; + + @Option( + names = {"--random-peer-priority-enabled"}, + description = + "Allow for incoming connections to be prioritized randomly. This will prevent (typically small, stable) networks from forming impenetrable peer cliques. (default: ${DEFAULT-VALUE})") + private final Boolean randomPeerPriority = Boolean.FALSE; + + @Option( + names = {"--banned-node-ids", "--banned-node-id"}, + paramLabel = MANDATORY_NODE_ID_FORMAT_HELP, + description = "A list of node IDs to ban from the P2P network.", + split = ",", + arity = "1..*") + void setBannedNodeIds(final List values) { + try { + bannedNodeIds = + values.stream() + .filter(value -> !value.isEmpty()) + .map(EnodeURLImpl::parseNodeId) + .collect(Collectors.toList()); + } catch (final IllegalArgumentException e) { + throw new ParameterException( + new CommandLine(this), + "Invalid ids supplied to '--banned-node-ids'. " + e.getMessage()); + } + } - // Completely disables P2P within Besu. - @Option( - names = {"--p2p-enabled"}, - description = "Enable P2P functionality (default: ${DEFAULT-VALUE})", - arity = "1") - private final Boolean p2pEnabled = true; - - // Boolean option to indicate if peers should NOT be discovered, default to - // false indicates that - // the peers should be discovered by default. - // - // This negative option is required because of the nature of the option that is - // true when - // added on the command line. You can't do --option=false, so false is set as - // default - // and you have not to set the option at all if you want it false. - // This seems to be the only way it works with Picocli. - // Also many other software use the same negative option scheme for false - // defaults - // meaning that it's probably the right way to handle disabling options. - @Option( - names = {"--discovery-enabled"}, - description = "Enable P2P discovery (default: ${DEFAULT-VALUE})", - arity = "1") - private final Boolean peerDiscoveryEnabled = true; - - // A list of bootstrap nodes can be passed - // and a hardcoded list will be used otherwise by the Runner. - // NOTE: we have no control over default value here. - @Option( - names = {"--bootnodes"}, - paramLabel = "", - description = - "Comma separated enode URLs for P2P discovery bootstrap. " - + "Default is a predefined list.", - split = ",", - arity = "0..*") - private final List bootNodes = null; - - @Option( - names = {"--max-peers"}, - paramLabel = MANDATORY_INTEGER_FORMAT_HELP, - description = "Maximum P2P connections that can be established (default: ${DEFAULT-VALUE})") - private final Integer maxPeers = DEFAULT_MAX_PEERS; - - @Option( - names = {"--remote-connections-limit-enabled"}, - description = - "Whether to limit the number of P2P connections initiated remotely. (default: ${DEFAULT-VALUE})") - private final Boolean isLimitRemoteWireConnectionsEnabled = true; - - @Option( - names = {"--remote-connections-max-percentage"}, - paramLabel = MANDATORY_DOUBLE_FORMAT_HELP, - description = - "The maximum percentage of P2P connections that can be initiated remotely. Must be between 0 and 100 inclusive. (default: ${DEFAULT-VALUE})", - arity = "1", - converter = PercentageConverter.class) - private final Integer maxRemoteConnectionsPercentage = - Fraction.fromFloat(DEFAULT_FRACTION_REMOTE_WIRE_CONNECTIONS_ALLOWED) - .toPercentage() - .getValue(); + private Collection bannedNodeIds = new ArrayList<>(); - @Option( - names = {"--random-peer-priority-enabled"}, - description = - "Allow for incoming connections to be prioritized randomly. This will prevent (typically small, stable) networks from forming impenetrable peer cliques. (default: ${DEFAULT-VALUE})") - private final Boolean randomPeerPriority = false; + // Used to discover the default IP of the client. + // Loopback IP is used by default as this is how smokeTests require it to be + // and it's probably a good security behaviour to default only on the localhost. + private InetAddress autoDiscoverDefaultIP() { + autoDiscoveredDefaultIP = + Optional.ofNullable(autoDiscoveredDefaultIP).orElseGet(InetAddress::getLoopbackAddress); - @Option( - names = {"--banned-node-ids", "--banned-node-id"}, - paramLabel = MANDATORY_NODE_ID_FORMAT_HELP, - description = "A list of node IDs to ban from the P2P network.", - split = ",", - arity = "1..*") - void setBannedNodeIds(final List values) { - try { - bannedNodeIds = - values.stream() - .filter(value -> !value.isEmpty()) - .map(EnodeURL::parseNodeId) - .collect(Collectors.toList()); - } catch (final IllegalArgumentException e) { - throw new ParameterException( - commandLine, "Invalid ids supplied to '--banned-node-ids'. " + e.getMessage()); + return autoDiscoveredDefaultIP; } } - private Collection bannedNodeIds = new ArrayList<>(); - @Option( names = {"--sync-mode"}, paramLabel = MANDATORY_MODE_FORMAT_HELP, @@ -401,41 +517,18 @@ void setBannedNodeIds(final List values) { names = {"--fast-sync-min-peers"}, paramLabel = MANDATORY_INTEGER_FORMAT_HELP, description = - "Minimum number of peers required before starting fast sync. (default: ${DEFAULT-VALUE})") + "Minimum number of peers required before starting fast sync. Has only effect on PoW networks. (default: ${DEFAULT-VALUE})") private final Integer fastSyncMinPeerCount = FAST_SYNC_MIN_PEER_COUNT; @Option( names = {"--network"}, paramLabel = MANDATORY_NETWORK_FORMAT_HELP, + defaultValue = "MAINNET", description = "Synchronize against the indicated network, possible values are ${COMPLETION-CANDIDATES}." - + " (default: MAINNET)") + + " (default: ${DEFAULT-VALUE})") private final NetworkName network = null; - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--p2p-host"}, - paramLabel = MANDATORY_HOST_FORMAT_HELP, - description = "Ip address this node advertises to its peers (default: ${DEFAULT-VALUE})", - arity = "1") - private String p2pHost = autoDiscoverDefaultIP().getHostAddress(); - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--p2p-interface"}, - paramLabel = MANDATORY_HOST_FORMAT_HELP, - description = - "The network interface address on which this node listens for P2P communication (default: ${DEFAULT-VALUE})", - arity = "1") - private String p2pInterface = NetworkUtility.INADDR_ANY; - - @Option( - names = {"--p2p-port"}, - paramLabel = MANDATORY_PORT_FORMAT_HELP, - description = "Port on which to listen for P2P communication (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer p2pPort = EnodeURL.DEFAULT_LISTENING_PORT; - @Option( names = {"--nat-method"}, description = @@ -452,275 +545,488 @@ void setBannedNodeIds(final List values) { private final BigInteger networkId = null; @Option( - names = {"--graphql-http-enabled"}, - description = "Set to start the GraphQL HTTP service (default: ${DEFAULT-VALUE})") - private final Boolean isGraphQLHttpEnabled = false; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--graphql-http-host"}, - paramLabel = MANDATORY_HOST_FORMAT_HELP, - description = "Host for GraphQL HTTP to listen on (default: ${DEFAULT-VALUE})", - arity = "1") - private String graphQLHttpHost = autoDiscoverDefaultIP().getHostAddress(); - - @Option( - names = {"--graphql-http-port"}, - paramLabel = MANDATORY_PORT_FORMAT_HELP, - description = "Port for GraphQL HTTP to listen on (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer graphQLHttpPort = DEFAULT_GRAPHQL_HTTP_PORT; - - @Option( - names = {"--graphql-http-cors-origins"}, - description = "Comma separated origin domain URLs for CORS validation (default: none)") - private final CorsAllowedOriginsProperty graphQLHttpCorsAllowedOrigins = - new CorsAllowedOriginsProperty(); - - @Option( - names = {"--rpc-http-enabled"}, - description = "Set to start the JSON-RPC HTTP service (default: ${DEFAULT-VALUE})") - private final Boolean isRpcHttpEnabled = false; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--rpc-http-host"}, - paramLabel = MANDATORY_HOST_FORMAT_HELP, - description = "Host for JSON-RPC HTTP to listen on (default: ${DEFAULT-VALUE})", - arity = "1") - private String rpcHttpHost = autoDiscoverDefaultIP().getHostAddress(); - - @Option( - names = {"--rpc-http-port"}, - paramLabel = MANDATORY_PORT_FORMAT_HELP, - description = "Port for JSON-RPC HTTP to listen on (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer rpcHttpPort = DEFAULT_JSON_RPC_PORT; - - // A list of origins URLs that are accepted by the JsonRpcHttpServer (CORS) - @Option( - names = {"--rpc-http-cors-origins"}, - description = "Comma separated origin domain URLs for CORS validation (default: none)") - private final CorsAllowedOriginsProperty rpcHttpCorsAllowedOrigins = - new CorsAllowedOriginsProperty(); - - @Option( - names = {"--rpc-http-api", "--rpc-http-apis"}, - paramLabel = "", - split = ",", - arity = "1..*", - converter = RpcApisConverter.class, - description = - "Comma separated list of APIs to enable on JSON-RPC HTTP service (default: ${DEFAULT-VALUE})") - private final Collection rpcHttpApis = DEFAULT_JSON_RPC_APIS; - - @Option( - names = {"--rpc-http-authentication-enabled"}, - description = - "Require authentication for the JSON-RPC HTTP service (default: ${DEFAULT-VALUE})") - private final Boolean isRpcHttpAuthenticationEnabled = false; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @CommandLine.Option( - names = {"--rpc-http-authentication-credentials-file"}, - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = - "Storage file for JSON-RPC HTTP authentication credentials (default: ${DEFAULT-VALUE})", - arity = "1") - private String rpcHttpAuthenticationCredentialsFile = null; - - @CommandLine.Option( - names = {"--rpc-http-authentication-jwt-public-key-file"}, - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = "JWT public key file for JSON-RPC HTTP authentication", - arity = "1") - private final File rpcHttpAuthenticationPublicKeyFile = null; - - @Option( - names = {"--rpc-http-tls-enabled"}, - description = "Enable TLS for the JSON-RPC HTTP service (default: ${DEFAULT-VALUE})") - private final Boolean isRpcHttpTlsEnabled = false; - - @Option( - names = {"--rpc-http-tls-keystore-file"}, - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = - "Keystore (PKCS#12) containing key/certificate for the JSON-RPC HTTP service. Required if TLS is enabled.") - private final Path rpcHttpTlsKeyStoreFile = null; - - @Option( - names = {"--rpc-http-tls-keystore-password-file"}, - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = - "File containing password to unlock keystore for the JSON-RPC HTTP service. Required if TLS is enabled.") - private final Path rpcHttpTlsKeyStorePasswordFile = null; - - @Option( - names = {"--rpc-http-tls-client-auth-enabled"}, - description = - "Enable TLS client authentication for the JSON-RPC HTTP service (default: ${DEFAULT-VALUE})") - private final Boolean isRpcHttpTlsClientAuthEnabled = false; - - @Option( - names = {"--rpc-http-tls-known-clients-file"}, - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = - "Path to file containing clients certificate common name and fingerprint for client authentication") - private final Path rpcHttpTlsKnownClientsFile = null; - - @Option( - names = {"--rpc-http-tls-ca-clients-enabled"}, - description = - "Enable to accept clients certificate signed by a valid CA for client authentication (default: ${DEFAULT-VALUE})") - private final Boolean isRpcHttpTlsCAClientsEnabled = false; - - @Option( - names = {"--rpc-ws-enabled"}, - description = "Set to start the JSON-RPC WebSocket service (default: ${DEFAULT-VALUE})") - private final Boolean isRpcWsEnabled = false; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--rpc-ws-host"}, - paramLabel = MANDATORY_HOST_FORMAT_HELP, - description = "Host for JSON-RPC WebSocket service to listen on (default: ${DEFAULT-VALUE})", - arity = "1") - private String rpcWsHost = autoDiscoverDefaultIP().getHostAddress(); - - @Option( - names = {"--rpc-ws-port"}, - paramLabel = MANDATORY_PORT_FORMAT_HELP, - description = "Port for JSON-RPC WebSocket service to listen on (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer rpcWsPort = DEFAULT_WEBSOCKET_PORT; - - @Option( - names = {"--rpc-ws-api", "--rpc-ws-apis"}, - paramLabel = "", - split = ",", - arity = "1..*", - converter = RpcApisConverter.class, - description = - "Comma separated list of APIs to enable on JSON-RPC WebSocket service (default: ${DEFAULT-VALUE})") - private final List rpcWsApis = DEFAULT_JSON_RPC_APIS; - - @Option( - names = {"--rpc-ws-authentication-enabled"}, - description = - "Require authentication for the JSON-RPC WebSocket service (default: ${DEFAULT-VALUE})") - private final Boolean isRpcWsAuthenticationEnabled = false; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @CommandLine.Option( - names = {"--rpc-ws-authentication-credentials-file"}, - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = - "Storage file for JSON-RPC WebSocket authentication credentials (default: ${DEFAULT-VALUE})", - arity = "1") - private String rpcWsAuthenticationCredentialsFile = null; - - @CommandLine.Option( - names = {"--rpc-ws-authentication-jwt-public-key-file"}, - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = "JWT public key file for JSON-RPC WebSocket authentication", - arity = "1") - private final File rpcWsAuthenticationPublicKeyFile = null; - - @Option( - names = {"--privacy-tls-enabled"}, - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = "Enable TLS for connecting to privacy enclave (default: ${DEFAULT-VALUE})") - private final Boolean isPrivacyTlsEnabled = false; - - @Option( - names = "--privacy-tls-keystore-file", - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = - "Path to a PKCS#12 formatted keystore; used to enable TLS on inbound connections.") - private final Path privacyKeyStoreFile = null; - - @Option( - names = "--privacy-tls-keystore-password-file", - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = "Path to a file containing the password used to decrypt the keystore.") - private final Path privacyKeyStorePasswordFile = null; - - @Option( - names = "--privacy-tls-known-enclave-file", + names = {"--kzg-trusted-setup"}, paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = "Path to a file containing the fingerprints of the authorized privacy enclave.") - private final Path privacyTlsKnownEnclaveFile = null; - - @Option( - names = {"--metrics-enabled"}, - description = "Set to start the metrics exporter (default: ${DEFAULT-VALUE})") - private final Boolean isMetricsEnabled = false; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--metrics-protocol"}, - description = - "Metrics protocol, one of PROMETHEUS, OPENTELEMETRY or NONE. (default: ${DEFAULT-VALUE})") - private MetricsProtocol metricsProtocol = PROMETHEUS; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--metrics-host"}, - paramLabel = MANDATORY_HOST_FORMAT_HELP, - description = "Host for the metrics exporter to listen on (default: ${DEFAULT-VALUE})", - arity = "1") - private String metricsHost = autoDiscoverDefaultIP().getHostAddress(); - - @Option( - names = {"--metrics-port"}, - paramLabel = MANDATORY_PORT_FORMAT_HELP, - description = "Port for the metrics exporter to listen on (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer metricsPort = DEFAULT_METRICS_PORT; - - @Option( - names = {"--metrics-category", "--metrics-categories"}, - paramLabel = "", - split = ",", - arity = "1..*", - description = - "Comma separated list of categories to track metrics for (default: ${DEFAULT-VALUE})") - private final Set metricCategories = DEFAULT_METRIC_CATEGORIES; - - @Option( - names = {"--metrics-push-enabled"}, - description = "Enable the metrics push gateway integration (default: ${DEFAULT-VALUE})") - private final Boolean isMetricsPushEnabled = false; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--metrics-push-host"}, - paramLabel = MANDATORY_HOST_FORMAT_HELP, - description = "Host of the Prometheus Push Gateway for push mode (default: ${DEFAULT-VALUE})", - arity = "1") - private String metricsPushHost = autoDiscoverDefaultIP().getHostAddress(); - - @Option( - names = {"--metrics-push-port"}, - paramLabel = MANDATORY_PORT_FORMAT_HELP, - description = "Port of the Prometheus Push Gateway for push mode (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer metricsPushPort = DEFAULT_METRICS_PUSH_PORT; - - @Option( - names = {"--metrics-push-interval"}, - paramLabel = MANDATORY_INTEGER_FORMAT_HELP, description = - "Interval in seconds to push metrics when in push mode (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer metricsPushInterval = 15; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--metrics-push-prometheus-job"}, - description = "Job name to use when in push mode (default: ${DEFAULT-VALUE})", + "Path to file containing the KZG trusted setup, mandatory for custom networks that support data blobs, " + + "optional for overriding named networks default.", arity = "1") - private String metricsPrometheusJob = "besu-client"; + private final Path kzgTrustedSetupFile = null; + + @CommandLine.ArgGroup(validate = false, heading = "@|bold GraphQL Options|@%n") + GraphQlOptionGroup graphQlOptionGroup = new GraphQlOptionGroup(); + + static class GraphQlOptionGroup { + @Option( + names = {"--graphql-http-enabled"}, + description = "Set to start the GraphQL HTTP service (default: ${DEFAULT-VALUE})") + private final Boolean isGraphQLHttpEnabled = false; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @Option( + names = {"--graphql-http-host"}, + paramLabel = MANDATORY_HOST_FORMAT_HELP, + description = "Host for GraphQL HTTP to listen on (default: ${DEFAULT-VALUE})", + arity = "1") + private String graphQLHttpHost; + + @Option( + names = {"--graphql-http-port"}, + paramLabel = MANDATORY_PORT_FORMAT_HELP, + description = "Port for GraphQL HTTP to listen on (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer graphQLHttpPort = DEFAULT_GRAPHQL_HTTP_PORT; + + @Option( + names = {"--graphql-http-cors-origins"}, + description = "Comma separated origin domain URLs for CORS validation (default: none)") + protected final CorsAllowedOriginsProperty graphQLHttpCorsAllowedOrigins = + new CorsAllowedOriginsProperty(); + } + + // Engine JSON-PRC Options + @CommandLine.ArgGroup(validate = false, heading = "@|bold Engine JSON-RPC Options|@%n") + EngineRPCOptionGroup engineRPCOptionGroup = new EngineRPCOptionGroup(); + + static class EngineRPCOptionGroup { + @Option( + names = {"--engine-rpc-enabled"}, + description = + "enable the engine api, even in the absence of merge-specific configurations.") + private final Boolean overrideEngineRpcEnabled = false; + + @Option( + names = {"--engine-rpc-port", "--engine-rpc-http-port"}, + paramLabel = MANDATORY_PORT_FORMAT_HELP, + description = "Port to provide consensus client APIS on (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer engineRpcPort = DEFAULT_ENGINE_JSON_RPC_PORT; + + @Option( + names = {"--engine-jwt-secret"}, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = "Path to file containing shared secret key for JWT signature verification") + private final Path engineJwtKeyFile = null; + + @Option( + names = {"--engine-jwt-enabled"}, + description = "deprecated option, engine jwt auth is enabled by default", + hidden = true) + @SuppressWarnings({"FieldCanBeFinal", "UnusedVariable"}) + private final Boolean deprecatedIsEngineAuthEnabled = true; + + @Option( + names = {"--engine-jwt-disabled"}, + description = "Disable authentication for Engine APIs (default: ${DEFAULT-VALUE})") + private final Boolean isEngineAuthDisabled = false; + + @Option( + names = {"--engine-host-allowlist"}, + paramLabel = "[,...]... or * or all", + description = + "Comma separated list of hostnames to allow for ENGINE API access (applies to both HTTP and websockets), or * to accept any host (default: ${DEFAULT-VALUE})", + defaultValue = "localhost,127.0.0.1") + private final JsonRPCAllowlistHostsProperty engineHostsAllowlist = + new JsonRPCAllowlistHostsProperty(); + } + + // JSON-RPC HTTP Options + @CommandLine.ArgGroup(validate = false, heading = "@|bold JSON-RPC HTTP Options|@%n") + JsonRPCHttpOptionGroup jsonRPCHttpOptionGroup = new JsonRPCHttpOptionGroup(); + + static class JsonRPCHttpOptionGroup { + @Option( + names = {"--rpc-http-enabled"}, + description = "Set to start the JSON-RPC HTTP service (default: ${DEFAULT-VALUE})") + private final Boolean isRpcHttpEnabled = false; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @Option( + names = {"--rpc-http-host"}, + paramLabel = MANDATORY_HOST_FORMAT_HELP, + description = "Host for JSON-RPC HTTP to listen on (default: ${DEFAULT-VALUE})", + arity = "1") + private String rpcHttpHost; + + @Option( + names = {"--rpc-http-port"}, + paramLabel = MANDATORY_PORT_FORMAT_HELP, + description = "Port for JSON-RPC HTTP to listen on (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer rpcHttpPort = DEFAULT_JSON_RPC_PORT; + + @Option( + names = {"--rpc-http-max-active-connections"}, + description = + "Maximum number of HTTP connections allowed for JSON-RPC (default: ${DEFAULT-VALUE}). Once this limit is reached, incoming connections will be rejected.", + arity = "1") + private final Integer rpcHttpMaxConnections = DEFAULT_HTTP_MAX_CONNECTIONS; + + // A list of origins URLs that are accepted by the JsonRpcHttpServer (CORS) + @Option( + names = {"--rpc-http-cors-origins"}, + description = "Comma separated origin domain URLs for CORS validation (default: none)") + private final CorsAllowedOriginsProperty rpcHttpCorsAllowedOrigins = + new CorsAllowedOriginsProperty(); + + @Option( + names = {"--rpc-http-api", "--rpc-http-apis"}, + paramLabel = "", + split = " {0,1}, {0,1}", + arity = "1..*", + description = + "Comma separated list of APIs to enable on JSON-RPC HTTP service (default: ${DEFAULT-VALUE})") + private final List rpcHttpApis = DEFAULT_RPC_APIS; + + @Option( + names = {"--rpc-http-api-method-no-auth", "--rpc-http-api-methods-no-auth"}, + paramLabel = "", + split = " {0,1}, {0,1}", + arity = "1..*", + description = + "Comma separated list of API methods to exclude from RPC authentication services, RPC HTTP authentication must be enabled") + private final List rpcHttpApiMethodsNoAuth = new ArrayList(); + + @Option( + names = {"--rpc-http-authentication-enabled"}, + description = + "Require authentication for the JSON-RPC HTTP service (default: ${DEFAULT-VALUE})") + private final Boolean isRpcHttpAuthenticationEnabled = false; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @CommandLine.Option( + names = {"--rpc-http-authentication-credentials-file"}, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = + "Storage file for JSON-RPC HTTP authentication credentials (default: ${DEFAULT-VALUE})", + arity = "1") + private String rpcHttpAuthenticationCredentialsFile = null; + + @CommandLine.Option( + names = {"--rpc-http-authentication-jwt-public-key-file"}, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = "JWT public key file for JSON-RPC HTTP authentication", + arity = "1") + private final File rpcHttpAuthenticationPublicKeyFile = null; + + @Option( + names = {"--rpc-http-authentication-jwt-algorithm"}, + description = + "Encryption algorithm used for HTTP JWT public key. Possible values are ${COMPLETION-CANDIDATES}" + + " (default: ${DEFAULT-VALUE})", + arity = "1") + private final JwtAlgorithm rpcHttpAuthenticationAlgorithm = DEFAULT_JWT_ALGORITHM; + + @Option( + names = {"--rpc-http-tls-enabled"}, + description = "Enable TLS for the JSON-RPC HTTP service (default: ${DEFAULT-VALUE})") + private final Boolean isRpcHttpTlsEnabled = false; + + @Option( + names = {"--rpc-http-tls-keystore-file"}, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = + "Keystore (PKCS#12) containing key/certificate for the JSON-RPC HTTP service. Required if TLS is enabled.") + private final Path rpcHttpTlsKeyStoreFile = null; + + @Option( + names = {"--rpc-http-tls-keystore-password-file"}, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = + "File containing password to unlock keystore for the JSON-RPC HTTP service. Required if TLS is enabled.") + private final Path rpcHttpTlsKeyStorePasswordFile = null; + + @Option( + names = {"--rpc-http-tls-client-auth-enabled"}, + description = + "Enable TLS client authentication for the JSON-RPC HTTP service (default: ${DEFAULT-VALUE})") + private final Boolean isRpcHttpTlsClientAuthEnabled = false; + + @Option( + names = {"--rpc-http-tls-known-clients-file"}, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = + "Path to file containing clients certificate common name and fingerprint for client authentication") + private final Path rpcHttpTlsKnownClientsFile = null; + + @Option( + names = {"--rpc-http-tls-ca-clients-enabled"}, + description = + "Enable to accept clients certificate signed by a valid CA for client authentication (default: ${DEFAULT-VALUE})") + private final Boolean isRpcHttpTlsCAClientsEnabled = false; + + @Option( + names = {"--rpc-http-tls-protocol", "--rpc-http-tls-protocols"}, + description = + "Comma separated list of TLS protocols to support (default: ${DEFAULT-VALUE})", + split = ",", + arity = "1..*") + private final List rpcHttpTlsProtocols = new ArrayList<>(DEFAULT_TLS_PROTOCOLS); + + @Option( + names = {"--rpc-http-tls-cipher-suite", "--rpc-http-tls-cipher-suites"}, + description = "Comma separated list of TLS cipher suites to support", + split = ",", + arity = "1..*") + private final List rpcHttpTlsCipherSuites = new ArrayList<>(); + + @CommandLine.Option( + names = {"--rpc-http-max-batch-size"}, + paramLabel = MANDATORY_INTEGER_FORMAT_HELP, + description = + "Specifies the maximum number of requests in a single RPC batch request via RPC. -1 specifies no limit (default: ${DEFAULT-VALUE})") + private final Integer rpcHttpMaxBatchSize = DEFAULT_HTTP_MAX_BATCH_SIZE; + + @CommandLine.Option( + names = {"--rpc-http-max-request-content-length"}, + paramLabel = MANDATORY_LONG_FORMAT_HELP, + description = "Specifies the maximum request content length. (default: ${DEFAULT-VALUE})") + private final Long rpcHttpMaxRequestContentLength = DEFAULT_MAX_REQUEST_CONTENT_LENGTH; + } + + // JSON-RPC Websocket Options + @CommandLine.ArgGroup(validate = false, heading = "@|bold JSON-RPC Websocket Options|@%n") + JsonRPCWebsocketOptionGroup jsonRPCWebsocketOptionGroup = new JsonRPCWebsocketOptionGroup(); + + static class JsonRPCWebsocketOptionGroup { + @Option( + names = {"--rpc-ws-authentication-jwt-algorithm"}, + description = + "Encryption algorithm used for Websockets JWT public key. Possible values are ${COMPLETION-CANDIDATES}" + + " (default: ${DEFAULT-VALUE})", + arity = "1") + private final JwtAlgorithm rpcWebsocketsAuthenticationAlgorithm = DEFAULT_JWT_ALGORITHM; + + @Option( + names = {"--rpc-ws-enabled"}, + description = "Set to start the JSON-RPC WebSocket service (default: ${DEFAULT-VALUE})") + private final Boolean isRpcWsEnabled = false; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @Option( + names = {"--rpc-ws-host"}, + paramLabel = MANDATORY_HOST_FORMAT_HELP, + description = + "Host for JSON-RPC WebSocket service to listen on (default: ${DEFAULT-VALUE})", + arity = "1") + private String rpcWsHost; + + @Option( + names = {"--rpc-ws-port"}, + paramLabel = MANDATORY_PORT_FORMAT_HELP, + description = + "Port for JSON-RPC WebSocket service to listen on (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer rpcWsPort = DEFAULT_WEBSOCKET_PORT; + + @Option( + names = {"--rpc-ws-max-frame-size"}, + description = + "Maximum size in bytes for JSON-RPC WebSocket frames (default: ${DEFAULT-VALUE}). If this limit is exceeded, the websocket will be disconnected.", + arity = "1") + private final Integer rpcWsMaxFrameSize = DEFAULT_WS_MAX_FRAME_SIZE; + + @Option( + names = {"--rpc-ws-max-active-connections"}, + description = + "Maximum number of WebSocket connections allowed for JSON-RPC (default: ${DEFAULT-VALUE}). Once this limit is reached, incoming connections will be rejected.", + arity = "1") + private final Integer rpcWsMaxConnections = DEFAULT_WS_MAX_CONNECTIONS; + + @Option( + names = {"--rpc-ws-api", "--rpc-ws-apis"}, + paramLabel = "", + split = " {0,1}, {0,1}", + arity = "1..*", + description = + "Comma separated list of APIs to enable on JSON-RPC WebSocket service (default: ${DEFAULT-VALUE})") + private final List rpcWsApis = DEFAULT_RPC_APIS; + + @Option( + names = {"--rpc-ws-api-methods-no-auth", "--rpc-ws-api-method-no-auth"}, + paramLabel = "", + split = " {0,1}, {0,1}", + arity = "1..*", + description = + "Comma separated list of RPC methods to exclude from RPC authentication services, RPC WebSocket authentication must be enabled") + private final List rpcWsApiMethodsNoAuth = new ArrayList(); + + @Option( + names = {"--rpc-ws-authentication-enabled"}, + description = + "Require authentication for the JSON-RPC WebSocket service (default: ${DEFAULT-VALUE})") + private final Boolean isRpcWsAuthenticationEnabled = false; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @CommandLine.Option( + names = {"--rpc-ws-authentication-credentials-file"}, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = + "Storage file for JSON-RPC WebSocket authentication credentials (default: ${DEFAULT-VALUE})", + arity = "1") + private String rpcWsAuthenticationCredentialsFile = null; + + @CommandLine.Option( + names = {"--rpc-ws-authentication-jwt-public-key-file"}, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = "JWT public key file for JSON-RPC WebSocket authentication", + arity = "1") + private final File rpcWsAuthenticationPublicKeyFile = null; + } + + // Privacy Options Group + @CommandLine.ArgGroup(validate = false, heading = "@|bold Privacy Options|@%n") + PrivacyOptionGroup privacyOptionGroup = new PrivacyOptionGroup(); + + static class PrivacyOptionGroup { + @Option( + names = {"--privacy-tls-enabled"}, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = "Enable TLS for connecting to privacy enclave (default: ${DEFAULT-VALUE})") + private final Boolean isPrivacyTlsEnabled = false; + + @Option( + names = "--privacy-tls-keystore-file", + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = + "Path to a PKCS#12 formatted keystore; used to enable TLS on inbound connections.") + private final Path privacyKeyStoreFile = null; + + @Option( + names = "--privacy-tls-keystore-password-file", + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = "Path to a file containing the password used to decrypt the keystore.") + private final Path privacyKeyStorePasswordFile = null; + + @Option( + names = "--privacy-tls-known-enclave-file", + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = + "Path to a file containing the fingerprints of the authorized privacy enclave.") + private final Path privacyTlsKnownEnclaveFile = null; + + @Option( + names = {"--privacy-enabled"}, + description = "Enable private transactions (default: ${DEFAULT-VALUE})") + private final Boolean isPrivacyEnabled = false; + + @Option( + names = {"--privacy-multi-tenancy-enabled"}, + description = "Enable multi-tenant private transactions (default: ${DEFAULT-VALUE})") + private final Boolean isPrivacyMultiTenancyEnabled = false; + + @Option( + names = {"--privacy-url"}, + description = "The URL on which the enclave is running") + private final URI privacyUrl = PrivacyParameters.DEFAULT_ENCLAVE_URL; + + @Option( + names = {"--privacy-public-key-file"}, + description = "The enclave's public key file") + private final File privacyPublicKeyFile = null; + + @Option( + names = {"--privacy-marker-transaction-signing-key-file"}, + description = + "The name of a file containing the private key used to sign privacy marker transactions. If unset, each will be signed with a random key.") + private final Path privateMarkerTransactionSigningKeyPath = null; + + @Option( + names = {"--privacy-enable-database-migration"}, + description = "Enable private database metadata migration (default: ${DEFAULT-VALUE})") + private final Boolean migratePrivateDatabase = false; + + @Option( + names = {"--privacy-flexible-groups-enabled"}, + description = "Enable flexible privacy groups (default: ${DEFAULT-VALUE})") + private final Boolean isFlexiblePrivacyGroupsEnabled = false; + + @Option( + hidden = true, + names = {"--privacy-onchain-groups-enabled"}, + description = + "!!DEPRECATED!! Use `--privacy-flexible-groups-enabled` instead. Enable flexible (onchain) privacy groups (default: ${DEFAULT-VALUE})") + private final Boolean isOnchainPrivacyGroupsEnabled = false; + } + + // Metrics Option Group + @CommandLine.ArgGroup(validate = false, heading = "@|bold Metrics Options|@%n") + MetricsOptionGroup metricsOptionGroup = new MetricsOptionGroup(); + + static class MetricsOptionGroup { + @Option( + names = {"--metrics-enabled"}, + description = "Set to start the metrics exporter (default: ${DEFAULT-VALUE})") + private final Boolean isMetricsEnabled = false; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @Option( + names = {"--metrics-protocol"}, + description = + "Metrics protocol, one of PROMETHEUS, OPENTELEMETRY or NONE. (default: ${DEFAULT-VALUE})") + private MetricsProtocol metricsProtocol = PROMETHEUS; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @Option( + names = {"--metrics-host"}, + paramLabel = MANDATORY_HOST_FORMAT_HELP, + description = "Host for the metrics exporter to listen on (default: ${DEFAULT-VALUE})", + arity = "1") + private String metricsHost; + + @Option( + names = {"--metrics-port"}, + paramLabel = MANDATORY_PORT_FORMAT_HELP, + description = "Port for the metrics exporter to listen on (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer metricsPort = DEFAULT_METRICS_PORT; + + @Option( + names = {"--metrics-category", "--metrics-categories"}, + paramLabel = "", + split = ",", + arity = "1..*", + description = + "Comma separated list of categories to track metrics for (default: ${DEFAULT-VALUE})") + private final Set metricCategories = DEFAULT_METRIC_CATEGORIES; + + @Option( + names = {"--metrics-push-enabled"}, + description = "Enable the metrics push gateway integration (default: ${DEFAULT-VALUE})") + private final Boolean isMetricsPushEnabled = false; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @Option( + names = {"--metrics-push-host"}, + paramLabel = MANDATORY_HOST_FORMAT_HELP, + description = + "Host of the Prometheus Push Gateway for push mode (default: ${DEFAULT-VALUE})", + arity = "1") + private String metricsPushHost; + + @Option( + names = {"--metrics-push-port"}, + paramLabel = MANDATORY_PORT_FORMAT_HELP, + description = + "Port of the Prometheus Push Gateway for push mode (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer metricsPushPort = DEFAULT_METRICS_PUSH_PORT; + + @Option( + names = {"--metrics-push-interval"}, + paramLabel = MANDATORY_INTEGER_FORMAT_HELP, + description = + "Interval in seconds to push metrics when in push mode (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer metricsPushInterval = 15; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @Option( + names = {"--metrics-push-prometheus-job"}, + description = "Job name to use when in push mode (default: ${DEFAULT-VALUE})", + arity = "1") + private String metricsPrometheusJob = "besu-client"; + } @Option( names = {"--host-allowlist"}, @@ -738,17 +1044,11 @@ void setBannedNodeIds(final List values) { "Deprecated in favor of --host-allowlist. Comma separated list of hostnames to allow for RPC access, or * to accept any host (default: ${DEFAULT-VALUE})") private final JsonRPCAllowlistHostsProperty hostsWhitelist = new JsonRPCAllowlistHostsProperty(); - @Option( - names = {"--logging", "-l"}, - paramLabel = "", - description = "Logging verbosity levels: OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL") - private final Level logLevel = null; - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) @Option( names = {"--color-enabled"}, description = - "Force color output to be enabled/disabled (default: colorized only if printing to console") + "Force color output to be enabled/disabled (default: colorized only if printing to console)") private static Boolean colorEnabled = null; @Option( @@ -757,34 +1057,48 @@ void setBannedNodeIds(final List values) { "How deep a chain reorganization must be in order for it to be logged (default: ${DEFAULT-VALUE})") private final Long reorgLoggingThreshold = 6L; - @Option( - names = {"--miner-enabled"}, - description = "Set if node will perform mining (default: ${DEFAULT-VALUE})") - private final Boolean isMiningEnabled = false; - - @Option( - names = {"--miner-stratum-enabled"}, - description = "Set if node will perform Stratum mining (default: ${DEFAULT-VALUE})") - private final Boolean iStratumMiningEnabled = false; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--miner-stratum-host"}, - description = "Host for Stratum network mining service (default: ${DEFAULT-VALUE})") - private String stratumNetworkInterface = "0.0.0.0"; - - @Option( - names = {"--miner-stratum-port"}, - description = "Stratum port binding (default: ${DEFAULT-VALUE})") - private final Integer stratumPort = 8008; - - @Option( - names = {"--miner-coinbase"}, - description = - "Account to which mining rewards are paid. You must specify a valid coinbase if " - + "mining is enabled using --miner-enabled option", - arity = "1") - private final Address coinbase = null; + // Miner options group + @CommandLine.ArgGroup(validate = false, heading = "@|bold Miner Options|@%n") + MinerOptionGroup minerOptionGroup = new MinerOptionGroup(); + + static class MinerOptionGroup { + @Option( + names = {"--miner-enabled"}, + description = "Set if node will perform mining (default: ${DEFAULT-VALUE})") + private final Boolean isMiningEnabled = false; + + @Option( + names = {"--miner-stratum-enabled"}, + description = "Set if node will perform Stratum mining (default: ${DEFAULT-VALUE})") + private final Boolean iStratumMiningEnabled = false; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @Option( + names = {"--miner-stratum-host"}, + description = "Host for Stratum network mining service (default: ${DEFAULT-VALUE})") + private String stratumNetworkInterface = "0.0.0.0"; + + @Option( + names = {"--miner-stratum-port"}, + description = "Stratum port binding (default: ${DEFAULT-VALUE})") + private final Integer stratumPort = 8008; + + @Option( + names = {"--miner-coinbase"}, + description = + "Account to which mining rewards are paid. You must specify a valid coinbase if " + + "mining is enabled using --miner-enabled option", + arity = "1") + private final Address coinbase = null; + + @Option( + names = {"--miner-extra-data"}, + description = + "A hex string representing the (32) bytes to be included in the extra data " + + "field of a mined block (default: ${DEFAULT-VALUE})", + arity = "1") + private final Bytes extraData = DEFAULT_EXTRA_DATA; + } @Option( names = {"--min-gas-price"}, @@ -807,81 +1121,70 @@ void setBannedNodeIds(final List values) { arity = "1") private final Double minBlockOccupancyRatio = DEFAULT_MIN_BLOCK_OCCUPANCY_RATIO; - @Option( - names = {"--miner-extra-data"}, - description = - "A hex string representing the (32) bytes to be included in the extra data " - + "field of a mined block (default: ${DEFAULT-VALUE})", - arity = "1") - private final Bytes extraData = DEFAULT_EXTRA_DATA; - @Option( names = {"--pruning-enabled"}, description = "Enable disk-space saving optimization that removes old state that is unlikely to be required (default: ${DEFAULT-VALUE})") private final Boolean pruningEnabled = false; - @Option( - names = {"--permissions-nodes-config-file-enabled"}, - description = "Enable node level permissions (default: ${DEFAULT-VALUE})") - private final Boolean permissionsNodesEnabled = false; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @CommandLine.Option( - names = {"--permissions-nodes-config-file"}, - description = - "Node permissioning config TOML file (default: a file named \"permissions_config.toml\" in the Besu data folder)") - private String nodePermissionsConfigFile = null; - - @Option( - names = {"--permissions-accounts-config-file-enabled"}, - description = "Enable account level permissions (default: ${DEFAULT-VALUE})") - private final Boolean permissionsAccountsEnabled = false; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @CommandLine.Option( - names = {"--permissions-accounts-config-file"}, - description = - "Account permissioning config TOML file (default: a file named \"permissions_config.toml\" in the Besu data folder)") - private String accountPermissionsConfigFile = null; - - @Option( - names = {"--permissions-nodes-contract-address"}, - description = "Address of the node permissioning smart contract", - arity = "1") - private final Address permissionsNodesContractAddress = null; - - @Option( - names = {"--permissions-nodes-contract-version"}, - description = "Version of the EEA Node Permissioning interface (default: ${DEFAULT-VALUE})") - private final Integer permissionsNodesContractVersion = 1; - - @Option( - names = {"--permissions-nodes-contract-enabled"}, - description = "Enable node level permissions via smart contract (default: ${DEFAULT-VALUE})") - private final Boolean permissionsNodesContractEnabled = false; - - @Option( - names = {"--permissions-accounts-contract-address"}, - description = "Address of the account permissioning smart contract", - arity = "1") - private final Address permissionsAccountsContractAddress = null; - - @Option( - names = {"--permissions-accounts-contract-enabled"}, - description = - "Enable account level permissions via smart contract (default: ${DEFAULT-VALUE})") - private final Boolean permissionsAccountsContractEnabled = false; - - @Option( - names = {"--privacy-enabled"}, - description = "Enable private transactions (default: ${DEFAULT-VALUE})") - private final Boolean isPrivacyEnabled = false; - - @Option( - names = {"--privacy-multi-tenancy-enabled"}, - description = "Enable multi-tenant private transactions (default: ${DEFAULT-VALUE})") - private final Boolean isPrivacyMultiTenancyEnabled = false; + // Permission Option Group + @CommandLine.ArgGroup(validate = false, heading = "@|bold Permissions Options|@%n") + PermissionsOptionGroup permissionsOptionGroup = new PermissionsOptionGroup(); + + static class PermissionsOptionGroup { + @Option( + names = {"--permissions-nodes-config-file-enabled"}, + description = "Enable node level permissions (default: ${DEFAULT-VALUE})") + private final Boolean permissionsNodesEnabled = false; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @CommandLine.Option( + names = {"--permissions-nodes-config-file"}, + description = + "Node permissioning config TOML file (default: a file named \"permissions_config.toml\" in the Besu data folder)") + private String nodePermissionsConfigFile = null; + + @Option( + names = {"--permissions-accounts-config-file-enabled"}, + description = "Enable account level permissions (default: ${DEFAULT-VALUE})") + private final Boolean permissionsAccountsEnabled = false; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. + @CommandLine.Option( + names = {"--permissions-accounts-config-file"}, + description = + "Account permissioning config TOML file (default: a file named \"permissions_config.toml\" in the Besu data folder)") + private String accountPermissionsConfigFile = null; + + @Option( + names = {"--permissions-nodes-contract-address"}, + description = "Address of the node permissioning smart contract", + arity = "1") + private final Address permissionsNodesContractAddress = null; + + @Option( + names = {"--permissions-nodes-contract-version"}, + description = "Version of the EEA Node Permissioning interface (default: ${DEFAULT-VALUE})") + private final Integer permissionsNodesContractVersion = 1; + + @Option( + names = {"--permissions-nodes-contract-enabled"}, + description = + "Enable node level permissions via smart contract (default: ${DEFAULT-VALUE})") + private final Boolean permissionsNodesContractEnabled = false; + + @Option( + names = {"--permissions-accounts-contract-address"}, + description = "Address of the account permissioning smart contract", + arity = "1") + private final Address permissionsAccountsContractAddress = null; + + @Option( + names = {"--permissions-accounts-contract-enabled"}, + description = + "Enable account level permissions via smart contract (default: ${DEFAULT-VALUE})") + private final Boolean permissionsAccountsContractEnabled = false; + } @Option( names = {"--revert-reason-enabled"}, @@ -897,79 +1200,80 @@ void setBannedNodeIds(final List values) { split = ",") private final Map requiredBlocks = new HashMap<>(); - @Option( - names = {"--privacy-url"}, - description = "The URL on which the enclave is running") - private final URI privacyUrl = PrivacyParameters.DEFAULT_ENCLAVE_URL; - - @CommandLine.Option( - names = {"--privacy-public-key-file"}, - description = "The enclave's public key file") - private final File privacyPublicKeyFile = null; - - @Option( - names = {"--privacy-precompiled-address"}, - description = - "The address to which the privacy pre-compiled contract will be mapped (default: ${DEFAULT-VALUE})", - hidden = true) - private final Integer privacyPrecompiledAddress = Address.PRIVACY; - - @Option( - names = {"--privacy-marker-transaction-signing-key-file"}, - description = - "The name of a file containing the private key used to sign privacy marker transactions. If unset, each will be signed with a random key.") - private final Path privacyMarkerTransactionSigningKeyPath = null; - - @Option( - names = {"--privacy-enable-database-migration"}, - description = "Enable private database metadata migration (default: ${DEFAULT-VALUE})") - private final Boolean migratePrivateDatabase = false; - - @Option( - names = {"--privacy-flexible-groups-enabled", "--privacy-onchain-groups-enabled"}, - description = "Enable flexible (onchain) privacy groups (default: ${DEFAULT-VALUE})") - private final Boolean isFlexiblePrivacyGroupsEnabled = false; - @Option( names = {"--target-gas-limit"}, description = - "Sets target gas limit per block. If set each block's gas limit will approach this setting over time if the current gas limit is different.") + "Sets target gas limit per block. If set, each block's gas limit will approach this setting over time if the current gas limit is different.") private final Long targetGasLimit = null; - @Option( - names = {"--tx-pool-max-size"}, - paramLabel = MANDATORY_INTEGER_FORMAT_HELP, - description = - "Maximum number of pending transactions that will be kept in the transaction pool (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer txPoolMaxSize = TransactionPoolConfiguration.MAX_PENDING_TRANSACTIONS; - - @Option( - names = {"--tx-pool-hashes-max-size"}, - paramLabel = MANDATORY_INTEGER_FORMAT_HELP, - description = - "Maximum number of pending transaction hashes that will be kept in the transaction pool (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer pooledTransactionHashesSize = - TransactionPoolConfiguration.MAX_PENDING_TRANSACTIONS_HASHES; - - @Option( - names = {"--tx-pool-retention-hours"}, - paramLabel = MANDATORY_INTEGER_FORMAT_HELP, - description = - "Maximum retention period of pending transactions in hours (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer pendingTxRetentionPeriod = - TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS; - - @Option( - names = {"--tx-pool-price-bump"}, - paramLabel = MANDATORY_INTEGER_FORMAT_HELP, - converter = PercentageConverter.class, - description = - "Price bump percentage to replace an already existing transaction (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer priceBump = TransactionPoolConfiguration.DEFAULT_PRICE_BUMP.getValue(); + // Tx Pool Option Group + @CommandLine.ArgGroup(validate = false, heading = "@|bold Tx Pool Options|@%n") + TxPoolOptionGroup txPoolOptionGroup = new TxPoolOptionGroup(); + + static class TxPoolOptionGroup { + @CommandLine.Option( + names = {"--tx-pool-disable-locals"}, + paramLabel = "", + description = + "Set to true if transactions sent via RPC should have the same checks and not be prioritized over remote ones (default: ${DEFAULT-VALUE})", + fallbackValue = "true", + arity = "0..1") + private Boolean disableLocalTxs = TransactionPoolConfiguration.DEFAULT_DISABLE_LOCAL_TXS; + + @CommandLine.Option( + names = {"--tx-pool-enable-save-restore"}, + paramLabel = "", + description = + "Set to true to enable saving the txpool content to file on shutdown and reloading it on startup (default: ${DEFAULT-VALUE})", + fallbackValue = "true", + arity = "0..1") + private Boolean saveRestoreEnabled = TransactionPoolConfiguration.DEFAULT_ENABLE_SAVE_RESTORE; + + @CommandLine.Option( + names = {"--tx-pool-limit-by-account-percentage"}, + paramLabel = "", + converter = FractionConverter.class, + description = + "Maximum portion of the transaction pool which a single account may occupy with future transactions (default: ${DEFAULT-VALUE})", + arity = "1") + private Float txPoolLimitByAccountPercentage = + TransactionPoolConfiguration.DEFAULT_LIMIT_TX_POOL_BY_ACCOUNT_PERCENTAGE; + + @CommandLine.Option( + names = {"--tx-pool-save-file"}, + paramLabel = "", + description = + "If saving the txpool content is enabled, define a custom path for the save file (default: ${DEFAULT-VALUE} in the data-dir)", + arity = "1") + private File saveFile = TransactionPoolConfiguration.DEFAULT_SAVE_FILE; + + @Option( + names = {"--tx-pool-max-size"}, + paramLabel = MANDATORY_INTEGER_FORMAT_HELP, + description = + "Maximum number of pending transactions that will be kept in the transaction pool (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer txPoolMaxSize = + TransactionPoolConfiguration.DEFAULT_MAX_PENDING_TRANSACTIONS; + + @Option( + names = {"--tx-pool-retention-hours"}, + paramLabel = MANDATORY_INTEGER_FORMAT_HELP, + description = + "Maximum retention period of pending transactions in hours (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer pendingTxRetentionPeriod = + TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS; + + @Option( + names = {"--tx-pool-price-bump"}, + paramLabel = MANDATORY_INTEGER_FORMAT_HELP, + converter = PercentageConverter.class, + description = + "Price bump percentage to replace an already existing transaction (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer priceBump = TransactionPoolConfiguration.DEFAULT_PRICE_BUMP.getValue(); + } @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. @Option( @@ -1029,45 +1333,77 @@ void setBannedNodeIds(final List values) { @CommandLine.Option( names = {"--api-gas-price-blocks"}, - paramLabel = MANDATORY_PATH_FORMAT_HELP, description = "Number of blocks to consider for eth_gasPrice (default: ${DEFAULT-VALUE})") private final Long apiGasPriceBlocks = 100L; @CommandLine.Option( names = {"--api-gas-price-percentile"}, - paramLabel = MANDATORY_PATH_FORMAT_HELP, description = "Percentile value to measure for eth_gasPrice (default: ${DEFAULT-VALUE})") private final Double apiGasPricePercentile = 50.0; @CommandLine.Option( names = {"--api-gas-price-max"}, - paramLabel = MANDATORY_PATH_FORMAT_HELP, description = "Maximum gas price for eth_gasPrice (default: ${DEFAULT-VALUE})") private final Long apiGasPriceMax = 500_000_000_000L; - @Option( - names = {"--goquorum-compatibility-enabled"}, - hidden = true, - description = "Start Besu in GoQuorum compatibility mode (default: ${DEFAULT-VALUE})") - private final Boolean isGoQuorumCompatibilityMode = false; + @CommandLine.Option( + names = {"--static-nodes-file"}, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = + "Specifies the static node file containing the static nodes for this node to connect to") + private final Path staticNodesFile = null; + + @CommandLine.Option( + names = {"--rpc-max-logs-range"}, + description = + "Specifies the maximum number of blocks to retrieve logs from via RPC. Must be >=0. 0 specifies no limit (default: ${DEFAULT-VALUE})") + private final Long rpcMaxLogsRange = 5000L; + + @Mixin private P2PTLSConfigOptions p2pTLSConfigOptions; + + @Mixin private PkiBlockCreationOptions pkiBlockCreationOptions; private EthNetworkConfig ethNetworkConfig; private JsonRpcConfiguration jsonRpcConfiguration; + private JsonRpcConfiguration engineJsonRpcConfiguration; private GraphQLConfiguration graphQLConfiguration; private WebSocketConfiguration webSocketConfiguration; + private JsonRpcIpcConfiguration jsonRpcIpcConfiguration; private ApiConfiguration apiConfiguration; private MetricsConfiguration metricsConfiguration; private Optional permissioningConfiguration; + private Optional p2pTLSConfiguration; private Collection staticNodes; private BesuController besuController; private BesuConfiguration pluginCommonConfiguration; + + private BesuComponent besuComponent; private final Supplier metricsSystem = - Suppliers.memoize(() -> MetricsSystemFactory.create(metricsConfiguration())); + Suppliers.memoize( + () -> + besuComponent == null || besuComponent.getObservableMetricsSystem() == null + ? MetricsSystemFactory.create(metricsConfiguration()) + : besuComponent.getObservableMetricsSystem()); private Vertx vertx; private EnodeDnsConfiguration enodeDnsConfiguration; + private KeyValueStorageProvider keyValueStorageProvider; + /** Sets GoQuorum compatibility mode. */ + protected Boolean isGoQuorumCompatibilityMode = false; + /** + * Besu command constructor. + * + * @param besuComponent BesuComponent which acts as our application context + * @param rlpBlockImporter RlpBlockImporter supplier + * @param jsonBlockImporterFactory instance of {@code Function} + * @param rlpBlockExporterFactory instance of {@code Function} + * @param runnerBuilder instance of RunnerBuilder + * @param controllerBuilderFactory instance of BesuController.Builder + * @param besuPluginContext instance of BesuPluginContextImpl + * @param environment Environment variables map + */ public BesuCommand( - final Logger logger, + final BesuComponent besuComponent, final Supplier rlpBlockImporter, final Function jsonBlockImporterFactory, final Function rlpBlockExporterFactory, @@ -1076,7 +1412,7 @@ public BesuCommand( final BesuPluginContextImpl besuPluginContext, final Map environment) { this( - logger, + besuComponent, rlpBlockImporter, jsonBlockImporterFactory, rlpBlockExporterFactory, @@ -1085,12 +1421,36 @@ public BesuCommand( besuPluginContext, environment, new StorageServiceImpl(), - new SecurityModuleServiceImpl()); + new SecurityModuleServiceImpl(), + new PermissioningServiceImpl(), + new PrivacyPluginServiceImpl(), + new PkiBlockCreationConfigurationProvider(), + new RpcEndpointServiceImpl(), + new TransactionSelectionServiceImpl()); } + /** + * Overloaded Besu command constructor visible for testing. + * + * @param besuComponent BesuComponent which acts as our application context + * @param rlpBlockImporter RlpBlockImporter supplier + * @param jsonBlockImporterFactory instance of {@code Function} + * @param rlpBlockExporterFactory instance of {@code Function} + * @param runnerBuilder instance of RunnerBuilder + * @param controllerBuilderFactory instance of BesuController.Builder + * @param besuPluginContext instance of BesuPluginContextImpl + * @param environment Environment variables map + * @param storageService instance of StorageServiceImpl + * @param securityModuleService instance of SecurityModuleServiceImpl + * @param permissioningService instance of PermissioningServiceImpl + * @param privacyPluginService instance of PrivacyPluginServiceImpl + * @param pkiBlockCreationConfigProvider instance of PkiBlockCreationConfigurationProvider + * @param rpcEndpointServiceImpl instance of RpcEndpointServiceImpl + * @param transactionSelectionServiceImpl instance of TransactionSelectionServiceImpl + */ @VisibleForTesting protected BesuCommand( - final Logger logger, + final BesuComponent besuComponent, final Supplier rlpBlockImporter, final Function jsonBlockImporterFactory, final Function rlpBlockExporterFactory, @@ -1099,8 +1459,14 @@ protected BesuCommand( final BesuPluginContextImpl besuPluginContext, final Map environment, final StorageServiceImpl storageService, - final SecurityModuleServiceImpl securityModuleService) { - this.logger = logger; + final SecurityModuleServiceImpl securityModuleService, + final PermissioningServiceImpl permissioningService, + final PrivacyPluginServiceImpl privacyPluginService, + final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider, + final RpcEndpointServiceImpl rpcEndpointServiceImpl, + final TransactionSelectionServiceImpl transactionSelectionServiceImpl) { + this.besuComponent = besuComponent; + this.logger = besuComponent.getBesuCommandLogger(); this.rlpBlockImporter = rlpBlockImporter; this.rlpBlockExporterFactory = rlpBlockExporterFactory; this.jsonBlockImporterFactory = jsonBlockImporterFactory; @@ -1110,42 +1476,100 @@ protected BesuCommand( this.environment = environment; this.storageService = storageService; this.securityModuleService = securityModuleService; - + this.permissioningService = permissioningService; + this.privacyPluginService = privacyPluginService; pluginCommonConfiguration = new BesuCommandConfigurationService(); besuPluginContext.addService(BesuConfiguration.class, pluginCommonConfiguration); + this.pkiBlockCreationConfigProvider = pkiBlockCreationConfigProvider; + this.rpcEndpointServiceImpl = rpcEndpointServiceImpl; + this.transactionSelectionServiceImpl = transactionSelectionServiceImpl; } - public void parse( - final AbstractParseResultHandler> resultHandler, - final BesuExceptionHandler exceptionHandler, + /** + * Parse Besu command line arguments. Visible for testing. + * + * @param resultHandler execution strategy. See PicoCLI. Typical argument is RunLast. + * @param parameterExceptionHandler Exception handler for handling parameters + * @param executionExceptionHandler Exception handler for business logic + * @param in Standard input stream + * @param args arguments to Besu command + * @return success or failure exit code. + */ + public int parse( + final IExecutionStrategy resultHandler, + final BesuParameterExceptionHandler parameterExceptionHandler, + final BesuExecutionExceptionHandler executionExceptionHandler, final InputStream in, final String... args) { - commandLine = - new CommandLine(this, new BesuCommandCustomFactory(besuPluginContext)) - .setCaseInsensitiveEnumValuesAllowed(true); - enableExperimentalEIPs(); - addSubCommands(resultHandler, in); + toCommandLine(); + + handleStableOptions(); + addSubCommands(in); registerConverters(); handleUnstableOptions(); preparePlugins(); - parse(resultHandler, exceptionHandler, args); + + final int exitCode = + parse(resultHandler, executionExceptionHandler, parameterExceptionHandler, args); + + return exitCode; + } + + /** Used by Dagger to parse all options into a commandline instance. */ + public void toCommandLine() { + commandLine = + new CommandLine(this, new BesuCommandCustomFactory(besuPluginContext)) + .setCaseInsensitiveEnumValuesAllowed(true); } @Override public void run() { + if (network != null && network.isDeprecated()) { + logger.warn(NetworkDeprecationMessage.generate(network)); + } + try { configureLogging(true); - configureNativeLibs(); - logger.info("Starting Besu version: {}", BesuInfo.nodeName(identityString)); + // Set the goquorum compatibility mode based on the genesis file + if (genesisFile != null) { + genesisConfigOptions = readGenesisConfigOptions(); + + if (genesisConfigOptions.isQuorum()) { + enableGoQuorumCompatibilityMode(); + } + } + + // set merge config on the basis of genesis config + setMergeConfigOptions(); + + setIgnorableStorageSegments(); + + instantiateSignatureAlgorithmFactory(); + + logger.info("Starting Besu"); + // Need to create vertx after cmdline has been parsed, such that metricsSystem is configurable vertx = createVertx(createVertxOptions(metricsSystem.get())); - final BesuCommand controller = validateOptions().configure().controller(); + validateOptions(); + configure(); + configureNativeLibs(); + besuController = initController(); + + besuPluginContext.beforeExternalServices(); - preSynchronizationTaskRunner.runTasks(controller.besuController); + final var runner = buildRunner(); + runner.startExternalServices(); + + startPlugins(); + validatePluginOptions(); + setReleaseMetrics(); + preSynchronization(); + + runner.startEthereumMainLoop(); + runner.awaitStop(); - controller.startPlugins().startSynchronization(); } catch (final Exception e) { throw new ParameterException(this.commandLine, e.getMessage(), e); } @@ -1156,37 +1580,39 @@ void setBesuConfiguration(final BesuConfiguration pluginCommonConfiguration) { this.pluginCommonConfiguration = pluginCommonConfiguration; } - private void enableExperimentalEIPs() { - // Usage of static command line flags is strictly reserved for experimental EIPs - commandLine.addMixin("experimentalEIPs", ExperimentalEIPs.class); - } - - private void addSubCommands( - final AbstractParseResultHandler> resultHandler, final InputStream in) { + private void addSubCommands(final InputStream in) { commandLine.addSubcommand( BlocksSubCommand.COMMAND_NAME, new BlocksSubCommand( rlpBlockImporter, jsonBlockImporterFactory, rlpBlockExporterFactory, - resultHandler.out())); + commandLine.getOut())); commandLine.addSubcommand( - PublicKeySubCommand.COMMAND_NAME, - new PublicKeySubCommand(resultHandler.out(), this::buildNodeKey)); + PublicKeySubCommand.COMMAND_NAME, new PublicKeySubCommand(commandLine.getOut())); commandLine.addSubcommand( - PasswordSubCommand.COMMAND_NAME, new PasswordSubCommand(resultHandler.out())); + PasswordSubCommand.COMMAND_NAME, new PasswordSubCommand(commandLine.getOut())); commandLine.addSubcommand(RetestethSubCommand.COMMAND_NAME, new RetestethSubCommand()); commandLine.addSubcommand( - RLPSubCommand.COMMAND_NAME, new RLPSubCommand(resultHandler.out(), in)); + RLPSubCommand.COMMAND_NAME, new RLPSubCommand(commandLine.getOut(), in)); + commandLine.addSubcommand( + OperatorSubCommand.COMMAND_NAME, new OperatorSubCommand(commandLine.getOut())); + commandLine.addSubcommand( + ValidateConfigSubCommand.COMMAND_NAME, + new ValidateConfigSubCommand(commandLine, commandLine.getOut())); + commandLine.addSubcommand( + StorageSubCommand.COMMAND_NAME, new StorageSubCommand(commandLine.getOut())); + final String generateCompletionSubcommandName = "generate-completion"; commandLine.addSubcommand( - OperatorSubCommand.COMMAND_NAME, new OperatorSubCommand(resultHandler.out())); + generateCompletionSubcommandName, AutoComplete.GenerateCompletion.class); + final CommandLine generateCompletionSubcommand = + commandLine.getSubcommands().get(generateCompletionSubcommandName); + generateCompletionSubcommand.getCommandSpec().usageMessage().hidden(true); } private void registerConverters() { commandLine.registerConverter(Address.class, Address::fromHexStringStrict); commandLine.registerConverter(Bytes.class, Bytes::fromHexString); - commandLine.registerConverter(Level.class, Level::valueOf); - commandLine.registerConverter(SyncMode.class, SyncMode::fromString); commandLine.registerConverter(MetricsProtocol.class, MetricsProtocol::fromString); commandLine.registerConverter(UInt256.class, (arg) -> UInt256.valueOf(new BigInteger(arg))); commandLine.registerConverter(Wei.class, (arg) -> Wei.of(Long.parseUnsignedLong(arg))); @@ -1200,6 +1626,13 @@ private void registerConverters() { commandLine.registerConverter(MetricCategory.class, metricCategoryConverter); } + private void handleStableOptions() { + commandLine.addMixin("Ethstats", ethstatsOptions); + commandLine.addMixin("Private key file", nodePrivateKeyFileOption); + commandLine.addMixin("Logging level", loggingLevelOption); + commandLine.addMixin("Data Storage Options", dataStorageOptions); + } + private void handleUnstableOptions() { // Add unstable options final ImmutableMap.Builder unstableOptionsBuild = ImmutableMap.builder(); @@ -1211,12 +1644,14 @@ private void handleUnstableOptions() { .put("RPC", unstableRPCOptions) .put("DNS Configuration", unstableDnsOptions) .put("NAT Configuration", unstableNatOptions) + .put("Privacy Plugin Configuration", unstablePrivacyPluginOptions) .put("Synchronizer", unstableSynchronizerOptions) .put("TransactionPool", unstableTransactionPoolOptions) - .put("Ethstats", unstableEthstatsOptions) .put("Mining", unstableMiningOptions) .put("Native Library", unstableNativeLibraryOptions) - .put("Data Storage Options", unstableDataStorageOptions) + .put("EVM Options", unstableEvmOptions) + .put("IPC Options", unstableIpcOptions) + .put("Chain Data Pruning Options", unstableChainPruningOptions) .build(); UnstableOptionsSubCommand.createUnstableOptions(commandLine, unstableOptions); @@ -1227,9 +1662,15 @@ private void preparePlugins() { besuPluginContext.addService(SecurityModuleService.class, securityModuleService); besuPluginContext.addService(StorageService.class, storageService); besuPluginContext.addService(MetricCategoryRegistry.class, metricCategoryRegistry); + besuPluginContext.addService(PermissioningService.class, permissioningService); + besuPluginContext.addService(PrivacyPluginService.class, privacyPluginService); + besuPluginContext.addService(RpcEndpointService.class, rpcEndpointServiceImpl); + besuPluginContext.addService( + TransactionSelectionService.class, transactionSelectionServiceImpl); // register built-in plugins - new RocksDBPlugin().register(besuPluginContext); + rocksDBPlugin = new RocksDBPlugin(); + rocksDBPlugin.register(besuPluginContext); new InMemoryStoragePlugin().register(besuPluginContext); besuPluginContext.registerPlugins(pluginsDir()); @@ -1244,40 +1685,60 @@ private void preparePlugins() { } private SecurityModule defaultSecurityModule() { - return new KeyPairSecurityModule(loadKeyPair()); + return new KeyPairSecurityModule(loadKeyPair(nodePrivateKeyFileOption.getNodePrivateKeyFile())); } - @VisibleForTesting - SECP256K1.KeyPair loadKeyPair() { - return KeyPairUtil.loadKeyPair(nodePrivateKeyFile()); + // loadKeyPair() is public because it is accessed by subcommands + + /** + * Load key pair from private key. Visible to be accessed by subcommands. + * + * @param nodePrivateKeyFile File containing private key + * @return KeyPair loaded from private key file + */ + public KeyPair loadKeyPair(final File nodePrivateKeyFile) { + return KeyPairUtil.loadKeyPair(resolveNodePrivateKeyFile(nodePrivateKeyFile)); } - private void parse( - final AbstractParseResultHandler> resultHandler, - final BesuExceptionHandler exceptionHandler, + private int parse( + final CommandLine.IExecutionStrategy resultHandler, + final BesuExecutionExceptionHandler besuExecutionExceptionHandler, + final BesuParameterExceptionHandler besuParameterExceptionHandler, final String... args) { // Create a handler that will search for a config file option and use it for // default values // and eventually it will run regular parsing of the remaining options. + final ConfigOptionSearchAndRunHandler configParsingHandler = new ConfigOptionSearchAndRunHandler( - resultHandler, exceptionHandler, CONFIG_FILE_OPTION_NAME, environment); - commandLine.parseWithHandlers(configParsingHandler, exceptionHandler, args); + resultHandler, besuParameterExceptionHandler, environment); + + return commandLine + .setExecutionStrategy(configParsingHandler) + .setParameterExceptionHandler(besuParameterExceptionHandler) + .setExecutionExceptionHandler(besuExecutionExceptionHandler) + .execute(args); + } + + private void preSynchronization() { + preSynchronizationTaskRunner.runTasks(besuController); } - private void startSynchronization() { - synchronize( + private Runner buildRunner() { + return synchronize( besuController, - p2pEnabled, - peerDiscoveryEnabled, + p2PDiscoveryOptionGroup.p2pEnabled, + p2pTLSConfiguration, + p2PDiscoveryOptionGroup.peerDiscoveryEnabled, ethNetworkConfig, - maxPeers, - p2pHost, - p2pInterface, - p2pPort, + p2PDiscoveryOptionGroup.p2pHost, + p2PDiscoveryOptionGroup.p2pInterface, + p2PDiscoveryOptionGroup.p2pPort, graphQLConfiguration, jsonRpcConfiguration, + engineJsonRpcConfiguration, webSocketConfiguration, + jsonRpcIpcConfiguration, apiConfiguration, metricsConfiguration, permissioningConfiguration, @@ -1285,7 +1746,7 @@ private void startSynchronization() { pidPath); } - private BesuCommand startPlugins() { + private void startPlugins() { besuPluginContext.addService( BesuEvents.class, new BesuEventsImpl( @@ -1294,64 +1755,218 @@ private BesuCommand startPlugins() { besuController.getTransactionPool(), besuController.getSyncState())); besuPluginContext.addService(MetricsSystem.class, getMetricsSystem()); + + besuPluginContext.addService( + BlockchainService.class, + new BlockchainServiceImpl(besuController.getProtocolContext().getBlockchain())); + + besuPluginContext.addService( + TraceService.class, + new TraceServiceImpl( + new BlockchainQueries( + besuController.getProtocolContext().getBlockchain(), + besuController.getProtocolContext().getWorldStateArchive()), + besuController.getProtocolSchedule())); + besuController.getAdditionalPluginServices().appendPluginServices(besuPluginContext); besuPluginContext.startPlugins(); - return this; } + private void validatePluginOptions() { + // plugins do not 'wire up' until start has been called + // consequently you can only do some configuration checks + // after start has been called on plugins + + if (Boolean.TRUE.equals(privacyOptionGroup.isPrivacyEnabled)) { + + if (privacyOptionGroup.privateMarkerTransactionSigningKeyPath != null + && privacyPluginService != null + && privacyPluginService.getPrivateMarkerTransactionFactory() != null) { + throw new ParameterException( + commandLine, + "--privacy-marker-transaction-signing-key-file can not be used in conjunction with a plugin that specifies a PrivateMarkerTransactionFactory"); + } + + if (Wei.ZERO.compareTo(minTransactionGasPrice) < 0 + && (privacyOptionGroup.privateMarkerTransactionSigningKeyPath == null + && (privacyPluginService == null + || privacyPluginService.getPrivateMarkerTransactionFactory() == null))) { + // if gas is required, cannot use random keys to sign private tx + // ie --privacy-marker-transaction-signing-key-file must be set + throw new ParameterException( + commandLine, + "Not a free gas network. --privacy-marker-transaction-signing-key-file must be specified and must be a funded account. Private transactions cannot be signed by random (non-funded) accounts in paid gas networks"); + } + + if (unstablePrivacyPluginOptions.isPrivacyPluginEnabled() + && privacyPluginService != null + && privacyPluginService.getPayloadProvider() == null) { + throw new ParameterException( + commandLine, + "No Payload Provider has been provided. You must register one when enabling privacy plugin!"); + } + + if (unstablePrivacyPluginOptions.isPrivacyPluginEnabled() + && (privacyOptionGroup.isFlexiblePrivacyGroupsEnabled + || privacyOptionGroup.isOnchainPrivacyGroupsEnabled)) { + throw new ParameterException( + commandLine, "Privacy Plugin can not be used with flexible privacy groups"); + } + } + } + + private void setReleaseMetrics() { + metricsSystem + .get() + .createLabelledGauge( + StandardMetricCategory.PROCESS, "release", "Release information", "version") + .labels(() -> 1, BesuInfo.version()); + } + + /** + * Configure logging framework for Besu + * + * @param announce sets to true to print the logging level on standard output + */ public void configureLogging(final boolean announce) { // To change the configuration if color was enabled/disabled - Configurator.reconfigure(); + LogConfigurator.reconfigure(); // set log level per CLI flags + final String logLevel = loggingLevelOption.getLogLevel(); if (logLevel != null) { if (announce) { - System.out.println("Setting logging level to " + logLevel.name()); + System.out.println("Setting logging level to " + logLevel); } - Configurator.setAllLevels("", logLevel); + LogConfigurator.setLevel("", logLevel); } } + /** + * Logging in Color enabled or not. + * + * @return Optional true or false representing logging color is enabled. Empty if not set. + */ public static Optional getColorEnabled() { return Optional.ofNullable(colorEnabled); } private void configureNativeLibs() { - if (unstableNativeLibraryOptions.getNativeAltbn128()) { - AbstractAltBnPrecompiledContract.enableNative(); + if (unstableNativeLibraryOptions.getNativeAltbn128() + && AbstractAltBnPrecompiledContract.isNative()) { + logger.info("Using the native implementation of alt bn128"); + } else { + AbstractAltBnPrecompiledContract.disableNative(); + logger.info("Using the Java implementation of alt bn128"); } - if (unstableNativeLibraryOptions.getNativeSecp256k1()) { - SECP256K1.enableNative(); + + if (unstableNativeLibraryOptions.getNativeModExp() + && BigIntegerModularExponentiationPrecompiledContract.isNative()) { + logger.info("Using the native implementation of modexp"); + } else { + BigIntegerModularExponentiationPrecompiledContract.disableNative(); + logger.info("Using the Java implementation of modexp"); + } + + if (unstableNativeLibraryOptions.getNativeSecp() + && SignatureAlgorithmFactory.getInstance().isNative()) { + logger.info("Using the native implementation of the signature algorithm"); + } else { + SignatureAlgorithmFactory.getInstance().disableNative(); + logger.info("Using the Java implementation of the signature algorithm"); + } + + if (unstableNativeLibraryOptions.getNativeBlake2bf() + && Blake2bfMessageDigest.Blake2bfDigest.isNative()) { + logger.info("Using the native implementation of the blake2bf algorithm"); + } else { + Blake2bfMessageDigest.Blake2bfDigest.disableNative(); + logger.info("Using the Java implementation of the blake2bf algorithm"); + } + + if (getActualGenesisConfigOptions().getCancunTime().isPresent()) { + // if custom genesis provided, then trusted setup file is mandatory + if (genesisFile != null && kzgTrustedSetupFile == null) { + throw new ParameterException( + this.commandLine, + "--kzg-trusted-setup is mandatory when providing a custom genesis that support data blobs"); + } + if (kzgTrustedSetupFile != null) { + KZGPointEvalPrecompiledContract.init(kzgTrustedSetupFile); + } else { + KZGPointEvalPrecompiledContract.init(network.name()); + } + } else if (kzgTrustedSetupFile != null) { + throw new ParameterException( + this.commandLine, + "--kzg-trusted-setup can only be specified on networks with data blobs enabled"); } } - private BesuCommand validateOptions() { + private void validateOptions() { + validateRequiredOptions(); issueOptionWarnings(); - - validateP2PInterface(p2pInterface); + validateP2PInterface(p2PDiscoveryOptionGroup.p2pInterface); validateMiningParams(); validateNatParams(); validateNetStatsParams(); validateDnsOptionsParams(); - - return this; + ensureValidPeerBoundParams(); + validateRpcOptionsParams(); + validateChainDataPruningParams(); + validatePostMergeCheckpointBlockRequirements(); + p2pTLSConfigOptions.checkP2PTLSOptionsDependencies(logger, commandLine); + pkiBlockCreationOptions.checkPkiBlockCreationOptionsDependencies(logger, commandLine); + } + + private void validateRequiredOptions() { + commandLine + .getCommandSpec() + .options() + .forEach( + option -> { + if (option.required() && option.stringValues().isEmpty()) { + throw new ParameterException( + this.commandLine, "Missing required option: " + option.longestName()); + } + }); } @SuppressWarnings("ConstantConditions") private void validateMiningParams() { - if (isMiningEnabled && coinbase == null) { + if (Boolean.TRUE.equals(minerOptionGroup.isMiningEnabled) + && minerOptionGroup.coinbase == null) { throw new ParameterException( this.commandLine, "Unable to mine without a valid coinbase. Either disable mining (remove --miner-enabled) " + "or specify the beneficiary of mining (via --miner-coinbase
)"); } - if (!isMiningEnabled && iStratumMiningEnabled) { + if (Boolean.FALSE.equals(minerOptionGroup.isMiningEnabled) + && Boolean.TRUE.equals(minerOptionGroup.iStratumMiningEnabled)) { throw new ParameterException( this.commandLine, "Unable to mine with Stratum if mining is disabled. Either disable Stratum mining (remove --miner-stratum-enabled) " + "or specify mining is enabled (--miner-enabled)"); } + if (unstableMiningOptions.getPosBlockCreationMaxTime() <= 0 + || unstableMiningOptions.getPosBlockCreationMaxTime() + > MiningParameters.DEFAULT_POS_BLOCK_CREATION_MAX_TIME) { + throw new ParameterException( + this.commandLine, "--Xpos-block-creation-max-time must be positive and ≤ 12000"); + } + + if (unstableMiningOptions.getPosBlockCreationRepetitionMinDuration() <= 0 + || unstableMiningOptions.getPosBlockCreationRepetitionMinDuration() > 2000) { + throw new ParameterException( + this.commandLine, + "--Xpos-block-creation-repetition-min-duration must be positive and ≤ 2000"); + } } + /** + * Validates P2P interface IP address/host name. Visible for testing. + * + * @param p2pInterface IP Address/host name + */ protected void validateP2PInterface(final String p2pInterface) { final String failMessage = "The provided --p2p-interface is not available: " + p2pInterface; try { @@ -1383,12 +1998,12 @@ private void validateNatParams() { } private void validateNetStatsParams() { - if (Strings.isNullOrEmpty(unstableEthstatsOptions.getEthstatsUrl()) - && !unstableEthstatsOptions.getEthstatsContact().isEmpty()) { + if (Strings.isNullOrEmpty(ethstatsOptions.getEthstatsUrl()) + && !ethstatsOptions.getEthstatsContact().isEmpty()) { throw new ParameterException( this.commandLine, - "The `--Xethstats-contact` requires ethstats server URL to be provided. Either remove --Xethstats-contact" - + " or provide an url (via --Xethstats=nodename:secret@host:port)"); + "The `--ethstats-contact` requires ethstats server URL to be provided. Either remove --ethstats-contact" + + " or provide a URL (via --ethstats=nodename:secret@host:port)"); } } @@ -1401,24 +2016,111 @@ private void validateDnsOptionsParams() { } } + private void ensureValidPeerBoundParams() { + maxPeers = p2PDiscoveryOptionGroup.maxPeers; + peersLowerBound = unstableNetworkingOptions.toDomainObject().getPeerLowerBound(); + if (peersLowerBound > maxPeers) { + logger.warn( + "`--Xp2p-peer-lower-bound` " + + peersLowerBound + + " must not exceed --max-peers " + + maxPeers); + logger.warn("setting --Xp2p-peer-lower-bound=" + maxPeers); + peersLowerBound = maxPeers; + } + final Boolean isLimitRemoteWireConnectionsEnabled = + p2PDiscoveryOptionGroup.isLimitRemoteWireConnectionsEnabled; + if (isLimitRemoteWireConnectionsEnabled) { + final float fraction = + Fraction.fromPercentage(p2PDiscoveryOptionGroup.maxRemoteConnectionsPercentage) + .getValue(); + checkState( + fraction >= 0.0 && fraction <= 1.0, + "Fraction of remote connections allowed must be between 0.0 and 1.0 (inclusive)."); + maxRemoteInitiatedPeers = (int) Math.floor(fraction * maxPeers); + } else { + maxRemoteInitiatedPeers = maxPeers; + } + } + + private void validateRpcOptionsParams() { + final Predicate configuredApis = + apiName -> + Arrays.stream(RpcApis.values()) + .anyMatch(builtInApi -> apiName.equals(builtInApi.name())) + || rpcEndpointServiceImpl.hasNamespace(apiName); + + if (!jsonRPCHttpOptionGroup.rpcHttpApis.stream().allMatch(configuredApis)) { + final List invalidHttpApis = + new ArrayList(jsonRPCHttpOptionGroup.rpcHttpApis); + invalidHttpApis.removeAll(VALID_APIS); + throw new ParameterException( + this.commandLine, + "Invalid value for option '--rpc-http-api': invalid entries found " + + invalidHttpApis.toString()); + } + + if (!jsonRPCWebsocketOptionGroup.rpcWsApis.stream().allMatch(configuredApis)) { + final List invalidWsApis = + new ArrayList(jsonRPCWebsocketOptionGroup.rpcWsApis); + invalidWsApis.removeAll(VALID_APIS); + throw new ParameterException( + this.commandLine, + "Invalid value for option '--rpc-ws-api': invalid entries found " + invalidWsApis); + } + + final boolean validHttpApiMethods = + jsonRPCHttpOptionGroup.rpcHttpApiMethodsNoAuth.stream() + .allMatch(RpcMethod::rpcMethodExists); + + if (!validHttpApiMethods) { + throw new ParameterException( + this.commandLine, + "Invalid value for option '--rpc-http-api-methods-no-auth', options must be valid RPC methods"); + } + + final boolean validWsApiMethods = + jsonRPCWebsocketOptionGroup.rpcWsApiMethodsNoAuth.stream() + .allMatch(RpcMethod::rpcMethodExists); + + if (!validWsApiMethods) { + throw new ParameterException( + this.commandLine, + "Invalid value for option '--rpc-ws-api-methods-no-auth', options must be valid RPC methods"); + } + } + + private void validateChainDataPruningParams() { + if (unstableChainPruningOptions.getChainDataPruningEnabled() + && unstableChainPruningOptions.getChainDataPruningBlocksRetained() + < ChainPruningOptions.DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED) { + throw new ParameterException( + this.commandLine, + "--Xchain-pruning-blocks-retained must be >= " + + ChainPruningOptions.DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED); + } + } + private GenesisConfigOptions readGenesisConfigOptions() { - final GenesisConfigOptions genesisConfigOptions; + try { final GenesisConfigFile genesisConfigFile = GenesisConfigFile.fromConfig(genesisConfig()); genesisConfigOptions = genesisConfigFile.getConfigOptions(genesisConfigOverrides); - } catch (Exception e) { - throw new IllegalStateException("Unable to read genesis file for GoQuorum options", e); + } catch (final Exception e) { + throw new ParameterException( + this.commandLine, "Unable to load genesis file. " + e.getCause()); } return genesisConfigOptions; } private void issueOptionWarnings() { + // Check that P2P options are able to work CommandLineUtils.checkOptionDependencies( logger, commandLine, "--p2p-enabled", - !p2pEnabled, + !p2PDiscoveryOptionGroup.p2pEnabled, asList( "--bootnodes", "--discovery-enabled", @@ -1429,53 +2131,96 @@ private void issueOptionWarnings() { "--p2p-interface", "--p2p-port", "--remote-connections-max-percentage")); + + // Check that block producer options work + if (!isMergeEnabled()) { + CommandLineUtils.checkOptionDependencies( + logger, + commandLine, + "--miner-enabled", + !minerOptionGroup.isMiningEnabled, + asList( + "--miner-coinbase", + "--min-gas-price", + "--min-block-occupancy-ratio", + "--miner-extra-data")); + } // Check that mining options are able to work CommandLineUtils.checkOptionDependencies( logger, commandLine, "--miner-enabled", - !isMiningEnabled, + !minerOptionGroup.isMiningEnabled, asList( - "--miner-coinbase", - "--min-gas-price", - "--min-block-occupancy-ratio", - "--miner-extra-data", "--miner-stratum-enabled", "--Xminer-remote-sealers-limit", "--Xminer-remote-sealers-hashrate-ttl")); - CommandLineUtils.checkOptionDependencies( - logger, + CommandLineUtils.failIfOptionDoesntMeetRequirement( commandLine, - "--sync-mode", - !SyncMode.FAST.equals(syncMode), + "--fast-sync-min-peers can't be used with FULL sync-mode", + !SyncMode.isFullSync(getDefaultSyncModeIfNotSet()), singletonList("--fast-sync-min-peers")); - if (!securityModuleName.equals(DEFAULT_SECURITY_MODULE) && nodePrivateKeyFile != null) { + CommandLineUtils.failIfOptionDoesntMeetRequirement( + commandLine, + "--Xcheckpoint-post-merge-enabled can only be used with X_CHECKPOINT sync-mode", + SyncMode.X_CHECKPOINT.equals(getDefaultSyncModeIfNotSet()), + singletonList("--Xcheckpoint-post-merge-enabled")); + + CommandLineUtils.failIfOptionDoesntMeetRequirement( + commandLine, + "--Xsnapsync-synchronizer-flat option can only be used when -Xsnapsync-synchronizer-flat-db-healing-enabled is true", + unstableSynchronizerOptions.isSnapsyncFlatDbHealingEnabled(), + asList( + "--Xsnapsync-synchronizer-flat-account-healed-count-per-request", + "--Xsnapsync-synchronizer-flat-slot-healed-count-per-request")); + + if (!securityModuleName.equals(DEFAULT_SECURITY_MODULE) + && nodePrivateKeyFileOption.getNodePrivateKeyFile() != null) { logger.warn( DEPENDENCY_WARNING_MSG, "--node-private-key-file", "--security-module=" + DEFAULT_SECURITY_MODULE); } + + if (Boolean.TRUE.equals(privacyOptionGroup.isOnchainPrivacyGroupsEnabled)) { + logger.warn( + DEPRECATION_WARNING_MSG, + "--privacy-onchain-groups-enabled", + "--privacy-flexible-groups-enabled"); + } } - private BesuCommand configure() throws Exception { + private void configure() throws Exception { checkPortClash(); + checkIfRequiredPortsAreAvailable(); + syncMode = getDefaultSyncModeIfNotSet(); - syncMode = - Optional.ofNullable(syncMode) - .orElse( - genesisFile == null && !isPrivacyEnabled && network != NetworkName.DEV - ? SyncMode.FAST - : SyncMode.FULL); + ethNetworkConfig = updateNetworkConfig(network); - ethNetworkConfig = updateNetworkConfig(getNetwork()); - if (isGoQuorumCompatibilityMode) { - checkGoQuorumCompatibilityConfig(ethNetworkConfig); + checkGoQuorumCompatibilityConfig(ethNetworkConfig); + + jsonRpcConfiguration = + jsonRpcConfiguration( + jsonRPCHttpOptionGroup.rpcHttpPort, jsonRPCHttpOptionGroup.rpcHttpApis, hostsAllowlist); + if (isEngineApiEnabled()) { + engineJsonRpcConfiguration = + createEngineJsonRpcConfiguration( + engineRPCOptionGroup.engineRpcPort, engineRPCOptionGroup.engineHostsAllowlist); } - jsonRpcConfiguration = jsonRpcConfiguration(); + p2pTLSConfiguration = p2pTLSConfigOptions.p2pTLSConfiguration(commandLine); graphQLConfiguration = graphQLConfiguration(); - webSocketConfiguration = webSocketConfiguration(); + webSocketConfiguration = + webSocketConfiguration( + jsonRPCWebsocketOptionGroup.rpcWsPort, + jsonRPCWebsocketOptionGroup.rpcWsApis, + hostsAllowlist); + jsonRpcIpcConfiguration = + jsonRpcIpcConfiguration( + unstableIpcOptions.isEnabled(), + unstableIpcOptions.getIpcPath(), + unstableIpcOptions.getRpcIpcApis()); apiConfiguration = apiConfiguration(); // hostsWhitelist is a hidden option. If it is specified, add the list to hostAllowlist if (!hostsWhitelist.isEmpty()) { @@ -1490,8 +2235,6 @@ private BesuCommand configure() throws Exception { permissioningConfiguration = permissioningConfiguration(); staticNodes = loadStaticNodes(); - logger.info("Connecting to {} static nodes.", staticNodes.size()); - logger.trace("Static Nodes = {}", staticNodes); final List enodeURIs = ethNetworkConfig.getBootNodes(); permissioningConfiguration .flatMap(PermissioningConfiguration::getLocalConfig) @@ -1502,14 +2245,24 @@ private BesuCommand configure() throws Exception { .ifPresent(p -> ensureAllNodesAreInAllowlist(staticNodes, p)); metricsConfiguration = metricsConfiguration(); + instantiateSignatureAlgorithmFactory(); + + logger.info(generateConfigurationOverview()); + logger.info("Connecting to {} static nodes.", staticNodes.size()); + logger.trace("Static Nodes = {}", staticNodes); logger.info("Security Module: {}", securityModuleName); - return this; } - private NetworkName getNetwork() { - // noinspection ConstantConditions network is not always null but injected by - // PicoCLI if used - return network == null ? MAINNET : network; + private JsonRpcIpcConfiguration jsonRpcIpcConfiguration( + final Boolean enabled, final Path ipcPath, final List rpcIpcApis) { + final Path actualPath; + if (ipcPath == null) { + actualPath = IpcOptions.getDefaultPath(dataDir()); + } else { + actualPath = ipcPath; + } + return new JsonRpcIpcConfiguration( + vertx.isNativeTransportEnabled() && enabled, actualPath, rpcIpcApis); } private void ensureAllNodesAreInAllowlist( @@ -1523,57 +2276,95 @@ private void ensureAllNodesAreInAllowlist( } } - private BesuCommand controller() { - besuController = buildController(); - return this; + private BesuController initController() { + return buildController(); } + /** + * Builds BesuController + * + * @return instance of BesuController + */ public BesuController buildController() { try { - return getControllerBuilder().build(); + return this.besuComponent == null + ? getControllerBuilder().build() + : getControllerBuilder().besuComponent(this.besuComponent).build(); } catch (final Exception e) { throw new ExecutionException(this.commandLine, e.getMessage(), e); } } + /** + * Builds BesuControllerBuilder which can be used to build BesuController + * + * @return instance of BesuControllerBuilder + */ public BesuControllerBuilder getControllerBuilder() { + final KeyValueStorageProvider storageProvider = keyValueStorageProvider(keyValueStorageName); + final Optional transactionSelectorFactory = + getTransactionSelectorFactory(); return controllerBuilderFactory - .fromEthNetworkConfig(updateNetworkConfig(getNetwork()), genesisConfigOverrides) + .fromEthNetworkConfig( + updateNetworkConfig(network), genesisConfigOverrides, getDefaultSyncModeIfNotSet()) .synchronizerConfiguration(buildSyncConfig()) .ethProtocolConfiguration(unstableEthProtocolOptions.toDomainObject()) + .networkConfiguration(unstableNetworkingOptions.toDomainObject()) + .transactionSelectorFactory(transactionSelectorFactory) .dataDirectory(dataDir()) .miningParameters( - new MiningParameters( - coinbase, - minTransactionGasPrice, - extraData, - isMiningEnabled, - iStratumMiningEnabled, - stratumNetworkInterface, - stratumPort, - unstableMiningOptions.getStratumExtranonce(), - Optional.empty(), - minBlockOccupancyRatio, - unstableMiningOptions.getRemoteSealersLimit(), - unstableMiningOptions.getRemoteSealersTimeToLive())) + new MiningParameters.Builder() + .coinbase(minerOptionGroup.coinbase) + .targetGasLimit(targetGasLimit) + .minTransactionGasPrice(minTransactionGasPrice) + .extraData(minerOptionGroup.extraData) + .miningEnabled(minerOptionGroup.isMiningEnabled) + .stratumMiningEnabled(minerOptionGroup.iStratumMiningEnabled) + .stratumNetworkInterface(minerOptionGroup.stratumNetworkInterface) + .stratumPort(minerOptionGroup.stratumPort) + .stratumExtranonce(unstableMiningOptions.getStratumExtranonce()) + .minBlockOccupancyRatio(minBlockOccupancyRatio) + .remoteSealersLimit(unstableMiningOptions.getRemoteSealersLimit()) + .remoteSealersTimeToLive(unstableMiningOptions.getRemoteSealersTimeToLive()) + .powJobTimeToLive(unstableMiningOptions.getPowJobTimeToLive()) + .maxOmmerDepth(unstableMiningOptions.getMaxOmmersDepth()) + .posBlockCreationMaxTime(unstableMiningOptions.getPosBlockCreationMaxTime()) + .posBlockCreationRepetitionMinDuration( + unstableMiningOptions.getPosBlockCreationRepetitionMinDuration()) + .build()) .transactionPoolConfiguration(buildTransactionPoolConfiguration()) - .nodeKey(buildNodeKey()) + .nodeKey(new NodeKey(securityModule())) .metricsSystem(metricsSystem.get()) + .messagePermissioningProviders(permissioningService.getMessagePermissioningProviders()) .privacyParameters(privacyParameters()) + .pkiBlockCreationConfiguration(maybePkiBlockCreationConfiguration()) .clock(Clock.systemUTC()) .isRevertReasonEnabled(isRevertReasonEnabled) - .storageProvider(keyStorageProvider(keyValueStorageName)) + .storageProvider(storageProvider) .isPruningEnabled(isPruningEnabled()) .pruningConfiguration( new PrunerConfiguration(pruningBlockConfirmations, pruningBlocksRetained)) .genesisConfigOverrides(genesisConfigOverrides) .gasLimitCalculator( Optional.ofNullable(targetGasLimit) - .map(TargetingGasLimitCalculator::new) + .map(z -> new FrontierTargetingGasLimitCalculator()) .orElse(GasLimitCalculator.constant())) .requiredBlocks(requiredBlocks) .reorgLoggingThreshold(reorgLoggingThreshold) - .dataStorageConfiguration(unstableDataStorageOptions.toDomainObject()); + .evmConfiguration(unstableEvmOptions.toDomainObject()) + .dataStorageConfiguration(dataStorageOptions.toDomainObject()) + .maxPeers(p2PDiscoveryOptionGroup.maxPeers) + .lowerBoundPeers(peersLowerBound) + .maxRemotelyInitiatedPeers(maxRemoteInitiatedPeers) + .randomPeerPriority(p2PDiscoveryOptionGroup.randomPeerPriority) + .chainPruningConfiguration(unstableChainPruningOptions.toDomainObject()); + } + + @NotNull + private Optional getTransactionSelectorFactory() { + final Optional txSelectionService = + besuPluginContext.getService(TransactionSelectionService.class); + return txSelectionService.isPresent() ? txSelectionService.get().get() : Optional.empty(); } private GraphQLConfiguration graphQLConfiguration() { @@ -1582,35 +2373,109 @@ private GraphQLConfiguration graphQLConfiguration() { logger, commandLine, "--graphql-http-enabled", - !isGraphQLHttpEnabled, + !graphQlOptionGroup.isGraphQLHttpEnabled, asList("--graphql-http-cors-origins", "--graphql-http-host", "--graphql-http-port")); - final GraphQLConfiguration graphQLConfiguration = GraphQLConfiguration.createDefault(); - graphQLConfiguration.setEnabled(isGraphQLHttpEnabled); - graphQLConfiguration.setHost(graphQLHttpHost); - graphQLConfiguration.setPort(graphQLHttpPort); + graphQLConfiguration.setEnabled(graphQlOptionGroup.isGraphQLHttpEnabled); + graphQLConfiguration.setHost( + Strings.isNullOrEmpty(graphQlOptionGroup.graphQLHttpHost) + ? p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress() + : graphQlOptionGroup.graphQLHttpHost); + graphQLConfiguration.setPort(graphQlOptionGroup.graphQLHttpPort); graphQLConfiguration.setHostsAllowlist(hostsAllowlist); - graphQLConfiguration.setCorsAllowedDomains(graphQLHttpCorsAllowedOrigins); + graphQLConfiguration.setCorsAllowedDomains(graphQlOptionGroup.graphQLHttpCorsAllowedOrigins); graphQLConfiguration.setHttpTimeoutSec(unstableRPCOptions.getHttpTimeoutSec()); return graphQLConfiguration; } - private JsonRpcConfiguration jsonRpcConfiguration() { + private JsonRpcConfiguration createEngineJsonRpcConfiguration( + final Integer listenPort, final List allowCallsFrom) { + final JsonRpcConfiguration engineConfig = + jsonRpcConfiguration(listenPort, Arrays.asList("ENGINE", "ETH"), allowCallsFrom); + engineConfig.setEnabled(isEngineApiEnabled()); + if (!engineRPCOptionGroup.isEngineAuthDisabled) { + engineConfig.setAuthenticationEnabled(true); + engineConfig.setAuthenticationAlgorithm(JwtAlgorithm.HS256); + if (Objects.nonNull(engineRPCOptionGroup.engineJwtKeyFile) + && java.nio.file.Files.exists(engineRPCOptionGroup.engineJwtKeyFile)) { + engineConfig.setAuthenticationPublicKeyFile(engineRPCOptionGroup.engineJwtKeyFile.toFile()); + } else { + logger.warn( + "Engine API authentication enabled without key file. Expect ephemeral jwt.hex file in datadir"); + } + } + return engineConfig; + } + + private JsonRpcConfiguration jsonRpcConfiguration( + final Integer listenPort, final List apiGroups, final List allowCallsFrom) { checkRpcTlsClientAuthOptionsDependencies(); checkRpcTlsOptionsDependencies(); + checkRpcHttpOptionsDependencies(); + + if (jsonRPCHttpOptionGroup.isRpcHttpAuthenticationEnabled) { + CommandLineUtils.checkOptionDependencies( + logger, + commandLine, + "--rpc-http-authentication-public-key-file", + jsonRPCHttpOptionGroup.rpcHttpAuthenticationPublicKeyFile == null, + asList("--rpc-http-authentication-jwt-algorithm")); + } + + if (jsonRPCHttpOptionGroup.isRpcHttpAuthenticationEnabled + && rpcHttpAuthenticationCredentialsFile() == null + && jsonRPCHttpOptionGroup.rpcHttpAuthenticationPublicKeyFile == null) { + throw new ParameterException( + commandLine, + "Unable to authenticate JSON-RPC HTTP endpoint without a supplied credentials file or authentication public key file"); + } + + final JsonRpcConfiguration jsonRpcConfiguration = JsonRpcConfiguration.createDefault(); + jsonRpcConfiguration.setEnabled(jsonRPCHttpOptionGroup.isRpcHttpEnabled); + jsonRpcConfiguration.setHost( + Strings.isNullOrEmpty(jsonRPCHttpOptionGroup.rpcHttpHost) + ? p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress() + : jsonRPCHttpOptionGroup.rpcHttpHost); + jsonRpcConfiguration.setPort(listenPort); + jsonRpcConfiguration.setMaxActiveConnections(jsonRPCHttpOptionGroup.rpcHttpMaxConnections); + jsonRpcConfiguration.setCorsAllowedDomains(jsonRPCHttpOptionGroup.rpcHttpCorsAllowedOrigins); + jsonRpcConfiguration.setRpcApis(apiGroups.stream().distinct().collect(Collectors.toList())); + jsonRpcConfiguration.setNoAuthRpcApis( + jsonRPCHttpOptionGroup.rpcHttpApiMethodsNoAuth.stream() + .distinct() + .collect(Collectors.toList())); + jsonRpcConfiguration.setHostsAllowlist(allowCallsFrom); + jsonRpcConfiguration.setAuthenticationEnabled( + jsonRPCHttpOptionGroup.isRpcHttpAuthenticationEnabled); + jsonRpcConfiguration.setAuthenticationCredentialsFile(rpcHttpAuthenticationCredentialsFile()); + jsonRpcConfiguration.setAuthenticationPublicKeyFile( + jsonRPCHttpOptionGroup.rpcHttpAuthenticationPublicKeyFile); + jsonRpcConfiguration.setAuthenticationAlgorithm( + jsonRPCHttpOptionGroup.rpcHttpAuthenticationAlgorithm); + jsonRpcConfiguration.setTlsConfiguration(rpcHttpTlsConfiguration()); + jsonRpcConfiguration.setHttpTimeoutSec(unstableRPCOptions.getHttpTimeoutSec()); + jsonRpcConfiguration.setMaxBatchSize(jsonRPCHttpOptionGroup.rpcHttpMaxBatchSize); + jsonRpcConfiguration.setMaxRequestContentLength( + jsonRPCHttpOptionGroup.rpcHttpMaxRequestContentLength); + return jsonRpcConfiguration; + } + private void checkRpcHttpOptionsDependencies() { CommandLineUtils.checkOptionDependencies( logger, commandLine, "--rpc-http-enabled", - !isRpcHttpEnabled, + !jsonRPCHttpOptionGroup.isRpcHttpEnabled, asList( "--rpc-http-api", "--rpc-http-apis", + "--rpc-http-api-method-no-auth", + "--rpc-http-api-methods-no-auth", "--rpc-http-cors-origins", "--rpc-http-host", "--rpc-http-port", + "--rpc-http-max-active-connections", "--rpc-http-authentication-enabled", "--rpc-http-authentication-credentials-file", "--rpc-http-authentication-public-key-file", @@ -1619,29 +2484,11 @@ private JsonRpcConfiguration jsonRpcConfiguration() { "--rpc-http-tls-keystore-password-file", "--rpc-http-tls-client-auth-enabled", "--rpc-http-tls-known-clients-file", - "--rpc-http-tls-ca-clients-enabled")); - - if (isRpcHttpAuthenticationEnabled - && rpcHttpAuthenticationCredentialsFile() == null - && rpcHttpAuthenticationPublicKeyFile == null) { - throw new ParameterException( - commandLine, - "Unable to authenticate JSON-RPC HTTP endpoint without a supplied credentials file or authentication public key file"); - } - - final JsonRpcConfiguration jsonRpcConfiguration = JsonRpcConfiguration.createDefault(); - jsonRpcConfiguration.setEnabled(isRpcHttpEnabled); - jsonRpcConfiguration.setHost(rpcHttpHost); - jsonRpcConfiguration.setPort(rpcHttpPort); - jsonRpcConfiguration.setCorsAllowedDomains(rpcHttpCorsAllowedOrigins); - jsonRpcConfiguration.setRpcApis(rpcHttpApis.stream().distinct().collect(Collectors.toList())); - jsonRpcConfiguration.setHostsAllowlist(hostsAllowlist); - jsonRpcConfiguration.setAuthenticationEnabled(isRpcHttpAuthenticationEnabled); - jsonRpcConfiguration.setAuthenticationCredentialsFile(rpcHttpAuthenticationCredentialsFile()); - jsonRpcConfiguration.setAuthenticationPublicKeyFile(rpcHttpAuthenticationPublicKeyFile); - jsonRpcConfiguration.setTlsConfiguration(rpcHttpTlsConfiguration()); - jsonRpcConfiguration.setHttpTimeoutSec(unstableRPCOptions.getHttpTimeoutSec()); - return jsonRpcConfiguration; + "--rpc-http-tls-ca-clients-enabled", + "--rpc-http-authentication-jwt-algorithm", + "--rpc-http-tls-protocols", + "--rpc-http-tls-cipher-suite", + "--rpc-http-tls-cipher-suites")); } private void checkRpcTlsOptionsDependencies() { @@ -1649,13 +2496,16 @@ private void checkRpcTlsOptionsDependencies() { logger, commandLine, "--rpc-http-tls-enabled", - !isRpcHttpTlsEnabled, + !jsonRPCHttpOptionGroup.isRpcHttpTlsEnabled, asList( "--rpc-http-tls-keystore-file", "--rpc-http-tls-keystore-password-file", "--rpc-http-tls-client-auth-enabled", "--rpc-http-tls-known-clients-file", - "--rpc-http-tls-ca-clients-enabled")); + "--rpc-http-tls-ca-clients-enabled", + "--rpc-http-tls-protocols", + "--rpc-http-tls-cipher-suite", + "--rpc-http-tls-cipher-suites")); } private void checkRpcTlsClientAuthOptionsDependencies() { @@ -1663,7 +2513,7 @@ private void checkRpcTlsClientAuthOptionsDependencies() { logger, commandLine, "--rpc-http-tls-client-auth-enabled", - !isRpcHttpTlsClientAuthEnabled, + !jsonRPCHttpOptionGroup.isRpcHttpTlsClientAuthEnabled, asList("--rpc-http-tls-known-clients-file", "--rpc-http-tls-ca-clients-enabled")); } @@ -1672,7 +2522,7 @@ private void checkPrivacyTlsOptionsDependencies() { logger, commandLine, "--privacy-tls-enabled", - !isPrivacyTlsEnabled, + !privacyOptionGroup.isPrivacyTlsEnabled, asList( "--privacy-tls-keystore-file", "--privacy-tls-keystore-password-file", @@ -1684,39 +2534,60 @@ private Optional rpcHttpTlsConfiguration() { return Optional.empty(); } - if (rpcHttpTlsKeyStoreFile == null) { + if (jsonRPCHttpOptionGroup.rpcHttpTlsKeyStoreFile == null) { throw new ParameterException( commandLine, "Keystore file is required when TLS is enabled for JSON-RPC HTTP endpoint"); } - if (rpcHttpTlsKeyStorePasswordFile == null) { + if (jsonRPCHttpOptionGroup.rpcHttpTlsKeyStorePasswordFile == null) { throw new ParameterException( commandLine, "File containing password to unlock keystore is required when TLS is enabled for JSON-RPC HTTP endpoint"); } - if (isRpcHttpTlsClientAuthEnabled - && !isRpcHttpTlsCAClientsEnabled - && rpcHttpTlsKnownClientsFile == null) { + if (jsonRPCHttpOptionGroup.isRpcHttpTlsClientAuthEnabled + && !jsonRPCHttpOptionGroup.isRpcHttpTlsCAClientsEnabled + && jsonRPCHttpOptionGroup.rpcHttpTlsKnownClientsFile == null) { throw new ParameterException( commandLine, "Known-clients file must be specified or CA clients must be enabled when TLS client authentication is enabled for JSON-RPC HTTP endpoint"); } + jsonRPCHttpOptionGroup.rpcHttpTlsProtocols.retainAll(getJDKEnabledProtocols()); + if (jsonRPCHttpOptionGroup.rpcHttpTlsProtocols.isEmpty()) { + throw new ParameterException( + commandLine, + "No valid TLS protocols specified (the following protocols are enabled: " + + getJDKEnabledProtocols() + + ")"); + } + + for (final String cipherSuite : jsonRPCHttpOptionGroup.rpcHttpTlsCipherSuites) { + if (!getJDKEnabledCipherSuites().contains(cipherSuite)) { + throw new ParameterException( + commandLine, "Invalid TLS cipher suite specified " + cipherSuite); + } + } + + jsonRPCHttpOptionGroup.rpcHttpTlsCipherSuites.retainAll(getJDKEnabledCipherSuites()); + return Optional.of( TlsConfiguration.Builder.aTlsConfiguration() - .withKeyStorePath(rpcHttpTlsKeyStoreFile) + .withKeyStorePath(jsonRPCHttpOptionGroup.rpcHttpTlsKeyStoreFile) .withKeyStorePasswordSupplier( - new FileBasedPasswordProvider(rpcHttpTlsKeyStorePasswordFile)) + new FileBasedPasswordProvider( + jsonRPCHttpOptionGroup.rpcHttpTlsKeyStorePasswordFile)) .withClientAuthConfiguration(rpcHttpTlsClientAuthConfiguration()) + .withSecureTransportProtocols(jsonRPCHttpOptionGroup.rpcHttpTlsProtocols) + .withCipherSuites(jsonRPCHttpOptionGroup.rpcHttpTlsCipherSuites) .build()); } private TlsClientAuthConfiguration rpcHttpTlsClientAuthConfiguration() { - if (isRpcHttpTlsClientAuthEnabled) { + if (jsonRPCHttpOptionGroup.isRpcHttpTlsClientAuthEnabled) { return TlsClientAuthConfiguration.Builder.aTlsClientAuthConfiguration() - .withKnownClientsFile(rpcHttpTlsKnownClientsFile) - .withCaClientsEnabled(isRpcHttpTlsCAClientsEnabled) + .withKnownClientsFile(jsonRPCHttpOptionGroup.rpcHttpTlsKnownClientsFile) + .withCaClientsEnabled(jsonRPCHttpOptionGroup.isRpcHttpTlsCAClientsEnabled) .build(); } @@ -1724,42 +2595,70 @@ private TlsClientAuthConfiguration rpcHttpTlsClientAuthConfiguration() { } private boolean isRpcTlsConfigurationRequired() { - return isRpcHttpEnabled && isRpcHttpTlsEnabled; + return jsonRPCHttpOptionGroup.isRpcHttpEnabled && jsonRPCHttpOptionGroup.isRpcHttpTlsEnabled; } - private WebSocketConfiguration webSocketConfiguration() { + private WebSocketConfiguration webSocketConfiguration( + final Integer listenPort, final List apiGroups, final List allowCallsFrom) { CommandLineUtils.checkOptionDependencies( logger, commandLine, "--rpc-ws-enabled", - !isRpcWsEnabled, + !jsonRPCWebsocketOptionGroup.isRpcWsEnabled, asList( "--rpc-ws-api", "--rpc-ws-apis", + "--rpc-ws-api-method-no-auth", + "--rpc-ws-api-methods-no-auth", "--rpc-ws-host", "--rpc-ws-port", + "--rpc-ws-max-frame-size", + "--rpc-ws-max-active-connections", "--rpc-ws-authentication-enabled", "--rpc-ws-authentication-credentials-file", - "--rpc-ws-authentication-public-key-file")); + "--rpc-ws-authentication-public-key-file", + "--rpc-ws-authentication-jwt-algorithm")); - if (isRpcWsAuthenticationEnabled + if (jsonRPCWebsocketOptionGroup.isRpcWsAuthenticationEnabled) { + CommandLineUtils.checkOptionDependencies( + logger, + commandLine, + "--rpc-ws-authentication-public-key-file", + jsonRPCWebsocketOptionGroup.rpcWsAuthenticationPublicKeyFile == null, + asList("--rpc-ws-authentication-jwt-algorithm")); + } + + if (jsonRPCWebsocketOptionGroup.isRpcWsAuthenticationEnabled && rpcWsAuthenticationCredentialsFile() == null - && rpcWsAuthenticationPublicKeyFile == null) { + && jsonRPCWebsocketOptionGroup.rpcWsAuthenticationPublicKeyFile == null) { throw new ParameterException( commandLine, "Unable to authenticate JSON-RPC WebSocket endpoint without a supplied credentials file or authentication public key file"); } final WebSocketConfiguration webSocketConfiguration = WebSocketConfiguration.createDefault(); - webSocketConfiguration.setEnabled(isRpcWsEnabled); - webSocketConfiguration.setHost(rpcWsHost); - webSocketConfiguration.setPort(rpcWsPort); - webSocketConfiguration.setRpcApis(rpcWsApis); - webSocketConfiguration.setAuthenticationEnabled(isRpcWsAuthenticationEnabled); + webSocketConfiguration.setEnabled(jsonRPCWebsocketOptionGroup.isRpcWsEnabled); + webSocketConfiguration.setHost( + Strings.isNullOrEmpty(jsonRPCWebsocketOptionGroup.rpcWsHost) + ? p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress() + : jsonRPCWebsocketOptionGroup.rpcWsHost); + webSocketConfiguration.setPort(listenPort); + webSocketConfiguration.setMaxFrameSize(jsonRPCWebsocketOptionGroup.rpcWsMaxFrameSize); + webSocketConfiguration.setMaxActiveConnections(jsonRPCWebsocketOptionGroup.rpcWsMaxConnections); + webSocketConfiguration.setRpcApis(apiGroups); + webSocketConfiguration.setRpcApisNoAuth( + jsonRPCWebsocketOptionGroup.rpcWsApiMethodsNoAuth.stream() + .distinct() + .collect(Collectors.toList())); + webSocketConfiguration.setAuthenticationEnabled( + jsonRPCWebsocketOptionGroup.isRpcWsAuthenticationEnabled); webSocketConfiguration.setAuthenticationCredentialsFile(rpcWsAuthenticationCredentialsFile()); - webSocketConfiguration.setHostsAllowlist(hostsAllowlist); - webSocketConfiguration.setAuthenticationPublicKeyFile(rpcWsAuthenticationPublicKeyFile); + webSocketConfiguration.setHostsAllowlist(allowCallsFrom); + webSocketConfiguration.setAuthenticationPublicKeyFile( + jsonRPCWebsocketOptionGroup.rpcWsAuthenticationPublicKeyFile); + webSocketConfiguration.setAuthenticationAlgorithm( + jsonRPCWebsocketOptionGroup.rpcWebsocketsAuthenticationAlgorithm); webSocketConfiguration.setTimeoutSec(unstableRPCOptions.getWsTimeoutSec()); return webSocketConfiguration; } @@ -1773,8 +2672,13 @@ private ApiConfiguration apiConfiguration() { .build(); } + /** + * Metrics Configuration for Besu + * + * @return instance of MetricsConfiguration. + */ public MetricsConfiguration metricsConfiguration() { - if (isMetricsEnabled && isMetricsPushEnabled) { + if (metricsOptionGroup.isMetricsEnabled && metricsOptionGroup.isMetricsPushEnabled) { throw new ParameterException( this.commandLine, "--metrics-enabled option and --metrics-push-enabled option can't be used at the same " @@ -1785,14 +2689,14 @@ public MetricsConfiguration metricsConfiguration() { logger, commandLine, "--metrics-enabled", - !isMetricsEnabled, + !metricsOptionGroup.isMetricsEnabled, asList("--metrics-host", "--metrics-port")); CommandLineUtils.checkOptionDependencies( logger, commandLine, "--metrics-push-enabled", - !isMetricsPushEnabled, + !metricsOptionGroup.isMetricsPushEnabled, asList( "--metrics-push-host", "--metrics-push-port", @@ -1801,23 +2705,30 @@ public MetricsConfiguration metricsConfiguration() { return unstableMetricsCLIOptions .toDomainObject() - .enabled(isMetricsEnabled) - .host(metricsHost) - .port(metricsPort) - .protocol(metricsProtocol) - .metricCategories(metricCategories) - .pushEnabled(isMetricsPushEnabled) - .pushHost(metricsPushHost) - .pushPort(metricsPushPort) - .pushInterval(metricsPushInterval) + .enabled(metricsOptionGroup.isMetricsEnabled) + .host( + Strings.isNullOrEmpty(metricsOptionGroup.metricsHost) + ? p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress() + : metricsOptionGroup.metricsHost) + .port(metricsOptionGroup.metricsPort) + .protocol(metricsOptionGroup.metricsProtocol) + .metricCategories(metricsOptionGroup.metricCategories) + .pushEnabled(metricsOptionGroup.isMetricsPushEnabled) + .pushHost( + Strings.isNullOrEmpty(metricsOptionGroup.metricsPushHost) + ? p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress() + : metricsOptionGroup.metricsPushHost) + .pushPort(metricsOptionGroup.metricsPushPort) + .pushInterval(metricsOptionGroup.metricsPushInterval) .hostsAllowlist(hostsAllowlist) - .prometheusJob(metricsPrometheusJob) + .prometheusJob(metricsOptionGroup.metricsPrometheusJob) .build(); } private Optional permissioningConfiguration() throws Exception { if (!(localPermissionsEnabled() || contractPermissionsEnabled())) { - if (rpcHttpApis.contains(RpcApis.PERM) || rpcWsApis.contains(RpcApis.PERM)) { + if (jsonRPCHttpOptionGroup.rpcHttpApis.contains(RpcApis.PERM.name()) + || jsonRPCWebsocketOptionGroup.rpcWsApis.contains(RpcApis.PERM.name())) { logger.warn( "Permissions are disabled. Cannot enable PERM APIs when not using Permissions."); } @@ -1827,30 +2738,32 @@ private Optional permissioningConfiguration() throws final Optional localPermissioningConfigurationOptional; if (localPermissionsEnabled()) { final Optional nodePermissioningConfigFile = - Optional.ofNullable(nodePermissionsConfigFile); + Optional.ofNullable(permissionsOptionGroup.nodePermissionsConfigFile); final Optional accountPermissioningConfigFile = - Optional.ofNullable(accountPermissionsConfigFile); + Optional.ofNullable(permissionsOptionGroup.accountPermissionsConfigFile); final LocalPermissioningConfiguration localPermissioningConfiguration = PermissioningConfigurationBuilder.permissioningConfiguration( - permissionsNodesEnabled, + permissionsOptionGroup.permissionsNodesEnabled, getEnodeDnsConfiguration(), nodePermissioningConfigFile.orElse(getDefaultPermissioningFilePath()), - permissionsAccountsEnabled, + permissionsOptionGroup.permissionsAccountsEnabled, accountPermissioningConfigFile.orElse(getDefaultPermissioningFilePath())); localPermissioningConfigurationOptional = Optional.of(localPermissioningConfiguration); } else { - if (nodePermissionsConfigFile != null && !permissionsNodesEnabled) { + if (permissionsOptionGroup.nodePermissionsConfigFile != null + && !permissionsOptionGroup.permissionsNodesEnabled) { logger.warn( "Node permissioning config file set {} but no permissions enabled", - nodePermissionsConfigFile); + permissionsOptionGroup.nodePermissionsConfigFile); } - if (accountPermissionsConfigFile != null && !permissionsAccountsEnabled) { + if (permissionsOptionGroup.accountPermissionsConfigFile != null + && !permissionsOptionGroup.permissionsAccountsEnabled) { logger.warn( "Account permissioning config file set {} but no permissions enabled", - accountPermissionsConfigFile); + permissionsOptionGroup.accountPermissionsConfigFile); } localPermissioningConfigurationOptional = Optional.empty(); } @@ -1858,40 +2771,40 @@ private Optional permissioningConfiguration() throws final SmartContractPermissioningConfiguration smartContractPermissioningConfiguration = SmartContractPermissioningConfiguration.createDefault(); - if (permissionsNodesContractEnabled) { - if (permissionsNodesContractAddress == null) { + if (Boolean.TRUE.equals(permissionsOptionGroup.permissionsNodesContractEnabled)) { + if (permissionsOptionGroup.permissionsNodesContractAddress == null) { throw new ParameterException( this.commandLine, "No node permissioning contract address specified. Cannot enable smart contract based node permissioning."); } else { smartContractPermissioningConfiguration.setSmartContractNodeAllowlistEnabled( - permissionsNodesContractEnabled); + permissionsOptionGroup.permissionsNodesContractEnabled); smartContractPermissioningConfiguration.setNodeSmartContractAddress( - permissionsNodesContractAddress); + permissionsOptionGroup.permissionsNodesContractAddress); smartContractPermissioningConfiguration.setNodeSmartContractInterfaceVersion( - permissionsNodesContractVersion); + permissionsOptionGroup.permissionsNodesContractVersion); } - } else if (permissionsNodesContractAddress != null) { + } else if (permissionsOptionGroup.permissionsNodesContractAddress != null) { logger.warn( "Node permissioning smart contract address set {} but smart contract node permissioning is disabled.", - permissionsNodesContractAddress); + permissionsOptionGroup.permissionsNodesContractAddress); } - if (permissionsAccountsContractEnabled) { - if (permissionsAccountsContractAddress == null) { + if (Boolean.TRUE.equals(permissionsOptionGroup.permissionsAccountsContractEnabled)) { + if (permissionsOptionGroup.permissionsAccountsContractAddress == null) { throw new ParameterException( this.commandLine, "No account permissioning contract address specified. Cannot enable smart contract based account permissioning."); } else { smartContractPermissioningConfiguration.setSmartContractAccountAllowlistEnabled( - permissionsAccountsContractEnabled); + permissionsOptionGroup.permissionsAccountsContractEnabled); smartContractPermissioningConfiguration.setAccountSmartContractAddress( - permissionsAccountsContractAddress); + permissionsOptionGroup.permissionsAccountsContractAddress); } - } else if (permissionsAccountsContractAddress != null) { + } else if (permissionsOptionGroup.permissionsAccountsContractAddress != null) { logger.warn( "Account permissioning smart contract address set {} but smart contract account permissioning is disabled.", - permissionsAccountsContractAddress); + permissionsOptionGroup.permissionsAccountsContractAddress); } final PermissioningConfiguration permissioningConfiguration = @@ -1903,27 +2816,29 @@ private Optional permissioningConfiguration() throws return Optional.of(permissioningConfiguration); } - private Optional quorumPermissioningConfig() { + private Optional quorumPermissioningConfig() { if (!isGoQuorumCompatibilityMode) { return Optional.empty(); } try { - final GenesisConfigOptions genesisConfigOptions = readGenesisConfigOptions(); final OptionalLong qip714BlockNumber = genesisConfigOptions.getQip714BlockNumber(); return Optional.of( - QuorumPermissioningConfiguration.enabled(qip714BlockNumber.orElse(QIP714_DEFAULT_BLOCK))); - } catch (Exception e) { + GoQuorumPermissioningConfiguration.enabled( + qip714BlockNumber.orElse(QIP714_DEFAULT_BLOCK))); + } catch (final Exception e) { throw new IllegalStateException("Error reading GoQuorum permissioning options", e); } } private boolean localPermissionsEnabled() { - return permissionsAccountsEnabled || permissionsNodesEnabled; + return permissionsOptionGroup.permissionsAccountsEnabled + || permissionsOptionGroup.permissionsNodesEnabled; } private boolean contractPermissionsEnabled() { - return permissionsNodesContractEnabled || permissionsAccountsContractEnabled; + return permissionsOptionGroup.permissionsNodesContractEnabled + || permissionsOptionGroup.permissionsAccountsContractEnabled; } private PrivacyParameters privacyParameters() { @@ -1932,17 +2847,20 @@ private PrivacyParameters privacyParameters() { logger, commandLine, "--privacy-enabled", - !isPrivacyEnabled, - asList( - "--privacy-url", - "--privacy-public-key-file", - "--privacy-multi-tenancy-enabled", - "--privacy-tls-enabled")); + !privacyOptionGroup.isPrivacyEnabled, + asList("--privacy-multi-tenancy-enabled", "--privacy-tls-enabled")); + + CommandLineUtils.checkMultiOptionDependencies( + logger, + commandLine, + "--privacy-url and/or --privacy-public-key-file ignored because none of --privacy-enabled or isQuorum (in genesis file) was defined.", + List.of(!privacyOptionGroup.isPrivacyEnabled, !isGoQuorumCompatibilityMode), + List.of("--privacy-url", "--privacy-public-key-file")); checkPrivacyTlsOptionsDependencies(); final PrivacyParameters.Builder privacyParametersBuilder = new PrivacyParameters.Builder(); - if (isPrivacyEnabled) { + if (Boolean.TRUE.equals(privacyOptionGroup.isPrivacyEnabled)) { final String errorSuffix = "cannot be enabled with privacy."; if (syncMode == SyncMode.FAST) { throw new ParameterException(commandLine, String.format("%s %s", "Fast sync", errorSuffix)); @@ -1950,24 +2868,49 @@ private PrivacyParameters privacyParameters() { if (isPruningEnabled()) { throw new ParameterException(commandLine, String.format("%s %s", "Pruning", errorSuffix)); } + if (isGoQuorumCompatibilityMode) { + throw new ParameterException( + commandLine, String.format("GoQuorum privacy is no longer supported in Besu")); + } - if (isPrivacyMultiTenancyEnabled - && !jsonRpcConfiguration.isAuthenticationEnabled() - && !webSocketConfiguration.isAuthenticationEnabled()) { + if (Boolean.TRUE.equals(privacyOptionGroup.isPrivacyMultiTenancyEnabled) + && Boolean.FALSE.equals(jsonRpcConfiguration.isAuthenticationEnabled()) + && Boolean.FALSE.equals(webSocketConfiguration.isAuthenticationEnabled())) { throw new ParameterException( commandLine, "Privacy multi-tenancy requires either http authentication to be enabled or WebSocket authentication to be enabled"); } privacyParametersBuilder.setEnabled(true); - privacyParametersBuilder.setEnclaveUrl(privacyUrl); - privacyParametersBuilder.setMultiTenancyEnabled(isPrivacyMultiTenancyEnabled); - privacyParametersBuilder.setOnchainPrivacyGroupsEnabled(isFlexiblePrivacyGroupsEnabled); + privacyParametersBuilder.setEnclaveUrl(privacyOptionGroup.privacyUrl); + privacyParametersBuilder.setMultiTenancyEnabled( + privacyOptionGroup.isPrivacyMultiTenancyEnabled); + privacyParametersBuilder.setFlexiblePrivacyGroupsEnabled( + privacyOptionGroup.isFlexiblePrivacyGroupsEnabled + || privacyOptionGroup.isOnchainPrivacyGroupsEnabled); + privacyParametersBuilder.setPrivacyPluginEnabled( + unstablePrivacyPluginOptions.isPrivacyPluginEnabled()); + + final boolean hasPrivacyPublicKey = privacyOptionGroup.privacyPublicKeyFile != null; + + if (hasPrivacyPublicKey + && Boolean.TRUE.equals(privacyOptionGroup.isPrivacyMultiTenancyEnabled)) { + throw new ParameterException( + commandLine, "Privacy multi-tenancy and privacy public key cannot be used together"); + } - final boolean hasPrivacyPublicKey = privacyPublicKeyFile != null; - if (hasPrivacyPublicKey && !isPrivacyMultiTenancyEnabled) { + if (!hasPrivacyPublicKey + && !privacyOptionGroup.isPrivacyMultiTenancyEnabled + && !unstablePrivacyPluginOptions.isPrivacyPluginEnabled()) { + throw new ParameterException( + commandLine, "Please specify Enclave public key file path to enable privacy"); + } + + if (hasPrivacyPublicKey + && Boolean.FALSE.equals(privacyOptionGroup.isPrivacyMultiTenancyEnabled)) { try { - privacyParametersBuilder.setEnclavePublicKeyUsingFile(privacyPublicKeyFile); + privacyParametersBuilder.setPrivacyUserIdUsingFile( + privacyOptionGroup.privacyPublicKeyFile); } catch (final IOException e) { throw new ParameterException( commandLine, "Problem with privacy-public-key-file: " + e.getMessage(), e); @@ -1975,59 +2918,43 @@ private PrivacyParameters privacyParameters() { throw new ParameterException( commandLine, "Contents of privacy-public-key-file invalid: " + e.getMessage(), e); } - } else if (hasPrivacyPublicKey) { - throw new ParameterException( - commandLine, "Privacy multi-tenancy and privacy public key cannot be used together"); - } else if (!isPrivacyMultiTenancyEnabled) { - throw new ParameterException( - commandLine, "Please specify Enclave public key file path to enable privacy"); - } - - if (Wei.ZERO.compareTo(minTransactionGasPrice) < 0) { - // if gas is required, cannot use random keys to sign private tx - // ie --privacy-marker-transaction-signing-key-file must be set - if (privacyMarkerTransactionSigningKeyPath == null) { - throw new ParameterException( - commandLine, - "Not a free gas network. --privacy-marker-transaction-signing-key-file must be specified and must be a funded account. Private transactions cannot be signed by random (non-funded) accounts in paid gas networks"); - } - } - - if (!Address.PRIVACY.equals(privacyPrecompiledAddress)) { - logger.warn( - "--privacy-precompiled-address option is deprecated. This address is derived, based on --privacy-onchain-groups-enabled."); } - privacyParametersBuilder.setPrivateKeyPath(privacyMarkerTransactionSigningKeyPath); + privacyParametersBuilder.setPrivateKeyPath( + privacyOptionGroup.privateMarkerTransactionSigningKeyPath); privacyParametersBuilder.setStorageProvider( privacyKeyStorageProvider(keyValueStorageName + "-privacy")); - if (isPrivacyTlsEnabled) { - privacyParametersBuilder.setPrivacyKeyStoreFile(privacyKeyStoreFile); - privacyParametersBuilder.setPrivacyKeyStorePasswordFile(privacyKeyStorePasswordFile); - privacyParametersBuilder.setPrivacyTlsKnownEnclaveFile(privacyTlsKnownEnclaveFile); + if (Boolean.TRUE.equals(privacyOptionGroup.isPrivacyTlsEnabled)) { + privacyParametersBuilder.setPrivacyKeyStoreFile(privacyOptionGroup.privacyKeyStoreFile); + privacyParametersBuilder.setPrivacyKeyStorePasswordFile( + privacyOptionGroup.privacyKeyStorePasswordFile); + privacyParametersBuilder.setPrivacyTlsKnownEnclaveFile( + privacyOptionGroup.privacyTlsKnownEnclaveFile); } privacyParametersBuilder.setEnclaveFactory(new EnclaveFactory(vertx)); - } else { - if (anyPrivacyApiEnabled()) { - logger.warn("Privacy is disabled. Cannot use EEA/PRIV API methods when not using Privacy."); - } } + if (Boolean.FALSE.equals(privacyOptionGroup.isPrivacyEnabled) && anyPrivacyApiEnabled()) { + logger.warn("Privacy is disabled. Cannot use EEA/PRIV API methods when not using Privacy."); + } + + privacyParametersBuilder.setPrivacyService(privacyPluginService); final PrivacyParameters privacyParameters = privacyParametersBuilder.build(); - if (isPrivacyEnabled) { + if (Boolean.TRUE.equals(privacyOptionGroup.isPrivacyEnabled)) { preSynchronizationTaskRunner.addTask( - new PrivateDatabaseMigrationPreSyncTask(privacyParameters, migratePrivateDatabase)); + new PrivateDatabaseMigrationPreSyncTask( + privacyParameters, privacyOptionGroup.migratePrivateDatabase)); } return privacyParameters; } private boolean anyPrivacyApiEnabled() { - return rpcHttpApis.contains(RpcApis.EEA) - || rpcWsApis.contains(RpcApis.EEA) - || rpcHttpApis.contains(RpcApis.PRIV) - || rpcWsApis.contains(RpcApis.PRIV); + return jsonRPCHttpOptionGroup.rpcHttpApis.contains(RpcApis.EEA.name()) + || jsonRPCWebsocketOptionGroup.rpcWsApis.contains(RpcApis.EEA.name()) + || jsonRPCHttpOptionGroup.rpcHttpApis.contains(RpcApis.PRIV.name()) + || jsonRPCWebsocketOptionGroup.rpcWsApis.contains(RpcApis.PRIV.name()); } private PrivacyKeyValueStorageProvider privacyKeyStorageProvider(final String name) { @@ -2046,16 +2973,37 @@ private PrivacyKeyValueStorageFactory privacyKeyValueStorageFactory(final String () -> new StorageException("No KeyValueStorageFactory found for key: " + name)); } - private KeyValueStorageProvider keyStorageProvider(final String name) { - return new KeyValueStorageProviderBuilder() - .withStorageFactory( - storageService - .getByName(name) - .orElseThrow( - () -> new StorageException("No KeyValueStorageFactory found for key: " + name))) - .withCommonConfiguration(pluginCommonConfiguration) - .withMetricsSystem(getMetricsSystem()) - .build(); + private KeyValueStorageProvider keyValueStorageProvider(final String name) { + if (this.keyValueStorageProvider == null) { + this.keyValueStorageProvider = + new KeyValueStorageProviderBuilder() + .withStorageFactory( + storageService + .getByName(name) + .orElseThrow( + () -> + new StorageException( + "No KeyValueStorageFactory found for key: " + name))) + .withCommonConfiguration(pluginCommonConfiguration) + .withMetricsSystem(getMetricsSystem()) + .build(); + } + return this.keyValueStorageProvider; + } + + /** + * Get the storage provider + * + * @return the storage provider + */ + public StorageProvider getStorageProvider() { + return keyValueStorageProvider(keyValueStorageName); + } + + private Optional maybePkiBlockCreationConfiguration() { + return pkiBlockCreationOptions + .asDomainConfig(commandLine) + .map(pkiBlockCreationConfigProvider::load); } private SynchronizerConfiguration buildSyncConfig() { @@ -2069,31 +3017,45 @@ private SynchronizerConfiguration buildSyncConfig() { private TransactionPoolConfiguration buildTransactionPoolConfiguration() { return unstableTransactionPoolOptions .toDomainObject() - .txPoolMaxSize(txPoolMaxSize) - .pooledTransactionHashesSize(pooledTransactionHashesSize) - .pendingTxRetentionPeriod(pendingTxRetentionPeriod) - .priceBump(Percentage.fromInt(priceBump)) + .enableSaveRestore(txPoolOptionGroup.saveRestoreEnabled) + .disableLocalTransactions(txPoolOptionGroup.disableLocalTxs) + .txPoolLimitByAccountPercentage(txPoolOptionGroup.txPoolLimitByAccountPercentage) + .txPoolMaxSize(txPoolOptionGroup.txPoolMaxSize) + .pendingTxRetentionPeriod(txPoolOptionGroup.pendingTxRetentionPeriod) + .priceBump(Percentage.fromInt(txPoolOptionGroup.priceBump)) .txFeeCap(txFeeCap) + .saveFile(dataPath.resolve(txPoolOptionGroup.saveFile.getPath()).toFile()) .build(); } + /** + * Return the file where to save txpool content if the relative option is enabled. + * + * @return the save file + */ + public File getSaveFile() { + return txPoolOptionGroup.saveFile; + } + private boolean isPruningEnabled() { return pruningEnabled; } - // Blockchain synchronisation from peers. - private void synchronize( + // Blockchain synchronization from peers. + private Runner synchronize( final BesuController controller, final boolean p2pEnabled, + final Optional p2pTLSConfiguration, final boolean peerDiscoveryEnabled, final EthNetworkConfig ethNetworkConfig, - final int maxPeers, final String p2pAdvertisedHost, final String p2pListenInterface, final int p2pListenPort, final GraphQLConfiguration graphQLConfiguration, final JsonRpcConfiguration jsonRpcConfiguration, + final JsonRpcConfiguration engineJsonRpcConfiguration, final WebSocketConfiguration webSocketConfiguration, + final JsonRpcIpcConfiguration jsonRpcIpcConfiguration, final ApiConfiguration apiConfiguration, final MetricsConfiguration metricsConfiguration, final Optional permissioningConfiguration, @@ -2102,7 +3064,7 @@ private void synchronize( checkNotNull(runnerBuilder); - permissioningConfiguration.ifPresent(runnerBuilder::permissioningConfiguration); + p2pTLSConfiguration.ifPresent(runnerBuilder::p2pTLSConfiguration); final ObservableMetricsSystem metricsSystem = this.metricsSystem.get(); final Runner runner = @@ -2115,44 +3077,54 @@ private void synchronize( .natMethodFallbackEnabled(unstableNatOptions.getNatMethodFallbackEnabled()) .discovery(peerDiscoveryEnabled) .ethNetworkConfig(ethNetworkConfig) + .permissioningConfiguration(permissioningConfiguration) .p2pAdvertisedHost(p2pAdvertisedHost) .p2pListenInterface(p2pListenInterface) .p2pListenPort(p2pListenPort) - .maxPeers(maxPeers) - .limitRemoteWireConnectionsEnabled(isLimitRemoteWireConnectionsEnabled) - .fractionRemoteConnectionsAllowed( - Fraction.fromPercentage(maxRemoteConnectionsPercentage).getValue()) - .randomPeerPriority(randomPeerPriority) .networkingConfiguration(unstableNetworkingOptions.toDomainObject()) + .legacyForkId(unstableEthProtocolOptions.toDomainObject().isLegacyEth64ForkIdEnabled()) .graphQLConfiguration(graphQLConfiguration) .jsonRpcConfiguration(jsonRpcConfiguration) + .engineJsonRpcConfiguration(engineJsonRpcConfiguration) .webSocketConfiguration(webSocketConfiguration) + .jsonRpcIpcConfiguration(jsonRpcIpcConfiguration) .apiConfiguration(apiConfiguration) .pidPath(pidPath) .dataDir(dataDir()) - .bannedNodeIds(bannedNodeIds) + .bannedNodeIds(p2PDiscoveryOptionGroup.bannedNodeIds) .metricsSystem(metricsSystem) + .permissioningService(permissioningService) .metricsConfiguration(metricsConfiguration) .staticNodes(staticNodes) .identityString(identityString) .besuPluginContext(besuPluginContext) .autoLogBloomCaching(autoLogBloomCachingEnabled) - .ethstatsUrl(unstableEthstatsOptions.getEthstatsUrl()) - .ethstatsContact(unstableEthstatsOptions.getEthstatsContact()) - .storageProvider(keyStorageProvider(keyValueStorageName)) + .ethstatsOptions(ethstatsOptions) + .storageProvider(keyValueStorageProvider(keyValueStorageName)) + .rpcEndpointService(rpcEndpointServiceImpl) + .rpcMaxLogsRange(rpcMaxLogsRange) + .enodeDnsConfiguration(getEnodeDnsConfiguration()) .build(); addShutdownHook(runner); - runner.start(); - runner.awaitStop(); + + return runner; } + /** + * Builds Vertx instance from VertxOptions. Visible for testing. + * + * @param vertxOptions Instance of VertxOptions + * @return Instance of Vertx. + */ + @VisibleForTesting protected Vertx createVertx(final VertxOptions vertxOptions) { return Vertx.vertx(vertxOptions); } private VertxOptions createVertxOptions(final MetricsSystem metricsSystem) { return new VertxOptions() + .setPreferNativeTransport(true) .setMetricsOptions( new MetricsOptions() .setEnabled(true) @@ -2167,45 +3139,20 @@ private void addShutdownHook(final Runner runner) { try { besuPluginContext.stopPlugins(); runner.close(); - LogManager.shutdown(); + LogConfigurator.shutdown(); } catch (final Exception e) { logger.error("Failed to stop Besu"); } - })); - } - - // Used to discover the default IP of the client. - // Loopback IP is used by default as this is how smokeTests require it to be - // and it's probably a good security behaviour to default only on the localhost. - private InetAddress autoDiscoverDefaultIP() { - - if (autoDiscoveredDefaultIP != null) { - return autoDiscoveredDefaultIP; - } - - autoDiscoveredDefaultIP = InetAddress.getLoopbackAddress(); - - return autoDiscoveredDefaultIP; + }, + "BesuCommand-Shutdown-Hook")); } private EthNetworkConfig updateNetworkConfig(final NetworkName network) { final EthNetworkConfig.Builder builder = new EthNetworkConfig.Builder(EthNetworkConfig.getNetworkConfig(network)); - // custom genesis file use comes with specific default values for the genesis - // file itself - // but also for the network id and the bootnodes list. if (genesisFile != null) { - - // noinspection ConstantConditions network is not always null but injected by - // PicoCLI if used - if (this.network != null) { - // We check if network option was really provided by user and not only looking - // at the - // default value. - // if user provided it and provided the genesis file option at the same time, it - // raises a - // conflict error + if (commandLine.getParseResult().hasMatchedOption("network")) { throw new ParameterException( this.commandLine, "--network option and --genesis-file option can't be used at the same time. Please " @@ -2215,17 +3162,7 @@ private EthNetworkConfig updateNetworkConfig(final NetworkName network) { builder.setGenesisConfig(genesisConfig()); if (networkId == null) { - // if no network id option is defined on the CLI we have to set a default value - // from the - // genesis file. - // We do the genesis parsing only in this case as we already have network id - // constants - // for known networks to speed up the process. - // Also we have to parse the genesis as we don't already have a parsed version - // at this - // stage. - // If no chain id is found in the genesis as it's an optional, we use mainnet - // network id. + // If no chain id is found in the genesis, use mainnet network id try { builder.setNetworkId( getGenesisConfigFile() @@ -2243,35 +3180,44 @@ private EthNetworkConfig updateNetworkConfig(final NetworkName network) { } } - if (bootNodes == null) { - // We default to an empty bootnodes list if the option is not provided on CLI - // because - // mainnet bootnodes won't work as the default value for a custom genesis, - // so it's better to have an empty list as default value that forces to create a - // custom one - // than a useless one that may make user think that it can work when it can't. + if (p2PDiscoveryOptionGroup.bootNodes == null) { builder.setBootNodes(new ArrayList<>()); } builder.setDnsDiscoveryUrl(null); } + if (p2PDiscoveryOptionGroup.discoveryDnsUrl != null) { + builder.setDnsDiscoveryUrl(p2PDiscoveryOptionGroup.discoveryDnsUrl); + } else if (genesisConfigOptions != null) { + final Optional discoveryDnsUrlFromGenesis = + genesisConfigOptions.getDiscoveryOptions().getDiscoveryDnsUrl(); + discoveryDnsUrlFromGenesis.ifPresent(builder::setDnsDiscoveryUrl); + } + if (networkId != null) { builder.setNetworkId(networkId); } - if (bootNodes != null) { + List listBootNodes = null; + if (p2PDiscoveryOptionGroup.bootNodes != null) { try { - - final List listBootNodes = - bootNodes.stream() - .filter(value -> !value.isEmpty()) - .map(url -> EnodeURL.fromString(url, getEnodeDnsConfiguration())) - .collect(Collectors.toList()); - DiscoveryConfiguration.assertValidBootnodes(listBootNodes); - builder.setBootNodes(listBootNodes); + listBootNodes = buildEnodes(p2PDiscoveryOptionGroup.bootNodes, getEnodeDnsConfiguration()); } catch (final IllegalArgumentException e) { throw new ParameterException(commandLine, e.getMessage()); } + } else if (genesisConfigOptions != null) { + final Optional> bootNodesFromGenesis = + genesisConfigOptions.getDiscoveryOptions().getBootNodes(); + if (bootNodesFromGenesis.isPresent()) { + listBootNodes = buildEnodes(bootNodesFromGenesis.get(), getEnodeDnsConfiguration()); + } + } + if (listBootNodes != null) { + if (!p2PDiscoveryOptionGroup.peerDiscoveryEnabled) { + logger.warn("Discovery disabled: bootnodes will be ignored."); + } + DiscoveryConfiguration.assertValidBootnodes(listBootNodes); + builder.setBootNodes(listBootNodes); } return builder.build(); } @@ -2285,11 +3231,24 @@ private String genesisConfig() { return Resources.toString(genesisFile.toURI().toURL(), UTF_8); } catch (final IOException e) { throw new ParameterException( - this.commandLine, String.format("Unable to load genesis file %s.", genesisFile), e); + this.commandLine, String.format("Unable to load genesis URL %s.", genesisFile), e); + } + } + + private static String genesisConfig(final NetworkName networkName) { + try (final InputStream genesisFileInputStream = + EthNetworkConfig.class.getResourceAsStream(networkName.getGenesisFile())) { + return new String(genesisFileInputStream.readAllBytes(), UTF_8); + } catch (final IOException | NullPointerException e) { + throw new IllegalStateException(e); } } - // dataDir() is public because it is accessed by subcommands + /** + * Returns data directory used by Besu. Visible as it is accessed by other subcommands. + * + * @return Path representing data directory. + */ public Path dataDir() { return dataPath.toAbsolutePath(); } @@ -2303,11 +3262,6 @@ private Path pluginsDir() { } } - @VisibleForTesting - NodeKey buildNodeKey() { - return new NodeKey(securityModule()); - } - private SecurityModule securityModule() { return securityModuleService .getByName(securityModuleName) @@ -2315,13 +3269,13 @@ private SecurityModule securityModule() { .get(); } - private File nodePrivateKeyFile() { + private File resolveNodePrivateKeyFile(final File nodePrivateKeyFile) { return Optional.ofNullable(nodePrivateKeyFile) .orElseGet(() -> KeyPairUtil.getDefaultKeyFile(dataDir())); } private String rpcHttpAuthenticationCredentialsFile() { - final String filename = rpcHttpAuthenticationCredentialsFile; + final String filename = jsonRPCHttpOptionGroup.rpcHttpAuthenticationCredentialsFile; if (filename != null) { RpcAuthFileValidator.validate(commandLine, filename, "HTTP"); @@ -2330,7 +3284,7 @@ private String rpcHttpAuthenticationCredentialsFile() { } private String rpcWsAuthenticationCredentialsFile() { - final String filename = rpcWsAuthenticationCredentialsFile; + final String filename = jsonRPCWebsocketOptionGroup.rpcWsAuthenticationCredentialsFile; if (filename != null) { RpcAuthFileValidator.validate(commandLine, filename, "WS"); @@ -2344,21 +3298,63 @@ private String getDefaultPermissioningFilePath() { + DefaultCommandValues.PERMISSIONING_CONFIG_LOCATION; } + /** + * Metrics System used by Besu + * + * @return Instance of MetricsSystem + */ public MetricsSystem getMetricsSystem() { return metricsSystem.get(); } private Set loadStaticNodes() throws IOException { - final String staticNodesFilename = "static-nodes.json"; - final Path staticNodesPath = dataDir().resolve(staticNodesFilename); - + final Path staticNodesPath; + if (staticNodesFile != null) { + staticNodesPath = staticNodesFile.toAbsolutePath(); + if (!staticNodesPath.toFile().exists()) { + throw new ParameterException( + commandLine, String.format("Static nodes file %s does not exist", staticNodesPath)); + } + } else { + final String staticNodesFilename = "static-nodes.json"; + staticNodesPath = dataDir().resolve(staticNodesFilename); + } + logger.debug("Static Nodes file: {}", staticNodesPath); return StaticNodesParser.fromPath(staticNodesPath, getEnodeDnsConfiguration()); } - public BesuExceptionHandler exceptionHandler() { - return new BesuExceptionHandler(this::getLogLevel); + private List buildEnodes( + final List bootNodes, final EnodeDnsConfiguration enodeDnsConfiguration) { + return bootNodes.stream() + .filter(bootNode -> !bootNode.isEmpty()) + .map(bootNode -> EnodeURLImpl.fromString(bootNode, enodeDnsConfiguration)) + .collect(Collectors.toList()); + } + + /** + * Besu CLI Paramaters exception handler used by VertX. Visible for testing. + * + * @return instance of BesuParameterExceptionHandler + */ + public BesuParameterExceptionHandler parameterExceptionHandler() { + return new BesuParameterExceptionHandler(this::getLogLevel); + } + + /** + * Returns BesuExecutionExceptionHandler. Visible as it is used in testing. + * + * @return instance of BesuExecutionExceptionHandler used by Vertx. + */ + public BesuExecutionExceptionHandler executionExceptionHandler() { + return new BesuExecutionExceptionHandler(); } + /** + * Represents Enode DNS Configuration. Visible for testing. + * + * @return instance of EnodeDnsConfiguration + */ + @VisibleForTesting public EnodeDnsConfiguration getEnodeDnsConfiguration() { if (enodeDnsConfiguration == null) { enodeDnsConfiguration = unstableDnsOptions.toDomainObject(); @@ -2382,6 +3378,35 @@ private void checkPortClash() { }); } + /** + * Check if required ports are available + * + * @throws InvalidConfigurationException if ports are not available. + */ + protected void checkIfRequiredPortsAreAvailable() { + final List unavailablePorts = new ArrayList<>(); + getEffectivePorts().stream() + .filter(Objects::nonNull) + .filter(port -> port > 0) + .forEach( + port -> { + if (port.equals(p2PDiscoveryOptionGroup.p2pPort) + && !NetworkUtility.isPortAvailable(port)) { + unavailablePorts.add(port); + } + if (!port.equals(p2PDiscoveryOptionGroup.p2pPort) + && !NetworkUtility.isPortAvailableForTcp(port)) { + unavailablePorts.add(port); + } + }); + if (!unavailablePorts.isEmpty()) { + throw new InvalidConfigurationException( + "Port(s) '" + + unavailablePorts + + "' already in use. Check for other processes using the port(s)."); + } + } + /** * * Gets the list of effective ports (ports that are enabled). * @@ -2389,18 +3414,30 @@ private void checkPortClash() { */ private List getEffectivePorts() { final List effectivePorts = new ArrayList<>(); - addPortIfEnabled(effectivePorts, p2pPort, p2pEnabled); - addPortIfEnabled(effectivePorts, graphQLHttpPort, isGraphQLHttpEnabled); - addPortIfEnabled(effectivePorts, rpcHttpPort, isRpcHttpEnabled); - addPortIfEnabled(effectivePorts, rpcWsPort, isRpcWsEnabled); - addPortIfEnabled(effectivePorts, metricsPort, isMetricsEnabled); - addPortIfEnabled(effectivePorts, metricsPushPort, isMetricsPushEnabled); - addPortIfEnabled(effectivePorts, stratumPort, iStratumMiningEnabled); + addPortIfEnabled( + effectivePorts, p2PDiscoveryOptionGroup.p2pPort, p2PDiscoveryOptionGroup.p2pEnabled); + addPortIfEnabled( + effectivePorts, + graphQlOptionGroup.graphQLHttpPort, + graphQlOptionGroup.isGraphQLHttpEnabled); + addPortIfEnabled( + effectivePorts, + jsonRPCHttpOptionGroup.rpcHttpPort, + jsonRPCHttpOptionGroup.isRpcHttpEnabled); + addPortIfEnabled( + effectivePorts, + jsonRPCWebsocketOptionGroup.rpcWsPort, + jsonRPCWebsocketOptionGroup.isRpcWsEnabled); + addPortIfEnabled(effectivePorts, engineRPCOptionGroup.engineRpcPort, isEngineApiEnabled()); + addPortIfEnabled( + effectivePorts, metricsOptionGroup.metricsPort, metricsOptionGroup.isMetricsEnabled); + addPortIfEnabled( + effectivePorts, minerOptionGroup.stratumPort, minerOptionGroup.iStratumMiningEnabled); return effectivePorts; } /** - * Adds port in the passed list only if enabled. + * Adds port to the specified list only if enabled. * * @param ports The list of ports * @param port The port value @@ -2415,46 +3452,35 @@ private void addPortIfEnabled( private void checkGoQuorumCompatibilityConfig(final EthNetworkConfig ethNetworkConfig) { if (isGoQuorumCompatibilityMode) { - final GenesisConfigOptions genesisConfigOptions = readGenesisConfigOptions(); - // this static flag is read by the RLP decoder - GoQuorumOptions.goquorumCompatibilityMode = true; - if (!genesisConfigOptions.isQuorum()) { - throw new IllegalStateException( - "GoQuorum compatibility mode (enabled) can only be used if genesis file has 'isQuorum' flag set to true."); - } - genesisConfigOptions - .getChainId() - .ifPresent( - chainId -> - ensureGoQuorumCompatibilityModeNotUsedOnMainnet( - chainId, isGoQuorumCompatibilityMode)); - - if (genesisFile != null - && getGenesisConfigFile().getConfigOptions().isQuorum() - && !minTransactionGasPrice.isZero()) { + logger.warn( + DEPRECATION_WARNING_MSG, + "isQuorum mode in genesis file (GoQuorum-compatible privacy mode)", + "--privacy-enabled"); + if (!minTransactionGasPrice.isZero()) { throw new ParameterException( this.commandLine, - "--min-gas-price must be set to zero if GoQuorum compatibility is enabled in the genesis config."); + "--min-gas-price must be set to zero if isQuorum mode is enabled in the genesis file."); } - if (ethNetworkConfig.getNetworkId().equals(EthNetworkConfig.MAINNET_NETWORK_ID)) { - throw new ParameterException( - this.commandLine, "GoQuorum compatibility mode (enabled) cannot be used on Mainnet."); + + if (ensureGoQuorumCompatibilityModeNotUsedOnMainnet(genesisConfigOptions, ethNetworkConfig)) { + throw new ParameterException(this.commandLine, "isQuorum mode cannot be used on Mainnet."); } } } - private void ensureGoQuorumCompatibilityModeNotUsedOnMainnet( - final BigInteger chainId, final boolean isGoQuorumCompatibilityMode) { - if (isGoQuorumCompatibilityMode && chainId.equals(EthNetworkConfig.MAINNET_NETWORK_ID)) { - throw new IllegalStateException( - "GoQuorum compatibility mode (enabled) cannot be used on Mainnet."); - } + private static boolean ensureGoQuorumCompatibilityModeNotUsedOnMainnet( + final GenesisConfigOptions genesisConfigOptions, final EthNetworkConfig ethNetworkConfig) { + return ethNetworkConfig.getNetworkId().equals(MAINNET.getNetworkId()) + || genesisConfigOptions + .getChainId() + .map(chainId -> chainId.equals(MAINNET.getNetworkId())) + .orElse(false); } @VisibleForTesting - Level getLogLevel() { - return logLevel; + String getLogLevel() { + return loggingLevelOption.getLogLevel(); } private class BesuCommandConfigurationService implements BesuConfiguration { @@ -2471,10 +3497,184 @@ public Path getDataPath() { @Override public int getDatabaseVersion() { - return unstableDataStorageOptions - .toDomainObject() - .getDataStorageFormat() - .getDatabaseVersion(); + return dataStorageOptions.toDomainObject().getDataStorageFormat().getDatabaseVersion(); + } + } + + private void instantiateSignatureAlgorithmFactory() { + if (SignatureAlgorithmFactory.isInstanceSet()) { + return; + } + + final Optional ecCurve = getEcCurveFromGenesisFile(); + + if (ecCurve.isEmpty()) { + SignatureAlgorithmFactory.setDefaultInstance(); + return; + } + + try { + SignatureAlgorithmFactory.setInstance(SignatureAlgorithmType.create(ecCurve.get())); + } catch (final IllegalArgumentException e) { + throw new CommandLine.InitializationException( + new StringBuilder() + .append("Invalid genesis file configuration for ecCurve. ") + .append(e.getMessage()) + .toString()); + } + } + + private Optional getEcCurveFromGenesisFile() { + if (genesisFile == null) { + return Optional.empty(); + } + return genesisConfigOptions.getEcCurve(); + } + + /** Enables Go Quorum Compatibility mode. Visible for testing. */ + @VisibleForTesting + protected void enableGoQuorumCompatibilityMode() { + // this static flag is still used for GoQuorum permissioning compatibility + isGoQuorumCompatibilityMode = true; + } + + private GenesisConfigOptions getActualGenesisConfigOptions() { + return Optional.ofNullable(genesisConfigOptions) + .orElseGet( + () -> + GenesisConfigFile.fromConfig( + genesisConfig(Optional.ofNullable(network).orElse(MAINNET))) + .getConfigOptions(genesisConfigOverrides)); + } + + private void setMergeConfigOptions() { + MergeConfigOptions.setMergeEnabled( + getActualGenesisConfigOptions().getTerminalTotalDifficulty().isPresent()); + } + + private void setIgnorableStorageSegments() { + if (!unstableChainPruningOptions.getChainDataPruningEnabled()) { + rocksDBPlugin.addIgnorableSegmentIdentifier(KeyValueSegmentIdentifier.CHAIN_PRUNER_STATE); + } + } + + private void validatePostMergeCheckpointBlockRequirements() { + final GenesisConfigOptions genesisOptions = getActualGenesisConfigOptions(); + final SynchronizerConfiguration synchronizerConfiguration = + unstableSynchronizerOptions.toDomainObject().build(); + final Optional terminalTotalDifficulty = genesisOptions.getTerminalTotalDifficulty(); + final CheckpointConfigOptions checkpointConfigOptions = genesisOptions.getCheckpointOptions(); + if (synchronizerConfiguration.isCheckpointPostMergeEnabled()) { + if (!checkpointConfigOptions.isValid()) { + throw new InvalidConfigurationException( + "PoS checkpoint sync requires a checkpoint block configured in the genesis file"); + } + terminalTotalDifficulty.ifPresentOrElse( + ttd -> { + if (UInt256.fromHexString( + genesisOptions.getCheckpointOptions().getTotalDifficulty().get()) + .equals(UInt256.ZERO) + && ttd.equals(UInt256.ZERO)) { + throw new InvalidConfigurationException( + "PoS checkpoint sync can't be used with TTD = 0 and checkpoint totalDifficulty = 0"); + } + if (UInt256.fromHexString( + genesisOptions.getCheckpointOptions().getTotalDifficulty().get()) + .lessThan(ttd)) { + throw new InvalidConfigurationException( + "PoS checkpoint sync requires a block with total difficulty greater or equal than the TTD"); + } + }, + () -> { + throw new InvalidConfigurationException( + "PoS checkpoint sync requires TTD in the genesis file"); + }); } } + + private boolean isMergeEnabled() { + return MergeConfigOptions.isMergeEnabled(); + } + + private boolean isEngineApiEnabled() { + return engineRPCOptionGroup.overrideEngineRpcEnabled || isMergeEnabled(); + } + + private static List getJDKEnabledCipherSuites() { + try { + final SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, null, null); + final SSLEngine engine = context.createSSLEngine(); + return Arrays.asList(engine.getEnabledCipherSuites()); + } catch (final KeyManagementException | NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + private static List getJDKEnabledProtocols() { + try { + final SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, null, null); + final SSLEngine engine = context.createSSLEngine(); + return Arrays.asList(engine.getEnabledProtocols()); + } catch (final KeyManagementException | NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + private SyncMode getDefaultSyncModeIfNotSet() { + return Optional.ofNullable(syncMode) + .orElse( + genesisFile == null + && !privacyOptionGroup.isPrivacyEnabled + && Optional.ofNullable(network).map(NetworkName::canFastSync).orElse(false) + ? SyncMode.FAST + : SyncMode.FULL); + } + + private String generateConfigurationOverview() { + final ConfigurationOverviewBuilder builder = new ConfigurationOverviewBuilder(logger); + + if (environment != null) { + builder.setEnvironment(environment); + } + + if (network != null) { + builder.setNetwork(network.normalize()); + } + + builder.setHasCustomGenesis(genesisFile != null); + builder.setNetworkId(ethNetworkConfig.getNetworkId()); + + builder + .setDataStorage(dataStorageOptions.normalizeDataStorageFormat()) + .setSyncMode(syncMode.normalize()); + + if (jsonRpcConfiguration != null && jsonRpcConfiguration.isEnabled()) { + builder + .setRpcPort(jsonRpcConfiguration.getPort()) + .setRpcHttpApis(jsonRpcConfiguration.getRpcApis()); + } + + if (engineJsonRpcConfiguration != null && engineJsonRpcConfiguration.isEnabled()) { + builder + .setEnginePort(engineJsonRpcConfiguration.getPort()) + .setEngineApis(engineJsonRpcConfiguration.getRpcApis()); + if (engineJsonRpcConfiguration.isAuthenticationEnabled()) { + if (engineJsonRpcConfiguration.getAuthenticationPublicKeyFile() != null) { + builder.setEngineJwtFile( + engineJsonRpcConfiguration.getAuthenticationPublicKeyFile().getAbsolutePath()); + } else { + // default ephemeral jwt created later + builder.setEngineJwtFile(dataDir().toAbsolutePath() + "/" + EPHEMERAL_JWT_FILE); + } + } + } + + if (rocksDBPlugin.isHighSpecEnabled()) { + builder.setHighSpecEnabled(); + } + + return builder.build(); + } } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java b/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java new file mode 100644 index 00000000000..1682aa14ba9 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java @@ -0,0 +1,295 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.cli; + +import org.hyperledger.besu.BesuInfo; +import org.hyperledger.besu.util.log.FramedLogMessage; +import org.hyperledger.besu.util.platform.PlatformDetector; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import org.slf4j.Logger; +import oshi.PlatformEnum; +import oshi.SystemInfo; +import oshi.hardware.HardwareAbstractionLayer; + +/** The Configuration overview builder. */ +public class ConfigurationOverviewBuilder { + @SuppressWarnings("PrivateStaticFinalLoggers") + private final Logger logger; + + private String network; + private BigInteger networkId; + private boolean hasCustomGenesis; + private String dataStorage; + private String syncMode; + private Integer rpcPort; + private Collection rpcHttpApis; + private Integer enginePort; + private Collection engineApis; + private String engineJwtFilePath; + private boolean isHighSpec = false; + private Map environment; + + /** + * @param logger the logger + */ + public ConfigurationOverviewBuilder(final Logger logger) { + this.logger = logger; + } + + /** + * Sets network. + * + * @param network the network + * @return the network + */ + public ConfigurationOverviewBuilder setNetwork(final String network) { + this.network = network; + return this; + } + + /** + * Sets whether a networkId has been specified + * + * @param networkId the specified networkId + * @return the builder + */ + public ConfigurationOverviewBuilder setNetworkId(final BigInteger networkId) { + this.networkId = networkId; + return this; + } + + /** + * Sets whether a custom genesis has been specified. + * + * @param hasCustomGenesis a boolean representing whether a custom genesis file was specified + * @return the builder + */ + public ConfigurationOverviewBuilder setHasCustomGenesis(final boolean hasCustomGenesis) { + this.hasCustomGenesis = hasCustomGenesis; + return this; + } + + /** + * Sets data storage. + * + * @param dataStorage the data storage + * @return the builder + */ + public ConfigurationOverviewBuilder setDataStorage(final String dataStorage) { + this.dataStorage = dataStorage; + return this; + } + + /** + * Sets sync mode. + * + * @param syncMode the sync mode + * @return the builder + */ + public ConfigurationOverviewBuilder setSyncMode(final String syncMode) { + this.syncMode = syncMode; + return this; + } + + /** + * Sets rpc port. + * + * @param rpcPort the rpc port + * @return the builder + */ + public ConfigurationOverviewBuilder setRpcPort(final Integer rpcPort) { + this.rpcPort = rpcPort; + return this; + } + + /** + * Sets rpc http apis. + * + * @param rpcHttpApis the rpc http apis + * @return the builder + */ + public ConfigurationOverviewBuilder setRpcHttpApis(final Collection rpcHttpApis) { + this.rpcHttpApis = rpcHttpApis; + return this; + } + + /** + * Sets engine port. + * + * @param enginePort the engine port + * @return the builder + */ + public ConfigurationOverviewBuilder setEnginePort(final Integer enginePort) { + this.enginePort = enginePort; + return this; + } + + /** + * Sets engine apis. + * + * @param engineApis the engine apis + * @return the builder + */ + public ConfigurationOverviewBuilder setEngineApis(final Collection engineApis) { + this.engineApis = engineApis; + return this; + } + + /** + * Sets high spec enabled. + * + * @return the builder + */ + public ConfigurationOverviewBuilder setHighSpecEnabled() { + isHighSpec = true; + return this; + } + + /** + * Sets the engine jwt file path. + * + * @param engineJwtFilePath the engine apis + * @return the builder + */ + public ConfigurationOverviewBuilder setEngineJwtFile(final String engineJwtFilePath) { + this.engineJwtFilePath = engineJwtFilePath; + return this; + } + + /** + * Sets the environment variables. + * + * @param environment the enveironment variables + * @return the builder + */ + public ConfigurationOverviewBuilder setEnvironment(final Map environment) { + this.environment = environment; + return this; + } + + /** + * Build configuration overview. + * + * @return the string representing configuration overview + */ + public String build() { + final List lines = new ArrayList<>(); + lines.add("Besu version " + BesuInfo.class.getPackage().getImplementationVersion()); + lines.add(""); + lines.add("Configuration:"); + + // Don't include the default network if a genesis file has been supplied + if (network != null && !hasCustomGenesis) { + lines.add("Network: " + network); + } + + if (hasCustomGenesis) { + lines.add("Network: Custom genesis file specified"); + } + + if (networkId != null) { + lines.add("Network Id: " + networkId); + } + + if (dataStorage != null) { + lines.add("Data storage: " + dataStorage); + } + + if (syncMode != null) { + lines.add("Sync mode: " + syncMode); + } + + if (rpcHttpApis != null) { + lines.add("RPC HTTP APIs: " + String.join(",", rpcHttpApis)); + } + if (rpcPort != null) { + lines.add("RPC HTTP port: " + rpcPort); + } + + if (engineApis != null) { + lines.add("Engine APIs: " + String.join(",", engineApis)); + } + if (enginePort != null) { + lines.add("Engine port: " + enginePort); + } + if (engineJwtFilePath != null) { + lines.add("Engine JWT: " + engineJwtFilePath); + } + + if (isHighSpec) { + lines.add("High spec configuration enabled"); + } + + lines.add(""); + lines.add("Host:"); + + lines.add("Java: " + PlatformDetector.getVM()); + lines.add("Maximum heap size: " + normalizeSize(Runtime.getRuntime().maxMemory())); + lines.add("OS: " + PlatformDetector.getOS()); + + if (SystemInfo.getCurrentPlatform() == PlatformEnum.LINUX) { + final String glibcVersion = PlatformDetector.getGlibc(); + if (glibcVersion != null) { + lines.add("glibc: " + glibcVersion); + } + + detectJemalloc(lines); + } + + final HardwareAbstractionLayer hardwareInfo = new SystemInfo().getHardware(); + + lines.add("Total memory: " + normalizeSize(hardwareInfo.getMemory().getTotal())); + lines.add("CPU cores: " + hardwareInfo.getProcessor().getLogicalProcessorCount()); + + return FramedLogMessage.generate(lines); + } + + private void detectJemalloc(final List lines) { + Optional.ofNullable(Objects.isNull(environment) ? null : environment.get("BESU_USING_JEMALLOC")) + .ifPresentOrElse( + t -> { + try { + final String version = PlatformDetector.getJemalloc(); + lines.add("jemalloc: " + version); + } catch (final Throwable throwable) { + logger.warn( + "BESU_USING_JEMALLOC is present but we failed to load jemalloc library to get the version", + throwable); + } + }, + () -> { + // in case the user is using jemalloc without BESU_USING_JEMALLOC env var + try { + final String version = PlatformDetector.getJemalloc(); + lines.add("jemalloc: " + version); + } catch (final Throwable throwable) { + logger.info( + "jemalloc library not found, memory usage may be reduced by installing it"); + } + }); + } + + private String normalizeSize(final long size) { + return String.format("%.02f", (double) (size) / 1024 / 1024 / 1024) + " GB"; + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/DefaultCommandValues.java b/besu/src/main/java/org/hyperledger/besu/cli/DefaultCommandValues.java index 1e34c764141..887e6120419 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/DefaultCommandValues.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/DefaultCommandValues.java @@ -14,7 +14,8 @@ */ package org.hyperledger.besu.cli; -import org.hyperledger.besu.ethereum.core.Wei; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.JwtAlgorithm; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.p2p.config.RlpxConfiguration; import org.hyperledger.besu.nat.NatMethod; @@ -26,42 +27,91 @@ import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; import org.apache.tuweni.bytes.Bytes; import picocli.CommandLine; +/** The interface Default command values. */ public interface DefaultCommandValues { + /** The constant CONFIG_FILE_OPTION_NAME. */ String CONFIG_FILE_OPTION_NAME = "--config-file"; + /** The constant MANDATORY_PATH_FORMAT_HELP. */ String MANDATORY_PATH_FORMAT_HELP = ""; + /** The constant MANDATORY_FILE_FORMAT_HELP. */ String MANDATORY_FILE_FORMAT_HELP = ""; + /** The constant MANDATORY_DIRECTORY_FORMAT_HELP. */ String MANDATORY_DIRECTORY_FORMAT_HELP = ""; + /** The constant BESU_HOME_PROPERTY_NAME. */ String BESU_HOME_PROPERTY_NAME = "besu.home"; + /** The constant DEFAULT_DATA_DIR_PATH. */ String DEFAULT_DATA_DIR_PATH = "./build/data"; + /** The constant MANDATORY_INTEGER_FORMAT_HELP. */ String MANDATORY_INTEGER_FORMAT_HELP = ""; + /** The constant MANDATORY_DOUBLE_FORMAT_HELP. */ String MANDATORY_DOUBLE_FORMAT_HELP = ""; + /** The constant MANDATORY_LONG_FORMAT_HELP. */ String MANDATORY_LONG_FORMAT_HELP = ""; + /** The constant MANDATORY_MODE_FORMAT_HELP. */ String MANDATORY_MODE_FORMAT_HELP = ""; + /** The constant MANDATORY_NETWORK_FORMAT_HELP. */ String MANDATORY_NETWORK_FORMAT_HELP = ""; + /** The constant MANDATORY_NODE_ID_FORMAT_HELP. */ String MANDATORY_NODE_ID_FORMAT_HELP = ""; + /** The constant DEFAULT_MIN_TRANSACTION_GAS_PRICE. */ Wei DEFAULT_MIN_TRANSACTION_GAS_PRICE = Wei.of(1000); + /** The constant DEFAULT_RPC_TX_FEE_CAP. */ Wei DEFAULT_RPC_TX_FEE_CAP = TransactionPoolConfiguration.DEFAULT_RPC_TX_FEE_CAP; + /** The constant DEFAULT_MIN_BLOCK_OCCUPANCY_RATIO. */ Double DEFAULT_MIN_BLOCK_OCCUPANCY_RATIO = 0.8; + /** The constant DEFAULT_EXTRA_DATA. */ Bytes DEFAULT_EXTRA_DATA = Bytes.EMPTY; - long DEFAULT_MAX_REFRESH_DELAY = 3600000; - long DEFAULT_MIN_REFRESH_DELAY = 1; + /** The constant PERMISSIONING_CONFIG_LOCATION. */ String PERMISSIONING_CONFIG_LOCATION = "permissions_config.toml"; + /** The constant MANDATORY_HOST_FORMAT_HELP. */ String MANDATORY_HOST_FORMAT_HELP = ""; + /** The constant MANDATORY_PORT_FORMAT_HELP. */ String MANDATORY_PORT_FORMAT_HELP = ""; + /** The constant DEFAULT_NAT_METHOD. */ NatMethod DEFAULT_NAT_METHOD = NatMethod.AUTO; + /** The constant DEFAULT_JWT_ALGORITHM. */ + JwtAlgorithm DEFAULT_JWT_ALGORITHM = JwtAlgorithm.RS256; + /** The constant FAST_SYNC_MIN_PEER_COUNT. */ int FAST_SYNC_MIN_PEER_COUNT = 5; + /** The constant DEFAULT_MAX_PEERS. */ int DEFAULT_MAX_PEERS = 25; + /** The constant DEFAULT_P2P_PEER_LOWER_BOUND. */ + int DEFAULT_P2P_PEER_LOWER_BOUND = 25; + /** The constant DEFAULT_HTTP_MAX_CONNECTIONS. */ + int DEFAULT_HTTP_MAX_CONNECTIONS = 80; + /** The constant DEFAULT_HTTP_MAX_BATCH_SIZE. */ + int DEFAULT_HTTP_MAX_BATCH_SIZE = 1024; + /** The constant DEFAULT_MAX_REQUEST_CONTENT_LENGTH. */ + long DEFAULT_MAX_REQUEST_CONTENT_LENGTH = 5 * 1024 * 1024; // 5MB + /** The constant DEFAULT_WS_MAX_CONNECTIONS. */ + int DEFAULT_WS_MAX_CONNECTIONS = 80; + /** The constant DEFAULT_WS_MAX_FRAME_SIZE. */ + int DEFAULT_WS_MAX_FRAME_SIZE = 1024 * 1024; + /** The constant DEFAULT_FRACTION_REMOTE_WIRE_CONNECTIONS_ALLOWED. */ float DEFAULT_FRACTION_REMOTE_WIRE_CONNECTIONS_ALLOWED = RlpxConfiguration.DEFAULT_FRACTION_REMOTE_CONNECTIONS_ALLOWED; + /** The constant DEFAULT_KEY_VALUE_STORAGE_NAME. */ String DEFAULT_KEY_VALUE_STORAGE_NAME = "rocksdb"; + /** The constant DEFAULT_SECURITY_MODULE. */ String DEFAULT_SECURITY_MODULE = "localfile"; + /** The constant DEFAULT_KEYSTORE_TYPE. */ + String DEFAULT_KEYSTORE_TYPE = "JKS"; + /** The Default tls protocols. */ + List DEFAULT_TLS_PROTOCOLS = List.of("TLSv1.3", "TLSv1.2"); + /** + * Gets default besu data path. + * + * @param command the command + * @return the default besu data path + */ static Path getDefaultBesuDataPath(final Object command) { // this property is retrieved from Gradle tasks or Besu running shell script. final String besuHomeProperty = System.getProperty(BESU_HOME_PROPERTY_NAME); diff --git a/besu/src/main/java/org/hyperledger/besu/cli/NetworkDeprecationMessage.java b/besu/src/main/java/org/hyperledger/besu/cli/NetworkDeprecationMessage.java new file mode 100644 index 00000000000..10c97d6a5ad --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/NetworkDeprecationMessage.java @@ -0,0 +1,45 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.cli; + +import org.hyperledger.besu.cli.config.NetworkName; +import org.hyperledger.besu.util.log.FramedLogMessage; + +import java.util.List; + +/** The Network deprecation message. */ +public class NetworkDeprecationMessage { + + /** + * Generate deprecation message for specified testnet network. + * + * @param network the network + * @return the deprecation message for specified network + */ + public static String generate(final NetworkName network) { + if (network.getDeprecationDate().isEmpty()) { + throw new AssertionError("Deprecation date is not set. Cannot print a deprecation message"); + } + + return FramedLogMessage.generateCentered( + List.of( + network.normalize() + + " is deprecated and will be shutdown " + + network.getDeprecationDate().get(), + "", + "For more details please go to", + "https://blog.ethereum.org/2022/06/21/testnet-deprecation/")); + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/config/EthNetworkConfig.java b/besu/src/main/java/org/hyperledger/besu/cli/config/EthNetworkConfig.java index d59db1ff232..3af85016c8c 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/config/EthNetworkConfig.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/config/EthNetworkConfig.java @@ -15,81 +15,82 @@ package org.hyperledger.besu.cli.config; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration.CLASSIC_BOOTSTRAP_NODES; -import static org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration.GOERLI_BOOTSTRAP_NODES; -import static org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration.GOERLI_DISCOVERY_URL; -import static org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration.KOTTI_BOOTSTRAP_NODES; -import static org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration.MAINNET_BOOTSTRAP_NODES; -import static org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration.MAINNET_DISCOVERY_URL; -import static org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration.MORDOR_BOOTSTRAP_NODES; -import static org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration.RINKEBY_BOOTSTRAP_NODES; -import static org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration.RINKEBY_DISCOVERY_URL; -import static org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration.ROPSTEN_BOOTSTRAP_NODES; -import static org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration.ROPSTEN_DISCOVERY_URL; -import static org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration.YOLO_V2_BOOTSTRAP_NODES; - -import org.hyperledger.besu.ethereum.p2p.peers.EnodeURL; + +import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfigOptions; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; +import org.hyperledger.besu.plugin.data.EnodeURL; import java.io.IOException; +import java.io.InputStream; import java.math.BigInteger; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; -import com.google.common.base.Preconditions; -import com.google.common.io.Resources; - +/** The Eth network config. */ public class EthNetworkConfig { - public static final BigInteger MAINNET_NETWORK_ID = BigInteger.valueOf(1); - public static final BigInteger ROPSTEN_NETWORK_ID = BigInteger.valueOf(3); - public static final BigInteger RINKEBY_NETWORK_ID = BigInteger.valueOf(4); - public static final BigInteger GOERLI_NETWORK_ID = BigInteger.valueOf(5); - public static final BigInteger DEV_NETWORK_ID = BigInteger.valueOf(2018); - public static final BigInteger CLASSIC_NETWORK_ID = BigInteger.valueOf(1); - public static final BigInteger KOTTI_NETWORK_ID = BigInteger.valueOf(6); - public static final BigInteger MORDOR_NETWORK_ID = BigInteger.valueOf(7); - private static final BigInteger YOLO_V2_NETWORK_ID = BigInteger.valueOf(133519467574834L); - private static final String MAINNET_GENESIS = "/mainnet.json"; - private static final String ROPSTEN_GENESIS = "/ropsten.json"; - private static final String RINKEBY_GENESIS = "/rinkeby.json"; - private static final String GOERLI_GENESIS = "/goerli.json"; - private static final String DEV_GENESIS = "/dev.json"; - private static final String CLASSIC_GENESIS = "/classic.json"; - private static final String KOTTI_GENESIS = "/kotti.json"; - private static final String MORDOR_GENESIS = "/mordor.json"; - private static final String YOLO_GENESIS = "/yolo.json"; + private final String genesisConfig; private final BigInteger networkId; private final List bootNodes; private final String dnsDiscoveryUrl; + /** + * Instantiates a new Eth network config. + * + * @param genesisConfig the genesis config + * @param networkId the network id + * @param bootNodes the boot nodes + * @param dnsDiscoveryUrl the dns discovery url + */ public EthNetworkConfig( final String genesisConfig, final BigInteger networkId, final List bootNodes, final String dnsDiscoveryUrl) { - Preconditions.checkNotNull(genesisConfig); - Preconditions.checkNotNull(bootNodes); + Objects.requireNonNull(genesisConfig); + Objects.requireNonNull(bootNodes); this.genesisConfig = genesisConfig; this.networkId = networkId; this.bootNodes = bootNodes; this.dnsDiscoveryUrl = dnsDiscoveryUrl; } + /** + * Gets genesis config. + * + * @return the genesis config + */ public String getGenesisConfig() { return genesisConfig; } + /** + * Gets network id. + * + * @return the network id + */ public BigInteger getNetworkId() { return networkId; } + /** + * Gets boot nodes. + * + * @return the boot nodes + */ public List getBootNodes() { return bootNodes; } + /** + * Gets dns discovery url. + * + * @return the dns discovery url + */ public String getDnsDiscoveryUrl() { return dnsDiscoveryUrl; } @@ -128,85 +129,51 @@ public String toString() { + '}'; } + /** + * Gets network config. + * + * @param networkName the network name + * @return the network config + */ public static EthNetworkConfig getNetworkConfig(final NetworkName networkName) { - switch (networkName) { - case ROPSTEN: - return new EthNetworkConfig( - jsonConfig(ROPSTEN_GENESIS), - ROPSTEN_NETWORK_ID, - ROPSTEN_BOOTSTRAP_NODES, - ROPSTEN_DISCOVERY_URL); - case RINKEBY: - return new EthNetworkConfig( - jsonConfig(RINKEBY_GENESIS), - RINKEBY_NETWORK_ID, - RINKEBY_BOOTSTRAP_NODES, - RINKEBY_DISCOVERY_URL); - case GOERLI: - return new EthNetworkConfig( - jsonConfig(GOERLI_GENESIS), - GOERLI_NETWORK_ID, - GOERLI_BOOTSTRAP_NODES, - GOERLI_DISCOVERY_URL); - case DEV: - return new EthNetworkConfig( - jsonConfig(DEV_GENESIS), DEV_NETWORK_ID, new ArrayList<>(), null); - case CLASSIC: - return new EthNetworkConfig( - jsonConfig(CLASSIC_GENESIS), CLASSIC_NETWORK_ID, CLASSIC_BOOTSTRAP_NODES, null); - case KOTTI: - return new EthNetworkConfig( - jsonConfig(KOTTI_GENESIS), KOTTI_NETWORK_ID, KOTTI_BOOTSTRAP_NODES, null); - case MORDOR: - return new EthNetworkConfig( - jsonConfig(MORDOR_GENESIS), MORDOR_NETWORK_ID, MORDOR_BOOTSTRAP_NODES, null); - case YOLO_V2: - return new EthNetworkConfig( - jsonConfig(YOLO_GENESIS), YOLO_V2_NETWORK_ID, YOLO_V2_BOOTSTRAP_NODES, null); - case MAINNET: - default: - return new EthNetworkConfig( - jsonConfig(MAINNET_GENESIS), - MAINNET_NETWORK_ID, - MAINNET_BOOTSTRAP_NODES, - MAINNET_DISCOVERY_URL); - } + final String genesisContent = jsonConfig(networkName.getGenesisFile()); + final GenesisConfigOptions genesisConfigOptions = + GenesisConfigFile.fromConfig(genesisContent).getConfigOptions(); + final Optional> rawBootNodes = + genesisConfigOptions.getDiscoveryOptions().getBootNodes(); + final List bootNodes = + rawBootNodes + .map( + strings -> + strings.stream().map(EnodeURLImpl::fromString).collect(Collectors.toList())) + .orElse(Collections.emptyList()); + return new EthNetworkConfig( + genesisContent, + networkName.getNetworkId(), + bootNodes, + genesisConfigOptions.getDiscoveryOptions().getDiscoveryDnsUrl().orElse(null)); } private static String jsonConfig(final String resourceName) { - try { - final URI uri = EthNetworkConfig.class.getResource(resourceName).toURI(); - return Resources.toString(uri.toURL(), UTF_8); - } catch (final URISyntaxException | IOException e) { + try (final InputStream genesisFileInputStream = + EthNetworkConfig.class.getResourceAsStream(resourceName)) { + return new String(genesisFileInputStream.readAllBytes(), UTF_8); + } catch (IOException | NullPointerException e) { throw new IllegalStateException(e); } } + /** + * Json config string. + * + * @param network the network + * @return the string + */ public static String jsonConfig(final NetworkName network) { - switch (network) { - case MAINNET: - return jsonConfig(MAINNET_GENESIS); - case ROPSTEN: - return jsonConfig(ROPSTEN_GENESIS); - case RINKEBY: - return jsonConfig(RINKEBY_GENESIS); - case GOERLI: - return jsonConfig(GOERLI_GENESIS); - case DEV: - return jsonConfig(DEV_GENESIS); - case CLASSIC: - return jsonConfig(CLASSIC_GENESIS); - case KOTTI: - return jsonConfig(KOTTI_GENESIS); - case MORDOR: - return jsonConfig(MORDOR_GENESIS); - case YOLO_V2: - return jsonConfig(YOLO_GENESIS); - default: - throw new IllegalArgumentException("Unknown network:" + network); - } + return jsonConfig(network.getGenesisFile()); } + /** The type Builder. */ public static class Builder { private String dnsDiscoveryUrl; @@ -214,6 +181,11 @@ public static class Builder { private BigInteger networkId; private List bootNodes; + /** + * Instantiates a new Builder. + * + * @param ethNetworkConfig the eth network config + */ public Builder(final EthNetworkConfig ethNetworkConfig) { this.genesisConfig = ethNetworkConfig.genesisConfig; this.networkId = ethNetworkConfig.networkId; @@ -221,26 +193,55 @@ public Builder(final EthNetworkConfig ethNetworkConfig) { this.dnsDiscoveryUrl = ethNetworkConfig.dnsDiscoveryUrl; } + /** + * Sets genesis config. + * + * @param genesisConfig the genesis config + * @return the genesis config + */ public Builder setGenesisConfig(final String genesisConfig) { this.genesisConfig = genesisConfig; return this; } + /** + * Sets network id. + * + * @param networkId the network id + * @return the network id + */ public Builder setNetworkId(final BigInteger networkId) { this.networkId = networkId; return this; } + /** + * Sets boot nodes. + * + * @param bootNodes the boot nodes + * @return the boot nodes + */ public Builder setBootNodes(final List bootNodes) { this.bootNodes = bootNodes; return this; } + /** + * Sets dns discovery url. + * + * @param dnsDiscoveryUrl the dns discovery url + * @return the dns discovery url + */ public Builder setDnsDiscoveryUrl(final String dnsDiscoveryUrl) { this.dnsDiscoveryUrl = dnsDiscoveryUrl; return this; } + /** + * Build eth network config. + * + * @return the eth network config + */ public EthNetworkConfig build() { return new EthNetworkConfig(genesisConfig, networkId, bootNodes, dnsDiscoveryUrl); } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java b/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java index 7f47f44efd8..9d949b08ae3 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java @@ -14,14 +14,100 @@ */ package org.hyperledger.besu.cli.config; +import java.math.BigInteger; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; + +/** The enum Network name. */ public enum NetworkName { - MAINNET, - RINKEBY, - ROPSTEN, - GOERLI, - DEV, - CLASSIC, - KOTTI, - MORDOR, - YOLO_V2 + /** Mainnet network name. */ + MAINNET("/mainnet.json", BigInteger.valueOf(1)), + /** Sepolia network name. */ + SEPOLIA("/sepolia.json", BigInteger.valueOf(11155111)), + /** Goerli network name. */ + GOERLI("/goerli.json", BigInteger.valueOf(5)), + /** Dev network name. */ + DEV("/dev.json", BigInteger.valueOf(2018), false), + /** Future EIPs network name. */ + FUTURE_EIPS("/future.json", BigInteger.valueOf(2022), false), + /** Experimental EIPs network name. */ + EXPERIMENTAL_EIPS("/experimental.json", BigInteger.valueOf(2023), false), + /** Classic network name. */ + CLASSIC("/classic.json", BigInteger.valueOf(1)), + /** Kotti network name. */ + KOTTI("/kotti.json", BigInteger.valueOf(6)), + /** Mordor network name. */ + MORDOR("/mordor.json", BigInteger.valueOf(7)); + + private final String genesisFile; + private final BigInteger networkId; + private final boolean canFastSync; + private final String deprecationDate; + + NetworkName(final String genesisFile, final BigInteger networkId) { + this(genesisFile, networkId, true); + } + + NetworkName(final String genesisFile, final BigInteger networkId, final boolean canFastSync) { + this.genesisFile = genesisFile; + this.networkId = networkId; + this.canFastSync = canFastSync; + // no deprecations planned + this.deprecationDate = null; + } + + /** + * Gets genesis file. + * + * @return the genesis file + */ + public String getGenesisFile() { + return genesisFile; + } + + /** + * Gets network id. + * + * @return the network id + */ + public BigInteger getNetworkId() { + return networkId; + } + + /** + * Can fast sync boolean. + * + * @return the boolean + */ + public boolean canFastSync() { + return canFastSync; + } + + /** + * Normalize string. + * + * @return the string + */ + public String normalize() { + return StringUtils.capitalize(name().toLowerCase()); + } + + /** + * Is deprecated boolean. + * + * @return the boolean + */ + public boolean isDeprecated() { + return deprecationDate != null; + } + + /** + * Gets deprecation date. + * + * @return the deprecation date + */ + public Optional getDeprecationDate() { + return Optional.ofNullable(deprecationDate); + } } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/converter/FractionConverter.java b/besu/src/main/java/org/hyperledger/besu/cli/converter/FractionConverter.java index e3fc064891e..969a6be8e9e 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/converter/FractionConverter.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/converter/FractionConverter.java @@ -19,6 +19,7 @@ import picocli.CommandLine; +/** The Fraction converter to convert floats in CLI. */ public class FractionConverter implements CommandLine.ITypeConverter { @Override diff --git a/besu/src/main/java/org/hyperledger/besu/cli/converter/MetricCategoryConverter.java b/besu/src/main/java/org/hyperledger/besu/cli/converter/MetricCategoryConverter.java index 9752c6df28d..684c3ce30c0 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/converter/MetricCategoryConverter.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/converter/MetricCategoryConverter.java @@ -23,6 +23,7 @@ import com.google.common.annotations.VisibleForTesting; import picocli.CommandLine; +/** The Metric category converter for CLI options. */ public class MetricCategoryConverter implements CommandLine.ITypeConverter { private final Map metricCategories = new HashMap<>(); @@ -36,15 +37,31 @@ public MetricCategory convert(final String value) { return category; } + /** + * Add Metrics categories. + * + * @param the type parameter + * @param categoryEnum the category enum + */ public & MetricCategory> void addCategories(final Class categoryEnum) { EnumSet.allOf(categoryEnum) .forEach(category -> metricCategories.put(category.name(), category)); } + /** + * Add registry category. + * + * @param metricCategory the metric category + */ public void addRegistryCategory(final MetricCategory metricCategory) { metricCategories.put(metricCategory.getName().toUpperCase(), metricCategory); } + /** + * Gets metric categories. + * + * @return the metric categories + */ @VisibleForTesting Map getMetricCategories() { return metricCategories; diff --git a/besu/src/main/java/org/hyperledger/besu/cli/converter/PercentageConverter.java b/besu/src/main/java/org/hyperledger/besu/cli/converter/PercentageConverter.java index d1b4ad836fd..23a2d94d33d 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/converter/PercentageConverter.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/converter/PercentageConverter.java @@ -19,6 +19,7 @@ import picocli.CommandLine; +/** The Percentage Cli type converter. */ public class PercentageConverter implements CommandLine.ITypeConverter { @Override diff --git a/besu/src/main/java/org/hyperledger/besu/cli/converter/RpcApisConverter.java b/besu/src/main/java/org/hyperledger/besu/cli/converter/RpcApisConverter.java deleted file mode 100644 index fd84d526ac1..00000000000 --- a/besu/src/main/java/org/hyperledger/besu/cli/converter/RpcApisConverter.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.cli.converter; - -import org.hyperledger.besu.cli.converter.exception.RpcApisConversionException; -import org.hyperledger.besu.consensus.clique.jsonrpc.CliqueRpcApis; -import org.hyperledger.besu.consensus.ibft.jsonrpc.IbftRpcApis; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; - -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Stream; - -import picocli.CommandLine; - -public class RpcApisConverter implements CommandLine.ITypeConverter { - - @Override - public RpcApi convert(final String name) throws RpcApisConversionException { - return Stream.>>of( - RpcApis::valueOf, CliqueRpcApis::valueOf, IbftRpcApis::valueOf) - .map(f -> f.apply(name.trim().toUpperCase())) - .filter(Optional::isPresent) - .map(Optional::get) - .findFirst() - .orElseThrow(() -> new RpcApisConversionException(name)); - } -} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/FractionConversionException.java b/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/FractionConversionException.java index dd908213806..4dc3d446b05 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/FractionConversionException.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/FractionConversionException.java @@ -16,8 +16,14 @@ import static java.lang.String.format; +/** The custom Fraction conversion exception. */ public final class FractionConversionException extends Exception { + /** + * Instantiates a new Fraction conversion exception. + * + * @param value the value + */ public FractionConversionException(final String value) { super(format("Invalid value: %s, should be a decimal between 0.0 and 1.0 inclusive.", value)); } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/PercentageConversionException.java b/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/PercentageConversionException.java index 42eab94947f..f016996d255 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/PercentageConversionException.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/PercentageConversionException.java @@ -16,8 +16,14 @@ import static java.lang.String.format; +/** The custom Percentage conversion exception. */ public final class PercentageConversionException extends Exception { + /** + * Instantiates a new Percentage conversion exception. + * + * @param value the invalid value to add in exception message + */ public PercentageConversionException(final String value) { super(format("Invalid value: %s, should be a number between 0 and 100 inclusive.", value)); } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/RpcApisConversionException.java b/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/RpcApisConversionException.java index 0de6ea638fe..8d58a166322 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/RpcApisConversionException.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/RpcApisConversionException.java @@ -16,8 +16,14 @@ import static java.lang.String.format; +/** The custom Rpc Apis conversion exception. */ public final class RpcApisConversionException extends Exception { + /** + * Instantiates a new Rpc apis conversion exception. + * + * @param name the invalid Rpc Api name to report in exception message + */ public RpcApisConversionException(final String name) { super(format("Invalid value: %s", name)); } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/custom/CorsAllowedOriginsProperty.java b/besu/src/main/java/org/hyperledger/besu/cli/custom/CorsAllowedOriginsProperty.java index 2b3a04b5266..9bdb2599d3d 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/custom/CorsAllowedOriginsProperty.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/custom/CorsAllowedOriginsProperty.java @@ -28,10 +28,12 @@ import com.google.common.base.Splitter; import com.google.common.base.Strings; +/** The Cors allowed origins property used in CLI */ public class CorsAllowedOriginsProperty extends AbstractList { private final List domains = new ArrayList<>(); + /** Instantiates a new Cors allowed origins property. */ public CorsAllowedOriginsProperty() {} @Override diff --git a/besu/src/main/java/org/hyperledger/besu/cli/custom/EnodeToURIPropertyConverter.java b/besu/src/main/java/org/hyperledger/besu/cli/custom/EnodeToURIPropertyConverter.java index 54dc2aefe6b..c51a1772dda 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/custom/EnodeToURIPropertyConverter.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/custom/EnodeToURIPropertyConverter.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.cli.custom; -import org.hyperledger.besu.ethereum.p2p.peers.EnodeURL; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import java.net.URI; import java.util.function.Function; @@ -22,14 +22,21 @@ import com.google.common.annotations.VisibleForTesting; import picocli.CommandLine.ITypeConverter; +/** The Enode to uri property converter. */ public class EnodeToURIPropertyConverter implements ITypeConverter { private final Function converter; + /** Instantiates a new Enode to uri property converter. */ EnodeToURIPropertyConverter() { - this.converter = (s) -> EnodeURL.fromString(s).toURI(); + this.converter = (s) -> EnodeURLImpl.fromString(s).toURI(); } + /** + * Instantiates a new Enode to uri property converter. + * + * @param converter the converter + */ @VisibleForTesting EnodeToURIPropertyConverter(final Function converter) { this.converter = converter; diff --git a/besu/src/main/java/org/hyperledger/besu/cli/custom/JsonRPCAllowlistHostsProperty.java b/besu/src/main/java/org/hyperledger/besu/cli/custom/JsonRPCAllowlistHostsProperty.java index d99ba0b3b62..6eec1f0ef67 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/custom/JsonRPCAllowlistHostsProperty.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/custom/JsonRPCAllowlistHostsProperty.java @@ -25,10 +25,12 @@ import com.google.common.base.Splitter; import com.google.common.base.Strings; +/** The Json Rpc allowlist hosts list for CLI option. */ public class JsonRPCAllowlistHostsProperty extends AbstractList { private final List hostnamesAllowlist = new ArrayList<>(); + /** Instantiates a new Json rpc allowlist hosts property. */ public JsonRPCAllowlistHostsProperty() {} @Override diff --git a/besu/src/main/java/org/hyperledger/besu/cli/custom/RpcAuthFileValidator.java b/besu/src/main/java/org/hyperledger/besu/cli/custom/RpcAuthFileValidator.java index 40a9155799e..35c5bf13865 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/custom/RpcAuthFileValidator.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/custom/RpcAuthFileValidator.java @@ -27,8 +27,17 @@ import picocli.CommandLine; import picocli.CommandLine.ParameterException; +/** The Rpc authentication file validator. */ public class RpcAuthFileValidator { + /** + * Validate auth file. + * + * @param commandLine the command line to use for parameter exceptions + * @param filename the auth file + * @param type the RPC type + * @return the auth filename + */ public static String validate( final CommandLine commandLine, final String filename, final String type) { @@ -80,9 +89,7 @@ private static boolean verifyAllUsersHavePassword(final TomlParseResult tomlPars int configuredUsers = tomlParseResult.getTable("Users").keySet().size(); int usersWithPasswords = - tomlParseResult - .keyPathSet() - .parallelStream() + tomlParseResult.keyPathSet().parallelStream() .filter( keySet -> keySet.contains("Users") @@ -95,9 +102,7 @@ private static boolean verifyAllUsersHavePassword(final TomlParseResult tomlPars } private static boolean verifyAllEntriesHaveValues(final TomlParseResult tomlParseResult) { - return tomlParseResult - .dottedKeySet() - .parallelStream() + return tomlParseResult.dottedKeySet().parallelStream() .filter(keySet -> !keySet.contains("password")) .allMatch(dottedKey -> verifyEntry(dottedKey, tomlParseResult)); } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/error/BesuExceptionHandler.java b/besu/src/main/java/org/hyperledger/besu/cli/error/BesuExceptionHandler.java deleted file mode 100644 index da44caf2d8d..00000000000 --- a/besu/src/main/java/org/hyperledger/besu/cli/error/BesuExceptionHandler.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.cli.error; - -import java.util.List; -import java.util.function.Supplier; - -import org.apache.logging.log4j.Level; -import picocli.CommandLine; - -public class BesuExceptionHandler - extends CommandLine.AbstractHandler, BesuExceptionHandler> - implements CommandLine.IExceptionHandler2> { - - private final Supplier levelSupplier; - - public BesuExceptionHandler(final Supplier levelSupplier) { - this.levelSupplier = levelSupplier; - } - - @Override - public List handleParseException( - final CommandLine.ParameterException ex, final String[] args) { - final Level logLevel = levelSupplier.get(); - if (logLevel != null && Level.DEBUG.isMoreSpecificThan(logLevel)) { - ex.printStackTrace(err()); - } else { - err().println(ex.getMessage()); - } - - CommandLine.UnmatchedArgumentException.printSuggestions(ex, err()); - - // don't print full help, just the instructions required to get it - ex.getCommandLine().getErr().println(); - ex.getCommandLine().getErr().println("To display full help:"); - ex.getCommandLine().getErr().println("besu [COMMAND] --help"); - - return returnResultOrExit(null); - } - - @Override - public List handleExecutionException( - final CommandLine.ExecutionException ex, final CommandLine.ParseResult parseResult) { - return throwOrExit(ex); - } - - @Override - protected BesuExceptionHandler self() { - return this; - } -} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/error/BesuExecutionExceptionHandler.java b/besu/src/main/java/org/hyperledger/besu/cli/error/BesuExecutionExceptionHandler.java new file mode 100644 index 00000000000..77b458eb78c --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/error/BesuExecutionExceptionHandler.java @@ -0,0 +1,34 @@ +/* + * Copyright contributors to Hyperledger Besu + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.cli.error; + +import picocli.CommandLine; +import picocli.CommandLine.IExecutionExceptionHandler; +import picocli.CommandLine.Model.CommandSpec; + +/** Custom Execution Exception Handler used by PicoCLI framework. */ +public class BesuExecutionExceptionHandler implements IExecutionExceptionHandler { + @Override + public int handleExecutionException( + final Exception ex, + final CommandLine commandLine, + final CommandLine.ParseResult parseResult) { + final CommandSpec spec = commandLine.getCommandSpec(); + commandLine.getErr().println(ex); + return commandLine.getExitCodeExceptionMapper() != null + ? commandLine.getExitCodeExceptionMapper().getExitCode(ex) + : spec.exitCodeOnExecutionException(); + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/error/BesuParameterExceptionHandler.java b/besu/src/main/java/org/hyperledger/besu/cli/error/BesuParameterExceptionHandler.java new file mode 100644 index 00000000000..6b7d8d6d6cb --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/error/BesuParameterExceptionHandler.java @@ -0,0 +1,62 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.cli.error; + +import java.io.PrintWriter; +import java.util.function.Supplier; + +import picocli.CommandLine; +import picocli.CommandLine.Model.CommandSpec; + +/** The custom parameter exception handler for Besu PicoCLI. */ +public class BesuParameterExceptionHandler implements CommandLine.IParameterExceptionHandler { + + private final Supplier levelSupplier; + + /** + * Instantiates a new Besu parameter exception handler. + * + * @param levelSupplier the logging level supplier + */ + public BesuParameterExceptionHandler(final Supplier levelSupplier) { + this.levelSupplier = levelSupplier; + } + + @Override + public int handleParseException(final CommandLine.ParameterException ex, final String[] args) { + final CommandLine cmd = ex.getCommandLine(); + final PrintWriter err = cmd.getErr(); + final String logLevel = levelSupplier.get(); + if (logLevel != null + && (logLevel.equals("DEBUG") || logLevel.equals("TRACE") || logLevel.equals("ALL"))) { + ex.printStackTrace(err); + } else { + err.println(ex.getMessage()); + } + + CommandLine.UnmatchedArgumentException.printSuggestions(ex, err); + + // don't print full help, just the instructions required to get it + err.println(); + err.println("To display full help:"); + err.println("besu [COMMAND] --help"); + + final CommandSpec spec = cmd.getCommandSpec(); + + return cmd.getExitCodeExceptionMapper() != null + ? cmd.getExitCodeExceptionMapper().getExitCode(ex) + : spec.exitCodeOnInvalidInput(); + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/logging/BesuLoggingConfigurationFactory.java b/besu/src/main/java/org/hyperledger/besu/cli/logging/BesuLoggingConfigurationFactory.java index f7e593a8270..c4af7e23b5b 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/logging/BesuLoggingConfigurationFactory.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/logging/BesuLoggingConfigurationFactory.java @@ -19,6 +19,7 @@ import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; +/** Custom Log4J Configuration Factory for Besu */ public class BesuLoggingConfigurationFactory extends ConfigurationFactory { @Override diff --git a/besu/src/main/java/org/hyperledger/besu/cli/logging/XmlExtensionConfiguration.java b/besu/src/main/java/org/hyperledger/besu/cli/logging/XmlExtensionConfiguration.java index 34f5f93674a..d2ae7071bdb 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/logging/XmlExtensionConfiguration.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/logging/XmlExtensionConfiguration.java @@ -19,7 +19,6 @@ import java.io.IOException; import java.util.stream.Stream; -import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.appender.ConsoleAppender; import org.apache.logging.log4j.core.config.AbstractConfiguration; @@ -27,9 +26,18 @@ import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.xml.XmlConfiguration; import org.apache.logging.log4j.core.layout.PatternLayout; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +/** The Xml extension configuration for Logging framework. */ public class XmlExtensionConfiguration extends XmlConfiguration { + /** + * Instantiates a new Xml extension configuration. + * + * @param loggerContext the logger context + * @param configSource the Configuration Source + */ public XmlExtensionConfiguration( final LoggerContext loggerContext, final ConfigurationSource configSource) { super(loggerContext, configSource); @@ -57,11 +65,13 @@ public Configuration reconfigure() { createConsoleAppender(); return refreshed; } catch (final IOException e) { - LogManager.getLogger().error("Failed to reload the Log4j2 Xml configuration file", e); + LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) + .error("Failed to reload the Log4j2 Xml configuration file", e); } } - LogManager.getLogger().warn("Cannot programmatically reconfigure loggers"); + LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) + .warn("Cannot programmatically reconfigure loggers"); return refreshedParent; } @@ -83,7 +93,7 @@ private void createConsoleAppender() { final PatternLayout patternLayout = PatternLayout.newBuilder() .withConfiguration(this) - .withDisableAnsi(!BesuCommand.getColorEnabled().orElse(true)) + .withDisableAnsi(!BesuCommand.getColorEnabled().orElse(!noColorSet())) .withNoConsoleNoAnsi(!BesuCommand.getColorEnabled().orElse(false)) .withPattern( String.join( @@ -100,6 +110,10 @@ private void createConsoleAppender() { this.getRootLogger().addAppender(consoleAppender, null, null); } + private static boolean noColorSet() { + return System.getenv("NO_COLOR") != null; + } + private boolean customLog4jConfigFilePresent() { return Stream.of("LOG4J_CONFIGURATION_FILE", "log4j.configurationFile") .flatMap( diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/OptionParser.java b/besu/src/main/java/org/hyperledger/besu/cli/options/OptionParser.java index 76d5b269511..73161742f90 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/OptionParser.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/OptionParser.java @@ -22,34 +22,77 @@ import com.google.common.collect.Range; import org.apache.tuweni.units.bigints.UInt256; +/** The Option parser. */ public class OptionParser { + /** + * Parse long range range. + * + * @param arg the arg + * @return the range + */ public static Range parseLongRange(final String arg) { checkArgument(arg.matches("-?\\d+\\.\\.-?\\d+")); final Iterator ends = Splitter.on("..").split(arg).iterator(); return Range.closed(parseLong(ends.next()), parseLong(ends.next())); } + /** + * Parse long from String. + * + * @param arg long value to parse from String + * @return the long + */ public static long parseLong(final String arg) { return Long.parseLong(arg, 10); } + /** + * Format Long values range. + * + * @param range the range + * @return the string + */ public static String format(final Range range) { return format(range.lowerEndpoint()) + ".." + format(range.upperEndpoint()); } + /** + * Format int to String. + * + * @param value the value + * @return the string + */ public static String format(final int value) { return Integer.toString(value, 10); } + /** + * Format long to String. + * + * @param value the value + * @return the string + */ public static String format(final long value) { return Long.toString(value, 10); } + /** + * Format float to string. + * + * @param value the value + * @return the string + */ public static String format(final float value) { return Float.toString(value); } + /** + * Format UInt256 to string. + * + * @param value the value + * @return the string + */ public static String format(final UInt256 value) { return value.toBigInteger().toString(10); } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java new file mode 100644 index 00000000000..c93761fdae1 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java @@ -0,0 +1,89 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +package org.hyperledger.besu.cli.options.stable; + +import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD; + +import org.hyperledger.besu.cli.options.CLIOptions; +import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; +import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; +import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import picocli.CommandLine.Option; + +/** The Data storage CLI options. */ +public class DataStorageOptions implements CLIOptions { + + private static final String DATA_STORAGE_FORMAT = "--data-storage-format"; + + private static final String BONSAI_STORAGE_FORMAT_MAX_LAYERS_TO_LOAD = + "--bonsai-historical-block-limit"; + + // Use Bonsai DB + @Option( + names = {DATA_STORAGE_FORMAT}, + description = + "Format to store trie data in. Either FOREST or BONSAI (default: ${DEFAULT-VALUE}).", + arity = "1") + private final DataStorageFormat dataStorageFormat = DataStorageFormat.FOREST; + + @Option( + names = {BONSAI_STORAGE_FORMAT_MAX_LAYERS_TO_LOAD, "--bonsai-maximum-back-layers-to-load"}, + paramLabel = "", + description = + "Limit of historical layers that can be loaded with BONSAI (default: ${DEFAULT-VALUE}).", + arity = "1") + private final Long bonsaiMaxLayersToLoad = DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD; + + /** + * Create data storage options. + * + * @return the data storage options + */ + public static DataStorageOptions create() { + return new DataStorageOptions(); + } + + @Override + public DataStorageConfiguration toDomainObject() { + return ImmutableDataStorageConfiguration.builder() + .dataStorageFormat(dataStorageFormat) + .bonsaiMaxLayersToLoad(bonsaiMaxLayersToLoad) + .build(); + } + + @Override + public List getCLIOptions() { + return List.of( + DATA_STORAGE_FORMAT, + dataStorageFormat.toString(), + BONSAI_STORAGE_FORMAT_MAX_LAYERS_TO_LOAD, + bonsaiMaxLayersToLoad.toString()); + } + + /** + * Normalize data storage format string. + * + * @return the normalized string + */ + public String normalizeDataStorageFormat() { + return StringUtils.capitalize(dataStorageFormat.toString().toLowerCase()); + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/EthstatsOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/EthstatsOptions.java new file mode 100644 index 00000000000..a6e939fdf0e --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/EthstatsOptions.java @@ -0,0 +1,109 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.cli.options.stable; + +import org.hyperledger.besu.cli.options.CLIOptions; +import org.hyperledger.besu.ethstats.util.EthStatsConnectOptions; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import picocli.CommandLine; + +/** The Ethstats CLI options. */ +public class EthstatsOptions implements CLIOptions { + + private static final String ETHSTATS = "--ethstats"; + private static final String ETHSTATS_CONTACT = "--ethstats-contact"; + private static final String ETHSTATS_CACERT_FILE = "--ethstats-cacert-file"; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) + @CommandLine.Option( + names = {ETHSTATS}, + paramLabel = "<[ws://|wss://]nodename:secret@host:[port]>", + description = "Reporting URL of a ethstats server. Scheme and port can be omitted.", + arity = "1") + private String ethstatsUrl = ""; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) + @CommandLine.Option( + names = {ETHSTATS_CONTACT}, + description = "Contact address to send to ethstats server", + arity = "1") + private String ethstatsContact = ""; + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) + @CommandLine.Option( + names = {ETHSTATS_CACERT_FILE}, + paramLabel = "", + description = + "Specifies the path to the root CA (Certificate Authority) certificate file that has signed ethstats server certificate. This option is optional.") + private Path ethstatsCaCert = null; + + private EthstatsOptions() {} + + /** + * Create ethstats options. + * + * @return the ethstats options + */ + public static EthstatsOptions create() { + return new EthstatsOptions(); + } + + @Override + public EthStatsConnectOptions toDomainObject() { + return EthStatsConnectOptions.fromParams(ethstatsUrl, ethstatsContact, ethstatsCaCert); + } + + /** + * Gets ethstats url. + * + * @return the ethstats url + */ + public String getEthstatsUrl() { + return ethstatsUrl; + } + + /** + * Gets ethstats contact. + * + * @return the ethstats contact + */ + public String getEthstatsContact() { + return ethstatsContact; + } + + /** + * Returns path to root CA cert file. + * + * @return Path to CA file. null if no CA file to set. + */ + public Path getEthstatsCaCert() { + return ethstatsCaCert; + } + + @Override + public List getCLIOptions() { + final List options = new ArrayList<>(); + options.add(ETHSTATS + "=" + ethstatsUrl); + options.add(ETHSTATS_CONTACT + "=" + ethstatsContact); + if (ethstatsCaCert != null) { + options.add(ETHSTATS_CACERT_FILE + "=" + ethstatsCaCert); + } + return options; + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/LoggingLevelOption.java b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/LoggingLevelOption.java new file mode 100644 index 00000000000..ad119ea61a0 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/LoggingLevelOption.java @@ -0,0 +1,71 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.cli.options.stable; + +import java.util.Set; + +import picocli.CommandLine; +import picocli.CommandLine.Model.CommandSpec; +import picocli.CommandLine.Spec; + +/** The Logging level CLI option. */ +public class LoggingLevelOption { + + /** + * Create logging level option. + * + * @return the logging level option + */ + public static LoggingLevelOption create() { + return new LoggingLevelOption(); + } + + private static final Set ACCEPTED_VALUES = + Set.of("OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE", "ALL"); + /** The Picocli CommandSpec. Visible for testing. Injected by Picocli framework at runtime. */ + @Spec CommandSpec spec; + + private String logLevel; + + /** + * Sets log level. + * + * @param logLevel the log level + */ + @CommandLine.Option( + names = {"--logging", "-l"}, + paramLabel = "", + description = "Logging verbosity levels: OFF, ERROR, WARN, INFO, DEBUG, TRACE, ALL") + public void setLogLevel(final String logLevel) { + if ("FATAL".equalsIgnoreCase(logLevel)) { + System.out.println("FATAL level is deprecated"); + this.logLevel = "ERROR"; + } else if (ACCEPTED_VALUES.contains(logLevel.toUpperCase())) { + this.logLevel = logLevel.toUpperCase(); + } else { + throw new CommandLine.ParameterException( + spec.commandLine(), "Unknown logging value: " + logLevel); + } + } + + /** + * Gets log level. + * + * @return the log level + */ + public String getLogLevel() { + return logLevel; + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/NodePrivateKeyFileOption.java b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/NodePrivateKeyFileOption.java new file mode 100644 index 00000000000..42789627d64 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/NodePrivateKeyFileOption.java @@ -0,0 +1,50 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.cli.options.stable; + +import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_PATH_FORMAT_HELP; + +import java.io.File; + +import picocli.CommandLine; + +/** The Node private key file Cli option. */ +public class NodePrivateKeyFileOption { + + /** + * Create node private key file option. + * + * @return the node private key file option + */ + public static NodePrivateKeyFileOption create() { + return new NodePrivateKeyFileOption(); + } + + @CommandLine.Option( + names = {"--node-private-key-file"}, + paramLabel = MANDATORY_PATH_FORMAT_HELP, + description = + "The node's private key file (default: a file named \"key\" in the Besu data directory)") + private final File nodePrivateKeyFile = null; + + /** + * Gets node private key file. + * + * @return the node private key file + */ + public File getNodePrivateKeyFile() { + return nodePrivateKeyFile; + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/P2PTLSConfigOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/P2PTLSConfigOptions.java new file mode 100644 index 00000000000..fefea4bb758 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/P2PTLSConfigOptions.java @@ -0,0 +1,160 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.cli.options.stable; + +import static java.util.Arrays.asList; +import static org.hyperledger.besu.cli.DefaultCommandValues.DEFAULT_KEYSTORE_TYPE; +import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_FILE_FORMAT_HELP; + +import org.hyperledger.besu.cli.util.CommandLineUtils; +import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider; +import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; + +import java.nio.file.Path; +import java.util.Optional; + +import org.slf4j.Logger; +import picocli.CommandLine; +import picocli.CommandLine.Option; +import picocli.CommandLine.ParameterException; + +/** The P2P TLS Config Cli Options. */ +public class P2PTLSConfigOptions { + @Option( + names = {"--Xp2p-tls-enabled"}, + hidden = true, + description = "Enable P2P TLS functionality (default: ${DEFAULT-VALUE})") + private final Boolean p2pTLSEnabled = false; + + @SuppressWarnings({ + "FieldCanBeFinal", + "FieldMayBeFinal" + }) // p2pTLSKeyStoreType requires non-final Strings. + @Option( + names = {"--Xp2p-tls-keystore-type"}, + hidden = true, + paramLabel = "", + description = "P2P service keystore type. Required if P2P TLS is enabled.") + private String p2pTLSKeyStoreType = DEFAULT_KEYSTORE_TYPE; + + @Option( + names = {"--Xp2p-tls-keystore-file"}, + hidden = true, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = "Keystore containing key/certificate for the P2P service.") + private final Path p2pTLSKeyStoreFile = null; + + @Option( + names = {"--Xp2p-tls-keystore-password-file"}, + hidden = true, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = + "File containing password to unlock keystore for the P2P service. Required if P2P TLS is enabled.") + private final Path p2pTLSKeyStorePasswordFile = null; + + @SuppressWarnings({ + "FieldCanBeFinal", + "FieldMayBeFinal" + }) // p2pTLSTrustStoreType requires non-final Strings. + @Option( + names = {"--Xp2p-tls-truststore-type"}, + hidden = true, + paramLabel = "", + description = "P2P service truststore type.") + private String p2pTLSTrustStoreType = DEFAULT_KEYSTORE_TYPE; + + @Option( + names = {"--Xp2p-tls-truststore-file"}, + hidden = true, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = "Truststore containing trusted certificates for the P2P service.") + private final Path p2pTLSTrustStoreFile = null; + + @Option( + names = {"--Xp2p-tls-truststore-password-file"}, + hidden = true, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = "File containing password to unlock truststore for the P2P service.") + private final Path p2pTLSTrustStorePasswordFile = null; + + @Option( + names = {"--Xp2p-tls-crl-file"}, + hidden = true, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = "Certificate revocation list for the P2P service.") + private final Path p2pCrlFile = null; + + @Option( + names = {"--Xp2p-tls-clienthello-sni"}, + hidden = true, + description = + "Whether to send a SNI header in the TLS ClientHello message (default: ${DEFAULT-VALUE})") + private final Boolean p2pTlsClientHelloSniHeaderEnabled = false; + + /** + * Generate P2p tls configuration. + * + * @param commandLine the command line object to report exceptions + * @return the optional TLSConfiguration + */ + public Optional p2pTLSConfiguration(final CommandLine commandLine) { + if (!p2pTLSEnabled) { + return Optional.empty(); + } + + if (p2pTLSKeyStoreType == null) { + throw new ParameterException( + commandLine, "Keystore type is required when p2p TLS is enabled"); + } + + if (p2pTLSKeyStorePasswordFile == null) { + throw new ParameterException( + commandLine, + "File containing password to unlock keystore is required when p2p TLS is enabled"); + } + + return Optional.of( + TLSConfiguration.Builder.tlsConfiguration() + .withKeyStoreType(p2pTLSKeyStoreType) + .withKeyStorePath(p2pTLSKeyStoreFile) + .withKeyStorePasswordSupplier(new FileBasedPasswordProvider(p2pTLSKeyStorePasswordFile)) + .withKeyStorePasswordPath(p2pTLSKeyStorePasswordFile) + .withTrustStoreType(p2pTLSTrustStoreType) + .withTrustStorePath(p2pTLSTrustStoreFile) + .withTrustStorePasswordSupplier( + null == p2pTLSTrustStorePasswordFile + ? null + : new FileBasedPasswordProvider(p2pTLSTrustStorePasswordFile)) + .withTrustStorePasswordPath(p2pTLSTrustStorePasswordFile) + .withCrlPath(p2pCrlFile) + .withClientHelloSniEnabled(p2pTlsClientHelloSniHeaderEnabled) + .build()); + } + + /** + * Check P2P Tls options dependencies. + * + * @param logger the logger + * @param commandLine the command line + */ + public void checkP2PTLSOptionsDependencies(final Logger logger, final CommandLine commandLine) { + CommandLineUtils.checkOptionDependencies( + logger, + commandLine, + "--Xp2p-tls-enabled", + !p2pTLSEnabled, + asList("--Xp2p-tls-keystore-type", "--Xp2p-tls-keystore-password-file")); + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/ChainPruningOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/ChainPruningOptions.java new file mode 100644 index 00000000000..e164ec8fa85 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/ChainPruningOptions.java @@ -0,0 +1,108 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + */ +package org.hyperledger.besu.cli.options.unstable; + +import org.hyperledger.besu.cli.options.CLIOptions; +import org.hyperledger.besu.ethereum.chain.ChainPrunerConfiguration; +import org.hyperledger.besu.util.number.PositiveNumber; + +import java.util.Arrays; +import java.util.List; + +import picocli.CommandLine; + +/** The Chain pruning CLI options. */ +public class ChainPruningOptions implements CLIOptions { + private static final String CHAIN_PRUNING_ENABLED_FLAG = "--Xchain-pruning-enabled"; + private static final String CHAIN_PRUNING_BLOCKS_RETAINED_FLAG = + "--Xchain-pruning-blocks-retained"; + private static final String CHAIN_PRUNING_FREQUENCY_FLAG = "--Xchain-pruning-frequency"; + /** The constant DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED. */ + public static final long DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED = 7200; + /** The constant DEFAULT_CHAIN_DATA_PRUNING_FREQUENCY. */ + public static final int DEFAULT_CHAIN_DATA_PRUNING_FREQUENCY = 256; + + @CommandLine.Option( + hidden = true, + names = {CHAIN_PRUNING_ENABLED_FLAG}, + description = + "Enable the chain pruner to actively prune old chain data (default: ${DEFAULT-VALUE})") + private final Boolean chainDataPruningEnabled = Boolean.FALSE; + + @CommandLine.Option( + hidden = true, + names = {CHAIN_PRUNING_BLOCKS_RETAINED_FLAG}, + description = + "The number of recent blocks for which to keep the chain data. Must be >= " + + DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED + + " (default: ${DEFAULT-VALUE})") + private final Long chainDataPruningBlocksRetained = + DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED; + + @CommandLine.Option( + hidden = true, + names = {CHAIN_PRUNING_FREQUENCY_FLAG}, + description = + "The number of blocks added to the chain between two pruning operations. Must be non-negative (default: ${DEFAULT-VALUE})") + private final PositiveNumber chainDataPruningBlocksFrequency = + PositiveNumber.fromInt(DEFAULT_CHAIN_DATA_PRUNING_FREQUENCY); + + /** + * Create chain pruning options. + * + * @return the chain pruning options + */ + public static ChainPruningOptions create() { + return new ChainPruningOptions(); + } + + /** + * Gets chain data pruning enabled. + * + * @return the chain data pruning enabled + */ + public Boolean getChainDataPruningEnabled() { + return chainDataPruningEnabled; + } + + /** + * Gets chain data pruning blocks retained. + * + * @return the chain data pruning blocks retained + */ + public Long getChainDataPruningBlocksRetained() { + return chainDataPruningBlocksRetained; + } + + @Override + public ChainPrunerConfiguration toDomainObject() { + return new ChainPrunerConfiguration( + chainDataPruningEnabled, + chainDataPruningBlocksRetained, + chainDataPruningBlocksFrequency.getValue()); + } + + @Override + public List getCLIOptions() { + return Arrays.asList( + CHAIN_PRUNING_ENABLED_FLAG, + chainDataPruningEnabled.toString(), + CHAIN_PRUNING_BLOCKS_RETAINED_FLAG, + chainDataPruningBlocksRetained.toString(), + CHAIN_PRUNING_FREQUENCY_FLAG, + chainDataPruningBlocksFrequency.toString()); + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/DataStorageOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/DataStorageOptions.java deleted file mode 100644 index c35ed4407a7..00000000000 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/DataStorageOptions.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * - */ - -package org.hyperledger.besu.cli.options.unstable; - -import org.hyperledger.besu.cli.options.CLIOptions; -import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; -import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; -import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration; - -import java.util.List; - -import picocli.CommandLine.Option; - -public class DataStorageOptions implements CLIOptions { - - private static final String DATA_STORAGE_FORMAT = "--Xdata-storage-format"; - - // Use Bonsai DB - @Option( - names = {DATA_STORAGE_FORMAT}, - hidden = true, - description = - "Format to store trie data in. Either FOREST or BONSAI (default: ${DEFAULT-VALUE}).", - arity = "1") - private final DataStorageFormat dataStorageFormat = DataStorageFormat.FOREST; - - public static DataStorageOptions create() { - return new DataStorageOptions(); - } - - @Override - public DataStorageConfiguration toDomainObject() { - return ImmutableDataStorageConfiguration.builder().dataStorageFormat(dataStorageFormat).build(); - } - - @Override - public List getCLIOptions() { - return List.of(DATA_STORAGE_FORMAT, dataStorageFormat.toString()); - } -} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/DnsOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/DnsOptions.java index 8926ea38d54..8d65a3264e9 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/DnsOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/DnsOptions.java @@ -23,6 +23,7 @@ import picocli.CommandLine; +/** The Dns CLI options. */ public class DnsOptions implements CLIOptions { private final String DNS_ENABLED = "--Xdns-enabled"; @@ -42,10 +43,21 @@ public class DnsOptions implements CLIOptions { arity = "1") private Boolean dnsUpdateEnabled = Boolean.FALSE; + /** + * Create dns options. + * + * @return the dns options + */ public static DnsOptions create() { return new DnsOptions(); } + /** + * From config dns options. + * + * @param enodeDnsConfiguration the enode dns configuration + * @return the dns options + */ public static DnsOptions fromConfig(final EnodeDnsConfiguration enodeDnsConfiguration) { final DnsOptions cliOptions = new DnsOptions(); cliOptions.dnsEnabled = enodeDnsConfiguration.dnsEnabled(); @@ -53,10 +65,20 @@ public static DnsOptions fromConfig(final EnodeDnsConfiguration enodeDnsConfigur return cliOptions; } + /** + * Gets dns enabled. + * + * @return the dns enabled + */ public Boolean getDnsEnabled() { return dnsEnabled; } + /** + * Gets dns update enabled. + * + * @return the dns update enabled + */ public Boolean getDnsUpdateEnabled() { return dnsUpdateEnabled; } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EthProtocolOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EthProtocolOptions.java index b838f6646d0..1d5434ff022 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EthProtocolOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EthProtocolOptions.java @@ -24,16 +24,29 @@ import picocli.CommandLine; +/** The Eth protocol CLI options. */ public class EthProtocolOptions implements CLIOptions { + private static final String MAX_MESSAGE_SIZE_FLAG = "--Xeth-max-message-size"; private static final String MAX_GET_HEADERS_FLAG = "--Xewp-max-get-headers"; private static final String MAX_GET_BODIES_FLAG = "--Xewp-max-get-bodies"; private static final String MAX_GET_RECEIPTS_FLAG = "--Xewp-max-get-receipts"; private static final String MAX_GET_NODE_DATA_FLAG = "--Xewp-max-get-node-data"; private static final String MAX_GET_POOLED_TRANSACTIONS = "--Xewp-max-get-pooled-transactions"; - private static final String ETH_65_ENABLED = "--Xeth-65-enabled"; private static final String LEGACY_ETH_64_FORK_ID_ENABLED = "--compatibility-eth64-forkid-enabled"; + private static final String MAX_CAPABILITY = "--Xeth-capability-max"; + private static final String MIN_CAPABILITY = "--Xeth-capability-min"; + + @CommandLine.Option( + hidden = true, + names = {MAX_MESSAGE_SIZE_FLAG}, + paramLabel = "", + description = + "Maximum message size (in bytes) for Ethereum Wire Protocol messages. (default: ${DEFAULT-VALUE})") + private PositiveNumber maxMessageSize = + PositiveNumber.fromInt(EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE); + @CommandLine.Option( hidden = true, names = {MAX_GET_HEADERS_FLAG}, @@ -79,13 +92,6 @@ public class EthProtocolOptions implements CLIOptions private PositiveNumber maxGetPooledTransactions = PositiveNumber.fromInt(EthProtocolConfiguration.DEFAULT_MAX_GET_POOLED_TRANSACTIONS); - @CommandLine.Option( - hidden = true, - names = {ETH_65_ENABLED}, - paramLabel = "", - description = "Enable the Eth/65 subprotocol. (default: ${DEFAULT-VALUE})") - private Boolean eth65Enabled = EthProtocolConfiguration.DEFAULT_ETH_65_ENABLED; - @CommandLine.Option( names = {LEGACY_ETH_64_FORK_ID_ENABLED}, paramLabel = "", @@ -93,40 +99,71 @@ public class EthProtocolOptions implements CLIOptions private Boolean legacyEth64ForkIdEnabled = EthProtocolConfiguration.DEFAULT_LEGACY_ETH_64_FORK_ID_ENABLED; + @CommandLine.Option( + hidden = true, + names = {MAX_CAPABILITY}, + paramLabel = "", + description = "Max protocol version to support") + private int maxEthCapability = EthProtocolConfiguration.DEFAULT_MAX_CAPABILITY; + + @CommandLine.Option( + hidden = true, + names = {MIN_CAPABILITY}, + paramLabel = "", + description = "Min protocol version to support") + private int minEthCapability = EthProtocolConfiguration.DEFAULT_MIN_CAPABILITY; + private EthProtocolOptions() {} + /** + * Create eth protocol options. + * + * @return the eth protocol options + */ public static EthProtocolOptions create() { return new EthProtocolOptions(); } + /** + * From config eth protocol options. + * + * @param config the config + * @return the eth protocol options + */ public static EthProtocolOptions fromConfig(final EthProtocolConfiguration config) { final EthProtocolOptions options = create(); + options.maxMessageSize = PositiveNumber.fromInt(config.getMaxMessageSize()); options.maxGetBlockHeaders = PositiveNumber.fromInt(config.getMaxGetBlockHeaders()); options.maxGetBlockBodies = PositiveNumber.fromInt(config.getMaxGetBlockBodies()); options.maxGetReceipts = PositiveNumber.fromInt(config.getMaxGetReceipts()); options.maxGetNodeData = PositiveNumber.fromInt(config.getMaxGetNodeData()); options.maxGetPooledTransactions = PositiveNumber.fromInt(config.getMaxGetPooledTransactions()); - options.eth65Enabled = config.isEth65Enabled(); options.legacyEth64ForkIdEnabled = config.isLegacyEth64ForkIdEnabled(); + options.maxEthCapability = config.getMaxEthCapability(); + options.minEthCapability = config.getMinEthCapability(); return options; } @Override public EthProtocolConfiguration toDomainObject() { return EthProtocolConfiguration.builder() + .maxMessageSize(maxMessageSize) .maxGetBlockHeaders(maxGetBlockHeaders) .maxGetBlockBodies(maxGetBlockBodies) .maxGetReceipts(maxGetReceipts) .maxGetNodeData(maxGetNodeData) .maxGetPooledTransactions(maxGetPooledTransactions) - .eth65Enabled(eth65Enabled) .legacyEth64ForkIdEnabled(legacyEth64ForkIdEnabled) + .maxEthCapability(maxEthCapability) + .minEthCapability(minEthCapability) .build(); } @Override public List getCLIOptions() { return Arrays.asList( + MAX_MESSAGE_SIZE_FLAG, + OptionParser.format(maxMessageSize.getValue()), MAX_GET_HEADERS_FLAG, OptionParser.format(maxGetBlockHeaders.getValue()), MAX_GET_BODIES_FLAG, @@ -137,7 +174,6 @@ public List getCLIOptions() { OptionParser.format(maxGetNodeData.getValue()), MAX_GET_POOLED_TRANSACTIONS, OptionParser.format(maxGetPooledTransactions.getValue()), - ETH_65_ENABLED + "=" + eth65Enabled, LEGACY_ETH_64_FORK_ID_ENABLED + "=" + legacyEth64ForkIdEnabled); } } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EthstatsOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EthstatsOptions.java deleted file mode 100644 index 556e96adc57..00000000000 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EthstatsOptions.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.cli.options.unstable; - -import org.hyperledger.besu.cli.options.CLIOptions; -import org.hyperledger.besu.ethstats.util.NetstatsUrl; - -import java.util.Arrays; -import java.util.List; - -import picocli.CommandLine; - -public class EthstatsOptions implements CLIOptions { - - private static final String ETHSTATS = "--Xethstats"; - private static final String ETHSTATS_CONTACT = "--Xethstats-contact"; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) - @CommandLine.Option( - hidden = true, - names = {ETHSTATS}, - paramLabel = "", - description = "Reporting URL of a ethstats server", - arity = "1") - private String ethstatsUrl = ""; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) - @CommandLine.Option( - hidden = true, - names = {ETHSTATS_CONTACT}, - description = "Contact address to send to ethstats server", - arity = "1") - private String ethstatsContact = ""; - - private EthstatsOptions() {} - - public static EthstatsOptions create() { - return new EthstatsOptions(); - } - - @Override - public NetstatsUrl toDomainObject() { - return NetstatsUrl.fromParams(ethstatsUrl, ethstatsContact); - } - - public String getEthstatsUrl() { - return ethstatsUrl; - } - - public String getEthstatsContact() { - return ethstatsContact; - } - - @Override - public List getCLIOptions() { - return Arrays.asList(ETHSTATS + "=" + ethstatsUrl, ETHSTATS_CONTACT + "=" + ethstatsContact); - } -} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EvmOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EvmOptions.java new file mode 100644 index 00000000000..7e787cf83b8 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EvmOptions.java @@ -0,0 +1,63 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.cli.options.unstable; + +import org.hyperledger.besu.cli.options.CLIOptions; +import org.hyperledger.besu.evm.internal.EvmConfiguration; + +import java.util.Arrays; +import java.util.List; + +import picocli.CommandLine; + +/** The Evm CLI options. */ +public class EvmOptions implements CLIOptions { + + /** The constant JUMPDEST_CACHE_WEIGHT. */ + public static final String JUMPDEST_CACHE_WEIGHT = "--Xevm-jumpdest-cache-weight-kb"; + + /** + * Create evm options. + * + * @return the evm options + */ + public static EvmOptions create() { + return new EvmOptions(); + } + + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) + @CommandLine.Option( + names = {JUMPDEST_CACHE_WEIGHT}, + description = + "size in kilobytes to allow the cache " + + "of valid jump destinations to grow to before evicting the least recently used entry", + fallbackValue = "32000", + defaultValue = "32000", + hidden = true, + arity = "1") + private Long jumpDestCacheWeightKilobytes = + 32_000L; // 10k contracts, (25k max contract size / 8 bit) + 32byte hash + + @Override + public EvmConfiguration toDomainObject() { + return new EvmConfiguration(jumpDestCacheWeightKilobytes); + } + + @Override + public List getCLIOptions() { + return Arrays.asList(JUMPDEST_CACHE_WEIGHT); + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/IpcOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/IpcOptions.java new file mode 100644 index 00000000000..d8b868ef909 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/IpcOptions.java @@ -0,0 +1,98 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.cli.options.unstable; + +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_RPC_APIS; + +import java.nio.file.Path; +import java.util.List; + +import picocli.CommandLine; + +/** The Ipc CLI options. */ +public class IpcOptions { + private static final String DEFAULT_IPC_FILE = "besu.ipc"; + + /** + * Create ipc options. + * + * @return the ipc options + */ + public static IpcOptions create() { + return new IpcOptions(); + } + + /** + * Gets default path. + * + * @param dataDir the data dir + * @return the default path + */ + public static Path getDefaultPath(final Path dataDir) { + return dataDir.resolve(DEFAULT_IPC_FILE); + } + + @CommandLine.Option( + names = {"--Xrpc-ipc-enabled"}, + hidden = true, + description = "Set to start the JSON-RPC IPC service (default: ${DEFAULT-VALUE})") + private final Boolean enabled = false; + + @CommandLine.Option( + names = {"--Xrpc-ipc-path"}, + hidden = true, + description = + "IPC socket/pipe file (default: a file named \"" + + DEFAULT_IPC_FILE + + "\" in the Besu data directory)") + private Path ipcPath; + + @CommandLine.Option( + names = {"--Xrpc-ipc-api", "--Xrpc-ipc-apis"}, + hidden = true, + paramLabel = "", + split = " {0,1}, {0,1}", + arity = "1..*", + description = + "Comma separated list of APIs to enable on JSON-RPC IPC service (default: ${DEFAULT-VALUE})") + private final List rpcIpcApis = DEFAULT_RPC_APIS; + + /** + * Whether IPC options are enabled. + * + * @return true for enabled, false otherwise. + */ + public Boolean isEnabled() { + return enabled; + } + + /** + * Gets ipc path. + * + * @return the ipc path + */ + public Path getIpcPath() { + return ipcPath; + } + + /** + * Gets rpc ipc apis. + * + * @return the rpc ipc apis + */ + public List getRpcIpcApis() { + return rpcIpcApis; + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/MetricsCLIOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/MetricsCLIOptions.java index c66a7f7671c..45270c808c9 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/MetricsCLIOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/MetricsCLIOptions.java @@ -22,35 +22,59 @@ import picocli.CommandLine; +/** The Metrics cli options. */ public class MetricsCLIOptions implements CLIOptions { private static final String TIMERS_ENABLED_FLAG = "--Xmetrics-timers-enabled"; + private static final String IDLE_TIMEOUT_FLAG = "--Xmetrics-idle-timeout"; @CommandLine.Option( names = TIMERS_ENABLED_FLAG, hidden = true, defaultValue = "true", description = "Whether to enable timer metrics (default: ${DEFAULT-VALUE}).") - private Boolean timersEnabled = MetricsConfiguration.DEFAULT_TIMERS_ENABLED; + private Boolean timersEnabled = MetricsConfiguration.DEFAULT_METRICS_TIMERS_ENABLED; + + @CommandLine.Option( + hidden = true, + names = {IDLE_TIMEOUT_FLAG}, + paramLabel = "", + description = "Timeout for metrics TCP connections, in seconds (default: ${DEFAULT-VALUE})", + arity = "1") + private int idleTimeout = MetricsConfiguration.DEFAULT_METRICS_IDLE_TIMEOUT_SECONDS; private MetricsCLIOptions() {} + /** + * Create metrics cli options. + * + * @return the metrics cli options + */ public static MetricsCLIOptions create() { return new MetricsCLIOptions(); } + /** + * From configuration metrics cli options. + * + * @param config the config + * @return the metrics cli options + */ public static MetricsCLIOptions fromConfiguration(final MetricsConfiguration config) { final MetricsCLIOptions metricsOptions = create(); metricsOptions.timersEnabled = config.isTimersEnabled(); + metricsOptions.idleTimeout = config.getIdleTimeout(); return metricsOptions; } @Override public MetricsConfiguration.Builder toDomainObject() { - return MetricsConfiguration.builder().timersEnabled(timersEnabled); + return MetricsConfiguration.builder().timersEnabled(timersEnabled).idleTimeout(idleTimeout); } @Override public List getCLIOptions() { - return Arrays.asList(TIMERS_ENABLED_FLAG + "=" + timersEnabled.toString()); + return Arrays.asList( + TIMERS_ENABLED_FLAG + "=" + timersEnabled.toString(), + IDLE_TIMEOUT_FLAG + "=" + idleTimeout); } } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/MiningOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/MiningOptions.java index 0f5960b4a8d..232554722e2 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/MiningOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/MiningOptions.java @@ -14,11 +14,16 @@ */ package org.hyperledger.besu.cli.options.unstable; +import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_MAX_OMMERS_DEPTH; +import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_POS_BLOCK_CREATION_MAX_TIME; +import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_POS_BLOCK_CREATION_REPETITION_MIN_DURATION; +import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_POW_JOB_TTL; import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_REMOTE_SEALERS_LIMIT; import static org.hyperledger.besu.ethereum.core.MiningParameters.DEFAULT_REMOTE_SEALERS_TTL; import picocli.CommandLine; +/** The Mining CLI options. */ public class MiningOptions { @CommandLine.Option( @@ -35,6 +40,20 @@ public class MiningOptions { "Specifies the lifetime of each entry in the cache. An entry will be automatically deleted if no update has been received before the deadline (default: ${DEFAULT-VALUE} minutes)") private final Long remoteSealersTimeToLive = DEFAULT_REMOTE_SEALERS_TTL; + @CommandLine.Option( + hidden = true, + names = {"--Xminer-pow-job-ttl"}, + description = + "Specifies the time PoW jobs are kept in cache and will accept a solution from miners (default: ${DEFAULT-VALUE} milliseconds)") + private final Long powJobTimeToLive = DEFAULT_POW_JOB_TTL; + + @CommandLine.Option( + hidden = true, + names = {"--Xmax-ommers-depth"}, + description = + "Specifies the depth of ommer blocks to accept when receiving solutions (default: ${DEFAULT-VALUE})") + private final Integer maxOmmersDepth = DEFAULT_MAX_OMMERS_DEPTH; + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. @CommandLine.Option( hidden = true, @@ -42,19 +61,91 @@ public class MiningOptions { description = "Extranonce for Stratum network miners (default: ${DEFAULT-VALUE})") private String stratumExtranonce = "080c"; + @CommandLine.Option( + hidden = true, + names = {"--Xpos-block-creation-max-time"}, + description = + "Specifies the maximum time, in milliseconds, a PoS block creation jobs is allowed to run. Must be positive and ≤ 12000 (default: ${DEFAULT-VALUE} milliseconds)") + private final Long posBlockCreationMaxTime = DEFAULT_POS_BLOCK_CREATION_MAX_TIME; + + @CommandLine.Option( + hidden = true, + names = {"--Xpos-block-creation-repetition-min-duration"}, + description = + "If a PoS block creation repetition takes less than this duration, in milliseconds," + + " then it waits before next repetition. Must be positive and ≤ 2000 (default: ${DEFAULT-VALUE} milliseconds)") + private final Long posBlockCreationRepetitionMinDuration = + DEFAULT_POS_BLOCK_CREATION_REPETITION_MIN_DURATION; + + /** + * Create mining options. + * + * @return the mining options + */ public static MiningOptions create() { return new MiningOptions(); } + /** + * Gets remote sealers limit. + * + * @return the remote sealers limit + */ public Integer getRemoteSealersLimit() { return remoteSealersLimit; } + /** + * Gets remote sealers time to live. + * + * @return the remote sealers time to live + */ public Long getRemoteSealersTimeToLive() { return remoteSealersTimeToLive; } + /** + * Gets stratum extra nonce. + * + * @return the stratum extra nonce + */ public String getStratumExtranonce() { return stratumExtranonce; } + + /** + * Gets pow job time to live. + * + * @return the pow job time to live + */ + public Long getPowJobTimeToLive() { + return powJobTimeToLive; + } + + /** + * Gets max ommers depth. + * + * @return the max ommers depth + */ + public int getMaxOmmersDepth() { + return maxOmmersDepth; + } + + /** + * Gets pos block creation max time. + * + * @return the pos block creation max time + */ + public Long getPosBlockCreationMaxTime() { + return posBlockCreationMaxTime; + } + + /** + * Gets pos block creation repetition min duration. + * + * @return the pos block creation repetition min duration. + */ + public Long getPosBlockCreationRepetitionMinDuration() { + return posBlockCreationRepetitionMinDuration; + } } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/NatOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/NatOptions.java index e622d367b3a..0a93d09a202 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/NatOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/NatOptions.java @@ -18,6 +18,7 @@ import picocli.CommandLine; +/** The Nat Cli options. */ public class NatOptions { @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. @@ -36,14 +37,29 @@ public class NatOptions { arity = "1") private final Boolean natMethodFallbackEnabled = true; + /** + * Create nat options. + * + * @return the nat options + */ public static NatOptions create() { return new NatOptions(); } + /** + * Gets nat manager service name. + * + * @return the nat manager service name + */ public String getNatManagerServiceName() { return natManagerServiceName; } + /** + * Whether nat method fallback is enabled. + * + * @return true if enabled, false otherwise. + */ public Boolean getNatMethodFallbackEnabled() { return natMethodFallbackEnabled; } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/NativeLibraryOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/NativeLibraryOptions.java index 319e4adfef2..5869aab0da9 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/NativeLibraryOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/NativeLibraryOptions.java @@ -16,31 +16,87 @@ import picocli.CommandLine; +/** The Native library CLI options. */ public class NativeLibraryOptions { @CommandLine.Option( hidden = true, - names = {"--Xsecp256k1-native-enabled"}, - description = "Path to PID file (optional)", + names = {"--Xsecp-native-enabled", "--Xsecp256k1-native-enabled"}, + description = + "Per default a native library is used for the signature algorithm. " + + "If the Java implementation should be used instead, this option must be set to false", arity = "1") - private final Boolean nativeSecp256k1 = Boolean.TRUE; + private final Boolean nativeSecp = Boolean.TRUE; @CommandLine.Option( hidden = true, names = {"--Xaltbn128-native-enabled"}, - description = "Path to PID file (optional)", + description = + "Per default a native library is used for altbn128. " + + "If the Java implementation should be used instead, this option must be set to false", arity = "1") private final Boolean nativeAltbn128 = Boolean.TRUE; + @CommandLine.Option( + hidden = true, + names = {"--Xblake2bf-native-enabled"}, + description = + "Per default a native library is used for blake2bf if present. " + + "If the Java implementation should be used instead, this option must be set to false", + arity = "1") + private final Boolean nativeBlake2bf = Boolean.TRUE; + + @CommandLine.Option( + hidden = true, + names = {"--Xmodexp-native-enabled"}, + description = + "Per default a native library is used for modexp. " + + "If the Java implementation should be used instead, this option must be set to false", + arity = "1") + private final Boolean nativeModExp = Boolean.TRUE; + + /** + * Create native library options. + * + * @return the native library options + */ public static NativeLibraryOptions create() { return new NativeLibraryOptions(); } - public Boolean getNativeSecp256k1() { - return nativeSecp256k1; + /** + * Whether native secp is enabled. + * + * @return true if enabled, false otherwise. + */ + public Boolean getNativeSecp() { + return nativeSecp; } + /** + * Whether native Altbn128 is enabled. + * + * @return true if enabled, false otherwise. + */ public Boolean getNativeAltbn128() { return nativeAltbn128; } + + /** + * Whether native blake2bf is enabled. + * + * @return true if enabled, false otherwise. + */ + public Boolean getNativeBlake2bf() { + return nativeBlake2bf; + } + + /** + * Whether native mod exp is enabled. + * + * @return true if enabled, false otherwise. + */ + public Boolean getNativeModExp() { + return nativeModExp; + } } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/NetworkingOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/NetworkingOptions.java index 630efee2bf3..0ad68e3627b 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/NetworkingOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/NetworkingOptions.java @@ -14,20 +14,30 @@ */ package org.hyperledger.besu.cli.options.unstable; +import org.hyperledger.besu.cli.DefaultCommandValues; import org.hyperledger.besu.cli.options.CLIOptions; import org.hyperledger.besu.cli.options.OptionParser; import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; import java.util.Arrays; import java.util.List; +import java.util.Optional; import picocli.CommandLine; +/** The Networking Cli options. */ public class NetworkingOptions implements CLIOptions { + /** The constant PEER_LOWER_BOUND_FLAG */ + public static final String PEER_LOWER_BOUND_FLAG = "--Xp2p-peer-lower-bound"; + private final String INITIATE_CONNECTIONS_FREQUENCY_FLAG = "--Xp2p-initiate-connections-frequency"; private final String CHECK_MAINTAINED_CONNECTIONS_FREQUENCY_FLAG = "--Xp2p-check-maintained-connections-frequency"; + private final String DNS_DISCOVERY_SERVER_OVERRIDE_FLAG = "--Xp2p-dns-discovery-server"; + private final String DISCOVERY_PROTOCOL_V5_ENABLED = "--Xv5-discovery-enabled"; + /** The constant FILTER_ON_ENR_FORK_ID. */ + public static final String FILTER_ON_ENR_FORK_ID = "--Xfilter-on-enr-fork-id"; @CommandLine.Option( names = INITIATE_CONNECTIONS_FREQUENCY_FLAG, @@ -47,37 +57,92 @@ public class NetworkingOptions implements CLIOptions { description = "The frequency (in seconds) at which to check maintained connections (default: ${DEFAULT-VALUE})") private int checkMaintainedConnectionsFrequencySec = - NetworkingConfiguration.DEFAULT_CHECK_MAINTAINED_CONNECTSION_FREQUENCY_SEC; + NetworkingConfiguration.DEFAULT_CHECK_MAINTAINED_CONNECTIONS_FREQUENCY_SEC; + + @CommandLine.Option( + names = DNS_DISCOVERY_SERVER_OVERRIDE_FLAG, + hidden = true, + description = + "DNS server host to use for doing DNS Discovery of peers, rather than the machine's configured DNS server") + private Optional dnsDiscoveryServerOverride = Optional.empty(); + + @CommandLine.Option( + names = DISCOVERY_PROTOCOL_V5_ENABLED, + hidden = true, + defaultValue = "false", + description = "Whether to enable P2P Discovery Protocol v5 (default: ${DEFAULT-VALUE})") + private final Boolean isPeerDiscoveryV5Enabled = false; + + @CommandLine.Option( + names = FILTER_ON_ENR_FORK_ID, + hidden = true, + defaultValue = "false", + description = "Whether to enable filtering of peers based on the ENR field ForkId)") + private final Boolean filterOnEnrForkId = false; + + @CommandLine.Option( + hidden = true, + names = PEER_LOWER_BOUND_FLAG, + description = + "Lower bound on the target number of P2P connections (default: ${DEFAULT-VALUE})") + private Integer peerLowerBoundConfig = DefaultCommandValues.DEFAULT_P2P_PEER_LOWER_BOUND; private NetworkingOptions() {} + /** + * Create networking options. + * + * @return the networking options + */ public static NetworkingOptions create() { return new NetworkingOptions(); } + /** + * Create networking options from Networking Configuration. + * + * @param networkingConfig the networking config + * @return the networking options + */ public static NetworkingOptions fromConfig(final NetworkingConfiguration networkingConfig) { final NetworkingOptions cliOptions = new NetworkingOptions(); cliOptions.checkMaintainedConnectionsFrequencySec = networkingConfig.getCheckMaintainedConnectionsFrequencySec(); cliOptions.initiateConnectionsFrequencySec = networkingConfig.getInitiateConnectionsFrequencySec(); + cliOptions.dnsDiscoveryServerOverride = networkingConfig.getDnsDiscoveryServerOverride(); + cliOptions.peerLowerBoundConfig = networkingConfig.getPeerLowerBound(); + return cliOptions; } @Override public NetworkingConfiguration toDomainObject() { - NetworkingConfiguration config = NetworkingConfiguration.create(); + final NetworkingConfiguration config = NetworkingConfiguration.create(); config.setCheckMaintainedConnectionsFrequency(checkMaintainedConnectionsFrequencySec); config.setInitiateConnectionsFrequency(initiateConnectionsFrequencySec); + config.setDnsDiscoveryServerOverride(dnsDiscoveryServerOverride); + config.getDiscovery().setDiscoveryV5Enabled(isPeerDiscoveryV5Enabled); + config.getDiscovery().setFilterOnEnrForkId(filterOnEnrForkId); + config.setPeerLowerBound(peerLowerBoundConfig); return config; } @Override public List getCLIOptions() { - return Arrays.asList( - CHECK_MAINTAINED_CONNECTIONS_FREQUENCY_FLAG, - OptionParser.format(checkMaintainedConnectionsFrequencySec), - INITIATE_CONNECTIONS_FREQUENCY_FLAG, - OptionParser.format(initiateConnectionsFrequencySec)); + final List retval = + Arrays.asList( + CHECK_MAINTAINED_CONNECTIONS_FREQUENCY_FLAG, + OptionParser.format(checkMaintainedConnectionsFrequencySec), + INITIATE_CONNECTIONS_FREQUENCY_FLAG, + OptionParser.format(initiateConnectionsFrequencySec), + PEER_LOWER_BOUND_FLAG, + OptionParser.format((peerLowerBoundConfig))); + + if (dnsDiscoveryServerOverride.isPresent()) { + retval.add(DNS_DISCOVERY_SERVER_OVERRIDE_FLAG); + retval.add(dnsDiscoveryServerOverride.get()); + } + return retval; } } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/PkiBlockCreationOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/PkiBlockCreationOptions.java new file mode 100644 index 00000000000..e3673a1ab8e --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/PkiBlockCreationOptions.java @@ -0,0 +1,162 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.cli.options.unstable; + +import static java.util.Arrays.asList; +import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_FILE_FORMAT_HELP; + +import org.hyperledger.besu.cli.util.CommandLineUtils; +import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration; + +import java.nio.file.Path; +import java.util.Optional; + +import org.slf4j.Logger; +import picocli.CommandLine; +import picocli.CommandLine.Option; +import picocli.CommandLine.ParameterException; + +/** The Pki block creation Cli options. */ +public class PkiBlockCreationOptions { + + /** The pki block creation enabled. */ + @Option( + names = {"--Xpki-block-creation-enabled"}, + hidden = true, + description = "Enable PKI integration (default: ${DEFAULT-VALUE})") + Boolean enabled = false; + + /** The Key store type. */ + @Option( + names = {"--Xpki-block-creation-keystore-type"}, + hidden = true, + paramLabel = "", + description = "PKI service keystore type. Required if PKI Block Creation is enabled.") + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) + String keyStoreType = PkiKeyStoreConfiguration.DEFAULT_KEYSTORE_TYPE; + + /** The Key store file. */ + @Option( + names = {"--Xpki-block-creation-keystore-file"}, + hidden = true, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = "Keystore containing key/certificate for PKI Block Creation.") + Path keyStoreFile = null; + + /** The Key store password file. */ + @Option( + names = {"--Xpki-block-creation-keystore-password-file"}, + hidden = true, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = + "File containing password to unlock keystore for PKI Integration. Required if PKI Block Creation is enabled.") + Path keyStorePasswordFile = null; + + /** The Certificate alias. */ + @Option( + names = {"--Xpki-block-creation-keystore-certificate-alias"}, + hidden = true, + paramLabel = "", + description = + "Alias of the certificate that will be included in the blocks proposed by this validator.") + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) + String certificateAlias = PkiKeyStoreConfiguration.DEFAULT_CERTIFICATE_ALIAS; + + /** The Trust store type. */ + @Option( + names = {"--Xpki-block-creation-truststore-type"}, + hidden = true, + paramLabel = "", + description = "PKI Integration truststore type.") + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) + String trustStoreType = PkiKeyStoreConfiguration.DEFAULT_KEYSTORE_TYPE; + + /** The Trust store file. */ + @Option( + names = {"--Xpki-block-creation-truststore-file"}, + hidden = true, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = "Truststore containing trusted certificates for PKI Block Creation.") + Path trustStoreFile = null; + + /** The Trust store password file. */ + @Option( + names = {"--Xpki-block-creation-truststore-password-file"}, + hidden = true, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = "File containing password to unlock truststore for PKI Block Creation.") + Path trustStorePasswordFile = null; + + /** The Crl file. */ + @Option( + names = {"--Xpki-block-creation-crl-file"}, + hidden = true, + paramLabel = MANDATORY_FILE_FORMAT_HELP, + description = "File with all CRLs for PKI Block Creation.") + Path crlFile = null; + + /** + * As domain config optional. + * + * @param commandLine the command line + * @return the optional + */ + public Optional asDomainConfig(final CommandLine commandLine) { + if (!enabled) { + return Optional.empty(); + } + + if (keyStoreFile == null) { + throw new ParameterException( + commandLine, "KeyStore file is required when PKI Block Creation is enabled"); + } + + if (keyStorePasswordFile == null) { + throw new ParameterException( + commandLine, + "File containing password to unlock keystore is required when PKI Block Creation is enabled"); + } + + return Optional.of( + new PkiKeyStoreConfiguration.Builder() + .withKeyStoreType(keyStoreType) + .withKeyStorePath(keyStoreFile) + .withKeyStorePasswordPath(keyStorePasswordFile) + .withCertificateAlias(certificateAlias) + .withTrustStoreType(trustStoreType) + .withTrustStorePath(trustStoreFile) + .withTrustStorePasswordPath(trustStorePasswordFile) + .withCrlFilePath(crlFile) + .build()); + } + + /** + * Check pki block creation options dependencies. + * + * @param logger the logger + * @param commandLine the command line + */ + public void checkPkiBlockCreationOptionsDependencies( + final Logger logger, final CommandLine commandLine) { + CommandLineUtils.checkOptionDependencies( + logger, + commandLine, + "--Xpki-block-creation-enabled", + !enabled, + asList( + "--Xpki-block-creation-keystore-file", "--Xpki-block-creation-keystore-password-file")); + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/PrivacyPluginOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/PrivacyPluginOptions.java new file mode 100644 index 00000000000..212d810f9d7 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/PrivacyPluginOptions.java @@ -0,0 +1,46 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.cli.options.unstable; + +import static picocli.CommandLine.Option; + +/** The Privacy plugin Cli options. */ +public class PrivacyPluginOptions { + + /** + * Create privacy plugin options. + * + * @return the privacy plugin options + */ + public static PrivacyPluginOptions create() { + return new PrivacyPluginOptions(); + } + + @Option( + names = "--Xprivacy-plugin-enabled", + description = + "Enables the use of a plugin to implement your own privacy strategy (default: ${DEFAULT-VALUE})", + hidden = true) + private final Boolean isPrivacyPluginEnabled = false; + + /** + * Is privacy plugin enabled boolean. + * + * @return the boolean + */ + public boolean isPrivacyPluginEnabled() { + return isPrivacyPluginEnabled; + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/RPCOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/RPCOptions.java index 11a185efb6b..3cb23655a08 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/RPCOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/RPCOptions.java @@ -18,6 +18,7 @@ import picocli.CommandLine; +/** The Rpc Cli options. */ public class RPCOptions { @CommandLine.Option( @@ -34,14 +35,29 @@ public class RPCOptions { arity = "1") private final Long wsTimeoutSec = TimeoutOptions.defaultOptions().getTimeoutSeconds(); + /** + * Create rpc options. + * + * @return the rpc options + */ public static RPCOptions create() { return new RPCOptions(); } + /** + * Gets http timeout sec. + * + * @return the http timeout sec + */ public Long getHttpTimeoutSec() { return httpTimeoutSec; } + /** + * Gets WebSocket timeout sec. + * + * @return the WebSocket timeout sec + */ public Long getWsTimeoutSec() { return wsTimeoutSec; } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/SynchronizerOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/SynchronizerOptions.java index ed641dcf4f3..8760258fba2 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/SynchronizerOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/SynchronizerOptions.java @@ -17,6 +17,8 @@ import org.hyperledger.besu.cli.options.CLIOptions; import org.hyperledger.besu.cli.options.OptionParser; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; +import org.hyperledger.besu.ethereum.eth.sync.snapsync.ImmutableSnapSyncConfiguration; +import org.hyperledger.besu.ethereum.eth.sync.snapsync.SnapSyncConfiguration; import java.util.Arrays; import java.util.List; @@ -25,6 +27,7 @@ import org.apache.tuweni.units.bigints.UInt256; import picocli.CommandLine; +/** The Synchronizer Cli options. */ public class SynchronizerOptions implements CLIOptions { private static final String BLOCK_PROPAGATION_RANGE_FLAG = "--Xsynchronizer-block-propagation-range"; @@ -59,6 +62,33 @@ public class SynchronizerOptions implements CLIOptions