diff --git a/.github/workflows/node-flow-build-application.yaml b/.github/workflows/node-flow-build-application.yaml index 29be2347300f..827d256ac531 100644 --- a/.github/workflows/node-flow-build-application.yaml +++ b/.github/workflows/node-flow-build-application.yaml @@ -83,7 +83,11 @@ jobs: enable-unit-tests: ${{ github.event_name == 'push' || github.event.inputs.enable-unit-tests == 'true' }} enable-sonar-analysis: ${{ github.event_name == 'push' || github.event.inputs.enable-sonar-analysis == 'true' }} enable-integration-tests: ${{ github.event_name == 'push' || github.event.inputs.enable-integration-tests == 'true' }} - enable-hapi-tests: ${{ github.event_name == 'push' || github.event.inputs.enable-hapi-tests == 'true' }} + enable-hapi-tests-misc: ${{ github.event_name == 'push' || github.event.inputs.enable-hapi-tests == 'true' }} + enable-hapi-tests-crypto: ${{ github.event_name == 'push' || github.event.inputs.enable-hapi-tests == 'true' }} + enable-hapi-tests-token: ${{ github.event_name == 'push' || github.event.inputs.enable-hapi-tests == 'true' }} + enable-hapi-tests-smart-contract: ${{ github.event_name == 'push' || github.event.inputs.enable-hapi-tests == 'true' }} + enable-hapi-tests-time-consuming: ${{ github.event_name == 'push' || github.event.inputs.enable-hapi-tests == 'true' }} enable-e2e-tests: ${{ github.event_name == 'push' || github.event.inputs.enable-e2e-tests == 'true' }} enable-spotless-check: ${{ github.event.inputs.enable-spotless-check == 'true' }} enable-snyk-scan: ${{ github.event_name == 'push' || github.event.inputs.enable-snyk-scan == 'true' }} diff --git a/.github/workflows/node-flow-pull-request-checks.yaml b/.github/workflows/node-flow-pull-request-checks.yaml index d879c4d48cdc..5264edab2cb7 100644 --- a/.github/workflows/node-flow-pull-request-checks.yaml +++ b/.github/workflows/node-flow-pull-request-checks.yaml @@ -50,7 +50,6 @@ jobs: enable-unit-tests: false enable-e2e-tests: false enable-integration-tests: false - enable-hapi-tests: false enable-sonar-analysis: false enable-spotless-check: true secrets: @@ -66,7 +65,6 @@ jobs: enable-unit-tests: true enable-e2e-tests: false enable-integration-tests: false - enable-hapi-tests: false enable-sonar-analysis: false secrets: access-token: ${{ secrets.GITHUB_TOKEN }} @@ -82,7 +80,6 @@ jobs: enable-unit-tests: false enable-e2e-tests: true enable-integration-tests: false - enable-hapi-tests: false enable-sonar-analysis: false enable-network-log-capture: true secrets: @@ -99,7 +96,6 @@ jobs: enable-unit-tests: false enable-e2e-tests: false enable-integration-tests: true - enable-hapi-tests: false enable-sonar-analysis: false enable-network-log-capture: true secrets: @@ -108,15 +104,83 @@ jobs: gradle-cache-password: ${{ secrets.GRADLE_CACHE_PASSWORD }} sonar-token: ${{ secrets.SONAR_TOKEN }} - hapi-tests: - name: HAPI Tests + hapi-tests-misc: + name: HAPI Tests (Misc) uses: ./.github/workflows/node-zxc-compile-application-code.yaml with: custom-job-label: Standard enable-unit-tests: false enable-e2e-tests: false enable-integration-tests: false - enable-hapi-tests: true + enable-hapi-tests-misc: true + enable-sonar-analysis: false + enable-network-log-capture: true + secrets: + access-token: ${{ secrets.GITHUB_TOKEN }} + gradle-cache-username: ${{ secrets.GRADLE_CACHE_USERNAME }} + gradle-cache-password: ${{ secrets.GRADLE_CACHE_PASSWORD }} + sonar-token: ${{ secrets.SONAR_TOKEN }} + + hapi-tests-crypto: + name: HAPI Tests (Crypto) + uses: ./.github/workflows/node-zxc-compile-application-code.yaml + with: + custom-job-label: Standard + enable-unit-tests: false + enable-e2e-tests: false + enable-integration-tests: false + enable-hapi-tests-crypto: true + enable-sonar-analysis: false + enable-network-log-capture: true + secrets: + access-token: ${{ secrets.GITHUB_TOKEN }} + gradle-cache-username: ${{ secrets.GRADLE_CACHE_USERNAME }} + gradle-cache-password: ${{ secrets.GRADLE_CACHE_PASSWORD }} + sonar-token: ${{ secrets.SONAR_TOKEN }} + + hapi-tests-token: + name: HAPI Tests (Token) + uses: ./.github/workflows/node-zxc-compile-application-code.yaml + with: + custom-job-label: Standard + enable-unit-tests: false + enable-e2e-tests: false + enable-integration-tests: false + enable-hapi-tests-token: true + enable-sonar-analysis: false + enable-network-log-capture: true + secrets: + access-token: ${{ secrets.GITHUB_TOKEN }} + gradle-cache-username: ${{ secrets.GRADLE_CACHE_USERNAME }} + gradle-cache-password: ${{ secrets.GRADLE_CACHE_PASSWORD }} + sonar-token: ${{ secrets.SONAR_TOKEN }} + + hapi-tests-smart-contract: + name: HAPI Tests (Smart Contract) + uses: ./.github/workflows/node-zxc-compile-application-code.yaml + with: + custom-job-label: Standard + enable-unit-tests: false + enable-e2e-tests: false + enable-integration-tests: false + enable-hapi-tests-smart-contract: true + enable-sonar-analysis: false + enable-network-log-capture: true + secrets: + access-token: ${{ secrets.GITHUB_TOKEN }} + gradle-cache-username: ${{ secrets.GRADLE_CACHE_USERNAME }} + gradle-cache-password: ${{ secrets.GRADLE_CACHE_PASSWORD }} + sonar-token: ${{ secrets.SONAR_TOKEN }} + + hapi-tests-time-consuming: + name: HAPI Tests (Time Consuming) + uses: ./.github/workflows/node-zxc-compile-application-code.yaml + with: + custom-job-label: Standard + enable-unit-tests: false + enable-e2e-tests: false + enable-integration-tests: false + enable-hapi-tests-time-consuming: true enable-sonar-analysis: false enable-network-log-capture: true secrets: @@ -144,6 +208,7 @@ jobs: gcp-project-number: ${{ secrets.PLATFORM_GCP_PROJECT_NUMBER }} gcp-sa-key-contents: ${{ secrets.PLATFORM_GCP_KEY_FILE }} slack-api-token: ${{ secrets.PLATFORM_SLACK_API_TOKEN }} + snyk-scan: name: Snyk Scan uses: ./.github/workflows/node-zxc-compile-application-code.yaml @@ -152,7 +217,6 @@ jobs: enable-unit-tests: false enable-e2e-tests: false enable-integration-tests: false - enable-hapi-tests: false enable-sonar-analysis: false enable-snyk-scan: true secrets: diff --git a/.github/workflows/node-zxc-build-release-artifact.yaml b/.github/workflows/node-zxc-build-release-artifact.yaml index bd59d11a024c..17e185ea365b 100644 --- a/.github/workflows/node-zxc-build-release-artifact.yaml +++ b/.github/workflows/node-zxc-build-release-artifact.yaml @@ -259,7 +259,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Authenticate to Google Cloud - uses: google-github-actions/auth@35b0e87d162680511bf346c299f71c9c5c379033 # v1.1.1 + uses: google-github-actions/auth@f105ef0cdb3b102a020be1767fcc8a974898b7c6 # v1.2.0 if: ${{ inputs.dry-run-enabled != true && !cancelled() && !failure() }} with: workload_identity_provider: "projects/235822363393/locations/global/workloadIdentityPools/hedera-builds-pool/providers/hedera-builds-gh-actions" @@ -370,7 +370,7 @@ jobs: - name: Notify Jenkins of Release (Integration) id: jenkins-integration - uses: fjogeleit/http-request-action@eab8015483ccea148feff7b1c65f320805ddc2bf # v1.14.1 + uses: fjogeleit/http-request-action@25a5a55111f57b7eeaaff0ba0c6a457ce1895b90 # v1.14.2 if: ${{ inputs.dry-run-enabled != true && inputs.trigger-env-deploy == 'integration' && !cancelled() && !failure() }} with: url: ${{ secrets.jenkins-integration-url }} @@ -414,7 +414,7 @@ jobs: - name: Authenticate to Google Cloud id: google-auth - uses: google-github-actions/auth@35b0e87d162680511bf346c299f71c9c5c379033 # v1.1.1 + uses: google-github-actions/auth@f105ef0cdb3b102a020be1767fcc8a974898b7c6 # v1.2.0 if: ${{ inputs.dry-run-enabled != true && !cancelled() && !failure() }} with: token_format: 'access_token' @@ -470,7 +470,7 @@ jobs: cp -rvf ~/artifact-build/* hedera-node/infrastructure/docker/containers/local-node/main-network-node/sdk/ - name: Build Haveged Image - uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 with: push: true platforms: linux/amd64,linux/arm64 @@ -478,7 +478,7 @@ jobs: tags: ${{ steps.set-registry.outputs.docker-tag-base }}/network-node-haveged:${{ needs.validate.outputs.version }} - name: Build Base Image - uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 with: push: true platforms: linux/amd64,linux/arm64 @@ -486,7 +486,7 @@ jobs: tags: ${{ steps.set-registry.outputs.docker-tag-base }}/network-node-base:${{ needs.validate.outputs.version }} - name: Build Network Node Image - uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 with: push: true platforms: linux/amd64,linux/arm64 @@ -610,7 +610,7 @@ jobs: OSSRH_PASSWORD: ${{ secrets.svcs-ossrh-password }} with: gradle-version: ${{ inputs.gradle-version }} - arguments: "releaseEvmMavenCentral --scan -PpublishSigningEnabled=true" + arguments: "releaseEvmMavenCentral --scan -PpublishSigningEnabled=true --no-configuration-cache --no-parallel" - name: Gradle Maven Central Snapshot uses: gradle/gradle-build-action@842c587ad8aa4c68eeba24c396e15af4c2e9f30a # v2.9.0 @@ -620,7 +620,7 @@ jobs: OSSRH_PASSWORD: ${{ secrets.svcs-ossrh-password }} with: gradle-version: ${{ inputs.gradle-version }} - arguments: "releaseEvmMavenCentralSnapshot --scan -PpublishSigningEnabled=true" + arguments: "releaseEvmMavenCentralSnapshot --scan -PpublishSigningEnabled=true --no-configuration-cache --no-parallel" sdk-publish: name: Publish Platform to ${{ inputs.version-policy == 'specified' && 'Maven Central' || 'GCP Registry' }} @@ -657,7 +657,7 @@ jobs: - name: Authenticate to Google Cloud id: google-auth - uses: google-github-actions/auth@35b0e87d162680511bf346c299f71c9c5c379033 # v1.1.1 + uses: google-github-actions/auth@f105ef0cdb3b102a020be1767fcc8a974898b7c6 # v1.2.0 with: workload_identity_provider: "projects/229164983194/locations/global/workloadIdentityPools/registry-identity-pool/providers/gh-provider" service_account: "artifact-deployer@swirlds-registry.iam.gserviceaccount.com" @@ -776,7 +776,7 @@ jobs: OSSRH_PASSWORD: ${{ secrets.sdk-ossrh-password }} with: gradle-version: ${{ inputs.gradle-version }} - arguments: "release${{ inputs.sdk-release-profile }} --scan -PpublishSigningEnabled=true --no-configuration-cache" + arguments: "release${{ inputs.sdk-release-profile }} --scan -PpublishSigningEnabled=true --no-configuration-cache --no-parallel" - name: Upload SDK Release Archives if: ${{ inputs.dry-run-enabled != true && inputs.version-policy == 'specified' && !cancelled() && !failure() }} diff --git a/.github/workflows/node-zxc-compile-application-code.yaml b/.github/workflows/node-zxc-compile-application-code.yaml index f19a7763de24..6b2bee122285 100644 --- a/.github/workflows/node-zxc-compile-application-code.yaml +++ b/.github/workflows/node-zxc-compile-application-code.yaml @@ -33,8 +33,28 @@ on: type: boolean required: false default: false - enable-hapi-tests: - description: "HAPI Testing Enabled" + enable-hapi-tests-misc: + description: "HAPI Testing (misc) Enabled" + type: boolean + required: false + default: false + enable-hapi-tests-crypto: + description: "HAPI Testing (crypto) Enabled" + type: boolean + required: false + default: false + enable-hapi-tests-token: + description: "HAPI Testing (token) Enabled" + type: boolean + required: false + default: false + enable-hapi-tests-smart-contract: + description: "HAPI Testing (smart contract) Enabled" + type: boolean + required: false + default: false + enable-hapi-tests-time-consuming: + description: "HAPI Testing (time consuming) Enabled" type: boolean required: false default: false @@ -115,6 +135,8 @@ permissions: env: GRADLE_CACHE_USERNAME: ${{ secrets.gradle-cache-username }} GRADLE_CACHE_PASSWORD: ${{ secrets.gradle-cache-password }} + GRADLE_EXEC: cgexec -g cpu,memory:gradle-${{ github.run_id }} --sticky ionice -c 2 -n 2 nice -n 19 ./gradlew + CG_EXEC: cgexec -g cpu,memory:gradle-${{ github.run_id }} --sticky ionice -c 2 -n 2 nice -n 19 jobs: compile: @@ -136,28 +158,68 @@ jobs: - name: Setup Gradle uses: gradle/gradle-build-action@842c587ad8aa4c68eeba24c396e15af4c2e9f30a # v2.9.0 + with: + gradle-home-cache-cleanup: true + cache-read-only: false - name: Setup NodeJS uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: node-version: ${{ inputs.node-version }} + - name: Setup Control Groups + run: | + echo "::group::Get System Configuration" + USR_ID="$(id -un)" + GRP_ID="$(id -gn)" + GRADLE_MEM_LIMIT="30064771072" + AGENT_MEM_LIMIT="2147483648" + GRADLE_GROUP_NAME="gradle-${{ github.run_id }}" + AGENT_GROUP_NAME="agent-${{ github.run_id }}" + echo "::endgroup::" + + echo "::group::Install Control Group Tools" + if ! command -v cgcreate >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y cgroup-tools + fi + echo "::endgroup::" + + echo "::group::Create Control Groups" + sudo cgcreate -g cpu,memory:${GRADLE_GROUP_NAME} -a ${USR_ID}:${GRP_ID} -t ${USR_ID}:${GRP_ID} + sudo cgcreate -g cpu,memory:${AGENT_GROUP_NAME} -a ${USR_ID}:${GRP_ID} -t ${USR_ID}:${GRP_ID} + echo "::endgroup::" + + echo "::group::Set Control Group Limits" + cgset -r cpu.shares=768 ${GRADLE_GROUP_NAME} + cgset -r cpu.shares=500 ${AGENT_GROUP_NAME} + cgset -r memory.limit_in_bytes=${GRADLE_MEM_LIMIT} ${GRADLE_GROUP_NAME} + cgset -r memory.limit_in_bytes=${AGENT_MEM_LIMIT} ${AGENT_GROUP_NAME} + cgset -r memory.memsw.limit_in_bytes=${GRADLE_MEM_LIMIT} ${GRADLE_GROUP_NAME} + cgset -r memory.memsw.limit_in_bytes=${AGENT_MEM_LIMIT} ${AGENT_GROUP_NAME} + echo "::endgroup::" + + echo "::group::Move Runner Processes to Control Groups" + sudo cgclassify --sticky -g cpu,memory:${AGENT_GROUP_NAME} $(pgrep 'Runner.Listener' | tr '\n' ' ') + sudo cgclassify -g cpu,memory:${AGENT_GROUP_NAME} $(pgrep 'Runner.Worker' | tr '\n' ' ') + echo "::endgroup::" + - name: Compile id: gradle-build - run: ionice -c 2 -n 2 nice -n 19 ./gradlew assemble --scan --no-daemon + run: ${GRADLE_EXEC} assemble --scan --no-daemon - name: Spotless Check if: ${{ inputs.enable-spotless-check && !cancelled() }} - run: ionice -c 2 -n 2 nice -n 19 ./gradlew spotlessCheck --scan --no-daemon + run: ${GRADLE_EXEC} spotlessCheck --scan --no-daemon - name: Gradle Dependency Scopes Check if: ${{ inputs.enable-dependency-check && steps.gradle-build.conclusion == 'success' && !cancelled() }} - run: ionice -c 2 -n 2 nice -n 19 ./gradlew checkAllModuleInfo --scan --continue --no-daemon + run: ${GRADLE_EXEC} checkAllModuleInfo --scan --continue --no-daemon - name: Unit Testing id: gradle-test if: ${{ inputs.enable-unit-tests && steps.gradle-build.conclusion == 'success' && !cancelled() }} - run: ionice -c 2 -n 2 nice -n 19 ./gradlew check --continue --scan --no-daemon + run: ${GRADLE_EXEC} check --continue --scan --no-daemon - name: Publish Unit Test Report uses: actionite/publish-unit-test-result-action@1e01e49081c6c4073913aa4b7980fa83e709f322 # v2.3.0 @@ -176,12 +238,12 @@ jobs: - name: Build Docker Image # build the image for hedera-node if: ${{ (inputs.enable-integration-tests || inputs.enable-e2e-tests) && steps.gradle-build.conclusion == 'success' && !cancelled() }} - run: ionice -c 2 -n 2 nice -n 19 ./gradlew createDockerImage --scan --no-daemon + run: ${GRADLE_EXEC} createDockerImage --scan --no-daemon - name: Integration Testing id: gradle-itest if: ${{ inputs.enable-integration-tests && steps.gradle-build.conclusion == 'success' && !cancelled() }} - run: ionice -c 2 -n 2 nice -n 19 ./gradlew itest --scan --no-daemon + run: ${GRADLE_EXEC} itest --scan --no-daemon - name: Publish Integration Test Report uses: actionite/publish-unit-test-result-action@1e01e49081c6c4073913aa4b7980fa83e709f322 # v2.3.0 @@ -200,35 +262,135 @@ jobs: path: | hedera-node/test-clients/build/network/itest/output/** - - name: HAPI Testing - id: gradle-hapiTest - if: ${{ inputs.enable-hapi-tests && steps.gradle-build.conclusion == 'success' && !cancelled() }} + - name: HAPI Testing (Misc) + id: gradle-hapi-misc + if: ${{ inputs.enable-hapi-tests-misc && steps.gradle-build.conclusion == 'success' && !cancelled() }} env: LC_ALL: en.UTF-8 LANG: en_US.UTF-8 - run: ionice -c 2 -n 2 nice -n 19 ./gradlew hapiTest -Dfile.encoding=UTF-8 --scan --no-daemon + run: ${GRADLE_EXEC} hapiTestMisc -Dfile.encoding=UTF-8 --scan --no-daemon - - name: Publish HAPI Test Report + - name: Publish HAPI Test (Misc) Report uses: actionite/publish-unit-test-result-action@1e01e49081c6c4073913aa4b7980fa83e709f322 # v2.3.0 - if: ${{ inputs.enable-hapi-tests && steps.gradle-build.conclusion == 'success' && !cancelled() }} + if: ${{ inputs.enable-hapi-tests-misc && steps.gradle-build.conclusion == 'success' && !cancelled() }} with: - check_name: 'Node: HAPI Test Results' + check_name: 'Node: HAPI Test (Misc) Results' check_run_disabled: false json_thousands_separator: ',' - junit_files: "**/build/test-results/hapiTest/TEST-*.xml" + junit_files: "**/build/test-results/hapiTestMisc/TEST-*.xml" - - name: Publish HAPI Test Network Logs + - name: Publish HAPI Test (Misc) Network Logs uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 - if: ${{ inputs.enable-hapi-tests && inputs.enable-network-log-capture && !cancelled() }} + if: ${{ inputs.enable-hapi-tests-misc && inputs.enable-network-log-capture && !cancelled() }} with: - name: HAPI Test Network Logs + name: HAPI Test (Misc) Network Logs + path: | + hedera-node/test-clients/build/hapi-test/**/output/** + + - name: HAPI Testing (Crypto) + id: gradle-hapi-crypto + if: ${{ inputs.enable-hapi-tests-crypto && steps.gradle-build.conclusion == 'success' && !cancelled() }} + env: + LC_ALL: en.UTF-8 + LANG: en_US.UTF-8 + run: ${GRADLE_EXEC} hapiTestCrypto -Dfile.encoding=UTF-8 --scan --no-daemon + + - name: Publish HAPI Test (Crypto) Report + uses: actionite/publish-unit-test-result-action@1e01e49081c6c4073913aa4b7980fa83e709f322 # v2.3.0 + if: ${{ inputs.enable-hapi-tests-crypto && steps.gradle-build.conclusion == 'success' && !cancelled() }} + with: + check_name: 'Node: HAPI Test (Crypto) Results' + check_run_disabled: false + json_thousands_separator: ',' + junit_files: "**/build/test-results/hapiTestCrypto/TEST-*.xml" + + - name: Publish HAPI Test (crypto) Network Logs + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + if: ${{ inputs.enable-hapi-tests-crypto && inputs.enable-network-log-capture && !cancelled() }} + with: + name: HAPI Test (Crypto) Network Logs + path: | + hedera-node/test-clients/build/hapi-test/**/output/** + + - name: HAPI Testing (Token) + id: gradle-hapi-token + if: ${{ inputs.enable-hapi-tests-token && steps.gradle-build.conclusion == 'success' && !cancelled() }} + env: + LC_ALL: en.UTF-8 + LANG: en_US.UTF-8 + run: ${GRADLE_EXEC} hapiTestToken -Dfile.encoding=UTF-8 --scan --no-daemon + + - name: Publish HAPI Test (Token) Report + uses: actionite/publish-unit-test-result-action@1e01e49081c6c4073913aa4b7980fa83e709f322 # v2.3.0 + if: ${{ inputs.enable-hapi-tests-token && steps.gradle-build.conclusion == 'success' && !cancelled() }} + with: + check_name: 'Node: HAPI Test (Token) Results' + check_run_disabled: false + json_thousands_separator: ',' + junit_files: "**/build/test-results/hapiTestToken/TEST-*.xml" + + - name: Publish HAPI Test (Token) Network Logs + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + if: ${{ inputs.enable-hapi-tests-token && inputs.enable-network-log-capture && !cancelled() }} + with: + name: HAPI Test (Token) Network Logs + path: | + hedera-node/test-clients/build/hapi-test/**/output/** + + - name: HAPI Testing (Smart Contract) + id: gradle-hapi-smart-contract + if: ${{ inputs.enable-hapi-tests-smart-contract && steps.gradle-build.conclusion == 'success' && !cancelled() }} + env: + LC_ALL: en.UTF-8 + LANG: en_US.UTF-8 + run: ${GRADLE_EXEC} hapiTestSmartContract -Dfile.encoding=UTF-8 --scan --no-daemon + + - name: Publish HAPI Test (Smart Contract) Report + uses: actionite/publish-unit-test-result-action@1e01e49081c6c4073913aa4b7980fa83e709f322 # v2.3.0 + if: ${{ inputs.enable-hapi-tests-smart-contract && steps.gradle-build.conclusion == 'success' && !cancelled() }} + with: + check_name: 'Node: HAPI Test (Smart Contract) Results' + check_run_disabled: false + json_thousands_separator: ',' + junit_files: "**/build/test-results/hapiTestSmartContract/TEST-*.xml" + + - name: Publish HAPI Test (Smart Contract) Network Logs + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + if: ${{ inputs.enable-hapi-tests-smart-contract && inputs.enable-network-log-capture && !cancelled() }} + with: + name: HAPI Test (Smart Contract) Network Logs + path: | + hedera-node/test-clients/build/hapi-test/**/output/** + + - name: HAPI Testing (Time Consuming) + id: gradle-hapi-time-consuming + if: ${{ inputs.enable-hapi-tests-time-consuming && steps.gradle-build.conclusion == 'success' && !cancelled() }} + env: + LC_ALL: en.UTF-8 + LANG: en_US.UTF-8 + run: ${GRADLE_EXEC} hapiTestTimeConsuming -Dfile.encoding=UTF-8 --scan --no-daemon + + - name: Publish HAPI Test (Time Consuming) Report + uses: actionite/publish-unit-test-result-action@1e01e49081c6c4073913aa4b7980fa83e709f322 # v2.3.0 + if: ${{ inputs.enable-hapi-tests-time-consuming && steps.gradle-build.conclusion == 'success' && !cancelled() }} + with: + check_name: 'Node: HAPI Test (Time Consuming) Results' + check_run_disabled: false + json_thousands_separator: ',' + junit_files: "**/build/test-results/hapiTestTimeConsuming/TEST-*.xml" + + - name: Publish HAPI Test (Time Consuming) Network Logs + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + if: ${{ inputs.enable-hapi-tests-time-consuming && inputs.enable-network-log-capture && !cancelled() }} + with: + name: HAPI Test (Time Consuming) Network Logs path: | hedera-node/test-clients/build/hapi-test/**/output/** - name: E2E Testing id: gradle-eet if: ${{ inputs.enable-e2e-tests && steps.gradle-build.conclusion == 'success' && !cancelled() }} - run: ionice -c 2 -n 2 nice -n 19 ./gradlew eet --scan --no-daemon + run: ${GRADLE_EXEC} eet --scan --no-daemon - name: Publish E2E Test Report uses: actionite/publish-unit-test-result-action@1e01e49081c6c4073913aa4b7980fa83e709f322 # v2.3.0 @@ -282,11 +444,9 @@ jobs: echo "options=${SONAR_OPTS}" >> "${GITHUB_OUTPUT}" - name: SonarCloud Scan - uses: gradle/gradle-build-action@842c587ad8aa4c68eeba24c396e15af4c2e9f30a # v2.9.0 env: GITHUB_TOKEN: ${{ secrets.access-token }} SONAR_TOKEN: ${{ secrets.sonar-token }} - SONAR_OPTS: ${{ steps.sonar-cloud.outputs.options }} if: >- ${{ inputs.enable-sonar-analysis && @@ -298,9 +458,7 @@ jobs: ) && !cancelled() }} - with: - gradle-version: ${{ inputs.gradle-version }} - arguments: sonar --info --scan --no-parallel ${{ steps.sonar-cloud.outputs.options }} + run: ${GRADLE_EXEC} sonar --info --scan --no-parallel ${{ steps.sonar-cloud.outputs.options }} - name: Setup Snyk env: @@ -316,7 +474,7 @@ jobs: ) && !cancelled() }} - run: npm install -g snyk snyk-to-html @wcj/html-to-markdown-cli + run: ${CG_EXEC} npm install -g snyk snyk-to-html @wcj/html-to-markdown-cli - name: Snyk Scan id: snyk @@ -333,7 +491,7 @@ jobs: ) && !cancelled() }} - run: ionice -c 2 -n 2 nice -n 19 snyk test --all-sub-projects --severity-threshold=high --json-file-output=snyk-test.json + run: ${CG_EXEC} snyk test --all-sub-projects --severity-threshold=high --json-file-output=snyk-test.json - name: Snyk Code id: snyk-code @@ -350,7 +508,7 @@ jobs: ) && !cancelled() }} - run: ionice -c 2 -n 2 nice -n 19 snyk code test --severity-threshold=high --json-file-output=snyk-code.json + run: ${CG_EXEC} snyk code test --severity-threshold=high --json-file-output=snyk-code.json - name: Publish Snyk Results if: >- diff --git a/.github/workflows/node-zxc-deploy-preview.yaml b/.github/workflows/node-zxc-deploy-preview.yaml index 545ef90464ca..96f4a7a24fc9 100644 --- a/.github/workflows/node-zxc-deploy-preview.yaml +++ b/.github/workflows/node-zxc-deploy-preview.yaml @@ -112,7 +112,7 @@ jobs: fi - name: Authenticate to Google Cloud - uses: google-github-actions/auth@35b0e87d162680511bf346c299f71c9c5c379033 # v1.1.1 + uses: google-github-actions/auth@f105ef0cdb3b102a020be1767fcc8a974898b7c6 # v1.2.0 if: ${{ inputs.dry-run-enabled != true && !cancelled() && !failure() }} with: workload_identity_provider: "projects/235822363393/locations/global/workloadIdentityPools/hedera-builds-pool/providers/hedera-builds-gh-actions" @@ -135,9 +135,9 @@ jobs: PRE_JSON_REQUEST: ${{ toJSON(github.event) }} run: echo "request=$(jq --compact-output '.ref = "v${{ inputs.new-version }}"' <<<"${PRE_JSON_REQUEST}")" >>"${GITHUB_OUTPUT}" - - name: Notify Jenkins of Release (Preview) + - name: Notify Jenkins of Release (Preview Network) id: jenkins-preview - uses: fjogeleit/http-request-action@eab8015483ccea148feff7b1c65f320805ddc2bf # v1.14.1 + uses: fjogeleit/http-request-action@25a5a55111f57b7eeaaff0ba0c6a457ce1895b90 # v1.14.2 if: ${{ inputs.dry-run-enabled != true && !cancelled() && !failure() }} with: url: ${{ secrets.jenkins-preview-url }} @@ -150,13 +150,13 @@ jobs: jq '.' <<<"${JSON_RESPONSE}" printf "### Jenkins Response Payload\n\`\`\`json\n%s\n\`\`\`\n" "$(jq '.' <<<"${JSON_RESPONSE}")" >>"${GITHUB_STEP_SUMMARY}" - - name: Check for Jenkins Failures (Preview) + - name: Check for Jenkins Failures (Preview Network) env: JSON_RESPONSE: ${{ steps.jenkins-preview.outputs.response }} run: | - PREVIEW_TRIGGERED="$(jq '.jobs."build-preview-testnet".triggered' <<<"${JSON_RESPONSE}")" + PREVIEW_TRIGGERED="$(jq '.jobs."build-previewnet".triggered' <<<"${JSON_RESPONSE}")" if [[ "${PREVIEW_TRIGGERED}" != true ]]; then - echo "::error title=Jenkins Trigger Failure::Failed to trigger the 'build-preview-testnet' job via the Jenkins 'preview' pipeline!" + echo "::error title=Jenkins Trigger Failure::Failed to trigger the 'build-previewnet' pipeline in Jenkins!" exit 1 fi diff --git a/.github/workflows/node-zxcron-release-branching.yaml b/.github/workflows/node-zxcron-release-branching.yaml index c4a95905e98a..6fcc1c4a74a3 100644 --- a/.github/workflows/node-zxcron-release-branching.yaml +++ b/.github/workflows/node-zxcron-release-branching.yaml @@ -45,7 +45,7 @@ jobs: - name: Read Trigger Time id: time - uses: mikefarah/yq@a198f72367ce9da70b564a2cc25399de8e27bf37 # v4.35.2 + uses: mikefarah/yq@1cf9ecc79df9cabe69ae75a0bbfa7df7f9fe8a2f # v4.40.2 with: cmd: yq '.release.branching.execution.time' '${{ env.WORKFLOW_CONFIG_FILE }}' diff --git a/.github/workflows/zxc-jrs-regression.yaml b/.github/workflows/zxc-jrs-regression.yaml index 13d016f44cf7..89455c8c1de2 100644 --- a/.github/workflows/zxc-jrs-regression.yaml +++ b/.github/workflows/zxc-jrs-regression.yaml @@ -279,7 +279,7 @@ jobs: - name: Authenticate to Google Cloud id: google-auth - uses: google-github-actions/auth@35b0e87d162680511bf346c299f71c9c5c379033 # v1.1.1 + uses: google-github-actions/auth@f105ef0cdb3b102a020be1767fcc8a974898b7c6 # v1.2.0 with: workload_identity_provider: 'projects/785813846068/locations/global/workloadIdentityPools/jrs-identity-pool/providers/gh-provider' service_account: 'swirlds-automation@swirlds-regression.iam.gserviceaccount.com' diff --git a/.gitignore b/.gitignore index 21402c65beff..cfd36a749071 100644 --- a/.gitignore +++ b/.gitignore @@ -1078,3 +1078,6 @@ hedera-node/hapi/checkouts.bin ### CI Pipeline Created Files gha-creds-*.json +/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/*.interp +/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/*.tokens + diff --git a/build-logic/project-plugins/build.gradle.kts b/build-logic/project-plugins/build.gradle.kts index 7731bfeae395..2b1a1da74fcd 100644 --- a/build-logic/project-plugins/build.gradle.kts +++ b/build-logic/project-plugins/build.gradle.kts @@ -22,7 +22,7 @@ plugins { dependencies { implementation("com.adarshr:gradle-test-logger-plugin:4.0.0") - implementation("com.autonomousapps:dependency-analysis-gradle-plugin:1.25.0") + implementation("com.autonomousapps:dependency-analysis-gradle-plugin:1.26.0") implementation("com.diffplug.spotless:spotless-plugin-gradle:6.22.0") implementation("com.github.johnrengelman:shadow:8.1.1") implementation("com.google.protobuf:protobuf-gradle-plugin:0.9.4") @@ -31,7 +31,7 @@ dependencies { ) implementation("me.champeau.jmh:jmh-gradle-plugin:0.7.2") implementation("net.swiftzer.semver:semver:1.3.0") - implementation("org.gradlex:extra-java-module-info:1.5") + implementation("org.gradlex:extra-java-module-info:1.6") implementation("org.gradlex:java-ecosystem-capabilities:1.3.1") implementation("org.gradlex:java-module-dependencies:1.4.1") implementation("org.owasp:dependency-check-gradle:8.4.2") diff --git a/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.conventions.gradle.kts b/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.conventions.gradle.kts index 49f9ec475d6c..e820a3607b59 100644 --- a/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.conventions.gradle.kts +++ b/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.conventions.gradle.kts @@ -44,6 +44,9 @@ testing { // directly, it doesn't force "test" to run. shouldRunAfter(tasks.test) + maxHeapSize = "8g" + jvmArgs("-XX:ActiveProcessorCount=6") + addTestListener( object : TestListener { override fun beforeSuite(suite: TestDescriptor) { @@ -84,6 +87,9 @@ testing { // concurrently, that "test" completes first. If you run "eet" // directly, it doesn't force "test" to run. shouldRunAfter(tasks.test) + + maxHeapSize = "8g" + jvmArgs("-XX:ActiveProcessorCount=6") } } } @@ -98,6 +104,9 @@ testing { // concurrently, that "test" completes first. If you run "xtest" // directly, it doesn't force "test" to run. shouldRunAfter(tasks.test) + + maxHeapSize = "8g" + jvmArgs("-XX:ActiveProcessorCount=7") } } } diff --git a/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.java.gradle.kts b/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.java.gradle.kts index 9eb5d7b57fd9..39d2f0461be5 100644 --- a/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.java.gradle.kts +++ b/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.java.gradle.kts @@ -140,7 +140,7 @@ testing { } // Increase the heap size for the unit tests maxHeapSize = "4096m" - jvmArgs("-XX:ActiveProcessorCount=16") + jvmArgs("-XX:ActiveProcessorCount=7") // Can be useful to set in some cases // testLogging.showStandardStreams = true } @@ -159,7 +159,7 @@ testing { useJUnitPlatform { includeTags("HAMMER") } maxHeapSize = "8g" - jvmArgs("-XX:ActiveProcessorCount=16") + jvmArgs("-XX:ActiveProcessorCount=7") } tasks.register("performanceTest") { @@ -175,7 +175,7 @@ testing { setForkEvery(1) minHeapSize = "2g" maxHeapSize = "16g" - jvmArgs("-XX:ActiveProcessorCount=16", "-XX:+UseZGC") + jvmArgs("-XX:ActiveProcessorCount=7", "-XX:+UseZGC") } } } diff --git a/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.jpms-module-dependencies.gradle.kts b/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.jpms-module-dependencies.gradle.kts index 2a5cdea62563..b23c2ca3e9e2 100644 --- a/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.jpms-module-dependencies.gradle.kts +++ b/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.jpms-module-dependencies.gradle.kts @@ -54,6 +54,8 @@ javaModuleDependencies { ) // Testing only + moduleNameToGA.put("com.google.protobuf.util", "com.google.protobuf:protobuf-java-util") + moduleNameToGA.put("org.hamcrest", "org.hamcrest:hamcrest") moduleNameToGA.put("org.mockito.junit.jupiter", "org.mockito:mockito-junit-jupiter") moduleNameToGA.put("org.objenesis", "org.objenesis:objenesis") } diff --git a/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.jpms-modules.gradle.kts b/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.jpms-modules.gradle.kts index 96bfabe0a668..273c2ece0eb7 100644 --- a/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.jpms-modules.gradle.kts +++ b/build-logic/project-plugins/src/main/kotlin/com.hedera.hashgraph.jpms-modules.gradle.kts @@ -89,7 +89,9 @@ extraJavaModuleInfo { } module("com.google.guava:guava", "com.google.common") { exportAllPackages() - requireAllDefinedDependencies() + // requireAllDefinedDependencies() <- Currently not possible due to a Gradlex plugin + // limitation + requires("com.google.guava.failureaccess") requires("java.logging") } module("com.google.guava:failureaccess", "com.google.guava.failureaccess") { @@ -212,11 +214,7 @@ extraJavaModuleInfo { exportAllPackages() // no dependencies } - module("org.yaml:snakeyaml", "org.yaml.snakeyaml") { - exportAllPackages() - // no dependencies - } - module("org.hyperledger.besu.internal:algorithms", "org.hyperledger.besu.internal.algorithms") { + module("org.hyperledger.besu.internal:algorithms", "org.hyperledger.besu.internal.crypto") { exportAllPackages() requireAllDefinedDependencies() } @@ -224,15 +222,15 @@ extraJavaModuleInfo { exportAllPackages() requireAllDefinedDependencies() } - module("org.hyperledger.besu:arithmetic", "org.hyperledger.besu.arithmetic") { + module("org.hyperledger.besu:arithmetic", "org.hyperledger.besu.nativelib.arithmetic") { exportAllPackages() requireAllDefinedDependencies() } - module("org.hyperledger.besu:blake2bf", "org.hyperledger.besu.blake2bf") { + module("org.hyperledger.besu:blake2bf", "org.hyperledger.besu.nativelib.blake2bf") { exportAllPackages() requireAllDefinedDependencies() } - module("org.hyperledger.besu:bls12-381", "org.hyperledger.besu.bls12.for381") { + module("org.hyperledger.besu:bls12-381", "org.hyperledger.besu.nativelib.bls12_381") { exportAllPackages() requireAllDefinedDependencies() } @@ -248,11 +246,11 @@ extraJavaModuleInfo { exportAllPackages() requireAllDefinedDependencies() } - module("org.hyperledger.besu:secp256k1", "org.hyperledger.besu.secp256k1") { + module("org.hyperledger.besu:secp256k1", "org.hyperledger.besu.nativelib.secp256k1") { exportAllPackages() requireAllDefinedDependencies() } - module("org.hyperledger.besu:secp256r1", "org.hyperledger.besu.secp256r1") { + module("org.hyperledger.besu:secp256r1", "org.hyperledger.besu.nativelib.secp256r1") { exportAllPackages() requireAllDefinedDependencies() } @@ -317,6 +315,8 @@ extraJavaModuleInfo { knownModule("org.jetbrains.kotlin:kotlin-stdlib-jdk8", "kotlin.stdlib.jdk8") knownModule("org.slf4j:slf4j-api", "org.slf4j") knownModule("jakarta.inject:jakarta.inject-api", "jakarta.inject") + knownModule("com.squareup:javapoet", "com.squareup.javapoet") + knownModule("com.google.auto.service:auto-service-annotations", "com.google.auto.service") // Annotation processing only automaticModule("com.google.dagger:dagger-compiler", "dagger.compiler") @@ -328,14 +328,14 @@ extraJavaModuleInfo { ) automaticModule("com.google.errorprone:javac-shaded", "com.google.errorprone.javac.shaded") automaticModule("com.google.googlejavaformat:google-java-format", "com.google.googlejavaformat") - automaticModule("com.squareup:javapoet", "com.squareup.javapoet") automaticModule("net.ltgt.gradle.incap:incap", "net.ltgt.gradle.incap") automaticModule("org.jetbrains.kotlinx:kotlinx-metadata-jvm", "kotlinx.metadata.jvm") + automaticModule("com.google.auto.service:auto-service", "com.google.auto.service.processor") + automaticModule("com.google.auto:auto-common", "com.google.auto.common") // Testing only automaticModule("com.google.jimfs:jimfs", "com.google.jimfs") automaticModule("org.awaitility:awaitility", "awaitility") - automaticModule("org.hamcrest:hamcrest", "org.hamcrest") automaticModule("org.hamcrest:hamcrest-core", "org.hamcrest.core") automaticModule("org.mockito:mockito-inline", "org.mockito.inline") automaticModule("uk.org.webcompere:system-stubs-core", "uk.org.webcompere.systemstubs.core") @@ -343,7 +343,6 @@ extraJavaModuleInfo { "uk.org.webcompere:system-stubs-jupiter", "uk.org.webcompere.systemstubs.jupiter" ) - automaticModule("com.google.protobuf:protobuf-java-util", "com.google.protobuf.util") // JMH only automaticModule("net.sf.jopt-simple:jopt-simple", "jopt.simple") diff --git a/hedera-dependency-versions/build.gradle.kts b/hedera-dependency-versions/build.gradle.kts index 15738639a18f..e5983ce38bc2 100644 --- a/hedera-dependency-versions/build.gradle.kts +++ b/hedera-dependency-versions/build.gradle.kts @@ -25,7 +25,7 @@ val daggerVersion = "2.42" val eclipseCollectionsVersion = "10.4.0" val grpcVersion = "1.54.1" val helidonVersion = "3.2.1" -val jacksonVersion = "2.13.5" +val jacksonVersion = "2.16.0" val log4jVersion = "2.21.1" val mockitoVersion = "4.11.0" val nettyVersion = "4.1.87.Final" @@ -49,11 +49,14 @@ moduleInfo { version("com.github.benmanes.caffeine", "3.1.1") version("com.github.docker.java.api", "3.2.13") version("com.github.spotbugs.annotations", "4.7.3") + version("com.google.auto.service", "1.1.1") + version("com.google.auto.service.processor", "1.1.1") version("com.google.common", "31.1-jre") version("com.google.jimfs", "1.2") version("com.google.protobuf", protobufVersion) version("com.google.protobuf.util", protobufVersion) version("com.hedera.pbj.runtime", "0.7.6") + version("com.squareup.javapoet", "1.13.0") version("com.sun.jna", "5.12.1") version("dagger", daggerVersion) version("dagger.compiler", daggerVersion) @@ -70,6 +73,7 @@ moduleInfo { version("io.perfmark", "0.25.0") version("io.prometheus.simpleclient", prometheusVersion) version("io.prometheus.simpleclient.httpserver", prometheusVersion) + version("jakarta.inject", "2.0.1") version("java.annotation", "1.3.2") version("javax.inject", "1") version("lazysodium.java", "5.1.1") @@ -91,7 +95,7 @@ moduleInfo { version("org.hamcrest", "2.2") version("org.hyperledger.besu.datatypes", besuVersion) version("org.hyperledger.besu.evm", besuVersion) - version("org.hyperledger.besu.secp256k1", besuNativeVersion) + version("org.hyperledger.besu.nativelib.secp256k1", besuNativeVersion) version("org.json", "20231013") version("org.junit.jupiter.api", "5.9.1") version("org.junit.platform.engine", "1.9.1") @@ -102,10 +106,9 @@ moduleInfo { version("org.opentest4j", "1.2.0") version("org.testcontainers", testContainersVersion) version("org.testcontainers.junit.jupiter", testContainersVersion) - version("org.yaml.snakeyaml", "1.33") + version("org.yaml.snakeyaml", "2.2") version("tuweni.bytes", tuweniVersion) version("tuweni.units", tuweniVersion) version("uk.org.webcompere.systemstubs.core", systemStubsVersion) version("uk.org.webcompere.systemstubs.jupiter", systemStubsVersion) - version("jakarta.inject", "2.0.1") } diff --git a/hedera-node/hapi-utils/src/main/java/module-info.java b/hedera-node/hapi-utils/src/main/java/module-info.java index 37a9439a53d5..e9458e324ab8 100644 --- a/hedera-node/hapi-utils/src/main/java/module-info.java +++ b/hedera-node/hapi-utils/src/main/java/module-info.java @@ -32,7 +32,7 @@ requires org.apache.logging.log4j; requires org.bouncycastle.pkix; requires org.bouncycastle.provider; - requires org.hyperledger.besu.secp256k1; + requires org.hyperledger.besu.nativelib.secp256k1; requires static com.github.spotbugs.annotations; requires static java.compiler; // javax.annotation.processing.Generated } diff --git a/hedera-node/hedera-app/build.gradle.kts b/hedera-node/hedera-app/build.gradle.kts index 165a9f50f039..5d5ec948af60 100644 --- a/hedera-node/hedera-app/build.gradle.kts +++ b/hedera-node/hedera-app/build.gradle.kts @@ -31,6 +31,7 @@ mainModuleInfo { } testModuleInfo { + requires("com.fasterxml.jackson.databind") requires("com.hedera.node.app") requires("com.hedera.node.app.spi.test.fixtures") requires("com.hedera.node.config.test.fixtures") diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/records/impl/producers/StreamFileProducerConcurrent.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/records/impl/producers/StreamFileProducerConcurrent.java index f0b90aec7194..7f712a367a0c 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/records/impl/producers/StreamFileProducerConcurrent.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/records/impl/producers/StreamFileProducerConcurrent.java @@ -33,6 +33,8 @@ import java.time.Instant; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Stream; import javax.inject.Inject; import javax.inject.Singleton; @@ -62,6 +64,8 @@ record TwoResults(A a, B b) {} private final BlockRecordFormat format; /** The executor service to use for background tasks */ private final ExecutorService executorService; + /** The lock to protect the following state */ + private final Lock lock = new ReentrantLock(); /** Future for running hash results of last running hash updates task */ private CompletableFuture lastRecordHashingResult = null; /** Future for running hash results of previous lastRecordHashingResult */ @@ -106,18 +110,23 @@ public StreamFileProducerConcurrent( /** {@inheritDoc} */ @Override public void initRunningHash(@NonNull final RunningHashes runningHashes) { - if (lastRecordHashingResult != null) { - throw new IllegalStateException("initRunningHash() can only be called once"); - } + lock.lock(); // Block until the lock is acquired + try { + if (lastRecordHashingResult != null) { + throw new IllegalStateException("initRunningHash() can only be called once"); + } - if (runningHashes.runningHash() == null) { - throw new IllegalArgumentException("The initial running hash cannot be null"); - } + if (runningHashes.runningHash() == null) { + throw new IllegalArgumentException("The initial running hash cannot be null"); + } - lastRecordHashingResult = completedFuture(runningHashes.runningHash()); - lastRecordHashingResultNMinus1 = completedFuture(runningHashes.nMinus1RunningHash()); - lastRecordHashingResultNMinus2 = completedFuture(runningHashes.nMinus2RunningHash()); - lastRecordHashingResultNMinus3 = completedFuture(runningHashes.nMinus3RunningHash()); + lastRecordHashingResult = completedFuture(runningHashes.runningHash()); + lastRecordHashingResultNMinus1 = completedFuture(runningHashes.nMinus1RunningHash()); + lastRecordHashingResultNMinus2 = completedFuture(runningHashes.nMinus2RunningHash()); + lastRecordHashingResultNMinus3 = completedFuture(runningHashes.nMinus3RunningHash()); + } finally { + lock.unlock(); // Always unlock. + } } /** {@inheritDoc} */ @@ -143,34 +152,40 @@ public void switchBlocks( final long lastBlockNumber, final long newBlockNumber, @NonNull final Instant newBlockFirstTransactionConsensusTime) { + lock.lock(); // Block until the lock is acquired - assert lastRecordHashingResult != null : "initRunningHash() must be called before switchBlocks"; - if (newBlockNumber != lastBlockNumber + 1) { - throw new IllegalArgumentException("Block numbers must be sequential, newBlockNumber=" + newBlockNumber - + ", lastBlockNumber=" + lastBlockNumber); - } + try { + assert lastRecordHashingResult != null : "initRunningHash() must be called before switchBlocks"; + if (newBlockNumber != lastBlockNumber + 1) { + throw new IllegalArgumentException("Block numbers must be sequential, newBlockNumber=" + newBlockNumber + + ", lastBlockNumber=" + lastBlockNumber); + } - this.currentBlockNumber = newBlockNumber; - requireNonNull(newBlockFirstTransactionConsensusTime); + this.currentBlockNumber = newBlockNumber; + requireNonNull(newBlockFirstTransactionConsensusTime); - if (currentRecordFileWriter == null) { - // We are at the start of a new block and there is no old one to close or wait for. So just create a new one - // which creates a new file and writes initializes it in the background - currentRecordFileWriter = lastRecordHashingResult.thenApply(lastRunningHash -> - createBlockRecordWriter(lastRunningHash, newBlockFirstTransactionConsensusTime, newBlockNumber)); - } else { - // wait for all background threads to finish, then in new background task finish the current block - currentRecordFileWriter = currentRecordFileWriter - .thenCombine(lastRecordHashingResult, TwoResults::new) - .thenApplyAsync( - twoResults -> { - final var writer = twoResults.a(); - final var lastRunningHash = twoResults.b(); - closeWriter(writer, lastRunningHash); - return createBlockRecordWriter( - lastRunningHash, newBlockFirstTransactionConsensusTime, newBlockNumber); - }, - executorService); + if (currentRecordFileWriter == null) { + // We are at the start of a new block and there is no old one to close or wait for. So just create a new + // one + // which creates a new file and writes initializes it in the background + currentRecordFileWriter = lastRecordHashingResult.thenApply(lastRunningHash -> createBlockRecordWriter( + lastRunningHash, newBlockFirstTransactionConsensusTime, newBlockNumber)); + } else { + // wait for all background threads to finish, then in new background task finish the current block + currentRecordFileWriter = currentRecordFileWriter + .thenCombine(lastRecordHashingResult, TwoResults::new) + .thenApplyAsync( + twoResults -> { + final var writer = twoResults.a(); + final var lastRunningHash = twoResults.b(); + closeWriter(writer, lastRunningHash); + return createBlockRecordWriter( + lastRunningHash, newBlockFirstTransactionConsensusTime, newBlockNumber); + }, + executorService); + } + } finally { + lock.unlock(); // Always unlock. } } @@ -182,64 +197,79 @@ public void switchBlocks( */ @Override public void writeRecordStreamItems(@NonNull final Stream recordStreamItems) { - assert lastRecordHashingResult != null : "initRunningHash() must be called before writeRecordStreamItems"; - assert currentRecordFileWriter != null : "switchBlocks() must be called before writeRecordStreamItems"; - requireNonNull(recordStreamItems); + lock.lock(); // Block until the lock is acquired - // serialize all the record stream items in background thread into SerializedSingleTransaction objects - final var futureSerializedRecords = CompletableFuture.supplyAsync( - () -> recordStreamItems - .map(item -> format.serialize(item, currentBlockNumber, hapiVersion)) - .toList(), - executorService); - // when serialization is done and previous running hash is computed, we can compute new running hash and write - // serialized items to record file in parallel update running hash in a background thread - lastRecordHashingResultNMinus3 = lastRecordHashingResultNMinus2; - lastRecordHashingResultNMinus2 = lastRecordHashingResultNMinus1; - lastRecordHashingResultNMinus1 = lastRecordHashingResult; - lastRecordHashingResult = lastRecordHashingResult - .thenCombine(futureSerializedRecords, TwoResults::new) - .thenApplyAsync( - twoResults -> format.computeNewRunningHash(twoResults.a(), twoResults.b()), executorService); - // write serialized items to record file in a background thread - currentRecordFileWriter = currentRecordFileWriter - .thenCombine(futureSerializedRecords, TwoResults::new) - .thenApplyAsync( - twoResults -> { - final var writer = twoResults.a(); - final var serializedItems = twoResults.b(); - serializedItems.forEach(item -> { - try { - writer.writeItem(item); - } catch (final Exception e) { - logger.error("Error writing record item to file", e); - } - }); - return writer; - }, - executorService); + try { + assert lastRecordHashingResult != null : "initRunningHash() must be called before writeRecordStreamItems"; + assert currentRecordFileWriter != null : "switchBlocks() must be called before writeRecordStreamItems"; + requireNonNull(recordStreamItems); + + // serialize all the record stream items in background thread into SerializedSingleTransaction objects + final var futureSerializedRecords = CompletableFuture.supplyAsync( + () -> recordStreamItems + .map(item -> format.serialize(item, currentBlockNumber, hapiVersion)) + .toList(), + executorService); + // when serialization is done and previous running hash is computed, we can compute new running hash and + // write + // serialized items to record file in parallel update running hash in a background thread + lastRecordHashingResultNMinus3 = lastRecordHashingResultNMinus2; + lastRecordHashingResultNMinus2 = lastRecordHashingResultNMinus1; + lastRecordHashingResultNMinus1 = lastRecordHashingResult; + lastRecordHashingResult = lastRecordHashingResult + .thenCombine(futureSerializedRecords, TwoResults::new) + .thenApplyAsync( + twoResults -> format.computeNewRunningHash(twoResults.a(), twoResults.b()), + executorService); + // write serialized items to record file in a background thread + currentRecordFileWriter = currentRecordFileWriter + .thenCombine(futureSerializedRecords, TwoResults::new) + .thenApplyAsync( + twoResults -> { + final var writer = twoResults.a(); + final var serializedItems = twoResults.b(); + serializedItems.forEach(item -> { + try { + writer.writeItem(item); + } catch (final Exception e) { + logger.error("Error writing record item to file", e); + } + }); + return writer; + }, + executorService); + } finally { + lock.unlock(); // Always unlock. + } } /** * Closes this StreamFileProducerBase wait for any background thread, close all files etc. This method is - * synchronous, so waits for all background threads to finish and files to be closed. + * synchronous, so waits for all background threads to finish and files to be closed. This method is thread-safe and + * can be called outside the context of the handle thread. */ @Override public void close() { - if (currentRecordFileWriter != null) { - CompletableFuture.allOf(currentRecordFileWriter, lastRecordHashingResult) - .thenAccept(aVoid -> { - final var writer = currentRecordFileWriter.join(); - final var lastRunningHash = lastRecordHashingResult.join(); - closeWriter(writer, lastRunningHash); - }) - .join(); + lock.lock(); // Block until the lock is acquired + + try { + if (currentRecordFileWriter != null) { + CompletableFuture.allOf(currentRecordFileWriter, lastRecordHashingResult) + .thenAccept(aVoid -> { + final var writer = currentRecordFileWriter.join(); + final var lastRunningHash = lastRecordHashingResult.join(); + closeWriter(writer, lastRunningHash); + }) + .join(); - lastRecordHashingResult = null; - lastRecordHashingResultNMinus1 = null; - lastRecordHashingResultNMinus2 = null; - lastRecordHashingResultNMinus3 = null; - currentRecordFileWriter = null; + lastRecordHashingResult = null; + lastRecordHashingResultNMinus1 = null; + lastRecordHashingResultNMinus2 = null; + lastRecordHashingResultNMinus3 = null; + currentRecordFileWriter = null; + } + } finally { + lock.unlock(); // Always unlock. } } diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/throttle/ThrottleAccumulator.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/throttle/ThrottleAccumulator.java index dd917c0cce51..11d2a32c3f11 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/throttle/ThrottleAccumulator.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/throttle/ThrottleAccumulator.java @@ -20,19 +20,27 @@ import static com.hedera.hapi.node.base.HederaFunctionality.CONTRACT_CALL_LOCAL; import static com.hedera.hapi.node.base.HederaFunctionality.CONTRACT_CREATE; import static com.hedera.hapi.node.base.HederaFunctionality.CRYPTO_CREATE; +import static com.hedera.hapi.node.base.HederaFunctionality.CRYPTO_TRANSFER; import static com.hedera.hapi.node.base.HederaFunctionality.ETHEREUM_TRANSACTION; import static com.hedera.node.app.hapi.utils.ethereum.EthTxData.populateEthTxData; import static com.hedera.node.app.hapi.utils.sysfiles.domain.throttling.ScaleFactor.ONE_TO_ONE; import static com.hedera.node.app.service.evm.accounts.HederaEvmContractAliases.isMirror; import static com.hedera.node.app.service.mono.utils.EntityIdUtils.isOfEvmAddressSize; +import static com.hedera.node.app.service.schedule.impl.handlers.HandlerUtility.childAsOrdinary; import static com.hedera.node.app.service.token.AliasUtils.isAlias; import static com.hedera.node.app.service.token.AliasUtils.isSerializedProtoKey; +import static com.hedera.node.app.spi.HapiUtils.functionOf; +import static com.hedera.node.app.throttle.ThrottleAccumulator.ThrottleType.FRONTEND_THROTTLE; import static java.util.Objects.requireNonNull; import com.hedera.hapi.node.base.AccountAmount; import com.hedera.hapi.node.base.AccountID; import com.hedera.hapi.node.base.HederaFunctionality; import com.hedera.hapi.node.base.NftTransfer; +import com.hedera.hapi.node.base.SignatureMap; +import com.hedera.hapi.node.base.Transaction; +import com.hedera.hapi.node.base.TransactionID; +import com.hedera.hapi.node.state.schedule.Schedule; import com.hedera.hapi.node.token.CryptoTransferTransactionBody; import com.hedera.hapi.node.token.TokenMintTransactionBody; import com.hedera.hapi.node.transaction.Query; @@ -44,8 +52,11 @@ import com.hedera.node.app.hapi.utils.throttles.DeterministicThrottle; import com.hedera.node.app.hapi.utils.throttles.GasLimitDeterministicThrottle; import com.hedera.node.app.service.mono.throttling.ThrottleReqsManager; +import com.hedera.node.app.service.schedule.ReadableScheduleStore; import com.hedera.node.app.service.token.ReadableAccountStore; +import com.hedera.node.app.spi.UnknownHederaFunctionality; import com.hedera.node.app.spi.throttle.HandleThrottleParser; +import com.hedera.node.app.spi.workflows.HandleException; import com.hedera.node.app.state.HederaState; import com.hedera.node.app.workflows.TransactionInfo; import com.hedera.node.app.workflows.dispatcher.ReadableStoreFactory; @@ -54,6 +65,7 @@ import com.hedera.node.config.data.AutoCreationConfig; import com.hedera.node.config.data.ContractsConfig; import com.hedera.node.config.data.LazyCreationConfig; +import com.hedera.node.config.data.SchedulingConfig; import com.hedera.node.config.data.TokensConfig; import com.hedera.pbj.runtime.io.buffer.Bytes; import com.swirlds.config.api.Configuration; @@ -117,7 +129,7 @@ public boolean shouldThrottle( @NonNull final HederaState state) { resetLastAllowedUse(); lastTxnWasGasThrottled = false; - if (shouldThrottleTxn(txnInfo, consensusTime, state)) { + if (shouldThrottleTxn(false, txnInfo, consensusTime, state)) { reclaimLastAllowedUse(); return true; } @@ -145,7 +157,7 @@ public boolean shouldThrottle( return false; } - final var shouldThrottleByGas = + final boolean shouldThrottleByGas = configuration.getConfigData(ContractsConfig.class).throttleThrottleByGas(); resetLastAllowedUse(); @@ -230,8 +242,22 @@ public static boolean isGasThrottled(@NonNull final HederaFunctionality function return GAS_THROTTLED_FUNCTIONS.contains(function); } + /* + * Resets the usage for all underlying throttles. + */ + public void resetUsage() { + lastTxnWasGasThrottled = false; + activeThrottles.forEach(DeterministicThrottle::resetUsage); + if (gasThrottle != null) { + gasThrottle.resetUsage(); + } + } + private boolean shouldThrottleTxn( - @NonNull final TransactionInfo txnInfo, @NonNull final Instant now, @NonNull final HederaState state) { + final boolean isScheduled, + @NonNull final TransactionInfo txnInfo, + @NonNull final Instant now, + @NonNull final HederaState state) { final var function = txnInfo.functionality(); final var configuration = configProvider.getConfiguration(); @@ -242,12 +268,12 @@ private boolean shouldThrottleTxn( // exemption // but this is only possible for the case of triggered transactions which is not yet implemented (see // MonoMultiplierSources.java) - final var isPayerThrottleExempt = throttleExempt(txnInfo.payerID(), configuration); + final boolean isPayerThrottleExempt = throttleExempt(txnInfo.payerID(), configuration); if (isPayerThrottleExempt) { return false; } - final var txGasLimit = getGasLimitForContractTx(txnInfo.txBody(), txnInfo.functionality()); + final long txGasLimit = getGasLimitForContractTx(txnInfo.txBody(), txnInfo.functionality()); if (isGasExhausted(function, now, txGasLimit, configuration)) { lastTxnWasGasThrottled = true; return true; @@ -259,6 +285,20 @@ private boolean shouldThrottleTxn( } return switch (function) { + case SCHEDULE_CREATE -> { + if (isScheduled) { + throw new IllegalStateException("ScheduleCreate cannot be a child!"); + } + + yield shouldThrottleScheduleCreate(manager, txnInfo, now, state); + } + case SCHEDULE_SIGN -> { + if (isScheduled) { + throw new IllegalStateException("ScheduleSign cannot be a child!"); + } + + yield shouldThrottleScheduleSign(manager, txnInfo, now, state); + } case TOKEN_MINT -> shouldThrottleMint(manager, txnInfo.txBody().tokenMint(), now, configuration); case CRYPTO_TRANSFER -> { final var accountStore = new ReadableStoreFactory(state).getStore(ReadableAccountStore.class); @@ -274,11 +314,149 @@ yield shouldThrottleEthTxn( }; } + private boolean shouldThrottleScheduleCreate( + final ThrottleReqsManager manager, + final TransactionInfo txnInfo, + final Instant now, + final HederaState state) { + final var txnBody = txnInfo.txBody(); + final var scheduleCreate = txnBody.scheduleCreate(); + final var scheduled = scheduleCreate.scheduledTransactionBody(); + final var schedule = Schedule.newBuilder() + .originalCreateTransaction(txnBody) + .payerAccountId(txnInfo.payerID()) + .scheduledTransaction(scheduled) + .build(); + + TransactionBody innerTxn; + HederaFunctionality scheduledFunction; + try { + innerTxn = childAsOrdinary(schedule); + scheduledFunction = functionOf(innerTxn); + } catch (HandleException | UnknownHederaFunctionality ex) { + log.debug("ScheduleCreate was associated with an invalid txn.", ex); + return true; + } + + // maintain legacy behaviour + final var configuration = configProvider.getConfiguration(); + final boolean areLongTermSchedulesEnabled = + configuration.getConfigData(SchedulingConfig.class).longTermEnabled(); + if (!areLongTermSchedulesEnabled) { + final boolean isAutoCreationEnabled = + configuration.getConfigData(AutoCreationConfig.class).enabled(); + final boolean isLazyCreationEnabled = + configuration.getConfigData(LazyCreationConfig.class).enabled(); + + // we check for CryptoTransfer because implicit creations (i.e. auto- or lazy-creation) may happen in it, + // and we need to throttle those separately + if ((isAutoCreationEnabled || isLazyCreationEnabled) && scheduledFunction == CRYPTO_TRANSFER) { + final var transfer = scheduled.cryptoTransfer(); + if (usesAliases(transfer)) { + final var accountStore = new ReadableStoreFactory(state).getStore(ReadableAccountStore.class); + final var transferTxnBody = TransactionBody.newBuilder() + .cryptoTransfer(transfer) + .build(); + final int implicitCreationsCount = getImplicitCreationsCount(transferTxnBody, accountStore); + if (implicitCreationsCount > 0) { + return shouldThrottleImplicitCreations(implicitCreationsCount, now); + } + } + } + return !manager.allReqsMetAt(now); + } else { + log.warn("Long term scheduling is enabled, but throttling of long term schedules is not yet implemented."); + if (!manager.allReqsMetAt(now)) { + return true; + } + + // only check deeply if the schedule could immediately execute + if ((!scheduleCreate.waitForExpiry()) && (throttleType == FRONTEND_THROTTLE)) { + var effectivePayer = scheduleCreate.hasPayerAccountID() + ? scheduleCreate.payerAccountID() + : txnBody.transactionID().accountID(); + + final var innerTxnInfo = new TransactionInfo( + Transaction.DEFAULT, + innerTxn, + TransactionID.DEFAULT, + effectivePayer, + SignatureMap.DEFAULT, + Bytes.EMPTY, + scheduledFunction); + + return shouldThrottleTxn(true, innerTxnInfo, now, state); + } + + return false; + } + } + + private boolean shouldThrottleScheduleSign( + ThrottleReqsManager manager, TransactionInfo txnInfo, Instant now, HederaState state) { + final var txnBody = txnInfo.txBody(); + if (!manager.allReqsMetAt(now)) { + return true; + } + + // maintain legacy behaviour + final var configuration = configProvider.getConfiguration(); + final boolean areLongTermSchedulesEnabled = + configuration.getConfigData(SchedulingConfig.class).longTermEnabled(); + if (!areLongTermSchedulesEnabled) { + return false; + } else { + log.warn("Long term scheduling is enabled, but throttling of long term schedules is not yet implemented."); + // deeply check throttle only in the frontend throttle + if (throttleType != FRONTEND_THROTTLE) { + return false; + } + + final var scheduledId = txnBody.scheduleSign().scheduleID(); + final var scheduleStore = new ReadableStoreFactory(state).getStore(ReadableScheduleStore.class); + final var schedule = scheduleStore.get(scheduledId); + if (schedule == null) { + log.error( + "Tried to throttle in the frontend throttle a ScheduleSign that does not exist! We should not get here."); + return true; + } + + // only check deeply if the schedule could immediately execute + if (schedule.waitForExpiry()) { + return false; + } + + TransactionBody innerTxn; + HederaFunctionality scheduledFunction; + try { + innerTxn = childAsOrdinary(schedule); + scheduledFunction = functionOf(innerTxn); + } catch (HandleException | UnknownHederaFunctionality ex) { + log.error("ScheduleSign was associated with an invalid txn.", ex); + return true; + } + + final var effectivePayer = + schedule.hasPayerAccountId() ? schedule.payerAccountId() : schedule.schedulerAccountId(); + + final var innerTxnInfo = new TransactionInfo( + Transaction.DEFAULT, + innerTxn, + TransactionID.DEFAULT, + effectivePayer, + SignatureMap.DEFAULT, + Bytes.EMPTY, + scheduledFunction); + + return shouldThrottleTxn(true, innerTxnInfo, now, state); + } + } + public static boolean throttleExempt( @NonNull final AccountID accountID, @NonNull final Configuration configuration) { - final var maxThrottleExemptNum = + final long maxThrottleExemptNum = configuration.getConfigData(AccountsConfig.class).lastThrottleExempt(); - final var accountNum = accountID.accountNum(); + final long accountNum = accountID.accountNum().longValue(); return 1L <= accountNum && accountNum <= maxThrottleExemptNum; } @@ -313,7 +491,7 @@ private boolean isGasExhausted( @NonNull final Instant now, final long txGasLimit, @NonNull final Configuration configuration) { - final var shouldThrottleByGas = + final boolean shouldThrottleByGas = configuration.getConfigData(ContractsConfig.class).throttleThrottleByGas(); return shouldThrottleByGas && isGasThrottled(function) @@ -325,7 +503,7 @@ private boolean shouldThrottleMint( @NonNull final TokenMintTransactionBody op, @NonNull final Instant now, @NonNull final Configuration configuration) { - final var numNfts = op.metadata().size(); + final int numNfts = op.metadata().size(); if (numNfts == 0) { return !manager.allReqsMetAt(now); } else { @@ -340,9 +518,9 @@ private boolean shouldThrottleCryptoTransfer( @NonNull final Instant now, @NonNull final Configuration configuration, final int implicitCreationsCount) { - final var isAutoCreationEnabled = + final boolean isAutoCreationEnabled = configuration.getConfigData(AutoCreationConfig.class).enabled(); - final var isLazyCreationEnabled = + final boolean isLazyCreationEnabled = configuration.getConfigData(LazyCreationConfig.class).enabled(); if (isAutoCreationEnabled || isLazyCreationEnabled) { return shouldThrottleBasedOnImplicitCreations(manager, implicitCreationsCount, now); @@ -356,9 +534,9 @@ private boolean shouldThrottleEthTxn( @NonNull final Instant now, @NonNull final Configuration configuration, final int implicitCreationsCount) { - final var isAutoCreationEnabled = + final boolean isAutoCreationEnabled = configuration.getConfigData(AutoCreationConfig.class).enabled(); - final var isLazyCreationEnabled = + final boolean isLazyCreationEnabled = configuration.getConfigData(LazyCreationConfig.class).enabled(); if (isAutoCreationEnabled && isLazyCreationEnabled) { return shouldThrottleBasedOnImplicitCreations(manager, implicitCreationsCount, now); @@ -369,7 +547,7 @@ private boolean shouldThrottleEthTxn( private int getImplicitCreationsCount( @NonNull final TransactionBody txnBody, @NonNull final ReadableAccountStore accountStore) { - var implicitCreationsCount = 0; + int implicitCreationsCount = 0; if (txnBody.hasEthereumTransaction()) { final var ethTxData = populateEthTxData( txnBody.ethereumTransaction().ethereumData().toByteArray()); @@ -377,7 +555,7 @@ private int getImplicitCreationsCount( return UNKNOWN_NUM_IMPLICIT_CREATIONS; } - final var doesNotExist = accountStore.containsAlias(Bytes.wrap(ethTxData.to())); + final boolean doesNotExist = accountStore.containsAlias(Bytes.wrap(ethTxData.to())); if (doesNotExist && ethTxData.value().compareTo(BigInteger.ZERO) > 0) { implicitCreationsCount++; } @@ -402,7 +580,7 @@ private int hbarAdjustsImplicitCreationsCount( return 0; } - var implicitCreationsCount = 0; + int implicitCreationsCount = 0; for (var adjust : cryptoTransferBody.transfers().accountAmounts()) { if (!isKnownAlias(adjust.accountID(), accountStore) && containsImplicitCreations(adjust)) { implicitCreationsCount++; @@ -419,7 +597,7 @@ private int tokenAdjustsImplicitCreationsCount( return 0; } - var implicitCreationsCount = 0; + int implicitCreationsCount = 0; for (var tokenAdjust : cryptoTransferBody.tokenTransfers()) { for (final var adjust : tokenAdjust.transfers()) { if (!isKnownAlias(adjust.accountID(), accountStore) && containsImplicitCreations(adjust)) { @@ -437,6 +615,29 @@ private int tokenAdjustsImplicitCreationsCount( return implicitCreationsCount; } + private boolean usesAliases(final CryptoTransferTransactionBody transferBody) { + for (var adjust : transferBody.transfers().accountAmounts()) { + if (isAlias(adjust.accountID())) { + return true; + } + } + + for (var tokenAdjusts : transferBody.tokenTransfers()) { + for (var ownershipChange : tokenAdjusts.nftTransfers()) { + if (isAlias(ownershipChange.senderAccountID()) || isAlias(ownershipChange.receiverAccountID())) { + return true; + } + } + for (var tokenAdjust : tokenAdjusts.transfers()) { + if (isAlias(tokenAdjust.accountID())) { + return true; + } + } + } + + return false; + } + private boolean isKnownAlias(@NonNull final AccountID idOrAlias, @NonNull final ReadableAccountStore accountStore) { if (isAlias(idOrAlias)) { final var alias = idOrAlias.alias(); diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/HandleContextImpl.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/HandleContextImpl.java index 697d34be355e..a193c603be67 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/HandleContextImpl.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/HandleContextImpl.java @@ -570,7 +570,7 @@ public T dispatchChildTransaction( @NonNull final AccountID syntheticPayerId, @NonNull final TransactionCategory childCategory) { final Supplier recordBuilderFactory = - () -> recordListBuilder.addChild(configuration()); + () -> recordListBuilder.addChild(configuration(), childCategory); return doDispatchChildTransaction( syntheticPayerId, txBody, recordBuilderFactory, recordBuilderClass, callback, childCategory); } @@ -702,7 +702,9 @@ private void dispatchSyntheticTxn( dispatcher.dispatchHandle(childContext); childRecordBuilder.status(ResponseCodeEnum.SUCCESS); final var finalizeContext = new ChildFinalizeContextImpl( - readableStoreFactory, new WritableStoreFactory(childStack, TokenService.NAME), childRecordBuilder); + new ReadableStoreFactory(childStack), + new WritableStoreFactory(childStack, TokenService.NAME), + childRecordBuilder); childRecordFinalizer.finalizeChildRecord(finalizeContext); childStack.commitFullStack(); } catch (final HandleException e) { @@ -804,7 +806,7 @@ private void assertPayerIsAuthorized( @Override @NonNull public T addChildRecordBuilder(@NonNull final Class recordBuilderClass) { - final var result = recordListBuilder.addChild(configuration()); + final var result = recordListBuilder.addChild(configuration(), CHILD); return castRecordBuilder(result, recordBuilderClass); } diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/record/RecordListBuilder.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/record/RecordListBuilder.java index 03a55348e36c..98498fdebda8 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/record/RecordListBuilder.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/record/RecordListBuilder.java @@ -24,6 +24,7 @@ import com.hedera.hapi.node.base.ResponseCodeEnum; import com.hedera.hapi.node.base.TransactionID; +import com.hedera.node.app.spi.workflows.HandleContext; import com.hedera.node.app.spi.workflows.HandleException; import com.hedera.node.app.spi.workflows.record.ExternalizedRecordCustomizer; import com.hedera.node.app.state.SingleTransactionRecord; @@ -200,9 +201,12 @@ public SingleTransactionRecordBuilderImpl doAddPreceding( * @throws NullPointerException if {@code consensusConfig} is {@code null} * @throws HandleException if no more child slots are available */ - public SingleTransactionRecordBuilderImpl addChild(@NonNull final Configuration configuration) { + public SingleTransactionRecordBuilderImpl addChild( + @NonNull final Configuration configuration, + @NonNull final HandleContext.TransactionCategory childCategory) { requireNonNull(configuration, CONFIGURATION_MUST_NOT_BE_NULL); - return doAddChild(configuration, ReversingBehavior.REVERSIBLE, NOOP_EXTERNALIZED_RECORD_CUSTOMIZER); + return doAddChild( + configuration, ReversingBehavior.REVERSIBLE, NOOP_EXTERNALIZED_RECORD_CUSTOMIZER, childCategory); } /** @@ -210,7 +214,7 @@ public SingleTransactionRecordBuilderImpl addChild(@NonNull final Configuration *

* If a parent transaction of this child transaction is rolled back, the record builder is removed entirely. This is * only needed in a very few special cases. Under normal circumstances, - * {@link #addChild(Configuration)} should be used. + * {@link #addChild(Configuration, HandleContext.TransactionCategory)} should be used. * * @param configuration the current configuration * @return the record builder for the child transaction @@ -219,7 +223,11 @@ public SingleTransactionRecordBuilderImpl addChild(@NonNull final Configuration */ public SingleTransactionRecordBuilderImpl addRemovableChild(@NonNull final Configuration configuration) { requireNonNull(configuration, CONFIGURATION_MUST_NOT_BE_NULL); - return doAddChild(configuration, ReversingBehavior.REMOVABLE, NOOP_EXTERNALIZED_RECORD_CUSTOMIZER); + return doAddChild( + configuration, + ReversingBehavior.REMOVABLE, + NOOP_EXTERNALIZED_RECORD_CUSTOMIZER, + HandleContext.TransactionCategory.CHILD); } /** @@ -239,13 +247,15 @@ public SingleTransactionRecordBuilderImpl addRemovableChildWithExternalizationCu @NonNull final Configuration configuration, @NonNull final ExternalizedRecordCustomizer customizer) { requireNonNull(configuration, CONFIGURATION_MUST_NOT_BE_NULL); requireNonNull(customizer, "customizer must not be null"); - return doAddChild(configuration, ReversingBehavior.REMOVABLE, customizer); + return doAddChild( + configuration, ReversingBehavior.REMOVABLE, customizer, HandleContext.TransactionCategory.CHILD); } private SingleTransactionRecordBuilderImpl doAddChild( @NonNull final Configuration configuration, final ReversingBehavior reversingBehavior, - @NonNull final ExternalizedRecordCustomizer customizer) { + @NonNull final ExternalizedRecordCustomizer customizer, + @NonNull final HandleContext.TransactionCategory childCategory) { // FUTURE: We should reuse the RecordListBuilder between handle calls, and we should reuse these lists, in // which case we will no longer have to create them lazily. if (childRecordBuilders == null) { @@ -266,8 +276,13 @@ private SingleTransactionRecordBuilderImpl doAddChild( : childRecordBuilders.get(childRecordBuilders.size() - 1).consensusNow(); final var consensusNow = prevConsensusNow.plusNanos(1L); // Note we do not repeat exchange rates for child transactions - final var recordBuilder = new SingleTransactionRecordBuilderImpl(consensusNow, reversingBehavior, customizer) - .parentConsensus(parentConsensusTimestamp); + final var recordBuilder = new SingleTransactionRecordBuilderImpl(consensusNow, reversingBehavior, customizer); + // Only set parent consensus timestamp for child records if one is not provided + if (!childCategory.equals(HandleContext.TransactionCategory.SCHEDULED)) { + recordBuilder.parentConsensus(parentConsensusTimestamp); + } else { + recordBuilder.exchangeRate(userTxnRecordBuilder.exchangeRate()); + } if (!customizer.shouldSuppressRecord()) { childRecordBuilders.add(recordBuilder); } @@ -281,7 +296,7 @@ private SingleTransactionRecordBuilderImpl doAddChild( * happens, because there are no children after the last one. * *

If the given builder is the next to last of these 10, then if the last one was added by - * {@link #addChild(Configuration)} it will still be in the list, but will have a status of + * {@link #addChild(Configuration, HandleContext.TransactionCategory)} it will still be in the list, but will have a status of * {@link ResponseCodeEnum#REVERTED_SUCCESS} (unless it had another failure mode already), otherwise it will * actually be removed from the list. * diff --git a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/throttle/ThrottleAccumulatorTest.java b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/throttle/ThrottleAccumulatorTest.java new file mode 100644 index 000000000000..94b9acc2b04e --- /dev/null +++ b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/throttle/ThrottleAccumulatorTest.java @@ -0,0 +1,1081 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hedera.node.app.throttle; + +import static com.hedera.hapi.node.base.HederaFunctionality.CONSENSUS_SUBMIT_MESSAGE; +import static com.hedera.hapi.node.base.HederaFunctionality.CRYPTO_TRANSFER; +import static com.hedera.hapi.node.base.HederaFunctionality.SCHEDULE_CREATE; +import static com.hedera.hapi.node.base.HederaFunctionality.SCHEDULE_SIGN; +import static com.hedera.node.app.service.schedule.impl.ScheduleServiceImpl.SCHEDULES_BY_ID_KEY; +import static com.hedera.node.app.throttle.ThrottleAccumulator.ThrottleType.FRONTEND_THROTTLE; +import static com.hedera.pbj.runtime.ProtoTestTools.getThreadLocalDataBuffer; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.hedera.hapi.node.base.AccountAmount; +import com.hedera.hapi.node.base.AccountID; +import com.hedera.hapi.node.base.Key; +import com.hedera.hapi.node.base.ScheduleID; +import com.hedera.hapi.node.base.SignatureMap; +import com.hedera.hapi.node.base.Transaction; +import com.hedera.hapi.node.base.TransactionID; +import com.hedera.hapi.node.base.TransferList; +import com.hedera.hapi.node.consensus.ConsensusSubmitMessageTransactionBody; +import com.hedera.hapi.node.scheduled.SchedulableTransactionBody; +import com.hedera.hapi.node.scheduled.ScheduleCreateTransactionBody; +import com.hedera.hapi.node.scheduled.ScheduleSignTransactionBody; +import com.hedera.hapi.node.state.schedule.Schedule; +import com.hedera.hapi.node.token.CryptoTransferTransactionBody; +import com.hedera.hapi.node.transaction.ThrottleDefinitions; +import com.hedera.hapi.node.transaction.TransactionBody; +import com.hedera.node.app.hapi.utils.throttles.BucketThrottle; +import com.hedera.node.app.spi.fixtures.util.LogCaptor; +import com.hedera.node.app.spi.fixtures.util.LogCaptureExtension; +import com.hedera.node.app.spi.fixtures.util.LoggingSubject; +import com.hedera.node.app.spi.fixtures.util.LoggingTarget; +import com.hedera.node.app.spi.state.ReadableKVState; +import com.hedera.node.app.spi.state.ReadableStates; +import com.hedera.node.app.state.HederaState; +import com.hedera.node.app.workflows.TransactionInfo; +import com.hedera.node.config.ConfigProvider; +import com.hedera.node.config.VersionedConfiguration; +import com.hedera.node.config.data.AccountsConfig; +import com.hedera.node.config.data.AutoCreationConfig; +import com.hedera.node.config.data.ContractsConfig; +import com.hedera.node.config.data.LazyCreationConfig; +import com.hedera.node.config.data.SchedulingConfig; +import com.hedera.pbj.runtime.io.buffer.Bytes; +import java.io.IOException; +import java.io.InputStream; +import java.time.Instant; +import java.util.ArrayList; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.EnumSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; + +@ExtendWith({MockitoExtension.class, LogCaptureExtension.class}) +class ThrottleAccumulatorTest { + private static final int CAPACITY_SPLIT = 2; + private static final Instant CONSENSUS_NOW = Instant.ofEpochSecond(1_234_567L, 123); + private static final AccountID PAYER_ID = + AccountID.newBuilder().accountNum(1234L).build(); + private static final Key A_PRIMITIVE_KEY = Key.newBuilder() + .ed25519(Bytes.wrap("01234567890123456789012345678901")) + .build(); + private static final ScheduleID SCHEDULE_ID = + ScheduleID.newBuilder().scheduleNum(333333L).build(); + + @LoggingSubject + private ThrottleAccumulator subject; + + @LoggingTarget + private LogCaptor logCaptor; + + @Mock + private ConfigProvider configProvider; + + @Mock + private VersionedConfiguration configuration; + + @Mock + private SchedulingConfig schedulingConfig; + + @Mock + private AccountsConfig accountsConfig; + + @Mock + private ContractsConfig contractsConfig; + + @Mock + private AutoCreationConfig autoCreationConfig; + + @Mock + private LazyCreationConfig lazyCreationConfig; + + @Mock + private HederaState state; + + @Mock + private ReadableStates readableStates; + + @Mock + private ReadableKVState aliases; + + @Mock + private ReadableKVState schedules; + + @ParameterizedTest + @CsvSource({ + "FRONTEND_THROTTLE,true,true", + "FRONTEND_THROTTLE,true,false", + "FRONTEND_THROTTLE,false,true", + "FRONTEND_THROTTLE,false,false", + "BACKEND_THROTTLE,true,true", + "BACKEND_THROTTLE,true,false", + "BACKEND_THROTTLE,false,true", + "BACKEND_THROTTLE,false,false", + }) + @MockitoSettings(strictness = org.mockito.quality.Strictness.LENIENT) + void usesScheduleCreateThrottleForSubmitMessage( + final ThrottleAccumulator.ThrottleType throttleType, + final boolean longTermEnabled, + final boolean waitForExpiry) + throws IOException { + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, throttleType); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + given(configuration.getConfigData(SchedulingConfig.class)).willReturn(schedulingConfig); + given(schedulingConfig.longTermEnabled()).willReturn(longTermEnabled); + given(configuration.getConfigData(AutoCreationConfig.class)).willReturn(autoCreationConfig); + given(autoCreationConfig.enabled()).willReturn(true); + given(configuration.getConfigData(LazyCreationConfig.class)).willReturn(lazyCreationConfig); + given(lazyCreationConfig.enabled()).willReturn(false); + + final var scheduledSubmit = SchedulableTransactionBody.newBuilder() + .consensusSubmitMessage(ConsensusSubmitMessageTransactionBody.DEFAULT) + .build(); + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles.json"); + subject.rebuildFor(defs); + + // when + final var txnInfo = scheduleCreate(scheduledSubmit, waitForExpiry, null); + final boolean firstAns = subject.shouldThrottle(txnInfo, CONSENSUS_NOW, state); + boolean subsequentAns = false; + for (int i = 1; i <= 150; i++) { + subsequentAns = subject.shouldThrottle(txnInfo, CONSENSUS_NOW.plusNanos(i), state); + } + + final var throttlesNow = subject.activeThrottlesFor(SCHEDULE_CREATE); + final var aNow = throttlesNow.get(0); + + // then + assertFalse(firstAns); + assertTrue(subsequentAns); + assertEquals(149999992500000L, aNow.used()); + assertEquals( + longTermEnabled && throttleType == FRONTEND_THROTTLE && (!waitForExpiry) ? 149999255000000L : 0, + subject.activeThrottlesFor(CONSENSUS_SUBMIT_MESSAGE).get(0).used()); + } + + @ParameterizedTest + @CsvSource({ + "FRONTEND_THROTTLE,true,true", + "FRONTEND_THROTTLE,true,false", + "FRONTEND_THROTTLE,false,true", + "FRONTEND_THROTTLE,false,false", + "BACKEND_THROTTLE,true,true", + "BACKEND_THROTTLE,true,false", + "BACKEND_THROTTLE,false,true", + "BACKEND_THROTTLE,false,false", + }) + @MockitoSettings(strictness = org.mockito.quality.Strictness.LENIENT) + void usesScheduleCreateThrottleWithNestedThrottleExempt( + final ThrottleAccumulator.ThrottleType throttleType, + final boolean longTermEnabled, + final boolean waitForExpiry) + throws IOException { + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, throttleType); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + given(configuration.getConfigData(SchedulingConfig.class)).willReturn(schedulingConfig); + given(schedulingConfig.longTermEnabled()).willReturn(longTermEnabled); + given(configuration.getConfigData(AutoCreationConfig.class)).willReturn(autoCreationConfig); + given(autoCreationConfig.enabled()).willReturn(true); + given(configuration.getConfigData(LazyCreationConfig.class)).willReturn(lazyCreationConfig); + given(lazyCreationConfig.enabled()).willReturn(false); + + final var scheduledSubmit = SchedulableTransactionBody.newBuilder() + .consensusSubmitMessage(ConsensusSubmitMessageTransactionBody.DEFAULT) + .build(); + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles.json"); + subject.rebuildFor(defs); + + // when + final var txnInfo = scheduleCreate( + scheduledSubmit, + waitForExpiry, + AccountID.newBuilder().accountNum(2L).build()); + final boolean firstAns = subject.shouldThrottle(txnInfo, CONSENSUS_NOW, state); + boolean subsequentAns = false; + for (int i = 1; i <= 150; i++) { + subsequentAns = subject.shouldThrottle(txnInfo, CONSENSUS_NOW.plusNanos(i), state); + } + + final var throttlesNow = subject.activeThrottlesFor(SCHEDULE_CREATE); + final var aNow = throttlesNow.get(0); + + // then + assertFalse(firstAns); + assertTrue(subsequentAns); + assertEquals(149999992500000L, aNow.used()); + assertEquals( + 0, subject.activeThrottlesFor(CONSENSUS_SUBMIT_MESSAGE).get(0).used()); + } + + @ParameterizedTest + @EnumSource + void scheduleCreateAlwaysThrottledWhenNoBody(final ThrottleAccumulator.ThrottleType throttleType) + throws IOException { + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, throttleType); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles.json"); + subject.rebuildFor(defs); + + // when + final var txnInfo = scheduleCreate(SchedulableTransactionBody.DEFAULT, false, null); + final boolean firstAns = subject.shouldThrottle(txnInfo, CONSENSUS_NOW, state); + for (int i = 1; i <= 150; i++) { + assertTrue(subject.shouldThrottle(txnInfo, CONSENSUS_NOW.plusNanos(i), state)); + } + + final var throttlesNow = subject.activeThrottlesFor(SCHEDULE_CREATE); + final var aNow = throttlesNow.get(0); + + // then + assertTrue(firstAns); + assertEquals(0, aNow.used()); + assertEquals( + 0, subject.activeThrottlesFor(CONSENSUS_SUBMIT_MESSAGE).get(0).used()); + } + + @ParameterizedTest + @CsvSource({ + "FRONTEND_THROTTLE,true", + "FRONTEND_THROTTLE,false", + "BACKEND_THROTTLE,true", + "BACKEND_THROTTLE,false", + }) + @MockitoSettings(strictness = org.mockito.quality.Strictness.LENIENT) + void usesScheduleCreateThrottleForCryptoTransferNoAutoCreations( + final ThrottleAccumulator.ThrottleType throttleType, final boolean longTermEnabled) throws IOException { + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, throttleType); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + given(configuration.getConfigData(SchedulingConfig.class)).willReturn(schedulingConfig); + given(schedulingConfig.longTermEnabled()).willReturn(longTermEnabled); + given(configuration.getConfigData(AutoCreationConfig.class)).willReturn(autoCreationConfig); + given(autoCreationConfig.enabled()).willReturn(true); + given(configuration.getConfigData(LazyCreationConfig.class)).willReturn(lazyCreationConfig); + given(lazyCreationConfig.enabled()).willReturn(false); + + given(state.createReadableStates(any())).willReturn(readableStates); + + final var scheduledTransferNoAliases = SchedulableTransactionBody.newBuilder() + .cryptoTransfer(cryptoTransferWithImplicitCreations(0)) + .build(); + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles.json"); + subject.rebuildFor(defs); + + // when + final var txnInfo = scheduleCreate(scheduledTransferNoAliases, false, null); + final boolean ans = subject.shouldThrottle(txnInfo, CONSENSUS_NOW, state); + final var throttlesNow = subject.activeThrottlesFor(SCHEDULE_CREATE); + final var aNow = throttlesNow.get(0); + + // then + assertFalse(ans); + assertEquals(BucketThrottle.capacityUnitsPerTxn(), aNow.used()); + assertEquals( + longTermEnabled && throttleType == FRONTEND_THROTTLE ? BucketThrottle.capacityUnitsPerTxn() : 0, + subject.activeThrottlesFor(CRYPTO_TRANSFER).get(0).used()); + } + + @ParameterizedTest + @CsvSource({ + "FRONTEND_THROTTLE,true", + "FRONTEND_THROTTLE,false", + "BACKEND_THROTTLE,true", + "BACKEND_THROTTLE,false", + }) + @MockitoSettings(strictness = org.mockito.quality.Strictness.LENIENT) + void doesntUseCryptoCreateThrottleForCryptoTransferWithAutoCreationIfAutoAndLazyCreationDisabled( + final ThrottleAccumulator.ThrottleType throttleType, final boolean longTermEnabled) throws IOException { + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, throttleType); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + given(configuration.getConfigData(SchedulingConfig.class)).willReturn(schedulingConfig); + given(schedulingConfig.longTermEnabled()).willReturn(longTermEnabled); + given(configuration.getConfigData(AutoCreationConfig.class)).willReturn(autoCreationConfig); + given(autoCreationConfig.enabled()).willReturn(false); + given(configuration.getConfigData(LazyCreationConfig.class)).willReturn(lazyCreationConfig); + given(lazyCreationConfig.enabled()).willReturn(false); + + given(state.createReadableStates(any())).willReturn(readableStates); + given(readableStates.get(any())).willReturn(aliases); + + final var alias = keyToBytes(A_PRIMITIVE_KEY); + var accountAmounts = new ArrayList(); + accountAmounts.add(AccountAmount.newBuilder() + .amount(-1_000_000_000L) + .accountID(AccountID.newBuilder().accountNum(3333L).build()) + .build()); + accountAmounts.add(AccountAmount.newBuilder() + .amount(+1_000_000_000L) + .accountID(AccountID.newBuilder().alias(alias).build()) + .build()); + final var scheduledTransferWithAutoCreation = SchedulableTransactionBody.newBuilder() + .cryptoTransfer(CryptoTransferTransactionBody.newBuilder() + .transfers(TransferList.newBuilder() + .accountAmounts(accountAmounts) + .build())) + .build(); + + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles.json"); + subject.rebuildFor(defs); + + // when + final var txnInfo = scheduleCreate(scheduledTransferWithAutoCreation, false, null); + final boolean ans = subject.shouldThrottle(txnInfo, CONSENSUS_NOW, state); + final var throttlesNow = subject.activeThrottlesFor(SCHEDULE_CREATE); + final var aNow = throttlesNow.get(0); + + // then + assertFalse(ans); + assertEquals(BucketThrottle.capacityUnitsPerTxn(), aNow.used()); + + assertEquals( + longTermEnabled && throttleType == FRONTEND_THROTTLE ? BucketThrottle.capacityUnitsPerTxn() : 0, + subject.activeThrottlesFor(CRYPTO_TRANSFER).get(0).used()); + } + + @ParameterizedTest + @CsvSource({ + "FRONTEND_THROTTLE,true,true", + "FRONTEND_THROTTLE,true,false", + "FRONTEND_THROTTLE,false,true", + "FRONTEND_THROTTLE,false,false", + "BACKEND_THROTTLE,true,true", + "BACKEND_THROTTLE,true,false", + "BACKEND_THROTTLE,false,true", + "BACKEND_THROTTLE,false,false", + }) + @MockitoSettings(strictness = org.mockito.quality.Strictness.LENIENT) + void doesntUseCryptoCreateThrottleForCryptoTransferWithNoAliases( + final ThrottleAccumulator.ThrottleType throttleType, + final boolean longTermEnabled, + final boolean autoOrLazyCreationEnabled) + throws IOException { + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, throttleType); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + given(configuration.getConfigData(SchedulingConfig.class)).willReturn(schedulingConfig); + given(schedulingConfig.longTermEnabled()).willReturn(longTermEnabled); + given(configuration.getConfigData(AutoCreationConfig.class)).willReturn(autoCreationConfig); + given(autoCreationConfig.enabled()).willReturn(autoOrLazyCreationEnabled); + given(configuration.getConfigData(LazyCreationConfig.class)).willReturn(lazyCreationConfig); + given(lazyCreationConfig.enabled()).willReturn(!autoOrLazyCreationEnabled); + + given(state.createReadableStates(any())).willReturn(readableStates); + + var accountAmounts = new ArrayList(); + accountAmounts.add(AccountAmount.newBuilder() + .amount(-1_000_000_000L) + .accountID(AccountID.newBuilder().accountNum(3333L).build()) + .build()); + accountAmounts.add(AccountAmount.newBuilder() + .amount(+1_000_000_000L) + .accountID(AccountID.newBuilder().accountNum(4444L).build()) + .build()); + final var scheduledTransferNoAliases = SchedulableTransactionBody.newBuilder() + .cryptoTransfer(CryptoTransferTransactionBody.newBuilder() + .transfers(TransferList.newBuilder() + .accountAmounts(accountAmounts) + .build())) + .build(); + + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles.json"); + subject.rebuildFor(defs); + + // when + final var txnInfo = scheduleCreate(scheduledTransferNoAliases, false, null); + final boolean ans = subject.shouldThrottle(txnInfo, CONSENSUS_NOW, state); + final var throttlesNow = subject.activeThrottlesFor(SCHEDULE_CREATE); + final var aNow = throttlesNow.get(0); + + // then + assertFalse(ans); + assertEquals(BucketThrottle.capacityUnitsPerTxn(), aNow.used()); + assertEquals( + longTermEnabled && throttleType == FRONTEND_THROTTLE ? BucketThrottle.capacityUnitsPerTxn() : 0, + subject.activeThrottlesFor(CRYPTO_TRANSFER).get(0).used()); + } + + @ParameterizedTest + @CsvSource({ + "FRONTEND_THROTTLE,true,true", + "FRONTEND_THROTTLE,true,false", + "FRONTEND_THROTTLE,false,true", + "FRONTEND_THROTTLE,false,false", + "BACKEND_THROTTLE,true,true", + "BACKEND_THROTTLE,true,false", + "BACKEND_THROTTLE,false,true", + "BACKEND_THROTTLE,false,false", + }) + void doesntUseCryptoCreateThrottleForNonCryptoTransfer( + final ThrottleAccumulator.ThrottleType throttleType, + final boolean autoCreationEnabled, + final boolean lazyCreationEnabled) + throws IOException { + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, throttleType); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + given(configuration.getConfigData(SchedulingConfig.class)).willReturn(schedulingConfig); + given(schedulingConfig.longTermEnabled()).willReturn(false); + given(configuration.getConfigData(AutoCreationConfig.class)).willReturn(autoCreationConfig); + given(autoCreationConfig.enabled()).willReturn(autoCreationEnabled); + given(configuration.getConfigData(LazyCreationConfig.class)).willReturn(lazyCreationConfig); + given(lazyCreationConfig.enabled()).willReturn(lazyCreationEnabled); + + final var scheduledTxn = SchedulableTransactionBody.newBuilder() + .consensusSubmitMessage(ConsensusSubmitMessageTransactionBody.DEFAULT) + .build(); + + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles.json"); + subject.rebuildFor(defs); + + // when + final var txnInfo = scheduleCreate(scheduledTxn, false, null); + final boolean ans = subject.shouldThrottle(txnInfo, CONSENSUS_NOW, state); + final var throttlesNow = subject.activeThrottlesFor(SCHEDULE_CREATE); + final var aNow = throttlesNow.get(0); + + // then + assertFalse(ans); + assertEquals(BucketThrottle.capacityUnitsPerTxn(), aNow.used()); + } + + @ParameterizedTest + @CsvSource({ + "FRONTEND_THROTTLE,true", + "FRONTEND_THROTTLE,false", + "BACKEND_THROTTLE,true", + "BACKEND_THROTTLE,false", + }) + @MockitoSettings(strictness = org.mockito.quality.Strictness.LENIENT) + void usesCryptoCreateThrottleForCryptoTransferWithAutoCreationInScheduleCreate( + final ThrottleAccumulator.ThrottleType throttleType, final boolean longTermEnabled) throws IOException { + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, throttleType); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + given(configuration.getConfigData(SchedulingConfig.class)).willReturn(schedulingConfig); + given(schedulingConfig.longTermEnabled()).willReturn(longTermEnabled); + given(configuration.getConfigData(AutoCreationConfig.class)).willReturn(autoCreationConfig); + given(autoCreationConfig.enabled()).willReturn(true); + given(configuration.getConfigData(LazyCreationConfig.class)).willReturn(lazyCreationConfig); + given(lazyCreationConfig.enabled()).willReturn(false); + + given(state.createReadableStates(any())).willReturn(readableStates); + given(readableStates.get(any())).willReturn(aliases); + + final var alias = keyToBytes(A_PRIMITIVE_KEY); + if (!(throttleType != FRONTEND_THROTTLE && longTermEnabled)) { + given(aliases.get(any())).willReturn(null); + } + + var accountAmounts = new ArrayList(); + accountAmounts.add(AccountAmount.newBuilder() + .amount(-1_000_000_000L) + .accountID(AccountID.newBuilder().accountNum(3333L).build()) + .build()); + accountAmounts.add(AccountAmount.newBuilder() + .amount(+1_000_000_000L) + .accountID(AccountID.newBuilder().alias(alias).build()) + .build()); + final var scheduledTransferWithAutoCreation = SchedulableTransactionBody.newBuilder() + .cryptoTransfer(CryptoTransferTransactionBody.newBuilder() + .transfers(TransferList.newBuilder() + .accountAmounts(accountAmounts) + .build())) + .build(); + + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles.json"); + subject.rebuildFor(defs); + + // when + final var txnInfo = scheduleCreate(scheduledTransferWithAutoCreation, false, null); + final boolean ans = subject.shouldThrottle(txnInfo, CONSENSUS_NOW, state); + final var throttlesNow = subject.activeThrottlesFor(SCHEDULE_CREATE); + final var aNow = throttlesNow.get(0); + + // then + assertFalse(ans); + if (longTermEnabled && throttleType == FRONTEND_THROTTLE) { + // with long term enabled, we count the schedule create in addition to the auto + // creations, which + // is how it should have been to start with + assertEquals(51 * BucketThrottle.capacityUnitsPerTxn(), aNow.used()); + } else if (longTermEnabled) { + // with long term enabled, consensus throttles do not count the contained txn + assertEquals(BucketThrottle.capacityUnitsPerTxn(), aNow.used()); + } else { + assertEquals(50 * BucketThrottle.capacityUnitsPerTxn(), aNow.used()); + } + + assertEquals(0, subject.activeThrottlesFor(CRYPTO_TRANSFER).get(0).used()); + } + + @ParameterizedTest + @CsvSource({ + "FRONTEND_THROTTLE,true", + "FRONTEND_THROTTLE,false", + "BACKEND_THROTTLE,true", + "BACKEND_THROTTLE,false", + }) + @MockitoSettings(strictness = org.mockito.quality.Strictness.LENIENT) + void usesScheduleCreateThrottleForAliasedCryptoTransferWithNoAutoCreation( + final ThrottleAccumulator.ThrottleType throttleType, final boolean longTermEnabled) throws IOException { + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, throttleType); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + given(configuration.getConfigData(SchedulingConfig.class)).willReturn(schedulingConfig); + given(schedulingConfig.longTermEnabled()).willReturn(longTermEnabled); + given(configuration.getConfigData(AutoCreationConfig.class)).willReturn(autoCreationConfig); + given(autoCreationConfig.enabled()).willReturn(true); + given(configuration.getConfigData(LazyCreationConfig.class)).willReturn(lazyCreationConfig); + given(lazyCreationConfig.enabled()).willReturn(false); + + given(state.createReadableStates(any())).willReturn(readableStates); + given(readableStates.get(any())).willReturn(aliases); + + final var alias = keyToBytes(A_PRIMITIVE_KEY); + if (!(throttleType != FRONTEND_THROTTLE && longTermEnabled)) { + given(aliases.get(any())) + .willReturn(AccountID.newBuilder().accountNum(1_234L).build()); + } + + var accountAmounts = new ArrayList(); + accountAmounts.add(AccountAmount.newBuilder() + .amount(-1_000_000_000L) + .accountID(AccountID.newBuilder().accountNum(3333L).build()) + .build()); + accountAmounts.add(AccountAmount.newBuilder() + .amount(+1_000_000_000L) + .accountID(AccountID.newBuilder().alias(alias).build()) + .build()); + final var scheduledTransferWithAutoCreation = SchedulableTransactionBody.newBuilder() + .cryptoTransfer(CryptoTransferTransactionBody.newBuilder() + .transfers(TransferList.newBuilder() + .accountAmounts(accountAmounts) + .build())) + .build(); + + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles.json"); + subject.rebuildFor(defs); + + // when + final var txnInfo = scheduleCreate(scheduledTransferWithAutoCreation, false, null); + final boolean ans = subject.shouldThrottle(txnInfo, CONSENSUS_NOW, state); + final var throttlesNow = subject.activeThrottlesFor(SCHEDULE_CREATE); + final var aNow = throttlesNow.get(0); + + // then + assertFalse(ans); + assertEquals(BucketThrottle.capacityUnitsPerTxn(), aNow.used()); + + assertEquals( + longTermEnabled && throttleType == FRONTEND_THROTTLE ? BucketThrottle.capacityUnitsPerTxn() : 0, + subject.activeThrottlesFor(CRYPTO_TRANSFER).get(0).used()); + } + + @Test + void reclaimsAllUsagesOnThrottledShouldThrottleTxn() throws IOException { + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, FRONTEND_THROTTLE); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + given(configuration.getConfigData(SchedulingConfig.class)).willReturn(schedulingConfig); + given(schedulingConfig.longTermEnabled()).willReturn(true); + + final var scheduledSubmit = SchedulableTransactionBody.newBuilder() + .consensusSubmitMessage(ConsensusSubmitMessageTransactionBody.DEFAULT) + .build(); + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles-inverted.json"); + subject.rebuildFor(defs); + + final var txnInfo = scheduleCreate(scheduledSubmit, false, null); + final boolean firstAns = subject.shouldThrottle(txnInfo, CONSENSUS_NOW, state); + boolean subsequentAns = false; + for (int i = 1; i <= 150; i++) { + subsequentAns = subject.shouldThrottle(txnInfo, CONSENSUS_NOW.plusNanos(i), state); + } + + assertFalse(firstAns); + assertTrue(subsequentAns); + assertEquals( + 4999250000000L, + subject.activeThrottlesFor(SCHEDULE_CREATE).get(0).used()); + + assertEquals( + 4999999250000L, + subject.activeThrottlesFor(CONSENSUS_SUBMIT_MESSAGE).get(0).used()); + + // when + subject.resetUsage(); + + // then + assertEquals(0L, subject.activeThrottlesFor(SCHEDULE_CREATE).get(0).used()); + assertEquals( + 0L, subject.activeThrottlesFor(CONSENSUS_SUBMIT_MESSAGE).get(0).used()); + } + + @ParameterizedTest + @CsvSource({ + "FRONTEND_THROTTLE,true,true", + "FRONTEND_THROTTLE,true,false", + "FRONTEND_THROTTLE,false,true", + "FRONTEND_THROTTLE,false,false", + "BACKEND_THROTTLE,true,true", + "BACKEND_THROTTLE,true,false", + "BACKEND_THROTTLE,false,true", + "BACKEND_THROTTLE,false,false", + }) + void usesScheduleSignThrottle( + final ThrottleAccumulator.ThrottleType throttleType, + final boolean longTermEnabled, + final boolean waitForExpiry) + throws IOException { + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, throttleType); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + given(configuration.getConfigData(SchedulingConfig.class)).willReturn(schedulingConfig); + given(schedulingConfig.longTermEnabled()).willReturn(longTermEnabled); + + if (longTermEnabled && throttleType == FRONTEND_THROTTLE) { + final var scheduledSubmit = SchedulableTransactionBody.newBuilder() + .consensusSubmitMessage(ConsensusSubmitMessageTransactionBody.DEFAULT) + .build(); + + final var txnInfo = scheduleCreate(scheduledSubmit, waitForExpiry, null); + final var schedule = Schedule.newBuilder() + .waitForExpiry(txnInfo.txBody().scheduleCreate().waitForExpiry()) + .originalCreateTransaction(txnInfo.txBody()) + .payerAccountId(txnInfo.payerID()) + .scheduledTransaction(scheduledSubmit) + .build(); + + given(state.createReadableStates(any())).willReturn(readableStates); + given(readableStates.get(any())).willReturn(schedules); + given(schedules.get(SCHEDULE_ID)).willReturn(schedule); + } + + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles.json"); + subject.rebuildFor(defs); + + // when + final var txnInfo = scheduleSign(SCHEDULE_ID); + final boolean firstAns = subject.shouldThrottle(txnInfo, CONSENSUS_NOW, state); + boolean subsequentAns = false; + for (int i = 1; i <= 150; i++) { + subsequentAns = subject.shouldThrottle(txnInfo, CONSENSUS_NOW.plusNanos(i), state); + } + + final var throttlesNow = subject.activeThrottlesFor(SCHEDULE_SIGN); + final var aNow = throttlesNow.get(0); + + // then + assertFalse(firstAns); + assertTrue(subsequentAns); + assertEquals(149999992500000L, aNow.used()); + + assertEquals( + longTermEnabled && throttleType == FRONTEND_THROTTLE && (!waitForExpiry) ? 149999255000000L : 0, + subject.activeThrottlesFor(CONSENSUS_SUBMIT_MESSAGE).get(0).used()); + } + + @ParameterizedTest + @CsvSource({ + "FRONTEND_THROTTLE,true,true", + "FRONTEND_THROTTLE,true,false", + "FRONTEND_THROTTLE,false,true", + "FRONTEND_THROTTLE,false,false", + "BACKEND_THROTTLE,true,true", + "BACKEND_THROTTLE,true,false", + "BACKEND_THROTTLE,false,true", + "BACKEND_THROTTLE,false,false", + }) + void usesScheduleSignThrottleWithNestedThrottleExempt( + final ThrottleAccumulator.ThrottleType throttleType, + final boolean longTermEnabled, + final boolean waitForExpiry) + throws IOException { + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, throttleType); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + given(configuration.getConfigData(SchedulingConfig.class)).willReturn(schedulingConfig); + given(schedulingConfig.longTermEnabled()).willReturn(longTermEnabled); + + if (longTermEnabled && throttleType == FRONTEND_THROTTLE) { + final var scheduledSubmit = SchedulableTransactionBody.newBuilder() + .consensusSubmitMessage(ConsensusSubmitMessageTransactionBody.DEFAULT) + .build(); + + final var txnInfo = scheduleCreate( + scheduledSubmit, + waitForExpiry, + AccountID.newBuilder().accountNum(2L).build()); + final var schedule = Schedule.newBuilder() + .waitForExpiry(txnInfo.txBody().scheduleCreate().waitForExpiry()) + .originalCreateTransaction(txnInfo.txBody()) + .payerAccountId(AccountID.newBuilder().accountNum(2L).build()) + .scheduledTransaction(scheduledSubmit) + .build(); + + given(state.createReadableStates(any())).willReturn(readableStates); + given(readableStates.get(any())).willReturn(schedules); + given(schedules.get(SCHEDULE_ID)).willReturn(schedule); + } + + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles.json"); + subject.rebuildFor(defs); + + // when + final var txnInfo = scheduleSign(SCHEDULE_ID); + final boolean firstAns = subject.shouldThrottle(txnInfo, CONSENSUS_NOW, state); + boolean subsequentAns = false; + for (int i = 1; i <= 150; i++) { + subsequentAns = subject.shouldThrottle(txnInfo, CONSENSUS_NOW.plusNanos(i), state); + } + + final var throttlesNow = subject.activeThrottlesFor(SCHEDULE_SIGN); + final var aNow = throttlesNow.get(0); + + // then + assertFalse(firstAns); + assertTrue(subsequentAns); + assertEquals(149999992500000L, aNow.used()); + + assertEquals( + 0, subject.activeThrottlesFor(CONSENSUS_SUBMIT_MESSAGE).get(0).used()); + } + + @Test + void scheduleSignAlwaysThrottledWhenNoBody() throws IOException { + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, FRONTEND_THROTTLE); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + given(configuration.getConfigData(SchedulingConfig.class)).willReturn(schedulingConfig); + given(schedulingConfig.longTermEnabled()).willReturn(true); + + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles.json"); + subject.rebuildFor(defs); + + final var scheduleCreateTxnInfo = scheduleCreate(SchedulableTransactionBody.DEFAULT, false, null); + final var schedule = Schedule.newBuilder() + .waitForExpiry(scheduleCreateTxnInfo.txBody().scheduleCreate().waitForExpiry()) + .originalCreateTransaction(scheduleCreateTxnInfo.txBody()) + .payerAccountId(AccountID.newBuilder().accountNum(2L).build()) + .scheduledTransaction(SchedulableTransactionBody.DEFAULT) + .build(); + + given(state.createReadableStates(any())).willReturn(readableStates); + given(readableStates.get(any())).willReturn(schedules); + given(schedules.get(SCHEDULE_ID)).willReturn(schedule); + + // when + final var scheduleSignTxnInfo = scheduleSign(SCHEDULE_ID); + final var firstAns = subject.shouldThrottle(scheduleSignTxnInfo, CONSENSUS_NOW, state); + for (int i = 1; i <= 150; i++) { + assertTrue(subject.shouldThrottle(scheduleSignTxnInfo, CONSENSUS_NOW.plusNanos(i), state)); + } + + final var throttlesNow = subject.activeThrottlesFor(SCHEDULE_SIGN); + final var aNow = throttlesNow.get(0); + + // then + assertTrue(firstAns); + assertEquals(0L, aNow.used()); + assertEquals( + 0, subject.activeThrottlesFor(CONSENSUS_SUBMIT_MESSAGE).get(0).used()); + } + + @Test + void scheduleSignAlwaysThrottledWhenNotExisting() throws IOException { + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, FRONTEND_THROTTLE); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + given(configuration.getConfigData(SchedulingConfig.class)).willReturn(schedulingConfig); + given(schedulingConfig.longTermEnabled()).willReturn(true); + + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles.json"); + subject.rebuildFor(defs); + + given(state.createReadableStates(any())).willReturn(readableStates); + given(readableStates.get(any())).willReturn(schedules); + + // when + final var scheduleSignTxnInfo = scheduleSign(SCHEDULE_ID); + final var firstAns = subject.shouldThrottle(scheduleSignTxnInfo, CONSENSUS_NOW, state); + for (int i = 1; i <= 150; i++) { + assertTrue(subject.shouldThrottle(scheduleSignTxnInfo, CONSENSUS_NOW.plusNanos(i), state)); + } + + final var throttlesNow = subject.activeThrottlesFor(SCHEDULE_SIGN); + final var aNow = throttlesNow.get(0); + + assertTrue(firstAns); + assertEquals(0L, aNow.used()); + + assertEquals( + 0, subject.activeThrottlesFor(CONSENSUS_SUBMIT_MESSAGE).get(0).used()); + } + + @ParameterizedTest + @CsvSource({ + "FRONTEND_THROTTLE,true", + "FRONTEND_THROTTLE,false", + "BACKEND_THROTTLE,true", + "BACKEND_THROTTLE,false", + }) + @MockitoSettings(strictness = org.mockito.quality.Strictness.LENIENT) + void usesCryptoCreateThrottleForCryptoTransferWithAutoCreationInScheduleSign( + final ThrottleAccumulator.ThrottleType throttleType, final boolean longTermEnabled) throws IOException { + + // given + subject = new ThrottleAccumulator(() -> CAPACITY_SPLIT, configProvider, throttleType); + + given(configProvider.getConfiguration()).willReturn(configuration); + given(configuration.getConfigData(AccountsConfig.class)).willReturn(accountsConfig); + given(accountsConfig.lastThrottleExempt()).willReturn(100L); + given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); + given(contractsConfig.throttleThrottleByGas()).willReturn(false); + given(configuration.getConfigData(SchedulingConfig.class)).willReturn(schedulingConfig); + given(schedulingConfig.longTermEnabled()).willReturn(longTermEnabled); + given(configuration.getConfigData(AutoCreationConfig.class)).willReturn(autoCreationConfig); + given(autoCreationConfig.enabled()).willReturn(true); + given(configuration.getConfigData(LazyCreationConfig.class)).willReturn(lazyCreationConfig); + given(lazyCreationConfig.enabled()).willReturn(false); + + given(state.createReadableStates(any())).willReturn(readableStates); + given(readableStates.get("ALIASES")).willReturn(aliases); + + final var alias = keyToBytes(A_PRIMITIVE_KEY); + if (throttleType == FRONTEND_THROTTLE && longTermEnabled) { + given(aliases.get(any())).willReturn(null); + } + + if (longTermEnabled && throttleType == FRONTEND_THROTTLE) { + var accountAmounts = new ArrayList(); + accountAmounts.add(AccountAmount.newBuilder() + .amount(-1_000_000_000L) + .accountID(AccountID.newBuilder().accountNum(3333L).build()) + .build()); + accountAmounts.add(AccountAmount.newBuilder() + .amount(+1_000_000_000L) + .accountID(AccountID.newBuilder().alias(alias).build()) + .build()); + final var scheduledTransferWithAutoCreation = SchedulableTransactionBody.newBuilder() + .cryptoTransfer(CryptoTransferTransactionBody.newBuilder() + .transfers(TransferList.newBuilder() + .accountAmounts(accountAmounts) + .build())) + .build(); + + final var scheduleCreateTxnInfo = scheduleCreate(scheduledTransferWithAutoCreation, false, null); + final var schedule = Schedule.newBuilder() + .waitForExpiry( + scheduleCreateTxnInfo.txBody().scheduleCreate().waitForExpiry()) + .originalCreateTransaction(scheduleCreateTxnInfo.txBody()) + .payerAccountId(scheduleCreateTxnInfo.payerID()) + .scheduledTransaction(scheduledTransferWithAutoCreation) + .build(); + given(readableStates.get(SCHEDULES_BY_ID_KEY)).willReturn(schedules); + given(schedules.get(SCHEDULE_ID)).willReturn(schedule); + } + + final var defs = getThrottleDefs("bootstrap/schedule-create-throttles.json"); + subject.rebuildFor(defs); + + // when + final var scheduleSignTxnInfo = scheduleSign(SCHEDULE_ID); + final var ans = subject.shouldThrottle(scheduleSignTxnInfo, CONSENSUS_NOW, state); + final var throttlesNow = subject.activeThrottlesFor(SCHEDULE_SIGN); + final var aNow = throttlesNow.get(0); + + // then + assertFalse(ans); + if (longTermEnabled && throttleType == FRONTEND_THROTTLE) { + // with long term enabled, we count the schedule create in addition to the auto + // creations, which + // is how it should have been to start with + assertEquals(51 * BucketThrottle.capacityUnitsPerTxn(), aNow.used()); + } else { + // with long term disabled or mode not being HAPI, ScheduleSign is the only part that + // counts + assertEquals(BucketThrottle.capacityUnitsPerTxn(), aNow.used()); + } + + assertEquals(0, subject.activeThrottlesFor(CRYPTO_TRANSFER).get(0).used()); + } + + @NotNull + private static Bytes keyToBytes(Key key) throws IOException { + final var dataBuffer = getThreadLocalDataBuffer(); + Key.PROTOBUF.write(key, dataBuffer); + // clamp limit to bytes written + dataBuffer.limit(dataBuffer.position()); + return dataBuffer.getBytes(0, dataBuffer.length()); + } + + private TransactionInfo scheduleCreate( + final SchedulableTransactionBody inner, boolean waitForExpiry, AccountID customPayer) { + final var schedule = ScheduleCreateTransactionBody.newBuilder() + .waitForExpiry(waitForExpiry) + .scheduledTransactionBody(inner); + if (customPayer != null) { + schedule.payerAccountID(customPayer); + } + final var body = TransactionBody.newBuilder() + .transactionID(TransactionID.newBuilder().accountID(PAYER_ID).build()) + .scheduleCreate(schedule) + .build(); + final var txn = Transaction.newBuilder().body(body).build(); + return new TransactionInfo( + txn, + body, + TransactionID.newBuilder().accountID(PAYER_ID).build(), + PAYER_ID, + SignatureMap.DEFAULT, + Bytes.EMPTY, + SCHEDULE_CREATE); + } + + private TransactionInfo scheduleSign(ScheduleID scheduleID) { + final var schedule = ScheduleSignTransactionBody.newBuilder().scheduleID(scheduleID); + final var body = TransactionBody.newBuilder() + .transactionID(TransactionID.newBuilder().accountID(PAYER_ID).build()) + .scheduleSign(schedule) + .build(); + final var txn = Transaction.newBuilder().body(body).build(); + return new TransactionInfo( + txn, + body, + TransactionID.newBuilder().accountID(PAYER_ID).build(), + PAYER_ID, + SignatureMap.DEFAULT, + Bytes.EMPTY, + SCHEDULE_SIGN); + } + + private ThrottleDefinitions getThrottleDefs(String testResource) throws IOException { + try (InputStream in = ThrottleDefinitions.class.getClassLoader().getResourceAsStream(testResource)) { + var om = new ObjectMapper(); + var throttleDefinitionsObj = om.readValue( + in, com.hedera.node.app.hapi.utils.sysfiles.domain.throttling.ThrottleDefinitions.class); + final var throttleDefsBytes = + Bytes.wrap(throttleDefinitionsObj.toProto().toByteArray()); + return ThrottleDefinitions.PROTOBUF.parse(throttleDefsBytes.toReadableSequentialData()); + } + } + + private CryptoTransferTransactionBody cryptoTransferWithImplicitCreations(int numImplicitCreations) { + var accountAmounts = new ArrayList(); + for (int i = 1; i <= numImplicitCreations; i++) { + accountAmounts.add(AccountAmount.newBuilder() + .accountID(AccountID.newBuilder() + .alias(Bytes.wrap("abcdeabcdeabcdeabcde")) + .build()) + .amount(i) + .build()); + } + + return CryptoTransferTransactionBody.newBuilder() + .transfers( + TransferList.newBuilder().accountAmounts(accountAmounts).build()) + .build(); + } +} diff --git a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/HandleContextImplTest.java b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/HandleContextImplTest.java index b5e246c7032f..59c147e428bc 100644 --- a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/HandleContextImplTest.java +++ b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/HandleContextImplTest.java @@ -720,7 +720,7 @@ void testGetRecordBuilder() { @Test void testAddChildRecordBuilder(@Mock final SingleTransactionRecordBuilderImpl childRecordBuilder) { // given - when(recordListBuilder.addChild(any())).thenReturn(childRecordBuilder); + when(recordListBuilder.addChild(any(), any())).thenReturn(childRecordBuilder); final var context = createContext(defaultTransactionBody()); // when @@ -796,7 +796,7 @@ void setup() { when(recordListBuilder.addPreceding(any(), eq(LIMITED_CHILD_RECORDS))) .thenReturn(childRecordBuilder); when(recordListBuilder.addReversiblePreceding(any())).thenReturn(childRecordBuilder); - when(recordListBuilder.addChild(any())).thenReturn(childRecordBuilder); + when(recordListBuilder.addChild(any(), any())).thenReturn(childRecordBuilder); when(recordListBuilder.addRemovableChild(any())).thenReturn(childRecordBuilder); when(recordListBuilder.addRemovableChildWithExternalizationCustomizer(any(), any())) .thenReturn(childRecordBuilder); diff --git a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/record/RecordListBuilderTest.java b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/record/RecordListBuilderTest.java index 46636be70e29..8f6ec39b1e00 100644 --- a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/record/RecordListBuilderTest.java +++ b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/record/RecordListBuilderTest.java @@ -19,6 +19,7 @@ import static com.hedera.hapi.node.base.ResponseCodeEnum.ACCOUNT_ID_DOES_NOT_EXIST; import static com.hedera.hapi.node.base.ResponseCodeEnum.OK; import static com.hedera.hapi.node.base.ResponseCodeEnum.REVERTED_SUCCESS; +import static com.hedera.node.app.spi.workflows.HandleContext.TransactionCategory.CHILD; import static com.hedera.node.app.spi.workflows.record.ExternalizedRecordCustomizer.SUPPRESSING_EXTERNALIZED_RECORD_CUSTOMIZER; import static com.hedera.node.app.workflows.handle.HandleContextImpl.PrecedingTransactionCategory.LIMITED_CHILD_RECORDS; import static org.assertj.core.api.Assertions.assertThat; @@ -322,7 +323,7 @@ void testRevertingChildDoesNotRevertPreceding() { final var recordListBuilder = new RecordListBuilder(consensusTime); addUserTransaction(recordListBuilder); recordListBuilder.addReversiblePreceding(CONFIGURATION).transaction(simpleCryptoTransfer()); - final var child = recordListBuilder.addChild(CONFIGURATION).transaction(simpleCryptoTransfer()); + final var child = recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(simpleCryptoTransfer()); // when recordListBuilder.revertChildrenOf(child); @@ -400,7 +401,7 @@ void testAddSingleChild() { addUserTransaction(recordListBuilder); // when - recordListBuilder.addChild(CONFIGURATION).transaction(simpleCryptoTransfer()); + recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(simpleCryptoTransfer()); final var result = recordListBuilder.build(); final var records = result.records(); @@ -422,8 +423,8 @@ void testAddMultipleChildren() { addUserTransaction(recordListBuilder); // when - recordListBuilder.addChild(CONFIGURATION).transaction(simpleCryptoTransfer()); - recordListBuilder.addChild(CONFIGURATION).transaction(simpleCryptoTransfer()); + recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(simpleCryptoTransfer()); + recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(simpleCryptoTransfer()); final var result = recordListBuilder.build(); final var records = result.records(); @@ -454,11 +455,11 @@ void testAddTooManyChildrenFails() { addUserTransaction(recordListBuilder); // when - recordListBuilder.addChild(config); - recordListBuilder.addChild(config); + recordListBuilder.addChild(config, CHILD); + recordListBuilder.addChild(config, CHILD); // then - assertThatThrownBy(() -> recordListBuilder.addChild(config)) + assertThatThrownBy(() -> recordListBuilder.addChild(config, CHILD)) .isInstanceOf(HandleException.class) .hasFieldOrPropertyWithValue("status", ResponseCodeEnum.MAX_CHILD_RECORDS_EXCEEDED); } @@ -476,10 +477,10 @@ void testAddPrecedingAndChildRecords() throws IOException { final var fourth = simpleCryptoTransferWithNonce(txnId, 3); final var fifth = simpleCryptoTransferWithNonce(txnId, 4); // mixing up preceding vs. following, but within which, in order - recordListBuilder.addChild(CONFIGURATION).transaction(fourth); + recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(fourth); recordListBuilder.addPreceding(CONFIGURATION, LIMITED_CHILD_RECORDS).transaction(first); recordListBuilder.addPreceding(CONFIGURATION, LIMITED_CHILD_RECORDS).transaction(second); - recordListBuilder.addChild(CONFIGURATION).transaction(fifth); + recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(fifth); final var result = recordListBuilder.build(); final var records = result.records(); @@ -515,11 +516,11 @@ void testRevertSingleChild() { final var consensusTime = Instant.now(); final var recordListBuilder = new RecordListBuilder(consensusTime); final var base = addUserTransaction(recordListBuilder); - recordListBuilder.addChild(CONFIGURATION).transaction(simpleCryptoTransfer()); + recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(simpleCryptoTransfer()); // when recordListBuilder.revertChildrenOf(base); - recordListBuilder.addChild(CONFIGURATION).transaction(simpleCryptoTransfer()); + recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(simpleCryptoTransfer()); final var result = recordListBuilder.build(); final var records = result.records(); @@ -558,14 +559,14 @@ void testRevertMultipleChildren() { final var consensusTime = Instant.now(); final var recordListBuilder = new RecordListBuilder(consensusTime); addUserTransaction(recordListBuilder); - final var child1 = recordListBuilder.addChild(CONFIGURATION).transaction(simpleCryptoTransfer()); - recordListBuilder.addChild(CONFIGURATION).transaction(simpleCryptoTransfer()); - final var child3 = recordListBuilder.addChild(CONFIGURATION).transaction(simpleCryptoTransfer()); + final var child1 = recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(simpleCryptoTransfer()); + recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(simpleCryptoTransfer()); + final var child3 = recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(simpleCryptoTransfer()); child3.status(ACCOUNT_ID_DOES_NOT_EXIST); // when recordListBuilder.revertChildrenOf(child1); - recordListBuilder.addChild(CONFIGURATION).transaction(simpleCryptoTransfer()); + recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(simpleCryptoTransfer()); final var result = recordListBuilder.build(); final var records = result.records(); @@ -780,14 +781,14 @@ void testRevertMultipleMixedChildren() { final var child1Tx = simpleCryptoTransferWithNonce(baseTxnId, 1); recordListBuilder.addRemovableChild(CONFIGURATION).transaction(child1Tx); final var child2Tx = simpleCryptoTransferWithNonce(baseTxnId, 2); - recordListBuilder.addChild(CONFIGURATION).transaction(child2Tx); + recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(child2Tx); final var child3Tx = simpleCryptoTransferWithNonce(baseTxnId, 3); - final var child3 = recordListBuilder.addChild(CONFIGURATION).transaction(child3Tx); + final var child3 = recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(child3Tx); recordListBuilder.addRemovableChild(CONFIGURATION).transaction(simpleCryptoTransfer()); // will be removed final var child5Tx = simpleCryptoTransferWithNonce(baseTxnId, 4); - recordListBuilder.addChild(CONFIGURATION).transaction(child5Tx); // will revert + recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(child5Tx); // will revert final var child6Tx = simpleCryptoTransferWithNonce(baseTxnId, 5); - recordListBuilder.addChild(CONFIGURATION).transaction(child6Tx); // will revert + recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(child6Tx); // will revert recordListBuilder.addRemovableChild(CONFIGURATION).transaction(simpleCryptoTransfer()); // will be removed // when @@ -795,7 +796,7 @@ void testRevertMultipleMixedChildren() { final var child8Tx = simpleCryptoTransferWithNonce(baseTxnId, 6); recordListBuilder.addRemovableChild(CONFIGURATION).transaction(child8Tx); final var child9Tx = simpleCryptoTransferWithNonce(baseTxnId, 7); - recordListBuilder.addChild(CONFIGURATION).transaction(child9Tx); + recordListBuilder.addChild(CONFIGURATION, CHILD).transaction(child9Tx); final var result = recordListBuilder.build(); final var records = result.records(); diff --git a/hedera-node/hedera-app/src/test/resources/bootstrap/schedule-create-throttles-inverted.json b/hedera-node/hedera-app/src/test/resources/bootstrap/schedule-create-throttles-inverted.json new file mode 100644 index 000000000000..7327ede332aa --- /dev/null +++ b/hedera-node/hedera-app/src/test/resources/bootstrap/schedule-create-throttles-inverted.json @@ -0,0 +1,42 @@ +{ + "buckets": [ + { + "name": "A", + "burstPeriod": 1, + "throttleGroups": [ + { + "operations": [ + "ContractCallLocal" + ], + "opsPerSec": 1 + } + ] + }, + { + "name": "A", + "burstPeriod": 1, + "throttleGroups": [ + { + "operations": [ + "CryptoTransfer", + "ConsensusSubmitMessage" + ], + "opsPerSec": 10 + } + ] + }, + { + "name": "C", + "burstPeriod": 1, + "throttleGroups": [ + { + "operations": [ + "ScheduleCreate", + "ScheduleSign" + ], + "opsPerSec": 10000 + } + ] + } + ] +} diff --git a/hedera-node/hedera-app/src/test/resources/bootstrap/schedule-create-throttles.json b/hedera-node/hedera-app/src/test/resources/bootstrap/schedule-create-throttles.json new file mode 100644 index 000000000000..4e40aefda917 --- /dev/null +++ b/hedera-node/hedera-app/src/test/resources/bootstrap/schedule-create-throttles.json @@ -0,0 +1,36 @@ +{ + "buckets": [ + { + "name": "A", + "burstPeriod": 2, + "throttleGroups": [ + { + "operations": [ + "CryptoTransfer", + "ConsensusSubmitMessage" + ], + "opsPerSec": 10000 + } + ] + }, + { + "name": "C", + "burstPeriod": 3, + "throttleGroups": [ + { + "operations": [ + "CryptoCreate" + ], + "opsPerSec": 2 + }, + { + "operations": [ + "ScheduleCreate", + "ScheduleSign" + ], + "opsPerSec": 100 + } + ] + } + ] +} diff --git a/hedera-node/hedera-app/src/xtest/java/contract/AbstractContractXTest.java b/hedera-node/hedera-app/src/xtest/java/contract/AbstractContractXTest.java index b6e61571ce8b..15e3acad6694 100644 --- a/hedera-node/hedera-app/src/xtest/java/contract/AbstractContractXTest.java +++ b/hedera-node/hedera-app/src/xtest/java/contract/AbstractContractXTest.java @@ -83,10 +83,12 @@ import java.util.Map; import java.util.Optional; import java.util.function.Consumer; +import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.precompile.PrecompiledContract; import org.junit.jupiter.api.BeforeEach; import org.mockito.Mock; +import org.mockito.Mockito; /** * Base class for {@code xtest} scenarios that focus on contract operations. @@ -296,6 +298,7 @@ private void runHtsCallAndExpect( stack.addFirst(frame); given(frame.getMessageFrameStack()).willReturn(stack); given(addressChecks.hasParentDelegateCall(frame)).willReturn(requiresDelegatePermission); + Mockito.lenient().when(frame.getValue()).thenReturn(Wei.MAX_WEI); final var attempt = callAttemptFactory.createCallAttemptFrom(input, frame); final var call = attempt.asExecutableCall(); diff --git a/hedera-node/hedera-app/src/xtest/java/contract/BurnsXTest.java b/hedera-node/hedera-app/src/xtest/java/contract/BurnsXTest.java index 7af7ece147ab..40f9991ce493 100644 --- a/hedera-node/hedera-app/src/xtest/java/contract/BurnsXTest.java +++ b/hedera-node/hedera-app/src/xtest/java/contract/BurnsXTest.java @@ -16,14 +16,20 @@ package contract; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_BURN_AMOUNT; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_ID; +import static com.hedera.hapi.node.base.ResponseCodeEnum.SUCCESS; import static com.hedera.hapi.node.base.ResponseCodeEnum.TOKEN_HAS_NO_SUPPLY_KEY; import static com.hedera.hapi.node.base.ResponseCodeEnum.TOKEN_NOT_ASSOCIATED_TO_ACCOUNT; import static contract.AssociationsXTestConstants.A_TOKEN_ADDRESS; import static contract.AssociationsXTestConstants.A_TOKEN_ID; import static contract.AssociationsXTestConstants.B_TOKEN_ADDRESS; import static contract.AssociationsXTestConstants.B_TOKEN_ID; +import static contract.AssociationsXTestConstants.C_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.C_TOKEN_ID; +import static contract.AssociationsXTestConstants.D_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.D_TOKEN_ID; import static contract.HtsErc721TransferXTestConstants.APPROVED_ID; import static contract.HtsErc721TransferXTestConstants.UNAUTHORIZED_SPENDER_ADDRESS; import static contract.HtsErc721TransferXTestConstants.UNAUTHORIZED_SPENDER_ID; @@ -44,7 +50,6 @@ import static contract.XTestConstants.SN_2345; import static contract.XTestConstants.addErc20Relation; import static contract.XTestConstants.addErc721Relation; -import static contract.XTestConstants.assertSuccess; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -58,8 +63,8 @@ import com.hedera.hapi.node.state.token.Nft; import com.hedera.hapi.node.state.token.Token; import com.hedera.hapi.node.state.token.TokenRelation; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.burn.BurnTranslator; +import com.hedera.node.app.spi.fixtures.Scenarios; import com.hedera.node.app.spi.state.ReadableKVState; import java.math.BigInteger; import java.util.HashMap; @@ -68,6 +73,27 @@ import org.apache.tuweni.bytes.Bytes; import org.jetbrains.annotations.NotNull; +/** + * Exercises burnToken on a fungible and non-fungible token via the following steps relative to an {@code OWNER} account: + *

    + *
  1. Burns {@code ERC20_TOKEN} via BURN_TOKEN_V1 operation
  2. + *
  3. Burns {@code ERC20_TOKEN} via BURN_TOKEN_V2 operation
  4. + *
  5. Burns {@code ERC20_TOKEN} without supplyKey via BURN_TOKEN_V1 operation. This should fail with TOKEN_HAS_NO_SUPPLY_KEY
  6. + *
  7. Burns {@code ERC20_TOKEN} without supplyKey via BURN_TOKEN_V2 operation. This should fail with TOKEN_HAS_NO_SUPPLY_KEY
  8. + *
  9. Burns {@code ERC20_TOKEN} token which is not associated to account via BURN_TOKEN_V1 operation. This should fail with TOKEN_NOT_ASSOCIATED_TO_ACCOUNT
  10. + *
  11. Burns {@code ERC20_TOKEN} token which is not associated to account via BURN_TOKEN_V2 operation. This should fail with TOKEN_NOT_ASSOCIATED_TO_ACCOUNT
  12. + *
  13. Burns {@code ERC20_TOKEN} token when totalSupply < amountToBurn via BURN_TOKEN_V1 operation. This should fail with INVALID_TOKEN_BURN_AMOUNT
  14. + *
  15. Burns {@code ERC20_TOKEN} token when totalSupply < amountToBurn via BURN_TOKEN_V2 operation. This should fail with INVALID_TOKEN_BURN_AMOUNT
  16. + *
  17. Burns {@code ERC20_TOKEN} token with invalid id via BURN_TOKEN_V1 operation. This should fail with INVALID_TOKEN_ID
  18. + *
  19. Burns {@code ERC20_TOKEN} token with invalid id via BURN_TOKEN_V2 operation. This should fail with INVALID_TOKEN_ID
  20. + *
  21. Burns {@code ERC20_TOKEN} with invalid supplyKey via BURN_TOKEN_V1 operation. This should fail with INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE
  22. + *
  23. Burns {@code ERC20_TOKEN} with invalid supplyKey via BURN_TOKEN_V2 operation. This should fail with INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE
  24. + *
  25. Burns {@code ERC721_TOKEN} via BURN_TOKEN_V1 operation
  26. + *
  27. Burns {@code ERC721_TOKEN} via BURN_TOKEN_V2 operation
  28. + *
  29. Burns {@code ERC721_TOKEN} with invalid supplyKey via BURN_TOKEN_V1 operation. This should fail with INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE
  30. + *
  31. Burns {@code ERC721_TOKEN} with invalid supplyKey via BURN_TOKEN_V2 operation. This should fail with INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE
  32. + *
+ */ public class BurnsXTest extends AbstractContractXTest { private static final long TOKEN_BALANCE = 9L; @@ -75,80 +101,215 @@ public class BurnsXTest extends AbstractContractXTest { @Override protected void doScenarioOperations() { - // should successfully burn fungible token with V1 + // should successfully burn fungible token via V1 runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 .encodeCallWithArgs(ERC20_TOKEN_ADDRESS, BigInteger.valueOf(TOKENS_TO_BURN), new long[] {}) .array()), - assertSuccess()); + output -> assertEquals( + Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 + .getOutputs() + .encodeElements((long) SUCCESS.protoOrdinal(), TOKEN_BALANCE - TOKENS_TO_BURN) + .array()), + output)); - // should successfully burn fungible token with V2 + // should successfully burn fungible token via V2 runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 .encodeCallWithArgs(ERC20_TOKEN_ADDRESS, TOKENS_TO_BURN, new long[] {}) .array()), - assertSuccess()); + output -> assertEquals( + Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 + .getOutputs() + .encodeElements((long) SUCCESS.protoOrdinal(), TOKEN_BALANCE - 2L) + .array()), + output)); - // should fail when token has no supplyKey + // should fail when token has no supplyKey via V1 runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 .encodeCallWithArgs(A_TOKEN_ADDRESS, BigInteger.valueOf(TOKENS_TO_BURN), new long[] {}) .array()), output -> assertEquals( - Bytes.wrap( - ReturnTypes.encodedRc(TOKEN_HAS_NO_SUPPLY_KEY).array()), + Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 + .getOutputs() + .encodeElements((long) TOKEN_HAS_NO_SUPPLY_KEY.protoOrdinal(), 0L) + .array()), + output)); + + // should fail when token has no supplyKey via V2 + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 + .encodeCallWithArgs(A_TOKEN_ADDRESS, TOKENS_TO_BURN, new long[] {}) + .array()), + output -> assertEquals( + Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 + .getOutputs() + .encodeElements((long) TOKEN_HAS_NO_SUPPLY_KEY.protoOrdinal(), 0L) + .array()), output)); - // should fail when token is not associated to account + // should fail when token is not associated to account via V1 runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 .encodeCallWithArgs(B_TOKEN_ADDRESS, BigInteger.valueOf(TOKENS_TO_BURN), new long[] {}) .array()), output -> assertEquals( - Bytes.wrap(ReturnTypes.encodedRc(TOKEN_NOT_ASSOCIATED_TO_ACCOUNT) + Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 + .getOutputs() + .encodeElements((long) TOKEN_NOT_ASSOCIATED_TO_ACCOUNT.protoOrdinal(), 0L) + .array()), + output)); + + // should fail when token is not associated to account via V2 + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 + .encodeCallWithArgs(B_TOKEN_ADDRESS, TOKENS_TO_BURN, new long[] {}) + .array()), + output -> assertEquals( + Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 + .getOutputs() + .encodeElements((long) TOKEN_NOT_ASSOCIATED_TO_ACCOUNT.protoOrdinal(), 0L) .array()), output)); - // should fail on totalSupply < amountToBurn + // should fail on totalSupply < amountToBurn via V1 runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 .encodeCallWithArgs(ERC20_TOKEN_ADDRESS, BigInteger.valueOf(TOKEN_BALANCE + 1), new long[] {}) .array()), output -> assertEquals( - Bytes.wrap( - ReturnTypes.encodedRc(INVALID_TOKEN_BURN_AMOUNT).array()), + Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 + .getOutputs() + .encodeElements((long) INVALID_TOKEN_BURN_AMOUNT.protoOrdinal(), 0L) + .array()), + output)); + + // should fail on totalSupply < amountToBurn via V2 + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 + .encodeCallWithArgs(ERC20_TOKEN_ADDRESS, TOKEN_BALANCE + 1, new long[] {}) + .array()), + output -> assertEquals( + Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 + .getOutputs() + .encodeElements((long) INVALID_TOKEN_BURN_AMOUNT.protoOrdinal(), 0L) + .array()), output)); - // should fail on invalid token id + // should fail on invalid token id via V2 runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 .encodeCallWithArgs(INVALID_TOKEN_ADDRESS, BigInteger.valueOf(TOKEN_BALANCE + 1), new long[] {}) .array()), output -> assertEquals( - Bytes.wrap(ReturnTypes.encodedRc(INVALID_TOKEN_ID).array()), output)); + Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 + .getOutputs() + .encodeElements((long) INVALID_TOKEN_ID.protoOrdinal(), 0L) + .array()), + output)); + + // should fail on invalid token id via V2 + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 + .encodeCallWithArgs(INVALID_TOKEN_ADDRESS, TOKEN_BALANCE + 1, new long[] {}) + .array()), + output -> assertEquals( + Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 + .getOutputs() + .encodeElements((long) INVALID_TOKEN_ID.protoOrdinal(), 0L) + .array()), + output)); + + // should fail when token has wrong supplyKey via V1 + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 + .encodeCallWithArgs(C_TOKEN_ADDRESS, BigInteger.valueOf(TOKENS_TO_BURN), new long[] {}) + .array()), + output -> assertEquals( + Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 + .getOutputs() + .encodeElements((long) INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE.protoOrdinal(), 0L) + .array()), + output)); + + // should fail when token has wrong supplyKey via V2 + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 + .encodeCallWithArgs(C_TOKEN_ADDRESS, TOKENS_TO_BURN, new long[] {}) + .array()), + output -> assertEquals( + Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 + .getOutputs() + .encodeElements((long) INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE.protoOrdinal(), 0L) + .array()), + output)); - // should successfully burn NFT with V1 + // should successfully burn NFT via V1 runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 .encodeCallWithArgs( ERC721_TOKEN_ADDRESS, BigInteger.valueOf(0L), new long[] {SN_1234.serialNumber()}) .array()), - assertSuccess()); + output -> assertEquals( + Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 + .getOutputs() + .encodeElements((long) SUCCESS.protoOrdinal(), TOKEN_BALANCE - TOKENS_TO_BURN) + .array()), + output)); - // should successfully burn NFT with V2 + // should successfully burn NFT via V2 runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 .encodeCallWithArgs(ERC721_TOKEN_ADDRESS, 0L, new long[] {SN_2345.serialNumber()}) .array()), - assertSuccess()); + output -> assertEquals( + Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 + .getOutputs() + .encodeElements((long) SUCCESS.protoOrdinal(), TOKEN_BALANCE - 2) + .array()), + output)); + + // should fail when NFT has wrong supplyKey via V1 + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 + .encodeCallWithArgs( + D_TOKEN_ADDRESS, BigInteger.valueOf(0L), new long[] {SN_1234.serialNumber()}) + .array()), + output -> assertEquals( + Bytes.wrap(BurnTranslator.BURN_TOKEN_V1 + .getOutputs() + .encodeElements((long) INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE.protoOrdinal(), 0L) + .array()), + output)); + + // should fail when NFT has wrong supplyKey via V2 + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 + .encodeCallWithArgs(D_TOKEN_ADDRESS, 0L, new long[] {SN_1234.serialNumber()}) + .array()), + output -> assertEquals( + Bytes.wrap(BurnTranslator.BURN_TOKEN_V2 + .getOutputs() + .encodeElements((long) INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE.protoOrdinal(), 0L) + .array()), + output)); } @Override @@ -207,6 +368,15 @@ protected Map initialTokens() { .supplyKey(AN_ED25519_KEY) .totalSupply(TOKEN_BALANCE) .build()); + tokens.put( + C_TOKEN_ID, + Token.newBuilder() + .tokenId(C_TOKEN_ID) + .treasuryAccountId(OWNER_ID) + .tokenType(TokenType.FUNGIBLE_COMMON) + .supplyKey(Scenarios.ALICE.account().key()) + .totalSupply(TOKEN_BALANCE) + .build()); tokens.put( ERC721_TOKEN_ID, Token.newBuilder() @@ -216,6 +386,15 @@ protected Map initialTokens() { .supplyKey(AN_ED25519_KEY) .totalSupply(TOKEN_BALANCE) .build()); + tokens.put( + D_TOKEN_ID, + Token.newBuilder() + .tokenId(D_TOKEN_ID) + .treasuryAccountId(OWNER_ID) + .tokenType(TokenType.NON_FUNGIBLE_UNIQUE) + .supplyKey(Scenarios.ALICE.account().key()) + .totalSupply(TOKEN_BALANCE) + .build()); return tokens; } diff --git a/hedera-node/hedera-app/src/xtest/java/contract/DeleteXTest.java b/hedera-node/hedera-app/src/xtest/java/contract/DeleteXTest.java index 0426b1001b51..a2d2c7f78c50 100644 --- a/hedera-node/hedera-app/src/xtest/java/contract/DeleteXTest.java +++ b/hedera-node/hedera-app/src/xtest/java/contract/DeleteXTest.java @@ -16,10 +16,21 @@ package contract; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_ID; import static com.hedera.hapi.node.base.ResponseCodeEnum.TOKEN_IS_IMMUTABLE; import static com.hedera.hapi.node.base.ResponseCodeEnum.TOKEN_WAS_DELETED; import static com.hedera.node.app.service.contract.impl.utils.ConversionUtils.asHeadlongAddress; +import static contract.AssociationsXTestConstants.A_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.A_TOKEN_ID; +import static contract.AssociationsXTestConstants.B_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.B_TOKEN_ID; +import static contract.AssociationsXTestConstants.C_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.C_TOKEN_ID; +import static contract.AssociationsXTestConstants.D_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.D_TOKEN_ID; +import static contract.HtsErc721TransferXTestConstants.UNAUTHORIZED_SPENDER_ID; +import static contract.XTestConstants.AN_ED25519_KEY; import static contract.XTestConstants.ERC20_TOKEN_ADDRESS; import static contract.XTestConstants.ERC20_TOKEN_ID; import static contract.XTestConstants.ERC721_TOKEN_ADDRESS; @@ -50,6 +61,20 @@ import java.util.Map; import org.apache.tuweni.bytes.Bytes; +/** + * Exercises delete on a fungible and non-fungible token via the following steps relative to an {@code OWNER} account: + *
    + *
  1. Deletes {@code ERC20_TOKEN} via DELETE operation
  2. + *
  3. Deletes {@code ERC721_TOKEN} via DELETE operation
  4. + *
  5. Freezes a deleted {@code ERC20_TOKEN}. This should fail with TOKEN_WAS_DELETED
  6. + *
  7. Freezes a deleted {@code ERC721_TOKEN}. This should fail with TOKEN_WAS_DELETED
  8. + *
  9. Deletes {@code ERC20_TOKEN} without admin key. This should fail with TOKEN_IS_IMMUTABLE
  10. + *
  11. Deletes {@code ERC721_TOKEN} without admin key. This should fail with TOKEN_IS_IMMUTABLE
  12. + *
  13. Deletes {@code ERC20_TOKEN} with wrong admin key. This should fail with INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE
  14. + *
  15. Deletes {@code ERC721_TOKEN} with wrong admin key. This should fail with INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE
  16. + *
  17. Deletes token with invalid token address via DELETE operation. This should fail with INVALID_TOKEN_ID
  18. + *
+ */ public class DeleteXTest extends AbstractContractXTest { @Override protected void doScenarioOperations() { @@ -61,6 +86,14 @@ protected void doScenarioOperations() { .array()), assertSuccess()); + // Successfully delete token + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(DeleteTranslator.DELETE_TOKEN + .encodeCallWithArgs(ERC721_TOKEN_ADDRESS) + .array()), + assertSuccess()); + // Try to freeze deleted token runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, @@ -70,15 +103,55 @@ protected void doScenarioOperations() { output -> assertEquals( Bytes.wrap(ReturnTypes.encodedRc(TOKEN_WAS_DELETED).array()), output)); + // Try to freeze deleted token + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(FreezeUnfreezeTranslator.FREEZE + .encodeCallWithArgs(ERC721_TOKEN_ADDRESS, asHeadlongAddress(SENDER_ADDRESS.toByteArray())) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(TOKEN_WAS_DELETED).array()), output)); + // Fail if token has no admin key runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, Bytes.wrap(DeleteTranslator.DELETE_TOKEN - .encodeCallWithArgs(ERC721_TOKEN_ADDRESS) + .encodeCallWithArgs(A_TOKEN_ADDRESS) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(TOKEN_IS_IMMUTABLE).array()), output)); + + // Fail if token has no admin key + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(DeleteTranslator.DELETE_TOKEN + .encodeCallWithArgs(B_TOKEN_ADDRESS) .array()), output -> assertEquals( Bytes.wrap(ReturnTypes.encodedRc(TOKEN_IS_IMMUTABLE).array()), output)); + // Fail if token has wrong admin key + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(DeleteTranslator.DELETE_TOKEN + .encodeCallWithArgs(C_TOKEN_ADDRESS) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE) + .array()), + output)); + + // Fail if token has wrong admin key + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(DeleteTranslator.DELETE_TOKEN + .encodeCallWithArgs(D_TOKEN_ADDRESS) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE) + .array()), + output)); + // should fail when token has invalid address runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, @@ -122,8 +195,40 @@ protected Map initialTokens() { Token.newBuilder() .tokenId(ERC721_TOKEN_ID) .treasuryAccountId(SENDER_ID) + .tokenType(TokenType.NON_FUNGIBLE_UNIQUE) + .adminKey(SENDER_CONTRACT_ID_KEY) + .freezeKey(SENDER_CONTRACT_ID_KEY) + .build()); + tokens.put( + A_TOKEN_ID, + Token.newBuilder() + .tokenId(A_TOKEN_ID) + .treasuryAccountId(SENDER_ID) .tokenType(TokenType.FUNGIBLE_COMMON) .build()); + tokens.put( + B_TOKEN_ID, + Token.newBuilder() + .tokenId(B_TOKEN_ID) + .treasuryAccountId(SENDER_ID) + .tokenType(TokenType.NON_FUNGIBLE_UNIQUE) + .build()); + tokens.put( + C_TOKEN_ID, + Token.newBuilder() + .tokenId(C_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.FUNGIBLE_COMMON) + .adminKey(AN_ED25519_KEY) + .build()); + tokens.put( + D_TOKEN_ID, + Token.newBuilder() + .tokenId(D_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.NON_FUNGIBLE_UNIQUE) + .adminKey(AN_ED25519_KEY) + .build()); return tokens; } diff --git a/hedera-node/hedera-app/src/xtest/java/contract/FreezeUnfreezeXTest.java b/hedera-node/hedera-app/src/xtest/java/contract/FreezeUnfreezeXTest.java index 45fe448ddfd0..7d14941dd110 100644 --- a/hedera-node/hedera-app/src/xtest/java/contract/FreezeUnfreezeXTest.java +++ b/hedera-node/hedera-app/src/xtest/java/contract/FreezeUnfreezeXTest.java @@ -18,6 +18,7 @@ import static com.hedera.hapi.node.base.ResponseCodeEnum.ACCOUNT_FROZEN_FOR_TOKEN; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_ACCOUNT_ID; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_ID; import static com.hedera.hapi.node.base.ResponseCodeEnum.TOKEN_HAS_NO_FREEZE_KEY; import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.transfer.Erc20TransfersTranslator.ERC_20_TRANSFER; @@ -26,6 +27,8 @@ import static contract.AssociationsXTestConstants.A_TOKEN_ID; import static contract.AssociationsXTestConstants.B_TOKEN_ADDRESS; import static contract.AssociationsXTestConstants.B_TOKEN_ID; +import static contract.AssociationsXTestConstants.C_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.C_TOKEN_ID; import static contract.HtsErc721TransferXTestConstants.UNAUTHORIZED_SPENDER_ID; import static contract.XTestConstants.AN_ED25519_KEY; import static contract.XTestConstants.OWNER_ADDRESS; @@ -49,6 +52,7 @@ import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.associations.AssociationsTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.freeze.FreezeUnfreezeTranslator; +import com.hedera.node.app.spi.fixtures.Scenarios; import com.hedera.node.app.spi.state.ReadableKVState; import java.math.BigInteger; import java.util.HashMap; @@ -69,7 +73,10 @@ *
  • Unfreeze {@code ERC20_TOKEN} via {@link FreezeUnfreezeTranslator#UNFREEZE}. This should fail with code INVALID_TOKEN_ID.
  • *
  • Unfreeze {@code ERC20_TOKEN} via {@link FreezeUnfreezeTranslator#UNFREEZE}.
  • *
  • Transfer {@code ERC20_TOKEN} from SENDER to RECEIVER. This should now succeed
  • - *
  • Freeze {@code ERC721_TOKEN} without provided freeze key via {@link FreezeUnfreezeTranslator#FREEZE}. This should fail with code TOKEN_HAS_NO_FREEZE_KEY.
  • + *
  • Freeze {@code ERC20_TOKEN} without provided freeze key via {@link FreezeUnfreezeTranslator#FREEZE}. This should fail with code TOKEN_HAS_NO_FREEZE_KEY.
  • + *
  • Unfreeze {@code ERC20_TOKEN} without provided freeze key via {@link FreezeUnfreezeTranslator#UNFREEZE}. This should fail with code TOKEN_HAS_NO_FREEZE_KEY.
  • + *
  • Unfreeze {@code ERC20_TOKEN} with different freeze key via {@link FreezeUnfreezeTranslator#UNFREEZE}. This should fail with code INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE.
  • + *
  • Freeze {@code ERC20_TOKEN} with different freeze key via {@link FreezeUnfreezeTranslator#FREEZE}. This should fail with code INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE.
  • * */ public class FreezeUnfreezeXTest extends AbstractContractXTest { @@ -154,6 +161,36 @@ protected void doScenarioOperations() { Bytes.wrap( ReturnTypes.encodedRc(TOKEN_HAS_NO_FREEZE_KEY).array()), output)); + // UNFREEZE NO FREEZE KEY + runHtsCallAndExpectOnSuccess( + OWNER_BESU_ADDRESS, + Bytes.wrap(FreezeUnfreezeTranslator.UNFREEZE + .encodeCallWithArgs(B_TOKEN_ADDRESS, OWNER_HEADLONG_ADDRESS) + .array()), + output -> assertEquals( + Bytes.wrap( + ReturnTypes.encodedRc(TOKEN_HAS_NO_FREEZE_KEY).array()), + output)); + // UNFREEZE DIFFERENT FREEZE KEY + runHtsCallAndExpectOnSuccess( + OWNER_BESU_ADDRESS, + Bytes.wrap(FreezeUnfreezeTranslator.UNFREEZE + .encodeCallWithArgs(C_TOKEN_ADDRESS, OWNER_HEADLONG_ADDRESS) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE) + .array()), + output)); + // FREEZE DIFFERENT FREEZE KEY + runHtsCallAndExpectOnSuccess( + OWNER_BESU_ADDRESS, + Bytes.wrap(FreezeUnfreezeTranslator.FREEZE + .encodeCallWithArgs(C_TOKEN_ADDRESS, OWNER_HEADLONG_ADDRESS) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE) + .array()), + output)); } @Override @@ -206,6 +243,14 @@ protected Map initialTokens() { .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) .tokenType(TokenType.FUNGIBLE_COMMON) .build()); + put( + C_TOKEN_ID, + Token.newBuilder() + .tokenId(C_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.FUNGIBLE_COMMON) + .freezeKey(Scenarios.BOB.account().key()) + .build()); } }; } diff --git a/hedera-node/hedera-app/src/xtest/java/contract/GrantRevokeKycXTest.java b/hedera-node/hedera-app/src/xtest/java/contract/GrantRevokeKycXTest.java index 7b7a6d26408b..070adcc1cc90 100644 --- a/hedera-node/hedera-app/src/xtest/java/contract/GrantRevokeKycXTest.java +++ b/hedera-node/hedera-app/src/xtest/java/contract/GrantRevokeKycXTest.java @@ -18,7 +18,13 @@ import static com.hedera.hapi.node.base.ResponseCodeEnum.ACCOUNT_KYC_NOT_GRANTED_FOR_TOKEN; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_ACCOUNT_ID; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_SIGNATURE; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_ID; +import static com.hedera.hapi.node.base.ResponseCodeEnum.TOKEN_HAS_NO_KYC_KEY; +import static contract.AssociationsXTestConstants.A_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.A_TOKEN_ID; +import static contract.AssociationsXTestConstants.B_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.B_TOKEN_ID; import static contract.HtsErc721TransferXTestConstants.APPROVED_ID; import static contract.HtsErc721TransferXTestConstants.UNAUTHORIZED_SPENDER_ID; import static contract.MiscClassicTransfersXTestConstants.INITIAL_RECEIVER_AUTO_ASSOCIATIONS; @@ -56,6 +62,7 @@ import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.grantrevokekyc.GrantRevokeKycTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.transfer.ClassicTransfersTranslator; +import com.hedera.node.app.spi.fixtures.Scenarios; import java.util.HashMap; import java.util.Map; import org.apache.tuweni.bytes.Bytes; @@ -72,6 +79,10 @@ *
  • Grant KYC {@code ERC721_TOKEN} via {@link GrantRevokeKycTranslator#GRANT_KYC}. This should fail with status INVALID_ACCOUNT_ID.
  • *
  • Grant KYC {@code ERC721_TOKEN} via {@link GrantRevokeKycTranslator#GRANT_KYC}.This should fail with status INVALID_TOKEN_ID.
  • *
  • Transfer {@code ERC721_TOKEN} serial 2345 from SENDER to RECEIVER. This should now succeed
  • * + *
  • Grant KYC {@code ERC721_TOKEN} via {@link GrantRevokeKycTranslator#GRANT_KYC}.This should fail with status INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE.
  • + *
  • Revoke KYC {@code ERC721_TOKEN} via {@link GrantRevokeKycTranslator#REVOKE_KYC}.This should fail with status INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE.
  • + *
  • Grant KYC {@code ERC721_TOKEN} via {@link GrantRevokeKycTranslator#GRANT_KYC}.This should fail with status TOKEN_HAS_NO_KYC_KEY.
  • + *
  • Revoke KYC {@code ERC721_TOKEN} via {@link GrantRevokeKycTranslator#REVOKE_KYC}.This should fail with status TOKEN_HAS_NO_KYC_KEY.
  • * */ public class GrantRevokeKycXTest extends AbstractContractXTest { @@ -177,6 +188,47 @@ protected void doScenarioOperations() { SN_2345.serialNumber()) .array()), assertSuccess("Should now be able to transfer ERC721_TOKEN serial 2345 to RECEIVER")); + + // GRANT_KYC with invalid key + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(GrantRevokeKycTranslator.GRANT_KYC + .encodeCallWithArgs(A_TOKEN_ADDRESS, RECEIVER_HEADLONG_ADDRESS) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_SIGNATURE).array()), + output, + "Should not be able to grant KYC with invalid signature")); + // REVOKE_KYC with invalid key + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(GrantRevokeKycTranslator.REVOKE_KYC + .encodeCallWithArgs(A_TOKEN_ADDRESS, RECEIVER_HEADLONG_ADDRESS) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_SIGNATURE).array()), + output, + "Should not be able to revoke KYC with invalid signature")); + // GRANT_KYC with no kyc key + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(GrantRevokeKycTranslator.GRANT_KYC + .encodeCallWithArgs(B_TOKEN_ADDRESS, RECEIVER_HEADLONG_ADDRESS) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(TOKEN_HAS_NO_KYC_KEY).array()), + output, + "Should not be able to grant KYC with missing signature")); + // REVOKE_KYC with no kyc key + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(GrantRevokeKycTranslator.REVOKE_KYC + .encodeCallWithArgs(B_TOKEN_ADDRESS, RECEIVER_HEADLONG_ADDRESS) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(TOKEN_HAS_NO_KYC_KEY).array()), + output, + "Should not be able to revoke KYC with missing signature")); } @Override @@ -202,6 +254,21 @@ protected Map initialTokens() { .tokenType(TokenType.NON_FUNGIBLE_UNIQUE) .kycKey(SENDER_CONTRACT_ID_KEY) .build()); + tokens.put( + A_TOKEN_ID, + Token.newBuilder() + .tokenId(A_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.NON_FUNGIBLE_UNIQUE) + .kycKey(Scenarios.ALICE.account().key()) + .build()); + tokens.put( + B_TOKEN_ID, + Token.newBuilder() + .tokenId(B_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.NON_FUNGIBLE_UNIQUE) + .build()); return tokens; } diff --git a/hedera-node/hedera-app/src/xtest/java/contract/MintsXTest.java b/hedera-node/hedera-app/src/xtest/java/contract/MintsXTest.java index 75f3746a03b9..9a9aa31eca19 100644 --- a/hedera-node/hedera-app/src/xtest/java/contract/MintsXTest.java +++ b/hedera-node/hedera-app/src/xtest/java/contract/MintsXTest.java @@ -17,6 +17,7 @@ package contract; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_ID; +import static com.hedera.hapi.node.base.ResponseCodeEnum.SUCCESS; import static com.hedera.hapi.node.base.ResponseCodeEnum.TOKEN_HAS_NO_SUPPLY_KEY; import static contract.AssociationsXTestConstants.A_TOKEN_ADDRESS; import static contract.AssociationsXTestConstants.A_TOKEN_ID; @@ -37,7 +38,6 @@ import static contract.XTestConstants.SN_1234_METADATA; import static contract.XTestConstants.addErc20Relation; import static contract.XTestConstants.addErc721Relation; -import static contract.XTestConstants.assertSuccess; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -51,7 +51,6 @@ import com.hedera.hapi.node.state.token.Nft; import com.hedera.hapi.node.state.token.Token; import com.hedera.hapi.node.state.token.TokenRelation; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.mint.MintTranslator; import com.hedera.node.app.spi.state.ReadableKVState; import java.math.BigInteger; @@ -84,7 +83,12 @@ protected void doScenarioOperations() { Bytes.wrap(MintTranslator.MINT .encodeCallWithArgs(ERC20_TOKEN_ADDRESS, BigInteger.valueOf(MINT_AMOUNT), new byte[][] {}) .array()), - assertSuccess()); + output -> assertEquals( + Bytes.wrap(MintTranslator.MINT + .getOutputs() + .encodeElements((long) SUCCESS.protoOrdinal(), 1010L, new long[] {}) + .array()), + output)); // Mint 10 Tokens via mintV2 runHtsCallAndExpectOnSuccess( @@ -92,7 +96,12 @@ protected void doScenarioOperations() { Bytes.wrap(MintTranslator.MINT_V2 .encodeCallWithArgs(ERC20_TOKEN_ADDRESS, MINT_AMOUNT, new byte[][] {}) .array()), - assertSuccess()); + output -> assertEquals( + Bytes.wrap(MintTranslator.MINT_V2 + .getOutputs() + .encodeElements((long) SUCCESS.protoOrdinal(), 1020L, new long[] {}) + .array()), + output)); // Mint NFT via mintV1 runHtsCallAndExpectOnSuccess( @@ -100,7 +109,12 @@ protected void doScenarioOperations() { Bytes.wrap(MintTranslator.MINT .encodeCallWithArgs(ERC721_TOKEN_ADDRESS, BigInteger.ZERO, metadata) .array()), - assertSuccess()); + output -> assertEquals( + Bytes.wrap(MintTranslator.MINT + .getOutputs() + .encodeElements((long) SUCCESS.protoOrdinal(), 1001L, new long[] {1L}) + .array()), + output)); // Mint NFT via mintV2 runHtsCallAndExpectOnSuccess( @@ -108,7 +122,12 @@ protected void doScenarioOperations() { Bytes.wrap(MintTranslator.MINT_V2 .encodeCallWithArgs(ERC721_TOKEN_ADDRESS, 0L, metadata) .array()), - assertSuccess()); + output -> assertEquals( + Bytes.wrap(MintTranslator.MINT_V2 + .getOutputs() + .encodeElements((long) SUCCESS.protoOrdinal(), 1002L, new long[] {2L}) + .array()), + output)); // should fail when token has no supplyKey runHtsCallAndExpectOnSuccess( @@ -117,8 +136,10 @@ protected void doScenarioOperations() { .encodeCallWithArgs(A_TOKEN_ADDRESS, BigInteger.valueOf(MINT_AMOUNT), new byte[][] {}) .array()), output -> assertEquals( - Bytes.wrap( - ReturnTypes.encodedRc(TOKEN_HAS_NO_SUPPLY_KEY).array()), + Bytes.wrap(MintTranslator.MINT + .getOutputs() + .encodeElements((long) TOKEN_HAS_NO_SUPPLY_KEY.protoOrdinal(), 0L, new long[] {}) + .array()), output)); // should fail when token has invalid address @@ -128,7 +149,11 @@ protected void doScenarioOperations() { .encodeCallWithArgs(INVALID_TOKEN_ADDRESS, BigInteger.valueOf(MINT_AMOUNT), new byte[][] {}) .array()), output -> assertEquals( - Bytes.wrap(ReturnTypes.encodedRc(INVALID_TOKEN_ID).array()), output)); + Bytes.wrap(MintTranslator.MINT + .getOutputs() + .encodeElements((long) INVALID_TOKEN_ID.protoOrdinal(), 0L, new long[] {}) + .array()), + output)); } @Override diff --git a/hedera-node/hedera-app/src/xtest/java/contract/PausesXTest.java b/hedera-node/hedera-app/src/xtest/java/contract/PausesXTest.java index 8b7bbc9b06cf..2eb13c6fd463 100644 --- a/hedera-node/hedera-app/src/xtest/java/contract/PausesXTest.java +++ b/hedera-node/hedera-app/src/xtest/java/contract/PausesXTest.java @@ -16,7 +16,13 @@ package contract; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE; +import static com.hedera.hapi.node.base.ResponseCodeEnum.TOKEN_HAS_NO_PAUSE_KEY; import static com.hedera.hapi.node.base.ResponseCodeEnum.TOKEN_IS_PAUSED; +import static contract.AssociationsXTestConstants.A_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.A_TOKEN_ID; +import static contract.AssociationsXTestConstants.B_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.B_TOKEN_ID; import static contract.HtsErc721TransferXTestConstants.APPROVED_ID; import static contract.HtsErc721TransferXTestConstants.UNAUTHORIZED_SPENDER_ID; import static contract.MiscClassicTransfersXTestConstants.INITIAL_RECEIVER_AUTO_ASSOCIATIONS; @@ -54,6 +60,7 @@ import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.pauses.PausesTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.transfer.ClassicTransfersTranslator; +import com.hedera.node.app.spi.fixtures.Scenarios; import java.util.HashMap; import java.util.Map; import org.apache.tuweni.bytes.Bytes; @@ -63,9 +70,13 @@ *
      *
    1. Transfer {@code ERC721_TOKEN} serial 1234 from SENDER to RECEIVER.
    2. * *
    3. Pause {@code ERC721_TOKEN} via {@link PausesTranslator#PAUSE}.
    4. - *
    5. Transfer {@code ERC721_TOKEN} serial 2345 from SENDER to RECEIVER. This should fail with code TOKEN_IS_PAUSED
    6. * + *
    7. Transfer {@code ERC721_TOKEN} serial 2345 from SENDER to RECEIVER. This should fail with code TOKEN_IS_PAUSED.
    8. * *
    9. Unpause {@code ERC721_TOKEN} via {@link PausesTranslator#UNPAUSE}.
    10. - *
    11. Transfer {@code ERC721_TOKEN} serial 2345 from SENDER to RECEIVER. This should now succeed
    12. * + *
    13. Transfer {@code ERC721_TOKEN} serial 2345 from SENDER to RECEIVER. This should now succeed.
    14. * + *
    15. Pause {@code ERC721_TOKEN} via {@link PausesTranslator#PAUSE}. This should fail with code INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE.
    16. + *
    17. Pause {@code ERC721_TOKEN} via {@link PausesTranslator#PAUSE}. This should fail with code TOKEN_HAS_NO_PAUSE_KEY.
    18. + *
    19. Unpause {@code ERC721_TOKEN} via {@link PausesTranslator#UNPAUSE}. This should fail with code INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE.
    20. + *
    21. Unpause {@code ERC721_TOKEN} via {@link PausesTranslator#UNPAUSE}. This should fail with code TOKEN_HAS_NO_PAUSE_KEY.
    22. *
    */ public class PausesXTest extends AbstractContractXTest { @@ -125,6 +136,52 @@ protected void doScenarioOperations() { SN_2345.serialNumber()) .array()), assertSuccess("Post-unpause transfer failed")); + + // PAUSE wrong pause key + runHtsCallAndExpectOnSuccess( + OWNER_BESU_ADDRESS, + Bytes.wrap(PausesTranslator.PAUSE + .encodeCallWithArgs(A_TOKEN_ADDRESS) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE) + .array()), + output, + "Token should have been paused")); + + // PAUSE no pause key + runHtsCallAndExpectOnSuccess( + OWNER_BESU_ADDRESS, + Bytes.wrap(PausesTranslator.PAUSE + .encodeCallWithArgs(B_TOKEN_ADDRESS) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(TOKEN_HAS_NO_PAUSE_KEY).array()), + output, + "Token should have been paused")); + + // UNPAUSE wrong pause key + runHtsCallAndExpectOnSuccess( + OWNER_BESU_ADDRESS, + Bytes.wrap(PausesTranslator.UNPAUSE + .encodeCallWithArgs(A_TOKEN_ADDRESS) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE) + .array()), + output, + "Token should have been paused")); + + // UNPAUSE no pause key + runHtsCallAndExpectOnSuccess( + OWNER_BESU_ADDRESS, + Bytes.wrap(PausesTranslator.UNPAUSE + .encodeCallWithArgs(B_TOKEN_ADDRESS) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(TOKEN_HAS_NO_PAUSE_KEY).array()), + output, + "Token should have been paused")); } @Override @@ -151,6 +208,21 @@ protected Map initialTokens() { .tokenType(TokenType.NON_FUNGIBLE_UNIQUE) .pauseKey(SENDER_CONTRACT_ID_KEY) .build()); + tokens.put( + A_TOKEN_ID, + Token.newBuilder() + .tokenId(A_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.NON_FUNGIBLE_UNIQUE) + .pauseKey(Scenarios.ALICE.account().key()) + .build()); + tokens.put( + B_TOKEN_ID, + Token.newBuilder() + .tokenId(B_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.NON_FUNGIBLE_UNIQUE) + .build()); return tokens; } diff --git a/hedera-node/hedera-app/src/xtest/java/contract/UpdatesExpiryXTest.java b/hedera-node/hedera-app/src/xtest/java/contract/UpdatesExpiryXTest.java index eb3a610f5038..564ea39e1c06 100644 --- a/hedera-node/hedera-app/src/xtest/java/contract/UpdatesExpiryXTest.java +++ b/hedera-node/hedera-app/src/xtest/java/contract/UpdatesExpiryXTest.java @@ -18,7 +18,11 @@ import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_EXPIRATION_TIME; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_RENEWAL_PERIOD; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_SIGNATURE; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_ID; +import static contract.AssociationsXTestConstants.A_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.A_TOKEN_ID; +import static contract.HtsErc721TransferXTestConstants.UNAUTHORIZED_SPENDER_ID; import static contract.XTestConstants.AN_ED25519_KEY; import static contract.XTestConstants.ERC20_TOKEN_ADDRESS; import static contract.XTestConstants.ERC20_TOKEN_ID; @@ -46,6 +50,7 @@ import com.hedera.hapi.node.state.token.TokenRelation; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateExpiryTranslator; +import com.hedera.node.app.spi.fixtures.Scenarios; import com.hedera.node.app.spi.state.ReadableKVState; import edu.umd.cs.findbugs.annotations.NonNull; import java.time.Instant; @@ -53,13 +58,28 @@ import java.util.Map; import org.apache.tuweni.bytes.Bytes; +/** + * Exercises update a token via the following steps relative to an {@code OWNER} account: + *
      + *
    1. Update expiry {@code ERC20_TOKEN} via {@link UpdateExpiryTranslator#UPDATE_TOKEN_EXPIRY_INFO_V1}.
    2. + *
    3. Update expiry {@code ERC20_TOKEN} via {@link UpdateExpiryTranslator#UPDATE_TOKEN_EXPIRY_INFO_V1}. This should fail with code INVALID_SIGNATURE.
    4. + *
    5. Update expiry {@code ERC20_TOKEN} via {@link UpdateExpiryTranslator#UPDATE_TOKEN_EXPIRY_INFO_V1}. This should fail with code INVALID_EXPIRATION_TIME.
    6. + *
    7. Update expiry {@code ERC20_TOKEN} via {@link UpdateExpiryTranslator#UPDATE_TOKEN_EXPIRY_INFO_V1}. This should fail with code INVALID_RENEWAL_PERIOD.
    8. + *
    9. Update expiry {@code ERC20_TOKEN} via {@link UpdateExpiryTranslator#UPDATE_TOKEN_EXPIRY_INFO_V1}. This should fail with code INVALID_TOKEN_ID.
    10. + *
    11. Update expiry {@code ERC20_TOKEN} via {@link UpdateExpiryTranslator#UPDATE_TOKEN_EXPIRY_INFO_V2}. + *
    12. Update expiry {@code ERC20_TOKEN} via {@link UpdateExpiryTranslator#UPDATE_TOKEN_EXPIRY_INFO_V2}. This should fail with code INVALID_SIGNATURE.
    13. + *
    14. Update expiry {@code ERC20_TOKEN} via {@link UpdateExpiryTranslator#UPDATE_TOKEN_EXPIRY_INFO_V2}. This should fail with code INVALID_EXPIRATION_TIME.
    15. + *
    16. Update expiry {@code ERC20_TOKEN} via {@link UpdateExpiryTranslator#UPDATE_TOKEN_EXPIRY_INFO_V2}. This should fail with code INVALID_RENEWAL_PERIOD.
    17. + *
    18. Update expiry {@code ERC20_TOKEN} via {@link UpdateExpiryTranslator#UPDATE_TOKEN_EXPIRY_INFO_V2}. This should fail with code INVALID_TOKEN_ID.
    19. + *
    + */ public class UpdatesExpiryXTest extends AbstractContractXTest { private static final long EXPIRY_TIMESTAMP = Instant.now().plusSeconds(3600).toEpochMilli() / 1000; private static final long AUTO_RENEW_PERIOD = 8_000_000L; @Override protected void doScenarioOperations() { - // Successfully update token via TOKEN_UPDATE_INFO V1 + // Successfully update token via UPDATE_TOKEN_EXPIRY_INFO_V1 runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, Bytes.wrap(UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V1 @@ -69,7 +89,49 @@ protected void doScenarioOperations() { .array()), assertSuccess()); - // Successfully update token via TOKEN_UPDATE_INFO V2 + // Should throw `INVALID_SIGNATURE` + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V1 + .encodeCallWithArgs( + A_TOKEN_ADDRESS, Tuple.of(EXPIRY_TIMESTAMP, SENDER_HEADLONG_ADDRESS, AUTO_RENEW_PERIOD)) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_SIGNATURE).array()), output, "Wrong key")); + + // Fails if the expiration time is invalid + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V1 + .encodeCallWithArgs(ERC20_TOKEN_ADDRESS, Tuple.of(123456L, asAddress(""), 0L)) + .array()), + output -> assertEquals( + Bytes.wrap( + ReturnTypes.encodedRc(INVALID_EXPIRATION_TIME).array()), + output)); + + // Fails if the renewal period is invalid + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V1 + .encodeCallWithArgs( + ERC20_TOKEN_ADDRESS, Tuple.of(EXPIRY_TIMESTAMP, SENDER_HEADLONG_ADDRESS, 1000L)) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_RENEWAL_PERIOD).array()), output)); + + // should fail when token has invalid address + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V1 + .encodeCallWithArgs( + INVALID_TOKEN_ADDRESS, + Tuple.of(EXPIRY_TIMESTAMP, SENDER_HEADLONG_ADDRESS, AUTO_RENEW_PERIOD)) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_TOKEN_ID).array()), output)); + + // Successfully update token via UPDATE_TOKEN_EXPIRY_INFO_V2 runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, Bytes.wrap(UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V2 @@ -79,10 +141,20 @@ protected void doScenarioOperations() { .array()), assertSuccess()); + // Should throw `INVALID_SIGNATURE` + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V2 + .encodeCallWithArgs( + A_TOKEN_ADDRESS, Tuple.of(EXPIRY_TIMESTAMP, SENDER_HEADLONG_ADDRESS, AUTO_RENEW_PERIOD)) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_SIGNATURE).array()), output, "Wrong key")); + // Fails if the expiration time is invalid runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, - Bytes.wrap(UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V1 + Bytes.wrap(UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V2 .encodeCallWithArgs(ERC20_TOKEN_ADDRESS, Tuple.of(123456L, asAddress(""), 0L)) .array()), output -> assertEquals( @@ -93,7 +165,7 @@ protected void doScenarioOperations() { // Fails if the renewal period is invalid runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, - Bytes.wrap(UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V1 + Bytes.wrap(UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V2 .encodeCallWithArgs( ERC20_TOKEN_ADDRESS, Tuple.of(EXPIRY_TIMESTAMP, SENDER_HEADLONG_ADDRESS, 1000L)) .array()), @@ -103,7 +175,7 @@ protected void doScenarioOperations() { // should fail when token has invalid address runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, - Bytes.wrap(UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V1 + Bytes.wrap(UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V2 .encodeCallWithArgs( INVALID_TOKEN_ADDRESS, Tuple.of(EXPIRY_TIMESTAMP, SENDER_HEADLONG_ADDRESS, AUTO_RENEW_PERIOD)) @@ -141,6 +213,15 @@ protected Map initialTokens() { .adminKey(SENDER_CONTRACT_ID_KEY) .autoRenewAccountId(SENDER_ID) .build()); + tokens.put( + A_TOKEN_ID, + Token.newBuilder() + .tokenId(A_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.FUNGIBLE_COMMON) + .supplyKey(Scenarios.ALICE.account().key()) + .adminKey(Scenarios.ALICE.account().key()) + .build()); return tokens; } diff --git a/hedera-node/hedera-app/src/xtest/java/contract/UpdateKeysXTest.java b/hedera-node/hedera-app/src/xtest/java/contract/UpdatesKeysXTest.java similarity index 78% rename from hedera-node/hedera-app/src/xtest/java/contract/UpdateKeysXTest.java rename to hedera-node/hedera-app/src/xtest/java/contract/UpdatesKeysXTest.java index a43f09b79ccb..a4be63c01caa 100644 --- a/hedera-node/hedera-app/src/xtest/java/contract/UpdateKeysXTest.java +++ b/hedera-node/hedera-app/src/xtest/java/contract/UpdatesKeysXTest.java @@ -17,7 +17,11 @@ package contract; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_ADMIN_KEY; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_SIGNATURE; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_ID; +import static contract.AssociationsXTestConstants.A_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.A_TOKEN_ID; +import static contract.HtsErc721TransferXTestConstants.UNAUTHORIZED_SPENDER_ID; import static contract.XTestConstants.AN_ED25519_KEY; import static contract.XTestConstants.ERC20_TOKEN_ADDRESS; import static contract.XTestConstants.ERC20_TOKEN_ID; @@ -47,12 +51,22 @@ import com.hedera.hapi.node.state.token.TokenRelation; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateKeysTranslator; +import com.hedera.node.app.spi.fixtures.Scenarios; import java.math.BigInteger; import java.util.HashMap; import java.util.Map; import org.apache.tuweni.bytes.Bytes; -public class UpdateKeysXTest extends AbstractContractXTest { +/** + * Exercises update a token via the following steps relative to an {@code OWNER} account: + *
      + *
    1. Update {@code ERC20_TOKEN} via {@link UpdateKeysTranslator#TOKEN_UPDATE_KEYS_FUNCTION}.
    2. + *
    3. Update {@code ERC20_TOKEN} via {@link UpdateKeysTranslator#TOKEN_UPDATE_KEYS_FUNCTION}. This should fail with code INVALID_SIGNATURE.
    4. + *
    5. Update {@code ERC20_TOKEN} via {@link UpdateKeysTranslator#TOKEN_UPDATE_KEYS_FUNCTION}. This should fail with code INVALID_ADMIN_KEY.
    6. + *
    7. Update {@code ERC20_TOKEN} via {@link UpdateKeysTranslator#TOKEN_UPDATE_KEYS_FUNCTION}. This should fail with code INVALID_TOKEN_ID.
    8. + *
    + */ +public class UpdatesKeysXTest extends AbstractContractXTest { private final Tuple[] TOKEN_KEY = new Tuple[] { Tuple.of( BigInteger.valueOf(1), @@ -73,6 +87,14 @@ protected void doScenarioOperations() { .encodeCallWithArgs(ERC20_TOKEN_ADDRESS, TOKEN_KEY) .array()), assertSuccess()); + // Should throw `INVALID_SIGNATURE` as we are passing an invalid admin key + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateKeysTranslator.TOKEN_UPDATE_KEYS_FUNCTION + .encodeCallWithArgs(A_TOKEN_ADDRESS, TOKEN_KEY) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_SIGNATURE).array()), output, "Wrong key")); // Should throw `INVALID_ADMIN_KEY` as we are passing an invalid key with key type admin key runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, @@ -135,6 +157,15 @@ protected Map initialTokens() { .adminKey(INVALID_CONTRACT_ID_KEY) .autoRenewAccountId(INVALID_ID) .build()); + tokens.put( + A_TOKEN_ID, + Token.newBuilder() + .tokenId(A_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.FUNGIBLE_COMMON) + .supplyKey(Scenarios.ALICE.account().key()) + .adminKey(Scenarios.ALICE.account().key()) + .build()); return tokens; } diff --git a/hedera-node/hedera-app/src/xtest/java/contract/UpdatesXTest.java b/hedera-node/hedera-app/src/xtest/java/contract/UpdatesXTest.java index 7e63bb711010..f406d3062e0e 100644 --- a/hedera-node/hedera-app/src/xtest/java/contract/UpdatesXTest.java +++ b/hedera-node/hedera-app/src/xtest/java/contract/UpdatesXTest.java @@ -17,10 +17,16 @@ package contract; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_EXPIRATION_TIME; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_SIGNATURE; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_ID; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TREASURY_ACCOUNT_FOR_TOKEN; +import static contract.AssociationsXTestConstants.A_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.A_TOKEN_ID; +import static contract.AssociationsXTestConstants.B_TOKEN_ID; +import static contract.HtsErc721TransferXTestConstants.UNAUTHORIZED_SPENDER_ADDRESS; +import static contract.HtsErc721TransferXTestConstants.UNAUTHORIZED_SPENDER_ID; +import static contract.MiscViewsXTestConstants.ERC20_TOKEN_ADDRESS; import static contract.XTestConstants.AN_ED25519_KEY; -import static contract.XTestConstants.ERC20_TOKEN_ADDRESS; import static contract.XTestConstants.ERC20_TOKEN_ID; import static contract.XTestConstants.ERC721_TOKEN_ADDRESS; import static contract.XTestConstants.OWNER_ADDRESS; @@ -46,12 +52,33 @@ import com.hedera.hapi.node.state.token.TokenRelation; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateTranslator; +import com.hedera.node.app.spi.fixtures.Scenarios; import com.hedera.node.app.spi.state.ReadableKVState; import edu.umd.cs.findbugs.annotations.NonNull; import java.util.HashMap; import java.util.Map; import org.apache.tuweni.bytes.Bytes; +/** + * Exercises update a token via the following steps relative to an {@code OWNER} account: + *
      + *
    1. Update {@code ERC20_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V1}.
    2. + *
    3. Update {@code ERC20_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V1}. This should fail with code INVALID_SIGNATURE.
    4. + *
    5. Update {@code ERC20_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V1}. This should fail with code INVALID_TREASURY_ACCOUNT_FOR_TOKEN.
    6. + * *
    7. Update {@code ERC721_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V1}. This should fail with code INVALID_TOKEN_ID.
    8. + * *
    9. Update {@code ERC20_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V1}. This should fail with code INVALID_EXPIRATION_TIME.
    10. + *
    11. Update {@code ERC20_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V2}. + *
    12. Update {@code ERC20_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V2}. This should fail with code INVALID_SIGNATURE.
    13. + *
    14. Update {@code ERC20_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V2}. This should fail with code INVALID_TREASURY_ACCOUNT_FOR_TOKEN.
    15. + *
    16. Update {@code ERC721_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V2}. This should fail with code INVALID_TOKEN_ID.
    17. + *
    18. Update {@code ERC20_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V2}. This should fail with code INVALID_EXPIRATION_TIME.
    19. + *
    20. Update {@code ERC20_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V3}. + *
    21. Update {@code ERC20_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V3}. This should fail with code INVALID_SIGNATURE.
    22. + *
    23. Update {@code ERC20_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V3}. This should fail with code INVALID_TREASURY_ACCOUNT_FOR_TOKEN.
    24. + *
    25. Update {@code ERC721_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V3}. This should fail with code INVALID_TOKEN_ID.
    26. + *
    27. Update {@code ERC20_TOKEN} via {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V3}. This should fail with code INVALID_EXPIRATION_TIME.
    28. + *
    + */ public class UpdatesXTest extends AbstractContractXTest { private static final String NEW_NAME = "New name"; private static final String NEW_SYMBOL = "New symbol"; @@ -61,7 +88,7 @@ protected void doScenarioOperations() { // Successfully update token via TOKEN_UPDATE_INFO V1 runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, - Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION + Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V1 .encodeCallWithArgs( ERC20_TOKEN_ADDRESS, Tuple.of( @@ -79,6 +106,102 @@ protected void doScenarioOperations() { .array()), assertSuccess("V1 update failed")); + // Should throw `INVALID_SIGNATURE` + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V1 + .encodeCallWithArgs( + A_TOKEN_ADDRESS, + Tuple.of( + NEW_NAME, + NEW_SYMBOL, + asHeadlongAddress(SENDER_ADDRESS.toByteArray()), + "memo", + true, + 1000L, + false, + // TokenKey + new Tuple[] {}, + // Expiry + Tuple.of(0L, asAddress(""), 0L))) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_SIGNATURE).array()), output, "Wrong key")); + + // Fails if the treasury is invalid (owner address is not initialized) + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V1 + .encodeCallWithArgs( + ERC20_TOKEN_ADDRESS, + Tuple.of( + NEW_NAME, + NEW_SYMBOL, + asHeadlongAddress(OWNER_ADDRESS.toByteArray()), + "memo", + true, + 1000L, + false, + // TokenKey + new Tuple[] {}, + // Expiry + Tuple.of(0L, asAddress(""), 0L))) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_TREASURY_ACCOUNT_FOR_TOKEN) + .array()), + output, + "Invalid treasury account not detected")); + + // Fails if the token ID is invalid (erc721 token address is not initialized) + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V1 + .encodeCallWithArgs( + ERC721_TOKEN_ADDRESS, + Tuple.of( + NEW_NAME, + NEW_SYMBOL, + asHeadlongAddress(SENDER_ADDRESS.toByteArray()), + "memo", + true, + 1000L, + false, + // TokenKey + new Tuple[] {}, + // Expiry + Tuple.of(0L, asAddress(""), 0L))) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_TOKEN_ID).array()), + output, + "Invalid token ID not detected")); + + // Fails if the expiration time is invalid + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V1 + .encodeCallWithArgs( + ERC20_TOKEN_ADDRESS, + Tuple.of( + NEW_NAME, + NEW_SYMBOL, + asHeadlongAddress(SENDER_ADDRESS.toByteArray()), + "memo", + true, + 1000L, + false, + // TokenKey + new Tuple[] {}, + // Expiry + Tuple.of(123456L, asAddress(""), 0L))) + .array()), + output -> assertEquals( + Bytes.wrap( + ReturnTypes.encodedRc(INVALID_EXPIRATION_TIME).array()), + output, + "Invalid expiration time not detected")); + // Successfully update token via TOKEN_UPDATE_INFO V2 runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, @@ -100,6 +223,102 @@ protected void doScenarioOperations() { .array()), assertSuccess("V2 update failed")); + // Should throw `INVALID_SIGNATURE` + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V2 + .encodeCallWithArgs( + A_TOKEN_ADDRESS, + Tuple.of( + NEW_NAME, + NEW_SYMBOL, + asHeadlongAddress(SENDER_ADDRESS.toByteArray()), + "memo", + true, + 1000L, + false, + // TokenKey + new Tuple[] {}, + // Expiry + Tuple.of(0L, asAddress(""), 0L))) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_SIGNATURE).array()), output, "Wrong key")); + + // Fails if the treasury is invalid (owner address is not initialized) + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V2 + .encodeCallWithArgs( + ERC20_TOKEN_ADDRESS, + Tuple.of( + NEW_NAME, + NEW_SYMBOL, + asHeadlongAddress(OWNER_ADDRESS.toByteArray()), + "memo", + true, + 1000L, + false, + // TokenKey + new Tuple[] {}, + // Expiry + Tuple.of(0L, asAddress(""), 0L))) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_TREASURY_ACCOUNT_FOR_TOKEN) + .array()), + output, + "Invalid treasury account not detected")); + + // Fails if the token ID is invalid (erc721 token address is not initialized) + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V2 + .encodeCallWithArgs( + ERC721_TOKEN_ADDRESS, + Tuple.of( + NEW_NAME, + NEW_SYMBOL, + asHeadlongAddress(SENDER_ADDRESS.toByteArray()), + "memo", + true, + 1000L, + false, + // TokenKey + new Tuple[] {}, + // Expiry + Tuple.of(0L, asAddress(""), 0L))) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_TOKEN_ID).array()), + output, + "Invalid token ID not detected")); + + // Fails if the expiration time is invalid + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V2 + .encodeCallWithArgs( + ERC20_TOKEN_ADDRESS, + Tuple.of( + NEW_NAME, + NEW_SYMBOL, + asHeadlongAddress(SENDER_ADDRESS.toByteArray()), + "memo", + true, + 1000L, + false, + // TokenKey + new Tuple[] {}, + // Expiry + Tuple.of(123456L, asAddress(""), 0L))) + .array()), + output -> assertEquals( + Bytes.wrap( + ReturnTypes.encodedRc(INVALID_EXPIRATION_TIME).array()), + output, + "Invalid expiration time not detected")); + // Successfully update token via TOKEN_UPDATE_INFO V3 runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, @@ -121,10 +340,32 @@ protected void doScenarioOperations() { .array()), assertSuccess("V3 update failed")); + // Should throw `INVALID_SIGNATURE` + runHtsCallAndExpectOnSuccess( + SENDER_BESU_ADDRESS, + Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V3 + .encodeCallWithArgs( + A_TOKEN_ADDRESS, + Tuple.of( + NEW_NAME, + NEW_SYMBOL, + asHeadlongAddress(SENDER_ADDRESS.toByteArray()), + "memo", + true, + 1000L, + false, + // TokenKey + new Tuple[] {}, + // Expiry + Tuple.of(0L, asAddress(""), 0L))) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_SIGNATURE).array()), output, "Wrong key")); + // Fails if the treasury is invalid (owner address is not initialized) runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, - Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION + Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V3 .encodeCallWithArgs( ERC20_TOKEN_ADDRESS, Tuple.of( @@ -149,7 +390,7 @@ protected void doScenarioOperations() { // Fails if the token ID is invalid (erc721 token address is not initialized) runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, - Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION + Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V3 .encodeCallWithArgs( ERC721_TOKEN_ADDRESS, Tuple.of( @@ -173,7 +414,7 @@ protected void doScenarioOperations() { // Fails if the expiration time is invalid runHtsCallAndExpectOnSuccess( SENDER_BESU_ADDRESS, - Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION + Bytes.wrap(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V3 .encodeCallWithArgs( ERC20_TOKEN_ADDRESS, Tuple.of( @@ -208,6 +449,7 @@ protected void assertExpectedTokens(@NonNull ReadableKVState tok protected Map initialAliases() { final var aliases = new HashMap(); aliases.put(ProtoBytes.newBuilder().value(SENDER_ADDRESS).build(), SENDER_ID); + aliases.put(ProtoBytes.newBuilder().value(UNAUTHORIZED_SPENDER_ADDRESS).build(), UNAUTHORIZED_SPENDER_ID); return aliases; } @@ -224,6 +466,22 @@ protected Map initialTokens() { .adminKey(SENDER_CONTRACT_ID_KEY) .autoRenewAccountId(SENDER_ID) .build()); + tokens.put( + A_TOKEN_ID, + Token.newBuilder() + .tokenId(A_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.FUNGIBLE_COMMON) + .supplyKey(Scenarios.ALICE.account().key()) + .adminKey(Scenarios.ALICE.account().key()) + .build()); + tokens.put( + B_TOKEN_ID, + Token.newBuilder() + .tokenId(B_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.FUNGIBLE_COMMON) + .build()); return tokens; } diff --git a/hedera-node/hedera-app/src/xtest/java/contract/WipeXTest.java b/hedera-node/hedera-app/src/xtest/java/contract/WipeXTest.java index f91bf589dc5b..5c2b7c5f990e 100644 --- a/hedera-node/hedera-app/src/xtest/java/contract/WipeXTest.java +++ b/hedera-node/hedera-app/src/xtest/java/contract/WipeXTest.java @@ -17,8 +17,18 @@ package contract; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_ACCOUNT_ID; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_NFT_ID; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_ID; +import static com.hedera.hapi.node.base.ResponseCodeEnum.TOKEN_HAS_NO_WIPE_KEY; +import static contract.AssociationsXTestConstants.A_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.A_TOKEN_ID; +import static contract.AssociationsXTestConstants.B_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.B_TOKEN_ID; +import static contract.AssociationsXTestConstants.C_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.C_TOKEN_ID; +import static contract.AssociationsXTestConstants.D_TOKEN_ADDRESS; +import static contract.AssociationsXTestConstants.D_TOKEN_ID; import static contract.HtsErc721TransferXTestConstants.APPROVED_ID; import static contract.HtsErc721TransferXTestConstants.UNAUTHORIZED_SPENDER_ID; import static contract.XTestConstants.AN_ED25519_KEY; @@ -52,6 +62,7 @@ import com.hedera.hapi.node.state.token.TokenRelation; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.wipe.WipeTranslator; +import com.hedera.node.app.spi.fixtures.Scenarios; import com.hedera.node.app.spi.state.ReadableKVState; import java.util.HashMap; import java.util.Map; @@ -64,6 +75,12 @@ *
  • Wipe {@code ERC721_TOKEN} serial 1234 from Owner's account and verify successful operation
  • * *
  • Wipe 10 {@code ERC20_TOKEN} Owner's account via wipeTokenAccountV1 and verify successful operation
  • * *
  • Wipe 10 {@code ERC20_TOKEN} Owner's account via wipeTokenAccountV2 and verify successful operation
  • * + *
  • Wipe {@code ERC721_TOKEN} serial 1234 from Owner's account. This should fail with INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE
  • * + *
  • Wipe {@code ERC721_TOKEN} serial 1234 from Owner's account. This should fail with TOKEN_HAS_NO_WIPE_KEY
  • * + *
  • Wipe 10 {@code ERC20_TOKEN} Owner's account via wipeTokenAccountV1. This should fail with INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE
  • * + *
  • Wipe 10 {@code ERC20_TOKEN} Owner's account via wipeTokenAccountV1. This should fail with TOKEN_HAS_NO_WIPE_KEY
  • * + *
  • Wipe 10 {@code ERC20_TOKEN} Owner's account via wipeTokenAccountV2. This should fail with INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE
  • * + *
  • Wipe 10 {@code ERC20_TOKEN} Owner's account via wipeTokenAccountV2. This should fail with TOKEN_HAS_NO_WIPE_KEY
  • * *
  • Via {@code assertExpectedAccounts} verify that owner's nft supply was decreased by 1.
  • * *
  • Via {@code assertExpectedTokenRelations} verify that owner's token balance was decreased by 20.
  • * * @@ -158,6 +175,77 @@ protected void doScenarioOperations() { Bytes.wrap(ReturnTypes.encodedRc(INVALID_ACCOUNT_ID).array()), output, "Expected INVALID_ACCOUNT_ID when trying to execute with invalid account address (V2)")); + + // WIPE NFT from OWNER's account with invalid key + runHtsCallAndExpectOnSuccess( + OWNER_BESU_ADDRESS, + Bytes.wrap(WipeTranslator.WIPE_NFT + .encodeCallWithArgs( + A_TOKEN_ADDRESS, OWNER_HEADLONG_ADDRESS, new long[] {SN_1234.serialNumber()}) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE) + .array()), + output, + "Expected INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE when trying to execute with invalid wipe key")); + + // WIPE NFT from OWNER's account without wipe key + runHtsCallAndExpectOnSuccess( + OWNER_BESU_ADDRESS, + Bytes.wrap(WipeTranslator.WIPE_NFT + .encodeCallWithArgs( + B_TOKEN_ADDRESS, OWNER_HEADLONG_ADDRESS, new long[] {SN_1234.serialNumber()}) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(TOKEN_HAS_NO_WIPE_KEY).array()), + output, + "Expected TOKEN_HAS_NO_WIPE_KEY when trying to execute with invalid wipe key")); + + // WIPE 10 Tokens via wipeTokenAccountV1 with invalid key + runHtsCallAndExpectOnSuccess( + OWNER_BESU_ADDRESS, + Bytes.wrap(WipeTranslator.WIPE_FUNGIBLE_V1 + .encodeCallWithArgs(C_TOKEN_ADDRESS, OWNER_HEADLONG_ADDRESS, 10L) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE) + .array()), + output, + "Expected INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE when trying to execute with invalid wipe key")); + + // WIPE 10 Tokens via wipeTokenAccountV1 without wipe key + runHtsCallAndExpectOnSuccess( + OWNER_BESU_ADDRESS, + Bytes.wrap(WipeTranslator.WIPE_FUNGIBLE_V1 + .encodeCallWithArgs(D_TOKEN_ADDRESS, OWNER_HEADLONG_ADDRESS, 10L) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(TOKEN_HAS_NO_WIPE_KEY).array()), + output, + "Expected TOKEN_HAS_NO_WIPE_KEY when trying to execute with invalid wipe key")); + + // WIPE 10 Tokens via wipeTokenAccountV2 with invalid key + runHtsCallAndExpectOnSuccess( + OWNER_BESU_ADDRESS, + Bytes.wrap(WipeTranslator.WIPE_FUNGIBLE_V2 + .encodeCallWithArgs(C_TOKEN_ADDRESS, OWNER_HEADLONG_ADDRESS, 10L) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE) + .array()), + output, + "Expected INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE when trying to execute with invalid wipe key")); + + // WIPE 10 Tokens via wipeTokenAccountV2 without wipe key + runHtsCallAndExpectOnSuccess( + OWNER_BESU_ADDRESS, + Bytes.wrap(WipeTranslator.WIPE_FUNGIBLE_V2 + .encodeCallWithArgs(D_TOKEN_ADDRESS, OWNER_HEADLONG_ADDRESS, 10L) + .array()), + output -> assertEquals( + Bytes.wrap(ReturnTypes.encodedRc(TOKEN_HAS_NO_WIPE_KEY).array()), + output, + "Expected TOKEN_HAS_NO_WIPE_KEY when trying to execute with invalid wipe key")); } @Override @@ -188,6 +276,40 @@ protected Map initialTokens() { .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) .tokenType(TokenType.FUNGIBLE_COMMON) .build()); + tokens.put( + A_TOKEN_ID, + Token.newBuilder() + .tokenId(A_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.NON_FUNGIBLE_UNIQUE) + .totalSupply(1000L) + .wipeKey(Scenarios.ALICE.account().key()) + .build()); + tokens.put( + B_TOKEN_ID, + Token.newBuilder() + .tokenId(B_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.NON_FUNGIBLE_UNIQUE) + .totalSupply(1000L) + .build()); + tokens.put( + C_TOKEN_ID, + Token.newBuilder() + .tokenId(C_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.FUNGIBLE_COMMON) + .totalSupply(1000L) + .wipeKey(Scenarios.ALICE.account().key()) + .build()); + tokens.put( + D_TOKEN_ID, + Token.newBuilder() + .tokenId(D_TOKEN_ID) + .treasuryAccountId(UNAUTHORIZED_SPENDER_ID) + .tokenType(TokenType.FUNGIBLE_COMMON) + .totalSupply(1000L) + .build()); return tokens; } diff --git a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/data/ContractsConfig.java b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/data/ContractsConfig.java index 479bb53f32c4..25f4cb5b85db 100644 --- a/hedera-node/hedera-config/src/main/java/com/hedera/node/config/data/ContractsConfig.java +++ b/hedera-node/hedera-config/src/main/java/com/hedera/node/config/data/ContractsConfig.java @@ -25,7 +25,7 @@ @ConfigData("contracts") public record ContractsConfig( @ConfigProperty(defaultValue = "true") @NetworkProperty boolean itemizeStorageFees, - // @ConfigProperty(defaultValue = "1062787,1461860") Set
    permittedDelegateCallers, + @ConfigProperty(defaultValue = "1062787,1461860") Set permittedDelegateCallers, @ConfigProperty(defaultValue = "31536000") @NetworkProperty long referenceSlotLifetime, @ConfigProperty(defaultValue = "100") @NetworkProperty int freeStorageTierLimit, @ConfigProperty(defaultValue = "0til100M,2000til450M") @NetworkProperty String storageSlotPriceTiers, diff --git a/hedera-node/hedera-evm/src/main/java/module-info.java b/hedera-node/hedera-evm/src/main/java/module-info.java index 759a41bc0545..957f3263f537 100644 --- a/hedera-node/hedera-evm/src/main/java/module-info.java +++ b/hedera-node/hedera-evm/src/main/java/module-info.java @@ -11,7 +11,7 @@ requires transitive org.apache.commons.lang3; requires transitive org.hyperledger.besu.datatypes; requires transitive org.hyperledger.besu.evm; - requires transitive org.hyperledger.besu.secp256k1; + requires transitive org.hyperledger.besu.nativelib.secp256k1; requires transitive tuweni.bytes; requires transitive tuweni.units; requires com.google.common; diff --git a/hedera-node/hedera-mono-service/src/main/java/com/hedera/node/app/service/mono/ledger/TransferLogic.java b/hedera-node/hedera-mono-service/src/main/java/com/hedera/node/app/service/mono/ledger/TransferLogic.java index 7e6655aade4f..9e10fb53f292 100644 --- a/hedera-node/hedera-mono-service/src/main/java/com/hedera/node/app/service/mono/ledger/TransferLogic.java +++ b/hedera-node/hedera-mono-service/src/main/java/com/hedera/node/app/service/mono/ledger/TransferLogic.java @@ -132,7 +132,14 @@ public void doZeroSum(final List changes) { hasSuccessfulAutoCreation |= validity == OK; autoCreationFee += result.getValue(); if (validity == OK && (change.isForToken())) { - validity = tokenStore.tryTokenChange(change); + if (change.isForNft()) { + // An NFT transfer needs its allowances validated here + validity = + accountsLedger.validate(change.accountId(), scopedCheck.setBalanceChange(change)); + } + if (validity == OK) { + validity = tokenStore.tryTokenChange(change); + } } } else { validity = MAX_CHILD_RECORDS_EXCEEDED; diff --git a/hedera-node/hedera-mono-service/src/main/java/module-info.java b/hedera-node/hedera-mono-service/src/main/java/module-info.java index 7ad490aebae9..5e3773832b03 100644 --- a/hedera-node/hedera-mono-service/src/main/java/module-info.java +++ b/hedera-node/hedera-mono-service/src/main/java/module-info.java @@ -280,7 +280,7 @@ requires org.apache.commons.io; requires org.bouncycastle.provider; requires org.eclipse.collections.impl; - requires org.hyperledger.besu.secp256k1; + requires org.hyperledger.besu.nativelib.secp256k1; requires static com.github.spotbugs.annotations; requires static java.compiler; // javax.annotation.processing.Generated } diff --git a/hedera-node/hedera-schedule-service-impl/src/main/java/com/hedera/node/app/service/schedule/impl/handlers/HandlerUtility.java b/hedera-node/hedera-schedule-service-impl/src/main/java/com/hedera/node/app/service/schedule/impl/handlers/HandlerUtility.java index fbc4101c3cc5..c47db26ae06a 100644 --- a/hedera-node/hedera-schedule-service-impl/src/main/java/com/hedera/node/app/service/schedule/impl/handlers/HandlerUtility.java +++ b/hedera-node/hedera-schedule-service-impl/src/main/java/com/hedera/node/app/service/schedule/impl/handlers/HandlerUtility.java @@ -40,11 +40,11 @@ /** * A package-private utility class for Schedule Handlers. */ -final class HandlerUtility { +public final class HandlerUtility { private HandlerUtility() {} @NonNull - static TransactionBody childAsOrdinary(@NonNull final Schedule scheduleInState) { + public static TransactionBody childAsOrdinary(@NonNull final Schedule scheduleInState) { final TransactionID scheduledTransactionId = transactionIdForScheduled(scheduleInState); final SchedulableTransactionBody scheduledTransaction = scheduleInState.scheduledTransaction(); final TransactionBody.Builder ordinary = TransactionBody.newBuilder(); diff --git a/hedera-node/hedera-schedule-service-impl/src/main/java/com/hedera/node/app/service/schedule/impl/handlers/ScheduleCreateHandler.java b/hedera-node/hedera-schedule-service-impl/src/main/java/com/hedera/node/app/service/schedule/impl/handlers/ScheduleCreateHandler.java index 3d0f2217ad45..8a915abec1c7 100644 --- a/hedera-node/hedera-schedule-service-impl/src/main/java/com/hedera/node/app/service/schedule/impl/handlers/ScheduleCreateHandler.java +++ b/hedera-node/hedera-schedule-service-impl/src/main/java/com/hedera/node/app/service/schedule/impl/handlers/ScheduleCreateHandler.java @@ -192,7 +192,15 @@ private boolean isPresentIn( for (final Schedule candidate : possibleDuplicates) { if (compareForDuplicates(candidate, provisionalSchedule)) { // Do not forget to set the ID of the existing duplicate in the receipt... - context.recordBuilder(ScheduleRecordBuilder.class).scheduleID(candidate.scheduleId()); + TransactionID scheduledTransactionID = candidate + .originalCreateTransaction() + .transactionID() + .copyBuilder() + .scheduled(true) + .build(); + context.recordBuilder(ScheduleRecordBuilder.class) + .scheduleID(candidate.scheduleId()) + .scheduledTransactionID(scheduledTransactionID); return true; } } diff --git a/hedera-node/hedera-schedule-service-impl/src/main/java/com/hedera/node/app/service/schedule/impl/handlers/ScheduleSignHandler.java b/hedera-node/hedera-schedule-service-impl/src/main/java/com/hedera/node/app/service/schedule/impl/handlers/ScheduleSignHandler.java index 384e94bc4790..fdf05b6d5cd3 100644 --- a/hedera-node/hedera-schedule-service-impl/src/main/java/com/hedera/node/app/service/schedule/impl/handlers/ScheduleSignHandler.java +++ b/hedera-node/hedera-schedule-service-impl/src/main/java/com/hedera/node/app/service/schedule/impl/handlers/ScheduleSignHandler.java @@ -151,7 +151,8 @@ public void handle(@NonNull final HandleContext context) throws HandleException } final ScheduleRecordBuilder scheduleRecords = context.recordBuilder(ScheduleRecordBuilder.class); - scheduleRecords.scheduleID(idToSign); + // Based on fuzzy-record matching this field is not set in mono-service records + // scheduleRecords.scheduleID(idToSign); } else { // Note, this will never happen, but Sonar static analysis can't figure that out. throw new HandleException(ResponseCodeEnum.INVALID_SCHEDULE_ID); diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/HtsCallAttempt.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/HtsCallAttempt.java index a0199afcdfc6..9d76716662f1 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/HtsCallAttempt.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/HtsCallAttempt.java @@ -41,8 +41,6 @@ import java.util.List; import org.apache.tuweni.bytes.Bytes; import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.datatypes.Wei; -import org.hyperledger.besu.evm.frame.BlockValues; /** * Manages the call attempted by a {@link Bytes} payload received by the {@link HtsSystemContract}. @@ -70,8 +68,6 @@ public class HtsCallAttempt { private final SystemContractGasCalculator gasCalculator; private final List callTranslators; private final boolean isStaticCall; - private final BlockValues blockValues; - private final Wei value; // too many parameters @SuppressWarnings("java:S107") public HtsCallAttempt( @@ -84,9 +80,7 @@ public HtsCallAttempt( @NonNull final VerificationStrategies verificationStrategies, @NonNull final SystemContractGasCalculator gasCalculator, @NonNull final List callTranslators, - final boolean isStaticCall, - @NonNull final BlockValues blockValues, - @NonNull final Wei value) { + final boolean isStaticCall) { requireNonNull(input); this.callTranslators = requireNonNull(callTranslators); this.gasCalculator = requireNonNull(gasCalculator); @@ -96,8 +90,6 @@ public HtsCallAttempt( this.enhancement = requireNonNull(enhancement); this.verificationStrategies = requireNonNull(verificationStrategies); this.onlyDelegatableContractKeysActive = onlyDelegatableContractKeysActive; - this.blockValues = blockValues; - this.value = value; this.isRedirect = isRedirect(input.toArrayUnsafe()); if (this.isRedirect) { @@ -197,13 +189,6 @@ public HtsCallAttempt( return senderAddress; } - public @NonNull BlockValues blockValues() { - return blockValues; - } - - public @NonNull Wei getValue() { - return value; - } /** * Returns whether only delegatable contract keys are active for this call. * diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/HtsCallFactory.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/HtsCallFactory.java index 8e980d750b6d..1764969fcf77 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/HtsCallFactory.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/HtsCallFactory.java @@ -75,8 +75,6 @@ public HtsCallFactory( verificationStrategies, systemContractGasCalculatorOf(frame), callTranslators, - frame.isStatic(), - frame.getBlockValues(), - frame.getValue()); + frame.isStatic()); } } diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/create/ClassicCreatesCall.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/create/ClassicCreatesCall.java index 92f740139585..ed8e613f71a4 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/create/ClassicCreatesCall.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/create/ClassicCreatesCall.java @@ -29,12 +29,14 @@ import static com.hedera.node.app.service.contract.impl.utils.SystemContractUtils.contractFunctionResultFailedFor; import static java.util.Objects.requireNonNull; +import com.hedera.hapi.node.base.AccountID; import com.hedera.hapi.node.base.ResponseCodeEnum; import com.hedera.hapi.node.base.TokenType; import com.hedera.hapi.node.token.TokenCreateTransactionBody; import com.hedera.hapi.node.transaction.TransactionBody; import com.hedera.node.app.service.contract.impl.exec.gas.SystemContractGasCalculator; import com.hedera.node.app.service.contract.impl.exec.scope.VerificationStrategy; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.FullResult; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.AbstractHtsCall; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.AddressIdConverter; import com.hedera.node.app.service.contract.impl.hevm.HederaWorldUpdater; @@ -44,7 +46,7 @@ import java.nio.ByteBuffer; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; -import org.hyperledger.besu.evm.frame.BlockValues; +import org.hyperledger.besu.evm.frame.MessageFrame; public class ClassicCreatesCall extends AbstractHtsCall { /** @@ -57,13 +59,8 @@ public class ClassicCreatesCall extends AbstractHtsCall { private final AddressIdConverter addressIdConverter; private final VerificationStrategy verificationStrategy; - private final org.hyperledger.besu.datatypes.Address spender; - - @NonNull - private final BlockValues blockValues; - - @NonNull - private final Wei value; + private final AccountID spenderId; + private final long gasRequirement; public ClassicCreatesCall( @NonNull final SystemContractGasCalculator systemContractGasCalculator, @@ -71,16 +68,14 @@ public ClassicCreatesCall( @NonNull final TransactionBody syntheticCreate, @NonNull final VerificationStrategy verificationStrategy, @NonNull final org.hyperledger.besu.datatypes.Address spender, - @NonNull final AddressIdConverter addressIdConverter, - @NonNull final BlockValues blockValues, - @NonNull final Wei value) { + @NonNull final AddressIdConverter addressIdConverter) { super(systemContractGasCalculator, enhancement, false); this.syntheticCreate = requireNonNull(syntheticCreate); this.verificationStrategy = requireNonNull(verificationStrategy); - this.spender = requireNonNull(spender); this.addressIdConverter = requireNonNull(addressIdConverter); - this.blockValues = blockValues; - this.value = value; + + this.spenderId = addressIdConverter.convert(asHeadlongAddress(spender.toArrayUnsafe())); + this.gasRequirement = gasCalculator.gasRequirement(syntheticCreate, spenderId, MINIMUM_TINYBAR_PRICE); } @Override @@ -95,16 +90,9 @@ public ClassicCreatesCall( if (treasuryAccount == null) { return externalizeUnsuccessfulResult(INVALID_ACCOUNT_ID, gasCalculator.viewGasRequirement()); } - if (token.autoRenewAccount() == null) { return externalizeUnsuccessfulResult(INVALID_EXPIRATION_TIME, gasCalculator.viewGasRequirement()); } - final var spenderId = addressIdConverter.convert(asHeadlongAddress(spender.toArrayUnsafe())); - - final long gasRequirement = gasCalculator.gasRequirement(syntheticCreate, spenderId, MINIMUM_TINYBAR_PRICE); - if (!value.greaterOrEqualThan(Wei.of(gasRequirement))) { - return externalizeUnsuccessfulResult(INSUFFICIENT_TX_FEE, gasCalculator.viewGasRequirement()); - } final var recordBuilder = systemContractOperations() .dispatch(syntheticCreate, verificationStrategy, spenderId, CryptoCreateRecordBuilder.class); @@ -140,9 +128,17 @@ public ClassicCreatesCall( } } + @Override + public @NonNull PricedResult execute(final MessageFrame frame) { + if (!frame.getValue().greaterOrEqualThan(Wei.of(gasRequirement))) { + return externalizeUnsuccessfulResult(INSUFFICIENT_TX_FEE, gasCalculator.viewGasRequirement()); + } + return execute(); + } + // @TODO extract externalizeResult() calls into a single location on a higher level private PricedResult externalizeUnsuccessfulResult(ResponseCodeEnum responseCode, long gasRequirement) { - final var result = gasOnly(revertResult(responseCode, gasRequirement), responseCode, false); + final var result = gasOnly(FullResult.revertResult(responseCode, gasRequirement), responseCode, false); final var contractID = asEvmContractId(Address.fromHexString(HTS_EVM_ADDRESS)); enhancement diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/create/CreateTranslator.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/create/CreateTranslator.java index c4b008868249..671501d1280b 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/create/CreateTranslator.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/create/CreateTranslator.java @@ -154,9 +154,7 @@ public ClassicCreatesCall callFrom(@NonNull HtsCallAttempt attempt) { nominalBodyFor(attempt), attempt.defaultVerificationStrategy(), attempt.senderAddress(), - attempt.addressIdConverter(), - attempt.blockValues(), - attempt.getValue()); + attempt.addressIdConverter()); } private TransactionBody nominalBodyFor(@NonNull final HtsCallAttempt attempt) { diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateDecoder.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateDecoder.java index 5bc107aabeed..267a979b601e 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateDecoder.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateDecoder.java @@ -96,13 +96,13 @@ private static boolean isKnownImmutable(@Nullable final Token token) { } /** - * Decodes a call to {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION} into a synthetic {@link TransactionBody}. + * Decodes a call to {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V1} into a synthetic {@link TransactionBody}. * * @param attempt the attempt * @return the synthetic transaction body */ public TransactionBody decodeTokenUpdateV1(@NonNull final HtsCallAttempt attempt) { - final var call = UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION.decodeCall( + final var call = UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V1.decodeCall( attempt.input().toArrayUnsafe()); return decodeTokenUpdate(call, attempt.addressIdConverter()); } diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateTranslator.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateTranslator.java index 90029c3a58ad..e20629cd5366 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateTranslator.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateTranslator.java @@ -45,7 +45,7 @@ public class UpdateTranslator extends AbstractHtsCallTranslator { "(string,string,address,string,bool,int64,bool," + TOKEN_KEY + ARRAY_BRACKETS + "," + EXPIRY + ")"; private static final String HEDERA_TOKEN_STRUCT_V3 = "(string,string,address,string,bool,int64,bool," + TOKEN_KEY + ARRAY_BRACKETS + "," + EXPIRY_V2 + ")"; - public static final Function TOKEN_UPDATE_INFO_FUNCTION = + public static final Function TOKEN_UPDATE_INFO_FUNCTION_V1 = new Function(UPDATE_TOKEN_INFO_STRING + HEDERA_TOKEN_STRUCT + ")", ReturnTypes.INT); public static final Function TOKEN_UPDATE_INFO_FUNCTION_V2 = new Function(UPDATE_TOKEN_INFO_STRING + HEDERA_TOKEN_STRUCT_V2 + ")", ReturnTypes.INT); @@ -62,7 +62,7 @@ public UpdateTranslator(UpdateDecoder decoder) { @Override public boolean matches(@NonNull HtsCallAttempt attempt) { - return Arrays.equals(attempt.selector(), TOKEN_UPDATE_INFO_FUNCTION.selector()) + return Arrays.equals(attempt.selector(), TOKEN_UPDATE_INFO_FUNCTION_V1.selector()) || Arrays.equals(attempt.selector(), TOKEN_UPDATE_INFO_FUNCTION_V2.selector()) || Arrays.equals(attempt.selector(), TOKEN_UPDATE_INFO_FUNCTION_V3.selector()); } @@ -86,7 +86,7 @@ public static long gasRequirement( } private TransactionBody nominalBodyFor(@NonNull final HtsCallAttempt attempt) { - if (Arrays.equals(attempt.selector(), TOKEN_UPDATE_INFO_FUNCTION.selector())) { + if (Arrays.equals(attempt.selector(), TOKEN_UPDATE_INFO_FUNCTION_V1.selector())) { return decoder.decodeTokenUpdateV1(attempt); } else if (Arrays.equals(attempt.selector(), TOKEN_UPDATE_INFO_FUNCTION_V2.selector())) { return decoder.decodeTokenUpdateV2(attempt); diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/utils/FrameUtils.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/utils/FrameUtils.java index 4b2076682e51..1d8c2b749a10 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/utils/FrameUtils.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/utils/FrameUtils.java @@ -25,6 +25,7 @@ import com.hedera.node.app.service.contract.impl.exec.processors.CustomMessageCallProcessor; import com.hedera.node.app.service.contract.impl.infra.StorageAccessTracker; import com.hedera.node.app.service.contract.impl.state.ProxyWorldUpdater; +import com.hedera.node.app.service.contract.impl.utils.ConversionUtils; import com.hedera.node.config.data.ContractsConfig; import com.swirlds.config.api.Configuration; import edu.umd.cs.findbugs.annotations.NonNull; @@ -136,11 +137,16 @@ public static boolean unqualifiedDelegateDetected(final MessageFrame frame) { if (!isDelegateCall(frame)) { return false; } + final Address recipient = frame.getRecipientAddress(); - final var recipient = frame.getRecipientAddress(); - // but we accept delegates if the token redirect contract calls us, - // so if they are not a token, then we are a delegate and we are done. - if (isToken(frame, recipient)) { + final var permittedDelegateCallers = contractsConfigOf(frame).permittedDelegateCallers(); + + // Evaluate whether the recipient is either a token or on the permitted callers list. + // This determines if we should treat this as a delegate call. + // We accept delegates if the token redirect contract calls us. + if (isToken(frame, recipient) + || (ConversionUtils.isLongZero(recipient) + && permittedDelegateCallers.contains(ConversionUtils.numberOfLongZero(recipient)))) { // make sure we have a parent calling context final var stack = frame.getMessageFrameStack(); final var frames = stack.iterator(); diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/handlers/ContractDeleteHandler.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/handlers/ContractDeleteHandler.java index f5982afc6355..0e03a402ce16 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/handlers/ContractDeleteHandler.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/handlers/ContractDeleteHandler.java @@ -87,8 +87,9 @@ public void handle(@NonNull final HandleContext context) throws HandleException final var accountStore = context.readableStore(ReadableAccountStore.class); final var toBeDeleted = requireNonNull(accountStore.getContractById(op.contractIDOrThrow())); final var obtainer = getObtainer(accountStore, op); - if (obtainer == null || obtainer.deleted()) { - throw new HandleException(OBTAINER_DOES_NOT_EXIST); + validateTrue(obtainer != null, OBTAINER_DOES_NOT_EXIST); + if (obtainer.deleted()) { + throw new HandleException(obtainer.smartContract() ? INVALID_CONTRACT_ID : OBTAINER_DOES_NOT_EXIST); } final var recordBuilder = context.recordBuilder(ContractDeleteRecordBuilder.class); final var deletedId = toBeDeleted.accountIdOrThrow(); diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/TestHelpers.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/TestHelpers.java index 441687e07cf6..be494057bf87 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/TestHelpers.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/TestHelpers.java @@ -100,6 +100,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Set; import org.apache.tuweni.units.bigints.UInt256; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; @@ -131,6 +132,9 @@ public class TestHelpers { .withValue("contracts.allowAutoAssociations", true) .getOrCreateConfig(); + public static final Configuration PERMITTED_CALLERS_CONFIG = HederaTestConfigBuilder.create() + .withValue("contracts.permittedContractCallers", Set.of(1062787L)) + .getOrCreateConfig(); public static final Configuration DEV_CHAIN_ID_CONFIG = HederaTestConfigBuilder.create().withValue("contracts.chainId", 298).getOrCreateConfig(); public static final LedgerConfig AUTO_ASSOCIATING_LEDGER_CONFIG = @@ -392,7 +396,8 @@ public class TestHelpers { .contractNum(numberOfLongZero(NON_SYSTEM_LONG_ZERO_ADDRESS)) .build(); public static final Address EIP_1014_ADDRESS = Address.fromHexString("0x89abcdef89abcdef89abcdef89abcdef89abcdef"); - + public static final Address PERMITTED_ADDRESS_CALLER = + Address.wrap((org.apache.tuweni.bytes.Bytes.wrap(asEvmAddress(1062787L)))); public static final Account OPERATOR = Account.newBuilder().accountId(B_NEW_ACCOUNT_ID).build(); diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/HtsCallAttemptTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/HtsCallAttemptTest.java index bc216116c289..56cfb58447ff 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/HtsCallAttemptTest.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/HtsCallAttemptTest.java @@ -77,8 +77,6 @@ import java.util.Arrays; import java.util.List; import org.apache.tuweni.bytes.Bytes; -import org.hyperledger.besu.datatypes.Wei; -import org.hyperledger.besu.evm.frame.BlockValues; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -92,9 +90,6 @@ class HtsCallAttemptTest extends HtsCallTestBase { @Mock private AddressIdConverter addressIdConverter; - @Mock - private BlockValues blockValues; - @Mock private VerificationStrategy strategy; @@ -109,8 +104,6 @@ class HtsCallAttemptTest extends HtsCallTestBase { private List callTranslators; - private Wei value = Wei.ZERO; - @BeforeEach void setUp() { callTranslators = List.of( @@ -143,9 +136,7 @@ void nonLongZeroAddressesArentTokens() { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertNull(subject.redirectToken()); verifyNoInteractions(nativeOperations); } @@ -165,9 +156,7 @@ void invalidSelectorLeadsToMissingCall() { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertNull(subject.asExecutableCall()); } @@ -185,9 +174,7 @@ void constructsDecimals() { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(DecimalsCall.class, subject.asExecutableCall()); } @@ -205,9 +192,7 @@ void constructsTokenUri() { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(TokenUriCall.class, subject.asExecutableCall()); } @@ -225,9 +210,7 @@ void constructsOwnerOf() { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(OwnerOfCall.class, subject.asExecutableCall()); } @@ -248,9 +231,7 @@ void constructsBalanceOf() { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(BalanceOfCall.class, subject.asExecutableCall()); } @@ -272,9 +253,7 @@ void constructsIsApprovedForAllErc() { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(IsApprovedForAllCall.class, subject.asExecutableCall()); } @@ -294,9 +273,7 @@ void constructsIsApprovedForAllClassic() { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(IsApprovedForAllCall.class, subject.asExecutableCall()); } @@ -314,9 +291,7 @@ void constructsTotalSupply() { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(TotalSupplyCall.class, subject.asExecutableCall()); } @@ -334,9 +309,7 @@ void constructsName() { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(NameCall.class, subject.asExecutableCall()); } @@ -354,9 +327,7 @@ void constructsSymbol() { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(SymbolCall.class, subject.asExecutableCall()); } @@ -385,9 +356,7 @@ void constructsErc721TransferFromRedirectToNonfungible() { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(Erc721TransferFromCall.class, subject.asExecutableCall()); } @@ -416,9 +385,7 @@ void constructsErc20TransferFromRedirectToFungible() { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(Erc20TransfersCall.class, subject.asExecutableCall()); } @@ -444,9 +411,7 @@ void constructsErc20TransferRedirectToFungible() { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(Erc20TransfersCall.class, subject.asExecutableCall()); } @@ -498,9 +463,7 @@ void constructsAssociations(boolean useExplicitCall, boolean isRedirect, String verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(DispatchForResponseCodeHtsCall.class, subject.asExecutableCall()); assertArrayEquals(selector, subject.selector()); @@ -562,9 +525,7 @@ void constructsClassicTransfers(String hexedSelector) { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(ClassicTransfersCall.class, subject.asExecutableCall()); assertArrayEquals(selector, subject.selector()); @@ -634,9 +595,7 @@ void constructsMints(String hexedSelector, LinkedTokenType linkedTokenType) { verificationStrategies, gasCalculator, callTranslators, - false, - blockValues, - value); + false); assertInstanceOf(DispatchForResponseCodeHtsCall.class, subject.asExecutableCall()); assertArrayEquals(selector, subject.selector()); diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/create/ClassicCreatesCallTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/create/ClassicCreatesCallTest.java index 0464909345a3..ff16ba97a940 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/create/ClassicCreatesCallTest.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/create/ClassicCreatesCallTest.java @@ -42,7 +42,6 @@ import java.math.BigInteger; import org.apache.tuweni.bytes.Bytes; import org.hyperledger.besu.datatypes.Wei; -import org.hyperledger.besu.evm.frame.BlockValues; import org.hyperledger.besu.evm.frame.MessageFrame; import org.junit.jupiter.api.Test; import org.mockito.Mock; @@ -62,11 +61,6 @@ public class ClassicCreatesCallTest extends HtsCallTestBase { @Mock private CryptoCreateRecordBuilder recordBuilder; - @Mock - private BlockValues blockValues; - - private Wei value = Wei.MAX_WEI; - private static final TransactionBody PRETEND_CREATE_TOKEN = TransactionBody.newBuilder() .tokenCreation(TokenCreateTransactionBody.newBuilder() .symbol("FT") @@ -82,7 +76,7 @@ void createFungibleTokenHappyPathV1() { commonGivens(); given(recordBuilder.status()).willReturn(SUCCESS); - final var result = subject.execute().fullResult().result(); + final var result = subject.execute(frame).fullResult().result(); assertEquals(MessageFrame.State.COMPLETED_SUCCESS, result.getState()); assertEquals( @@ -97,7 +91,7 @@ void createFungibleTokenHappyPathV2() { commonGivens(); given(recordBuilder.status()).willReturn(SUCCESS); - final var result = subject.execute().fullResult().result(); + final var result = subject.execute(frame).fullResult().result(); assertEquals(MessageFrame.State.COMPLETED_SUCCESS, result.getState()); assertEquals( @@ -112,7 +106,7 @@ void createFungibleTokenHappyPathV3() { commonGivens(); given(recordBuilder.status()).willReturn(SUCCESS); - final var result = subject.execute().fullResult().result(); + final var result = subject.execute(frame).fullResult().result(); assertEquals(MessageFrame.State.COMPLETED_SUCCESS, result.getState()); assertEquals( @@ -127,7 +121,7 @@ void createFungibleTokenWithCustomFeesHappyPathV1() { commonGivens(); given(recordBuilder.status()).willReturn(SUCCESS); - final var result = subject.execute().fullResult().result(); + final var result = subject.execute(frame).fullResult().result(); assertEquals(MessageFrame.State.COMPLETED_SUCCESS, result.getState()); assertEquals( @@ -142,7 +136,7 @@ void createFungibleTokenWithCustomFeesHappyPathV2() { commonGivens(); given(recordBuilder.status()).willReturn(SUCCESS); - final var result = subject.execute().fullResult().result(); + final var result = subject.execute(frame).fullResult().result(); assertEquals(MessageFrame.State.COMPLETED_SUCCESS, result.getState()); assertEquals( @@ -157,7 +151,7 @@ void createFungibleTokenWithCustomFeesHappyPathV3() { commonGivens(); given(recordBuilder.status()).willReturn(SUCCESS); - final var result = subject.execute().fullResult().result(); + final var result = subject.execute(frame).fullResult().result(); assertEquals(MessageFrame.State.COMPLETED_SUCCESS, result.getState()); assertEquals( @@ -172,7 +166,7 @@ void createNonFungibleTokenHappyPathV1() { commonGivens(); given(recordBuilder.status()).willReturn(SUCCESS); - final var result = subject.execute().fullResult().result(); + final var result = subject.execute(frame).fullResult().result(); assertEquals(MessageFrame.State.COMPLETED_SUCCESS, result.getState()); assertEquals( @@ -187,7 +181,7 @@ void createNonFungibleTokenHappyPathV2() { commonGivens(); given(recordBuilder.status()).willReturn(SUCCESS); - final var result = subject.execute().fullResult().result(); + final var result = subject.execute(frame).fullResult().result(); assertEquals(MessageFrame.State.COMPLETED_SUCCESS, result.getState()); assertEquals( @@ -202,7 +196,7 @@ void createNonFungibleTokenHappyPathV3() { commonGivens(); given(recordBuilder.status()).willReturn(SUCCESS); - final var result = subject.execute().fullResult().result(); + final var result = subject.execute(frame).fullResult().result(); assertEquals(MessageFrame.State.COMPLETED_SUCCESS, result.getState()); assertEquals( @@ -217,7 +211,7 @@ void createNonFungibleTokenWithCustomFeesHappyPathV1() { commonGivens(); given(recordBuilder.status()).willReturn(SUCCESS); - final var result = subject.execute().fullResult().result(); + final var result = subject.execute(frame).fullResult().result(); assertEquals(MessageFrame.State.COMPLETED_SUCCESS, result.getState()); assertEquals( @@ -232,7 +226,7 @@ void createNonFungibleTokenWithCustomFeesHappyPathV2() { commonGivens(); given(recordBuilder.status()).willReturn(SUCCESS); - final var result = subject.execute().fullResult().result(); + final var result = subject.execute(frame).fullResult().result(); assertEquals(MessageFrame.State.COMPLETED_SUCCESS, result.getState()); assertEquals( @@ -247,7 +241,7 @@ void createNonFungibleTokenWithCustomFeesHappyPathV3() { commonGivens(); given(recordBuilder.status()).willReturn(SUCCESS); - final var result = subject.execute().fullResult().result(); + final var result = subject.execute(frame).fullResult().result(); assertEquals(MessageFrame.State.COMPLETED_SUCCESS, result.getState()); assertEquals( @@ -262,26 +256,26 @@ void createFungibleTokenUnhappyPathRevertsWithReason() { commonGivens(); given(recordBuilder.status()).willReturn(TOKEN_HAS_NO_SUPPLY_KEY); - final var result = subject.execute().fullResult().result(); + final var result = subject.execute(frame).fullResult().result(); assertEquals(MessageFrame.State.REVERT, result.getState()); assertEquals(Bytes.wrap(TOKEN_HAS_NO_SUPPLY_KEY.protoName().getBytes()), result.getOutput()); } private void commonGivens() { + given(frame.getValue()).willReturn(Wei.ZERO); + given(addressIdConverter.convert(asHeadlongAddress(FRAME_SENDER_ADDRESS))) + .willReturn(A_NEW_ACCOUNT_ID); + given(nativeOperations.getAccount(A_NEW_ACCOUNT_ID.accountNumOrThrow())).willReturn(ALIASED_SOMEBODY); + subject = new ClassicCreatesCall( systemContractGasCalculator, mockEnhancement(), PRETEND_CREATE_TOKEN, verificationStrategy, FRAME_SENDER_ADDRESS, - addressIdConverter, - blockValues, - value); + addressIdConverter); - given(addressIdConverter.convert(asHeadlongAddress(FRAME_SENDER_ADDRESS))) - .willReturn(A_NEW_ACCOUNT_ID); - given(nativeOperations.getAccount(A_NEW_ACCOUNT_ID.accountNumOrThrow())).willReturn(ALIASED_SOMEBODY); given(systemContractOperations.dispatch( any(TransactionBody.class), eq(verificationStrategy), diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateDecoderTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateDecoderTest.java index 7798d0512f1b..e6d79f32d9bb 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateDecoderTest.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateDecoderTest.java @@ -71,7 +71,7 @@ void setUp() { @Test void updateV1Works() { - final var encoded = Bytes.wrapByteBuffer(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION.encodeCallWithArgs( + final var encoded = Bytes.wrapByteBuffer(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V1.encodeCallWithArgs( FUNGIBLE_TOKEN_HEADLONG_ADDRESS, hederaToken)); given(attempt.input()).willReturn(encoded); diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateTranslatorTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateTranslatorTest.java index d0207c768b6b..6e023067ffbc 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateTranslatorTest.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateTranslatorTest.java @@ -155,7 +155,7 @@ void failureCustomizerDoesNothingForInvalidTokenId() { @Test void matchesUpdateV1Test() { - given(attempt.selector()).willReturn(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION.selector()); + given(attempt.selector()).willReturn(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V1.selector()); final var matches = subject.matches(attempt); assertThat(matches).isTrue(); } @@ -177,9 +177,9 @@ void matchesUpdateV3Test() { @Test void callFromUpdateTest() { Tuple tuple = new Tuple(NON_FUNGIBLE_TOKEN_HEADLONG_ADDRESS, hederaToken); - Bytes inputBytes = Bytes.wrapByteBuffer(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION.encodeCall(tuple)); + Bytes inputBytes = Bytes.wrapByteBuffer(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V1.encodeCall(tuple)); given(attempt.input()).willReturn(inputBytes); - given(attempt.selector()).willReturn(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION.selector()); + given(attempt.selector()).willReturn(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V1.selector()); given(attempt.enhancement()).willReturn(mockEnhancement()); given(attempt.addressIdConverter()).willReturn(addressIdConverter); given(addressIdConverter.convertSender(any())).willReturn(NON_SYSTEM_ACCOUNT_ID); diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/utils/FrameUtilsTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/utils/FrameUtilsTest.java index e490454a570b..e8671431254e 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/utils/FrameUtilsTest.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/utils/FrameUtilsTest.java @@ -23,6 +23,9 @@ import static com.hedera.node.app.service.contract.impl.test.TestHelpers.DEFAULT_CONFIG; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.EIP_1014_ADDRESS; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.NON_SYSTEM_LONG_ZERO_ADDRESS; +import static com.hedera.node.app.service.contract.impl.test.TestHelpers.PERMITTED_ADDRESS_CALLER; +import static com.hedera.node.app.service.contract.impl.test.TestHelpers.PERMITTED_CALLERS_CONFIG; +import static com.hedera.node.app.service.evm.store.contracts.HederaEvmWorldStateTokenAccount.TOKEN_PROXY_ACCOUNT_NONCE; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; @@ -44,7 +47,9 @@ import java.util.Deque; import java.util.HashSet; import java.util.Set; +import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.worldstate.WorldUpdater; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -68,6 +73,12 @@ class FrameUtilsTest { @Mock private MessageFrame initialFrame; + @Mock + private MutableAccount account; + + @Mock + private WorldUpdater worldUpdater; + private final Deque stack = new ArrayDeque<>(); @Test @@ -103,6 +114,73 @@ void childOfParentExecutingItsOwnCodeDoesNotAcquireSenderAuthorizationViaDelegat assertFalse(FrameUtils.acquiredSenderAuthorizationViaDelegateCall(frame)); } + @Test + void unqualifiedDelegateDetectedValidationPass() { + // given + stack.push(initialFrame); + stack.push(frame); + given(frame.getWorldUpdater()).willReturn(worldUpdater); + given(frame.getMessageFrameStack()).willReturn(stack); + + given(frame.getRecipientAddress()).willReturn(EIP_1014_ADDRESS); + given(frame.getContractAddress()).willReturn(NON_SYSTEM_LONG_ZERO_ADDRESS); + given(initialFrame.getRecipientAddress()).willReturn(EIP_1014_ADDRESS); + given(initialFrame.getContractAddress()).willReturn(EIP_1014_ADDRESS); + + given(worldUpdater.get(EIP_1014_ADDRESS)).willReturn(account); + given(account.getNonce()).willReturn(TOKEN_PROXY_ACCOUNT_NONCE); + given(initialFrame.getContextVariable(CONFIG_CONTEXT_VARIABLE)).willReturn(DEFAULT_CONFIG); + + // when + final var isQualifiedForDelegate = !FrameUtils.unqualifiedDelegateDetected(frame); + + // then + assertTrue(isQualifiedForDelegate); + } + + @Test + void unqualifiedDelegateDetectedValidationFailTokenNull() { + // given + givenNonInitialFrame(); + given(frame.getMessageFrameStack()).willReturn(stack); + given(frame.getWorldUpdater()).willReturn(worldUpdater); + + given(frame.getRecipientAddress()).willReturn(EIP_1014_ADDRESS); + given(frame.getContractAddress()).willReturn(NON_SYSTEM_LONG_ZERO_ADDRESS); + + given(worldUpdater.get(EIP_1014_ADDRESS)).willReturn(null); + given(initialFrame.getContextVariable(CONFIG_CONTEXT_VARIABLE)).willReturn(DEFAULT_CONFIG); + + // when + final var isQualifiedForDelegate = !FrameUtils.unqualifiedDelegateDetected(frame); + + // then + assertFalse(isQualifiedForDelegate); + } + + @Test + void unqualifiedDelegateDetectedValidationPassWithPermittedCaller() { + // given + stack.push(initialFrame); + stack.push(frame); + given(frame.getMessageFrameStack()).willReturn(stack); + given(frame.getWorldUpdater()).willReturn(worldUpdater); + + given(frame.getRecipientAddress()).willReturn(PERMITTED_ADDRESS_CALLER); + given(frame.getContractAddress()).willReturn(NON_SYSTEM_LONG_ZERO_ADDRESS); + given(initialFrame.getRecipientAddress()).willReturn(PERMITTED_ADDRESS_CALLER); + given(initialFrame.getContractAddress()).willReturn(PERMITTED_ADDRESS_CALLER); + + given(worldUpdater.get(PERMITTED_ADDRESS_CALLER)).willReturn(null); + given(initialFrame.getContextVariable(CONFIG_CONTEXT_VARIABLE)).willReturn(PERMITTED_CALLERS_CONFIG); + + // when + final var isQualifiedForDelegate = !FrameUtils.unqualifiedDelegateDetected(frame); + + // then + assertTrue(isQualifiedForDelegate); + } + @Test void childOfParentExecutingDelegateCodeDoesAcquireSenderAuthorizationViaDelegateCall() { given(initialFrame.getRecipientAddress()).willReturn(EIP_1014_ADDRESS); diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/handlers/ContractDeleteHandlerTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/handlers/ContractDeleteHandlerTest.java index 7a3dd148db32..e602b44ccb56 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/handlers/ContractDeleteHandlerTest.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/handlers/ContractDeleteHandlerTest.java @@ -16,6 +16,7 @@ package com.hedera.node.app.service.contract.impl.test.handlers; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_CONTRACT_ID; import static com.hedera.hapi.node.base.ResponseCodeEnum.MODIFYING_IMMUTABLE_CONTRACT; import static com.hedera.hapi.node.base.ResponseCodeEnum.OBTAINER_DOES_NOT_EXIST; import static com.hedera.hapi.node.base.ResponseCodeEnum.OBTAINER_REQUIRED; @@ -136,7 +137,7 @@ void failsWithoutObtainerExtant() { } @Test - void failsWithObtainerDeleted() { + void failsWithInvalidContractId() { given(context.readableStore(ReadableAccountStore.class)).willReturn(readableAccountStore); final var deletedObtainer = OBTAINER_ACCOUNT.copyBuilder().smartContract(true).deleted(true).build(); @@ -144,6 +145,21 @@ void failsWithObtainerDeleted() { given(readableAccountStore.getContractById(CALLED_CONTRACT_ID)).willReturn(deletedObtainer); givenFailContextWith(deletion(VALID_CONTRACT_ADDRESS, CALLED_CONTRACT_ID)); + assertFailsWith(INVALID_CONTRACT_ID, () -> subject.handle(context)); + } + + @Test + void failsWithObtainerDeleted() { + given(context.readableStore(ReadableAccountStore.class)).willReturn(readableAccountStore); + final var deletedObtainer = OBTAINER_ACCOUNT + .copyBuilder() + .smartContract(false) + .deleted(true) + .build(); + given(readableAccountStore.getContractById(VALID_CONTRACT_ADDRESS)).willReturn(TBD_CONTRACT); + given(readableAccountStore.getContractById(CALLED_CONTRACT_ID)).willReturn(deletedObtainer); + givenFailContextWith(deletion(VALID_CONTRACT_ADDRESS, CALLED_CONTRACT_ID)); + assertFailsWith(OBTAINER_DOES_NOT_EXIST, () -> subject.handle(context)); } diff --git a/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/RecordFinalizerBase.java b/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/RecordFinalizerBase.java index 34e70874306c..61aef3da31da 100644 --- a/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/RecordFinalizerBase.java +++ b/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/RecordFinalizerBase.java @@ -20,6 +20,7 @@ import static com.hedera.node.app.service.token.impl.comparator.TokenComparators.ACCOUNT_AMOUNT_COMPARATOR; import static com.hedera.node.app.service.token.impl.handlers.staking.StakingRewardsHelper.asAccountAmounts; import static com.hedera.node.app.spi.workflows.HandleException.validateTrue; +import static java.util.Objects.requireNonNull; import com.hedera.hapi.node.base.AccountID; import com.hedera.hapi.node.base.NftID; @@ -91,9 +92,9 @@ protected Map fungibleChangesFrom( @NonNull final ReadableTokenStore tokenStore) { final var fungibleChanges = new HashMap(); for (final EntityIDPair modifiedRel : writableTokenRelStore.modifiedTokens()) { - final var relAcctId = modifiedRel.accountId(); - final var relTokenId = modifiedRel.tokenId(); - final var token = tokenStore.get(relTokenId); + final var relAcctId = modifiedRel.accountIdOrThrow(); + final var relTokenId = modifiedRel.tokenIdOrThrow(); + final var token = requireNonNull(tokenStore.get(relTokenId)); // Add this to fungible token transfer list only if this token is a fungible token if (!token.tokenType().equals(TokenType.FUNGIBLE_COMMON)) { continue; diff --git a/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/handlers/transfer/customfees/CustomRoyaltyFeeAssessor.java b/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/handlers/transfer/customfees/CustomRoyaltyFeeAssessor.java index 8304041daacf..072e6cd46da2 100644 --- a/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/handlers/transfer/customfees/CustomRoyaltyFeeAssessor.java +++ b/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/handlers/transfer/customfees/CustomRoyaltyFeeAssessor.java @@ -86,6 +86,10 @@ public void assessRoyaltyFees( if (!royaltyFee.hasFallbackFee()) { continue; } + // Skip if the receiver has already paid the fallback fee for this token + if (result.getRoyaltiesPaid().contains(Pair.of(receiver, tokenId))) { + continue; + } final var fallback = royaltyFee.fallbackFeeOrThrow(); final var fallbackFee = asFixedFee( fallback.amount(), fallback.denominatingTokenId(), collector, fee.allCollectorsAreExempt()); diff --git a/hedera-node/test-clients/build.gradle.kts b/hedera-node/test-clients/build.gradle.kts index eaa3d176e5af..3cd02165f8b0 100644 --- a/hedera-node/test-clients/build.gradle.kts +++ b/hedera-node/test-clients/build.gradle.kts @@ -54,14 +54,95 @@ tasks.withType { modularity.inferModulePath.set(false) } -// This task runs the 'HapiTestEngine' tests (residing in src/main/java). +// The following tasks run the 'HapiTestEngine' tests (residing in src/main/java). // IntelliJ picks up this task when running tests through in the IDE. + +// Runs all tests tasks.register("hapiTest") { testClassesDirs = sourceSets.main.get().output.classesDirs classpath = sourceSets.main.get().runtimeClasspath useJUnitPlatform() + // Limit heap and number of processors + maxHeapSize = "8g" + jvmArgs("-XX:ActiveProcessorCount=6") + + // Do not yet run things on the '--module-path' + modularity.inferModulePath.set(false) +} + +// Runs all tests that are not part of other test tasks +tasks.register("hapiTestMisc") { + testClassesDirs = sourceSets.main.get().output.classesDirs + classpath = sourceSets.main.get().runtimeClasspath + + useJUnitPlatform { excludeTags("CRYPTO", "TOKEN", "SMART_CONTRACT", "TIME_CONSUMING") } + + // Limit heap and number of processors + maxHeapSize = "8g" + jvmArgs("-XX:ActiveProcessorCount=6") + + // Do not yet run things on the '--module-path' + modularity.inferModulePath.set(false) +} + +// Runs all tests of CryptoService +tasks.register("hapiTestCrypto") { + testClassesDirs = sourceSets.main.get().output.classesDirs + classpath = sourceSets.main.get().runtimeClasspath + + useJUnitPlatform { includeTags("CRYPTO") } + + // Limit heap and number of processors + maxHeapSize = "8g" + jvmArgs("-XX:ActiveProcessorCount=6") + + // Do not yet run things on the '--module-path' + modularity.inferModulePath.set(false) +} + +// Runs all tests of TokenService +tasks.register("hapiTestToken") { + testClassesDirs = sourceSets.main.get().output.classesDirs + classpath = sourceSets.main.get().runtimeClasspath + + useJUnitPlatform { includeTags("TOKEN") } + + // Limit heap and number of processors + maxHeapSize = "8g" + jvmArgs("-XX:ActiveProcessorCount=6") + + // Do not yet run things on the '--module-path' + modularity.inferModulePath.set(false) +} + +// Runs all tests of SmartContractService +tasks.register("hapiTestSmartContract") { + testClassesDirs = sourceSets.main.get().output.classesDirs + classpath = sourceSets.main.get().runtimeClasspath + + useJUnitPlatform { includeTags("SMART_CONTRACT") } + + // Limit heap and number of processors + maxHeapSize = "8g" + jvmArgs("-XX:ActiveProcessorCount=6") + + // Do not yet run things on the '--module-path' + modularity.inferModulePath.set(false) +} + +// Runs a handful of test-suites that are extremely time-consuming (10+ minutes) +tasks.register("hapiTestTimeConsuming") { + testClassesDirs = sourceSets.main.get().output.classesDirs + classpath = sourceSets.main.get().runtimeClasspath + + useJUnitPlatform { includeTags("TIME_CONSUMING") } + + // Limit heap and number of processors + maxHeapSize = "8g" + jvmArgs("-XX:ActiveProcessorCount=6") + // Do not yet run things on the '--module-path' modularity.inferModulePath.set(false) } diff --git a/hedera-node/test-clients/record-snapshots/AutoAccountUpdate.json b/hedera-node/test-clients/record-snapshots/AutoAccountUpdate.json new file mode 100644 index 000000000000..15f3713f79f7 --- /dev/null +++ b/hedera-node/test-clients/record-snapshots/AutoAccountUpdate.json @@ -0,0 +1 @@ +{"specSnapshots":{"updateKeyOnAutoCreatedAccount":{"placeholderNum":1001,"encodedItems":[{"b64Body":"Cg8KCQj1++qqBhD4BBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloyCiISII56Yi1lxqcyhei00isq0Djj/K4+Ud3monyOL5I5p7bLEIDQ28P0AkoFCIDO2gM=","b64Record":"CiUIFhIDGOoHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjB6aZ9zEsrEVkGlRqPsgH0ivgYGD4z0VGXQW+KA10hiVQPFFsAEtsWRNCHnY+Jdj8YaCwix/OqqBhC7naBIIg8KCQj1++qqBhD4BBICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhsKCwoCGAIQ/5+3h+kFCgwKAxjqBxCAoLeH6QU="},{"b64Body":"ChIKCQj1++qqBhD6BBIDGOoHIAFaZgoiEiCC/sncZx1DjTs/6RHbcGIPha1upfE9wBBDkZ1NdfEXCkoFCIDO2gNqFGF1dG8tY3JlYXRlZCBhY2NvdW50kgEiEiCC/sncZx1DjTs/6RHbcGIPha1upfE9wBBDkZ1NdfEXCg==","b64Record":"CgcIFhIDGOsHEjCt7LfWdlpzP7AilLcDdQemX9FnZiGcWAsxK6zRrmchnCWtWm/KqOr6gG1VOQRRjFcaDAix/OqqBhCC25CwAiISCgkI9fvqqgYQ+gQSAxjqByABKhRhdXRvLWNyZWF0ZWQgYWNjb3VudDDv9+USUgA="},{"b64Body":"ChAKCQj1++qqBhD6BBIDGOoHEgIYAxiqkAUiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnI9CjsKLAokIiISIIL+ydxnHUONOz/pEdtwYg+FrW6l8T3AEEORnU118RcKEICQ38BKCgsKAxjqBxD/j9/ASg==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw3cZ6IDAmtPe+hHRfsWkxux3/aV7IJVjJqxM3Pxq/TNB+39NOjlZ49f2S9HUNIH6tGgwIsfzqqgYQg9uQsAIiEAoJCPX76qoGEPoEEgMY6gcqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMJmI6xJSOgoHCgIYAxCWNQoJCgIYYhCoxfMhCgoKAxigBhD0leIDCgsKAxjqBxCxoLXmSgoLCgMY6wcQgJDfwEo="},{"b64Body":"ChAKCQj2++qqBhCMBRIDGOoHEgIYAxjK5jYiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnqlBBIDGOsHGp0EKpoECAISlQQKhwIqhAIIARL/AQoiEiDX+Ngv9QyTxg79bRiWf1wCe+OHrBf0m6MtQ2rFr66crgojOiEDmCjvmjhkrm43Zkbyv3m1GJHvSsJ5xpgphqvTyISAT7cKIhIgfgpXFKfyCxvNereWjRYaAc4+dWD7dxD3ufz0GnxbLQAKIzohAvhgkckIB5hV+OcAICtWirftukd6LM6vS4TRKgvHhmE1CiISIF1xNvuX1LJFdmYh1/U/YXPgJm+vGe6bL8wds1CfKi8DCiM6IQNolChuycZSvXl1auF/Csi52YOC114S1w8ONWR+aSLKVwoiEiAq2ZTvkbSA5e+8Qn14nvLPiIWaMfuz30kUieyRfnZXFAqIAiqFAggDEoACCiM6IQKGuDO3BKZ6fxqTC2TpvkVySWyMlLXhDQlJeF5/reteNwoiEiAkDpblNioy34N71GUZpW+Ac6q3s8nmjOnBN/7ggBF0XwojOiECzbEpAUSsn8avvb75ldP8djXr9nyYdorL+shBUdcojnYKIhIgw4E6bgSBgHqyHOI5h7F/lZEKhOQFXxYbXwHdLVQHQYwKIzohA4CnEbqDMmqdDp4C0SS9tJX8wALZq7UW0LStYsrdRaZXCiISILiKYa6HkU8wqI6xJzyO+rY306xtzbxnE76W7vqEyLCqCiM6IQKsVtXOTk5GtrDDmDIGQ/5VHuawbMskAENOmvgduW+W3Q==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwbP0TtIxc5HJa2lvlFRZDKAcw+HtNc7A0VqCmhkbQPNvVcFZoCJfIrd8OdBdUSKrHGgwIsvzqqgYQ08+diAEiEAoJCPb76qoGEIwFEgMY6gcqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMMrmNlIqCggKAhgDEJyPAQoICgIYYhCs0WEKCQoDGKAGEMzsCgoJCgMY6gcQk81t"}]},"modifySigRequiredAfterAutoAccountCreation":{"placeholderNum":1004,"encodedItems":[{"b64Body":"Cg8KCQj6++qqBhCgBRICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloyCiISIJmZog6knu6zvxyRlxRUmkOlCrSzNGrhxBfpl8JOlak2EIDQ28P0AkoFCIDO2gM=","b64Record":"CiUIFhIDGO0HKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBxk/Lvl2UgfBGJnw0Iw5SuZ+/3ihxdyV/CyBDh+W/H9T3yFrUi6k/VPfkl3hUcH5waDAi2/OqqBhCz+dWGAiIPCgkI+vvqqgYQoAUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+ft4fpBQoMCgMY7QcQgKC3h+kF"},{"b64Body":"ChEKCQj7++qqBhCiBRICGAIgAVpmCiISIDHcxATbbhWjbfEpumVwmEy/mqYiK3cytGmaKOw5Ui9vSgUIgM7aA2oUYXV0by1jcmVhdGVkIGFjY291bnSSASISIDHcxATbbhWjbfEpumVwmEy/mqYiK3cytGmaKOw5Ui9v","b64Record":"CgcIFhIDGO4HEjC24a5o69IO4jJlM2Z3G3Qj94kCdAYybG7c2b7MID/++bgzSwv5eRd78Ekd+Pml22oaCwi3/OqqBhDajNgRIhEKCQj7++qqBhCiBRICGAIgASoUYXV0by1jcmVhdGVkIGFjY291bnRSAA=="},{"b64Body":"Cg8KCQj7++qqBhCiBRICGAISAhgDGKKmCCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOcj0KOwosCiQiIhIgMdzEBNtuFaNt8Sm6ZXCYTL+apiIrdzK0aZoo7DlSL28QgJDfwEoKCwoDGO0HEP+P38BK","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw33CvTtTlhCou6RG9kz2H414SGutrzmrQPEePhD44lVc8/wFeCb8vTn9wGduMCtvpGgsIt/zqqgYQ24zYESIPCgkI+/vqqgYQogUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIaCgsKAxjtBxD/j9/ASgoLCgMY7gcQgJDfwEo="},{"b64Body":"Cg8KCQj7++qqBhC0BRICGAISAhgDGN/JGCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOegkSAxjuB2oCCAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwNGDQ+HKVVrs6nmaLM3oR2tDtF9X7fba34KnRjzDBOlsBsVSKMYu1Ym2qaAwpyprZGgwIt/zqqgYQm7b2rQIiDwoJCPv76qoGELQFEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQj8++qqBhC8BRICGAISAhgDGJq8CyICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOchwKGgoLCgMY7gcQgJDfwEoKCwoDGO0HEP+P38BK","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwYReDNMgWAyDr9ye9IVzeneAJnddAtqjtbfUso6sni+RDzX0hRoIl8uKgUNtOdTwFGgwIuPzqqgYQ26PtuQIiDwoJCPz76qoGELwFEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SGgoLCgMY7QcQ/4/fwEoKCwoDGO4HEICQ38BK"}]}}} \ No newline at end of file diff --git a/hedera-node/test-clients/record-snapshots/CryptoApproveAllowance.json b/hedera-node/test-clients/record-snapshots/CryptoApproveAllowance.json new file mode 100644 index 000000000000..f29098b9b2f8 --- /dev/null +++ b/hedera-node/test-clients/record-snapshots/CryptoApproveAllowance.json @@ -0,0 +1 @@ +{"specSnapshots":{"canHaveMultipleOwners":{"placeholderNum":1001,"encodedItems":[{"b64Body":"Cg8KCQiU3/OqBhDqARICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIHP2oRidNaI+EAmxz/nKd2fLzIYwgUHMCcCob3djZMw+EIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGOoHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDWLTb6NT53Artoe5maU6UqTyNiu0oK/2NTTsVimQCSL7Xz2XBTx5N2+iSzrrqx9jcaDAjQ3/OqBhC7g5G/ASIPCgkIlN/zqgYQ6gESAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjqBxCAkN/ASg=="},{"b64Body":"Cg8KCQiU3/OqBhDsARICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIFfn62u50O7vBgtveQ25c4yJtBr3H6qElMhCHoNCza5BEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGOsHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCGUvQ8CJQxwNAJ48ia3y4fIfT3WlaZFyUPkGA3OWPB/FPCjDED7DUwVHPpQQkpMkQaDAjQ3/OqBhDbrfOlAyIPCgkIlN/zqgYQ7AESAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjrBxCAkN/ASg=="},{"b64Body":"Cg8KCQiV3/OqBhDuARICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISICr5ax0xdcvn7Lznd5KV/57YiBiMMqnQjdyc4AD/wfX/EIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGOwHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCOzOWxXVMUVTlJRWH0itNK4e4QmQjgaLb1KfwHboj09SKHg9L0393Ei7+Rd1wBrDAaDAjR3/OqBhDbkPbJASIPCgkIld/zqgYQ7gESAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjsBxCAkN/ASg=="},{"b64Body":"Cg8KCQiV3/OqBhDwARICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIAURHH0uP9lh5Rhc/MP5pLj8TGfOuQ3KkQ+G4TuQbXg3EICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGO0HKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAioKxv2HoBJVQgNAy8g2GjJaoYvApc2pIF4u12DZlqbUqnp6uVOyYD5vtFr48MgJsaDAjR3/OqBhCj1pCxAyIPCgkIld/zqgYQ8AESAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMY7QcQgMCoypo6"},{"b64Body":"Cg8KCQiW3/OqBhDyARICGAISAhgDGJvmqekCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVQKCGZ1bmdpYmxlEghNU1ZMQVhaSSAKKgMY7QdSIhIgftQhcZlMJ+goAihK7M8k0xzMAoKu1O4WqhdJBNxHEphqDAjSrc6uBhDYjYnEAZABAZgBkE4=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGO4HEjDhy6JzvlD2iW5yuDda5/UgNzBv4NHKQMUMOvxaLUb97CzhIliP3d32J/7TDV/nYzwaDAjS3/OqBhDL+uvUASIPCgkIlt/zqgYQ8gESAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg4KAxjuBxIHCgMY7QcQFHIKCgMY7gcSAxjtBw=="},{"b64Body":"Cg8KCQiW3/OqBhD0ARICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghDRExXUklZUioDGO0HUiISIH7UIXGZTCfoKAIoSuzPJNMczAKCrtTuFqoXSQTcRxKYagwI0q3OrgYQsOSWxAOIAQGQAQGYAQo=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGO8HEjA1kFR23YmJSu5XOcWTWa3Vzr7YFvJrPMIwfVXTDOszxFFI2xUWSCH04uUU7e+ApngaDAjS3/OqBhD7wbfWAyIPCgkIlt/zqgYQ9AESAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxjvBxIDGO0H"},{"b64Body":"Cg8KCQiX3/OqBhD6ARICGAISAhgDGMHw7CAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICDwoDGOoHEgMY7gcSAxjvBw==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwYRU+Tr1V0bXXZiCjYJEKN+GEbq96WoGi+VVrxxhIKQru4G/sEEloYCzEeJ6GcarrGgwI09/zqgYQ06H6+QEiDwoJCJff86oGEPoBEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQiY3/OqBhCAAhICGAISAhgDGMHw7CAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICDwoDGOsHEgMY7gcSAxjvBw==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw9Wma7cPpdqvLs5n1EIJT/qMeeA2pt35gXP74IGNY2vNYuZ+IbkLOYnmob7xuKpFwGgsI1N/zqgYQm/GcBSIPCgkImN/zqgYQgAISAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQiY3/OqBhCGAhICGAISAhgDGKmP9i8iAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCFwoDGO8HGgFhGgFiGgFjGgFkGgFlGgFm","b64Record":"CioIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gGcgYBAgMEBQYSMBlWGuEVE0FSrZPPuExsDY2Ed2lcBKoBhVIv9ZbFTKJcrvE3QjidmlpEYC52+YfO/xoMCNTf86oGEIPOwoUCIg8KCQiY3/OqBhCGAhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaUwoDGO8HGgsKAhgAEgMY7QcYARoLCgIYABIDGO0HGAIaCwoCGAASAxjtBxgDGgsKAhgAEgMY7QcYBBoLCgIYABIDGO0HGAUaCwoCGAASAxjtBxgG"},{"b64Body":"Cg8KCQiZ3/OqBhCOAhICGAISAhgDGO/KUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOqgIICgMY7gcQ6Ac=","b64Record":"CiMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1jyBxIwOS4bwolh327PTe3aLKtfkxn6J4928RanRGI2IQhjOwouV9AB3fBKQdhFNxwmQSuTGgsI1d/zqgYQq/DxKSIPCgkImd/zqgYQjgISAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg8KAxjuBxIICgMY7QcQ0A8="},{"b64Body":"Cg8KCQiZ3/OqBhCSAhICGAISAhgDGOa47wEiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnKAARIjCgMY7gcSCAoDGO0HEM8PEggKAxjqBxDoBxIICgMY6wcQ6AcSWQoDGO8HGgwKAxjtBxIDGOoHGAEaDAoDGO0HEgMY6gcYAhoMCgMY7QcSAxjqBxgDGgwKAxjtBxIDGOsHGAQaDAoDGO0HEgMY6wcYBRoMCgMY7QcSAxjrBxgG","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwJ8jl5uOFvhoKvCt0sn6kkkHxDJrtWcQbYjMZRrl4ubN328HkWKzjA+iZLOjCdOg+GgwI1d/zqgYQs4GRqgIiDwoJCJnf86oGEJICEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFojCgMY7gcSCAoDGOoHEOgHEggKAxjrBxDoBxIICgMY7QcQzw9aWQoDGO8HGgwKAxjtBxIDGOoHGAEaDAoDGO0HEgMY6gcYAhoMCgMY7QcSAxjqBxgDGgwKAxjtBxIDGOsHGAQaDAoDGO0HEgMY6wcYBRoMCgMY7QcSAxjrBxgG"},{"b64Body":"Cg8KCQib3/OqBhCqAhICGAISAhgDGPCZzjgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjoIDdgoPCgMY6gcSAxjsBxiAwtcvCg8KAxjrBxIDGOwHGICEr18SFAoDGO8HEgMY6gcaAxjsByIBASoAEhUKAxjvBxIDGOsHGgMY7AciAgQFKgAaEQoDGO4HEgMY6gcaAxjsByBkGhIKAxjuBxIDGOsHGgMY7AcgrAI=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwn7uoxMcqyg4c5ipQpAUfyDOnJhupeT8J5nQMyW8Pmm9PXDJm9Cpznx0LYBn+yKOcGgwI19/zqgYQu7H12wIiDwoJCJvf86oGEKoCEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="}]},"noOwnerDefaultsToPayer":{"placeholderNum":1008,"encodedItems":[{"b64Body":"Cg8KCQig3/OqBhC+AhICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIO8G7kfN/op7/qxITIKYDVcOSE+TxGPbuoqgs900E+JwEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGPEHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjClB31+QeMA4ULek3eoKT4S7NnHflPQlq1QUTgT3JCM7DCBFLWeLuIzos5x2bGS/V8aDAjc3/OqBhCzgLutASIPCgkIoN/zqgYQvgISAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjxBxCAkN/ASg=="},{"b64Body":"Cg8KCQig3/OqBhDAAhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIMylGV4zmPKreqWc8pleIE+DsPnuHOkyY2Lr2o6RT1HBEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGPIHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDW7gyG1tLeD+AmxQL50lSaG3oQyEeEgzsLPbA7KEhl/8YeL7zcaJ6kHL/ZvAdJfB0aDAjc3/OqBhCz9f+tAyIPCgkIoN/zqgYQwAISAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjyBxCAkN/ASg=="},{"b64Body":"Cg8KCQih3/OqBhDCAhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISINnFKbQipztOq+vD2x8FwZkcFArqgTGGAMItLHh6rdwGEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGPMHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBrqj5MMN0Eq7f3vRTw1W5A5ZUsML11H+mcpIy3Wx58JrSScLYdc2bfz5ei1zCNtN8aDAjd3/OqBhCDsuW3ASIPCgkIod/zqgYQwgISAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjzBxCAkN/ASg=="},{"b64Body":"Cg8KCQih3/OqBhDEAhICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIIkuxdX/hE9cZfIcMgDr01H909/gwDkHd4uMd58H2mNrEICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGPQHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCuPQRKkNFQVnUwBj/+gOpfR/6RPoS4yvm3OA+Y00Ty88dmiqQ200/ZXj7+Fivfx2MaDAjd3/OqBhCLkoyfAyIPCgkIod/zqgYQxAISAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMY9AcQgMCoypo6"},{"b64Body":"Cg8KCQii3/OqBhDGAhICGAISAhgDGJvmqekCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVQKCGZ1bmdpYmxlEghHVU1KRUdEWCAKKgMY9AdSIhIguLNxd8sobSm9nNYR5dEfFqb54nMTlk4PbM6MSX324WpqDAjerc6uBhDQx++zAZABAZgB6Ac=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGPUHEjDLfk2DLZYPebhAiW7uTrn+UUgnrTrUp0nvBNmFcDjDno5kIZH0A41sb3Wi+LKp+WgaDAje3/OqBhDTiNfCASIPCgkIot/zqgYQxgISAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg4KAxj1BxIHCgMY9AcQFHIKCgMY9QcSAxj0Bw=="},{"b64Body":"Cg8KCQii3/OqBhDIAhICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghNSEVJQlVIQyoDGPQHUiISILizcXfLKG0pvZzWEeXRHxam+eJzE5ZOD2zOjEl99uFqagwI3q3OrgYQ2JDQpgOIAQGQAQGYAQo=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGPYHEjCgr1KVJth460pZJT3bJKiaFnvVbyahg0f/XJGDwimMIsPj84K8bkBkI0wtLvKnqcEaDAje3/OqBhCDpNWqAyIPCgkIot/zqgYQyAISAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxj2BxIDGPQH"},{"b64Body":"Cg8KCQij3/OqBhDOAhICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGPEHEgMY9Qc=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwioWX9SvOSOt/wLV5WtnS0UNj4Sc1Fi22fr2YbniAbH779fKXPApz7pFapDnDVndAGgwI39/zqgYQ28KDzgEiDwoJCKPf86oGEM4CEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQij3/OqBhDUAhICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGPEHEgMY9gc=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwoq1rhadySMzZjZPCEYZuX2PmLi3nh+14ChnfCbyJCi5gX+xA11QRdnvBRE6c8gO+GgwI39/zqgYQy4S/zgMiDwoJCKPf86oGENQCEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQik3/OqBhDaAhICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGPYHGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMHPSvChbCn9SpM2CZ7utJ/39AxrcXk1erqlBSPC2VUUKp3r0D2xwfbo+eTYEl6tZRxoMCODf86oGEPvNvNkBIg8KCQik3/OqBhDaAhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaLAoDGPYHGgsKAhgAEgMY9AcYARoLCgIYABIDGPQHGAIaCwoCGAASAxj0BxgD"},{"b64Body":"Cg8KCQik3/OqBhDiAhICGAISAhgDGO/KUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOqgIICgMY9QcQ9AM=","b64Record":"CiMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1j+AxIw00cWNXNGl4VipdTrgZBE+XDMbKhxjE8idcHC1ph0nFGB9DKPu5mQ9s03BwlvThAWGgwI4N/zqgYQ48Cu2gMiDwoJCKTf86oGEOICEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoPCgMY9QcSCAoDGPQHEOgH"},{"b64Body":"Cg8KCQil3/OqBhDmAhICGAISAhgDGID+PCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOcjESLwoDGPYHGgwKAxj0BxIDGPEHGAEaDAoDGPQHEgMY8QcYAhoMCgMY9AcSAxjxBxgD","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwEHhOfdyLQoD8ds/ncov1coCX/1xOT4/iZ2zoxhTcwkaHWYsE+oC1aRtaZ9RAJYvhGgwI4d/zqgYQ0//z4wEiDwoJCKXf86oGEOYCEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFovCgMY9gcaDAoDGPQHEgMY8QcYARoMCgMY9AcSAxjxBxgCGgwKAxj0BxIDGPEHGAM="},{"b64Body":"ChAKCQil3/OqBhDsAhIDGPEHEgIYAxiKmugUIgIIeIIDKAoHEgMY8wcYZBIPCgMY9gcaAxjyByIBASoAGgwKAxj1BxoDGPIHIGQ=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwm55508EHDxOvchWvF9wJbZo+JxMyqw+1bshs9C8+pRireWcOonq0NxpHj7+M+YosGgsI4t/zqgYQs8P2ByIQCgkIpd/zqgYQ7AISAxjxBzCKmugUUi4KCQoCGAMQnojQAQoJCgIYYhDEp4AkCgoKAxigBhCyhIAECgoKAxjxBxCTtNAp"}]},"invalidSpenderFails":{"placeholderNum":1015,"encodedItems":[{"b64Body":"Cg8KCQiq3/OqBhCGAxICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIHrTTF26tQYHQbLsi83RZxFTbPp8MgHFlbF7b9v2xBgNEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGPgHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCvH0TXzwRp79qRh/Ze2vvjnYx36NDRJk6E9G0iJAPKQXFIbvM7bRZmuYwioBPtpAsaDAjm3/OqBhDDyNrNASIPCgkIqt/zqgYQhgMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxj4BxCAkN/ASg=="},{"b64Body":"Cg8KCQiq3/OqBhCIAxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIJAP++pNLrSl6OIDGDqYPYQxFIQH6+/o/rmn23DQlV/eEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGPkHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCdC39gGYTiqsrpmu0og/IrCpo5GmO9AOrCBOiIsIcVVG9K0gs9GJqwAgRqtNgIAR4aDAjm3/OqBhCbydfOAyIPCgkIqt/zqgYQiAMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxj5BxCAkN/ASg=="},{"b64Body":"Cg8KCQir3/OqBhCKAxICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIKMKtiWfAZDt8TmcsctlIXERddTDgc5zrDUqOjWp0dG4EICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGPoHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjB+ZSMaCF48EfmP+LvFPzWK67+64u5iAT756WYoZlcZRuW9FT1GplDyGgn4iFFz1BAaDAjn3/OqBhD7yJTZASIPCgkIq9/zqgYQigMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMY+gcQgMCoypo6"},{"b64Body":"Cg8KCQir3/OqBhCMAxICGAISAhgDGJvmqekCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVQKCGZ1bmdpYmxlEghQRVVPT1JBUyAKKgMY+gdSIhIgAgrwRMNp5JjLiOAdwBPy7VgFWoYhywpNRCtCZYiaO3JqDAjnrc6uBhDgipq9A5ABAZgB6Ac=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGPsHEjA3sup6PRBXk6eFSYSeuTV3ROu7TNFpDccmSyMJiwFrZm7aSE7DKemYwHiq9yE+akwaDAjn3/OqBhDDyPK/AyIPCgkIq9/zqgYQjAMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg4KAxj7BxIHCgMY+gcQFHIKCgMY+wcSAxj6Bw=="},{"b64Body":"Cg8KCQis3/OqBhCOAxICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghBWVpMUFZNQSoDGPoHUiISIAIK8ETDaeSYy4jgHcAT8u1YBVqGIcsKTUQrQmWImjtyagwI6K3OrgYQkKva0gGIAQGQAQGYAQo=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGPwHEjDBQmf65op0zYOrqTDCMnrfuFimZGdqwsKi3OE0DQtsP0Ucbt88+rwzjqN/SJXPbmcaDAjo3/OqBhDb/rDiASIPCgkIrN/zqgYQjgMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxj8BxIDGPoH"},{"b64Body":"Cg8KCQis3/OqBhCUAxICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGPgHEgMY+wc=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwrBUmKbMvUyEznKkhulhcX/bYO5K+At7gG2psaaQoho84QSR9YoTRx019taBfG7eVGgwI6N/zqgYQo+u4ywMiDwoJCKzf86oGEJQDEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQit3/OqBhCaAxICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGPgHEgMY/Ac=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwfAneRMNE1CaNUdsbCfPGs/Ni6Ud/DVfNTqSWhmBsXCmW3XDXQC8zgOn6QkpXwy7ZGgwI6d/zqgYQs8mt7wEiDwoJCK3f86oGEJoDEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQit3/OqBhCgAxICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGPwHGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMF/Fr14dZaMq96Nj/s77hQuG6uPlbAHzTwX/3qLLPNJZQNGP2MqhRSN9MWqOG8LP9hoLCOrf86oGELO91xIiDwoJCK3f86oGEKADEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFosCgMY/AcaCwoCGAASAxj6BxgBGgsKAhgAEgMY+gcYAhoLCgIYABIDGPoHGAM="},{"b64Body":"Cg8KCQiu3/OqBhCoAxICGAISAhgDGO/KUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOqgIICgMY+wcQ9AM=","b64Record":"CiMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1j+AxIwk39w3n4fKFRK5/bAxLyN6dbsP6W4h9KMtFemfBrom17Veq0FbG87cHUBXXOD2/hLGgwI6t/zqgYQ+7jg+QEiDwoJCK7f86oGEKgDEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoPCgMY+wcSCAoDGPoHEOgH"},{"b64Body":"Cg8KCQiv3/OqBhCsAxICGAISAhgDGID+PCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOcjESLwoDGPwHGgwKAxj6BxIDGPgHGAEaDAoDGPoHEgMY+AcYAhoMCgMY+gcSAxj4BxgD","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwo7uluatYCPbYNR0rGYB9rZWaEV2XGjw+Iqd8ii8jGhla5YW2ID0mGYWUW60Mqe9VGgsI69/zqgYQ89iYHSIPCgkIr9/zqgYQrAMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWi8KAxj8BxoMCgMY+gcSAxj4BxgBGgwKAxj6BxIDGPgHGAIaDAoDGPoHEgMY+AcYAw=="},{"b64Body":"Cg8KCQiv3/OqBhCuAxICGAISAhgDGMHongMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjmIJCgIYAhIDGPkH","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwuaQ4aexUAJZB4arH76X9CIrEV3JLMSidOmiNOfhU8t19F7IL9pTdiXt8uND7vHJYGgwI69/zqgYQw6iQhQIiDwoJCK/f86oGEK4DEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SGQoKCgIYAhCAkN/ASgoLCgMY+QcQ/4/fwEo="}]},"invalidOwnerFails":{"placeholderNum":1021,"encodedItems":[{"b64Body":"Cg8KCQi13/OqBhDQAxICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIJc8GGLuy9Z1BLZi3xdsPbMO97EojtOQWjfliwBRI59BEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGP4HKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAAoKpixtvfi+Osz5mGqnuMDdOXaXiykHT6ozwA6voY0BjSfBT1f7a9Fi1Z7dmSO1IaDAjx3/OqBhDT64j7ASIPCgkItd/zqgYQ0AMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxj+BxCAkN/ASg=="},{"b64Body":"Cg8KCQi23/OqBhDSAxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISICsCgmdRyWcHAT7/D5e811ZmPS26HckeGDqPqn8oMiRBEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGP8HKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDSB2/koiLlU7LSZA2MZOzYmusUP3Pr88zNovlKOu4Rps4yLhHLoQtPdG/HDNAAeDoaCwjy3/OqBhCriNkFIg8KCQi23/OqBhDSAxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGP8HEICQ38BK"},{"b64Body":"Cg8KCQi23/OqBhDUAxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIDHfZKIl9IFEjMesmGpbj4URK50GbjDphhOkog4q8LiSEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGIAIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBBUzPRCskd432cVvFxEGLt9sjjPJsp/fR+Eewaefqwnx74PrgnfxnMzR7AsNv/z+QaDAjy3/OqBhDbmOOGAiIPCgkItt/zqgYQ1AMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxiACBCAkN/ASg=="},{"b64Body":"Cg8KCQi33/OqBhDWAxICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIBIas2nhUf9ZubFKijIp6Jqxk29U/mYmVZkQZ+864t7iEICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGIEIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCk5QJa3CvBSYq6YytxIicwDYp5LoXiFcQd4luhfd+IbLG3fZ4vLQTz7IrtQERgBzAaCwjz3/OqBhCjhNMRIg8KCQi33/OqBhDWAxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhsKCwoCGAIQ/7+oypo6CgwKAxiBCBCAwKjKmjo="},{"b64Body":"Cg8KCQi33/OqBhDYAxICGAISAhgDGJvmqekCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVQKCGZ1bmdpYmxlEghOT1VEREdFVCAKKgMYgQhSIhIg/6r2jUrM3aRkC2sNXd6AVHiAEKNqySaye/Up5eRSclVqDAjzrc6uBhCw8cb+AZABAZgB6Ac=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGIIIEjABjARaFv/8uBtkxRKujCeFNSVcvUsr79BlmyPtqZ2tC5AaR/pRZrB2sBt4a1HQleIaDAjz3/OqBhDb4KeSAiIPCgkIt9/zqgYQ2AMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg4KAxiCCBIHCgMYgQgQFHIKCgMYgggSAxiBCA=="},{"b64Body":"Cg8KCQi43/OqBhDaAxICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVYKC25vbkZ1bmdpYmxlEghRVE5VS0RKVSoDGIEIUiISIP+q9o1KzN2kZAtrDV3egFR4gBCjaskmsnv1KeXkUnJVagsI9K3OrgYQqKvNE4gBAZABAZgBCg==","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGIMIEjCYsUURslFh3B5RdrISO3O7avVuBYZ6Nr/jnrtzZ64j6XHVvhYxzBgd91K1lPEdFp0aCwj03/OqBhD70IEcIg8KCQi43/OqBhDaAxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgByCgoDGIMIEgMYgQg="},{"b64Body":"Cg8KCQi43/OqBhDgAxICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGIMIGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMBu1JTvhQozZYkKT8V1Gqnmy9xSKcjGyfgTDe73ku4TfybmMviuuEK70mLUHM3SnExoMCPTf86oGEKuY0JwCIg8KCQi43/OqBhDgAxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaLAoDGIMIGgsKAhgAEgMYgQgYARoLCgIYABIDGIEIGAIaCwoCGAASAxiBCBgD"},{"b64Body":"Cg8KCQi53/OqBhDoAxICGAISAhgDGO/KUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOqgIICgMYgggQ9AM=","b64Record":"CiMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1j+AxIwsg6mMl3ACXH0jvF3FtC7y2Ab++TuMZAEjwNtCALb2Oohl7cHkcY7AyKqVh0u37aEGgsI9d/zqgYQi/LvJiIPCgkIud/zqgYQ6AMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg8KAxiCCBIICgMYgQgQ6Ac="},{"b64Body":"ChAKCQi53/OqBhDwAxIDGP8HEgIYAxiMoZggIgIIeIIDDgoMCgMY/gcSAxiACBhk","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwf1gTccB1KWjskLj2LjnywnV5mviHvRjo/68cQXTRqhoata56BwajbV4AYOSdU9IMGgwI9d/zqgYQ45q2pwIiEAoJCLnf86oGEPADEgMY/wcwjKGYIFIuCgkKAhgDEKiizwEKCQoCGGIQpva9OAoKCgMYoAYQyqmjBgoKCgMY/wcQl8KwQA=="},{"b64Body":"Cg8KCQi63/OqBhDyAxICGAISAhgDGMHongMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjmIJCgIYAhIDGP4H","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwlMUG9lfQNa5hIFbwpup1VtfVeBs47imKFA8wE+0HHXFcBORB95Du5JZoHHEvkMy/GgsI9t/zqgYQ4/m0MSIPCgkIut/zqgYQ8gMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEICQ38BKCgsKAxj+BxD/j9/ASg=="}]},"happyPathWorks":{"placeholderNum":1028,"encodedItems":[{"b64Body":"Cg8KCQi+3/OqBhCWBBICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIDWdXiek1Cy5SdH9j2ewlHi7TZ73wGzueRDLLevDWAr3EIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGIUIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCWLO+kZPQAJFzFdiNKYrkAyXt6zZZNBRXAv9rwIGlhsBiQllHNTG39qThwFy3H3y0aDAj63/OqBhCz1cOQAiIPCgkIvt/zqgYQlgQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxiFCBCAkN/ASg=="},{"b64Body":"Cg8KCQi/3/OqBhCYBBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISILlebVZI9Ws/EzwPTAvjrMvNFlliIAVjZyOvwkaEBpswEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGIYIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAH5jrkCQDSU0/ImVHtbHSGBDpaai6/D8VBCuqN2wij0D1L4LGbeVmuAAcDgUfbu/oaCwj73/OqBhC7n4U1Ig8KCQi/3/OqBhCYBBICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGIYIEICQ38BK"},{"b64Body":"Cg8KCQi/3/OqBhCaBBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIFMCxmW+6ia2QKff1vj+Swr07xyfXecWv4ZQmIOpVZzbEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGIcIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCeeUvpWnnxS/XlBv+Gc+fAog5OqML+TTMBIqRcWQDH6VCvt4FdHwoeVa3A3vKfUksaDAj73/OqBhCryZmbAiIPCgkIv9/zqgYQmgQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxiHCBCAkN/ASg=="},{"b64Body":"Cg8KCQjA3/OqBhCcBBICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIJYZYYWNZmzEBSiAzb4kLQxj43+93uxllYbFs8rTBAfYEICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGIgIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDGP4XGalWvyZDf2H106MnNZ1c7UoAVvyofuHF7DGgr1COjWtZ1JoXuffeJ1EkC02AaCwj83/OqBhCjhJclIg8KCQjA3/OqBhCcBBICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhsKCwoCGAIQ/7+oypo6CgwKAxiICBCAwKjKmjo="},{"b64Body":"Cg8KCQjA3/OqBhCeBBICGAISAhgDGJvmqekCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVQKCGZ1bmdpYmxlEghPREhEUVpMUyAKKgMYiAhSIhIgU1Ah9mV4oFgkSXQFbT2YkrWVKr6ZpUet5560+CYqVShqDAj8rc6uBhCYxb+UApABAZgB6Ac=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGIkIEjA4b49dRZxKGtLXheuHJkKIX6/PJckP7yxY3JIP98LrKWNy24/Lakr3+AMEDEX+rXcaDAj83/OqBhCjkP6lAiIPCgkIwN/zqgYQngQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg4KAxiJCBIHCgMYiAgQFHIKCgMYiQgSAxiICA=="},{"b64Body":"Cg8KCQjB3/OqBhCgBBICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVYKC25vbkZ1bmdpYmxlEghQWlhCV1RLSyoDGIgIUiISIFNQIfZleKBYJEl0BW09mJK1lSq+maVHreeetPgmKlUoagsI/a3OrgYQ+MKvKogBAZABAZgBCg==","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGIoIEjAtg+iZfxC0mBCSC/S9OaDWUwajtFiIWoU4iq+JcifPMn2wrTKv2u4yRayofEgWEcoaCwj93/OqBhDT9PUvIg8KCQjB3/OqBhCgBBICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgByCgoDGIoIEgMYiAg="},{"b64Body":"Cg8KCQjB3/OqBhCmBBICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGIUIEgMYiQg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwAkjbcuECXwQ956u3JxQyaEHK0rpRouWsINR+ABSc3o3CHGlV7CQoJWGba60h2o7UGgwI/d/zqgYQs9m1sAIiDwoJCMHf86oGEKYEEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjC3/OqBhCsBBICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGIUIEgMYigg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwAiruCBRoPyyEJhd1FvD+WZvQ/pp3/+0AejV5t6R8nIuZD7fxJKapny0TuLp/uQbvGgsI/t/zqgYQ8+23OiIPCgkIwt/zqgYQrAQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQjC3/OqBhCyBBICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGIoIGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMLGhQpswemeKKg8FaMfl3ATGS4Aj/yIIRySihyIuqztDbJxoOBw3Cvqv21i2h6qqcxoMCP7f86oGEMOW9LkCIg8KCQjC3/OqBhCyBBICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaLAoDGIoIGgsKAhgAEgMYiAgYARoLCgIYABIDGIgIGAIaCwoCGAASAxiICBgD"},{"b64Body":"Cg8KCQjD3/OqBhC6BBICGAISAhgDGO/KUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOqgIICgMYiQgQ9AM=","b64Record":"CiMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1j+AxIwrAtwfZjUZgOoznCjS7rzf89wyNjrSJPu0c6JDnb/tB4dKdVCBWol2lbPbqvpnwd6GgsI/9/zqgYQ05C2XSIPCgkIw9/zqgYQugQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg8KAxiJCBIICgMYiAgQ6Ac="},{"b64Body":"Cg8KCQjD3/OqBhC+BBICGAISAhgDGID+PCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOcjESLwoDGIoIGgwKAxiICBIDGIUIGAEaDAoDGIgIEgMYhQgYAhoMCgMYiAgSAxiFCBgD","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwGIkVJkbule+t2cczHFA6EXC2Ew1ouL+Y9GNrnz3WdiQc1+/yxHQ47/MEtwbp1nOkGgwI/9/zqgYQs5GOxQIiDwoJCMPf86oGEL4EEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFovCgMYiggaDAoDGIgIEgMYhQgYARoMCgMYiAgSAxiFCBgCGgwKAxiICBIDGIUIGAM="},{"b64Body":"ChAKCQjE3/OqBhDEBBIDGIUIEgIYAxjzkO8TIgIIeIIDDgoMCgMYhQgSAxiGCBhk","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw6a+z64osZjXqKCc22HmCpv/nPjXKQQUns9vwmaXFfgvXj+yfjjNMcKtdzewic5T6GgsIgODzqgYQ+9zeTyIQCgkIxN/zqgYQxAQSAxiFCDDzkO8TUi4KCQoCGAMQzPXKAQoJCgIYYhCygasiCgoKAxigBhDoqugDCgoKAxiFCBDlod4n"},{"b64Body":"ChAKCQjE3/OqBhDOBBIDGIUIEgIYAxiKmugUIgIIeIIDNwoMCgMYhQgSAxiHCBhkEhQKAxiKCBIDGIUIGgMYhggiAQEqABoRCgMYiQgSAxiFCBoDGIYIIGQ=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw5YOInMATkDU2ygaurHG/1VuZP6KrTeJ1CuSqw8pqf5WERUMV6mQnzg4iXbniPRsIGgwIgODzqgYQm6ST0AIiEAoJCMTf86oGEM4EEgMYhQgwiproFFIuCgkKAhgDEJ6I0AEKCQoCGGIQxKeAJAoKCgMYoAYQsoSABAoKCgMYhQgQk7TQKQ=="}]},"emptyAllowancesRejected":{"placeholderNum":1035,"encodedItems":[{"b64Body":"Cg8KCQjJ3/OqBhDoBBICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIJQM1MOZ1FiMgMUUwEz4sjzD7R7M5SMDe4ktRGX9PZDCEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGIwIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCM9xcw01FOwnJweiG5y6c+Xs80amlzIUV1Cs0RD+ZRLXUwHO+0KWZVbKEbYZ2P/8YaCwiF4POqBhCDxfBQIg8KCQjJ3/OqBhDoBBICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGIwIEICQ38BK"}]},"negativeAmountFailsForFungible":{"placeholderNum":1037,"encodedItems":[{"b64Body":"Cg8KCQjN3/OqBhD5BBICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIFvRNSBSY9vDJOAIr9/J1y0dC6qeEkYtwVXSDn5Iv42AEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGI4IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjD6OB32Jda7fpmUQDtc0R8yUNiIeIjfU3LDyGTIQasLstV3cqjA1lPU/aQF9fxSztMaDAiJ4POqBhD739TMAiIPCgkIzd/zqgYQ+QQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxiOCBCAkN/ASg=="},{"b64Body":"Cg8KCQjO3/OqBhD7BBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISINiHiTCqhUDfxNM/J6Qeujg97f8HgzXYczw7dtEBd1e7EIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGI8IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBDzDOUMnsxbXINC8R12+h4tGhNjzfnrqVhJdGVlweSw/JojL8Hp4Z7U2ehw9SFC8EaCwiK4POqBhCjjKVXIg8KCQjO3/OqBhD7BBICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGI8IEICQ38BK"},{"b64Body":"Cg8KCQjO3/OqBhD9BBICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIMLU/bGNiYArSNiff284yA6OrqoCit1QvyDnebaPCs/QEICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGJAIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBLHP9Y/A+6t6oLr5+koT7ur2E9pRhb94mmPfhWtjnPTbOuckXX5px/iUOelQo3CO0aDAiK4POqBhDbhvDXAiIPCgkIzt/zqgYQ/QQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMYkAgQgMCoypo6"},{"b64Body":"Cg8KCQjP3/OqBhD/BBICGAISAhgDGJvmqekCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVMKCGZ1bmdpYmxlEghJVVdQVVlUSiAKKgMYkAhSIhIghOZEY3e8DG20K/1XoXWKoQ3DcEXpzHlXM6BUdMNbKMJqCwiLrs6uBhDYlJhdkAEBmAHoBw==","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGJEIEjDiB4zWbfs5vPoNCpA2sPkm26hpiPfAUcr9gEIRSKh61uYNBYAoczdSsFluPFklyXQaCwiL4POqBhDDpYZiIg8KCQjP3/OqBhD/BBICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaDgoDGJEIEgcKAxiQCBAUcgoKAxiRCBIDGJAI"},{"b64Body":"Cg8KCQjP3/OqBhCBBRICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghBV0laTFRWQyoDGJAIUiISIITmRGN3vAxttCv9V6F1iqENw3BF6cx5VzOgVHTDWyjCagwIi67OrgYQgKu90AKIAQGQAQGYAQo=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGJIIEjD61nFVu1VpNXlA+ueXa3sG0lzTjyY4aH5rutk/ARd/pfCiqeOhtBDTTOPhy7AYnG4aDAiL4POqBhDb6a7iAiIPCgkIz9/zqgYQgQUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxiSCBIDGJAI"},{"b64Body":"Cg8KCQjQ3/OqBhCHBRICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGI4IEgMYkQg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwKZAFhzZnAnDXRytJ+57R13uSWosEPLOhtwO+dfg4wvZTcLoEC25xJ4v3rIP+lO8DGgsIjODzqgYQo7DaayIPCgkI0N/zqgYQhwUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQjQ3/OqBhCNBRICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGI4IEgMYkgg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw5a6cUKUQI5ht7sDdJMRKLzcPq06FjF/Ov/ti1B3z43f71OTUR4lGlUDii5SRO0CfGgwIjODzqgYQm+jS6wIiDwoJCNDf86oGEI0FEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjR3/OqBhCTBRICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGJIIGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMO9Y1jqmiQaSOQlnY/PeJSVB/hl8ISMdA24kVJWNZF08RFOpqyKshtULwS95fQllLBoMCI3g86oGENOI8JABIg8KCQjR3/OqBhCTBRICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaLAoDGJIIGgsKAhgAEgMYkAgYARoLCgIYABIDGJAIGAIaCwoCGAASAxiQCBgD"},{"b64Body":"Cg8KCQjR3/OqBhCbBRICGAISAhgDGO/KUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOqgIICgMYkQgQ9AM=","b64Record":"CiMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1j+AxIwYsMsi/oxAEZrIqFeDpxwTqdWgvQ4W8Rbe6k2zvpQA9jxoDSvwYNO7QPgb4/oXc6TGgwIjeDzqgYQ46/rkAMiDwoJCNHf86oGEJsFEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoPCgMYkQgSCAoDGJAIEOgH"},{"b64Body":"Cg8KCQjS3/OqBhCfBRICGAISAhgDGID+PCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOcjESLwoDGJIIGgwKAxiQCBIDGI4IGAEaDAoDGJAIEgMYjggYAhoMCgMYkAgSAxiOCBgD","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw1s0l16paWcD7B6PE1WnJ1XCBgK4pCk9twEsljFIsq0Y78og5sUrL/2QhmiFxEkBvGgwIjuDzqgYQ47LemgEiDwoJCNLf86oGEJ8FEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFovCgMYkggaDAoDGJAIEgMYjggYARoMCgMYkAgSAxiOCBgCGgwKAxiQCBIDGI4IGAM="}]},"tokenNotAssociatedToAccountFails":{"placeholderNum":1043,"encodedItems":[{"b64Body":"Cg8KCQjW3/OqBhCzBRICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISILdX4c+3clqtkONqUyrLdf+yPv5ths4SrG1IGVUBg8f6EIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGJQIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCuMsPhJZuLVLnlqzxTp5J57AonwV76RDFnvTrJohDYh5OIfCxQv6+Hq4sDgIMEo1QaDAiS4POqBhDLgZDhAiIPCgkI1t/zqgYQswUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxiUCBCAkN/ASg=="},{"b64Body":"Cg8KCQjX3/OqBhC1BRICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIHJgYf6rdhDmHCwpGnLAUmVzLogeJXXDAqwUmww6x25REIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGJUIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCcDcIigaejsNqhAiQ6nWaE+Z5wOS8zfru+6q3EQMkQ62FVgTCI1CO+pbGB/lhoajkaDAiT4POqBhDL3+qEASIPCgkI19/zqgYQtQUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxiVCBCAkN/ASg=="},{"b64Body":"Cg8KCQjX3/OqBhC3BRICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIJxVbX4C6jS3oyyIXWHKMTOfX73O28eKqtr32u+uE+JuEICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGJYIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAAExFYKyteYb+joRnxLgH4KG+orUyXY+PTEfeHK3a5gmYDPzUH0qjYC8Zu4TaxGvQaDAiT4POqBhCDnprrAiIPCgkI19/zqgYQtwUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMYlggQgMCoypo6"},{"b64Body":"Cg8KCQjY3/OqBhC5BRICGAISAhgDGJvmqekCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVMKCGZ1bmdpYmxlEghFVU9WSE5FUCAKKgMYlghSIhIgxXqqs0ZBXcejEYXU6ep1Q30spCXlJIttdAsylNDe6gZqCwiUrs6uBhCYnPp6kAEBmAHoBw==","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGJcIEjAtqPD8u4/qRf6dN31tYEIwaaHWNjbCIVkLwu+OyC0x/RKNZjkjwtsqU0Exq73s7nQaDAiU4POqBhDL7seOASIPCgkI2N/zqgYQuQUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg4KAxiXCBIHCgMYlggQFHIKCgMYlwgSAxiWCA=="},{"b64Body":"Cg8KCQjY3/OqBhC7BRICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghTUFBaVVhUWSoDGJYIUiISIMV6qrNGQV3HoxGF1OnqdUN9LKQl5SSLbXQLMpTQ3uoGagwIlK7OrgYQ0Pv67AKIAQGQAQGYAQo=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGJgIEjACney0KrsyRNLn0tss5OHmpfiAcLI+et2PaqaKCt6iMebGCYpii1sLrbB3196A7doaDAiU4POqBhCj7r/1AiIPCgkI2N/zqgYQuwUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxiYCBIDGJYI"},{"b64Body":"Cg8KCQjZ3/OqBhDBBRICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGJgIGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMHnitJFhvlagz4cSc2pxouTwtSHhPMOD1xKQS1I39RQjCXeJY/1qqrexgvLhsGYSXxoMCJXg86oGEIuqqJkBIg8KCQjZ3/OqBhDBBRICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaLAoDGJgIGgsKAhgAEgMYlggYARoLCgIYABIDGJYIGAIaCwoCGAASAxiWCBgD"},{"b64Body":"Cg8KCQjZ3/OqBhDJBRICGAISAhgDGO/KUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOqgIICgMYlwgQ9AM=","b64Record":"CiMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1j+AxIwsFJlGaB09fpdvDsgiZpci2KAEot0SJpMpXbeUTnfixGleWX28Dp3sD4q9LPug7tfGgwIleDzqgYQ8/7ugQMiDwoJCNnf86oGEMkFEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoPCgMYlwgSCAoDGJYIEOgH"}]},"invalidTokenTypeFails":{"placeholderNum":1049,"encodedItems":[{"b64Body":"Cg8KCQje3/OqBhDfBRICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIIpBDnatc8/6gNXfWTY9j3fXUkPHWuTr6BtgLwpalfniEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGJoIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAN0xVcaVLETcsNStZeZKPZEehzt1KEu73mHqV9ceMaD1fCUaUKHu4YqZ2IUYnpeHcaDAia4POqBhCLjOuGASIPCgkI3t/zqgYQ3wUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxiaCBCAkN/ASg=="},{"b64Body":"Cg8KCQje3/OqBhDhBRICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIAlPjkTFlJyz7r+IvhgLC/Cd3tp6U8nHlcvMlewALRwlEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGJsIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCnVErFAX1mElIvSn/yJUp6Iw+J/Z0fTspG1sX6x7VV1VFgKGq73wUwR0tU0SlVy4UaDAia4POqBhCznOiHAyIPCgkI3t/zqgYQ4QUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxibCBCAkN/ASg=="},{"b64Body":"Cg8KCQjf3/OqBhDjBRICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIMzC5MEjxvsdS6RybW0zWqg0v6pxaQTWFJ/PsZgwj6THEICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGJwIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBnBW+TPixqXqtnL9dI1DPnsf7Ven0YFaQEbZdyNfnarTBKtbx1+4fcXfG1gF27Zf0aDAib4POqBhDbzeORASIPCgkI39/zqgYQ4wUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMYnAgQgMCoypo6"},{"b64Body":"Cg8KCQjf3/OqBhDlBRICGAISAhgDGJvmqekCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVQKCGZ1bmdpYmxlEghHTkFGTldTQSAKKgMYnAhSIhIg1SbPkI4q0d1GwFyNxz8dJKQ2bY5rNsm7m5WhrFMbpPVqDAibrs6uBhDQ9+mAA5ABAZgB6Ac=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGJ0IEjAy/dQSx9KLorpKaHk3CjzVyHwDU/aLwYnU0G75KxJS/sZ36fc+xhN5TLImbDAHZSkaDAib4POqBhCznZqTAyIPCgkI39/zqgYQ5QUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg4KAxidCBIHCgMYnAgQFHIKCgMYnQgSAxicCA=="},{"b64Body":"Cg8KCQjg3/OqBhDnBRICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghRTktFVUVFSyoDGJwIUiISINUmz5COKtHdRsBcjcc/HSSkNm2OazbJu5uVoaxTG6T1agwInK7OrgYQ0OTjmAGIAQGQAQGYAQo=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGJ4IEjAzuGTuJVrNW3ZmNVx6OUX1HlByI85K82yAx1OYwe3KBFBg+VS6dGzyMisAiJmESWMaDAic4POqBhCL1redASIPCgkI4N/zqgYQ5wUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxieCBIDGJwI"},{"b64Body":"Cg8KCQjg3/OqBhDtBRICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGJoIEgMYnQg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw/kFzpwtiCgJKbJN4P62aMZWgmYsGhSxhQ4M/uVg4eyw/6L2Ak8JGb2msveu3gufAGgwInODzqgYQ67+inQMiDwoJCODf86oGEO0FEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjh3/OqBhDzBRICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGJoIEgMYngg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw4EqDhOZiTklVjnrHgxGQnp92uvJ9TxaJCrSM5z8Ap3/hynfMe9wdPX06kxbmJqN0GgwIneDzqgYQs6zopwEiDwoJCOHf86oGEPMFEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjh3/OqBhD5BRICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGJ4IGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMCAlB4Zj8j8JyqhetIbY5XYLuDvN05wPn/MGt0N818aUzKWJafUZRdmHnQfBKcXnrBoMCJ3g86oGEOP2sqkDIg8KCQjh3/OqBhD5BRICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaLAoDGJ4IGgsKAhgAEgMYnAgYARoLCgIYABIDGJwIGAIaCwoCGAASAxicCBgD"},{"b64Body":"Cg8KCQji3/OqBhCBBhICGAISAhgDGO/KUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOqgIICgMYnQgQ9AM=","b64Record":"CiMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1j+AxIwZ6nFF7pcECltwifbMfxT5UlIwS+mV0VAz9aOQ0wpMYspLtAgZ30QcL6wg+eozjUOGgwInuDzqgYQs8S8swEiDwoJCOLf86oGEIEGEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoPCgMYnQgSCAoDGJwIEOgH"},{"b64Body":"Cg8KCQji3/OqBhCFBhICGAISAhgDGID+PCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOcjESLwoDGJ4IGgwKAxicCBIDGJoIGAEaDAoDGJwIEgMYmggYAhoMCgMYnAgSAxiaCBgD","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwzH6HE5Ldo6/9R2tZPEEto5qaxb+fqifHQk/8TSJNWZXhVF//y9LPpJ+YmIfuHNh+GgwInuDzqgYQw7CetAMiDwoJCOLf86oGEIUGEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFovCgMYnggaDAoDGJwIEgMYmggYARoMCgMYnAgSAxiaCBgCGgwKAxicCBIDGJoIGAM="}]},"validatesSerialNums":{"placeholderNum":1055,"encodedItems":[{"b64Body":"Cg8KCQjn3/OqBhCXBhICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIADBTNQsN4NgYJH7Zb11f21SIRERn6azykjuP52JDl1QEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGKAIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCjNqwA4BdoNW9BsW3QuocUR5D0NCD8iYwPI3aPUyipikvkVz0ot5m8Mb0J03B/fH4aDAij4POqBhCr7Oy2ASIPCgkI59/zqgYQlwYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxigCBCAkN/ASg=="},{"b64Body":"Cg8KCQjn3/OqBhCZBhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIJxabFStqklHhXg1cFYa7SfjSSdcGtH22IMn54B/MU0bEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGKEIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCHHO9qtjsvcwvYZFE/QwKNmpk49KHmIHm4GbTDvcvITyW9RahryFBmhJExrRDNxcEaDAij4POqBhDLwcm2AyIPCgkI59/zqgYQmQYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxihCBCAkN/ASg=="},{"b64Body":"Cg8KCQjo3/OqBhCbBhICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIF5MUEVjmwpzV5YXxQ+M5rkjG+nfErxTLt+/cCH0GvprEICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGKIIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAmpl4Y4o6cmjGgth0YSMdUPBCmFBaHczOju8HQ/C+61O9azWKkTe6xj4bAG7AEWrEaDAik4POqBhDDiZnAASIPCgkI6N/zqgYQmwYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMYoggQgMCoypo6"},{"b64Body":"Cg8KCQjo3/OqBhCdBhICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghKWFRJVk1aWSoDGKIIUiISIFopXNGcxHQoMXSl2iusblXgVJHjgiE0pRzHiAfMJ0QoagwIpK7OrgYQuJCipAOIAQGQAQGYAQo=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGKMIEjAqViTVSc1PouQWASwtVQSFXBFDfaGJ5foWCt2YHSVixH0gOCBGmbvV0quU80ZDxMcaDAik4POqBhDz+qqmAyIPCgkI6N/zqgYQnQYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxijCBIDGKII"},{"b64Body":"Cg8KCQjp3/OqBhCjBhICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGKAIEgMYowg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwTJlVkyHo1xs9IpedCQEBo9PN0/UEURowl8DpeZtCgYAlcpJsVVrUdwAmp7+8g+9TGgwIpeDzqgYQy/GSyQEiDwoJCOnf86oGEKMGEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjp3/OqBhCpBhICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGKMIGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMD3cg01dnEGZ3lqSCRNbzn4jjqxYaLBhz3pwDvcUXkL1k7O5LslZl/xWHY6Z8wmgXhoMCKXg86oGEPum5MoDIg8KCQjp3/OqBhCpBhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaLAoDGKMIGgsKAhgAEgMYoggYARoLCgIYABIDGKIIGAIaCwoCGAASAxiiCBgD"},{"b64Body":"Cg8KCQjq3/OqBhCtBhICGAISAhgDGIfiPCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOciMSIQoDGKMIGgwKAxiiCBIDGKAIGAEaDAoDGKIIEgMYoAgYAg==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwAkLf161xlRxNk0aDhIxy37uvHMYj5on1naaMMNQ8j3Q3U2GTixqQK0hRzwIWObobGgwIpuDzqgYQ45G11QEiDwoJCOrf86oGEK0GEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFohCgMYowgaDAoDGKIIEgMYoAgYARoMCgMYoggSAxigCBgC"},{"b64Body":"ChAKCQjq3/OqBhCwBhIDGKAIEgIYAxiAyK+gJSICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOggMWEhQKAxijCBIDGKAIGgMYoQgiAQMqAA==","b64Record":"CiEI7QEqHAoMCAEQDBoGCICumaQPEgwIARAPGgYIgK6ZpA8SMMqkV0Z9GeZCTGGrvluZXNvIYMNKowgt/pdja871nxLfFm9LqPEZ/DkGuEPdNOST+RoMCKbg86oGELPrsdYDIhAKCQjq3/OqBhCwBhIDGKAIKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjjCZ7ogUUi4KCQoCGAMQnq/NAQoJCgIYYhCGj9ciCgoKAxigBhCOnu0DCgoKAxigCBCx3JEo"},{"b64Body":"ChAKCQjr3/OqBhCxBhIDGKAIEgIYAxiAyK+gJSICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOggMYEhYKAxijCBIDGKAIGgMYoQgiAwICAioA","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwBTNpefrZPUSn6GihJ8Lnca2o/etfsDOMqphxxCnX9ySvJ1F48aibGLOoKmZqkLE2GgwIp+DzqgYQs6Lq3wEiEAoJCOvf86oGELEGEgMYoAgqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOML+TkxRSLgoJCgIYAxDYrM4BCgkKAhhiEKTh6CIKCgoDGKAGEIKZ7wMKCgoDGKAIEP2mpig="}]},"tokenExceedsMaxSupplyFails":{"placeholderNum":1060,"encodedItems":[{"b64Body":"Cg8KCQjv3/OqBhDBBhICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIMfbq0oxb0fibk1FAJsHh78ZiOq7GL0ph0YRatAtugviEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGKUIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCDrGF2K+vhL1SkStFF4T8Ughj2DoMIvjrWYG/Wkdvp6EUKKZzIINqtYK1CsH9Xii8aDAir4POqBhCz2KPBAyIPCgkI79/zqgYQwQYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxilCBCAkN/ASg=="},{"b64Body":"Cg8KCQjw3/OqBhDDBhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIE699fI9VFqpaVcbwP4QAsvpXuD95IoLP1N/I/f53Tt8EIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGKYIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBkjruO9iXA4Rq4OqiT9ka3zIbRPrMiNFbZeQktOaQQnzOyoJVpaID1aNIsVi/f8kAaDAis4POqBhDb9NTlASIPCgkI8N/zqgYQwwYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAximCBCAkN/ASg=="},{"b64Body":"Cg8KCQjw3/OqBhDFBhICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIChnYuhn7bjXs9Trh0LocPjZOo/iLUqoCk8XMzX9HvUpEICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGKcIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDYgJh22w8Ad8/EKKP3MP1R9tCy39ISRj79EthQnMN1BaGhO0KGKJ/y0LjF2lDo3/waDAis4POqBhDD5JjMAyIPCgkI8N/zqgYQxQYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMYpwgQgMCoypo6"},{"b64Body":"Cg8KCQjx3/OqBhDHBhICGAISAhgDGJvmqekCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVQKCGZ1bmdpYmxlEghEVFZIWFBPViAKKgMYpwhSIhIg33ZXy0Y+7NB9sSWFIbPT39HDepGyCevFP1FIdJojTrFqDAitrs6uBhDI8e7UAZABAZgB6Ac=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGKgIEjDhpnVFYaJA/7lQrJeoEcvGIBHkvFmKCLJHVURLQ2/slayxuvvFgO+vawziiRpKTL0aDAit4POqBhCrhq7WASIPCgkI8d/zqgYQxwYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg4KAxioCBIHCgMYpwgQFHIKCgMYqAgSAxinCA=="},{"b64Body":"Cg8KCQjx3/OqBhDNBhICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGKUIEgMYqAg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwjbDm7Dk7d/SOjp8N306hbpxrxV8CuHkPXAZhccilYtK6qo8m12NGdqrVAZ6cJxsKGgwIreDzqgYQg/uu1wMiDwoJCPHf86oGEM0GEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjy3/OqBhDTBhICGAISAhgDGO/KUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOqgIICgMYqAgQ9AM=","b64Record":"CiMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1j+AxIwO/9N7ifkcK0AlmCzE6hmnQxf8rsRIikAot2fc5a/nCtyMuHDm+3oB3bqEydiHY9ZGgwIruDzqgYQi7rE/QEiDwoJCPLf86oGENMGEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoPCgMYqAgSCAoDGKcIEOgH"}]},"succeedsWhenTokenPausedFrozenKycRevoked":{"placeholderNum":1065,"encodedItems":[{"b64Body":"Cg8KCQj23/OqBhDmBhICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIJuwUtE50MEDCan0aiGZmsYiq4/QzcUfhWupYLjr3hQiEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGKoIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjD9J9toOcytzovDsBhYR8wb3GI3YLrU9xUnbkW1zi+NWTIzBLCOTBsJkum3XbTKnjwaCgiz4POqBhD7ohEiDwoJCPbf86oGEOYGEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SGQoKCgIYAhD/j9/ASgoLCgMYqggQgJDfwEo="},{"b64Body":"Cg8KCQj33/OqBhDoBhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIOxDu3ALglEGwyO9+QyNcEHMv7YSP8OQny9a6Q2DAeGREIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGKsIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjA3iTZvG0iX4Vv9dDqsynsCAIxDFPj0HOYbQJUPN/1In3HcpdhLv83340s4TjfRwhoaDAiz4POqBhCzwMjnASIPCgkI99/zqgYQ6AYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxirCBCAkN/ASg=="},{"b64Body":"Cg8KCQj33/OqBhDqBhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIMgQrGMZXidFpGiR6fqu0PrvqhfBdD3OLg8+mk/hda5FEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGKwIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAglKBwO3fggQjhU0PkPdiDErAzYKAyhB3PkqguZnZLyKgjiXJslZzXp7fxYRfnQtQaCwi04POqBhDTo4ILIg8KCQj33/OqBhDqBhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGKwIEICQ38BK"},{"b64Body":"Cg8KCQj43/OqBhDsBhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIMzbJPwEHKEurmRSkI6SHgNMf0tnzYcuOMZysuu99S4/EIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGK0IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCp12QmLFgk/AGIHN5TVfc1sL1zXtaxTencfNoODC3t9DU/McV/LroRewnPc6HIgXEaDAi04POqBhD7yvLxASIPCgkI+N/zqgYQ7AYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxitCBCAkN/ASg=="},{"b64Body":"Cg8KCQj53/OqBhDuBhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIPNlh9PRE7BFf/v4D7VIYZ8UQPfWvEE2wggeoNDnH3nSEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGK4IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDJC30pdFo18IyaTsxJfS24S2aYvGM/lGJ7TfBcu2FxEKNBQLfR8r7v8DywO26NdDkaCwi14POqBhCz3e0VIg8KCQj53/OqBhDuBhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGK4IEICQ38BK"},{"b64Body":"Cg8KCQj53/OqBhDwBhICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIC/rn2W31R2aYJ/zRQBc/XYzMP+c6EKL9etrYbwq4oh5EICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGK8IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjADxbNqE+SCYK+mVyxY7UJxxJU44VNfu1FeDgb8QaM2B1/lgdrtTN+i3QThVBMQTkYaDAi14POqBhD7gMD8ASIPCgkI+d/zqgYQ8AYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMYrwgQgMCoypo6"},{"b64Body":"Cg8KCQj63/OqBhDyBhICGAISAhgDGLWzs48DIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAeQBCghmdW5naWJsZRIIUE5OWEJYVlogCioDGK8IMiISIDPQ/sGcywAE49gMhenyM6mGSkrMH1dzD9k5jfVT/kawOiISIIMT1Kr0X89lquK8g+q8QRebXyr4jru9fAnMCMMl9Ri6QiISIIbqkGyuyFLW+vAn0eYJRcUB2EMK1lnwhXTRLl2vBod8UiISIJMaYD0TwiI6UnyNRUs21KejkEpQQcIdq2S2LH5MIE91agsItq7OrgYQ2MCpDZABAZgB6AeyASISIIOA0WKvfhHDDbN8/XWn9vqTHm/+drmRZdUcR6PjCSmV","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGLAIEjBkyeDgcF3gCmgIy0kuP9VM4jOC4aw3YM8Gn/ebNPzVx30QMlbQFfCqpPmglhC7JswaCwi24POqBhCrvM0fIg8KCQj63/OqBhDyBhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaDgoDGLAIEgcKAxivCBAUcgoKAxiwCBIDGK8I"},{"b64Body":"Cg8KCQj63/OqBhD0BhICGAISAhgDGOLh8o4DIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAegBCgtub25GdW5naWJsZRIIVU1YSVJBTlMqAxivCDIiEiAz0P7BnMsABOPYDIXp8jOphkpKzB9Xcw/ZOY31U/5GsDoiEiCDE9Sq9F/PZarivIPqvEEXm18q+I67vXwJzAjDJfUYukIiEiCG6pBsrshS1vrwJ9HmCUXFAdhDCtZZ8IV00S5drwaHfFIiEiCTGmA9E8IiOlJ8jUVLNtSno5BKUEHCHatktix+TCBPdWoMCLauzq4GELDY9f8BiAEBkAEBmAEKsgEiEiCDgNFir34Rww2zfP11p/b6kx5v/na5kWXVHEej4wkplQ==","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGLEIEjC/hkMwiWYDz05+OKGTyxHZjF/mYlsQ3KOJPKyeV+KE+FEQ4NqrlsrzL5kgX5shSjcaDAi24POqBhCTs+KGAiIPCgkI+t/zqgYQ9AYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxixCBIDGK8I"},{"b64Body":"Cg8KCQj73/OqBhD6BhICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGKoIEgMYsAg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw1jhEC3FkltMMbYjjuJyjfVpBvJ74YO0FadsF7BWA5xGsYu0YH4jRBoPFZN6dXxLHGgsIt+DzqgYQ4/X0KiIPCgkI+9/zqgYQ+gYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQj73/OqBhCABxICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGKoIEgMYsQg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwuni4kqSf06pqD/w8Zfi3gAZSI0bqi/3Z833f0DofxIf1j889OuvUFDflj9EvdWynGgwIt+DzqgYQm8XFkgIiDwoJCPvf86oGEIAHEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQj83/OqBhCGBxICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGLEIGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMHrhR6UinNCzYl4uL/u0iJ+M/nAkGIV1r8xfs2Odr/NBu5mGnq+6MJG52cNSVeh4hhoLCLjg86oGENvf+jQiDwoJCPzf86oGEIYHEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFosCgMYsQgaCwoCGAASAxivCBgBGgsKAhgAEgMYrwgYAhoLCgIYABIDGK8IGAM="},{"b64Body":"Cg8KCQj83/OqBhCOBxICGAISAhgDGO/KUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOqgIICgMYsAgQ9AM=","b64Record":"CiMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1j+AxIwhQdij6owwenoNOodhrHrIqyclINcwZiQUKZ//Z3o2x110Ic0op0j2oMHw+Of8sfgGgwIuODzqgYQi7bEtQIiDwoJCPzf86oGEI4HEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoPCgMYsAgSCAoDGK8IEOgH"},{"b64Body":"Cg8KCQj93/OqBhCSBxICGAISAhgDGKX7UiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOigIKCgMYsAgSAxiqCA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwgT4HISBLN4ICFOjOE1JlOL/oh0jeUIPveo5XdmwCmYUc+hASt4PqWjCITGs/JZW6GgsIueDzqgYQs8vyPyIPCgkI/d/zqgYQkgcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQj93/OqBhCUBxICGAISAhgDGKX7UiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOigIKCgMYsQgSAxiqCA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwMnSRnIK6rGMi4dOXBmYo2u2AO/IaLA7Brr+1jpJEzNKpjIPAY9onAghSfzIM4kZBGgwIueDzqgYQg9a1wAIiDwoJCP3f86oGEJQHEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQj+3/OqBhCWBxICGAISAhgDGID+PCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOcjESLwoDGLEIGgwKAxivCBIDGKoIGAEaDAoDGK8IEgMYqggYAhoMCgMYrwgSAxiqCBgD","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwUVgZtpeH5JmE9vOJjVkp2NLzMb7Dzyjo+ynbdS7w23QXy4qAt41CyndbibIkNXd7GgsIuuDzqgYQq8acSiIPCgkI/t/zqgYQlgcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWi8KAxixCBoMCgMYrwgSAxiqCBgBGgwKAxivCBIDGKoIGAIaDAoDGK8IEgMYqggYAw=="},{"b64Body":"ChAKCQj+3/OqBhCXBxIDGKoIEgIYAxiAwtcvIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo6CAykSFAoDGLEIEgMYqggaAxirCCIBASoAGhEKAxiwCBIDGKoIGgMYqwggZA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwcrFpk3EbgsdRSpDS2mRRgyByhULn8xkeP0ccoyHm3GwCUtjAFTrUykJtr07KOQDjGgwIuuDzqgYQ09H0yQIiEAoJCP7f86oGEJcHEgMYqggqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMP3vxRRSLgoJCgIYAxDw6M8BCgkKAhhiELDewiMKCgoDGKAGENqY+QMKCgoDGKoIEPnfiyk="},{"b64Body":"Cg8KCQj/3/OqBhCZBxICGAISAhgDGKX7UiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOkgIKCgMYsAgSAxiqCA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwhKoDtnexbVDsiPjFk4pywOizfnDMWs0HAYxpXXRrH7nrvh2R8o2mf+R0pHTauIlWGgsIu+DzqgYQo4yuVCIPCgkI/9/zqgYQmQcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQj/3/OqBhCbBxICGAISAhgDGKX7UiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOkgIKCgMYsQgSAxiqCA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwi4mN7hp62krYWeLt22y7kPqQgpKhyFdgCEUE2jlyRztj8m9wjA2l80h0KvPtVuQ4GgwIu+DzqgYQg8LT1AIiDwoJCP/f86oGEJsHEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"ChAKCQiA4POqBhCcBxIDGKoIEgIYAxiAwtcvIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo6CAykSFAoDGLEIEgMYqggaAxisCCIBASoAGhEKAxiwCBIDGKoIGgMYrAggZA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw/ZLYLcMFKNPbo3/aU2FJxWA2AuPlF5a3vbngCut7SvEerG8yd/X6m/EfJ3CljzqdGgsIvODzqgYQg6P7XiIQCgkIgODzqgYQnAcSAxiqCCogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo4w/e/FFFIuCgkKAhgDEPDozwEKCQoCGGIQsN7CIwoKCgMYoAYQ2pj5AwoKCgMYqggQ+d+LKQ=="},{"b64Body":"Cg8KCQiA4POqBhCeBxICGAISAhgDGISpUyICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KO8gIFCgMYsAg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw7iWJUvPwXZlse+wpdLM6DaXM9+HFNDhXXoWR1n+g6jcf7kjOytHxs4Vs4IS0042lGgwIvODzqgYQ86bvxQIiDwoJCIDg86oGEJ4HEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQiB4POqBhCgBxICGAISAhgDGISpUyICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KO8gIFCgMYsQg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwUsd5G7tGs6DC5mopNuGc0Q+WGiFp68A/ZYArHfUHx2rvysHZVVYZw7sy2hdX+d86GgsIveDzqgYQm4ngaSIPCgkIgeDzqgYQoAcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"ChAKCQiB4POqBhChBxIDGKoIEgIYAxiAwtcvIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo6CAykSFAoDGLEIEgMYqggaAxitCCIBAioAGhEKAxiwCBIDGKoIGgMYrQggZA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwGOFlVPNNaSUmvc0vhlqTaceA2nRJBXnv1KtBn/I2EkHlEw2NMN4pVBQr7eFKhSQbGgwIveDzqgYQu9Di0AIiEAoJCIHg86oGEKEHEgMYqggqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMP3vxRRSLgoJCgIYAxDw6M8BCgkKAhhiELDewiMKCgoDGKAGENqY+QMKCgoDGKoIEPnfiyk="},{"b64Body":"Cg8KCQiC4POqBhCjBxICGAISAhgDGISpUyICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KO+gIFCgMYsAg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw33NncFL7fn4jto5eZTkUDFCxfYcDXwRNMiGHRgbkKR1GhhhK8WT1PuwrBlTxCWEiGgsIvuDzqgYQ49/EdCIPCgkIguDzqgYQowcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQiC4POqBhClBxICGAISAhgDGISpUyICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KO+gIFCgMYsQg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwm+76qymnqVGofxu4MDPGk2dUQgEncgI+6wvjLvsB7rtlA24J/u4oArcGZxEtMp9AGgwIvuDzqgYQ88722gIiDwoJCILg86oGEKUHEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQiD4POqBhCnBxICGAISAhgDGMmPUyICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KO+gEKCgMYsAgSAxiqCA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw45Z3gkKJl2if7ZE8stEsnas9TFaiFbm7SYJQ/SaHiR2aFBUc2cjP3BX17JM05OgMGgsIv+DzqgYQ05X4fiIPCgkIg+DzqgYQpwcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQiD4POqBhCpBxICGAISAhgDGMmPUyICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KO+gEKCgMYsQgSAxiqCA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwvpNnN+15kNSeFFdO10pTb8/g3XTf7Q06Ouv3f2TGyYUT+4qqfCiFQuplvxX1f6GHGgwIv+DzqgYQm8nK/wIiDwoJCIPg86oGEKkHEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"ChAKCQiE4POqBhCqBxIDGKoIEgIYAxiAwtcvIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo6CAykSFAoDGLEIEgMYqggaAxiuCCIBAyoAGhEKAxiwCBIDGKoIGgMYrgggZA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwkd+64GwE5Svg1y/stRju8tqnwxpQi1F2jL/9YN6TwDfh204Yxk+FCV6Ky3EJMrw+GgwIwODzqgYQw8OBigEiEAoJCITg86oGEKoHEgMYqggqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMP3vxRRSLgoJCgIYAxDw6M8BCgkKAhhiELDewiMKCgoDGKAGENqY+QMKCgoDGKoIEPnfiyk="}]},"serialsInAscendingOrder":{"placeholderNum":1074,"encodedItems":[{"b64Body":"Cg8KCQiI4POqBhC8BxICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIFLylqRCgD61Yn2sJKplM2+019pnJf5V1SAI5XXRQCHJEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGLMIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjC/fsw8r/MEUemOGC1ySqOGdEe/FsD7SmuRiK2fXvkzXCzIGhNGMbPES3h7Wgqbr7caDAjE4POqBhCzk+q0AiIPCgkIiODzqgYQvAcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxizCBCAkN/ASg=="},{"b64Body":"Cg8KCQiJ4POqBhC+BxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIH5/yZV5Voo80jfp8BoJKw8McMq8XL0BCo8lnSrhgqkbEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGLQIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDB4Inzg1yIVokF0wCKDqdgekkpobWST89qB2ndaFXasgwzpKwrSDTgbhcdHeuxP0QaCwjF4POqBhD7/YY/Ig8KCQiJ4POqBhC+BxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGLQIEICQ38BK"},{"b64Body":"Cg8KCQiJ4POqBhDABxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIB5epw9cdqmIghSwCntmb9CEFYLCANLcWv41jLSCtkW7EIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGLUIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjA8FprZfQfcDzbSA7augjXkbe45fWEwqjJnDrvbCPNLJ5kGrVX+ND1x+5oNcx3Ri6IaDAjF4POqBhDzire/AiIPCgkIieDzqgYQwAcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxi1CBCAkN/ASg=="},{"b64Body":"Cg8KCQiK4POqBhDCBxICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIJbdLdCj0dm0XUTFxsK6zhZxPm/gSSv1KOsk6JjNaW07EICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGLYIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCuN/SjMNPwkwyoYk50zvKRqt8wh9+GfQR4VsGVmaDohbZrq4eUKelDPytBVCgQe8kaCwjG4POqBhC76IRJIg8KCQiK4POqBhDCBxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhsKCwoCGAIQ/7+oypo6CgwKAxi2CBCAwKjKmjo="},{"b64Body":"Cg8KCQiK4POqBhDEBxICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghOUkhSQlpaRSoDGLYIUiISINExRr+o6Ss9FGvgGgj3WqSdXVIr9ZzjmG+qhxeglMAwagwIxq7OrgYQ0LDQrwKIAQGQAQGYAQo=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGLcIEjAHFf9/fx11dwo2B0qy2R6NFb4BebxyZ/KUqwtIzm3NVFr4y6D5Ms9AJJRLHvNq0ZIaDAjG4POqBhDL/YLKAiIPCgkIiuDzqgYQxAcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxi3CBIDGLYI"},{"b64Body":"Cg8KCQiL4POqBhDKBxICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGLMIEgMYtwg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw9HlZIY8PkvNfpUkLy/ZjS1eesDOmMTpHrdEtpEEnV7pgTHhzQvzUzZX7hbPePfACGgsIx+DzqgYQk//BVCIPCgkIi+DzqgYQygcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQiL4POqBhDQBxICGAISAhgDGNPOgyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCEQoDGLcIGgFhGgFiGgFjGgFk","b64Record":"CigIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gEcgQBAgMEEjAGZccbrWu7LoS3bvqaf45iyeO7s4/SwpgVWscWGdXmdTUM6xB6kPw6jY2uuji3MHkaDAjH4POqBhCD5pW7AiIPCgkIi+DzqgYQ0AcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWjkKAxi3CBoLCgIYABIDGLYIGAEaCwoCGAASAxi2CBgCGgsKAhgAEgMYtggYAxoLCgIYABIDGLYIGAQ="},{"b64Body":"Cg8KCQiM4POqBhDUBxICGAISAhgDGPqZPSICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOcj8SPQoDGLcIGgwKAxi2CBIDGLMIGAEaDAoDGLYIEgMYswgYAhoMCgMYtggSAxizCBgDGgwKAxi2CBIDGLMIGAQ=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwX+1G80lOXjlXg9hH9gcmi9RQjpUTLaSXGJRwuWRR2BsULUE40XR91+UB2TfP6Kj0GgsIyODzqgYQi+PMXSIPCgkIjODzqgYQ1AcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWj0KAxi3CBoMCgMYtggSAxizCBgBGgwKAxi2CBIDGLMIGAIaDAoDGLYIEgMYswgYAxoMCgMYtggSAxizCBgE"},{"b64Body":"ChAKCQiM4POqBhDVBxIDGLMIEgIYAxiAwtcvIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo6CAxgSFgoDGLcIEgMYswgaAxi0CCIBASoCCAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw2y8R2Nfe+cdkZHo+tcgaLqlPEHBQzyRCPEi1xGAI7PodBfTmgybMvS/Vv7gbuau5GgwIyODzqgYQ85akxAIiEAoJCIzg86oGENUHEgMYswgqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMJnuiBRSLgoJCgIYAxCer80BCgkKAhhiEIaP1yIKCgoDGKAGEI6e7QMKCgoDGLMIELHckSg="},{"b64Body":"ChAKCQiN4POqBhDWBxIDGLMIEgIYAxiAwtcvIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo6CAxgSFgoDGLcIEgMYswgaAxi1CCIDBAIDKgA=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwSf0taghtchm42wVCYQWK9fXI2DJCShRHDjvr4YyMQoPYDxpIUSowDd17LW5tyM7RGgsIyeDzqgYQo666aCIQCgkIjeDzqgYQ1gcSAxizCCogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo4wv5OTFFIuCgkKAhgDENiszgEKCQoCGGIQpOHoIgoKCgMYoAYQgpnvAwoKCgMYswgQ/aamKA=="}]},"feesAsExpected":{"placeholderNum":1080,"encodedItems":[{"b64Body":"Cg8KCQiR4POqBhDoBxICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIOOV7dlN9ezBNmdXlffsH+zfiBWXOS/jr5cJZssl61upEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGLkIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDXci9Y1pVnxEGpJI3WHNbgfi54UUh+a9Gsp/FDX2rno5g7EpKo85REv5vW4hTEasUaDAjN4POqBhC7lZnhAiIPCgkIkeDzqgYQ6AcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxi5CBCAkN/ASg=="},{"b64Body":"Cg8KCQiS4POqBhDqBxICGAISAhgDGPGj9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIApNCuRo9VF/KcZnyj6iD54q/q/MhacVM8gA4uzYxPL+EIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGLoIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCJ3tgV9GOFEqqmauB5uar3tzvDawAkIdqKKH52r6yCbFIIiOGOMJTKonCJ3hdgGFcaCwjO4POqBhDj3OBrIg8KCQiS4POqBhDqBxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGLoIEICQ38BK"},{"b64Body":"Cg8KCQiS4POqBhDsBxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIHHilOcESllYMNkLuQQTWr98jkcxKqCA3fIYgw89VI6fEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGLsIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjB7KlI9EUg3x54YHF3StXK4oOCbMX801UKt4jgGnqKJEtmCWbZkFHL1iLIw5pKYs5oaDAjO4POqBhC74NzsAiIPCgkIkuDzqgYQ7AcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxi7CBCAkN/ASg=="},{"b64Body":"Cg8KCQiT4POqBhDuBxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIMK17aUvj8ueoGtgO3Jfp2QOjDvMUcOVsx2Evct25hMUEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGLwIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCYwYrQpxOqGtsWmtLU0+FuRDp2DpVf6aL/3hbyZgmcguAEgB7/ifj+xxqlFuKLLqkaCwjP4POqBhCjhJt3Ig8KCQiT4POqBhDuBxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGLwIEICQ38BK"},{"b64Body":"Cg8KCQiT4POqBhDwBxICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIITEEoWBTTUmiiOsf+k1/iMJeLVT7ch5oPgP8JFcwYjgEICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGL0IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjApCJYRxMG7UyXoXkbDXCMHM8WVMiPMjyPewI0HWno81djggB4vcZFMUAxiatO8FYgaDAjP4POqBhDr0Lj4AiIPCgkIk+DzqgYQ8AcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMYvQgQgMCoypo6"},{"b64Body":"Cg8KCQiU4POqBhDyBxICGAISAhgDGJvmqekCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVMKCGZ1bmdpYmxlEghZRUJES0FMUyAKKgMYvQhSIhIg58rvDmgIANjOyiaYtczz4CmabIQRVSrqbrZo6vfBtT5qCwjQrs6uBhCA+oR8kAEBmAHoBw==","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGL4IEjCZx+KRAWEiF6ENtBJQ5z/RZcVWcxNu15ce/SfWvLBJ3YAdmO47EZTAmKqxmXI2ff4aDAjQ4POqBhC7wraCASIPCgkIlODzqgYQ8gcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg4KAxi+CBIHCgMYvQgQFHIKCgMYvggSAxi9CA=="},{"b64Body":"Cg8KCQiU4POqBhD0BxICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghKTkhJVERSWCoDGL0IUiISIOfK7w5oCADYzsommLXM8+ApmmyEEVUq6m62aOr3wbU+agwI0K7OrgYQqNq+7gKIAQGQAQGYAQo=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGL8IEjClAt9mww6PwEVUFCVGoeu+ia5yn8E8MMMgLFuj/LBajD7A5QpZaX7Eob+JAAWR8hgaDAjQ4POqBhDb85uDAyIPCgkIlODzqgYQ9AcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxi/CBIDGL0I"},{"b64Body":"Cg8KCQiV4POqBhD6BxICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGLkIEgMYvgg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwDS6S1AzRw37VdPpl0YWK/5F8SazPCZU27BkvzEz0HaxiB7q1bAskZjZAldGI6ZH+GgwI0eDzqgYQs5npjQEiDwoJCJXg86oGEPoHEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQiV4POqBhCACBICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGLkIEgMYvwg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwJuqOMcL4vQPvWjkLFouuf0k5vITHDT0oNEn2gqjle8yU5OCWsa6KW+trJFHI7yPDGgwI0eDzqgYQ+9K5jgMiDwoJCJXg86oGEIAIEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQiW4POqBhCGCBICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGL8IGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMKas9yC0wS+EbdGKbByKcolIaVjiU9fJz5pWwGjJy+5+1XpFXu0vZ2Jv+7ywRpfhExoMCNLg86oGEJug9ZcBIg8KCQiW4POqBhCGCBICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaLAoDGL8IGgsKAhgAEgMYvQgYARoLCgIYABIDGL0IGAIaCwoCGAASAxi9CBgD"},{"b64Body":"Cg8KCQiW4POqBhCOCBICGAISAhgDGO/KUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOqgIICgMYvggQ9AM=","b64Record":"CiMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1j+AxIwe/V9XAxTXwfKZIkaMMgEQ1QDihOsbPo2Xqdtc4GB9Qrese0qxftq+uWYPAyQeUusGgwI0uDzqgYQw9u9lwMiDwoJCJbg86oGEI4IEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoPCgMYvggSCAoDGL0IEOgH"},{"b64Body":"Cg8KCQiX4POqBhCSCBICGAISAhgDGID+PCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOcjESLwoDGL8IGgwKAxi9CBIDGLkIGAEaDAoDGL0IEgMYuQgYAhoMCgMYvQgSAxi5CBgD","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwyGfvg69vteO7+8skgN2jjVkFJU7MNpyKJ8BVZEPO3W87XNvzn+owh64CJ9Mr5i9/GgwI0+DzqgYQ+6D2oQEiDwoJCJfg86oGEJIIEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFovCgMYvwgaDAoDGL0IEgMYuQgYARoMCgMYvQgSAxi5CBgCGgwKAxi9CBIDGLkIGAM="},{"b64Body":"ChAKCQiX4POqBhCTCBIDGLkIEgIYAxiAwtcvIgIIeIIDDgoMCgMYuQgSAxi6CBhk","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwpMZgJaDeljJyO7s79hMU+8Ub4NsYJhZVSoEnz1fslTv+L2xFa6Rd1XpLIs5i3piBGgwI0+DzqgYQi5nXoQMiEAoJCJfg86oGEJMIEgMYuQgw85DvE1IuCgkKAhgDEMz1ygEKCQoCGGIQsoGrIgoKCgMYoAYQ6KroAwoKCgMYuQgQ5aHeJw=="},{"b64Body":"ChAKCQiY4POqBhCYCBIDGLkIEgIYAxiAwtcvIgIIeIIDExoRCgMYvggSAxi5CBoDGLoIIGQ=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwxCUUBKP5oCJB09sggB9YntWE3gqd+uILYE8FuMr8t90dKYJGZ/0zwSeYsnxoJMYEGgwI1ODzqgYQq5mCqwEiEAoJCJjg86oGEJgIEgMYuQgw7531E1IuCgkKAhgDEPqUywEKCQoCGGIQ9OK1IgoKCgMYoAYQ8MPpAwoKCgMYuQgQ3bvqJw=="},{"b64Body":"ChAKCQiY4POqBhCdCBIDGLkIEgIYAxiAwtcvIgIIeIIDFhIUCgMYvwgSAxi5CBoDGLoIIgEBKgA=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwjNuDOOIcwe9msqahOw2dphOXch3YjSXfPcWpreeAtbx+zayAyDWBcyEa8BB+xUc1GgwI1ODzqgYQk/OoqwMiEAoJCJjg86oGEJ0IEgMYuQgwxaP0E1IuCgkKAhgDEKi0ywEKCQoCGGIQwOqzIgoKCgMYoAYQoqjpAwoKCgMYuQgQicfoJw=="},{"b64Body":"ChAKCQiZ4POqBhCiCBIDGLkIEgIYAxiAwtcvIgIIeIIDFRITCgMYvwgSAxi5CBoDGLsIKgIIAQ==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwl2n301dAT3R0Y4UvX4yK91RvIsPTknbhlBk+EufE9K0PUXzItW2Ovio/ycltYleQGgwI1eDzqgYQ05XTtAEiEAoJCJng86oGEKIIEgMYuQgw85DvE1IuCgkKAhgDEMz1ygEKCQoCGGIQsoGrIgoKCgMYoAYQ6KroAwoKCgMYuQgQ5aHeJw=="},{"b64Body":"ChAKCQiZ4POqBhCnCBIDGLkIEgIYAxiAwtcvIgIIeIIDNwoMCgMYuQgSAxi8CBhkEhQKAxi/CBIDGLkIGgMYvAgiAQEqABoRCgMYvggSAxi5CBoDGLwIIGQ=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw3CamsdrL3rvRKJV36Y2QkBfpfAEWtqooKwNfqac4ArQe6eUuUlFusR9O/7L6BpSgGgwI1eDzqgYQ07jftAMiEAoJCJng86oGEKcIEgMYuQgwiproFFIuCgkKAhgDEJ6I0AEKCQoCGGIQxKeAJAoKCgMYoAYQsoSABAoKCgMYuQgQk7TQKQ=="},{"b64Body":"ChAKCQia4POqBhCuCBIDGLkIEgIYAxiAwtcvIgIIeIIDDwoNCgMYuQgSAxi8CBjIAQ==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwqfnyoOtTUoF/485LD0GuoAKmBywtVRNIBY835YRfXH2tK9QwOaiRFDUtJxv66YuxGgwI1uDzqgYQw5WYvwEiEAoJCJrg86oGEK4IEgMYuQgwgrDPE1IuCgkKAhgDEMz1ygEKCQoCGGIQzOzxIQoKCgMYoAYQ7P3hAwoKCgMYuQgQg+CeJw=="},{"b64Body":"ChAKCQia4POqBhCzCBIDGLkIEgIYAxiAwtcvIgIIeIIDFBoSCgMYvggSAxi5CBoDGLwIIMgB","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw7q0b6dMjRvHZo2miloEEvcs8AIZfVqtg85RdqwOzyN304ccHPf9MdAZCW3ckqVEMGgwI1uDzqgYQk4eNwAMiEAoJCJrg86oGELMIEgMYuQgwq/nRE1IuCgkKAhgDEPqUywEKCQoCGGIQlKH2IQoKCgMYoAYQyLziAwoKCgMYuQgQ1fKjJw=="},{"b64Body":"ChAKCQib4POqBhC4CBIDGLkIEgIYAxiAwtcvIgIIeIIDExIRCgMYvwgSAxi5CBoDGLsIKgA=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwdnSqIngnhvNI7fPBZpiqeCzjMtafrs7xtHlQVocvCfQ1YqQtdBG2Ui9iOgcVcXn3GgwI1+DzqgYQ492TygEiEAoJCJvg86oGELgIEgMYuQgwgrDPE1IuCgkKAhgDEMz1ygEKCQoCGGIQzOzxIQoKCgMYoAYQ7P3hAwoKCgMYuQgQg+CeJw=="}]},"CannotHaveMultipleAllowedSpendersForTheSameNFTSerial":{"placeholderNum":1088,"encodedItems":[{"b64Body":"Cg8KCQif4POqBhDOCBICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIPceqRUf1JDHpzjlPXGjsRMT+yxWWlRKM0pZtk8tQSiqEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGMEIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDCyQWYeRH1+E7MO9ZREDXrw3OPAK63Hkve3fqtZPTimqcp4kq84M5nKxHLwF8E9Z8aDAjb4POqBhC7qbWNAyIPCgkIn+DzqgYQzggSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjBCBCAkN/ASg=="},{"b64Body":"Cg8KCQig4POqBhDQCBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIJUkWR79xb7fbxaZxbRwpioclDZ8bVqPfJj1lWNwp5z2EIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGMIIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBovT86V0Ggv8K/cbJzhrOVcGlwQyGFuIB/LVjoeG8KaEuyxLTO6j8IAGNqDpIPbhsaDAjc4POqBhCDnf6xASIPCgkIoODzqgYQ0AgSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjCCBCAkN/ASg=="},{"b64Body":"Cg8KCQig4POqBhDSCBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIGZcuUfDJ3NnnR6LeHS/eeTnAD3VFpSpJgeSFDFTj03iEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGMMIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCGk6AF9ma3vnLFjO2xao1JJKFjgl1NCKpwS3tBhis/1Hr8XPr7Y0J8GRzmc0VDGk8aDAjc4POqBhCjyYmZAyIPCgkIoODzqgYQ0ggSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjDCBCAkN/ASg=="},{"b64Body":"Cg8KCQih4POqBhDUCBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIA15U0AtmPGxCX/T/3Jaw9G21mdaT5GyI8H/GdCwyf+cEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGMQIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjALU9LwVkm54jC+XwcTq1JTzTyNmojA+FqfGkhg+oQ9PTxmuJgnPpwKbkI/9yN57UgaDAjd4POqBhCjs+C8ASIPCgkIoeDzqgYQ1AgSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjECBCAkN/ASg=="},{"b64Body":"Cg8KCQih4POqBhDWCBICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIEAMmy7CZ3+P0NUhUtUHWx2jFqlHujr+JrYJ/0VhOBi1EICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGMUIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjC9JSatburAK554kmzOV19TQstynxsBo67snmFwODzRYqZg+BbRRby/PfZnTMRdKCsaDAjd4POqBhCLnvmjAyIPCgkIoeDzqgYQ1ggSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMYxQgQgMCoypo6"},{"b64Body":"Cg8KCQii4POqBhDYCBICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghESkRQVUhUTSoDGMUIUiISIGHEMlG+h+fbUwcCNUV0JhJERF+/6tdOQf3NnoqXWBv1agwI3q7OrgYQiLPyqQGIAQGQAQGYAQo=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGMYIEjB5sSx/3nHnpRAtYuxOcZQ4vA48xUD/IOL5NLT1dW6pOveAEz7z2pbmBSAFaXf5fpAaDAje4POqBhD7oMyvASIPCgkIouDzqgYQ2AgSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxjGCBIDGMUI"},{"b64Body":"Cg8KCQii4POqBhDeCBICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGMEIEgMYxgg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwPeKKFqhwSywtAAgNi1qHvITZsNGoTaz1JQ/qZ3j8tH9HVSC3q0zVKPqH+Xg8DZ1bGgwI3uDzqgYQy7XirwMiDwoJCKLg86oGEN4IEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQij4POqBhDkCBICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGMQIEgMYxgg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwgs+44xTzgWMQg86W2J9tmCqyfWc0Py0+hS6UVABzhZvQHXOUsI/T3imejOErKliEGgwI3+DzqgYQ666zuwEiDwoJCKPg86oGEOQIEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQij4POqBhDqCBICGAISAhgDGNPtlwgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCCAoDGMYIGgFh","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gBcgEBEjB/DCSWWYj7CTAinCSIwErgeuhQ94XQbu6IsxqyP62sxJqTQWCqOJ3T+YHHXfTLfAMaDAjf4POqBhCrgOm9AyIPCgkIo+DzqgYQ6ggSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWhIKAxjGCBoLCgIYABIDGMUIGAE="},{"b64Body":"Cg8KCQik4POqBhDuCBICGAISAhgDGI3GPCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOchUSEwoDGMYIGgwKAxjFCBIDGMEIGAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwddqRiGhSjZxGBOV2QfF55YvGoLcbQ+E2PkD53GmtTKfMe42g52b9oKM8oawL3LbqGgwI4ODzqgYQ65HsxwEiDwoJCKTg86oGEO4IEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoTCgMYxggaDAoDGMUIEgMYwQgYAQ=="},{"b64Body":"Cg8KCQik4POqBhD0CBICGAISAhgDGNjp2yMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjoIDGBIWCgMYxggSAxjBCBoDGMIIIgEBKgIIAQ==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwD8q/8wdp1EBeYREf3dUC19UQGIWY8WXJt3ZnJXdTeEBMMBCXSPKTgQgeMEWwHTt5GgwI4ODzqgYQm/GyyAMiDwoJCKTg86oGEPQIEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQil4POqBhD6CBICGAISAhgDGNjp2yMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjoIDGBIWCgMYxggSAxjBCBoDGMMIIgEBKgIIAQ==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw1AyOIhGqpdN65k3Nri5cr1Hs3Bm4+6fpINXzWQWfOGXLC7fJB8mf+CXwlOseFzPXGgwI4eDzqgYQi6mk0gEiDwoJCKXg86oGEPoIEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"ChAKCQil4POqBhCCCRIDGMMIEgIYAxiv/jIiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnIXEhUKAxjGCBoOCgMYwQgSAxjECBgBIAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwVDcqC9rcPc7nw5700s9xB216sejdC0C2tYwgITIJRSYztYDLWrD0TWPKsW5w9o7qGgwI4eDzqgYQ87Tk0gMiEAoJCKXg86oGEIIJEgMYwwgqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMK/+MlIqCggKAhgDELLRBAoICgIYYhC2zVcKCQoDGKAGEPbdCQoJCgMYwwgQ3fxlWhMKAxjGCBoMCgMYwQgSAxjECBgB"},{"b64Body":"Cg8KCQim4POqBhCICRICGAISAhgDGI3GPCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOchUSEwoDGMYIGgwKAxjECBIDGMEIGAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwwNW6kNLN6lk7IZy8eW7FCFz3bfba7LK272yXb//8IyXdR4d0g+gJJlVkmoHGXXheGgwI4uDzqgYQu92W3QEiDwoJCKbg86oGEIgJEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoTCgMYxggaDAoDGMQIEgMYwQgYAQ=="},{"b64Body":"ChAKCQim4POqBhCKCRIDGMMIEgIYAxiv/jIiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnIXEhUKAxjGCBoOCgMYwQgSAxjECBgBIAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwul/W2XvTu/tG00lf3N7K8Arq+z0uoVegaVDmbqBqV0f4jrif3/PlJ+Vm84LEW9/KGgsI4+DzqgYQ44mZASIQCgkIpuDzqgYQigkSAxjDCCogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo4wr/4yUioKCAoCGAMQstEECggKAhhiELbNVwoJCgMYoAYQ9t0JCgkKAxjDCBDd/GVaEwoDGMYIGgwKAxjBCBIDGMQIGAE="},{"b64Body":"Cg8KCQin4POqBhCQCRICGAISAhgDGP3W1iMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjoIDExIRCgMYxggSAxjBCBoDGMMIKgA=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwQRxU9ZyyN9JSt7VAx+67re48n/zhBtAxuAsqM8V/zqrCtSPjxNY1SIRN+MLeyDAnGgwI4+DzqgYQy9eO6QEiDwoJCKfg86oGEJAJEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQin4POqBhCUCRICGAISAhgDGI3GPCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOchUSEwoDGMYIGgwKAxjECBIDGMEIGAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw6yX04+i68PN8yLmrCUg3Wz6f6gOAaXRoVX4PPJq+Tm9D4IEWwvTiO2eJEitTVqgcGgsI5ODzqgYQ48qMDCIPCgkIp+DzqgYQlAkSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWhMKAxjGCBoMCgMYxAgSAxjBCBgB"},{"b64Body":"ChAKCQio4POqBhCWCRIDGMMIEgIYAxiv/jIiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnIXEhUKAxjGCBoOCgMYwQgSAxjECBgBIAE=","b64Record":"CiEIpAIqHAoMCAEQDBoGCICumaQPEgwIARAPGgYIgK6ZpA8SMGL2dHTwhwihw2O6ujfFw0V0syTDQhyEl1nD3KXlyyDh0tFh0D9j93luO7yPxdU1URoMCOTg86oGELuoufMBIhAKCQio4POqBhCWCRIDGMMIKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjjCv/jJSKgoICgIYAxCy0QQKCAoCGGIQts1XCgkKAxigBhD23QkKCQoDGMMIEN38ZQ=="},{"b64Body":"Cg8KCQio4POqBhCcCRICGAISAhgDGNHp2yMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjoIDFhIUCgMYxggSAxjBCBoDGMMIIgEBKgA=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwnYbmnHniN/BdlZIpsuvE0CM3Cm1CHC6V5+ldJtJ6HHMctWFNKIkSDHrgIOHupr69GgsI5eDzqgYQq8O8FiIPCgkIqODzqgYQnAkSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"ChAKCQip4POqBhCeCRIDGMMIEgIYAxiv/jIiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnIXEhUKAxjGCBoOCgMYwQgSAxjECBgBIAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw4nuLXkPhdl0cDoWGpv8+h2QXRKYh6CV9/2GZD1R1cqF3ogLHmweywUexkqB0QbFmGgwI5eDzqgYQu+Xd/AEiEAoJCKng86oGEJ4JEgMYwwgqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMK/+MlIqCggKAhgDELLRBAoICgIYYhC2zVcKCQoDGKAGEPbdCQoJCgMYwwgQ3fxlWhMKAxjGCBoMCgMYwQgSAxjECBgB"},{"b64Body":"Cg8KCQiq4POqBhCgCRICGAISAhgDGI3GPCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOchUSEwoDGMYIGgwKAxjECBIDGMEIGAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwS/We002m4ZxZsrcionAsSY+sMttUlr+uKwXlI/B27NdEl3ei6ie0VVWbN2T6cD61GgsI5uDzqgYQq9SQByIPCgkIquDzqgYQoAkSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWhMKAxjGCBoMCgMYxAgSAxjBCBgB"},{"b64Body":"ChAKCQiq4POqBhCiCRIDGMMIEgIYAxiv/jIiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnIXEhUKAxjGCBoOCgMYwQgSAxjECBgBIAE=","b64Record":"CiEIpAIqHAoMCAEQDBoGCICumaQPEgwIARAPGgYIgK6ZpA8SMC5qO4/bdAf0bGllI357gXkoGPRPcVIkB71MHTv30XUB/0j3kE8YbJzGrK4P0QaoURoMCObg86oGEJPQ/4cCIhAKCQiq4POqBhCiCRIDGMMIKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjjCv/jJSKgoICgIYAxCy0QQKCAoCGGIQts1XCgkKAxigBhD23QkKCQoDGMMIEN38ZQ=="}]},"approveForAllDoesNotSetExplicitNFTSpender":{"placeholderNum":1095,"encodedItems":[{"b64Body":"Cg8KCQiu4POqBhCyCRICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIKqivCcAiK3P/pY0aJqYl1TanDCiRs3cSFfuhYedyfknEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGMgIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBHL76JqxMNahADBbSMKcqrimqWbfURqQSzbBToGqy/AaE2/7U23IPS5UIicwhyNWYaDAjq4POqBhCT/77MAyIPCgkIruDzqgYQsgkSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjICBCAkN/ASg=="},{"b64Body":"Cg8KCQiv4POqBhC0CRICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISINgxGg5DC53B09tU7p5PsaxnSgkOGDiziZ/JW2/U3nKqEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGMkIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBpaJCvOMZGEoqHng0pMM6PVLrD+MCbvb/16V87OX0q+7GO2SreecQKRyuLajMN64QaDAjr4POqBhD75OrVASIPCgkIr+DzqgYQtAkSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjJCBCAkN/ASg=="},{"b64Body":"Cg8KCQiv4POqBhC2CRICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIJdLSUbEXGzRC8kfa1zcz93amzKllCw0+NKrLt19HMTeEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGMoIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjClk0Jtlw8+LLv1oB+sOonxDe8GTYBmo8FLklx65Sg8JyTKApGQWhkwdRTOaay5CaMaDAjr4POqBhDr7o7WAyIPCgkIr+DzqgYQtgkSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjKCBCAkN/ASg=="},{"b64Body":"Cg8KCQiw4POqBhC4CRICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIEiDA47pAAjgiW41alS9Tti9cW28Y6otsbi8mrOTYpFgEICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGMsIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAzXGz3DyGVfhB66MDmGIa0qPSNlLUOw1ZuOJGgDsDCQMg5/yfSXVLYg6cwU7XLb9AaDAjs4POqBhCzsI/gASIPCgkIsODzqgYQuAkSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMYywgQgMCoypo6"},{"b64Body":"Cg8KCQiw4POqBhC6CRICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghaS1RLVk5UTioDGMsIUiISIPzSElxAFFk7BmlbEQ3BG80LiEoxARfCabRzgGwMBeCFagwI7K7OrgYQuInixwOIAQGQAQGYAQo=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGMwIEjCsifaq133vTuXcRrw7Q/R2rLuhpO7w4thpz/j9PIROJrqIq3WCfJXjp74FakNnSQsaCwjt4POqBhDz8ooDIg8KCQiw4POqBhC6CRICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgByCgoDGMwIEgMYywg="},{"b64Body":"Cg8KCQix4POqBhDACRICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGMgIEgMYzAg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIww2dpJLVTrF+1DdDe2bltJjWBGuObl+NB/p26QkZtY5WZGX90Yh3ivh07ugGGJNbcGgwI7eDzqgYQ06KA6gEiDwoJCLHg86oGEMAJEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQix4POqBhDGCRICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGMoIEgMYzAg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwB7LsvJWCy2gSJAAA/jatQvK+Z5s0kRYRE1KUY3n0cL2hlPN53AcKZw5azgznELY3GgsI7uDzqgYQs9XeDSIPCgkIseDzqgYQxgkSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQiy4POqBhDMCRICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGMkIEgMYzAg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw9xBbtFzh0UnN09AV+0wvxW9Z3Euol6Rilppjf+fgsVrqgg6SSQ9Ifo+rZNqjmq9DGgwI7uDzqgYQu7KJ9AEiDwoJCLLg86oGEMwJEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQiy4POqBhDSCRICGAISAhgDGNPtlwgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCCAoDGMwIGgFh","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gBcgEBEjCf89bXVDTbslJ06LYIUWw3auuRki1zvTfDIjLYDMuMy4XzFKwK7QB7nuh251CRxyYaCwjv4POqBhC7iZMXIg8KCQiy4POqBhDSCRICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaEgoDGMwIGgsKAhgAEgMYywgYAQ=="},{"b64Body":"Cg8KCQiz4POqBhDWCRICGAISAhgDGI3GPCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOchUSEwoDGMwIGgwKAxjLCBIDGMgIGAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwPl3knUD4WziHlbF0mch16F9jsMI1qzMGB1b8YCLR+wUHrthuGhknljrv7SjpusygGgwI7+DzqgYQ+6/R/wEiDwoJCLPg86oGENYJEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoTCgMYzAgaDAoDGMsIEgMYyAgYAQ=="},{"b64Body":"Cg8KCQi04POqBhDcCRICGAISAhgDGP3W1iMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjoIDFRITCgMYzAgSAxjICBoDGMkIKgIIAQ==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwCo7d8aqR1aP/IlMnQq9T/4O+ygSSYJ98zjRi06FC35mRk7nffNwwKPgeZcfSK7yvGgsI8ODzqgYQw8m6IyIPCgkItODzqgYQ3AkSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"ChAKCQi04POqBhDkCRIDGMkIEgIYAxiNxjwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnIXEhUKAxjMCBoOCgMYyAgSAxjKCBgBIAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwBxNpRGiQPXSdNjoaG4Qf5w43qsgzuS/MUbf2fHiq0jKMZsM6LGsj47TlEzcYggVsGgwI8ODzqgYQu53LigIiEAoJCLTg86oGEOQJEgMYyQgqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMI3GPFIqCggKAhgDEOLUBAoICgIYYhCM5WgKCQoDGKAGEKzSCwoJCgMYyQgQmYx5WhMKAxjMCBoMCgMYyAgSAxjKCBgB"}]},"canGrantNftAllowancesWithTreasuryOwner":{"placeholderNum":1101,"encodedItems":[{"b64Body":"Cg8KCQi44POqBhD4CRICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISINgJcWLCOcDyBIO+Cdjbu6HaQWbnAtIpcmUPWMXY72k+EICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGM4IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAT/mY+JoMA6Onrnk0iaa4rYIMsVV0SSqqtKL27y0Nnx8BtePTRMSzaAo9cuGhJbjwaCwj14POqBhDbnY4MIg8KCQi44POqBhD4CRICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/6fWuQcKCwoDGM4IEICo1rkH"},{"b64Body":"Cg8KCQi54POqBhD6CRICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIBkPpCWBOjgL9n3oOaowNZ9rqvVJYQUeG32QkMf/dksCEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGM8IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCZAj2hYhAbzLonwnjRZM7xzbjjycMZJlZUMTpVU88WmMkZC/RMMafWVQmqMfAUENQaDAj14POqBhDThpjzASIPCgkIueDzqgYQ+gkSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxjPCBCAqNa5Bw=="},{"b64Body":"Cg8KCQi64POqBhD8CRICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVAKC25vbkZ1bmdpYmxlEghTVUZTSEhOTCoDGM4IUiISIA35A3Yrrgm86iKYiqnWt8caA4Zs3za6p6RHa2+c57L/agsI9q7OrgYQiJj/AYgBAQ==","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGNAIEjDUHZZlK6U2Hkf48GUsQx3jql/9JMCt2QKcDnzkoG+LTnXDhBOLfKDyiH+bdB+YesoaCwj24POqBhCruekWIg8KCQi64POqBhD8CRICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgByCgoDGNAIEgMYzgg="},{"b64Body":"Cg8KCQi64POqBhCCChICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGNAIGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMGaFlOoyNBfF0UK0WGAecQmLycYDLUlvDFYm8uXCNa2+mwz08hIJ5RRygXlmwmIP7RoMCPbg86oGEMvtm/4BIg8KCQi64POqBhCCChICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaLAoDGNAIGgsKAhgAEgMYzggYARoLCgIYABIDGM4IGAIaCwoCGAASAxjOCBgD"},{"b64Body":"Cg8KCQi74POqBhCGChICGAISAhgDGMae0hUiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloyCiISIO76bdBwu4woU8/0kobGauvL8DIzj2YJza+ZIRr6mCfVEIDC1y9KBQiAztoDcAE=","b64Record":"CiUIFhIDGNEIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCNKs955Y3XYlbdm/SwgNI3h8rB7znZGRHtHUqkUOkOcCD8Yu9beeQAKEyNdgJSvOkaCwj34POqBhCbibgjIg8KCQi74POqBhCGChICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhcKCQoCGAIQ/4OvXwoKCgMY0QgQgISvXw=="},{"b64Body":"Cg8KCQi74POqBhCSChICGAISAhgDGKT84CMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjoIDFxIVCgMY0AgSAxjOCBoDGM8IIgIBAyoA","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwvaA0iOtKenZHuroXKBTxDfpYTGQpAebnSy1FUxN34xvdlnRh3sKkyo+ryQLpxp7nGgwI9+DzqgYQ++WeigIiDwoJCLvg86oGEJIKEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"ChAKCQi84POqBhCYChIDGM8IEgIYAxiv/jIiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnIXEhUKAxjQCBoOCgMYzggSAxjRCBgBIAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwPxc0UkljLTPlvmsyc47iOxSIZ633d4y+i48FolU7ZxX3MH8Hif3ZH+NU0y2AjTffGgsI+ODzqgYQ64jJLSIQCgkIvODzqgYQmAoSAxjPCCogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo4wr/4yUioKCAoCGAMQstEECggKAhhiELbNVwoJCgMYoAYQ9t0JCgkKAxjPCBDd/GVaEwoDGNAIGgwKAxjOCBIDGNEIGAFyCgoDGNAIEgMY0Qg="}]},"canGrantFungibleAllowancesWithTreasuryOwner":{"placeholderNum":1106,"encodedItems":[{"b64Body":"Cg8KCQjA4POqBhCqChICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIJ57glHIbqgD/2m3l+Ep+gZgKU6DzxfAj6+6ztSvkQ0QEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGNMIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjABXRQa4oGqm6VJAFVKPlunrl5d3edIuCsQlAhuIGUkWJQfmxHHARP7k99dYn64U2waDAj84POqBhCb+PukAiIPCgkIwODzqgYQqgoSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxjTCBCAqNa5Bw=="},{"b64Body":"Cg8KCQjB4POqBhCsChICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIPZOCtk2fwBFMaA0ZmJFpy6OzaNBRgRMY5LrY6InYatfEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGNQIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAhVMU/tWZws3H11ar/bWzpPMkUz2oMsd7Q92a1eCuw1Bm1/64DCuVwqKDy0uSAE08aCwj94POqBhDzt+0uIg8KCQjB4POqBhCsChICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/6fWuQcKCwoDGNQIEICo1rkH"},{"b64Body":"Cg8KCQjB4POqBhCuChICGAISAhgDGLzj4ugCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qATEKCGZ1bmdpYmxlEghORVFOVFVMQSCIJyoDGNMIagwI/a7OrgYQ2N2lkwKQAQGYAZBO","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGNUIEjAARKBnJdLsMSO/essPj+N5D+4kVSgaZN3rFOiYpcqBAWWUJ9TAfaFO9/dbFZ4/n9oaDAj94POqBhDzgbuVAiIPCgkIweDzqgYQrgoSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg8KAxjVCBIICgMY0wgQkE5yCgoDGNUIEgMY0wg="},{"b64Body":"Cg8KCQjC4POqBhCwChICGAISAhgDGMae0hUiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloyCiISIDUcXI+KnpIg+XroDxVr9MSsD7OgGORxzn4URCks+6/oEIDC1y9KBQiAztoDcAE=","b64Record":"CiUIFhIDGNYIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDwF9WA4yuP49wOHdzVxXAgcMnoMHJ0SKqrLQAJvhI1gMIxBqck9bOxiikkeVCoQYYaCwj+4POqBhCbisk5Ig8KCQjC4POqBhCwChICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhcKCQoCGAIQ/4OvXwoKCgMY1ggQgISvXw=="},{"b64Body":"Cg8KCQjC4POqBhC2ChICGAISAhgDGKqMjCQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjoIDExoRCgMY1QgSAxjTCBoDGNQIIAo=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwn0l0p+wnx6SRoDzKX0ZrckfkjqFesU9TUa2WYrZHKT3MiCm0vNPFouxao2JQfyY6GgwI/uDzqgYQ2/7woAIiDwoJCMLg86oGELYKEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjD4POqBhC8ChICGAISAhgDGKqMjCQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjoIDExoRCgMY1QgSAxjTCBoDGNQIIG4=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwCrIeScHKGlfcEnAzU/qsN9mHVq6XgAdGDXPgBiNbfiy2xWpDTxtIK1kMrmNVG5p4GgsI/+DzqgYQ07jKRCIPCgkIw+DzqgYQvAoSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"ChAKCQjD4POqBhC+ChIDGNQIEgIYAxj+8zIiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnIdEhsKAxjVCBIJCgMY0wgQOxgBEgkKAxjWCBA8GAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwGbiIsXxwJGOUY1+lnoJ7igt5KbHXDBcFEYg3KCHeTLsty1MsCLz7ORHdARsMcqyqGgwI/+DzqgYQ88WMqwIiEAoJCMPg86oGEL4KEgMY1AgqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMP7zMlIqCggKAhgDENriBAoICgIYYhCSq1cKCQoDGKAGEJDaCQoJCgMY1AgQ++dlWhcKAxjVCBIHCgMY0wgQOxIHCgMY1ggQPHIKCgMY1QgSAxjWCA=="}]},"approveForAllSpenderCanDelegateOnNFT":{"placeholderNum":1111,"encodedItems":[{"b64Body":"Cg8KCQjI4POqBhDSChICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIEvFCZOYbgxyRqvXG9OEfANZO/mcjhWtpSoZIz/ljw9dEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGNgIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAOqtJvDZkJyQvRJNfvTfETY0hAt0JfeIMK4qMb13HvYqGOwu3JnvIQm/4EcU9fKmkaCwiE4fOqBhCzwYpHIg8KCQjI4POqBhDSChICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGNgIEICQ38BK"},{"b64Body":"Cg8KCQjI4POqBhDUChICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIJoGyvBlhGNrWZdB20tXbtAA7Umebxqosj9XPwjDmN59EIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGNkIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBqP9ZmLfUWn5iVbxdLeDdEu1HJpE/iaeTb6pxzQyRFU9xzwPIApynYbaPB5EGrIlkaDAiE4fOqBhCrncKuAiIPCgkIyODzqgYQ1AoSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjZCBCAkN/ASg=="},{"b64Body":"Cg8KCQjJ4POqBhDWChICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIOWWZj2jFNSkQJrTMhAqQlbU+QKSVV8JVVe6cCo/oaY5EIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGNoIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjC8t0d/dCXEB06Rb9X/KhFpHwa0/KKmf3xJoRbeQPvOctwsYzr7fLYEP7QjvAPwq5caCwiF4fOqBhDzt4FSIg8KCQjJ4POqBhDWChICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGNoIEICQ38BK"},{"b64Body":"Cg8KCQjJ4POqBhDYChICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISINJ9MtmNh0I0F/SscIY/CQ+i9PNieGQlrCTAwd0rVhMNEICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGNsIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCDpBfFWlVyILZB9FCY6lgpqYJexZBELA/iYK//SLrsk5afqSA4qtIF8vUiECULP+QaDAiF4fOqBhCbmN+4AiIPCgkIyeDzqgYQ2AoSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMY2wgQgMCoypo6"},{"b64Body":"Cg8KCQjK4POqBhDaChICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVYKC25vbkZ1bmdpYmxlEghTSlpDQ1RMQyoDGNsIUiISIFhnkcFNklVEFEgEJ3OTjEP5Lpv2O8MEtwiIP2AuCGZ+agsIhq/OrgYQ6LX7QYgBAZABAZgBCg==","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGNwIEjCw3v1u8eN4xdngyuVJUhXcEWpQqbw9Gr+8oXyRxIRavtgzuEIgpn3e6LqJboNf8zIaCwiG4fOqBhDzhZVDIg8KCQjK4POqBhDaChICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgByCgoDGNwIEgMY2wg="},{"b64Body":"Cg8KCQjK4POqBhDgChICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGNgIEgMY3Ag=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwzsIwAdrfqpT/RNdfxuUBVut6NG0b+qCDXbTecRNiX7TJzhW07wUaTlpLfqbzZoW4GgwIhuHzqgYQ+7PUwwIiDwoJCMrg86oGEOAKEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjL4POqBhDmChICGAISAhgDGP2NkRAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCCwoDGNwIGgFhGgFi","b64Record":"CiYIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gCcgIBAhIwm1ZJn3mp/+1QwFE8dVdqlzMQQSYOwmM8ibGH8dS9Z7nkKC+lPyymDO3xLpgHrjvYGgsIh+HzqgYQo8C6ZiIPCgkIy+DzqgYQ5goSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWh8KAxjcCBoLCgIYABIDGNsIGAEaCwoCGAASAxjbCBgC"},{"b64Body":"Cg8KCQjL4POqBhDqChICGAISAhgDGIfiPCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOciMSIQoDGNwIGgwKAxjbCBIDGNgIGAEaDAoDGNsIEgMY2AgYAg==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwH2zmWoR/3Gr4lFI23VR/hUjHqO7BTR+5ojVRGwh5N7jwoc288ZR+jZWpxQGIwxXAGgwIh+HzqgYQw8mnzQIiDwoJCMvg86oGEOoKEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFohCgMY3AgaDAoDGNsIEgMY2AgYARoMCgMY2wgSAxjYCBgC"},{"b64Body":"Cg8KCQjM4POqBhDwChICGAISAhgDGKrcwSciAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjoIDLhIWCgMY3AgSAxjYCBoDGNkIIgEBKgIIARIUCgMY3AgSAxjYCBoDGNoIIgECKgA=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwfIO3Eh4y4sPszmpQ9JghP1EFMpvof7SLIwVNxBN9zgs5ujVJXOkhZ1G50adkdmboGgsIiOHzqgYQs7vZVyIPCgkIzODzqgYQ8AoSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQjN4POqBhCQCxICGAISAhgDGNHp2yMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjoIDGxIZCgMY3AgSAxjYCBoDGNoIIgEBKgAyAxjZCA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw5kH+0DhIj4mgHhWp6uOUh09+QC6QvdiqGrcL5EvTF+GZBUe+HjsLKmgQba7edVRLGgsIieHzqgYQw5qSeyIPCgkIzeDzqgYQkAsSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"}]},"duplicateEntriesGetsReplacedWithDifferentTxn":{"placeholderNum":1117,"encodedItems":[{"b64Body":"Cg8KCQjR4POqBhCkCxICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIGJNwof29Ywqh6bnwSYhrjTdJDQuMGSEY58k7Yxvjz0kEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGN4IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBA6+f9pmmb9qvgLp0Jw6zC1+PIbdn/EI3Q7wAWFjnAcos2ghuW2+3WF8u9njkZ8QgaDAiN4fOqBhDzo7rXAiIPCgkI0eDzqgYQpAsSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjeCBCAkN/ASg=="},{"b64Body":"Cg8KCQjS4POqBhCmCxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIPXR8MzTXB52/gzlKKJjDE0gX8jfmN0aKnPJl7kRlPqxEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGN8IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjB845FBTIMfPKzsoWS90fiNwDn6rgwsfX6O7aDlk3pRNUokLihWlAJeutY6rntNHXgaCwiO4fOqBhCj0JphIg8KCQjS4POqBhCmCxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGN8IEICQ38BK"},{"b64Body":"Cg8KCQjS4POqBhCoCxICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIBb5PW1s+/y61aMtpD9C0+k8p8TxrsMqJ/mOowqgOTBeEICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGOAIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDQhfzzC3dmLacTGBlQJZeK7Ma059NgRpAbLFY6PBACih9TQ2ovm/ljFNoWLv/PbTsaDAiO4fOqBhDDrZ7hAiIPCgkI0uDzqgYQqAsSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMY4AgQgMCoypo6"},{"b64Body":"Cg8KCQjT4POqBhCqCxICGAISAhgDGJvmqekCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVMKCGZ1bmdpYmxlEghCWEtFWU1VRCAKKgMY4AhSIhIgD+GhL7FvzDkOi/ro3IE0uzrxk7ykVyvIj/kFVxk4Ud5qCwiPr86uBhDArpJdkAEBmAHoBw==","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGOEIEjC0+2EEgf6cOLqnid0/K41vQkm6yZhJt8zSGvtDB59+JoXn40U/c0DEenk3WtVX/MsaCwiP4fOqBhDj7tprIg8KCQjT4POqBhCqCxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaDgoDGOEIEgcKAxjgCBAUcgoKAxjhCBIDGOAI"},{"b64Body":"Cg8KCQjT4POqBhCsCxICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghQV1VRWFVYWSoDGOAIUiISIA/hoS+xb8w5Dov66NyBNLs68ZO8pFcryI/5BVcZOFHeagwIj6/OrgYQyIPvzwKIAQGQAQGYAQo=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGOIIEjARg7LRn0w6JitIQS/usYVVGWpFMUAYPERNn9eTQ2LS9/0CGAl5DVr/+q30F67QRVEaDAiP4fOqBhD7sKjSAiIPCgkI0+DzqgYQrAsSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxjiCBIDGOAI"},{"b64Body":"Cg8KCQjU4POqBhCyCxICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGN4IEgMY4Qg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw5MWRwUx2Ypg7nbwch+nPXmUKXyus7IvJpA5Fcfjao6KeXSKt86lNXbtoWRVog5E1GgsIkOHzqgYQ+4KKdSIPCgkI1ODzqgYQsgsSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQjU4POqBhC4CxICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGN4IEgMY4gg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwjq7J9l6uTpUnfaSZDgFLbou3wCa8zUTXT/9gcaiUoXYaKM5SPyAZfjGosetG2cDMGgwIkOHzqgYQy/TP2wIiDwoJCNTg86oGELgLEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjV4POqBhC+CxICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGOIIGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMLv7m8eqquK3R+RkDIUsjCrE6VVEvpsRffvwdGnqnpLxRPGRxxCdtu+XWIoqzwzoMxoLCJHh86oGEJvG3X8iDwoJCNXg86oGEL4LEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFosCgMY4ggaCwoCGAASAxjgCBgBGgsKAhgAEgMY4AgYAhoLCgIYABIDGOAIGAM="},{"b64Body":"Cg8KCQjV4POqBhDGCxICGAISAhgDGO/KUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOqgIICgMY4QgQ9AM=","b64Record":"CiMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1j+AxIwL7war2fWCVz57Fopk0cREBwf6qTgaODvltedMOJi85Dy2F3Nx2Gje9v8otUFjkAyGgwIkeHzqgYQm7ijgAMiDwoJCNXg86oGEMYLEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoPCgMY4QgSCAoDGOAIEOgH"},{"b64Body":"Cg8KCQjW4POqBhDKCxICGAISAhgDGID+PCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOcjESLwoDGOIIGgwKAxjgCBIDGN4IGAEaDAoDGOAIEgMY3ggYAhoMCgMY4AgSAxjeCBgD","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw4pxwsVHLQkyv5S8JXjv9gMP2YISd9C8GBoagrByzzWvOzsmi12mBjlZ0moGXfB1UGgwIkuHzqgYQy5rvigEiDwoJCNbg86oGEMoLEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFovCgMY4ggaDAoDGOAIEgMY3ggYARoMCgMY4AgSAxjeCBgCGgwKAxjgCBIDGN4IGAM="},{"b64Body":"ChAKCQjW4POqBhDQCxIDGN4IEgIYAxjerO0UIgIIeIIDOgoMCgMY3ggSAxjfCBhkEhcKAxjiCBIDGN4IGgMY3wgiAgECKgIIARoRCgMY4QgSAxjeCBoDGN8IIGQ=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw3I6teFAxSJ2mmG/D0qo/QBgqqcKv69KjNIaH9zpD+/Nt22RBdSK3oj42PXfbF/w6GgwIkuHzqgYQu6CM8gIiEAoJCNbg86oGENALEgMY3ggw3qztFFIuCgkKAhgDEPzG0AEKCQoCGGIQ1JCJJAoKCgMYoAYQ7IGBBAoKCgMY3ggQu9naKQ=="},{"b64Body":"ChAKCQjX4POqBhDgCxIDGN4IEgIYAxje5PwUIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo6CAzkKDQoDGN4IEgMY3wgYyAESFAoDGOIIEgMY3ggaAxjfCCIBAyoAGhIKAxjhCBIDGN4IGgMY3wggrAI=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwo4Xg1RgncqYRl4cxKAgG++jLv/NeLVjqpbV66CQSdzGVpOUMc//3YqpZcNL29WcuGgwIk+HzqgYQw/v0lQEiEAoJCNfg86oGEOALEgMY3ggqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMMT+mRRSLgoJCgIYAxCUg9IBCgkKAhhiEPbg8SIKCgoDGKAGEP6Y8AMKCgoDGN4IEIf9syg="},{"b64Body":"ChAKCQjX4POqBhD0CxIDGN4IEgIYAxiL0vcUIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo6CAzIKCgoDGN4IEgMY3wgSEwoDGOIIEgMY3ggaAxjfCCoCCAEaDwoDGOEIEgMY3ggaAxjfCA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw13j3GGDTUfOV06FL8M/1JlQPQgADI85HGKRU+BL+nmoRdprZgIUtWQpbsfijO2qhGgwIk+HzqgYQy6+1lQMiEAoJCNfg86oGEPQLEgMY3ggqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMNzMtBRSLgoJCgIYAxC2xNEBCgkKAhhiEMKMoiMKCgoDGKAGEMDI9QMKCgoDGN4IELeZ6Sg="}]},"duplicateKeysAndSerialsInSameTxnDoesntThrow":{"placeholderNum":1123,"encodedItems":[{"b64Body":"Cg8KCQjc4POqBhCSDBICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIJ05h9uiWO/lkrRSfaktrDfgmHJkfdKz4r/Lk/o/yNjFEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGOQIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDKjYWKZrjTEHRBSUsy6MA3itjIUGohr1O+PuSXIiSiej//8S6++Cj+lVkRpbyRasIaDAiY4fOqBhDDtNyXASIPCgkI3ODzqgYQkgwSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjkCBCAkN/ASg=="},{"b64Body":"Cg8KCQjc4POqBhCUDBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIFR+iJsjKKtf/YJn4Y5MyGjezD27SUepbuZlsI3XLqGYEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGOUIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBhfBkZmgdvbwVMSL5vUZ5++8tvtTmaZHlrvWNAp7Tp9YNxC9uo6WZc5c2rehRA8rIaDAiY4fOqBhDDxbz+AiIPCgkI3ODzqgYQlAwSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjlCBCAkN/ASg=="},{"b64Body":"Cg8KCQjd4POqBhCWDBICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIB8uD/lOL+2MB+o5ASZNoQIN+B6tXEWalERUVN1STRYWEICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGOYIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjB8Q2FZO/fP9TH+MlsZ/LJGriP3nQUeWJjzUI0kHN/NzeBchk1UMYaeY/qstOsgSdQaDAiZ4fOqBhDTs9CIASIPCgkI3eDzqgYQlgwSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMY5ggQgMCoypo6"},{"b64Body":"Cg8KCQjd4POqBhCYDBICGAISAhgDGJvmqekCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVQKCGZ1bmdpYmxlEghBSktMVlNVSCAKKgMY5ghSIhIg6nDXSlw+3kOvy2U5428qZzOjwAVHGzIjbOd3p97gIolqDAiZr86uBhCIhbj2ApABAZgB6Ac=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGOcIEjC8E73huE9gCzAWrInWRn4Ex8wWRV28UYb0WWRqVYAQrK/9On79ABdtFV6u789VI2gaDAiZ4fOqBhDrpb2JAyIPCgkI3eDzqgYQmAwSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg4KAxjnCBIHCgMY5ggQFHIKCgMY5wgSAxjmCA=="},{"b64Body":"Cg8KCQje4POqBhCaDBICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghJSEZLS0dQTCoDGOYIUiISIOpw10pcPt5Dr8tlOeNvKmczo8AFRxsyI2znd6fe4CKJagwImq/OrgYQ2MycjQGIAQGQAQGYAQo=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGOgIEjAED3ffP4CbhY7eG3YOHXNYQw+5eKYP1L+PUwd8Ic7zeaIdxB9PR69Y+p2x2qgZBQkaDAia4fOqBhDD66yTASIPCgkI3uDzqgYQmgwSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxjoCBIDGOYI"},{"b64Body":"Cg8KCQje4POqBhCgDBICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGOQIEgMY5wg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwI2uOnK0hT1JZ4Xuc6xgs1vlp1WYn1ZH3cYzaGAodyksdI4NKO4lDe1sZsA4C06EjGgwImuHzqgYQs7DnkwMiDwoJCN7g86oGEKAMEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjf4POqBhCmDBICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGOQIEgMY6Ag=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwlw/tzNGPJjmA8KDwpYr9DAfezxWdAX/cyL5d2oxabp0Kkk2BI+AODZ8ykBOHr28SGgwIm+HzqgYQy4W6ngEiDwoJCN/g86oGEKYMEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjf4POqBhCsDBICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGOgIGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMGnROBOamiEzvwq//quRK6kRq0sjl0iU7oSmGvELCdRV7qML1gGc+c9XieRt1dt1exoMCJvh86oGEMPGr54DIg8KCQjf4POqBhCsDBICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaLAoDGOgIGgsKAhgAEgMY5ggYARoLCgIYABIDGOYIGAIaCwoCGAASAxjmCBgD"},{"b64Body":"Cg8KCQjg4POqBhC0DBICGAISAhgDGO/KUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOqgIICgMY5wgQ9AM=","b64Record":"CiMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1j+AxIwR+NfXAuHRBhZdsQ7kiqt8DUnT0Ju/YR3HxmbFCw6+FoAwTu6o1Bsw14C6tU4q9jwGgwInOHzqgYQo8rBqAEiDwoJCODg86oGELQMEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoPCgMY5wgSCAoDGOYIEOgH"},{"b64Body":"Cg8KCQjg4POqBhC4DBICGAISAhgDGID+PCICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOcjESLwoDGOgIGgwKAxjmCBIDGOQIGAEaDAoDGOYIEgMY5AgYAhoMCgMY5ggSAxjkCBgD","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwXBOpHzLZ0UiZWLLhlj7TZNwXqECDK2xc/AOL7MAqHpOIUj37cAhVLlhJiaoE1Z8EGgwInOHzqgYQg9P1qAMiDwoJCODg86oGELgMEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFovCgMY6AgaDAoDGOYIEgMY5AgYARoMCgMY5ggSAxjkCBgCGgwKAxjmCBIDGOQIGAM="},{"b64Body":"ChAKCQjh4POqBhC+DBIDGOQIEgIYAxjppIYUIgIIeIIDHQoMCgMY5AgSAxjlCBhkCg0KAxjkCBIDGOUIGMgB","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwC8bJzfLlaQKnBmQ9I3x6vAdTG7xUHrjErqiN2aNywXrfENY5Elqnr9XumFtTEPozGgwIneHzqgYQ86axswEiEAoJCOHg86oGEL4MEgMY5Agw6aSGFFIuCgkKAhgDEPCPzQEKCQoCGGIQstrSIgoKCgMYoAYQsN/sAwoKCgMY5AgQ0cmMKA=="},{"b64Body":"ChAKCQjh4POqBhDGDBIDGOQIEgIYAxjw78UUIgIIeIIDNwoNCgMY5AgSAxjlCBisAhoSCgMY5wgSAxjkCBoDGOUIIKwCGhIKAxjnCBIDGOQIGgMY5Qgg9AM=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwqAjfrIyyccwW1j3/Z/ZZNDRSrf6xiJlE8tUoOkwDNXtW2MZuzt0jfw+Onh8QfC/qGgwIneHzqgYQ6+X6swMiEAoJCOHg86oGEMYMEgMY5AgwhY+mFFIuCgkKAhgDEPDozwEKCQoCGGIQvsmJIwoKCgMYoAYQ3OvyAwoKCgMY5AgQiZ7MKA=="},{"b64Body":"ChAKCQji4POqBhDODBIDGOQIEgIYAxiz2NEVIgIIeIIDgwEKDQoDGOQIEgMY5QgY9AMSGAoDGOgIEgMY5AgaAxjlCCIFAQICAgIqABIWCgMY6AgSAxjkCBoDGOUIIgEBKgIIARIUCgMY6AgSAxjkCBoDGOUIIgECKgASFgoDGOgIEgMY5AgaAxjlCCIBAyoCCAEaEgoDGOcIEgMY5AgaAxjlCCDYBA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwi4SEwaBlqP02C7S+mgIfg5WBkUg8t7Y0OuM/oecVWfvpjjSR3WXhTskbm7hYU2TmGgwInuHzqgYQ86PD1wEiEAoJCOLg86oGEM4MEgMY5AgwhNOOFVIuCgkKAhgDEJaO2gEKCQoCGGIQ9Lu8JAoKCgMYoAYQ/tuGBAoKCgMY5AgQh6adKg=="}]},"ScheduledCryptoApproveAllowanceWorks":{"placeholderNum":1129,"encodedItems":[{"b64Body":"Cg8KCQjm4POqBhDsDBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIDeU2zwUgoN19NZdR4k8tnG7yNWW48OzXJzd4lkiTw/JEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGOoIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAKsjIC+DP6XiDt1zLiC9c1HeWeNjUCaTY5y/ts5zuPO5DlWa9XJ4n6sGvZePNcn2UaDAii4fOqBhCbwPmaAyIPCgkI5uDzqgYQ7AwSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxjqCBCAqNa5Bw=="},{"b64Body":"Cg8KCQjn4POqBhDuDBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIGteTTVFUbrXrom/knQ10QI11IiyXg1XT2SPuda754kbEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGOsIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjA1CYvYtMj9RcCu7mLeGydLfT2knZ40Cmdyw8hfNW18q8QidnA+QUhsJ0E/O6+s3jgaDAij4fOqBhCb2Je+ASIPCgkI5+DzqgYQ7gwSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjrCBCAkN/ASg=="},{"b64Body":"Cg8KCQjn4POqBhDwDBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIIxyg89WoJL+urDMcUVfuXpzUXqrLllFqPHX8m9taKHJEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGOwIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCXS7pnwb0cePU+3IfMMWSzz5t/3bYF+wzkTVD9Jpu1fAabwirNdjJdmmjqD138wlMaDAij4fOqBhDT3q+kAyIPCgkI5+DzqgYQ8AwSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxjsCBCAkN/ASg=="},{"b64Body":"Cg8KCQjo4POqBhDyDBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIAGP27rx3HBodLqumbmGrMK814Jw1dUNJ+h9a1BBcX5REICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGO0IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDI4vlnQRmmer/YyjOSz5RVxkJjM9ND5xnpP3xt41+IEwLbC6+5dErwH1Aa5Ep3MkgaDAik4fOqBhDj08bIASIPCgkI6ODzqgYQ8gwSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxjtCBCAqNa5Bw=="},{"b64Body":"Cg8KCQjo4POqBhD0DBICGAISAhgDGMae0hUiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloyCiISIEeqZTyVL/Pc5ZATOUmD6CfFVZaTMERBOCOTOuNkOYo7EIDC1y9KBQiAztoDcAE=","b64Record":"CiUIFhIDGO4IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAc9VxvkjyOHktVaYuDoBI4QxKRxXEeh+WpIcKOso+uLwzCsFt5OCaXiis4Kh84gRcaDAik4fOqBhD7g5ewAyIPCgkI6ODzqgYQ9AwSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIXCgkKAhgCEP+Dr18KCgoDGO4IEICEr18="},{"b64Body":"Cg8KCQjp4POqBhD2DBICGAISAhgDGLzj4ugCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qATEKCGZ1bmdpYmxlEghVRE1BUExEWCCIJyoDGOoIagwIpa/OrgYQuJWstAGQAQGYAZBO","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGO8IEjAq+rfZDZOdUzrqtTpRPV8jyTqKgd+o+Ip1beq7/T+qynNRob3IsNNSEq1DFylnKNoaDAil4fOqBhDjxqS5ASIPCgkI6eDzqgYQ9gwSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg8KAxjvCBIICgMY6ggQkE5yCgoDGO8IEgMY6gg="},{"b64Body":"Cg8KCQjp4POqBhD4DBICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghPRE9IWEJLQyoDGOoIUiISII2YEDxWC8N2WowLzcoFBxfpL3JG5QKo87FmRAPrcTKmagwIpa/OrgYQwMyPqAOIAQGQAQGYAQw=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGPAIEjAkcZesAzvMWAxTA6BGNcSFftbi07W1sc+KOBML8BtEe2rtWaqRy/nML5OcRPQ+eQ4aDAil4fOqBhCrjPG5AyIPCgkI6eDzqgYQ+AwSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxjwCBIDGOoI"},{"b64Body":"Cg8KCQjq4POqBhD6DBICGAISAhgDGJqYttEFIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAUkKEnRva2VuV2l0aEN1c3RvbUZlZRIIVEtWWURSSFQg6AcqAxjqCGoMCKavzq4GEJicq74BkAEBmAGIJ6oBCwoECAoSABoDGOoI","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGPEIEjAEfcUq4+62wa8jtMRUERdTkmkrbd02xxe9GYugNOUoJbPJzRt9Iq+uj39y/bgTVX8aDAim4fOqBhDD58TDASIPCgkI6uDzqgYQ+gwSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg8KAxjxCBIICgMY6ggQ0A9yCgoDGPEIEgMY6gg="},{"b64Body":"Cg8KCQjq4POqBhCADRICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGPAIGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMKrQqTWMj+DylhDU9HTH45GJYd0quLvx58cIxONsjVOmvJ1dlxOYmx0wuZ8/vO8fQxoMCKbh86oGEKu+6cQDIg8KCQjq4POqBhCADRICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaLAoDGPAIGgsKAhgAEgMY6ggYARoLCgIYABIDGOoIGAIaCwoCGAASAxjqCBgD"},{"b64Body":"Cg8KCQjr4POqBhCIDRICGAISAhgDGJuqziEiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICFAoDGOsIEgMY7wgSAxjwCBIDGPEI","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwdjziZpxqshwfw3dRixW0WxMNEia3KF6Kj9CIcfI/f4yK++tiWARu/ZmCLYDlO1e7GgwIp+HzqgYQo+HuzgEiDwoJCOvg86oGEIgNEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjr4POqBhCODRICGAISAhgDGJuqziEiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICFAoDGO0IEgMY7wgSAxjwCBIDGPEI","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw6rX37JxcQU3DD3HZ6nWI+6y66PZFdkq8jVYXzt2Eq0QxnRjvqKVG2LrV2O9ODF5NGgwIp+HzqgYQ+5CJzwMiDwoJCOvg86oGEI4NEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjs4POqBhCQDRICGAISAhgDGObhwQIiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnJlEhkKAxjvCBIICgMY6ggQzw8SCAoDGOsIENAPEi8KAxjwCBoMCgMY6ggSAxjrCBgBGgwKAxjqCBIDGOsIGAIaDAoDGOoIEgMY6wgYAxIXCgMY8QgSBwoDGOoIEB0SBwoDGOsIEB4=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwNkfd1e3bi8ImYgRC51MKH77HULp5duI5fRz9VR51yGrBFXxnrjS0JH1VFll7/7O2GgwIqOHzqgYQ+++K2AEiDwoJCOzg86oGEJANEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoZCgMY7wgSCAoDGOoIEM8PEggKAxjrCBDQD1ovCgMY8AgaDAoDGOoIEgMY6wgYARoMCgMY6ggSAxjrCBgCGgwKAxjqCBIDGOsIGANaFwoDGPEIEgcKAxjqCBAdEgcKAxjrCBAe"},{"b64Body":"Cg8KCQjs4POqBhCTDRICGAISAhgDGIn6uAIiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjtICfgp8CIDIr6AlEiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCUQoQCgMY6wgSAxjsCBiAlOvcAxIWCgMY8AgSAxjrCBoDGOwIIgMBAgMqABoSCgMY7wgSAxjrCBoDGOwIINwLGhEKAxjxCBIDGOsIGgMY7AggZA==","b64Record":"CjgIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD2IDGPIIahEKCQjs4POqBhCTDRICGAIYARIw+bAFjhdC/hwCkLv2C/EqPJ8Mv76cpZ7ipYYA1KhBUJtnh2YddpOYhp/E2Tuc/C4uGgwIqOHzqgYQg+qH2AMiDwoJCOzg86oGEJMNEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"ChAKCQjt4POqBhCZDRIDGOwIEgIYAxiNxjwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnIXEhUKAxjwCBoOCgMY6wgSAxjuCBgDIAE=","b64Record":"CiEIpAIqHAoMCAEQDBoGCICumaQPEgwIARAPGgYIgK6ZpA8SMBpLILNbgzb5DBpi5LvTLZJ79RVgHPpH22+Jkj7e1rJxm+9pldLatfxVgOIR5TMDBhoMCKnh86oGEPO5mv4BIhAKCQjt4POqBhCZDRIDGOwIKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjjCNxjxSKgoICgIYAxDi1AQKCAoCGGIQjOVoCgkKAxigBhCs0gsKCQoDGOwIEJmMeQ=="},{"b64Body":"ChAKCQjt4POqBhCbDRIDGOwIEgIYAxjrnzYiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnIdEhsKAxjvCBIJCgMY6wgQYxgBEgkKAxjtCBBkGAE=","b64Record":"CiEIpAIqHAoMCAEQDBoGCICumaQPEgwIARAPGgYIgK6ZpA8SMN1Xl8qIPXOxkpMIhOZTAhTPlOCk18MoUk0joxm1uPLqgWDQw4a6n/mBz+jfQ9fw1RoLCKrh86oGEJOB2AciEAoJCO3g86oGEJsNEgMY7AgqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMOufNlIqCggKAhgDEPDjBAoICgIYYhCcrF0KCQoDGKAGEMqvCgoJCgMY7AgQ1b9s"},{"b64Body":"ChAKCQju4POqBhCdDRIDGOwIEgIYAxiipggiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnIgCh4KDQoDGO0IEICU69wDGAEKDQoDGOsIEP+T69wDGAE=","b64Record":"CiEIpAIqHAoMCAEQDBoGCICumaQPEgwIARAPGgYIgK6ZpA8SMJwRe2JdCgAmlzgXt1oTBDbeIbhvUBfZGyXBC3SdKpz5/685pECKKWSPCccSrWMGUhoMCKrh86oGEOPa14cCIhAKCQju4POqBhCdDRIDGOwIKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjjCipghSKQoHCgIYAxCkNgoICgIYYhCexw4KCQoDGKAGEILPAQoJCgMY7AgQw8wQ"},{"b64Body":"Cg8KCQjv4POqBhCjDRICGAISAhgDGLnwMiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KO4gIFCgMY8gg=","b64Record":"CjMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD2oRCgkI7ODzqgYQkw0SAhgCGAESMMv84gyyyShydffPY8cT0NQ8ukOkR/xxRkzYS+/oaP+F8at5c8cRfL4QiSgIbvS7qxoLCKvh86oGEKORpREiDwoJCO/g86oGEKMNEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"ChEKCQjs4POqBhCTDRICGAIYARiAyK+gJTIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo6CA1EKEAoDGOsIEgMY7AgYgJTr3AMSFgoDGPAIEgMY6wgaAxjsCCIDAQIDKgAaEgoDGO8IEgMY6wgaAxjsCCDcCxoRCgMY8QgSAxjrCBoDGOwIIGQ=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwYttYQCj+DhZDfbC0g2pZXvOeFr9KAPQ/NJYgQsWEHvG+Jq3K3JeO9cqtVpHJM5XiGgsIq+HzqgYQp5GlESIRCgkI7ODzqgYQkw0SAhgCGAEqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBiAxjyCA=="},{"b64Body":"ChAKCQjv4POqBhClDRIDGOwIEgIYAxiNxjwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnIXEhUKAxjwCBoOCgMY6wgSAxjuCBgDIAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwSG3xBcVdhxceMVBvK/o1kuybrfG67fENKN/YnVilRfiZtOKi5IrRpDsoKU/xX969GgwIq+HzqgYQ882BkgIiEAoJCO/g86oGEKUNEgMY7AgqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMI3GPFIqCggKAhgDEOLUBAoICgIYYhCM5WgKCQoDGKAGEKzSCwoJCgMY7AgQmYx5WhMKAxjwCBoMCgMY6wgSAxjuCBgDcgoKAxjwCBIDGO4I"},{"b64Body":"ChAKCQjw4POqBhCnDRIDGOwIEgIYAxjrnzYiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnIdEhsKAxjvCBIJCgMY6wgQYxgBEgkKAxjtCBBkGAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwsR9J6DSegR7I+8FemkiQz1doYfFAGwe56l2+QeC74fltwW0HN6XUbLMJe011Tg5DGgsIrOHzqgYQs8GRGyIQCgkI8ODzqgYQpw0SAxjsCCogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo4w6582UioKCAoCGAMQ8OMECggKAhhiEJysXQoJCgMYoAYQyq8KCgkKAxjsCBDVv2xaFwoDGO8IEgcKAxjrCBBjEgcKAxjtCBBk"},{"b64Body":"ChAKCQjw4POqBhCpDRIDGOwIEgIYAxiipggiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnIgCh4KDQoDGO0IEICU69wDGAEKDQoDGOsIEP+T69wDGAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwPTfcOUF6wLqP/RN2SQqC8wIbgZvS6CYQf3xZWF5T0HW2jGZ+s1TTik7y4aXYWBv6GgwIrOHzqgYQu/mgnAIiEAoJCPDg86oGEKkNEgMY7AgqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMKKmCFJDCgcKAhgDEKQ2CggKAhhiEJ7HDgoJCgMYoAYQgs8BCgsKAxjrCBD/k+vcAwoJCgMY7AgQw8wQCgsKAxjtCBCAlOvcAw=="}]},"canDeleteAllowanceFromDeletedSpender":{"placeholderNum":1139,"encodedItems":[{"b64Body":"Cg8KCQj04POqBhC5DRICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIJlU9j8RUQ36Mo/QyyY62eynazyxYG5NBh83UpLI/MAuEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGPQIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjB6zfoPWP19YOmR81/87iKtTwNrkFXUiCMDb+CXTXWHgEFWM7O7P+pEr/BU3+zIOe8aDAiw4fOqBhCT7P3HAyIPCgkI9ODzqgYQuQ0SAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxj0CBCAkN/ASg=="},{"b64Body":"Cg8KCQj14POqBhC7DRICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISINP6FZUq9VJzNKhafF4AUdONU058tSJCMPhnVbYB2a6UEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGPUIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDr7JA/8eduPhdX4rmMRazHRlFb3HrENBslO9tJpEvis+GHC0S92b2ePwRZGCqA2IwaDAix4fOqBhCz0eDrASIPCgkI9eDzqgYQuw0SAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxj1CBCAkN/ASg=="},{"b64Body":"Cg8KCQj14POqBhC9DRICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIPG9qGz50tqfTAB7bc1ECpkvi5BzmXhhUoPzX/pf9qv8EICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGPYIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBKFXG/Tcdwd6B2Hg56hEt7d4D7gSlN6MaY3wEo+SJwVFmM6tLJY4MEiR1iukjA+ZIaDAix4fOqBhCjkO7RAyIPCgkI9eDzqgYQvQ0SAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMY9ggQgMCoypo6"},{"b64Body":"Cg8KCQj24POqBhC/DRICGAISAhgDGJvmqekCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVQKCGZ1bmdpYmxlEghIWURWWk5JSSAKKgMY9ghSIhIg9IT3olNLLem/2Gcd2cBZLG29xXMQCSjk1E+f0/DBSGdqDAiyr86uBhDYxc/eAZABAZgB6Ac=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGPcIEjBrA2Io8QoNYkkN07IAkv05yg8ZVAT04DX5YdtZ4lV9+DqCTmWa5uCsHQ/OdymK9S8aDAiy4fOqBhDbncH1ASIPCgkI9uDzqgYQvw0SAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg4KAxj3CBIHCgMY9ggQFHIKCgMY9wgSAxj2CA=="},{"b64Body":"Cg8KCQj24POqBhDBDRICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVcKC25vbkZ1bmdpYmxlEghPQkpGSURYTSoDGPYIUiISIPSE96JTSy3pv9hnHdnAWSxtvcVzEAko5NRPn9PwwUhnagwIsq/OrgYQuLa10QOIAQGQAQGYAQo=","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGPgIEjBROQoeHRX1W5hXM+U967GQ7Xc33+PVzCicwFqQXGA4d8IuLcFB/X/3aYbt5qw4fwUaDAiy4fOqBhDT+6TcAyIPCgkI9uDzqgYQwQ0SAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAcgoKAxj4CBIDGPYI"},{"b64Body":"Cg8KCQj34POqBhDHDRICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGPQIEgMY9wg=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwUIBR1Vwsa019rAZOyAKhvi+deHkpNdV4mAyJW/hCa8CbCXmIV5uUCNo7oRgcwAoIGgwIs+HzqgYQ0/+f/wEiDwoJCPfg86oGEMcNEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQj44POqBhDNDRICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGPQIEgMY+Ag=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwHggLlqLQGRAuwxhcx7dOBaJ43mu9Q4dp//iFWdPwDJdLPzrRTjCVtUWZts0GetPlGgsItOHzqgYQu+7FCSIPCgkI+ODzqgYQzQ0SAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQj44POqBhDTDRICGAISAhgDGO/KUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOqgIICgMY9wgQ9AM=","b64Record":"CiMIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1j+AxIwf6QLQt5OxtJLM0Q+6y2mUhHkMJiJcHJxCXRmKp0Kf1z03qf2QwZjNB9Y0AmjZtwmGgwItOHzqgYQm5/DiQIiDwoJCPjg86oGENMNEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoPCgMY9wgSCAoDGPYIEOgH"},{"b64Body":"Cg8KCQj54POqBhDbDRICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGPgIGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMBDAnWiLJSWy3O3NyJ0MiT8TM0MubWYOkpNtX+saDkqCVjBJrffmPRqRi3ZlwIUKQhoLCLXh86oGEOPmwRMiDwoJCPng86oGENsNEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFosCgMY+AgaCwoCGAASAxj2CBgBGgsKAhgAEgMY9ggYAhoLCgIYABIDGPYIGAM="},{"b64Body":"ChAKCQj54POqBhDjDRIDGPQIEgIYAxiL0vcUIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo6CAzYKDAoDGPQIEgMY9QgYZBITCgMY+AgSAxj0CBoDGPUIKgIIARoRCgMY9wgSAxj0CBoDGPUIIAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw4unPbcsKdO33m/0sx/d4iV0MZSZ+/ABW/i6DBHCBwAtBTSWTA3hjlJZVBW74RVeKGgwIteHzqgYQk+XUkwIiEAoJCPng86oGEOMNEgMY9AgqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMIvS9xRSLgoJCgIYAxC2xNEBCgkKAhhiEP7imiQKCgoDGKAGEOL8ggQKCgoDGPQIEJWk7yk="},{"b64Body":"Cg8KCQj64POqBhDnDRICGAISAhgDGMHongMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjmIJCgIYAhIDGPUI","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwE7PDMl6WLTiFrhlW2XXRMht90RT5je8s7gkh+pa1HlIcTQJ58eTYwBaWpMc8ry4OGgsItuHzqgYQg7K/HSIPCgkI+uDzqgYQ5w0SAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEICQ38BKCgsKAxj1CBD/j9/ASg=="},{"b64Body":"ChAKCQj64POqBhDtDRIDGPQIEgIYAxjzkO8TIgIIeIIDDAoKCgMY9AgSAxj1CA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwuXYUcR54ONb7t3++DJDHkXSjbcj7PTS4uiTcLO3up7oK4RJqFBKJnPx2M8jg2DanGgwItuHzqgYQg7aCnQIiEAoJCPrg86oGEO0NEgMY9AgwgrDPE1IuCgkKAhgDEMz1ygEKCQoCGGIQzOzxIQoKCgMYoAYQ7P3hAwoKCgMY9AgQg+CeJw=="},{"b64Body":"ChAKCQj74POqBhD1DRIDGPQIEgIYAxjvnfUTIgIIeIIDERoPCgMY9wgSAxj0CBoDGPUI","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwGIC6+gamz2EvWlao90Vfvau1yLR7Wk7PG//h2QYbRewLLKFs0SnjOsgUQEyOFh5dGgsIt+HzqgYQ46LyJiIQCgkI++DzqgYQ9Q0SAxj0CDCr+dETUi4KCQoCGAMQ+pTLAQoJCgIYYhCUofYhCgoKAxigBhDIvOIDCgoKAxj0CBDV8qMn"},{"b64Body":"ChAKCQj84POqBhCNDhIDGPQIEgIYAxjG24MUIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo6CAxMSEQoDGPgIEgMY9AgaAxj1CCoA","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwnkZb02tXpbqyNYMQY64ZrjTMnFlLGhRvmoK96pJg2EQqnVSVg8cNII6/RBdYl/5fGgsIuOHzqgYQ8+HcLyIQCgkI/ODzqgYQjQ4SAxj0CCogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo4w2/rjE1IuCgkKAhgDEMDwzAEKCQoCGGIQnpGVIgoKCgMYoAYQ2PPlAwoKCgMY9AgQtfXHJw=="}]},"cannotPayForAnyTransactionWithContractAccount":{"placeholderNum":1145,"encodedItems":[{"b64Body":"Cg8KCQiA4fOqBhCfDhICGAISAhgDGP7LzSwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjooBjwESDAi8r86uBhDgwYOKAhptCiISICixqG13lzkvP0hCIyt5BoSY0nFS2hj5bGzytBL5FCdoCiM6IQMDbJKkO7RbeQlWOxqJmdTz6wlj3zZYSdRvE86jQN5OEgoiEiBh6/biFNaVXd1nPGwULn5RDkQWbZjz9eGYb+v4I5ob3SIMSGVsbG8gV29ybGQhKgAyAA==","b64Record":"CiUIFhoDGPoIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAPCSErx+Cr9+3AG0tYh7Xq1Ilq4lmSeGawvSLmOZCasyLKRnQZ5xz5DpVOSAH1KNoaDAi84fOqBhCDlKKkAiIPCgkIgOHzqgYQnw4SAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQiB4fOqBhCjDhICGAISAhgDGIu5+SwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjpoBpgEKAxj6CCKeATYwODA2MDQwNTI2MDNlODA2MDExNjAwMDM5NjAwMGYzZmU2MDgwNjA0MDUyNjAwMDgwZmRmZWEyNjU2MjdhN2E3MjMxNTgyMDRiZTFjMTBiOTdmMmU3ZTAwMDc5MTE1MjAwYzIxZWJmMmMxNWM4ZWRhNjY1OTY2ODUxNTBjZDZmNTM1NjQ2NDY2NDczNmY2YzYzNDMwMDA1MTEwMDMy","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw0g6mfXLt5FNlaFWXAObA9As2wd1rLkIZjzFOIL5dxK1z1jufKYSrV/Dke5eYA8SRGgsIveHzqgYQq46ORyIPCgkIgeHzqgYQow4SAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQiB4fOqBhClDhICGAISAhgDGJb7rp0CIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5CSwoDGPoIGiISICqSpS08l/XE7oIbWUmK4bgC6SVJztQLot4EMlaI8XBTIJChDyiAyK+gJUIFCIDO2gNSAFoAagtjZWxsYXIgZG9vcg==","b64Record":"CiUIFiIDGPsIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAj1q/bVr49CDnRcmoO99C0vKAvjkOByFDYr0BNbgTQepeAmT9ufMTeQzHeQOK7SsIaDAi94fOqBhCb1+utAiIPCgkIgeHzqgYQpQ4SAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjjDA2eIGQvICCgMY+wgSPmCAYEBSYACA/f6iZWJ6enIxWCBL4cELl/Ln4AB5EVIAwh6/LBXI7aZllmhRUM1vU1ZGRmRzb2xjQwAFEQAyIoACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACjAmgw6Axj7CEoWChQAAAAAAAAAAAAAAAAAAAAAAAAEe3IHCgMY+wgQAVIkCgoKAhgCEP/CpM5KCgkKAhhiEICzxQ0KCwoDGPsIEICQ38BK"}]},"TransferringMissingNftViaApprovalFailsWithInvalidNftId":{"placeholderNum":1148,"encodedItems":[{"b64Body":"Cg8KCQiG4fOqBhC2DhICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIP5COgJ/6/U/bg6t0yvZNLhaa1E36niA4DmcXmcrS5CREIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGP0IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCGStkHd+5phvEZJr58yHVs/HBs08SuL/DwPAww4ZNtCiFbt8kywbMqCxsv6O2mp7oaCwjC4fOqBhCznrotIg8KCQiG4fOqBhC2DhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGP0IEICQ38BK"},{"b64Body":"Cg8KCQiG4fOqBhC4DhICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISIF3aFcsPhno2ZzORdloexuK1RSKIZYWDvGP90Do+tmWIEIDIr6AlSgUIgM7aA3AK","b64Record":"CiUIFhIDGP4IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAYAP4efwlYlgkHrrIBNXLhClkMjTskkIROPpXgW3ygQG8m4vMlEoPAXNbwPCPJxp8aDAjC4fOqBhDj4batAiIPCgkIhuHzqgYQuA4SAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxj+CBCAkN/ASg=="},{"b64Body":"Cg8KCQiH4fOqBhC6DhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIKQXOcudqQQpOPbaPEELwQaS/obXniD8tXP7kAyjbnKAEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGP8IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjB4dB3wDwZrelhBe/6Wtx5eaxRBRlX+G7ThBNNMf7yqWG1hU0gJhDmkhSKOXbYGMm0aCwjD4fOqBhCzu782Ig8KCQiH4fOqBhC6DhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGP8IEICQ38BK"},{"b64Body":"Cg8KCQiH4fOqBhC8DhICGAISAhgDGNuZihwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIMAgW9OOj6cChmX9OVlx4W6uUqeuGXBShL4AT8K3vTBcEICglKWNHUoFCIDO2gNwCg==","b64Record":"CiUIFhIDGIAJKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBSxSlJvFMBIS3t/+3koauoSt+Vw2VNilW7bGqVjtFEqtMlOpzrO5DNEsBQZa6NsCAaDAjD4fOqBhDrs963AiIPCgkIh+HzqgYQvA4SAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+/qMqaOgoMCgMYgAkQgMCoypo6"},{"b64Body":"Cg8KCQiI4fOqBhC+DhICGAISAhgDGLb67+gCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAVYKC25vbkZ1bmdpYmxlEghEWEtEQU1HUSoDGIAJUiISILj04hco/kPsgkSnjq7WJt8t8Z4QhlPcWvA8/ZUYpnIfagsIxK/OrgYQqKzDMogBAZABAZgBCg==","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGIEJEjDwOU5s/Wo7ITcXcWFWsHdTtnHs7zrLQ6x+lsqTVUMZNchHKbwUw7u9XuNNsFaXqCYaCwjE4fOqBhDb6vlBIg8KCQiI4fOqBhC+DhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgByCgoDGIEJEgMYgAk="},{"b64Body":"Cg8KCQiI4fOqBhDEDhICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGP0IEgMYgQk=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwo38XAne+bngh76B3jzCazZSQ9xZnF2ywA7sXLnwszHx1sQ8mARFcUkt5CyrX6HXcGgwIxOHzqgYQ+9bGqAIiDwoJCIjh86oGEMQOEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQiJ4fOqBhDKDhICGAISAhgDGKmuihgiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjqoCDgoDGIEJGgFhGgFiGgFj","b64Record":"CicIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1gDcgMBAgMSMFE9UwJ3tvkINByAi8hwvYBCmZI6dkTetNmViYlNOkrkaELd29Z2P21fdcsRNY+tUhoLCMXh86oGENPG10wiDwoJCInh86oGEMoOEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFosCgMYgQkaCwoCGAASAxiACRgBGgsKAhgAEgMYgAkYAhoLCgIYABIDGIAJGAM="}]}}} \ No newline at end of file diff --git a/hedera-node/test-clients/record-snapshots/CryptoCreate.json b/hedera-node/test-clients/record-snapshots/CryptoCreate.json new file mode 100644 index 000000000000..363434982f2b --- /dev/null +++ b/hedera-node/test-clients/record-snapshots/CryptoCreate.json @@ -0,0 +1 @@ +{"specSnapshots":{"createAnAccountEmptyThresholdKey":{"placeholderNum":1001,"encodedItems":[]},"createAnAccountEmptyKeyList":{"placeholderNum":1002,"encodedItems":[]},"createAnAccountEmptyNestedKey":{"placeholderNum":1003,"encodedItems":[]},"createAnAccountInvalidKeyList":{"placeholderNum":1004,"encodedItems":[]},"createAnAccountInvalidNestedKeyList":{"placeholderNum":1005,"encodedItems":[]},"createAnAccountInvalidThresholdKey":{"placeholderNum":1006,"encodedItems":[]},"createAnAccountInvalidNestedThresholdKey":{"placeholderNum":1007,"encodedItems":[]},"createAnAccountThresholdKeyWithInvalidThreshold":{"placeholderNum":1008,"encodedItems":[]},"createAnAccountInvalidED25519":{"placeholderNum":1009,"encodedItems":[]},"SyntaxChecksAreAsExpected":{"placeholderNum":1010,"encodedItems":[]},"usdFeeAsExpected":{"placeholderNum":1011,"encodedItems":[{"b64Body":"Cg8KCQjq9+qqBhDLAhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIG+85WDX4c333E9EvVJ4KdJmiF7jBtjZd91KeIdVx/6eEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGPQHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDW8RAJujUNCvewXadKPtTo4GswEpFcqcRDPSkIpBunf6RopWdbvA43SVwMa8TBLsAaDAim+OqqBhCjnJifASIPCgkI6vfqqgYQywISAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxj0BxCAkN/ASg=="},{"b64Body":"Cg8KCQjq9+qqBhDNAhICGAISAhgDGIKu5dYCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qASYKBXRva2VuEghNV0pQVU5PSyCQTioCGAJqDAimxsWuBhDQ98iLAw==","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGPUHEjBqw/hpCDRcWabnZC16vHuNSbNMLp5u4yquDEzqHJKy3NTziCEneL9o2XUeZCMBADIaDAim+OqqBhCDz7ihAyIPCgkI6vfqqgYQzQISAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg8KAxj1BxIICgIYAhCgnAFyCQoDGPUHEgIYAg=="},{"b64Body":"ChAKCQjr9+qqBhDQAhIDGPQHEgIYAxjjkO8TIgIIeForCiISIG+85WDX4c333E9EvVJ4KdJmiF7jBtjZd91KeIdVx/6eSgUIgM7aAw==","b64Record":"CiUIFhIDGPYHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCXQJ9LpdJXHFte5pMgIj0D1dC+D9wTzUM3Jd4deWSdWjfJD9qBefEW/jh1N1/eY18aDAin+OqqBhDTgs3GASIQCgkI6/fqqgYQ0AISAxj0BzDjkO8TUi4KCQoCGAMQjMuCAQoJCgIYYhDojewiCgoKAxigBhDSyO8DCgoKAxj0BxDFod4n"},{"b64Body":"ChAKCQjr9+qqBhDSAhIDGPQHEgIYAxitmcsUIgIIeFotCiISIG+85WDX4c333E9EvVJ4KdJmiF7jBtjZd91KeIdVx/6eSgUIgM7aA3AB","b64Record":"CiUIFhIDGPcHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjC066qOKOG3aU2NUgYD7AuNdD5Z9Eq1U+jJ1B2eS+RV17LfxTDftLqFFwOVgLSbv8saDAin+OqqBhCLid+uAyIQCgkI6/fqqgYQ0gISAxj0BzCtmcsUUi4KCQoCGAMQ3s2CAQoJCgIYYhDW55EkCgoKAxigBhCm/YEECgoKAxj0BxDZspYp"},{"b64Body":"ChAKCQjs9+qqBhDUAhIDGPQHEgIYAxjClIMbIgIIeFotCiISIG+85WDX4c333E9EvVJ4KdJmiF7jBtjZd91KeIdVx/6eSgUIgM7aA3AK","b64Record":"CiUIFhIDGPgHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBVBeD2qLuwZUB7zKEis+BfvY2qXwhw9qWKhG+UNvV22GAKOGES6TsnO3N40FMxUlcaDAio+OqqBhCb2ZzYASIQCgkI7PfqqgYQ1AISAxj0BzDClIMbUi4KCQoCGAMQ3s2CAQoJCgIYYhDK+NwvCgoKAxigBhDc4qYFCgoKAxj0BxCDqYY2"}]},"createAnAccountWithStakingFields":{"placeholderNum":1017,"encodedItems":[{"b64Body":"Cg8KCQjw9+qqBhD0AhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo3CiISIHuwZHc1ZPczFaMKgRoyn8nQP+xbJEWhcUzXNIXdCJkQEIDIr6AlSgUIgM7aA4ABAIgBAQ==","b64Record":"CiUIFhIDGPoHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAN/FS+7AhaIosf7vYw2s/4fHiBxdL32cPG6O1y50Vm31Uwj1m/Nfci2IbNz14uzOIaDAis+OqqBhCjzp+fAyIPCgkI8PfqqgYQ9AISAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxj6BxCAkN/ASg=="},{"b64Body":"Cg8KCQjx9+qqBhD6AhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo4CiISIEj9OPN9ahrRKS9PIA86uoCPNa5LnAu4SCbFhQZkeaXMEIDIr6AlSgUIgM7aA3oCGAqIAQE=","b64Record":"CiUIFhIDGPsHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAct/HMdbrZW1XqzVxmhy0cb70j4Xxtt18dE4Q6YWNDUcUW30lalm0AcZjo0Cv0l38aDAit+OqqBhDDtvvEASIPCgkI8ffqqgYQ+gISAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxj7BxCAkN/ASg=="},{"b64Body":"Cg8KCQjx9+qqBhCAAxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISIK/v5/AoAqm9x0rO08HtlJsAHfqM2XsMElnhVF1moGJuEIDIr6AlSgUIgM7aA4ABAA==","b64Record":"CiUIFhIDGPwHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjA73rWEpen2Ey0sdPPfdam29op3cht24f9dRY70xw3s+D37EJCg6nx0H1n4j0F2bf8aDAit+OqqBhC7uqjHAyIPCgkI8ffqqgYQgAMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxj8BxCAkN/ASg=="},{"b64Body":"Cg8KCQjy9+qqBhCGAxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo1CiISIK8A+vZ0m8GeBtp5q0DLcwMD3a36Thxmd+O4SHgAU6HsEIDIr6AlSgUIgM7aA3oCGAo=","b64Record":"CiUIFhIDGP0HKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjA3aC0KeU8gWeFmj6iLDpBV5UcAgb4j2Owa3iyjwzEaob2VBL9H/vOgi6NP8M2ZOdoaDAiu+OqqBhDr44PTASIPCgkI8vfqqgYQhgMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxj9BxCAkN/ASg=="}]},"CreateAnAccountWithECDSAAlias":{"placeholderNum":1022,"encodedItems":[]},"CreateAnAccountWithED25519Alias":{"placeholderNum":1023,"encodedItems":[]},"CreateAnAccountWithECKeyAndNoAlias":{"placeholderNum":1024,"encodedItems":[{"b64Body":"Cg8KCQj/9+qqBhC+AxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloyCiM6IQP3UBEFggTRrkpeL7OlPJe57w8XM98EW2m6gVeVO+E2mxCAlOvcA0oFCIDO2gM=","b64Record":"CiUIFhIDGIEIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAldWuM1uLZnrsFvTXKyEDafcLKyg2dvl9efM7aodS0Vku1fd9XhxHmY3C+wEIqt4saCwi7+OqqBhDr1eN9Ig8KCQj/9+qqBhC+AxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/6fWuQcKCwoDGIEIEICo1rkH"}]},"CreateAnAccountWithEDKeyAndNoAlias":{"placeholderNum":1026,"encodedItems":[{"b64Body":"Cg8KCQiD+OqqBhDaAxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIPPou65lQNmAWYs67GjnqHh0tMPMCphz/iodvR1o6lQUEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGIMIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDmLECjCf3HaOvd+D+kE6Lr079NTRZfc1P+mmkoLE8Z2tmA8w3/yASBwS8dQRoEK1QaDAi/+OqqBhCz65KQAiIPCgkIg/jqqgYQ2gMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxiDCBCAqNa5Bw=="}]},"CreateAnAccountWithED25519KeyAndED25519Alias":{"placeholderNum":1028,"encodedItems":[]},"CreateAnAccountWithECKeyAndECKeyAlias":{"placeholderNum":1029,"encodedItems":[{"b64Body":"Cg8KCQiM+OqqBhCABBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloyCiM6IQLClWAyaj9cIhvCT+URtXB7cZLwTe9ENN734cVp2prlHRCAyK+gJUoFCIDO2gM=","b64Record":"CiUIFhIDGIYIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBibamIEtvOfLB7OiGHVsfqvORF77NxjmNplfL1/bdD724ltfR6kcMlUsAeDbpDaAMaCwjI+OqqBhCzhZhJIg8KCQiM+OqqBhCABBICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/4/fwEoKCwoDGIYIEICQ38BK"}]},"createAnAccountWithEVMAddressAliasFromSameKey":{"placeholderNum":1031,"encodedItems":[{"b64Body":"Cg8KCQiQ+OqqBhCWBBICGAISAhgDGNP09xQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlpJCiM6IQKqC0eCbsO1OyI50G3j/0fIxG3UFFbw/dgM5BNL0JLk0hCAyK+gJUoFCIDO2gOSARSNC1IHDlcEjzjzxWaCujfSXF09kg==","b64Record":"CiUIFhIDGIgIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDQErVVcEY/wrQ+5nKy/0O97DILrMszOeWStgFK2f+VrPL5epRAESqRw4pBr6tbn9caDAjM+OqqBhDr98rEAiIPCgkIkPjqqgYQlgQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxiICBCAkN/ASg=="}]},"createAnAccountWithEVMAddressAliasFromDifferentKey":{"placeholderNum":1033,"encodedItems":[{"b64Body":"Cg8KCQiV+OqqBhCwBBICGAISAhgDGNP09xQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlpICiISILFGfh4Xl0M8YnGaRSfGikWjI9SF7HebM9xOMRwHSmLHEIDIr6AlSgUIgM7aA5IBFDm6T7bD51N+NxLAeU+7SQQmMLHh","b64Record":"CiUIFhIDGIoIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAcQGOyS8pIQDJOPFsissvQUgc3HbZQWnkCTttgqD1mYRYtGnxqraOWHSbczsF1X0gaDAjR+OqqBhCzq8nmAiIPCgkIlfjqqgYQsAQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxiKCBCAkN/ASg=="}]},"createAnAccountWithECDSAKeyAliasDifferentThanAdminKeyShouldFail":{"placeholderNum":1035,"encodedItems":[]},"createAnAccountWithEDKeyAliasDifferentThanAdminKeyShouldFail":{"placeholderNum":1036,"encodedItems":[]},"cannotCreateAnAccountWithLongZeroKeyButCanUseEvmAddress":{"placeholderNum":1037,"encodedItems":[{"b64Body":"Cg8KCQii+OqqBhDmBBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlpJCiM6IQLZBEEo3rcQtjdyyqMRLZCwKEUAv/JyNi+rUUWKdDqnFBCAlOvcA0oFCIDO2gOSARQAcTBD6X4aXqxfolZCJH2GtN51YQ==","b64Record":"CiUIFhIDGI4IKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjD0diykJaYpd9WTJJe74hYPAdKGfHoegnTCxsMfJjJ7Ti/0sZmtSpgZnMeisZ654qcaDAje+OqqBhDr1qyrASIPCgkIovjqqgYQ5gQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxiOCBCAqNa5Bw=="}]}}} \ No newline at end of file diff --git a/hedera-node/test-clients/record-snapshots/CryptoDelete.json b/hedera-node/test-clients/record-snapshots/CryptoDelete.json new file mode 100644 index 000000000000..92c7824212c5 --- /dev/null +++ b/hedera-node/test-clients/record-snapshots/CryptoDelete.json @@ -0,0 +1 @@ +{"specSnapshots":{"FundsTransferOnDelete":{"placeholderNum":1001,"encodedItems":[{"b64Body":"Cg8KCQjMsPWqBhClBhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIGlODxhMAKLBvuTG9w0t32dsavvCK4J/rQOV/8I/abg4EICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGOoHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjD1u/MNCK6ORuM+DJgRh68XiJT4Hi6XLsuJfPoNyYWjlTeD260kF+FWhXG4EZBl9+4aDAiIsfWqBhCD37+SAiIPCgkIzLD1qgYQpQYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxjqBxCAqNa5Bw=="},{"b64Body":"Cg8KCQjNsPWqBhCnBhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlorCiISIGfqMZQYXNbym0PyTXQlci6IMWVG8CG1OtgPXzwXw2bvSgUIgM7aAw==","b64Record":"CiUIFhIDGOsHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAOncKRDLkYpGodiF11Y99QFLVYscCPnfxZ1Jpv3pMUADrKbt2jSRYRGCLZakEPbAoaCwiJsfWqBhCj0JI6Ig8KCQjNsPWqBhCnBhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgA="},{"b64Body":"Cg8KCQjNsPWqBhCpBhICGAISAhgDGM/jvAQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjmIKCgMY6wcSAxjqBw==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw6LoeXYSGNkJIrocAiAOWxOKdzpBInnSIDazGCgdQgMbH+TqfZEAvcg/cG010hCOIGgwIibH1qgYQy6qbvQIiDwoJCM2w9aoGEKkGEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SGgoLCgMY6gcQ/6fWuQcKCwoDGOsHEICo1rkH"}]},"CannotDeleteAccountsWithNonzeroTokenBalances":{"placeholderNum":1004,"encodedItems":[{"b64Body":"Cg8KCQjSsPWqBhDBBhICGAISAhgDGMae0hUiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlozCiISICb6fXXrCpKNvpazYtGvCKaAYRYj837zUePtFjFa0H0GEICU69wDSgUIgM7aA3AB","b64Record":"CiUIFhIDGO0HKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBnhOcIHsWMwNB75Pnb1sKtRyUtfhooKgwedElb0dRbbIOy0SgG0kpjR0tla3ywDhwaCwiOsfWqBhCrxe4TIg8KCQjSsPWqBhDBBhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/6fWuQcKCwoDGO0HEICo1rkH"},{"b64Body":"Cg8KCQjSsPWqBhDDBhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIKCPrnvUJd4tN0zqrKblG9YS8JDBTv6h2g9ZRJ+PszONEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGO4HKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDD1pNxf/plWHm6wnuLKn45dqI1W1tKJCa/yiuo/8fiFAREqkCMgvuJxjJJcZKpCXIaDAiOsfWqBhDbv6yUAiIPCgkI0rD1qgYQwwYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxjuBxCAqNa5Bw=="},{"b64Body":"Cg8KCQjTsPWqBhDFBhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIKWCf7gW8yVQnp8X67AXNnWRDYWIFsMZzdh1tvvXUHTQEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGO8HKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjB+yf7ZUSKLcgJBqnPyC5mjtscukXU2GRPjm6A+3g8rsiGFobSEld8QafGgg087GjIaCwiPsfWqBhCTqIMfIg8KCQjTsPWqBhDFBhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/6fWuQcKCwoDGO8HEICo1rkH"},{"b64Body":"Cg8KCQjTsPWqBhDHBhICGAISAhgDGIjXl/sCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAUoKBG1pc2MSCE5KU0ZDWlVHIPQDKgMY7wcyIhIgf8l51GVLCXWgtFBTrhqHL8pQz31tXghV63xPQJgK3ChqDAiP/8+uBhDwjqWNAg==","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGPAHEjB13OwGO/eCMp4sI5p729jFCCWh9NE460BwxWsqGBWMP8fNgKVXvDHLW5Q408NJ2QoaDAiPsfWqBhCjhJqeAiIPCgkI07D1qgYQxwYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg8KAxjwBxIICgMY7wcQ6AdyCgoDGPAHEgMY7wc="},{"b64Body":"Cg8KCQjUsPWqBhDNBhICGAISAhgDGOC2iyAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsICCgoDGO0HEgMY8Ac=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwghN9L4h3uAyjAcFb2oDNsVGx9JWCRuor8NE2MaPXGwj3A6LR126uzPiblXsdr71ZGgsIkLH1qgYQo6uzQSIPCgkI1LD1qgYQzQYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQjUsPWqBhDPBhICGAISAhgDGOufNiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOchsSGQoDGPAHEggKAxjvBxDnBxIICgMY7QcQ6Ac=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwS3DhWYiJQDSDZPeQte6spHsXbieum+z4AJsT1AnNly1oFAV7MrP97xRWp4i4bxfxGgwIkLH1qgYQo6rIwgIiDwoJCNSw9aoGEM8GEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoZCgMY8AcSCAoDGO0HEOgHEggKAxjvBxDnBw=="},{"b64Body":"Cg8KCQjVsPWqBhDRBhICGAISAhgDGM/jvAQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjmIKCgMY7gcSAxjtBw==","b64Record":"CiEIwwEqHAoMCAEQDBoGCICumaQPEgwIARAPGgYIgK6ZpA8SMLFfIOOSeDI01JEwnFNSpD5d1mEAkiOFp+aDI2/Wkaf5OrChe4egQHsDPD8/BKzxjxoLCJGx9aoGEOu2sEwiDwoJCNWw9aoGENEGEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjVsPWqBhDTBhICGAISAhgDGOufNiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOchsSGQoDGPAHEggKAxjtBxDnBxIICgMY7wcQ6Ac=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw0Kcn7Ib3pC0b+BVogacsy9DnyxOryIHwNl5lcwE/L1RcbzfwQ+1+AnKKk1O6HpIEGgwIkbH1qgYQw9HRzAIiDwoJCNWw9aoGENMGEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoZCgMY8AcSCAoDGO0HEOcHEggKAxjvBxDoBw=="},{"b64Body":"Cg8KCQjWsPWqBhDVBhICGAISAhgDGJWVtCAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsoCCgoDGO0HEgMY8Ac=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwmdm66ElmhvmRmYC81AWkOH1fobxcaubC+SSMulF7OtjuFEE5BZTbmBujN9zJ4KTUGgsIkrH1qgYQ07TucCIPCgkI1rD1qgYQ1QYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQjWsPWqBhDXBhICGAISAhgDGOufNiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOchsSGQoDGPAHEggKAxjvBxDnBxIICgMY7QcQ6Ac=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwIgqTDLfDujFky6ta9qIa6Iu5UPSiZpUMO0rDsC/XOtzPDozCK93+/0rTZLgsp1c4GgwIkrH1qgYQi4KW2AIiDwoJCNaw9aoGENcGEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoZCgMY8AcSCAoDGO0HEOgHEggKAxjvBxDnB3IKCgMY8AcSAxjtBw=="},{"b64Body":"Cg8KCQjXsPWqBhDZBhICGAISAhgDGM/jvAQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjmIKCgMY7gcSAxjtBw==","b64Record":"CiEIwwEqHAoMCAEQDBoGCICumaQPEgwIARAPGgYIgK6ZpA8SMIIWFwExqEj7R4QJ+8i6JmoVYMgVvV9WgkPWkajaxQsFyowjr9txyWXoFpABPNd8ORoLCJOx9aoGEPOohXwiDwoJCNew9aoGENkGEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjXsPWqBhDbBhICGAISAhgDGMHongMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjmIJCgIYAhIDGO8H","b64Record":"CiEIxAEqHAoMCAEQDBoGCICumaQPEgwIARAPGgYIgK6ZpA8SMJ/EKQSSw7f1DqpdJKD0ebpZWpvDsTyyoHQj5TgT8DzzM4CjaUAaILNXCLWtCQSAWBoMCJOx9aoGEOPVmOICIg8KCQjXsPWqBhDbBhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgA="},{"b64Body":"Cg8KCQjYsPWqBhDdBhICGAISAhgDGOufNiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOchsSGQoDGPAHEggKAxjtBxDnBxIICgMY7wcQ6Ac=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwhoPLbvgHKrgrqrNCAXJ85kEiI3zPIwvn3GZK8sIiO8rY4i2deWiwgsH1u8pT7oC0GgwIlLH1qgYQ45v+hAEiDwoJCNiw9aoGEN0GEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoZCgMY8AcSCAoDGO0HEOcHEggKAxjvBxDoBw=="},{"b64Body":"Cg8KCQjYsPWqBhDfBhICGAISAhgDGMHongMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjmIJCgIYAhIDGO0H","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwn2m+2u3ARIJBPtJ6ad0z2HpGVKeH7OOQIELSI9iwm+A6pcRpEaRKURbxN5IhxSM7GgwIlLH1qgYQ29vu6gIiDwoJCNiw9aoGEN8GEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SGQoKCgIYAhCAqNa5BwoLCgMY7QcQ/6fWuQc="},{"b64Body":"Cg8KCQjZsPWqBhDjBhICGAISAhgDGKHTUiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOmgIFCgMY8Ac=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw5gMrIcCJcj3JBIzOKdhEwduj/OBr0sCLUnQrNGcjGz7JLdBgBozA6wBW6vk/YwDqGgwIlbH1qgYQs4qq9AIiDwoJCNmw9aoGEOMGEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjasPWqBhDlBhICGAISAhgDGJWVtCAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjsoCCgoDGO8HEgMY8Ac=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw34QjjQvTBF4v7Q5n/GcrF8/w14yoEZRnGAw8OX0558AeLy5X4eX5/nJR0fed7MmPGgwIlrH1qgYQm///lwEiDwoJCNqw9aoGEOUGEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoPCgMY8AcSCAoDGO8HEOcH"},{"b64Body":"Cg8KCQjasPWqBhDnBhICGAISAhgDGMHongMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjmIJCgIYAhIDGO8H","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwqCcBRvSST/Wq68FRrCXMSY8WZKdDq6VKCSlpRuGSTyNs7WCm3I4KskbjHOjCQjBfGgwIlrH1qgYQs4vf/gIiDwoJCNqw9aoGEOcGEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SGQoKCgIYAhCAqNa5BwoLCgMY7wcQ/6fWuQc="}]},"CannotDeleteAlreadyDeletedAccount":{"placeholderNum":1009,"encodedItems":[{"b64Body":"Cg8KCQjfsPWqBhD3BhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIKRLTtcu7DlPZRW9Z/yPQumafDg/dnP5KI5vif8fDs8SEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGPIHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBoJUZgUTSFYVJnGK4ThBJ0xdMXEX8bgb6LHbgjtMu2lCyNMV85qWgPEU3xid2bbfQaCwibsfWqBhC76vUxIg8KCQjfsPWqBhD3BhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/6fWuQcKCwoDGPIHEICo1rkH"},{"b64Body":"Cg8KCQjfsPWqBhD5BhICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIMTqXvTdxkaPZhB+jLMeFEW18B7I1YDTPSwGeuDXh32LEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGPMHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjD+/IAxl0h+5uvlOIjhoJd3X0qwnk3JF+OAlC607uI28ED5hrpAJ43Mp4bmvqhXJRUaDAibsfWqBhDD45mzAiIPCgkI37D1qgYQ+QYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxjzBxCAqNa5Bw=="},{"b64Body":"Cg8KCQjgsPWqBhD7BhICGAISAhgDGM/jvAQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjmIKCgMY8wcSAxjyBw==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwMQpnhh5MtysFafq5FAs79DUEwN+i13GEKFLUFrYB9859PgUTy6cXR0Ta30b4qVtgGgsInLH1qgYQ+8j0PCIPCgkI4LD1qgYQ+wYSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIaCgsKAxjyBxD/p9a5BwoLCgMY8wcQgKjWuQc="}]},"CannotDeleteAccountWithSameBeneficiary":{"placeholderNum":1012,"encodedItems":[{"b64Body":"Cg8KCQjlsPWqBhCNBxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIFaQFga85mNlkbza6czAWSZIYhx2sIyFL4vC4LbJd4d1EICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGPUHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDL0IBOHiq3KDEEz6ZdlS/l1DtX3xx08uAAksTbg6UyzVnABDKpkmCTHoEFeO7eFMsaCwihsfWqBhDT1OFVIg8KCQjlsPWqBhCNBxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/6fWuQcKCwoDGPUHEICo1rkH"}]},"CannotDeleteTreasuryAccount":{"placeholderNum":1014,"encodedItems":[{"b64Body":"Cg8KCQjpsPWqBhCfBxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIFFRcsg78krdk+c5+g53fOubeXaCeHew9nzTmdRRxvXWEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGPcHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAcWuey0h2d9eTQS0fXXt5doapWZPuOMQ9LJNx0sUuV9eugKpHlNwXK9X0gZBECQ2AaDAilsfWqBhCD2unKAiIPCgkI6bD1qgYQnwcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxj3BxCAqNa5Bw=="},{"b64Body":"Cg8KCQjqsPWqBhChBxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIPO2PRzGab4oCDLro5y4YZnGRqapuGptKQXXPVvyno+ZEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGPgHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDU190SUf2mOGbqed+j/ih03sw2lUApdFWgICMo/VK6McQIn82TYOW1sFYBL+BEUh0aCwimsfWqBhCzjqNuIg8KCQjqsPWqBhChBxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/6fWuQcKCwoDGPgHEICo1rkH"},{"b64Body":"Cg8KCQjqsPWqBhCjBxICGAISAhgDGIao8ugCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qATEKD3RvQmVUcmFuc2ZlcnJlZBIIQ0RHRFdBWFUg9AMqAxj3B2oMCKb/z64GEKC5rskC","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGPkHEjCC14DPGz5lvc6D5hQj5PXjpxFZkOvthxuc+0e7w1kzH++ROo7wE4KFq+g4WNW5MCUaDAimsfWqBhDrqbHVAiIPCgkI6rD1qgYQowcSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWg8KAxj5BxIICgMY9wcQ6AdyCgoDGPkHEgMY9wc="},{"b64Body":"Cg8KCQjrsPWqBhClBxICGAISAhgDGM/jvAQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjmIKCgMY+AcSAxj3Bw==","b64Record":"CiEIxAEqHAoMCAEQDBoGCICumaQPEgwIARAPGgYIgK6ZpA8SMM3kLpmvJd7fepq9DDxU/lvKSJjgoSWi6SYYSaD29HXR/e8EgqQ6Z4Tii2PB5xMloBoLCKex9aoGEOO98HciDwoJCOuw9aoGEKUHEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="}]},"CanQueryForRecordsWithDeletedPayers":{"placeholderNum":1020,"encodedItems":[{"b64Body":"Cg8KCQjysPWqBhDFBxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIBANaEWjKNU7x406xsziU1Et/JBiwB89tkltafkhXxe3EICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGP0HKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAtPtaK/c5oDEOHQVzHAXgAW44PzFsB2HxZxnqPjQoWRX6W84fNIZIPcsBMdgJzsuEaCwiusfWqBhDbmsh2Ig8KCQjysPWqBhDFBxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/6fWuQcKCwoDGP0HEICo1rkH"},{"b64Body":"ChAKCQjysPWqBhDHBxIDGP0HEgIYAxiqkAUiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjnITChEKBgoCGGIQAgoHCgMY/QcQAQ==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw0N/+4mnm/23V3/sFymeXMAIoeriSkVaPt0vmjFh+51JozVgP94X+q1I8qXOLzkgaGgwIrrH1qgYQo/bj9gIiEAoJCPKw9aoGEMcHEgMY/QcqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMKqQBVIoCgcKAhgDEJY1CggKAhhiEMjtCAoICgMYoAYQ+H0KCQoDGP0HENWgCg=="},{"b64Body":"Cg8KCQjzsPWqBhDJBxICGAISAhgDGMHongMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjmIJCgIYAhIDGP0H","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw1c0KdrVGEL9aeQOmFok8r2I8P9AP7t2pS8m2wse0zd/9FwlJtvVQGJlJnh7u9O/KGgwIr7H1qgYQ05zGgAEiDwoJCPOw9aoGEMkHEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SGQoKCgIYAhCqh8y5BwoLCgMY/QcQqYfMuQc="}]}}} \ No newline at end of file diff --git a/hedera-node/test-clients/record-snapshots/CryptoUpdate.json b/hedera-node/test-clients/record-snapshots/CryptoUpdate.json new file mode 100644 index 000000000000..e0d1afd8a7de --- /dev/null +++ b/hedera-node/test-clients/record-snapshots/CryptoUpdate.json @@ -0,0 +1 @@ +{"specSnapshots":{"UpdateWithUniqueSigs":{"placeholderNum":1001,"encodedItems":[{"b64Body":"Cg8KCQi/vd+qBhDMAhICGAISAhgDGLOy7SEiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlqsBAqcBCqZBAgCEpQECocCKoQCCAES/wEKIhIgyiDpgRoa8JXZoOES3S/IsDprEzLG+7BJHbI1dEjXGCwKIzohAvSgHG2S2+4hljUslxFrK11HX6yAepsThtNie1Z83EWlCiISID3CaOj7Toy1hCPM74kNu0yKcbZHdYGHTvICaLKHpdVsCiM6IQKcjXpMqgfZ/13LrqSrvuLo3FXFlQTg6qcm1FFH7+Q61QoiEiCkMuV+NNOx+Xao1FOuRfU/Wxj1V3Ia8zh3bfUS4BeFJgojOiED17Tznm8huame52TqpKIJL8hMoA02OLWjvUu00Hv4L7MKIhIgkfklv6xAHZWNRAAKvPWFHAZ7umTC8yhIJpCOjBOXv5EKhwIqhAIIAxL/AQojOiEDNUBIh1w3hOZxJfyHmTvLFniNF9oHTTCUlzQ8Q95CAbsKIhIgRrISlMF+RcTp1VJmZqsZG9NaCCBD+ZVX1MhR5OD+EBEKIzohAvWmsBQ+PFeDotCSQVQls2h2viZ0OkMCoBy7oWK/uovSCiISIMp4PewmoDC8dr+OrUwoz2eNPLB18KWGtdD92jyVlT0dCiM6IQK3mdhPm4iJpyUyR8qZQjM6HVxVGTlDwteao6W4cLIlNgoiEiC8Jiues0CtH0EJV7h9dwgpq4Edi3nIAibAR80ouq8DYQoiEiDKIOmBGhrwldmg4RLdL8iwOmsTMsb7sEkdsjV0SNcYLBCAlOvcA0oFCIDO2gM=","b64Record":"CiUIFhIDGOoHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCllyNwiPjmnbQRTsxK+UGOHa6KA0RKRiZ2RrfS6QZZI7e93fSf3VQzsQVyzI4WMasaCwj7vd+qBhDzlOBSIg8KCQi/vd+qBhDMAhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/6fWuQcKCwoDGOoHEICo1rkH"},{"b64Body":"Cg8KCQi/vd+qBhDSAhICGAISAhgDGOqdJiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOegkSAxjqB2oCCAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwvshiRiARUgaaB/1c47gzwv2lxEbfWVKDacMewoQ9g87yXV9M9/PQ3Rsw+bdtctOFGgwI+73fqgYQ85Py1AIiDwoJCL+936oGENICEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="}]},"UpdateWithOverlappingSigs":{"placeholderNum":1003,"encodedItems":[{"b64Body":"Cg8KCQjEvd+qBhDiAhICGAISAhgDGL2k7SEiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlqsBAqcBCqZBAgCEpQECocCKoQCCAES/wEKIhIgTEnsg3R2jE5fixVvNjp+ZNM1a9XTpcHwhA0NeCAsJ04KIzohAgH9nahglFjpm6iePu1QWiTT6I1Po/rESIaJOKPAJ4dHCiISIAN2pS7WbydQiUBnvjuHdMKJtVYLfocMdfPaDG8STOE6CiM6IQOSxGVDYIKR96y3wOWQFEnT9wvKAQT+G+9WV8VZYG/g2goiEiCGsklYT7V21y/oX5mMLKOXLDQarqiqZodqCi7+5pnP9AojOiEDGiAX1XV6t/3OgQAZFyXDoweovqPPAPHxSoiGhDQZysQKIhIgzzmqqK3vEk3T4fOKxJyc8JmLUoXrykYSnrPTH+JZFDYKhwIqhAIIAxL/AQojOiEDbSEIay7bkqc4vxAAziu3nSFRFn0cE3B0jfNSmKaf9OgKIhIgU6ecJNFZKX27KxAfh6aIopahY2jsDBfqEe3Y2wPm7akKIzohAy2U3kBliO/vStNJ/z869QVdGmnLD0bdBe3iu+spKKNOCiISINnE7GeZi660Xt1oWSHoPUll5nQ3/Pq1d/nk+16q1R9NCiM6IQOBdgPURfqHAAOnoFIzFaLQxNiJI8DsN+sMAPS5wHn+bwoiEiAp2U2BlmwlXJkuAgTBL0b5uIyre5oQwzM28hx8YX3q+goiEiBMSeyDdHaMTl+LFW82On5k0zVr1dOlwfCEDQ14ICwnThCAlOvcA0oFCIDO2gM=","b64Record":"CiUIFhIDGOwHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBe2+34tKUKfCyrxgvaKJkoojLHlzkys4aByuBHIt8ZmGOyNu3A8NcI49MyUKg2Xa8aCwiAvt+qBhDL268pIg8KCQjEvd+qBhDiAhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/6fWuQcKCwoDGOwHEICo1rkH"},{"b64Body":"Cg8KCQjEvd+qBhDoAhICGAISAhgDGOSzHyICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOegkSAxjsB2oCCAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwaTG25b3FQ9uqX2KCeA96jp0PlgrENjfPUlNFY/SPntKp9JvGCjRQIQyThULgEneeGgwIgL7fqgYQi47tkAIiDwoJCMS936oGEOgCEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="}]},"UpdateWithOneEffectiveSig":{"placeholderNum":1005,"encodedItems":[{"b64Body":"Cg8KCQjJvd+qBhD4AhICGAISAhgDGNGsrRUiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlqmBAqWBCqTBAgCEo4ECoQCKoECCAES/AEKIhIgaaCjzZ6IZSAWtzTki1T4EsGj6yNEkw/Z1BrDcKMhHAYKIhIgaaCjzZ6IZSAWtzTki1T4EsGj6yNEkw/Z1BrDcKMhHAYKIhIgaaCjzZ6IZSAWtzTki1T4EsGj6yNEkw/Z1BrDcKMhHAYKIhIgaaCjzZ6IZSAWtzTki1T4EsGj6yNEkw/Z1BrDcKMhHAYKIhIgaaCjzZ6IZSAWtzTki1T4EsGj6yNEkw/Z1BrDcKMhHAYKIhIgaaCjzZ6IZSAWtzTki1T4EsGj6yNEkw/Z1BrDcKMhHAYKIhIgaaCjzZ6IZSAWtzTki1T4EsGj6yNEkw/Z1BrDcKMhHAYKhAIqgQIIAxL8AQoiEiBpoKPNnohlIBa3NOSLVPgSwaPrI0STD9nUGsNwoyEcBgoiEiBpoKPNnohlIBa3NOSLVPgSwaPrI0STD9nUGsNwoyEcBgoiEiBpoKPNnohlIBa3NOSLVPgSwaPrI0STD9nUGsNwoyEcBgoiEiBpoKPNnohlIBa3NOSLVPgSwaPrI0STD9nUGsNwoyEcBgoiEiBpoKPNnohlIBa3NOSLVPgSwaPrI0STD9nUGsNwoyEcBgoiEiBpoKPNnohlIBa3NOSLVPgSwaPrI0STD9nUGsNwoyEcBgoiEiBpoKPNnohlIBa3NOSLVPgSwaPrI0STD9nUGsNwoyEcBhCAlOvcA0oFCIDO2gM=","b64Record":"CiUIFhIDGO4HKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjD+uaMvHl9FvoTPK7Q6ms6GXQCgEOqdbAONZD7kjT1wnlUVMGL/ZSvb3OhyZBAoGpYaCwiFvt+qBhDT7ZU0Ig8KCQjJvd+qBhD4AhICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/6fWuQcKCwoDGO4HEICo1rkH"},{"b64Body":"Cg8KCQjJvd+qBhD+AhICGAISAhgDGIbgESICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOegkSAxjuB2oCCAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwM+dSuTva5zlWX22f/Z3EYacZZgxd7c3XAwG9QS/L+7Ja3ixh1NmCcy2DwQXBfDbyGgwIhb7fqgYQy8DQmwIiDwoJCMm936oGEP4CEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="}]},"CanUpdateMemo":{"placeholderNum":1007,"encodedItems":[{"b64Body":"Cg8KCQjOvd+qBhCOAxICGAISAhgDGLzo9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloyCiISIDUeNoVB4VKRhm0w/Jn/kaAr1hsGuIJmPgTmkrBIigxuSgUIgM7aA2oFRmlyc3Q=","b64Record":"CiUIFhIDGPAHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBd9ZFEUV+ViAWDwwMS2KQPRJnR2KbS9IU3w4FPClkYUXRaogw4MY4hhJltCRJDIE8aCwiKvt+qBhCrka48Ig8KCQjOvd+qBhCOAxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgA="},{"b64Body":"Cg8KCQjOvd+qBhCaAxICGAISAhgDGNfiESICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOeg8SAxjwB3IICgZTZWNvbmQ=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwHtcIHzqN57i53y6rnve/542id6/xttC7Wz9cNDJ+b22/4WoWSg1GRftxr5uAAhSpGgwIir7fqgYQw/vzvAIiDwoJCM6936oGEJoDEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="}]},"UpdateFailsWithInsufficientSigs":{"placeholderNum":1009,"encodedItems":[{"b64Body":"Cg8KCQjTvd+qBhCsAxICGAISAhgDGL2k7SEiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlqsBAqcBCqZBAgCEpQECocCKoQCCAES/wEKIhIgLit47I53iyyouXOhd7I6fx60lcH1jxbTgqjI6vYWHZMKIzohA2oAbHb7U3Qy0finmFr247CeVinjPL+DY52fLi7F+pbJCiISIOPkfc5Les/rJxI/15kOiPzFvOHuHH9OLSM5ajRGLGpCCiM6IQI/eLkhXBL0sshYrA3G7zW/ym6S74+xqyO7PPCWqCzMVQoiEiCbCLeAfAYChE8zMl16RKpaVNMRWR0htX3HG+j52W/E8wojOiECQi/gQfjG0+U7Pf7gdgVD9ckA+tBgWE9URcHSIplFzzoKIhIgd+1pO3J1RW93s5OyUV+7CnoPmxeWVWTqUenhGKQ/Qq0KhwIqhAIIAxL/AQojOiECPNBFqFNl9eWhL5fJKCuM6FS5hHJh/G/8A+Kml78f5fcKIhIgJslil+bgpgotsS4Utl1Emi/jWJ2a5xQOGTYi6Lwfg/sKIzohAiBhWT0uv82z1gZmWSefAxSR4nMzZgrTZDBj07FOD2QcCiISIEKRk1AaEX0jGv2XeSvhJuNJ6xjVCTQ+F7esgWxzNhI8CiM6IQOjgshmI7aQngT5mIIeg2yyEcC7A2LLGtd8+l9RWrQetwoiEiBAJxWa1rjaV2rsGFL5UpYwt+vo0qPVd6fxr07XKBPEjwoiEiAuK3jsjneLLKi5c6F3sjp/HrSVwfWPFtOCqMjq9hYdkxCAlOvcA0oFCIDO2gM=","b64Record":"CiUIFhIDGPIHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBY/frO0eiVY6HkLu9lgy/d8rallQJ03n1wfmW7zOm8Wcr8QC2eErdlXEyqtK9nwrwaCwiPvt+qBhDLu61JIg8KCQjTvd+qBhCsAxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/6fWuQcKCwoDGPIHEICo1rkH"}]},"CannotSetThresholdNegative":{"placeholderNum":1011,"encodedItems":[{"b64Body":"Cg8KCQjYvd+qBhDCAxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIH5zlIO/SlILEK4clGQtz2/drpU1lrI7kas+S7AujAdPEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGPQHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCCTcMheF85apePV29tr3piaZOUq5hOh5pA+WiK6OYYEB62TdI6xXRh39ZHArD+D3oaCwiUvt+qBhDjwqR0Ig8KCQjYvd+qBhDCAxICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUhkKCgoCGAIQ/6fWuQcKCwoDGPQHEICo1rkH"},{"b64Body":"Cg8KCQjYvd+qBhDIAxICGAISAhgDGIbgESICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOehISAxj0B1oLCP///////////wE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwICEXjgjJ3EOpXuL44sRKcL/a0ECIjCAeSHiSIteh6WE3FtdOANuieGNbPFHrMu2GGgwIlL7fqgYQm6vA3AIiDwoJCNi936oGEMgDEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="}]},"updateWithEmptyKeyFails":{"placeholderNum":1013,"encodedItems":[{"b64Body":"Cg8KCQjdvd+qBhDYAxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIFh6wZOWP5+v4t7eXSWKyhklyw8j/r1BQ5kKIB/pr9+dEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGPYHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCjZ9tkO1e+RISnDDBrKiHRuTxLvetvhD1QbqSehRwGrjF8I5jSq7Tw4+5l84mgZhsaDAiZvt+qBhDriLuFASIPCgkI3b3fqgYQ2AMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxj2BxCAqNa5Bw=="}]},"UpdateFailsIfMissingSigs":{"placeholderNum":1015,"encodedItems":[{"b64Body":"Cg8KCQjhvd+qBhDuAxICGAISAhgDGJKXjhciAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlq0AQqiASqfAQgDEpoBCiISIPFuaH9qdVme7zWyMpXsjm6odO5P3p7hUtlxiolDXApJCiM6IQJOcUyVh/lHeVz1W4+6CSyUx6XBBFVKtJ9UJ6dBC9xmgQpPKk0IARJJCiISIMVhyPPu9ZywO+iXnLVQaegzk/Qv6iekirIUi7K2G/5rCiM6IQMdKfdhoP4eZmdNM6QZCu8v00OUkRkFtoe6x5xBwvRbChCAlOvcA0ABSgUIgM7aAw==","b64Record":"CiUIFhIDGPgHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBpfSeXKEDJee21FNUspVCYY5Ji5WGrwOQhAFyMc8BeItkKSPtdWaUVMvxHjjoYf8YaDAidvt+qBhDr56qIAyIPCgkI4b3fqgYQ7gMSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxj4BxCAqNa5Bw=="}]},"UpdateFailsWithContractKey":{"placeholderNum":1017,"encodedItems":[{"b64Body":"Cg8KCQjmvd+qBhCEBBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISINC0fePJ2w+Q3R5Ct0E3XfqaNu3ZNCTns7yPPopll5iMEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGPoHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCBtBMktb+jNqqIBJbQZQUvq4M4X+yAc09K3OB8zvyaxGMCo2Fzp7RLmUOiiqFOHWkaDAiivt+qBhDroNmcAyIPCgkI5r3fqgYQhAQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxj6BxCAqNa5Bw=="},{"b64Body":"Cg8KCQjnvd+qBhCGBBICGAISAhgDGP7LzSwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjooBjwESDAijjLquBhCQtp+fARptCiISIEhhJ2JbQkVuGXlBrLKQ306lvkLasFTodazXSBOTp+fUCiM6IQPaMBjTx+xGpewsRAnj5W+GkW2qzQE0lFi0CD/9rnTKCAoiEiDvNJXDWZtDtlXZxyvlqirnO0or0RYO38uGGzyhquAQsSIMSGVsbG8gV29ybGQhKgAyAA==","b64Record":"CiUIFhoDGPsHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAYc/0R8vXfLnumkSeeeBP6wXv8k3889XkiPjWgB5yI7np2heMUyXutkagWq6BsbN0aDAijvt+qBhCj+eSlASIPCgkI573fqgYQhgQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQjnvd+qBhCKBBICGAISAhgDGN2ZoTMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjpoBzgwKAxj7ByLGDDYwODA2MDQwNTI2MDJhNjAwMDgwNjEwMTAwMGE4MTU0ODE2M2ZmZmZmZmZmMDIxOTE2OTA4MzYzZmZmZmZmZmYxNjAyMTc5MDU1NTA2MTAyZWY4MDYxMDAzNDYwMDAzOTYwMDBmM2ZlNjA4MDYwNDA1MjYwMDQzNjEwNjEwMDM0NTc2MDAwMzU2MGUwMWM4MDYzMmI2YWRmNDMxNDYxMDAzNjU3ODA2MzNkOTllODBkMTQ2MTAxMDE1NzgwNjM0YmZkYWI3MDE0NjEwMTQyNTc1YjAwNWI2MTAwZmY2MDA0ODAzNjAzNjA0MDgxMTAxNTYxMDA0YzU3NjAwMDgwZmQ1YjgxMDE5MDgwODAzNTYzZmZmZmZmZmYxNjkwNjAyMDAxOTA5MjkxOTA4MDM1OTA2MDIwMDE5MDY0MDEwMDAwMDAwMDgxMTExNTYxMDA3OTU3NjAwMDgwZmQ1YjgyMDE4MzYwMjA4MjAxMTExNTYxMDA4YjU3NjAwMDgwZmQ1YjgwMzU5MDYwMjAwMTkxODQ2MDAxODMwMjg0MDExMTY0MDEwMDAwMDAwMDgzMTExNzE1NjEwMGFkNTc2MDAwODBmZDViOTE5MDgwODA2MDFmMDE2MDIwODA5MTA0MDI2MDIwMDE2MDQwNTE5MDgxMDE2MDQwNTI4MDkzOTI5MTkwODE4MTUyNjAyMDAxODM4MzgwODI4NDM3NjAwMDgxODQwMTUyNjAxZjE5NjAxZjgyMDExNjkwNTA4MDgzMDE5MjUwNTA1MDUwNTA1MDUwOTE5MjkxOTI5MDUwNTA1MDYxMDE3OTU2NWIwMDViMzQ4MDE1NjEwMTBkNTc2MDAwODBmZDViNTA2MTAxNDA2MDA0ODAzNjAzNjAyMDgxMTAxNTYxMDEyNDU3NjAwMDgwZmQ1YjgxMDE5MDgwODAzNTYzZmZmZmZmZmYxNjkwNjAyMDAxOTA5MjkxOTA1MDUwNTA2MTAyN2U1NjViMDA1YjM0ODAxNTYxMDE0ZTU3NjAwMDgwZmQ1YjUwNjEwMTU3NjEwMmExNTY1YjYwNDA1MTgwODI2M2ZmZmZmZmZmMTY2M2ZmZmZmZmZmMTY4MTUyNjAyMDAxOTE1MDUwNjA0MDUxODA5MTAzOTBmMzViNjAwMDgyNjNmZmZmZmZmZjE2NmVmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmYxNjkwNTA4MDczZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZjE2NjEwOGZjNjAwMTkwODExNTAyOTA2MDQwNTE2MDAwNjA0MDUxODA4MzAzODE4NTg4ODhmMTkzNTA1MDUwNTAxNTgwMTU2MTAxZGM1NzNkNjAwMDgwM2UzZDYwMDBmZDViNTA3ZjkzMGY2MjhhMDk1MDE3M2M1NWI4ZjdkMzE2MzZhYTgyZTQ4MWYwOWQ3MDE5MWFkYzM4YjhjOGNkMTg2YTBhZDc4MjYwNDA1MTgwODA2MDIwMDE4MjgxMDM4MjUyODM4MTgxNTE4MTUyNjAyMDAxOTE1MDgwNTE5MDYwMjAwMTkwODA4MzgzNjAwMDViODM4MTEwMTU2MTAyM2Y1NzgwODIwMTUxODE4NDAxNTI2MDIwODEwMTkwNTA2MTAyMjQ1NjViNTA1MDUwNTA5MDUwOTA4MTAxOTA2MDFmMTY4MDE1NjEwMjZjNTc4MDgyMDM4MDUxNjAwMTgzNjAyMDAzNjEwMTAwMGEwMzE5MTY4MTUyNjAyMDAxOTE1MDViNTA5MjUwNTA1MDYwNDA1MTgwOTEwMzkwYTE1MDUwNTA1NjViODA2MDAwODA2MTAxMDAwYTgxNTQ4MTYzZmZmZmZmZmYwMjE5MTY5MDgzNjNmZmZmZmZmZjE2MDIxNzkwNTU1MDUwNTY1YjYwMDA4MDYwMDA5MDU0OTA2MTAxMDAwYTkwMDQ2M2ZmZmZmZmZmMTY5MDUwOTA1NmZlYTI2NTYyN2E3YTcyMzE1ODIwMGNiM2Y0NTNmODk2NWIyOGE5NjI2NjBiODAzODAzMWUzMDNmNGQ4MWZkMThmMTliYWMxZGI2MDkxMDBkZDE0ODY0NzM2ZjZjNjM0MzAwMDUxMTAwMzI=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwtZXnZfKkqySSZkz4FxAtRu1zsXrCGX8A2QK38Hg7hou/07lZU/xXVWGO4MCTg0g7GgwIo77fqgYQo432pQMiDwoJCOe936oGEIoEEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQjovd+qBhCMBBICGAISAhgDGJb7rp0CIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5CRQoDGPsHGiISIIKkbrwIUYPMT4BNCVv2UgAlmKhsz1PCI80FLJ1gwyLUIJChD0IFCIDO2gNSAFoAagtjZWxsYXIgZG9vcg==","b64Record":"CiUIFiIDGPwHKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBjQVRN6tbS4I3W5GAbv4FI6Jh1D+fkHakRDTR4thYFRgE0oZjxe9cLPY/SEX9ZsfoaDAikvt+qBhDD4ofKASIPCgkI6L3fqgYQjAQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjjDA2eIGQqQICgMY/AcS7wVggGBAUmAENhBhADRXYAA1YOAcgGMrat9DFGEANleAYz2Z6A0UYQEBV4BjS/2rcBRhAUJXWwBbYQD/YASANgNgQIEQFWEATFdgAID9W4EBkICANWP/////FpBgIAGQkpGQgDWQYCABkGQBAAAAAIERFWEAeVdgAID9W4IBg2AgggERFWEAi1dgAID9W4A1kGAgAZGEYAGDAoQBEWQBAAAAAIMRFxVhAK1XYACA/VuRkICAYB8BYCCAkQQCYCABYEBRkIEBYEBSgJOSkZCBgVJgIAGDg4CChDdgAIGEAVJgHxlgH4IBFpBQgIMBklBQUFBQUFCRkpGSkFBQUGEBeVZbAFs0gBVhAQ1XYACA/VtQYQFAYASANgNgIIEQFWEBJFdgAID9W4EBkICANWP/////FpBgIAGQkpGQUFBQYQJ+VlsAWzSAFWEBTldgAID9W1BhAVdhAqFWW2BAUYCCY/////8WY/////8WgVJgIAGRUFBgQFGAkQOQ81tgAIJj/////xZu////////////////////FpBQgHP//////////////////////////xZhCPxgAZCBFQKQYEBRYABgQFGAgwOBhYiI8ZNQUFBQFYAVYQHcVz1gAIA+PWAA/VtQf5MPYooJUBc8Vbj30xY2qoLkgfCdcBka3Di4yM0YagrXgmBAUYCAYCABgoEDglKDgYFRgVJgIAGRUIBRkGAgAZCAg4NgAFuDgRAVYQI/V4CCAVGBhAFSYCCBAZBQYQIkVltQUFBQkFCQgQGQYB8WgBVhAmxXgIIDgFFgAYNgIANhAQAKAxkWgVJgIAGRUFtQklBQUGBAUYCRA5ChUFBQVluAYACAYQEACoFUgWP/////AhkWkINj/////xYCF5BVUFBWW2AAgGAAkFSQYQEACpAEY/////8WkFCQVv6iZWJ6enIxWCAMs/RT+JZbKKliZguAOAMeMD9Ngf0Y8ZusHbYJEA3RSGRzb2xjQwAFEQAyIoACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACjAmgw6Axj8B0oWChQAAAAAAAAAAAAAAAAAAAAAAAAD/HIHCgMY/AcQAVIWCgkKAhgCEP+yxQ0KCQoCGGIQgLPFDQ=="},{"b64Body":"Cg8KCQjovd+qBhCSBBICGAISAhgDGLnrESICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOegwSAxj6BxoFCgMY/Ac=","b64Record":"CiAIByocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwDxdvEy+xeEynNnDcM/L1Fc3JEw55aeTyXR10DLM2I9eQaYlAVihmFKYAasr220gWGgwIpL7fqgYQ27SjsQMiDwoJCOi936oGEJIEEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="}]},"UpdateFailsWithOverlyLongLifetime":{"placeholderNum":1021,"encodedItems":[{"b64Body":"Cg8KCQjtvd+qBhCiBBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISINz0U/AY3HhOh4I+ACrrMl98651cHlVK3btGFcS53wVJEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGP4HKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjD3OK2QnILNLb94ZmwLbbDwWvGR2+dQOP9d2b9I9D9FVWwBqpLpko+ASsrjq6PDWqIaDAipvt+qBhCTqfm6ASIPCgkI7b3fqgYQogQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxj+BxCAqNa5Bw=="}]},"usdFeeAsExpectedCryptoUpdate":{"placeholderNum":1023,"encodedItems":[{"b64Body":"Cg8KCQjyvd+qBhC4BBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloyCiISIORsbnrL5fjaDg03O7v42So2+mHzLUCZ3RZqosh03StNEIDQ28P0AkoFCIDO2gM=","b64Record":"CiUIFhIDGIAIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAp9UmpyRYCvCKfUjMV2m5Cjp9l3D7RokM1VVLlCzz5vcn70iuhOHwp7aDbssnaGBoaDAiuvt+qBhD7oLbgASIPCgkI8r3fqgYQuAQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIbCgsKAhgCEP+ft4fpBQoMCgMYgAgQgKC3h+kF"},{"b64Body":"ChAKCQjyvd+qBhC6BBIDGIAIEgIYAxjjkO8TIgIIeFoxCiISIORsbnrL5fjaDg03O7v42So2+mHzLUCZ3RZqosh03StNEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGIEIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDnEo061PELIaGziPJUeIAU8L6DgpYEf16JNrRT6nq4UR2+zH/lH2Sg0SsZsYbFgTcaDAiuvt+qBhDj59fIAyIQCgkI8r3fqgYQugQSAxiACDDjkO8TUjwKCQoCGAMQjMuCAQoJCgIYYhDojewiCgoKAxigBhDSyO8DCgsKAxiACBDFsb3oSgoLCgMYgQgQgJDfwEo="},{"b64Body":"ChAKCQjzvd+qBhC8BBIDGIAIEgIYAxjjkO8TIgIIeFoxCiISIORsbnrL5fjaDg03O7v42So2+mHzLUCZ3RZqosh03StNEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGIIIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjB+2vTUNOBb+n/EjDnMKvZj75HlqDdP3JN0kpE4TQNdZUaMVcSzLg+Xm/QHXMftBlgaDAivvt+qBhCzt4fUASIQCgkI873fqgYQvAQSAxiACDDjkO8TUjwKCQoCGAMQjMuCAQoJCgIYYhDojewiCgoKAxigBhDSyO8DCgsKAxiACBDFsb3oSgoLCgMYgggQgJDfwEo="},{"b64Body":"ChAKCQjzvd+qBhDGBBIDGIEIEgIYAxjUogsiAgh4eg0SAxiBCEoGCK7alLIG","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwxyh+J3cOAdymlIylZwNm+Fmi9OR7E4Dj3b2cBZpmKAxiIrfEDOjDhS1EnCxzKWLkGgwIr77fqgYQ68/C1gMiEAoJCPO936oGEMYEEgMYgQgw1KILUikKBwoCGAMQonAKCAoCGGIQ4L8TCgkKAxigBhCmlQIKCQoDGIEIEKfFFg=="},{"b64Body":"ChAKCQj0vd+qBhDMBBIDGIIIEgIYAxi9zWYiAgh4egkSAxiCCHoCCAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwe9G32rPYwBkDX7Fd7euuLdT+t4y4YHJRaaAHXkEGoVq/cpOnziSj0ntcNHOzcPawGgwIsL7fqgYQ26SA/AEiEAoJCPS936oGEMwEEgMYgggwvc1mUisKBwoCGAMQknAKCQoCGGIQrPO3AQoJCgMYoAYQvLcUCgoKAxiCCBD5ms0B"},{"b64Body":"ChAKCQj0vd+qBhDSBBIDGIIIEgIYAxijt6AHIgIIeHoJEgMYggh6AggL","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwAa2yBrPVfiLS+yLHS4bjdYxTMU+9MNY+bMG+Dn5x0vXtYvLV0GKudP0WdK1YYU35GgsIsb7fqgYQ08CuByIQCgkI9L3fqgYQ0gQSAxiCCDCjt6AHUiwKBwoCGAMQknAKCQoCGGIQ4rGGDQoKCgMYoAYQ0sy5AQoKCgMYgggQxe7ADg=="}]},"sysAccountKeyUpdateBySpecialWontNeedNewKeyTxnSign":{"placeholderNum":1027,"encodedItems":[{"b64Body":"Cg8KCQj5vd+qBhDuBBICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIL7Hd10mqWhaL78umX2ZFvf57uwRzVa/IaVSAyR48ZebEICU69wDSgUIgM7aAw==","b64Record":"CiUIFhIDGIQIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjAXG/2oiWupDcjG6y+kaWo625yyfsR8hKsp92J2/6pfM9ZtkDqm13kVek3ASC/t+0EaDAi1vt+qBhDbvrn0ASIPCgkI+b3fqgYQ7gQSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxiECBCAqNa5Bw=="},{"b64Body":"Cg8KCQj5vd+qBhD0BBICGAISAhgDGOGBCyICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOeigSAhhjGiISILm1FOcX3TFGU0So27h3jIs90dWBetlwWAb9lP64jvHB","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwbwF0pjXnpBjY1mp3A4LbVvZ9MhoZXYmMQVBoS4j0vnS/MOI2aHuTAGtgNdjHyDJnGgwItb7fqgYQ246C3AMiDwoJCPm936oGEPQEEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="}]},"updateMaxAutoAssociationsWorks":{"placeholderNum":1029,"encodedItems":[{"b64Body":"Cg8KCQj+vd+qBhCKBRICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjloxCiISIIxx1tVpjDPX4ywj9xOQSTTVMX/I/8Cu8Ggw6Dt2UP4GEIDIr6AlSgUIgM7aAw==","b64Record":"CiUIFhIDGIYIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDKRSlrj6HjuByCAn0ipxzvCSovJAENdrq14fnFIE11Zt56HE53+H7sLaNgrLZv2nUaDAi6vt+qBhC7+d+HAiIPCgkI/r3fqgYQigUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxiGCBCAkN/ASg=="},{"b64Body":"Cg8KCQj/vd+qBhCPBRICGAISAhgDIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo6aATwKAhh5EgsIu4y6rgYQ4PPsHyIpCicKH2NvbnRyYWN0cy5hbGxvd0F1dG9Bc3NvY2lhdGlvbnMSBHRydWU=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwv5c6mg8SgGATIqVKYAS7Noogi1KOkXNw1syIHn/kO3yAO2oGYop3rzFZ37BMqQBNGgsIu77fqgYQy/jDLSIPCgkI/73fqgYQjwUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQj/vd+qBhCRBRICGAISAhgDGP7LzSwiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjooBjwESDAi7jLquBhCIx9GTAhptCiISIK1RjfRw4np4SRfJ3rYtQdAOcA4uslORgpJ+wulDRQnkCiM6IQMAb+vNwoC710gDUqfWoWFI1r3XlAEngZPe/FeViarJEwoiEiBfWhvz2ZpNd4MY4+BRYz6BmMqghF+2FNvXWGuyYCV/VSIMSGVsbG8gV29ybGQhKgAyAA==","b64Record":"CiUIFhoDGIcIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjCCpS9hXqH/s9TSdXQPedrab8HpcrB8HMyJtJ60c/Qywv9dup8EnRll6+vemIUKjNkaDAi7vt+qBhDD76GvAiIPCgkI/73fqgYQkQUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQiAvt+qBhCVBRICGAISAhgDGN2ZoTMiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjpoBzgwKAxiHCCLGDDYwODA2MDQwNTI2MDJhNjAwMDgwNjEwMTAwMGE4MTU0ODE2M2ZmZmZmZmZmMDIxOTE2OTA4MzYzZmZmZmZmZmYxNjAyMTc5MDU1NTA2MTAyZWY4MDYxMDAzNDYwMDAzOTYwMDBmM2ZlNjA4MDYwNDA1MjYwMDQzNjEwNjEwMDM0NTc2MDAwMzU2MGUwMWM4MDYzMmI2YWRmNDMxNDYxMDAzNjU3ODA2MzNkOTllODBkMTQ2MTAxMDE1NzgwNjM0YmZkYWI3MDE0NjEwMTQyNTc1YjAwNWI2MTAwZmY2MDA0ODAzNjAzNjA0MDgxMTAxNTYxMDA0YzU3NjAwMDgwZmQ1YjgxMDE5MDgwODAzNTYzZmZmZmZmZmYxNjkwNjAyMDAxOTA5MjkxOTA4MDM1OTA2MDIwMDE5MDY0MDEwMDAwMDAwMDgxMTExNTYxMDA3OTU3NjAwMDgwZmQ1YjgyMDE4MzYwMjA4MjAxMTExNTYxMDA4YjU3NjAwMDgwZmQ1YjgwMzU5MDYwMjAwMTkxODQ2MDAxODMwMjg0MDExMTY0MDEwMDAwMDAwMDgzMTExNzE1NjEwMGFkNTc2MDAwODBmZDViOTE5MDgwODA2MDFmMDE2MDIwODA5MTA0MDI2MDIwMDE2MDQwNTE5MDgxMDE2MDQwNTI4MDkzOTI5MTkwODE4MTUyNjAyMDAxODM4MzgwODI4NDM3NjAwMDgxODQwMTUyNjAxZjE5NjAxZjgyMDExNjkwNTA4MDgzMDE5MjUwNTA1MDUwNTA1MDUwOTE5MjkxOTI5MDUwNTA1MDYxMDE3OTU2NWIwMDViMzQ4MDE1NjEwMTBkNTc2MDAwODBmZDViNTA2MTAxNDA2MDA0ODAzNjAzNjAyMDgxMTAxNTYxMDEyNDU3NjAwMDgwZmQ1YjgxMDE5MDgwODAzNTYzZmZmZmZmZmYxNjkwNjAyMDAxOTA5MjkxOTA1MDUwNTA2MTAyN2U1NjViMDA1YjM0ODAxNTYxMDE0ZTU3NjAwMDgwZmQ1YjUwNjEwMTU3NjEwMmExNTY1YjYwNDA1MTgwODI2M2ZmZmZmZmZmMTY2M2ZmZmZmZmZmMTY4MTUyNjAyMDAxOTE1MDUwNjA0MDUxODA5MTAzOTBmMzViNjAwMDgyNjNmZmZmZmZmZjE2NmVmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmYxNjkwNTA4MDczZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZjE2NjEwOGZjNjAwMTkwODExNTAyOTA2MDQwNTE2MDAwNjA0MDUxODA4MzAzODE4NTg4ODhmMTkzNTA1MDUwNTAxNTgwMTU2MTAxZGM1NzNkNjAwMDgwM2UzZDYwMDBmZDViNTA3ZjkzMGY2MjhhMDk1MDE3M2M1NWI4ZjdkMzE2MzZhYTgyZTQ4MWYwOWQ3MDE5MWFkYzM4YjhjOGNkMTg2YTBhZDc4MjYwNDA1MTgwODA2MDIwMDE4MjgxMDM4MjUyODM4MTgxNTE4MTUyNjAyMDAxOTE1MDgwNTE5MDYwMjAwMTkwODA4MzgzNjAwMDViODM4MTEwMTU2MTAyM2Y1NzgwODIwMTUxODE4NDAxNTI2MDIwODEwMTkwNTA2MTAyMjQ1NjViNTA1MDUwNTA5MDUwOTA4MTAxOTA2MDFmMTY4MDE1NjEwMjZjNTc4MDgyMDM4MDUxNjAwMTgzNjAyMDAzNjEwMTAwMGEwMzE5MTY4MTUyNjAyMDAxOTE1MDViNTA5MjUwNTA1MDYwNDA1MTgwOTEwMzkwYTE1MDUwNTA1NjViODA2MDAwODA2MTAxMDAwYTgxNTQ4MTYzZmZmZmZmZmYwMjE5MTY5MDgzNjNmZmZmZmZmZjE2MDIxNzkwNTU1MDUwNTY1YjYwMDA4MDYwMDA5MDU0OTA2MTAxMDAwYTkwMDQ2M2ZmZmZmZmZmMTY5MDUwOTA1NmZlYTI2NTYyN2E3YTcyMzE1ODIwMGNiM2Y0NTNmODk2NWIyOGE5NjI2NjBiODAzODAzMWUzMDNmNGQ4MWZkMThmMTliYWMxZGI2MDkxMDBkZDE0ODY0NzM2ZjZjNjM0MzAwMDUxMTAwMzI=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwXk+mAOPrejF+Iwr8WXfY798vZHzLMvUGDUiZCYaofiVxpxTok1g91ZMuoZuJCNDCGgsIvL7fqgYQy/fDOyIPCgkIgL7fqgYQlQUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQiAvt+qBhCXBRICGAISAhgDGJb7rp0CIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5CRwoDGIcIGiISIG+znFlpHyEhmzCYffNLmgq1+CWnIWuutwKImq2mBmM4IJChD0IFCIDO2gNSAFoAagtjZWxsYXIgZG9vcnAC","b64Record":"CiUIFiIDGIgIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjDbCrQQn92Hja5KyxiM5scyvYk5JRyVHx8x4jkvZ0BV38EtMn5FwmGeZXpC3/uCRYwaDAi8vt+qBhCD8LCjAiIPCgkIgL7fqgYQlwUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjjDA2eIGQqQICgMYiAgS7wVggGBAUmAENhBhADRXYAA1YOAcgGMrat9DFGEANleAYz2Z6A0UYQEBV4BjS/2rcBRhAUJXWwBbYQD/YASANgNgQIEQFWEATFdgAID9W4EBkICANWP/////FpBgIAGQkpGQgDWQYCABkGQBAAAAAIERFWEAeVdgAID9W4IBg2AgggERFWEAi1dgAID9W4A1kGAgAZGEYAGDAoQBEWQBAAAAAIMRFxVhAK1XYACA/VuRkICAYB8BYCCAkQQCYCABYEBRkIEBYEBSgJOSkZCBgVJgIAGDg4CChDdgAIGEAVJgHxlgH4IBFpBQgIMBklBQUFBQUFCRkpGSkFBQUGEBeVZbAFs0gBVhAQ1XYACA/VtQYQFAYASANgNgIIEQFWEBJFdgAID9W4EBkICANWP/////FpBgIAGQkpGQUFBQYQJ+VlsAWzSAFWEBTldgAID9W1BhAVdhAqFWW2BAUYCCY/////8WY/////8WgVJgIAGRUFBgQFGAkQOQ81tgAIJj/////xZu////////////////////FpBQgHP//////////////////////////xZhCPxgAZCBFQKQYEBRYABgQFGAgwOBhYiI8ZNQUFBQFYAVYQHcVz1gAIA+PWAA/VtQf5MPYooJUBc8Vbj30xY2qoLkgfCdcBka3Di4yM0YagrXgmBAUYCAYCABgoEDglKDgYFRgVJgIAGRUIBRkGAgAZCAg4NgAFuDgRAVYQI/V4CCAVGBhAFSYCCBAZBQYQIkVltQUFBQkFCQgQGQYB8WgBVhAmxXgIIDgFFgAYNgIANhAQAKAxkWgVJgIAGRUFtQklBQUGBAUYCRA5ChUFBQVluAYACAYQEACoFUgWP/////AhkWkINj/////xYCF5BVUFBWW2AAgGAAkFSQYQEACpAEY/////8WkFCQVv6iZWJ6enIxWCAMs/RT+JZbKKliZguAOAMeMD9Ngf0Y8ZusHbYJEA3RSGRzb2xjQwAFEQAyIoACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACjAmgw6AxiICEoWChQAAAAAAAAAAAAAAAAAAAAAAAAECHIHCgMYiAgQAVIWCgkKAhgCEP+yxQ0KCQoCGGIQgLPFDQ=="},{"b64Body":"Cg8KCQiBvt+qBhCZBRICGAISAhgDGKWr3ugCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAS4KBnRva2VuQRIISURGS01TRksg//////////9/KgMYhghqCwi9jLquBhCwlvI3","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGIkIEjDsdMsrx2bd22batln4RTd8/F8lDGrnFSZN6qGvD+sWQbSR1Wz9EStiaT+4K85Rg+EaCwi9vt+qBhDDycVJIg8KCQiBvt+qBhCZBRICGAIqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOUgBaFwoDGIkIEhAKAxiGCBD+//////////8BcgoKAxiJCBIDGIYI"},{"b64Body":"Cg8KCQiBvt+qBhCfBRICGAISAhgDGKWr3ugCIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo7qAS8KBnRva2VuQhIIQUtXT0hFUFkg//////////9/KgMYhghqDAi9jLquBhCQg9+2Ag==","b64Record":"CiUIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkD1IDGIoIEjCw3rZX6BMwYFRdlut+hzb2Zv2qVuRGpKKodhMYI8CxqefZaDyITkLZICiDMcebh6waDAi9vt+qBhD7weHLAiIPCgkIgb7fqgYQnwUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWhcKAxiKCBIQCgMYhggQ/v//////////AXIKCgMYiggSAxiGCA=="},{"b64Body":"Cg8KCQiCvt+qBhCpBRICGAISAhgDGOufNiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOchkSFwoDGIkIEgcKAxiGCBABEgcKAxiICBAC","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwWqNjBcGyCDDEqf+sFLMznjNW0YO6++F00oiNyR1zMgsBu1rdjKLXBMGLjUd05tVoGgsIvr7fqgYQu9W8cCIPCgkIgr7fqgYQqQUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIAWhcKAxiJCBIHCgMYhggQARIHCgMYiAgQAnIKCgMYiQgSAxiICA=="},{"b64Body":"Cg8KCQiCvt+qBhCvBRICGAISAhgDGOufNiICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOchkSFwoDGIoIEgcKAxiGCBABEgcKAxiICBAC","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwBE0a277grhQnfx7Boa5WvUtV3JgXBYT2P4TbkVtjYDaygY33z2YC6M3w8WySzIEhGgwIvr7fqgYQo+P21gIiDwoJCIK+36oGEK8FEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAFoXCgMYiggSBwoDGIYIEAESBwoDGIgIEAJyCgoDGIoIEgMYiAg="},{"b64Body":"Cg8KCQiDvt+qBhC9BRICGAISAhgDGNGF2hAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjkoJCgMYiAhaAggB","b64Record":"CiEIhwIqHAoMCAEQDBoGCICumaQPEgwIARAPGgYIgK6ZpA8SMMLViOgrwbYgz9ZPyGsAxNq/JjVNx2r7uuVLPBCuU35YoCvk0XBCt5RZL3WVu3BvGhoLCL++36oGEMvR4HsiDwoJCIO+36oGEL0FEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQiDvt+qBhDDBRICGAISAhgDGNGF2hAiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjkoJCgMYiAhaAggD","b64Record":"CiUIFiIDGIgIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBWHemNv4Fb0oUuLzAASrGS3n+ER5zbdTSjAyaT0/CXOm129aXzGhWvZRT5B+L73z8aDAi/vt+qBhCT7br8AiIPCgkIg77fqgYQwwUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"}]},"updateStakingFieldsWorks":{"placeholderNum":1035,"encodedItems":[{"b64Body":"Cg8KCQiIvt+qBhDZBRICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo4CiISIFyQLS6L6dQHQDubB60o/QkGHv7ZUkY4AGFcnfbSWhMZEICU69wDSgUIgM7aA3oCGBSIAQE=","b64Record":"CiUIFhIDGIwIKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjBGrNMkTymmWZ/kkJpnAKEVFTMpxasVS9utY4vCPZ8e3X/rgK0Lfs6SSsis0ghdadYaDAjEvt+qBhDjj8W/AiIPCgkIiL7fqgYQ2QUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+n1rkHCgsKAxiMCBCAqNa5Bw=="},{"b64Body":"Cg8KCQiJvt+qBhDjBRICGAISAhgDGIbgESICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOegsSAxiMCIgBAJIBAA==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwBPniEofYywnDNld7Jc8jFYED/2A07EjpVtR7K8wl1sIsNVcjheCu7esRLm4p5u/wGgsIxb7fqgYQw46sSiIPCgkIib7fqgYQ4wUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQiJvt+qBhDtBRICGAISAhgDGIbgESICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOehESAxiMCIgB////////////AQ==","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwlyRU7uibRS33aYuyrVfk1ZZu2MhDfBIUWtGnNv1RBj+ETjH9md41KjgLBRueJFe3GgwIxb7fqgYQy7uVywIiDwoJCIm+36oGEO0FEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="},{"b64Body":"Cg8KCQiKvt+qBhD3BRICGAISAhgDGLnrESICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOejMSAxiMCBoiEiBckC0ui+nUB0A7mwetKP0JBh7+2VJGOABhXJ320loTGYIBAhgUkgECCAE=","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwqNDbERl3v3C/G/gUTfHWDXfGnDKds28+JiizBJ4IbwAdojwxkk0+CFx35PD7Y/B1GgsIxr7fqgYQo8S/ViIPCgkIir7fqgYQ9wUSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQiKvt+qBhCBBhICGAISAhgDGLnrESICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOei4SAxiMCBoiEiBckC0ui+nUB0A7mwetKP0JBh7+2VJGOABhXJ320loTGYIBAhgA","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw2UZUMllEWzGP3lM2zDKVNNRkSwX70fFyPAlM6YcvZ3V1beE8xx2qJcvya9S5uSyIGgwIxr7fqgYQk7/l1wIiDwoJCIq+36oGEIEGEgIYAiogw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo5SAA=="}]}}} \ No newline at end of file diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/HapiTestEngine.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/HapiTestEngine.java index 14bfcb36a873..bec5e1d5d2de 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/HapiTestEngine.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/HapiTestEngine.java @@ -229,6 +229,8 @@ private static final class ClassTestDescriptor extends AbstractTestDescriptor /** Whether a separate cluster of nodes should be created for this test class (or reset the normal cluster) */ private final boolean isolated; + private final boolean fuzzyMatch; + private final Set testTags; /** Creates a new descriptor for the given test class. */ @@ -271,6 +273,7 @@ public ClassTestDescriptor(Class testClass, TestDescriptor parent, EngineDisc final var annotation = findAnnotation(testClass, HapiTestSuite.class).orElseThrow(); this.isolated = annotation.isolated(); + this.fuzzyMatch = annotation.fuzzyMatch(); } @Override @@ -380,6 +383,9 @@ public HapiTestEngineExecutionContext execute( if (testMethod.getParameterCount() == 0) { final var spec = (HapiSpec) testMethod.invoke(suite); spec.setTargetNetworkType(TargetNetworkType.HAPI_TEST_NETWORK); + if (parent.fuzzyMatch) { + spec.addOverrideProperties(Map.of("recordStream.autoSnapshotManagement", "true")); + } final var env = context.getEnv(); // Third, call `runSuite` with just the one HapiSpec. final var result = suite.runSpecSync(spec, env.getNodes()); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/HapiTestSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/HapiTestSuite.java index 87fc1dea9374..6a9d33358491 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/HapiTestSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/HapiTestSuite.java @@ -34,4 +34,11 @@ public @interface HapiTestSuite { /** If true, then a new cluster is created for this test suite */ boolean isolated() default false; + + /** + * If true, we will set recordStream.autoSnapshotManagement property to true and enable fuzzy + * matching or every spec in the suite + * @return true if we want to enable fuzzy matching for every spec in the suite + */ + boolean fuzzyMatch() default false; } diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/SubProcessHapiTestNode.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/SubProcessHapiTestNode.java index 60244e1e198d..be3389691713 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/SubProcessHapiTestNode.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/SubProcessHapiTestNode.java @@ -169,6 +169,7 @@ public void start() { "-agentlib:jdwp=transport=dt_socket,server=y,suspend=" + (nodeId == 0 ? "n" : "n") + ",address=*:" + (5005 + nodeId), "-Dhedera.recordStream.logDir=data/recordStreams", + "-Dhedera.profiles.active=DEV", "-classpath", classPath, "-Dfile.encoding=UTF-8", diff --git a/platform-sdk/swirlds-config-benchmark/build.gradle.kts b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/TestTags.java similarity index 56% rename from platform-sdk/swirlds-config-benchmark/build.gradle.kts rename to hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/TestTags.java index 10f8c4b478eb..fac971fc6a9d 100644 --- a/platform-sdk/swirlds-config-benchmark/build.gradle.kts +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/junit/TestTags.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,16 +14,16 @@ * limitations under the License. */ -plugins { - id("com.hedera.hashgraph.sdk.conventions") - id("com.hedera.hashgraph.benchmark-conventions") -} +package com.hedera.services.bdd.junit; -jmhModuleInfo { - requires("com.swirlds.common") - requires("com.swirlds.config.api") - requires("com.swirlds.config.extensions") - requires("jmh.core") -} +public class TestTags { -tasks.withType().configureEach { enabled = false } + private TestTags() { + throw new UnsupportedOperationException("Utility class"); + } + + public static final String CRYPTO = "CRYPTO"; + public static final String SMART_CONTRACT = "SMART_CONTRACT"; + public static final String TIME_CONSUMING = "TIME_CONSUMING"; + public static final String TOKEN = "TOKEN"; +} diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/infrastructure/HapiSpecRegistry.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/infrastructure/HapiSpecRegistry.java index 54fca913d8c5..aea2121c921a 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/infrastructure/HapiSpecRegistry.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/infrastructure/HapiSpecRegistry.java @@ -56,6 +56,7 @@ import com.hederahashgraph.api.proto.java.TransactionID; import com.hederahashgraph.api.proto.java.TransactionRecord; import com.swirlds.common.utility.CommonUtils; +import edu.umd.cs.findbugs.annotations.NonNull; import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; @@ -587,6 +588,11 @@ public AccountID getAccountAlias(String name) { return get(name, AccountID.class); } + public AccountID getKeyAlias(@NonNull final String keyName) { + final var key = get(keyName, Key.class); + return AccountID.newBuilder().setAlias(key.toByteString()).build(); + } + public void forgetTokenId(String name) { try { var id = getTokenID(name); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/persistence/EntityManager.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/persistence/EntityManager.java index 174d3d7961fa..e66206d6277b 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/persistence/EntityManager.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/persistence/EntityManager.java @@ -37,6 +37,7 @@ import java.util.Optional; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; @@ -102,7 +103,7 @@ public boolean init() { parentEntitiesDir += File.separator; } - var yamlIn = new Yaml(new Constructor(Entity.class)); + var yamlIn = new Yaml(new Constructor(Entity.class, new LoaderOptions())); List candEntities = new ArrayList<>(); for (String subDir : ALL_SUBDIRS) { String entitiesDir = parentEntitiesDir + subDir; diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/persistence/SkipNullRepresenter.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/persistence/SkipNullRepresenter.java index dc1904d7adf7..62d0ef2366a8 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/persistence/SkipNullRepresenter.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/persistence/SkipNullRepresenter.java @@ -16,12 +16,18 @@ package com.hedera.services.bdd.spec.persistence; +import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.introspector.Property; import org.yaml.snakeyaml.nodes.NodeTuple; import org.yaml.snakeyaml.nodes.Tag; import org.yaml.snakeyaml.representer.Representer; public class SkipNullRepresenter extends Representer { + + public SkipNullRepresenter() { + super(new DumperOptions()); + } + @Override protected NodeTuple representJavaBeanProperty( Object javaBean, Property property, Object propertyValue, Tag customTag) { diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/utilops/UtilStateChange.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/utilops/UtilStateChange.java index bc04119462ba..ce54fe31347c 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/utilops/UtilStateChange.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/utilops/UtilStateChange.java @@ -82,7 +82,8 @@ private static void createEthereumAccount( final var newSpecKey = new NewSpecKey(secp256k1Key).shape(secp256k1Shape); final var cryptoTransfer = new HapiCryptoTransfer( tinyBarsFromAccountToAlias(GENESIS, secp256k1Key, 20 * ONE_MILLION_HBARS)) - .via(txnName); + .via(txnName) + .payingWith(GENESIS); final var idLookup = getTxnRecord(txnName).andAllChildRecords().assertingNothing(); newSpecKey.execFor(spec); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/utilops/UtilVerbs.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/utilops/UtilVerbs.java index 05163df6296a..37cf9db4941d 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/utilops/UtilVerbs.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/utilops/UtilVerbs.java @@ -575,7 +575,8 @@ public static HapiSpecOperation overridingThree( public static HapiSpecOperation overridingAllOf(@NonNull final Map explicit) { return withOpContext((spec, opLog) -> { final var updated121 = getUpdated121(spec, explicit); - final var multiStepUpdate = updateLargeFile(GENESIS, APP_PROPERTIES, ByteString.copyFrom(updated121)); + final var multiStepUpdate = updateLargeFile( + GENESIS, APP_PROPERTIES, ByteString.copyFrom(updated121), true, OptionalLong.of(0L)); allRunFor(spec, multiStepUpdate); }); } diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/utilops/records/SnapshotModeOp.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/utilops/records/SnapshotModeOp.java index 66e48c818527..4e94bcdfe560 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/utilops/records/SnapshotModeOp.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/spec/utilops/records/SnapshotModeOp.java @@ -728,9 +728,7 @@ private List hapiTestStreamLocs() { private boolean shouldSkip(@NonNull final String expectedName, @NonNull final Class expectedType) { requireNonNull(expectedName); requireNonNull(expectedType); - // System.out.println("Should skip? " + expectedName + " " + expectedType); if ("contractCallResult".equals(expectedName) && ByteString.class.isAssignableFrom(expectedType)) { - // if ("contractCallResult".equals(expectedName) && ByteString.class.equals(expectedType)) { return matchModes.contains(NONDETERMINISTIC_CONTRACT_CALL_RESULTS); } else if ("functionParameters".equals(expectedName)) { return matchModes.contains(NONDETERMINISTIC_FUNCTION_PARAMETERS); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractCallLocalSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractCallLocalSuite.java index fd560c3f4d54..249f67e3591f 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractCallLocalSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractCallLocalSuite.java @@ -17,6 +17,7 @@ package com.hedera.services.bdd.suites.contract.hapi; import static com.hedera.node.app.service.evm.utils.EthSigsUtils.recoverAddressFromPubKey; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asSolidityAddress; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.isLiteralResult; @@ -68,8 +69,10 @@ import org.apache.logging.log4j.Logger; import org.apache.tuweni.bytes.Bytes; import org.hyperledger.besu.datatypes.Address; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ContractCallLocalSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(ContractCallLocalSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractCallSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractCallSuite.java index 08b613dc528e..09ffb0339797 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractCallSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractCallSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.hapi; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asContract; import static com.hedera.services.bdd.spec.HapiPropertySource.asContractString; import static com.hedera.services.bdd.spec.HapiPropertySource.asHexedSolidityAddress; @@ -69,6 +70,7 @@ import static com.hedera.services.bdd.spec.utilops.UtilVerbs.sourcing; import static com.hedera.services.bdd.spec.utilops.UtilVerbs.streamMustIncludeNoFailuresFrom; import static com.hedera.services.bdd.spec.utilops.UtilVerbs.withOpContext; +import static com.hedera.services.bdd.spec.utilops.records.SnapshotMatchMode.NONDETERMINISTIC_TRANSACTION_FEES; import static com.hedera.services.bdd.suites.contract.Utils.FunctionType.FUNCTION; import static com.hedera.services.bdd.suites.contract.Utils.asAddress; import static com.hedera.services.bdd.suites.contract.Utils.asToken; @@ -126,8 +128,10 @@ import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ContractCallSuite extends HapiSuite { private static final Logger LOG = LogManager.getLogger(ContractCallSuite.class); @@ -1365,7 +1369,7 @@ inlineTestContract, GET_CODE_SIZE, asHeadlongAddress(acctAddress)) @HapiTest private HapiSpec multipleSelfDestructsAreSafe() { final var contract = "Fuse"; - return defaultHapiSpec("MultipleSelfDestructsAreSafe") + return defaultHapiSpec("MultipleSelfDestructsAreSafe", NONDETERMINISTIC_TRANSACTION_FEES) .given(uploadInitCode(contract), contractCreate(contract).gas(300_000)) .when(contractCall(contract, "light").via("lightTxn").scrambleTxnBody(tx -> tx)) .then(getTxnRecord("lightTxn").logged()); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractCreateSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractCreateSuite.java index 3cbda5ce41e5..0111e6e0193f 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractCreateSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractCreateSuite.java @@ -17,6 +17,7 @@ package com.hedera.services.bdd.suites.contract.hapi; import static com.hedera.node.app.hapi.utils.ethereum.EthTxSigs.signMessage; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountInfoAsserts.accountWith; import static com.hedera.services.bdd.spec.assertions.AssertUtils.inOrder; @@ -104,8 +105,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tuweni.bytes.Bytes32; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ContractCreateSuite extends HapiSuite { public static final String EMPTY_CONSTRUCTOR_CONTRACT = "EmptyConstructor"; diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractDeleteSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractDeleteSuite.java index 311c1b475ef4..92f2bdb2b264 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractDeleteSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractDeleteSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.hapi; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asHexedSolidityAddress; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractInfoAsserts.contractWith; @@ -74,8 +75,10 @@ import java.util.stream.IntStream; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ContractDeleteSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(ContractDeleteSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractGetBytecodeSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractGetBytecodeSuite.java index 59cb2bc2f27f..5d8accf400e3 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractGetBytecodeSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractGetBytecodeSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.hapi; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getContractBytecode; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.contractCreate; @@ -38,8 +39,10 @@ import org.apache.logging.log4j.Logger; import org.bouncycastle.util.encoders.Hex; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ContractGetBytecodeSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(ContractGetBytecodeSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractGetInfoSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractGetInfoSuite.java index 0780959313ed..21129722e2a1 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractGetInfoSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractGetInfoSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.hapi; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractInfoAsserts.contractWith; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getContractInfo; @@ -33,8 +34,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ContractGetInfoSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(ContractGetInfoSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractUpdateSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractUpdateSuite.java index ce3eb9566ea8..5cb6b8d9ada1 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractUpdateSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/hapi/ContractUpdateSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.hapi; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.isLiteralResult; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; @@ -60,8 +61,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ContractUpdateSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(ContractUpdateSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/BalanceOperationSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/BalanceOperationSuite.java index e1117ca90f29..4a381a40ebe1 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/BalanceOperationSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/BalanceOperationSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asHexedSolidityAddress; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.isLiteralResult; @@ -45,8 +46,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class BalanceOperationSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(BalanceOperationSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/CallCodeOperationSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/CallCodeOperationSuite.java index 84c5bcf09255..b4fd41ec9356 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/CallCodeOperationSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/CallCodeOperationSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.contractCall; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.contractCreate; @@ -34,8 +35,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class CallCodeOperationSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(CallCodeOperationSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/CallOperationSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/CallOperationSuite.java index 0ebb71ac48ca..51479d9b1c4f 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/CallOperationSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/CallOperationSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.contractCallLocal; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountBalance; @@ -38,8 +39,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class CallOperationSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(CallOperationSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/Create2OperationSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/Create2OperationSuite.java index 417a9d72bceb..1f2b402b3d2b 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/Create2OperationSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/Create2OperationSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.accountIdFromHexedMirrorAddress; import static com.hedera.services.bdd.spec.HapiPropertySource.asContractString; import static com.hedera.services.bdd.spec.HapiPropertySource.asHexedSolidityAddress; @@ -133,8 +134,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class Create2OperationSuite extends HapiSuite { public static final String GET_BYTECODE = "getBytecode"; diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/CreateOperationSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/CreateOperationSuite.java index 4ee240b148ee..7dd3119c0dcd 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/CreateOperationSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/CreateOperationSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AssertUtils.inOrder; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; @@ -54,8 +55,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class CreateOperationSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(CreateOperationSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/DelegateCallOperationSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/DelegateCallOperationSuite.java index 9ef3dfcdc4ca..75aa82e6c810 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/DelegateCallOperationSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/DelegateCallOperationSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.contractCall; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.contractCreate; @@ -34,8 +35,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class DelegateCallOperationSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(DelegateCallOperationSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/ExtCodeCopyOperationSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/ExtCodeCopyOperationSuite.java index 15400ac44018..1eff4ed465bc 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/ExtCodeCopyOperationSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/ExtCodeCopyOperationSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asHexedSolidityAddress; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.contractCallLocal; @@ -39,8 +40,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ExtCodeCopyOperationSuite extends HapiSuite { private static final Logger LOG = LogManager.getLogger(ExtCodeCopyOperationSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/ExtCodeHashOperationSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/ExtCodeHashOperationSuite.java index 290c76c6d53d..8ab37156667f 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/ExtCodeHashOperationSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/ExtCodeHashOperationSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asHexedSolidityAddress; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.contractCallLocal; @@ -41,8 +42,10 @@ import org.apache.tuweni.bytes.Bytes; import org.hyperledger.besu.crypto.Hash; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ExtCodeHashOperationSuite extends HapiSuite { private static final Logger LOG = LogManager.getLogger(ExtCodeHashOperationSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/ExtCodeSizeOperationSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/ExtCodeSizeOperationSuite.java index 6c66c93908a1..a872a0f7dcda 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/ExtCodeSizeOperationSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/ExtCodeSizeOperationSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asHexedSolidityAddress; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.isLiteralResult; @@ -45,8 +46,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ExtCodeSizeOperationSuite extends HapiSuite { private static final Logger LOG = LogManager.getLogger(ExtCodeSizeOperationSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/GlobalPropertiesSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/GlobalPropertiesSuite.java index 27067ce2d398..814adc46fff5 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/GlobalPropertiesSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/GlobalPropertiesSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.*; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; @@ -42,8 +43,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class GlobalPropertiesSuite extends HapiSuite { private static final Logger LOG = LogManager.getLogger(GlobalPropertiesSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/PrngSeedOperationSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/PrngSeedOperationSuite.java index 40e3e510b7c6..d76bcf0d9423 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/PrngSeedOperationSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/PrngSeedOperationSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.isLiteralResult; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.isRandomResult; @@ -44,8 +45,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class PrngSeedOperationSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(PrngSeedOperationSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/PushZeroOperationSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/PushZeroOperationSuite.java index 1ec70c8dab03..b3578cef1ccb 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/PushZeroOperationSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/PushZeroOperationSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.isLiteralResult; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; @@ -37,8 +38,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class PushZeroOperationSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(PushZeroOperationSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/SStoreSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/SStoreSuite.java index 2fc36953f19e..e47a653ff50a 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/SStoreSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/SStoreSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.isLiteralResult; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; @@ -44,8 +45,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) /** - CONCURRENCY STATUS - . Can run concurrent without temporarySStoreRefundTest() */ public class SStoreSuite extends HapiSuite { diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/SelfDestructSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/SelfDestructSuite.java index 9d770c28f170..170980cab8b8 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/SelfDestructSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/SelfDestructSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountInfoAsserts.accountWith; import static com.hedera.services.bdd.spec.assertions.ContractInfoAsserts.contractWith; @@ -41,8 +42,10 @@ import java.util.concurrent.atomic.AtomicLong; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class SelfDestructSuite extends HapiSuite { private final Logger LOGGER = LogManager.getLogger(SelfDestructSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/StaticCallOperationSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/StaticCallOperationSuite.java index c6d94e48622a..e67d59f21872 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/StaticCallOperationSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/opcodes/StaticCallOperationSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.opcodes; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.contractCallLocal; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.contractCall; @@ -35,8 +36,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class StaticCallOperationSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(StaticCallOperationSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/openzeppelin/ERC1155ContractInteractions.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/openzeppelin/ERC1155ContractInteractions.java index 1973f7bf0a0c..43946a5ef38a 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/openzeppelin/ERC1155ContractInteractions.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/openzeppelin/ERC1155ContractInteractions.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.openzeppelin; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountBalance; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountInfo; @@ -42,8 +43,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ERC1155ContractInteractions extends HapiSuite { private static final Logger log = LogManager.getLogger(ERC1155ContractInteractions.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/openzeppelin/ERC20ContractInteractions.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/openzeppelin/ERC20ContractInteractions.java index c35f5ea14f3a..59bf9ec4ca1d 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/openzeppelin/ERC20ContractInteractions.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/openzeppelin/ERC20ContractInteractions.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.openzeppelin; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AssertUtils.inOrder; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; @@ -46,8 +47,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ERC20ContractInteractions extends HapiSuite { private static final Logger log = LogManager.getLogger(ERC20ContractInteractions.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/openzeppelin/ERC721ContractInteractions.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/openzeppelin/ERC721ContractInteractions.java index df41d726df73..4b0ba75adbe0 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/openzeppelin/ERC721ContractInteractions.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/openzeppelin/ERC721ContractInteractions.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.openzeppelin; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.contractCall; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.contractCreate; @@ -33,8 +34,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ERC721ContractInteractions extends HapiSuite { private static final Logger log = LogManager.getLogger(ERC721ContractInteractions.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ApproveAllowanceSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ApproveAllowanceSuite.java index aab31e2e74cd..a597f1776cac 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ApproveAllowanceSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ApproveAllowanceSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asHexedSolidityAddress; import static com.hedera.services.bdd.spec.HapiPropertySource.asSolidityAddress; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; @@ -49,6 +50,7 @@ import static com.hedera.services.bdd.suites.contract.Utils.eventSignatureOf; import static com.hedera.services.bdd.suites.contract.Utils.parsedToByteString; import static com.hedera.services.bdd.suites.utils.contracts.precompile.HTSPrecompileResult.htsPrecompileResult; +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.SPENDER_DOES_NOT_HAVE_ALLOWANCE; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.SUCCESS; import static com.hederahashgraph.api.proto.java.TokenType.FUNGIBLE_COMMON; import static com.hederahashgraph.api.proto.java.TokenType.NON_FUNGIBLE_UNIQUE; @@ -60,8 +62,10 @@ import com.hedera.services.bdd.spec.HapiSpec; import com.hedera.services.bdd.suites.BddMethodIsNotATest; import com.hedera.services.bdd.suites.HapiSuite; +import com.hederahashgraph.api.proto.java.NftTransfer; import com.hederahashgraph.api.proto.java.TokenID; import com.hederahashgraph.api.proto.java.TokenSupplyType; +import com.hederahashgraph.api.proto.java.TokenTransferList; import com.hederahashgraph.api.proto.java.TokenType; import edu.umd.cs.findbugs.annotations.NonNull; import java.math.BigInteger; @@ -69,8 +73,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ApproveAllowanceSuite extends HapiSuite { public static final String CONTRACTS_PERMITTED_DELEGATE_CALLERS = "contracts.permittedDelegateCallers"; @@ -110,12 +116,56 @@ public List getSpecsInSuite() { htsTokenAllowance(), htsTokenApprove(), htsTokenApproveToInnerContract(), + nftAutoCreationIncludeAllowanceCheck(), testIndirectApprovalWithDirectPrecompileCallee(), testIndirectApprovalWithDelegateErc20Callee(), testIndirectApprovalWithDelegatePrecompileCallee(), testIndirectApprovalWithDirectErc20Callee()); } + private HapiSpec nftAutoCreationIncludeAllowanceCheck() { + final var ownerAccount = "owningAlias"; + final var receivingAlias = "receivingAlias"; + return defaultHapiSpec("NftAutoCreationIncludeAllowanceCheck") + .given( + newKeyNamed(MULTI_KEY), + cryptoCreate(ownerAccount), + newKeyNamed(receivingAlias), + // Accounts to be referenced with aliases as well + cryptoCreate(TOKEN_TREASURY).balance(100 * ONE_HUNDRED_HBARS), + // A non-fungible token with 6 serial nos + tokenCreate(NON_FUNGIBLE_TOKEN) + .tokenType(NON_FUNGIBLE_UNIQUE) + .initialSupply(0) + .treasury(TOKEN_TREASURY) + .adminKey(MULTI_KEY) + .supplyKey(MULTI_KEY)) + .when( + mintToken( + NON_FUNGIBLE_TOKEN, + List.of( + ByteString.copyFromUtf8("A"), + ByteString.copyFromUtf8("B"), + ByteString.copyFromUtf8("C"), + ByteString.copyFromUtf8("D"), + ByteString.copyFromUtf8("E"), + ByteString.copyFromUtf8("F"))), + tokenAssociate(ownerAccount, List.of(NON_FUNGIBLE_TOKEN)), + cryptoTransfer(movingUnique(NON_FUNGIBLE_TOKEN, 1L, 2L).between(TOKEN_TREASURY, ownerAccount))) + .then(cryptoTransfer((spec, b) -> b.addTokenTransfers(TokenTransferList.newBuilder() + .setToken(spec.registry().getTokenID(NON_FUNGIBLE_TOKEN)) + .addNftTransfers(NftTransfer.newBuilder() + .setSenderAccountID(spec.registry().getAccountID(ownerAccount)) + .setReceiverAccountID(spec.registry().getKeyAlias(receivingAlias)) + .setSerialNumber(1L) + .setIsApproval(true) + .build()) + .build())) + .signedBy(DEFAULT_PAYER) + .fee(10 * ONE_HBAR) + .hasKnownStatus(SPENDER_DOES_NOT_HAVE_ALLOWANCE)); + } + public static final String DELEGATE_PRECOMPILE_CALLEE = "PretendCallee"; private static final String DIRECT_PRECOMPILE_CALLEE = "DirectPrecompileCallee"; public static final String DELEGATE_ERC_CALLEE = "ERC20DelegateCallee"; diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/AssociatePrecompileSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/AssociatePrecompileSuite.java index 52337dd4d20f..bd76ef612385 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/AssociatePrecompileSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/AssociatePrecompileSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.idAsHeadlongAddress; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; @@ -63,8 +64,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class AssociatePrecompileSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(AssociatePrecompileSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/AtomicCryptoTransferHTSSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/AtomicCryptoTransferHTSSuite.java index 3afb9beb971b..3541af7731ca 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/AtomicCryptoTransferHTSSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/AtomicCryptoTransferHTSSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountDetailsAsserts.accountDetailsWith; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; @@ -78,8 +79,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class AtomicCryptoTransferHTSSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(AtomicCryptoTransferHTSSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractBurnHTSSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractBurnHTSSuite.java index f6fd4744c264..9376d240c0a2 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractBurnHTSSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractBurnHTSSuite.java @@ -17,6 +17,7 @@ package com.hedera.services.bdd.suites.contract.precompile; import static com.google.protobuf.ByteString.copyFromUtf8; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountBalance; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.contractCall; @@ -43,8 +44,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ContractBurnHTSSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(ContractBurnHTSSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractHTSSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractHTSSuite.java index 0e2642a3e41d..2594ea0ac0ba 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractHTSSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractHTSSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; @@ -48,8 +49,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ContractHTSSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(ContractHTSSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractKeysHTSSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractKeysHTSSuite.java index 28d852110178..5aa7cd8e61b3 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractKeysHTSSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractKeysHTSSuite.java @@ -17,6 +17,7 @@ package com.hedera.services.bdd.suites.contract.precompile; import static com.google.protobuf.ByteString.copyFromUtf8; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asDotDelimitedLongArray; import static com.hedera.services.bdd.spec.HapiPropertySource.asToken; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; @@ -88,8 +89,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ContractKeysHTSSuite extends HapiSuite { private static final long GAS_TO_OFFER = 1_500_000L; diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractKeysStillWorkAsExpectedSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractKeysStillWorkAsExpectedSuite.java index 8eafc8f7bf81..2fe8034c8e3f 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractKeysStillWorkAsExpectedSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractKeysStillWorkAsExpectedSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.idAsHeadlongAddress; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.HapiSpec.propertyPreservingHapiSpec; @@ -85,8 +86,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ContractKeysStillWorkAsExpectedSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(ContractKeysStillWorkAsExpectedSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractMintHTSSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractMintHTSSuite.java index 4d775e599fe6..065d9f20cf4d 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractMintHTSSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ContractMintHTSSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; @@ -63,8 +64,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ContractMintHTSSuite extends HapiSuite { private static final Logger LOG = LogManager.getLogger(ContractMintHTSSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/CreatePrecompileSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/CreatePrecompileSuite.java index 8d14b44d1ed6..9a0b1e78ec00 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/CreatePrecompileSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/CreatePrecompileSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountInfoAsserts.changeFromSnapshot; import static com.hedera.services.bdd.spec.keys.KeyShape.ED25519; @@ -55,12 +56,14 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; // Some of the test cases cannot be converted to use eth calls, // since they use admin keys, which are held by the txn payer. // In the case of an eth txn, we revoke the payers keys and the txn would fail. // The only way an eth account to create a token is the admin key to be of a contractId type. @HapiTestSuite +@Tag(SMART_CONTRACT) public class CreatePrecompileSuite extends HapiSuite { public static final String ACCOUNT_2 = "account2"; public static final String CONTRACT_ADMIN_KEY = "contractAdminKey"; @@ -122,6 +125,7 @@ List negativeSpecs() { // TEST-007 & TEST-016 // Should fail on insufficient value sent + @HapiTest private HapiSpec tokenCreateWithEmptyKeysReverts() { return defaultHapiSpec("tokenCreateWithEmptyKeysReverts") .given( @@ -233,6 +237,7 @@ private HapiSpec tokenCreateWithFixedFeeWithMultiplePaymentsReverts() { // TEST-010 & TEST-017 // Should fail on insufficient value sent + @HapiTest private HapiSpec createTokenWithEmptyTokenStruct() { return defaultHapiSpec("createTokenWithEmptyTokenStruct") .given(cryptoCreate(ACCOUNT).balance(ONE_MILLION_HBARS), uploadInitCode(TOKEN_CREATE_CONTRACT)) @@ -359,6 +364,7 @@ private HapiSpec createTokenWithInvalidTreasury() { // TEST-018 // Should fail on insufficient value sent + @HapiTest private HapiSpec createTokenWithInsufficientValueSent() { return defaultHapiSpec("createTokenWithInsufficientValueSent") .given( diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/CryptoTransferHTSSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/CryptoTransferHTSSuite.java index 35f4bb9c4620..1071a5d9a961 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/CryptoTransferHTSSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/CryptoTransferHTSSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountDetailsAsserts.accountDetailsWith; import static com.hedera.services.bdd.spec.assertions.AssertUtils.inOrder; @@ -95,8 +96,10 @@ import java.util.OptionalLong; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class CryptoTransferHTSSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(CryptoTransferHTSSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DefaultTokenStatusSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DefaultTokenStatusSuite.java index f56a5ffb66d6..fcc53138dca8 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DefaultTokenStatusSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DefaultTokenStatusSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; @@ -47,8 +48,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class DefaultTokenStatusSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(DefaultTokenStatusSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DelegatePrecompileSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DelegatePrecompileSuite.java index 20650d35d4ab..b5916490a55c 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DelegatePrecompileSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DelegatePrecompileSuite.java @@ -17,6 +17,7 @@ package com.hedera.services.bdd.suites.contract.precompile; import static com.google.protobuf.ByteString.copyFromUtf8; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asToken; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; @@ -49,6 +50,7 @@ import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.SUCCESS; import com.hedera.node.app.hapi.utils.contracts.ParsingConstants.FunctionType; +import com.hedera.services.bdd.junit.HapiTest; import com.hedera.services.bdd.junit.HapiTestSuite; import com.hedera.services.bdd.spec.HapiSpec; import com.hedera.services.bdd.spec.keys.KeyShape; @@ -62,8 +64,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class DelegatePrecompileSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(DelegatePrecompileSuite.class); @@ -97,6 +101,7 @@ public List getSpecsInSuite() { return List.of(delegateCallForTransfer(), delegateCallForBurn(), delegateCallForMint()); } + @HapiTest private HapiSpec delegateCallForTransfer() { final AtomicReference accountID = new AtomicReference<>(); final AtomicReference vanillaTokenTokenID = new AtomicReference<>(); @@ -153,6 +158,7 @@ OUTER_CONTRACT, asHeadlongAddress(getNestedContractAddress(NESTED_CONTRACT, spec getAccountBalance(RECEIVER).hasTokenBalance(VANILLA_TOKEN, 1)); } + @HapiTest private HapiSpec delegateCallForBurn() { final AtomicReference vanillaTokenTokenID = new AtomicReference<>(); @@ -201,6 +207,7 @@ OUTER_CONTRACT, asHeadlongAddress(getNestedContractAddress(NESTED_CONTRACT, spec getAccountBalance(TOKEN_TREASURY).hasTokenBalance(VANILLA_TOKEN, 1)); } + @HapiTest private HapiSpec delegateCallForMint() { final AtomicReference vanillaTokenTokenID = new AtomicReference<>(); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DeleteTokenPrecompileSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DeleteTokenPrecompileSuite.java index d510fadd41c0..b3b099b69470 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DeleteTokenPrecompileSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DeleteTokenPrecompileSuite.java @@ -16,14 +16,18 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; + import com.hedera.services.bdd.junit.HapiTestSuite; import com.hedera.services.bdd.spec.HapiSpec; import com.hedera.services.bdd.suites.HapiSuite; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class DeleteTokenPrecompileSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(DeleteTokenPrecompileSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DissociatePrecompileSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DissociatePrecompileSuite.java index 98e5bd017f6c..426fd0f115b4 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DissociatePrecompileSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/DissociatePrecompileSuite.java @@ -16,14 +16,18 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; + import com.hedera.services.bdd.junit.HapiTestSuite; import com.hedera.services.bdd.spec.HapiSpec; import com.hedera.services.bdd.suites.HapiSuite; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class DissociatePrecompileSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(DissociatePrecompileSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ERCPrecompileSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ERCPrecompileSuite.java index 2bd81e90a309..9b61b3110470 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ERCPrecompileSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/ERCPrecompileSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asHexedSolidityAddress; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountDetailsAsserts.accountDetailsWith; @@ -100,8 +101,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class ERCPrecompileSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(ERCPrecompileSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/FreezeUnfreezeTokenPrecompileSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/FreezeUnfreezeTokenPrecompileSuite.java index 267ad8883fa0..ab1a11a818fb 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/FreezeUnfreezeTokenPrecompileSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/FreezeUnfreezeTokenPrecompileSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; import static com.hedera.services.bdd.spec.queries.QueryVerbs.contractCallLocal; @@ -52,8 +53,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class FreezeUnfreezeTokenPrecompileSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(FreezeUnfreezeTokenPrecompileSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/GrantRevokeKycSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/GrantRevokeKycSuite.java index 77534392e073..dd9441adafb1 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/GrantRevokeKycSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/GrantRevokeKycSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; @@ -55,8 +56,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class GrantRevokeKycSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(GrantRevokeKycSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/HRCPrecompileSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/HRCPrecompileSuite.java index e4790fb25b58..b690af460d10 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/HRCPrecompileSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/HRCPrecompileSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asHexedSolidityAddress; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; @@ -44,6 +45,7 @@ import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.TOKEN_NOT_ASSOCIATED_TO_ACCOUNT; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.TRANSACTION_REQUIRES_ZERO_TOKEN_BALANCES; +import com.hedera.services.bdd.junit.HapiTest; import com.hedera.services.bdd.junit.HapiTestSuite; import com.hedera.services.bdd.spec.HapiSpec; import com.hedera.services.bdd.suites.HapiSuite; @@ -53,8 +55,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class HRCPrecompileSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(HRCPrecompileSuite.class); @@ -97,6 +101,7 @@ public List getSpecsInSuite() { hrcTooManyTokenAssociateShouldFail()); } + @HapiTest private HapiSpec hrcNftAndFungibleTokenAssociateFromEOA() { final AtomicReference fungibleTokenNum = new AtomicReference<>(); final AtomicReference nonfungibleTokenNum = new AtomicReference<>(); @@ -208,6 +213,7 @@ private HapiSpec hrcNftAndFungibleTokenAssociateFromEOA() { htsPrecompileResult().withStatus(SUCCESS))))))); } + @HapiTest private HapiSpec hrcNFTAndFungibleTokenAssociateFromContract() { return defaultHapiSpec("hrcNFTAndFungibleTokenAssociateFromContract") .given( @@ -314,6 +320,7 @@ private HapiSpec hrcNFTAndFungibleTokenAssociateFromContract() { htsPrecompileResult().withStatus(SUCCESS))))))); } + @HapiTest private HapiSpec hrcTokenAssociateFromSameEOATwiceShouldFail() { final AtomicReference fungibleTokenNum = new AtomicReference<>(); @@ -379,6 +386,7 @@ private HapiSpec hrcTokenAssociateFromSameEOATwiceShouldFail() { .withStatus(TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT))))))); } + @HapiTest private HapiSpec hrcTokenDissociateWhenNotAssociatedShouldFail() { final AtomicReference fungibleTokenNum = new AtomicReference<>(); @@ -426,6 +434,7 @@ private HapiSpec hrcTokenDissociateWhenNotAssociatedShouldFail() { .withStatus(TOKEN_NOT_ASSOCIATED_TO_ACCOUNT))))))); } + @HapiTest private HapiSpec hrcTokenDissociateWhenBalanceNotZeroShouldFail() { final AtomicReference fungibleTokenNum = new AtomicReference<>(); @@ -493,6 +502,7 @@ private HapiSpec hrcTokenDissociateWhenBalanceNotZeroShouldFail() { .withStatus(TRANSACTION_REQUIRES_ZERO_TOKEN_BALANCES))))))); } + @HapiTest private HapiSpec hrcTooManyTokenAssociateShouldFail() { final AtomicReference fungibleTokenNum1 = new AtomicReference<>(); final AtomicReference fungibleTokenNum2 = new AtomicReference<>(); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/LazyCreateThroughPrecompileSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/LazyCreateThroughPrecompileSuite.java index 3146ee94b0de..4626a6275dc5 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/LazyCreateThroughPrecompileSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/LazyCreateThroughPrecompileSuite.java @@ -17,6 +17,7 @@ package com.hedera.services.bdd.suites.contract.precompile; import static com.hedera.node.app.service.evm.utils.EthSigsUtils.recoverAddressFromPubKey; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asHexedSolidityAddress; import static com.hedera.services.bdd.spec.HapiPropertySource.asToken; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; @@ -88,8 +89,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class LazyCreateThroughPrecompileSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(LazyCreateThroughPrecompileSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/PauseUnpauseTokenAccountPrecompileSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/PauseUnpauseTokenAccountPrecompileSuite.java index b8152076a1b3..ffc2b8ded9d2 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/PauseUnpauseTokenAccountPrecompileSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/PauseUnpauseTokenAccountPrecompileSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; @@ -50,8 +51,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class PauseUnpauseTokenAccountPrecompileSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(PauseUnpauseTokenAccountPrecompileSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/PrngPrecompileSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/PrngPrecompileSuite.java index 1ba53d24fc6c..9f5f5a1d1f69 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/PrngPrecompileSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/PrngPrecompileSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.isRandomResult; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; @@ -44,8 +45,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class PrngPrecompileSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(PrngPrecompileSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/RedirectPrecompileSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/RedirectPrecompileSuite.java index af89b8e1a7f3..56f70682cf60 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/RedirectPrecompileSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/RedirectPrecompileSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; @@ -38,8 +39,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class RedirectPrecompileSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(RedirectPrecompileSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/SigningReqsSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/SigningReqsSuite.java index f19f63213bdf..1ede9f6f2e02 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/SigningReqsSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/SigningReqsSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asTokenString; import static com.hedera.services.bdd.spec.HapiPropertySource.idAsHeadlongAddress; import static com.hedera.services.bdd.spec.HapiSpec.propertyPreservingHapiSpec; @@ -38,12 +39,14 @@ import java.util.*; import java.util.concurrent.atomic.*; import org.apache.logging.log4j.*; +import org.junit.jupiter.api.Tag; // Some of the test cases cannot be converted to use eth calls, // since they use admin keys, which are held by the txn payer. // In the case of an eth txn, we revoke the payers keys and the txn would fail. // The only way an eth account to create a token is the admin key to be of a contractId type. @HapiTestSuite +@Tag(SMART_CONTRACT) public class SigningReqsSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(SigningReqsSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenAndTypeCheckSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenAndTypeCheckSuite.java index ee3aea1ae616..74fc7c3bab59 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenAndTypeCheckSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenAndTypeCheckSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.isLiteralResult; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; @@ -51,8 +52,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class TokenAndTypeCheckSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(TokenAndTypeCheckSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenExpiryInfoSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenExpiryInfoSuite.java index 7fe6835871af..c6f4e710ac3d 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenExpiryInfoSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenExpiryInfoSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; @@ -51,8 +52,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class TokenExpiryInfoSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(TokenExpiryInfoSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenInfoHTSSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenInfoHTSSuite.java index 5204b7ded076..0c5d2677871e 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenInfoHTSSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenInfoHTSSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; @@ -81,8 +82,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class TokenInfoHTSSuite extends HapiSuite { private static final Logger LOG = LogManager.getLogger(TokenInfoHTSSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenUpdatePrecompileSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenUpdatePrecompileSuite.java index b30e2975dd41..9c82a7d01985 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenUpdatePrecompileSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenUpdatePrecompileSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.keys.KeyShape.CONTRACT; import static com.hedera.services.bdd.spec.keys.KeyShape.DELEGATE_CONTRACT; @@ -61,8 +62,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class TokenUpdatePrecompileSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(TokenUpdatePrecompileSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TopLevelSigsCanBeToggledByPrecompileTypeSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TopLevelSigsCanBeToggledByPrecompileTypeSuite.java index 14405c1740de..fecad407fef7 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TopLevelSigsCanBeToggledByPrecompileTypeSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TopLevelSigsCanBeToggledByPrecompileTypeSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.propertyPreservingHapiSpec; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; import static com.hedera.services.bdd.spec.keys.KeyShape.CONTRACT; @@ -99,8 +100,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) @SuppressWarnings("java:S1192") // "string literal should not be duplicated" - this rule makes test suites worse public class TopLevelSigsCanBeToggledByPrecompileTypeSuite extends HapiSuite { diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/WipeTokenAccountPrecompileSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/WipeTokenAccountPrecompileSuite.java index e6eef0a3b027..513b45d8c60b 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/WipeTokenAccountPrecompileSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/WipeTokenAccountPrecompileSuite.java @@ -16,14 +16,18 @@ package com.hedera.services.bdd.suites.contract.precompile; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; + import com.hedera.services.bdd.junit.HapiTestSuite; import com.hedera.services.bdd.spec.HapiSpec; import com.hedera.services.bdd.suites.HapiSuite; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class WipeTokenAccountPrecompileSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(WipeTokenAccountPrecompileSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/records/LogsSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/records/LogsSuite.java index 3a4c8679fde0..bcafe10e1f0c 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/records/LogsSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/records/LogsSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.records; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AssertUtils.inOrder; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; @@ -36,8 +37,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class LogsSuite extends HapiSuite { private static final long GAS_TO_OFFER = 25_000L; diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/records/RecordsSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/records/RecordsSuite.java index e48637576ca1..a867dfd16a60 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/records/RecordsSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/records/RecordsSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.contract.records; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getTxnRecord; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.contractCall; @@ -37,8 +38,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class RecordsSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(RecordsSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/traceability/TraceabilitySuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/traceability/TraceabilitySuite.java index db1815141a38..0b65f05038f8 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/traceability/TraceabilitySuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/traceability/TraceabilitySuite.java @@ -17,6 +17,7 @@ package com.hedera.services.bdd.suites.contract.traceability; import static com.hedera.node.app.service.evm.utils.EthSigsUtils.recoverAddressFromPubKey; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asContract; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.HapiSpec.propertyPreservingHapiSpec; @@ -130,8 +131,10 @@ import org.apache.logging.log4j.Logger; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.units.bigints.UInt256; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class TraceabilitySuite extends HapiSuite { private static final Logger log = LogManager.getLogger(TraceabilitySuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/AutoAccountCreationSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/AutoAccountCreationSuite.java index 78d5de2889e9..ecbcf7cd78c1 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/AutoAccountCreationSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/AutoAccountCreationSuite.java @@ -18,6 +18,7 @@ import static com.google.protobuf.ByteString.copyFromUtf8; import static com.hedera.node.app.service.evm.utils.EthSigsUtils.recoverAddressFromPubKey; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiPropertySource.asSolidityAddress; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.PropertySource.asAccount; @@ -114,8 +115,10 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class AutoAccountCreationSuite extends HapiSuite { private static final Logger LOG = LogManager.getLogger(AutoAccountCreationSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/AutoAccountUpdateSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/AutoAccountUpdateSuite.java index 303a9b1f3024..e50c5754f58b 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/AutoAccountUpdateSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/AutoAccountUpdateSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountInfoAsserts.accountWith; import static com.hedera.services.bdd.spec.keys.SigControl.OFF; @@ -28,6 +29,7 @@ import static com.hedera.services.bdd.spec.transactions.crypto.HapiCryptoTransfer.tinyBarsFromToWithAlias; import static com.hedera.services.bdd.spec.utilops.UtilVerbs.newKeyNamed; import static com.hedera.services.bdd.spec.utilops.UtilVerbs.withOpContext; +import static com.hedera.services.bdd.spec.utilops.records.SnapshotMatchMode.NONDETERMINISTIC_TRANSACTION_FEES; import static com.hedera.services.bdd.suites.crypto.AutoCreateUtils.updateSpecFor; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_SIGNATURE; @@ -40,6 +42,7 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; /** * Note that we cannot test the behavior of the network when the auto-created account expires, @@ -48,6 +51,7 @@ * the auto-created account is about to expire. */ @HapiTestSuite +@Tag(CRYPTO) public class AutoAccountUpdateSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(AutoAccountUpdateSuite.class); public static final long INITIAL_BALANCE = 1000L; @@ -129,7 +133,7 @@ private HapiSpec updateKeyOnAutoCreatedAccount() { KeyShape.threshSigs(1, OFF, OFF, OFF, OFF, OFF, OFF, ON), KeyShape.threshSigs(3, ON, ON, ON, OFF, OFF, OFF, OFF)); - return defaultHapiSpec("updateKeyOnAutoCreatedAccount") + return defaultHapiSpec("updateKeyOnAutoCreatedAccount", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(ALIAS), newKeyNamed(complexKey).shape(ENOUGH_UNIQUE_SIGS), diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoApproveAllowanceSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoApproveAllowanceSuite.java index 5b473d4dcff2..2ff07eff8a6f 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoApproveAllowanceSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoApproveAllowanceSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountDetailsAsserts.accountDetailsWith; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountBalance; @@ -50,6 +51,8 @@ import static com.hedera.services.bdd.spec.utilops.UtilVerbs.newKeyNamed; import static com.hedera.services.bdd.spec.utilops.UtilVerbs.sourcing; import static com.hedera.services.bdd.spec.utilops.UtilVerbs.validateChargedUsdWithin; +import static com.hedera.services.bdd.spec.utilops.records.SnapshotMatchMode.EXPECT_STREAMLINED_INGEST_RECORDS; +import static com.hedera.services.bdd.spec.utilops.records.SnapshotMatchMode.NONDETERMINISTIC_TRANSACTION_FEES; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.ACCOUNT_DELETED; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.AMOUNT_EXCEEDS_TOKEN_MAX_SUPPLY; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.DELEGATING_SPENDER_CANNOT_GRANT_APPROVE_FOR_ALL; @@ -83,8 +86,10 @@ import java.util.concurrent.atomic.AtomicLong; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class CryptoApproveAllowanceSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(CryptoApproveAllowanceSuite.class); @@ -160,7 +165,7 @@ private HapiSpec cannotPayForAnyTransactionWithContractAccount() { final var cryptoAdminKey = "cryptoAdminKey"; final var contractNum = new AtomicLong(); final var contract = "PayableConstructor"; - return defaultHapiSpec("cannotPayForAnyTransactionWithContractAccount") + return defaultHapiSpec("cannotPayForAnyTransactionWithContractAccount", EXPECT_STREAMLINED_INGEST_RECORDS) .given( newKeyNamed(cryptoAdminKey), uploadInitCode(contract), @@ -218,7 +223,7 @@ private HapiSpec transferringMissingNftViaApprovalFailsWithInvalidNftId() { @HapiTest private HapiSpec canDeleteAllowanceFromDeletedSpender() { - return defaultHapiSpec("canDeleteAllowanceFromDeletedSpender") + return defaultHapiSpec("canDeleteAllowanceFromDeletedSpender", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(OWNER).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(10), @@ -315,7 +320,7 @@ private HapiSpec canDeleteAllowanceFromDeletedSpender() { @HapiTest private HapiSpec duplicateKeysAndSerialsInSameTxnDoesntThrow() { - return defaultHapiSpec("duplicateKeysAndSerialsInSameTxnDoesntThrow") + return defaultHapiSpec("duplicateKeysAndSerialsInSameTxnDoesntThrow", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(OWNER).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(10), @@ -403,7 +408,7 @@ private HapiSpec duplicateKeysAndSerialsInSameTxnDoesntThrow() { private HapiSpec approveForAllSpenderCanDelegateOnNFT() { final String delegatingSpender = "delegatingSpender"; final String newSpender = "newSpender"; - return defaultHapiSpec("approveForAllSpenderCanDelegateOnNFT") + return defaultHapiSpec("approveForAllSpenderCanDelegateOnNFT", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(OWNER).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(10), @@ -465,7 +470,7 @@ private HapiSpec approveForAllSpenderCanDelegateOnNFT() { @HapiTest private HapiSpec canGrantFungibleAllowancesWithTreasuryOwner() { - return defaultHapiSpec("canGrantFungibleAllowancesWithTreasuryOwner") + return defaultHapiSpec("canGrantFungibleAllowancesWithTreasuryOwner", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(TOKEN_TREASURY), @@ -500,7 +505,7 @@ private HapiSpec canGrantFungibleAllowancesWithTreasuryOwner() { @HapiTest private HapiSpec canGrantNftAllowancesWithTreasuryOwner() { - return defaultHapiSpec("canGrantNftAllowancesWithTreasuryOwner") + return defaultHapiSpec("canGrantNftAllowancesWithTreasuryOwner", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(TOKEN_TREASURY), @@ -544,7 +549,7 @@ private HapiSpec canGrantNftAllowancesWithTreasuryOwner() { @HapiTest private HapiSpec invalidOwnerFails() { - return defaultHapiSpec("invalidOwnerFails") + return defaultHapiSpec("invalidOwnerFails", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(OWNER).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(10), @@ -666,7 +671,7 @@ private HapiSpec invalidSpenderFails() { @HapiTest private HapiSpec noOwnerDefaultsToPayer() { - return defaultHapiSpec("noOwnerDefaultsToPayer") + return defaultHapiSpec("noOwnerDefaultsToPayer", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(PAYER).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(10), @@ -725,7 +730,7 @@ private HapiSpec noOwnerDefaultsToPayer() { @HapiTest private HapiSpec canHaveMultipleOwners() { - return defaultHapiSpec("canHaveMultipleOwners") + return defaultHapiSpec("canHaveMultipleOwners", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(OWNER).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(10), @@ -820,7 +825,7 @@ private HapiSpec canHaveMultipleOwners() { @HapiTest private HapiSpec feesAsExpected() { - return defaultHapiSpec("feesAsExpected") + return defaultHapiSpec("feesAsExpected", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(OWNER).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(10), @@ -991,7 +996,7 @@ private HapiSpec serialsInAscendingOrder() { @HapiTest private HapiSpec succeedsWhenTokenPausedFrozenKycRevoked() { - return defaultHapiSpec("succeedsWhenTokenPausedFrozenKycRevoked") + return defaultHapiSpec("succeedsWhenTokenPausedFrozenKycRevoked", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), newKeyNamed(ADMIN_KEY), @@ -1082,7 +1087,7 @@ private HapiSpec succeedsWhenTokenPausedFrozenKycRevoked() { @HapiTest private HapiSpec tokenExceedsMaxSupplyFails() { - return defaultHapiSpec("tokenExceedsMaxSupplyFails") + return defaultHapiSpec("tokenExceedsMaxSupplyFails", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(OWNER).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(10), @@ -1322,7 +1327,7 @@ private HapiSpec negativeAmountFailsForFungible() { @HapiTest private HapiSpec happyPathWorks() { - return defaultHapiSpec("happyPathWorks") + return defaultHapiSpec("happyPathWorks", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(OWNER).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(10), @@ -1388,7 +1393,7 @@ private HapiSpec happyPathWorks() { @HapiTest private HapiSpec duplicateEntriesGetsReplacedWithDifferentTxn() { - return defaultHapiSpec("duplicateEntriesGetsReplacedWithDifferentTxn") + return defaultHapiSpec("duplicateEntriesGetsReplacedWithDifferentTxn", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(OWNER).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(10), @@ -1480,7 +1485,8 @@ private HapiSpec duplicateEntriesGetsReplacedWithDifferentTxn() { @HapiTest private HapiSpec cannotHaveMultipleAllowedSpendersForTheSameNFTSerial() { - return defaultHapiSpec("CannotHaveMultipleAllowedSpendersForTheSameNFTSerial") + return defaultHapiSpec( + "CannotHaveMultipleAllowedSpendersForTheSameNFTSerial", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(OWNER).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(10), @@ -1559,7 +1565,7 @@ private HapiSpec cannotHaveMultipleAllowedSpendersForTheSameNFTSerial() { @HapiTest private HapiSpec approveForAllDoesNotSetExplicitNFTSpender() { - return defaultHapiSpec("approveForAllDoesNotSetExplicitNFTSpender") + return defaultHapiSpec("approveForAllDoesNotSetExplicitNFTSpender", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(OWNER).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(10), @@ -1599,7 +1605,7 @@ private HapiSpec approveForAllDoesNotSetExplicitNFTSpender() { @HapiTest private HapiSpec scheduledCryptoApproveAllowanceWorks() { - return defaultHapiSpec("ScheduledCryptoApproveAllowanceWorks") + return defaultHapiSpec("ScheduledCryptoApproveAllowanceWorks", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SUPPLY_KEY), cryptoCreate(TOKEN_TREASURY), @@ -1648,7 +1654,8 @@ private HapiSpec scheduledCryptoApproveAllowanceWorks() { .addNftAllowance( OWNER, NON_FUNGIBLE_TOKEN, SPENDER, false, List.of(1L, 2L, 3L)) .fee(ONE_HUNDRED_HBARS)) - .via("successTx")) + .via("successTx"), + getTxnRecord("successTx").logged()) .then( cryptoTransfer(movingUniqueWithAllowance(NON_FUNGIBLE_TOKEN, 3) .between(OWNER, OTHER_RECEIVER)) diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoCornerCasesSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoCornerCasesSuite.java index 77c25e1c2901..289f3ddaa6f4 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoCornerCasesSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoCornerCasesSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoCreate; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_NODE_ACCOUNT; @@ -40,8 +41,10 @@ import org.apache.commons.lang3.RandomStringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class CryptoCornerCasesSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(CryptoCornerCasesSuite.class); private static final String NEW_PAYEE = "newPayee"; diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoCreateSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoCreateSuite.java index bd6a4176ba18..231df0e4c00f 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoCreateSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoCreateSuite.java @@ -17,8 +17,8 @@ package com.hedera.services.bdd.suites.crypto; import static com.hedera.node.app.service.evm.utils.EthSigsUtils.recoverAddressFromPubKey; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; -import static com.hedera.services.bdd.spec.HapiSpec.onlyDefaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountInfoAsserts.accountWith; import static com.hedera.services.bdd.spec.keys.KeyShape.ED25519; import static com.hedera.services.bdd.spec.keys.KeyShape.SIMPLE; @@ -64,8 +64,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class CryptoCreateSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(CryptoCreateSuite.class); @@ -213,7 +215,7 @@ private HapiSpec usdFeeAsExpected() { final var tenAutoAssocSlots = "tenAutoAssocSlots"; final var token = "token"; - return onlyDefaultHapiSpec("usdFeeAsExpected") + return defaultHapiSpec("usdFeeAsExpected") .given( cryptoCreate(CIVILIAN).balance(ONE_HUNDRED_HBARS), getAccountBalance(CIVILIAN).hasTinyBars(ONE_HUNDRED_HBARS)) diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoDeleteAllowanceSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoDeleteAllowanceSuite.java index 55224a6f7e08..d01bcdfabfc1 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoDeleteAllowanceSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoDeleteAllowanceSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountDetailsAsserts.accountDetailsWith; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountDetails; @@ -61,8 +62,10 @@ import java.util.Map; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class CryptoDeleteAllowanceSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(CryptoDeleteAllowanceSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoDeleteSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoDeleteSuite.java index e835f1bd8aa8..3219eb213d02 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoDeleteSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoDeleteSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountInfoAsserts.accountWith; import static com.hedera.services.bdd.spec.assertions.AccountInfoAsserts.approxChangeFromSnapshot; @@ -35,6 +36,8 @@ import static com.hedera.services.bdd.spec.transactions.token.TokenMovement.moving; import static com.hedera.services.bdd.spec.utilops.UtilVerbs.balanceSnapshot; import static com.hedera.services.bdd.spec.utilops.UtilVerbs.newKeyNamed; +import static com.hedera.services.bdd.spec.utilops.records.SnapshotMatchMode.FULLY_NONDETERMINISTIC; +import static com.hedera.services.bdd.spec.utilops.records.SnapshotMatchMode.NONDETERMINISTIC_TRANSACTION_FEES; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.ACCOUNT_DELETED; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.ACCOUNT_IS_TREASURY; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.PAYER_ACCOUNT_DELETED; @@ -50,8 +53,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class CryptoDeleteSuite extends HapiSuite { static final Logger log = LogManager.getLogger(CryptoDeleteSuite.class); private static final long TOKEN_INITIAL_SUPPLY = 500; @@ -81,6 +86,8 @@ public List getSpecsInSuite() { } @HapiTest + // In this transactionFee is not set in mono-service record, because it fails in node due diligence. + // But it feels right to set it. So setting this HIGHLY_NONDETERMINISTIC_TRANSACTION_FEES private HapiSpec deletedAccountCannotBePayer() { // Account Names String SUBMITTING_NODE_ACCOUNT = "0.0.3"; @@ -90,7 +97,7 @@ private HapiSpec deletedAccountCannotBePayer() { String SUBMITTING_NODE_PRE_TRANSFER = "submittingNodePreTransfer"; String SUBMITTING_NODE_AFTER_BALANCE_LOAD = "submittingNodeAfterBalanceLoad"; - return defaultHapiSpec("DeletedAccountCannotBePayer") + return defaultHapiSpec("DeletedAccountCannotBePayer", FULLY_NONDETERMINISTIC) .given( cryptoCreate(ACCOUNT_TO_BE_DELETED), cryptoCreate(BENEFICIARY_ACCOUNT).balance(0L)) @@ -183,7 +190,7 @@ private HapiSpec cannotDeleteAccountsWithNonzeroTokenBalances() { @HapiTest private HapiSpec cannotDeleteAlreadyDeletedAccount() { - return defaultHapiSpec("CannotDeleteAlreadyDeletedAccount") + return defaultHapiSpec("CannotDeleteAlreadyDeletedAccount", NONDETERMINISTIC_TRANSACTION_FEES) .given(cryptoCreate(ACCOUNT_TO_BE_DELETED), cryptoCreate(TRANSFER_ACCOUNT)) .when(cryptoDelete(ACCOUNT_TO_BE_DELETED) .transfer(TRANSFER_ACCOUNT) @@ -205,7 +212,7 @@ private HapiSpec cannotDeleteAccountWithSameBeneficiary() { @HapiTest private HapiSpec cannotDeleteTreasuryAccount() { - return defaultHapiSpec("CannotDeleteTreasuryAccount") + return defaultHapiSpec("CannotDeleteTreasuryAccount", NONDETERMINISTIC_TRANSACTION_FEES) .given(cryptoCreate(TREASURY), cryptoCreate(TRANSFER_ACCOUNT)) .when(tokenCreate("toBeTransferred") .initialSupply(TOKEN_INITIAL_SUPPLY) diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoGetInfoRegression.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoGetInfoRegression.java index 1ad8dc62894d..e54a604aebd4 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoGetInfoRegression.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoGetInfoRegression.java @@ -16,7 +16,9 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; +import static com.hedera.services.bdd.spec.HapiSpec.propertyPreservingHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountInfoAsserts.accountWith; import static com.hedera.services.bdd.spec.keys.KeyShape.SIMPLE; import static com.hedera.services.bdd.spec.keys.KeyShape.listOf; @@ -52,8 +54,10 @@ import java.util.Map; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class CryptoGetInfoRegression extends HapiSuite { static final Logger log = LogManager.getLogger(CryptoGetInfoRegression.class); @@ -94,7 +98,8 @@ private HapiSpec fetchesOnlyALimitedTokenAssociations() { final var token6 = "token6"; final var token7 = "token7"; final var token8 = "token8"; - return defaultHapiSpec("FetchesOnlyALimitedTokenAssociations") + return propertyPreservingHapiSpec("FetchesOnlyALimitedTokenAssociations") + .preserving("tokens.maxRelsPerInfoQuery") .given( fileUpdate(APP_PROPERTIES) .payingWith(ADDRESS_BOOK_CONTROL) diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoGetRecordsRegression.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoGetRecordsRegression.java index 3e57ed463b66..8d86224e7950 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoGetRecordsRegression.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoGetRecordsRegression.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; import static com.hedera.services.bdd.spec.assertions.TransferListAsserts.including; @@ -42,8 +43,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class CryptoGetRecordsRegression extends HapiSuite { static final Logger log = LogManager.getLogger(CryptoGetRecordsRegression.class); private static final String LOW_THRESH_PAYER = "lowThreshPayer"; diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoTransferSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoTransferSuite.java index 0e8917fb5b05..c1a4a2effebf 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoTransferSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoTransferSuite.java @@ -17,6 +17,7 @@ package com.hedera.services.bdd.suites.crypto; import static com.google.protobuf.ByteString.copyFromUtf8; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiPropertySource.accountIdFromHexedMirrorAddress; import static com.hedera.services.bdd.spec.HapiPropertySource.asAccountString; import static com.hedera.services.bdd.spec.HapiPropertySource.asSolidityAddress; @@ -150,8 +151,10 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class CryptoTransferSuite extends HapiSuite { private static final Logger LOG = LogManager.getLogger(CryptoTransferSuite.class); private static final String OWNER = "owner"; diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoUpdateSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoUpdateSuite.java index e2c40bf27119..b36ac1667787 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoUpdateSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoUpdateSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountDetailsAsserts.accountDetailsWith; import static com.hedera.services.bdd.spec.assertions.ContractInfoAsserts.contractWith; @@ -42,6 +43,8 @@ import static com.hedera.services.bdd.spec.utilops.UtilVerbs.overriding; import static com.hedera.services.bdd.spec.utilops.UtilVerbs.sourcing; import static com.hedera.services.bdd.spec.utilops.UtilVerbs.validateChargedUsd; +import static com.hedera.services.bdd.spec.utilops.records.SnapshotMatchMode.EXPECT_STREAMLINED_INGEST_RECORDS; +import static com.hedera.services.bdd.spec.utilops.records.SnapshotMatchMode.NONDETERMINISTIC_TRANSACTION_FEES; import static com.hedera.services.bdd.suites.contract.hapi.ContractUpdateSuite.ADMIN_KEY; import static com.hederahashgraph.api.proto.java.HederaFunctionality.CryptoUpdate; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.EXISTING_AUTOMATIC_ASSOCIATIONS_EXCEED_GIVEN_LIMIT; @@ -62,6 +65,8 @@ import com.hedera.services.bdd.spec.keys.KeyShape; import com.hedera.services.bdd.spec.keys.SigControl; import com.hedera.services.bdd.suites.HapiSuite; +import com.hederahashgraph.api.proto.java.ContractID; +import com.hederahashgraph.api.proto.java.Key; import com.hederahashgraph.api.proto.java.TokenType; import java.time.Instant; import java.util.List; @@ -70,8 +75,10 @@ import java.util.concurrent.atomic.AtomicLong; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class CryptoUpdateSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(CryptoUpdateSuite.class); @@ -83,7 +90,7 @@ public class CryptoUpdateSuite extends HapiSuite { public static final String UPD_KEY = "updKey"; public static void main(String... args) { - new CryptoUpdateSuite().runSuiteConcurrentWithOverrides(Map.of("spec.autoScheduledTxns", "CryptoUpdate")); + new CryptoUpdateSuite().runSuiteConcurrentWithOverrides(Map.of("spec.autoScheduledTxns", "")); } private final SigControl twoLevelThresh = SigControl.threshSigs( @@ -135,7 +142,7 @@ public List getSpecsInSuite() { @HapiTest private HapiSpec updateStakingFieldsWorks() { - return defaultHapiSpec("updateStakingFieldsWorks") + return defaultHapiSpec("updateStakingFieldsWorks", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(ADMIN_KEY), cryptoCreate("user") @@ -196,7 +203,7 @@ private HapiSpec usdFeeAsExpectedCryptoUpdate() { final var allowedPercentDiff = 1.0; AtomicLong expiration = new AtomicLong(); - return defaultHapiSpec("usdFeeAsExpectedCryptoUpdate") + return defaultHapiSpec("usdFeeAsExpectedCryptoUpdate", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed("key").shape(SIMPLE), cryptoCreate("payer").key("key").balance(1_000 * ONE_HBAR), @@ -292,7 +299,7 @@ private HapiSpec canUpdateMemo() { @HapiTest private HapiSpec updateWithUniqueSigs() { - return defaultHapiSpec("UpdateWithUniqueSigs") + return defaultHapiSpec("UpdateWithUniqueSigs", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(TARGET_KEY).shape(twoLevelThresh).labels(overlappingKeys), cryptoCreate(TARGET_ACCOUNT).key(TARGET_KEY)) @@ -311,7 +318,7 @@ private HapiSpec updateWithOneEffectiveSig() { SigControl.threshSigs(1, OFF, OFF, OFF, OFF, OFF, OFF, OFF), SigControl.threshSigs(3, OFF, OFF, OFF, ON, OFF, OFF, OFF)); - return defaultHapiSpec("UpdateWithOneEffectiveSig") + return defaultHapiSpec("UpdateWithOneEffectiveSig", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(REPEATING_KEY).shape(twoLevelThresh).labels(oneUniqueKey), cryptoCreate(TARGET_ACCOUNT).key(REPEATING_KEY).balance(1_000_000_000L)) @@ -324,7 +331,7 @@ private HapiSpec updateWithOneEffectiveSig() { @HapiTest private HapiSpec updateWithOverlappingSigs() { - return defaultHapiSpec("UpdateWithOverlappingSigs") + return defaultHapiSpec("UpdateWithOverlappingSigs", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(TARGET_KEY).shape(twoLevelThresh).labels(overlappingKeys), cryptoCreate(TARGET_ACCOUNT).key(TARGET_KEY)) @@ -337,15 +344,29 @@ private HapiSpec updateWithOverlappingSigs() { @HapiTest private HapiSpec updateFailsWithContractKey() { - return defaultHapiSpec("UpdateFailsWithContractKey") - .given(cryptoCreate(TARGET_ACCOUNT)) + AtomicLong id = new AtomicLong(); + final var CONTRACT = "Multipurpose"; + return defaultHapiSpec( + "UpdateFailsWithContractKey", + NONDETERMINISTIC_TRANSACTION_FEES, + EXPECT_STREAMLINED_INGEST_RECORDS) + .given( + cryptoCreate(TARGET_ACCOUNT), + uploadInitCode(CONTRACT), + contractCreate(CONTRACT).exposingNumTo(id::set)) .when() - .then(cryptoUpdate(TARGET_ACCOUNT).usingContractKey().hasKnownStatus(INVALID_SIGNATURE)); + .then(sourcing(() -> cryptoUpdate(TARGET_ACCOUNT) + .protoKey(Key.newBuilder() + .setContractID(ContractID.newBuilder() + .setContractNum(id.get()) + .build()) + .build()) + .hasKnownStatus(INVALID_SIGNATURE))); } @HapiTest private HapiSpec updateFailsWithInsufficientSigs() { - return defaultHapiSpec("UpdateFailsWithInsufficientSigs") + return defaultHapiSpec("UpdateFailsWithInsufficientSigs", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(TARGET_KEY).shape(twoLevelThresh).labels(overlappingKeys), cryptoCreate(TARGET_ACCOUNT).key(TARGET_KEY)) @@ -358,7 +379,7 @@ private HapiSpec updateFailsWithInsufficientSigs() { @HapiTest private HapiSpec cannotSetThresholdNegative() { - return defaultHapiSpec("CannotSetThresholdNegative") + return defaultHapiSpec("CannotSetThresholdNegative", NONDETERMINISTIC_TRANSACTION_FEES) .given(cryptoCreate(TEST_ACCOUNT)) .when() .then(cryptoUpdate(TEST_ACCOUNT).sendThreshold(-1L)); @@ -369,7 +390,7 @@ private HapiSpec updateFailsIfMissingSigs() { SigControl origKeySigs = SigControl.threshSigs(3, ON, ON, SigControl.threshSigs(1, OFF, ON)); SigControl updKeySigs = SigControl.listSigs(ON, OFF, SigControl.threshSigs(1, ON, OFF, OFF, OFF)); - return defaultHapiSpec("UpdateFailsIfMissingSigs") + return defaultHapiSpec("UpdateFailsIfMissingSigs", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(ORIG_KEY).shape(origKeySigs), newKeyNamed(UPD_KEY).shape(updKeySigs)) @@ -387,7 +408,7 @@ private HapiSpec updateFailsIfMissingSigs() { private HapiSpec updateWithEmptyKeyFails() { SigControl updKeySigs = threshOf(0, 0); - return defaultHapiSpec("updateWithEmptyKeyFails") + return defaultHapiSpec("updateWithEmptyKeyFails", NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(ORIG_KEY).shape(KeyShape.SIMPLE), newKeyNamed(UPD_KEY).shape(updKeySigs)) @@ -412,7 +433,7 @@ private HapiSpec updateMaxAutoAssociationsWorks() { final String CONTRACT = "Multipurpose"; final String ADMIN_KEY = "adminKey"; - return defaultHapiSpec("updateMaxAutoAssociationsWorks") + return defaultHapiSpec("updateMaxAutoAssociationsWorks", NONDETERMINISTIC_TRANSACTION_FEES) .given( cryptoCreate(treasury).balance(ONE_HUNDRED_HBARS), newKeyNamed(ADMIN_KEY), diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CrytoCreateSuiteWithUTF8.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CrytoCreateSuiteWithUTF8.java index e4e7bc077f4c..74de46f86389 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CrytoCreateSuiteWithUTF8.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CrytoCreateSuiteWithUTF8.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.UTF8Mode.FALSE; import static com.hedera.services.bdd.spec.HapiSpec.customHapiSpec; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; @@ -31,8 +32,10 @@ import java.util.Map; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class CrytoCreateSuiteWithUTF8 extends HapiSuite { private static final Logger log = LogManager.getLogger(CrytoCreateSuiteWithUTF8.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/HelloWorldSpec.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/HelloWorldSpec.java index 4723e6300cd0..2e412352f6c8 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/HelloWorldSpec.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/HelloWorldSpec.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountInfoAsserts.changeFromSnapshot; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountBalance; @@ -31,8 +32,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class HelloWorldSpec extends HapiSuite { private static final Logger log = LogManager.getLogger(HelloWorldSpec.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/HollowAccountFinalizationSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/HollowAccountFinalizationSuite.java index 6dcb2ee4767c..1bbfe118efd7 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/HollowAccountFinalizationSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/HollowAccountFinalizationSuite.java @@ -17,6 +17,7 @@ package com.hedera.services.bdd.suites.crypto; import static com.hedera.node.app.service.evm.utils.EthSigsUtils.recoverAddressFromPubKey; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiPropertySource.asSolidityAddress; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountInfoAsserts.accountWith; @@ -80,8 +81,10 @@ import java.util.function.Function; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class HollowAccountFinalizationSuite extends HapiSuite { private static final Logger LOG = LogManager.getLogger(HollowAccountFinalizationSuite.class); private static final String ANOTHER_SECP_256K1_SOURCE_KEY = "anotherSecp256k1Alias"; @@ -302,7 +305,9 @@ private HapiSpec hollowAccountFinalizationWhenAccountNotPresentInPreHandle() { @HapiTest private HapiSpec hollowAccountFinalizationOccursOnlyOnceWhenMultipleFinalizationTensComeInAtTheSameTime() { final var ECDSA_2 = "ECDSA_2"; - return defaultHapiSpec("hollowAccountFinalizationOccursOnlyOnceWhenMultipleFinalizationTensComeInAtTheSameTime") + return defaultHapiSpec( + "hollowAccountFinalizationOccursOnlyOnceWhenMultipleFinalizationTensComeInAtTheSameTime", + NONDETERMINISTIC_TRANSACTION_FEES) .given( newKeyNamed(SECP_256K1_SOURCE_KEY).shape(SECP_256K1_SHAPE), newKeyNamed(ECDSA_2).shape(SECP_256K1_SHAPE), diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/MiscCryptoSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/MiscCryptoSuite.java index 86f181615b3e..cc18f8b256b1 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/MiscCryptoSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/MiscCryptoSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; import static com.hedera.services.bdd.spec.keys.KeyShape.SIMPLE; @@ -43,8 +44,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class MiscCryptoSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(MiscCryptoSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/NftTransferSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/NftTransferSuite.java index 0141b74cec84..9e07de11b703 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/NftTransferSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/NftTransferSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoCreate; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoTransfer; @@ -40,8 +41,10 @@ import java.util.stream.IntStream; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class NftTransferSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(NftTransferSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/QueryPaymentSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/QueryPaymentSuite.java index 7a04105c1c67..5562d7d394d1 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/QueryPaymentSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/QueryPaymentSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiPropertySource.asAccount; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountInfo; @@ -36,8 +37,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class QueryPaymentSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(QueryPaymentSuite.class); private static final String NODE = "0.0.3"; diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/RandomOps.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/RandomOps.java index 3b99367405a2..6267ebe79167 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/RandomOps.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/RandomOps.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.customHapiSpec; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountDetailsAsserts.accountDetailsWith; @@ -47,8 +48,10 @@ import java.util.Map; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class RandomOps extends HapiSuite { private static final Logger log = LogManager.getLogger(RandomOps.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/TransferWithCustomFees.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/TransferWithCustomFees.java index a51f2059f336..88576387c147 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/TransferWithCustomFees.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/TransferWithCustomFees.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountBalance; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoCreate; @@ -36,8 +37,10 @@ import java.util.OptionalLong; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class TransferWithCustomFees extends HapiSuite { private static final Logger log = LogManager.getLogger(TransferWithCustomFees.class); private final long hbarFee = 1_000L; diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/TxnReceiptRegression.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/TxnReceiptRegression.java index c32984659772..a1cbe0a2036d 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/TxnReceiptRegression.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/TxnReceiptRegression.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getReceipt; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoCreate; @@ -37,8 +38,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class TxnReceiptRegression extends HapiSuite { static final Logger log = LogManager.getLogger(TxnReceiptRegression.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/TxnRecordRegression.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/TxnRecordRegression.java index 6f7387260935..ee688a849b5c 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/TxnRecordRegression.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/TxnRecordRegression.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getReceipt; @@ -40,6 +41,7 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; /** * ! WARNING - Requires a RecordCache TTL of 3s to pass ! @@ -47,6 +49,7 @@ *

    Even with a 3s TTL, a number of these tests fail. FUTURE: revisit * */ @HapiTestSuite +@Tag(CRYPTO) public class TxnRecordRegression extends HapiSuite { static final Logger log = LogManager.getLogger(TxnRecordRegression.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/UnsupportedQueriesRegression.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/UnsupportedQueriesRegression.java index b3e479b1eb77..51a8487f1f35 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/UnsupportedQueriesRegression.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/UnsupportedQueriesRegression.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto; +import static com.hedera.services.bdd.junit.TestTags.CRYPTO; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.utilops.UtilVerbs.getAccountNftInfosNotSupported; import static com.hedera.services.bdd.spec.utilops.UtilVerbs.getBySolidityIdNotSupported; @@ -31,8 +32,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(CRYPTO) public class UnsupportedQueriesRegression extends HapiSuite { static final Logger log = LogManager.getLogger(UnsupportedQueriesRegression.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/staking/StakingSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/staking/StakingSuite.java index b3f8428d28d6..f427182c7b48 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/staking/StakingSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/staking/StakingSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.crypto.staking; +import static com.hedera.services.bdd.junit.TestTags.TIME_CONSUMING; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountInfoAsserts.accountWith; import static com.hedera.services.bdd.spec.assertions.ContractInfoAsserts.contractWith; @@ -48,6 +49,7 @@ import static com.hedera.services.bdd.suites.records.ContractRecordsSanityCheckSuite.PAYABLE_CONTRACT; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_STAKING_ID; +import com.hedera.services.bdd.junit.HapiTest; import com.hedera.services.bdd.junit.HapiTestSuite; import com.hedera.services.bdd.spec.HapiSpec; import com.hedera.services.bdd.spec.HapiSpecOperation; @@ -62,8 +64,10 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(TIME_CONSUMING) public class StakingSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(StakingSuite.class); @@ -123,6 +127,7 @@ public List getSpecsInSuite() { * periods, a series of credits and debits are made to them, and they are confirmed to have * received the expected rewards (all zero). */ + @HapiTest private HapiSpec zeroStakeAccountsHaveMetadataResetOnFirstDayTheyReceiveFunds() { final var zeroStakeAccount = "zeroStakeAccount"; final var numZeroStakeAccounts = 10; @@ -174,6 +179,7 @@ private HapiSpec zeroStakeAccountsHaveMetadataResetOnFirstDayTheyReceiveFunds() * Tests a scenario in which Alice repeatedly transfers her balance to Baldwin right before the * end of a staking period, only to receive it back shortly after that period starts. */ + @HapiTest private HapiSpec stakeIsManagedCorrectlyInTxnsAroundPeriodBoundaries() { final var alice = "alice"; final var baldwin = "baldwin"; @@ -255,6 +261,7 @@ private HapiSpec stakeIsManagedCorrectlyInTxnsAroundPeriodBoundaries() { * * @return the spec described above */ + @HapiTest private HapiSpec autoRenewalsCanTriggerStakingRewards() { final var initBalance = ONE_HBAR * 1000; final var minimalLifetime = 3; @@ -284,6 +291,7 @@ private HapiSpec autoRenewalsCanTriggerStakingRewards() { .then(cryptoTransfer(tinyBarsFromTo(GENESIS, NODE, 1L))); } + @HapiTest private HapiSpec canBeRewardedWithoutMinStakeIfSoConfigured() { final var patientlyWaiting = "patientlyWaiting"; @@ -694,6 +702,7 @@ private HapiSpec endOfStakingPeriodRecTest() { .logged()); } + @HapiTest private HapiSpec rewardsOfDeletedAreRedirectedToBeneficiary() { final var bob = "bob"; final var deletion = "deletion"; diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/ethereum/EthereumSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/ethereum/EthereumSuite.java index bac306ca9bf2..75952f7974de 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/ethereum/EthereumSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/ethereum/EthereumSuite.java @@ -18,6 +18,7 @@ import static com.hedera.node.app.hapi.utils.CommonUtils.asEvmAddress; import static com.hedera.node.app.service.evm.utils.EthSigsUtils.recoverAddressFromPubKey; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asContract; import static com.hedera.services.bdd.spec.HapiPropertySource.asHexedSolidityAddress; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; @@ -108,8 +109,10 @@ import org.bouncycastle.util.encoders.Hex; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) @SuppressWarnings("java:S5960") public class EthereumSuite extends HapiSuite { diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/ethereum/HelloWorldEthereumSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/ethereum/HelloWorldEthereumSuite.java index c3b2ded22763..2875b1c20397 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/ethereum/HelloWorldEthereumSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/ethereum/HelloWorldEthereumSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.ethereum; +import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiPropertySource.asAccountString; import static com.hedera.services.bdd.spec.HapiPropertySource.asHexedSolidityAddress; import static com.hedera.services.bdd.spec.HapiPropertySource.asSolidityAddress; @@ -76,8 +77,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(SMART_CONTRACT) public class HelloWorldEthereumSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(HelloWorldEthereumSuite.class); private static final long depositAmount = 20_000L; diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/file/FileUpdateSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/file/FileUpdateSuite.java index fc4ca19160fa..a7c8cb5fc148 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/file/FileUpdateSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/file/FileUpdateSuite.java @@ -75,9 +75,11 @@ import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.MAX_STORAGE_IN_PRICE_REGIME_HAS_BEEN_USED; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.MESSAGE_SIZE_TOO_LARGE; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.NOT_SUPPORTED; +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.OK; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.SUCCESS; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.TOKEN_ID_REPEATED_IN_TOKEN_LIST; +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.UNAUTHORIZED; import static com.hederahashgraph.api.proto.java.TokenFreezeStatus.FreezeNotApplicable; import static com.hederahashgraph.api.proto.java.TokenFreezeStatus.Frozen; import static com.hederahashgraph.api.proto.java.TokenFreezeStatus.Unfrozen; @@ -99,7 +101,6 @@ import java.math.BigInteger; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.atomic.AtomicLong; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -184,7 +185,8 @@ public List getSpecsInSuite() { @HapiTest private HapiSpec associateHasExpectedSemantics() { - return defaultHapiSpec("AssociateHasExpectedSemantics") + return propertyPreservingHapiSpec("AssociateHasExpectedSemantics") + .preserving("tokens.maxRelsPerInfoQuery") .given(flattened((Object[]) TokenAssociationSpecs.basicKeysAndTokens())) .when( cryptoCreate("misc").balance(0L), @@ -248,7 +250,7 @@ private HapiSpec optimisticSpecialFileUpdate() { .then(getFileContents(specialFile).hasContents(ignore -> specialFileContents.toByteArray())); } - // It is not implemented yet in SystemFileUpdateFacility line number 127 + @HapiTest private HapiSpec apiPermissionsChangeDynamically() { final var civilian = CIVILIAN; return defaultHapiSpec("ApiPermissionsChangeDynamically") @@ -260,10 +262,13 @@ private HapiSpec apiPermissionsChangeDynamically() { .when( fileUpdate(API_PERMISSIONS) .payingWith(ADDRESS_BOOK_CONTROL) - .erasingProps(Set.of("tokenCreate")), + .overridingProps(Map.of("tokenCreate", "0-1")), getFileContents(API_PERMISSIONS).logged()) .then( - tokenCreate("poc").payingWith(civilian).hasPrecheck(NOT_SUPPORTED), + tokenCreate("poc") + .payingWith(civilian) + .hasPrecheckFrom(NOT_SUPPORTED, OK) + .hasKnownStatus(UNAUTHORIZED), fileUpdate(API_PERMISSIONS) .payingWith(ADDRESS_BOOK_CONTROL) .overridingProps(Map.of("tokenCreate", "0-*")), @@ -449,6 +454,7 @@ private HapiSpec kvLimitsEnforced() { } @SuppressWarnings("java:S5960") + @HapiTest private HapiSpec serviceFeeRefundedIfConsGasExhausted() { final var contract = "User"; final var gasToOffer = Long.parseLong(DEFAULT_MAX_CONS_GAS); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/issues/Issue2051Spec.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/issues/Issue2051Spec.java index 6cee045d9fea..8ad16f15a7c1 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/issues/Issue2051Spec.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/issues/Issue2051Spec.java @@ -73,6 +73,7 @@ private HapiSpec tbdCanPayForItsOwnDeletion() { getTxnRecord("selfFinanced").logged()); } + @HapiTest private HapiSpec transferAccountCannotBeDeleted() { return defaultHapiSpec("TransferAccountCannotBeDeleted") .given(cryptoCreate(PAYER), cryptoCreate(TRANSFER), cryptoCreate("tbd")) @@ -88,6 +89,7 @@ private HapiSpec transferAccountCannotBeDeleted() { getAccountBalance(PAYER).hasTinyBars(approxChangeFromSnapshot(SNAPSHOT, -9384399, 1000))); } + @HapiTest private HapiSpec transferAccountCannotBeDeletedForContractTarget() { return defaultHapiSpec("TransferAccountCannotBeDeletedForContractTarget") .given( diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/leaky/LeakyContractTestsSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/leaky/LeakyContractTestsSuite.java index 0fb6b0e8ba27..fea0b941f857 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/leaky/LeakyContractTestsSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/leaky/LeakyContractTestsSuite.java @@ -340,6 +340,7 @@ private HapiSpec transferErc20TokenFromErc721TokenFails() { .then(getTxnRecord(TRANSFER_TXN).andAllChildRecords().logged()); } + @HapiTest private HapiSpec transferErc20TokenFromContractWithApproval() { final var transferFromOtherContractWithSignaturesTxn = "transferFromOtherContractWithSignaturesTxn"; final var nestedContract = "NestedERC20Contract"; @@ -2035,6 +2036,7 @@ private HapiSpec erc20TransferFromDoesNotWorkIfFlagIsDisabled() { overriding(HEDERA_ALLOWANCES_IS_ENABLED, "true")); } + @HapiTest private HapiSpec whitelistPositiveCase() { final AtomicLong whitelistedCalleeMirrorNum = new AtomicLong(); final AtomicReference tokenID = new AtomicReference<>(); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/records/ContractRecordsSanityCheckSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/records/ContractRecordsSanityCheckSuite.java index b7c2c586110e..1f53374e3207 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/records/ContractRecordsSanityCheckSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/records/ContractRecordsSanityCheckSuite.java @@ -87,6 +87,7 @@ private HapiSpec contractDeleteRecordSanityChecks() { validateRecordTransactionFees("txn")); } + @HapiTest private HapiSpec contractCreateRecordSanityChecks() { return defaultHapiSpec("ContractCreateRecordSanityChecks") .given(flattened( @@ -100,6 +101,7 @@ private HapiSpec contractCreateRecordSanityChecks() { validateRecordTransactionFees("txn")); } + @HapiTest private HapiSpec contractCallWithSendRecordSanityChecks() { return defaultHapiSpec("ContractCallWithSendRecordSanityChecks") .given(flattened( @@ -117,6 +119,7 @@ private HapiSpec contractCallWithSendRecordSanityChecks() { validateRecordTransactionFees("txn")); } + @HapiTest private HapiSpec circularTransfersRecordSanityChecks() { final var contractName = "CircularTransfers"; int numAltruists = 3; @@ -191,6 +194,7 @@ private HapiSpec circularTransfersRecordSanityChecks() { })); } + @HapiTest private HapiSpec contractUpdateRecordSanityChecks() { return defaultHapiSpec("ContractUpdateRecordSanityChecks") .given(flattened( diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/regression/SteadyStateThrottlingCheck.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/regression/SteadyStateThrottlingCheck.java index 58497e4de475..78347da9bc1f 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/regression/SteadyStateThrottlingCheck.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/regression/SteadyStateThrottlingCheck.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.regression; +import static com.hedera.services.bdd.junit.TestTags.TIME_CONSUMING; import static com.hedera.services.bdd.spec.HapiSpec.customHapiSpec; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountBalance; @@ -41,6 +42,7 @@ import com.google.common.base.Stopwatch; import com.google.protobuf.ByteString; +import com.hedera.services.bdd.junit.HapiTest; import com.hedera.services.bdd.junit.HapiTestSuite; import com.hedera.services.bdd.spec.HapiSpec; import com.hedera.services.bdd.spec.HapiSpecOperation; @@ -61,8 +63,14 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.TestMethodOrder; @HapiTestSuite +@TestMethodOrder(OrderAnnotation.class) +@Tag(TIME_CONSUMING) public class SteadyStateThrottlingCheck extends HapiSuite { private static final Logger LOG = LogManager.getLogger(SteadyStateThrottlingCheck.class); @@ -120,6 +128,8 @@ public List getSpecsInSuite() { restoreDevLimits()); } + @HapiTest + @Order(1) private HapiSpec setArtificialLimits() { var artificialLimits = protoDefsFromResource("testSystemFiles/artificial-limits.json"); @@ -131,6 +141,38 @@ private HapiSpec setArtificialLimits() { .contents(artificialLimits.toByteArray())); } + @HapiTest + @Order(2) + private HapiSpec checkXfersTps() { + return checkTps("Xfers", EXPECTED_XFER_TPS, xferOps()); + } + + @HapiTest + @Order(3) + private HapiSpec checkFungibleMintsTps() { + return checkTps("FungibleMints", EXPECTED_FUNGIBLE_MINT_TPS, fungibleMintOps()); + } + + // @HapiTest - This test fails + @Order(4) + private HapiSpec checkContractCallsTps() { + return checkTps("ContractCalls", EXPECTED_CONTRACT_CALL_TPS, scCallOps()); + } + + // @HapiTest - This test fails + @Order(5) + private HapiSpec checkCryptoCreatesTps() { + return checkTps("CryptoCreates", EXPECTED_CRYPTO_CREATE_TPS, cryptoCreateOps()); + } + + // @HapiTest - This test hangs + @Order(6) + private HapiSpec checkBalanceQps() { + return checkBalanceQps(1000, EXPECTED_GET_BALANCE_QPS); + } + + @HapiTest + @Order(7) private HapiSpec restoreDevLimits() { var defaultThrottles = protoDefsFromResource("testSystemFiles/throttles-dev.json"); return defaultHapiSpec("RestoreDevLimits") diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/schedule/ScheduleCreateSpecs.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/schedule/ScheduleCreateSpecs.java index 48f8f2413aaa..e178ae43f817 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/schedule/ScheduleCreateSpecs.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/schedule/ScheduleCreateSpecs.java @@ -337,6 +337,7 @@ private HapiSpec notIdenticalScheduleIfAdminKeyChanges() { .payingWith(FIRST_PAYER)); } + @HapiTest private HapiSpec recognizesIdenticalScheduleEvenWithDifferentDesignatedPayer() { return defaultHapiSpec("recognizesIdenticalScheduleEvenWithDifferentDesignatedPayer") .given( @@ -409,7 +410,7 @@ private HapiSpec infoIncludesTxnIdFromCreationReceipt() { .logged()); } - // @todo('9869') + @HapiTest private HapiSpec preservesRevocationServiceSemanticsForFileDelete() { KeyShape waclShape = listOf(SIMPLE, threshOf(2, 3)); SigControl adequateSigs = waclShape.signedWith(sigs(OFF, sigs(ON, ON, OFF))); @@ -556,7 +557,7 @@ public HapiSpec rejectsFunctionlessTxn() { .payingWith(GENESIS)); } - // Disabled because schedule throttle is not implemented yet + @HapiTest public HapiSpec functionlessTxnBusyWithNonExemptPayer() { return defaultHapiSpec("FunctionlessTxnBusyWithNonExemptPayer") .given() diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/Hip17UnhappyAccountsSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/Hip17UnhappyAccountsSuite.java index fb7221b21f18..89ec93071607 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/Hip17UnhappyAccountsSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/Hip17UnhappyAccountsSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.token; +import static com.hedera.services.bdd.junit.TestTags.TOKEN; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoCreate; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoDelete; @@ -44,8 +45,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(TOKEN) public class Hip17UnhappyAccountsSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(Hip17UnhappyAccountsSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/Hip17UnhappyTokensSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/Hip17UnhappyTokensSuite.java index 4c1f6e3cd0d3..3e7e210e2b4e 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/Hip17UnhappyTokensSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/Hip17UnhappyTokensSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.token; +import static com.hedera.services.bdd.junit.TestTags.TOKEN; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountBalance; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountInfo; @@ -62,8 +63,10 @@ import java.util.Set; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(TOKEN) public class Hip17UnhappyTokensSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(Hip17UnhappyTokensSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenAssociationSpecs.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenAssociationSpecs.java index be2081c492a0..2bddb345410d 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenAssociationSpecs.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenAssociationSpecs.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.token; +import static com.hedera.services.bdd.junit.TestTags.TOKEN; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.NoTokenTransfers.emptyTokenTransfers; import static com.hedera.services.bdd.spec.assertions.SomeFungibleTransfers.changingFungibleBalances; @@ -74,8 +75,10 @@ import java.util.concurrent.atomic.AtomicLong; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(TOKEN) public class TokenAssociationSpecs extends HapiSuite { private static final Logger log = LogManager.getLogger(TokenAssociationSpecs.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenCreateSpecs.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenCreateSpecs.java index 7a0a0536f171..e4b42fc84906 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenCreateSpecs.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenCreateSpecs.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.token; +import static com.hedera.services.bdd.junit.TestTags.TOKEN; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.HapiSpecOperation.UnknownFieldLocation.*; import static com.hedera.services.bdd.spec.assertions.AccountInfoAsserts.accountWith; @@ -74,6 +75,7 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; /** * Validates the {@code TokenCreate} transaction, including its: @@ -83,6 +85,7 @@ * */ @HapiTestSuite +@Tag(TOKEN) public class TokenCreateSpecs extends HapiSuite { private static final Logger log = LogManager.getLogger(TokenCreateSpecs.class); private static final String NON_FUNGIBLE_UNIQUE_FINITE = "non-fungible-unique-finite"; diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenDeleteSpecs.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenDeleteSpecs.java index 80e0c283c87b..07a1f7c3493c 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenDeleteSpecs.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenDeleteSpecs.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.token; +import static com.hedera.services.bdd.junit.TestTags.TOKEN; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountInfo; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getTokenInfo; @@ -46,8 +47,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(TOKEN) public class TokenDeleteSpecs extends HapiSuite { private static final Logger log = LogManager.getLogger(TokenDeleteSpecs.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenFeeScheduleUpdateSpecs.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenFeeScheduleUpdateSpecs.java index 18dbb3176f55..e988c60b59da 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenFeeScheduleUpdateSpecs.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenFeeScheduleUpdateSpecs.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.token; +import static com.hedera.services.bdd.junit.TestTags.TOKEN; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getTokenInfo; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoCreate; @@ -51,8 +52,10 @@ import java.util.OptionalLong; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(TOKEN) public class TokenFeeScheduleUpdateSpecs extends HapiSuite { private static final Logger log = LogManager.getLogger(TokenFeeScheduleUpdateSpecs.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenManagementSpecs.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenManagementSpecs.java index ae03a8324d29..ddf4049bab82 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenManagementSpecs.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenManagementSpecs.java @@ -17,6 +17,7 @@ package com.hedera.services.bdd.suites.token; import static com.google.protobuf.ByteString.copyFromUtf8; +import static com.hedera.services.bdd.junit.TestTags.TOKEN; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountBalance; @@ -76,8 +77,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(TOKEN) public class TokenManagementSpecs extends HapiSuite { private static final Logger log = LogManager.getLogger(TokenManagementSpecs.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenManagementSpecsStateful.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenManagementSpecsStateful.java index e025d1497046..61e397e1d9dc 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenManagementSpecsStateful.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenManagementSpecsStateful.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.token; +import static com.hedera.services.bdd.junit.TestTags.TOKEN; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getTokenInfo; import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoCreate; @@ -43,8 +44,10 @@ import java.util.Map; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(TOKEN) public class TokenManagementSpecsStateful extends HapiSuite { private static final Logger log = LogManager.getLogger(TokenManagementSpecsStateful.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenPauseSpecs.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenPauseSpecs.java index 49512c157f88..5d3b61dac460 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenPauseSpecs.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenPauseSpecs.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.token; +import static com.hedera.services.bdd.junit.TestTags.TOKEN; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountInfo; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getTokenInfo; @@ -69,8 +70,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(TOKEN) public final class TokenPauseSpecs extends HapiSuite { private static final Logger LOG = LogManager.getLogger(TokenPauseSpecs.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenTotalSupplyAfterMintBurnWipeSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenTotalSupplyAfterMintBurnWipeSuite.java index 884d65be0926..6bf803461042 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenTotalSupplyAfterMintBurnWipeSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenTotalSupplyAfterMintBurnWipeSuite.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.token; +import static com.hedera.services.bdd.junit.TestTags.TOKEN; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountBalance; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountInfo; @@ -39,8 +40,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(TOKEN) public class TokenTotalSupplyAfterMintBurnWipeSuite extends HapiSuite { private static final Logger log = LogManager.getLogger(TokenTotalSupplyAfterMintBurnWipeSuite.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenTransactSpecs.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenTransactSpecs.java index 3b9e3439092e..ee2c9982f64a 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenTransactSpecs.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenTransactSpecs.java @@ -17,6 +17,7 @@ package com.hedera.services.bdd.suites.token; import static com.google.protobuf.ByteString.copyFromUtf8; +import static com.hedera.services.bdd.junit.TestTags.TOKEN; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.assertions.AccountInfoAsserts.accountWith; import static com.hedera.services.bdd.spec.assertions.AccountInfoAsserts.changeFromSnapshot; @@ -95,8 +96,10 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(TOKEN) public class TokenTransactSpecs extends HapiSuite { private static final Logger log = LogManager.getLogger(TokenTransactSpecs.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenUpdateSpecs.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenUpdateSpecs.java index 90c59080fc3e..e83d3236bf34 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenUpdateSpecs.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/TokenUpdateSpecs.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.token; +import static com.hedera.services.bdd.junit.TestTags.TOKEN; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountBalance; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountInfo; @@ -78,8 +79,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(TOKEN) public class TokenUpdateSpecs extends HapiSuite { private static final Logger log = LogManager.getLogger(TokenUpdateSpecs.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/UniqueTokenManagementSpecs.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/UniqueTokenManagementSpecs.java index 68088f86c79f..c4cb1d00818f 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/UniqueTokenManagementSpecs.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/token/UniqueTokenManagementSpecs.java @@ -16,6 +16,7 @@ package com.hedera.services.bdd.suites.token; +import static com.hedera.services.bdd.junit.TestTags.TOKEN; import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec; import static com.hedera.services.bdd.spec.HapiSpec.onlyDefaultHapiSpec; import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountBalance; @@ -77,8 +78,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; @HapiTestSuite +@Tag(TOKEN) public class UniqueTokenManagementSpecs extends HapiSuite { private static final org.apache.logging.log4j.Logger log = LogManager.getLogger(UniqueTokenManagementSpecs.class); diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/utils/validation/ValidationScenarios.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/utils/validation/ValidationScenarios.java index db0178d845b2..57478d978ee7 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/utils/validation/ValidationScenarios.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/utils/validation/ValidationScenarios.java @@ -182,6 +182,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Assertions; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; import org.yaml.snakeyaml.introspector.Property; @@ -1800,7 +1802,7 @@ private static void assertValidParams() { } private static void readConfig() { - var yamlIn = new Yaml(new Constructor(ValidationConfig.class)); + var yamlIn = new Yaml(new Constructor(ValidationConfig.class, new LoaderOptions())); try { System.out.println("Config loc: " + params.getConfigLoc()); validationConfig = yamlIn.load(Files.newInputStream(Paths.get(params.getConfigLoc()))); @@ -1924,6 +1926,10 @@ private static void persistUpdatedConfig() { private static class SkipNullRepresenter extends Representer { + public SkipNullRepresenter() { + super(new DumperOptions()); + } + @Override protected NodeTuple representJavaBeanProperty( Object javaBean, Property property, Object propertyValue, Tag customTag) { diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/validation/PostUpgradeValidation.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/validation/PostUpgradeValidation.java index fc49f0980ac1..55eadc1f4f63 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/validation/PostUpgradeValidation.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/validation/PostUpgradeValidation.java @@ -25,6 +25,7 @@ import java.util.concurrent.Callable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; import picocli.CommandLine; @@ -91,7 +92,7 @@ public static void main(String... args) { } private void loadConfig() { - var yamlIn = new Yaml(new Constructor(TopLevelConfig.class)); + var yamlIn = new Yaml(new Constructor(TopLevelConfig.class, new LoaderOptions())); try { config = yamlIn.load(Files.newInputStream(Paths.get(CONFIG_LOC))); } catch (IOException e) { diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/yahcli/config/ConfigManager.java b/hedera-node/test-clients/src/main/java/com/hedera/services/yahcli/config/ConfigManager.java index 7cd55c87ce2e..ae9f5464e96d 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/yahcli/config/ConfigManager.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/yahcli/config/ConfigManager.java @@ -35,6 +35,7 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.*; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; import picocli.CommandLine; @@ -57,7 +58,7 @@ public ConfigManager(Yahcli yahcli, GlobalConfig global) { static ConfigManager from(Yahcli yahcli) throws IOException { var yamlLoc = yahcli.getConfigLoc(); - var yamlIn = new Yaml(new Constructor(GlobalConfig.class)); + var yamlIn = new Yaml(new Constructor(GlobalConfig.class, new LoaderOptions())); try (InputStream fin = Files.newInputStream(Paths.get(yamlLoc))) { GlobalConfig globalConfig = yamlIn.load(fin); return new ConfigManager(yahcli, globalConfig); diff --git a/hedera-node/test-clients/src/main/java/module-info.java b/hedera-node/test-clients/src/main/java/module-info.java index f771cc3cf0f2..168bc078a47d 100644 --- a/hedera-node/test-clients/src/main/java/module-info.java +++ b/hedera-node/test-clients/src/main/java/module-info.java @@ -36,7 +36,7 @@ requires org.bouncycastle.provider; requires org.hyperledger.besu.datatypes; requires org.hyperledger.besu.evm; - requires org.hyperledger.besu.internal.algorithms; + requires org.hyperledger.besu.internal.crypto; requires org.json; requires org.opentest4j; requires tuweni.units; diff --git a/hedera-node/test-clients/src/main/resource/spec-default.properties b/hedera-node/test-clients/src/main/resource/spec-default.properties index 62b42f171306..74aa7244b040 100644 --- a/hedera-node/test-clients/src/main/resource/spec-default.properties +++ b/hedera-node/test-clients/src/main/resource/spec-default.properties @@ -39,9 +39,9 @@ default.payer=0.0.2 recordStream.path=hedera-node/data/recordstreams/record0.0.3 recordStream.autoSnapshotManagement=false #recordStream.autoSnapshotTarget=MONO_SERVICE -#recordStream.autoMatchTarget=HAPI_TEST +recordStream.autoMatchTarget=HAPI_TEST recordStream.autoSnapshotTarget=MONO_SERVICE -recordStream.autoMatchTarget=MONO_SERVICE +#recordStream.autoMatchTarget=MONO_SERVICE #default.payer=0.0.50 #default.payer=0.0.950 default.payer.key= diff --git a/platform-sdk/docs/base/test-support/test-support.md b/platform-sdk/docs/base/test-support/test-support.md index 46c581e7ec3b..f9e794a5a3f9 100644 --- a/platform-sdk/docs/base/test-support/test-support.md +++ b/platform-sdk/docs/base/test-support/test-support.md @@ -61,4 +61,39 @@ executed in isolation (see `org.junit.jupiter.api.parallel.Isolated`). ### Context support The `@WithContext`, `@WithGlobalContext`, `@WithThreadLocalContext` annotation are documented in the chapter of -the [Context API](./../context/context.md). \ No newline at end of file +the [Context API](./../context/context.md). + +### Executor support + +The `@WithTestExecutor` annotation is used to inject a `TestExecutor` instance into a test. Each test using +`@WithTestExecutor` runs in isolation, ensuring that multiple tests do not share the same underlying thread pool +concurrently. This isolation helps prevent side effects between tests due to shared resources. + +#### Usage + +```java +@WithTestExecutor +public class MyConcurrentTest { + // Your concurrent test methods here... +} +``` +#### Example + +```java +@WithTestExecutor +public class TestExecutorExample { + @Inject + TestExecutor testExecutor; + + // more code ... + + @Test + void testWithConfig() { + // given + final List runnables = + IntStream.range(0, 20).mapToObj(this::createRunnable).toList(); + testExecutor.executeAndWait(runnables); + } +} +``` + diff --git a/platform-sdk/platform-apps/tests/PlatformTestingTool/build.gradle.kts b/platform-sdk/platform-apps/tests/PlatformTestingTool/build.gradle.kts index 46b904a0dc98..d5dc1a3707c0 100644 --- a/platform-sdk/platform-apps/tests/PlatformTestingTool/build.gradle.kts +++ b/platform-sdk/platform-apps/tests/PlatformTestingTool/build.gradle.kts @@ -24,6 +24,7 @@ plugins { application.mainClass.set("com.swirlds.demo.platform.PlatformTestingToolMain") testModuleInfo { + requires("com.swirlds.common.testing") requires("com.swirlds.test.framework") requires("org.apache.logging.log4j.core") requires("org.bouncycastle.provider") diff --git a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/merkle/map/internal/DummyExpectedFCMFamily.java b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/merkle/map/internal/DummyExpectedFCMFamily.java index c20c74ce9d3c..aeb6ac4e3bc9 100644 --- a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/merkle/map/internal/DummyExpectedFCMFamily.java +++ b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/merkle/map/internal/DummyExpectedFCMFamily.java @@ -16,8 +16,8 @@ package com.swirlds.demo.merkle.map.internal; -import com.swirlds.common.test.set.RandomAccessHashSet; -import com.swirlds.common.test.set.RandomAccessSet; +import com.swirlds.common.test.fixtures.set.RandomAccessHashSet; +import com.swirlds.common.test.fixtures.set.RandomAccessSet; import com.swirlds.demo.merkle.map.FCMConfig; import com.swirlds.demo.merkle.map.FCMFamily; import com.swirlds.demo.platform.PAYLOAD_TYPE; diff --git a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/merkle/map/internal/ExpectedFCMFamilyImpl.java b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/merkle/map/internal/ExpectedFCMFamilyImpl.java index b17e4428d9cb..cd27707c1959 100644 --- a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/merkle/map/internal/ExpectedFCMFamilyImpl.java +++ b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/merkle/map/internal/ExpectedFCMFamilyImpl.java @@ -30,7 +30,7 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.swirlds.common.crypto.Hash; import com.swirlds.common.merkle.MerkleNode; -import com.swirlds.common.test.set.RandomAccessHashSet; +import com.swirlds.common.test.fixtures.set.RandomAccessHashSet; import com.swirlds.demo.merkle.map.FCMConfig; import com.swirlds.demo.merkle.map.FCMFamily; import com.swirlds.demo.merkle.map.FCMTransactionUtils; diff --git a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/module-info.java b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/module-info.java index 548b0bf63789..a86949d384ac 100644 --- a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/module-info.java +++ b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/module-info.java @@ -29,7 +29,6 @@ requires com.google.protobuf; requires com.swirlds.base; requires com.swirlds.common.test.fixtures; - requires com.swirlds.common.testing; requires com.swirlds.common; requires com.swirlds.fchashmap; requires com.swirlds.fcqueue; diff --git a/platform-sdk/swirlds-base/src/main/java/com/swirlds/base/context/Context.java b/platform-sdk/swirlds-base/src/main/java/com/swirlds/base/context/Context.java index 4a3715e41950..7947cf67eeca 100644 --- a/platform-sdk/swirlds-base/src/main/java/com/swirlds/base/context/Context.java +++ b/platform-sdk/swirlds-base/src/main/java/com/swirlds/base/context/Context.java @@ -35,56 +35,27 @@ public interface Context { * * @param key the key * @param value the value + * @return an {@link AutoCloseable} that can be used to remove the key-value pair from the context + * @throws NullPointerException if the key or value is null */ - void add(@NonNull final String key, @NonNull final String value); + AutoCloseable add(@NonNull String key, @NonNull String value); /** * remove a key-value pair from the context if available. * * @param key the key to remove */ - void remove(@NonNull final String key); - - /** - * Adds a key-value pair to the context. The returned {@link AutoCloseable} can be used to remove the value for the - * given key. - *

    - * Internally the context does not use a stack to store changes. If the value has been changed between this call and - * any future call that sets the same key, the new value will be removed. - * - * @param key the key - * @param value the value - * @return an {@link AutoCloseable} that can be used to remove the key-value pair from the context - * @throws NullPointerException if the key or value is null - */ - @NonNull - default AutoCloseable addWithRemovalOnClose(@NonNull final String key, @NonNull final String value) { - add(key, value); - return () -> remove(key); - } + void remove(@NonNull String key); /** * Adds a key-value pair to the context. * * @param key the key * @param value the value - */ - @NonNull - default void add(@NonNull final String key, final int value) { - add(key, Integer.toString(value)); - } - - /** - * Adds a key-value pair to the context. The returned {@link AutoCloseable} can be used to remove the value for the given key. - *

    - * Internally the context does not use a stack to store changes. If the value has been changed between this call and any future call that sets the same key, the new value will be removed. - * @param key the key - * @param value the value * @return an {@link AutoCloseable} that can be used to remove the key-value pair from the context */ - @NonNull - default AutoCloseable addWithRemovalOnClose(@NonNull final String key, final int value) { - return addWithRemovalOnClose(key, Integer.toString(value)); + default AutoCloseable add(@NonNull String key, int value) { + return add(key, Integer.toString(value)); } /** @@ -92,23 +63,10 @@ default AutoCloseable addWithRemovalOnClose(@NonNull final String key, final int * * @param key the key * @param value the value - */ - @NonNull - default void add(@NonNull final String key, final long value) { - add(key, Long.toString(value)); - } - - /** - * Adds a key-value pair to the context. The returned {@link AutoCloseable} can be used to remove the value for the given key. - *

    - * Internally the context does not use a stack to store changes. If the value has been changed between this call and any future call that sets the same key, the new value will be removed. - * @param key the key - * @param value the value * @return an {@link AutoCloseable} that can be used to remove the key-value pair from the context */ - @NonNull - default AutoCloseable addWithRemovalOnClose(@NonNull final String key, final long value) { - return addWithRemovalOnClose(key, Long.toString(value)); + default AutoCloseable add(@NonNull String key, long value) { + return add(key, Long.toString(value)); } /** @@ -116,26 +74,10 @@ default AutoCloseable addWithRemovalOnClose(@NonNull final String key, final lon * * @param key the key * @param value the value - */ - @NonNull - default void add(@NonNull final String key, final float value) { - add(key, Float.toString(value)); - } - - /** - * Adds a key-value pair to the context. The returned {@link AutoCloseable} can be used to remove the value for the - * given key. - *

    - * Internally the context does not use a stack to store changes. If the value has been changed between this call and - * any future call that sets the same key, the new value will be removed. - * - * @param key the key - * @param value the value * @return an {@link AutoCloseable} that can be used to remove the key-value pair from the context */ - @NonNull - default AutoCloseable addWithRemovalOnClose(@NonNull final String key, final float value) { - return addWithRemovalOnClose(key, Float.toString(value)); + default AutoCloseable add(@NonNull String key, float value) { + return add(key, Float.toString(value)); } /** @@ -143,26 +85,10 @@ default AutoCloseable addWithRemovalOnClose(@NonNull final String key, final flo * * @param key the key * @param value the value - */ - @NonNull - default void add(@NonNull final String key, final double value) { - add(key, Double.toString(value)); - } - - /** - * Adds a key-value pair to the context. The returned {@link AutoCloseable} can be used to remove the value for the - * given key. - *

    - * Internally the context does not use a stack to store changes. If the value has been changed between this call and - * any future call that sets the same key, the new value will be removed. - * - * @param key the key - * @param value the value * @return an {@link AutoCloseable} that can be used to remove the key-value pair from the context */ - @NonNull - default AutoCloseable addWithRemovalOnClose(@NonNull final String key, final double value) { - return addWithRemovalOnClose(key, Double.toString(value)); + default AutoCloseable add(@NonNull String key, double value) { + return add(key, Double.toString(value)); } /** @@ -170,26 +96,10 @@ default AutoCloseable addWithRemovalOnClose(@NonNull final String key, final dou * * @param key the key * @param value the value - */ - @NonNull - default void add(@NonNull final String key, final boolean value) { - add(key, Boolean.toString(value)); - } - - /** - * Adds a key-value pair to the context. The returned {@link AutoCloseable} can be used to remove the value for the - * given key. - *

    - * Internally the context does not use a stack to store changes. If the value has been changed between this call and - * any future call that sets the same key, the new value will be removed. - * - * @param key the key - * @param value the value * @return an {@link AutoCloseable} that can be used to remove the key-value pair from the context */ - @NonNull - default AutoCloseable addWithRemovalOnClose(@NonNull final String key, final boolean value) { - return addWithRemovalOnClose(key, Boolean.toString(value)); + default AutoCloseable add(@NonNull String key, boolean value) { + return add(key, Boolean.toString(value)); } /** diff --git a/platform-sdk/swirlds-base/src/main/java/com/swirlds/base/context/internal/GlobalContext.java b/platform-sdk/swirlds-base/src/main/java/com/swirlds/base/context/internal/GlobalContext.java index 8997cb91a7c1..7dd83ae7c27a 100644 --- a/platform-sdk/swirlds-base/src/main/java/com/swirlds/base/context/internal/GlobalContext.java +++ b/platform-sdk/swirlds-base/src/main/java/com/swirlds/base/context/internal/GlobalContext.java @@ -44,10 +44,12 @@ private GlobalContext() { } @Override - public void add(@NonNull String key, @NonNull String value) { + public AutoCloseable add(@NonNull String key, @NonNull String value) { Objects.requireNonNull(key, "key must not be null"); Objects.requireNonNull(value, "value must not be null"); + contextMap.put(key, value); + return () -> remove(key); } @Override diff --git a/platform-sdk/swirlds-base/src/main/java/com/swirlds/base/context/internal/ThreadLocalContext.java b/platform-sdk/swirlds-base/src/main/java/com/swirlds/base/context/internal/ThreadLocalContext.java index 77d8e29510ba..f8de17b00414 100644 --- a/platform-sdk/swirlds-base/src/main/java/com/swirlds/base/context/internal/ThreadLocalContext.java +++ b/platform-sdk/swirlds-base/src/main/java/com/swirlds/base/context/internal/ThreadLocalContext.java @@ -44,7 +44,7 @@ private ThreadLocalContext() { } @Override - public void add(@NonNull String key, @NonNull String value) { + public AutoCloseable add(@NonNull String key, @NonNull String value) { Objects.requireNonNull(key, "key must not be null"); Objects.requireNonNull(value, "value must not be null"); @@ -54,6 +54,7 @@ public void add(@NonNull String key, @NonNull String value) { contextThreadLocal.set(contextMap); } contextMap.put(key, value); + return () -> remove(key); } @Override diff --git a/platform-sdk/swirlds-base/src/main/java/module-info.java b/platform-sdk/swirlds-base/src/main/java/module-info.java index c39990dbe064..0cc6ea2a2020 100644 --- a/platform-sdk/swirlds-base/src/main/java/module-info.java +++ b/platform-sdk/swirlds-base/src/main/java/module-info.java @@ -6,7 +6,8 @@ exports com.swirlds.base.utility; exports com.swirlds.base.context; exports com.swirlds.base.context.internal to - com.swirlds.base.test.fixtures; + com.swirlds.base.test.fixtures, + com.swirlds.logging; requires static com.github.spotbugs.annotations; } diff --git a/platform-sdk/swirlds-base/src/test/java/com/swirlds/base/context/GlobalContextTest.java b/platform-sdk/swirlds-base/src/test/java/com/swirlds/base/context/GlobalContextTest.java index b513b6094867..e50af3a1518e 100644 --- a/platform-sdk/swirlds-base/src/test/java/com/swirlds/base/context/GlobalContextTest.java +++ b/platform-sdk/swirlds-base/src/test/java/com/swirlds/base/context/GlobalContextTest.java @@ -31,14 +31,14 @@ void testNullKeyOrValue() { GlobalContext context = GlobalContext.getInstance(); // then - Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, "value")); - Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, 1)); - Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, 1L)); - Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, 1.0D)); - Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, 1.0F)); - Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, true)); - Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose("foo", null)); - Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, null)); + Assertions.assertThrows(NullPointerException.class, () -> context.add(null, "value")); + Assertions.assertThrows(NullPointerException.class, () -> context.add(null, 1)); + Assertions.assertThrows(NullPointerException.class, () -> context.add(null, 1L)); + Assertions.assertThrows(NullPointerException.class, () -> context.add(null, 1.0D)); + Assertions.assertThrows(NullPointerException.class, () -> context.add(null, 1.0F)); + Assertions.assertThrows(NullPointerException.class, () -> context.add(null, true)); + Assertions.assertThrows(NullPointerException.class, () -> context.add("foo", null)); + Assertions.assertThrows(NullPointerException.class, () -> context.add(null, null)); } @Test @@ -47,12 +47,12 @@ void testAllPut() { GlobalContext context = GlobalContext.getInstance(); // when - context.addWithRemovalOnClose("key-string", "value"); - context.addWithRemovalOnClose("key-int", 1); - context.addWithRemovalOnClose("key-long", 1L); - context.addWithRemovalOnClose("key-double", 1.0D); - context.addWithRemovalOnClose("key-float", 1.0F); - context.addWithRemovalOnClose("key-boolean", true); + context.add("key-string", "value"); + context.add("key-int", 1); + context.add("key-long", 1L); + context.add("key-double", 1.0D); + context.add("key-float", 1.0F); + context.add("key-boolean", true); // then final Map contextMap = context.getContextMap(); @@ -71,9 +71,9 @@ void testOverwrite() { GlobalContext context = GlobalContext.getInstance(); // when - context.addWithRemovalOnClose("key", "a"); - context.addWithRemovalOnClose("key", "b"); - context.addWithRemovalOnClose("key", "c"); + context.add("key", "a"); + context.add("key", "b"); + context.add("key", "c"); // then final Map contextMap = context.getContextMap(); @@ -87,7 +87,7 @@ void testRemove() { GlobalContext context = GlobalContext.getInstance(); // when - context.addWithRemovalOnClose("key", "a"); + context.add("key", "a"); context.remove("key"); // then @@ -108,8 +108,8 @@ void testRemoveNullKey() { void testClear() { // given GlobalContext context = GlobalContext.getInstance(); - context.addWithRemovalOnClose("key", "a"); - context.addWithRemovalOnClose("key-2", "a"); + context.add("key", "a"); + context.add("key-2", "a"); // when context.clear(); @@ -123,7 +123,7 @@ void testClear() { void testAutocloseable() { // given GlobalContext context = GlobalContext.getInstance(); - AutoCloseable closeable = context.addWithRemovalOnClose("key", "a"); + AutoCloseable closeable = context.add("key", "a"); // when Assertions.assertDoesNotThrow(() -> closeable.close()); diff --git a/platform-sdk/swirlds-base/src/test/java/com/swirlds/base/context/ThreadLocalContextTest.java b/platform-sdk/swirlds-base/src/test/java/com/swirlds/base/context/ThreadLocalContextTest.java index 00fc91a3adc3..834a0a2d3047 100644 --- a/platform-sdk/swirlds-base/src/test/java/com/swirlds/base/context/ThreadLocalContextTest.java +++ b/platform-sdk/swirlds-base/src/test/java/com/swirlds/base/context/ThreadLocalContextTest.java @@ -16,16 +16,12 @@ package com.swirlds.base.context; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; - import com.swirlds.base.context.internal.ThreadLocalContext; import com.swirlds.base.test.fixtures.context.WithContext; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @WithContext @@ -37,14 +33,14 @@ void testNullKeyOrValue() { ThreadLocalContext context = ThreadLocalContext.getInstance(); // then - assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, "value")); - assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, 1)); - assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, 1L)); - assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, 1.0D)); - assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, 1.0F)); - assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, true)); - assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose("foo", null)); - assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, null)); + Assertions.assertThrows(NullPointerException.class, () -> context.add(null, "value")); + Assertions.assertThrows(NullPointerException.class, () -> context.add(null, 1)); + Assertions.assertThrows(NullPointerException.class, () -> context.add(null, 1L)); + Assertions.assertThrows(NullPointerException.class, () -> context.add(null, 1.0D)); + Assertions.assertThrows(NullPointerException.class, () -> context.add(null, 1.0F)); + Assertions.assertThrows(NullPointerException.class, () -> context.add(null, true)); + Assertions.assertThrows(NullPointerException.class, () -> context.add("foo", null)); + Assertions.assertThrows(NullPointerException.class, () -> context.add(null, null)); } @Test @@ -53,22 +49,22 @@ void testAllPut() { ThreadLocalContext context = ThreadLocalContext.getInstance(); // when - context.addWithRemovalOnClose("key-string", "value"); - context.addWithRemovalOnClose("key-int", 1); - context.addWithRemovalOnClose("key-long", 1L); - context.addWithRemovalOnClose("key-double", 1.0D); - context.addWithRemovalOnClose("key-float", 1.0F); - context.addWithRemovalOnClose("key-boolean", true); + context.add("key-string", "value"); + context.add("key-int", 1); + context.add("key-long", 1L); + context.add("key-double", 1.0D); + context.add("key-float", 1.0F); + context.add("key-boolean", true); // then final Map contextMap = context.getContextMap(); - assertEquals(6, contextMap.size()); - assertEquals("value", contextMap.get("key-string")); - assertEquals("1", contextMap.get("key-int")); - assertEquals("1", contextMap.get("key-long")); - assertEquals("1.0", contextMap.get("key-double")); - assertEquals("1.0", contextMap.get("key-float")); - assertEquals("true", contextMap.get("key-boolean")); + Assertions.assertEquals(6, contextMap.size()); + Assertions.assertEquals("value", contextMap.get("key-string")); + Assertions.assertEquals("1", contextMap.get("key-int")); + Assertions.assertEquals("1", contextMap.get("key-long")); + Assertions.assertEquals("1.0", contextMap.get("key-double")); + Assertions.assertEquals("1.0", contextMap.get("key-float")); + Assertions.assertEquals("true", contextMap.get("key-boolean")); } @Test @@ -77,14 +73,14 @@ void testOverwrite() { ThreadLocalContext context = ThreadLocalContext.getInstance(); // when - context.addWithRemovalOnClose("key", "a"); - context.addWithRemovalOnClose("key", "b"); - context.addWithRemovalOnClose("key", "c"); + context.add("key", "a"); + context.add("key", "b"); + context.add("key", "c"); // then final Map contextMap = context.getContextMap(); - assertEquals(1, contextMap.size()); - assertEquals("c", contextMap.get("key")); + Assertions.assertEquals(1, contextMap.size()); + Assertions.assertEquals("c", contextMap.get("key")); } @Test @@ -93,12 +89,12 @@ void testRemove() { ThreadLocalContext context = ThreadLocalContext.getInstance(); // when - context.addWithRemovalOnClose("key", "a"); + context.add("key", "a"); context.remove("key"); // then final Map contextMap = context.getContextMap(); - assertEquals(0, contextMap.size()); + Assertions.assertEquals(0, contextMap.size()); } @Test @@ -107,36 +103,36 @@ void testRemoveNullKey() { ThreadLocalContext context = ThreadLocalContext.getInstance(); // then - assertThrows(NullPointerException.class, () -> context.remove(null)); + Assertions.assertThrows(NullPointerException.class, () -> context.remove(null)); } @Test void testClear() { // given ThreadLocalContext context = ThreadLocalContext.getInstance(); - context.addWithRemovalOnClose("key", "a"); - context.addWithRemovalOnClose("key-2", "a"); + context.add("key", "a"); + context.add("key-2", "a"); // when context.clear(); // then final Map contextMap = context.getContextMap(); - assertEquals(0, contextMap.size()); + Assertions.assertEquals(0, contextMap.size()); } @Test void testAutocloseable() { // given ThreadLocalContext context = ThreadLocalContext.getInstance(); - AutoCloseable closeable = context.addWithRemovalOnClose("key", "a"); + AutoCloseable closeable = context.add("key", "a"); // when - assertDoesNotThrow(() -> closeable.close()); + Assertions.assertDoesNotThrow(() -> closeable.close()); // then final Map contextMap = context.getContextMap(); - assertEquals(0, contextMap.size()); + Assertions.assertEquals(0, contextMap.size()); } @Test @@ -150,14 +146,14 @@ void testOnDifferentThreads() throws Exception { // when final Map mapFromExecutor1 = executor1 .submit(() -> { - context.addWithRemovalOnClose("key", "a1"); + context.add("key", "a1"); return context.getContextMap(); }) .get(); final Map mapFromExecutor2 = executor2 .submit(() -> { - context.addWithRemovalOnClose("key", "a2"); + context.add("key", "a2"); return context.getContextMap(); }) .get(); @@ -168,15 +164,15 @@ void testOnDifferentThreads() throws Exception { .get(); // then - assertNotNull(mapFromExecutor1); - assertEquals(1, mapFromExecutor1.size()); - assertEquals("a1", mapFromExecutor1.get("key")); + Assertions.assertNotNull(mapFromExecutor1); + Assertions.assertEquals(1, mapFromExecutor1.size()); + Assertions.assertEquals("a1", mapFromExecutor1.get("key")); - assertNotNull(mapFromExecutor2); - assertEquals(1, mapFromExecutor2.size()); - assertEquals("a2", mapFromExecutor2.get("key")); + Assertions.assertNotNull(mapFromExecutor2); + Assertions.assertEquals(1, mapFromExecutor2.size()); + Assertions.assertEquals("a2", mapFromExecutor2.get("key")); - assertNotNull(mapFromExecutor3); - assertEquals(0, mapFromExecutor3.size()); + Assertions.assertNotNull(mapFromExecutor3); + Assertions.assertEquals(0, mapFromExecutor3.size()); } } diff --git a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/TestExecutor.java b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/TestExecutor.java new file mode 100644 index 000000000000..b3bdc126b4eb --- /dev/null +++ b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/TestExecutor.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.base.test.fixtures.concurrent; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeoutException; + +/** + * A test executor that can be used to run tasks in parallel. The executor is responsible for managing the threads that + * are used to run the tasks. The executor is also responsible for waiting for the tasks to complete. All threads that + * are used are daemon threads. All blocking methods calls will block for a maximum duration that is defined when + * creating the executor. + */ +public interface TestExecutor { + + /** + * Executes the given runnables in parallel. This method will block until all the callables have completed. If the + * callables do not return within the maximum wait time, then the callables will be cancelled and a + * {@link TimeoutException} will be thrown. + * + * @param runnables the runnables to execute + */ + void executeAndWait(Collection runnables); + + /** + * Executes the given runnables in parallel. This method will block until all the callables have completed. If the + * callables do not return within the maximum wait time, then the callables will be cancelled and a + * {@link TimeoutException} will be thrown. + * + * @param runnables the runnables to execute + */ + void executeAndWait(Runnable... runnables); + + /** + * Executes the given callables in parallel. This method will block until all the callables have completed. If the + * callables do not return within the maximum wait time, then the callables will be cancelled and a + * {@link TimeoutException} will be thrown. + * + * @param callables the callables to execute + * @param the type of the callable result + * @return the results of the callables + */ + List submitAndWait(Collection> callables); + + /** + * Executes the given callables in parallel. This method will block until all the callables have completed. If the + * callables do not return within the maximum wait time, then the callables will be cancelled and a + * {@link TimeoutException} will be thrown. + * + * @param callables the callables to execute + * @param the type of the callable result + * @return the results of the callables + */ + List submitAndWait(Callable... callables); +} diff --git a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/WithTestExecutor.java b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/WithTestExecutor.java new file mode 100644 index 000000000000..758afae6a19b --- /dev/null +++ b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/WithTestExecutor.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.base.test.fixtures.concurrent; + +import com.swirlds.base.test.fixtures.concurrent.internal.TestExecutorExtension; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.junit.jupiter.api.extension.ExtendWith; + +/** + * This annotation is used to inject a {@link TestExecutor} instance into a test. + * + * @see TestExecutor + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@ExtendWith(TestExecutorExtension.class) +public @interface WithTestExecutor {} diff --git a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/internal/ConcurrentTestSupport.java b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/internal/ConcurrentTestSupport.java new file mode 100644 index 000000000000..a02880276bd4 --- /dev/null +++ b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/internal/ConcurrentTestSupport.java @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.base.test.fixtures.concurrent.internal; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import com.swirlds.base.test.fixtures.concurrent.TestExecutor; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * A utility class for executing and waiting for concurrent tasks using a thread pool. + */ +public class ConcurrentTestSupport implements TestExecutor { + + private static final ExecutorService SINGLE_EXECUTOR = Executors.newSingleThreadExecutor(r -> { + final Thread thread = new Thread(r); + thread.setName("ParallelStressTester-SingleExecutor"); + thread.setDaemon(true); + return thread; + }); + + private final AtomicLong poolThreadCounter = new AtomicLong(0); + + private final ExecutorService poolExecutor = Executors.newCachedThreadPool(r -> { + final Thread thread = new Thread(r); + thread.setName("ParallelStressTester-Pool-" + poolThreadCounter.getAndIncrement()); + thread.setDaemon(true); + return thread; + }); + + private final Duration maxWaitTime; + + /** + * Constructs a ConcurrentTestSupport instance with the specified maximum wait time. + * + * @param maxWaitTime The maximum time to wait for task completion. + * Must not be null. + */ + public ConcurrentTestSupport(@NonNull final Duration maxWaitTime) { + this.maxWaitTime = Objects.requireNonNull(maxWaitTime, "maxWaitTime must not be null"); + } + + /** + * Constructs a ConcurrentTestSupport instance with a default maximum wait time of 1 minute. + */ + public ConcurrentTestSupport() { + this(Duration.ofMinutes(1)); + } + + /** + * Executes a collection of Runnables concurrently and waits for their completion. + * + * @param runnables The collection of Runnables to execute. + */ + public void executeAndWait(@NonNull final Collection runnables) { + final List> callables = runnables.stream() + .map(r -> (Callable) () -> { + r.run(); + return null; + }) + .toList(); + submitAndWait(callables); + } + + /** + * Executes an array of Runnables concurrently and waits for their completion. + * + * @param runnable An array of Runnables to execute. + */ + public void executeAndWait(@NonNull final Runnable... runnable) { + executeAndWait(List.of(runnable)); + } + + /** + * Submits a collection of Callables for execution concurrently and waits for their results. + * + * @param callables The collection of Callables to submit. + * @param The type of the results returned by the Callables. + * @return A list of results from the executed Callables. + */ + @SuppressWarnings("unchecked") + @NonNull + public List submitAndWait(@NonNull final Collection> callables) { + Objects.requireNonNull(callables, "callables must not be null"); + return submitAndWait(callables.toArray(new Callable[0])); + } + + /** + * Submits an array of Callables for execution concurrently and waits for their results. + * + * @param callables An array of Callables to submit. + * @param The type of the results returned by the Callables. + * @return A list of results from the executed Callables. + */ + @SafeVarargs + @NonNull + public final List submitAndWait(@NonNull final Callable... callables) { + final Lock callLock = new ReentrantLock(); + final Condition allPassedToExecutor = callLock.newCondition(); + callLock.lock(); + try { + final Future> futureForAll = SINGLE_EXECUTOR.submit(() -> { + final List> futures = new ArrayList<>(); + callLock.lock(); + try { + Arrays.stream(callables).map(poolExecutor::submit).forEach(futures::add); + allPassedToExecutor.signal(); // now all futures in results and the original method can return + // In the single executor singleton we will wait until all tasks are done. + // By doing so we ensure that only 1 call to this utils is executed in parallel. All other calls + // will be queued. + try { + return waitForAllDone(futures); + } catch (Exception e) { + futures.forEach(f -> f.cancel(true)); + throw new RuntimeException("Error in wait", e); + } + } finally { + callLock.unlock(); + } + }); + allPassedToExecutor.await(); + try { + return waitForDone(futureForAll); + } catch (Exception e) { + throw new RuntimeException("Error in wait", e); + } + } catch (Exception e) { + throw new RuntimeException("Error in parallel execution", e); + } finally { + callLock.unlock(); + } + } + + /** + * Waits for the completion of a Future and retrieves its result. + * + * @param future The Future to wait for. + * @param The type of the result. + * @return The result of the Future. + * @throws InterruptedException If the waiting thread is interrupted. + * @throws ExecutionException If an exception occurs while executing the Future. + * @throws TimeoutException If the waiting time exceeds the maximum wait time. + */ + @NonNull + private T waitForDone(@NonNull final Future future) + throws InterruptedException, ExecutionException, TimeoutException { + return waitForAllDone(List.of(future)).get(0); + } + + /** + * Waits for the completion of a list of Futures and retrieves their results. + * + * @param futures The list of Futures to wait for. + * @param The type of the results. + * @return A list of results from the Futures. + * @throws InterruptedException If the waiting thread is interrupted. + * @throws ExecutionException If an exception occurs while executing any of the Futures. + * @throws TimeoutException If the waiting time exceeds the maximum wait time. + */ + @NonNull + private List waitForAllDone(@NonNull final List> futures) + throws InterruptedException, ExecutionException, TimeoutException { + final List results = new ArrayList<>(); + final long startTime = System.currentTimeMillis(); + if (futures.isEmpty()) { + return List.of(); + } + for (final Future future : futures) { + final long maxWaitTimeMs = maxWaitTime.toMillis() - (System.currentTimeMillis() - startTime); + final T val = future.get(maxWaitTimeMs, MILLISECONDS); + results.add(val); + } + return results; + } +} diff --git a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/internal/TestExecutorExtension.java b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/internal/TestExecutorExtension.java new file mode 100644 index 000000000000..3c1e83f27cd4 --- /dev/null +++ b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/internal/TestExecutorExtension.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.base.test.fixtures.concurrent.internal; + +import com.swirlds.base.test.fixtures.concurrent.TestExecutor; +import com.swirlds.base.test.fixtures.util.TestInjector; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.lang.reflect.Method; +import java.util.Objects; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.InvocationInterceptor; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolutionException; +import org.junit.jupiter.api.extension.ParameterResolver; +import org.junit.jupiter.api.extension.ReflectiveInvocationContext; + +/** + * The TestExecutorExtension is a JUnit 5 extension designed to facilitate the integration of + * a {@link TestExecutor} into your test classes. It serves as both an {@link InvocationInterceptor} and a + * {@link ParameterResolver}, enabling seamless injection of a {@code TestExecutor} instance and supporting its + * use within your test methods. + *

    + * When applied, this extension injects a {@code TestExecutor} instance into the test class, allowing + * you to execute tests in a controlled manner, such as concurrently or with customized behaviors. + * + * @see TestExecutor + * @see InvocationInterceptor + * @see ParameterResolver + */ +public class TestExecutorExtension implements InvocationInterceptor, ParameterResolver { + + /** + * Intercept the execution of a test method and inject a TestExecutor instance into the + * current test context. + * + * @param invocation The invocation of the test method. + * @param invocationContext The context of the method invocation. + * @param extensionContext The context of the test extension. + * @throws Throwable if an error occurs during method interception. + */ + @Override + public void interceptTestMethod( + @NonNull final Invocation invocation, + @NonNull final ReflectiveInvocationContext invocationContext, + @NonNull final ExtensionContext extensionContext) + throws Throwable { + Objects.requireNonNull(invocation, "invocation must not be null"); + Objects.requireNonNull(extensionContext, "extensionContext must not be null"); + + TestInjector.injectInTest(TestExecutor.class, () -> new ConcurrentTestSupport(), extensionContext); + + invocation.proceed(); + } + + /** + * Check if this extension supports parameter resolution for the given parameter context. + * + * @param parameterContext The context of the parameter to be resolved. + * @param extensionContext The context of the test extension. + * @return true if parameter resolution is supported, false otherwise. + * @throws ParameterResolutionException if an error occurs during parameter resolution. + */ + @Override + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + return TestInjector.supportsParameter(parameterContext, TestExecutor.class); + } + + /** + * Resolve the parameter of a test method, providing a TestExecutor instance when needed. + * + * @param parameterContext The context of the parameter to be resolved. + * @param extensionContext The context of the test extension. + * @return The resolved parameter value. + * @throws ParameterResolutionException if an error occurs during parameter resolution. + */ + @Override + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + return TestInjector.resolveParameter(parameterContext, () -> new ConcurrentTestSupport()); + } +} diff --git a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/package-info.java b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/package-info.java new file mode 100644 index 000000000000..35c03169b8ef --- /dev/null +++ b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/concurrent/package-info.java @@ -0,0 +1,5 @@ +/** + * This package contains general utilities for testing concurrent code or to test code in parallel (like for stress + * tests). + */ +package com.swirlds.base.test.fixtures.concurrent; diff --git a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/context/internal/GlobalContextExtension.java b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/context/internal/GlobalContextExtension.java index f490cd48d8c2..f88e3fc0e946 100644 --- a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/context/internal/GlobalContextExtension.java +++ b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/context/internal/GlobalContextExtension.java @@ -39,7 +39,6 @@ public void beforeEach(ExtensionContext context) throws Exception { @Override public void afterEach(ExtensionContext context) throws Exception { GlobalContext.getInstance().clear(); - Optional.ofNullable(savedSate.get()) - .ifPresent(map -> map.forEach(GlobalContext.getInstance()::addWithRemovalOnClose)); + Optional.ofNullable(savedSate.get()).ifPresent(map -> map.forEach(GlobalContext.getInstance()::add)); } } diff --git a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/context/internal/ThreadLocalContextExtension.java b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/context/internal/ThreadLocalContextExtension.java index ced8073e9f99..de024491a705 100644 --- a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/context/internal/ThreadLocalContextExtension.java +++ b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/context/internal/ThreadLocalContextExtension.java @@ -39,7 +39,6 @@ public void beforeEach(ExtensionContext context) throws Exception { @Override public void afterEach(ExtensionContext context) throws Exception { ThreadLocalContext.getInstance().clear(); - Optional.ofNullable(savedSate.get()) - .ifPresent(map -> map.forEach(ThreadLocalContext.getInstance()::addWithRemovalOnClose)); + Optional.ofNullable(savedSate.get()).ifPresent(map -> map.forEach(ThreadLocalContext.getInstance()::add)); } } diff --git a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/io/internal/SystemErrorExtension.java b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/io/internal/SystemErrorExtension.java index be240347daa1..f846de52620e 100644 --- a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/io/internal/SystemErrorExtension.java +++ b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/io/internal/SystemErrorExtension.java @@ -17,14 +17,11 @@ package com.swirlds.base.test.fixtures.io.internal; import com.swirlds.base.test.fixtures.io.SystemErrProvider; -import com.swirlds.base.test.fixtures.io.WithSystemError; +import com.swirlds.base.test.fixtures.util.TestInjector; import edu.umd.cs.findbugs.annotations.NonNull; -import jakarta.inject.Inject; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; import java.util.Objects; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.InvocationInterceptor; @@ -33,7 +30,7 @@ /** * This class is used to inject a {@link SystemErrProvider} instance into a test and run the test in isolation. * - * @see WithSystemError + * @see com.swirlds.base.test.fixtures.io.WithSystemError */ public class SystemErrorExtension implements InvocationInterceptor { @@ -49,20 +46,7 @@ public void interceptTestMethod( try (final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { final SystemIoProvider provider = new SystemIoProvider(byteArrayOutputStream); System.setErr(new PrintStream(byteArrayOutputStream)); - final Class testClass = extensionContext.getRequiredTestClass(); - Arrays.asList(testClass.getDeclaredFields()).stream() - .filter(field -> !Modifier.isFinal(field.getModifiers())) - .filter(field -> !Modifier.isStatic(field.getModifiers())) - .filter(field -> field.isAnnotationPresent(Inject.class)) - .filter(field -> Objects.equals(field.getType(), SystemErrProvider.class)) - .forEach(field -> { - try { - field.setAccessible(true); - field.set(extensionContext.getRequiredTestInstance(), provider); - } catch (Exception ex) { - throw new RuntimeException("Error in injecting mirror", ex); - } - }); + TestInjector.injectInTest(SystemErrProvider.class, () -> provider, extensionContext); invocation.proceed(); } finally { System.setErr(originalSystemErrorPrintStream); diff --git a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/io/internal/SystemIoProvider.java b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/io/internal/SystemIoProvider.java index 3598f58ce8b0..fa96e5e6a8f3 100644 --- a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/io/internal/SystemIoProvider.java +++ b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/io/internal/SystemIoProvider.java @@ -28,12 +28,12 @@ */ public class SystemIoProvider implements SystemOutProvider, SystemErrProvider { - private final ByteArrayOutputStream outputStream; - private final StringBuilder internalBuilder = new StringBuilder(); private boolean readAll = false; + private final ByteArrayOutputStream outputStream; + /** * Constructs a new instance. * diff --git a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/io/internal/SystemOutExtension.java b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/io/internal/SystemOutExtension.java index f29e3ccebc36..d722d2624706 100644 --- a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/io/internal/SystemOutExtension.java +++ b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/io/internal/SystemOutExtension.java @@ -17,13 +17,11 @@ package com.swirlds.base.test.fixtures.io.internal; import com.swirlds.base.test.fixtures.io.SystemOutProvider; +import com.swirlds.base.test.fixtures.util.TestInjector; import edu.umd.cs.findbugs.annotations.NonNull; -import jakarta.inject.Inject; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; import java.util.Objects; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.InvocationInterceptor; @@ -46,20 +44,7 @@ public void interceptTestMethod( try (final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { final SystemIoProvider provider = new SystemIoProvider(byteArrayOutputStream); System.setOut(new PrintStream(byteArrayOutputStream)); - final Class testClass = extensionContext.getRequiredTestClass(); - Arrays.asList(testClass.getDeclaredFields()).stream() - .filter(field -> !Modifier.isFinal(field.getModifiers())) - .filter(field -> !Modifier.isStatic(field.getModifiers())) - .filter(field -> field.isAnnotationPresent(Inject.class)) - .filter(field -> Objects.equals(field.getType(), SystemOutProvider.class)) - .forEach(field -> { - try { - field.setAccessible(true); - field.set(extensionContext.getRequiredTestInstance(), provider); - } catch (Exception ex) { - throw new RuntimeException("Error in injecting mirror", ex); - } - }); + TestInjector.injectInTest(SystemOutProvider.class, () -> provider, extensionContext); invocation.proceed(); } finally { System.setOut(originalSystemOutPrintStream); diff --git a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/util/TestInjector.java b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/util/TestInjector.java new file mode 100644 index 000000000000..6fede04fda5a --- /dev/null +++ b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/util/TestInjector.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.base.test.fixtures.util; + +import com.swirlds.base.test.fixtures.concurrent.TestExecutor; +import edu.umd.cs.findbugs.annotations.NonNull; +import jakarta.inject.Inject; +import java.lang.reflect.Modifier; +import java.lang.reflect.Parameter; +import java.util.Arrays; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Supplier; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolutionException; + +/** + * This class is used to inject a dependency into a test. It should be used by JUnit extensions. + */ +public class TestInjector { + + /** + * This class should not be instantiated. + */ + private TestInjector() {} + + /** + * Injects the result of the given supplier into the test instance. The result of the supplier is injected into any + * field of the test instance that is annotated with {@link Inject} and is of the given type. + * + * @param type the type of the dependency to inject + * @param supplier the supplier that provides the dependency + * @param extensionContext the extension context of the test + * @param the type of the dependency to inject + */ + public static void injectInTest(Class type, Supplier supplier, ExtensionContext extensionContext) { + final Class testClass = extensionContext.getRequiredTestClass(); + Arrays.stream(testClass.getDeclaredFields()) + .filter(field -> !Modifier.isFinal(field.getModifiers())) + .filter(field -> !Modifier.isStatic(field.getModifiers())) + .filter(field -> field.isAnnotationPresent(Inject.class)) + .filter(field -> Objects.equals(field.getType(), type)) + .forEach(field -> { + try { + field.setAccessible(true); + field.set(extensionContext.getRequiredTestInstance(), supplier.get()); + } catch (Exception ex) { + throw new RuntimeException("Error in injection", ex); + } + }); + } + + /** + * Checks if the given parameter context supports a parameter of the specified class type. + * + * @param parameterContext The parameter context to check for support. + * @param cls The class type to check support for. + * @param The type of the class. + * @return True if the parameter context supports the specified class type, false otherwise. + * @throws NullPointerException If either parameterContext or cls is null. + */ + public static boolean supportsParameter( + final @NonNull ParameterContext parameterContext, final @NonNull Class cls) { + Objects.requireNonNull(parameterContext, "parameterContext must not be null"); + Objects.requireNonNull(cls, "cls must not be null"); + + return Optional.of(parameterContext) + .map(ParameterContext::getParameter) + .map(Parameter::getType) + .filter(cls::isAssignableFrom) + .isPresent(); + } + + /** + * Resolves a parameter from the given parameter context using the provided instance supplier. + * + * @param parameterContext The parameter context to resolve the parameter from. + * @param instanceSupplier The supplier that provides an instance of the parameter type. + * @param The type of the parameter to resolve. + * @return The resolved parameter. + * @throws NullPointerException If either parameterContext or instanceSupplier is null. + * @throws ParameterResolutionException If the parameter cannot be resolved. + */ + public static T resolveParameter( + final @NonNull ParameterContext parameterContext, final @NonNull Supplier instanceSupplier) { + Objects.requireNonNull(parameterContext, "parameterContext must not be null"); + Objects.requireNonNull(instanceSupplier, "instanceSupplier must not be null"); + + return Optional.of(parameterContext) + .map(ParameterContext::getParameter) + .map(Parameter::getType) + .filter(t -> t.equals(TestExecutor.class)) + .map(t -> instanceSupplier.get()) + .orElseThrow(() -> new ParameterResolutionException("Could not resolve parameter")); + } +} diff --git a/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/util/package-info.java b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/util/package-info.java new file mode 100644 index 000000000000..ed3290b8e70a --- /dev/null +++ b/platform-sdk/swirlds-base/src/testFixtures/java/com/swirlds/base/test/fixtures/util/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains general utils for creating tests and junit extensions. + */ +package com.swirlds.base.test.fixtures.util; diff --git a/platform-sdk/swirlds-base/src/testFixtures/java/module-info.java b/platform-sdk/swirlds-base/src/testFixtures/java/module-info.java index 867313f34090..c0fc526a4965 100644 --- a/platform-sdk/swirlds-base/src/testFixtures/java/module-info.java +++ b/platform-sdk/swirlds-base/src/testFixtures/java/module-info.java @@ -1,6 +1,9 @@ open module com.swirlds.base.test.fixtures { exports com.swirlds.base.test.fixtures.context; exports com.swirlds.base.test.fixtures.time; + exports com.swirlds.base.test.fixtures.io; + exports com.swirlds.base.test.fixtures.util; + exports com.swirlds.base.test.fixtures.concurrent; requires transitive com.swirlds.base; requires transitive org.junit.jupiter.api; diff --git a/platform-sdk/swirlds-cli/src/main/java/com/swirlds/cli/PlatformCli.java b/platform-sdk/swirlds-cli/src/main/java/com/swirlds/cli/PlatformCli.java index 8e399d98efb2..b4396ff69e64 100644 --- a/platform-sdk/swirlds-cli/src/main/java/com/swirlds/cli/PlatformCli.java +++ b/platform-sdk/swirlds-cli/src/main/java/com/swirlds/cli/PlatformCli.java @@ -136,11 +136,21 @@ private void setIgnoreJars(final boolean ignoreJars) { + DOCUMENTATION_PURPOSES_ONLY); } + @CommandLine.Option( + names = {"-B", "--bootstrap"}, + scope = CommandLine.ScopeType.INHERIT, + description = "The fully qualified name of the function to run before the command is executed." + + "Can be used to do arbitrary bootstrapping. Should be a static method " + + "that implements the interface Runnable. " + + "e.g. '-B com.swirlds.cli.utility.PlatformCliPreParser.exampleBootstrapFunction'") + private void setBoostrapFunction(final String boostrapFunction) { + throw buildParameterException("This argument is parsed by the pre-parser. " + DOCUMENTATION_PURPOSES_ONLY); + } + /** * Before we do the main parsing pass, we first need to extract a small selection of parameters. * - * @param args - * the program arguments + * @param args the program arguments * @return the arguments that weren't handled by pre-parsing */ private static PlatformCliPreParser preParse(final String[] args) { @@ -157,8 +167,7 @@ private static PlatformCliPreParser preParse(final String[] args) { /** * Main entrypoint for the platform CLI. * - * @param args - * program arguments + * @param args program arguments */ @SuppressWarnings("java:S106") public static void main(final String[] args) throws InterruptedException { @@ -171,6 +180,8 @@ public static void main(final String[] args) throws InterruptedException { final CountDownLatch log4jLatch = Log4jSetup.startLoggingFramework(preParser.getLog4jPath()); + preParser.runBootstrapFunction(); + whitelistCliPackage("com.swirlds.platform.cli"); whitelistCliPackage("com.swirlds.platform.state.editor"); if (preParser.getCliPackagePrefixes() != null) { diff --git a/platform-sdk/swirlds-cli/src/main/java/com/swirlds/cli/utility/PlatformCliPreParser.java b/platform-sdk/swirlds-cli/src/main/java/com/swirlds/cli/utility/PlatformCliPreParser.java index 288ed9536e28..28cefcfba1e8 100644 --- a/platform-sdk/swirlds-cli/src/main/java/com/swirlds/cli/utility/PlatformCliPreParser.java +++ b/platform-sdk/swirlds-cli/src/main/java/com/swirlds/cli/utility/PlatformCliPreParser.java @@ -16,6 +16,7 @@ package com.swirlds.cli.utility; +import java.lang.reflect.Method; import java.nio.file.Path; import java.util.List; import picocli.CommandLine; @@ -30,6 +31,9 @@ public class PlatformCliPreParser implements Runnable { private Path log4jPath; private String[] unparsedArgs; private boolean colorDisabled; + private String bootstrapFunction; + + private static final ClassLoader classLoader = PlatformCliPreParser.class.getClassLoader(); @CommandLine.Option(names = {"-C", "--cli"}) private void setCliPackagePrefixes(final List cliPackagePrefixes) { @@ -49,6 +53,11 @@ private void setColorDisabled(final boolean colorDisabled) { this.colorDisabled = colorDisabled; } + @CommandLine.Option(names = {"-B", "--bootstrap"}) + private void setBoostrapFunction(final String boostrapFunction) { + this.bootstrapFunction = boostrapFunction; + } + /** * Get CLI package prefixes that should be scanned for additional CLI commands. Returns null if there are none. */ @@ -84,6 +93,38 @@ public void setUnparsedArgs(final String[] unparsedArgs) { this.unparsedArgs = unparsedArgs; } + /** + * An example bootstrap function. + */ + public static void exampleBootstrapFunction() { + System.out.println("running example bootstrap function"); + } + + /** + * Run the bootstrap function if one was provided. + */ + public void runBootstrapFunction() { + if (bootstrapFunction == null) { + return; + } + + try { + final int lastPeriodIndex = bootstrapFunction.lastIndexOf('.'); + final String className = bootstrapFunction.substring(0, lastPeriodIndex); + final String methodName = bootstrapFunction.substring(lastPeriodIndex + 1); + + final Class clazz = classLoader.loadClass(className); + final Method method = clazz.getMethod(methodName); + + method.invoke(null); + + } catch (final Throwable t) { + System.err.println("Error running bootstrap function " + bootstrapFunction); + t.printStackTrace(); + System.exit(1); + } + } + /** * {@inheritDoc} */ diff --git a/platform-sdk/swirlds-common/build.gradle.kts b/platform-sdk/swirlds-common/build.gradle.kts index 2004484ac043..34617ec0b3fd 100644 --- a/platform-sdk/swirlds-common/build.gradle.kts +++ b/platform-sdk/swirlds-common/build.gradle.kts @@ -21,6 +21,8 @@ plugins { } mainModuleInfo { + annotationProcessor("com.swirlds.config.processor") + runtimeOnly("resource.loader") runtimeOnly("com.sun.jna") } diff --git a/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/BasicConfig.java b/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/BasicConfig.java index 57b8b52b9bc1..eff2fa244006 100644 --- a/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/BasicConfig.java +++ b/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/BasicConfig.java @@ -29,7 +29,7 @@ * *

    * Do not add new settings to this record unless you have a very good reason. New settings should go - * into config records with a prefix defined by a {@link ConfigData @ConfigData("prefix")} tag. Adding + * into config records with a prefix defined by a {@link ConfigData} tag. Adding * settings to this record pollutes the top level namespace. * * @param showInternalStats diff --git a/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/EventConfig.java b/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/EventConfig.java index 8aae73fe1954..64d98b839991 100644 --- a/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/EventConfig.java +++ b/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/EventConfig.java @@ -35,7 +35,7 @@ * because syncs that started before the throttle engages can grow the queue to * very large sizes on larger networks. * @param randomEventProbability The probability that after a sync, a node will create an event with a random - * other parent. The probability is is 1 in X, where X is the value of + * other parent. The probability is 1 in X, where X is the value of * randomEventProbability. A value of 0 means that a node will not create any * random events. *

    @@ -57,6 +57,7 @@ * @param eventsLogDir eventStream files will be generated in this directory. * @param enableEventStreaming enable stream event to server. * @param prehandlePoolSize the size of the thread pool used for prehandling transactions + * @param useLegacyIntake if true then use the legacy intake monolith, if false then use the new intake pipeline */ @ConfigData("event") public record EventConfig( @@ -70,4 +71,5 @@ public record EventConfig( @ConfigProperty(defaultValue = "5") long eventsLogPeriod, @ConfigProperty(defaultValue = "/opt/hgcapp/eventsStreams") String eventsLogDir, @ConfigProperty(defaultValue = "true") boolean enableEventStreaming, - @ConfigProperty(defaultValue = "8") int prehandlePoolSize) {} + @ConfigProperty(defaultValue = "8") int prehandlePoolSize, + @ConfigProperty(defaultValue = "false") boolean useLegacyIntake) {} diff --git a/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/PlatformSchedulersConfig.java b/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/PlatformSchedulersConfig.java new file mode 100644 index 000000000000..db39c7e135aa --- /dev/null +++ b/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/PlatformSchedulersConfig.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2022-2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.common.config; + +import com.swirlds.common.wiring.schedulers.builders.TaskSchedulerType; +import com.swirlds.config.api.ConfigData; +import com.swirlds.config.api.ConfigProperty; + +/** + * Contains configuration values for the platform schedulers. + * + * @param internalEventValidatorSchedulerType the internal event validator scheduler type + * @param internalEventValidatorUnhandledCapacity number of unhandled events allowed in the internal event validator scheduler + * @param eventDeduplicatorSchedulerType the event deduplicator scheduler type + * @param eventDeduplicatorUnhandledCapacity number of unhandled tasks allowed in the event deduplicator scheduler + * @param eventSignatureValidatorSchedulerType the event signature validator scheduler type + * @param eventSignatureValidatorUnhandledCapacity number of unhandled tasks allowed in the event signature validator scheduler + * @param orphanBufferSchedulerType the orphan buffer scheduler type + * @param orphanBufferUnhandledCapacity number of unhandled tasks allowed in the orphan buffer scheduler + * @param inOrderLinkerSchedulerType the in-order linker scheduler type + * @param inOrderLinkerUnhandledCapacity number of unhandled tasks allowed in the in-order linker scheduler + * @param linkedEventIntakeSchedulerType the linked event intake scheduler type + * @param linkedEventIntakeUnhandledCapacity number of unhandled tasks allowed in the linked event intake scheduler + */ +@ConfigData("platformSchedulers") +public record PlatformSchedulersConfig( + @ConfigProperty(defaultValue = "SEQUENTIAL") String internalEventValidatorSchedulerType, + @ConfigProperty(defaultValue = "500") int internalEventValidatorUnhandledCapacity, + @ConfigProperty(defaultValue = "SEQUENTIAL") String eventDeduplicatorSchedulerType, + @ConfigProperty(defaultValue = "500") int eventDeduplicatorUnhandledCapacity, + @ConfigProperty(defaultValue = "SEQUENTIAL") String eventSignatureValidatorSchedulerType, + @ConfigProperty(defaultValue = "500") int eventSignatureValidatorUnhandledCapacity, + @ConfigProperty(defaultValue = "SEQUENTIAL") String orphanBufferSchedulerType, + @ConfigProperty(defaultValue = "500") int orphanBufferUnhandledCapacity, + @ConfigProperty(defaultValue = "SEQUENTIAL") String inOrderLinkerSchedulerType, + @ConfigProperty(defaultValue = "500") int inOrderLinkerUnhandledCapacity, + @ConfigProperty(defaultValue = "SEQUENTIAL") String linkedEventIntakeSchedulerType, + @ConfigProperty(defaultValue = "500") int linkedEventIntakeUnhandledCapacity) { + + /** + * Get the internal event validator scheduler type + * + * @return the internal event validator scheduler type + */ + public TaskSchedulerType getInternalEventValidatorSchedulerType() { + return TaskSchedulerType.valueOf(internalEventValidatorSchedulerType); + } + + /** + * Get the event deduplicator scheduler type + * + * @return the event deduplicator scheduler type + */ + public TaskSchedulerType getEventDeduplicatorSchedulerType() { + return TaskSchedulerType.valueOf(eventDeduplicatorSchedulerType); + } + + /** + * Get the event signature validator scheduler type + * + * @return the event signature validator scheduler type + */ + public TaskSchedulerType getEventSignatureValidatorSchedulerType() { + return TaskSchedulerType.valueOf(eventSignatureValidatorSchedulerType); + } + + /** + * Get the orphan buffer scheduler type + * + * @return the orphan buffer scheduler type + */ + public TaskSchedulerType getOrphanBufferSchedulerType() { + return TaskSchedulerType.valueOf(orphanBufferSchedulerType); + } + + /** + * Get the in-order linker scheduler type + * + * @return the in-order linker scheduler type + */ + public TaskSchedulerType getInOrderLinkerSchedulerType() { + return TaskSchedulerType.valueOf(inOrderLinkerSchedulerType); + } + + /** + * Get the linked event intake scheduler type + * + * @return the linked event intake scheduler type + */ + public TaskSchedulerType getLinkedEventIntakeSchedulerType() { + return TaskSchedulerType.valueOf(linkedEventIntakeSchedulerType); + } +} diff --git a/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/StateConfig.java b/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/StateConfig.java index 25d236941a4f..90d5b8b522e4 100644 --- a/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/StateConfig.java +++ b/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/config/StateConfig.java @@ -39,10 +39,6 @@ * @param signedStateDisk Keep at least this many of the old complete signed states on disk. This should * be at least 2 so that we don't delete an old state while a new one is in the * process of writing to disk. set to 0 to not keep any states to disk. - * @param dumpStateOnAnyISS If true, save the state to disk when an ISS is detected. May negatively affect - * the performance of the node where the ISS occurs. This feature is for debugging - * purposes and should not be active in production systems. - * @param dumpStateOnFatal If true, then save the state to disk when there is a fatal exception. * @param haltOnAnyIss

    * Halt this node whenever any ISS in the network is detected. A halt causes the * node to stop doing work, but does not shut down the JVM. @@ -55,10 +51,6 @@ * @param automatedSelfIssRecovery If true, then attempt to recover automatically when a self ISS is detected. * @param haltOnCatastrophicIss If true, then halt this node if a catastrophic ISS is detected. A halt causes * the node to stop doing work, but does not shut down the JVM. - * @param secondsBetweenISSDumps If one ISS is detected, it is likely that others will be detected shortly - * afterward. Specify the minimum time, in seconds, that must transpire after - * dumping a state before another state dump is permitted. Ignored if - * dumpStateOnISS is false. * @param secondsBetweenIssLogs The minimum time that must pass between log messages about ISS events. If ISS * events happen with a higher frequency then they are squelched. * @param enableHashStreamLogging When enabled, hashes for the nodes are logged per round. @@ -103,12 +95,9 @@ public record StateConfig( @ConfigProperty(defaultValue = "20") int stateSavingQueueSize, @ConfigProperty(defaultValue = "900") int saveStatePeriod, @ConfigProperty(defaultValue = "5") int signedStateDisk, - @ConfigProperty(defaultValue = "false") boolean dumpStateOnAnyISS, - @ConfigProperty(defaultValue = "true") boolean dumpStateOnFatal, @ConfigProperty(defaultValue = "false") boolean haltOnAnyIss, @ConfigProperty(defaultValue = "false") boolean automatedSelfIssRecovery, @ConfigProperty(defaultValue = "false") boolean haltOnCatastrophicIss, - @ConfigProperty(defaultValue = "21600") long secondsBetweenISSDumps, @ConfigProperty(defaultValue = "300") long secondsBetweenIssLogs, @ConfigProperty(defaultValue = "true") boolean enableHashStreamLogging, @ConfigProperty(defaultValue = "5") int debugHashDepth, diff --git a/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/wiring/model/internal/WiringFlowchart.java b/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/wiring/model/internal/WiringFlowchart.java index 23e18e2944d9..5185d5421fdf 100644 --- a/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/wiring/model/internal/WiringFlowchart.java +++ b/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/wiring/model/internal/WiringFlowchart.java @@ -34,9 +34,10 @@ public final class WiringFlowchart { private WiringFlowchart() {} private static final String INDENTATION = " "; - private static final String SCHEDULER_COLOR = "362"; - private static final String DIRECT_SCHEDULER_COLOR = "666"; - private static final String GROUP_COLOR = "555"; + private static final String SCHEDULER_COLOR = "ff9"; + private static final String DIRECT_SCHEDULER_COLOR = "ccc"; + private static final String TEXT_COLOR = "000"; + private static final String GROUP_COLOR = "9cf"; /** * Draw an edge. @@ -99,9 +100,9 @@ private static void modifyVertexShape(@NonNull final StringBuilder sb, @NonNull if (vertex.getType() == TaskSchedulerType.CONCURRENT) { sb.append("[[").append(vertex.getName()).append("]]"); } else if (vertex.getType() == TaskSchedulerType.DIRECT) { - sb.append("((").append(vertex.getName()).append("))"); + sb.append("[/").append(vertex.getName()).append("/]"); } else if (vertex.getType() == TaskSchedulerType.DIRECT_STATELESS) { - sb.append("(((").append(vertex.getName()).append(")))"); + sb.append("{{").append(vertex.getName()).append("}}"); } } @@ -150,7 +151,9 @@ private static void drawVertex( .append(vertex.getName()) .append(" fill:#") .append(getVertexColor(vertex)) - .append(",stroke:#000,stroke-width:2px,color:#fff\n"); + .append(",stroke:#") + .append(TEXT_COLOR) + .append(",stroke-width:2px\n"); } } @@ -174,7 +177,9 @@ private static void drawGroup( .append(group.name()) .append(" fill:#") .append(color) - .append(",stroke:#000,stroke-width:2px,color:#fff\n"); + .append(",stroke:#") + .append(TEXT_COLOR) + .append(",stroke-width:2px\n"); vertices.stream().sorted().forEachOrdered(vertex -> drawVertex(sb, vertex, collapsedVertexMap, 2)); sb.append(INDENTATION).append("end\n"); diff --git a/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/wiring/wires/input/BindableInputWire.java b/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/wiring/wires/input/BindableInputWire.java index d4b3338025b8..b1b0eea3db12 100644 --- a/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/wiring/wires/input/BindableInputWire.java +++ b/platform-sdk/swirlds-common/src/main/java/com/swirlds/common/wiring/wires/input/BindableInputWire.java @@ -76,7 +76,6 @@ public void bind(@NonNull final Function handler) { taskSchedulerInput.forward(output); } }); - model.registerInputWireBinding(taskSchedulerName, getName()); } } diff --git a/platform-sdk/swirlds-common/src/main/java/module-info.java b/platform-sdk/swirlds-common/src/main/java/module-info.java index bf05b6411fad..bcec69831e7f 100644 --- a/platform-sdk/swirlds-common/src/main/java/module-info.java +++ b/platform-sdk/swirlds-common/src/main/java/module-info.java @@ -182,6 +182,6 @@ requires jdk.management; requires org.apache.logging.log4j.core; requires org.bouncycastle.provider; - requires org.hyperledger.besu.secp256k1; + requires org.hyperledger.besu.nativelib.secp256k1; requires static com.github.spotbugs.annotations; } diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/crypto/CryptographyBenchmarkTests.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/crypto/CryptographyBenchmarkTests.java similarity index 95% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/crypto/CryptographyBenchmarkTests.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/crypto/CryptographyBenchmarkTests.java index d63d71aefb12..87a5e71d3478 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/crypto/CryptographyBenchmarkTests.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/crypto/CryptographyBenchmarkTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,16 +14,10 @@ * limitations under the License. */ -package com.swirlds.common.test.crypto; +package com.swirlds.common.crypto; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.swirlds.common.crypto.Cryptography; -import com.swirlds.common.crypto.CryptographyHolder; -import com.swirlds.common.crypto.DigestType; -import com.swirlds.common.crypto.Message; -import com.swirlds.common.crypto.SignatureType; -import com.swirlds.common.crypto.TransactionSignature; import com.swirlds.common.test.fixtures.crypto.EcdsaSignedTxnPool; import com.swirlds.common.test.fixtures.crypto.MessageDigestPool; import com.swirlds.common.test.fixtures.crypto.SignaturePool; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/AsyncOrderedIntegerListener.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/AsyncOrderedIntegerListener.java similarity index 70% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/AsyncOrderedIntegerListener.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/AsyncOrderedIntegerListener.java index 64773698f962..09f59959f54d 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/AsyncOrderedIntegerListener.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/AsyncOrderedIntegerListener.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.notification; - -import com.swirlds.common.notification.DispatchMode; -import com.swirlds.common.notification.DispatchModel; -import com.swirlds.common.notification.DispatchOrder; -import com.swirlds.common.notification.Listener; +package com.swirlds.common.notification; @DispatchModel(mode = DispatchMode.ASYNC, order = DispatchOrder.ORDERED) public interface AsyncOrderedIntegerListener extends Listener {} diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/AsyncUnorderedIntegerListener.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/AsyncUnorderedIntegerListener.java similarity index 70% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/AsyncUnorderedIntegerListener.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/AsyncUnorderedIntegerListener.java index 4c34a967cbb4..b56340e51348 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/AsyncUnorderedIntegerListener.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/AsyncUnorderedIntegerListener.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.notification; - -import com.swirlds.common.notification.DispatchMode; -import com.swirlds.common.notification.DispatchModel; -import com.swirlds.common.notification.DispatchOrder; -import com.swirlds.common.notification.Listener; +package com.swirlds.common.notification; @DispatchModel(mode = DispatchMode.ASYNC, order = DispatchOrder.UNORDERED) public interface AsyncUnorderedIntegerListener extends Listener {} diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/DispatcherTests.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/DispatcherTests.java similarity index 96% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/DispatcherTests.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/DispatcherTests.java index c5d26146a0f9..70151e1c7f3f 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/DispatcherTests.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/DispatcherTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,12 @@ * limitations under the License. */ -package com.swirlds.common.test.notification; +package com.swirlds.common.notification; import static com.swirlds.common.threading.manager.AdHocThreadManager.getStaticThreadManager; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import com.swirlds.common.notification.NotificationResult; import com.swirlds.common.notification.internal.Dispatcher; import com.swirlds.common.threading.futures.StandardFuture; import com.swirlds.test.framework.TestComponentTags; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/IntegerNotification.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/IntegerNotification.java similarity index 83% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/IntegerNotification.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/IntegerNotification.java index 4c0f7b418a89..df7c93414469 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/IntegerNotification.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/IntegerNotification.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.notification; - -import com.swirlds.common.notification.AbstractNotification; +package com.swirlds.common.notification; public class IntegerNotification extends AbstractNotification { diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/IntegerNotificationTests.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/IntegerNotificationTests.java similarity index 98% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/IntegerNotificationTests.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/IntegerNotificationTests.java index a241d83ab59e..4581559eceba 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/IntegerNotificationTests.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/IntegerNotificationTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.notification; +package com.swirlds.common.notification; import static com.swirlds.common.test.fixtures.AssertionUtils.completeBeforeTimeout; import static com.swirlds.common.threading.interrupt.Uninterruptable.abortAndThrowIfInterrupted; @@ -29,13 +29,6 @@ import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.swirlds.common.notification.DispatchException; -import com.swirlds.common.notification.DispatchMode; -import com.swirlds.common.notification.DispatchModel; -import com.swirlds.common.notification.DispatchOrder; -import com.swirlds.common.notification.Listener; -import com.swirlds.common.notification.NotificationEngine; -import com.swirlds.common.notification.NotificationResult; import com.swirlds.common.notification.internal.AsyncNotificationEngine; import com.swirlds.common.threading.framework.config.ThreadConfiguration; import com.swirlds.common.threading.futures.ConcurrentFuturePool; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/SyncOrderedIntegerListener.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/SyncOrderedIntegerListener.java similarity index 70% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/SyncOrderedIntegerListener.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/SyncOrderedIntegerListener.java index ad3f9b3174ee..342bba87c7fa 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/SyncOrderedIntegerListener.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/SyncOrderedIntegerListener.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.notification; - -import com.swirlds.common.notification.DispatchMode; -import com.swirlds.common.notification.DispatchModel; -import com.swirlds.common.notification.DispatchOrder; -import com.swirlds.common.notification.Listener; +package com.swirlds.common.notification; @DispatchModel(mode = DispatchMode.SYNC, order = DispatchOrder.ORDERED) public interface SyncOrderedIntegerListener extends Listener {} diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/SyncUnorderedIntegerListener.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/SyncUnorderedIntegerListener.java similarity index 81% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/SyncUnorderedIntegerListener.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/SyncUnorderedIntegerListener.java index e2c2e3bb97c4..4c4529264815 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/notification/SyncUnorderedIntegerListener.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/notification/SyncUnorderedIntegerListener.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,8 +14,6 @@ * limitations under the License. */ -package com.swirlds.common.test.notification; - -import com.swirlds.common.notification.Listener; +package com.swirlds.common.notification; public interface SyncUnorderedIntegerListener extends Listener {} diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/set/RandomAccessSetTest.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/set/RandomAccessSetTest.java similarity index 98% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/set/RandomAccessSetTest.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/set/RandomAccessSetTest.java index 6441f627c0e8..e18c3c9161d8 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/set/RandomAccessSetTest.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/set/RandomAccessSetTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,17 @@ * limitations under the License. */ -package com.swirlds.common.test.set; +package com.swirlds.common.set; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import com.swirlds.base.utility.Pair; +import com.swirlds.common.test.fixtures.set.Hotspot; +import com.swirlds.common.test.fixtures.set.HotspotHashSet; +import com.swirlds.common.test.fixtures.set.RandomAccessHashSet; +import com.swirlds.common.test.fixtures.set.RandomAccessSet; import com.swirlds.test.framework.TestComponentTags; import com.swirlds.test.framework.TestQualifierTags; import com.swirlds.test.framework.TestTypeTags; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/CachedPoolParallelExecutorTest.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/CachedPoolParallelExecutorTest.java similarity index 98% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/CachedPoolParallelExecutorTest.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/CachedPoolParallelExecutorTest.java index 883985e342d1..ac43ee2a8374 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/CachedPoolParallelExecutorTest.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/CachedPoolParallelExecutorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.threading; +package com.swirlds.common.threading; import static com.swirlds.common.threading.manager.AdHocThreadManager.getStaticThreadManager; import static org.assertj.core.api.Assertions.assertThat; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/ControllableQueue.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/ControllableQueue.java similarity index 97% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/ControllableQueue.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/ControllableQueue.java index a2d3868bb8f8..68acea0b8e5b 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/ControllableQueue.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/ControllableQueue.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.threading; +package com.swirlds.common.threading; import com.swirlds.common.threading.framework.internal.AbstractBlockingQueue; import java.util.concurrent.LinkedBlockingQueue; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/ExceptionSuppressingParallelExecutorTests.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/ExceptionSuppressingParallelExecutorTests.java similarity index 94% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/ExceptionSuppressingParallelExecutorTests.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/ExceptionSuppressingParallelExecutorTests.java index 17bb7b5553e3..3a3ee20f5f7e 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/ExceptionSuppressingParallelExecutorTests.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/ExceptionSuppressingParallelExecutorTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.threading; +package com.swirlds.common.threading; import static com.swirlds.common.threading.manager.AdHocThreadManager.getStaticThreadManager; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/MultiQueueThreadTests.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/MultiQueueThreadTests.java similarity index 99% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/MultiQueueThreadTests.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/MultiQueueThreadTests.java index c060e5b9f7fa..32d57c9b49bb 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/MultiQueueThreadTests.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/MultiQueueThreadTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.threading; +package com.swirlds.common.threading; import static java.util.concurrent.TimeUnit.SECONDS; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/QueueThreadPoolTests.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/QueueThreadPoolTests.java similarity index 99% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/QueueThreadPoolTests.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/QueueThreadPoolTests.java index 28f779640590..f386116d806c 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/QueueThreadPoolTests.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/QueueThreadPoolTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.threading; +package com.swirlds.common.threading; import static com.swirlds.common.test.fixtures.AssertionUtils.assertEventuallyEquals; import static com.swirlds.common.test.fixtures.AssertionUtils.assertEventuallyFalse; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/QueueThreadTests.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/QueueThreadTests.java similarity index 99% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/QueueThreadTests.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/QueueThreadTests.java index 276c53bf5f3c..94ecda42f130 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/QueueThreadTests.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/QueueThreadTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.threading; +package com.swirlds.common.threading; import static com.swirlds.common.metrics.Metrics.INTERNAL_CATEGORY; import static com.swirlds.common.test.fixtures.AssertionUtils.assertEventuallyEquals; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/ReplaceSyncPhaseParallelExecutorTests.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/ReplaceSyncPhaseParallelExecutorTests.java similarity index 98% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/ReplaceSyncPhaseParallelExecutorTests.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/ReplaceSyncPhaseParallelExecutorTests.java index 0814dea19aa3..6f66a963402a 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/ReplaceSyncPhaseParallelExecutorTests.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/ReplaceSyncPhaseParallelExecutorTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.threading; +package com.swirlds.common.threading; import static com.swirlds.common.threading.manager.AdHocThreadManager.getStaticThreadManager; import static java.lang.String.format; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/StoppableThreadTests.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/StoppableThreadTests.java similarity index 99% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/StoppableThreadTests.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/StoppableThreadTests.java index f4ac22965605..4a174b030da0 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/StoppableThreadTests.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/StoppableThreadTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.threading; +package com.swirlds.common.threading; import static com.swirlds.common.test.fixtures.AssertionUtils.assertEventuallyEquals; import static com.swirlds.common.test.fixtures.AssertionUtils.assertEventuallyFalse; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/SyncPhaseParallelExecutorTest.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/SyncPhaseParallelExecutorTest.java similarity index 98% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/SyncPhaseParallelExecutorTest.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/SyncPhaseParallelExecutorTest.java index 243b8671b6e4..4b391657f486 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/SyncPhaseParallelExecutorTest.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/SyncPhaseParallelExecutorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.threading; +package com.swirlds.common.threading; import static com.swirlds.common.threading.manager.AdHocThreadManager.getStaticThreadManager; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/ThreadTests.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/ThreadTests.java similarity index 99% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/ThreadTests.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/ThreadTests.java index cc94f2c2d427..af207b083f69 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/threading/ThreadTests.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/threading/ThreadTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.threading; +package com.swirlds.common.threading; import static com.swirlds.common.test.fixtures.AssertionUtils.assertEventuallyTrue; import static com.swirlds.common.threading.framework.config.ThreadConfiguration.captureThreadConfiguration; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/time/IntegerEpochTimeTest.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/time/IntegerEpochTimeTest.java similarity index 98% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/time/IntegerEpochTimeTest.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/time/IntegerEpochTimeTest.java index b9b34266a551..697325bb00ba 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/time/IntegerEpochTimeTest.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/time/IntegerEpochTimeTest.java @@ -14,13 +14,12 @@ * limitations under the License. */ -package com.swirlds.common.test.time; +package com.swirlds.common.time; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import com.swirlds.base.test.fixtures.time.FakeTime; -import com.swirlds.common.time.IntegerEpochTime; import com.swirlds.common.units.UnitConstants; import java.time.Duration; import java.time.Instant; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/LongRunningAverageTests.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/LongRunningAverageTests.java similarity index 94% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/LongRunningAverageTests.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/LongRunningAverageTests.java index 6d10ac8fdfd1..ed6c4d820f0a 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/LongRunningAverageTests.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/LongRunningAverageTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,13 @@ * limitations under the License. */ -package com.swirlds.common.test.utility; +package com.swirlds.common.utility; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.swirlds.common.utility.LongRunningAverage; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/MnemonicsTests.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/MnemonicsTests.java similarity index 99% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/MnemonicsTests.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/MnemonicsTests.java index ee6f8e185830..d83152ae3eb0 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/MnemonicsTests.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/MnemonicsTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.utility; +package com.swirlds.common.utility; import static com.swirlds.common.test.fixtures.RandomUtils.getRandomPrintSeed; import static com.swirlds.common.utility.Mnemonics.generateMnemonic; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/NonCryptographicHashTest.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/NonCryptographicHashTest.java similarity index 99% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/NonCryptographicHashTest.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/NonCryptographicHashTest.java index b6229adc836b..866437c93810 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/NonCryptographicHashTest.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/NonCryptographicHashTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.utility; +package com.swirlds.common.utility; import static com.swirlds.common.test.fixtures.RandomUtils.getRandomPrintSeed; import static com.swirlds.common.utility.NonCryptographicHashing.hash32; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/PlatformVersionTest.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/PlatformVersionTest.java similarity index 97% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/PlatformVersionTest.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/PlatformVersionTest.java index f8de5d710301..39c132096ca3 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/PlatformVersionTest.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/PlatformVersionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.utility; +package com.swirlds.common.utility; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -25,9 +25,6 @@ import com.swirlds.common.constructable.ConstructableRegistry; import com.swirlds.common.constructable.ConstructableRegistryException; import com.swirlds.common.test.fixtures.io.SerializationUtils; -import com.swirlds.common.utility.InvalidSemanticVersionException; -import com.swirlds.common.utility.PlatformVersion; -import com.swirlds.common.utility.SemanticVersion; import com.swirlds.test.framework.TestComponentTags; import com.swirlds.test.framework.TestTypeTags; import java.io.IOException; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/SemanticVersionTest.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/SemanticVersionTest.java similarity index 97% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/SemanticVersionTest.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/SemanticVersionTest.java index e83096733b65..a400fe82a6cf 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/SemanticVersionTest.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/SemanticVersionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.utility; +package com.swirlds.common.utility; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -25,8 +25,6 @@ import com.swirlds.common.constructable.ConstructableRegistry; import com.swirlds.common.constructable.ConstructableRegistryException; import com.swirlds.common.test.fixtures.io.SerializationUtils; -import com.swirlds.common.utility.InvalidSemanticVersionException; -import com.swirlds.common.utility.SemanticVersion; import com.swirlds.test.framework.TestComponentTags; import com.swirlds.test.framework.TestTypeTags; import java.io.IOException; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/ThresholdTests.java b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/ThresholdTests.java similarity index 99% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/ThresholdTests.java rename to platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/ThresholdTests.java index c35ee9b5e07c..b8ac7b82cee8 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/java/com/swirlds/common/test/utility/ThresholdTests.java +++ b/platform-sdk/swirlds-common/src/test/java/com/swirlds/common/utility/ThresholdTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.utility; +package com.swirlds.common.utility; import static com.swirlds.common.utility.Threshold.MAJORITY; import static com.swirlds.common.utility.Threshold.STRONG_MINORITY; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/resources/platform/version/bad-version-descriptor.jar b/platform-sdk/swirlds-common/src/test/resources/platform/version/bad-version-descriptor.jar similarity index 100% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/resources/platform/version/bad-version-descriptor.jar rename to platform-sdk/swirlds-common/src/test/resources/platform/version/bad-version-descriptor.jar diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/resources/platform/version/bad.git.properties b/platform-sdk/swirlds-common/src/test/resources/platform/version/bad.git.properties similarity index 100% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/resources/platform/version/bad.git.properties rename to platform-sdk/swirlds-common/src/test/resources/platform/version/bad.git.properties diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/resources/platform/version/example-version-descriptor.jar b/platform-sdk/swirlds-common/src/test/resources/platform/version/example-version-descriptor.jar similarity index 100% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/resources/platform/version/example-version-descriptor.jar rename to platform-sdk/swirlds-common/src/test/resources/platform/version/example-version-descriptor.jar diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/resources/platform/version/git.properties b/platform-sdk/swirlds-common/src/test/resources/platform/version/git.properties similarity index 100% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/test/resources/platform/version/git.properties rename to platform-sdk/swirlds-common/src/test/resources/platform/version/git.properties diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/AbstractBenchmarkOperation.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/AbstractBenchmarkOperation.java similarity index 94% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/AbstractBenchmarkOperation.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/AbstractBenchmarkOperation.java index b3f91e1f6aae..073087f58c6d 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/AbstractBenchmarkOperation.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/AbstractBenchmarkOperation.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.benchmark; +package com.swirlds.common.test.fixtures.benchmark; import com.swirlds.common.merkle.MerkleNode; import java.util.Random; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/Benchmark.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/Benchmark.java similarity index 99% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/Benchmark.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/Benchmark.java index b60f2ef94bfe..294452637fb3 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/Benchmark.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/Benchmark.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.benchmark; +package com.swirlds.common.test.fixtures.benchmark; import com.swirlds.common.crypto.Hash; import com.swirlds.common.merkle.MerkleNode; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/BenchmarkConfiguration.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/BenchmarkConfiguration.java similarity index 98% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/BenchmarkConfiguration.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/BenchmarkConfiguration.java index 558ac75f6495..225218c6845e 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/BenchmarkConfiguration.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/BenchmarkConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.benchmark; +package com.swirlds.common.test.fixtures.benchmark; import com.swirlds.common.merkle.MerkleNode; import java.time.Duration; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/BenchmarkMetadata.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/BenchmarkMetadata.java similarity index 87% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/BenchmarkMetadata.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/BenchmarkMetadata.java index 2437ba8cb63c..6e88d891fde6 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/BenchmarkMetadata.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/BenchmarkMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.benchmark; +package com.swirlds.common.test.fixtures.benchmark; /** * Non-merkle benchmark specific state. diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/BenchmarkOperation.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/BenchmarkOperation.java similarity index 96% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/BenchmarkOperation.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/BenchmarkOperation.java index e893d0d58acb..dec613021451 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/BenchmarkOperation.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/BenchmarkOperation.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.benchmark; +package com.swirlds.common.test.fixtures.benchmark; import com.swirlds.common.merkle.MerkleNode; import java.util.Random; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/BenchmarkStatistic.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/BenchmarkStatistic.java similarity index 97% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/BenchmarkStatistic.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/BenchmarkStatistic.java index fdf8ad49b478..7ceb5eaaafe6 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/BenchmarkStatistic.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/BenchmarkStatistic.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.benchmark; +package com.swirlds.common.test.fixtures.benchmark; import java.time.Duration; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/ImmutableStateManager.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/ImmutableStateManager.java similarity index 93% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/ImmutableStateManager.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/ImmutableStateManager.java index ba0c18ab21ee..18d836579a1b 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/ImmutableStateManager.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/ImmutableStateManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.benchmark; +package com.swirlds.common.test.fixtures.benchmark; import com.swirlds.common.merkle.MerkleNode; import com.swirlds.common.utility.AutoCloseableWrapper; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/MutableStateManager.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/MutableStateManager.java similarity index 94% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/MutableStateManager.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/MutableStateManager.java index 0cebac4f2d5c..150d13bef76f 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/MutableStateManager.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/MutableStateManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.benchmark; +package com.swirlds.common.test.fixtures.benchmark; import com.swirlds.common.merkle.MerkleNode; import com.swirlds.common.utility.AutoCloseableWrapper; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/StateManager.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/StateManager.java similarity index 89% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/StateManager.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/StateManager.java index 72d3659cfca8..c0ae47c113df 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/benchmark/StateManager.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/benchmark/StateManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.benchmark; +package com.swirlds.common.test.fixtures.benchmark; import com.swirlds.common.merkle.MerkleNode; import com.swirlds.common.utility.AutoCloseableWrapper; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/dummy/Key.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/dummy/Key.java similarity index 97% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/dummy/Key.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/dummy/Key.java index fe427874249d..5f830f15de41 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/dummy/Key.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/dummy/Key.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.dummy; +package com.swirlds.common.test.fixtures.dummy; import com.swirlds.common.FastCopyable; import com.swirlds.common.io.SelfSerializable; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/dummy/MerkleKey.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/dummy/MerkleKey.java similarity index 95% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/dummy/MerkleKey.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/dummy/MerkleKey.java index 9348b63c1041..bfaaa0862fe4 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/dummy/MerkleKey.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/dummy/MerkleKey.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.dummy; +package com.swirlds.common.test.fixtures.dummy; import com.swirlds.common.io.streams.SerializableDataInputStream; import com.swirlds.common.io.streams.SerializableDataOutputStream; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/dummy/Value.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/dummy/Value.java similarity index 98% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/dummy/Value.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/dummy/Value.java index 56309b9cb033..1625545d86c5 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/dummy/Value.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/dummy/Value.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.dummy; +package com.swirlds.common.test.fixtures.dummy; import com.swirlds.common.io.streams.SerializableDataInputStream; import com.swirlds.common.io.streams.SerializableDataOutputStream; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/map/MapPair.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/map/MapPair.java similarity index 96% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/map/MapPair.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/map/MapPair.java index 8415fb5fc2ba..c2eb2adb5dc9 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/map/MapPair.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/map/MapPair.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.map; +package com.swirlds.common.test.fixtures.map; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/map/MapPairs.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/map/MapPairs.java similarity index 94% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/map/MapPairs.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/map/MapPairs.java index 884c29688aaf..2ec4b853d0bc 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/map/MapPairs.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/map/MapPairs.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.map; +package com.swirlds.common.test.fixtures.map; import com.swirlds.common.FastCopyable; import java.util.LinkedList; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/Hotspot.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/Hotspot.java similarity index 94% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/Hotspot.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/Hotspot.java index 2a8c958710e4..9c818d569f03 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/Hotspot.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/Hotspot.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.set; +package com.swirlds.common.test.fixtures.set; /** * Describes a hotspot in a {@link HotspotHashSet}. diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/HotspotHashSet.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/HotspotHashSet.java similarity index 99% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/HotspotHashSet.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/HotspotHashSet.java index 85075071770b..26d4c8fbd784 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/HotspotHashSet.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/HotspotHashSet.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.set; +package com.swirlds.common.test.fixtures.set; import java.util.ArrayList; import java.util.Collection; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/HotspotSetIterator.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/HotspotSetIterator.java similarity index 94% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/HotspotSetIterator.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/HotspotSetIterator.java index 271d9a6c7123..ac45bc5f42d1 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/HotspotSetIterator.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/HotspotSetIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.set; +package com.swirlds.common.test.fixtures.set; import java.util.Iterator; import java.util.List; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/RandomAccessHashSet.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/RandomAccessHashSet.java similarity index 97% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/RandomAccessHashSet.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/RandomAccessHashSet.java index 159f3d68f3ae..68e76ca3df35 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/RandomAccessHashSet.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/RandomAccessHashSet.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.set; +package com.swirlds.common.test.fixtures.set; import java.util.ArrayList; import java.util.HashMap; diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/RandomAccessSet.java b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/RandomAccessSet.java similarity index 96% rename from platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/RandomAccessSet.java rename to platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/RandomAccessSet.java index 71ad3a7c9139..62ca1aa3f30f 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/com/swirlds/common/test/set/RandomAccessSet.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/com/swirlds/common/test/fixtures/set/RandomAccessSet.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.common.test.set; +package com.swirlds.common.test.fixtures.set; import java.util.Collection; import java.util.Random; diff --git a/platform-sdk/swirlds-common/src/testFixtures/java/module-info.java b/platform-sdk/swirlds-common/src/testFixtures/java/module-info.java index 9ceba497ca12..97f483385e28 100644 --- a/platform-sdk/swirlds-common/src/testFixtures/java/module-info.java +++ b/platform-sdk/swirlds-common/src/testFixtures/java/module-info.java @@ -1,9 +1,13 @@ open module com.swirlds.common.test.fixtures { exports com.swirlds.common.test.fixtures; + exports com.swirlds.common.test.fixtures.benchmark; exports com.swirlds.common.test.fixtures.crypto; + exports com.swirlds.common.test.fixtures.dummy; exports com.swirlds.common.test.fixtures.io; + exports com.swirlds.common.test.fixtures.map; exports com.swirlds.common.test.fixtures.merkle.util; exports com.swirlds.common.test.fixtures.threading; + exports com.swirlds.common.test.fixtures.set; exports com.swirlds.common.test.fixtures.stream; exports com.swirlds.common.test.fixtures.fcqueue; diff --git a/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/converter/package-info.java b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/converter/package-info.java new file mode 100644 index 000000000000..3f7536bb12af --- /dev/null +++ b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/converter/package-info.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * 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. + * + */ + +/** + * This package defines the converter api of the config api that can be used to support custom data types as values for + * configuration properties. + * + * @see com.swirlds.config.api.ConfigurationBuilder#withConverter(com.swirlds.config.api.converter.ConfigConverter) + */ +package com.swirlds.config.api.converter; diff --git a/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/intern/package-info.java b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/intern/package-info.java new file mode 100644 index 000000000000..4f1107849c09 --- /dev/null +++ b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/intern/package-info.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * 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. + * + */ + +/** + * This private package contains internal classes that are not part of the public API. It defines how a concrete + * implementation of the config API is loaded. + */ +package com.swirlds.config.api.intern; diff --git a/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/package-info.java b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/package-info.java new file mode 100644 index 000000000000..2c5835ddda16 --- /dev/null +++ b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/package-info.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * 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. + * + */ + +/** + * The config API. + * At its core, it offers the primary interface, {@link com.swirlds.config.api.Configuration}, which serves as the central point for interacting with your application's configuration settings. + * + * @see com.swirlds.config.api.Configuration + */ +package com.swirlds.config.api; diff --git a/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/source/package-info.java b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/source/package-info.java new file mode 100644 index 000000000000..acb617d29071 --- /dev/null +++ b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/source/package-info.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * 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. + * + */ + +/** + * This package defines the source api of the config api that can be used to add custom sources for config properties to + * a configuration. + * + * @see com.swirlds.config.api.ConfigurationBuilder#withSource(com.swirlds.config.api.source.ConfigSource) + */ +package com.swirlds.config.api.source; diff --git a/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/spi/package-info.java b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/spi/package-info.java new file mode 100644 index 000000000000..ac9350ea6577 --- /dev/null +++ b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/spi/package-info.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * 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. + * + */ + +/** + * The package defines the entry point for an implementation of the config api. An implementation must implement the + * {@link com.swirlds.config.api.spi.ConfigurationBuilderFactory} interface and provide it to the Java SPI. + */ +package com.swirlds.config.api.spi; diff --git a/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/validation/annotation/package-info.java b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/validation/annotation/package-info.java new file mode 100644 index 000000000000..04a3e4bb61d5 --- /dev/null +++ b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/validation/annotation/package-info.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * 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. + * + */ + +/** + * This package contains annotations that can be added to config properties in a config data object to add validation to + * the config data object. + */ +package com.swirlds.config.api.validation.annotation; diff --git a/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/validation/package-info.java b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/validation/package-info.java new file mode 100644 index 000000000000..b58f4f786977 --- /dev/null +++ b/platform-sdk/swirlds-config-api/src/main/java/com/swirlds/config/api/validation/package-info.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * 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. + * + */ + +/** + * The package provides an api to validate configuration properties at creation time of a configuration. The interface + * {@link com.swirlds.config.api.validation.ConfigValidator} is the most basic way to add a validation (see + * {@link + * com.swirlds.config.api.ConfigurationBuilder#withValidator(com.swirlds.config.api.validation.ConfigValidator)}). When + * working with config data object (see {@link com.swirlds.config.api.ConfigData}) the + * {@link com.swirlds.config.api.validation.annotation} package provides annotations to add validation to the config + * data objects. + * + * @see com.swirlds.config.api.validation.ConfigValidator + * @see com.swirlds.config.api.ConfigurationBuilder#withValidator(com.swirlds.config.api.validation.ConfigValidator) + */ +package com.swirlds.config.api.validation; diff --git a/platform-sdk/swirlds-config-benchmark/src/main/java/module-info.java b/platform-sdk/swirlds-config-benchmark/src/main/java/module-info.java deleted file mode 100644 index 7a75e9fa4e8a..000000000000 --- a/platform-sdk/swirlds-config-benchmark/src/main/java/module-info.java +++ /dev/null @@ -1 +0,0 @@ -module com.swirlds.config.benchmark {} diff --git a/platform-sdk/swirlds-config-extensions/build.gradle.kts b/platform-sdk/swirlds-config-extensions/build.gradle.kts index 7d45e559a9ab..b021f5410d97 100644 --- a/platform-sdk/swirlds-config-extensions/build.gradle.kts +++ b/platform-sdk/swirlds-config-extensions/build.gradle.kts @@ -18,8 +18,3 @@ plugins { id("com.hedera.hashgraph.sdk.conventions") id("com.hedera.hashgraph.platform-maven-publish") } - -testModuleInfo { - requires("com.swirlds.test.framework") - requires("org.junit.jupiter.api") -} diff --git a/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/package-info.java b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/package-info.java new file mode 100644 index 000000000000..0e13457c52a1 --- /dev/null +++ b/platform-sdk/swirlds-config-extensions/src/main/java/com/swirlds/config/extensions/package-info.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * 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. + * + */ + +/** + * Extensions for the config API + * + * @see com.swirlds.config.api + * @see com.swirlds.config.api.Configuration + */ +package com.swirlds.config.extensions; diff --git a/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/sources/MappedConfigSourceTest.java b/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/MappedConfigSourceTest.java similarity index 96% rename from platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/sources/MappedConfigSourceTest.java rename to platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/MappedConfigSourceTest.java index 02aeb9720d8a..63066ac4a557 100644 --- a/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/sources/MappedConfigSourceTest.java +++ b/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/MappedConfigSourceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,8 +14,10 @@ * limitations under the License. */ -package com.swirlds.config.extensions.sources; +package com.swirlds.config.extensions.test; +import com.swirlds.config.extensions.sources.MappedConfigSource; +import com.swirlds.config.extensions.sources.SimpleConfigSource; import com.swirlds.test.framework.config.TestConfigBuilder; import java.util.NoSuchElementException; import java.util.Set; diff --git a/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/sources/PropertyFileConfigSourceTest.java b/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/PropertyFileConfigSourceTest.java similarity index 93% rename from platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/sources/PropertyFileConfigSourceTest.java rename to platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/PropertyFileConfigSourceTest.java index fb69a48be1ef..113f49726e26 100644 --- a/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/sources/PropertyFileConfigSourceTest.java +++ b/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/PropertyFileConfigSourceTest.java @@ -14,13 +14,14 @@ * limitations under the License. */ -package com.swirlds.config.extensions.sources; +package com.swirlds.config.extensions.test; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import com.swirlds.config.api.Configuration; import com.swirlds.config.api.ConfigurationBuilder; +import com.swirlds.config.extensions.sources.PropertyFileConfigSource; import java.nio.file.Path; import org.junit.jupiter.api.Test; @@ -31,6 +32,7 @@ void testConfig2HigherOrdinal() { // given final int ordinal1 = 100; final Path configFile1 = Path.of(PropertyFileConfigSourceTest.class + .getClassLoader() .getResource("config1.properties") .getFile()); final PropertyFileConfigSource source1 = @@ -38,6 +40,7 @@ void testConfig2HigherOrdinal() { final int ordinal2 = 200; final Path configFile2 = Path.of(PropertyFileConfigSourceTest.class + .getClassLoader() .getResource("config2.properties") .getFile()); final PropertyFileConfigSource source2 = @@ -62,6 +65,7 @@ void testConfig1HigherOrdinal() { // given final int ordinal1 = 200; final Path configFile1 = Path.of(PropertyFileConfigSourceTest.class + .getClassLoader() .getResource("config1.properties") .getFile()); final PropertyFileConfigSource source1 = @@ -69,6 +73,7 @@ void testConfig1HigherOrdinal() { final int ordinal2 = 100; final Path configFile2 = Path.of(PropertyFileConfigSourceTest.class + .getClassLoader() .getResource("config2.properties") .getFile()); final PropertyFileConfigSource source2 = @@ -93,18 +98,21 @@ void testConfigDefaultOrdinal() { // given final int ordinal1 = 199; final Path configFile1 = Path.of(PropertyFileConfigSourceTest.class + .getClassLoader() .getResource("config1.properties") .getFile()); final PropertyFileConfigSource source1 = assertDoesNotThrow(() -> new PropertyFileConfigSource(configFile1, ordinal1)); final Path configFile2 = Path.of(PropertyFileConfigSourceTest.class + .getClassLoader() .getResource("config2.properties") .getFile()); final PropertyFileConfigSource source2 = assertDoesNotThrow(() -> new PropertyFileConfigSource(configFile2)); final int ordinal3 = 201; final Path configFile3 = Path.of(PropertyFileConfigSourceTest.class + .getClassLoader() .getResource("config3.properties") .getFile()); final PropertyFileConfigSource source3 = diff --git a/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/sources/SimpleConfigSourceTest.java b/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/SimpleConfigSourceTest.java similarity index 98% rename from platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/sources/SimpleConfigSourceTest.java rename to platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/SimpleConfigSourceTest.java index 2e55d50e25b8..c095357b0fe3 100644 --- a/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/sources/SimpleConfigSourceTest.java +++ b/platform-sdk/swirlds-config-extensions/src/test/java/com/swirlds/config/extensions/test/SimpleConfigSourceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.swirlds.config.extensions.sources; +package com.swirlds.config.extensions.test; import com.swirlds.config.api.Configuration; import com.swirlds.config.api.ConfigurationBuilder; +import com.swirlds.config.extensions.sources.SimpleConfigSource; import java.util.List; import java.util.stream.Collectors; import org.junit.jupiter.api.Assertions; diff --git a/platform-sdk/swirlds-config-extensions/src/test/java/module-info.java b/platform-sdk/swirlds-config-extensions/src/test/java/module-info.java new file mode 100644 index 000000000000..e1fabb2a9b4f --- /dev/null +++ b/platform-sdk/swirlds-config-extensions/src/test/java/module-info.java @@ -0,0 +1,5 @@ +open module com.swirlds.config.extensions.test { + requires com.swirlds.config.extensions; + requires com.swirlds.test.framework; + requires org.junit.jupiter.api; +} diff --git a/platform-sdk/swirlds-config-extensions/src/test/resources/com/swirlds/config/extensions/sources/config1.properties b/platform-sdk/swirlds-config-extensions/src/test/resources/config1.properties similarity index 100% rename from platform-sdk/swirlds-config-extensions/src/test/resources/com/swirlds/config/extensions/sources/config1.properties rename to platform-sdk/swirlds-config-extensions/src/test/resources/config1.properties diff --git a/platform-sdk/swirlds-config-extensions/src/test/resources/com/swirlds/config/extensions/sources/config2.properties b/platform-sdk/swirlds-config-extensions/src/test/resources/config2.properties similarity index 100% rename from platform-sdk/swirlds-config-extensions/src/test/resources/com/swirlds/config/extensions/sources/config2.properties rename to platform-sdk/swirlds-config-extensions/src/test/resources/config2.properties diff --git a/platform-sdk/swirlds-config-extensions/src/test/resources/com/swirlds/config/extensions/sources/config3.properties b/platform-sdk/swirlds-config-extensions/src/test/resources/config3.properties similarity index 100% rename from platform-sdk/swirlds-config-extensions/src/test/resources/com/swirlds/config/extensions/sources/config3.properties rename to platform-sdk/swirlds-config-extensions/src/test/resources/config3.properties diff --git a/platform-sdk/swirlds-config-impl/build.gradle.kts b/platform-sdk/swirlds-config-impl/build.gradle.kts index 57818d9fb55b..0e0bf6deca0e 100644 --- a/platform-sdk/swirlds-config-impl/build.gradle.kts +++ b/platform-sdk/swirlds-config-impl/build.gradle.kts @@ -17,9 +17,17 @@ plugins { id("com.hedera.hashgraph.sdk.conventions") id("com.hedera.hashgraph.platform-maven-publish") + id("com.hedera.hashgraph.benchmark-conventions") } testModuleInfo { requires("org.junit.jupiter.api") requires("org.junit.jupiter.params") } + +jmhModuleInfo { + requires("com.swirlds.common") + requires("com.swirlds.config.api") + requires("com.swirlds.config.extensions") + requires("jmh.core") +} diff --git a/platform-sdk/swirlds-config-benchmark/src/jmh/java/com/swirlds/config/benchmark/ConfigBenchmark.java b/platform-sdk/swirlds-config-impl/src/jmh/java/com/swirlds/config/benchmark/ConfigBenchmark.java similarity index 97% rename from platform-sdk/swirlds-config-benchmark/src/jmh/java/com/swirlds/config/benchmark/ConfigBenchmark.java rename to platform-sdk/swirlds-config-impl/src/jmh/java/com/swirlds/config/benchmark/ConfigBenchmark.java index e466585cffe5..06feca411e70 100644 --- a/platform-sdk/swirlds-config-benchmark/src/jmh/java/com/swirlds/config/benchmark/ConfigBenchmark.java +++ b/platform-sdk/swirlds-config-impl/src/jmh/java/com/swirlds/config/benchmark/ConfigBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -67,6 +67,7 @@ public void setup() throws IOException, URISyntaxException { fileSystem = FileSystems.newFileSystem(configUri, Collections.emptyMap()); final Path configFile = Paths.get(configUri); configuration = ConfigurationBuilder.create() + .withConfigDataType(AppConfig.class) .withSource(new PropertyFileConfigSource(configFile)) .build(); } diff --git a/platform-sdk/swirlds-config-benchmark/src/jmh/java/com/swirlds/config/benchmark/ConfigUtilsBenchmark.java b/platform-sdk/swirlds-config-impl/src/jmh/java/com/swirlds/config/benchmark/ConfigUtilsBenchmark.java similarity index 100% rename from platform-sdk/swirlds-config-benchmark/src/jmh/java/com/swirlds/config/benchmark/ConfigUtilsBenchmark.java rename to platform-sdk/swirlds-config-impl/src/jmh/java/com/swirlds/config/benchmark/ConfigUtilsBenchmark.java diff --git a/platform-sdk/swirlds-config-benchmark/src/jmh/resources/com/swirlds/config/benchmark/app.properties b/platform-sdk/swirlds-config-impl/src/jmh/resources/com/swirlds/config/benchmark/app.properties similarity index 100% rename from platform-sdk/swirlds-config-benchmark/src/jmh/resources/com/swirlds/config/benchmark/app.properties rename to platform-sdk/swirlds-config-impl/src/jmh/resources/com/swirlds/config/benchmark/app.properties diff --git a/platform-sdk/swirlds-config-processor/build.gradle.kts b/platform-sdk/swirlds-config-processor/build.gradle.kts new file mode 100644 index 000000000000..bf1e20a29685 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/build.gradle.kts @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2020-2023 Hedera Hashgraph, LLC + * + * 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. + */ + +plugins { + id("com.hedera.hashgraph.sdk.conventions") + id("com.hedera.hashgraph.platform-maven-publish") + // antlr +} + +mainModuleInfo { annotationProcessor("com.google.auto.service.processor") } + +testModuleInfo { requires("org.junit.jupiter.api") } + +tasks.register("generateParser") { + conventionMapping.map("antlrClasspath") { + configurations.detachedConfiguration(dependencies.create("org.antlr:antlr4:4.13.1")) + } + source(layout.projectDirectory.dir("src/main/antlr")) + outputDirectory = + File( + sourceSets.main.get().java.sourceDirectories.singleFile, + "com/swirlds/config/processor/antlr/generated" + ) +} diff --git a/platform-sdk/swirlds-config-processor/src/main/antlr/JavaLexer.g4 b/platform-sdk/swirlds-config-processor/src/main/antlr/JavaLexer.g4 new file mode 100644 index 000000000000..cd274be2d90d --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/antlr/JavaLexer.g4 @@ -0,0 +1,246 @@ +/* + [The "BSD licence"] + Copyright (c) 2013 Terence Parr, Sam Harwell + Copyright (c) 2017 Ivan Kochurkin (upgrade to Java 8) + Copyright (c) 2021 Michał Lorek (upgrade to Java 11) + Copyright (c) 2022 Michał Lorek (upgrade to Java 17) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +lexer grammar JavaLexer; + +@lexer::header { +package com.swirlds.config.processor.antlr.generated; +} + +// Keywords + +ABSTRACT: 'abstract'; +ASSERT: 'assert'; +BOOLEAN: 'boolean'; +BREAK: 'break'; +BYTE: 'byte'; +CASE: 'case'; +CATCH: 'catch'; +CHAR: 'char'; +CLASS: 'class'; +CONST: 'const'; +CONTINUE: 'continue'; +DEFAULT: 'default'; +DO: 'do'; +DOUBLE: 'double'; +ELSE: 'else'; +ENUM: 'enum'; +EXTENDS: 'extends'; +FINAL: 'final'; +FINALLY: 'finally'; +FLOAT: 'float'; +FOR: 'for'; +IF: 'if'; +GOTO: 'goto'; +IMPLEMENTS: 'implements'; +IMPORT: 'import'; +INSTANCEOF: 'instanceof'; +INT: 'int'; +INTERFACE: 'interface'; +LONG: 'long'; +NATIVE: 'native'; +NEW: 'new'; +PACKAGE: 'package'; +PRIVATE: 'private'; +PROTECTED: 'protected'; +PUBLIC: 'public'; +RETURN: 'return'; +SHORT: 'short'; +STATIC: 'static'; +STRICTFP: 'strictfp'; +SUPER: 'super'; +SWITCH: 'switch'; +SYNCHRONIZED: 'synchronized'; +THIS: 'this'; +THROW: 'throw'; +THROWS: 'throws'; +TRANSIENT: 'transient'; +TRY: 'try'; +VOID: 'void'; +VOLATILE: 'volatile'; +WHILE: 'while'; + +// Module related keywords +MODULE: 'module'; +OPEN: 'open'; +REQUIRES: 'requires'; +EXPORTS: 'exports'; +OPENS: 'opens'; +TO: 'to'; +USES: 'uses'; +PROVIDES: 'provides'; +WITH: 'with'; +TRANSITIVE: 'transitive'; + +// Local Variable Type Inference +VAR: 'var'; // reserved type name + +// Switch Expressions +YIELD: 'yield'; // reserved type name from Java 14 + +// Records +RECORD: 'record'; + +// Sealed Classes +SEALED: 'sealed'; +PERMITS: 'permits'; +NON_SEALED: 'non-sealed'; + +// Literals + +DECIMAL_LITERAL: ('0' | [1-9] (Digits? | '_'+ Digits)) [lL]?; +HEX_LITERAL: '0' [xX] [0-9a-fA-F] ([0-9a-fA-F_]* [0-9a-fA-F])? [lL]?; +OCT_LITERAL: '0' '_'* [0-7] ([0-7_]* [0-7])? [lL]?; +BINARY_LITERAL: '0' [bB] [01] ([01_]* [01])? [lL]?; + +FLOAT_LITERAL: (Digits '.' Digits? | '.' Digits) ExponentPart? [fFdD]? + | Digits (ExponentPart [fFdD]? | [fFdD]) + ; + +HEX_FLOAT_LITERAL: '0' [xX] (HexDigits '.'? | HexDigits? '.' HexDigits) [pP] [+-]? Digits [fFdD]?; + +BOOL_LITERAL: 'true' + | 'false' + ; + +CHAR_LITERAL: '\'' (~['\\\r\n] | EscapeSequence) '\''; + +STRING_LITERAL: '"' (~["\\\r\n] | EscapeSequence)* '"'; + +TEXT_BLOCK: '"""' [ \t]* [\r\n] (. | EscapeSequence)*? '"""'; + +NULL_LITERAL: 'null'; + +// Separators + +LPAREN: '('; +RPAREN: ')'; +LBRACE: '{'; +RBRACE: '}'; +LBRACK: '['; +RBRACK: ']'; +SEMI: ';'; +COMMA: ','; +DOT: '.'; + +// Operators + +ASSIGN: '='; +GT: '>'; +LT: '<'; +BANG: '!'; +TILDE: '~'; +QUESTION: '?'; +COLON: ':'; +EQUAL: '=='; +LE: '<='; +GE: '>='; +NOTEQUAL: '!='; +AND: '&&'; +OR: '||'; +INC: '++'; +DEC: '--'; +ADD: '+'; +SUB: '-'; +MUL: '*'; +DIV: '/'; +BITAND: '&'; +BITOR: '|'; +CARET: '^'; +MOD: '%'; + +ADD_ASSIGN: '+='; +SUB_ASSIGN: '-='; +MUL_ASSIGN: '*='; +DIV_ASSIGN: '/='; +AND_ASSIGN: '&='; +OR_ASSIGN: '|='; +XOR_ASSIGN: '^='; +MOD_ASSIGN: '%='; +LSHIFT_ASSIGN: '<<='; +RSHIFT_ASSIGN: '>>='; +URSHIFT_ASSIGN: '>>>='; + +// Java 8 tokens + +ARROW: '->'; +COLONCOLON: '::'; + +// Additional symbols not defined in the lexical specification + +AT: '@'; +ELLIPSIS: '...'; + +// Whitespace and comments + +JAVADOC_COMMENT: '/**' .*? '*/'; +WS: [ \t\r\n\u000C]+ -> channel(HIDDEN); +COMMENT: '/*' .*? '*/' -> channel(HIDDEN); +LINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN); + +// Identifiers + +IDENTIFIER: Letter LetterOrDigit*; + +// Fragment rules + +fragment ExponentPart + : [eE] [+-]? Digits + ; + +fragment EscapeSequence + : '\\' 'u005c'? [btnfr"'\\] + | '\\' 'u005c'? ([0-3]? [0-7])? [0-7] + | '\\' 'u'+ HexDigit HexDigit HexDigit HexDigit + ; + +fragment HexDigits + : HexDigit ((HexDigit | '_')* HexDigit)? + ; + +fragment HexDigit + : [0-9a-fA-F] + ; + +fragment Digits + : [0-9] ([0-9_]* [0-9])? + ; + +fragment LetterOrDigit + : Letter + | [0-9] + ; + +fragment Letter + : [a-zA-Z$_] // these are the "java letters" below 0x7F + | ~[\u0000-\u007F\uD800-\uDBFF] // covers all characters above 0x7F which are not a surrogate + | [\uD800-\uDBFF] [\uDC00-\uDFFF] // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + ; diff --git a/platform-sdk/swirlds-config-processor/src/main/antlr/JavaParser.g4 b/platform-sdk/swirlds-config-processor/src/main/antlr/JavaParser.g4 new file mode 100644 index 000000000000..6df48c644da2 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/antlr/JavaParser.g4 @@ -0,0 +1,784 @@ +/* + [The "BSD licence"] + Copyright (c) 2013 Terence Parr, Sam Harwell + Copyright (c) 2017 Ivan Kochurkin (upgrade to Java 8) + Copyright (c) 2021 Michał Lorek (upgrade to Java 11) + Copyright (c) 2022 Michał Lorek (upgrade to Java 17) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +parser grammar JavaParser; + +@header { +package com.swirlds.config.processor.antlr.generated; +} + +options { tokenVocab=JavaLexer; } + +compilationUnit + : packageDeclaration? (importDeclaration | ';')* JAVADOC_COMMENT* (typeDeclaration | ';')* + | moduleDeclaration EOF + ; + +packageDeclaration + : annotation* PACKAGE qualifiedName ';' + ; + +importDeclaration + : IMPORT STATIC? qualifiedName ('.' '*')? ';' + ; + +typeDeclaration + : classOrInterfaceModifier* + (classDeclaration | enumDeclaration | interfaceDeclaration | annotationTypeDeclaration | recordDeclaration) + ; + +modifier + : classOrInterfaceModifier + | NATIVE + | SYNCHRONIZED + | TRANSIENT + | VOLATILE + ; + +classOrInterfaceModifier + : annotation + | PUBLIC + | PROTECTED + | PRIVATE + | STATIC + | ABSTRACT + | FINAL // FINAL for class only -- does not apply to interfaces + | STRICTFP + | SEALED // Java17 + | NON_SEALED // Java17 + ; + +variableModifier + : FINAL + | annotation + ; + +classDeclaration + : CLASS identifier typeParameters? + (EXTENDS typeType)? + (IMPLEMENTS typeList)? + (PERMITS typeList)? // Java17 + classBody + ; + +typeParameters + : '<' typeParameter (',' typeParameter)* '>' + ; + +typeParameter + : annotation* identifier (EXTENDS annotation* typeBound)? + ; + +typeBound + : typeType ('&' typeType)* + ; + +enumDeclaration + : ENUM identifier (IMPLEMENTS typeList)? '{' enumConstants? ','? enumBodyDeclarations? '}' + ; + +enumConstants + : enumConstant (',' enumConstant)* + ; + +enumConstant + : annotation* identifier arguments? classBody? + ; + +enumBodyDeclarations + : ';' classBodyDeclaration* + ; + +interfaceDeclaration + : INTERFACE identifier typeParameters? (EXTENDS typeList)? (PERMITS typeList)? interfaceBody + ; + +classBody + : '{' classBodyDeclaration* '}' + ; + +interfaceBody + : '{' interfaceBodyDeclaration* '}' + ; + +classBodyDeclaration + : ';' + | STATIC? block + | modifier* memberDeclaration + ; + +memberDeclaration + : recordDeclaration //Java17 + | methodDeclaration + | genericMethodDeclaration + | fieldDeclaration + | constructorDeclaration + | genericConstructorDeclaration + | interfaceDeclaration + | annotationTypeDeclaration + | classDeclaration + | enumDeclaration + ; + +/* We use rule this even for void methods which cannot have [] after parameters. + This simplifies grammar and we can consider void to be a type, which + renders the [] matching as a context-sensitive issue or a semantic check + for invalid return type after parsing. + */ +methodDeclaration + : typeTypeOrVoid identifier formalParameters ('[' ']')* + (THROWS qualifiedNameList)? + methodBody + ; + +methodBody + : block + | ';' + ; + +typeTypeOrVoid + : typeType + | VOID + ; + +genericMethodDeclaration + : typeParameters methodDeclaration + ; + +genericConstructorDeclaration + : typeParameters constructorDeclaration + ; + +constructorDeclaration + : identifier formalParameters (THROWS qualifiedNameList)? constructorBody=block + ; + +compactConstructorDeclaration + : modifier* identifier constructorBody=block + ; + +fieldDeclaration + : typeType variableDeclarators ';' + ; + +interfaceBodyDeclaration + : modifier* interfaceMemberDeclaration + | ';' + ; + +interfaceMemberDeclaration + : recordDeclaration // Java17 + | constDeclaration + | interfaceMethodDeclaration + | genericInterfaceMethodDeclaration + | interfaceDeclaration + | annotationTypeDeclaration + | classDeclaration + | enumDeclaration + ; + +constDeclaration + : typeType constantDeclarator (',' constantDeclarator)* ';' + ; + +constantDeclarator + : identifier ('[' ']')* '=' variableInitializer + ; + +// Early versions of Java allows brackets after the method name, eg. +// public int[] return2DArray() [] { ... } +// is the same as +// public int[][] return2DArray() { ... } +interfaceMethodDeclaration + : interfaceMethodModifier* interfaceCommonBodyDeclaration + ; + +// Java8 +interfaceMethodModifier + : annotation + | PUBLIC + | ABSTRACT + | DEFAULT + | STATIC + | STRICTFP + ; + +genericInterfaceMethodDeclaration + : interfaceMethodModifier* typeParameters interfaceCommonBodyDeclaration + ; + +interfaceCommonBodyDeclaration + : annotation* typeTypeOrVoid identifier formalParameters ('[' ']')* (THROWS qualifiedNameList)? methodBody + ; + +variableDeclarators + : variableDeclarator (',' variableDeclarator)* + ; + +variableDeclarator + : variableDeclaratorId ('=' variableInitializer)? + ; + +variableDeclaratorId + : identifier ('[' ']')* + ; + +variableInitializer + : arrayInitializer + | expression + ; + +arrayInitializer + : '{' (variableInitializer (',' variableInitializer)* ','? )? '}' + ; + +classOrInterfaceType + : (identifier typeArguments? '.')* typeIdentifier typeArguments? + ; + +typeArgument + : typeType + | annotation* '?' ((EXTENDS | SUPER) typeType)? + ; + +qualifiedNameList + : qualifiedName (',' qualifiedName)* + ; + +formalParameters + : '(' ( receiverParameter? + | receiverParameter (',' formalParameterList)? + | formalParameterList? + ) ')' + ; + +receiverParameter + : typeType (identifier '.')* THIS + ; + +formalParameterList + : formalParameter (',' formalParameter)* (',' lastFormalParameter)? + | lastFormalParameter + ; + +formalParameter + : variableModifier* typeType variableDeclaratorId + ; + +lastFormalParameter + : variableModifier* typeType annotation* '...' variableDeclaratorId + ; + +// local variable type inference +lambdaLVTIList + : lambdaLVTIParameter (',' lambdaLVTIParameter)* + ; + +lambdaLVTIParameter + : variableModifier* VAR identifier + ; + +qualifiedName + : identifier ('.' identifier)* + ; + +literal + : integerLiteral + | floatLiteral + | CHAR_LITERAL + | STRING_LITERAL + | BOOL_LITERAL + | NULL_LITERAL + | TEXT_BLOCK // Java17 + ; + +integerLiteral + : DECIMAL_LITERAL + | HEX_LITERAL + | OCT_LITERAL + | BINARY_LITERAL + ; + +floatLiteral + : FLOAT_LITERAL + | HEX_FLOAT_LITERAL + ; + +// ANNOTATIONS +altAnnotationQualifiedName + : (identifier DOT)* '@' identifier + ; + +annotation + : ('@' qualifiedName | altAnnotationQualifiedName) ('(' ( elementValuePairs | elementValue )? ')')? + ; + +elementValuePairs + : elementValuePair (',' elementValuePair)* + ; + +elementValuePair + : identifier '=' elementValue + ; + +elementValue + : expression + | annotation + | elementValueArrayInitializer + ; + +elementValueArrayInitializer + : '{' (elementValue (',' elementValue)*)? ','? '}' + ; + +annotationTypeDeclaration + : '@' INTERFACE identifier annotationTypeBody + ; + +annotationTypeBody + : '{' annotationTypeElementDeclaration* '}' + ; + +annotationTypeElementDeclaration + : modifier* annotationTypeElementRest + | ';' // this is not allowed by the grammar, but apparently allowed by the actual compiler + ; + +annotationTypeElementRest + : typeType annotationMethodOrConstantRest ';' + | classDeclaration ';'? + | interfaceDeclaration ';'? + | enumDeclaration ';'? + | annotationTypeDeclaration ';'? + | recordDeclaration ';'? // Java17 + ; + +annotationMethodOrConstantRest + : annotationMethodRest + | annotationConstantRest + ; + +annotationMethodRest + : identifier '(' ')' defaultValue? + ; + +annotationConstantRest + : variableDeclarators + ; + +defaultValue + : DEFAULT elementValue + ; + +// MODULES - Java9 + +moduleDeclaration + : OPEN? MODULE qualifiedName moduleBody + ; + +moduleBody + : '{' moduleDirective* '}' + ; + +moduleDirective + : REQUIRES requiresModifier* qualifiedName ';' + | EXPORTS qualifiedName (TO qualifiedName)? ';' + | OPENS qualifiedName (TO qualifiedName)? ';' + | USES qualifiedName ';' + | PROVIDES qualifiedName WITH qualifiedName ';' + ; + +requiresModifier + : TRANSITIVE + | STATIC + ; + +// RECORDS - Java 17 + +recordDeclaration + : RECORD identifier typeParameters? recordHeader + (IMPLEMENTS typeList)? + recordBody + ; + +recordHeader + : '(' recordComponentList? ')' + ; + +recordComponentList + : recordComponent (',' recordComponent)* + ; + +recordComponent + : typeType identifier + ; + +recordBody + : '{' (classBodyDeclaration | compactConstructorDeclaration)* '}' + ; + +// STATEMENTS / BLOCKS + +block + : '{' blockStatement* '}' + ; + +blockStatement + : localVariableDeclaration ';' + | localTypeDeclaration + | statement + ; + +localVariableDeclaration + : variableModifier* (VAR identifier '=' expression | typeType variableDeclarators) + ; + +identifier + : IDENTIFIER + | MODULE + | OPEN + | REQUIRES + | EXPORTS + | OPENS + | TO + | USES + | PROVIDES + | WITH + | TRANSITIVE + | YIELD + | SEALED + | PERMITS + | RECORD + | VAR + ; + +typeIdentifier // Identifiers that are not restricted for type declarations + : IDENTIFIER + | MODULE + | OPEN + | REQUIRES + | EXPORTS + | OPENS + | TO + | USES + | PROVIDES + | WITH + | TRANSITIVE + | SEALED + | PERMITS + | RECORD + ; + +localTypeDeclaration + : classOrInterfaceModifier* + (classDeclaration | interfaceDeclaration | recordDeclaration) + ; + +statement + : blockLabel=block + | ASSERT expression (':' expression)? ';' + | IF parExpression statement (ELSE statement)? + | FOR '(' forControl ')' statement + | WHILE parExpression statement + | DO statement WHILE parExpression ';' + | TRY block (catchClause+ finallyBlock? | finallyBlock) + | TRY resourceSpecification block catchClause* finallyBlock? + | SWITCH parExpression '{' switchBlockStatementGroup* switchLabel* '}' + | SYNCHRONIZED parExpression block + | RETURN expression? ';' + | THROW expression ';' + | BREAK identifier? ';' + | CONTINUE identifier? ';' + | YIELD expression ';' // Java17 + | SEMI + | statementExpression=expression ';' + | switchExpression ';'? // Java17 + | identifierLabel=identifier ':' statement + ; + +catchClause + : CATCH '(' variableModifier* catchType identifier ')' block + ; + +catchType + : qualifiedName ('|' qualifiedName)* + ; + +finallyBlock + : FINALLY block + ; + +resourceSpecification + : '(' resources ';'? ')' + ; + +resources + : resource (';' resource)* + ; + +resource + : variableModifier* ( classOrInterfaceType variableDeclaratorId | VAR identifier ) '=' expression + | qualifiedName + ; + +/** Matches cases then statements, both of which are mandatory. + * To handle empty cases at the end, we add switchLabel* to statement. + */ +switchBlockStatementGroup + : switchLabel+ blockStatement+ + ; + +switchLabel + : CASE (constantExpression=expression | enumConstantName=IDENTIFIER | typeType varName=identifier) ':' + | DEFAULT ':' + ; + +forControl + : enhancedForControl + | forInit? ';' expression? ';' forUpdate=expressionList? + ; + +forInit + : localVariableDeclaration + | expressionList + ; + +enhancedForControl + : variableModifier* (typeType | VAR) variableDeclaratorId ':' expression + ; + +// EXPRESSIONS + +parExpression + : '(' expression ')' + ; + +expressionList + : expression (',' expression)* + ; + +methodCall + : (identifier | THIS | SUPER) arguments + ; + +expression + // Expression order in accordance with https://introcs.cs.princeton.edu/java/11precedence/ + // Level 16, Primary, array and member access + : primary + | expression '[' expression ']' + | expression bop='.' + ( + identifier + | methodCall + | THIS + | NEW nonWildcardTypeArguments? innerCreator + | SUPER superSuffix + | explicitGenericInvocation + ) + // Method calls and method references are part of primary, and hence level 16 precedence + | methodCall + | expression '::' typeArguments? identifier + | typeType '::' (typeArguments? identifier | NEW) + | classType '::' typeArguments? NEW + + | switchExpression // Java17 + + // Level 15 Post-increment/decrement operators + | expression postfix=('++' | '--') + + // Level 14, Unary operators + | prefix=('+'|'-'|'++'|'--'|'~'|'!') expression + + // Level 13 Cast and object creation + | '(' annotation* typeType ('&' typeType)* ')' expression + | NEW creator + + // Level 12 to 1, Remaining operators + | expression bop=('*'|'/'|'%') expression // Level 12, Multiplicative operators + | expression bop=('+'|'-') expression // Level 11, Additive operators + | expression ('<' '<' | '>' '>' '>' | '>' '>') expression // Level 10, Shift operators + | expression bop=('<=' | '>=' | '>' | '<') expression // Level 9, Relational operators + | expression bop=INSTANCEOF (typeType | pattern) + | expression bop=('==' | '!=') expression // Level 8, Equality Operators + | expression bop='&' expression // Level 7, Bitwise AND + | expression bop='^' expression // Level 6, Bitwise XOR + | expression bop='|' expression // Level 5, Bitwise OR + | expression bop='&&' expression // Level 4, Logic AND + | expression bop='||' expression // Level 3, Logic OR + | expression bop='?' expression ':' expression // Level 2, Ternary + // Level 1, Assignment + | expression + bop=('=' | '+=' | '-=' | '*=' | '/=' | '&=' | '|=' | '^=' | '>>=' | '>>>=' | '<<=' | '%=') + expression + + // Level 0, Lambda Expression + | lambdaExpression // Java8 + ; + +// Java17 +pattern + : variableModifier* typeType annotation* identifier + ; + +// Java8 +lambdaExpression + : lambdaParameters '->' lambdaBody + ; + +// Java8 +lambdaParameters + : identifier + | '(' formalParameterList? ')' + | '(' identifier (',' identifier)* ')' + | '(' lambdaLVTIList? ')' + ; + +// Java8 +lambdaBody + : expression + | block + ; + +primary + : '(' expression ')' + | THIS + | SUPER + | literal + | identifier + | typeTypeOrVoid '.' CLASS + | nonWildcardTypeArguments (explicitGenericInvocationSuffix | THIS arguments) + ; + +// Java17 +switchExpression + : SWITCH parExpression '{' switchLabeledRule* '}' + ; + +// Java17 +switchLabeledRule + : CASE (expressionList | NULL_LITERAL | guardedPattern) (ARROW | COLON) switchRuleOutcome + | DEFAULT (ARROW | COLON) switchRuleOutcome + ; + +// Java17 +guardedPattern + : '(' guardedPattern ')' + | variableModifier* typeType annotation* identifier ('&&' expression)* + | guardedPattern '&&' expression + ; + +// Java17 +switchRuleOutcome + : block + | blockStatement* + ; + +classType + : (classOrInterfaceType '.')? annotation* identifier typeArguments? + ; + +creator + : nonWildcardTypeArguments? createdName classCreatorRest + | createdName arrayCreatorRest + ; + +createdName + : identifier typeArgumentsOrDiamond? ('.' identifier typeArgumentsOrDiamond?)* + | primitiveType + ; + +innerCreator + : identifier nonWildcardTypeArgumentsOrDiamond? classCreatorRest + ; + +arrayCreatorRest + : ('[' ']')+ arrayInitializer + | ('[' expression ']')+ ('[' ']')* + ; + +classCreatorRest + : arguments classBody? + ; + +explicitGenericInvocation + : nonWildcardTypeArguments explicitGenericInvocationSuffix + ; + +typeArgumentsOrDiamond + : '<' '>' + | typeArguments + ; + +nonWildcardTypeArgumentsOrDiamond + : '<' '>' + | nonWildcardTypeArguments + ; + +nonWildcardTypeArguments + : '<' typeList '>' + ; + +typeList + : typeType (',' typeType)* + ; + +typeType + : annotation* (classOrInterfaceType | primitiveType) (annotation* '[' ']')* + ; + +primitiveType + : BOOLEAN + | CHAR + | BYTE + | SHORT + | INT + | LONG + | FLOAT + | DOUBLE + ; + +typeArguments + : '<' typeArgument (',' typeArgument)* '>' + ; + +superSuffix + : arguments + | '.' typeArguments? identifier arguments? + ; + +explicitGenericInvocationSuffix + : SUPER superSuffix + | identifier arguments + ; + +arguments + : '(' expressionList? ')' + ; diff --git a/platform-sdk/swirlds-config-processor/src/main/antlr/JavadocLexer.g4 b/platform-sdk/swirlds-config-processor/src/main/antlr/JavadocLexer.g4 new file mode 100644 index 000000000000..e086f75b43ef --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/antlr/JavadocLexer.g4 @@ -0,0 +1,83 @@ +/* + [The "BSD licence"] + Copyright (c) 2016 Pascal Gruen + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +lexer grammar JavadocLexer; + +@lexer::header { +package com.swirlds.config.processor.antlr.generated; +} + +NAME + : [a-zA-Z]+ + ; + +NEWLINE + : '\n' (SPACE? (STAR {_input.LA(1) != '/'}?)+)? + | '\r\n' (SPACE? (STAR {_input.LA(1) != '/'}?)+)? + | '\r' (SPACE? (STAR {_input.LA(1) != '/'}?)+)? + ; + +SPACE + : (' '|'\t')+ + ; + +TEXT_CONTENT + : ~[\n\r\t @*{}/a-zA-Z]+ + ; + +AT + : '@' + ; + +STAR + : '*' + ; + +SLASH + : '/' + ; + +JAVADOC_START + : '/**' STAR* + ; + +JAVADOC_END + : SPACE? STAR* '*/' + ; + +INLINE_TAG_START + : '{@' + ; + +BRACE_OPEN + : '{' + ; + +BRACE_CLOSE + : '}' + ; diff --git a/platform-sdk/swirlds-config-processor/src/main/antlr/JavadocParser.g4 b/platform-sdk/swirlds-config-processor/src/main/antlr/JavadocParser.g4 new file mode 100644 index 000000000000..5b6983ef4cfe --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/antlr/JavadocParser.g4 @@ -0,0 +1,153 @@ +/* + [The "BSD licence"] + Copyright (c) 2016 Pascal Gruen + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +parser grammar JavadocParser; + +@header { +package com.swirlds.config.processor.antlr.generated; +} + +options { tokenVocab=JavadocLexer; } + + +documentation + : EOF + | JAVADOC_START skipWhitespace* documentationContent JAVADOC_END EOF + | skipWhitespace* documentationContent EOF + ; + +documentationContent + : description skipWhitespace* + | skipWhitespace* tagSection + | description NEWLINE+ skipWhitespace* tagSection + ; + +skipWhitespace + : SPACE + | NEWLINE + ; + + +description + : descriptionLine (descriptionNewline+ descriptionLine)* + ; + +descriptionLine + : descriptionLineStart descriptionLineElement* + | inlineTag descriptionLineElement* + ; + +descriptionLineStart + : SPACE? descriptionLineNoSpaceNoAt+ (descriptionLineNoSpaceNoAt | SPACE | AT)* + ; + +descriptionLineNoSpaceNoAt + : TEXT_CONTENT + | NAME + | STAR + | SLASH + | BRACE_OPEN + | BRACE_CLOSE + ; + +descriptionLineElement + : inlineTag + | descriptionLineText + ; + +descriptionLineText + : (descriptionLineNoSpaceNoAt | SPACE | AT)+ + ; + +descriptionNewline + : NEWLINE + ; + + +tagSection + : blockTag+ + ; + +blockTag + : SPACE? AT blockTagName SPACE? blockTagContent* + ; + +blockTagName + : NAME + ; + +blockTagContent + : blockTagText + | inlineTag + | NEWLINE + ; + +blockTagText + : blockTagTextElement+ + ; + +blockTagTextElement + : TEXT_CONTENT + | NAME + | SPACE + | STAR + | SLASH + | BRACE_OPEN + | BRACE_CLOSE + ; + + +inlineTag + : INLINE_TAG_START inlineTagName SPACE* inlineTagContent? BRACE_CLOSE + ; + +inlineTagName + : NAME + ; + +inlineTagContent + : braceContent+ + ; + +braceExpression + : BRACE_OPEN braceContent* BRACE_CLOSE + ; + +braceContent + : braceExpression + | braceText (NEWLINE* braceText)* + ; + +braceText + : TEXT_CONTENT + | NAME + | SPACE + | STAR + | SLASH + | NEWLINE + ; diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConfigDataAnnotationProcessor.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConfigDataAnnotationProcessor.java new file mode 100644 index 000000000000..13bb5680fac8 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConfigDataAnnotationProcessor.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor; + +import static com.swirlds.config.processor.ConfigProcessorConstants.CONSTANTS_CLASS_SUFFIX; + +import com.google.auto.service.AutoService; +import com.swirlds.config.processor.antlr.AntlrConfigRecordParser; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic.Kind; +import javax.tools.FileObject; +import javax.tools.JavaFileObject; +import javax.tools.StandardLocation; + +/** + * An annotation processor that creates documentation and constants for config data records. + */ +@SupportedAnnotationTypes(ConfigProcessorConstants.CONFIG_DATA_ANNOTATION) +@SupportedSourceVersion(SourceVersion.RELEASE_17) +@AutoService(Processor.class) +public final class ConfigDataAnnotationProcessor extends AbstractProcessor { + + @Override + public boolean process( + final @NonNull Set annotations, final @NonNull RoundEnvironment roundEnv) { + Objects.requireNonNull(roundEnv, "annotations must not be null"); + Objects.requireNonNull(roundEnv, "roundEnv must not be null"); + + if (annotations.isEmpty()) { + return false; + } + final String executionPath = System.getProperty("user.dir"); + final Path configDocumentationFile = Paths.get(executionPath, "build/docs/config.md"); + try { + Files.deleteIfExists(configDocumentationFile); + } catch (final IOException e) { + throw new RuntimeException("Error while deleting " + configDocumentationFile, e); + } + configDocumentationFile.toFile().getParentFile().mkdirs(); + + log("Config Data Annotation Processor started..."); + try { + annotations.stream() + .map(annotation -> (TypeElement) annotation) + .flatMap(annotation -> roundEnv.getElementsAnnotatedWith(annotation).stream()) + .filter(element -> element.getKind() == ElementKind.RECORD) + .filter(element -> element instanceof TypeElement) + .map(TypeElement.class::cast) + .forEach(typeElement -> handleTypeElement(typeElement, configDocumentationFile)); + return true; + } catch (final Exception e) { + log("Error while processing annotations: " + e.getMessage()); + e.printStackTrace(); + return false; + } + } + + private void handleTypeElement( + @NonNull final TypeElement typeElement, @NonNull final Path configDocumentationFile) { + final String simpleClassName = typeElement.getSimpleName().toString(); + final String fileName = simpleClassName + ConfigProcessorConstants.JAVA_FILE_EXTENSION; + + final String packageName = processingEnv + .getElementUtils() + .getPackageOf(typeElement) + .getQualifiedName() + .toString(); + log("handling: " + fileName + " in " + packageName); + try { + final FileObject recordSource = getSource(fileName, packageName); + final List recordDefinitions = AntlrConfigRecordParser.parse( + recordSource.getCharContent(true).toString()); + + if (!recordDefinitions.isEmpty()) { + final JavaFileObject constantsSourceFile = + getConstantSourceFile(packageName, simpleClassName, typeElement); + log("generating config constants file: " + constantsSourceFile.getName()); + ConstantClassFactory.doWork(recordDefinitions.get(0), constantsSourceFile); + log("generating config doc file: " + configDocumentationFile.getFileName()); + DocumentationFactory.doWork(recordDefinitions.get(0), configDocumentationFile); + } + } catch (final IOException e) { + throw new RuntimeException("Error while handling " + typeElement, e); + } + } + + @NonNull + private JavaFileObject getConstantSourceFile( + @NonNull final String packageName, + @NonNull final String simpleClassName, + @NonNull final TypeElement originatingElement) + throws IOException { + Objects.requireNonNull(packageName, "packageName must not be null"); + Objects.requireNonNull(simpleClassName, "simpleClassName must not be null"); + Objects.requireNonNull(originatingElement, "originatingElement must not be null"); + + final String constantsClassName = packageName + "." + simpleClassName + CONSTANTS_CLASS_SUFFIX; + return processingEnv.getFiler().createSourceFile(constantsClassName, originatingElement); + } + + @NonNull + private FileObject getSource(@NonNull final String fileName, @NonNull final String packageName) throws IOException { + Objects.requireNonNull(fileName, "fileName must not be null"); + Objects.requireNonNull(packageName, "packageName must not be null"); + + return processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, packageName, fileName); + } + + protected void log(@NonNull final String message) { + Objects.requireNonNull(message, "message must not be null"); + + processingEnv.getMessager().printMessage(Kind.NOTE, message); + } +} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConfigDataPropertyDefinition.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConfigDataPropertyDefinition.java new file mode 100644 index 000000000000..d081f2162393 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConfigDataPropertyDefinition.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor; + +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; + +/** + * Metadata for a config property definition. + * @param fieldName the field name like "maxSize" + * @param name the full name like "com.swirlds.config.foo.bar" + * @param type the type like "int" + * @param defaultValue the default value like "100" + * @param description the description like "the maximum size" + */ +public record ConfigDataPropertyDefinition( + @NonNull String fieldName, + @NonNull String name, + @NonNull String type, + @Nullable String defaultValue, + @Nullable String description) {} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConfigDataRecordDefinition.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConfigDataRecordDefinition.java new file mode 100644 index 000000000000..646e7ba4ba95 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConfigDataRecordDefinition.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor; + +import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.Set; + +/** + * Metadata of a config data record (a Java Record that is annotated by @ConfigData). + * + * @param packageName the package name like "com.swirlds.config.foo" + * @param simpleClassName the simple class name like "FooConfig" + * @param configDataName the prefix that is used for config properties that are part of the config data like + * "state" for properties that start with "state." like "state.maxSize". + * @param propertyDefinitions the property definitions + */ +public record ConfigDataRecordDefinition( + @NonNull String packageName, + @NonNull String simpleClassName, + @NonNull String configDataName, + @NonNull Set propertyDefinitions) {} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConfigProcessorConstants.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConfigProcessorConstants.java new file mode 100644 index 000000000000..254440596071 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConfigProcessorConstants.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor; + +/** + * Constants used by the config processor. + */ +public final class ConfigProcessorConstants { + + /** + * The extension for java files. + */ + public static final String JAVA_FILE_EXTENSION = ".java"; + + /** + * Suffix for the generated classes + */ + public static final String CONSTANTS_CLASS_SUFFIX = "_"; + + /** + * Class name of the ConfigData annotation. + */ + public static final String CONFIG_DATA_ANNOTATION = "com.swirlds.config.api.ConfigData"; + + /** + * private constructor for utility class. + */ + private ConfigProcessorConstants() {} +} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConstantClassFactory.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConstantClassFactory.java new file mode 100644 index 000000000000..817b615e3bdc --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/ConstantClassFactory.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor; + +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.TypeSpec; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.io.IOException; +import java.io.Writer; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Objects; +import javax.lang.model.element.Modifier; +import javax.tools.JavaFileObject; + +/** + * Utilities for creating constant class files from {@link ConfigDataRecordDefinition} instances. + * Its methods should be accessed statically, and it should not be instantiated. + */ +public final class ConstantClassFactory { + + /** + * private constructor to prevent instantiation + */ + private ConstantClassFactory() {} + + /** + * Processes a given {@link ConfigDataRecordDefinition} and writes a corresponding constant class file. + * + * @param configDataRecordDefinition The record definition to be processed. Must not be {@code null}. + * @param constantsSourceFile The Java file object where the constant class should be written. Must not be {@code null}. + * + * @throws IOException If an error occurs while writing the constant class. + */ + public static void doWork( + @NonNull final ConfigDataRecordDefinition configDataRecordDefinition, + @NonNull final JavaFileObject constantsSourceFile) + throws IOException { + + Objects.requireNonNull(configDataRecordDefinition, "configDataRecordDefinition must not be null"); + Objects.requireNonNull(constantsSourceFile, "constantsSourceFile must not be null"); + + final String originalRecordClassName = + configDataRecordDefinition.packageName() + "." + configDataRecordDefinition.simpleClassName(); + + TypeSpec.Builder constantsClassBuilder = TypeSpec.classBuilder( + configDataRecordDefinition.simpleClassName() + ConfigProcessorConstants.CONSTANTS_CLASS_SUFFIX) + .addModifiers(Modifier.FINAL, Modifier.PUBLIC) + .addJavadoc( + "Constraints constants for all the property names that are part of {@link $L}. Generated by {@code $L} on $L.\n@see $L\n", + originalRecordClassName, + ConstantClassFactory.class.getName(), + DateTimeFormatter.ISO_DATE_TIME.format(LocalDateTime.now()), + originalRecordClassName); + + configDataRecordDefinition.propertyDefinitions().forEach(propertyDefinition -> { + final String name = toConstantName( + propertyDefinition.name().replace(configDataRecordDefinition.configDataName() + ".", "")); + FieldSpec fieldSpec = FieldSpec.builder( + String.class, name, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("$S", propertyDefinition.name()) + .addJavadoc( + "Name of the {@link $L#$L} property\n@see $L#$L\n", + originalRecordClassName, + propertyDefinition.fieldName(), + originalRecordClassName, + propertyDefinition.fieldName()) + .build(); + constantsClassBuilder.addField(fieldSpec); + }); + + TypeSpec constantsClass = constantsClassBuilder.build(); + JavaFile javaFile = JavaFile.builder(configDataRecordDefinition.packageName(), constantsClass) + .build(); + + try (Writer writer = constantsSourceFile.openWriter()) { + javaFile.writeTo(writer); + } + } + + /** + * Converts a property name into a constant name. The conversion is based on changing from camel case to snake case + * + * @param propertyName The property name to be converted. Must not be {@code null}. + * + * @return The converted constant name. Never {@code null}. + */ + @NonNull + public static String toConstantName(@NonNull final String propertyName) { + Objects.requireNonNull(propertyName, "propertyName must not be null"); + + final StringBuilder builder = new StringBuilder(); + for (int i = 0; i < propertyName.length(); i++) { + final char character = propertyName.charAt(i); + if (i > 0 && Character.isUpperCase(character)) { + builder.append("_"); + builder.append(character); + } else { + builder.append(Character.toUpperCase(character)); + } + } + return builder.toString(); + } +} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/DocumentationFactory.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/DocumentationFactory.java new file mode 100644 index 000000000000..57290d819023 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/DocumentationFactory.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor; + +import static com.swirlds.config.processor.MarkdownSyntax.NEWLINE; +import static com.swirlds.config.processor.MarkdownSyntax.asCode; + +import com.swirlds.config.api.ConfigProperty; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Objects; +import java.util.Optional; + +/** + * Utilities for generating documentation based on a given {@link ConfigDataRecordDefinition}. + * Its methods should be accessed statically, and it should not be instantiated. + */ +public class DocumentationFactory { + + /** + * Prevents instantiation. + */ + private DocumentationFactory() {} + + /** + * Writes the documentation of the given {@link ConfigDataRecordDefinition} to a file. + *

    + * The documentation includes the name, type, default value, and description of each property of the given record. + * The file to write to is determined by the {@code configDocumentationFile} parameter. + * Existing contents of the file are not overwritten; new contents are appended. + * + * @param configDataRecordDefinition The record definition to document. Must not be {@code null}. + * @param configDocumentationFile The file to which the documentation should be written. Must not be {@code null}. + * + * @throws IOException If an I/O error occurs while writing to the file. + * @throws RuntimeException If an error occurs while writing a property's documentation. + */ + public static void doWork( + @NonNull final ConfigDataRecordDefinition configDataRecordDefinition, + @NonNull final Path configDocumentationFile) + throws IOException { + Objects.requireNonNull(configDataRecordDefinition, "configDataRecordDefinition must not be null"); + Objects.requireNonNull(configDocumentationFile, "configDocumentationFile must not be null"); + try (final FileWriter writer = new FileWriter(configDocumentationFile.toString(), true)) { + configDataRecordDefinition.propertyDefinitions().forEach(propertyDefinition -> { + try { + writer.write(MarkdownSyntax.H2_PREFIX + propertyDefinition.name() + NEWLINE); + final String fullRecordName = Optional.ofNullable(configDataRecordDefinition.packageName()) + .map(packageName -> packageName + "." + configDataRecordDefinition.simpleClassName()) + .orElse(configDataRecordDefinition.simpleClassName()); + writer.write(MarkdownSyntax.RECORD + asCode(fullRecordName) + NEWLINE); + writer.write(MarkdownSyntax.TYPE + asCode(propertyDefinition.type()) + NEWLINE); + if (Objects.equals(propertyDefinition.defaultValue(), ConfigProperty.UNDEFINED_DEFAULT_VALUE)) { + writer.write(MarkdownSyntax.NO_DEFAULT_VALUE + NEWLINE); + } else if (Objects.equals(propertyDefinition.defaultValue(), ConfigProperty.NULL_DEFAULT_VALUE)) { + writer.write(MarkdownSyntax.DEFAULT_VALUE_IS_NULL + NEWLINE); + } else { + writer.write( + MarkdownSyntax.DEFAULT_VALUE + asCode(propertyDefinition.defaultValue()) + NEWLINE); + } + writer.write(MarkdownSyntax.DESCRIPTION + propertyDefinition.description() + NEWLINE); + writer.write("\n"); + } catch (IOException e) { + throw new RuntimeException("Error while writing doc", e); + } + }); + } catch (IOException e) { + throw new RuntimeException("Error while writing doc", e); + } + } +} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/MarkdownSyntax.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/MarkdownSyntax.java new file mode 100644 index 000000000000..1d1b97228a3c --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/MarkdownSyntax.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor; + +public final class MarkdownSyntax { + + public static final String H2_PREFIX = "## "; + public static final String BOLD_MARKER = "**"; + + public static final String CODE_MARKER = "`"; + + public static final String NEWLINE = "\n\n"; + + public static final String DEFAULT_VALUE = BOLD_MARKER + "default value:" + BOLD_MARKER + " "; + + public static final String DESCRIPTION = BOLD_MARKER + "description:" + BOLD_MARKER + " "; + + public static final String RECORD = BOLD_MARKER + "record:" + BOLD_MARKER + " "; + + public static final String TYPE = BOLD_MARKER + "type:" + BOLD_MARKER + " "; + public static final String NO_DEFAULT_VALUE = BOLD_MARKER + "no default value" + BOLD_MARKER; + public static final String DEFAULT_VALUE_IS_NULL = + BOLD_MARKER + "default value is " + CODE_MARKER + "null" + CODE_MARKER + BOLD_MARKER; + + /** + * Private constructor to prevent instantiation. + */ + private MarkdownSyntax() {} + + /** + * Returns the given text as code in markdown. + * + * @param text The text to return as code in markdown. + * @return The given text as code in markdown. + */ + public static String asCode(final String text) { + return CODE_MARKER + text + CODE_MARKER; + } +} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/AntlrConfigRecordParser.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/AntlrConfigRecordParser.java new file mode 100644 index 000000000000..9c60a81f6fad --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/AntlrConfigRecordParser.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor.antlr; + +import com.swirlds.config.api.ConfigData; +import com.swirlds.config.api.ConfigProperty; +import com.swirlds.config.processor.ConfigDataPropertyDefinition; +import com.swirlds.config.processor.ConfigDataRecordDefinition; +import com.swirlds.config.processor.antlr.generated.JavaParser.AnnotationContext; +import com.swirlds.config.processor.antlr.generated.JavaParser.CompilationUnitContext; +import com.swirlds.config.processor.antlr.generated.JavaParser.RecordComponentContext; +import com.swirlds.config.processor.antlr.generated.JavaParser.RecordDeclarationContext; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +public final class AntlrConfigRecordParser { + + private static boolean isAnnotatedWithConfigData( + @NonNull final RecordDeclarationContext ctx, @NonNull String packageName, @NonNull List imports) { + final List allAnnotations = AntlrUtils.getAllAnnotations(ctx); + return AntlrUtils.findAnnotationOfType(ConfigData.class, allAnnotations, packageName, imports) + .isPresent(); + } + + @NonNull + private static Optional getConfigDataAnnotation( + @NonNull final RecordDeclarationContext ctx, + @NonNull final String packageName, + @NonNull final List imports) { + final List annotations = AntlrUtils.getAllAnnotations(ctx); + return AntlrUtils.findAnnotationOfType(ConfigData.class, annotations, packageName, imports); + } + + @NonNull + private static String getConfigDataAnnotationValue( + @NonNull final RecordDeclarationContext ctx, + @NonNull final String packageName, + @NonNull final List imports) { + return getConfigDataAnnotation(ctx, packageName, imports) + .map(annotationContext -> annotationContext.elementValue()) + .map(elementValueContext -> elementValueContext.getText()) + .map(text -> text.substring(1, text.length() - 1)) // remove quotes + .orElse(""); + } + + @NonNull + private static Optional getConfigPropertyAnnotation( + @NonNull final RecordComponentContext ctx, + @NonNull final String packageName, + @NonNull final List imports) { + final List annotations = AntlrUtils.getAllAnnotations(ctx); + return AntlrUtils.findAnnotationOfType(ConfigProperty.class, annotations, packageName, imports); + } + + @NonNull + private static String getConfigPropertyAnnotationDefaultValue( + @NonNull final RecordComponentContext ctx, + @NonNull final String packageName, + @NonNull final List imports) { + return getConfigPropertyAnnotation(ctx, packageName, imports) + .flatMap(annotationContext -> AntlrUtils.getAnnotationValue(annotationContext, "defaultValue")) + .orElse(ConfigProperty.UNDEFINED_DEFAULT_VALUE); + } + + @NonNull + private static Optional getConfigPropertyAnnotationName( + @NonNull final RecordComponentContext ctx, + @NonNull final String packageName, + @NonNull final List imports) { + return getConfigPropertyAnnotation(ctx, packageName, imports) + .flatMap(annotationContext -> AntlrUtils.getAnnotationValue(annotationContext)); + } + + @NonNull + private static ConfigDataPropertyDefinition createPropertyDefinition( + @NonNull final RecordComponentContext ctx, + @NonNull final String configPropertyNamePrefix, + @NonNull final String packageName, + @NonNull final List imports, + @NonNull final Map javadocParams) { + final String componentName = ctx.identifier().getText(); + final String configPropertyNameSuffix = + getConfigPropertyAnnotationName(ctx, packageName, imports).orElse(componentName); + final String name = createPropertyName(configPropertyNamePrefix, configPropertyNameSuffix); + final String defaultValue = getConfigPropertyAnnotationDefaultValue(ctx, packageName, imports); + final String type = Optional.ofNullable(ctx.typeType().classOrInterfaceType()) + .map(c -> c.getText()) + .map(typeText -> imports.stream() + .filter(importText -> importText.endsWith(typeText)) + .findAny() + .orElse(typeText)) + .map(typeText -> getTypeForJavaLang(typeText)) + .orElseGet(() -> ctx.typeType().primitiveType().getText()); + final String description = + Optional.ofNullable(javadocParams.get(componentName)).orElse(""); + return new ConfigDataPropertyDefinition(componentName, name, type, defaultValue, description); + } + + @NonNull + private static String createPropertyName( + @NonNull final String configPropertyNamePrefix, @NonNull final String configPropertyNameSuffix) { + if (configPropertyNamePrefix.isBlank()) { + return configPropertyNameSuffix; + } else { + return configPropertyNamePrefix + "." + configPropertyNameSuffix; + } + } + + @NonNull + private static String getTypeForJavaLang(@NonNull final String type) { + if (!type.contains(".")) { + return String.class.getPackageName() + "." + type; + } + return type; + } + + @NonNull + private static List createDefinitions( + @NonNull final CompilationUnitContext unitContext) { + final String packageName = AntlrUtils.getPackage(unitContext); + final List imports = AntlrUtils.getImports(unitContext); + return AntlrUtils.getRecordDeclarationContext(unitContext).stream() + .filter(c -> isAnnotatedWithConfigData(c, packageName, imports)) + .map(recordContext -> createDefinition(unitContext, recordContext, packageName, imports)) + .collect(Collectors.toList()); + } + + @NonNull + private static ConfigDataRecordDefinition createDefinition( + @NonNull final CompilationUnitContext unitContext, + @NonNull final RecordDeclarationContext recordContext, + @NonNull final String packageName, + @NonNull final List imports) { + final String recordName = recordContext.identifier().getText(); + final String configPropertyNamePrefix = getConfigDataAnnotationValue(recordContext, packageName, imports); + final Map javadocParams = unitContext.children.stream() + .filter(c -> AntlrUtils.isJavaDocNode(c)) + .map(c -> c.getText()) + .map(t -> AntlrUtils.getJavaDocParams(t)) + .reduce((m1, m2) -> { + m1.putAll(m2); + return m1; + }) + .orElse(Map.of()); + final Set propertyDefinitions = + recordContext.recordHeader().recordComponentList().recordComponent().stream() + .map(c -> createPropertyDefinition( + c, configPropertyNamePrefix, packageName, imports, javadocParams)) + .collect(Collectors.toSet()); + return new ConfigDataRecordDefinition(packageName, recordName, configPropertyNamePrefix, propertyDefinitions); + } + + /** + * Creates a list of {@link ConfigDataRecordDefinition} from a given Java source file. + * + * @param fileContent the content of the Java source file + */ + @NonNull + public static List parse(@NonNull final String fileContent) throws IOException { + final CompilationUnitContext parsedContext = AntlrUtils.parse(fileContent); + return createDefinitions(parsedContext); + } +} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/AntlrUtils.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/AntlrUtils.java new file mode 100644 index 000000000000..5877d13f805b --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/AntlrUtils.java @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor.antlr; + +import com.swirlds.config.processor.ConfigDataRecordDefinition; +import com.swirlds.config.processor.antlr.generated.JavaLexer; +import com.swirlds.config.processor.antlr.generated.JavaParser; +import com.swirlds.config.processor.antlr.generated.JavaParser.AnnotationContext; +import com.swirlds.config.processor.antlr.generated.JavaParser.ClassOrInterfaceModifierContext; +import com.swirlds.config.processor.antlr.generated.JavaParser.CompilationUnitContext; +import com.swirlds.config.processor.antlr.generated.JavaParser.ElementValueContext; +import com.swirlds.config.processor.antlr.generated.JavaParser.RecordComponentContext; +import com.swirlds.config.processor.antlr.generated.JavaParser.RecordDeclarationContext; +import com.swirlds.config.processor.antlr.generated.JavaParser.TypeDeclarationContext; +import com.swirlds.config.processor.antlr.generated.JavadocLexer; +import com.swirlds.config.processor.antlr.generated.JavadocParser; +import com.swirlds.config.processor.antlr.generated.JavadocParser.BlockTagContext; +import com.swirlds.config.processor.antlr.generated.JavadocParser.DocumentationContentContext; +import com.swirlds.config.processor.antlr.generated.JavadocParser.DocumentationContext; +import com.swirlds.config.processor.antlr.generated.JavadocParser.TagSectionContext; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +/** + * Utils for antlr4 parsing of Java source code + */ +public final class AntlrUtils { + + public static final String JAVADOC_PARAM = "param"; + + private AntlrUtils() {} + + /** + * Get all annotations for a given {@code record} declaration context + * + * @param ctx the antlr context of the {@code record} + * @return all annotations as antlr context instances + */ + @NonNull + public static List getAllAnnotations(@NonNull final RecordDeclarationContext ctx) { + Objects.requireNonNull(ctx, "ctx must not be null"); + return ctx.getParent().children.stream() + .filter(child -> child instanceof ClassOrInterfaceModifierContext) + .map(child -> (ClassOrInterfaceModifierContext) child) + .flatMap(modifierContext -> modifierContext.children.stream()) + .filter(child -> child instanceof AnnotationContext) + .map(child -> (AnnotationContext) child) + .collect(Collectors.toList()); + } + + /** + * Get all annotations for a given {@code record} component context + * + * @param ctx the antlr context of the {@code record} component + * @return all annotations as antlr context instances + */ + @NonNull + public static List getAllAnnotations(@NonNull RecordComponentContext ctx) { + return Collections.unmodifiableList(ctx.typeType().annotation()); + } + + /** + * Search in the given annotation context for an optional annotation context for a given {@code Annotation}. + * + * @param the annotation type + * @param annotation the annotation class + * @param annotations all possible annotations + * @param packageName the package name of the context in that all contexts life in + * @param imports the imports of the context in that all contexts life in + * @return the optional annotation + */ + @NonNull + public static Optional findAnnotationOfType( + @NonNull final Class annotation, + @NonNull final List annotations, + @NonNull final String packageName, + @NonNull final List imports) { + Objects.requireNonNull(annotation, "annotation must not be null"); + Objects.requireNonNull(annotations, "annotations must not be null"); + return annotations.stream() + .filter(c -> c.qualifiedName().getText().endsWith(annotation.getSimpleName())) + .filter(c -> isValid(c, annotation, packageName, imports)) + .findAny(); + } + + /** + * Checks if the annotationContext is a valid usage of the annotation. + * + * @param annotationContext the annotation context + * @param annotation the annotation class + * @param packageName the package name of the context in that all contexts life in + * @param imports the imports of the context in that all contexts life in + * @param the annotation type + * @return true if the annotation is valid + */ + private static boolean isValid( + @NonNull final AnnotationContext annotationContext, + @NonNull final Class annotation, + @NonNull final String packageName, + @NonNull final List imports) { + Objects.requireNonNull(annotationContext, "annotationContext must not be null"); + Objects.requireNonNull(annotation, "annotation must not be null"); + Objects.requireNonNull(packageName, "packageName must not be null"); + Objects.requireNonNull(imports, "imports must not be null"); + return imports.contains(annotation.getName()) + || annotationContext.qualifiedName().getText().equals(annotation.getName()) + || annotationContext.qualifiedName().getText().equals(packageName + "." + annotation.getSimpleName()); + } + + /** + * Returns the compilation unit context for a given antlr context by doing a (recursive) search in the parent + * contexts. + * + * @param ctx the antlr context + * @return the compilation unit context + */ + @NonNull + public static CompilationUnitContext getCompilationUnit(@NonNull final ParserRuleContext ctx) { + Objects.requireNonNull(ctx, "ctx must not be null"); + if (ctx instanceof CompilationUnitContext compilationUnitContext) { + return compilationUnitContext; + } else { + return getCompilationUnit(ctx.getParent()); + } + } + + /** + * Returns all imports of a given declaration context (by going up to the compilation unit context) + * + * @param ctx the antlr contexts + * @return all imports as strings + */ + @NonNull + public static List getImports(@NonNull final ParserRuleContext ctx) { + final CompilationUnitContext compilationUnitContext = getCompilationUnit(ctx); + return compilationUnitContext.importDeclaration().stream() + .map(context -> context.qualifiedName()) + .map(name -> name.getText()) + .collect(Collectors.toList()); + } + + /** + * Returns the package name of a given declaration context (by going up to the compilation unit context) + * + * @param ctx the antlr context + * @return the package name + */ + @NonNull + public static String getPackage(@NonNull final ParserRuleContext ctx) { + final CompilationUnitContext compilationUnitContext = getCompilationUnit(ctx); + return compilationUnitContext.packageDeclaration().qualifiedName().getText(); + } + + /** + * Returns the value of an annotation attribute + * + * @param annotationContext the annotation context + * @param identifier the identifier of the attribute + * @return the value of the attribute + */ + @NonNull + public static Optional getAnnotationValue( + @NonNull final AnnotationContext annotationContext, @NonNull final String identifier) { + return annotationContext.elementValuePairs().elementValuePair().stream() + .filter(p -> Objects.equals(p.identifier().getText(), identifier)) + .map(p -> p.elementValue().getText()) + .map(text -> { + if (text.startsWith("\"") && text.endsWith("\"")) { + return text.substring(1, text.length() - 1); + } + return text; + }) + .findAny(); + } + + public static boolean isJavaDocNode(@NonNull final ParseTree node) { + if (node instanceof TerminalNode terminalNode) { + if (terminalNode.getSymbol().getType() == JavaParser.JAVADOC_COMMENT) { + return true; + } + } + return false; + } + + /** + * Returns the value of an annotation {@code value} attribute + * + * @param annotationContext the annotation context + * @return the value of the {@code value} attribute + */ + @NonNull + public static Optional getAnnotationValue(@NonNull final AnnotationContext annotationContext) { + final ElementValueContext elementValueContext = annotationContext.elementValue(); + if (elementValueContext != null) { + return Optional.of(elementValueContext.getText()); + } + return getAnnotationValue(annotationContext, "value"); + } + + public static List getRecordDeclarationContext( + @NonNull final CompilationUnitContext compilationUnitContext) { + return compilationUnitContext.children.stream() + .filter(child -> child instanceof TypeDeclarationContext) + .map(child -> (TypeDeclarationContext) child) + .flatMap(typeDeclarationContext -> typeDeclarationContext.children.stream()) + .filter(child -> child instanceof RecordDeclarationContext) + .map(child -> (RecordDeclarationContext) child) + .collect(Collectors.toList()); + } + + /** + * Returns all {@code @param} tags of a given java doc. The key of the map is the name of the parameter and the + * value is the description of the parameter. + * + * @param rawDocContent the javadoc + * @return the params + */ + @NonNull + public static Map getJavaDocParams(@NonNull String rawDocContent) { + Objects.requireNonNull(rawDocContent, "rawDocContent must not be null"); + final Map params = new HashMap<>(); + final Lexer lexer = new JavadocLexer(CharStreams.fromString(rawDocContent)); + final TokenStream tokens = new CommonTokenStream(lexer); + final JavadocParser parser = new JavadocParser(tokens); + final DocumentationContext documentationContext = parser.documentation(); + Optional.ofNullable(documentationContext.exception).ifPresent(e -> { + throw new IllegalStateException("Error in ANTLR parsing", e); + }); + documentationContext.children.stream() + .filter(c -> c instanceof DocumentationContentContext) + .map(c -> (DocumentationContentContext) c) + .flatMap(context -> context.children.stream()) + .filter(c -> c instanceof TagSectionContext) + .map(c -> (TagSectionContext) c) + .flatMap(context -> context.children.stream()) + .filter(c -> c instanceof BlockTagContext btc) + .map(c -> (BlockTagContext) c) + .filter(c -> Objects.equals(c.blockTagName().NAME().getText(), JAVADOC_PARAM)) + .map(c -> extractFullText(c)) + .filter(fullText -> !fullText.isBlank()) + .filter(fullText -> fullText.contains(" ")) + .forEach(fullText -> { + final String paramName = fullText.split(" ")[0].trim(); + final String description = + fullText.substring(paramName.length()).trim(); + params.put(paramName.trim(), description.trim()); + }); + return params; + } + + private static String extractFullText(@NonNull final BlockTagContext c) { + final String[] split = c.getText().trim().split("\n \\*"); + final String result = Arrays.asList(split).stream() + .map(s -> s.trim()) + .filter(s -> !s.isBlank()) + .reduce((a, b) -> a + " " + b) + .orElse(""); + if (result.startsWith("@param")) { + return result.substring("@param".length()).trim(); + } + return result.trim(); + } + + /** + * Parse the given file content and return a {@link ConfigDataRecordDefinition} object. The file must be a valid + * Java file. + * + * @param fileContent the file content to parse + * @return the {@link ConfigDataRecordDefinition} object + * @throws IOException if an I/O error occurs + */ + public static CompilationUnitContext parse(@NonNull final String fileContent) throws IOException { + final Lexer lexer = new JavaLexer(CharStreams.fromString(fileContent)); + final TokenStream tokens = new CommonTokenStream(lexer); + final JavaParser parser = new JavaParser(tokens); + final CompilationUnitContext context = parser.compilationUnit(); + Optional.ofNullable(context.exception).ifPresent(e -> { + throw new IllegalStateException("Error in ANTLR parsing", e); + }); + return context; + } +} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavaLexer.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavaLexer.java new file mode 100644 index 000000000000..35c6db4cbba7 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavaLexer.java @@ -0,0 +1,1364 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor.antlr.generated; + +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.misc.*; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue", "this-escape"}) +public class JavaLexer extends Lexer { + static { + RuntimeMetaData.checkVersion("4.13.1", RuntimeMetaData.VERSION); + } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache(); + public static final int ABSTRACT = 1, + ASSERT = 2, + BOOLEAN = 3, + BREAK = 4, + BYTE = 5, + CASE = 6, + CATCH = 7, + CHAR = 8, + CLASS = 9, + CONST = 10, + CONTINUE = 11, + DEFAULT = 12, + DO = 13, + DOUBLE = 14, + ELSE = 15, + ENUM = 16, + EXTENDS = 17, + FINAL = 18, + FINALLY = 19, + FLOAT = 20, + FOR = 21, + IF = 22, + GOTO = 23, + IMPLEMENTS = 24, + IMPORT = 25, + INSTANCEOF = 26, + INT = 27, + INTERFACE = 28, + LONG = 29, + NATIVE = 30, + NEW = 31, + PACKAGE = 32, + PRIVATE = 33, + PROTECTED = 34, + PUBLIC = 35, + RETURN = 36, + SHORT = 37, + STATIC = 38, + STRICTFP = 39, + SUPER = 40, + SWITCH = 41, + SYNCHRONIZED = 42, + THIS = 43, + THROW = 44, + THROWS = 45, + TRANSIENT = 46, + TRY = 47, + VOID = 48, + VOLATILE = 49, + WHILE = 50, + MODULE = 51, + OPEN = 52, + REQUIRES = 53, + EXPORTS = 54, + OPENS = 55, + TO = 56, + USES = 57, + PROVIDES = 58, + WITH = 59, + TRANSITIVE = 60, + VAR = 61, + YIELD = 62, + RECORD = 63, + SEALED = 64, + PERMITS = 65, + NON_SEALED = 66, + DECIMAL_LITERAL = 67, + HEX_LITERAL = 68, + OCT_LITERAL = 69, + BINARY_LITERAL = 70, + FLOAT_LITERAL = 71, + HEX_FLOAT_LITERAL = 72, + BOOL_LITERAL = 73, + CHAR_LITERAL = 74, + STRING_LITERAL = 75, + TEXT_BLOCK = 76, + NULL_LITERAL = 77, + LPAREN = 78, + RPAREN = 79, + LBRACE = 80, + RBRACE = 81, + LBRACK = 82, + RBRACK = 83, + SEMI = 84, + COMMA = 85, + DOT = 86, + ASSIGN = 87, + GT = 88, + LT = 89, + BANG = 90, + TILDE = 91, + QUESTION = 92, + COLON = 93, + EQUAL = 94, + LE = 95, + GE = 96, + NOTEQUAL = 97, + AND = 98, + OR = 99, + INC = 100, + DEC = 101, + ADD = 102, + SUB = 103, + MUL = 104, + DIV = 105, + BITAND = 106, + BITOR = 107, + CARET = 108, + MOD = 109, + ADD_ASSIGN = 110, + SUB_ASSIGN = 111, + MUL_ASSIGN = 112, + DIV_ASSIGN = 113, + AND_ASSIGN = 114, + OR_ASSIGN = 115, + XOR_ASSIGN = 116, + MOD_ASSIGN = 117, + LSHIFT_ASSIGN = 118, + RSHIFT_ASSIGN = 119, + URSHIFT_ASSIGN = 120, + ARROW = 121, + COLONCOLON = 122, + AT = 123, + ELLIPSIS = 124, + JAVADOC_COMMENT = 125, + WS = 126, + COMMENT = 127, + LINE_COMMENT = 128, + IDENTIFIER = 129; + public static String[] channelNames = {"DEFAULT_TOKEN_CHANNEL", "HIDDEN"}; + + public static String[] modeNames = {"DEFAULT_MODE"}; + + private static String[] makeRuleNames() { + return new String[] { + "ABSTRACT", + "ASSERT", + "BOOLEAN", + "BREAK", + "BYTE", + "CASE", + "CATCH", + "CHAR", + "CLASS", + "CONST", + "CONTINUE", + "DEFAULT", + "DO", + "DOUBLE", + "ELSE", + "ENUM", + "EXTENDS", + "FINAL", + "FINALLY", + "FLOAT", + "FOR", + "IF", + "GOTO", + "IMPLEMENTS", + "IMPORT", + "INSTANCEOF", + "INT", + "INTERFACE", + "LONG", + "NATIVE", + "NEW", + "PACKAGE", + "PRIVATE", + "PROTECTED", + "PUBLIC", + "RETURN", + "SHORT", + "STATIC", + "STRICTFP", + "SUPER", + "SWITCH", + "SYNCHRONIZED", + "THIS", + "THROW", + "THROWS", + "TRANSIENT", + "TRY", + "VOID", + "VOLATILE", + "WHILE", + "MODULE", + "OPEN", + "REQUIRES", + "EXPORTS", + "OPENS", + "TO", + "USES", + "PROVIDES", + "WITH", + "TRANSITIVE", + "VAR", + "YIELD", + "RECORD", + "SEALED", + "PERMITS", + "NON_SEALED", + "DECIMAL_LITERAL", + "HEX_LITERAL", + "OCT_LITERAL", + "BINARY_LITERAL", + "FLOAT_LITERAL", + "HEX_FLOAT_LITERAL", + "BOOL_LITERAL", + "CHAR_LITERAL", + "STRING_LITERAL", + "TEXT_BLOCK", + "NULL_LITERAL", + "LPAREN", + "RPAREN", + "LBRACE", + "RBRACE", + "LBRACK", + "RBRACK", + "SEMI", + "COMMA", + "DOT", + "ASSIGN", + "GT", + "LT", + "BANG", + "TILDE", + "QUESTION", + "COLON", + "EQUAL", + "LE", + "GE", + "NOTEQUAL", + "AND", + "OR", + "INC", + "DEC", + "ADD", + "SUB", + "MUL", + "DIV", + "BITAND", + "BITOR", + "CARET", + "MOD", + "ADD_ASSIGN", + "SUB_ASSIGN", + "MUL_ASSIGN", + "DIV_ASSIGN", + "AND_ASSIGN", + "OR_ASSIGN", + "XOR_ASSIGN", + "MOD_ASSIGN", + "LSHIFT_ASSIGN", + "RSHIFT_ASSIGN", + "URSHIFT_ASSIGN", + "ARROW", + "COLONCOLON", + "AT", + "ELLIPSIS", + "JAVADOC_COMMENT", + "WS", + "COMMENT", + "LINE_COMMENT", + "IDENTIFIER", + "ExponentPart", + "EscapeSequence", + "HexDigits", + "HexDigit", + "Digits", + "LetterOrDigit", + "Letter" + }; + } + + public static final String[] ruleNames = makeRuleNames(); + + private static String[] makeLiteralNames() { + return new String[] { + null, + "'abstract'", + "'assert'", + "'boolean'", + "'break'", + "'byte'", + "'case'", + "'catch'", + "'char'", + "'class'", + "'const'", + "'continue'", + "'default'", + "'do'", + "'double'", + "'else'", + "'enum'", + "'extends'", + "'final'", + "'finally'", + "'float'", + "'for'", + "'if'", + "'goto'", + "'implements'", + "'import'", + "'instanceof'", + "'int'", + "'interface'", + "'long'", + "'native'", + "'new'", + "'package'", + "'private'", + "'protected'", + "'public'", + "'return'", + "'short'", + "'static'", + "'strictfp'", + "'super'", + "'switch'", + "'synchronized'", + "'this'", + "'throw'", + "'throws'", + "'transient'", + "'try'", + "'void'", + "'volatile'", + "'while'", + "'module'", + "'open'", + "'requires'", + "'exports'", + "'opens'", + "'to'", + "'uses'", + "'provides'", + "'with'", + "'transitive'", + "'var'", + "'yield'", + "'record'", + "'sealed'", + "'permits'", + "'non-sealed'", + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + "'null'", + "'('", + "')'", + "'{'", + "'}'", + "'['", + "']'", + "';'", + "','", + "'.'", + "'='", + "'>'", + "'<'", + "'!'", + "'~'", + "'?'", + "':'", + "'=='", + "'<='", + "'>='", + "'!='", + "'&&'", + "'||'", + "'++'", + "'--'", + "'+'", + "'-'", + "'*'", + "'/'", + "'&'", + "'|'", + "'^'", + "'%'", + "'+='", + "'-='", + "'*='", + "'/='", + "'&='", + "'|='", + "'^='", + "'%='", + "'<<='", + "'>>='", + "'>>>='", + "'->'", + "'::'", + "'@'", + "'...'" + }; + } + + private static final String[] _LITERAL_NAMES = makeLiteralNames(); + + private static String[] makeSymbolicNames() { + return new String[] { + null, + "ABSTRACT", + "ASSERT", + "BOOLEAN", + "BREAK", + "BYTE", + "CASE", + "CATCH", + "CHAR", + "CLASS", + "CONST", + "CONTINUE", + "DEFAULT", + "DO", + "DOUBLE", + "ELSE", + "ENUM", + "EXTENDS", + "FINAL", + "FINALLY", + "FLOAT", + "FOR", + "IF", + "GOTO", + "IMPLEMENTS", + "IMPORT", + "INSTANCEOF", + "INT", + "INTERFACE", + "LONG", + "NATIVE", + "NEW", + "PACKAGE", + "PRIVATE", + "PROTECTED", + "PUBLIC", + "RETURN", + "SHORT", + "STATIC", + "STRICTFP", + "SUPER", + "SWITCH", + "SYNCHRONIZED", + "THIS", + "THROW", + "THROWS", + "TRANSIENT", + "TRY", + "VOID", + "VOLATILE", + "WHILE", + "MODULE", + "OPEN", + "REQUIRES", + "EXPORTS", + "OPENS", + "TO", + "USES", + "PROVIDES", + "WITH", + "TRANSITIVE", + "VAR", + "YIELD", + "RECORD", + "SEALED", + "PERMITS", + "NON_SEALED", + "DECIMAL_LITERAL", + "HEX_LITERAL", + "OCT_LITERAL", + "BINARY_LITERAL", + "FLOAT_LITERAL", + "HEX_FLOAT_LITERAL", + "BOOL_LITERAL", + "CHAR_LITERAL", + "STRING_LITERAL", + "TEXT_BLOCK", + "NULL_LITERAL", + "LPAREN", + "RPAREN", + "LBRACE", + "RBRACE", + "LBRACK", + "RBRACK", + "SEMI", + "COMMA", + "DOT", + "ASSIGN", + "GT", + "LT", + "BANG", + "TILDE", + "QUESTION", + "COLON", + "EQUAL", + "LE", + "GE", + "NOTEQUAL", + "AND", + "OR", + "INC", + "DEC", + "ADD", + "SUB", + "MUL", + "DIV", + "BITAND", + "BITOR", + "CARET", + "MOD", + "ADD_ASSIGN", + "SUB_ASSIGN", + "MUL_ASSIGN", + "DIV_ASSIGN", + "AND_ASSIGN", + "OR_ASSIGN", + "XOR_ASSIGN", + "MOD_ASSIGN", + "LSHIFT_ASSIGN", + "RSHIFT_ASSIGN", + "URSHIFT_ASSIGN", + "ARROW", + "COLONCOLON", + "AT", + "ELLIPSIS", + "JAVADOC_COMMENT", + "WS", + "COMMENT", + "LINE_COMMENT", + "IDENTIFIER" + }; + } + + private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + public JavaLexer(CharStream input) { + super(input); + _interp = new LexerATNSimulator(this, _ATN, _decisionToDFA, _sharedContextCache); + } + + @Override + public String getGrammarFileName() { + return "JavaLexer.g4"; + } + + @Override + public String[] getRuleNames() { + return ruleNames; + } + + @Override + public String getSerializedATN() { + return _serializedATN; + } + + @Override + public String[] getChannelNames() { + return channelNames; + } + + @Override + public String[] getModeNames() { + return modeNames; + } + + @Override + public ATN getATN() { + return _ATN; + } + + public static final String _serializedATN = + "\u0004\u0000\u0081\u0475\u0006\uffff\uffff\u0002\u0000\u0007\u0000\u0002" + + "\u0001\u0007\u0001\u0002\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002" + + "\u0004\u0007\u0004\u0002\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002" + + "\u0007\u0007\u0007\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002" + + "\u000b\u0007\u000b\u0002\f\u0007\f\u0002\r\u0007\r\u0002\u000e\u0007\u000e" + + "\u0002\u000f\u0007\u000f\u0002\u0010\u0007\u0010\u0002\u0011\u0007\u0011" + + "\u0002\u0012\u0007\u0012\u0002\u0013\u0007\u0013\u0002\u0014\u0007\u0014" + + "\u0002\u0015\u0007\u0015\u0002\u0016\u0007\u0016\u0002\u0017\u0007\u0017" + + "\u0002\u0018\u0007\u0018\u0002\u0019\u0007\u0019\u0002\u001a\u0007\u001a" + + "\u0002\u001b\u0007\u001b\u0002\u001c\u0007\u001c\u0002\u001d\u0007\u001d" + + "\u0002\u001e\u0007\u001e\u0002\u001f\u0007\u001f\u0002 \u0007 \u0002!" + + "\u0007!\u0002\"\u0007\"\u0002#\u0007#\u0002$\u0007$\u0002%\u0007%\u0002" + + "&\u0007&\u0002\'\u0007\'\u0002(\u0007(\u0002)\u0007)\u0002*\u0007*\u0002" + + "+\u0007+\u0002,\u0007,\u0002-\u0007-\u0002.\u0007.\u0002/\u0007/\u0002" + + "0\u00070\u00021\u00071\u00022\u00072\u00023\u00073\u00024\u00074\u0002" + + "5\u00075\u00026\u00076\u00027\u00077\u00028\u00078\u00029\u00079\u0002" + + ":\u0007:\u0002;\u0007;\u0002<\u0007<\u0002=\u0007=\u0002>\u0007>\u0002" + + "?\u0007?\u0002@\u0007@\u0002A\u0007A\u0002B\u0007B\u0002C\u0007C\u0002" + + "D\u0007D\u0002E\u0007E\u0002F\u0007F\u0002G\u0007G\u0002H\u0007H\u0002" + + "I\u0007I\u0002J\u0007J\u0002K\u0007K\u0002L\u0007L\u0002M\u0007M\u0002" + + "N\u0007N\u0002O\u0007O\u0002P\u0007P\u0002Q\u0007Q\u0002R\u0007R\u0002" + + "S\u0007S\u0002T\u0007T\u0002U\u0007U\u0002V\u0007V\u0002W\u0007W\u0002" + + "X\u0007X\u0002Y\u0007Y\u0002Z\u0007Z\u0002[\u0007[\u0002\\\u0007\\\u0002" + + "]\u0007]\u0002^\u0007^\u0002_\u0007_\u0002`\u0007`\u0002a\u0007a\u0002" + + "b\u0007b\u0002c\u0007c\u0002d\u0007d\u0002e\u0007e\u0002f\u0007f\u0002" + + "g\u0007g\u0002h\u0007h\u0002i\u0007i\u0002j\u0007j\u0002k\u0007k\u0002" + + "l\u0007l\u0002m\u0007m\u0002n\u0007n\u0002o\u0007o\u0002p\u0007p\u0002" + + "q\u0007q\u0002r\u0007r\u0002s\u0007s\u0002t\u0007t\u0002u\u0007u\u0002" + + "v\u0007v\u0002w\u0007w\u0002x\u0007x\u0002y\u0007y\u0002z\u0007z\u0002" + + "{\u0007{\u0002|\u0007|\u0002}\u0007}\u0002~\u0007~\u0002\u007f\u0007\u007f" + + "\u0002\u0080\u0007\u0080\u0002\u0081\u0007\u0081\u0002\u0082\u0007\u0082" + + "\u0002\u0083\u0007\u0083\u0002\u0084\u0007\u0084\u0002\u0085\u0007\u0085" + + "\u0002\u0086\u0007\u0086\u0002\u0087\u0007\u0087\u0001\u0000\u0001\u0000" + + "\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000" + + "\u0001\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001" + + "\u0001\u0001\u0001\u0001\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002" + + "\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0003\u0001\u0003" + + "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0004\u0001\u0004" + + "\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005\u0001\u0005" + + "\u0001\u0005\u0001\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006" + + "\u0001\u0006\u0001\u0006\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007" + + "\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\t\u0001" + + "\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\n\u0001\n\u0001\n\u0001\n\u0001" + + "\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\u000b\u0001\u000b\u0001\u000b" + + "\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\f\u0001" + + "\f\u0001\f\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001" + + "\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000f\u0001" + + "\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0001" + + "\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001" + + "\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001" + + "\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001" + + "\u0012\u0001\u0012\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001" + + "\u0013\u0001\u0013\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001" + + "\u0015\u0001\u0015\u0001\u0015\u0001\u0016\u0001\u0016\u0001\u0016\u0001" + + "\u0016\u0001\u0016\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001" + + "\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001" + + "\u0017\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001" + + "\u0018\u0001\u0018\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001" + + "\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001" + + "\u0019\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001b\u0001" + + "\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0001" + + "\u001b\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001\u001c\u0001" + + "\u001c\u0001\u001c\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001" + + "\u001d\u0001\u001d\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001e\u0001" + + "\u001e\u0001\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001" + + "\u001f\u0001\u001f\u0001\u001f\u0001 \u0001 \u0001 \u0001 \u0001 \u0001" + + " \u0001 \u0001 \u0001!\u0001!\u0001!\u0001!\u0001!\u0001!\u0001!\u0001" + + "!\u0001!\u0001!\u0001\"\u0001\"\u0001\"\u0001\"\u0001\"\u0001\"\u0001" + + "\"\u0001#\u0001#\u0001#\u0001#\u0001#\u0001#\u0001#\u0001$\u0001$\u0001" + + "$\u0001$\u0001$\u0001$\u0001%\u0001%\u0001%\u0001%\u0001%\u0001%\u0001" + + "%\u0001&\u0001&\u0001&\u0001&\u0001&\u0001&\u0001&\u0001&\u0001&\u0001" + + "\'\u0001\'\u0001\'\u0001\'\u0001\'\u0001\'\u0001(\u0001(\u0001(\u0001" + + "(\u0001(\u0001(\u0001(\u0001)\u0001)\u0001)\u0001)\u0001)\u0001)\u0001" + + ")\u0001)\u0001)\u0001)\u0001)\u0001)\u0001)\u0001*\u0001*\u0001*\u0001" + + "*\u0001*\u0001+\u0001+\u0001+\u0001+\u0001+\u0001+\u0001,\u0001,\u0001" + + ",\u0001,\u0001,\u0001,\u0001,\u0001-\u0001-\u0001-\u0001-\u0001-\u0001" + + "-\u0001-\u0001-\u0001-\u0001-\u0001.\u0001.\u0001.\u0001.\u0001/\u0001" + + "/\u0001/\u0001/\u0001/\u00010\u00010\u00010\u00010\u00010\u00010\u0001" + + "0\u00010\u00010\u00011\u00011\u00011\u00011\u00011\u00011\u00012\u0001" + + "2\u00012\u00012\u00012\u00012\u00012\u00013\u00013\u00013\u00013\u0001" + + "3\u00014\u00014\u00014\u00014\u00014\u00014\u00014\u00014\u00014\u0001" + + "5\u00015\u00015\u00015\u00015\u00015\u00015\u00015\u00016\u00016\u0001" + + "6\u00016\u00016\u00016\u00017\u00017\u00017\u00018\u00018\u00018\u0001" + + "8\u00018\u00019\u00019\u00019\u00019\u00019\u00019\u00019\u00019\u0001" + + "9\u0001:\u0001:\u0001:\u0001:\u0001:\u0001;\u0001;\u0001;\u0001;\u0001" + + ";\u0001;\u0001;\u0001;\u0001;\u0001;\u0001;\u0001<\u0001<\u0001<\u0001" + + "<\u0001=\u0001=\u0001=\u0001=\u0001=\u0001=\u0001>\u0001>\u0001>\u0001" + + ">\u0001>\u0001>\u0001>\u0001?\u0001?\u0001?\u0001?\u0001?\u0001?\u0001" + + "?\u0001@\u0001@\u0001@\u0001@\u0001@\u0001@\u0001@\u0001@\u0001A\u0001" + + "A\u0001A\u0001A\u0001A\u0001A\u0001A\u0001A\u0001A\u0001A\u0001A\u0001" + + "B\u0001B\u0001B\u0003B\u02d7\bB\u0001B\u0004B\u02da\bB\u000bB\fB\u02db" + + "\u0001B\u0003B\u02df\bB\u0003B\u02e1\bB\u0001B\u0003B\u02e4\bB\u0001C" + + "\u0001C\u0001C\u0001C\u0005C\u02ea\bC\nC\fC\u02ed\tC\u0001C\u0003C\u02f0" + + "\bC\u0001C\u0003C\u02f3\bC\u0001D\u0001D\u0005D\u02f7\bD\nD\fD\u02fa\t" + + "D\u0001D\u0001D\u0005D\u02fe\bD\nD\fD\u0301\tD\u0001D\u0003D\u0304\bD" + + "\u0001D\u0003D\u0307\bD\u0001E\u0001E\u0001E\u0001E\u0005E\u030d\bE\n" + + "E\fE\u0310\tE\u0001E\u0003E\u0313\bE\u0001E\u0003E\u0316\bE\u0001F\u0001" + + "F\u0001F\u0003F\u031b\bF\u0001F\u0001F\u0003F\u031f\bF\u0001F\u0003F\u0322" + + "\bF\u0001F\u0003F\u0325\bF\u0001F\u0001F\u0001F\u0003F\u032a\bF\u0001" + + "F\u0003F\u032d\bF\u0003F\u032f\bF\u0001G\u0001G\u0001G\u0001G\u0003G\u0335" + + "\bG\u0001G\u0003G\u0338\bG\u0001G\u0001G\u0003G\u033c\bG\u0001G\u0001" + + "G\u0003G\u0340\bG\u0001G\u0001G\u0003G\u0344\bG\u0001H\u0001H\u0001H\u0001" + + "H\u0001H\u0001H\u0001H\u0001H\u0001H\u0003H\u034f\bH\u0001I\u0001I\u0001" + + "I\u0003I\u0354\bI\u0001I\u0001I\u0001J\u0001J\u0001J\u0005J\u035b\bJ\n" + + "J\fJ\u035e\tJ\u0001J\u0001J\u0001K\u0001K\u0001K\u0001K\u0001K\u0005K" + + "\u0367\bK\nK\fK\u036a\tK\u0001K\u0001K\u0001K\u0005K\u036f\bK\nK\fK\u0372" + + "\tK\u0001K\u0001K\u0001K\u0001K\u0001L\u0001L\u0001L\u0001L\u0001L\u0001" + + "M\u0001M\u0001N\u0001N\u0001O\u0001O\u0001P\u0001P\u0001Q\u0001Q\u0001" + + "R\u0001R\u0001S\u0001S\u0001T\u0001T\u0001U\u0001U\u0001V\u0001V\u0001" + + "W\u0001W\u0001X\u0001X\u0001Y\u0001Y\u0001Z\u0001Z\u0001[\u0001[\u0001" + + "\\\u0001\\\u0001]\u0001]\u0001]\u0001^\u0001^\u0001^\u0001_\u0001_\u0001" + + "_\u0001`\u0001`\u0001`\u0001a\u0001a\u0001a\u0001b\u0001b\u0001b\u0001" + + "c\u0001c\u0001c\u0001d\u0001d\u0001d\u0001e\u0001e\u0001f\u0001f\u0001" + + "g\u0001g\u0001h\u0001h\u0001i\u0001i\u0001j\u0001j\u0001k\u0001k\u0001" + + "l\u0001l\u0001m\u0001m\u0001m\u0001n\u0001n\u0001n\u0001o\u0001o\u0001" + + "o\u0001p\u0001p\u0001p\u0001q\u0001q\u0001q\u0001r\u0001r\u0001r\u0001" + + "s\u0001s\u0001s\u0001t\u0001t\u0001t\u0001u\u0001u\u0001u\u0001u\u0001" + + "v\u0001v\u0001v\u0001v\u0001w\u0001w\u0001w\u0001w\u0001w\u0001x\u0001" + + "x\u0001x\u0001y\u0001y\u0001y\u0001z\u0001z\u0001{\u0001{\u0001{\u0001" + + "{\u0001|\u0001|\u0001|\u0001|\u0001|\u0005|\u03fb\b|\n|\f|\u03fe\t|\u0001" + + "|\u0001|\u0001|\u0001}\u0004}\u0404\b}\u000b}\f}\u0405\u0001}\u0001}\u0001" + + "~\u0001~\u0001~\u0001~\u0005~\u040e\b~\n~\f~\u0411\t~\u0001~\u0001~\u0001" + + "~\u0001~\u0001~\u0001\u007f\u0001\u007f\u0001\u007f\u0001\u007f\u0005" + + "\u007f\u041c\b\u007f\n\u007f\f\u007f\u041f\t\u007f\u0001\u007f\u0001\u007f" + + "\u0001\u0080\u0001\u0080\u0005\u0080\u0425\b\u0080\n\u0080\f\u0080\u0428" + + "\t\u0080\u0001\u0081\u0001\u0081\u0003\u0081\u042c\b\u0081\u0001\u0081" + + "\u0001\u0081\u0001\u0082\u0001\u0082\u0001\u0082\u0001\u0082\u0001\u0082" + + "\u0001\u0082\u0003\u0082\u0436\b\u0082\u0001\u0082\u0001\u0082\u0001\u0082" + + "\u0001\u0082\u0001\u0082\u0001\u0082\u0001\u0082\u0003\u0082\u043f\b\u0082" + + "\u0001\u0082\u0003\u0082\u0442\b\u0082\u0001\u0082\u0003\u0082\u0445\b" + + "\u0082\u0001\u0082\u0001\u0082\u0001\u0082\u0004\u0082\u044a\b\u0082\u000b" + + "\u0082\f\u0082\u044b\u0001\u0082\u0001\u0082\u0001\u0082\u0001\u0082\u0001" + + "\u0082\u0003\u0082\u0453\b\u0082\u0001\u0083\u0001\u0083\u0001\u0083\u0005" + + "\u0083\u0458\b\u0083\n\u0083\f\u0083\u045b\t\u0083\u0001\u0083\u0003\u0083" + + "\u045e\b\u0083\u0001\u0084\u0001\u0084\u0001\u0085\u0001\u0085\u0005\u0085" + + "\u0464\b\u0085\n\u0085\f\u0085\u0467\t\u0085\u0001\u0085\u0003\u0085\u046a" + + "\b\u0085\u0001\u0086\u0001\u0086\u0003\u0086\u046e\b\u0086\u0001\u0087" + + "\u0001\u0087\u0001\u0087\u0001\u0087\u0003\u0087\u0474\b\u0087\u0003\u0370" + + "\u03fc\u040f\u0000\u0088\u0001\u0001\u0003\u0002\u0005\u0003\u0007\u0004" + + "\t\u0005\u000b\u0006\r\u0007\u000f\b\u0011\t\u0013\n\u0015\u000b\u0017" + + "\f\u0019\r\u001b\u000e\u001d\u000f\u001f\u0010!\u0011#\u0012%\u0013\'" + + "\u0014)\u0015+\u0016-\u0017/\u00181\u00193\u001a5\u001b7\u001c9\u001d" + + ";\u001e=\u001f? A!C\"E#G$I%K&M\'O(Q)S*U+W,Y-[.]/_0a1c2e3g4i5k6m7o8q9s" + + ":u;w}?\u007f@\u0081A\u0083B\u0085C\u0087D\u0089E\u008bF\u008dG\u008f" + + "H\u0091I\u0093J\u0095K\u0097L\u0099M\u009bN\u009dO\u009fP\u00a1Q\u00a3" + + "R\u00a5S\u00a7T\u00a9U\u00abV\u00adW\u00afX\u00b1Y\u00b3Z\u00b5[\u00b7" + + "\\\u00b9]\u00bb^\u00bd_\u00bf`\u00c1a\u00c3b\u00c5c\u00c7d\u00c9e\u00cb" + + "f\u00cdg\u00cfh\u00d1i\u00d3j\u00d5k\u00d7l\u00d9m\u00dbn\u00ddo\u00df" + + "p\u00e1q\u00e3r\u00e5s\u00e7t\u00e9u\u00ebv\u00edw\u00efx\u00f1y\u00f3" + + "z\u00f5{\u00f7|\u00f9}\u00fb~\u00fd\u007f\u00ff\u0080\u0101\u0081\u0103" + + "\u0000\u0105\u0000\u0107\u0000\u0109\u0000\u010b\u0000\u010d\u0000\u010f" + + "\u0000\u0001\u0000\u001b\u0001\u000019\u0002\u0000LLll\u0002\u0000XXx" + + "x\u0003\u000009AFaf\u0004\u000009AF__af\u0001\u000007\u0002\u000007__" + + "\u0002\u0000BBbb\u0001\u000001\u0002\u000001__\u0004\u0000DDFFddff\u0002" + + "\u0000PPpp\u0002\u0000++--\u0004\u0000\n\n\r\r\'\'\\\\\u0004\u0000\n\n" + + "\r\r\"\"\\\\\u0002\u0000\t\t \u0002\u0000\n\n\r\r\u0003\u0000\t\n\f\r" + + " \u0002\u0000EEee\b\u0000\"\"\'\'\\\\bbffnnrrtt\u0001\u000003\u0001\u0000" + + "09\u0002\u000009__\u0004\u0000$$AZ__az\u0002\u0000\u0000\u007f\u8000\ud800" + + "\u8000\udbff\u0001\u0000\u8000\ud800\u8000\udbff\u0001\u0000\u8000\udc00" + + "\u8000\udfff\u04a4\u0000\u0001\u0001\u0000\u0000\u0000\u0000\u0003\u0001" + + "\u0000\u0000\u0000\u0000\u0005\u0001\u0000\u0000\u0000\u0000\u0007\u0001" + + "\u0000\u0000\u0000\u0000\t\u0001\u0000\u0000\u0000\u0000\u000b\u0001\u0000" + + "\u0000\u0000\u0000\r\u0001\u0000\u0000\u0000\u0000\u000f\u0001\u0000\u0000" + + "\u0000\u0000\u0011\u0001\u0000\u0000\u0000\u0000\u0013\u0001\u0000\u0000" + + "\u0000\u0000\u0015\u0001\u0000\u0000\u0000\u0000\u0017\u0001\u0000\u0000" + + "\u0000\u0000\u0019\u0001\u0000\u0000\u0000\u0000\u001b\u0001\u0000\u0000" + + "\u0000\u0000\u001d\u0001\u0000\u0000\u0000\u0000\u001f\u0001\u0000\u0000" + + "\u0000\u0000!\u0001\u0000\u0000\u0000\u0000#\u0001\u0000\u0000\u0000\u0000" + + "%\u0001\u0000\u0000\u0000\u0000\'\u0001\u0000\u0000\u0000\u0000)\u0001" + + "\u0000\u0000\u0000\u0000+\u0001\u0000\u0000\u0000\u0000-\u0001\u0000\u0000" + + "\u0000\u0000/\u0001\u0000\u0000\u0000\u00001\u0001\u0000\u0000\u0000\u0000" + + "3\u0001\u0000\u0000\u0000\u00005\u0001\u0000\u0000\u0000\u00007\u0001" + + "\u0000\u0000\u0000\u00009\u0001\u0000\u0000\u0000\u0000;\u0001\u0000\u0000" + + "\u0000\u0000=\u0001\u0000\u0000\u0000\u0000?\u0001\u0000\u0000\u0000\u0000" + + "A\u0001\u0000\u0000\u0000\u0000C\u0001\u0000\u0000\u0000\u0000E\u0001" + + "\u0000\u0000\u0000\u0000G\u0001\u0000\u0000\u0000\u0000I\u0001\u0000\u0000" + + "\u0000\u0000K\u0001\u0000\u0000\u0000\u0000M\u0001\u0000\u0000\u0000\u0000" + + "O\u0001\u0000\u0000\u0000\u0000Q\u0001\u0000\u0000\u0000\u0000S\u0001" + + "\u0000\u0000\u0000\u0000U\u0001\u0000\u0000\u0000\u0000W\u0001\u0000\u0000" + + "\u0000\u0000Y\u0001\u0000\u0000\u0000\u0000[\u0001\u0000\u0000\u0000\u0000" + + "]\u0001\u0000\u0000\u0000\u0000_\u0001\u0000\u0000\u0000\u0000a\u0001" + + "\u0000\u0000\u0000\u0000c\u0001\u0000\u0000\u0000\u0000e\u0001\u0000\u0000" + + "\u0000\u0000g\u0001\u0000\u0000\u0000\u0000i\u0001\u0000\u0000\u0000\u0000" + + "k\u0001\u0000\u0000\u0000\u0000m\u0001\u0000\u0000\u0000\u0000o\u0001" + + "\u0000\u0000\u0000\u0000q\u0001\u0000\u0000\u0000\u0000s\u0001\u0000\u0000" + + "\u0000\u0000u\u0001\u0000\u0000\u0000\u0000w\u0001\u0000\u0000\u0000\u0000" + + "y\u0001\u0000\u0000\u0000\u0000{\u0001\u0000\u0000\u0000\u0000}\u0001" + + "\u0000\u0000\u0000\u0000\u007f\u0001\u0000\u0000\u0000\u0000\u0081\u0001" + + "\u0000\u0000\u0000\u0000\u0083\u0001\u0000\u0000\u0000\u0000\u0085\u0001" + + "\u0000\u0000\u0000\u0000\u0087\u0001\u0000\u0000\u0000\u0000\u0089\u0001" + + "\u0000\u0000\u0000\u0000\u008b\u0001\u0000\u0000\u0000\u0000\u008d\u0001" + + "\u0000\u0000\u0000\u0000\u008f\u0001\u0000\u0000\u0000\u0000\u0091\u0001" + + "\u0000\u0000\u0000\u0000\u0093\u0001\u0000\u0000\u0000\u0000\u0095\u0001" + + "\u0000\u0000\u0000\u0000\u0097\u0001\u0000\u0000\u0000\u0000\u0099\u0001" + + "\u0000\u0000\u0000\u0000\u009b\u0001\u0000\u0000\u0000\u0000\u009d\u0001" + + "\u0000\u0000\u0000\u0000\u009f\u0001\u0000\u0000\u0000\u0000\u00a1\u0001" + + "\u0000\u0000\u0000\u0000\u00a3\u0001\u0000\u0000\u0000\u0000\u00a5\u0001" + + "\u0000\u0000\u0000\u0000\u00a7\u0001\u0000\u0000\u0000\u0000\u00a9\u0001" + + "\u0000\u0000\u0000\u0000\u00ab\u0001\u0000\u0000\u0000\u0000\u00ad\u0001" + + "\u0000\u0000\u0000\u0000\u00af\u0001\u0000\u0000\u0000\u0000\u00b1\u0001" + + "\u0000\u0000\u0000\u0000\u00b3\u0001\u0000\u0000\u0000\u0000\u00b5\u0001" + + "\u0000\u0000\u0000\u0000\u00b7\u0001\u0000\u0000\u0000\u0000\u00b9\u0001" + + "\u0000\u0000\u0000\u0000\u00bb\u0001\u0000\u0000\u0000\u0000\u00bd\u0001" + + "\u0000\u0000\u0000\u0000\u00bf\u0001\u0000\u0000\u0000\u0000\u00c1\u0001" + + "\u0000\u0000\u0000\u0000\u00c3\u0001\u0000\u0000\u0000\u0000\u00c5\u0001" + + "\u0000\u0000\u0000\u0000\u00c7\u0001\u0000\u0000\u0000\u0000\u00c9\u0001" + + "\u0000\u0000\u0000\u0000\u00cb\u0001\u0000\u0000\u0000\u0000\u00cd\u0001" + + "\u0000\u0000\u0000\u0000\u00cf\u0001\u0000\u0000\u0000\u0000\u00d1\u0001" + + "\u0000\u0000\u0000\u0000\u00d3\u0001\u0000\u0000\u0000\u0000\u00d5\u0001" + + "\u0000\u0000\u0000\u0000\u00d7\u0001\u0000\u0000\u0000\u0000\u00d9\u0001" + + "\u0000\u0000\u0000\u0000\u00db\u0001\u0000\u0000\u0000\u0000\u00dd\u0001" + + "\u0000\u0000\u0000\u0000\u00df\u0001\u0000\u0000\u0000\u0000\u00e1\u0001" + + "\u0000\u0000\u0000\u0000\u00e3\u0001\u0000\u0000\u0000\u0000\u00e5\u0001" + + "\u0000\u0000\u0000\u0000\u00e7\u0001\u0000\u0000\u0000\u0000\u00e9\u0001" + + "\u0000\u0000\u0000\u0000\u00eb\u0001\u0000\u0000\u0000\u0000\u00ed\u0001" + + "\u0000\u0000\u0000\u0000\u00ef\u0001\u0000\u0000\u0000\u0000\u00f1\u0001" + + "\u0000\u0000\u0000\u0000\u00f3\u0001\u0000\u0000\u0000\u0000\u00f5\u0001" + + "\u0000\u0000\u0000\u0000\u00f7\u0001\u0000\u0000\u0000\u0000\u00f9\u0001" + + "\u0000\u0000\u0000\u0000\u00fb\u0001\u0000\u0000\u0000\u0000\u00fd\u0001" + + "\u0000\u0000\u0000\u0000\u00ff\u0001\u0000\u0000\u0000\u0000\u0101\u0001" + + "\u0000\u0000\u0000\u0001\u0111\u0001\u0000\u0000\u0000\u0003\u011a\u0001" + + "\u0000\u0000\u0000\u0005\u0121\u0001\u0000\u0000\u0000\u0007\u0129\u0001" + + "\u0000\u0000\u0000\t\u012f\u0001\u0000\u0000\u0000\u000b\u0134\u0001\u0000" + + "\u0000\u0000\r\u0139\u0001\u0000\u0000\u0000\u000f\u013f\u0001\u0000\u0000" + + "\u0000\u0011\u0144\u0001\u0000\u0000\u0000\u0013\u014a\u0001\u0000\u0000" + + "\u0000\u0015\u0150\u0001\u0000\u0000\u0000\u0017\u0159\u0001\u0000\u0000" + + "\u0000\u0019\u0161\u0001\u0000\u0000\u0000\u001b\u0164\u0001\u0000\u0000" + + "\u0000\u001d\u016b\u0001\u0000\u0000\u0000\u001f\u0170\u0001\u0000\u0000" + + "\u0000!\u0175\u0001\u0000\u0000\u0000#\u017d\u0001\u0000\u0000\u0000%" + + "\u0183\u0001\u0000\u0000\u0000\'\u018b\u0001\u0000\u0000\u0000)\u0191" + + "\u0001\u0000\u0000\u0000+\u0195\u0001\u0000\u0000\u0000-\u0198\u0001\u0000" + + "\u0000\u0000/\u019d\u0001\u0000\u0000\u00001\u01a8\u0001\u0000\u0000\u0000" + + "3\u01af\u0001\u0000\u0000\u00005\u01ba\u0001\u0000\u0000\u00007\u01be" + + "\u0001\u0000\u0000\u00009\u01c8\u0001\u0000\u0000\u0000;\u01cd\u0001\u0000" + + "\u0000\u0000=\u01d4\u0001\u0000\u0000\u0000?\u01d8\u0001\u0000\u0000\u0000" + + "A\u01e0\u0001\u0000\u0000\u0000C\u01e8\u0001\u0000\u0000\u0000E\u01f2" + + "\u0001\u0000\u0000\u0000G\u01f9\u0001\u0000\u0000\u0000I\u0200\u0001\u0000" + + "\u0000\u0000K\u0206\u0001\u0000\u0000\u0000M\u020d\u0001\u0000\u0000\u0000" + + "O\u0216\u0001\u0000\u0000\u0000Q\u021c\u0001\u0000\u0000\u0000S\u0223" + + "\u0001\u0000\u0000\u0000U\u0230\u0001\u0000\u0000\u0000W\u0235\u0001\u0000" + + "\u0000\u0000Y\u023b\u0001\u0000\u0000\u0000[\u0242\u0001\u0000\u0000\u0000" + + "]\u024c\u0001\u0000\u0000\u0000_\u0250\u0001\u0000\u0000\u0000a\u0255" + + "\u0001\u0000\u0000\u0000c\u025e\u0001\u0000\u0000\u0000e\u0264\u0001\u0000" + + "\u0000\u0000g\u026b\u0001\u0000\u0000\u0000i\u0270\u0001\u0000\u0000\u0000" + + "k\u0279\u0001\u0000\u0000\u0000m\u0281\u0001\u0000\u0000\u0000o\u0287" + + "\u0001\u0000\u0000\u0000q\u028a\u0001\u0000\u0000\u0000s\u028f\u0001\u0000" + + "\u0000\u0000u\u0298\u0001\u0000\u0000\u0000w\u029d\u0001\u0000\u0000\u0000" + + "y\u02a8\u0001\u0000\u0000\u0000{\u02ac\u0001\u0000\u0000\u0000}\u02b2" + + "\u0001\u0000\u0000\u0000\u007f\u02b9\u0001\u0000\u0000\u0000\u0081\u02c0" + + "\u0001\u0000\u0000\u0000\u0083\u02c8\u0001\u0000\u0000\u0000\u0085\u02e0" + + "\u0001\u0000\u0000\u0000\u0087\u02e5\u0001\u0000\u0000\u0000\u0089\u02f4" + + "\u0001\u0000\u0000\u0000\u008b\u0308\u0001\u0000\u0000\u0000\u008d\u032e" + + "\u0001\u0000\u0000\u0000\u008f\u0330\u0001\u0000\u0000\u0000\u0091\u034e" + + "\u0001\u0000\u0000\u0000\u0093\u0350\u0001\u0000\u0000\u0000\u0095\u0357" + + "\u0001\u0000\u0000\u0000\u0097\u0361\u0001\u0000\u0000\u0000\u0099\u0377" + + "\u0001\u0000\u0000\u0000\u009b\u037c\u0001\u0000\u0000\u0000\u009d\u037e" + + "\u0001\u0000\u0000\u0000\u009f\u0380\u0001\u0000\u0000\u0000\u00a1\u0382" + + "\u0001\u0000\u0000\u0000\u00a3\u0384\u0001\u0000\u0000\u0000\u00a5\u0386" + + "\u0001\u0000\u0000\u0000\u00a7\u0388\u0001\u0000\u0000\u0000\u00a9\u038a" + + "\u0001\u0000\u0000\u0000\u00ab\u038c\u0001\u0000\u0000\u0000\u00ad\u038e" + + "\u0001\u0000\u0000\u0000\u00af\u0390\u0001\u0000\u0000\u0000\u00b1\u0392" + + "\u0001\u0000\u0000\u0000\u00b3\u0394\u0001\u0000\u0000\u0000\u00b5\u0396" + + "\u0001\u0000\u0000\u0000\u00b7\u0398\u0001\u0000\u0000\u0000\u00b9\u039a" + + "\u0001\u0000\u0000\u0000\u00bb\u039c\u0001\u0000\u0000\u0000\u00bd\u039f" + + "\u0001\u0000\u0000\u0000\u00bf\u03a2\u0001\u0000\u0000\u0000\u00c1\u03a5" + + "\u0001\u0000\u0000\u0000\u00c3\u03a8\u0001\u0000\u0000\u0000\u00c5\u03ab" + + "\u0001\u0000\u0000\u0000\u00c7\u03ae\u0001\u0000\u0000\u0000\u00c9\u03b1" + + "\u0001\u0000\u0000\u0000\u00cb\u03b4\u0001\u0000\u0000\u0000\u00cd\u03b6" + + "\u0001\u0000\u0000\u0000\u00cf\u03b8\u0001\u0000\u0000\u0000\u00d1\u03ba" + + "\u0001\u0000\u0000\u0000\u00d3\u03bc\u0001\u0000\u0000\u0000\u00d5\u03be" + + "\u0001\u0000\u0000\u0000\u00d7\u03c0\u0001\u0000\u0000\u0000\u00d9\u03c2" + + "\u0001\u0000\u0000\u0000\u00db\u03c4\u0001\u0000\u0000\u0000\u00dd\u03c7" + + "\u0001\u0000\u0000\u0000\u00df\u03ca\u0001\u0000\u0000\u0000\u00e1\u03cd" + + "\u0001\u0000\u0000\u0000\u00e3\u03d0\u0001\u0000\u0000\u0000\u00e5\u03d3" + + "\u0001\u0000\u0000\u0000\u00e7\u03d6\u0001\u0000\u0000\u0000\u00e9\u03d9" + + "\u0001\u0000\u0000\u0000\u00eb\u03dc\u0001\u0000\u0000\u0000\u00ed\u03e0" + + "\u0001\u0000\u0000\u0000\u00ef\u03e4\u0001\u0000\u0000\u0000\u00f1\u03e9" + + "\u0001\u0000\u0000\u0000\u00f3\u03ec\u0001\u0000\u0000\u0000\u00f5\u03ef" + + "\u0001\u0000\u0000\u0000\u00f7\u03f1\u0001\u0000\u0000\u0000\u00f9\u03f5" + + "\u0001\u0000\u0000\u0000\u00fb\u0403\u0001\u0000\u0000\u0000\u00fd\u0409" + + "\u0001\u0000\u0000\u0000\u00ff\u0417\u0001\u0000\u0000\u0000\u0101\u0422" + + "\u0001\u0000\u0000\u0000\u0103\u0429\u0001\u0000\u0000\u0000\u0105\u0452" + + "\u0001\u0000\u0000\u0000\u0107\u0454\u0001\u0000\u0000\u0000\u0109\u045f" + + "\u0001\u0000\u0000\u0000\u010b\u0461\u0001\u0000\u0000\u0000\u010d\u046d" + + "\u0001\u0000\u0000\u0000\u010f\u0473\u0001\u0000\u0000\u0000\u0111\u0112" + + "\u0005a\u0000\u0000\u0112\u0113\u0005b\u0000\u0000\u0113\u0114\u0005s" + + "\u0000\u0000\u0114\u0115\u0005t\u0000\u0000\u0115\u0116\u0005r\u0000\u0000" + + "\u0116\u0117\u0005a\u0000\u0000\u0117\u0118\u0005c\u0000\u0000\u0118\u0119" + + "\u0005t\u0000\u0000\u0119\u0002\u0001\u0000\u0000\u0000\u011a\u011b\u0005" + + "a\u0000\u0000\u011b\u011c\u0005s\u0000\u0000\u011c\u011d\u0005s\u0000" + + "\u0000\u011d\u011e\u0005e\u0000\u0000\u011e\u011f\u0005r\u0000\u0000\u011f" + + "\u0120\u0005t\u0000\u0000\u0120\u0004\u0001\u0000\u0000\u0000\u0121\u0122" + + "\u0005b\u0000\u0000\u0122\u0123\u0005o\u0000\u0000\u0123\u0124\u0005o" + + "\u0000\u0000\u0124\u0125\u0005l\u0000\u0000\u0125\u0126\u0005e\u0000\u0000" + + "\u0126\u0127\u0005a\u0000\u0000\u0127\u0128\u0005n\u0000\u0000\u0128\u0006" + + "\u0001\u0000\u0000\u0000\u0129\u012a\u0005b\u0000\u0000\u012a\u012b\u0005" + + "r\u0000\u0000\u012b\u012c\u0005e\u0000\u0000\u012c\u012d\u0005a\u0000" + + "\u0000\u012d\u012e\u0005k\u0000\u0000\u012e\b\u0001\u0000\u0000\u0000" + + "\u012f\u0130\u0005b\u0000\u0000\u0130\u0131\u0005y\u0000\u0000\u0131\u0132" + + "\u0005t\u0000\u0000\u0132\u0133\u0005e\u0000\u0000\u0133\n\u0001\u0000" + + "\u0000\u0000\u0134\u0135\u0005c\u0000\u0000\u0135\u0136\u0005a\u0000\u0000" + + "\u0136\u0137\u0005s\u0000\u0000\u0137\u0138\u0005e\u0000\u0000\u0138\f" + + "\u0001\u0000\u0000\u0000\u0139\u013a\u0005c\u0000\u0000\u013a\u013b\u0005" + + "a\u0000\u0000\u013b\u013c\u0005t\u0000\u0000\u013c\u013d\u0005c\u0000" + + "\u0000\u013d\u013e\u0005h\u0000\u0000\u013e\u000e\u0001\u0000\u0000\u0000" + + "\u013f\u0140\u0005c\u0000\u0000\u0140\u0141\u0005h\u0000\u0000\u0141\u0142" + + "\u0005a\u0000\u0000\u0142\u0143\u0005r\u0000\u0000\u0143\u0010\u0001\u0000" + + "\u0000\u0000\u0144\u0145\u0005c\u0000\u0000\u0145\u0146\u0005l\u0000\u0000" + + "\u0146\u0147\u0005a\u0000\u0000\u0147\u0148\u0005s\u0000\u0000\u0148\u0149" + + "\u0005s\u0000\u0000\u0149\u0012\u0001\u0000\u0000\u0000\u014a\u014b\u0005" + + "c\u0000\u0000\u014b\u014c\u0005o\u0000\u0000\u014c\u014d\u0005n\u0000" + + "\u0000\u014d\u014e\u0005s\u0000\u0000\u014e\u014f\u0005t\u0000\u0000\u014f" + + "\u0014\u0001\u0000\u0000\u0000\u0150\u0151\u0005c\u0000\u0000\u0151\u0152" + + "\u0005o\u0000\u0000\u0152\u0153\u0005n\u0000\u0000\u0153\u0154\u0005t" + + "\u0000\u0000\u0154\u0155\u0005i\u0000\u0000\u0155\u0156\u0005n\u0000\u0000" + + "\u0156\u0157\u0005u\u0000\u0000\u0157\u0158\u0005e\u0000\u0000\u0158\u0016" + + "\u0001\u0000\u0000\u0000\u0159\u015a\u0005d\u0000\u0000\u015a\u015b\u0005" + + "e\u0000\u0000\u015b\u015c\u0005f\u0000\u0000\u015c\u015d\u0005a\u0000" + + "\u0000\u015d\u015e\u0005u\u0000\u0000\u015e\u015f\u0005l\u0000\u0000\u015f" + + "\u0160\u0005t\u0000\u0000\u0160\u0018\u0001\u0000\u0000\u0000\u0161\u0162" + + "\u0005d\u0000\u0000\u0162\u0163\u0005o\u0000\u0000\u0163\u001a\u0001\u0000" + + "\u0000\u0000\u0164\u0165\u0005d\u0000\u0000\u0165\u0166\u0005o\u0000\u0000" + + "\u0166\u0167\u0005u\u0000\u0000\u0167\u0168\u0005b\u0000\u0000\u0168\u0169" + + "\u0005l\u0000\u0000\u0169\u016a\u0005e\u0000\u0000\u016a\u001c\u0001\u0000" + + "\u0000\u0000\u016b\u016c\u0005e\u0000\u0000\u016c\u016d\u0005l\u0000\u0000" + + "\u016d\u016e\u0005s\u0000\u0000\u016e\u016f\u0005e\u0000\u0000\u016f\u001e" + + "\u0001\u0000\u0000\u0000\u0170\u0171\u0005e\u0000\u0000\u0171\u0172\u0005" + + "n\u0000\u0000\u0172\u0173\u0005u\u0000\u0000\u0173\u0174\u0005m\u0000" + + "\u0000\u0174 \u0001\u0000\u0000\u0000\u0175\u0176\u0005e\u0000\u0000\u0176" + + "\u0177\u0005x\u0000\u0000\u0177\u0178\u0005t\u0000\u0000\u0178\u0179\u0005" + + "e\u0000\u0000\u0179\u017a\u0005n\u0000\u0000\u017a\u017b\u0005d\u0000" + + "\u0000\u017b\u017c\u0005s\u0000\u0000\u017c\"\u0001\u0000\u0000\u0000" + + "\u017d\u017e\u0005f\u0000\u0000\u017e\u017f\u0005i\u0000\u0000\u017f\u0180" + + "\u0005n\u0000\u0000\u0180\u0181\u0005a\u0000\u0000\u0181\u0182\u0005l" + + "\u0000\u0000\u0182$\u0001\u0000\u0000\u0000\u0183\u0184\u0005f\u0000\u0000" + + "\u0184\u0185\u0005i\u0000\u0000\u0185\u0186\u0005n\u0000\u0000\u0186\u0187" + + "\u0005a\u0000\u0000\u0187\u0188\u0005l\u0000\u0000\u0188\u0189\u0005l" + + "\u0000\u0000\u0189\u018a\u0005y\u0000\u0000\u018a&\u0001\u0000\u0000\u0000" + + "\u018b\u018c\u0005f\u0000\u0000\u018c\u018d\u0005l\u0000\u0000\u018d\u018e" + + "\u0005o\u0000\u0000\u018e\u018f\u0005a\u0000\u0000\u018f\u0190\u0005t" + + "\u0000\u0000\u0190(\u0001\u0000\u0000\u0000\u0191\u0192\u0005f\u0000\u0000" + + "\u0192\u0193\u0005o\u0000\u0000\u0193\u0194\u0005r\u0000\u0000\u0194*" + + "\u0001\u0000\u0000\u0000\u0195\u0196\u0005i\u0000\u0000\u0196\u0197\u0005" + + "f\u0000\u0000\u0197,\u0001\u0000\u0000\u0000\u0198\u0199\u0005g\u0000" + + "\u0000\u0199\u019a\u0005o\u0000\u0000\u019a\u019b\u0005t\u0000\u0000\u019b" + + "\u019c\u0005o\u0000\u0000\u019c.\u0001\u0000\u0000\u0000\u019d\u019e\u0005" + + "i\u0000\u0000\u019e\u019f\u0005m\u0000\u0000\u019f\u01a0\u0005p\u0000" + + "\u0000\u01a0\u01a1\u0005l\u0000\u0000\u01a1\u01a2\u0005e\u0000\u0000\u01a2" + + "\u01a3\u0005m\u0000\u0000\u01a3\u01a4\u0005e\u0000\u0000\u01a4\u01a5\u0005" + + "n\u0000\u0000\u01a5\u01a6\u0005t\u0000\u0000\u01a6\u01a7\u0005s\u0000" + + "\u0000\u01a70\u0001\u0000\u0000\u0000\u01a8\u01a9\u0005i\u0000\u0000\u01a9" + + "\u01aa\u0005m\u0000\u0000\u01aa\u01ab\u0005p\u0000\u0000\u01ab\u01ac\u0005" + + "o\u0000\u0000\u01ac\u01ad\u0005r\u0000\u0000\u01ad\u01ae\u0005t\u0000" + + "\u0000\u01ae2\u0001\u0000\u0000\u0000\u01af\u01b0\u0005i\u0000\u0000\u01b0" + + "\u01b1\u0005n\u0000\u0000\u01b1\u01b2\u0005s\u0000\u0000\u01b2\u01b3\u0005" + + "t\u0000\u0000\u01b3\u01b4\u0005a\u0000\u0000\u01b4\u01b5\u0005n\u0000" + + "\u0000\u01b5\u01b6\u0005c\u0000\u0000\u01b6\u01b7\u0005e\u0000\u0000\u01b7" + + "\u01b8\u0005o\u0000\u0000\u01b8\u01b9\u0005f\u0000\u0000\u01b94\u0001" + + "\u0000\u0000\u0000\u01ba\u01bb\u0005i\u0000\u0000\u01bb\u01bc\u0005n\u0000" + + "\u0000\u01bc\u01bd\u0005t\u0000\u0000\u01bd6\u0001\u0000\u0000\u0000\u01be" + + "\u01bf\u0005i\u0000\u0000\u01bf\u01c0\u0005n\u0000\u0000\u01c0\u01c1\u0005" + + "t\u0000\u0000\u01c1\u01c2\u0005e\u0000\u0000\u01c2\u01c3\u0005r\u0000" + + "\u0000\u01c3\u01c4\u0005f\u0000\u0000\u01c4\u01c5\u0005a\u0000\u0000\u01c5" + + "\u01c6\u0005c\u0000\u0000\u01c6\u01c7\u0005e\u0000\u0000\u01c78\u0001" + + "\u0000\u0000\u0000\u01c8\u01c9\u0005l\u0000\u0000\u01c9\u01ca\u0005o\u0000" + + "\u0000\u01ca\u01cb\u0005n\u0000\u0000\u01cb\u01cc\u0005g\u0000\u0000\u01cc" + + ":\u0001\u0000\u0000\u0000\u01cd\u01ce\u0005n\u0000\u0000\u01ce\u01cf\u0005" + + "a\u0000\u0000\u01cf\u01d0\u0005t\u0000\u0000\u01d0\u01d1\u0005i\u0000" + + "\u0000\u01d1\u01d2\u0005v\u0000\u0000\u01d2\u01d3\u0005e\u0000\u0000\u01d3" + + "<\u0001\u0000\u0000\u0000\u01d4\u01d5\u0005n\u0000\u0000\u01d5\u01d6\u0005" + + "e\u0000\u0000\u01d6\u01d7\u0005w\u0000\u0000\u01d7>\u0001\u0000\u0000" + + "\u0000\u01d8\u01d9\u0005p\u0000\u0000\u01d9\u01da\u0005a\u0000\u0000\u01da" + + "\u01db\u0005c\u0000\u0000\u01db\u01dc\u0005k\u0000\u0000\u01dc\u01dd\u0005" + + "a\u0000\u0000\u01dd\u01de\u0005g\u0000\u0000\u01de\u01df\u0005e\u0000" + + "\u0000\u01df@\u0001\u0000\u0000\u0000\u01e0\u01e1\u0005p\u0000\u0000\u01e1" + + "\u01e2\u0005r\u0000\u0000\u01e2\u01e3\u0005i\u0000\u0000\u01e3\u01e4\u0005" + + "v\u0000\u0000\u01e4\u01e5\u0005a\u0000\u0000\u01e5\u01e6\u0005t\u0000" + + "\u0000\u01e6\u01e7\u0005e\u0000\u0000\u01e7B\u0001\u0000\u0000\u0000\u01e8" + + "\u01e9\u0005p\u0000\u0000\u01e9\u01ea\u0005r\u0000\u0000\u01ea\u01eb\u0005" + + "o\u0000\u0000\u01eb\u01ec\u0005t\u0000\u0000\u01ec\u01ed\u0005e\u0000" + + "\u0000\u01ed\u01ee\u0005c\u0000\u0000\u01ee\u01ef\u0005t\u0000\u0000\u01ef" + + "\u01f0\u0005e\u0000\u0000\u01f0\u01f1\u0005d\u0000\u0000\u01f1D\u0001" + + "\u0000\u0000\u0000\u01f2\u01f3\u0005p\u0000\u0000\u01f3\u01f4\u0005u\u0000" + + "\u0000\u01f4\u01f5\u0005b\u0000\u0000\u01f5\u01f6\u0005l\u0000\u0000\u01f6" + + "\u01f7\u0005i\u0000\u0000\u01f7\u01f8\u0005c\u0000\u0000\u01f8F\u0001" + + "\u0000\u0000\u0000\u01f9\u01fa\u0005r\u0000\u0000\u01fa\u01fb\u0005e\u0000" + + "\u0000\u01fb\u01fc\u0005t\u0000\u0000\u01fc\u01fd\u0005u\u0000\u0000\u01fd" + + "\u01fe\u0005r\u0000\u0000\u01fe\u01ff\u0005n\u0000\u0000\u01ffH\u0001" + + "\u0000\u0000\u0000\u0200\u0201\u0005s\u0000\u0000\u0201\u0202\u0005h\u0000" + + "\u0000\u0202\u0203\u0005o\u0000\u0000\u0203\u0204\u0005r\u0000\u0000\u0204" + + "\u0205\u0005t\u0000\u0000\u0205J\u0001\u0000\u0000\u0000\u0206\u0207\u0005" + + "s\u0000\u0000\u0207\u0208\u0005t\u0000\u0000\u0208\u0209\u0005a\u0000" + + "\u0000\u0209\u020a\u0005t\u0000\u0000\u020a\u020b\u0005i\u0000\u0000\u020b" + + "\u020c\u0005c\u0000\u0000\u020cL\u0001\u0000\u0000\u0000\u020d\u020e\u0005" + + "s\u0000\u0000\u020e\u020f\u0005t\u0000\u0000\u020f\u0210\u0005r\u0000" + + "\u0000\u0210\u0211\u0005i\u0000\u0000\u0211\u0212\u0005c\u0000\u0000\u0212" + + "\u0213\u0005t\u0000\u0000\u0213\u0214\u0005f\u0000\u0000\u0214\u0215\u0005" + + "p\u0000\u0000\u0215N\u0001\u0000\u0000\u0000\u0216\u0217\u0005s\u0000" + + "\u0000\u0217\u0218\u0005u\u0000\u0000\u0218\u0219\u0005p\u0000\u0000\u0219" + + "\u021a\u0005e\u0000\u0000\u021a\u021b\u0005r\u0000\u0000\u021bP\u0001" + + "\u0000\u0000\u0000\u021c\u021d\u0005s\u0000\u0000\u021d\u021e\u0005w\u0000" + + "\u0000\u021e\u021f\u0005i\u0000\u0000\u021f\u0220\u0005t\u0000\u0000\u0220" + + "\u0221\u0005c\u0000\u0000\u0221\u0222\u0005h\u0000\u0000\u0222R\u0001" + + "\u0000\u0000\u0000\u0223\u0224\u0005s\u0000\u0000\u0224\u0225\u0005y\u0000" + + "\u0000\u0225\u0226\u0005n\u0000\u0000\u0226\u0227\u0005c\u0000\u0000\u0227" + + "\u0228\u0005h\u0000\u0000\u0228\u0229\u0005r\u0000\u0000\u0229\u022a\u0005" + + "o\u0000\u0000\u022a\u022b\u0005n\u0000\u0000\u022b\u022c\u0005i\u0000" + + "\u0000\u022c\u022d\u0005z\u0000\u0000\u022d\u022e\u0005e\u0000\u0000\u022e" + + "\u022f\u0005d\u0000\u0000\u022fT\u0001\u0000\u0000\u0000\u0230\u0231\u0005" + + "t\u0000\u0000\u0231\u0232\u0005h\u0000\u0000\u0232\u0233\u0005i\u0000" + + "\u0000\u0233\u0234\u0005s\u0000\u0000\u0234V\u0001\u0000\u0000\u0000\u0235" + + "\u0236\u0005t\u0000\u0000\u0236\u0237\u0005h\u0000\u0000\u0237\u0238\u0005" + + "r\u0000\u0000\u0238\u0239\u0005o\u0000\u0000\u0239\u023a\u0005w\u0000" + + "\u0000\u023aX\u0001\u0000\u0000\u0000\u023b\u023c\u0005t\u0000\u0000\u023c" + + "\u023d\u0005h\u0000\u0000\u023d\u023e\u0005r\u0000\u0000\u023e\u023f\u0005" + + "o\u0000\u0000\u023f\u0240\u0005w\u0000\u0000\u0240\u0241\u0005s\u0000" + + "\u0000\u0241Z\u0001\u0000\u0000\u0000\u0242\u0243\u0005t\u0000\u0000\u0243" + + "\u0244\u0005r\u0000\u0000\u0244\u0245\u0005a\u0000\u0000\u0245\u0246\u0005" + + "n\u0000\u0000\u0246\u0247\u0005s\u0000\u0000\u0247\u0248\u0005i\u0000" + + "\u0000\u0248\u0249\u0005e\u0000\u0000\u0249\u024a\u0005n\u0000\u0000\u024a" + + "\u024b\u0005t\u0000\u0000\u024b\\\u0001\u0000\u0000\u0000\u024c\u024d" + + "\u0005t\u0000\u0000\u024d\u024e\u0005r\u0000\u0000\u024e\u024f\u0005y" + + "\u0000\u0000\u024f^\u0001\u0000\u0000\u0000\u0250\u0251\u0005v\u0000\u0000" + + "\u0251\u0252\u0005o\u0000\u0000\u0252\u0253\u0005i\u0000\u0000\u0253\u0254" + + "\u0005d\u0000\u0000\u0254`\u0001\u0000\u0000\u0000\u0255\u0256\u0005v" + + "\u0000\u0000\u0256\u0257\u0005o\u0000\u0000\u0257\u0258\u0005l\u0000\u0000" + + "\u0258\u0259\u0005a\u0000\u0000\u0259\u025a\u0005t\u0000\u0000\u025a\u025b" + + "\u0005i\u0000\u0000\u025b\u025c\u0005l\u0000\u0000\u025c\u025d\u0005e" + + "\u0000\u0000\u025db\u0001\u0000\u0000\u0000\u025e\u025f\u0005w\u0000\u0000" + + "\u025f\u0260\u0005h\u0000\u0000\u0260\u0261\u0005i\u0000\u0000\u0261\u0262" + + "\u0005l\u0000\u0000\u0262\u0263\u0005e\u0000\u0000\u0263d\u0001\u0000" + + "\u0000\u0000\u0264\u0265\u0005m\u0000\u0000\u0265\u0266\u0005o\u0000\u0000" + + "\u0266\u0267\u0005d\u0000\u0000\u0267\u0268\u0005u\u0000\u0000\u0268\u0269" + + "\u0005l\u0000\u0000\u0269\u026a\u0005e\u0000\u0000\u026af\u0001\u0000" + + "\u0000\u0000\u026b\u026c\u0005o\u0000\u0000\u026c\u026d\u0005p\u0000\u0000" + + "\u026d\u026e\u0005e\u0000\u0000\u026e\u026f\u0005n\u0000\u0000\u026fh" + + "\u0001\u0000\u0000\u0000\u0270\u0271\u0005r\u0000\u0000\u0271\u0272\u0005" + + "e\u0000\u0000\u0272\u0273\u0005q\u0000\u0000\u0273\u0274\u0005u\u0000" + + "\u0000\u0274\u0275\u0005i\u0000\u0000\u0275\u0276\u0005r\u0000\u0000\u0276" + + "\u0277\u0005e\u0000\u0000\u0277\u0278\u0005s\u0000\u0000\u0278j\u0001" + + "\u0000\u0000\u0000\u0279\u027a\u0005e\u0000\u0000\u027a\u027b\u0005x\u0000" + + "\u0000\u027b\u027c\u0005p\u0000\u0000\u027c\u027d\u0005o\u0000\u0000\u027d" + + "\u027e\u0005r\u0000\u0000\u027e\u027f\u0005t\u0000\u0000\u027f\u0280\u0005" + + "s\u0000\u0000\u0280l\u0001\u0000\u0000\u0000\u0281\u0282\u0005o\u0000" + + "\u0000\u0282\u0283\u0005p\u0000\u0000\u0283\u0284\u0005e\u0000\u0000\u0284" + + "\u0285\u0005n\u0000\u0000\u0285\u0286\u0005s\u0000\u0000\u0286n\u0001" + + "\u0000\u0000\u0000\u0287\u0288\u0005t\u0000\u0000\u0288\u0289\u0005o\u0000" + + "\u0000\u0289p\u0001\u0000\u0000\u0000\u028a\u028b\u0005u\u0000\u0000\u028b" + + "\u028c\u0005s\u0000\u0000\u028c\u028d\u0005e\u0000\u0000\u028d\u028e\u0005" + + "s\u0000\u0000\u028er\u0001\u0000\u0000\u0000\u028f\u0290\u0005p\u0000" + + "\u0000\u0290\u0291\u0005r\u0000\u0000\u0291\u0292\u0005o\u0000\u0000\u0292" + + "\u0293\u0005v\u0000\u0000\u0293\u0294\u0005i\u0000\u0000\u0294\u0295\u0005" + + "d\u0000\u0000\u0295\u0296\u0005e\u0000\u0000\u0296\u0297\u0005s\u0000" + + "\u0000\u0297t\u0001\u0000\u0000\u0000\u0298\u0299\u0005w\u0000\u0000\u0299" + + "\u029a\u0005i\u0000\u0000\u029a\u029b\u0005t\u0000\u0000\u029b\u029c\u0005" + + "h\u0000\u0000\u029cv\u0001\u0000\u0000\u0000\u029d\u029e\u0005t\u0000" + + "\u0000\u029e\u029f\u0005r\u0000\u0000\u029f\u02a0\u0005a\u0000\u0000\u02a0" + + "\u02a1\u0005n\u0000\u0000\u02a1\u02a2\u0005s\u0000\u0000\u02a2\u02a3\u0005" + + "i\u0000\u0000\u02a3\u02a4\u0005t\u0000\u0000\u02a4\u02a5\u0005i\u0000" + + "\u0000\u02a5\u02a6\u0005v\u0000\u0000\u02a6\u02a7\u0005e\u0000\u0000\u02a7" + + "x\u0001\u0000\u0000\u0000\u02a8\u02a9\u0005v\u0000\u0000\u02a9\u02aa\u0005" + + "a\u0000\u0000\u02aa\u02ab\u0005r\u0000\u0000\u02abz\u0001\u0000\u0000" + + "\u0000\u02ac\u02ad\u0005y\u0000\u0000\u02ad\u02ae\u0005i\u0000\u0000\u02ae" + + "\u02af\u0005e\u0000\u0000\u02af\u02b0\u0005l\u0000\u0000\u02b0\u02b1\u0005" + + "d\u0000\u0000\u02b1|\u0001\u0000\u0000\u0000\u02b2\u02b3\u0005r\u0000" + + "\u0000\u02b3\u02b4\u0005e\u0000\u0000\u02b4\u02b5\u0005c\u0000\u0000\u02b5" + + "\u02b6\u0005o\u0000\u0000\u02b6\u02b7\u0005r\u0000\u0000\u02b7\u02b8\u0005" + + "d\u0000\u0000\u02b8~\u0001\u0000\u0000\u0000\u02b9\u02ba\u0005s\u0000" + + "\u0000\u02ba\u02bb\u0005e\u0000\u0000\u02bb\u02bc\u0005a\u0000\u0000\u02bc" + + "\u02bd\u0005l\u0000\u0000\u02bd\u02be\u0005e\u0000\u0000\u02be\u02bf\u0005" + + "d\u0000\u0000\u02bf\u0080\u0001\u0000\u0000\u0000\u02c0\u02c1\u0005p\u0000" + + "\u0000\u02c1\u02c2\u0005e\u0000\u0000\u02c2\u02c3\u0005r\u0000\u0000\u02c3" + + "\u02c4\u0005m\u0000\u0000\u02c4\u02c5\u0005i\u0000\u0000\u02c5\u02c6\u0005" + + "t\u0000\u0000\u02c6\u02c7\u0005s\u0000\u0000\u02c7\u0082\u0001\u0000\u0000" + + "\u0000\u02c8\u02c9\u0005n\u0000\u0000\u02c9\u02ca\u0005o\u0000\u0000\u02ca" + + "\u02cb\u0005n\u0000\u0000\u02cb\u02cc\u0005-\u0000\u0000\u02cc\u02cd\u0005" + + "s\u0000\u0000\u02cd\u02ce\u0005e\u0000\u0000\u02ce\u02cf\u0005a\u0000" + + "\u0000\u02cf\u02d0\u0005l\u0000\u0000\u02d0\u02d1\u0005e\u0000\u0000\u02d1" + + "\u02d2\u0005d\u0000\u0000\u02d2\u0084\u0001\u0000\u0000\u0000\u02d3\u02e1" + + "\u00050\u0000\u0000\u02d4\u02de\u0007\u0000\u0000\u0000\u02d5\u02d7\u0003" + + "\u010b\u0085\u0000\u02d6\u02d5\u0001\u0000\u0000\u0000\u02d6\u02d7\u0001" + + "\u0000\u0000\u0000\u02d7\u02df\u0001\u0000\u0000\u0000\u02d8\u02da\u0005" + + "_\u0000\u0000\u02d9\u02d8\u0001\u0000\u0000\u0000\u02da\u02db\u0001\u0000" + + "\u0000\u0000\u02db\u02d9\u0001\u0000\u0000\u0000\u02db\u02dc\u0001\u0000" + + "\u0000\u0000\u02dc\u02dd\u0001\u0000\u0000\u0000\u02dd\u02df\u0003\u010b" + + "\u0085\u0000\u02de\u02d6\u0001\u0000\u0000\u0000\u02de\u02d9\u0001\u0000" + + "\u0000\u0000\u02df\u02e1\u0001\u0000\u0000\u0000\u02e0\u02d3\u0001\u0000" + + "\u0000\u0000\u02e0\u02d4\u0001\u0000\u0000\u0000\u02e1\u02e3\u0001\u0000" + + "\u0000\u0000\u02e2\u02e4\u0007\u0001\u0000\u0000\u02e3\u02e2\u0001\u0000" + + "\u0000\u0000\u02e3\u02e4\u0001\u0000\u0000\u0000\u02e4\u0086\u0001\u0000" + + "\u0000\u0000\u02e5\u02e6\u00050\u0000\u0000\u02e6\u02e7\u0007\u0002\u0000" + + "\u0000\u02e7\u02ef\u0007\u0003\u0000\u0000\u02e8\u02ea\u0007\u0004\u0000" + + "\u0000\u02e9\u02e8\u0001\u0000\u0000\u0000\u02ea\u02ed\u0001\u0000\u0000" + + "\u0000\u02eb\u02e9\u0001\u0000\u0000\u0000\u02eb\u02ec\u0001\u0000\u0000" + + "\u0000\u02ec\u02ee\u0001\u0000\u0000\u0000\u02ed\u02eb\u0001\u0000\u0000" + + "\u0000\u02ee\u02f0\u0007\u0003\u0000\u0000\u02ef\u02eb\u0001\u0000\u0000" + + "\u0000\u02ef\u02f0\u0001\u0000\u0000\u0000\u02f0\u02f2\u0001\u0000\u0000" + + "\u0000\u02f1\u02f3\u0007\u0001\u0000\u0000\u02f2\u02f1\u0001\u0000\u0000" + + "\u0000\u02f2\u02f3\u0001\u0000\u0000\u0000\u02f3\u0088\u0001\u0000\u0000" + + "\u0000\u02f4\u02f8\u00050\u0000\u0000\u02f5\u02f7\u0005_\u0000\u0000\u02f6" + + "\u02f5\u0001\u0000\u0000\u0000\u02f7\u02fa\u0001\u0000\u0000\u0000\u02f8" + + "\u02f6\u0001\u0000\u0000\u0000\u02f8\u02f9\u0001\u0000\u0000\u0000\u02f9" + + "\u02fb\u0001\u0000\u0000\u0000\u02fa\u02f8\u0001\u0000\u0000\u0000\u02fb" + + "\u0303\u0007\u0005\u0000\u0000\u02fc\u02fe\u0007\u0006\u0000\u0000\u02fd" + + "\u02fc\u0001\u0000\u0000\u0000\u02fe\u0301\u0001\u0000\u0000\u0000\u02ff" + + "\u02fd\u0001\u0000\u0000\u0000\u02ff\u0300\u0001\u0000\u0000\u0000\u0300" + + "\u0302\u0001\u0000\u0000\u0000\u0301\u02ff\u0001\u0000\u0000\u0000\u0302" + + "\u0304\u0007\u0005\u0000\u0000\u0303\u02ff\u0001\u0000\u0000\u0000\u0303" + + "\u0304\u0001\u0000\u0000\u0000\u0304\u0306\u0001\u0000\u0000\u0000\u0305" + + "\u0307\u0007\u0001\u0000\u0000\u0306\u0305\u0001\u0000\u0000\u0000\u0306" + + "\u0307\u0001\u0000\u0000\u0000\u0307\u008a\u0001\u0000\u0000\u0000\u0308" + + "\u0309\u00050\u0000\u0000\u0309\u030a\u0007\u0007\u0000\u0000\u030a\u0312" + + "\u0007\b\u0000\u0000\u030b\u030d\u0007\t\u0000\u0000\u030c\u030b\u0001" + + "\u0000\u0000\u0000\u030d\u0310\u0001\u0000\u0000\u0000\u030e\u030c\u0001" + + "\u0000\u0000\u0000\u030e\u030f\u0001\u0000\u0000\u0000\u030f\u0311\u0001" + + "\u0000\u0000\u0000\u0310\u030e\u0001\u0000\u0000\u0000\u0311\u0313\u0007" + + "\b\u0000\u0000\u0312\u030e\u0001\u0000\u0000\u0000\u0312\u0313\u0001\u0000" + + "\u0000\u0000\u0313\u0315\u0001\u0000\u0000\u0000\u0314\u0316\u0007\u0001" + + "\u0000\u0000\u0315\u0314\u0001\u0000\u0000\u0000\u0315\u0316\u0001\u0000" + + "\u0000\u0000\u0316\u008c\u0001\u0000\u0000\u0000\u0317\u0318\u0003\u010b" + + "\u0085\u0000\u0318\u031a\u0005.\u0000\u0000\u0319\u031b\u0003\u010b\u0085" + + "\u0000\u031a\u0319\u0001\u0000\u0000\u0000\u031a\u031b\u0001\u0000\u0000" + + "\u0000\u031b\u031f\u0001\u0000\u0000\u0000\u031c\u031d\u0005.\u0000\u0000" + + "\u031d\u031f\u0003\u010b\u0085\u0000\u031e\u0317\u0001\u0000\u0000\u0000" + + "\u031e\u031c\u0001\u0000\u0000\u0000\u031f\u0321\u0001\u0000\u0000\u0000" + + "\u0320\u0322\u0003\u0103\u0081\u0000\u0321\u0320\u0001\u0000\u0000\u0000" + + "\u0321\u0322\u0001\u0000\u0000\u0000\u0322\u0324\u0001\u0000\u0000\u0000" + + "\u0323\u0325\u0007\n\u0000\u0000\u0324\u0323\u0001\u0000\u0000\u0000\u0324" + + "\u0325\u0001\u0000\u0000\u0000\u0325\u032f\u0001\u0000\u0000\u0000\u0326" + + "\u032c\u0003\u010b\u0085\u0000\u0327\u0329\u0003\u0103\u0081\u0000\u0328" + + "\u032a\u0007\n\u0000\u0000\u0329\u0328\u0001\u0000\u0000\u0000\u0329\u032a" + + "\u0001\u0000\u0000\u0000\u032a\u032d\u0001\u0000\u0000\u0000\u032b\u032d" + + "\u0007\n\u0000\u0000\u032c\u0327\u0001\u0000\u0000\u0000\u032c\u032b\u0001" + + "\u0000\u0000\u0000\u032d\u032f\u0001\u0000\u0000\u0000\u032e\u031e\u0001" + + "\u0000\u0000\u0000\u032e\u0326\u0001\u0000\u0000\u0000\u032f\u008e\u0001" + + "\u0000\u0000\u0000\u0330\u0331\u00050\u0000\u0000\u0331\u033b\u0007\u0002" + + "\u0000\u0000\u0332\u0334\u0003\u0107\u0083\u0000\u0333\u0335\u0005.\u0000" + + "\u0000\u0334\u0333\u0001\u0000\u0000\u0000\u0334\u0335\u0001\u0000\u0000" + + "\u0000\u0335\u033c\u0001\u0000\u0000\u0000\u0336\u0338\u0003\u0107\u0083" + + "\u0000\u0337\u0336\u0001\u0000\u0000\u0000\u0337\u0338\u0001\u0000\u0000" + + "\u0000\u0338\u0339\u0001\u0000\u0000\u0000\u0339\u033a\u0005.\u0000\u0000" + + "\u033a\u033c\u0003\u0107\u0083\u0000\u033b\u0332\u0001\u0000\u0000\u0000" + + "\u033b\u0337\u0001\u0000\u0000\u0000\u033c\u033d\u0001\u0000\u0000\u0000" + + "\u033d\u033f\u0007\u000b\u0000\u0000\u033e\u0340\u0007\f\u0000\u0000\u033f" + + "\u033e\u0001\u0000\u0000\u0000\u033f\u0340\u0001\u0000\u0000\u0000\u0340" + + "\u0341\u0001\u0000\u0000\u0000\u0341\u0343\u0003\u010b\u0085\u0000\u0342" + + "\u0344\u0007\n\u0000\u0000\u0343\u0342\u0001\u0000\u0000\u0000\u0343\u0344" + + "\u0001\u0000\u0000\u0000\u0344\u0090\u0001\u0000\u0000\u0000\u0345\u0346" + + "\u0005t\u0000\u0000\u0346\u0347\u0005r\u0000\u0000\u0347\u0348\u0005u" + + "\u0000\u0000\u0348\u034f\u0005e\u0000\u0000\u0349\u034a\u0005f\u0000\u0000" + + "\u034a\u034b\u0005a\u0000\u0000\u034b\u034c\u0005l\u0000\u0000\u034c\u034d" + + "\u0005s\u0000\u0000\u034d\u034f\u0005e\u0000\u0000\u034e\u0345\u0001\u0000" + + "\u0000\u0000\u034e\u0349\u0001\u0000\u0000\u0000\u034f\u0092\u0001\u0000" + + "\u0000\u0000\u0350\u0353\u0005\'\u0000\u0000\u0351\u0354\b\r\u0000\u0000" + + "\u0352\u0354\u0003\u0105\u0082\u0000\u0353\u0351\u0001\u0000\u0000\u0000" + + "\u0353\u0352\u0001\u0000\u0000\u0000\u0354\u0355\u0001\u0000\u0000\u0000" + + "\u0355\u0356\u0005\'\u0000\u0000\u0356\u0094\u0001\u0000\u0000\u0000\u0357" + + "\u035c\u0005\"\u0000\u0000\u0358\u035b\b\u000e\u0000\u0000\u0359\u035b" + + "\u0003\u0105\u0082\u0000\u035a\u0358\u0001\u0000\u0000\u0000\u035a\u0359" + + "\u0001\u0000\u0000\u0000\u035b\u035e\u0001\u0000\u0000\u0000\u035c\u035a" + + "\u0001\u0000\u0000\u0000\u035c\u035d\u0001\u0000\u0000\u0000\u035d\u035f" + + "\u0001\u0000\u0000\u0000\u035e\u035c\u0001\u0000\u0000\u0000\u035f\u0360" + + "\u0005\"\u0000\u0000\u0360\u0096\u0001\u0000\u0000\u0000\u0361\u0362\u0005" + + "\"\u0000\u0000\u0362\u0363\u0005\"\u0000\u0000\u0363\u0364\u0005\"\u0000" + + "\u0000\u0364\u0368\u0001\u0000\u0000\u0000\u0365\u0367\u0007\u000f\u0000" + + "\u0000\u0366\u0365\u0001\u0000\u0000\u0000\u0367\u036a\u0001\u0000\u0000" + + "\u0000\u0368\u0366\u0001\u0000\u0000\u0000\u0368\u0369\u0001\u0000\u0000" + + "\u0000\u0369\u036b\u0001\u0000\u0000\u0000\u036a\u0368\u0001\u0000\u0000" + + "\u0000\u036b\u0370\u0007\u0010\u0000\u0000\u036c\u036f\t\u0000\u0000\u0000" + + "\u036d\u036f\u0003\u0105\u0082\u0000\u036e\u036c\u0001\u0000\u0000\u0000" + + "\u036e\u036d\u0001\u0000\u0000\u0000\u036f\u0372\u0001\u0000\u0000\u0000" + + "\u0370\u0371\u0001\u0000\u0000\u0000\u0370\u036e\u0001\u0000\u0000\u0000" + + "\u0371\u0373\u0001\u0000\u0000\u0000\u0372\u0370\u0001\u0000\u0000\u0000" + + "\u0373\u0374\u0005\"\u0000\u0000\u0374\u0375\u0005\"\u0000\u0000\u0375" + + "\u0376\u0005\"\u0000\u0000\u0376\u0098\u0001\u0000\u0000\u0000\u0377\u0378" + + "\u0005n\u0000\u0000\u0378\u0379\u0005u\u0000\u0000\u0379\u037a\u0005l" + + "\u0000\u0000\u037a\u037b\u0005l\u0000\u0000\u037b\u009a\u0001\u0000\u0000" + + "\u0000\u037c\u037d\u0005(\u0000\u0000\u037d\u009c\u0001\u0000\u0000\u0000" + + "\u037e\u037f\u0005)\u0000\u0000\u037f\u009e\u0001\u0000\u0000\u0000\u0380" + + "\u0381\u0005{\u0000\u0000\u0381\u00a0\u0001\u0000\u0000\u0000\u0382\u0383" + + "\u0005}\u0000\u0000\u0383\u00a2\u0001\u0000\u0000\u0000\u0384\u0385\u0005" + + "[\u0000\u0000\u0385\u00a4\u0001\u0000\u0000\u0000\u0386\u0387\u0005]\u0000" + + "\u0000\u0387\u00a6\u0001\u0000\u0000\u0000\u0388\u0389\u0005;\u0000\u0000" + + "\u0389\u00a8\u0001\u0000\u0000\u0000\u038a\u038b\u0005,\u0000\u0000\u038b" + + "\u00aa\u0001\u0000\u0000\u0000\u038c\u038d\u0005.\u0000\u0000\u038d\u00ac" + + "\u0001\u0000\u0000\u0000\u038e\u038f\u0005=\u0000\u0000\u038f\u00ae\u0001" + + "\u0000\u0000\u0000\u0390\u0391\u0005>\u0000\u0000\u0391\u00b0\u0001\u0000" + + "\u0000\u0000\u0392\u0393\u0005<\u0000\u0000\u0393\u00b2\u0001\u0000\u0000" + + "\u0000\u0394\u0395\u0005!\u0000\u0000\u0395\u00b4\u0001\u0000\u0000\u0000" + + "\u0396\u0397\u0005~\u0000\u0000\u0397\u00b6\u0001\u0000\u0000\u0000\u0398" + + "\u0399\u0005?\u0000\u0000\u0399\u00b8\u0001\u0000\u0000\u0000\u039a\u039b" + + "\u0005:\u0000\u0000\u039b\u00ba\u0001\u0000\u0000\u0000\u039c\u039d\u0005" + + "=\u0000\u0000\u039d\u039e\u0005=\u0000\u0000\u039e\u00bc\u0001\u0000\u0000" + + "\u0000\u039f\u03a0\u0005<\u0000\u0000\u03a0\u03a1\u0005=\u0000\u0000\u03a1" + + "\u00be\u0001\u0000\u0000\u0000\u03a2\u03a3\u0005>\u0000\u0000\u03a3\u03a4" + + "\u0005=\u0000\u0000\u03a4\u00c0\u0001\u0000\u0000\u0000\u03a5\u03a6\u0005" + + "!\u0000\u0000\u03a6\u03a7\u0005=\u0000\u0000\u03a7\u00c2\u0001\u0000\u0000" + + "\u0000\u03a8\u03a9\u0005&\u0000\u0000\u03a9\u03aa\u0005&\u0000\u0000\u03aa" + + "\u00c4\u0001\u0000\u0000\u0000\u03ab\u03ac\u0005|\u0000\u0000\u03ac\u03ad" + + "\u0005|\u0000\u0000\u03ad\u00c6\u0001\u0000\u0000\u0000\u03ae\u03af\u0005" + + "+\u0000\u0000\u03af\u03b0\u0005+\u0000\u0000\u03b0\u00c8\u0001\u0000\u0000" + + "\u0000\u03b1\u03b2\u0005-\u0000\u0000\u03b2\u03b3\u0005-\u0000\u0000\u03b3" + + "\u00ca\u0001\u0000\u0000\u0000\u03b4\u03b5\u0005+\u0000\u0000\u03b5\u00cc" + + "\u0001\u0000\u0000\u0000\u03b6\u03b7\u0005-\u0000\u0000\u03b7\u00ce\u0001" + + "\u0000\u0000\u0000\u03b8\u03b9\u0005*\u0000\u0000\u03b9\u00d0\u0001\u0000" + + "\u0000\u0000\u03ba\u03bb\u0005/\u0000\u0000\u03bb\u00d2\u0001\u0000\u0000" + + "\u0000\u03bc\u03bd\u0005&\u0000\u0000\u03bd\u00d4\u0001\u0000\u0000\u0000" + + "\u03be\u03bf\u0005|\u0000\u0000\u03bf\u00d6\u0001\u0000\u0000\u0000\u03c0" + + "\u03c1\u0005^\u0000\u0000\u03c1\u00d8\u0001\u0000\u0000\u0000\u03c2\u03c3" + + "\u0005%\u0000\u0000\u03c3\u00da\u0001\u0000\u0000\u0000\u03c4\u03c5\u0005" + + "+\u0000\u0000\u03c5\u03c6\u0005=\u0000\u0000\u03c6\u00dc\u0001\u0000\u0000" + + "\u0000\u03c7\u03c8\u0005-\u0000\u0000\u03c8\u03c9\u0005=\u0000\u0000\u03c9" + + "\u00de\u0001\u0000\u0000\u0000\u03ca\u03cb\u0005*\u0000\u0000\u03cb\u03cc" + + "\u0005=\u0000\u0000\u03cc\u00e0\u0001\u0000\u0000\u0000\u03cd\u03ce\u0005" + + "/\u0000\u0000\u03ce\u03cf\u0005=\u0000\u0000\u03cf\u00e2\u0001\u0000\u0000" + + "\u0000\u03d0\u03d1\u0005&\u0000\u0000\u03d1\u03d2\u0005=\u0000\u0000\u03d2" + + "\u00e4\u0001\u0000\u0000\u0000\u03d3\u03d4\u0005|\u0000\u0000\u03d4\u03d5" + + "\u0005=\u0000\u0000\u03d5\u00e6\u0001\u0000\u0000\u0000\u03d6\u03d7\u0005" + + "^\u0000\u0000\u03d7\u03d8\u0005=\u0000\u0000\u03d8\u00e8\u0001\u0000\u0000" + + "\u0000\u03d9\u03da\u0005%\u0000\u0000\u03da\u03db\u0005=\u0000\u0000\u03db" + + "\u00ea\u0001\u0000\u0000\u0000\u03dc\u03dd\u0005<\u0000\u0000\u03dd\u03de" + + "\u0005<\u0000\u0000\u03de\u03df\u0005=\u0000\u0000\u03df\u00ec\u0001\u0000" + + "\u0000\u0000\u03e0\u03e1\u0005>\u0000\u0000\u03e1\u03e2\u0005>\u0000\u0000" + + "\u03e2\u03e3\u0005=\u0000\u0000\u03e3\u00ee\u0001\u0000\u0000\u0000\u03e4" + + "\u03e5\u0005>\u0000\u0000\u03e5\u03e6\u0005>\u0000\u0000\u03e6\u03e7\u0005" + + ">\u0000\u0000\u03e7\u03e8\u0005=\u0000\u0000\u03e8\u00f0\u0001\u0000\u0000" + + "\u0000\u03e9\u03ea\u0005-\u0000\u0000\u03ea\u03eb\u0005>\u0000\u0000\u03eb" + + "\u00f2\u0001\u0000\u0000\u0000\u03ec\u03ed\u0005:\u0000\u0000\u03ed\u03ee" + + "\u0005:\u0000\u0000\u03ee\u00f4\u0001\u0000\u0000\u0000\u03ef\u03f0\u0005" + + "@\u0000\u0000\u03f0\u00f6\u0001\u0000\u0000\u0000\u03f1\u03f2\u0005.\u0000" + + "\u0000\u03f2\u03f3\u0005.\u0000\u0000\u03f3\u03f4\u0005.\u0000\u0000\u03f4" + + "\u00f8\u0001\u0000\u0000\u0000\u03f5\u03f6\u0005/\u0000\u0000\u03f6\u03f7" + + "\u0005*\u0000\u0000\u03f7\u03f8\u0005*\u0000\u0000\u03f8\u03fc\u0001\u0000" + + "\u0000\u0000\u03f9\u03fb\t\u0000\u0000\u0000\u03fa\u03f9\u0001\u0000\u0000" + + "\u0000\u03fb\u03fe\u0001\u0000\u0000\u0000\u03fc\u03fd\u0001\u0000\u0000" + + "\u0000\u03fc\u03fa\u0001\u0000\u0000\u0000\u03fd\u03ff\u0001\u0000\u0000" + + "\u0000\u03fe\u03fc\u0001\u0000\u0000\u0000\u03ff\u0400\u0005*\u0000\u0000" + + "\u0400\u0401\u0005/\u0000\u0000\u0401\u00fa\u0001\u0000\u0000\u0000\u0402" + + "\u0404\u0007\u0011\u0000\u0000\u0403\u0402\u0001\u0000\u0000\u0000\u0404" + + "\u0405\u0001\u0000\u0000\u0000\u0405\u0403\u0001\u0000\u0000\u0000\u0405" + + "\u0406\u0001\u0000\u0000\u0000\u0406\u0407\u0001\u0000\u0000\u0000\u0407" + + "\u0408\u0006}\u0000\u0000\u0408\u00fc\u0001\u0000\u0000\u0000\u0409\u040a" + + "\u0005/\u0000\u0000\u040a\u040b\u0005*\u0000\u0000\u040b\u040f\u0001\u0000" + + "\u0000\u0000\u040c\u040e\t\u0000\u0000\u0000\u040d\u040c\u0001\u0000\u0000" + + "\u0000\u040e\u0411\u0001\u0000\u0000\u0000\u040f\u0410\u0001\u0000\u0000" + + "\u0000\u040f\u040d\u0001\u0000\u0000\u0000\u0410\u0412\u0001\u0000\u0000" + + "\u0000\u0411\u040f\u0001\u0000\u0000\u0000\u0412\u0413\u0005*\u0000\u0000" + + "\u0413\u0414\u0005/\u0000\u0000\u0414\u0415\u0001\u0000\u0000\u0000\u0415" + + "\u0416\u0006~\u0000\u0000\u0416\u00fe\u0001\u0000\u0000\u0000\u0417\u0418" + + "\u0005/\u0000\u0000\u0418\u0419\u0005/\u0000\u0000\u0419\u041d\u0001\u0000" + + "\u0000\u0000\u041a\u041c\b\u0010\u0000\u0000\u041b\u041a\u0001\u0000\u0000" + + "\u0000\u041c\u041f\u0001\u0000\u0000\u0000\u041d\u041b\u0001\u0000\u0000" + + "\u0000\u041d\u041e\u0001\u0000\u0000\u0000\u041e\u0420\u0001\u0000\u0000" + + "\u0000\u041f\u041d\u0001\u0000\u0000\u0000\u0420\u0421\u0006\u007f\u0000" + + "\u0000\u0421\u0100\u0001\u0000\u0000\u0000\u0422\u0426\u0003\u010f\u0087" + + "\u0000\u0423\u0425\u0003\u010d\u0086\u0000\u0424\u0423\u0001\u0000\u0000" + + "\u0000\u0425\u0428\u0001\u0000\u0000\u0000\u0426\u0424\u0001\u0000\u0000" + + "\u0000\u0426\u0427\u0001\u0000\u0000\u0000\u0427\u0102\u0001\u0000\u0000" + + "\u0000\u0428\u0426\u0001\u0000\u0000\u0000\u0429\u042b\u0007\u0012\u0000" + + "\u0000\u042a\u042c\u0007\f\u0000\u0000\u042b\u042a\u0001\u0000\u0000\u0000" + + "\u042b\u042c\u0001\u0000\u0000\u0000\u042c\u042d\u0001\u0000\u0000\u0000" + + "\u042d\u042e\u0003\u010b\u0085\u0000\u042e\u0104\u0001\u0000\u0000\u0000" + + "\u042f\u0435\u0005\\\u0000\u0000\u0430\u0431\u0005u\u0000\u0000\u0431" + + "\u0432\u00050\u0000\u0000\u0432\u0433\u00050\u0000\u0000\u0433\u0434\u0005" + + "5\u0000\u0000\u0434\u0436\u0005c\u0000\u0000\u0435\u0430\u0001\u0000\u0000" + + "\u0000\u0435\u0436\u0001\u0000\u0000\u0000\u0436\u0437\u0001\u0000\u0000" + + "\u0000\u0437\u0453\u0007\u0013\u0000\u0000\u0438\u043e\u0005\\\u0000\u0000" + + "\u0439\u043a\u0005u\u0000\u0000\u043a\u043b\u00050\u0000\u0000\u043b\u043c" + + "\u00050\u0000\u0000\u043c\u043d\u00055\u0000\u0000\u043d\u043f\u0005c" + + "\u0000\u0000\u043e\u0439\u0001\u0000\u0000\u0000\u043e\u043f\u0001\u0000" + + "\u0000\u0000\u043f\u0444\u0001\u0000\u0000\u0000\u0440\u0442\u0007\u0014" + + "\u0000\u0000\u0441\u0440\u0001\u0000\u0000\u0000\u0441\u0442\u0001\u0000" + + "\u0000\u0000\u0442\u0443\u0001\u0000\u0000\u0000\u0443\u0445\u0007\u0005" + + "\u0000\u0000\u0444\u0441\u0001\u0000\u0000\u0000\u0444\u0445\u0001\u0000" + + "\u0000\u0000\u0445\u0446\u0001\u0000\u0000\u0000\u0446\u0453\u0007\u0005" + + "\u0000\u0000\u0447\u0449\u0005\\\u0000\u0000\u0448\u044a\u0005u\u0000" + + "\u0000\u0449\u0448\u0001\u0000\u0000\u0000\u044a\u044b\u0001\u0000\u0000" + + "\u0000\u044b\u0449\u0001\u0000\u0000\u0000\u044b\u044c\u0001\u0000\u0000" + + "\u0000\u044c\u044d\u0001\u0000\u0000\u0000\u044d\u044e\u0003\u0109\u0084" + + "\u0000\u044e\u044f\u0003\u0109\u0084\u0000\u044f\u0450\u0003\u0109\u0084" + + "\u0000\u0450\u0451\u0003\u0109\u0084\u0000\u0451\u0453\u0001\u0000\u0000" + + "\u0000\u0452\u042f\u0001\u0000\u0000\u0000\u0452\u0438\u0001\u0000\u0000" + + "\u0000\u0452\u0447\u0001\u0000\u0000\u0000\u0453\u0106\u0001\u0000\u0000" + + "\u0000\u0454\u045d\u0003\u0109\u0084\u0000\u0455\u0458\u0003\u0109\u0084" + + "\u0000\u0456\u0458\u0005_\u0000\u0000\u0457\u0455\u0001\u0000\u0000\u0000" + + "\u0457\u0456\u0001\u0000\u0000\u0000\u0458\u045b\u0001\u0000\u0000\u0000" + + "\u0459\u0457\u0001\u0000\u0000\u0000\u0459\u045a\u0001\u0000\u0000\u0000" + + "\u045a\u045c\u0001\u0000\u0000\u0000\u045b\u0459\u0001\u0000\u0000\u0000" + + "\u045c\u045e\u0003\u0109\u0084\u0000\u045d\u0459\u0001\u0000\u0000\u0000" + + "\u045d\u045e\u0001\u0000\u0000\u0000\u045e\u0108\u0001\u0000\u0000\u0000" + + "\u045f\u0460\u0007\u0003\u0000\u0000\u0460\u010a\u0001\u0000\u0000\u0000" + + "\u0461\u0469\u0007\u0015\u0000\u0000\u0462\u0464\u0007\u0016\u0000\u0000" + + "\u0463\u0462\u0001\u0000\u0000\u0000\u0464\u0467\u0001\u0000\u0000\u0000" + + "\u0465\u0463\u0001\u0000\u0000\u0000\u0465\u0466\u0001\u0000\u0000\u0000" + + "\u0466\u0468\u0001\u0000\u0000\u0000\u0467\u0465\u0001\u0000\u0000\u0000" + + "\u0468\u046a\u0007\u0015\u0000\u0000\u0469\u0465\u0001\u0000\u0000\u0000" + + "\u0469\u046a\u0001\u0000\u0000\u0000\u046a\u010c\u0001\u0000\u0000\u0000" + + "\u046b\u046e\u0003\u010f\u0087\u0000\u046c\u046e\u0007\u0015\u0000\u0000" + + "\u046d\u046b\u0001\u0000\u0000\u0000\u046d\u046c\u0001\u0000\u0000\u0000" + + "\u046e\u010e\u0001\u0000\u0000\u0000\u046f\u0474\u0007\u0017\u0000\u0000" + + "\u0470\u0474\b\u0018\u0000\u0000\u0471\u0472\u0007\u0019\u0000\u0000\u0472" + + "\u0474\u0007\u001a\u0000\u0000\u0473\u046f\u0001\u0000\u0000\u0000\u0473" + + "\u0470\u0001\u0000\u0000\u0000\u0473\u0471\u0001\u0000\u0000\u0000\u0474" + + "\u0110\u0001\u0000\u0000\u00006\u0000\u02d6\u02db\u02de\u02e0\u02e3\u02eb" + + "\u02ef\u02f2\u02f8\u02ff\u0303\u0306\u030e\u0312\u0315\u031a\u031e\u0321" + + "\u0324\u0329\u032c\u032e\u0334\u0337\u033b\u033f\u0343\u034e\u0353\u035a" + + "\u035c\u0368\u036e\u0370\u03fc\u0405\u040f\u041d\u0426\u042b\u0435\u043e" + + "\u0441\u0444\u044b\u0452\u0457\u0459\u045d\u0465\u0469\u046d\u0473\u0001" + + "\u0000\u0001\u0000"; + public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavaParser.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavaParser.java new file mode 100644 index 000000000000..7c5ee6f615b0 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavaParser.java @@ -0,0 +1,15100 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor.antlr.generated; + +import java.util.List; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.misc.*; +import org.antlr.v4.runtime.tree.*; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue"}) +public class JavaParser extends Parser { + static { + RuntimeMetaData.checkVersion("4.13.1", RuntimeMetaData.VERSION); + } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache(); + public static final int ABSTRACT = 1, + ASSERT = 2, + BOOLEAN = 3, + BREAK = 4, + BYTE = 5, + CASE = 6, + CATCH = 7, + CHAR = 8, + CLASS = 9, + CONST = 10, + CONTINUE = 11, + DEFAULT = 12, + DO = 13, + DOUBLE = 14, + ELSE = 15, + ENUM = 16, + EXTENDS = 17, + FINAL = 18, + FINALLY = 19, + FLOAT = 20, + FOR = 21, + IF = 22, + GOTO = 23, + IMPLEMENTS = 24, + IMPORT = 25, + INSTANCEOF = 26, + INT = 27, + INTERFACE = 28, + LONG = 29, + NATIVE = 30, + NEW = 31, + PACKAGE = 32, + PRIVATE = 33, + PROTECTED = 34, + PUBLIC = 35, + RETURN = 36, + SHORT = 37, + STATIC = 38, + STRICTFP = 39, + SUPER = 40, + SWITCH = 41, + SYNCHRONIZED = 42, + THIS = 43, + THROW = 44, + THROWS = 45, + TRANSIENT = 46, + TRY = 47, + VOID = 48, + VOLATILE = 49, + WHILE = 50, + MODULE = 51, + OPEN = 52, + REQUIRES = 53, + EXPORTS = 54, + OPENS = 55, + TO = 56, + USES = 57, + PROVIDES = 58, + WITH = 59, + TRANSITIVE = 60, + VAR = 61, + YIELD = 62, + RECORD = 63, + SEALED = 64, + PERMITS = 65, + NON_SEALED = 66, + DECIMAL_LITERAL = 67, + HEX_LITERAL = 68, + OCT_LITERAL = 69, + BINARY_LITERAL = 70, + FLOAT_LITERAL = 71, + HEX_FLOAT_LITERAL = 72, + BOOL_LITERAL = 73, + CHAR_LITERAL = 74, + STRING_LITERAL = 75, + TEXT_BLOCK = 76, + NULL_LITERAL = 77, + LPAREN = 78, + RPAREN = 79, + LBRACE = 80, + RBRACE = 81, + LBRACK = 82, + RBRACK = 83, + SEMI = 84, + COMMA = 85, + DOT = 86, + ASSIGN = 87, + GT = 88, + LT = 89, + BANG = 90, + TILDE = 91, + QUESTION = 92, + COLON = 93, + EQUAL = 94, + LE = 95, + GE = 96, + NOTEQUAL = 97, + AND = 98, + OR = 99, + INC = 100, + DEC = 101, + ADD = 102, + SUB = 103, + MUL = 104, + DIV = 105, + BITAND = 106, + BITOR = 107, + CARET = 108, + MOD = 109, + ADD_ASSIGN = 110, + SUB_ASSIGN = 111, + MUL_ASSIGN = 112, + DIV_ASSIGN = 113, + AND_ASSIGN = 114, + OR_ASSIGN = 115, + XOR_ASSIGN = 116, + MOD_ASSIGN = 117, + LSHIFT_ASSIGN = 118, + RSHIFT_ASSIGN = 119, + URSHIFT_ASSIGN = 120, + ARROW = 121, + COLONCOLON = 122, + AT = 123, + ELLIPSIS = 124, + JAVADOC_COMMENT = 125, + WS = 126, + COMMENT = 127, + LINE_COMMENT = 128, + IDENTIFIER = 129; + public static final int RULE_compilationUnit = 0, + RULE_packageDeclaration = 1, + RULE_importDeclaration = 2, + RULE_typeDeclaration = 3, + RULE_modifier = 4, + RULE_classOrInterfaceModifier = 5, + RULE_variableModifier = 6, + RULE_classDeclaration = 7, + RULE_typeParameters = 8, + RULE_typeParameter = 9, + RULE_typeBound = 10, + RULE_enumDeclaration = 11, + RULE_enumConstants = 12, + RULE_enumConstant = 13, + RULE_enumBodyDeclarations = 14, + RULE_interfaceDeclaration = 15, + RULE_classBody = 16, + RULE_interfaceBody = 17, + RULE_classBodyDeclaration = 18, + RULE_memberDeclaration = 19, + RULE_methodDeclaration = 20, + RULE_methodBody = 21, + RULE_typeTypeOrVoid = 22, + RULE_genericMethodDeclaration = 23, + RULE_genericConstructorDeclaration = 24, + RULE_constructorDeclaration = 25, + RULE_compactConstructorDeclaration = 26, + RULE_fieldDeclaration = 27, + RULE_interfaceBodyDeclaration = 28, + RULE_interfaceMemberDeclaration = 29, + RULE_constDeclaration = 30, + RULE_constantDeclarator = 31, + RULE_interfaceMethodDeclaration = 32, + RULE_interfaceMethodModifier = 33, + RULE_genericInterfaceMethodDeclaration = 34, + RULE_interfaceCommonBodyDeclaration = 35, + RULE_variableDeclarators = 36, + RULE_variableDeclarator = 37, + RULE_variableDeclaratorId = 38, + RULE_variableInitializer = 39, + RULE_arrayInitializer = 40, + RULE_classOrInterfaceType = 41, + RULE_typeArgument = 42, + RULE_qualifiedNameList = 43, + RULE_formalParameters = 44, + RULE_receiverParameter = 45, + RULE_formalParameterList = 46, + RULE_formalParameter = 47, + RULE_lastFormalParameter = 48, + RULE_lambdaLVTIList = 49, + RULE_lambdaLVTIParameter = 50, + RULE_qualifiedName = 51, + RULE_literal = 52, + RULE_integerLiteral = 53, + RULE_floatLiteral = 54, + RULE_altAnnotationQualifiedName = 55, + RULE_annotation = 56, + RULE_elementValuePairs = 57, + RULE_elementValuePair = 58, + RULE_elementValue = 59, + RULE_elementValueArrayInitializer = 60, + RULE_annotationTypeDeclaration = 61, + RULE_annotationTypeBody = 62, + RULE_annotationTypeElementDeclaration = 63, + RULE_annotationTypeElementRest = 64, + RULE_annotationMethodOrConstantRest = 65, + RULE_annotationMethodRest = 66, + RULE_annotationConstantRest = 67, + RULE_defaultValue = 68, + RULE_moduleDeclaration = 69, + RULE_moduleBody = 70, + RULE_moduleDirective = 71, + RULE_requiresModifier = 72, + RULE_recordDeclaration = 73, + RULE_recordHeader = 74, + RULE_recordComponentList = 75, + RULE_recordComponent = 76, + RULE_recordBody = 77, + RULE_block = 78, + RULE_blockStatement = 79, + RULE_localVariableDeclaration = 80, + RULE_identifier = 81, + RULE_typeIdentifier = 82, + RULE_localTypeDeclaration = 83, + RULE_statement = 84, + RULE_catchClause = 85, + RULE_catchType = 86, + RULE_finallyBlock = 87, + RULE_resourceSpecification = 88, + RULE_resources = 89, + RULE_resource = 90, + RULE_switchBlockStatementGroup = 91, + RULE_switchLabel = 92, + RULE_forControl = 93, + RULE_forInit = 94, + RULE_enhancedForControl = 95, + RULE_parExpression = 96, + RULE_expressionList = 97, + RULE_methodCall = 98, + RULE_expression = 99, + RULE_pattern = 100, + RULE_lambdaExpression = 101, + RULE_lambdaParameters = 102, + RULE_lambdaBody = 103, + RULE_primary = 104, + RULE_switchExpression = 105, + RULE_switchLabeledRule = 106, + RULE_guardedPattern = 107, + RULE_switchRuleOutcome = 108, + RULE_classType = 109, + RULE_creator = 110, + RULE_createdName = 111, + RULE_innerCreator = 112, + RULE_arrayCreatorRest = 113, + RULE_classCreatorRest = 114, + RULE_explicitGenericInvocation = 115, + RULE_typeArgumentsOrDiamond = 116, + RULE_nonWildcardTypeArgumentsOrDiamond = 117, + RULE_nonWildcardTypeArguments = 118, + RULE_typeList = 119, + RULE_typeType = 120, + RULE_primitiveType = 121, + RULE_typeArguments = 122, + RULE_superSuffix = 123, + RULE_explicitGenericInvocationSuffix = 124, + RULE_arguments = 125; + + private static String[] makeRuleNames() { + return new String[] { + "compilationUnit", + "packageDeclaration", + "importDeclaration", + "typeDeclaration", + "modifier", + "classOrInterfaceModifier", + "variableModifier", + "classDeclaration", + "typeParameters", + "typeParameter", + "typeBound", + "enumDeclaration", + "enumConstants", + "enumConstant", + "enumBodyDeclarations", + "interfaceDeclaration", + "classBody", + "interfaceBody", + "classBodyDeclaration", + "memberDeclaration", + "methodDeclaration", + "methodBody", + "typeTypeOrVoid", + "genericMethodDeclaration", + "genericConstructorDeclaration", + "constructorDeclaration", + "compactConstructorDeclaration", + "fieldDeclaration", + "interfaceBodyDeclaration", + "interfaceMemberDeclaration", + "constDeclaration", + "constantDeclarator", + "interfaceMethodDeclaration", + "interfaceMethodModifier", + "genericInterfaceMethodDeclaration", + "interfaceCommonBodyDeclaration", + "variableDeclarators", + "variableDeclarator", + "variableDeclaratorId", + "variableInitializer", + "arrayInitializer", + "classOrInterfaceType", + "typeArgument", + "qualifiedNameList", + "formalParameters", + "receiverParameter", + "formalParameterList", + "formalParameter", + "lastFormalParameter", + "lambdaLVTIList", + "lambdaLVTIParameter", + "qualifiedName", + "literal", + "integerLiteral", + "floatLiteral", + "altAnnotationQualifiedName", + "annotation", + "elementValuePairs", + "elementValuePair", + "elementValue", + "elementValueArrayInitializer", + "annotationTypeDeclaration", + "annotationTypeBody", + "annotationTypeElementDeclaration", + "annotationTypeElementRest", + "annotationMethodOrConstantRest", + "annotationMethodRest", + "annotationConstantRest", + "defaultValue", + "moduleDeclaration", + "moduleBody", + "moduleDirective", + "requiresModifier", + "recordDeclaration", + "recordHeader", + "recordComponentList", + "recordComponent", + "recordBody", + "block", + "blockStatement", + "localVariableDeclaration", + "identifier", + "typeIdentifier", + "localTypeDeclaration", + "statement", + "catchClause", + "catchType", + "finallyBlock", + "resourceSpecification", + "resources", + "resource", + "switchBlockStatementGroup", + "switchLabel", + "forControl", + "forInit", + "enhancedForControl", + "parExpression", + "expressionList", + "methodCall", + "expression", + "pattern", + "lambdaExpression", + "lambdaParameters", + "lambdaBody", + "primary", + "switchExpression", + "switchLabeledRule", + "guardedPattern", + "switchRuleOutcome", + "classType", + "creator", + "createdName", + "innerCreator", + "arrayCreatorRest", + "classCreatorRest", + "explicitGenericInvocation", + "typeArgumentsOrDiamond", + "nonWildcardTypeArgumentsOrDiamond", + "nonWildcardTypeArguments", + "typeList", + "typeType", + "primitiveType", + "typeArguments", + "superSuffix", + "explicitGenericInvocationSuffix", + "arguments" + }; + } + + public static final String[] ruleNames = makeRuleNames(); + + private static String[] makeLiteralNames() { + return new String[] { + null, + "'abstract'", + "'assert'", + "'boolean'", + "'break'", + "'byte'", + "'case'", + "'catch'", + "'char'", + "'class'", + "'const'", + "'continue'", + "'default'", + "'do'", + "'double'", + "'else'", + "'enum'", + "'extends'", + "'final'", + "'finally'", + "'float'", + "'for'", + "'if'", + "'goto'", + "'implements'", + "'import'", + "'instanceof'", + "'int'", + "'interface'", + "'long'", + "'native'", + "'new'", + "'package'", + "'private'", + "'protected'", + "'public'", + "'return'", + "'short'", + "'static'", + "'strictfp'", + "'super'", + "'switch'", + "'synchronized'", + "'this'", + "'throw'", + "'throws'", + "'transient'", + "'try'", + "'void'", + "'volatile'", + "'while'", + "'module'", + "'open'", + "'requires'", + "'exports'", + "'opens'", + "'to'", + "'uses'", + "'provides'", + "'with'", + "'transitive'", + "'var'", + "'yield'", + "'record'", + "'sealed'", + "'permits'", + "'non-sealed'", + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + "'null'", + "'('", + "')'", + "'{'", + "'}'", + "'['", + "']'", + "';'", + "','", + "'.'", + "'='", + "'>'", + "'<'", + "'!'", + "'~'", + "'?'", + "':'", + "'=='", + "'<='", + "'>='", + "'!='", + "'&&'", + "'||'", + "'++'", + "'--'", + "'+'", + "'-'", + "'*'", + "'/'", + "'&'", + "'|'", + "'^'", + "'%'", + "'+='", + "'-='", + "'*='", + "'/='", + "'&='", + "'|='", + "'^='", + "'%='", + "'<<='", + "'>>='", + "'>>>='", + "'->'", + "'::'", + "'@'", + "'...'" + }; + } + + private static final String[] _LITERAL_NAMES = makeLiteralNames(); + + private static String[] makeSymbolicNames() { + return new String[] { + null, + "ABSTRACT", + "ASSERT", + "BOOLEAN", + "BREAK", + "BYTE", + "CASE", + "CATCH", + "CHAR", + "CLASS", + "CONST", + "CONTINUE", + "DEFAULT", + "DO", + "DOUBLE", + "ELSE", + "ENUM", + "EXTENDS", + "FINAL", + "FINALLY", + "FLOAT", + "FOR", + "IF", + "GOTO", + "IMPLEMENTS", + "IMPORT", + "INSTANCEOF", + "INT", + "INTERFACE", + "LONG", + "NATIVE", + "NEW", + "PACKAGE", + "PRIVATE", + "PROTECTED", + "PUBLIC", + "RETURN", + "SHORT", + "STATIC", + "STRICTFP", + "SUPER", + "SWITCH", + "SYNCHRONIZED", + "THIS", + "THROW", + "THROWS", + "TRANSIENT", + "TRY", + "VOID", + "VOLATILE", + "WHILE", + "MODULE", + "OPEN", + "REQUIRES", + "EXPORTS", + "OPENS", + "TO", + "USES", + "PROVIDES", + "WITH", + "TRANSITIVE", + "VAR", + "YIELD", + "RECORD", + "SEALED", + "PERMITS", + "NON_SEALED", + "DECIMAL_LITERAL", + "HEX_LITERAL", + "OCT_LITERAL", + "BINARY_LITERAL", + "FLOAT_LITERAL", + "HEX_FLOAT_LITERAL", + "BOOL_LITERAL", + "CHAR_LITERAL", + "STRING_LITERAL", + "TEXT_BLOCK", + "NULL_LITERAL", + "LPAREN", + "RPAREN", + "LBRACE", + "RBRACE", + "LBRACK", + "RBRACK", + "SEMI", + "COMMA", + "DOT", + "ASSIGN", + "GT", + "LT", + "BANG", + "TILDE", + "QUESTION", + "COLON", + "EQUAL", + "LE", + "GE", + "NOTEQUAL", + "AND", + "OR", + "INC", + "DEC", + "ADD", + "SUB", + "MUL", + "DIV", + "BITAND", + "BITOR", + "CARET", + "MOD", + "ADD_ASSIGN", + "SUB_ASSIGN", + "MUL_ASSIGN", + "DIV_ASSIGN", + "AND_ASSIGN", + "OR_ASSIGN", + "XOR_ASSIGN", + "MOD_ASSIGN", + "LSHIFT_ASSIGN", + "RSHIFT_ASSIGN", + "URSHIFT_ASSIGN", + "ARROW", + "COLONCOLON", + "AT", + "ELLIPSIS", + "JAVADOC_COMMENT", + "WS", + "COMMENT", + "LINE_COMMENT", + "IDENTIFIER" + }; + } + + private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + @Override + public String getGrammarFileName() { + return "JavaParser.g4"; + } + + @Override + public String[] getRuleNames() { + return ruleNames; + } + + @Override + public String getSerializedATN() { + return _serializedATN; + } + + @Override + public ATN getATN() { + return _ATN; + } + + public JavaParser(TokenStream input) { + super(input); + _interp = new ParserATNSimulator(this, _ATN, _decisionToDFA, _sharedContextCache); + } + + @SuppressWarnings("CheckReturnValue") + public static class CompilationUnitContext extends ParserRuleContext { + public PackageDeclarationContext packageDeclaration() { + return getRuleContext(PackageDeclarationContext.class, 0); + } + + public List importDeclaration() { + return getRuleContexts(ImportDeclarationContext.class); + } + + public ImportDeclarationContext importDeclaration(int i) { + return getRuleContext(ImportDeclarationContext.class, i); + } + + public List SEMI() { + return getTokens(JavaParser.SEMI); + } + + public TerminalNode SEMI(int i) { + return getToken(JavaParser.SEMI, i); + } + + public List JAVADOC_COMMENT() { + return getTokens(JavaParser.JAVADOC_COMMENT); + } + + public TerminalNode JAVADOC_COMMENT(int i) { + return getToken(JavaParser.JAVADOC_COMMENT, i); + } + + public List typeDeclaration() { + return getRuleContexts(TypeDeclarationContext.class); + } + + public TypeDeclarationContext typeDeclaration(int i) { + return getRuleContext(TypeDeclarationContext.class, i); + } + + public ModuleDeclarationContext moduleDeclaration() { + return getRuleContext(ModuleDeclarationContext.class, 0); + } + + public TerminalNode EOF() { + return getToken(JavaParser.EOF, 0); + } + + public CompilationUnitContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_compilationUnit; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterCompilationUnit(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitCompilationUnit(this); + } + } + + public final CompilationUnitContext compilationUnit() throws RecognitionException { + CompilationUnitContext _localctx = new CompilationUnitContext(_ctx, getState()); + enterRule(_localctx, 0, RULE_compilationUnit); + int _la; + try { + int _alt; + setState(278); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 6, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(253); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 0, _ctx)) { + case 1: + { + setState(252); + packageDeclaration(); + } + break; + } + setState(259); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 2, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + setState(257); + _errHandler.sync(this); + switch (_input.LA(1)) { + case IMPORT: + { + setState(255); + importDeclaration(); + } + break; + case SEMI: + { + setState(256); + match(SEMI); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + setState(261); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 2, _ctx); + } + setState(265); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == JAVADOC_COMMENT) { + { + { + setState(262); + match(JAVADOC_COMMENT); + } + } + setState(267); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(272); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & -2250914781658622L) != 0) + || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & 576460752304472071L) != 0) + || _la == IDENTIFIER) { + { + setState(270); + _errHandler.sync(this); + switch (_input.LA(1)) { + case ABSTRACT: + case CLASS: + case ENUM: + case FINAL: + case INTERFACE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case STATIC: + case STRICTFP: + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case NON_SEALED: + case AT: + case IDENTIFIER: + { + setState(268); + typeDeclaration(); + } + break; + case SEMI: + { + setState(269); + match(SEMI); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(274); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(275); + moduleDeclaration(); + setState(276); + match(EOF); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class PackageDeclarationContext extends ParserRuleContext { + public TerminalNode PACKAGE() { + return getToken(JavaParser.PACKAGE, 0); + } + + public QualifiedNameContext qualifiedName() { + return getRuleContext(QualifiedNameContext.class, 0); + } + + public TerminalNode SEMI() { + return getToken(JavaParser.SEMI, 0); + } + + public List annotation() { + return getRuleContexts(AnnotationContext.class); + } + + public AnnotationContext annotation(int i) { + return getRuleContext(AnnotationContext.class, i); + } + + public PackageDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_packageDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterPackageDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitPackageDeclaration(this); + } + } + + public final PackageDeclarationContext packageDeclaration() throws RecognitionException { + PackageDeclarationContext _localctx = new PackageDeclarationContext(_ctx, getState()); + enterRule(_localctx, 2, RULE_packageDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(283); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 51)) & ~0x3f) == 0 && ((1L << (_la - 51)) & 32767L) != 0) + || _la == AT + || _la == IDENTIFIER) { + { + { + setState(280); + annotation(); + } + } + setState(285); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(286); + match(PACKAGE); + setState(287); + qualifiedName(); + setState(288); + match(SEMI); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ImportDeclarationContext extends ParserRuleContext { + public TerminalNode IMPORT() { + return getToken(JavaParser.IMPORT, 0); + } + + public QualifiedNameContext qualifiedName() { + return getRuleContext(QualifiedNameContext.class, 0); + } + + public TerminalNode SEMI() { + return getToken(JavaParser.SEMI, 0); + } + + public TerminalNode STATIC() { + return getToken(JavaParser.STATIC, 0); + } + + public TerminalNode DOT() { + return getToken(JavaParser.DOT, 0); + } + + public TerminalNode MUL() { + return getToken(JavaParser.MUL, 0); + } + + public ImportDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_importDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterImportDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitImportDeclaration(this); + } + } + + public final ImportDeclarationContext importDeclaration() throws RecognitionException { + ImportDeclarationContext _localctx = new ImportDeclarationContext(_ctx, getState()); + enterRule(_localctx, 4, RULE_importDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(290); + match(IMPORT); + setState(292); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == STATIC) { + { + setState(291); + match(STATIC); + } + } + + setState(294); + qualifiedName(); + setState(297); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == DOT) { + { + setState(295); + match(DOT); + setState(296); + match(MUL); + } + } + + setState(299); + match(SEMI); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class TypeDeclarationContext extends ParserRuleContext { + public ClassDeclarationContext classDeclaration() { + return getRuleContext(ClassDeclarationContext.class, 0); + } + + public EnumDeclarationContext enumDeclaration() { + return getRuleContext(EnumDeclarationContext.class, 0); + } + + public InterfaceDeclarationContext interfaceDeclaration() { + return getRuleContext(InterfaceDeclarationContext.class, 0); + } + + public AnnotationTypeDeclarationContext annotationTypeDeclaration() { + return getRuleContext(AnnotationTypeDeclarationContext.class, 0); + } + + public RecordDeclarationContext recordDeclaration() { + return getRuleContext(RecordDeclarationContext.class, 0); + } + + public List classOrInterfaceModifier() { + return getRuleContexts(ClassOrInterfaceModifierContext.class); + } + + public ClassOrInterfaceModifierContext classOrInterfaceModifier(int i) { + return getRuleContext(ClassOrInterfaceModifierContext.class, i); + } + + public TypeDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_typeDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterTypeDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitTypeDeclaration(this); + } + } + + public final TypeDeclarationContext typeDeclaration() throws RecognitionException { + TypeDeclarationContext _localctx = new TypeDeclarationContext(_ctx, getState()); + enterRule(_localctx, 6, RULE_typeDeclaration); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(304); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 10, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(301); + classOrInterfaceModifier(); + } + } + } + setState(306); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 10, _ctx); + } + setState(312); + _errHandler.sync(this); + switch (_input.LA(1)) { + case CLASS: + { + setState(307); + classDeclaration(); + } + break; + case ENUM: + { + setState(308); + enumDeclaration(); + } + break; + case INTERFACE: + { + setState(309); + interfaceDeclaration(); + } + break; + case AT: + { + setState(310); + annotationTypeDeclaration(); + } + break; + case RECORD: + { + setState(311); + recordDeclaration(); + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ModifierContext extends ParserRuleContext { + public ClassOrInterfaceModifierContext classOrInterfaceModifier() { + return getRuleContext(ClassOrInterfaceModifierContext.class, 0); + } + + public TerminalNode NATIVE() { + return getToken(JavaParser.NATIVE, 0); + } + + public TerminalNode SYNCHRONIZED() { + return getToken(JavaParser.SYNCHRONIZED, 0); + } + + public TerminalNode TRANSIENT() { + return getToken(JavaParser.TRANSIENT, 0); + } + + public TerminalNode VOLATILE() { + return getToken(JavaParser.VOLATILE, 0); + } + + public ModifierContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_modifier; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterModifier(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitModifier(this); + } + } + + public final ModifierContext modifier() throws RecognitionException { + ModifierContext _localctx = new ModifierContext(_ctx, getState()); + enterRule(_localctx, 8, RULE_modifier); + try { + setState(319); + _errHandler.sync(this); + switch (_input.LA(1)) { + case ABSTRACT: + case FINAL: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case STATIC: + case STRICTFP: + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case NON_SEALED: + case AT: + case IDENTIFIER: + enterOuterAlt(_localctx, 1); + { + setState(314); + classOrInterfaceModifier(); + } + break; + case NATIVE: + enterOuterAlt(_localctx, 2); + { + setState(315); + match(NATIVE); + } + break; + case SYNCHRONIZED: + enterOuterAlt(_localctx, 3); + { + setState(316); + match(SYNCHRONIZED); + } + break; + case TRANSIENT: + enterOuterAlt(_localctx, 4); + { + setState(317); + match(TRANSIENT); + } + break; + case VOLATILE: + enterOuterAlt(_localctx, 5); + { + setState(318); + match(VOLATILE); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ClassOrInterfaceModifierContext extends ParserRuleContext { + public AnnotationContext annotation() { + return getRuleContext(AnnotationContext.class, 0); + } + + public TerminalNode PUBLIC() { + return getToken(JavaParser.PUBLIC, 0); + } + + public TerminalNode PROTECTED() { + return getToken(JavaParser.PROTECTED, 0); + } + + public TerminalNode PRIVATE() { + return getToken(JavaParser.PRIVATE, 0); + } + + public TerminalNode STATIC() { + return getToken(JavaParser.STATIC, 0); + } + + public TerminalNode ABSTRACT() { + return getToken(JavaParser.ABSTRACT, 0); + } + + public TerminalNode FINAL() { + return getToken(JavaParser.FINAL, 0); + } + + public TerminalNode STRICTFP() { + return getToken(JavaParser.STRICTFP, 0); + } + + public TerminalNode SEALED() { + return getToken(JavaParser.SEALED, 0); + } + + public TerminalNode NON_SEALED() { + return getToken(JavaParser.NON_SEALED, 0); + } + + public ClassOrInterfaceModifierContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_classOrInterfaceModifier; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterClassOrInterfaceModifier(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitClassOrInterfaceModifier(this); + } + } + + public final ClassOrInterfaceModifierContext classOrInterfaceModifier() throws RecognitionException { + ClassOrInterfaceModifierContext _localctx = new ClassOrInterfaceModifierContext(_ctx, getState()); + enterRule(_localctx, 10, RULE_classOrInterfaceModifier); + try { + setState(331); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 13, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(321); + annotation(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(322); + match(PUBLIC); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(323); + match(PROTECTED); + } + break; + case 4: + enterOuterAlt(_localctx, 4); + { + setState(324); + match(PRIVATE); + } + break; + case 5: + enterOuterAlt(_localctx, 5); + { + setState(325); + match(STATIC); + } + break; + case 6: + enterOuterAlt(_localctx, 6); + { + setState(326); + match(ABSTRACT); + } + break; + case 7: + enterOuterAlt(_localctx, 7); + { + setState(327); + match(FINAL); + } + break; + case 8: + enterOuterAlt(_localctx, 8); + { + setState(328); + match(STRICTFP); + } + break; + case 9: + enterOuterAlt(_localctx, 9); + { + setState(329); + match(SEALED); + } + break; + case 10: + enterOuterAlt(_localctx, 10); + { + setState(330); + match(NON_SEALED); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class VariableModifierContext extends ParserRuleContext { + public TerminalNode FINAL() { + return getToken(JavaParser.FINAL, 0); + } + + public AnnotationContext annotation() { + return getRuleContext(AnnotationContext.class, 0); + } + + public VariableModifierContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_variableModifier; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterVariableModifier(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitVariableModifier(this); + } + } + + public final VariableModifierContext variableModifier() throws RecognitionException { + VariableModifierContext _localctx = new VariableModifierContext(_ctx, getState()); + enterRule(_localctx, 12, RULE_variableModifier); + try { + setState(335); + _errHandler.sync(this); + switch (_input.LA(1)) { + case FINAL: + enterOuterAlt(_localctx, 1); + { + setState(333); + match(FINAL); + } + break; + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case AT: + case IDENTIFIER: + enterOuterAlt(_localctx, 2); + { + setState(334); + annotation(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ClassDeclarationContext extends ParserRuleContext { + public TerminalNode CLASS() { + return getToken(JavaParser.CLASS, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public ClassBodyContext classBody() { + return getRuleContext(ClassBodyContext.class, 0); + } + + public TypeParametersContext typeParameters() { + return getRuleContext(TypeParametersContext.class, 0); + } + + public TerminalNode EXTENDS() { + return getToken(JavaParser.EXTENDS, 0); + } + + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public TerminalNode IMPLEMENTS() { + return getToken(JavaParser.IMPLEMENTS, 0); + } + + public List typeList() { + return getRuleContexts(TypeListContext.class); + } + + public TypeListContext typeList(int i) { + return getRuleContext(TypeListContext.class, i); + } + + public TerminalNode PERMITS() { + return getToken(JavaParser.PERMITS, 0); + } + + public ClassDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_classDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterClassDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitClassDeclaration(this); + } + } + + public final ClassDeclarationContext classDeclaration() throws RecognitionException { + ClassDeclarationContext _localctx = new ClassDeclarationContext(_ctx, getState()); + enterRule(_localctx, 14, RULE_classDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(337); + match(CLASS); + setState(338); + identifier(); + setState(340); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LT) { + { + setState(339); + typeParameters(); + } + } + + setState(344); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == EXTENDS) { + { + setState(342); + match(EXTENDS); + setState(343); + typeType(); + } + } + + setState(348); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == IMPLEMENTS) { + { + setState(346); + match(IMPLEMENTS); + setState(347); + typeList(); + } + } + + setState(352); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == PERMITS) { + { + setState(350); + match(PERMITS); + setState(351); + typeList(); + } + } + + setState(354); + classBody(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class TypeParametersContext extends ParserRuleContext { + public TerminalNode LT() { + return getToken(JavaParser.LT, 0); + } + + public List typeParameter() { + return getRuleContexts(TypeParameterContext.class); + } + + public TypeParameterContext typeParameter(int i) { + return getRuleContext(TypeParameterContext.class, i); + } + + public TerminalNode GT() { + return getToken(JavaParser.GT, 0); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public TypeParametersContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_typeParameters; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterTypeParameters(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitTypeParameters(this); + } + } + + public final TypeParametersContext typeParameters() throws RecognitionException { + TypeParametersContext _localctx = new TypeParametersContext(_ctx, getState()); + enterRule(_localctx, 16, RULE_typeParameters); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(356); + match(LT); + setState(357); + typeParameter(); + setState(362); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == COMMA) { + { + { + setState(358); + match(COMMA); + setState(359); + typeParameter(); + } + } + setState(364); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(365); + match(GT); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class TypeParameterContext extends ParserRuleContext { + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public List annotation() { + return getRuleContexts(AnnotationContext.class); + } + + public AnnotationContext annotation(int i) { + return getRuleContext(AnnotationContext.class, i); + } + + public TerminalNode EXTENDS() { + return getToken(JavaParser.EXTENDS, 0); + } + + public TypeBoundContext typeBound() { + return getRuleContext(TypeBoundContext.class, 0); + } + + public TypeParameterContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_typeParameter; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterTypeParameter(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitTypeParameter(this); + } + } + + public final TypeParameterContext typeParameter() throws RecognitionException { + TypeParameterContext _localctx = new TypeParameterContext(_ctx, getState()); + enterRule(_localctx, 18, RULE_typeParameter); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(370); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 20, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(367); + annotation(); + } + } + } + setState(372); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 20, _ctx); + } + setState(373); + identifier(); + setState(382); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == EXTENDS) { + { + setState(374); + match(EXTENDS); + setState(378); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 21, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(375); + annotation(); + } + } + } + setState(380); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 21, _ctx); + } + setState(381); + typeBound(); + } + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class TypeBoundContext extends ParserRuleContext { + public List typeType() { + return getRuleContexts(TypeTypeContext.class); + } + + public TypeTypeContext typeType(int i) { + return getRuleContext(TypeTypeContext.class, i); + } + + public List BITAND() { + return getTokens(JavaParser.BITAND); + } + + public TerminalNode BITAND(int i) { + return getToken(JavaParser.BITAND, i); + } + + public TypeBoundContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_typeBound; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterTypeBound(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitTypeBound(this); + } + } + + public final TypeBoundContext typeBound() throws RecognitionException { + TypeBoundContext _localctx = new TypeBoundContext(_ctx, getState()); + enterRule(_localctx, 20, RULE_typeBound); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(384); + typeType(); + setState(389); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == BITAND) { + { + { + setState(385); + match(BITAND); + setState(386); + typeType(); + } + } + setState(391); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class EnumDeclarationContext extends ParserRuleContext { + public TerminalNode ENUM() { + return getToken(JavaParser.ENUM, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public TerminalNode LBRACE() { + return getToken(JavaParser.LBRACE, 0); + } + + public TerminalNode RBRACE() { + return getToken(JavaParser.RBRACE, 0); + } + + public TerminalNode IMPLEMENTS() { + return getToken(JavaParser.IMPLEMENTS, 0); + } + + public TypeListContext typeList() { + return getRuleContext(TypeListContext.class, 0); + } + + public EnumConstantsContext enumConstants() { + return getRuleContext(EnumConstantsContext.class, 0); + } + + public TerminalNode COMMA() { + return getToken(JavaParser.COMMA, 0); + } + + public EnumBodyDeclarationsContext enumBodyDeclarations() { + return getRuleContext(EnumBodyDeclarationsContext.class, 0); + } + + public EnumDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_enumDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterEnumDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitEnumDeclaration(this); + } + } + + public final EnumDeclarationContext enumDeclaration() throws RecognitionException { + EnumDeclarationContext _localctx = new EnumDeclarationContext(_ctx, getState()); + enterRule(_localctx, 22, RULE_enumDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(392); + match(ENUM); + setState(393); + identifier(); + setState(396); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == IMPLEMENTS) { + { + setState(394); + match(IMPLEMENTS); + setState(395); + typeList(); + } + } + + setState(398); + match(LBRACE); + setState(400); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 51)) & ~0x3f) == 0 && ((1L << (_la - 51)) & 32767L) != 0) + || _la == AT + || _la == IDENTIFIER) { + { + setState(399); + enumConstants(); + } + } + + setState(403); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == COMMA) { + { + setState(402); + match(COMMA); + } + } + + setState(406); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == SEMI) { + { + setState(405); + enumBodyDeclarations(); + } + } + + setState(408); + match(RBRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class EnumConstantsContext extends ParserRuleContext { + public List enumConstant() { + return getRuleContexts(EnumConstantContext.class); + } + + public EnumConstantContext enumConstant(int i) { + return getRuleContext(EnumConstantContext.class, i); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public EnumConstantsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_enumConstants; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterEnumConstants(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitEnumConstants(this); + } + } + + public final EnumConstantsContext enumConstants() throws RecognitionException { + EnumConstantsContext _localctx = new EnumConstantsContext(_ctx, getState()); + enterRule(_localctx, 24, RULE_enumConstants); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(410); + enumConstant(); + setState(415); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 28, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(411); + match(COMMA); + setState(412); + enumConstant(); + } + } + } + setState(417); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 28, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class EnumConstantContext extends ParserRuleContext { + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public List annotation() { + return getRuleContexts(AnnotationContext.class); + } + + public AnnotationContext annotation(int i) { + return getRuleContext(AnnotationContext.class, i); + } + + public ArgumentsContext arguments() { + return getRuleContext(ArgumentsContext.class, 0); + } + + public ClassBodyContext classBody() { + return getRuleContext(ClassBodyContext.class, 0); + } + + public EnumConstantContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_enumConstant; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterEnumConstant(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitEnumConstant(this); + } + } + + public final EnumConstantContext enumConstant() throws RecognitionException { + EnumConstantContext _localctx = new EnumConstantContext(_ctx, getState()); + enterRule(_localctx, 26, RULE_enumConstant); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(421); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 29, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(418); + annotation(); + } + } + } + setState(423); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 29, _ctx); + } + setState(424); + identifier(); + setState(426); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LPAREN) { + { + setState(425); + arguments(); + } + } + + setState(429); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LBRACE) { + { + setState(428); + classBody(); + } + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class EnumBodyDeclarationsContext extends ParserRuleContext { + public TerminalNode SEMI() { + return getToken(JavaParser.SEMI, 0); + } + + public List classBodyDeclaration() { + return getRuleContexts(ClassBodyDeclarationContext.class); + } + + public ClassBodyDeclarationContext classBodyDeclaration(int i) { + return getRuleContext(ClassBodyDeclarationContext.class, i); + } + + public EnumBodyDeclarationsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_enumBodyDeclarations; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterEnumBodyDeclarations(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitEnumBodyDeclarations(this); + } + } + + public final EnumBodyDeclarationsContext enumBodyDeclarations() throws RecognitionException { + EnumBodyDeclarationsContext _localctx = new EnumBodyDeclarationsContext(_ctx, getState()); + enterRule(_localctx, 28, RULE_enumBodyDeclarations); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(431); + match(SEMI); + setState(435); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & -1331583875988694L) != 0) + || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & 576460752338092039L) != 0) + || _la == IDENTIFIER) { + { + { + setState(432); + classBodyDeclaration(); + } + } + setState(437); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class InterfaceDeclarationContext extends ParserRuleContext { + public TerminalNode INTERFACE() { + return getToken(JavaParser.INTERFACE, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public InterfaceBodyContext interfaceBody() { + return getRuleContext(InterfaceBodyContext.class, 0); + } + + public TypeParametersContext typeParameters() { + return getRuleContext(TypeParametersContext.class, 0); + } + + public TerminalNode EXTENDS() { + return getToken(JavaParser.EXTENDS, 0); + } + + public List typeList() { + return getRuleContexts(TypeListContext.class); + } + + public TypeListContext typeList(int i) { + return getRuleContext(TypeListContext.class, i); + } + + public TerminalNode PERMITS() { + return getToken(JavaParser.PERMITS, 0); + } + + public InterfaceDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_interfaceDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterInterfaceDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitInterfaceDeclaration(this); + } + } + + public final InterfaceDeclarationContext interfaceDeclaration() throws RecognitionException { + InterfaceDeclarationContext _localctx = new InterfaceDeclarationContext(_ctx, getState()); + enterRule(_localctx, 30, RULE_interfaceDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(438); + match(INTERFACE); + setState(439); + identifier(); + setState(441); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LT) { + { + setState(440); + typeParameters(); + } + } + + setState(445); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == EXTENDS) { + { + setState(443); + match(EXTENDS); + setState(444); + typeList(); + } + } + + setState(449); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == PERMITS) { + { + setState(447); + match(PERMITS); + setState(448); + typeList(); + } + } + + setState(451); + interfaceBody(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ClassBodyContext extends ParserRuleContext { + public TerminalNode LBRACE() { + return getToken(JavaParser.LBRACE, 0); + } + + public TerminalNode RBRACE() { + return getToken(JavaParser.RBRACE, 0); + } + + public List classBodyDeclaration() { + return getRuleContexts(ClassBodyDeclarationContext.class); + } + + public ClassBodyDeclarationContext classBodyDeclaration(int i) { + return getRuleContext(ClassBodyDeclarationContext.class, i); + } + + public ClassBodyContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_classBody; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterClassBody(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitClassBody(this); + } + } + + public final ClassBodyContext classBody() throws RecognitionException { + ClassBodyContext _localctx = new ClassBodyContext(_ctx, getState()); + enterRule(_localctx, 32, RULE_classBody); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(453); + match(LBRACE); + setState(457); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & -1331583875988694L) != 0) + || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & 576460752338092039L) != 0) + || _la == IDENTIFIER) { + { + { + setState(454); + classBodyDeclaration(); + } + } + setState(459); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(460); + match(RBRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class InterfaceBodyContext extends ParserRuleContext { + public TerminalNode LBRACE() { + return getToken(JavaParser.LBRACE, 0); + } + + public TerminalNode RBRACE() { + return getToken(JavaParser.RBRACE, 0); + } + + public List interfaceBodyDeclaration() { + return getRuleContexts(InterfaceBodyDeclarationContext.class); + } + + public InterfaceBodyDeclarationContext interfaceBodyDeclaration(int i) { + return getRuleContext(InterfaceBodyDeclarationContext.class, i); + } + + public InterfaceBodyContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_interfaceBody; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterInterfaceBody(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitInterfaceBody(this); + } + } + + public final InterfaceBodyContext interfaceBody() throws RecognitionException { + InterfaceBodyContext _localctx = new InterfaceBodyContext(_ctx, getState()); + enterRule(_localctx, 34, RULE_interfaceBody); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(462); + match(LBRACE); + setState(466); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & -1331583875984598L) != 0) + || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & 576460752338026503L) != 0) + || _la == IDENTIFIER) { + { + { + setState(463); + interfaceBodyDeclaration(); + } + } + setState(468); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(469); + match(RBRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ClassBodyDeclarationContext extends ParserRuleContext { + public TerminalNode SEMI() { + return getToken(JavaParser.SEMI, 0); + } + + public BlockContext block() { + return getRuleContext(BlockContext.class, 0); + } + + public TerminalNode STATIC() { + return getToken(JavaParser.STATIC, 0); + } + + public MemberDeclarationContext memberDeclaration() { + return getRuleContext(MemberDeclarationContext.class, 0); + } + + public List modifier() { + return getRuleContexts(ModifierContext.class); + } + + public ModifierContext modifier(int i) { + return getRuleContext(ModifierContext.class, i); + } + + public ClassBodyDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_classBodyDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterClassBodyDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitClassBodyDeclaration(this); + } + } + + public final ClassBodyDeclarationContext classBodyDeclaration() throws RecognitionException { + ClassBodyDeclarationContext _localctx = new ClassBodyDeclarationContext(_ctx, getState()); + enterRule(_localctx, 36, RULE_classBodyDeclaration); + int _la; + try { + int _alt; + setState(483); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 40, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(471); + match(SEMI); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(473); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == STATIC) { + { + setState(472); + match(STATIC); + } + } + + setState(475); + block(); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(479); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 39, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(476); + modifier(); + } + } + } + setState(481); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 39, _ctx); + } + setState(482); + memberDeclaration(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class MemberDeclarationContext extends ParserRuleContext { + public RecordDeclarationContext recordDeclaration() { + return getRuleContext(RecordDeclarationContext.class, 0); + } + + public MethodDeclarationContext methodDeclaration() { + return getRuleContext(MethodDeclarationContext.class, 0); + } + + public GenericMethodDeclarationContext genericMethodDeclaration() { + return getRuleContext(GenericMethodDeclarationContext.class, 0); + } + + public FieldDeclarationContext fieldDeclaration() { + return getRuleContext(FieldDeclarationContext.class, 0); + } + + public ConstructorDeclarationContext constructorDeclaration() { + return getRuleContext(ConstructorDeclarationContext.class, 0); + } + + public GenericConstructorDeclarationContext genericConstructorDeclaration() { + return getRuleContext(GenericConstructorDeclarationContext.class, 0); + } + + public InterfaceDeclarationContext interfaceDeclaration() { + return getRuleContext(InterfaceDeclarationContext.class, 0); + } + + public AnnotationTypeDeclarationContext annotationTypeDeclaration() { + return getRuleContext(AnnotationTypeDeclarationContext.class, 0); + } + + public ClassDeclarationContext classDeclaration() { + return getRuleContext(ClassDeclarationContext.class, 0); + } + + public EnumDeclarationContext enumDeclaration() { + return getRuleContext(EnumDeclarationContext.class, 0); + } + + public MemberDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_memberDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterMemberDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitMemberDeclaration(this); + } + } + + public final MemberDeclarationContext memberDeclaration() throws RecognitionException { + MemberDeclarationContext _localctx = new MemberDeclarationContext(_ctx, getState()); + enterRule(_localctx, 38, RULE_memberDeclaration); + try { + setState(495); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 41, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(485); + recordDeclaration(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(486); + methodDeclaration(); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(487); + genericMethodDeclaration(); + } + break; + case 4: + enterOuterAlt(_localctx, 4); + { + setState(488); + fieldDeclaration(); + } + break; + case 5: + enterOuterAlt(_localctx, 5); + { + setState(489); + constructorDeclaration(); + } + break; + case 6: + enterOuterAlt(_localctx, 6); + { + setState(490); + genericConstructorDeclaration(); + } + break; + case 7: + enterOuterAlt(_localctx, 7); + { + setState(491); + interfaceDeclaration(); + } + break; + case 8: + enterOuterAlt(_localctx, 8); + { + setState(492); + annotationTypeDeclaration(); + } + break; + case 9: + enterOuterAlt(_localctx, 9); + { + setState(493); + classDeclaration(); + } + break; + case 10: + enterOuterAlt(_localctx, 10); + { + setState(494); + enumDeclaration(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class MethodDeclarationContext extends ParserRuleContext { + public TypeTypeOrVoidContext typeTypeOrVoid() { + return getRuleContext(TypeTypeOrVoidContext.class, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public FormalParametersContext formalParameters() { + return getRuleContext(FormalParametersContext.class, 0); + } + + public MethodBodyContext methodBody() { + return getRuleContext(MethodBodyContext.class, 0); + } + + public List LBRACK() { + return getTokens(JavaParser.LBRACK); + } + + public TerminalNode LBRACK(int i) { + return getToken(JavaParser.LBRACK, i); + } + + public List RBRACK() { + return getTokens(JavaParser.RBRACK); + } + + public TerminalNode RBRACK(int i) { + return getToken(JavaParser.RBRACK, i); + } + + public TerminalNode THROWS() { + return getToken(JavaParser.THROWS, 0); + } + + public QualifiedNameListContext qualifiedNameList() { + return getRuleContext(QualifiedNameListContext.class, 0); + } + + public MethodDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_methodDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterMethodDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitMethodDeclaration(this); + } + } + + public final MethodDeclarationContext methodDeclaration() throws RecognitionException { + MethodDeclarationContext _localctx = new MethodDeclarationContext(_ctx, getState()); + enterRule(_localctx, 40, RULE_methodDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(497); + typeTypeOrVoid(); + setState(498); + identifier(); + setState(499); + formalParameters(); + setState(504); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == LBRACK) { + { + { + setState(500); + match(LBRACK); + setState(501); + match(RBRACK); + } + } + setState(506); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(509); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == THROWS) { + { + setState(507); + match(THROWS); + setState(508); + qualifiedNameList(); + } + } + + setState(511); + methodBody(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class MethodBodyContext extends ParserRuleContext { + public BlockContext block() { + return getRuleContext(BlockContext.class, 0); + } + + public TerminalNode SEMI() { + return getToken(JavaParser.SEMI, 0); + } + + public MethodBodyContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_methodBody; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterMethodBody(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitMethodBody(this); + } + } + + public final MethodBodyContext methodBody() throws RecognitionException { + MethodBodyContext _localctx = new MethodBodyContext(_ctx, getState()); + enterRule(_localctx, 42, RULE_methodBody); + try { + setState(515); + _errHandler.sync(this); + switch (_input.LA(1)) { + case LBRACE: + enterOuterAlt(_localctx, 1); + { + setState(513); + block(); + } + break; + case SEMI: + enterOuterAlt(_localctx, 2); + { + setState(514); + match(SEMI); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class TypeTypeOrVoidContext extends ParserRuleContext { + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public TerminalNode VOID() { + return getToken(JavaParser.VOID, 0); + } + + public TypeTypeOrVoidContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_typeTypeOrVoid; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterTypeTypeOrVoid(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitTypeTypeOrVoid(this); + } + } + + public final TypeTypeOrVoidContext typeTypeOrVoid() throws RecognitionException { + TypeTypeOrVoidContext _localctx = new TypeTypeOrVoidContext(_ctx, getState()); + enterRule(_localctx, 44, RULE_typeTypeOrVoid); + try { + setState(519); + _errHandler.sync(this); + switch (_input.LA(1)) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case AT: + case IDENTIFIER: + enterOuterAlt(_localctx, 1); + { + setState(517); + typeType(); + } + break; + case VOID: + enterOuterAlt(_localctx, 2); + { + setState(518); + match(VOID); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class GenericMethodDeclarationContext extends ParserRuleContext { + public TypeParametersContext typeParameters() { + return getRuleContext(TypeParametersContext.class, 0); + } + + public MethodDeclarationContext methodDeclaration() { + return getRuleContext(MethodDeclarationContext.class, 0); + } + + public GenericMethodDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_genericMethodDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterGenericMethodDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitGenericMethodDeclaration(this); + } + } + + public final GenericMethodDeclarationContext genericMethodDeclaration() throws RecognitionException { + GenericMethodDeclarationContext _localctx = new GenericMethodDeclarationContext(_ctx, getState()); + enterRule(_localctx, 46, RULE_genericMethodDeclaration); + try { + enterOuterAlt(_localctx, 1); + { + setState(521); + typeParameters(); + setState(522); + methodDeclaration(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class GenericConstructorDeclarationContext extends ParserRuleContext { + public TypeParametersContext typeParameters() { + return getRuleContext(TypeParametersContext.class, 0); + } + + public ConstructorDeclarationContext constructorDeclaration() { + return getRuleContext(ConstructorDeclarationContext.class, 0); + } + + public GenericConstructorDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_genericConstructorDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterGenericConstructorDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitGenericConstructorDeclaration(this); + } + } + + public final GenericConstructorDeclarationContext genericConstructorDeclaration() throws RecognitionException { + GenericConstructorDeclarationContext _localctx = new GenericConstructorDeclarationContext(_ctx, getState()); + enterRule(_localctx, 48, RULE_genericConstructorDeclaration); + try { + enterOuterAlt(_localctx, 1); + { + setState(524); + typeParameters(); + setState(525); + constructorDeclaration(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ConstructorDeclarationContext extends ParserRuleContext { + public BlockContext constructorBody; + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public FormalParametersContext formalParameters() { + return getRuleContext(FormalParametersContext.class, 0); + } + + public BlockContext block() { + return getRuleContext(BlockContext.class, 0); + } + + public TerminalNode THROWS() { + return getToken(JavaParser.THROWS, 0); + } + + public QualifiedNameListContext qualifiedNameList() { + return getRuleContext(QualifiedNameListContext.class, 0); + } + + public ConstructorDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_constructorDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterConstructorDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitConstructorDeclaration(this); + } + } + + public final ConstructorDeclarationContext constructorDeclaration() throws RecognitionException { + ConstructorDeclarationContext _localctx = new ConstructorDeclarationContext(_ctx, getState()); + enterRule(_localctx, 50, RULE_constructorDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(527); + identifier(); + setState(528); + formalParameters(); + setState(531); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == THROWS) { + { + setState(529); + match(THROWS); + setState(530); + qualifiedNameList(); + } + } + + setState(533); + ((ConstructorDeclarationContext) _localctx).constructorBody = block(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class CompactConstructorDeclarationContext extends ParserRuleContext { + public BlockContext constructorBody; + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public BlockContext block() { + return getRuleContext(BlockContext.class, 0); + } + + public List modifier() { + return getRuleContexts(ModifierContext.class); + } + + public ModifierContext modifier(int i) { + return getRuleContext(ModifierContext.class, i); + } + + public CompactConstructorDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_compactConstructorDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterCompactConstructorDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitCompactConstructorDeclaration(this); + } + } + + public final CompactConstructorDeclarationContext compactConstructorDeclaration() throws RecognitionException { + CompactConstructorDeclarationContext _localctx = new CompactConstructorDeclarationContext(_ctx, getState()); + enterRule(_localctx, 52, RULE_compactConstructorDeclaration); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(538); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 47, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(535); + modifier(); + } + } + } + setState(540); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 47, _ctx); + } + setState(541); + identifier(); + setState(542); + ((CompactConstructorDeclarationContext) _localctx).constructorBody = block(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class FieldDeclarationContext extends ParserRuleContext { + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public VariableDeclaratorsContext variableDeclarators() { + return getRuleContext(VariableDeclaratorsContext.class, 0); + } + + public TerminalNode SEMI() { + return getToken(JavaParser.SEMI, 0); + } + + public FieldDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_fieldDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterFieldDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitFieldDeclaration(this); + } + } + + public final FieldDeclarationContext fieldDeclaration() throws RecognitionException { + FieldDeclarationContext _localctx = new FieldDeclarationContext(_ctx, getState()); + enterRule(_localctx, 54, RULE_fieldDeclaration); + try { + enterOuterAlt(_localctx, 1); + { + setState(544); + typeType(); + setState(545); + variableDeclarators(); + setState(546); + match(SEMI); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class InterfaceBodyDeclarationContext extends ParserRuleContext { + public InterfaceMemberDeclarationContext interfaceMemberDeclaration() { + return getRuleContext(InterfaceMemberDeclarationContext.class, 0); + } + + public List modifier() { + return getRuleContexts(ModifierContext.class); + } + + public ModifierContext modifier(int i) { + return getRuleContext(ModifierContext.class, i); + } + + public TerminalNode SEMI() { + return getToken(JavaParser.SEMI, 0); + } + + public InterfaceBodyDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_interfaceBodyDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterInterfaceBodyDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitInterfaceBodyDeclaration(this); + } + } + + public final InterfaceBodyDeclarationContext interfaceBodyDeclaration() throws RecognitionException { + InterfaceBodyDeclarationContext _localctx = new InterfaceBodyDeclarationContext(_ctx, getState()); + enterRule(_localctx, 56, RULE_interfaceBodyDeclaration); + try { + int _alt; + setState(556); + _errHandler.sync(this); + switch (_input.LA(1)) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case CLASS: + case DEFAULT: + case DOUBLE: + case ENUM: + case FINAL: + case FLOAT: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOID: + case VOLATILE: + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case NON_SEALED: + case LT: + case AT: + case IDENTIFIER: + enterOuterAlt(_localctx, 1); + { + setState(551); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 48, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(548); + modifier(); + } + } + } + setState(553); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 48, _ctx); + } + setState(554); + interfaceMemberDeclaration(); + } + break; + case SEMI: + enterOuterAlt(_localctx, 2); + { + setState(555); + match(SEMI); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class InterfaceMemberDeclarationContext extends ParserRuleContext { + public RecordDeclarationContext recordDeclaration() { + return getRuleContext(RecordDeclarationContext.class, 0); + } + + public ConstDeclarationContext constDeclaration() { + return getRuleContext(ConstDeclarationContext.class, 0); + } + + public InterfaceMethodDeclarationContext interfaceMethodDeclaration() { + return getRuleContext(InterfaceMethodDeclarationContext.class, 0); + } + + public GenericInterfaceMethodDeclarationContext genericInterfaceMethodDeclaration() { + return getRuleContext(GenericInterfaceMethodDeclarationContext.class, 0); + } + + public InterfaceDeclarationContext interfaceDeclaration() { + return getRuleContext(InterfaceDeclarationContext.class, 0); + } + + public AnnotationTypeDeclarationContext annotationTypeDeclaration() { + return getRuleContext(AnnotationTypeDeclarationContext.class, 0); + } + + public ClassDeclarationContext classDeclaration() { + return getRuleContext(ClassDeclarationContext.class, 0); + } + + public EnumDeclarationContext enumDeclaration() { + return getRuleContext(EnumDeclarationContext.class, 0); + } + + public InterfaceMemberDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_interfaceMemberDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterInterfaceMemberDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitInterfaceMemberDeclaration(this); + } + } + + public final InterfaceMemberDeclarationContext interfaceMemberDeclaration() throws RecognitionException { + InterfaceMemberDeclarationContext _localctx = new InterfaceMemberDeclarationContext(_ctx, getState()); + enterRule(_localctx, 58, RULE_interfaceMemberDeclaration); + try { + setState(566); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 50, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(558); + recordDeclaration(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(559); + constDeclaration(); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(560); + interfaceMethodDeclaration(); + } + break; + case 4: + enterOuterAlt(_localctx, 4); + { + setState(561); + genericInterfaceMethodDeclaration(); + } + break; + case 5: + enterOuterAlt(_localctx, 5); + { + setState(562); + interfaceDeclaration(); + } + break; + case 6: + enterOuterAlt(_localctx, 6); + { + setState(563); + annotationTypeDeclaration(); + } + break; + case 7: + enterOuterAlt(_localctx, 7); + { + setState(564); + classDeclaration(); + } + break; + case 8: + enterOuterAlt(_localctx, 8); + { + setState(565); + enumDeclaration(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ConstDeclarationContext extends ParserRuleContext { + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public List constantDeclarator() { + return getRuleContexts(ConstantDeclaratorContext.class); + } + + public ConstantDeclaratorContext constantDeclarator(int i) { + return getRuleContext(ConstantDeclaratorContext.class, i); + } + + public TerminalNode SEMI() { + return getToken(JavaParser.SEMI, 0); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public ConstDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_constDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterConstDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitConstDeclaration(this); + } + } + + public final ConstDeclarationContext constDeclaration() throws RecognitionException { + ConstDeclarationContext _localctx = new ConstDeclarationContext(_ctx, getState()); + enterRule(_localctx, 60, RULE_constDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(568); + typeType(); + setState(569); + constantDeclarator(); + setState(574); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == COMMA) { + { + { + setState(570); + match(COMMA); + setState(571); + constantDeclarator(); + } + } + setState(576); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(577); + match(SEMI); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ConstantDeclaratorContext extends ParserRuleContext { + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public TerminalNode ASSIGN() { + return getToken(JavaParser.ASSIGN, 0); + } + + public VariableInitializerContext variableInitializer() { + return getRuleContext(VariableInitializerContext.class, 0); + } + + public List LBRACK() { + return getTokens(JavaParser.LBRACK); + } + + public TerminalNode LBRACK(int i) { + return getToken(JavaParser.LBRACK, i); + } + + public List RBRACK() { + return getTokens(JavaParser.RBRACK); + } + + public TerminalNode RBRACK(int i) { + return getToken(JavaParser.RBRACK, i); + } + + public ConstantDeclaratorContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_constantDeclarator; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterConstantDeclarator(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitConstantDeclarator(this); + } + } + + public final ConstantDeclaratorContext constantDeclarator() throws RecognitionException { + ConstantDeclaratorContext _localctx = new ConstantDeclaratorContext(_ctx, getState()); + enterRule(_localctx, 62, RULE_constantDeclarator); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(579); + identifier(); + setState(584); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == LBRACK) { + { + { + setState(580); + match(LBRACK); + setState(581); + match(RBRACK); + } + } + setState(586); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(587); + match(ASSIGN); + setState(588); + variableInitializer(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class InterfaceMethodDeclarationContext extends ParserRuleContext { + public InterfaceCommonBodyDeclarationContext interfaceCommonBodyDeclaration() { + return getRuleContext(InterfaceCommonBodyDeclarationContext.class, 0); + } + + public List interfaceMethodModifier() { + return getRuleContexts(InterfaceMethodModifierContext.class); + } + + public InterfaceMethodModifierContext interfaceMethodModifier(int i) { + return getRuleContext(InterfaceMethodModifierContext.class, i); + } + + public InterfaceMethodDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_interfaceMethodDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterInterfaceMethodDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitInterfaceMethodDeclaration(this); + } + } + + public final InterfaceMethodDeclarationContext interfaceMethodDeclaration() throws RecognitionException { + InterfaceMethodDeclarationContext _localctx = new InterfaceMethodDeclarationContext(_ctx, getState()); + enterRule(_localctx, 64, RULE_interfaceMethodDeclaration); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(593); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 53, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(590); + interfaceMethodModifier(); + } + } + } + setState(595); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 53, _ctx); + } + setState(596); + interfaceCommonBodyDeclaration(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class InterfaceMethodModifierContext extends ParserRuleContext { + public AnnotationContext annotation() { + return getRuleContext(AnnotationContext.class, 0); + } + + public TerminalNode PUBLIC() { + return getToken(JavaParser.PUBLIC, 0); + } + + public TerminalNode ABSTRACT() { + return getToken(JavaParser.ABSTRACT, 0); + } + + public TerminalNode DEFAULT() { + return getToken(JavaParser.DEFAULT, 0); + } + + public TerminalNode STATIC() { + return getToken(JavaParser.STATIC, 0); + } + + public TerminalNode STRICTFP() { + return getToken(JavaParser.STRICTFP, 0); + } + + public InterfaceMethodModifierContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_interfaceMethodModifier; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterInterfaceMethodModifier(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitInterfaceMethodModifier(this); + } + } + + public final InterfaceMethodModifierContext interfaceMethodModifier() throws RecognitionException { + InterfaceMethodModifierContext _localctx = new InterfaceMethodModifierContext(_ctx, getState()); + enterRule(_localctx, 66, RULE_interfaceMethodModifier); + try { + setState(604); + _errHandler.sync(this); + switch (_input.LA(1)) { + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case AT: + case IDENTIFIER: + enterOuterAlt(_localctx, 1); + { + setState(598); + annotation(); + } + break; + case PUBLIC: + enterOuterAlt(_localctx, 2); + { + setState(599); + match(PUBLIC); + } + break; + case ABSTRACT: + enterOuterAlt(_localctx, 3); + { + setState(600); + match(ABSTRACT); + } + break; + case DEFAULT: + enterOuterAlt(_localctx, 4); + { + setState(601); + match(DEFAULT); + } + break; + case STATIC: + enterOuterAlt(_localctx, 5); + { + setState(602); + match(STATIC); + } + break; + case STRICTFP: + enterOuterAlt(_localctx, 6); + { + setState(603); + match(STRICTFP); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class GenericInterfaceMethodDeclarationContext extends ParserRuleContext { + public TypeParametersContext typeParameters() { + return getRuleContext(TypeParametersContext.class, 0); + } + + public InterfaceCommonBodyDeclarationContext interfaceCommonBodyDeclaration() { + return getRuleContext(InterfaceCommonBodyDeclarationContext.class, 0); + } + + public List interfaceMethodModifier() { + return getRuleContexts(InterfaceMethodModifierContext.class); + } + + public InterfaceMethodModifierContext interfaceMethodModifier(int i) { + return getRuleContext(InterfaceMethodModifierContext.class, i); + } + + public GenericInterfaceMethodDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_genericInterfaceMethodDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterGenericInterfaceMethodDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitGenericInterfaceMethodDeclaration(this); + } + } + + public final GenericInterfaceMethodDeclarationContext genericInterfaceMethodDeclaration() + throws RecognitionException { + GenericInterfaceMethodDeclarationContext _localctx = + new GenericInterfaceMethodDeclarationContext(_ctx, getState()); + enterRule(_localctx, 68, RULE_genericInterfaceMethodDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(609); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & -2250940820221950L) != 0) + || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & 576460752303423491L) != 0) + || _la == IDENTIFIER) { + { + { + setState(606); + interfaceMethodModifier(); + } + } + setState(611); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(612); + typeParameters(); + setState(613); + interfaceCommonBodyDeclaration(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class InterfaceCommonBodyDeclarationContext extends ParserRuleContext { + public TypeTypeOrVoidContext typeTypeOrVoid() { + return getRuleContext(TypeTypeOrVoidContext.class, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public FormalParametersContext formalParameters() { + return getRuleContext(FormalParametersContext.class, 0); + } + + public MethodBodyContext methodBody() { + return getRuleContext(MethodBodyContext.class, 0); + } + + public List annotation() { + return getRuleContexts(AnnotationContext.class); + } + + public AnnotationContext annotation(int i) { + return getRuleContext(AnnotationContext.class, i); + } + + public List LBRACK() { + return getTokens(JavaParser.LBRACK); + } + + public TerminalNode LBRACK(int i) { + return getToken(JavaParser.LBRACK, i); + } + + public List RBRACK() { + return getTokens(JavaParser.RBRACK); + } + + public TerminalNode RBRACK(int i) { + return getToken(JavaParser.RBRACK, i); + } + + public TerminalNode THROWS() { + return getToken(JavaParser.THROWS, 0); + } + + public QualifiedNameListContext qualifiedNameList() { + return getRuleContext(QualifiedNameListContext.class, 0); + } + + public InterfaceCommonBodyDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_interfaceCommonBodyDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterInterfaceCommonBodyDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitInterfaceCommonBodyDeclaration(this); + } + } + + public final InterfaceCommonBodyDeclarationContext interfaceCommonBodyDeclaration() throws RecognitionException { + InterfaceCommonBodyDeclarationContext _localctx = new InterfaceCommonBodyDeclarationContext(_ctx, getState()); + enterRule(_localctx, 70, RULE_interfaceCommonBodyDeclaration); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(618); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 56, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(615); + annotation(); + } + } + } + setState(620); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 56, _ctx); + } + setState(621); + typeTypeOrVoid(); + setState(622); + identifier(); + setState(623); + formalParameters(); + setState(628); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == LBRACK) { + { + { + setState(624); + match(LBRACK); + setState(625); + match(RBRACK); + } + } + setState(630); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(633); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == THROWS) { + { + setState(631); + match(THROWS); + setState(632); + qualifiedNameList(); + } + } + + setState(635); + methodBody(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class VariableDeclaratorsContext extends ParserRuleContext { + public List variableDeclarator() { + return getRuleContexts(VariableDeclaratorContext.class); + } + + public VariableDeclaratorContext variableDeclarator(int i) { + return getRuleContext(VariableDeclaratorContext.class, i); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public VariableDeclaratorsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_variableDeclarators; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterVariableDeclarators(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitVariableDeclarators(this); + } + } + + public final VariableDeclaratorsContext variableDeclarators() throws RecognitionException { + VariableDeclaratorsContext _localctx = new VariableDeclaratorsContext(_ctx, getState()); + enterRule(_localctx, 72, RULE_variableDeclarators); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(637); + variableDeclarator(); + setState(642); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == COMMA) { + { + { + setState(638); + match(COMMA); + setState(639); + variableDeclarator(); + } + } + setState(644); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class VariableDeclaratorContext extends ParserRuleContext { + public VariableDeclaratorIdContext variableDeclaratorId() { + return getRuleContext(VariableDeclaratorIdContext.class, 0); + } + + public TerminalNode ASSIGN() { + return getToken(JavaParser.ASSIGN, 0); + } + + public VariableInitializerContext variableInitializer() { + return getRuleContext(VariableInitializerContext.class, 0); + } + + public VariableDeclaratorContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_variableDeclarator; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterVariableDeclarator(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitVariableDeclarator(this); + } + } + + public final VariableDeclaratorContext variableDeclarator() throws RecognitionException { + VariableDeclaratorContext _localctx = new VariableDeclaratorContext(_ctx, getState()); + enterRule(_localctx, 74, RULE_variableDeclarator); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(645); + variableDeclaratorId(); + setState(648); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == ASSIGN) { + { + setState(646); + match(ASSIGN); + setState(647); + variableInitializer(); + } + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class VariableDeclaratorIdContext extends ParserRuleContext { + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public List LBRACK() { + return getTokens(JavaParser.LBRACK); + } + + public TerminalNode LBRACK(int i) { + return getToken(JavaParser.LBRACK, i); + } + + public List RBRACK() { + return getTokens(JavaParser.RBRACK); + } + + public TerminalNode RBRACK(int i) { + return getToken(JavaParser.RBRACK, i); + } + + public VariableDeclaratorIdContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_variableDeclaratorId; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterVariableDeclaratorId(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitVariableDeclaratorId(this); + } + } + + public final VariableDeclaratorIdContext variableDeclaratorId() throws RecognitionException { + VariableDeclaratorIdContext _localctx = new VariableDeclaratorIdContext(_ctx, getState()); + enterRule(_localctx, 76, RULE_variableDeclaratorId); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(650); + identifier(); + setState(655); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == LBRACK) { + { + { + setState(651); + match(LBRACK); + setState(652); + match(RBRACK); + } + } + setState(657); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class VariableInitializerContext extends ParserRuleContext { + public ArrayInitializerContext arrayInitializer() { + return getRuleContext(ArrayInitializerContext.class, 0); + } + + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class, 0); + } + + public VariableInitializerContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_variableInitializer; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterVariableInitializer(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitVariableInitializer(this); + } + } + + public final VariableInitializerContext variableInitializer() throws RecognitionException { + VariableInitializerContext _localctx = new VariableInitializerContext(_ctx, getState()); + enterRule(_localctx, 78, RULE_variableInitializer); + try { + setState(660); + _errHandler.sync(this); + switch (_input.LA(1)) { + case LBRACE: + enterOuterAlt(_localctx, 1); + { + setState(658); + arrayInitializer(); + } + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case NEW: + case SHORT: + case SUPER: + case SWITCH: + case THIS: + case VOID: + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case DECIMAL_LITERAL: + case HEX_LITERAL: + case OCT_LITERAL: + case BINARY_LITERAL: + case FLOAT_LITERAL: + case HEX_FLOAT_LITERAL: + case BOOL_LITERAL: + case CHAR_LITERAL: + case STRING_LITERAL: + case TEXT_BLOCK: + case NULL_LITERAL: + case LPAREN: + case LT: + case BANG: + case TILDE: + case INC: + case DEC: + case ADD: + case SUB: + case AT: + case IDENTIFIER: + enterOuterAlt(_localctx, 2); + { + setState(659); + expression(0); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ArrayInitializerContext extends ParserRuleContext { + public TerminalNode LBRACE() { + return getToken(JavaParser.LBRACE, 0); + } + + public TerminalNode RBRACE() { + return getToken(JavaParser.RBRACE, 0); + } + + public List variableInitializer() { + return getRuleContexts(VariableInitializerContext.class); + } + + public VariableInitializerContext variableInitializer(int i) { + return getRuleContext(VariableInitializerContext.class, i); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public ArrayInitializerContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_arrayInitializer; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterArrayInitializer(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitArrayInitializer(this); + } + } + + public final ArrayInitializerContext arrayInitializer() throws RecognitionException { + ArrayInitializerContext _localctx = new ArrayInitializerContext(_ctx, getState()); + enterRule(_localctx, 80, RULE_arrayInitializer); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(662); + match(LBRACE); + setState(674); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & 9223127275610966053L) != 0) + || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & 4683743741343707135L) != 0)) { + { + setState(663); + variableInitializer(); + setState(668); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 63, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(664); + match(COMMA); + setState(665); + variableInitializer(); + } + } + } + setState(670); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 63, _ctx); + } + setState(672); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == COMMA) { + { + setState(671); + match(COMMA); + } + } + } + } + + setState(676); + match(RBRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ClassOrInterfaceTypeContext extends ParserRuleContext { + public TypeIdentifierContext typeIdentifier() { + return getRuleContext(TypeIdentifierContext.class, 0); + } + + public List identifier() { + return getRuleContexts(IdentifierContext.class); + } + + public IdentifierContext identifier(int i) { + return getRuleContext(IdentifierContext.class, i); + } + + public List DOT() { + return getTokens(JavaParser.DOT); + } + + public TerminalNode DOT(int i) { + return getToken(JavaParser.DOT, i); + } + + public List typeArguments() { + return getRuleContexts(TypeArgumentsContext.class); + } + + public TypeArgumentsContext typeArguments(int i) { + return getRuleContext(TypeArgumentsContext.class, i); + } + + public ClassOrInterfaceTypeContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_classOrInterfaceType; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterClassOrInterfaceType(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitClassOrInterfaceType(this); + } + } + + public final ClassOrInterfaceTypeContext classOrInterfaceType() throws RecognitionException { + ClassOrInterfaceTypeContext _localctx = new ClassOrInterfaceTypeContext(_ctx, getState()); + enterRule(_localctx, 82, RULE_classOrInterfaceType); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(686); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 67, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(678); + identifier(); + setState(680); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LT) { + { + setState(679); + typeArguments(); + } + } + + setState(682); + match(DOT); + } + } + } + setState(688); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 67, _ctx); + } + setState(689); + typeIdentifier(); + setState(691); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 68, _ctx)) { + case 1: + { + setState(690); + typeArguments(); + } + break; + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class TypeArgumentContext extends ParserRuleContext { + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public TerminalNode QUESTION() { + return getToken(JavaParser.QUESTION, 0); + } + + public List annotation() { + return getRuleContexts(AnnotationContext.class); + } + + public AnnotationContext annotation(int i) { + return getRuleContext(AnnotationContext.class, i); + } + + public TerminalNode EXTENDS() { + return getToken(JavaParser.EXTENDS, 0); + } + + public TerminalNode SUPER() { + return getToken(JavaParser.SUPER, 0); + } + + public TypeArgumentContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_typeArgument; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterTypeArgument(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitTypeArgument(this); + } + } + + public final TypeArgumentContext typeArgument() throws RecognitionException { + TypeArgumentContext _localctx = new TypeArgumentContext(_ctx, getState()); + enterRule(_localctx, 84, RULE_typeArgument); + int _la; + try { + setState(705); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 71, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(693); + typeType(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(697); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 51)) & ~0x3f) == 0 && ((1L << (_la - 51)) & 32767L) != 0) + || _la == AT + || _la == IDENTIFIER) { + { + { + setState(694); + annotation(); + } + } + setState(699); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(700); + match(QUESTION); + setState(703); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == EXTENDS || _la == SUPER) { + { + setState(701); + _la = _input.LA(1); + if (!(_la == EXTENDS || _la == SUPER)) { + _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(702); + typeType(); + } + } + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class QualifiedNameListContext extends ParserRuleContext { + public List qualifiedName() { + return getRuleContexts(QualifiedNameContext.class); + } + + public QualifiedNameContext qualifiedName(int i) { + return getRuleContext(QualifiedNameContext.class, i); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public QualifiedNameListContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_qualifiedNameList; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterQualifiedNameList(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitQualifiedNameList(this); + } + } + + public final QualifiedNameListContext qualifiedNameList() throws RecognitionException { + QualifiedNameListContext _localctx = new QualifiedNameListContext(_ctx, getState()); + enterRule(_localctx, 86, RULE_qualifiedNameList); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(707); + qualifiedName(); + setState(712); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == COMMA) { + { + { + setState(708); + match(COMMA); + setState(709); + qualifiedName(); + } + } + setState(714); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class FormalParametersContext extends ParserRuleContext { + public TerminalNode LPAREN() { + return getToken(JavaParser.LPAREN, 0); + } + + public TerminalNode RPAREN() { + return getToken(JavaParser.RPAREN, 0); + } + + public ReceiverParameterContext receiverParameter() { + return getRuleContext(ReceiverParameterContext.class, 0); + } + + public TerminalNode COMMA() { + return getToken(JavaParser.COMMA, 0); + } + + public FormalParameterListContext formalParameterList() { + return getRuleContext(FormalParameterListContext.class, 0); + } + + public FormalParametersContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_formalParameters; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterFormalParameters(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitFormalParameters(this); + } + } + + public final FormalParametersContext formalParameters() throws RecognitionException { + FormalParametersContext _localctx = new FormalParametersContext(_ctx, getState()); + enterRule(_localctx, 88, RULE_formalParameters); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(715); + match(LPAREN); + setState(727); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 76, _ctx)) { + case 1: + { + setState(717); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & 9223090579141953573L) != 0) + || _la == AT + || _la == IDENTIFIER) { + { + setState(716); + receiverParameter(); + } + } + } + break; + case 2: + { + setState(719); + receiverParameter(); + setState(722); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == COMMA) { + { + setState(720); + match(COMMA); + setState(721); + formalParameterList(); + } + } + } + break; + case 3: + { + setState(725); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & 9223090579141986341L) != 0) + || _la == AT + || _la == IDENTIFIER) { + { + setState(724); + formalParameterList(); + } + } + } + break; + } + setState(729); + match(RPAREN); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ReceiverParameterContext extends ParserRuleContext { + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public TerminalNode THIS() { + return getToken(JavaParser.THIS, 0); + } + + public List identifier() { + return getRuleContexts(IdentifierContext.class); + } + + public IdentifierContext identifier(int i) { + return getRuleContext(IdentifierContext.class, i); + } + + public List DOT() { + return getTokens(JavaParser.DOT); + } + + public TerminalNode DOT(int i) { + return getToken(JavaParser.DOT, i); + } + + public ReceiverParameterContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_receiverParameter; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterReceiverParameter(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitReceiverParameter(this); + } + } + + public final ReceiverParameterContext receiverParameter() throws RecognitionException { + ReceiverParameterContext _localctx = new ReceiverParameterContext(_ctx, getState()); + enterRule(_localctx, 90, RULE_receiverParameter); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(731); + typeType(); + setState(737); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 51)) & ~0x3f) == 0 && ((1L << (_la - 51)) & 32767L) != 0) || _la == IDENTIFIER) { + { + { + setState(732); + identifier(); + setState(733); + match(DOT); + } + } + setState(739); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(740); + match(THIS); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class FormalParameterListContext extends ParserRuleContext { + public List formalParameter() { + return getRuleContexts(FormalParameterContext.class); + } + + public FormalParameterContext formalParameter(int i) { + return getRuleContext(FormalParameterContext.class, i); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public LastFormalParameterContext lastFormalParameter() { + return getRuleContext(LastFormalParameterContext.class, 0); + } + + public FormalParameterListContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_formalParameterList; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterFormalParameterList(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitFormalParameterList(this); + } + } + + public final FormalParameterListContext formalParameterList() throws RecognitionException { + FormalParameterListContext _localctx = new FormalParameterListContext(_ctx, getState()); + enterRule(_localctx, 92, RULE_formalParameterList); + int _la; + try { + int _alt; + setState(755); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 80, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(742); + formalParameter(); + setState(747); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 78, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(743); + match(COMMA); + setState(744); + formalParameter(); + } + } + } + setState(749); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 78, _ctx); + } + setState(752); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == COMMA) { + { + setState(750); + match(COMMA); + setState(751); + lastFormalParameter(); + } + } + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(754); + lastFormalParameter(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class FormalParameterContext extends ParserRuleContext { + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public VariableDeclaratorIdContext variableDeclaratorId() { + return getRuleContext(VariableDeclaratorIdContext.class, 0); + } + + public List variableModifier() { + return getRuleContexts(VariableModifierContext.class); + } + + public VariableModifierContext variableModifier(int i) { + return getRuleContext(VariableModifierContext.class, i); + } + + public FormalParameterContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_formalParameter; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterFormalParameter(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitFormalParameter(this); + } + } + + public final FormalParameterContext formalParameter() throws RecognitionException { + FormalParameterContext _localctx = new FormalParameterContext(_ctx, getState()); + enterRule(_localctx, 94, RULE_formalParameter); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(760); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 81, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(757); + variableModifier(); + } + } + } + setState(762); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 81, _ctx); + } + setState(763); + typeType(); + setState(764); + variableDeclaratorId(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class LastFormalParameterContext extends ParserRuleContext { + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public TerminalNode ELLIPSIS() { + return getToken(JavaParser.ELLIPSIS, 0); + } + + public VariableDeclaratorIdContext variableDeclaratorId() { + return getRuleContext(VariableDeclaratorIdContext.class, 0); + } + + public List variableModifier() { + return getRuleContexts(VariableModifierContext.class); + } + + public VariableModifierContext variableModifier(int i) { + return getRuleContext(VariableModifierContext.class, i); + } + + public List annotation() { + return getRuleContexts(AnnotationContext.class); + } + + public AnnotationContext annotation(int i) { + return getRuleContext(AnnotationContext.class, i); + } + + public LastFormalParameterContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_lastFormalParameter; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterLastFormalParameter(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitLastFormalParameter(this); + } + } + + public final LastFormalParameterContext lastFormalParameter() throws RecognitionException { + LastFormalParameterContext _localctx = new LastFormalParameterContext(_ctx, getState()); + enterRule(_localctx, 96, RULE_lastFormalParameter); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(769); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 82, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(766); + variableModifier(); + } + } + } + setState(771); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 82, _ctx); + } + setState(772); + typeType(); + setState(776); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 51)) & ~0x3f) == 0 && ((1L << (_la - 51)) & 32767L) != 0) + || _la == AT + || _la == IDENTIFIER) { + { + { + setState(773); + annotation(); + } + } + setState(778); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(779); + match(ELLIPSIS); + setState(780); + variableDeclaratorId(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class LambdaLVTIListContext extends ParserRuleContext { + public List lambdaLVTIParameter() { + return getRuleContexts(LambdaLVTIParameterContext.class); + } + + public LambdaLVTIParameterContext lambdaLVTIParameter(int i) { + return getRuleContext(LambdaLVTIParameterContext.class, i); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public LambdaLVTIListContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_lambdaLVTIList; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterLambdaLVTIList(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitLambdaLVTIList(this); + } + } + + public final LambdaLVTIListContext lambdaLVTIList() throws RecognitionException { + LambdaLVTIListContext _localctx = new LambdaLVTIListContext(_ctx, getState()); + enterRule(_localctx, 98, RULE_lambdaLVTIList); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(782); + lambdaLVTIParameter(); + setState(787); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == COMMA) { + { + { + setState(783); + match(COMMA); + setState(784); + lambdaLVTIParameter(); + } + } + setState(789); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class LambdaLVTIParameterContext extends ParserRuleContext { + public TerminalNode VAR() { + return getToken(JavaParser.VAR, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public List variableModifier() { + return getRuleContexts(VariableModifierContext.class); + } + + public VariableModifierContext variableModifier(int i) { + return getRuleContext(VariableModifierContext.class, i); + } + + public LambdaLVTIParameterContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_lambdaLVTIParameter; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterLambdaLVTIParameter(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitLambdaLVTIParameter(this); + } + } + + public final LambdaLVTIParameterContext lambdaLVTIParameter() throws RecognitionException { + LambdaLVTIParameterContext _localctx = new LambdaLVTIParameterContext(_ctx, getState()); + enterRule(_localctx, 100, RULE_lambdaLVTIParameter); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(793); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 85, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(790); + variableModifier(); + } + } + } + setState(795); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 85, _ctx); + } + setState(796); + match(VAR); + setState(797); + identifier(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class QualifiedNameContext extends ParserRuleContext { + public List identifier() { + return getRuleContexts(IdentifierContext.class); + } + + public IdentifierContext identifier(int i) { + return getRuleContext(IdentifierContext.class, i); + } + + public List DOT() { + return getTokens(JavaParser.DOT); + } + + public TerminalNode DOT(int i) { + return getToken(JavaParser.DOT, i); + } + + public QualifiedNameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_qualifiedName; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterQualifiedName(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitQualifiedName(this); + } + } + + public final QualifiedNameContext qualifiedName() throws RecognitionException { + QualifiedNameContext _localctx = new QualifiedNameContext(_ctx, getState()); + enterRule(_localctx, 102, RULE_qualifiedName); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(799); + identifier(); + setState(804); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 86, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(800); + match(DOT); + setState(801); + identifier(); + } + } + } + setState(806); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 86, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class LiteralContext extends ParserRuleContext { + public IntegerLiteralContext integerLiteral() { + return getRuleContext(IntegerLiteralContext.class, 0); + } + + public FloatLiteralContext floatLiteral() { + return getRuleContext(FloatLiteralContext.class, 0); + } + + public TerminalNode CHAR_LITERAL() { + return getToken(JavaParser.CHAR_LITERAL, 0); + } + + public TerminalNode STRING_LITERAL() { + return getToken(JavaParser.STRING_LITERAL, 0); + } + + public TerminalNode BOOL_LITERAL() { + return getToken(JavaParser.BOOL_LITERAL, 0); + } + + public TerminalNode NULL_LITERAL() { + return getToken(JavaParser.NULL_LITERAL, 0); + } + + public TerminalNode TEXT_BLOCK() { + return getToken(JavaParser.TEXT_BLOCK, 0); + } + + public LiteralContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_literal; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterLiteral(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitLiteral(this); + } + } + + public final LiteralContext literal() throws RecognitionException { + LiteralContext _localctx = new LiteralContext(_ctx, getState()); + enterRule(_localctx, 104, RULE_literal); + try { + setState(814); + _errHandler.sync(this); + switch (_input.LA(1)) { + case DECIMAL_LITERAL: + case HEX_LITERAL: + case OCT_LITERAL: + case BINARY_LITERAL: + enterOuterAlt(_localctx, 1); + { + setState(807); + integerLiteral(); + } + break; + case FLOAT_LITERAL: + case HEX_FLOAT_LITERAL: + enterOuterAlt(_localctx, 2); + { + setState(808); + floatLiteral(); + } + break; + case CHAR_LITERAL: + enterOuterAlt(_localctx, 3); + { + setState(809); + match(CHAR_LITERAL); + } + break; + case STRING_LITERAL: + enterOuterAlt(_localctx, 4); + { + setState(810); + match(STRING_LITERAL); + } + break; + case BOOL_LITERAL: + enterOuterAlt(_localctx, 5); + { + setState(811); + match(BOOL_LITERAL); + } + break; + case NULL_LITERAL: + enterOuterAlt(_localctx, 6); + { + setState(812); + match(NULL_LITERAL); + } + break; + case TEXT_BLOCK: + enterOuterAlt(_localctx, 7); + { + setState(813); + match(TEXT_BLOCK); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class IntegerLiteralContext extends ParserRuleContext { + public TerminalNode DECIMAL_LITERAL() { + return getToken(JavaParser.DECIMAL_LITERAL, 0); + } + + public TerminalNode HEX_LITERAL() { + return getToken(JavaParser.HEX_LITERAL, 0); + } + + public TerminalNode OCT_LITERAL() { + return getToken(JavaParser.OCT_LITERAL, 0); + } + + public TerminalNode BINARY_LITERAL() { + return getToken(JavaParser.BINARY_LITERAL, 0); + } + + public IntegerLiteralContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_integerLiteral; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterIntegerLiteral(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitIntegerLiteral(this); + } + } + + public final IntegerLiteralContext integerLiteral() throws RecognitionException { + IntegerLiteralContext _localctx = new IntegerLiteralContext(_ctx, getState()); + enterRule(_localctx, 106, RULE_integerLiteral); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(816); + _la = _input.LA(1); + if (!(((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & 15L) != 0))) { + _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class FloatLiteralContext extends ParserRuleContext { + public TerminalNode FLOAT_LITERAL() { + return getToken(JavaParser.FLOAT_LITERAL, 0); + } + + public TerminalNode HEX_FLOAT_LITERAL() { + return getToken(JavaParser.HEX_FLOAT_LITERAL, 0); + } + + public FloatLiteralContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_floatLiteral; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterFloatLiteral(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitFloatLiteral(this); + } + } + + public final FloatLiteralContext floatLiteral() throws RecognitionException { + FloatLiteralContext _localctx = new FloatLiteralContext(_ctx, getState()); + enterRule(_localctx, 108, RULE_floatLiteral); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(818); + _la = _input.LA(1); + if (!(_la == FLOAT_LITERAL || _la == HEX_FLOAT_LITERAL)) { + _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class AltAnnotationQualifiedNameContext extends ParserRuleContext { + public TerminalNode AT() { + return getToken(JavaParser.AT, 0); + } + + public List identifier() { + return getRuleContexts(IdentifierContext.class); + } + + public IdentifierContext identifier(int i) { + return getRuleContext(IdentifierContext.class, i); + } + + public List DOT() { + return getTokens(JavaParser.DOT); + } + + public TerminalNode DOT(int i) { + return getToken(JavaParser.DOT, i); + } + + public AltAnnotationQualifiedNameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_altAnnotationQualifiedName; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterAltAnnotationQualifiedName(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitAltAnnotationQualifiedName(this); + } + } + + public final AltAnnotationQualifiedNameContext altAnnotationQualifiedName() throws RecognitionException { + AltAnnotationQualifiedNameContext _localctx = new AltAnnotationQualifiedNameContext(_ctx, getState()); + enterRule(_localctx, 110, RULE_altAnnotationQualifiedName); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(825); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 51)) & ~0x3f) == 0 && ((1L << (_la - 51)) & 32767L) != 0) || _la == IDENTIFIER) { + { + { + setState(820); + identifier(); + setState(821); + match(DOT); + } + } + setState(827); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(828); + match(AT); + setState(829); + identifier(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class AnnotationContext extends ParserRuleContext { + public TerminalNode AT() { + return getToken(JavaParser.AT, 0); + } + + public QualifiedNameContext qualifiedName() { + return getRuleContext(QualifiedNameContext.class, 0); + } + + public AltAnnotationQualifiedNameContext altAnnotationQualifiedName() { + return getRuleContext(AltAnnotationQualifiedNameContext.class, 0); + } + + public TerminalNode LPAREN() { + return getToken(JavaParser.LPAREN, 0); + } + + public TerminalNode RPAREN() { + return getToken(JavaParser.RPAREN, 0); + } + + public ElementValuePairsContext elementValuePairs() { + return getRuleContext(ElementValuePairsContext.class, 0); + } + + public ElementValueContext elementValue() { + return getRuleContext(ElementValueContext.class, 0); + } + + public AnnotationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_annotation; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterAnnotation(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitAnnotation(this); + } + } + + public final AnnotationContext annotation() throws RecognitionException { + AnnotationContext _localctx = new AnnotationContext(_ctx, getState()); + enterRule(_localctx, 112, RULE_annotation); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(834); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 89, _ctx)) { + case 1: + { + setState(831); + match(AT); + setState(832); + qualifiedName(); + } + break; + case 2: + { + setState(833); + altAnnotationQualifiedName(); + } + break; + } + setState(842); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LPAREN) { + { + setState(836); + match(LPAREN); + setState(839); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 90, _ctx)) { + case 1: + { + setState(837); + elementValuePairs(); + } + break; + case 2: + { + setState(838); + elementValue(); + } + break; + } + setState(841); + match(RPAREN); + } + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ElementValuePairsContext extends ParserRuleContext { + public List elementValuePair() { + return getRuleContexts(ElementValuePairContext.class); + } + + public ElementValuePairContext elementValuePair(int i) { + return getRuleContext(ElementValuePairContext.class, i); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public ElementValuePairsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_elementValuePairs; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterElementValuePairs(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitElementValuePairs(this); + } + } + + public final ElementValuePairsContext elementValuePairs() throws RecognitionException { + ElementValuePairsContext _localctx = new ElementValuePairsContext(_ctx, getState()); + enterRule(_localctx, 114, RULE_elementValuePairs); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(844); + elementValuePair(); + setState(849); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == COMMA) { + { + { + setState(845); + match(COMMA); + setState(846); + elementValuePair(); + } + } + setState(851); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ElementValuePairContext extends ParserRuleContext { + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public TerminalNode ASSIGN() { + return getToken(JavaParser.ASSIGN, 0); + } + + public ElementValueContext elementValue() { + return getRuleContext(ElementValueContext.class, 0); + } + + public ElementValuePairContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_elementValuePair; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterElementValuePair(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitElementValuePair(this); + } + } + + public final ElementValuePairContext elementValuePair() throws RecognitionException { + ElementValuePairContext _localctx = new ElementValuePairContext(_ctx, getState()); + enterRule(_localctx, 116, RULE_elementValuePair); + try { + enterOuterAlt(_localctx, 1); + { + setState(852); + identifier(); + setState(853); + match(ASSIGN); + setState(854); + elementValue(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ElementValueContext extends ParserRuleContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class, 0); + } + + public AnnotationContext annotation() { + return getRuleContext(AnnotationContext.class, 0); + } + + public ElementValueArrayInitializerContext elementValueArrayInitializer() { + return getRuleContext(ElementValueArrayInitializerContext.class, 0); + } + + public ElementValueContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_elementValue; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterElementValue(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitElementValue(this); + } + } + + public final ElementValueContext elementValue() throws RecognitionException { + ElementValueContext _localctx = new ElementValueContext(_ctx, getState()); + enterRule(_localctx, 118, RULE_elementValue); + try { + setState(859); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 93, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(856); + expression(0); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(857); + annotation(); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(858); + elementValueArrayInitializer(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ElementValueArrayInitializerContext extends ParserRuleContext { + public TerminalNode LBRACE() { + return getToken(JavaParser.LBRACE, 0); + } + + public TerminalNode RBRACE() { + return getToken(JavaParser.RBRACE, 0); + } + + public List elementValue() { + return getRuleContexts(ElementValueContext.class); + } + + public ElementValueContext elementValue(int i) { + return getRuleContext(ElementValueContext.class, i); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public ElementValueArrayInitializerContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_elementValueArrayInitializer; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterElementValueArrayInitializer(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitElementValueArrayInitializer(this); + } + } + + public final ElementValueArrayInitializerContext elementValueArrayInitializer() throws RecognitionException { + ElementValueArrayInitializerContext _localctx = new ElementValueArrayInitializerContext(_ctx, getState()); + enterRule(_localctx, 120, RULE_elementValueArrayInitializer); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(861); + match(LBRACE); + setState(870); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & 9223127275610966053L) != 0) + || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & 4683743741343707135L) != 0)) { + { + setState(862); + elementValue(); + setState(867); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 94, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(863); + match(COMMA); + setState(864); + elementValue(); + } + } + } + setState(869); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 94, _ctx); + } + } + } + + setState(873); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == COMMA) { + { + setState(872); + match(COMMA); + } + } + + setState(875); + match(RBRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class AnnotationTypeDeclarationContext extends ParserRuleContext { + public TerminalNode AT() { + return getToken(JavaParser.AT, 0); + } + + public TerminalNode INTERFACE() { + return getToken(JavaParser.INTERFACE, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public AnnotationTypeBodyContext annotationTypeBody() { + return getRuleContext(AnnotationTypeBodyContext.class, 0); + } + + public AnnotationTypeDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_annotationTypeDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterAnnotationTypeDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitAnnotationTypeDeclaration(this); + } + } + + public final AnnotationTypeDeclarationContext annotationTypeDeclaration() throws RecognitionException { + AnnotationTypeDeclarationContext _localctx = new AnnotationTypeDeclarationContext(_ctx, getState()); + enterRule(_localctx, 122, RULE_annotationTypeDeclaration); + try { + enterOuterAlt(_localctx, 1); + { + setState(877); + match(AT); + setState(878); + match(INTERFACE); + setState(879); + identifier(); + setState(880); + annotationTypeBody(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class AnnotationTypeBodyContext extends ParserRuleContext { + public TerminalNode LBRACE() { + return getToken(JavaParser.LBRACE, 0); + } + + public TerminalNode RBRACE() { + return getToken(JavaParser.RBRACE, 0); + } + + public List annotationTypeElementDeclaration() { + return getRuleContexts(AnnotationTypeElementDeclarationContext.class); + } + + public AnnotationTypeElementDeclarationContext annotationTypeElementDeclaration(int i) { + return getRuleContext(AnnotationTypeElementDeclarationContext.class, i); + } + + public AnnotationTypeBodyContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_annotationTypeBody; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterAnnotationTypeBody(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitAnnotationTypeBody(this); + } + } + + public final AnnotationTypeBodyContext annotationTypeBody() throws RecognitionException { + AnnotationTypeBodyContext _localctx = new AnnotationTypeBodyContext(_ctx, getState()); + enterRule(_localctx, 124, RULE_annotationTypeBody); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(882); + match(LBRACE); + setState(886); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & -1613058852699350L) != 0) + || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & 576460752304472071L) != 0) + || _la == IDENTIFIER) { + { + { + setState(883); + annotationTypeElementDeclaration(); + } + } + setState(888); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(889); + match(RBRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class AnnotationTypeElementDeclarationContext extends ParserRuleContext { + public AnnotationTypeElementRestContext annotationTypeElementRest() { + return getRuleContext(AnnotationTypeElementRestContext.class, 0); + } + + public List modifier() { + return getRuleContexts(ModifierContext.class); + } + + public ModifierContext modifier(int i) { + return getRuleContext(ModifierContext.class, i); + } + + public TerminalNode SEMI() { + return getToken(JavaParser.SEMI, 0); + } + + public AnnotationTypeElementDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_annotationTypeElementDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterAnnotationTypeElementDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitAnnotationTypeElementDeclaration(this); + } + } + + public final AnnotationTypeElementDeclarationContext annotationTypeElementDeclaration() + throws RecognitionException { + AnnotationTypeElementDeclarationContext _localctx = + new AnnotationTypeElementDeclarationContext(_ctx, getState()); + enterRule(_localctx, 126, RULE_annotationTypeElementDeclaration); + try { + int _alt; + setState(899); + _errHandler.sync(this); + switch (_input.LA(1)) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case CLASS: + case DOUBLE: + case ENUM: + case FINAL: + case FLOAT: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOLATILE: + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case NON_SEALED: + case AT: + case IDENTIFIER: + enterOuterAlt(_localctx, 1); + { + setState(894); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 98, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(891); + modifier(); + } + } + } + setState(896); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 98, _ctx); + } + setState(897); + annotationTypeElementRest(); + } + break; + case SEMI: + enterOuterAlt(_localctx, 2); + { + setState(898); + match(SEMI); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class AnnotationTypeElementRestContext extends ParserRuleContext { + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public AnnotationMethodOrConstantRestContext annotationMethodOrConstantRest() { + return getRuleContext(AnnotationMethodOrConstantRestContext.class, 0); + } + + public TerminalNode SEMI() { + return getToken(JavaParser.SEMI, 0); + } + + public ClassDeclarationContext classDeclaration() { + return getRuleContext(ClassDeclarationContext.class, 0); + } + + public InterfaceDeclarationContext interfaceDeclaration() { + return getRuleContext(InterfaceDeclarationContext.class, 0); + } + + public EnumDeclarationContext enumDeclaration() { + return getRuleContext(EnumDeclarationContext.class, 0); + } + + public AnnotationTypeDeclarationContext annotationTypeDeclaration() { + return getRuleContext(AnnotationTypeDeclarationContext.class, 0); + } + + public RecordDeclarationContext recordDeclaration() { + return getRuleContext(RecordDeclarationContext.class, 0); + } + + public AnnotationTypeElementRestContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_annotationTypeElementRest; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterAnnotationTypeElementRest(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitAnnotationTypeElementRest(this); + } + } + + public final AnnotationTypeElementRestContext annotationTypeElementRest() throws RecognitionException { + AnnotationTypeElementRestContext _localctx = new AnnotationTypeElementRestContext(_ctx, getState()); + enterRule(_localctx, 128, RULE_annotationTypeElementRest); + try { + setState(925); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 105, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(901); + typeType(); + setState(902); + annotationMethodOrConstantRest(); + setState(903); + match(SEMI); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(905); + classDeclaration(); + setState(907); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 100, _ctx)) { + case 1: + { + setState(906); + match(SEMI); + } + break; + } + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(909); + interfaceDeclaration(); + setState(911); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 101, _ctx)) { + case 1: + { + setState(910); + match(SEMI); + } + break; + } + } + break; + case 4: + enterOuterAlt(_localctx, 4); + { + setState(913); + enumDeclaration(); + setState(915); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 102, _ctx)) { + case 1: + { + setState(914); + match(SEMI); + } + break; + } + } + break; + case 5: + enterOuterAlt(_localctx, 5); + { + setState(917); + annotationTypeDeclaration(); + setState(919); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 103, _ctx)) { + case 1: + { + setState(918); + match(SEMI); + } + break; + } + } + break; + case 6: + enterOuterAlt(_localctx, 6); + { + setState(921); + recordDeclaration(); + setState(923); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 104, _ctx)) { + case 1: + { + setState(922); + match(SEMI); + } + break; + } + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class AnnotationMethodOrConstantRestContext extends ParserRuleContext { + public AnnotationMethodRestContext annotationMethodRest() { + return getRuleContext(AnnotationMethodRestContext.class, 0); + } + + public AnnotationConstantRestContext annotationConstantRest() { + return getRuleContext(AnnotationConstantRestContext.class, 0); + } + + public AnnotationMethodOrConstantRestContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_annotationMethodOrConstantRest; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterAnnotationMethodOrConstantRest(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitAnnotationMethodOrConstantRest(this); + } + } + + public final AnnotationMethodOrConstantRestContext annotationMethodOrConstantRest() throws RecognitionException { + AnnotationMethodOrConstantRestContext _localctx = new AnnotationMethodOrConstantRestContext(_ctx, getState()); + enterRule(_localctx, 130, RULE_annotationMethodOrConstantRest); + try { + setState(929); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 106, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(927); + annotationMethodRest(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(928); + annotationConstantRest(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class AnnotationMethodRestContext extends ParserRuleContext { + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public TerminalNode LPAREN() { + return getToken(JavaParser.LPAREN, 0); + } + + public TerminalNode RPAREN() { + return getToken(JavaParser.RPAREN, 0); + } + + public DefaultValueContext defaultValue() { + return getRuleContext(DefaultValueContext.class, 0); + } + + public AnnotationMethodRestContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_annotationMethodRest; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterAnnotationMethodRest(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitAnnotationMethodRest(this); + } + } + + public final AnnotationMethodRestContext annotationMethodRest() throws RecognitionException { + AnnotationMethodRestContext _localctx = new AnnotationMethodRestContext(_ctx, getState()); + enterRule(_localctx, 132, RULE_annotationMethodRest); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(931); + identifier(); + setState(932); + match(LPAREN); + setState(933); + match(RPAREN); + setState(935); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == DEFAULT) { + { + setState(934); + defaultValue(); + } + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class AnnotationConstantRestContext extends ParserRuleContext { + public VariableDeclaratorsContext variableDeclarators() { + return getRuleContext(VariableDeclaratorsContext.class, 0); + } + + public AnnotationConstantRestContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_annotationConstantRest; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterAnnotationConstantRest(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitAnnotationConstantRest(this); + } + } + + public final AnnotationConstantRestContext annotationConstantRest() throws RecognitionException { + AnnotationConstantRestContext _localctx = new AnnotationConstantRestContext(_ctx, getState()); + enterRule(_localctx, 134, RULE_annotationConstantRest); + try { + enterOuterAlt(_localctx, 1); + { + setState(937); + variableDeclarators(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class DefaultValueContext extends ParserRuleContext { + public TerminalNode DEFAULT() { + return getToken(JavaParser.DEFAULT, 0); + } + + public ElementValueContext elementValue() { + return getRuleContext(ElementValueContext.class, 0); + } + + public DefaultValueContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_defaultValue; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterDefaultValue(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitDefaultValue(this); + } + } + + public final DefaultValueContext defaultValue() throws RecognitionException { + DefaultValueContext _localctx = new DefaultValueContext(_ctx, getState()); + enterRule(_localctx, 136, RULE_defaultValue); + try { + enterOuterAlt(_localctx, 1); + { + setState(939); + match(DEFAULT); + setState(940); + elementValue(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ModuleDeclarationContext extends ParserRuleContext { + public TerminalNode MODULE() { + return getToken(JavaParser.MODULE, 0); + } + + public QualifiedNameContext qualifiedName() { + return getRuleContext(QualifiedNameContext.class, 0); + } + + public ModuleBodyContext moduleBody() { + return getRuleContext(ModuleBodyContext.class, 0); + } + + public TerminalNode OPEN() { + return getToken(JavaParser.OPEN, 0); + } + + public ModuleDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_moduleDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterModuleDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitModuleDeclaration(this); + } + } + + public final ModuleDeclarationContext moduleDeclaration() throws RecognitionException { + ModuleDeclarationContext _localctx = new ModuleDeclarationContext(_ctx, getState()); + enterRule(_localctx, 138, RULE_moduleDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(943); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == OPEN) { + { + setState(942); + match(OPEN); + } + } + + setState(945); + match(MODULE); + setState(946); + qualifiedName(); + setState(947); + moduleBody(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ModuleBodyContext extends ParserRuleContext { + public TerminalNode LBRACE() { + return getToken(JavaParser.LBRACE, 0); + } + + public TerminalNode RBRACE() { + return getToken(JavaParser.RBRACE, 0); + } + + public List moduleDirective() { + return getRuleContexts(ModuleDirectiveContext.class); + } + + public ModuleDirectiveContext moduleDirective(int i) { + return getRuleContext(ModuleDirectiveContext.class, i); + } + + public ModuleBodyContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_moduleBody; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterModuleBody(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitModuleBody(this); + } + } + + public final ModuleBodyContext moduleBody() throws RecognitionException { + ModuleBodyContext _localctx = new ModuleBodyContext(_ctx, getState()); + enterRule(_localctx, 140, RULE_moduleBody); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(949); + match(LBRACE); + setState(953); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 495395959010754560L) != 0)) { + { + { + setState(950); + moduleDirective(); + } + } + setState(955); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(956); + match(RBRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ModuleDirectiveContext extends ParserRuleContext { + public TerminalNode REQUIRES() { + return getToken(JavaParser.REQUIRES, 0); + } + + public List qualifiedName() { + return getRuleContexts(QualifiedNameContext.class); + } + + public QualifiedNameContext qualifiedName(int i) { + return getRuleContext(QualifiedNameContext.class, i); + } + + public TerminalNode SEMI() { + return getToken(JavaParser.SEMI, 0); + } + + public List requiresModifier() { + return getRuleContexts(RequiresModifierContext.class); + } + + public RequiresModifierContext requiresModifier(int i) { + return getRuleContext(RequiresModifierContext.class, i); + } + + public TerminalNode EXPORTS() { + return getToken(JavaParser.EXPORTS, 0); + } + + public TerminalNode TO() { + return getToken(JavaParser.TO, 0); + } + + public TerminalNode OPENS() { + return getToken(JavaParser.OPENS, 0); + } + + public TerminalNode USES() { + return getToken(JavaParser.USES, 0); + } + + public TerminalNode PROVIDES() { + return getToken(JavaParser.PROVIDES, 0); + } + + public TerminalNode WITH() { + return getToken(JavaParser.WITH, 0); + } + + public ModuleDirectiveContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_moduleDirective; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterModuleDirective(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitModuleDirective(this); + } + } + + public final ModuleDirectiveContext moduleDirective() throws RecognitionException { + ModuleDirectiveContext _localctx = new ModuleDirectiveContext(_ctx, getState()); + enterRule(_localctx, 142, RULE_moduleDirective); + int _la; + try { + int _alt; + setState(994); + _errHandler.sync(this); + switch (_input.LA(1)) { + case REQUIRES: + enterOuterAlt(_localctx, 1); + { + setState(958); + match(REQUIRES); + setState(962); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 110, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(959); + requiresModifier(); + } + } + } + setState(964); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 110, _ctx); + } + setState(965); + qualifiedName(); + setState(966); + match(SEMI); + } + break; + case EXPORTS: + enterOuterAlt(_localctx, 2); + { + setState(968); + match(EXPORTS); + setState(969); + qualifiedName(); + setState(972); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == TO) { + { + setState(970); + match(TO); + setState(971); + qualifiedName(); + } + } + + setState(974); + match(SEMI); + } + break; + case OPENS: + enterOuterAlt(_localctx, 3); + { + setState(976); + match(OPENS); + setState(977); + qualifiedName(); + setState(980); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == TO) { + { + setState(978); + match(TO); + setState(979); + qualifiedName(); + } + } + + setState(982); + match(SEMI); + } + break; + case USES: + enterOuterAlt(_localctx, 4); + { + setState(984); + match(USES); + setState(985); + qualifiedName(); + setState(986); + match(SEMI); + } + break; + case PROVIDES: + enterOuterAlt(_localctx, 5); + { + setState(988); + match(PROVIDES); + setState(989); + qualifiedName(); + setState(990); + match(WITH); + setState(991); + qualifiedName(); + setState(992); + match(SEMI); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class RequiresModifierContext extends ParserRuleContext { + public TerminalNode TRANSITIVE() { + return getToken(JavaParser.TRANSITIVE, 0); + } + + public TerminalNode STATIC() { + return getToken(JavaParser.STATIC, 0); + } + + public RequiresModifierContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_requiresModifier; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterRequiresModifier(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitRequiresModifier(this); + } + } + + public final RequiresModifierContext requiresModifier() throws RecognitionException { + RequiresModifierContext _localctx = new RequiresModifierContext(_ctx, getState()); + enterRule(_localctx, 144, RULE_requiresModifier); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(996); + _la = _input.LA(1); + if (!(_la == STATIC || _la == TRANSITIVE)) { + _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class RecordDeclarationContext extends ParserRuleContext { + public TerminalNode RECORD() { + return getToken(JavaParser.RECORD, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public RecordHeaderContext recordHeader() { + return getRuleContext(RecordHeaderContext.class, 0); + } + + public RecordBodyContext recordBody() { + return getRuleContext(RecordBodyContext.class, 0); + } + + public TypeParametersContext typeParameters() { + return getRuleContext(TypeParametersContext.class, 0); + } + + public TerminalNode IMPLEMENTS() { + return getToken(JavaParser.IMPLEMENTS, 0); + } + + public TypeListContext typeList() { + return getRuleContext(TypeListContext.class, 0); + } + + public RecordDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_recordDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterRecordDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitRecordDeclaration(this); + } + } + + public final RecordDeclarationContext recordDeclaration() throws RecognitionException { + RecordDeclarationContext _localctx = new RecordDeclarationContext(_ctx, getState()); + enterRule(_localctx, 146, RULE_recordDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(998); + match(RECORD); + setState(999); + identifier(); + setState(1001); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LT) { + { + setState(1000); + typeParameters(); + } + } + + setState(1003); + recordHeader(); + setState(1006); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == IMPLEMENTS) { + { + setState(1004); + match(IMPLEMENTS); + setState(1005); + typeList(); + } + } + + setState(1008); + recordBody(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class RecordHeaderContext extends ParserRuleContext { + public TerminalNode LPAREN() { + return getToken(JavaParser.LPAREN, 0); + } + + public TerminalNode RPAREN() { + return getToken(JavaParser.RPAREN, 0); + } + + public RecordComponentListContext recordComponentList() { + return getRuleContext(RecordComponentListContext.class, 0); + } + + public RecordHeaderContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_recordHeader; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterRecordHeader(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitRecordHeader(this); + } + } + + public final RecordHeaderContext recordHeader() throws RecognitionException { + RecordHeaderContext _localctx = new RecordHeaderContext(_ctx, getState()); + enterRule(_localctx, 148, RULE_recordHeader); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1010); + match(LPAREN); + setState(1012); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & 9223090579141953573L) != 0) + || _la == AT + || _la == IDENTIFIER) { + { + setState(1011); + recordComponentList(); + } + } + + setState(1014); + match(RPAREN); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class RecordComponentListContext extends ParserRuleContext { + public List recordComponent() { + return getRuleContexts(RecordComponentContext.class); + } + + public RecordComponentContext recordComponent(int i) { + return getRuleContext(RecordComponentContext.class, i); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public RecordComponentListContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_recordComponentList; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterRecordComponentList(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitRecordComponentList(this); + } + } + + public final RecordComponentListContext recordComponentList() throws RecognitionException { + RecordComponentListContext _localctx = new RecordComponentListContext(_ctx, getState()); + enterRule(_localctx, 150, RULE_recordComponentList); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1016); + recordComponent(); + setState(1021); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == COMMA) { + { + { + setState(1017); + match(COMMA); + setState(1018); + recordComponent(); + } + } + setState(1023); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class RecordComponentContext extends ParserRuleContext { + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public RecordComponentContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_recordComponent; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterRecordComponent(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitRecordComponent(this); + } + } + + public final RecordComponentContext recordComponent() throws RecognitionException { + RecordComponentContext _localctx = new RecordComponentContext(_ctx, getState()); + enterRule(_localctx, 152, RULE_recordComponent); + try { + enterOuterAlt(_localctx, 1); + { + setState(1024); + typeType(); + setState(1025); + identifier(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class RecordBodyContext extends ParserRuleContext { + public TerminalNode LBRACE() { + return getToken(JavaParser.LBRACE, 0); + } + + public TerminalNode RBRACE() { + return getToken(JavaParser.RBRACE, 0); + } + + public List classBodyDeclaration() { + return getRuleContexts(ClassBodyDeclarationContext.class); + } + + public ClassBodyDeclarationContext classBodyDeclaration(int i) { + return getRuleContext(ClassBodyDeclarationContext.class, i); + } + + public List compactConstructorDeclaration() { + return getRuleContexts(CompactConstructorDeclarationContext.class); + } + + public CompactConstructorDeclarationContext compactConstructorDeclaration(int i) { + return getRuleContext(CompactConstructorDeclarationContext.class, i); + } + + public RecordBodyContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_recordBody; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterRecordBody(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitRecordBody(this); + } + } + + public final RecordBodyContext recordBody() throws RecognitionException { + RecordBodyContext _localctx = new RecordBodyContext(_ctx, getState()); + enterRule(_localctx, 154, RULE_recordBody); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1027); + match(LBRACE); + setState(1032); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & -1331583875988694L) != 0) + || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & 576460752338092039L) != 0) + || _la == IDENTIFIER) { + { + setState(1030); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 118, _ctx)) { + case 1: + { + setState(1028); + classBodyDeclaration(); + } + break; + case 2: + { + setState(1029); + compactConstructorDeclaration(); + } + break; + } + } + setState(1034); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1035); + match(RBRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class BlockContext extends ParserRuleContext { + public TerminalNode LBRACE() { + return getToken(JavaParser.LBRACE, 0); + } + + public TerminalNode RBRACE() { + return getToken(JavaParser.RBRACE, 0); + } + + public List blockStatement() { + return getRuleContexts(BlockStatementContext.class); + } + + public BlockStatementContext blockStatement(int i) { + return getRuleContext(BlockStatementContext.class, i); + } + + public BlockContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_block; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterBlock(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitBlock(this); + } + } + + public final BlockContext block() throws RecognitionException { + BlockContext _localctx = new BlockContext(_ctx, getState()); + enterRule(_localctx, 156, RULE_block); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1037); + match(LBRACE); + setState(1041); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & -668508564985026L) != 0) + || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & 576461783331602431L) != 0) + || _la == IDENTIFIER) { + { + { + setState(1038); + blockStatement(); + } + } + setState(1043); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1044); + match(RBRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class BlockStatementContext extends ParserRuleContext { + public LocalVariableDeclarationContext localVariableDeclaration() { + return getRuleContext(LocalVariableDeclarationContext.class, 0); + } + + public TerminalNode SEMI() { + return getToken(JavaParser.SEMI, 0); + } + + public LocalTypeDeclarationContext localTypeDeclaration() { + return getRuleContext(LocalTypeDeclarationContext.class, 0); + } + + public StatementContext statement() { + return getRuleContext(StatementContext.class, 0); + } + + public BlockStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_blockStatement; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterBlockStatement(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitBlockStatement(this); + } + } + + public final BlockStatementContext blockStatement() throws RecognitionException { + BlockStatementContext _localctx = new BlockStatementContext(_ctx, getState()); + enterRule(_localctx, 158, RULE_blockStatement); + try { + setState(1051); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 121, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(1046); + localVariableDeclaration(); + setState(1047); + match(SEMI); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(1049); + localTypeDeclaration(); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(1050); + statement(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class LocalVariableDeclarationContext extends ParserRuleContext { + public TerminalNode VAR() { + return getToken(JavaParser.VAR, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public TerminalNode ASSIGN() { + return getToken(JavaParser.ASSIGN, 0); + } + + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class, 0); + } + + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public VariableDeclaratorsContext variableDeclarators() { + return getRuleContext(VariableDeclaratorsContext.class, 0); + } + + public List variableModifier() { + return getRuleContexts(VariableModifierContext.class); + } + + public VariableModifierContext variableModifier(int i) { + return getRuleContext(VariableModifierContext.class, i); + } + + public LocalVariableDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_localVariableDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterLocalVariableDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitLocalVariableDeclaration(this); + } + } + + public final LocalVariableDeclarationContext localVariableDeclaration() throws RecognitionException { + LocalVariableDeclarationContext _localctx = new LocalVariableDeclarationContext(_ctx, getState()); + enterRule(_localctx, 160, RULE_localVariableDeclaration); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(1056); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 122, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1053); + variableModifier(); + } + } + } + setState(1058); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 122, _ctx); + } + setState(1067); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 123, _ctx)) { + case 1: + { + setState(1059); + match(VAR); + setState(1060); + identifier(); + setState(1061); + match(ASSIGN); + setState(1062); + expression(0); + } + break; + case 2: + { + setState(1064); + typeType(); + setState(1065); + variableDeclarators(); + } + break; + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class IdentifierContext extends ParserRuleContext { + public TerminalNode IDENTIFIER() { + return getToken(JavaParser.IDENTIFIER, 0); + } + + public TerminalNode MODULE() { + return getToken(JavaParser.MODULE, 0); + } + + public TerminalNode OPEN() { + return getToken(JavaParser.OPEN, 0); + } + + public TerminalNode REQUIRES() { + return getToken(JavaParser.REQUIRES, 0); + } + + public TerminalNode EXPORTS() { + return getToken(JavaParser.EXPORTS, 0); + } + + public TerminalNode OPENS() { + return getToken(JavaParser.OPENS, 0); + } + + public TerminalNode TO() { + return getToken(JavaParser.TO, 0); + } + + public TerminalNode USES() { + return getToken(JavaParser.USES, 0); + } + + public TerminalNode PROVIDES() { + return getToken(JavaParser.PROVIDES, 0); + } + + public TerminalNode WITH() { + return getToken(JavaParser.WITH, 0); + } + + public TerminalNode TRANSITIVE() { + return getToken(JavaParser.TRANSITIVE, 0); + } + + public TerminalNode YIELD() { + return getToken(JavaParser.YIELD, 0); + } + + public TerminalNode SEALED() { + return getToken(JavaParser.SEALED, 0); + } + + public TerminalNode PERMITS() { + return getToken(JavaParser.PERMITS, 0); + } + + public TerminalNode RECORD() { + return getToken(JavaParser.RECORD, 0); + } + + public TerminalNode VAR() { + return getToken(JavaParser.VAR, 0); + } + + public IdentifierContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_identifier; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterIdentifier(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitIdentifier(this); + } + } + + public final IdentifierContext identifier() throws RecognitionException { + IdentifierContext _localctx = new IdentifierContext(_ctx, getState()); + enterRule(_localctx, 162, RULE_identifier); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1069); + _la = _input.LA(1); + if (!(((((_la - 51)) & ~0x3f) == 0 && ((1L << (_la - 51)) & 32767L) != 0) || _la == IDENTIFIER)) { + _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class TypeIdentifierContext extends ParserRuleContext { + public TerminalNode IDENTIFIER() { + return getToken(JavaParser.IDENTIFIER, 0); + } + + public TerminalNode MODULE() { + return getToken(JavaParser.MODULE, 0); + } + + public TerminalNode OPEN() { + return getToken(JavaParser.OPEN, 0); + } + + public TerminalNode REQUIRES() { + return getToken(JavaParser.REQUIRES, 0); + } + + public TerminalNode EXPORTS() { + return getToken(JavaParser.EXPORTS, 0); + } + + public TerminalNode OPENS() { + return getToken(JavaParser.OPENS, 0); + } + + public TerminalNode TO() { + return getToken(JavaParser.TO, 0); + } + + public TerminalNode USES() { + return getToken(JavaParser.USES, 0); + } + + public TerminalNode PROVIDES() { + return getToken(JavaParser.PROVIDES, 0); + } + + public TerminalNode WITH() { + return getToken(JavaParser.WITH, 0); + } + + public TerminalNode TRANSITIVE() { + return getToken(JavaParser.TRANSITIVE, 0); + } + + public TerminalNode SEALED() { + return getToken(JavaParser.SEALED, 0); + } + + public TerminalNode PERMITS() { + return getToken(JavaParser.PERMITS, 0); + } + + public TerminalNode RECORD() { + return getToken(JavaParser.RECORD, 0); + } + + public TypeIdentifierContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_typeIdentifier; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterTypeIdentifier(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitTypeIdentifier(this); + } + } + + public final TypeIdentifierContext typeIdentifier() throws RecognitionException { + TypeIdentifierContext _localctx = new TypeIdentifierContext(_ctx, getState()); + enterRule(_localctx, 164, RULE_typeIdentifier); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1071); + _la = _input.LA(1); + if (!(((((_la - 51)) & ~0x3f) == 0 && ((1L << (_la - 51)) & 29695L) != 0) || _la == IDENTIFIER)) { + _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class LocalTypeDeclarationContext extends ParserRuleContext { + public ClassDeclarationContext classDeclaration() { + return getRuleContext(ClassDeclarationContext.class, 0); + } + + public InterfaceDeclarationContext interfaceDeclaration() { + return getRuleContext(InterfaceDeclarationContext.class, 0); + } + + public RecordDeclarationContext recordDeclaration() { + return getRuleContext(RecordDeclarationContext.class, 0); + } + + public List classOrInterfaceModifier() { + return getRuleContexts(ClassOrInterfaceModifierContext.class); + } + + public ClassOrInterfaceModifierContext classOrInterfaceModifier(int i) { + return getRuleContext(ClassOrInterfaceModifierContext.class, i); + } + + public LocalTypeDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_localTypeDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterLocalTypeDeclaration(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitLocalTypeDeclaration(this); + } + } + + public final LocalTypeDeclarationContext localTypeDeclaration() throws RecognitionException { + LocalTypeDeclarationContext _localctx = new LocalTypeDeclarationContext(_ctx, getState()); + enterRule(_localctx, 166, RULE_localTypeDeclaration); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(1076); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 124, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1073); + classOrInterfaceModifier(); + } + } + } + setState(1078); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 124, _ctx); + } + setState(1082); + _errHandler.sync(this); + switch (_input.LA(1)) { + case CLASS: + { + setState(1079); + classDeclaration(); + } + break; + case INTERFACE: + { + setState(1080); + interfaceDeclaration(); + } + break; + case RECORD: + { + setState(1081); + recordDeclaration(); + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class StatementContext extends ParserRuleContext { + public BlockContext blockLabel; + public ExpressionContext statementExpression; + public IdentifierContext identifierLabel; + + public BlockContext block() { + return getRuleContext(BlockContext.class, 0); + } + + public TerminalNode ASSERT() { + return getToken(JavaParser.ASSERT, 0); + } + + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class, i); + } + + public TerminalNode SEMI() { + return getToken(JavaParser.SEMI, 0); + } + + public TerminalNode COLON() { + return getToken(JavaParser.COLON, 0); + } + + public TerminalNode IF() { + return getToken(JavaParser.IF, 0); + } + + public ParExpressionContext parExpression() { + return getRuleContext(ParExpressionContext.class, 0); + } + + public List statement() { + return getRuleContexts(StatementContext.class); + } + + public StatementContext statement(int i) { + return getRuleContext(StatementContext.class, i); + } + + public TerminalNode ELSE() { + return getToken(JavaParser.ELSE, 0); + } + + public TerminalNode FOR() { + return getToken(JavaParser.FOR, 0); + } + + public TerminalNode LPAREN() { + return getToken(JavaParser.LPAREN, 0); + } + + public ForControlContext forControl() { + return getRuleContext(ForControlContext.class, 0); + } + + public TerminalNode RPAREN() { + return getToken(JavaParser.RPAREN, 0); + } + + public TerminalNode WHILE() { + return getToken(JavaParser.WHILE, 0); + } + + public TerminalNode DO() { + return getToken(JavaParser.DO, 0); + } + + public TerminalNode TRY() { + return getToken(JavaParser.TRY, 0); + } + + public FinallyBlockContext finallyBlock() { + return getRuleContext(FinallyBlockContext.class, 0); + } + + public List catchClause() { + return getRuleContexts(CatchClauseContext.class); + } + + public CatchClauseContext catchClause(int i) { + return getRuleContext(CatchClauseContext.class, i); + } + + public ResourceSpecificationContext resourceSpecification() { + return getRuleContext(ResourceSpecificationContext.class, 0); + } + + public TerminalNode SWITCH() { + return getToken(JavaParser.SWITCH, 0); + } + + public TerminalNode LBRACE() { + return getToken(JavaParser.LBRACE, 0); + } + + public TerminalNode RBRACE() { + return getToken(JavaParser.RBRACE, 0); + } + + public List switchBlockStatementGroup() { + return getRuleContexts(SwitchBlockStatementGroupContext.class); + } + + public SwitchBlockStatementGroupContext switchBlockStatementGroup(int i) { + return getRuleContext(SwitchBlockStatementGroupContext.class, i); + } + + public List switchLabel() { + return getRuleContexts(SwitchLabelContext.class); + } + + public SwitchLabelContext switchLabel(int i) { + return getRuleContext(SwitchLabelContext.class, i); + } + + public TerminalNode SYNCHRONIZED() { + return getToken(JavaParser.SYNCHRONIZED, 0); + } + + public TerminalNode RETURN() { + return getToken(JavaParser.RETURN, 0); + } + + public TerminalNode THROW() { + return getToken(JavaParser.THROW, 0); + } + + public TerminalNode BREAK() { + return getToken(JavaParser.BREAK, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public TerminalNode CONTINUE() { + return getToken(JavaParser.CONTINUE, 0); + } + + public TerminalNode YIELD() { + return getToken(JavaParser.YIELD, 0); + } + + public SwitchExpressionContext switchExpression() { + return getRuleContext(SwitchExpressionContext.class, 0); + } + + public StatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_statement; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterStatement(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitStatement(this); + } + } + + public final StatementContext statement() throws RecognitionException { + StatementContext _localctx = new StatementContext(_ctx, getState()); + enterRule(_localctx, 168, RULE_statement); + int _la; + try { + int _alt; + setState(1197); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 139, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(1084); + ((StatementContext) _localctx).blockLabel = block(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(1085); + match(ASSERT); + setState(1086); + expression(0); + setState(1089); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == COLON) { + { + setState(1087); + match(COLON); + setState(1088); + expression(0); + } + } + + setState(1091); + match(SEMI); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(1093); + match(IF); + setState(1094); + parExpression(); + setState(1095); + statement(); + setState(1098); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 127, _ctx)) { + case 1: + { + setState(1096); + match(ELSE); + setState(1097); + statement(); + } + break; + } + } + break; + case 4: + enterOuterAlt(_localctx, 4); + { + setState(1100); + match(FOR); + setState(1101); + match(LPAREN); + setState(1102); + forControl(); + setState(1103); + match(RPAREN); + setState(1104); + statement(); + } + break; + case 5: + enterOuterAlt(_localctx, 5); + { + setState(1106); + match(WHILE); + setState(1107); + parExpression(); + setState(1108); + statement(); + } + break; + case 6: + enterOuterAlt(_localctx, 6); + { + setState(1110); + match(DO); + setState(1111); + statement(); + setState(1112); + match(WHILE); + setState(1113); + parExpression(); + setState(1114); + match(SEMI); + } + break; + case 7: + enterOuterAlt(_localctx, 7); + { + setState(1116); + match(TRY); + setState(1117); + block(); + setState(1127); + _errHandler.sync(this); + switch (_input.LA(1)) { + case CATCH: + { + setState(1119); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(1118); + catchClause(); + } + } + setState(1121); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == CATCH); + setState(1124); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == FINALLY) { + { + setState(1123); + finallyBlock(); + } + } + } + break; + case FINALLY: + { + setState(1126); + finallyBlock(); + } + break; + default: + throw new NoViableAltException(this); + } + } + break; + case 8: + enterOuterAlt(_localctx, 8); + { + setState(1129); + match(TRY); + setState(1130); + resourceSpecification(); + setState(1131); + block(); + setState(1135); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == CATCH) { + { + { + setState(1132); + catchClause(); + } + } + setState(1137); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1139); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == FINALLY) { + { + setState(1138); + finallyBlock(); + } + } + } + break; + case 9: + enterOuterAlt(_localctx, 9); + { + setState(1141); + match(SWITCH); + setState(1142); + parExpression(); + setState(1143); + match(LBRACE); + setState(1147); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 133, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1144); + switchBlockStatementGroup(); + } + } + } + setState(1149); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 133, _ctx); + } + setState(1153); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == CASE || _la == DEFAULT) { + { + { + setState(1150); + switchLabel(); + } + } + setState(1155); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1156); + match(RBRACE); + } + break; + case 10: + enterOuterAlt(_localctx, 10); + { + setState(1158); + match(SYNCHRONIZED); + setState(1159); + parExpression(); + setState(1160); + block(); + } + break; + case 11: + enterOuterAlt(_localctx, 11); + { + setState(1162); + match(RETURN); + setState(1164); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & 9223127275610966053L) != 0) + || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & 4683743741343698943L) != 0)) { + { + setState(1163); + expression(0); + } + } + + setState(1166); + match(SEMI); + } + break; + case 12: + enterOuterAlt(_localctx, 12); + { + setState(1167); + match(THROW); + setState(1168); + expression(0); + setState(1169); + match(SEMI); + } + break; + case 13: + enterOuterAlt(_localctx, 13); + { + setState(1171); + match(BREAK); + setState(1173); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 51)) & ~0x3f) == 0 && ((1L << (_la - 51)) & 32767L) != 0) || _la == IDENTIFIER) { + { + setState(1172); + identifier(); + } + } + + setState(1175); + match(SEMI); + } + break; + case 14: + enterOuterAlt(_localctx, 14); + { + setState(1176); + match(CONTINUE); + setState(1178); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 51)) & ~0x3f) == 0 && ((1L << (_la - 51)) & 32767L) != 0) || _la == IDENTIFIER) { + { + setState(1177); + identifier(); + } + } + + setState(1180); + match(SEMI); + } + break; + case 15: + enterOuterAlt(_localctx, 15); + { + setState(1181); + match(YIELD); + setState(1182); + expression(0); + setState(1183); + match(SEMI); + } + break; + case 16: + enterOuterAlt(_localctx, 16); + { + setState(1185); + match(SEMI); + } + break; + case 17: + enterOuterAlt(_localctx, 17); + { + setState(1186); + ((StatementContext) _localctx).statementExpression = expression(0); + setState(1187); + match(SEMI); + } + break; + case 18: + enterOuterAlt(_localctx, 18); + { + setState(1189); + switchExpression(); + setState(1191); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 138, _ctx)) { + case 1: + { + setState(1190); + match(SEMI); + } + break; + } + } + break; + case 19: + enterOuterAlt(_localctx, 19); + { + setState(1193); + ((StatementContext) _localctx).identifierLabel = identifier(); + setState(1194); + match(COLON); + setState(1195); + statement(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class CatchClauseContext extends ParserRuleContext { + public TerminalNode CATCH() { + return getToken(JavaParser.CATCH, 0); + } + + public TerminalNode LPAREN() { + return getToken(JavaParser.LPAREN, 0); + } + + public CatchTypeContext catchType() { + return getRuleContext(CatchTypeContext.class, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public TerminalNode RPAREN() { + return getToken(JavaParser.RPAREN, 0); + } + + public BlockContext block() { + return getRuleContext(BlockContext.class, 0); + } + + public List variableModifier() { + return getRuleContexts(VariableModifierContext.class); + } + + public VariableModifierContext variableModifier(int i) { + return getRuleContext(VariableModifierContext.class, i); + } + + public CatchClauseContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_catchClause; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterCatchClause(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitCatchClause(this); + } + } + + public final CatchClauseContext catchClause() throws RecognitionException { + CatchClauseContext _localctx = new CatchClauseContext(_ctx, getState()); + enterRule(_localctx, 170, RULE_catchClause); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(1199); + match(CATCH); + setState(1200); + match(LPAREN); + setState(1204); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 140, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1201); + variableModifier(); + } + } + } + setState(1206); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 140, _ctx); + } + setState(1207); + catchType(); + setState(1208); + identifier(); + setState(1209); + match(RPAREN); + setState(1210); + block(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class CatchTypeContext extends ParserRuleContext { + public List qualifiedName() { + return getRuleContexts(QualifiedNameContext.class); + } + + public QualifiedNameContext qualifiedName(int i) { + return getRuleContext(QualifiedNameContext.class, i); + } + + public List BITOR() { + return getTokens(JavaParser.BITOR); + } + + public TerminalNode BITOR(int i) { + return getToken(JavaParser.BITOR, i); + } + + public CatchTypeContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_catchType; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterCatchType(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitCatchType(this); + } + } + + public final CatchTypeContext catchType() throws RecognitionException { + CatchTypeContext _localctx = new CatchTypeContext(_ctx, getState()); + enterRule(_localctx, 172, RULE_catchType); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1212); + qualifiedName(); + setState(1217); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == BITOR) { + { + { + setState(1213); + match(BITOR); + setState(1214); + qualifiedName(); + } + } + setState(1219); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class FinallyBlockContext extends ParserRuleContext { + public TerminalNode FINALLY() { + return getToken(JavaParser.FINALLY, 0); + } + + public BlockContext block() { + return getRuleContext(BlockContext.class, 0); + } + + public FinallyBlockContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_finallyBlock; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterFinallyBlock(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitFinallyBlock(this); + } + } + + public final FinallyBlockContext finallyBlock() throws RecognitionException { + FinallyBlockContext _localctx = new FinallyBlockContext(_ctx, getState()); + enterRule(_localctx, 174, RULE_finallyBlock); + try { + enterOuterAlt(_localctx, 1); + { + setState(1220); + match(FINALLY); + setState(1221); + block(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ResourceSpecificationContext extends ParserRuleContext { + public TerminalNode LPAREN() { + return getToken(JavaParser.LPAREN, 0); + } + + public ResourcesContext resources() { + return getRuleContext(ResourcesContext.class, 0); + } + + public TerminalNode RPAREN() { + return getToken(JavaParser.RPAREN, 0); + } + + public TerminalNode SEMI() { + return getToken(JavaParser.SEMI, 0); + } + + public ResourceSpecificationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_resourceSpecification; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterResourceSpecification(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitResourceSpecification(this); + } + } + + public final ResourceSpecificationContext resourceSpecification() throws RecognitionException { + ResourceSpecificationContext _localctx = new ResourceSpecificationContext(_ctx, getState()); + enterRule(_localctx, 176, RULE_resourceSpecification); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1223); + match(LPAREN); + setState(1224); + resources(); + setState(1226); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == SEMI) { + { + setState(1225); + match(SEMI); + } + } + + setState(1228); + match(RPAREN); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ResourcesContext extends ParserRuleContext { + public List resource() { + return getRuleContexts(ResourceContext.class); + } + + public ResourceContext resource(int i) { + return getRuleContext(ResourceContext.class, i); + } + + public List SEMI() { + return getTokens(JavaParser.SEMI); + } + + public TerminalNode SEMI(int i) { + return getToken(JavaParser.SEMI, i); + } + + public ResourcesContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_resources; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterResources(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitResources(this); + } + } + + public final ResourcesContext resources() throws RecognitionException { + ResourcesContext _localctx = new ResourcesContext(_ctx, getState()); + enterRule(_localctx, 178, RULE_resources); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(1230); + resource(); + setState(1235); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 143, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1231); + match(SEMI); + setState(1232); + resource(); + } + } + } + setState(1237); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 143, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ResourceContext extends ParserRuleContext { + public TerminalNode ASSIGN() { + return getToken(JavaParser.ASSIGN, 0); + } + + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class, 0); + } + + public ClassOrInterfaceTypeContext classOrInterfaceType() { + return getRuleContext(ClassOrInterfaceTypeContext.class, 0); + } + + public VariableDeclaratorIdContext variableDeclaratorId() { + return getRuleContext(VariableDeclaratorIdContext.class, 0); + } + + public TerminalNode VAR() { + return getToken(JavaParser.VAR, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public List variableModifier() { + return getRuleContexts(VariableModifierContext.class); + } + + public VariableModifierContext variableModifier(int i) { + return getRuleContext(VariableModifierContext.class, i); + } + + public QualifiedNameContext qualifiedName() { + return getRuleContext(QualifiedNameContext.class, 0); + } + + public ResourceContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_resource; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterResource(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitResource(this); + } + } + + public final ResourceContext resource() throws RecognitionException { + ResourceContext _localctx = new ResourceContext(_ctx, getState()); + enterRule(_localctx, 180, RULE_resource); + try { + int _alt; + setState(1255); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 146, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(1241); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 144, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1238); + variableModifier(); + } + } + } + setState(1243); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 144, _ctx); + } + setState(1249); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 145, _ctx)) { + case 1: + { + setState(1244); + classOrInterfaceType(); + setState(1245); + variableDeclaratorId(); + } + break; + case 2: + { + setState(1247); + match(VAR); + setState(1248); + identifier(); + } + break; + } + setState(1251); + match(ASSIGN); + setState(1252); + expression(0); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(1254); + qualifiedName(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SwitchBlockStatementGroupContext extends ParserRuleContext { + public List switchLabel() { + return getRuleContexts(SwitchLabelContext.class); + } + + public SwitchLabelContext switchLabel(int i) { + return getRuleContext(SwitchLabelContext.class, i); + } + + public List blockStatement() { + return getRuleContexts(BlockStatementContext.class); + } + + public BlockStatementContext blockStatement(int i) { + return getRuleContext(BlockStatementContext.class, i); + } + + public SwitchBlockStatementGroupContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_switchBlockStatementGroup; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterSwitchBlockStatementGroup(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitSwitchBlockStatementGroup(this); + } + } + + public final SwitchBlockStatementGroupContext switchBlockStatementGroup() throws RecognitionException { + SwitchBlockStatementGroupContext _localctx = new SwitchBlockStatementGroupContext(_ctx, getState()); + enterRule(_localctx, 182, RULE_switchBlockStatementGroup); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1258); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(1257); + switchLabel(); + } + } + setState(1260); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == CASE || _la == DEFAULT); + setState(1263); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(1262); + blockStatement(); + } + } + setState(1265); + _errHandler.sync(this); + _la = _input.LA(1); + } while ((((_la) & ~0x3f) == 0 && ((1L << _la) & -668508564985026L) != 0) + || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & 576461783331602431L) != 0) + || _la == IDENTIFIER); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SwitchLabelContext extends ParserRuleContext { + public ExpressionContext constantExpression; + public Token enumConstantName; + public IdentifierContext varName; + + public TerminalNode CASE() { + return getToken(JavaParser.CASE, 0); + } + + public TerminalNode COLON() { + return getToken(JavaParser.COLON, 0); + } + + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class, 0); + } + + public TerminalNode IDENTIFIER() { + return getToken(JavaParser.IDENTIFIER, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public TerminalNode DEFAULT() { + return getToken(JavaParser.DEFAULT, 0); + } + + public SwitchLabelContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_switchLabel; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterSwitchLabel(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitSwitchLabel(this); + } + } + + public final SwitchLabelContext switchLabel() throws RecognitionException { + SwitchLabelContext _localctx = new SwitchLabelContext(_ctx, getState()); + enterRule(_localctx, 184, RULE_switchLabel); + try { + setState(1278); + _errHandler.sync(this); + switch (_input.LA(1)) { + case CASE: + enterOuterAlt(_localctx, 1); + { + setState(1267); + match(CASE); + setState(1273); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 149, _ctx)) { + case 1: + { + setState(1268); + ((SwitchLabelContext) _localctx).constantExpression = expression(0); + } + break; + case 2: + { + setState(1269); + ((SwitchLabelContext) _localctx).enumConstantName = match(IDENTIFIER); + } + break; + case 3: + { + setState(1270); + typeType(); + setState(1271); + ((SwitchLabelContext) _localctx).varName = identifier(); + } + break; + } + setState(1275); + match(COLON); + } + break; + case DEFAULT: + enterOuterAlt(_localctx, 2); + { + setState(1276); + match(DEFAULT); + setState(1277); + match(COLON); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ForControlContext extends ParserRuleContext { + public ExpressionListContext forUpdate; + + public EnhancedForControlContext enhancedForControl() { + return getRuleContext(EnhancedForControlContext.class, 0); + } + + public List SEMI() { + return getTokens(JavaParser.SEMI); + } + + public TerminalNode SEMI(int i) { + return getToken(JavaParser.SEMI, i); + } + + public ForInitContext forInit() { + return getRuleContext(ForInitContext.class, 0); + } + + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class, 0); + } + + public ExpressionListContext expressionList() { + return getRuleContext(ExpressionListContext.class, 0); + } + + public ForControlContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_forControl; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterForControl(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitForControl(this); + } + } + + public final ForControlContext forControl() throws RecognitionException { + ForControlContext _localctx = new ForControlContext(_ctx, getState()); + enterRule(_localctx, 186, RULE_forControl); + int _la; + try { + setState(1292); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 154, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(1280); + enhancedForControl(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(1282); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & 9223127275610998821L) != 0) + || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & 4683743741343698943L) != 0)) { + { + setState(1281); + forInit(); + } + } + + setState(1284); + match(SEMI); + setState(1286); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & 9223127275610966053L) != 0) + || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & 4683743741343698943L) != 0)) { + { + setState(1285); + expression(0); + } + } + + setState(1288); + match(SEMI); + setState(1290); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & 9223127275610966053L) != 0) + || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & 4683743741343698943L) != 0)) { + { + setState(1289); + ((ForControlContext) _localctx).forUpdate = expressionList(); + } + } + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ForInitContext extends ParserRuleContext { + public LocalVariableDeclarationContext localVariableDeclaration() { + return getRuleContext(LocalVariableDeclarationContext.class, 0); + } + + public ExpressionListContext expressionList() { + return getRuleContext(ExpressionListContext.class, 0); + } + + public ForInitContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_forInit; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterForInit(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitForInit(this); + } + } + + public final ForInitContext forInit() throws RecognitionException { + ForInitContext _localctx = new ForInitContext(_ctx, getState()); + enterRule(_localctx, 188, RULE_forInit); + try { + setState(1296); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 155, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(1294); + localVariableDeclaration(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(1295); + expressionList(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class EnhancedForControlContext extends ParserRuleContext { + public VariableDeclaratorIdContext variableDeclaratorId() { + return getRuleContext(VariableDeclaratorIdContext.class, 0); + } + + public TerminalNode COLON() { + return getToken(JavaParser.COLON, 0); + } + + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class, 0); + } + + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public TerminalNode VAR() { + return getToken(JavaParser.VAR, 0); + } + + public List variableModifier() { + return getRuleContexts(VariableModifierContext.class); + } + + public VariableModifierContext variableModifier(int i) { + return getRuleContext(VariableModifierContext.class, i); + } + + public EnhancedForControlContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_enhancedForControl; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterEnhancedForControl(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitEnhancedForControl(this); + } + } + + public final EnhancedForControlContext enhancedForControl() throws RecognitionException { + EnhancedForControlContext _localctx = new EnhancedForControlContext(_ctx, getState()); + enterRule(_localctx, 190, RULE_enhancedForControl); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(1301); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 156, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1298); + variableModifier(); + } + } + } + setState(1303); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 156, _ctx); + } + setState(1306); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 157, _ctx)) { + case 1: + { + setState(1304); + typeType(); + } + break; + case 2: + { + setState(1305); + match(VAR); + } + break; + } + setState(1308); + variableDeclaratorId(); + setState(1309); + match(COLON); + setState(1310); + expression(0); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ParExpressionContext extends ParserRuleContext { + public TerminalNode LPAREN() { + return getToken(JavaParser.LPAREN, 0); + } + + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class, 0); + } + + public TerminalNode RPAREN() { + return getToken(JavaParser.RPAREN, 0); + } + + public ParExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_parExpression; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterParExpression(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitParExpression(this); + } + } + + public final ParExpressionContext parExpression() throws RecognitionException { + ParExpressionContext _localctx = new ParExpressionContext(_ctx, getState()); + enterRule(_localctx, 192, RULE_parExpression); + try { + enterOuterAlt(_localctx, 1); + { + setState(1312); + match(LPAREN); + setState(1313); + expression(0); + setState(1314); + match(RPAREN); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ExpressionListContext extends ParserRuleContext { + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class, i); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public ExpressionListContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_expressionList; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterExpressionList(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitExpressionList(this); + } + } + + public final ExpressionListContext expressionList() throws RecognitionException { + ExpressionListContext _localctx = new ExpressionListContext(_ctx, getState()); + enterRule(_localctx, 194, RULE_expressionList); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1316); + expression(0); + setState(1321); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == COMMA) { + { + { + setState(1317); + match(COMMA); + setState(1318); + expression(0); + } + } + setState(1323); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class MethodCallContext extends ParserRuleContext { + public ArgumentsContext arguments() { + return getRuleContext(ArgumentsContext.class, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public TerminalNode THIS() { + return getToken(JavaParser.THIS, 0); + } + + public TerminalNode SUPER() { + return getToken(JavaParser.SUPER, 0); + } + + public MethodCallContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_methodCall; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterMethodCall(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitMethodCall(this); + } + } + + public final MethodCallContext methodCall() throws RecognitionException { + MethodCallContext _localctx = new MethodCallContext(_ctx, getState()); + enterRule(_localctx, 196, RULE_methodCall); + try { + enterOuterAlt(_localctx, 1); + { + setState(1327); + _errHandler.sync(this); + switch (_input.LA(1)) { + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case IDENTIFIER: + { + setState(1324); + identifier(); + } + break; + case THIS: + { + setState(1325); + match(THIS); + } + break; + case SUPER: + { + setState(1326); + match(SUPER); + } + break; + default: + throw new NoViableAltException(this); + } + setState(1329); + arguments(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ExpressionContext extends ParserRuleContext { + public Token prefix; + public Token bop; + public Token postfix; + + public PrimaryContext primary() { + return getRuleContext(PrimaryContext.class, 0); + } + + public MethodCallContext methodCall() { + return getRuleContext(MethodCallContext.class, 0); + } + + public List typeType() { + return getRuleContexts(TypeTypeContext.class); + } + + public TypeTypeContext typeType(int i) { + return getRuleContext(TypeTypeContext.class, i); + } + + public TerminalNode COLONCOLON() { + return getToken(JavaParser.COLONCOLON, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public TerminalNode NEW() { + return getToken(JavaParser.NEW, 0); + } + + public TypeArgumentsContext typeArguments() { + return getRuleContext(TypeArgumentsContext.class, 0); + } + + public ClassTypeContext classType() { + return getRuleContext(ClassTypeContext.class, 0); + } + + public SwitchExpressionContext switchExpression() { + return getRuleContext(SwitchExpressionContext.class, 0); + } + + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class, i); + } + + public TerminalNode ADD() { + return getToken(JavaParser.ADD, 0); + } + + public TerminalNode SUB() { + return getToken(JavaParser.SUB, 0); + } + + public TerminalNode INC() { + return getToken(JavaParser.INC, 0); + } + + public TerminalNode DEC() { + return getToken(JavaParser.DEC, 0); + } + + public TerminalNode TILDE() { + return getToken(JavaParser.TILDE, 0); + } + + public TerminalNode BANG() { + return getToken(JavaParser.BANG, 0); + } + + public TerminalNode LPAREN() { + return getToken(JavaParser.LPAREN, 0); + } + + public TerminalNode RPAREN() { + return getToken(JavaParser.RPAREN, 0); + } + + public List annotation() { + return getRuleContexts(AnnotationContext.class); + } + + public AnnotationContext annotation(int i) { + return getRuleContext(AnnotationContext.class, i); + } + + public List BITAND() { + return getTokens(JavaParser.BITAND); + } + + public TerminalNode BITAND(int i) { + return getToken(JavaParser.BITAND, i); + } + + public CreatorContext creator() { + return getRuleContext(CreatorContext.class, 0); + } + + public LambdaExpressionContext lambdaExpression() { + return getRuleContext(LambdaExpressionContext.class, 0); + } + + public TerminalNode MUL() { + return getToken(JavaParser.MUL, 0); + } + + public TerminalNode DIV() { + return getToken(JavaParser.DIV, 0); + } + + public TerminalNode MOD() { + return getToken(JavaParser.MOD, 0); + } + + public List LT() { + return getTokens(JavaParser.LT); + } + + public TerminalNode LT(int i) { + return getToken(JavaParser.LT, i); + } + + public List GT() { + return getTokens(JavaParser.GT); + } + + public TerminalNode GT(int i) { + return getToken(JavaParser.GT, i); + } + + public TerminalNode LE() { + return getToken(JavaParser.LE, 0); + } + + public TerminalNode GE() { + return getToken(JavaParser.GE, 0); + } + + public TerminalNode EQUAL() { + return getToken(JavaParser.EQUAL, 0); + } + + public TerminalNode NOTEQUAL() { + return getToken(JavaParser.NOTEQUAL, 0); + } + + public TerminalNode CARET() { + return getToken(JavaParser.CARET, 0); + } + + public TerminalNode BITOR() { + return getToken(JavaParser.BITOR, 0); + } + + public TerminalNode AND() { + return getToken(JavaParser.AND, 0); + } + + public TerminalNode OR() { + return getToken(JavaParser.OR, 0); + } + + public TerminalNode COLON() { + return getToken(JavaParser.COLON, 0); + } + + public TerminalNode QUESTION() { + return getToken(JavaParser.QUESTION, 0); + } + + public TerminalNode ASSIGN() { + return getToken(JavaParser.ASSIGN, 0); + } + + public TerminalNode ADD_ASSIGN() { + return getToken(JavaParser.ADD_ASSIGN, 0); + } + + public TerminalNode SUB_ASSIGN() { + return getToken(JavaParser.SUB_ASSIGN, 0); + } + + public TerminalNode MUL_ASSIGN() { + return getToken(JavaParser.MUL_ASSIGN, 0); + } + + public TerminalNode DIV_ASSIGN() { + return getToken(JavaParser.DIV_ASSIGN, 0); + } + + public TerminalNode AND_ASSIGN() { + return getToken(JavaParser.AND_ASSIGN, 0); + } + + public TerminalNode OR_ASSIGN() { + return getToken(JavaParser.OR_ASSIGN, 0); + } + + public TerminalNode XOR_ASSIGN() { + return getToken(JavaParser.XOR_ASSIGN, 0); + } + + public TerminalNode RSHIFT_ASSIGN() { + return getToken(JavaParser.RSHIFT_ASSIGN, 0); + } + + public TerminalNode URSHIFT_ASSIGN() { + return getToken(JavaParser.URSHIFT_ASSIGN, 0); + } + + public TerminalNode LSHIFT_ASSIGN() { + return getToken(JavaParser.LSHIFT_ASSIGN, 0); + } + + public TerminalNode MOD_ASSIGN() { + return getToken(JavaParser.MOD_ASSIGN, 0); + } + + public TerminalNode LBRACK() { + return getToken(JavaParser.LBRACK, 0); + } + + public TerminalNode RBRACK() { + return getToken(JavaParser.RBRACK, 0); + } + + public TerminalNode DOT() { + return getToken(JavaParser.DOT, 0); + } + + public TerminalNode THIS() { + return getToken(JavaParser.THIS, 0); + } + + public InnerCreatorContext innerCreator() { + return getRuleContext(InnerCreatorContext.class, 0); + } + + public TerminalNode SUPER() { + return getToken(JavaParser.SUPER, 0); + } + + public SuperSuffixContext superSuffix() { + return getRuleContext(SuperSuffixContext.class, 0); + } + + public ExplicitGenericInvocationContext explicitGenericInvocation() { + return getRuleContext(ExplicitGenericInvocationContext.class, 0); + } + + public NonWildcardTypeArgumentsContext nonWildcardTypeArguments() { + return getRuleContext(NonWildcardTypeArgumentsContext.class, 0); + } + + public TerminalNode INSTANCEOF() { + return getToken(JavaParser.INSTANCEOF, 0); + } + + public PatternContext pattern() { + return getRuleContext(PatternContext.class, 0); + } + + public ExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_expression; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterExpression(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitExpression(this); + } + } + + public final ExpressionContext expression() throws RecognitionException { + return expression(0); + } + + private ExpressionContext expression(int _p) throws RecognitionException { + ParserRuleContext _parentctx = _ctx; + int _parentState = getState(); + ExpressionContext _localctx = new ExpressionContext(_ctx, _parentState); + ExpressionContext _prevctx = _localctx; + int _startState = 198; + enterRecursionRule(_localctx, 198, RULE_expression, _p); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(1374); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 165, _ctx)) { + case 1: + { + setState(1332); + primary(); + } + break; + case 2: + { + setState(1333); + methodCall(); + } + break; + case 3: + { + setState(1334); + typeType(); + setState(1335); + match(COLONCOLON); + setState(1341); + _errHandler.sync(this); + switch (_input.LA(1)) { + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case LT: + case IDENTIFIER: + { + setState(1337); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LT) { + { + setState(1336); + typeArguments(); + } + } + + setState(1339); + identifier(); + } + break; + case NEW: + { + setState(1340); + match(NEW); + } + break; + default: + throw new NoViableAltException(this); + } + } + break; + case 4: + { + setState(1343); + classType(); + setState(1344); + match(COLONCOLON); + setState(1346); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LT) { + { + setState(1345); + typeArguments(); + } + } + + setState(1348); + match(NEW); + } + break; + case 5: + { + setState(1350); + switchExpression(); + } + break; + case 6: + { + setState(1351); + ((ExpressionContext) _localctx).prefix = _input.LT(1); + _la = _input.LA(1); + if (!(((((_la - 90)) & ~0x3f) == 0 && ((1L << (_la - 90)) & 15363L) != 0))) { + ((ExpressionContext) _localctx).prefix = (Token) _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1352); + expression(17); + } + break; + case 7: + { + setState(1353); + match(LPAREN); + setState(1357); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 163, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1354); + annotation(); + } + } + } + setState(1359); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 163, _ctx); + } + setState(1360); + typeType(); + setState(1365); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == BITAND) { + { + { + setState(1361); + match(BITAND); + setState(1362); + typeType(); + } + } + setState(1367); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1368); + match(RPAREN); + setState(1369); + expression(16); + } + break; + case 8: + { + setState(1371); + match(NEW); + setState(1372); + creator(); + } + break; + case 9: + { + setState(1373); + lambdaExpression(); + } + break; + } + _ctx.stop = _input.LT(-1); + setState(1459); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 172, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + if (_parseListeners != null) triggerExitRuleEvent(); + _prevctx = _localctx; + { + setState(1457); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 171, _ctx)) { + case 1: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1376); + if (!(precpred(_ctx, 14))) + throw new FailedPredicateException(this, "precpred(_ctx, 14)"); + setState(1377); + ((ExpressionContext) _localctx).bop = _input.LT(1); + _la = _input.LA(1); + if (!(((((_la - 104)) & ~0x3f) == 0 && ((1L << (_la - 104)) & 35L) != 0))) { + ((ExpressionContext) _localctx).bop = + (Token) _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1378); + expression(15); + } + break; + case 2: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1379); + if (!(precpred(_ctx, 13))) + throw new FailedPredicateException(this, "precpred(_ctx, 13)"); + setState(1380); + ((ExpressionContext) _localctx).bop = _input.LT(1); + _la = _input.LA(1); + if (!(_la == ADD || _la == SUB)) { + ((ExpressionContext) _localctx).bop = + (Token) _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1381); + expression(14); + } + break; + case 3: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1382); + if (!(precpred(_ctx, 12))) + throw new FailedPredicateException(this, "precpred(_ctx, 12)"); + setState(1390); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 166, _ctx)) { + case 1: + { + setState(1383); + match(LT); + setState(1384); + match(LT); + } + break; + case 2: + { + setState(1385); + match(GT); + setState(1386); + match(GT); + setState(1387); + match(GT); + } + break; + case 3: + { + setState(1388); + match(GT); + setState(1389); + match(GT); + } + break; + } + setState(1392); + expression(13); + } + break; + case 4: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1393); + if (!(precpred(_ctx, 11))) + throw new FailedPredicateException(this, "precpred(_ctx, 11)"); + setState(1394); + ((ExpressionContext) _localctx).bop = _input.LT(1); + _la = _input.LA(1); + if (!(((((_la - 88)) & ~0x3f) == 0 && ((1L << (_la - 88)) & 387L) != 0))) { + ((ExpressionContext) _localctx).bop = + (Token) _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1395); + expression(12); + } + break; + case 5: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1396); + if (!(precpred(_ctx, 9))) + throw new FailedPredicateException(this, "precpred(_ctx, 9)"); + setState(1397); + ((ExpressionContext) _localctx).bop = _input.LT(1); + _la = _input.LA(1); + if (!(_la == EQUAL || _la == NOTEQUAL)) { + ((ExpressionContext) _localctx).bop = + (Token) _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1398); + expression(10); + } + break; + case 6: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1399); + if (!(precpred(_ctx, 8))) + throw new FailedPredicateException(this, "precpred(_ctx, 8)"); + setState(1400); + ((ExpressionContext) _localctx).bop = match(BITAND); + setState(1401); + expression(9); + } + break; + case 7: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1402); + if (!(precpred(_ctx, 7))) + throw new FailedPredicateException(this, "precpred(_ctx, 7)"); + setState(1403); + ((ExpressionContext) _localctx).bop = match(CARET); + setState(1404); + expression(8); + } + break; + case 8: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1405); + if (!(precpred(_ctx, 6))) + throw new FailedPredicateException(this, "precpred(_ctx, 6)"); + setState(1406); + ((ExpressionContext) _localctx).bop = match(BITOR); + setState(1407); + expression(7); + } + break; + case 9: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1408); + if (!(precpred(_ctx, 5))) + throw new FailedPredicateException(this, "precpred(_ctx, 5)"); + setState(1409); + ((ExpressionContext) _localctx).bop = match(AND); + setState(1410); + expression(6); + } + break; + case 10: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1411); + if (!(precpred(_ctx, 4))) + throw new FailedPredicateException(this, "precpred(_ctx, 4)"); + setState(1412); + ((ExpressionContext) _localctx).bop = match(OR); + setState(1413); + expression(5); + } + break; + case 11: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1414); + if (!(precpred(_ctx, 3))) + throw new FailedPredicateException(this, "precpred(_ctx, 3)"); + setState(1415); + ((ExpressionContext) _localctx).bop = match(QUESTION); + setState(1416); + expression(0); + setState(1417); + match(COLON); + setState(1418); + expression(3); + } + break; + case 12: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1420); + if (!(precpred(_ctx, 2))) + throw new FailedPredicateException(this, "precpred(_ctx, 2)"); + setState(1421); + ((ExpressionContext) _localctx).bop = _input.LT(1); + _la = _input.LA(1); + if (!(((((_la - 87)) & ~0x3f) == 0 + && ((1L << (_la - 87)) & 17171480577L) != 0))) { + ((ExpressionContext) _localctx).bop = + (Token) _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1422); + expression(2); + } + break; + case 13: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1423); + if (!(precpred(_ctx, 25))) + throw new FailedPredicateException(this, "precpred(_ctx, 25)"); + setState(1424); + match(LBRACK); + setState(1425); + expression(0); + setState(1426); + match(RBRACK); + } + break; + case 14: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1428); + if (!(precpred(_ctx, 24))) + throw new FailedPredicateException(this, "precpred(_ctx, 24)"); + setState(1429); + ((ExpressionContext) _localctx).bop = match(DOT); + setState(1441); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 168, _ctx)) { + case 1: + { + setState(1430); + identifier(); + } + break; + case 2: + { + setState(1431); + methodCall(); + } + break; + case 3: + { + setState(1432); + match(THIS); + } + break; + case 4: + { + setState(1433); + match(NEW); + setState(1435); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LT) { + { + setState(1434); + nonWildcardTypeArguments(); + } + } + + setState(1437); + innerCreator(); + } + break; + case 5: + { + setState(1438); + match(SUPER); + setState(1439); + superSuffix(); + } + break; + case 6: + { + setState(1440); + explicitGenericInvocation(); + } + break; + } + } + break; + case 15: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1443); + if (!(precpred(_ctx, 22))) + throw new FailedPredicateException(this, "precpred(_ctx, 22)"); + setState(1444); + match(COLONCOLON); + setState(1446); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LT) { + { + setState(1445); + typeArguments(); + } + } + + setState(1448); + identifier(); + } + break; + case 16: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1449); + if (!(precpred(_ctx, 18))) + throw new FailedPredicateException(this, "precpred(_ctx, 18)"); + setState(1450); + ((ExpressionContext) _localctx).postfix = _input.LT(1); + _la = _input.LA(1); + if (!(_la == INC || _la == DEC)) { + ((ExpressionContext) _localctx).postfix = + (Token) _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + break; + case 17: + { + _localctx = new ExpressionContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1451); + if (!(precpred(_ctx, 10))) + throw new FailedPredicateException(this, "precpred(_ctx, 10)"); + setState(1452); + ((ExpressionContext) _localctx).bop = match(INSTANCEOF); + setState(1455); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 170, _ctx)) { + case 1: + { + setState(1453); + typeType(); + } + break; + case 2: + { + setState(1454); + pattern(); + } + break; + } + } + break; + } + } + } + setState(1461); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 172, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + unrollRecursionContexts(_parentctx); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class PatternContext extends ParserRuleContext { + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public List variableModifier() { + return getRuleContexts(VariableModifierContext.class); + } + + public VariableModifierContext variableModifier(int i) { + return getRuleContext(VariableModifierContext.class, i); + } + + public List annotation() { + return getRuleContexts(AnnotationContext.class); + } + + public AnnotationContext annotation(int i) { + return getRuleContext(AnnotationContext.class, i); + } + + public PatternContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_pattern; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterPattern(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitPattern(this); + } + } + + public final PatternContext pattern() throws RecognitionException { + PatternContext _localctx = new PatternContext(_ctx, getState()); + enterRule(_localctx, 200, RULE_pattern); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(1465); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 173, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1462); + variableModifier(); + } + } + } + setState(1467); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 173, _ctx); + } + setState(1468); + typeType(); + setState(1472); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 174, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1469); + annotation(); + } + } + } + setState(1474); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 174, _ctx); + } + setState(1475); + identifier(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class LambdaExpressionContext extends ParserRuleContext { + public LambdaParametersContext lambdaParameters() { + return getRuleContext(LambdaParametersContext.class, 0); + } + + public TerminalNode ARROW() { + return getToken(JavaParser.ARROW, 0); + } + + public LambdaBodyContext lambdaBody() { + return getRuleContext(LambdaBodyContext.class, 0); + } + + public LambdaExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_lambdaExpression; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterLambdaExpression(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitLambdaExpression(this); + } + } + + public final LambdaExpressionContext lambdaExpression() throws RecognitionException { + LambdaExpressionContext _localctx = new LambdaExpressionContext(_ctx, getState()); + enterRule(_localctx, 202, RULE_lambdaExpression); + try { + enterOuterAlt(_localctx, 1); + { + setState(1477); + lambdaParameters(); + setState(1478); + match(ARROW); + setState(1479); + lambdaBody(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class LambdaParametersContext extends ParserRuleContext { + public List identifier() { + return getRuleContexts(IdentifierContext.class); + } + + public IdentifierContext identifier(int i) { + return getRuleContext(IdentifierContext.class, i); + } + + public TerminalNode LPAREN() { + return getToken(JavaParser.LPAREN, 0); + } + + public TerminalNode RPAREN() { + return getToken(JavaParser.RPAREN, 0); + } + + public FormalParameterListContext formalParameterList() { + return getRuleContext(FormalParameterListContext.class, 0); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public LambdaLVTIListContext lambdaLVTIList() { + return getRuleContext(LambdaLVTIListContext.class, 0); + } + + public LambdaParametersContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_lambdaParameters; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterLambdaParameters(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitLambdaParameters(this); + } + } + + public final LambdaParametersContext lambdaParameters() throws RecognitionException { + LambdaParametersContext _localctx = new LambdaParametersContext(_ctx, getState()); + enterRule(_localctx, 204, RULE_lambdaParameters); + int _la; + try { + setState(1503); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 178, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(1481); + identifier(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(1482); + match(LPAREN); + setState(1484); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & 9223090579141986341L) != 0) + || _la == AT + || _la == IDENTIFIER) { + { + setState(1483); + formalParameterList(); + } + } + + setState(1486); + match(RPAREN); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(1487); + match(LPAREN); + setState(1488); + identifier(); + setState(1493); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == COMMA) { + { + { + setState(1489); + match(COMMA); + setState(1490); + identifier(); + } + } + setState(1495); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1496); + match(RPAREN); + } + break; + case 4: + enterOuterAlt(_localctx, 4); + { + setState(1498); + match(LPAREN); + setState(1500); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 18)) & ~0x3f) == 0 && ((1L << (_la - 18)) & 281466386776065L) != 0) + || _la == AT + || _la == IDENTIFIER) { + { + setState(1499); + lambdaLVTIList(); + } + } + + setState(1502); + match(RPAREN); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class LambdaBodyContext extends ParserRuleContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class, 0); + } + + public BlockContext block() { + return getRuleContext(BlockContext.class, 0); + } + + public LambdaBodyContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_lambdaBody; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterLambdaBody(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitLambdaBody(this); + } + } + + public final LambdaBodyContext lambdaBody() throws RecognitionException { + LambdaBodyContext _localctx = new LambdaBodyContext(_ctx, getState()); + enterRule(_localctx, 206, RULE_lambdaBody); + try { + setState(1507); + _errHandler.sync(this); + switch (_input.LA(1)) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case NEW: + case SHORT: + case SUPER: + case SWITCH: + case THIS: + case VOID: + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case DECIMAL_LITERAL: + case HEX_LITERAL: + case OCT_LITERAL: + case BINARY_LITERAL: + case FLOAT_LITERAL: + case HEX_FLOAT_LITERAL: + case BOOL_LITERAL: + case CHAR_LITERAL: + case STRING_LITERAL: + case TEXT_BLOCK: + case NULL_LITERAL: + case LPAREN: + case LT: + case BANG: + case TILDE: + case INC: + case DEC: + case ADD: + case SUB: + case AT: + case IDENTIFIER: + enterOuterAlt(_localctx, 1); + { + setState(1505); + expression(0); + } + break; + case LBRACE: + enterOuterAlt(_localctx, 2); + { + setState(1506); + block(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class PrimaryContext extends ParserRuleContext { + public TerminalNode LPAREN() { + return getToken(JavaParser.LPAREN, 0); + } + + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class, 0); + } + + public TerminalNode RPAREN() { + return getToken(JavaParser.RPAREN, 0); + } + + public TerminalNode THIS() { + return getToken(JavaParser.THIS, 0); + } + + public TerminalNode SUPER() { + return getToken(JavaParser.SUPER, 0); + } + + public LiteralContext literal() { + return getRuleContext(LiteralContext.class, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public TypeTypeOrVoidContext typeTypeOrVoid() { + return getRuleContext(TypeTypeOrVoidContext.class, 0); + } + + public TerminalNode DOT() { + return getToken(JavaParser.DOT, 0); + } + + public TerminalNode CLASS() { + return getToken(JavaParser.CLASS, 0); + } + + public NonWildcardTypeArgumentsContext nonWildcardTypeArguments() { + return getRuleContext(NonWildcardTypeArgumentsContext.class, 0); + } + + public ExplicitGenericInvocationSuffixContext explicitGenericInvocationSuffix() { + return getRuleContext(ExplicitGenericInvocationSuffixContext.class, 0); + } + + public ArgumentsContext arguments() { + return getRuleContext(ArgumentsContext.class, 0); + } + + public PrimaryContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_primary; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterPrimary(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitPrimary(this); + } + } + + public final PrimaryContext primary() throws RecognitionException { + PrimaryContext _localctx = new PrimaryContext(_ctx, getState()); + enterRule(_localctx, 208, RULE_primary); + try { + setState(1527); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 181, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(1509); + match(LPAREN); + setState(1510); + expression(0); + setState(1511); + match(RPAREN); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(1513); + match(THIS); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(1514); + match(SUPER); + } + break; + case 4: + enterOuterAlt(_localctx, 4); + { + setState(1515); + literal(); + } + break; + case 5: + enterOuterAlt(_localctx, 5); + { + setState(1516); + identifier(); + } + break; + case 6: + enterOuterAlt(_localctx, 6); + { + setState(1517); + typeTypeOrVoid(); + setState(1518); + match(DOT); + setState(1519); + match(CLASS); + } + break; + case 7: + enterOuterAlt(_localctx, 7); + { + setState(1521); + nonWildcardTypeArguments(); + setState(1525); + _errHandler.sync(this); + switch (_input.LA(1)) { + case SUPER: + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case IDENTIFIER: + { + setState(1522); + explicitGenericInvocationSuffix(); + } + break; + case THIS: + { + setState(1523); + match(THIS); + setState(1524); + arguments(); + } + break; + default: + throw new NoViableAltException(this); + } + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SwitchExpressionContext extends ParserRuleContext { + public TerminalNode SWITCH() { + return getToken(JavaParser.SWITCH, 0); + } + + public ParExpressionContext parExpression() { + return getRuleContext(ParExpressionContext.class, 0); + } + + public TerminalNode LBRACE() { + return getToken(JavaParser.LBRACE, 0); + } + + public TerminalNode RBRACE() { + return getToken(JavaParser.RBRACE, 0); + } + + public List switchLabeledRule() { + return getRuleContexts(SwitchLabeledRuleContext.class); + } + + public SwitchLabeledRuleContext switchLabeledRule(int i) { + return getRuleContext(SwitchLabeledRuleContext.class, i); + } + + public SwitchExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_switchExpression; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterSwitchExpression(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitSwitchExpression(this); + } + } + + public final SwitchExpressionContext switchExpression() throws RecognitionException { + SwitchExpressionContext _localctx = new SwitchExpressionContext(_ctx, getState()); + enterRule(_localctx, 210, RULE_switchExpression); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1529); + match(SWITCH); + setState(1530); + parExpression(); + setState(1531); + match(LBRACE); + setState(1535); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == CASE || _la == DEFAULT) { + { + { + setState(1532); + switchLabeledRule(); + } + } + setState(1537); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1538); + match(RBRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SwitchLabeledRuleContext extends ParserRuleContext { + public TerminalNode CASE() { + return getToken(JavaParser.CASE, 0); + } + + public SwitchRuleOutcomeContext switchRuleOutcome() { + return getRuleContext(SwitchRuleOutcomeContext.class, 0); + } + + public TerminalNode ARROW() { + return getToken(JavaParser.ARROW, 0); + } + + public TerminalNode COLON() { + return getToken(JavaParser.COLON, 0); + } + + public ExpressionListContext expressionList() { + return getRuleContext(ExpressionListContext.class, 0); + } + + public TerminalNode NULL_LITERAL() { + return getToken(JavaParser.NULL_LITERAL, 0); + } + + public GuardedPatternContext guardedPattern() { + return getRuleContext(GuardedPatternContext.class, 0); + } + + public TerminalNode DEFAULT() { + return getToken(JavaParser.DEFAULT, 0); + } + + public SwitchLabeledRuleContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_switchLabeledRule; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterSwitchLabeledRule(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitSwitchLabeledRule(this); + } + } + + public final SwitchLabeledRuleContext switchLabeledRule() throws RecognitionException { + SwitchLabeledRuleContext _localctx = new SwitchLabeledRuleContext(_ctx, getState()); + enterRule(_localctx, 212, RULE_switchLabeledRule); + int _la; + try { + setState(1551); + _errHandler.sync(this); + switch (_input.LA(1)) { + case CASE: + enterOuterAlt(_localctx, 1); + { + setState(1540); + match(CASE); + setState(1544); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 183, _ctx)) { + case 1: + { + setState(1541); + expressionList(); + } + break; + case 2: + { + setState(1542); + match(NULL_LITERAL); + } + break; + case 3: + { + setState(1543); + guardedPattern(0); + } + break; + } + setState(1546); + _la = _input.LA(1); + if (!(_la == COLON || _la == ARROW)) { + _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1547); + switchRuleOutcome(); + } + break; + case DEFAULT: + enterOuterAlt(_localctx, 2); + { + setState(1548); + match(DEFAULT); + setState(1549); + _la = _input.LA(1); + if (!(_la == COLON || _la == ARROW)) { + _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1550); + switchRuleOutcome(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class GuardedPatternContext extends ParserRuleContext { + public TerminalNode LPAREN() { + return getToken(JavaParser.LPAREN, 0); + } + + public GuardedPatternContext guardedPattern() { + return getRuleContext(GuardedPatternContext.class, 0); + } + + public TerminalNode RPAREN() { + return getToken(JavaParser.RPAREN, 0); + } + + public TypeTypeContext typeType() { + return getRuleContext(TypeTypeContext.class, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public List variableModifier() { + return getRuleContexts(VariableModifierContext.class); + } + + public VariableModifierContext variableModifier(int i) { + return getRuleContext(VariableModifierContext.class, i); + } + + public List annotation() { + return getRuleContexts(AnnotationContext.class); + } + + public AnnotationContext annotation(int i) { + return getRuleContext(AnnotationContext.class, i); + } + + public List AND() { + return getTokens(JavaParser.AND); + } + + public TerminalNode AND(int i) { + return getToken(JavaParser.AND, i); + } + + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class, i); + } + + public GuardedPatternContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_guardedPattern; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterGuardedPattern(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitGuardedPattern(this); + } + } + + public final GuardedPatternContext guardedPattern() throws RecognitionException { + return guardedPattern(0); + } + + private GuardedPatternContext guardedPattern(int _p) throws RecognitionException { + ParserRuleContext _parentctx = _ctx; + int _parentState = getState(); + GuardedPatternContext _localctx = new GuardedPatternContext(_ctx, _parentState); + GuardedPatternContext _prevctx = _localctx; + int _startState = 214; + enterRecursionRule(_localctx, 214, RULE_guardedPattern, _p); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(1579); + _errHandler.sync(this); + switch (_input.LA(1)) { + case LPAREN: + { + setState(1554); + match(LPAREN); + setState(1555); + guardedPattern(0); + setState(1556); + match(RPAREN); + } + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FINAL: + case FLOAT: + case INT: + case LONG: + case SHORT: + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case AT: + case IDENTIFIER: + { + setState(1561); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 185, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1558); + variableModifier(); + } + } + } + setState(1563); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 185, _ctx); + } + setState(1564); + typeType(); + setState(1568); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 186, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1565); + annotation(); + } + } + } + setState(1570); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 186, _ctx); + } + setState(1571); + identifier(); + setState(1576); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 187, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1572); + match(AND); + setState(1573); + expression(0); + } + } + } + setState(1578); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 187, _ctx); + } + } + break; + default: + throw new NoViableAltException(this); + } + _ctx.stop = _input.LT(-1); + setState(1586); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 189, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + if (_parseListeners != null) triggerExitRuleEvent(); + _prevctx = _localctx; + { + { + _localctx = new GuardedPatternContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_guardedPattern); + setState(1581); + if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); + setState(1582); + match(AND); + setState(1583); + expression(0); + } + } + } + setState(1588); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 189, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + unrollRecursionContexts(_parentctx); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SwitchRuleOutcomeContext extends ParserRuleContext { + public BlockContext block() { + return getRuleContext(BlockContext.class, 0); + } + + public List blockStatement() { + return getRuleContexts(BlockStatementContext.class); + } + + public BlockStatementContext blockStatement(int i) { + return getRuleContext(BlockStatementContext.class, i); + } + + public SwitchRuleOutcomeContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_switchRuleOutcome; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterSwitchRuleOutcome(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitSwitchRuleOutcome(this); + } + } + + public final SwitchRuleOutcomeContext switchRuleOutcome() throws RecognitionException { + SwitchRuleOutcomeContext _localctx = new SwitchRuleOutcomeContext(_ctx, getState()); + enterRule(_localctx, 216, RULE_switchRuleOutcome); + int _la; + try { + setState(1596); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 191, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(1589); + block(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(1593); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & -668508564985026L) != 0) + || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & 576461783331602431L) != 0) + || _la == IDENTIFIER) { + { + { + setState(1590); + blockStatement(); + } + } + setState(1595); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ClassTypeContext extends ParserRuleContext { + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public ClassOrInterfaceTypeContext classOrInterfaceType() { + return getRuleContext(ClassOrInterfaceTypeContext.class, 0); + } + + public TerminalNode DOT() { + return getToken(JavaParser.DOT, 0); + } + + public List annotation() { + return getRuleContexts(AnnotationContext.class); + } + + public AnnotationContext annotation(int i) { + return getRuleContext(AnnotationContext.class, i); + } + + public TypeArgumentsContext typeArguments() { + return getRuleContext(TypeArgumentsContext.class, 0); + } + + public ClassTypeContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_classType; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterClassType(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitClassType(this); + } + } + + public final ClassTypeContext classType() throws RecognitionException { + ClassTypeContext _localctx = new ClassTypeContext(_ctx, getState()); + enterRule(_localctx, 218, RULE_classType); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(1601); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 192, _ctx)) { + case 1: + { + setState(1598); + classOrInterfaceType(); + setState(1599); + match(DOT); + } + break; + } + setState(1606); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 193, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1603); + annotation(); + } + } + } + setState(1608); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 193, _ctx); + } + setState(1609); + identifier(); + setState(1611); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LT) { + { + setState(1610); + typeArguments(); + } + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class CreatorContext extends ParserRuleContext { + public CreatedNameContext createdName() { + return getRuleContext(CreatedNameContext.class, 0); + } + + public ClassCreatorRestContext classCreatorRest() { + return getRuleContext(ClassCreatorRestContext.class, 0); + } + + public NonWildcardTypeArgumentsContext nonWildcardTypeArguments() { + return getRuleContext(NonWildcardTypeArgumentsContext.class, 0); + } + + public ArrayCreatorRestContext arrayCreatorRest() { + return getRuleContext(ArrayCreatorRestContext.class, 0); + } + + public CreatorContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_creator; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterCreator(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitCreator(this); + } + } + + public final CreatorContext creator() throws RecognitionException { + CreatorContext _localctx = new CreatorContext(_ctx, getState()); + enterRule(_localctx, 220, RULE_creator); + int _la; + try { + setState(1622); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 196, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(1614); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LT) { + { + setState(1613); + nonWildcardTypeArguments(); + } + } + + setState(1616); + createdName(); + setState(1617); + classCreatorRest(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(1619); + createdName(); + setState(1620); + arrayCreatorRest(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class CreatedNameContext extends ParserRuleContext { + public List identifier() { + return getRuleContexts(IdentifierContext.class); + } + + public IdentifierContext identifier(int i) { + return getRuleContext(IdentifierContext.class, i); + } + + public List typeArgumentsOrDiamond() { + return getRuleContexts(TypeArgumentsOrDiamondContext.class); + } + + public TypeArgumentsOrDiamondContext typeArgumentsOrDiamond(int i) { + return getRuleContext(TypeArgumentsOrDiamondContext.class, i); + } + + public List DOT() { + return getTokens(JavaParser.DOT); + } + + public TerminalNode DOT(int i) { + return getToken(JavaParser.DOT, i); + } + + public PrimitiveTypeContext primitiveType() { + return getRuleContext(PrimitiveTypeContext.class, 0); + } + + public CreatedNameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_createdName; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterCreatedName(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitCreatedName(this); + } + } + + public final CreatedNameContext createdName() throws RecognitionException { + CreatedNameContext _localctx = new CreatedNameContext(_ctx, getState()); + enterRule(_localctx, 222, RULE_createdName); + int _la; + try { + setState(1639); + _errHandler.sync(this); + switch (_input.LA(1)) { + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case IDENTIFIER: + enterOuterAlt(_localctx, 1); + { + setState(1624); + identifier(); + setState(1626); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LT) { + { + setState(1625); + typeArgumentsOrDiamond(); + } + } + + setState(1635); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == DOT) { + { + { + setState(1628); + match(DOT); + setState(1629); + identifier(); + setState(1631); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LT) { + { + setState(1630); + typeArgumentsOrDiamond(); + } + } + } + } + setState(1637); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + enterOuterAlt(_localctx, 2); + { + setState(1638); + primitiveType(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class InnerCreatorContext extends ParserRuleContext { + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public ClassCreatorRestContext classCreatorRest() { + return getRuleContext(ClassCreatorRestContext.class, 0); + } + + public NonWildcardTypeArgumentsOrDiamondContext nonWildcardTypeArgumentsOrDiamond() { + return getRuleContext(NonWildcardTypeArgumentsOrDiamondContext.class, 0); + } + + public InnerCreatorContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_innerCreator; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterInnerCreator(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitInnerCreator(this); + } + } + + public final InnerCreatorContext innerCreator() throws RecognitionException { + InnerCreatorContext _localctx = new InnerCreatorContext(_ctx, getState()); + enterRule(_localctx, 224, RULE_innerCreator); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1641); + identifier(); + setState(1643); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LT) { + { + setState(1642); + nonWildcardTypeArgumentsOrDiamond(); + } + } + + setState(1645); + classCreatorRest(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ArrayCreatorRestContext extends ParserRuleContext { + public ArrayInitializerContext arrayInitializer() { + return getRuleContext(ArrayInitializerContext.class, 0); + } + + public List LBRACK() { + return getTokens(JavaParser.LBRACK); + } + + public TerminalNode LBRACK(int i) { + return getToken(JavaParser.LBRACK, i); + } + + public List RBRACK() { + return getTokens(JavaParser.RBRACK); + } + + public TerminalNode RBRACK(int i) { + return getToken(JavaParser.RBRACK, i); + } + + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class, i); + } + + public ArrayCreatorRestContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_arrayCreatorRest; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterArrayCreatorRest(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitArrayCreatorRest(this); + } + } + + public final ArrayCreatorRestContext arrayCreatorRest() throws RecognitionException { + ArrayCreatorRestContext _localctx = new ArrayCreatorRestContext(_ctx, getState()); + enterRule(_localctx, 226, RULE_arrayCreatorRest); + int _la; + try { + int _alt; + setState(1669); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 205, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(1649); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(1647); + match(LBRACK); + setState(1648); + match(RBRACK); + } + } + setState(1651); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == LBRACK); + setState(1653); + arrayInitializer(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(1658); + _errHandler.sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + { + setState(1654); + match(LBRACK); + setState(1655); + expression(0); + setState(1656); + match(RBRACK); + } + } + break; + default: + throw new NoViableAltException(this); + } + setState(1660); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 203, _ctx); + } while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER); + setState(1666); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 204, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1662); + match(LBRACK); + setState(1663); + match(RBRACK); + } + } + } + setState(1668); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 204, _ctx); + } + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ClassCreatorRestContext extends ParserRuleContext { + public ArgumentsContext arguments() { + return getRuleContext(ArgumentsContext.class, 0); + } + + public ClassBodyContext classBody() { + return getRuleContext(ClassBodyContext.class, 0); + } + + public ClassCreatorRestContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_classCreatorRest; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterClassCreatorRest(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitClassCreatorRest(this); + } + } + + public final ClassCreatorRestContext classCreatorRest() throws RecognitionException { + ClassCreatorRestContext _localctx = new ClassCreatorRestContext(_ctx, getState()); + enterRule(_localctx, 228, RULE_classCreatorRest); + try { + enterOuterAlt(_localctx, 1); + { + setState(1671); + arguments(); + setState(1673); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 206, _ctx)) { + case 1: + { + setState(1672); + classBody(); + } + break; + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ExplicitGenericInvocationContext extends ParserRuleContext { + public NonWildcardTypeArgumentsContext nonWildcardTypeArguments() { + return getRuleContext(NonWildcardTypeArgumentsContext.class, 0); + } + + public ExplicitGenericInvocationSuffixContext explicitGenericInvocationSuffix() { + return getRuleContext(ExplicitGenericInvocationSuffixContext.class, 0); + } + + public ExplicitGenericInvocationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_explicitGenericInvocation; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterExplicitGenericInvocation(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitExplicitGenericInvocation(this); + } + } + + public final ExplicitGenericInvocationContext explicitGenericInvocation() throws RecognitionException { + ExplicitGenericInvocationContext _localctx = new ExplicitGenericInvocationContext(_ctx, getState()); + enterRule(_localctx, 230, RULE_explicitGenericInvocation); + try { + enterOuterAlt(_localctx, 1); + { + setState(1675); + nonWildcardTypeArguments(); + setState(1676); + explicitGenericInvocationSuffix(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class TypeArgumentsOrDiamondContext extends ParserRuleContext { + public TerminalNode LT() { + return getToken(JavaParser.LT, 0); + } + + public TerminalNode GT() { + return getToken(JavaParser.GT, 0); + } + + public TypeArgumentsContext typeArguments() { + return getRuleContext(TypeArgumentsContext.class, 0); + } + + public TypeArgumentsOrDiamondContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_typeArgumentsOrDiamond; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterTypeArgumentsOrDiamond(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitTypeArgumentsOrDiamond(this); + } + } + + public final TypeArgumentsOrDiamondContext typeArgumentsOrDiamond() throws RecognitionException { + TypeArgumentsOrDiamondContext _localctx = new TypeArgumentsOrDiamondContext(_ctx, getState()); + enterRule(_localctx, 232, RULE_typeArgumentsOrDiamond); + try { + setState(1681); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 207, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(1678); + match(LT); + setState(1679); + match(GT); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(1680); + typeArguments(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class NonWildcardTypeArgumentsOrDiamondContext extends ParserRuleContext { + public TerminalNode LT() { + return getToken(JavaParser.LT, 0); + } + + public TerminalNode GT() { + return getToken(JavaParser.GT, 0); + } + + public NonWildcardTypeArgumentsContext nonWildcardTypeArguments() { + return getRuleContext(NonWildcardTypeArgumentsContext.class, 0); + } + + public NonWildcardTypeArgumentsOrDiamondContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_nonWildcardTypeArgumentsOrDiamond; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterNonWildcardTypeArgumentsOrDiamond(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitNonWildcardTypeArgumentsOrDiamond(this); + } + } + + public final NonWildcardTypeArgumentsOrDiamondContext nonWildcardTypeArgumentsOrDiamond() + throws RecognitionException { + NonWildcardTypeArgumentsOrDiamondContext _localctx = + new NonWildcardTypeArgumentsOrDiamondContext(_ctx, getState()); + enterRule(_localctx, 234, RULE_nonWildcardTypeArgumentsOrDiamond); + try { + setState(1686); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 208, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(1683); + match(LT); + setState(1684); + match(GT); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(1685); + nonWildcardTypeArguments(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class NonWildcardTypeArgumentsContext extends ParserRuleContext { + public TerminalNode LT() { + return getToken(JavaParser.LT, 0); + } + + public TypeListContext typeList() { + return getRuleContext(TypeListContext.class, 0); + } + + public TerminalNode GT() { + return getToken(JavaParser.GT, 0); + } + + public NonWildcardTypeArgumentsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_nonWildcardTypeArguments; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterNonWildcardTypeArguments(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitNonWildcardTypeArguments(this); + } + } + + public final NonWildcardTypeArgumentsContext nonWildcardTypeArguments() throws RecognitionException { + NonWildcardTypeArgumentsContext _localctx = new NonWildcardTypeArgumentsContext(_ctx, getState()); + enterRule(_localctx, 236, RULE_nonWildcardTypeArguments); + try { + enterOuterAlt(_localctx, 1); + { + setState(1688); + match(LT); + setState(1689); + typeList(); + setState(1690); + match(GT); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class TypeListContext extends ParserRuleContext { + public List typeType() { + return getRuleContexts(TypeTypeContext.class); + } + + public TypeTypeContext typeType(int i) { + return getRuleContext(TypeTypeContext.class, i); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public TypeListContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_typeList; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterTypeList(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitTypeList(this); + } + } + + public final TypeListContext typeList() throws RecognitionException { + TypeListContext _localctx = new TypeListContext(_ctx, getState()); + enterRule(_localctx, 238, RULE_typeList); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1692); + typeType(); + setState(1697); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == COMMA) { + { + { + setState(1693); + match(COMMA); + setState(1694); + typeType(); + } + } + setState(1699); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class TypeTypeContext extends ParserRuleContext { + public ClassOrInterfaceTypeContext classOrInterfaceType() { + return getRuleContext(ClassOrInterfaceTypeContext.class, 0); + } + + public PrimitiveTypeContext primitiveType() { + return getRuleContext(PrimitiveTypeContext.class, 0); + } + + public List annotation() { + return getRuleContexts(AnnotationContext.class); + } + + public AnnotationContext annotation(int i) { + return getRuleContext(AnnotationContext.class, i); + } + + public List LBRACK() { + return getTokens(JavaParser.LBRACK); + } + + public TerminalNode LBRACK(int i) { + return getToken(JavaParser.LBRACK, i); + } + + public List RBRACK() { + return getTokens(JavaParser.RBRACK); + } + + public TerminalNode RBRACK(int i) { + return getToken(JavaParser.RBRACK, i); + } + + public TypeTypeContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_typeType; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterTypeType(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitTypeType(this); + } + } + + public final TypeTypeContext typeType() throws RecognitionException { + TypeTypeContext _localctx = new TypeTypeContext(_ctx, getState()); + enterRule(_localctx, 240, RULE_typeType); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(1703); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 210, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1700); + annotation(); + } + } + } + setState(1705); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 210, _ctx); + } + setState(1708); + _errHandler.sync(this); + switch (_input.LA(1)) { + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case IDENTIFIER: + { + setState(1706); + classOrInterfaceType(); + } + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + { + setState(1707); + primitiveType(); + } + break; + default: + throw new NoViableAltException(this); + } + setState(1720); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 213, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(1713); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 51)) & ~0x3f) == 0 && ((1L << (_la - 51)) & 32767L) != 0) + || _la == AT + || _la == IDENTIFIER) { + { + { + setState(1710); + annotation(); + } + } + setState(1715); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1716); + match(LBRACK); + setState(1717); + match(RBRACK); + } + } + } + setState(1722); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 213, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class PrimitiveTypeContext extends ParserRuleContext { + public TerminalNode BOOLEAN() { + return getToken(JavaParser.BOOLEAN, 0); + } + + public TerminalNode CHAR() { + return getToken(JavaParser.CHAR, 0); + } + + public TerminalNode BYTE() { + return getToken(JavaParser.BYTE, 0); + } + + public TerminalNode SHORT() { + return getToken(JavaParser.SHORT, 0); + } + + public TerminalNode INT() { + return getToken(JavaParser.INT, 0); + } + + public TerminalNode LONG() { + return getToken(JavaParser.LONG, 0); + } + + public TerminalNode FLOAT() { + return getToken(JavaParser.FLOAT, 0); + } + + public TerminalNode DOUBLE() { + return getToken(JavaParser.DOUBLE, 0); + } + + public PrimitiveTypeContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_primitiveType; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterPrimitiveType(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitPrimitiveType(this); + } + } + + public final PrimitiveTypeContext primitiveType() throws RecognitionException { + PrimitiveTypeContext _localctx = new PrimitiveTypeContext(_ctx, getState()); + enterRule(_localctx, 242, RULE_primitiveType); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1723); + _la = _input.LA(1); + if (!((((_la) & ~0x3f) == 0 && ((1L << _la) & 138111107368L) != 0))) { + _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class TypeArgumentsContext extends ParserRuleContext { + public TerminalNode LT() { + return getToken(JavaParser.LT, 0); + } + + public List typeArgument() { + return getRuleContexts(TypeArgumentContext.class); + } + + public TypeArgumentContext typeArgument(int i) { + return getRuleContext(TypeArgumentContext.class, i); + } + + public TerminalNode GT() { + return getToken(JavaParser.GT, 0); + } + + public List COMMA() { + return getTokens(JavaParser.COMMA); + } + + public TerminalNode COMMA(int i) { + return getToken(JavaParser.COMMA, i); + } + + public TypeArgumentsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_typeArguments; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterTypeArguments(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitTypeArguments(this); + } + } + + public final TypeArgumentsContext typeArguments() throws RecognitionException { + TypeArgumentsContext _localctx = new TypeArgumentsContext(_ctx, getState()); + enterRule(_localctx, 244, RULE_typeArguments); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1725); + match(LT); + setState(1726); + typeArgument(); + setState(1731); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == COMMA) { + { + { + setState(1727); + match(COMMA); + setState(1728); + typeArgument(); + } + } + setState(1733); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1734); + match(GT); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SuperSuffixContext extends ParserRuleContext { + public ArgumentsContext arguments() { + return getRuleContext(ArgumentsContext.class, 0); + } + + public TerminalNode DOT() { + return getToken(JavaParser.DOT, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public TypeArgumentsContext typeArguments() { + return getRuleContext(TypeArgumentsContext.class, 0); + } + + public SuperSuffixContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_superSuffix; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterSuperSuffix(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitSuperSuffix(this); + } + } + + public final SuperSuffixContext superSuffix() throws RecognitionException { + SuperSuffixContext _localctx = new SuperSuffixContext(_ctx, getState()); + enterRule(_localctx, 246, RULE_superSuffix); + int _la; + try { + setState(1745); + _errHandler.sync(this); + switch (_input.LA(1)) { + case LPAREN: + enterOuterAlt(_localctx, 1); + { + setState(1736); + arguments(); + } + break; + case DOT: + enterOuterAlt(_localctx, 2); + { + setState(1737); + match(DOT); + setState(1739); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == LT) { + { + setState(1738); + typeArguments(); + } + } + + setState(1741); + identifier(); + setState(1743); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 216, _ctx)) { + case 1: + { + setState(1742); + arguments(); + } + break; + } + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ExplicitGenericInvocationSuffixContext extends ParserRuleContext { + public TerminalNode SUPER() { + return getToken(JavaParser.SUPER, 0); + } + + public SuperSuffixContext superSuffix() { + return getRuleContext(SuperSuffixContext.class, 0); + } + + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class, 0); + } + + public ArgumentsContext arguments() { + return getRuleContext(ArgumentsContext.class, 0); + } + + public ExplicitGenericInvocationSuffixContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_explicitGenericInvocationSuffix; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).enterExplicitGenericInvocationSuffix(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) + ((JavaParserListener) listener).exitExplicitGenericInvocationSuffix(this); + } + } + + public final ExplicitGenericInvocationSuffixContext explicitGenericInvocationSuffix() throws RecognitionException { + ExplicitGenericInvocationSuffixContext _localctx = new ExplicitGenericInvocationSuffixContext(_ctx, getState()); + enterRule(_localctx, 248, RULE_explicitGenericInvocationSuffix); + try { + setState(1752); + _errHandler.sync(this); + switch (_input.LA(1)) { + case SUPER: + enterOuterAlt(_localctx, 1); + { + setState(1747); + match(SUPER); + setState(1748); + superSuffix(); + } + break; + case MODULE: + case OPEN: + case REQUIRES: + case EXPORTS: + case OPENS: + case TO: + case USES: + case PROVIDES: + case WITH: + case TRANSITIVE: + case VAR: + case YIELD: + case RECORD: + case SEALED: + case PERMITS: + case IDENTIFIER: + enterOuterAlt(_localctx, 2); + { + setState(1749); + identifier(); + setState(1750); + arguments(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ArgumentsContext extends ParserRuleContext { + public TerminalNode LPAREN() { + return getToken(JavaParser.LPAREN, 0); + } + + public TerminalNode RPAREN() { + return getToken(JavaParser.RPAREN, 0); + } + + public ExpressionListContext expressionList() { + return getRuleContext(ExpressionListContext.class, 0); + } + + public ArgumentsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_arguments; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).enterArguments(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavaParserListener) ((JavaParserListener) listener).exitArguments(this); + } + } + + public final ArgumentsContext arguments() throws RecognitionException { + ArgumentsContext _localctx = new ArgumentsContext(_ctx, getState()); + enterRule(_localctx, 250, RULE_arguments); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1754); + match(LPAREN); + setState(1756); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & 9223127275610966053L) != 0) + || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & 4683743741343698943L) != 0)) { + { + setState(1755); + expressionList(); + } + } + + setState(1758); + match(RPAREN); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { + switch (ruleIndex) { + case 99: + return expression_sempred((ExpressionContext) _localctx, predIndex); + case 107: + return guardedPattern_sempred((GuardedPatternContext) _localctx, predIndex); + } + return true; + } + + private boolean expression_sempred(ExpressionContext _localctx, int predIndex) { + switch (predIndex) { + case 0: + return precpred(_ctx, 14); + case 1: + return precpred(_ctx, 13); + case 2: + return precpred(_ctx, 12); + case 3: + return precpred(_ctx, 11); + case 4: + return precpred(_ctx, 9); + case 5: + return precpred(_ctx, 8); + case 6: + return precpred(_ctx, 7); + case 7: + return precpred(_ctx, 6); + case 8: + return precpred(_ctx, 5); + case 9: + return precpred(_ctx, 4); + case 10: + return precpred(_ctx, 3); + case 11: + return precpred(_ctx, 2); + case 12: + return precpred(_ctx, 25); + case 13: + return precpred(_ctx, 24); + case 14: + return precpred(_ctx, 22); + case 15: + return precpred(_ctx, 18); + case 16: + return precpred(_ctx, 10); + } + return true; + } + + private boolean guardedPattern_sempred(GuardedPatternContext _localctx, int predIndex) { + switch (predIndex) { + case 17: + return precpred(_ctx, 1); + } + return true; + } + + public static final String _serializedATN = + "\u0004\u0001\u0081\u06e1\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001" + + "\u0002\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004\u0007\u0004" + + "\u0002\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007\u0007\u0007" + + "\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b\u0007\u000b" + + "\u0002\f\u0007\f\u0002\r\u0007\r\u0002\u000e\u0007\u000e\u0002\u000f\u0007" + + "\u000f\u0002\u0010\u0007\u0010\u0002\u0011\u0007\u0011\u0002\u0012\u0007" + + "\u0012\u0002\u0013\u0007\u0013\u0002\u0014\u0007\u0014\u0002\u0015\u0007" + + "\u0015\u0002\u0016\u0007\u0016\u0002\u0017\u0007\u0017\u0002\u0018\u0007" + + "\u0018\u0002\u0019\u0007\u0019\u0002\u001a\u0007\u001a\u0002\u001b\u0007" + + "\u001b\u0002\u001c\u0007\u001c\u0002\u001d\u0007\u001d\u0002\u001e\u0007" + + "\u001e\u0002\u001f\u0007\u001f\u0002 \u0007 \u0002!\u0007!\u0002\"\u0007" + + "\"\u0002#\u0007#\u0002$\u0007$\u0002%\u0007%\u0002&\u0007&\u0002\'\u0007" + + "\'\u0002(\u0007(\u0002)\u0007)\u0002*\u0007*\u0002+\u0007+\u0002,\u0007" + + ",\u0002-\u0007-\u0002.\u0007.\u0002/\u0007/\u00020\u00070\u00021\u0007" + + "1\u00022\u00072\u00023\u00073\u00024\u00074\u00025\u00075\u00026\u0007" + + "6\u00027\u00077\u00028\u00078\u00029\u00079\u0002:\u0007:\u0002;\u0007" + + ";\u0002<\u0007<\u0002=\u0007=\u0002>\u0007>\u0002?\u0007?\u0002@\u0007" + + "@\u0002A\u0007A\u0002B\u0007B\u0002C\u0007C\u0002D\u0007D\u0002E\u0007" + + "E\u0002F\u0007F\u0002G\u0007G\u0002H\u0007H\u0002I\u0007I\u0002J\u0007" + + "J\u0002K\u0007K\u0002L\u0007L\u0002M\u0007M\u0002N\u0007N\u0002O\u0007" + + "O\u0002P\u0007P\u0002Q\u0007Q\u0002R\u0007R\u0002S\u0007S\u0002T\u0007" + + "T\u0002U\u0007U\u0002V\u0007V\u0002W\u0007W\u0002X\u0007X\u0002Y\u0007" + + "Y\u0002Z\u0007Z\u0002[\u0007[\u0002\\\u0007\\\u0002]\u0007]\u0002^\u0007" + + "^\u0002_\u0007_\u0002`\u0007`\u0002a\u0007a\u0002b\u0007b\u0002c\u0007" + + "c\u0002d\u0007d\u0002e\u0007e\u0002f\u0007f\u0002g\u0007g\u0002h\u0007" + + "h\u0002i\u0007i\u0002j\u0007j\u0002k\u0007k\u0002l\u0007l\u0002m\u0007" + + "m\u0002n\u0007n\u0002o\u0007o\u0002p\u0007p\u0002q\u0007q\u0002r\u0007" + + "r\u0002s\u0007s\u0002t\u0007t\u0002u\u0007u\u0002v\u0007v\u0002w\u0007" + + "w\u0002x\u0007x\u0002y\u0007y\u0002z\u0007z\u0002{\u0007{\u0002|\u0007" + + "|\u0002}\u0007}\u0001\u0000\u0003\u0000\u00fe\b\u0000\u0001\u0000\u0001" + + "\u0000\u0005\u0000\u0102\b\u0000\n\u0000\f\u0000\u0105\t\u0000\u0001\u0000" + + "\u0005\u0000\u0108\b\u0000\n\u0000\f\u0000\u010b\t\u0000\u0001\u0000\u0001" + + "\u0000\u0005\u0000\u010f\b\u0000\n\u0000\f\u0000\u0112\t\u0000\u0001\u0000" + + "\u0001\u0000\u0001\u0000\u0003\u0000\u0117\b\u0000\u0001\u0001\u0005\u0001" + + "\u011a\b\u0001\n\u0001\f\u0001\u011d\t\u0001\u0001\u0001\u0001\u0001\u0001" + + "\u0001\u0001\u0001\u0001\u0002\u0001\u0002\u0003\u0002\u0125\b\u0002\u0001" + + "\u0002\u0001\u0002\u0001\u0002\u0003\u0002\u012a\b\u0002\u0001\u0002\u0001" + + "\u0002\u0001\u0003\u0005\u0003\u012f\b\u0003\n\u0003\f\u0003\u0132\t\u0003" + + "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0003\u0003" + + "\u0139\b\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004" + + "\u0003\u0004\u0140\b\u0004\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005" + + "\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005" + + "\u0003\u0005\u014c\b\u0005\u0001\u0006\u0001\u0006\u0003\u0006\u0150\b" + + "\u0006\u0001\u0007\u0001\u0007\u0001\u0007\u0003\u0007\u0155\b\u0007\u0001" + + "\u0007\u0001\u0007\u0003\u0007\u0159\b\u0007\u0001\u0007\u0001\u0007\u0003" + + "\u0007\u015d\b\u0007\u0001\u0007\u0001\u0007\u0003\u0007\u0161\b\u0007" + + "\u0001\u0007\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001\b\u0005\b\u0169" + + "\b\b\n\b\f\b\u016c\t\b\u0001\b\u0001\b\u0001\t\u0005\t\u0171\b\t\n\t\f" + + "\t\u0174\t\t\u0001\t\u0001\t\u0001\t\u0005\t\u0179\b\t\n\t\f\t\u017c\t" + + "\t\u0001\t\u0003\t\u017f\b\t\u0001\n\u0001\n\u0001\n\u0005\n\u0184\b\n" + + "\n\n\f\n\u0187\t\n\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0003" + + "\u000b\u018d\b\u000b\u0001\u000b\u0001\u000b\u0003\u000b\u0191\b\u000b" + + "\u0001\u000b\u0003\u000b\u0194\b\u000b\u0001\u000b\u0003\u000b\u0197\b" + + "\u000b\u0001\u000b\u0001\u000b\u0001\f\u0001\f\u0001\f\u0005\f\u019e\b" + + "\f\n\f\f\f\u01a1\t\f\u0001\r\u0005\r\u01a4\b\r\n\r\f\r\u01a7\t\r\u0001" + + "\r\u0001\r\u0003\r\u01ab\b\r\u0001\r\u0003\r\u01ae\b\r\u0001\u000e\u0001" + + "\u000e\u0005\u000e\u01b2\b\u000e\n\u000e\f\u000e\u01b5\t\u000e\u0001\u000f" + + "\u0001\u000f\u0001\u000f\u0003\u000f\u01ba\b\u000f\u0001\u000f\u0001\u000f" + + "\u0003\u000f\u01be\b\u000f\u0001\u000f\u0001\u000f\u0003\u000f\u01c2\b" + + "\u000f\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0005\u0010\u01c8" + + "\b\u0010\n\u0010\f\u0010\u01cb\t\u0010\u0001\u0010\u0001\u0010\u0001\u0011" + + "\u0001\u0011\u0005\u0011\u01d1\b\u0011\n\u0011\f\u0011\u01d4\t\u0011\u0001" + + "\u0011\u0001\u0011\u0001\u0012\u0001\u0012\u0003\u0012\u01da\b\u0012\u0001" + + "\u0012\u0001\u0012\u0005\u0012\u01de\b\u0012\n\u0012\f\u0012\u01e1\t\u0012" + + "\u0001\u0012\u0003\u0012\u01e4\b\u0012\u0001\u0013\u0001\u0013\u0001\u0013" + + "\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013" + + "\u0001\u0013\u0003\u0013\u01f0\b\u0013\u0001\u0014\u0001\u0014\u0001\u0014" + + "\u0001\u0014\u0001\u0014\u0005\u0014\u01f7\b\u0014\n\u0014\f\u0014\u01fa" + + "\t\u0014\u0001\u0014\u0001\u0014\u0003\u0014\u01fe\b\u0014\u0001\u0014" + + "\u0001\u0014\u0001\u0015\u0001\u0015\u0003\u0015\u0204\b\u0015\u0001\u0016" + + "\u0001\u0016\u0003\u0016\u0208\b\u0016\u0001\u0017\u0001\u0017\u0001\u0017" + + "\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0019\u0001\u0019\u0001\u0019" + + "\u0001\u0019\u0003\u0019\u0214\b\u0019\u0001\u0019\u0001\u0019\u0001\u001a" + + "\u0005\u001a\u0219\b\u001a\n\u001a\f\u001a\u021c\t\u001a\u0001\u001a\u0001" + + "\u001a\u0001\u001a\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0001" + + "\u001c\u0005\u001c\u0226\b\u001c\n\u001c\f\u001c\u0229\t\u001c\u0001\u001c" + + "\u0001\u001c\u0003\u001c\u022d\b\u001c\u0001\u001d\u0001\u001d\u0001\u001d" + + "\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0003\u001d" + + "\u0237\b\u001d\u0001\u001e\u0001\u001e\u0001\u001e\u0001\u001e\u0005\u001e" + + "\u023d\b\u001e\n\u001e\f\u001e\u0240\t\u001e\u0001\u001e\u0001\u001e\u0001" + + "\u001f\u0001\u001f\u0001\u001f\u0005\u001f\u0247\b\u001f\n\u001f\f\u001f" + + "\u024a\t\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001 \u0005 \u0250" + + "\b \n \f \u0253\t \u0001 \u0001 \u0001!\u0001!\u0001!\u0001!\u0001!\u0001" + + "!\u0003!\u025d\b!\u0001\"\u0005\"\u0260\b\"\n\"\f\"\u0263\t\"\u0001\"" + + "\u0001\"\u0001\"\u0001#\u0005#\u0269\b#\n#\f#\u026c\t#\u0001#\u0001#\u0001" + + "#\u0001#\u0001#\u0005#\u0273\b#\n#\f#\u0276\t#\u0001#\u0001#\u0003#\u027a" + + "\b#\u0001#\u0001#\u0001$\u0001$\u0001$\u0005$\u0281\b$\n$\f$\u0284\t$" + + "\u0001%\u0001%\u0001%\u0003%\u0289\b%\u0001&\u0001&\u0001&\u0005&\u028e" + + "\b&\n&\f&\u0291\t&\u0001\'\u0001\'\u0003\'\u0295\b\'\u0001(\u0001(\u0001" + + "(\u0001(\u0005(\u029b\b(\n(\f(\u029e\t(\u0001(\u0003(\u02a1\b(\u0003(" + + "\u02a3\b(\u0001(\u0001(\u0001)\u0001)\u0003)\u02a9\b)\u0001)\u0001)\u0005" + + ")\u02ad\b)\n)\f)\u02b0\t)\u0001)\u0001)\u0003)\u02b4\b)\u0001*\u0001*" + + "\u0005*\u02b8\b*\n*\f*\u02bb\t*\u0001*\u0001*\u0001*\u0003*\u02c0\b*\u0003" + + "*\u02c2\b*\u0001+\u0001+\u0001+\u0005+\u02c7\b+\n+\f+\u02ca\t+\u0001," + + "\u0001,\u0003,\u02ce\b,\u0001,\u0001,\u0001,\u0003,\u02d3\b,\u0001,\u0003" + + ",\u02d6\b,\u0003,\u02d8\b,\u0001,\u0001,\u0001-\u0001-\u0001-\u0001-\u0005" + + "-\u02e0\b-\n-\f-\u02e3\t-\u0001-\u0001-\u0001.\u0001.\u0001.\u0005.\u02ea" + + "\b.\n.\f.\u02ed\t.\u0001.\u0001.\u0003.\u02f1\b.\u0001.\u0003.\u02f4\b" + + ".\u0001/\u0005/\u02f7\b/\n/\f/\u02fa\t/\u0001/\u0001/\u0001/\u00010\u0005" + + "0\u0300\b0\n0\f0\u0303\t0\u00010\u00010\u00050\u0307\b0\n0\f0\u030a\t" + + "0\u00010\u00010\u00010\u00011\u00011\u00011\u00051\u0312\b1\n1\f1\u0315" + + "\t1\u00012\u00052\u0318\b2\n2\f2\u031b\t2\u00012\u00012\u00012\u00013" + + "\u00013\u00013\u00053\u0323\b3\n3\f3\u0326\t3\u00014\u00014\u00014\u0001" + + "4\u00014\u00014\u00014\u00034\u032f\b4\u00015\u00015\u00016\u00016\u0001" + + "7\u00017\u00017\u00057\u0338\b7\n7\f7\u033b\t7\u00017\u00017\u00017\u0001" + + "8\u00018\u00018\u00038\u0343\b8\u00018\u00018\u00018\u00038\u0348\b8\u0001" + + "8\u00038\u034b\b8\u00019\u00019\u00019\u00059\u0350\b9\n9\f9\u0353\t9" + + "\u0001:\u0001:\u0001:\u0001:\u0001;\u0001;\u0001;\u0003;\u035c\b;\u0001" + + "<\u0001<\u0001<\u0001<\u0005<\u0362\b<\n<\f<\u0365\t<\u0003<\u0367\b<" + + "\u0001<\u0003<\u036a\b<\u0001<\u0001<\u0001=\u0001=\u0001=\u0001=\u0001" + + "=\u0001>\u0001>\u0005>\u0375\b>\n>\f>\u0378\t>\u0001>\u0001>\u0001?\u0005" + + "?\u037d\b?\n?\f?\u0380\t?\u0001?\u0001?\u0003?\u0384\b?\u0001@\u0001@" + + "\u0001@\u0001@\u0001@\u0001@\u0003@\u038c\b@\u0001@\u0001@\u0003@\u0390" + + "\b@\u0001@\u0001@\u0003@\u0394\b@\u0001@\u0001@\u0003@\u0398\b@\u0001" + + "@\u0001@\u0003@\u039c\b@\u0003@\u039e\b@\u0001A\u0001A\u0003A\u03a2\b" + + "A\u0001B\u0001B\u0001B\u0001B\u0003B\u03a8\bB\u0001C\u0001C\u0001D\u0001" + + "D\u0001D\u0001E\u0003E\u03b0\bE\u0001E\u0001E\u0001E\u0001E\u0001F\u0001" + + "F\u0005F\u03b8\bF\nF\fF\u03bb\tF\u0001F\u0001F\u0001G\u0001G\u0005G\u03c1" + + "\bG\nG\fG\u03c4\tG\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0003" + + "G\u03cd\bG\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0003G\u03d5\bG\u0001" + + "G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001" + + "G\u0001G\u0003G\u03e3\bG\u0001H\u0001H\u0001I\u0001I\u0001I\u0003I\u03ea" + + "\bI\u0001I\u0001I\u0001I\u0003I\u03ef\bI\u0001I\u0001I\u0001J\u0001J\u0003" + + "J\u03f5\bJ\u0001J\u0001J\u0001K\u0001K\u0001K\u0005K\u03fc\bK\nK\fK\u03ff" + + "\tK\u0001L\u0001L\u0001L\u0001M\u0001M\u0001M\u0005M\u0407\bM\nM\fM\u040a" + + "\tM\u0001M\u0001M\u0001N\u0001N\u0005N\u0410\bN\nN\fN\u0413\tN\u0001N" + + "\u0001N\u0001O\u0001O\u0001O\u0001O\u0001O\u0003O\u041c\bO\u0001P\u0005" + + "P\u041f\bP\nP\fP\u0422\tP\u0001P\u0001P\u0001P\u0001P\u0001P\u0001P\u0001" + + "P\u0001P\u0003P\u042c\bP\u0001Q\u0001Q\u0001R\u0001R\u0001S\u0005S\u0433" + + "\bS\nS\fS\u0436\tS\u0001S\u0001S\u0001S\u0003S\u043b\bS\u0001T\u0001T" + + "\u0001T\u0001T\u0001T\u0003T\u0442\bT\u0001T\u0001T\u0001T\u0001T\u0001" + + "T\u0001T\u0001T\u0003T\u044b\bT\u0001T\u0001T\u0001T\u0001T\u0001T\u0001" + + "T\u0001T\u0001T\u0001T\u0001T\u0001T\u0001T\u0001T\u0001T\u0001T\u0001" + + "T\u0001T\u0001T\u0001T\u0004T\u0460\bT\u000bT\fT\u0461\u0001T\u0003T\u0465" + + "\bT\u0001T\u0003T\u0468\bT\u0001T\u0001T\u0001T\u0001T\u0005T\u046e\b" + + "T\nT\fT\u0471\tT\u0001T\u0003T\u0474\bT\u0001T\u0001T\u0001T\u0001T\u0005" + + "T\u047a\bT\nT\fT\u047d\tT\u0001T\u0005T\u0480\bT\nT\fT\u0483\tT\u0001" + + "T\u0001T\u0001T\u0001T\u0001T\u0001T\u0001T\u0001T\u0003T\u048d\bT\u0001" + + "T\u0001T\u0001T\u0001T\u0001T\u0001T\u0001T\u0003T\u0496\bT\u0001T\u0001" + + "T\u0001T\u0003T\u049b\bT\u0001T\u0001T\u0001T\u0001T\u0001T\u0001T\u0001" + + "T\u0001T\u0001T\u0001T\u0001T\u0003T\u04a8\bT\u0001T\u0001T\u0001T\u0001" + + "T\u0003T\u04ae\bT\u0001U\u0001U\u0001U\u0005U\u04b3\bU\nU\fU\u04b6\tU" + + "\u0001U\u0001U\u0001U\u0001U\u0001U\u0001V\u0001V\u0001V\u0005V\u04c0" + + "\bV\nV\fV\u04c3\tV\u0001W\u0001W\u0001W\u0001X\u0001X\u0001X\u0003X\u04cb" + + "\bX\u0001X\u0001X\u0001Y\u0001Y\u0001Y\u0005Y\u04d2\bY\nY\fY\u04d5\tY" + + "\u0001Z\u0005Z\u04d8\bZ\nZ\fZ\u04db\tZ\u0001Z\u0001Z\u0001Z\u0001Z\u0001" + + "Z\u0003Z\u04e2\bZ\u0001Z\u0001Z\u0001Z\u0001Z\u0003Z\u04e8\bZ\u0001[\u0004" + + "[\u04eb\b[\u000b[\f[\u04ec\u0001[\u0004[\u04f0\b[\u000b[\f[\u04f1\u0001" + + "\\\u0001\\\u0001\\\u0001\\\u0001\\\u0001\\\u0003\\\u04fa\b\\\u0001\\\u0001" + + "\\\u0001\\\u0003\\\u04ff\b\\\u0001]\u0001]\u0003]\u0503\b]\u0001]\u0001" + + "]\u0003]\u0507\b]\u0001]\u0001]\u0003]\u050b\b]\u0003]\u050d\b]\u0001" + + "^\u0001^\u0003^\u0511\b^\u0001_\u0005_\u0514\b_\n_\f_\u0517\t_\u0001_" + + "\u0001_\u0003_\u051b\b_\u0001_\u0001_\u0001_\u0001_\u0001`\u0001`\u0001" + + "`\u0001`\u0001a\u0001a\u0001a\u0005a\u0528\ba\na\fa\u052b\ta\u0001b\u0001" + + "b\u0001b\u0003b\u0530\bb\u0001b\u0001b\u0001c\u0001c\u0001c\u0001c\u0001" + + "c\u0001c\u0003c\u053a\bc\u0001c\u0001c\u0003c\u053e\bc\u0001c\u0001c\u0001" + + "c\u0003c\u0543\bc\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0005" + + "c\u054c\bc\nc\fc\u054f\tc\u0001c\u0001c\u0001c\u0005c\u0554\bc\nc\fc\u0557" + + "\tc\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0003c\u055f\bc\u0001c\u0001" + + "c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001" + + "c\u0001c\u0001c\u0003c\u056f\bc\u0001c\u0001c\u0001c\u0001c\u0001c\u0001" + + "c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001" + + "c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001" + + "c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001" + + "c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0003c\u059c\bc\u0001" + + "c\u0001c\u0001c\u0001c\u0003c\u05a2\bc\u0001c\u0001c\u0001c\u0003c\u05a7" + + "\bc\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0001c\u0003c\u05b0\bc\u0005" + + "c\u05b2\bc\nc\fc\u05b5\tc\u0001d\u0005d\u05b8\bd\nd\fd\u05bb\td\u0001" + + "d\u0001d\u0005d\u05bf\bd\nd\fd\u05c2\td\u0001d\u0001d\u0001e\u0001e\u0001" + + "e\u0001e\u0001f\u0001f\u0001f\u0003f\u05cd\bf\u0001f\u0001f\u0001f\u0001" + + "f\u0001f\u0005f\u05d4\bf\nf\ff\u05d7\tf\u0001f\u0001f\u0001f\u0001f\u0003" + + "f\u05dd\bf\u0001f\u0003f\u05e0\bf\u0001g\u0001g\u0003g\u05e4\bg\u0001" + + "h\u0001h\u0001h\u0001h\u0001h\u0001h\u0001h\u0001h\u0001h\u0001h\u0001" + + "h\u0001h\u0001h\u0001h\u0001h\u0001h\u0003h\u05f6\bh\u0003h\u05f8\bh\u0001" + + "i\u0001i\u0001i\u0001i\u0005i\u05fe\bi\ni\fi\u0601\ti\u0001i\u0001i\u0001" + + "j\u0001j\u0001j\u0001j\u0003j\u0609\bj\u0001j\u0001j\u0001j\u0001j\u0001" + + "j\u0003j\u0610\bj\u0001k\u0001k\u0001k\u0001k\u0001k\u0001k\u0005k\u0618" + + "\bk\nk\fk\u061b\tk\u0001k\u0001k\u0005k\u061f\bk\nk\fk\u0622\tk\u0001" + + "k\u0001k\u0001k\u0005k\u0627\bk\nk\fk\u062a\tk\u0003k\u062c\bk\u0001k" + + "\u0001k\u0001k\u0005k\u0631\bk\nk\fk\u0634\tk\u0001l\u0001l\u0005l\u0638" + + "\bl\nl\fl\u063b\tl\u0003l\u063d\bl\u0001m\u0001m\u0001m\u0003m\u0642\b" + + "m\u0001m\u0005m\u0645\bm\nm\fm\u0648\tm\u0001m\u0001m\u0003m\u064c\bm" + + "\u0001n\u0003n\u064f\bn\u0001n\u0001n\u0001n\u0001n\u0001n\u0001n\u0003" + + "n\u0657\bn\u0001o\u0001o\u0003o\u065b\bo\u0001o\u0001o\u0001o\u0003o\u0660" + + "\bo\u0005o\u0662\bo\no\fo\u0665\to\u0001o\u0003o\u0668\bo\u0001p\u0001" + + "p\u0003p\u066c\bp\u0001p\u0001p\u0001q\u0001q\u0004q\u0672\bq\u000bq\f" + + "q\u0673\u0001q\u0001q\u0001q\u0001q\u0001q\u0004q\u067b\bq\u000bq\fq\u067c" + + "\u0001q\u0001q\u0005q\u0681\bq\nq\fq\u0684\tq\u0003q\u0686\bq\u0001r\u0001" + + "r\u0003r\u068a\br\u0001s\u0001s\u0001s\u0001t\u0001t\u0001t\u0003t\u0692" + + "\bt\u0001u\u0001u\u0001u\u0003u\u0697\bu\u0001v\u0001v\u0001v\u0001v\u0001" + + "w\u0001w\u0001w\u0005w\u06a0\bw\nw\fw\u06a3\tw\u0001x\u0005x\u06a6\bx" + + "\nx\fx\u06a9\tx\u0001x\u0001x\u0003x\u06ad\bx\u0001x\u0005x\u06b0\bx\n" + + "x\fx\u06b3\tx\u0001x\u0001x\u0005x\u06b7\bx\nx\fx\u06ba\tx\u0001y\u0001" + + "y\u0001z\u0001z\u0001z\u0001z\u0005z\u06c2\bz\nz\fz\u06c5\tz\u0001z\u0001" + + "z\u0001{\u0001{\u0001{\u0003{\u06cc\b{\u0001{\u0001{\u0003{\u06d0\b{\u0003" + + "{\u06d2\b{\u0001|\u0001|\u0001|\u0001|\u0001|\u0003|\u06d9\b|\u0001}\u0001" + + "}\u0003}\u06dd\b}\u0001}\u0001}\u0001}\u0000\u0002\u00c6\u00d6~\u0000" + + "\u0002\u0004\u0006\b\n\f\u000e\u0010\u0012\u0014\u0016\u0018\u001a\u001c" + + "\u001e \"$&(*,.02468:<>@BDFHJLNPRTVXZ\\^`bdfhjlnprtvxz|~\u0080\u0082\u0084" + + "\u0086\u0088\u008a\u008c\u008e\u0090\u0092\u0094\u0096\u0098\u009a\u009c" + + "\u009e\u00a0\u00a2\u00a4\u00a6\u00a8\u00aa\u00ac\u00ae\u00b0\u00b2\u00b4" + + "\u00b6\u00b8\u00ba\u00bc\u00be\u00c0\u00c2\u00c4\u00c6\u00c8\u00ca\u00cc" + + "\u00ce\u00d0\u00d2\u00d4\u00d6\u00d8\u00da\u00dc\u00de\u00e0\u00e2\u00e4" + + "\u00e6\u00e8\u00ea\u00ec\u00ee\u00f0\u00f2\u00f4\u00f6\u00f8\u00fa\u0000" + + "\u000f\u0002\u0000\u0011\u0011((\u0001\u0000CF\u0001\u0000GH\u0002\u0000" + + "&&<<\u0002\u00003A\u0081\u0081\u0003\u00003\u0243\u0001\u0000\u0000\u0000@\u0251\u0001\u0000\u0000\u0000" + + "B\u025c\u0001\u0000\u0000\u0000D\u0261\u0001\u0000\u0000\u0000F\u026a" + + "\u0001\u0000\u0000\u0000H\u027d\u0001\u0000\u0000\u0000J\u0285\u0001\u0000" + + "\u0000\u0000L\u028a\u0001\u0000\u0000\u0000N\u0294\u0001\u0000\u0000\u0000" + + "P\u0296\u0001\u0000\u0000\u0000R\u02ae\u0001\u0000\u0000\u0000T\u02c1" + + "\u0001\u0000\u0000\u0000V\u02c3\u0001\u0000\u0000\u0000X\u02cb\u0001\u0000" + + "\u0000\u0000Z\u02db\u0001\u0000\u0000\u0000\\\u02f3\u0001\u0000\u0000" + + "\u0000^\u02f8\u0001\u0000\u0000\u0000`\u0301\u0001\u0000\u0000\u0000b" + + "\u030e\u0001\u0000\u0000\u0000d\u0319\u0001\u0000\u0000\u0000f\u031f\u0001" + + "\u0000\u0000\u0000h\u032e\u0001\u0000\u0000\u0000j\u0330\u0001\u0000\u0000" + + "\u0000l\u0332\u0001\u0000\u0000\u0000n\u0339\u0001\u0000\u0000\u0000p" + + "\u0342\u0001\u0000\u0000\u0000r\u034c\u0001\u0000\u0000\u0000t\u0354\u0001" + + "\u0000\u0000\u0000v\u035b\u0001\u0000\u0000\u0000x\u035d\u0001\u0000\u0000" + + "\u0000z\u036d\u0001\u0000\u0000\u0000|\u0372\u0001\u0000\u0000\u0000~" + + "\u0383\u0001\u0000\u0000\u0000\u0080\u039d\u0001\u0000\u0000\u0000\u0082" + + "\u03a1\u0001\u0000\u0000\u0000\u0084\u03a3\u0001\u0000\u0000\u0000\u0086" + + "\u03a9\u0001\u0000\u0000\u0000\u0088\u03ab\u0001\u0000\u0000\u0000\u008a" + + "\u03af\u0001\u0000\u0000\u0000\u008c\u03b5\u0001\u0000\u0000\u0000\u008e" + + "\u03e2\u0001\u0000\u0000\u0000\u0090\u03e4\u0001\u0000\u0000\u0000\u0092" + + "\u03e6\u0001\u0000\u0000\u0000\u0094\u03f2\u0001\u0000\u0000\u0000\u0096" + + "\u03f8\u0001\u0000\u0000\u0000\u0098\u0400\u0001\u0000\u0000\u0000\u009a" + + "\u0403\u0001\u0000\u0000\u0000\u009c\u040d\u0001\u0000\u0000\u0000\u009e" + + "\u041b\u0001\u0000\u0000\u0000\u00a0\u0420\u0001\u0000\u0000\u0000\u00a2" + + "\u042d\u0001\u0000\u0000\u0000\u00a4\u042f\u0001\u0000\u0000\u0000\u00a6" + + "\u0434\u0001\u0000\u0000\u0000\u00a8\u04ad\u0001\u0000\u0000\u0000\u00aa" + + "\u04af\u0001\u0000\u0000\u0000\u00ac\u04bc\u0001\u0000\u0000\u0000\u00ae" + + "\u04c4\u0001\u0000\u0000\u0000\u00b0\u04c7\u0001\u0000\u0000\u0000\u00b2" + + "\u04ce\u0001\u0000\u0000\u0000\u00b4\u04e7\u0001\u0000\u0000\u0000\u00b6" + + "\u04ea\u0001\u0000\u0000\u0000\u00b8\u04fe\u0001\u0000\u0000\u0000\u00ba" + + "\u050c\u0001\u0000\u0000\u0000\u00bc\u0510\u0001\u0000\u0000\u0000\u00be" + + "\u0515\u0001\u0000\u0000\u0000\u00c0\u0520\u0001\u0000\u0000\u0000\u00c2" + + "\u0524\u0001\u0000\u0000\u0000\u00c4\u052f\u0001\u0000\u0000\u0000\u00c6" + + "\u055e\u0001\u0000\u0000\u0000\u00c8\u05b9\u0001\u0000\u0000\u0000\u00ca" + + "\u05c5\u0001\u0000\u0000\u0000\u00cc\u05df\u0001\u0000\u0000\u0000\u00ce" + + "\u05e3\u0001\u0000\u0000\u0000\u00d0\u05f7\u0001\u0000\u0000\u0000\u00d2" + + "\u05f9\u0001\u0000\u0000\u0000\u00d4\u060f\u0001\u0000\u0000\u0000\u00d6" + + "\u062b\u0001\u0000\u0000\u0000\u00d8\u063c\u0001\u0000\u0000\u0000\u00da" + + "\u0641\u0001\u0000\u0000\u0000\u00dc\u0656\u0001\u0000\u0000\u0000\u00de" + + "\u0667\u0001\u0000\u0000\u0000\u00e0\u0669\u0001\u0000\u0000\u0000\u00e2" + + "\u0685\u0001\u0000\u0000\u0000\u00e4\u0687\u0001\u0000\u0000\u0000\u00e6" + + "\u068b\u0001\u0000\u0000\u0000\u00e8\u0691\u0001\u0000\u0000\u0000\u00ea" + + "\u0696\u0001\u0000\u0000\u0000\u00ec\u0698\u0001\u0000\u0000\u0000\u00ee" + + "\u069c\u0001\u0000\u0000\u0000\u00f0\u06a7\u0001\u0000\u0000\u0000\u00f2" + + "\u06bb\u0001\u0000\u0000\u0000\u00f4\u06bd\u0001\u0000\u0000\u0000\u00f6" + + "\u06d1\u0001\u0000\u0000\u0000\u00f8\u06d8\u0001\u0000\u0000\u0000\u00fa" + + "\u06da\u0001\u0000\u0000\u0000\u00fc\u00fe\u0003\u0002\u0001\u0000\u00fd" + + "\u00fc\u0001\u0000\u0000\u0000\u00fd\u00fe\u0001\u0000\u0000\u0000\u00fe" + + "\u0103\u0001\u0000\u0000\u0000\u00ff\u0102\u0003\u0004\u0002\u0000\u0100" + + "\u0102\u0005T\u0000\u0000\u0101\u00ff\u0001\u0000\u0000\u0000\u0101\u0100" + + "\u0001\u0000\u0000\u0000\u0102\u0105\u0001\u0000\u0000\u0000\u0103\u0101" + + "\u0001\u0000\u0000\u0000\u0103\u0104\u0001\u0000\u0000\u0000\u0104\u0109" + + "\u0001\u0000\u0000\u0000\u0105\u0103\u0001\u0000\u0000\u0000\u0106\u0108" + + "\u0005}\u0000\u0000\u0107\u0106\u0001\u0000\u0000\u0000\u0108\u010b\u0001" + + "\u0000\u0000\u0000\u0109\u0107\u0001\u0000\u0000\u0000\u0109\u010a\u0001" + + "\u0000\u0000\u0000\u010a\u0110\u0001\u0000\u0000\u0000\u010b\u0109\u0001" + + "\u0000\u0000\u0000\u010c\u010f\u0003\u0006\u0003\u0000\u010d\u010f\u0005" + + "T\u0000\u0000\u010e\u010c\u0001\u0000\u0000\u0000\u010e\u010d\u0001\u0000" + + "\u0000\u0000\u010f\u0112\u0001\u0000\u0000\u0000\u0110\u010e\u0001\u0000" + + "\u0000\u0000\u0110\u0111\u0001\u0000\u0000\u0000\u0111\u0117\u0001\u0000" + + "\u0000\u0000\u0112\u0110\u0001\u0000\u0000\u0000\u0113\u0114\u0003\u008a" + + "E\u0000\u0114\u0115\u0005\u0000\u0000\u0001\u0115\u0117\u0001\u0000\u0000" + + "\u0000\u0116\u00fd\u0001\u0000\u0000\u0000\u0116\u0113\u0001\u0000\u0000" + + "\u0000\u0117\u0001\u0001\u0000\u0000\u0000\u0118\u011a\u0003p8\u0000\u0119" + + "\u0118\u0001\u0000\u0000\u0000\u011a\u011d\u0001\u0000\u0000\u0000\u011b" + + "\u0119\u0001\u0000\u0000\u0000\u011b\u011c\u0001\u0000\u0000\u0000\u011c" + + "\u011e\u0001\u0000\u0000\u0000\u011d\u011b\u0001\u0000\u0000\u0000\u011e" + + "\u011f\u0005 \u0000\u0000\u011f\u0120\u0003f3\u0000\u0120\u0121\u0005" + + "T\u0000\u0000\u0121\u0003\u0001\u0000\u0000\u0000\u0122\u0124\u0005\u0019" + + "\u0000\u0000\u0123\u0125\u0005&\u0000\u0000\u0124\u0123\u0001\u0000\u0000" + + "\u0000\u0124\u0125\u0001\u0000\u0000\u0000\u0125\u0126\u0001\u0000\u0000" + + "\u0000\u0126\u0129\u0003f3\u0000\u0127\u0128\u0005V\u0000\u0000\u0128" + + "\u012a\u0005h\u0000\u0000\u0129\u0127\u0001\u0000\u0000\u0000\u0129\u012a" + + "\u0001\u0000\u0000\u0000\u012a\u012b\u0001\u0000\u0000\u0000\u012b\u012c" + + "\u0005T\u0000\u0000\u012c\u0005\u0001\u0000\u0000\u0000\u012d\u012f\u0003" + + "\n\u0005\u0000\u012e\u012d\u0001\u0000\u0000\u0000\u012f\u0132\u0001\u0000" + + "\u0000\u0000\u0130\u012e\u0001\u0000\u0000\u0000\u0130\u0131\u0001\u0000" + + "\u0000\u0000\u0131\u0138\u0001\u0000\u0000\u0000\u0132\u0130\u0001\u0000" + + "\u0000\u0000\u0133\u0139\u0003\u000e\u0007\u0000\u0134\u0139\u0003\u0016" + + "\u000b\u0000\u0135\u0139\u0003\u001e\u000f\u0000\u0136\u0139\u0003z=\u0000" + + "\u0137\u0139\u0003\u0092I\u0000\u0138\u0133\u0001\u0000\u0000\u0000\u0138" + + "\u0134\u0001\u0000\u0000\u0000\u0138\u0135\u0001\u0000\u0000\u0000\u0138" + + "\u0136\u0001\u0000\u0000\u0000\u0138\u0137\u0001\u0000\u0000\u0000\u0139" + + "\u0007\u0001\u0000\u0000\u0000\u013a\u0140\u0003\n\u0005\u0000\u013b\u0140" + + "\u0005\u001e\u0000\u0000\u013c\u0140\u0005*\u0000\u0000\u013d\u0140\u0005" + + ".\u0000\u0000\u013e\u0140\u00051\u0000\u0000\u013f\u013a\u0001\u0000\u0000" + + "\u0000\u013f\u013b\u0001\u0000\u0000\u0000\u013f\u013c\u0001\u0000\u0000" + + "\u0000\u013f\u013d\u0001\u0000\u0000\u0000\u013f\u013e\u0001\u0000\u0000" + + "\u0000\u0140\t\u0001\u0000\u0000\u0000\u0141\u014c\u0003p8\u0000\u0142" + + "\u014c\u0005#\u0000\u0000\u0143\u014c\u0005\"\u0000\u0000\u0144\u014c" + + "\u0005!\u0000\u0000\u0145\u014c\u0005&\u0000\u0000\u0146\u014c\u0005\u0001" + + "\u0000\u0000\u0147\u014c\u0005\u0012\u0000\u0000\u0148\u014c\u0005\'\u0000" + + "\u0000\u0149\u014c\u0005@\u0000\u0000\u014a\u014c\u0005B\u0000\u0000\u014b" + + "\u0141\u0001\u0000\u0000\u0000\u014b\u0142\u0001\u0000\u0000\u0000\u014b" + + "\u0143\u0001\u0000\u0000\u0000\u014b\u0144\u0001\u0000\u0000\u0000\u014b" + + "\u0145\u0001\u0000\u0000\u0000\u014b\u0146\u0001\u0000\u0000\u0000\u014b" + + "\u0147\u0001\u0000\u0000\u0000\u014b\u0148\u0001\u0000\u0000\u0000\u014b" + + "\u0149\u0001\u0000\u0000\u0000\u014b\u014a\u0001\u0000\u0000\u0000\u014c" + + "\u000b\u0001\u0000\u0000\u0000\u014d\u0150\u0005\u0012\u0000\u0000\u014e" + + "\u0150\u0003p8\u0000\u014f\u014d\u0001\u0000\u0000\u0000\u014f\u014e\u0001" + + "\u0000\u0000\u0000\u0150\r\u0001\u0000\u0000\u0000\u0151\u0152\u0005\t" + + "\u0000\u0000\u0152\u0154\u0003\u00a2Q\u0000\u0153\u0155\u0003\u0010\b" + + "\u0000\u0154\u0153\u0001\u0000\u0000\u0000\u0154\u0155\u0001\u0000\u0000" + + "\u0000\u0155\u0158\u0001\u0000\u0000\u0000\u0156\u0157\u0005\u0011\u0000" + + "\u0000\u0157\u0159\u0003\u00f0x\u0000\u0158\u0156\u0001\u0000\u0000\u0000" + + "\u0158\u0159\u0001\u0000\u0000\u0000\u0159\u015c\u0001\u0000\u0000\u0000" + + "\u015a\u015b\u0005\u0018\u0000\u0000\u015b\u015d\u0003\u00eew\u0000\u015c" + + "\u015a\u0001\u0000\u0000\u0000\u015c\u015d\u0001\u0000\u0000\u0000\u015d" + + "\u0160\u0001\u0000\u0000\u0000\u015e\u015f\u0005A\u0000\u0000\u015f\u0161" + + "\u0003\u00eew\u0000\u0160\u015e\u0001\u0000\u0000\u0000\u0160\u0161\u0001" + + "\u0000\u0000\u0000\u0161\u0162\u0001\u0000\u0000\u0000\u0162\u0163\u0003" + + " \u0010\u0000\u0163\u000f\u0001\u0000\u0000\u0000\u0164\u0165\u0005Y\u0000" + + "\u0000\u0165\u016a\u0003\u0012\t\u0000\u0166\u0167\u0005U\u0000\u0000" + + "\u0167\u0169\u0003\u0012\t\u0000\u0168\u0166\u0001\u0000\u0000\u0000\u0169" + + "\u016c\u0001\u0000\u0000\u0000\u016a\u0168\u0001\u0000\u0000\u0000\u016a" + + "\u016b\u0001\u0000\u0000\u0000\u016b\u016d\u0001\u0000\u0000\u0000\u016c" + + "\u016a\u0001\u0000\u0000\u0000\u016d\u016e\u0005X\u0000\u0000\u016e\u0011" + + "\u0001\u0000\u0000\u0000\u016f\u0171\u0003p8\u0000\u0170\u016f\u0001\u0000" + + "\u0000\u0000\u0171\u0174\u0001\u0000\u0000\u0000\u0172\u0170\u0001\u0000" + + "\u0000\u0000\u0172\u0173\u0001\u0000\u0000\u0000\u0173\u0175\u0001\u0000" + + "\u0000\u0000\u0174\u0172\u0001\u0000\u0000\u0000\u0175\u017e\u0003\u00a2" + + "Q\u0000\u0176\u017a\u0005\u0011\u0000\u0000\u0177\u0179\u0003p8\u0000" + + "\u0178\u0177\u0001\u0000\u0000\u0000\u0179\u017c\u0001\u0000\u0000\u0000" + + "\u017a\u0178\u0001\u0000\u0000\u0000\u017a\u017b\u0001\u0000\u0000\u0000" + + "\u017b\u017d\u0001\u0000\u0000\u0000\u017c\u017a\u0001\u0000\u0000\u0000" + + "\u017d\u017f\u0003\u0014\n\u0000\u017e\u0176\u0001\u0000\u0000\u0000\u017e" + + "\u017f\u0001\u0000\u0000\u0000\u017f\u0013\u0001\u0000\u0000\u0000\u0180" + + "\u0185\u0003\u00f0x\u0000\u0181\u0182\u0005j\u0000\u0000\u0182\u0184\u0003" + + "\u00f0x\u0000\u0183\u0181\u0001\u0000\u0000\u0000\u0184\u0187\u0001\u0000" + + "\u0000\u0000\u0185\u0183\u0001\u0000\u0000\u0000\u0185\u0186\u0001\u0000" + + "\u0000\u0000\u0186\u0015\u0001\u0000\u0000\u0000\u0187\u0185\u0001\u0000" + + "\u0000\u0000\u0188\u0189\u0005\u0010\u0000\u0000\u0189\u018c\u0003\u00a2" + + "Q\u0000\u018a\u018b\u0005\u0018\u0000\u0000\u018b\u018d\u0003\u00eew\u0000" + + "\u018c\u018a\u0001\u0000\u0000\u0000\u018c\u018d\u0001\u0000\u0000\u0000" + + "\u018d\u018e\u0001\u0000\u0000\u0000\u018e\u0190\u0005P\u0000\u0000\u018f" + + "\u0191\u0003\u0018\f\u0000\u0190\u018f\u0001\u0000\u0000\u0000\u0190\u0191" + + "\u0001\u0000\u0000\u0000\u0191\u0193\u0001\u0000\u0000\u0000\u0192\u0194" + + "\u0005U\u0000\u0000\u0193\u0192\u0001\u0000\u0000\u0000\u0193\u0194\u0001" + + "\u0000\u0000\u0000\u0194\u0196\u0001\u0000\u0000\u0000\u0195\u0197\u0003" + + "\u001c\u000e\u0000\u0196\u0195\u0001\u0000\u0000\u0000\u0196\u0197\u0001" + + "\u0000\u0000\u0000\u0197\u0198\u0001\u0000\u0000\u0000\u0198\u0199\u0005" + + "Q\u0000\u0000\u0199\u0017\u0001\u0000\u0000\u0000\u019a\u019f\u0003\u001a" + + "\r\u0000\u019b\u019c\u0005U\u0000\u0000\u019c\u019e\u0003\u001a\r\u0000" + + "\u019d\u019b\u0001\u0000\u0000\u0000\u019e\u01a1\u0001\u0000\u0000\u0000" + + "\u019f\u019d\u0001\u0000\u0000\u0000\u019f\u01a0\u0001\u0000\u0000\u0000" + + "\u01a0\u0019\u0001\u0000\u0000\u0000\u01a1\u019f\u0001\u0000\u0000\u0000" + + "\u01a2\u01a4\u0003p8\u0000\u01a3\u01a2\u0001\u0000\u0000\u0000\u01a4\u01a7" + + "\u0001\u0000\u0000\u0000\u01a5\u01a3\u0001\u0000\u0000\u0000\u01a5\u01a6" + + "\u0001\u0000\u0000\u0000\u01a6\u01a8\u0001\u0000\u0000\u0000\u01a7\u01a5" + + "\u0001\u0000\u0000\u0000\u01a8\u01aa\u0003\u00a2Q\u0000\u01a9\u01ab\u0003" + + "\u00fa}\u0000\u01aa\u01a9\u0001\u0000\u0000\u0000\u01aa\u01ab\u0001\u0000" + + "\u0000\u0000\u01ab\u01ad\u0001\u0000\u0000\u0000\u01ac\u01ae\u0003 \u0010" + + "\u0000\u01ad\u01ac\u0001\u0000\u0000\u0000\u01ad\u01ae\u0001\u0000\u0000" + + "\u0000\u01ae\u001b\u0001\u0000\u0000\u0000\u01af\u01b3\u0005T\u0000\u0000" + + "\u01b0\u01b2\u0003$\u0012\u0000\u01b1\u01b0\u0001\u0000\u0000\u0000\u01b2" + + "\u01b5\u0001\u0000\u0000\u0000\u01b3\u01b1\u0001\u0000\u0000\u0000\u01b3" + + "\u01b4\u0001\u0000\u0000\u0000\u01b4\u001d\u0001\u0000\u0000\u0000\u01b5" + + "\u01b3\u0001\u0000\u0000\u0000\u01b6\u01b7\u0005\u001c\u0000\u0000\u01b7" + + "\u01b9\u0003\u00a2Q\u0000\u01b8\u01ba\u0003\u0010\b\u0000\u01b9\u01b8" + + "\u0001\u0000\u0000\u0000\u01b9\u01ba\u0001\u0000\u0000\u0000\u01ba\u01bd" + + "\u0001\u0000\u0000\u0000\u01bb\u01bc\u0005\u0011\u0000\u0000\u01bc\u01be" + + "\u0003\u00eew\u0000\u01bd\u01bb\u0001\u0000\u0000\u0000\u01bd\u01be\u0001" + + "\u0000\u0000\u0000\u01be\u01c1\u0001\u0000\u0000\u0000\u01bf\u01c0\u0005" + + "A\u0000\u0000\u01c0\u01c2\u0003\u00eew\u0000\u01c1\u01bf\u0001\u0000\u0000" + + "\u0000\u01c1\u01c2\u0001\u0000\u0000\u0000\u01c2\u01c3\u0001\u0000\u0000" + + "\u0000\u01c3\u01c4\u0003\"\u0011\u0000\u01c4\u001f\u0001\u0000\u0000\u0000" + + "\u01c5\u01c9\u0005P\u0000\u0000\u01c6\u01c8\u0003$\u0012\u0000\u01c7\u01c6" + + "\u0001\u0000\u0000\u0000\u01c8\u01cb\u0001\u0000\u0000\u0000\u01c9\u01c7" + + "\u0001\u0000\u0000\u0000\u01c9\u01ca\u0001\u0000\u0000\u0000\u01ca\u01cc" + + "\u0001\u0000\u0000\u0000\u01cb\u01c9\u0001\u0000\u0000\u0000\u01cc\u01cd" + + "\u0005Q\u0000\u0000\u01cd!\u0001\u0000\u0000\u0000\u01ce\u01d2\u0005P" + + "\u0000\u0000\u01cf\u01d1\u00038\u001c\u0000\u01d0\u01cf\u0001\u0000\u0000" + + "\u0000\u01d1\u01d4\u0001\u0000\u0000\u0000\u01d2\u01d0\u0001\u0000\u0000" + + "\u0000\u01d2\u01d3\u0001\u0000\u0000\u0000\u01d3\u01d5\u0001\u0000\u0000" + + "\u0000\u01d4\u01d2\u0001\u0000\u0000\u0000\u01d5\u01d6\u0005Q\u0000\u0000" + + "\u01d6#\u0001\u0000\u0000\u0000\u01d7\u01e4\u0005T\u0000\u0000\u01d8\u01da" + + "\u0005&\u0000\u0000\u01d9\u01d8\u0001\u0000\u0000\u0000\u01d9\u01da\u0001" + + "\u0000\u0000\u0000\u01da\u01db\u0001\u0000\u0000\u0000\u01db\u01e4\u0003" + + "\u009cN\u0000\u01dc\u01de\u0003\b\u0004\u0000\u01dd\u01dc\u0001\u0000" + + "\u0000\u0000\u01de\u01e1\u0001\u0000\u0000\u0000\u01df\u01dd\u0001\u0000" + + "\u0000\u0000\u01df\u01e0\u0001\u0000\u0000\u0000\u01e0\u01e2\u0001\u0000" + + "\u0000\u0000\u01e1\u01df\u0001\u0000\u0000\u0000\u01e2\u01e4\u0003&\u0013" + + "\u0000\u01e3\u01d7\u0001\u0000\u0000\u0000\u01e3\u01d9\u0001\u0000\u0000" + + "\u0000\u01e3\u01df\u0001\u0000\u0000\u0000\u01e4%\u0001\u0000\u0000\u0000" + + "\u01e5\u01f0\u0003\u0092I\u0000\u01e6\u01f0\u0003(\u0014\u0000\u01e7\u01f0" + + "\u0003.\u0017\u0000\u01e8\u01f0\u00036\u001b\u0000\u01e9\u01f0\u00032" + + "\u0019\u0000\u01ea\u01f0\u00030\u0018\u0000\u01eb\u01f0\u0003\u001e\u000f" + + "\u0000\u01ec\u01f0\u0003z=\u0000\u01ed\u01f0\u0003\u000e\u0007\u0000\u01ee" + + "\u01f0\u0003\u0016\u000b\u0000\u01ef\u01e5\u0001\u0000\u0000\u0000\u01ef" + + "\u01e6\u0001\u0000\u0000\u0000\u01ef\u01e7\u0001\u0000\u0000\u0000\u01ef" + + "\u01e8\u0001\u0000\u0000\u0000\u01ef\u01e9\u0001\u0000\u0000\u0000\u01ef" + + "\u01ea\u0001\u0000\u0000\u0000\u01ef\u01eb\u0001\u0000\u0000\u0000\u01ef" + + "\u01ec\u0001\u0000\u0000\u0000\u01ef\u01ed\u0001\u0000\u0000\u0000\u01ef" + + "\u01ee\u0001\u0000\u0000\u0000\u01f0\'\u0001\u0000\u0000\u0000\u01f1\u01f2" + + "\u0003,\u0016\u0000\u01f2\u01f3\u0003\u00a2Q\u0000\u01f3\u01f8\u0003X" + + ",\u0000\u01f4\u01f5\u0005R\u0000\u0000\u01f5\u01f7\u0005S\u0000\u0000" + + "\u01f6\u01f4\u0001\u0000\u0000\u0000\u01f7\u01fa\u0001\u0000\u0000\u0000" + + "\u01f8\u01f6\u0001\u0000\u0000\u0000\u01f8\u01f9\u0001\u0000\u0000\u0000" + + "\u01f9\u01fd\u0001\u0000\u0000\u0000\u01fa\u01f8\u0001\u0000\u0000\u0000" + + "\u01fb\u01fc\u0005-\u0000\u0000\u01fc\u01fe\u0003V+\u0000\u01fd\u01fb" + + "\u0001\u0000\u0000\u0000\u01fd\u01fe\u0001\u0000\u0000\u0000\u01fe\u01ff" + + "\u0001\u0000\u0000\u0000\u01ff\u0200\u0003*\u0015\u0000\u0200)\u0001\u0000" + + "\u0000\u0000\u0201\u0204\u0003\u009cN\u0000\u0202\u0204\u0005T\u0000\u0000" + + "\u0203\u0201\u0001\u0000\u0000\u0000\u0203\u0202\u0001\u0000\u0000\u0000" + + "\u0204+\u0001\u0000\u0000\u0000\u0205\u0208\u0003\u00f0x\u0000\u0206\u0208" + + "\u00050\u0000\u0000\u0207\u0205\u0001\u0000\u0000\u0000\u0207\u0206\u0001" + + "\u0000\u0000\u0000\u0208-\u0001\u0000\u0000\u0000\u0209\u020a\u0003\u0010" + + "\b\u0000\u020a\u020b\u0003(\u0014\u0000\u020b/\u0001\u0000\u0000\u0000" + + "\u020c\u020d\u0003\u0010\b\u0000\u020d\u020e\u00032\u0019\u0000\u020e" + + "1\u0001\u0000\u0000\u0000\u020f\u0210\u0003\u00a2Q\u0000\u0210\u0213\u0003" + + "X,\u0000\u0211\u0212\u0005-\u0000\u0000\u0212\u0214\u0003V+\u0000\u0213" + + "\u0211\u0001\u0000\u0000\u0000\u0213\u0214\u0001\u0000\u0000\u0000\u0214" + + "\u0215\u0001\u0000\u0000\u0000\u0215\u0216\u0003\u009cN\u0000\u02163\u0001" + + "\u0000\u0000\u0000\u0217\u0219\u0003\b\u0004\u0000\u0218\u0217\u0001\u0000" + + "\u0000\u0000\u0219\u021c\u0001\u0000\u0000\u0000\u021a\u0218\u0001\u0000" + + "\u0000\u0000\u021a\u021b\u0001\u0000\u0000\u0000\u021b\u021d\u0001\u0000" + + "\u0000\u0000\u021c\u021a\u0001\u0000\u0000\u0000\u021d\u021e\u0003\u00a2" + + "Q\u0000\u021e\u021f\u0003\u009cN\u0000\u021f5\u0001\u0000\u0000\u0000" + + "\u0220\u0221\u0003\u00f0x\u0000\u0221\u0222\u0003H$\u0000\u0222\u0223" + + "\u0005T\u0000\u0000\u02237\u0001\u0000\u0000\u0000\u0224\u0226\u0003\b" + + "\u0004\u0000\u0225\u0224\u0001\u0000\u0000\u0000\u0226\u0229\u0001\u0000" + + "\u0000\u0000\u0227\u0225\u0001\u0000\u0000\u0000\u0227\u0228\u0001\u0000" + + "\u0000\u0000\u0228\u022a\u0001\u0000\u0000\u0000\u0229\u0227\u0001\u0000" + + "\u0000\u0000\u022a\u022d\u0003:\u001d\u0000\u022b\u022d\u0005T\u0000\u0000" + + "\u022c\u0227\u0001\u0000\u0000\u0000\u022c\u022b\u0001\u0000\u0000\u0000" + + "\u022d9\u0001\u0000\u0000\u0000\u022e\u0237\u0003\u0092I\u0000\u022f\u0237" + + "\u0003<\u001e\u0000\u0230\u0237\u0003@ \u0000\u0231\u0237\u0003D\"\u0000" + + "\u0232\u0237\u0003\u001e\u000f\u0000\u0233\u0237\u0003z=\u0000\u0234\u0237" + + "\u0003\u000e\u0007\u0000\u0235\u0237\u0003\u0016\u000b\u0000\u0236\u022e" + + "\u0001\u0000\u0000\u0000\u0236\u022f\u0001\u0000\u0000\u0000\u0236\u0230" + + "\u0001\u0000\u0000\u0000\u0236\u0231\u0001\u0000\u0000\u0000\u0236\u0232" + + "\u0001\u0000\u0000\u0000\u0236\u0233\u0001\u0000\u0000\u0000\u0236\u0234" + + "\u0001\u0000\u0000\u0000\u0236\u0235\u0001\u0000\u0000\u0000\u0237;\u0001" + + "\u0000\u0000\u0000\u0238\u0239\u0003\u00f0x\u0000\u0239\u023e\u0003>\u001f" + + "\u0000\u023a\u023b\u0005U\u0000\u0000\u023b\u023d\u0003>\u001f\u0000\u023c" + + "\u023a\u0001\u0000\u0000\u0000\u023d\u0240\u0001\u0000\u0000\u0000\u023e" + + "\u023c\u0001\u0000\u0000\u0000\u023e\u023f\u0001\u0000\u0000\u0000\u023f" + + "\u0241\u0001\u0000\u0000\u0000\u0240\u023e\u0001\u0000\u0000\u0000\u0241" + + "\u0242\u0005T\u0000\u0000\u0242=\u0001\u0000\u0000\u0000\u0243\u0248\u0003" + + "\u00a2Q\u0000\u0244\u0245\u0005R\u0000\u0000\u0245\u0247\u0005S\u0000" + + "\u0000\u0246\u0244\u0001\u0000\u0000\u0000\u0247\u024a\u0001\u0000\u0000" + + "\u0000\u0248\u0246\u0001\u0000\u0000\u0000\u0248\u0249\u0001\u0000\u0000" + + "\u0000\u0249\u024b\u0001\u0000\u0000\u0000\u024a\u0248\u0001\u0000\u0000" + + "\u0000\u024b\u024c\u0005W\u0000\u0000\u024c\u024d\u0003N\'\u0000\u024d" + + "?\u0001\u0000\u0000\u0000\u024e\u0250\u0003B!\u0000\u024f\u024e\u0001" + + "\u0000\u0000\u0000\u0250\u0253\u0001\u0000\u0000\u0000\u0251\u024f\u0001" + + "\u0000\u0000\u0000\u0251\u0252\u0001\u0000\u0000\u0000\u0252\u0254\u0001" + + "\u0000\u0000\u0000\u0253\u0251\u0001\u0000\u0000\u0000\u0254\u0255\u0003" + + "F#\u0000\u0255A\u0001\u0000\u0000\u0000\u0256\u025d\u0003p8\u0000\u0257" + + "\u025d\u0005#\u0000\u0000\u0258\u025d\u0005\u0001\u0000\u0000\u0259\u025d" + + "\u0005\f\u0000\u0000\u025a\u025d\u0005&\u0000\u0000\u025b\u025d\u0005" + + "\'\u0000\u0000\u025c\u0256\u0001\u0000\u0000\u0000\u025c\u0257\u0001\u0000" + + "\u0000\u0000\u025c\u0258\u0001\u0000\u0000\u0000\u025c\u0259\u0001\u0000" + + "\u0000\u0000\u025c\u025a\u0001\u0000\u0000\u0000\u025c\u025b\u0001\u0000" + + "\u0000\u0000\u025dC\u0001\u0000\u0000\u0000\u025e\u0260\u0003B!\u0000" + + "\u025f\u025e\u0001\u0000\u0000\u0000\u0260\u0263\u0001\u0000\u0000\u0000" + + "\u0261\u025f\u0001\u0000\u0000\u0000\u0261\u0262\u0001\u0000\u0000\u0000" + + "\u0262\u0264\u0001\u0000\u0000\u0000\u0263\u0261\u0001\u0000\u0000\u0000" + + "\u0264\u0265\u0003\u0010\b\u0000\u0265\u0266\u0003F#\u0000\u0266E\u0001" + + "\u0000\u0000\u0000\u0267\u0269\u0003p8\u0000\u0268\u0267\u0001\u0000\u0000" + + "\u0000\u0269\u026c\u0001\u0000\u0000\u0000\u026a\u0268\u0001\u0000\u0000" + + "\u0000\u026a\u026b\u0001\u0000\u0000\u0000\u026b\u026d\u0001\u0000\u0000" + + "\u0000\u026c\u026a\u0001\u0000\u0000\u0000\u026d\u026e\u0003,\u0016\u0000" + + "\u026e\u026f\u0003\u00a2Q\u0000\u026f\u0274\u0003X,\u0000\u0270\u0271" + + "\u0005R\u0000\u0000\u0271\u0273\u0005S\u0000\u0000\u0272\u0270\u0001\u0000" + + "\u0000\u0000\u0273\u0276\u0001\u0000\u0000\u0000\u0274\u0272\u0001\u0000" + + "\u0000\u0000\u0274\u0275\u0001\u0000\u0000\u0000\u0275\u0279\u0001\u0000" + + "\u0000\u0000\u0276\u0274\u0001\u0000\u0000\u0000\u0277\u0278\u0005-\u0000" + + "\u0000\u0278\u027a\u0003V+\u0000\u0279\u0277\u0001\u0000\u0000\u0000\u0279" + + "\u027a\u0001\u0000\u0000\u0000\u027a\u027b\u0001\u0000\u0000\u0000\u027b" + + "\u027c\u0003*\u0015\u0000\u027cG\u0001\u0000\u0000\u0000\u027d\u0282\u0003" + + "J%\u0000\u027e\u027f\u0005U\u0000\u0000\u027f\u0281\u0003J%\u0000\u0280" + + "\u027e\u0001\u0000\u0000\u0000\u0281\u0284\u0001\u0000\u0000\u0000\u0282" + + "\u0280\u0001\u0000\u0000\u0000\u0282\u0283\u0001\u0000\u0000\u0000\u0283" + + "I\u0001\u0000\u0000\u0000\u0284\u0282\u0001\u0000\u0000\u0000\u0285\u0288" + + "\u0003L&\u0000\u0286\u0287\u0005W\u0000\u0000\u0287\u0289\u0003N\'\u0000" + + "\u0288\u0286\u0001\u0000\u0000\u0000\u0288\u0289\u0001\u0000\u0000\u0000" + + "\u0289K\u0001\u0000\u0000\u0000\u028a\u028f\u0003\u00a2Q\u0000\u028b\u028c" + + "\u0005R\u0000\u0000\u028c\u028e\u0005S\u0000\u0000\u028d\u028b\u0001\u0000" + + "\u0000\u0000\u028e\u0291\u0001\u0000\u0000\u0000\u028f\u028d\u0001\u0000" + + "\u0000\u0000\u028f\u0290\u0001\u0000\u0000\u0000\u0290M\u0001\u0000\u0000" + + "\u0000\u0291\u028f\u0001\u0000\u0000\u0000\u0292\u0295\u0003P(\u0000\u0293" + + "\u0295\u0003\u00c6c\u0000\u0294\u0292\u0001\u0000\u0000\u0000\u0294\u0293" + + "\u0001\u0000\u0000\u0000\u0295O\u0001\u0000\u0000\u0000\u0296\u02a2\u0005" + + "P\u0000\u0000\u0297\u029c\u0003N\'\u0000\u0298\u0299\u0005U\u0000\u0000" + + "\u0299\u029b\u0003N\'\u0000\u029a\u0298\u0001\u0000\u0000\u0000\u029b" + + "\u029e\u0001\u0000\u0000\u0000\u029c\u029a\u0001\u0000\u0000\u0000\u029c" + + "\u029d\u0001\u0000\u0000\u0000\u029d\u02a0\u0001\u0000\u0000\u0000\u029e" + + "\u029c\u0001\u0000\u0000\u0000\u029f\u02a1\u0005U\u0000\u0000\u02a0\u029f" + + "\u0001\u0000\u0000\u0000\u02a0\u02a1\u0001\u0000\u0000\u0000\u02a1\u02a3" + + "\u0001\u0000\u0000\u0000\u02a2\u0297\u0001\u0000\u0000\u0000\u02a2\u02a3" + + "\u0001\u0000\u0000\u0000\u02a3\u02a4\u0001\u0000\u0000\u0000\u02a4\u02a5" + + "\u0005Q\u0000\u0000\u02a5Q\u0001\u0000\u0000\u0000\u02a6\u02a8\u0003\u00a2" + + "Q\u0000\u02a7\u02a9\u0003\u00f4z\u0000\u02a8\u02a7\u0001\u0000\u0000\u0000" + + "\u02a8\u02a9\u0001\u0000\u0000\u0000\u02a9\u02aa\u0001\u0000\u0000\u0000" + + "\u02aa\u02ab\u0005V\u0000\u0000\u02ab\u02ad\u0001\u0000\u0000\u0000\u02ac" + + "\u02a6\u0001\u0000\u0000\u0000\u02ad\u02b0\u0001\u0000\u0000\u0000\u02ae" + + "\u02ac\u0001\u0000\u0000\u0000\u02ae\u02af\u0001\u0000\u0000\u0000\u02af" + + "\u02b1\u0001\u0000\u0000\u0000\u02b0\u02ae\u0001\u0000\u0000\u0000\u02b1" + + "\u02b3\u0003\u00a4R\u0000\u02b2\u02b4\u0003\u00f4z\u0000\u02b3\u02b2\u0001" + + "\u0000\u0000\u0000\u02b3\u02b4\u0001\u0000\u0000\u0000\u02b4S\u0001\u0000" + + "\u0000\u0000\u02b5\u02c2\u0003\u00f0x\u0000\u02b6\u02b8\u0003p8\u0000" + + "\u02b7\u02b6\u0001\u0000\u0000\u0000\u02b8\u02bb\u0001\u0000\u0000\u0000" + + "\u02b9\u02b7\u0001\u0000\u0000\u0000\u02b9\u02ba\u0001\u0000\u0000\u0000" + + "\u02ba\u02bc\u0001\u0000\u0000\u0000\u02bb\u02b9\u0001\u0000\u0000\u0000" + + "\u02bc\u02bf\u0005\\\u0000\u0000\u02bd\u02be\u0007\u0000\u0000\u0000\u02be" + + "\u02c0\u0003\u00f0x\u0000\u02bf\u02bd\u0001\u0000\u0000\u0000\u02bf\u02c0" + + "\u0001\u0000\u0000\u0000\u02c0\u02c2\u0001\u0000\u0000\u0000\u02c1\u02b5" + + "\u0001\u0000\u0000\u0000\u02c1\u02b9\u0001\u0000\u0000\u0000\u02c2U\u0001" + + "\u0000\u0000\u0000\u02c3\u02c8\u0003f3\u0000\u02c4\u02c5\u0005U\u0000" + + "\u0000\u02c5\u02c7\u0003f3\u0000\u02c6\u02c4\u0001\u0000\u0000\u0000\u02c7" + + "\u02ca\u0001\u0000\u0000\u0000\u02c8\u02c6\u0001\u0000\u0000\u0000\u02c8" + + "\u02c9\u0001\u0000\u0000\u0000\u02c9W\u0001\u0000\u0000\u0000\u02ca\u02c8" + + "\u0001\u0000\u0000\u0000\u02cb\u02d7\u0005N\u0000\u0000\u02cc\u02ce\u0003" + + "Z-\u0000\u02cd\u02cc\u0001\u0000\u0000\u0000\u02cd\u02ce\u0001\u0000\u0000" + + "\u0000\u02ce\u02d8\u0001\u0000\u0000\u0000\u02cf\u02d2\u0003Z-\u0000\u02d0" + + "\u02d1\u0005U\u0000\u0000\u02d1\u02d3\u0003\\.\u0000\u02d2\u02d0\u0001" + + "\u0000\u0000\u0000\u02d2\u02d3\u0001\u0000\u0000\u0000\u02d3\u02d8\u0001" + + "\u0000\u0000\u0000\u02d4\u02d6\u0003\\.\u0000\u02d5\u02d4\u0001\u0000" + + "\u0000\u0000\u02d5\u02d6\u0001\u0000\u0000\u0000\u02d6\u02d8\u0001\u0000" + + "\u0000\u0000\u02d7\u02cd\u0001\u0000\u0000\u0000\u02d7\u02cf\u0001\u0000" + + "\u0000\u0000\u02d7\u02d5\u0001\u0000\u0000\u0000\u02d8\u02d9\u0001\u0000" + + "\u0000\u0000\u02d9\u02da\u0005O\u0000\u0000\u02daY\u0001\u0000\u0000\u0000" + + "\u02db\u02e1\u0003\u00f0x\u0000\u02dc\u02dd\u0003\u00a2Q\u0000\u02dd\u02de" + + "\u0005V\u0000\u0000\u02de\u02e0\u0001\u0000\u0000\u0000\u02df\u02dc\u0001" + + "\u0000\u0000\u0000\u02e0\u02e3\u0001\u0000\u0000\u0000\u02e1\u02df\u0001" + + "\u0000\u0000\u0000\u02e1\u02e2\u0001\u0000\u0000\u0000\u02e2\u02e4\u0001" + + "\u0000\u0000\u0000\u02e3\u02e1\u0001\u0000\u0000\u0000\u02e4\u02e5\u0005" + + "+\u0000\u0000\u02e5[\u0001\u0000\u0000\u0000\u02e6\u02eb\u0003^/\u0000" + + "\u02e7\u02e8\u0005U\u0000\u0000\u02e8\u02ea\u0003^/\u0000\u02e9\u02e7" + + "\u0001\u0000\u0000\u0000\u02ea\u02ed\u0001\u0000\u0000\u0000\u02eb\u02e9" + + "\u0001\u0000\u0000\u0000\u02eb\u02ec\u0001\u0000\u0000\u0000\u02ec\u02f0" + + "\u0001\u0000\u0000\u0000\u02ed\u02eb\u0001\u0000\u0000\u0000\u02ee\u02ef" + + "\u0005U\u0000\u0000\u02ef\u02f1\u0003`0\u0000\u02f0\u02ee\u0001\u0000" + + "\u0000\u0000\u02f0\u02f1\u0001\u0000\u0000\u0000\u02f1\u02f4\u0001\u0000" + + "\u0000\u0000\u02f2\u02f4\u0003`0\u0000\u02f3\u02e6\u0001\u0000\u0000\u0000" + + "\u02f3\u02f2\u0001\u0000\u0000\u0000\u02f4]\u0001\u0000\u0000\u0000\u02f5" + + "\u02f7\u0003\f\u0006\u0000\u02f6\u02f5\u0001\u0000\u0000\u0000\u02f7\u02fa" + + "\u0001\u0000\u0000\u0000\u02f8\u02f6\u0001\u0000\u0000\u0000\u02f8\u02f9" + + "\u0001\u0000\u0000\u0000\u02f9\u02fb\u0001\u0000\u0000\u0000\u02fa\u02f8" + + "\u0001\u0000\u0000\u0000\u02fb\u02fc\u0003\u00f0x\u0000\u02fc\u02fd\u0003" + + "L&\u0000\u02fd_\u0001\u0000\u0000\u0000\u02fe\u0300\u0003\f\u0006\u0000" + + "\u02ff\u02fe\u0001\u0000\u0000\u0000\u0300\u0303\u0001\u0000\u0000\u0000" + + "\u0301\u02ff\u0001\u0000\u0000\u0000\u0301\u0302\u0001\u0000\u0000\u0000" + + "\u0302\u0304\u0001\u0000\u0000\u0000\u0303\u0301\u0001\u0000\u0000\u0000" + + "\u0304\u0308\u0003\u00f0x\u0000\u0305\u0307\u0003p8\u0000\u0306\u0305" + + "\u0001\u0000\u0000\u0000\u0307\u030a\u0001\u0000\u0000\u0000\u0308\u0306" + + "\u0001\u0000\u0000\u0000\u0308\u0309\u0001\u0000\u0000\u0000\u0309\u030b" + + "\u0001\u0000\u0000\u0000\u030a\u0308\u0001\u0000\u0000\u0000\u030b\u030c" + + "\u0005|\u0000\u0000\u030c\u030d\u0003L&\u0000\u030da\u0001\u0000\u0000" + + "\u0000\u030e\u0313\u0003d2\u0000\u030f\u0310\u0005U\u0000\u0000\u0310" + + "\u0312\u0003d2\u0000\u0311\u030f\u0001\u0000\u0000\u0000\u0312\u0315\u0001" + + "\u0000\u0000\u0000\u0313\u0311\u0001\u0000\u0000\u0000\u0313\u0314\u0001" + + "\u0000\u0000\u0000\u0314c\u0001\u0000\u0000\u0000\u0315\u0313\u0001\u0000" + + "\u0000\u0000\u0316\u0318\u0003\f\u0006\u0000\u0317\u0316\u0001\u0000\u0000" + + "\u0000\u0318\u031b\u0001\u0000\u0000\u0000\u0319\u0317\u0001\u0000\u0000" + + "\u0000\u0319\u031a\u0001\u0000\u0000\u0000\u031a\u031c\u0001\u0000\u0000" + + "\u0000\u031b\u0319\u0001\u0000\u0000\u0000\u031c\u031d\u0005=\u0000\u0000" + + "\u031d\u031e\u0003\u00a2Q\u0000\u031ee\u0001\u0000\u0000\u0000\u031f\u0324" + + "\u0003\u00a2Q\u0000\u0320\u0321\u0005V\u0000\u0000\u0321\u0323\u0003\u00a2" + + "Q\u0000\u0322\u0320\u0001\u0000\u0000\u0000\u0323\u0326\u0001\u0000\u0000" + + "\u0000\u0324\u0322\u0001\u0000\u0000\u0000\u0324\u0325\u0001\u0000\u0000" + + "\u0000\u0325g\u0001\u0000\u0000\u0000\u0326\u0324\u0001\u0000\u0000\u0000" + + "\u0327\u032f\u0003j5\u0000\u0328\u032f\u0003l6\u0000\u0329\u032f\u0005" + + "J\u0000\u0000\u032a\u032f\u0005K\u0000\u0000\u032b\u032f\u0005I\u0000" + + "\u0000\u032c\u032f\u0005M\u0000\u0000\u032d\u032f\u0005L\u0000\u0000\u032e" + + "\u0327\u0001\u0000\u0000\u0000\u032e\u0328\u0001\u0000\u0000\u0000\u032e" + + "\u0329\u0001\u0000\u0000\u0000\u032e\u032a\u0001\u0000\u0000\u0000\u032e" + + "\u032b\u0001\u0000\u0000\u0000\u032e\u032c\u0001\u0000\u0000\u0000\u032e" + + "\u032d\u0001\u0000\u0000\u0000\u032fi\u0001\u0000\u0000\u0000\u0330\u0331" + + "\u0007\u0001\u0000\u0000\u0331k\u0001\u0000\u0000\u0000\u0332\u0333\u0007" + + "\u0002\u0000\u0000\u0333m\u0001\u0000\u0000\u0000\u0334\u0335\u0003\u00a2" + + "Q\u0000\u0335\u0336\u0005V\u0000\u0000\u0336\u0338\u0001\u0000\u0000\u0000" + + "\u0337\u0334\u0001\u0000\u0000\u0000\u0338\u033b\u0001\u0000\u0000\u0000" + + "\u0339\u0337\u0001\u0000\u0000\u0000\u0339\u033a\u0001\u0000\u0000\u0000" + + "\u033a\u033c\u0001\u0000\u0000\u0000\u033b\u0339\u0001\u0000\u0000\u0000" + + "\u033c\u033d\u0005{\u0000\u0000\u033d\u033e\u0003\u00a2Q\u0000\u033eo" + + "\u0001\u0000\u0000\u0000\u033f\u0340\u0005{\u0000\u0000\u0340\u0343\u0003" + + "f3\u0000\u0341\u0343\u0003n7\u0000\u0342\u033f\u0001\u0000\u0000\u0000" + + "\u0342\u0341\u0001\u0000\u0000\u0000\u0343\u034a\u0001\u0000\u0000\u0000" + + "\u0344\u0347\u0005N\u0000\u0000\u0345\u0348\u0003r9\u0000\u0346\u0348" + + "\u0003v;\u0000\u0347\u0345\u0001\u0000\u0000\u0000\u0347\u0346\u0001\u0000" + + "\u0000\u0000\u0347\u0348\u0001\u0000\u0000\u0000\u0348\u0349\u0001\u0000" + + "\u0000\u0000\u0349\u034b\u0005O\u0000\u0000\u034a\u0344\u0001\u0000\u0000" + + "\u0000\u034a\u034b\u0001\u0000\u0000\u0000\u034bq\u0001\u0000\u0000\u0000" + + "\u034c\u0351\u0003t:\u0000\u034d\u034e\u0005U\u0000\u0000\u034e\u0350" + + "\u0003t:\u0000\u034f\u034d\u0001\u0000\u0000\u0000\u0350\u0353\u0001\u0000" + + "\u0000\u0000\u0351\u034f\u0001\u0000\u0000\u0000\u0351\u0352\u0001\u0000" + + "\u0000\u0000\u0352s\u0001\u0000\u0000\u0000\u0353\u0351\u0001\u0000\u0000" + + "\u0000\u0354\u0355\u0003\u00a2Q\u0000\u0355\u0356\u0005W\u0000\u0000\u0356" + + "\u0357\u0003v;\u0000\u0357u\u0001\u0000\u0000\u0000\u0358\u035c\u0003" + + "\u00c6c\u0000\u0359\u035c\u0003p8\u0000\u035a\u035c\u0003x<\u0000\u035b" + + "\u0358\u0001\u0000\u0000\u0000\u035b\u0359\u0001\u0000\u0000\u0000\u035b" + + "\u035a\u0001\u0000\u0000\u0000\u035cw\u0001\u0000\u0000\u0000\u035d\u0366" + + "\u0005P\u0000\u0000\u035e\u0363\u0003v;\u0000\u035f\u0360\u0005U\u0000" + + "\u0000\u0360\u0362\u0003v;\u0000\u0361\u035f\u0001\u0000\u0000\u0000\u0362" + + "\u0365\u0001\u0000\u0000\u0000\u0363\u0361\u0001\u0000\u0000\u0000\u0363" + + "\u0364\u0001\u0000\u0000\u0000\u0364\u0367\u0001\u0000\u0000\u0000\u0365" + + "\u0363\u0001\u0000\u0000\u0000\u0366\u035e\u0001\u0000\u0000\u0000\u0366" + + "\u0367\u0001\u0000\u0000\u0000\u0367\u0369\u0001\u0000\u0000\u0000\u0368" + + "\u036a\u0005U\u0000\u0000\u0369\u0368\u0001\u0000\u0000\u0000\u0369\u036a" + + "\u0001\u0000\u0000\u0000\u036a\u036b\u0001\u0000\u0000\u0000\u036b\u036c" + + "\u0005Q\u0000\u0000\u036cy\u0001\u0000\u0000\u0000\u036d\u036e\u0005{" + + "\u0000\u0000\u036e\u036f\u0005\u001c\u0000\u0000\u036f\u0370\u0003\u00a2" + + "Q\u0000\u0370\u0371\u0003|>\u0000\u0371{\u0001\u0000\u0000\u0000\u0372" + + "\u0376\u0005P\u0000\u0000\u0373\u0375\u0003~?\u0000\u0374\u0373\u0001" + + "\u0000\u0000\u0000\u0375\u0378\u0001\u0000\u0000\u0000\u0376\u0374\u0001" + + "\u0000\u0000\u0000\u0376\u0377\u0001\u0000\u0000\u0000\u0377\u0379\u0001" + + "\u0000\u0000\u0000\u0378\u0376\u0001\u0000\u0000\u0000\u0379\u037a\u0005" + + "Q\u0000\u0000\u037a}\u0001\u0000\u0000\u0000\u037b\u037d\u0003\b\u0004" + + "\u0000\u037c\u037b\u0001\u0000\u0000\u0000\u037d\u0380\u0001\u0000\u0000" + + "\u0000\u037e\u037c\u0001\u0000\u0000\u0000\u037e\u037f\u0001\u0000\u0000" + + "\u0000\u037f\u0381\u0001\u0000\u0000\u0000\u0380\u037e\u0001\u0000\u0000" + + "\u0000\u0381\u0384\u0003\u0080@\u0000\u0382\u0384\u0005T\u0000\u0000\u0383" + + "\u037e\u0001\u0000\u0000\u0000\u0383\u0382\u0001\u0000\u0000\u0000\u0384" + + "\u007f\u0001\u0000\u0000\u0000\u0385\u0386\u0003\u00f0x\u0000\u0386\u0387" + + "\u0003\u0082A\u0000\u0387\u0388\u0005T\u0000\u0000\u0388\u039e\u0001\u0000" + + "\u0000\u0000\u0389\u038b\u0003\u000e\u0007\u0000\u038a\u038c\u0005T\u0000" + + "\u0000\u038b\u038a\u0001\u0000\u0000\u0000\u038b\u038c\u0001\u0000\u0000" + + "\u0000\u038c\u039e\u0001\u0000\u0000\u0000\u038d\u038f\u0003\u001e\u000f" + + "\u0000\u038e\u0390\u0005T\u0000\u0000\u038f\u038e\u0001\u0000\u0000\u0000" + + "\u038f\u0390\u0001\u0000\u0000\u0000\u0390\u039e\u0001\u0000\u0000\u0000" + + "\u0391\u0393\u0003\u0016\u000b\u0000\u0392\u0394\u0005T\u0000\u0000\u0393" + + "\u0392\u0001\u0000\u0000\u0000\u0393\u0394\u0001\u0000\u0000\u0000\u0394" + + "\u039e\u0001\u0000\u0000\u0000\u0395\u0397\u0003z=\u0000\u0396\u0398\u0005" + + "T\u0000\u0000\u0397\u0396\u0001\u0000\u0000\u0000\u0397\u0398\u0001\u0000" + + "\u0000\u0000\u0398\u039e\u0001\u0000\u0000\u0000\u0399\u039b\u0003\u0092" + + "I\u0000\u039a\u039c\u0005T\u0000\u0000\u039b\u039a\u0001\u0000\u0000\u0000" + + "\u039b\u039c\u0001\u0000\u0000\u0000\u039c\u039e\u0001\u0000\u0000\u0000" + + "\u039d\u0385\u0001\u0000\u0000\u0000\u039d\u0389\u0001\u0000\u0000\u0000" + + "\u039d\u038d\u0001\u0000\u0000\u0000\u039d\u0391\u0001\u0000\u0000\u0000" + + "\u039d\u0395\u0001\u0000\u0000\u0000\u039d\u0399\u0001\u0000\u0000\u0000" + + "\u039e\u0081\u0001\u0000\u0000\u0000\u039f\u03a2\u0003\u0084B\u0000\u03a0" + + "\u03a2\u0003\u0086C\u0000\u03a1\u039f\u0001\u0000\u0000\u0000\u03a1\u03a0" + + "\u0001\u0000\u0000\u0000\u03a2\u0083\u0001\u0000\u0000\u0000\u03a3\u03a4" + + "\u0003\u00a2Q\u0000\u03a4\u03a5\u0005N\u0000\u0000\u03a5\u03a7\u0005O" + + "\u0000\u0000\u03a6\u03a8\u0003\u0088D\u0000\u03a7\u03a6\u0001\u0000\u0000" + + "\u0000\u03a7\u03a8\u0001\u0000\u0000\u0000\u03a8\u0085\u0001\u0000\u0000" + + "\u0000\u03a9\u03aa\u0003H$\u0000\u03aa\u0087\u0001\u0000\u0000\u0000\u03ab" + + "\u03ac\u0005\f\u0000\u0000\u03ac\u03ad\u0003v;\u0000\u03ad\u0089\u0001" + + "\u0000\u0000\u0000\u03ae\u03b0\u00054\u0000\u0000\u03af\u03ae\u0001\u0000" + + "\u0000\u0000\u03af\u03b0\u0001\u0000\u0000\u0000\u03b0\u03b1\u0001\u0000" + + "\u0000\u0000\u03b1\u03b2\u00053\u0000\u0000\u03b2\u03b3\u0003f3\u0000" + + "\u03b3\u03b4\u0003\u008cF\u0000\u03b4\u008b\u0001\u0000\u0000\u0000\u03b5" + + "\u03b9\u0005P\u0000\u0000\u03b6\u03b8\u0003\u008eG\u0000\u03b7\u03b6\u0001" + + "\u0000\u0000\u0000\u03b8\u03bb\u0001\u0000\u0000\u0000\u03b9\u03b7\u0001" + + "\u0000\u0000\u0000\u03b9\u03ba\u0001\u0000\u0000\u0000\u03ba\u03bc\u0001" + + "\u0000\u0000\u0000\u03bb\u03b9\u0001\u0000\u0000\u0000\u03bc\u03bd\u0005" + + "Q\u0000\u0000\u03bd\u008d\u0001\u0000\u0000\u0000\u03be\u03c2\u00055\u0000" + + "\u0000\u03bf\u03c1\u0003\u0090H\u0000\u03c0\u03bf\u0001\u0000\u0000\u0000" + + "\u03c1\u03c4\u0001\u0000\u0000\u0000\u03c2\u03c0\u0001\u0000\u0000\u0000" + + "\u03c2\u03c3\u0001\u0000\u0000\u0000\u03c3\u03c5\u0001\u0000\u0000\u0000" + + "\u03c4\u03c2\u0001\u0000\u0000\u0000\u03c5\u03c6\u0003f3\u0000\u03c6\u03c7" + + "\u0005T\u0000\u0000\u03c7\u03e3\u0001\u0000\u0000\u0000\u03c8\u03c9\u0005" + + "6\u0000\u0000\u03c9\u03cc\u0003f3\u0000\u03ca\u03cb\u00058\u0000\u0000" + + "\u03cb\u03cd\u0003f3\u0000\u03cc\u03ca\u0001\u0000\u0000\u0000\u03cc\u03cd" + + "\u0001\u0000\u0000\u0000\u03cd\u03ce\u0001\u0000\u0000\u0000\u03ce\u03cf" + + "\u0005T\u0000\u0000\u03cf\u03e3\u0001\u0000\u0000\u0000\u03d0\u03d1\u0005" + + "7\u0000\u0000\u03d1\u03d4\u0003f3\u0000\u03d2\u03d3\u00058\u0000\u0000" + + "\u03d3\u03d5\u0003f3\u0000\u03d4\u03d2\u0001\u0000\u0000\u0000\u03d4\u03d5" + + "\u0001\u0000\u0000\u0000\u03d5\u03d6\u0001\u0000\u0000\u0000\u03d6\u03d7" + + "\u0005T\u0000\u0000\u03d7\u03e3\u0001\u0000\u0000\u0000\u03d8\u03d9\u0005" + + "9\u0000\u0000\u03d9\u03da\u0003f3\u0000\u03da\u03db\u0005T\u0000\u0000" + + "\u03db\u03e3\u0001\u0000\u0000\u0000\u03dc\u03dd\u0005:\u0000\u0000\u03dd" + + "\u03de\u0003f3\u0000\u03de\u03df\u0005;\u0000\u0000\u03df\u03e0\u0003" + + "f3\u0000\u03e0\u03e1\u0005T\u0000\u0000\u03e1\u03e3\u0001\u0000\u0000" + + "\u0000\u03e2\u03be\u0001\u0000\u0000\u0000\u03e2\u03c8\u0001\u0000\u0000" + + "\u0000\u03e2\u03d0\u0001\u0000\u0000\u0000\u03e2\u03d8\u0001\u0000\u0000" + + "\u0000\u03e2\u03dc\u0001\u0000\u0000\u0000\u03e3\u008f\u0001\u0000\u0000" + + "\u0000\u03e4\u03e5\u0007\u0003\u0000\u0000\u03e5\u0091\u0001\u0000\u0000" + + "\u0000\u03e6\u03e7\u0005?\u0000\u0000\u03e7\u03e9\u0003\u00a2Q\u0000\u03e8" + + "\u03ea\u0003\u0010\b\u0000\u03e9\u03e8\u0001\u0000\u0000\u0000\u03e9\u03ea" + + "\u0001\u0000\u0000\u0000\u03ea\u03eb\u0001\u0000\u0000\u0000\u03eb\u03ee" + + "\u0003\u0094J\u0000\u03ec\u03ed\u0005\u0018\u0000\u0000\u03ed\u03ef\u0003" + + "\u00eew\u0000\u03ee\u03ec\u0001\u0000\u0000\u0000\u03ee\u03ef\u0001\u0000" + + "\u0000\u0000\u03ef\u03f0\u0001\u0000\u0000\u0000\u03f0\u03f1\u0003\u009a" + + "M\u0000\u03f1\u0093\u0001\u0000\u0000\u0000\u03f2\u03f4\u0005N\u0000\u0000" + + "\u03f3\u03f5\u0003\u0096K\u0000\u03f4\u03f3\u0001\u0000\u0000\u0000\u03f4" + + "\u03f5\u0001\u0000\u0000\u0000\u03f5\u03f6\u0001\u0000\u0000\u0000\u03f6" + + "\u03f7\u0005O\u0000\u0000\u03f7\u0095\u0001\u0000\u0000\u0000\u03f8\u03fd" + + "\u0003\u0098L\u0000\u03f9\u03fa\u0005U\u0000\u0000\u03fa\u03fc\u0003\u0098" + + "L\u0000\u03fb\u03f9\u0001\u0000\u0000\u0000\u03fc\u03ff\u0001\u0000\u0000" + + "\u0000\u03fd\u03fb\u0001\u0000\u0000\u0000\u03fd\u03fe\u0001\u0000\u0000" + + "\u0000\u03fe\u0097\u0001\u0000\u0000\u0000\u03ff\u03fd\u0001\u0000\u0000" + + "\u0000\u0400\u0401\u0003\u00f0x\u0000\u0401\u0402\u0003\u00a2Q\u0000\u0402" + + "\u0099\u0001\u0000\u0000\u0000\u0403\u0408\u0005P\u0000\u0000\u0404\u0407" + + "\u0003$\u0012\u0000\u0405\u0407\u00034\u001a\u0000\u0406\u0404\u0001\u0000" + + "\u0000\u0000\u0406\u0405\u0001\u0000\u0000\u0000\u0407\u040a\u0001\u0000" + + "\u0000\u0000\u0408\u0406\u0001\u0000\u0000\u0000\u0408\u0409\u0001\u0000" + + "\u0000\u0000\u0409\u040b\u0001\u0000\u0000\u0000\u040a\u0408\u0001\u0000" + + "\u0000\u0000\u040b\u040c\u0005Q\u0000\u0000\u040c\u009b\u0001\u0000\u0000" + + "\u0000\u040d\u0411\u0005P\u0000\u0000\u040e\u0410\u0003\u009eO\u0000\u040f" + + "\u040e\u0001\u0000\u0000\u0000\u0410\u0413\u0001\u0000\u0000\u0000\u0411" + + "\u040f\u0001\u0000\u0000\u0000\u0411\u0412\u0001\u0000\u0000\u0000\u0412" + + "\u0414\u0001\u0000\u0000\u0000\u0413\u0411\u0001\u0000\u0000\u0000\u0414" + + "\u0415\u0005Q\u0000\u0000\u0415\u009d\u0001\u0000\u0000\u0000\u0416\u0417" + + "\u0003\u00a0P\u0000\u0417\u0418\u0005T\u0000\u0000\u0418\u041c\u0001\u0000" + + "\u0000\u0000\u0419\u041c\u0003\u00a6S\u0000\u041a\u041c\u0003\u00a8T\u0000" + + "\u041b\u0416\u0001\u0000\u0000\u0000\u041b\u0419\u0001\u0000\u0000\u0000" + + "\u041b\u041a\u0001\u0000\u0000\u0000\u041c\u009f\u0001\u0000\u0000\u0000" + + "\u041d\u041f\u0003\f\u0006\u0000\u041e\u041d\u0001\u0000\u0000\u0000\u041f" + + "\u0422\u0001\u0000\u0000\u0000\u0420\u041e\u0001\u0000\u0000\u0000\u0420" + + "\u0421\u0001\u0000\u0000\u0000\u0421\u042b\u0001\u0000\u0000\u0000\u0422" + + "\u0420\u0001\u0000\u0000\u0000\u0423\u0424\u0005=\u0000\u0000\u0424\u0425" + + "\u0003\u00a2Q\u0000\u0425\u0426\u0005W\u0000\u0000\u0426\u0427\u0003\u00c6" + + "c\u0000\u0427\u042c\u0001\u0000\u0000\u0000\u0428\u0429\u0003\u00f0x\u0000" + + "\u0429\u042a\u0003H$\u0000\u042a\u042c\u0001\u0000\u0000\u0000\u042b\u0423" + + "\u0001\u0000\u0000\u0000\u042b\u0428\u0001\u0000\u0000\u0000\u042c\u00a1" + + "\u0001\u0000\u0000\u0000\u042d\u042e\u0007\u0004\u0000\u0000\u042e\u00a3" + + "\u0001\u0000\u0000\u0000\u042f\u0430\u0007\u0005\u0000\u0000\u0430\u00a5" + + "\u0001\u0000\u0000\u0000\u0431\u0433\u0003\n\u0005\u0000\u0432\u0431\u0001" + + "\u0000\u0000\u0000\u0433\u0436\u0001\u0000\u0000\u0000\u0434\u0432\u0001" + + "\u0000\u0000\u0000\u0434\u0435\u0001\u0000\u0000\u0000\u0435\u043a\u0001" + + "\u0000\u0000\u0000\u0436\u0434\u0001\u0000\u0000\u0000\u0437\u043b\u0003" + + "\u000e\u0007\u0000\u0438\u043b\u0003\u001e\u000f\u0000\u0439\u043b\u0003" + + "\u0092I\u0000\u043a\u0437\u0001\u0000\u0000\u0000\u043a\u0438\u0001\u0000" + + "\u0000\u0000\u043a\u0439\u0001\u0000\u0000\u0000\u043b\u00a7\u0001\u0000" + + "\u0000\u0000\u043c\u04ae\u0003\u009cN\u0000\u043d\u043e\u0005\u0002\u0000" + + "\u0000\u043e\u0441\u0003\u00c6c\u0000\u043f\u0440\u0005]\u0000\u0000\u0440" + + "\u0442\u0003\u00c6c\u0000\u0441\u043f\u0001\u0000\u0000\u0000\u0441\u0442" + + "\u0001\u0000\u0000\u0000\u0442\u0443\u0001\u0000\u0000\u0000\u0443\u0444" + + "\u0005T\u0000\u0000\u0444\u04ae\u0001\u0000\u0000\u0000\u0445\u0446\u0005" + + "\u0016\u0000\u0000\u0446\u0447\u0003\u00c0`\u0000\u0447\u044a\u0003\u00a8" + + "T\u0000\u0448\u0449\u0005\u000f\u0000\u0000\u0449\u044b\u0003\u00a8T\u0000" + + "\u044a\u0448\u0001\u0000\u0000\u0000\u044a\u044b\u0001\u0000\u0000\u0000" + + "\u044b\u04ae\u0001\u0000\u0000\u0000\u044c\u044d\u0005\u0015\u0000\u0000" + + "\u044d\u044e\u0005N\u0000\u0000\u044e\u044f\u0003\u00ba]\u0000\u044f\u0450" + + "\u0005O\u0000\u0000\u0450\u0451\u0003\u00a8T\u0000\u0451\u04ae\u0001\u0000" + + "\u0000\u0000\u0452\u0453\u00052\u0000\u0000\u0453\u0454\u0003\u00c0`\u0000" + + "\u0454\u0455\u0003\u00a8T\u0000\u0455\u04ae\u0001\u0000\u0000\u0000\u0456" + + "\u0457\u0005\r\u0000\u0000\u0457\u0458\u0003\u00a8T\u0000\u0458\u0459" + + "\u00052\u0000\u0000\u0459\u045a\u0003\u00c0`\u0000\u045a\u045b\u0005T" + + "\u0000\u0000\u045b\u04ae\u0001\u0000\u0000\u0000\u045c\u045d\u0005/\u0000" + + "\u0000\u045d\u0467\u0003\u009cN\u0000\u045e\u0460\u0003\u00aaU\u0000\u045f" + + "\u045e\u0001\u0000\u0000\u0000\u0460\u0461\u0001\u0000\u0000\u0000\u0461" + + "\u045f\u0001\u0000\u0000\u0000\u0461\u0462\u0001\u0000\u0000\u0000\u0462" + + "\u0464\u0001\u0000\u0000\u0000\u0463\u0465\u0003\u00aeW\u0000\u0464\u0463" + + "\u0001\u0000\u0000\u0000\u0464\u0465\u0001\u0000\u0000\u0000\u0465\u0468" + + "\u0001\u0000\u0000\u0000\u0466\u0468\u0003\u00aeW\u0000\u0467\u045f\u0001" + + "\u0000\u0000\u0000\u0467\u0466\u0001\u0000\u0000\u0000\u0468\u04ae\u0001" + + "\u0000\u0000\u0000\u0469\u046a\u0005/\u0000\u0000\u046a\u046b\u0003\u00b0" + + "X\u0000\u046b\u046f\u0003\u009cN\u0000\u046c\u046e\u0003\u00aaU\u0000" + + "\u046d\u046c\u0001\u0000\u0000\u0000\u046e\u0471\u0001\u0000\u0000\u0000" + + "\u046f\u046d\u0001\u0000\u0000\u0000\u046f\u0470\u0001\u0000\u0000\u0000" + + "\u0470\u0473\u0001\u0000\u0000\u0000\u0471\u046f\u0001\u0000\u0000\u0000" + + "\u0472\u0474\u0003\u00aeW\u0000\u0473\u0472\u0001\u0000\u0000\u0000\u0473" + + "\u0474\u0001\u0000\u0000\u0000\u0474\u04ae\u0001\u0000\u0000\u0000\u0475" + + "\u0476\u0005)\u0000\u0000\u0476\u0477\u0003\u00c0`\u0000\u0477\u047b\u0005" + + "P\u0000\u0000\u0478\u047a\u0003\u00b6[\u0000\u0479\u0478\u0001\u0000\u0000" + + "\u0000\u047a\u047d\u0001\u0000\u0000\u0000\u047b\u0479\u0001\u0000\u0000" + + "\u0000\u047b\u047c\u0001\u0000\u0000\u0000\u047c\u0481\u0001\u0000\u0000" + + "\u0000\u047d\u047b\u0001\u0000\u0000\u0000\u047e\u0480\u0003\u00b8\\\u0000" + + "\u047f\u047e\u0001\u0000\u0000\u0000\u0480\u0483\u0001\u0000\u0000\u0000" + + "\u0481\u047f\u0001\u0000\u0000\u0000\u0481\u0482\u0001\u0000\u0000\u0000" + + "\u0482\u0484\u0001\u0000\u0000\u0000\u0483\u0481\u0001\u0000\u0000\u0000" + + "\u0484\u0485\u0005Q\u0000\u0000\u0485\u04ae\u0001\u0000\u0000\u0000\u0486" + + "\u0487\u0005*\u0000\u0000\u0487\u0488\u0003\u00c0`\u0000\u0488\u0489\u0003" + + "\u009cN\u0000\u0489\u04ae\u0001\u0000\u0000\u0000\u048a\u048c\u0005$\u0000" + + "\u0000\u048b\u048d\u0003\u00c6c\u0000\u048c\u048b\u0001\u0000\u0000\u0000" + + "\u048c\u048d\u0001\u0000\u0000\u0000\u048d\u048e\u0001\u0000\u0000\u0000" + + "\u048e\u04ae\u0005T\u0000\u0000\u048f\u0490\u0005,\u0000\u0000\u0490\u0491" + + "\u0003\u00c6c\u0000\u0491\u0492\u0005T\u0000\u0000\u0492\u04ae\u0001\u0000" + + "\u0000\u0000\u0493\u0495\u0005\u0004\u0000\u0000\u0494\u0496\u0003\u00a2" + + "Q\u0000\u0495\u0494\u0001\u0000\u0000\u0000\u0495\u0496\u0001\u0000\u0000" + + "\u0000\u0496\u0497\u0001\u0000\u0000\u0000\u0497\u04ae\u0005T\u0000\u0000" + + "\u0498\u049a\u0005\u000b\u0000\u0000\u0499\u049b\u0003\u00a2Q\u0000\u049a" + + "\u0499\u0001\u0000\u0000\u0000\u049a\u049b\u0001\u0000\u0000\u0000\u049b" + + "\u049c\u0001\u0000\u0000\u0000\u049c\u04ae\u0005T\u0000\u0000\u049d\u049e" + + "\u0005>\u0000\u0000\u049e\u049f\u0003\u00c6c\u0000\u049f\u04a0\u0005T" + + "\u0000\u0000\u04a0\u04ae\u0001\u0000\u0000\u0000\u04a1\u04ae\u0005T\u0000" + + "\u0000\u04a2\u04a3\u0003\u00c6c\u0000\u04a3\u04a4\u0005T\u0000\u0000\u04a4" + + "\u04ae\u0001\u0000\u0000\u0000\u04a5\u04a7\u0003\u00d2i\u0000\u04a6\u04a8" + + "\u0005T\u0000\u0000\u04a7\u04a6\u0001\u0000\u0000\u0000\u04a7\u04a8\u0001" + + "\u0000\u0000\u0000\u04a8\u04ae\u0001\u0000\u0000\u0000\u04a9\u04aa\u0003" + + "\u00a2Q\u0000\u04aa\u04ab\u0005]\u0000\u0000\u04ab\u04ac\u0003\u00a8T" + + "\u0000\u04ac\u04ae\u0001\u0000\u0000\u0000\u04ad\u043c\u0001\u0000\u0000" + + "\u0000\u04ad\u043d\u0001\u0000\u0000\u0000\u04ad\u0445\u0001\u0000\u0000" + + "\u0000\u04ad\u044c\u0001\u0000\u0000\u0000\u04ad\u0452\u0001\u0000\u0000" + + "\u0000\u04ad\u0456\u0001\u0000\u0000\u0000\u04ad\u045c\u0001\u0000\u0000" + + "\u0000\u04ad\u0469\u0001\u0000\u0000\u0000\u04ad\u0475\u0001\u0000\u0000" + + "\u0000\u04ad\u0486\u0001\u0000\u0000\u0000\u04ad\u048a\u0001\u0000\u0000" + + "\u0000\u04ad\u048f\u0001\u0000\u0000\u0000\u04ad\u0493\u0001\u0000\u0000" + + "\u0000\u04ad\u0498\u0001\u0000\u0000\u0000\u04ad\u049d\u0001\u0000\u0000" + + "\u0000\u04ad\u04a1\u0001\u0000\u0000\u0000\u04ad\u04a2\u0001\u0000\u0000" + + "\u0000\u04ad\u04a5\u0001\u0000\u0000\u0000\u04ad\u04a9\u0001\u0000\u0000" + + "\u0000\u04ae\u00a9\u0001\u0000\u0000\u0000\u04af\u04b0\u0005\u0007\u0000" + + "\u0000\u04b0\u04b4\u0005N\u0000\u0000\u04b1\u04b3\u0003\f\u0006\u0000" + + "\u04b2\u04b1\u0001\u0000\u0000\u0000\u04b3\u04b6\u0001\u0000\u0000\u0000" + + "\u04b4\u04b2\u0001\u0000\u0000\u0000\u04b4\u04b5\u0001\u0000\u0000\u0000" + + "\u04b5\u04b7\u0001\u0000\u0000\u0000\u04b6\u04b4\u0001\u0000\u0000\u0000" + + "\u04b7\u04b8\u0003\u00acV\u0000\u04b8\u04b9\u0003\u00a2Q\u0000\u04b9\u04ba" + + "\u0005O\u0000\u0000\u04ba\u04bb\u0003\u009cN\u0000\u04bb\u00ab\u0001\u0000" + + "\u0000\u0000\u04bc\u04c1\u0003f3\u0000\u04bd\u04be\u0005k\u0000\u0000" + + "\u04be\u04c0\u0003f3\u0000\u04bf\u04bd\u0001\u0000\u0000\u0000\u04c0\u04c3" + + "\u0001\u0000\u0000\u0000\u04c1\u04bf\u0001\u0000\u0000\u0000\u04c1\u04c2" + + "\u0001\u0000\u0000\u0000\u04c2\u00ad\u0001\u0000\u0000\u0000\u04c3\u04c1" + + "\u0001\u0000\u0000\u0000\u04c4\u04c5\u0005\u0013\u0000\u0000\u04c5\u04c6" + + "\u0003\u009cN\u0000\u04c6\u00af\u0001\u0000\u0000\u0000\u04c7\u04c8\u0005" + + "N\u0000\u0000\u04c8\u04ca\u0003\u00b2Y\u0000\u04c9\u04cb\u0005T\u0000" + + "\u0000\u04ca\u04c9\u0001\u0000\u0000\u0000\u04ca\u04cb\u0001\u0000\u0000" + + "\u0000\u04cb\u04cc\u0001\u0000\u0000\u0000\u04cc\u04cd\u0005O\u0000\u0000" + + "\u04cd\u00b1\u0001\u0000\u0000\u0000\u04ce\u04d3\u0003\u00b4Z\u0000\u04cf" + + "\u04d0\u0005T\u0000\u0000\u04d0\u04d2\u0003\u00b4Z\u0000\u04d1\u04cf\u0001" + + "\u0000\u0000\u0000\u04d2\u04d5\u0001\u0000\u0000\u0000\u04d3\u04d1\u0001" + + "\u0000\u0000\u0000\u04d3\u04d4\u0001\u0000\u0000\u0000\u04d4\u00b3\u0001" + + "\u0000\u0000\u0000\u04d5\u04d3\u0001\u0000\u0000\u0000\u04d6\u04d8\u0003" + + "\f\u0006\u0000\u04d7\u04d6\u0001\u0000\u0000\u0000\u04d8\u04db\u0001\u0000" + + "\u0000\u0000\u04d9\u04d7\u0001\u0000\u0000\u0000\u04d9\u04da\u0001\u0000" + + "\u0000\u0000\u04da\u04e1\u0001\u0000\u0000\u0000\u04db\u04d9\u0001\u0000" + + "\u0000\u0000\u04dc\u04dd\u0003R)\u0000\u04dd\u04de\u0003L&\u0000\u04de" + + "\u04e2\u0001\u0000\u0000\u0000\u04df\u04e0\u0005=\u0000\u0000\u04e0\u04e2" + + "\u0003\u00a2Q\u0000\u04e1\u04dc\u0001\u0000\u0000\u0000\u04e1\u04df\u0001" + + "\u0000\u0000\u0000\u04e2\u04e3\u0001\u0000\u0000\u0000\u04e3\u04e4\u0005" + + "W\u0000\u0000\u04e4\u04e5\u0003\u00c6c\u0000\u04e5\u04e8\u0001\u0000\u0000" + + "\u0000\u04e6\u04e8\u0003f3\u0000\u04e7\u04d9\u0001\u0000\u0000\u0000\u04e7" + + "\u04e6\u0001\u0000\u0000\u0000\u04e8\u00b5\u0001\u0000\u0000\u0000\u04e9" + + "\u04eb\u0003\u00b8\\\u0000\u04ea\u04e9\u0001\u0000\u0000\u0000\u04eb\u04ec" + + "\u0001\u0000\u0000\u0000\u04ec\u04ea\u0001\u0000\u0000\u0000\u04ec\u04ed" + + "\u0001\u0000\u0000\u0000\u04ed\u04ef\u0001\u0000\u0000\u0000\u04ee\u04f0" + + "\u0003\u009eO\u0000\u04ef\u04ee\u0001\u0000\u0000\u0000\u04f0\u04f1\u0001" + + "\u0000\u0000\u0000\u04f1\u04ef\u0001\u0000\u0000\u0000\u04f1\u04f2\u0001" + + "\u0000\u0000\u0000\u04f2\u00b7\u0001\u0000\u0000\u0000\u04f3\u04f9\u0005" + + "\u0006\u0000\u0000\u04f4\u04fa\u0003\u00c6c\u0000\u04f5\u04fa\u0005\u0081" + + "\u0000\u0000\u04f6\u04f7\u0003\u00f0x\u0000\u04f7\u04f8\u0003\u00a2Q\u0000" + + "\u04f8\u04fa\u0001\u0000\u0000\u0000\u04f9\u04f4\u0001\u0000\u0000\u0000" + + "\u04f9\u04f5\u0001\u0000\u0000\u0000\u04f9\u04f6\u0001\u0000\u0000\u0000" + + "\u04fa\u04fb\u0001\u0000\u0000\u0000\u04fb\u04ff\u0005]\u0000\u0000\u04fc" + + "\u04fd\u0005\f\u0000\u0000\u04fd\u04ff\u0005]\u0000\u0000\u04fe\u04f3" + + "\u0001\u0000\u0000\u0000\u04fe\u04fc\u0001\u0000\u0000\u0000\u04ff\u00b9" + + "\u0001\u0000\u0000\u0000\u0500\u050d\u0003\u00be_\u0000\u0501\u0503\u0003" + + "\u00bc^\u0000\u0502\u0501\u0001\u0000\u0000\u0000\u0502\u0503\u0001\u0000" + + "\u0000\u0000\u0503\u0504\u0001\u0000\u0000\u0000\u0504\u0506\u0005T\u0000" + + "\u0000\u0505\u0507\u0003\u00c6c\u0000\u0506\u0505\u0001\u0000\u0000\u0000" + + "\u0506\u0507\u0001\u0000\u0000\u0000\u0507\u0508\u0001\u0000\u0000\u0000" + + "\u0508\u050a\u0005T\u0000\u0000\u0509\u050b\u0003\u00c2a\u0000\u050a\u0509" + + "\u0001\u0000\u0000\u0000\u050a\u050b\u0001\u0000\u0000\u0000\u050b\u050d" + + "\u0001\u0000\u0000\u0000\u050c\u0500\u0001\u0000\u0000\u0000\u050c\u0502" + + "\u0001\u0000\u0000\u0000\u050d\u00bb\u0001\u0000\u0000\u0000\u050e\u0511" + + "\u0003\u00a0P\u0000\u050f\u0511\u0003\u00c2a\u0000\u0510\u050e\u0001\u0000" + + "\u0000\u0000\u0510\u050f\u0001\u0000\u0000\u0000\u0511\u00bd\u0001\u0000" + + "\u0000\u0000\u0512\u0514\u0003\f\u0006\u0000\u0513\u0512\u0001\u0000\u0000" + + "\u0000\u0514\u0517\u0001\u0000\u0000\u0000\u0515\u0513\u0001\u0000\u0000" + + "\u0000\u0515\u0516\u0001\u0000\u0000\u0000\u0516\u051a\u0001\u0000\u0000" + + "\u0000\u0517\u0515\u0001\u0000\u0000\u0000\u0518\u051b\u0003\u00f0x\u0000" + + "\u0519\u051b\u0005=\u0000\u0000\u051a\u0518\u0001\u0000\u0000\u0000\u051a" + + "\u0519\u0001\u0000\u0000\u0000\u051b\u051c\u0001\u0000\u0000\u0000\u051c" + + "\u051d\u0003L&\u0000\u051d\u051e\u0005]\u0000\u0000\u051e\u051f\u0003" + + "\u00c6c\u0000\u051f\u00bf\u0001\u0000\u0000\u0000\u0520\u0521\u0005N\u0000" + + "\u0000\u0521\u0522\u0003\u00c6c\u0000\u0522\u0523\u0005O\u0000\u0000\u0523" + + "\u00c1\u0001\u0000\u0000\u0000\u0524\u0529\u0003\u00c6c\u0000\u0525\u0526" + + "\u0005U\u0000\u0000\u0526\u0528\u0003\u00c6c\u0000\u0527\u0525\u0001\u0000" + + "\u0000\u0000\u0528\u052b\u0001\u0000\u0000\u0000\u0529\u0527\u0001\u0000" + + "\u0000\u0000\u0529\u052a\u0001\u0000\u0000\u0000\u052a\u00c3\u0001\u0000" + + "\u0000\u0000\u052b\u0529\u0001\u0000\u0000\u0000\u052c\u0530\u0003\u00a2" + + "Q\u0000\u052d\u0530\u0005+\u0000\u0000\u052e\u0530\u0005(\u0000\u0000" + + "\u052f\u052c\u0001\u0000\u0000\u0000\u052f\u052d\u0001\u0000\u0000\u0000" + + "\u052f\u052e\u0001\u0000\u0000\u0000\u0530\u0531\u0001\u0000\u0000\u0000" + + "\u0531\u0532\u0003\u00fa}\u0000\u0532\u00c5\u0001\u0000\u0000\u0000\u0533" + + "\u0534\u0006c\uffff\uffff\u0000\u0534\u055f\u0003\u00d0h\u0000\u0535\u055f" + + "\u0003\u00c4b\u0000\u0536\u0537\u0003\u00f0x\u0000\u0537\u053d\u0005z" + + "\u0000\u0000\u0538\u053a\u0003\u00f4z\u0000\u0539\u0538\u0001\u0000\u0000" + + "\u0000\u0539\u053a\u0001\u0000\u0000\u0000\u053a\u053b\u0001\u0000\u0000" + + "\u0000\u053b\u053e\u0003\u00a2Q\u0000\u053c\u053e\u0005\u001f\u0000\u0000" + + "\u053d\u0539\u0001\u0000\u0000\u0000\u053d\u053c\u0001\u0000\u0000\u0000" + + "\u053e\u055f\u0001\u0000\u0000\u0000\u053f\u0540\u0003\u00dam\u0000\u0540" + + "\u0542\u0005z\u0000\u0000\u0541\u0543\u0003\u00f4z\u0000\u0542\u0541\u0001" + + "\u0000\u0000\u0000\u0542\u0543\u0001\u0000\u0000\u0000\u0543\u0544\u0001" + + "\u0000\u0000\u0000\u0544\u0545\u0005\u001f\u0000\u0000\u0545\u055f\u0001" + + "\u0000\u0000\u0000\u0546\u055f\u0003\u00d2i\u0000\u0547\u0548\u0007\u0006" + + "\u0000\u0000\u0548\u055f\u0003\u00c6c\u0011\u0549\u054d\u0005N\u0000\u0000" + + "\u054a\u054c\u0003p8\u0000\u054b\u054a\u0001\u0000\u0000\u0000\u054c\u054f" + + "\u0001\u0000\u0000\u0000\u054d\u054b\u0001\u0000\u0000\u0000\u054d\u054e" + + "\u0001\u0000\u0000\u0000\u054e\u0550\u0001\u0000\u0000\u0000\u054f\u054d" + + "\u0001\u0000\u0000\u0000\u0550\u0555\u0003\u00f0x\u0000\u0551\u0552\u0005" + + "j\u0000\u0000\u0552\u0554\u0003\u00f0x\u0000\u0553\u0551\u0001\u0000\u0000" + + "\u0000\u0554\u0557\u0001\u0000\u0000\u0000\u0555\u0553\u0001\u0000\u0000" + + "\u0000\u0555\u0556\u0001\u0000\u0000\u0000\u0556\u0558\u0001\u0000\u0000" + + "\u0000\u0557\u0555\u0001\u0000\u0000\u0000\u0558\u0559\u0005O\u0000\u0000" + + "\u0559\u055a\u0003\u00c6c\u0010\u055a\u055f\u0001\u0000\u0000\u0000\u055b" + + "\u055c\u0005\u001f\u0000\u0000\u055c\u055f\u0003\u00dcn\u0000\u055d\u055f" + + "\u0003\u00cae\u0000\u055e\u0533\u0001\u0000\u0000\u0000\u055e\u0535\u0001" + + "\u0000\u0000\u0000\u055e\u0536\u0001\u0000\u0000\u0000\u055e\u053f\u0001" + + "\u0000\u0000\u0000\u055e\u0546\u0001\u0000\u0000\u0000\u055e\u0547\u0001" + + "\u0000\u0000\u0000\u055e\u0549\u0001\u0000\u0000\u0000\u055e\u055b\u0001" + + "\u0000\u0000\u0000\u055e\u055d\u0001\u0000\u0000\u0000\u055f\u05b3\u0001" + + "\u0000\u0000\u0000\u0560\u0561\n\u000e\u0000\u0000\u0561\u0562\u0007\u0007" + + "\u0000\u0000\u0562\u05b2\u0003\u00c6c\u000f\u0563\u0564\n\r\u0000\u0000" + + "\u0564\u0565\u0007\b\u0000\u0000\u0565\u05b2\u0003\u00c6c\u000e\u0566" + + "\u056e\n\f\u0000\u0000\u0567\u0568\u0005Y\u0000\u0000\u0568\u056f\u0005" + + "Y\u0000\u0000\u0569\u056a\u0005X\u0000\u0000\u056a\u056b\u0005X\u0000" + + "\u0000\u056b\u056f\u0005X\u0000\u0000\u056c\u056d\u0005X\u0000\u0000\u056d" + + "\u056f\u0005X\u0000\u0000\u056e\u0567\u0001\u0000\u0000\u0000\u056e\u0569" + + "\u0001\u0000\u0000\u0000\u056e\u056c\u0001\u0000\u0000\u0000\u056f\u0570" + + "\u0001\u0000\u0000\u0000\u0570\u05b2\u0003\u00c6c\r\u0571\u0572\n\u000b" + + "\u0000\u0000\u0572\u0573\u0007\t\u0000\u0000\u0573\u05b2\u0003\u00c6c" + + "\f\u0574\u0575\n\t\u0000\u0000\u0575\u0576\u0007\n\u0000\u0000\u0576\u05b2" + + "\u0003\u00c6c\n\u0577\u0578\n\b\u0000\u0000\u0578\u0579\u0005j\u0000\u0000" + + "\u0579\u05b2\u0003\u00c6c\t\u057a\u057b\n\u0007\u0000\u0000\u057b\u057c" + + "\u0005l\u0000\u0000\u057c\u05b2\u0003\u00c6c\b\u057d\u057e\n\u0006\u0000" + + "\u0000\u057e\u057f\u0005k\u0000\u0000\u057f\u05b2\u0003\u00c6c\u0007\u0580" + + "\u0581\n\u0005\u0000\u0000\u0581\u0582\u0005b\u0000\u0000\u0582\u05b2" + + "\u0003\u00c6c\u0006\u0583\u0584\n\u0004\u0000\u0000\u0584\u0585\u0005" + + "c\u0000\u0000\u0585\u05b2\u0003\u00c6c\u0005\u0586\u0587\n\u0003\u0000" + + "\u0000\u0587\u0588\u0005\\\u0000\u0000\u0588\u0589\u0003\u00c6c\u0000" + + "\u0589\u058a\u0005]\u0000\u0000\u058a\u058b\u0003\u00c6c\u0003\u058b\u05b2" + + "\u0001\u0000\u0000\u0000\u058c\u058d\n\u0002\u0000\u0000\u058d\u058e\u0007" + + "\u000b\u0000\u0000\u058e\u05b2\u0003\u00c6c\u0002\u058f\u0590\n\u0019" + + "\u0000\u0000\u0590\u0591\u0005R\u0000\u0000\u0591\u0592\u0003\u00c6c\u0000" + + "\u0592\u0593\u0005S\u0000\u0000\u0593\u05b2\u0001\u0000\u0000\u0000\u0594" + + "\u0595\n\u0018\u0000\u0000\u0595\u05a1\u0005V\u0000\u0000\u0596\u05a2" + + "\u0003\u00a2Q\u0000\u0597\u05a2\u0003\u00c4b\u0000\u0598\u05a2\u0005+" + + "\u0000\u0000\u0599\u059b\u0005\u001f\u0000\u0000\u059a\u059c\u0003\u00ec" + + "v\u0000\u059b\u059a\u0001\u0000\u0000\u0000\u059b\u059c\u0001\u0000\u0000" + + "\u0000\u059c\u059d\u0001\u0000\u0000\u0000\u059d\u05a2\u0003\u00e0p\u0000" + + "\u059e\u059f\u0005(\u0000\u0000\u059f\u05a2\u0003\u00f6{\u0000\u05a0\u05a2" + + "\u0003\u00e6s\u0000\u05a1\u0596\u0001\u0000\u0000\u0000\u05a1\u0597\u0001" + + "\u0000\u0000\u0000\u05a1\u0598\u0001\u0000\u0000\u0000\u05a1\u0599\u0001" + + "\u0000\u0000\u0000\u05a1\u059e\u0001\u0000\u0000\u0000\u05a1\u05a0\u0001" + + "\u0000\u0000\u0000\u05a2\u05b2\u0001\u0000\u0000\u0000\u05a3\u05a4\n\u0016" + + "\u0000\u0000\u05a4\u05a6\u0005z\u0000\u0000\u05a5\u05a7\u0003\u00f4z\u0000" + + "\u05a6\u05a5\u0001\u0000\u0000\u0000\u05a6\u05a7\u0001\u0000\u0000\u0000" + + "\u05a7\u05a8\u0001\u0000\u0000\u0000\u05a8\u05b2\u0003\u00a2Q\u0000\u05a9" + + "\u05aa\n\u0012\u0000\u0000\u05aa\u05b2\u0007\f\u0000\u0000\u05ab\u05ac" + + "\n\n\u0000\u0000\u05ac\u05af\u0005\u001a\u0000\u0000\u05ad\u05b0\u0003" + + "\u00f0x\u0000\u05ae\u05b0\u0003\u00c8d\u0000\u05af\u05ad\u0001\u0000\u0000" + + "\u0000\u05af\u05ae\u0001\u0000\u0000\u0000\u05b0\u05b2\u0001\u0000\u0000" + + "\u0000\u05b1\u0560\u0001\u0000\u0000\u0000\u05b1\u0563\u0001\u0000\u0000" + + "\u0000\u05b1\u0566\u0001\u0000\u0000\u0000\u05b1\u0571\u0001\u0000\u0000" + + "\u0000\u05b1\u0574\u0001\u0000\u0000\u0000\u05b1\u0577\u0001\u0000\u0000" + + "\u0000\u05b1\u057a\u0001\u0000\u0000\u0000\u05b1\u057d\u0001\u0000\u0000" + + "\u0000\u05b1\u0580\u0001\u0000\u0000\u0000\u05b1\u0583\u0001\u0000\u0000" + + "\u0000\u05b1\u0586\u0001\u0000\u0000\u0000\u05b1\u058c\u0001\u0000\u0000" + + "\u0000\u05b1\u058f\u0001\u0000\u0000\u0000\u05b1\u0594\u0001\u0000\u0000" + + "\u0000\u05b1\u05a3\u0001\u0000\u0000\u0000\u05b1\u05a9\u0001\u0000\u0000" + + "\u0000\u05b1\u05ab\u0001\u0000\u0000\u0000\u05b2\u05b5\u0001\u0000\u0000" + + "\u0000\u05b3\u05b1\u0001\u0000\u0000\u0000\u05b3\u05b4\u0001\u0000\u0000" + + "\u0000\u05b4\u00c7\u0001\u0000\u0000\u0000\u05b5\u05b3\u0001\u0000\u0000" + + "\u0000\u05b6\u05b8\u0003\f\u0006\u0000\u05b7\u05b6\u0001\u0000\u0000\u0000" + + "\u05b8\u05bb\u0001\u0000\u0000\u0000\u05b9\u05b7\u0001\u0000\u0000\u0000" + + "\u05b9\u05ba\u0001\u0000\u0000\u0000\u05ba\u05bc\u0001\u0000\u0000\u0000" + + "\u05bb\u05b9\u0001\u0000\u0000\u0000\u05bc\u05c0\u0003\u00f0x\u0000\u05bd" + + "\u05bf\u0003p8\u0000\u05be\u05bd\u0001\u0000\u0000\u0000\u05bf\u05c2\u0001" + + "\u0000\u0000\u0000\u05c0\u05be\u0001\u0000\u0000\u0000\u05c0\u05c1\u0001" + + "\u0000\u0000\u0000\u05c1\u05c3\u0001\u0000\u0000\u0000\u05c2\u05c0\u0001" + + "\u0000\u0000\u0000\u05c3\u05c4\u0003\u00a2Q\u0000\u05c4\u00c9\u0001\u0000" + + "\u0000\u0000\u05c5\u05c6\u0003\u00ccf\u0000\u05c6\u05c7\u0005y\u0000\u0000" + + "\u05c7\u05c8\u0003\u00ceg\u0000\u05c8\u00cb\u0001\u0000\u0000\u0000\u05c9" + + "\u05e0\u0003\u00a2Q\u0000\u05ca\u05cc\u0005N\u0000\u0000\u05cb\u05cd\u0003" + + "\\.\u0000\u05cc\u05cb\u0001\u0000\u0000\u0000\u05cc\u05cd\u0001\u0000" + + "\u0000\u0000\u05cd\u05ce\u0001\u0000\u0000\u0000\u05ce\u05e0\u0005O\u0000" + + "\u0000\u05cf\u05d0\u0005N\u0000\u0000\u05d0\u05d5\u0003\u00a2Q\u0000\u05d1" + + "\u05d2\u0005U\u0000\u0000\u05d2\u05d4\u0003\u00a2Q\u0000\u05d3\u05d1\u0001" + + "\u0000\u0000\u0000\u05d4\u05d7\u0001\u0000\u0000\u0000\u05d5\u05d3\u0001" + + "\u0000\u0000\u0000\u05d5\u05d6\u0001\u0000\u0000\u0000\u05d6\u05d8\u0001" + + "\u0000\u0000\u0000\u05d7\u05d5\u0001\u0000\u0000\u0000\u05d8\u05d9\u0005" + + "O\u0000\u0000\u05d9\u05e0\u0001\u0000\u0000\u0000\u05da\u05dc\u0005N\u0000" + + "\u0000\u05db\u05dd\u0003b1\u0000\u05dc\u05db\u0001\u0000\u0000\u0000\u05dc" + + "\u05dd\u0001\u0000\u0000\u0000\u05dd\u05de\u0001\u0000\u0000\u0000\u05de" + + "\u05e0\u0005O\u0000\u0000\u05df\u05c9\u0001\u0000\u0000\u0000\u05df\u05ca" + + "\u0001\u0000\u0000\u0000\u05df\u05cf\u0001\u0000\u0000\u0000\u05df\u05da" + + "\u0001\u0000\u0000\u0000\u05e0\u00cd\u0001\u0000\u0000\u0000\u05e1\u05e4" + + "\u0003\u00c6c\u0000\u05e2\u05e4\u0003\u009cN\u0000\u05e3\u05e1\u0001\u0000" + + "\u0000\u0000\u05e3\u05e2\u0001\u0000\u0000\u0000\u05e4\u00cf\u0001\u0000" + + "\u0000\u0000\u05e5\u05e6\u0005N\u0000\u0000\u05e6\u05e7\u0003\u00c6c\u0000" + + "\u05e7\u05e8\u0005O\u0000\u0000\u05e8\u05f8\u0001\u0000\u0000\u0000\u05e9" + + "\u05f8\u0005+\u0000\u0000\u05ea\u05f8\u0005(\u0000\u0000\u05eb\u05f8\u0003" + + "h4\u0000\u05ec\u05f8\u0003\u00a2Q\u0000\u05ed\u05ee\u0003,\u0016\u0000" + + "\u05ee\u05ef\u0005V\u0000\u0000\u05ef\u05f0\u0005\t\u0000\u0000\u05f0" + + "\u05f8\u0001\u0000\u0000\u0000\u05f1\u05f5\u0003\u00ecv\u0000\u05f2\u05f6" + + "\u0003\u00f8|\u0000\u05f3\u05f4\u0005+\u0000\u0000\u05f4\u05f6\u0003\u00fa" + + "}\u0000\u05f5\u05f2\u0001\u0000\u0000\u0000\u05f5\u05f3\u0001\u0000\u0000" + + "\u0000\u05f6\u05f8\u0001\u0000\u0000\u0000\u05f7\u05e5\u0001\u0000\u0000" + + "\u0000\u05f7\u05e9\u0001\u0000\u0000\u0000\u05f7\u05ea\u0001\u0000\u0000" + + "\u0000\u05f7\u05eb\u0001\u0000\u0000\u0000\u05f7\u05ec\u0001\u0000\u0000" + + "\u0000\u05f7\u05ed\u0001\u0000\u0000\u0000\u05f7\u05f1\u0001\u0000\u0000" + + "\u0000\u05f8\u00d1\u0001\u0000\u0000\u0000\u05f9\u05fa\u0005)\u0000\u0000" + + "\u05fa\u05fb\u0003\u00c0`\u0000\u05fb\u05ff\u0005P\u0000\u0000\u05fc\u05fe" + + "\u0003\u00d4j\u0000\u05fd\u05fc\u0001\u0000\u0000\u0000\u05fe\u0601\u0001" + + "\u0000\u0000\u0000\u05ff\u05fd\u0001\u0000\u0000\u0000\u05ff\u0600\u0001" + + "\u0000\u0000\u0000\u0600\u0602\u0001\u0000\u0000\u0000\u0601\u05ff\u0001" + + "\u0000\u0000\u0000\u0602\u0603\u0005Q\u0000\u0000\u0603\u00d3\u0001\u0000" + + "\u0000\u0000\u0604\u0608\u0005\u0006\u0000\u0000\u0605\u0609\u0003\u00c2" + + "a\u0000\u0606\u0609\u0005M\u0000\u0000\u0607\u0609\u0003\u00d6k\u0000" + + "\u0608\u0605\u0001\u0000\u0000\u0000\u0608\u0606\u0001\u0000\u0000\u0000" + + "\u0608\u0607\u0001\u0000\u0000\u0000\u0609\u060a\u0001\u0000\u0000\u0000" + + "\u060a\u060b\u0007\r\u0000\u0000\u060b\u0610\u0003\u00d8l\u0000\u060c" + + "\u060d\u0005\f\u0000\u0000\u060d\u060e\u0007\r\u0000\u0000\u060e\u0610" + + "\u0003\u00d8l\u0000\u060f\u0604\u0001\u0000\u0000\u0000\u060f\u060c\u0001" + + "\u0000\u0000\u0000\u0610\u00d5\u0001\u0000\u0000\u0000\u0611\u0612\u0006" + + "k\uffff\uffff\u0000\u0612\u0613\u0005N\u0000\u0000\u0613\u0614\u0003\u00d6" + + "k\u0000\u0614\u0615\u0005O\u0000\u0000\u0615\u062c\u0001\u0000\u0000\u0000" + + "\u0616\u0618\u0003\f\u0006\u0000\u0617\u0616\u0001\u0000\u0000\u0000\u0618" + + "\u061b\u0001\u0000\u0000\u0000\u0619\u0617\u0001\u0000\u0000\u0000\u0619" + + "\u061a\u0001\u0000\u0000\u0000\u061a\u061c\u0001\u0000\u0000\u0000\u061b" + + "\u0619\u0001\u0000\u0000\u0000\u061c\u0620\u0003\u00f0x\u0000\u061d\u061f" + + "\u0003p8\u0000\u061e\u061d\u0001\u0000\u0000\u0000\u061f\u0622\u0001\u0000" + + "\u0000\u0000\u0620\u061e\u0001\u0000\u0000\u0000\u0620\u0621\u0001\u0000" + + "\u0000\u0000\u0621\u0623\u0001\u0000\u0000\u0000\u0622\u0620\u0001\u0000" + + "\u0000\u0000\u0623\u0628\u0003\u00a2Q\u0000\u0624\u0625\u0005b\u0000\u0000" + + "\u0625\u0627\u0003\u00c6c\u0000\u0626\u0624\u0001\u0000\u0000\u0000\u0627" + + "\u062a\u0001\u0000\u0000\u0000\u0628\u0626\u0001\u0000\u0000\u0000\u0628" + + "\u0629\u0001\u0000\u0000\u0000\u0629\u062c\u0001\u0000\u0000\u0000\u062a" + + "\u0628\u0001\u0000\u0000\u0000\u062b\u0611\u0001\u0000\u0000\u0000\u062b" + + "\u0619\u0001\u0000\u0000\u0000\u062c\u0632\u0001\u0000\u0000\u0000\u062d" + + "\u062e\n\u0001\u0000\u0000\u062e\u062f\u0005b\u0000\u0000\u062f\u0631" + + "\u0003\u00c6c\u0000\u0630\u062d\u0001\u0000\u0000\u0000\u0631\u0634\u0001" + + "\u0000\u0000\u0000\u0632\u0630\u0001\u0000\u0000\u0000\u0632\u0633\u0001" + + "\u0000\u0000\u0000\u0633\u00d7\u0001\u0000\u0000\u0000\u0634\u0632\u0001" + + "\u0000\u0000\u0000\u0635\u063d\u0003\u009cN\u0000\u0636\u0638\u0003\u009e" + + "O\u0000\u0637\u0636\u0001\u0000\u0000\u0000\u0638\u063b\u0001\u0000\u0000" + + "\u0000\u0639\u0637\u0001\u0000\u0000\u0000\u0639\u063a\u0001\u0000\u0000" + + "\u0000\u063a\u063d\u0001\u0000\u0000\u0000\u063b\u0639\u0001\u0000\u0000" + + "\u0000\u063c\u0635\u0001\u0000\u0000\u0000\u063c\u0639\u0001\u0000\u0000" + + "\u0000\u063d\u00d9\u0001\u0000\u0000\u0000\u063e\u063f\u0003R)\u0000\u063f" + + "\u0640\u0005V\u0000\u0000\u0640\u0642\u0001\u0000\u0000\u0000\u0641\u063e" + + "\u0001\u0000\u0000\u0000\u0641\u0642\u0001\u0000\u0000\u0000\u0642\u0646" + + "\u0001\u0000\u0000\u0000\u0643\u0645\u0003p8\u0000\u0644\u0643\u0001\u0000" + + "\u0000\u0000\u0645\u0648\u0001\u0000\u0000\u0000\u0646\u0644\u0001\u0000" + + "\u0000\u0000\u0646\u0647\u0001\u0000\u0000\u0000\u0647\u0649\u0001\u0000" + + "\u0000\u0000\u0648\u0646\u0001\u0000\u0000\u0000\u0649\u064b\u0003\u00a2" + + "Q\u0000\u064a\u064c\u0003\u00f4z\u0000\u064b\u064a\u0001\u0000\u0000\u0000" + + "\u064b\u064c\u0001\u0000\u0000\u0000\u064c\u00db\u0001\u0000\u0000\u0000" + + "\u064d\u064f\u0003\u00ecv\u0000\u064e\u064d\u0001\u0000\u0000\u0000\u064e" + + "\u064f\u0001\u0000\u0000\u0000\u064f\u0650\u0001\u0000\u0000\u0000\u0650" + + "\u0651\u0003\u00deo\u0000\u0651\u0652\u0003\u00e4r\u0000\u0652\u0657\u0001" + + "\u0000\u0000\u0000\u0653\u0654\u0003\u00deo\u0000\u0654\u0655\u0003\u00e2" + + "q\u0000\u0655\u0657\u0001\u0000\u0000\u0000\u0656\u064e\u0001\u0000\u0000" + + "\u0000\u0656\u0653\u0001\u0000\u0000\u0000\u0657\u00dd\u0001\u0000\u0000" + + "\u0000\u0658\u065a\u0003\u00a2Q\u0000\u0659\u065b\u0003\u00e8t\u0000\u065a" + + "\u0659\u0001\u0000\u0000\u0000\u065a\u065b\u0001\u0000\u0000\u0000\u065b" + + "\u0663\u0001\u0000\u0000\u0000\u065c\u065d\u0005V\u0000\u0000\u065d\u065f" + + "\u0003\u00a2Q\u0000\u065e\u0660\u0003\u00e8t\u0000\u065f\u065e\u0001\u0000" + + "\u0000\u0000\u065f\u0660\u0001\u0000\u0000\u0000\u0660\u0662\u0001\u0000" + + "\u0000\u0000\u0661\u065c\u0001\u0000\u0000\u0000\u0662\u0665\u0001\u0000" + + "\u0000\u0000\u0663\u0661\u0001\u0000\u0000\u0000\u0663\u0664\u0001\u0000" + + "\u0000\u0000\u0664\u0668\u0001\u0000\u0000\u0000\u0665\u0663\u0001\u0000" + + "\u0000\u0000\u0666\u0668\u0003\u00f2y\u0000\u0667\u0658\u0001\u0000\u0000" + + "\u0000\u0667\u0666\u0001\u0000\u0000\u0000\u0668\u00df\u0001\u0000\u0000" + + "\u0000\u0669\u066b\u0003\u00a2Q\u0000\u066a\u066c\u0003\u00eau\u0000\u066b" + + "\u066a\u0001\u0000\u0000\u0000\u066b\u066c\u0001\u0000\u0000\u0000\u066c" + + "\u066d\u0001\u0000\u0000\u0000\u066d\u066e\u0003\u00e4r\u0000\u066e\u00e1" + + "\u0001\u0000\u0000\u0000\u066f\u0670\u0005R\u0000\u0000\u0670\u0672\u0005" + + "S\u0000\u0000\u0671\u066f\u0001\u0000\u0000\u0000\u0672\u0673\u0001\u0000" + + "\u0000\u0000\u0673\u0671\u0001\u0000\u0000\u0000\u0673\u0674\u0001\u0000" + + "\u0000\u0000\u0674\u0675\u0001\u0000\u0000\u0000\u0675\u0686\u0003P(\u0000" + + "\u0676\u0677\u0005R\u0000\u0000\u0677\u0678\u0003\u00c6c\u0000\u0678\u0679" + + "\u0005S\u0000\u0000\u0679\u067b\u0001\u0000\u0000\u0000\u067a\u0676\u0001" + + "\u0000\u0000\u0000\u067b\u067c\u0001\u0000\u0000\u0000\u067c\u067a\u0001" + + "\u0000\u0000\u0000\u067c\u067d\u0001\u0000\u0000\u0000\u067d\u0682\u0001" + + "\u0000\u0000\u0000\u067e\u067f\u0005R\u0000\u0000\u067f\u0681\u0005S\u0000" + + "\u0000\u0680\u067e\u0001\u0000\u0000\u0000\u0681\u0684\u0001\u0000\u0000" + + "\u0000\u0682\u0680\u0001\u0000\u0000\u0000\u0682\u0683\u0001\u0000\u0000" + + "\u0000\u0683\u0686\u0001\u0000\u0000\u0000\u0684\u0682\u0001\u0000\u0000" + + "\u0000\u0685\u0671\u0001\u0000\u0000\u0000\u0685\u067a\u0001\u0000\u0000" + + "\u0000\u0686\u00e3\u0001\u0000\u0000\u0000\u0687\u0689\u0003\u00fa}\u0000" + + "\u0688\u068a\u0003 \u0010\u0000\u0689\u0688\u0001\u0000\u0000\u0000\u0689" + + "\u068a\u0001\u0000\u0000\u0000\u068a\u00e5\u0001\u0000\u0000\u0000\u068b" + + "\u068c\u0003\u00ecv\u0000\u068c\u068d\u0003\u00f8|\u0000\u068d\u00e7\u0001" + + "\u0000\u0000\u0000\u068e\u068f\u0005Y\u0000\u0000\u068f\u0692\u0005X\u0000" + + "\u0000\u0690\u0692\u0003\u00f4z\u0000\u0691\u068e\u0001\u0000\u0000\u0000" + + "\u0691\u0690\u0001\u0000\u0000\u0000\u0692\u00e9\u0001\u0000\u0000\u0000" + + "\u0693\u0694\u0005Y\u0000\u0000\u0694\u0697\u0005X\u0000\u0000\u0695\u0697" + + "\u0003\u00ecv\u0000\u0696\u0693\u0001\u0000\u0000\u0000\u0696\u0695\u0001" + + "\u0000\u0000\u0000\u0697\u00eb\u0001\u0000\u0000\u0000\u0698\u0699\u0005" + + "Y\u0000\u0000\u0699\u069a\u0003\u00eew\u0000\u069a\u069b\u0005X\u0000" + + "\u0000\u069b\u00ed\u0001\u0000\u0000\u0000\u069c\u06a1\u0003\u00f0x\u0000" + + "\u069d\u069e\u0005U\u0000\u0000\u069e\u06a0\u0003\u00f0x\u0000\u069f\u069d" + + "\u0001\u0000\u0000\u0000\u06a0\u06a3\u0001\u0000\u0000\u0000\u06a1\u069f" + + "\u0001\u0000\u0000\u0000\u06a1\u06a2\u0001\u0000\u0000\u0000\u06a2\u00ef" + + "\u0001\u0000\u0000\u0000\u06a3\u06a1\u0001\u0000\u0000\u0000\u06a4\u06a6" + + "\u0003p8\u0000\u06a5\u06a4\u0001\u0000\u0000\u0000\u06a6\u06a9\u0001\u0000" + + "\u0000\u0000\u06a7\u06a5\u0001\u0000\u0000\u0000\u06a7\u06a8\u0001\u0000" + + "\u0000\u0000\u06a8\u06ac\u0001\u0000\u0000\u0000\u06a9\u06a7\u0001\u0000" + + "\u0000\u0000\u06aa\u06ad\u0003R)\u0000\u06ab\u06ad\u0003\u00f2y\u0000" + + "\u06ac\u06aa\u0001\u0000\u0000\u0000\u06ac\u06ab\u0001\u0000\u0000\u0000" + + "\u06ad\u06b8\u0001\u0000\u0000\u0000\u06ae\u06b0\u0003p8\u0000\u06af\u06ae" + + "\u0001\u0000\u0000\u0000\u06b0\u06b3\u0001\u0000\u0000\u0000\u06b1\u06af" + + "\u0001\u0000\u0000\u0000\u06b1\u06b2\u0001\u0000\u0000\u0000\u06b2\u06b4" + + "\u0001\u0000\u0000\u0000\u06b3\u06b1\u0001\u0000\u0000\u0000\u06b4\u06b5" + + "\u0005R\u0000\u0000\u06b5\u06b7\u0005S\u0000\u0000\u06b6\u06b1\u0001\u0000" + + "\u0000\u0000\u06b7\u06ba\u0001\u0000\u0000\u0000\u06b8\u06b6\u0001\u0000" + + "\u0000\u0000\u06b8\u06b9\u0001\u0000\u0000\u0000\u06b9\u00f1\u0001\u0000" + + "\u0000\u0000\u06ba\u06b8\u0001\u0000\u0000\u0000\u06bb\u06bc\u0007\u000e" + + "\u0000\u0000\u06bc\u00f3\u0001\u0000\u0000\u0000\u06bd\u06be\u0005Y\u0000" + + "\u0000\u06be\u06c3\u0003T*\u0000\u06bf\u06c0\u0005U\u0000\u0000\u06c0" + + "\u06c2\u0003T*\u0000\u06c1\u06bf\u0001\u0000\u0000\u0000\u06c2\u06c5\u0001" + + "\u0000\u0000\u0000\u06c3\u06c1\u0001\u0000\u0000\u0000\u06c3\u06c4\u0001" + + "\u0000\u0000\u0000\u06c4\u06c6\u0001\u0000\u0000\u0000\u06c5\u06c3\u0001" + + "\u0000\u0000\u0000\u06c6\u06c7\u0005X\u0000\u0000\u06c7\u00f5\u0001\u0000" + + "\u0000\u0000\u06c8\u06d2\u0003\u00fa}\u0000\u06c9\u06cb\u0005V\u0000\u0000" + + "\u06ca\u06cc\u0003\u00f4z\u0000\u06cb\u06ca\u0001\u0000\u0000\u0000\u06cb" + + "\u06cc\u0001\u0000\u0000\u0000\u06cc\u06cd\u0001\u0000\u0000\u0000\u06cd" + + "\u06cf\u0003\u00a2Q\u0000\u06ce\u06d0\u0003\u00fa}\u0000\u06cf\u06ce\u0001" + + "\u0000\u0000\u0000\u06cf\u06d0\u0001\u0000\u0000\u0000\u06d0\u06d2\u0001" + + "\u0000\u0000\u0000\u06d1\u06c8\u0001\u0000\u0000\u0000\u06d1\u06c9\u0001" + + "\u0000\u0000\u0000\u06d2\u00f7\u0001\u0000\u0000\u0000\u06d3\u06d4\u0005" + + "(\u0000\u0000\u06d4\u06d9\u0003\u00f6{\u0000\u06d5\u06d6\u0003\u00a2Q" + + "\u0000\u06d6\u06d7\u0003\u00fa}\u0000\u06d7\u06d9\u0001\u0000\u0000\u0000" + + "\u06d8\u06d3\u0001\u0000\u0000\u0000\u06d8\u06d5\u0001\u0000\u0000\u0000" + + "\u06d9\u00f9\u0001\u0000\u0000\u0000\u06da\u06dc\u0005N\u0000\u0000\u06db" + + "\u06dd\u0003\u00c2a\u0000\u06dc\u06db\u0001\u0000\u0000\u0000\u06dc\u06dd" + + "\u0001\u0000\u0000\u0000\u06dd\u06de\u0001\u0000\u0000\u0000\u06de\u06df" + + "\u0005O\u0000\u0000\u06df\u00fb\u0001\u0000\u0000\u0000\u00dc\u00fd\u0101" + + "\u0103\u0109\u010e\u0110\u0116\u011b\u0124\u0129\u0130\u0138\u013f\u014b" + + "\u014f\u0154\u0158\u015c\u0160\u016a\u0172\u017a\u017e\u0185\u018c\u0190" + + "\u0193\u0196\u019f\u01a5\u01aa\u01ad\u01b3\u01b9\u01bd\u01c1\u01c9\u01d2" + + "\u01d9\u01df\u01e3\u01ef\u01f8\u01fd\u0203\u0207\u0213\u021a\u0227\u022c" + + "\u0236\u023e\u0248\u0251\u025c\u0261\u026a\u0274\u0279\u0282\u0288\u028f" + + "\u0294\u029c\u02a0\u02a2\u02a8\u02ae\u02b3\u02b9\u02bf\u02c1\u02c8\u02cd" + + "\u02d2\u02d5\u02d7\u02e1\u02eb\u02f0\u02f3\u02f8\u0301\u0308\u0313\u0319" + + "\u0324\u032e\u0339\u0342\u0347\u034a\u0351\u035b\u0363\u0366\u0369\u0376" + + "\u037e\u0383\u038b\u038f\u0393\u0397\u039b\u039d\u03a1\u03a7\u03af\u03b9" + + "\u03c2\u03cc\u03d4\u03e2\u03e9\u03ee\u03f4\u03fd\u0406\u0408\u0411\u041b" + + "\u0420\u042b\u0434\u043a\u0441\u044a\u0461\u0464\u0467\u046f\u0473\u047b" + + "\u0481\u048c\u0495\u049a\u04a7\u04ad\u04b4\u04c1\u04ca\u04d3\u04d9\u04e1" + + "\u04e7\u04ec\u04f1\u04f9\u04fe\u0502\u0506\u050a\u050c\u0510\u0515\u051a" + + "\u0529\u052f\u0539\u053d\u0542\u054d\u0555\u055e\u056e\u059b\u05a1\u05a6" + + "\u05af\u05b1\u05b3\u05b9\u05c0\u05cc\u05d5\u05dc\u05df\u05e3\u05f5\u05f7" + + "\u05ff\u0608\u060f\u0619\u0620\u0628\u062b\u0632\u0639\u063c\u0641\u0646" + + "\u064b\u064e\u0656\u065a\u065f\u0663\u0667\u066b\u0673\u067c\u0682\u0685" + + "\u0689\u0691\u0696\u06a1\u06a7\u06ac\u06b1\u06b8\u06c3\u06cb\u06cf\u06d1" + + "\u06d8\u06dc"; + public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavaParserBaseListener.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavaParserBaseListener.java new file mode 100644 index 000000000000..247682ea9c1f --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavaParserBaseListener.java @@ -0,0 +1,1823 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor.antlr.generated; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.TerminalNode; + +/** + * This class provides an empty implementation of {@link JavaParserListener}, + * which can be extended to create a listener which only needs to handle a subset + * of the available methods. + */ +@SuppressWarnings("CheckReturnValue") +public class JavaParserBaseListener implements JavaParserListener { + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterCompilationUnit(JavaParser.CompilationUnitContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitCompilationUnit(JavaParser.CompilationUnitContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterPackageDeclaration(JavaParser.PackageDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitPackageDeclaration(JavaParser.PackageDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterImportDeclaration(JavaParser.ImportDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitImportDeclaration(JavaParser.ImportDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterTypeDeclaration(JavaParser.TypeDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitTypeDeclaration(JavaParser.TypeDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterModifier(JavaParser.ModifierContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitModifier(JavaParser.ModifierContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterClassOrInterfaceModifier(JavaParser.ClassOrInterfaceModifierContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitClassOrInterfaceModifier(JavaParser.ClassOrInterfaceModifierContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterVariableModifier(JavaParser.VariableModifierContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitVariableModifier(JavaParser.VariableModifierContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterClassDeclaration(JavaParser.ClassDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitClassDeclaration(JavaParser.ClassDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterTypeParameters(JavaParser.TypeParametersContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitTypeParameters(JavaParser.TypeParametersContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterTypeParameter(JavaParser.TypeParameterContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitTypeParameter(JavaParser.TypeParameterContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterTypeBound(JavaParser.TypeBoundContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitTypeBound(JavaParser.TypeBoundContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterEnumDeclaration(JavaParser.EnumDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitEnumDeclaration(JavaParser.EnumDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterEnumConstants(JavaParser.EnumConstantsContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitEnumConstants(JavaParser.EnumConstantsContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterEnumConstant(JavaParser.EnumConstantContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitEnumConstant(JavaParser.EnumConstantContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterEnumBodyDeclarations(JavaParser.EnumBodyDeclarationsContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitEnumBodyDeclarations(JavaParser.EnumBodyDeclarationsContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterInterfaceDeclaration(JavaParser.InterfaceDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitInterfaceDeclaration(JavaParser.InterfaceDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterClassBody(JavaParser.ClassBodyContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitClassBody(JavaParser.ClassBodyContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterInterfaceBody(JavaParser.InterfaceBodyContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitInterfaceBody(JavaParser.InterfaceBodyContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterClassBodyDeclaration(JavaParser.ClassBodyDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitClassBodyDeclaration(JavaParser.ClassBodyDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterMemberDeclaration(JavaParser.MemberDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitMemberDeclaration(JavaParser.MemberDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterMethodDeclaration(JavaParser.MethodDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitMethodDeclaration(JavaParser.MethodDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterMethodBody(JavaParser.MethodBodyContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitMethodBody(JavaParser.MethodBodyContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterTypeTypeOrVoid(JavaParser.TypeTypeOrVoidContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitTypeTypeOrVoid(JavaParser.TypeTypeOrVoidContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterGenericMethodDeclaration(JavaParser.GenericMethodDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitGenericMethodDeclaration(JavaParser.GenericMethodDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterGenericConstructorDeclaration(JavaParser.GenericConstructorDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitGenericConstructorDeclaration(JavaParser.GenericConstructorDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterConstructorDeclaration(JavaParser.ConstructorDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitConstructorDeclaration(JavaParser.ConstructorDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterCompactConstructorDeclaration(JavaParser.CompactConstructorDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitCompactConstructorDeclaration(JavaParser.CompactConstructorDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterFieldDeclaration(JavaParser.FieldDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitFieldDeclaration(JavaParser.FieldDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterInterfaceBodyDeclaration(JavaParser.InterfaceBodyDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitInterfaceBodyDeclaration(JavaParser.InterfaceBodyDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterInterfaceMemberDeclaration(JavaParser.InterfaceMemberDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitInterfaceMemberDeclaration(JavaParser.InterfaceMemberDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterConstDeclaration(JavaParser.ConstDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitConstDeclaration(JavaParser.ConstDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterConstantDeclarator(JavaParser.ConstantDeclaratorContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitConstantDeclarator(JavaParser.ConstantDeclaratorContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterInterfaceMethodDeclaration(JavaParser.InterfaceMethodDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitInterfaceMethodDeclaration(JavaParser.InterfaceMethodDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterInterfaceMethodModifier(JavaParser.InterfaceMethodModifierContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitInterfaceMethodModifier(JavaParser.InterfaceMethodModifierContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterGenericInterfaceMethodDeclaration(JavaParser.GenericInterfaceMethodDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitGenericInterfaceMethodDeclaration(JavaParser.GenericInterfaceMethodDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterInterfaceCommonBodyDeclaration(JavaParser.InterfaceCommonBodyDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitInterfaceCommonBodyDeclaration(JavaParser.InterfaceCommonBodyDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterVariableDeclarators(JavaParser.VariableDeclaratorsContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitVariableDeclarators(JavaParser.VariableDeclaratorsContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterVariableDeclarator(JavaParser.VariableDeclaratorContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitVariableDeclarator(JavaParser.VariableDeclaratorContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterVariableDeclaratorId(JavaParser.VariableDeclaratorIdContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitVariableDeclaratorId(JavaParser.VariableDeclaratorIdContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterVariableInitializer(JavaParser.VariableInitializerContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitVariableInitializer(JavaParser.VariableInitializerContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterArrayInitializer(JavaParser.ArrayInitializerContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitArrayInitializer(JavaParser.ArrayInitializerContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterClassOrInterfaceType(JavaParser.ClassOrInterfaceTypeContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitClassOrInterfaceType(JavaParser.ClassOrInterfaceTypeContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterTypeArgument(JavaParser.TypeArgumentContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitTypeArgument(JavaParser.TypeArgumentContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterQualifiedNameList(JavaParser.QualifiedNameListContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitQualifiedNameList(JavaParser.QualifiedNameListContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterFormalParameters(JavaParser.FormalParametersContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitFormalParameters(JavaParser.FormalParametersContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterReceiverParameter(JavaParser.ReceiverParameterContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitReceiverParameter(JavaParser.ReceiverParameterContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterFormalParameterList(JavaParser.FormalParameterListContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitFormalParameterList(JavaParser.FormalParameterListContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterFormalParameter(JavaParser.FormalParameterContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitFormalParameter(JavaParser.FormalParameterContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterLastFormalParameter(JavaParser.LastFormalParameterContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitLastFormalParameter(JavaParser.LastFormalParameterContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterLambdaLVTIList(JavaParser.LambdaLVTIListContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitLambdaLVTIList(JavaParser.LambdaLVTIListContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterLambdaLVTIParameter(JavaParser.LambdaLVTIParameterContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitLambdaLVTIParameter(JavaParser.LambdaLVTIParameterContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterQualifiedName(JavaParser.QualifiedNameContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitQualifiedName(JavaParser.QualifiedNameContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterLiteral(JavaParser.LiteralContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitLiteral(JavaParser.LiteralContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterIntegerLiteral(JavaParser.IntegerLiteralContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitIntegerLiteral(JavaParser.IntegerLiteralContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterFloatLiteral(JavaParser.FloatLiteralContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitFloatLiteral(JavaParser.FloatLiteralContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterAltAnnotationQualifiedName(JavaParser.AltAnnotationQualifiedNameContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitAltAnnotationQualifiedName(JavaParser.AltAnnotationQualifiedNameContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterAnnotation(JavaParser.AnnotationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitAnnotation(JavaParser.AnnotationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterElementValuePairs(JavaParser.ElementValuePairsContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitElementValuePairs(JavaParser.ElementValuePairsContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterElementValuePair(JavaParser.ElementValuePairContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitElementValuePair(JavaParser.ElementValuePairContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterElementValue(JavaParser.ElementValueContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitElementValue(JavaParser.ElementValueContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterElementValueArrayInitializer(JavaParser.ElementValueArrayInitializerContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitElementValueArrayInitializer(JavaParser.ElementValueArrayInitializerContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterAnnotationTypeDeclaration(JavaParser.AnnotationTypeDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitAnnotationTypeDeclaration(JavaParser.AnnotationTypeDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterAnnotationTypeBody(JavaParser.AnnotationTypeBodyContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitAnnotationTypeBody(JavaParser.AnnotationTypeBodyContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterAnnotationTypeElementDeclaration(JavaParser.AnnotationTypeElementDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitAnnotationTypeElementDeclaration(JavaParser.AnnotationTypeElementDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterAnnotationTypeElementRest(JavaParser.AnnotationTypeElementRestContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitAnnotationTypeElementRest(JavaParser.AnnotationTypeElementRestContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterAnnotationMethodOrConstantRest(JavaParser.AnnotationMethodOrConstantRestContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitAnnotationMethodOrConstantRest(JavaParser.AnnotationMethodOrConstantRestContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterAnnotationMethodRest(JavaParser.AnnotationMethodRestContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitAnnotationMethodRest(JavaParser.AnnotationMethodRestContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterAnnotationConstantRest(JavaParser.AnnotationConstantRestContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitAnnotationConstantRest(JavaParser.AnnotationConstantRestContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterDefaultValue(JavaParser.DefaultValueContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitDefaultValue(JavaParser.DefaultValueContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterModuleDeclaration(JavaParser.ModuleDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitModuleDeclaration(JavaParser.ModuleDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterModuleBody(JavaParser.ModuleBodyContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitModuleBody(JavaParser.ModuleBodyContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterModuleDirective(JavaParser.ModuleDirectiveContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitModuleDirective(JavaParser.ModuleDirectiveContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterRequiresModifier(JavaParser.RequiresModifierContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitRequiresModifier(JavaParser.RequiresModifierContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterRecordDeclaration(JavaParser.RecordDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitRecordDeclaration(JavaParser.RecordDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterRecordHeader(JavaParser.RecordHeaderContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitRecordHeader(JavaParser.RecordHeaderContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterRecordComponentList(JavaParser.RecordComponentListContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitRecordComponentList(JavaParser.RecordComponentListContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterRecordComponent(JavaParser.RecordComponentContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitRecordComponent(JavaParser.RecordComponentContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterRecordBody(JavaParser.RecordBodyContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitRecordBody(JavaParser.RecordBodyContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterBlock(JavaParser.BlockContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitBlock(JavaParser.BlockContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterBlockStatement(JavaParser.BlockStatementContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitBlockStatement(JavaParser.BlockStatementContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterLocalVariableDeclaration(JavaParser.LocalVariableDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitLocalVariableDeclaration(JavaParser.LocalVariableDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterIdentifier(JavaParser.IdentifierContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitIdentifier(JavaParser.IdentifierContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterTypeIdentifier(JavaParser.TypeIdentifierContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitTypeIdentifier(JavaParser.TypeIdentifierContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterLocalTypeDeclaration(JavaParser.LocalTypeDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitLocalTypeDeclaration(JavaParser.LocalTypeDeclarationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterStatement(JavaParser.StatementContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitStatement(JavaParser.StatementContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterCatchClause(JavaParser.CatchClauseContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitCatchClause(JavaParser.CatchClauseContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterCatchType(JavaParser.CatchTypeContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitCatchType(JavaParser.CatchTypeContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterFinallyBlock(JavaParser.FinallyBlockContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitFinallyBlock(JavaParser.FinallyBlockContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterResourceSpecification(JavaParser.ResourceSpecificationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitResourceSpecification(JavaParser.ResourceSpecificationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterResources(JavaParser.ResourcesContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitResources(JavaParser.ResourcesContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterResource(JavaParser.ResourceContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitResource(JavaParser.ResourceContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterSwitchBlockStatementGroup(JavaParser.SwitchBlockStatementGroupContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitSwitchBlockStatementGroup(JavaParser.SwitchBlockStatementGroupContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterSwitchLabel(JavaParser.SwitchLabelContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitSwitchLabel(JavaParser.SwitchLabelContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterForControl(JavaParser.ForControlContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitForControl(JavaParser.ForControlContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterForInit(JavaParser.ForInitContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitForInit(JavaParser.ForInitContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterEnhancedForControl(JavaParser.EnhancedForControlContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitEnhancedForControl(JavaParser.EnhancedForControlContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterParExpression(JavaParser.ParExpressionContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitParExpression(JavaParser.ParExpressionContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterExpressionList(JavaParser.ExpressionListContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitExpressionList(JavaParser.ExpressionListContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterMethodCall(JavaParser.MethodCallContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitMethodCall(JavaParser.MethodCallContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterExpression(JavaParser.ExpressionContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitExpression(JavaParser.ExpressionContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterPattern(JavaParser.PatternContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitPattern(JavaParser.PatternContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterLambdaExpression(JavaParser.LambdaExpressionContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitLambdaExpression(JavaParser.LambdaExpressionContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterLambdaParameters(JavaParser.LambdaParametersContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitLambdaParameters(JavaParser.LambdaParametersContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterLambdaBody(JavaParser.LambdaBodyContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitLambdaBody(JavaParser.LambdaBodyContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterPrimary(JavaParser.PrimaryContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitPrimary(JavaParser.PrimaryContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterSwitchExpression(JavaParser.SwitchExpressionContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitSwitchExpression(JavaParser.SwitchExpressionContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterSwitchLabeledRule(JavaParser.SwitchLabeledRuleContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitSwitchLabeledRule(JavaParser.SwitchLabeledRuleContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterGuardedPattern(JavaParser.GuardedPatternContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitGuardedPattern(JavaParser.GuardedPatternContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterSwitchRuleOutcome(JavaParser.SwitchRuleOutcomeContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitSwitchRuleOutcome(JavaParser.SwitchRuleOutcomeContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterClassType(JavaParser.ClassTypeContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitClassType(JavaParser.ClassTypeContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterCreator(JavaParser.CreatorContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitCreator(JavaParser.CreatorContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterCreatedName(JavaParser.CreatedNameContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitCreatedName(JavaParser.CreatedNameContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterInnerCreator(JavaParser.InnerCreatorContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitInnerCreator(JavaParser.InnerCreatorContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterArrayCreatorRest(JavaParser.ArrayCreatorRestContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitArrayCreatorRest(JavaParser.ArrayCreatorRestContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterClassCreatorRest(JavaParser.ClassCreatorRestContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitClassCreatorRest(JavaParser.ClassCreatorRestContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterExplicitGenericInvocation(JavaParser.ExplicitGenericInvocationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitExplicitGenericInvocation(JavaParser.ExplicitGenericInvocationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterTypeArgumentsOrDiamond(JavaParser.TypeArgumentsOrDiamondContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitTypeArgumentsOrDiamond(JavaParser.TypeArgumentsOrDiamondContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterNonWildcardTypeArgumentsOrDiamond(JavaParser.NonWildcardTypeArgumentsOrDiamondContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitNonWildcardTypeArgumentsOrDiamond(JavaParser.NonWildcardTypeArgumentsOrDiamondContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterNonWildcardTypeArguments(JavaParser.NonWildcardTypeArgumentsContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitNonWildcardTypeArguments(JavaParser.NonWildcardTypeArgumentsContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterTypeList(JavaParser.TypeListContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitTypeList(JavaParser.TypeListContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterTypeType(JavaParser.TypeTypeContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitTypeType(JavaParser.TypeTypeContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterPrimitiveType(JavaParser.PrimitiveTypeContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitPrimitiveType(JavaParser.PrimitiveTypeContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterTypeArguments(JavaParser.TypeArgumentsContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitTypeArguments(JavaParser.TypeArgumentsContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterSuperSuffix(JavaParser.SuperSuffixContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitSuperSuffix(JavaParser.SuperSuffixContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterExplicitGenericInvocationSuffix(JavaParser.ExplicitGenericInvocationSuffixContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitExplicitGenericInvocationSuffix(JavaParser.ExplicitGenericInvocationSuffixContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterArguments(JavaParser.ArgumentsContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitArguments(JavaParser.ArgumentsContext ctx) {} + + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterEveryRule(ParserRuleContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitEveryRule(ParserRuleContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void visitTerminal(TerminalNode node) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void visitErrorNode(ErrorNode node) {} +} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavaParserListener.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavaParserListener.java new file mode 100644 index 000000000000..9f1d383cd74d --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavaParserListener.java @@ -0,0 +1,1286 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor.antlr.generated; + +import org.antlr.v4.runtime.tree.ParseTreeListener; + +/** + * This interface defines a complete listener for a parse tree produced by + * {@link JavaParser}. + */ +public interface JavaParserListener extends ParseTreeListener { + /** + * Enter a parse tree produced by {@link JavaParser#compilationUnit}. + * @param ctx the parse tree + */ + void enterCompilationUnit(JavaParser.CompilationUnitContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#compilationUnit}. + * @param ctx the parse tree + */ + void exitCompilationUnit(JavaParser.CompilationUnitContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#packageDeclaration}. + * @param ctx the parse tree + */ + void enterPackageDeclaration(JavaParser.PackageDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#packageDeclaration}. + * @param ctx the parse tree + */ + void exitPackageDeclaration(JavaParser.PackageDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#importDeclaration}. + * @param ctx the parse tree + */ + void enterImportDeclaration(JavaParser.ImportDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#importDeclaration}. + * @param ctx the parse tree + */ + void exitImportDeclaration(JavaParser.ImportDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#typeDeclaration}. + * @param ctx the parse tree + */ + void enterTypeDeclaration(JavaParser.TypeDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#typeDeclaration}. + * @param ctx the parse tree + */ + void exitTypeDeclaration(JavaParser.TypeDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#modifier}. + * @param ctx the parse tree + */ + void enterModifier(JavaParser.ModifierContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#modifier}. + * @param ctx the parse tree + */ + void exitModifier(JavaParser.ModifierContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#classOrInterfaceModifier}. + * @param ctx the parse tree + */ + void enterClassOrInterfaceModifier(JavaParser.ClassOrInterfaceModifierContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#classOrInterfaceModifier}. + * @param ctx the parse tree + */ + void exitClassOrInterfaceModifier(JavaParser.ClassOrInterfaceModifierContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#variableModifier}. + * @param ctx the parse tree + */ + void enterVariableModifier(JavaParser.VariableModifierContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#variableModifier}. + * @param ctx the parse tree + */ + void exitVariableModifier(JavaParser.VariableModifierContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#classDeclaration}. + * @param ctx the parse tree + */ + void enterClassDeclaration(JavaParser.ClassDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#classDeclaration}. + * @param ctx the parse tree + */ + void exitClassDeclaration(JavaParser.ClassDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#typeParameters}. + * @param ctx the parse tree + */ + void enterTypeParameters(JavaParser.TypeParametersContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#typeParameters}. + * @param ctx the parse tree + */ + void exitTypeParameters(JavaParser.TypeParametersContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#typeParameter}. + * @param ctx the parse tree + */ + void enterTypeParameter(JavaParser.TypeParameterContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#typeParameter}. + * @param ctx the parse tree + */ + void exitTypeParameter(JavaParser.TypeParameterContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#typeBound}. + * @param ctx the parse tree + */ + void enterTypeBound(JavaParser.TypeBoundContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#typeBound}. + * @param ctx the parse tree + */ + void exitTypeBound(JavaParser.TypeBoundContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#enumDeclaration}. + * @param ctx the parse tree + */ + void enterEnumDeclaration(JavaParser.EnumDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#enumDeclaration}. + * @param ctx the parse tree + */ + void exitEnumDeclaration(JavaParser.EnumDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#enumConstants}. + * @param ctx the parse tree + */ + void enterEnumConstants(JavaParser.EnumConstantsContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#enumConstants}. + * @param ctx the parse tree + */ + void exitEnumConstants(JavaParser.EnumConstantsContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#enumConstant}. + * @param ctx the parse tree + */ + void enterEnumConstant(JavaParser.EnumConstantContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#enumConstant}. + * @param ctx the parse tree + */ + void exitEnumConstant(JavaParser.EnumConstantContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#enumBodyDeclarations}. + * @param ctx the parse tree + */ + void enterEnumBodyDeclarations(JavaParser.EnumBodyDeclarationsContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#enumBodyDeclarations}. + * @param ctx the parse tree + */ + void exitEnumBodyDeclarations(JavaParser.EnumBodyDeclarationsContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#interfaceDeclaration}. + * @param ctx the parse tree + */ + void enterInterfaceDeclaration(JavaParser.InterfaceDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#interfaceDeclaration}. + * @param ctx the parse tree + */ + void exitInterfaceDeclaration(JavaParser.InterfaceDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#classBody}. + * @param ctx the parse tree + */ + void enterClassBody(JavaParser.ClassBodyContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#classBody}. + * @param ctx the parse tree + */ + void exitClassBody(JavaParser.ClassBodyContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#interfaceBody}. + * @param ctx the parse tree + */ + void enterInterfaceBody(JavaParser.InterfaceBodyContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#interfaceBody}. + * @param ctx the parse tree + */ + void exitInterfaceBody(JavaParser.InterfaceBodyContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#classBodyDeclaration}. + * @param ctx the parse tree + */ + void enterClassBodyDeclaration(JavaParser.ClassBodyDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#classBodyDeclaration}. + * @param ctx the parse tree + */ + void exitClassBodyDeclaration(JavaParser.ClassBodyDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#memberDeclaration}. + * @param ctx the parse tree + */ + void enterMemberDeclaration(JavaParser.MemberDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#memberDeclaration}. + * @param ctx the parse tree + */ + void exitMemberDeclaration(JavaParser.MemberDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#methodDeclaration}. + * @param ctx the parse tree + */ + void enterMethodDeclaration(JavaParser.MethodDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#methodDeclaration}. + * @param ctx the parse tree + */ + void exitMethodDeclaration(JavaParser.MethodDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#methodBody}. + * @param ctx the parse tree + */ + void enterMethodBody(JavaParser.MethodBodyContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#methodBody}. + * @param ctx the parse tree + */ + void exitMethodBody(JavaParser.MethodBodyContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#typeTypeOrVoid}. + * @param ctx the parse tree + */ + void enterTypeTypeOrVoid(JavaParser.TypeTypeOrVoidContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#typeTypeOrVoid}. + * @param ctx the parse tree + */ + void exitTypeTypeOrVoid(JavaParser.TypeTypeOrVoidContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#genericMethodDeclaration}. + * @param ctx the parse tree + */ + void enterGenericMethodDeclaration(JavaParser.GenericMethodDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#genericMethodDeclaration}. + * @param ctx the parse tree + */ + void exitGenericMethodDeclaration(JavaParser.GenericMethodDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#genericConstructorDeclaration}. + * @param ctx the parse tree + */ + void enterGenericConstructorDeclaration(JavaParser.GenericConstructorDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#genericConstructorDeclaration}. + * @param ctx the parse tree + */ + void exitGenericConstructorDeclaration(JavaParser.GenericConstructorDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#constructorDeclaration}. + * @param ctx the parse tree + */ + void enterConstructorDeclaration(JavaParser.ConstructorDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#constructorDeclaration}. + * @param ctx the parse tree + */ + void exitConstructorDeclaration(JavaParser.ConstructorDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#compactConstructorDeclaration}. + * @param ctx the parse tree + */ + void enterCompactConstructorDeclaration(JavaParser.CompactConstructorDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#compactConstructorDeclaration}. + * @param ctx the parse tree + */ + void exitCompactConstructorDeclaration(JavaParser.CompactConstructorDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#fieldDeclaration}. + * @param ctx the parse tree + */ + void enterFieldDeclaration(JavaParser.FieldDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#fieldDeclaration}. + * @param ctx the parse tree + */ + void exitFieldDeclaration(JavaParser.FieldDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#interfaceBodyDeclaration}. + * @param ctx the parse tree + */ + void enterInterfaceBodyDeclaration(JavaParser.InterfaceBodyDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#interfaceBodyDeclaration}. + * @param ctx the parse tree + */ + void exitInterfaceBodyDeclaration(JavaParser.InterfaceBodyDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#interfaceMemberDeclaration}. + * @param ctx the parse tree + */ + void enterInterfaceMemberDeclaration(JavaParser.InterfaceMemberDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#interfaceMemberDeclaration}. + * @param ctx the parse tree + */ + void exitInterfaceMemberDeclaration(JavaParser.InterfaceMemberDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#constDeclaration}. + * @param ctx the parse tree + */ + void enterConstDeclaration(JavaParser.ConstDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#constDeclaration}. + * @param ctx the parse tree + */ + void exitConstDeclaration(JavaParser.ConstDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#constantDeclarator}. + * @param ctx the parse tree + */ + void enterConstantDeclarator(JavaParser.ConstantDeclaratorContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#constantDeclarator}. + * @param ctx the parse tree + */ + void exitConstantDeclarator(JavaParser.ConstantDeclaratorContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#interfaceMethodDeclaration}. + * @param ctx the parse tree + */ + void enterInterfaceMethodDeclaration(JavaParser.InterfaceMethodDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#interfaceMethodDeclaration}. + * @param ctx the parse tree + */ + void exitInterfaceMethodDeclaration(JavaParser.InterfaceMethodDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#interfaceMethodModifier}. + * @param ctx the parse tree + */ + void enterInterfaceMethodModifier(JavaParser.InterfaceMethodModifierContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#interfaceMethodModifier}. + * @param ctx the parse tree + */ + void exitInterfaceMethodModifier(JavaParser.InterfaceMethodModifierContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#genericInterfaceMethodDeclaration}. + * @param ctx the parse tree + */ + void enterGenericInterfaceMethodDeclaration(JavaParser.GenericInterfaceMethodDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#genericInterfaceMethodDeclaration}. + * @param ctx the parse tree + */ + void exitGenericInterfaceMethodDeclaration(JavaParser.GenericInterfaceMethodDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#interfaceCommonBodyDeclaration}. + * @param ctx the parse tree + */ + void enterInterfaceCommonBodyDeclaration(JavaParser.InterfaceCommonBodyDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#interfaceCommonBodyDeclaration}. + * @param ctx the parse tree + */ + void exitInterfaceCommonBodyDeclaration(JavaParser.InterfaceCommonBodyDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#variableDeclarators}. + * @param ctx the parse tree + */ + void enterVariableDeclarators(JavaParser.VariableDeclaratorsContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#variableDeclarators}. + * @param ctx the parse tree + */ + void exitVariableDeclarators(JavaParser.VariableDeclaratorsContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#variableDeclarator}. + * @param ctx the parse tree + */ + void enterVariableDeclarator(JavaParser.VariableDeclaratorContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#variableDeclarator}. + * @param ctx the parse tree + */ + void exitVariableDeclarator(JavaParser.VariableDeclaratorContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#variableDeclaratorId}. + * @param ctx the parse tree + */ + void enterVariableDeclaratorId(JavaParser.VariableDeclaratorIdContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#variableDeclaratorId}. + * @param ctx the parse tree + */ + void exitVariableDeclaratorId(JavaParser.VariableDeclaratorIdContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#variableInitializer}. + * @param ctx the parse tree + */ + void enterVariableInitializer(JavaParser.VariableInitializerContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#variableInitializer}. + * @param ctx the parse tree + */ + void exitVariableInitializer(JavaParser.VariableInitializerContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#arrayInitializer}. + * @param ctx the parse tree + */ + void enterArrayInitializer(JavaParser.ArrayInitializerContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#arrayInitializer}. + * @param ctx the parse tree + */ + void exitArrayInitializer(JavaParser.ArrayInitializerContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#classOrInterfaceType}. + * @param ctx the parse tree + */ + void enterClassOrInterfaceType(JavaParser.ClassOrInterfaceTypeContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#classOrInterfaceType}. + * @param ctx the parse tree + */ + void exitClassOrInterfaceType(JavaParser.ClassOrInterfaceTypeContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#typeArgument}. + * @param ctx the parse tree + */ + void enterTypeArgument(JavaParser.TypeArgumentContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#typeArgument}. + * @param ctx the parse tree + */ + void exitTypeArgument(JavaParser.TypeArgumentContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#qualifiedNameList}. + * @param ctx the parse tree + */ + void enterQualifiedNameList(JavaParser.QualifiedNameListContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#qualifiedNameList}. + * @param ctx the parse tree + */ + void exitQualifiedNameList(JavaParser.QualifiedNameListContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#formalParameters}. + * @param ctx the parse tree + */ + void enterFormalParameters(JavaParser.FormalParametersContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#formalParameters}. + * @param ctx the parse tree + */ + void exitFormalParameters(JavaParser.FormalParametersContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#receiverParameter}. + * @param ctx the parse tree + */ + void enterReceiverParameter(JavaParser.ReceiverParameterContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#receiverParameter}. + * @param ctx the parse tree + */ + void exitReceiverParameter(JavaParser.ReceiverParameterContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#formalParameterList}. + * @param ctx the parse tree + */ + void enterFormalParameterList(JavaParser.FormalParameterListContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#formalParameterList}. + * @param ctx the parse tree + */ + void exitFormalParameterList(JavaParser.FormalParameterListContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#formalParameter}. + * @param ctx the parse tree + */ + void enterFormalParameter(JavaParser.FormalParameterContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#formalParameter}. + * @param ctx the parse tree + */ + void exitFormalParameter(JavaParser.FormalParameterContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#lastFormalParameter}. + * @param ctx the parse tree + */ + void enterLastFormalParameter(JavaParser.LastFormalParameterContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#lastFormalParameter}. + * @param ctx the parse tree + */ + void exitLastFormalParameter(JavaParser.LastFormalParameterContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#lambdaLVTIList}. + * @param ctx the parse tree + */ + void enterLambdaLVTIList(JavaParser.LambdaLVTIListContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#lambdaLVTIList}. + * @param ctx the parse tree + */ + void exitLambdaLVTIList(JavaParser.LambdaLVTIListContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#lambdaLVTIParameter}. + * @param ctx the parse tree + */ + void enterLambdaLVTIParameter(JavaParser.LambdaLVTIParameterContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#lambdaLVTIParameter}. + * @param ctx the parse tree + */ + void exitLambdaLVTIParameter(JavaParser.LambdaLVTIParameterContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#qualifiedName}. + * @param ctx the parse tree + */ + void enterQualifiedName(JavaParser.QualifiedNameContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#qualifiedName}. + * @param ctx the parse tree + */ + void exitQualifiedName(JavaParser.QualifiedNameContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#literal}. + * @param ctx the parse tree + */ + void enterLiteral(JavaParser.LiteralContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#literal}. + * @param ctx the parse tree + */ + void exitLiteral(JavaParser.LiteralContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#integerLiteral}. + * @param ctx the parse tree + */ + void enterIntegerLiteral(JavaParser.IntegerLiteralContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#integerLiteral}. + * @param ctx the parse tree + */ + void exitIntegerLiteral(JavaParser.IntegerLiteralContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#floatLiteral}. + * @param ctx the parse tree + */ + void enterFloatLiteral(JavaParser.FloatLiteralContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#floatLiteral}. + * @param ctx the parse tree + */ + void exitFloatLiteral(JavaParser.FloatLiteralContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#altAnnotationQualifiedName}. + * @param ctx the parse tree + */ + void enterAltAnnotationQualifiedName(JavaParser.AltAnnotationQualifiedNameContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#altAnnotationQualifiedName}. + * @param ctx the parse tree + */ + void exitAltAnnotationQualifiedName(JavaParser.AltAnnotationQualifiedNameContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#annotation}. + * @param ctx the parse tree + */ + void enterAnnotation(JavaParser.AnnotationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#annotation}. + * @param ctx the parse tree + */ + void exitAnnotation(JavaParser.AnnotationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#elementValuePairs}. + * @param ctx the parse tree + */ + void enterElementValuePairs(JavaParser.ElementValuePairsContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#elementValuePairs}. + * @param ctx the parse tree + */ + void exitElementValuePairs(JavaParser.ElementValuePairsContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#elementValuePair}. + * @param ctx the parse tree + */ + void enterElementValuePair(JavaParser.ElementValuePairContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#elementValuePair}. + * @param ctx the parse tree + */ + void exitElementValuePair(JavaParser.ElementValuePairContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#elementValue}. + * @param ctx the parse tree + */ + void enterElementValue(JavaParser.ElementValueContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#elementValue}. + * @param ctx the parse tree + */ + void exitElementValue(JavaParser.ElementValueContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#elementValueArrayInitializer}. + * @param ctx the parse tree + */ + void enterElementValueArrayInitializer(JavaParser.ElementValueArrayInitializerContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#elementValueArrayInitializer}. + * @param ctx the parse tree + */ + void exitElementValueArrayInitializer(JavaParser.ElementValueArrayInitializerContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#annotationTypeDeclaration}. + * @param ctx the parse tree + */ + void enterAnnotationTypeDeclaration(JavaParser.AnnotationTypeDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#annotationTypeDeclaration}. + * @param ctx the parse tree + */ + void exitAnnotationTypeDeclaration(JavaParser.AnnotationTypeDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#annotationTypeBody}. + * @param ctx the parse tree + */ + void enterAnnotationTypeBody(JavaParser.AnnotationTypeBodyContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#annotationTypeBody}. + * @param ctx the parse tree + */ + void exitAnnotationTypeBody(JavaParser.AnnotationTypeBodyContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#annotationTypeElementDeclaration}. + * @param ctx the parse tree + */ + void enterAnnotationTypeElementDeclaration(JavaParser.AnnotationTypeElementDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#annotationTypeElementDeclaration}. + * @param ctx the parse tree + */ + void exitAnnotationTypeElementDeclaration(JavaParser.AnnotationTypeElementDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#annotationTypeElementRest}. + * @param ctx the parse tree + */ + void enterAnnotationTypeElementRest(JavaParser.AnnotationTypeElementRestContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#annotationTypeElementRest}. + * @param ctx the parse tree + */ + void exitAnnotationTypeElementRest(JavaParser.AnnotationTypeElementRestContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#annotationMethodOrConstantRest}. + * @param ctx the parse tree + */ + void enterAnnotationMethodOrConstantRest(JavaParser.AnnotationMethodOrConstantRestContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#annotationMethodOrConstantRest}. + * @param ctx the parse tree + */ + void exitAnnotationMethodOrConstantRest(JavaParser.AnnotationMethodOrConstantRestContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#annotationMethodRest}. + * @param ctx the parse tree + */ + void enterAnnotationMethodRest(JavaParser.AnnotationMethodRestContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#annotationMethodRest}. + * @param ctx the parse tree + */ + void exitAnnotationMethodRest(JavaParser.AnnotationMethodRestContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#annotationConstantRest}. + * @param ctx the parse tree + */ + void enterAnnotationConstantRest(JavaParser.AnnotationConstantRestContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#annotationConstantRest}. + * @param ctx the parse tree + */ + void exitAnnotationConstantRest(JavaParser.AnnotationConstantRestContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#defaultValue}. + * @param ctx the parse tree + */ + void enterDefaultValue(JavaParser.DefaultValueContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#defaultValue}. + * @param ctx the parse tree + */ + void exitDefaultValue(JavaParser.DefaultValueContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#moduleDeclaration}. + * @param ctx the parse tree + */ + void enterModuleDeclaration(JavaParser.ModuleDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#moduleDeclaration}. + * @param ctx the parse tree + */ + void exitModuleDeclaration(JavaParser.ModuleDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#moduleBody}. + * @param ctx the parse tree + */ + void enterModuleBody(JavaParser.ModuleBodyContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#moduleBody}. + * @param ctx the parse tree + */ + void exitModuleBody(JavaParser.ModuleBodyContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#moduleDirective}. + * @param ctx the parse tree + */ + void enterModuleDirective(JavaParser.ModuleDirectiveContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#moduleDirective}. + * @param ctx the parse tree + */ + void exitModuleDirective(JavaParser.ModuleDirectiveContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#requiresModifier}. + * @param ctx the parse tree + */ + void enterRequiresModifier(JavaParser.RequiresModifierContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#requiresModifier}. + * @param ctx the parse tree + */ + void exitRequiresModifier(JavaParser.RequiresModifierContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#recordDeclaration}. + * @param ctx the parse tree + */ + void enterRecordDeclaration(JavaParser.RecordDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#recordDeclaration}. + * @param ctx the parse tree + */ + void exitRecordDeclaration(JavaParser.RecordDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#recordHeader}. + * @param ctx the parse tree + */ + void enterRecordHeader(JavaParser.RecordHeaderContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#recordHeader}. + * @param ctx the parse tree + */ + void exitRecordHeader(JavaParser.RecordHeaderContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#recordComponentList}. + * @param ctx the parse tree + */ + void enterRecordComponentList(JavaParser.RecordComponentListContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#recordComponentList}. + * @param ctx the parse tree + */ + void exitRecordComponentList(JavaParser.RecordComponentListContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#recordComponent}. + * @param ctx the parse tree + */ + void enterRecordComponent(JavaParser.RecordComponentContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#recordComponent}. + * @param ctx the parse tree + */ + void exitRecordComponent(JavaParser.RecordComponentContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#recordBody}. + * @param ctx the parse tree + */ + void enterRecordBody(JavaParser.RecordBodyContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#recordBody}. + * @param ctx the parse tree + */ + void exitRecordBody(JavaParser.RecordBodyContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#block}. + * @param ctx the parse tree + */ + void enterBlock(JavaParser.BlockContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#block}. + * @param ctx the parse tree + */ + void exitBlock(JavaParser.BlockContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#blockStatement}. + * @param ctx the parse tree + */ + void enterBlockStatement(JavaParser.BlockStatementContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#blockStatement}. + * @param ctx the parse tree + */ + void exitBlockStatement(JavaParser.BlockStatementContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#localVariableDeclaration}. + * @param ctx the parse tree + */ + void enterLocalVariableDeclaration(JavaParser.LocalVariableDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#localVariableDeclaration}. + * @param ctx the parse tree + */ + void exitLocalVariableDeclaration(JavaParser.LocalVariableDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#identifier}. + * @param ctx the parse tree + */ + void enterIdentifier(JavaParser.IdentifierContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#identifier}. + * @param ctx the parse tree + */ + void exitIdentifier(JavaParser.IdentifierContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#typeIdentifier}. + * @param ctx the parse tree + */ + void enterTypeIdentifier(JavaParser.TypeIdentifierContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#typeIdentifier}. + * @param ctx the parse tree + */ + void exitTypeIdentifier(JavaParser.TypeIdentifierContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#localTypeDeclaration}. + * @param ctx the parse tree + */ + void enterLocalTypeDeclaration(JavaParser.LocalTypeDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#localTypeDeclaration}. + * @param ctx the parse tree + */ + void exitLocalTypeDeclaration(JavaParser.LocalTypeDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#statement}. + * @param ctx the parse tree + */ + void enterStatement(JavaParser.StatementContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#statement}. + * @param ctx the parse tree + */ + void exitStatement(JavaParser.StatementContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#catchClause}. + * @param ctx the parse tree + */ + void enterCatchClause(JavaParser.CatchClauseContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#catchClause}. + * @param ctx the parse tree + */ + void exitCatchClause(JavaParser.CatchClauseContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#catchType}. + * @param ctx the parse tree + */ + void enterCatchType(JavaParser.CatchTypeContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#catchType}. + * @param ctx the parse tree + */ + void exitCatchType(JavaParser.CatchTypeContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#finallyBlock}. + * @param ctx the parse tree + */ + void enterFinallyBlock(JavaParser.FinallyBlockContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#finallyBlock}. + * @param ctx the parse tree + */ + void exitFinallyBlock(JavaParser.FinallyBlockContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#resourceSpecification}. + * @param ctx the parse tree + */ + void enterResourceSpecification(JavaParser.ResourceSpecificationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#resourceSpecification}. + * @param ctx the parse tree + */ + void exitResourceSpecification(JavaParser.ResourceSpecificationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#resources}. + * @param ctx the parse tree + */ + void enterResources(JavaParser.ResourcesContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#resources}. + * @param ctx the parse tree + */ + void exitResources(JavaParser.ResourcesContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#resource}. + * @param ctx the parse tree + */ + void enterResource(JavaParser.ResourceContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#resource}. + * @param ctx the parse tree + */ + void exitResource(JavaParser.ResourceContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#switchBlockStatementGroup}. + * @param ctx the parse tree + */ + void enterSwitchBlockStatementGroup(JavaParser.SwitchBlockStatementGroupContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#switchBlockStatementGroup}. + * @param ctx the parse tree + */ + void exitSwitchBlockStatementGroup(JavaParser.SwitchBlockStatementGroupContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#switchLabel}. + * @param ctx the parse tree + */ + void enterSwitchLabel(JavaParser.SwitchLabelContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#switchLabel}. + * @param ctx the parse tree + */ + void exitSwitchLabel(JavaParser.SwitchLabelContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#forControl}. + * @param ctx the parse tree + */ + void enterForControl(JavaParser.ForControlContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#forControl}. + * @param ctx the parse tree + */ + void exitForControl(JavaParser.ForControlContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#forInit}. + * @param ctx the parse tree + */ + void enterForInit(JavaParser.ForInitContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#forInit}. + * @param ctx the parse tree + */ + void exitForInit(JavaParser.ForInitContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#enhancedForControl}. + * @param ctx the parse tree + */ + void enterEnhancedForControl(JavaParser.EnhancedForControlContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#enhancedForControl}. + * @param ctx the parse tree + */ + void exitEnhancedForControl(JavaParser.EnhancedForControlContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#parExpression}. + * @param ctx the parse tree + */ + void enterParExpression(JavaParser.ParExpressionContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#parExpression}. + * @param ctx the parse tree + */ + void exitParExpression(JavaParser.ParExpressionContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#expressionList}. + * @param ctx the parse tree + */ + void enterExpressionList(JavaParser.ExpressionListContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#expressionList}. + * @param ctx the parse tree + */ + void exitExpressionList(JavaParser.ExpressionListContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#methodCall}. + * @param ctx the parse tree + */ + void enterMethodCall(JavaParser.MethodCallContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#methodCall}. + * @param ctx the parse tree + */ + void exitMethodCall(JavaParser.MethodCallContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#expression}. + * @param ctx the parse tree + */ + void enterExpression(JavaParser.ExpressionContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#expression}. + * @param ctx the parse tree + */ + void exitExpression(JavaParser.ExpressionContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#pattern}. + * @param ctx the parse tree + */ + void enterPattern(JavaParser.PatternContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#pattern}. + * @param ctx the parse tree + */ + void exitPattern(JavaParser.PatternContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#lambdaExpression}. + * @param ctx the parse tree + */ + void enterLambdaExpression(JavaParser.LambdaExpressionContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#lambdaExpression}. + * @param ctx the parse tree + */ + void exitLambdaExpression(JavaParser.LambdaExpressionContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#lambdaParameters}. + * @param ctx the parse tree + */ + void enterLambdaParameters(JavaParser.LambdaParametersContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#lambdaParameters}. + * @param ctx the parse tree + */ + void exitLambdaParameters(JavaParser.LambdaParametersContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#lambdaBody}. + * @param ctx the parse tree + */ + void enterLambdaBody(JavaParser.LambdaBodyContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#lambdaBody}. + * @param ctx the parse tree + */ + void exitLambdaBody(JavaParser.LambdaBodyContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#primary}. + * @param ctx the parse tree + */ + void enterPrimary(JavaParser.PrimaryContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#primary}. + * @param ctx the parse tree + */ + void exitPrimary(JavaParser.PrimaryContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#switchExpression}. + * @param ctx the parse tree + */ + void enterSwitchExpression(JavaParser.SwitchExpressionContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#switchExpression}. + * @param ctx the parse tree + */ + void exitSwitchExpression(JavaParser.SwitchExpressionContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#switchLabeledRule}. + * @param ctx the parse tree + */ + void enterSwitchLabeledRule(JavaParser.SwitchLabeledRuleContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#switchLabeledRule}. + * @param ctx the parse tree + */ + void exitSwitchLabeledRule(JavaParser.SwitchLabeledRuleContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#guardedPattern}. + * @param ctx the parse tree + */ + void enterGuardedPattern(JavaParser.GuardedPatternContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#guardedPattern}. + * @param ctx the parse tree + */ + void exitGuardedPattern(JavaParser.GuardedPatternContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#switchRuleOutcome}. + * @param ctx the parse tree + */ + void enterSwitchRuleOutcome(JavaParser.SwitchRuleOutcomeContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#switchRuleOutcome}. + * @param ctx the parse tree + */ + void exitSwitchRuleOutcome(JavaParser.SwitchRuleOutcomeContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#classType}. + * @param ctx the parse tree + */ + void enterClassType(JavaParser.ClassTypeContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#classType}. + * @param ctx the parse tree + */ + void exitClassType(JavaParser.ClassTypeContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#creator}. + * @param ctx the parse tree + */ + void enterCreator(JavaParser.CreatorContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#creator}. + * @param ctx the parse tree + */ + void exitCreator(JavaParser.CreatorContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#createdName}. + * @param ctx the parse tree + */ + void enterCreatedName(JavaParser.CreatedNameContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#createdName}. + * @param ctx the parse tree + */ + void exitCreatedName(JavaParser.CreatedNameContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#innerCreator}. + * @param ctx the parse tree + */ + void enterInnerCreator(JavaParser.InnerCreatorContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#innerCreator}. + * @param ctx the parse tree + */ + void exitInnerCreator(JavaParser.InnerCreatorContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#arrayCreatorRest}. + * @param ctx the parse tree + */ + void enterArrayCreatorRest(JavaParser.ArrayCreatorRestContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#arrayCreatorRest}. + * @param ctx the parse tree + */ + void exitArrayCreatorRest(JavaParser.ArrayCreatorRestContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#classCreatorRest}. + * @param ctx the parse tree + */ + void enterClassCreatorRest(JavaParser.ClassCreatorRestContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#classCreatorRest}. + * @param ctx the parse tree + */ + void exitClassCreatorRest(JavaParser.ClassCreatorRestContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#explicitGenericInvocation}. + * @param ctx the parse tree + */ + void enterExplicitGenericInvocation(JavaParser.ExplicitGenericInvocationContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#explicitGenericInvocation}. + * @param ctx the parse tree + */ + void exitExplicitGenericInvocation(JavaParser.ExplicitGenericInvocationContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#typeArgumentsOrDiamond}. + * @param ctx the parse tree + */ + void enterTypeArgumentsOrDiamond(JavaParser.TypeArgumentsOrDiamondContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#typeArgumentsOrDiamond}. + * @param ctx the parse tree + */ + void exitTypeArgumentsOrDiamond(JavaParser.TypeArgumentsOrDiamondContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#nonWildcardTypeArgumentsOrDiamond}. + * @param ctx the parse tree + */ + void enterNonWildcardTypeArgumentsOrDiamond(JavaParser.NonWildcardTypeArgumentsOrDiamondContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#nonWildcardTypeArgumentsOrDiamond}. + * @param ctx the parse tree + */ + void exitNonWildcardTypeArgumentsOrDiamond(JavaParser.NonWildcardTypeArgumentsOrDiamondContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#nonWildcardTypeArguments}. + * @param ctx the parse tree + */ + void enterNonWildcardTypeArguments(JavaParser.NonWildcardTypeArgumentsContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#nonWildcardTypeArguments}. + * @param ctx the parse tree + */ + void exitNonWildcardTypeArguments(JavaParser.NonWildcardTypeArgumentsContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#typeList}. + * @param ctx the parse tree + */ + void enterTypeList(JavaParser.TypeListContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#typeList}. + * @param ctx the parse tree + */ + void exitTypeList(JavaParser.TypeListContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#typeType}. + * @param ctx the parse tree + */ + void enterTypeType(JavaParser.TypeTypeContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#typeType}. + * @param ctx the parse tree + */ + void exitTypeType(JavaParser.TypeTypeContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#primitiveType}. + * @param ctx the parse tree + */ + void enterPrimitiveType(JavaParser.PrimitiveTypeContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#primitiveType}. + * @param ctx the parse tree + */ + void exitPrimitiveType(JavaParser.PrimitiveTypeContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#typeArguments}. + * @param ctx the parse tree + */ + void enterTypeArguments(JavaParser.TypeArgumentsContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#typeArguments}. + * @param ctx the parse tree + */ + void exitTypeArguments(JavaParser.TypeArgumentsContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#superSuffix}. + * @param ctx the parse tree + */ + void enterSuperSuffix(JavaParser.SuperSuffixContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#superSuffix}. + * @param ctx the parse tree + */ + void exitSuperSuffix(JavaParser.SuperSuffixContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#explicitGenericInvocationSuffix}. + * @param ctx the parse tree + */ + void enterExplicitGenericInvocationSuffix(JavaParser.ExplicitGenericInvocationSuffixContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#explicitGenericInvocationSuffix}. + * @param ctx the parse tree + */ + void exitExplicitGenericInvocationSuffix(JavaParser.ExplicitGenericInvocationSuffixContext ctx); + /** + * Enter a parse tree produced by {@link JavaParser#arguments}. + * @param ctx the parse tree + */ + void enterArguments(JavaParser.ArgumentsContext ctx); + /** + * Exit a parse tree produced by {@link JavaParser#arguments}. + * @param ctx the parse tree + */ + void exitArguments(JavaParser.ArgumentsContext ctx); +} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavadocLexer.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavadocLexer.java new file mode 100644 index 000000000000..dfe9ced6f667 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavadocLexer.java @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor.antlr.generated; + +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.misc.*; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue", "this-escape"}) +public class JavadocLexer extends Lexer { + static { + RuntimeMetaData.checkVersion("4.13.1", RuntimeMetaData.VERSION); + } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache(); + public static final int NAME = 1, + NEWLINE = 2, + SPACE = 3, + TEXT_CONTENT = 4, + AT = 5, + STAR = 6, + SLASH = 7, + JAVADOC_START = 8, + JAVADOC_END = 9, + INLINE_TAG_START = 10, + BRACE_OPEN = 11, + BRACE_CLOSE = 12; + public static String[] channelNames = {"DEFAULT_TOKEN_CHANNEL", "HIDDEN"}; + + public static String[] modeNames = {"DEFAULT_MODE"}; + + private static String[] makeRuleNames() { + return new String[] { + "NAME", + "NEWLINE", + "SPACE", + "TEXT_CONTENT", + "AT", + "STAR", + "SLASH", + "JAVADOC_START", + "JAVADOC_END", + "INLINE_TAG_START", + "BRACE_OPEN", + "BRACE_CLOSE" + }; + } + + public static final String[] ruleNames = makeRuleNames(); + + private static String[] makeLiteralNames() { + return new String[] {null, null, null, null, null, "'@'", "'*'", "'/'", null, null, "'{@'", "'{'", "'}'"}; + } + + private static final String[] _LITERAL_NAMES = makeLiteralNames(); + + private static String[] makeSymbolicNames() { + return new String[] { + null, + "NAME", + "NEWLINE", + "SPACE", + "TEXT_CONTENT", + "AT", + "STAR", + "SLASH", + "JAVADOC_START", + "JAVADOC_END", + "INLINE_TAG_START", + "BRACE_OPEN", + "BRACE_CLOSE" + }; + } + + private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + public JavadocLexer(CharStream input) { + super(input); + _interp = new LexerATNSimulator(this, _ATN, _decisionToDFA, _sharedContextCache); + } + + @Override + public String getGrammarFileName() { + return "JavadocLexer.g4"; + } + + @Override + public String[] getRuleNames() { + return ruleNames; + } + + @Override + public String getSerializedATN() { + return _serializedATN; + } + + @Override + public String[] getChannelNames() { + return channelNames; + } + + @Override + public String[] getModeNames() { + return modeNames; + } + + @Override + public ATN getATN() { + return _ATN; + } + + @Override + public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { + switch (ruleIndex) { + case 1: + return NEWLINE_sempred((RuleContext) _localctx, predIndex); + } + return true; + } + + private boolean NEWLINE_sempred(RuleContext _localctx, int predIndex) { + switch (predIndex) { + case 0: + return _input.LA(1) != '/'; + case 1: + return _input.LA(1) != '/'; + case 2: + return _input.LA(1) != '/'; + } + return true; + } + + public static final String _serializedATN = "\u0004\u0000\fv\u0006\uffff\uffff\u0002\u0000\u0007\u0000\u0002\u0001" + + "\u0007\u0001\u0002\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004" + + "\u0007\u0004\u0002\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007" + + "\u0007\u0007\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b" + + "\u0007\u000b\u0001\u0000\u0004\u0000\u001b\b\u0000\u000b\u0000\f\u0000" + + "\u001c\u0001\u0001\u0001\u0001\u0003\u0001!\b\u0001\u0001\u0001\u0001" + + "\u0001\u0001\u0001\u0004\u0001&\b\u0001\u000b\u0001\f\u0001\'\u0003\u0001" + + "*\b\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0001" + + "0\b\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0004\u00015\b\u0001\u000b" + + "\u0001\f\u00016\u0003\u00019\b\u0001\u0001\u0001\u0001\u0001\u0003\u0001" + + "=\b\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0004\u0001B\b\u0001\u000b" + + "\u0001\f\u0001C\u0003\u0001F\b\u0001\u0003\u0001H\b\u0001\u0001\u0002" + + "\u0004\u0002K\b\u0002\u000b\u0002\f\u0002L\u0001\u0003\u0004\u0003P\b" + + "\u0003\u000b\u0003\f\u0003Q\u0001\u0004\u0001\u0004\u0001\u0005\u0001" + + "\u0005\u0001\u0006\u0001\u0006\u0001\u0007\u0001\u0007\u0001\u0007\u0001" + + "\u0007\u0001\u0007\u0005\u0007_\b\u0007\n\u0007\f\u0007b\t\u0007\u0001" + + "\b\u0003\be\b\b\u0001\b\u0005\bh\b\b\n\b\f\bk\t\b\u0001\b\u0001\b\u0001" + + "\b\u0001\t\u0001\t\u0001\t\u0001\n\u0001\n\u0001\u000b\u0001\u000b\u0000" + + "\u0000\f\u0001\u0001\u0003\u0002\u0005\u0003\u0007\u0004\t\u0005\u000b" + + "\u0006\r\u0007\u000f\b\u0011\t\u0013\n\u0015\u000b\u0017\f\u0001\u0000" + + "\u0003\u0002\u0000AZaz\u0002\u0000\t\t \b\u0000\t\n\r\r **//@Za{}}\u0086" + + "\u0000\u0001\u0001\u0000\u0000\u0000\u0000\u0003\u0001\u0000\u0000\u0000" + + "\u0000\u0005\u0001\u0000\u0000\u0000\u0000\u0007\u0001\u0000\u0000\u0000" + + "\u0000\t\u0001\u0000\u0000\u0000\u0000\u000b\u0001\u0000\u0000\u0000\u0000" + + "\r\u0001\u0000\u0000\u0000\u0000\u000f\u0001\u0000\u0000\u0000\u0000\u0011" + + "\u0001\u0000\u0000\u0000\u0000\u0013\u0001\u0000\u0000\u0000\u0000\u0015" + + "\u0001\u0000\u0000\u0000\u0000\u0017\u0001\u0000\u0000\u0000\u0001\u001a" + + "\u0001\u0000\u0000\u0000\u0003G\u0001\u0000\u0000\u0000\u0005J\u0001\u0000" + + "\u0000\u0000\u0007O\u0001\u0000\u0000\u0000\tS\u0001\u0000\u0000\u0000" + + "\u000bU\u0001\u0000\u0000\u0000\rW\u0001\u0000\u0000\u0000\u000fY\u0001" + + "\u0000\u0000\u0000\u0011d\u0001\u0000\u0000\u0000\u0013o\u0001\u0000\u0000" + + "\u0000\u0015r\u0001\u0000\u0000\u0000\u0017t\u0001\u0000\u0000\u0000\u0019" + + "\u001b\u0007\u0000\u0000\u0000\u001a\u0019\u0001\u0000\u0000\u0000\u001b" + + "\u001c\u0001\u0000\u0000\u0000\u001c\u001a\u0001\u0000\u0000\u0000\u001c" + + "\u001d\u0001\u0000\u0000\u0000\u001d\u0002\u0001\u0000\u0000\u0000\u001e" + + ")\u0005\n\u0000\u0000\u001f!\u0003\u0005\u0002\u0000 \u001f\u0001\u0000" + + "\u0000\u0000 !\u0001\u0000\u0000\u0000!%\u0001\u0000\u0000\u0000\"#\u0003" + + "\u000b\u0005\u0000#$\u0004\u0001\u0000\u0000$&\u0001\u0000\u0000\u0000" + + "%\"\u0001\u0000\u0000\u0000&\'\u0001\u0000\u0000\u0000\'%\u0001\u0000" + + "\u0000\u0000\'(\u0001\u0000\u0000\u0000(*\u0001\u0000\u0000\u0000) \u0001" + + "\u0000\u0000\u0000)*\u0001\u0000\u0000\u0000*H\u0001\u0000\u0000\u0000" + + "+,\u0005\r\u0000\u0000,-\u0005\n\u0000\u0000-8\u0001\u0000\u0000\u0000" + + ".0\u0003\u0005\u0002\u0000/.\u0001\u0000\u0000\u0000/0\u0001\u0000\u0000" + + "\u000004\u0001\u0000\u0000\u000012\u0003\u000b\u0005\u000023\u0004\u0001" + + "\u0001\u000035\u0001\u0000\u0000\u000041\u0001\u0000\u0000\u000056\u0001" + + "\u0000\u0000\u000064\u0001\u0000\u0000\u000067\u0001\u0000\u0000\u0000" + + "79\u0001\u0000\u0000\u00008/\u0001\u0000\u0000\u000089\u0001\u0000\u0000" + + "\u00009H\u0001\u0000\u0000\u0000:E\u0005\r\u0000\u0000;=\u0003\u0005\u0002" + + "\u0000<;\u0001\u0000\u0000\u0000<=\u0001\u0000\u0000\u0000=A\u0001\u0000" + + "\u0000\u0000>?\u0003\u000b\u0005\u0000?@\u0004\u0001\u0002\u0000@B\u0001" + + "\u0000\u0000\u0000A>\u0001\u0000\u0000\u0000BC\u0001\u0000\u0000\u0000" + + "CA\u0001\u0000\u0000\u0000CD\u0001\u0000\u0000\u0000DF\u0001\u0000\u0000" + + "\u0000E<\u0001\u0000\u0000\u0000EF\u0001\u0000\u0000\u0000FH\u0001\u0000" + + "\u0000\u0000G\u001e\u0001\u0000\u0000\u0000G+\u0001\u0000\u0000\u0000" + + "G:\u0001\u0000\u0000\u0000H\u0004\u0001\u0000\u0000\u0000IK\u0007\u0001" + + "\u0000\u0000JI\u0001\u0000\u0000\u0000KL\u0001\u0000\u0000\u0000LJ\u0001" + + "\u0000\u0000\u0000LM\u0001\u0000\u0000\u0000M\u0006\u0001\u0000\u0000" + + "\u0000NP\b\u0002\u0000\u0000ON\u0001\u0000\u0000\u0000PQ\u0001\u0000\u0000" + + "\u0000QO\u0001\u0000\u0000\u0000QR\u0001\u0000\u0000\u0000R\b\u0001\u0000" + + "\u0000\u0000ST\u0005@\u0000\u0000T\n\u0001\u0000\u0000\u0000UV\u0005*" + + "\u0000\u0000V\f\u0001\u0000\u0000\u0000WX\u0005/\u0000\u0000X\u000e\u0001" + + "\u0000\u0000\u0000YZ\u0005/\u0000\u0000Z[\u0005*\u0000\u0000[\\\u0005" + + "*\u0000\u0000\\`\u0001\u0000\u0000\u0000]_\u0003\u000b\u0005\u0000^]\u0001" + + "\u0000\u0000\u0000_b\u0001\u0000\u0000\u0000`^\u0001\u0000\u0000\u0000" + + "`a\u0001\u0000\u0000\u0000a\u0010\u0001\u0000\u0000\u0000b`\u0001\u0000" + + "\u0000\u0000ce\u0003\u0005\u0002\u0000dc\u0001\u0000\u0000\u0000de\u0001" + + "\u0000\u0000\u0000ei\u0001\u0000\u0000\u0000fh\u0003\u000b\u0005\u0000" + + "gf\u0001\u0000\u0000\u0000hk\u0001\u0000\u0000\u0000ig\u0001\u0000\u0000" + + "\u0000ij\u0001\u0000\u0000\u0000jl\u0001\u0000\u0000\u0000ki\u0001\u0000" + + "\u0000\u0000lm\u0005*\u0000\u0000mn\u0005/\u0000\u0000n\u0012\u0001\u0000" + + "\u0000\u0000op\u0005{\u0000\u0000pq\u0005@\u0000\u0000q\u0014\u0001\u0000" + + "\u0000\u0000rs\u0005{\u0000\u0000s\u0016\u0001\u0000\u0000\u0000tu\u0005" + + "}\u0000\u0000u\u0018\u0001\u0000\u0000\u0000\u0011\u0000\u001c \')/68" + + " skipWhitespace() { + return getRuleContexts(SkipWhitespaceContext.class); + } + + public SkipWhitespaceContext skipWhitespace(int i) { + return getRuleContext(SkipWhitespaceContext.class, i); + } + + public DocumentationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_documentation; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).enterDocumentation(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).exitDocumentation(this); + } + } + + public final DocumentationContext documentation() throws RecognitionException { + DocumentationContext _localctx = new DocumentationContext(_ctx, getState()); + enterRule(_localctx, 0, RULE_documentation); + try { + int _alt; + setState(65); + _errHandler.sync(this); + switch (_input.LA(1)) { + case EOF: + enterOuterAlt(_localctx, 1); + { + setState(44); + match(EOF); + } + break; + case JAVADOC_START: + enterOuterAlt(_localctx, 2); + { + setState(45); + match(JAVADOC_START); + setState(49); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 0, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(46); + skipWhitespace(); + } + } + } + setState(51); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 0, _ctx); + } + setState(52); + documentationContent(); + setState(53); + match(JAVADOC_END); + setState(54); + match(EOF); + } + break; + case NAME: + case NEWLINE: + case SPACE: + case TEXT_CONTENT: + case AT: + case STAR: + case SLASH: + case INLINE_TAG_START: + case BRACE_OPEN: + case BRACE_CLOSE: + enterOuterAlt(_localctx, 3); + { + setState(59); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 1, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(56); + skipWhitespace(); + } + } + } + setState(61); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 1, _ctx); + } + setState(62); + documentationContent(); + setState(63); + match(EOF); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class DocumentationContentContext extends ParserRuleContext { + public DescriptionContext description() { + return getRuleContext(DescriptionContext.class, 0); + } + + public List skipWhitespace() { + return getRuleContexts(SkipWhitespaceContext.class); + } + + public SkipWhitespaceContext skipWhitespace(int i) { + return getRuleContext(SkipWhitespaceContext.class, i); + } + + public TagSectionContext tagSection() { + return getRuleContext(TagSectionContext.class, 0); + } + + public List NEWLINE() { + return getTokens(JavadocParser.NEWLINE); + } + + public TerminalNode NEWLINE(int i) { + return getToken(JavadocParser.NEWLINE, i); + } + + public DocumentationContentContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_documentationContent; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).enterDocumentationContent(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).exitDocumentationContent(this); + } + } + + public final DocumentationContentContext documentationContent() throws RecognitionException { + DocumentationContentContext _localctx = new DocumentationContentContext(_ctx, getState()); + enterRule(_localctx, 2, RULE_documentationContent); + int _la; + try { + int _alt; + setState(95); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 7, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(67); + description(); + setState(71); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == NEWLINE || _la == SPACE) { + { + { + setState(68); + skipWhitespace(); + } + } + setState(73); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(77); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 4, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(74); + skipWhitespace(); + } + } + } + setState(79); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 4, _ctx); + } + setState(80); + tagSection(); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(81); + description(); + setState(83); + _errHandler.sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + { + setState(82); + match(NEWLINE); + } + } + break; + default: + throw new NoViableAltException(this); + } + setState(85); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 5, _ctx); + } while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER); + setState(90); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 6, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(87); + skipWhitespace(); + } + } + } + setState(92); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 6, _ctx); + } + setState(93); + tagSection(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SkipWhitespaceContext extends ParserRuleContext { + public TerminalNode SPACE() { + return getToken(JavadocParser.SPACE, 0); + } + + public TerminalNode NEWLINE() { + return getToken(JavadocParser.NEWLINE, 0); + } + + public SkipWhitespaceContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_skipWhitespace; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).enterSkipWhitespace(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).exitSkipWhitespace(this); + } + } + + public final SkipWhitespaceContext skipWhitespace() throws RecognitionException { + SkipWhitespaceContext _localctx = new SkipWhitespaceContext(_ctx, getState()); + enterRule(_localctx, 4, RULE_skipWhitespace); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(97); + _la = _input.LA(1); + if (!(_la == NEWLINE || _la == SPACE)) { + _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class DescriptionContext extends ParserRuleContext { + public List descriptionLine() { + return getRuleContexts(DescriptionLineContext.class); + } + + public DescriptionLineContext descriptionLine(int i) { + return getRuleContext(DescriptionLineContext.class, i); + } + + public List descriptionNewline() { + return getRuleContexts(DescriptionNewlineContext.class); + } + + public DescriptionNewlineContext descriptionNewline(int i) { + return getRuleContext(DescriptionNewlineContext.class, i); + } + + public DescriptionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_description; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).enterDescription(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).exitDescription(this); + } + } + + public final DescriptionContext description() throws RecognitionException { + DescriptionContext _localctx = new DescriptionContext(_ctx, getState()); + enterRule(_localctx, 6, RULE_description); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(99); + descriptionLine(); + setState(109); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 9, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(101); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(100); + descriptionNewline(); + } + } + setState(103); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == NEWLINE); + setState(105); + descriptionLine(); + } + } + } + setState(111); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 9, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class DescriptionLineContext extends ParserRuleContext { + public DescriptionLineStartContext descriptionLineStart() { + return getRuleContext(DescriptionLineStartContext.class, 0); + } + + public List descriptionLineElement() { + return getRuleContexts(DescriptionLineElementContext.class); + } + + public DescriptionLineElementContext descriptionLineElement(int i) { + return getRuleContext(DescriptionLineElementContext.class, i); + } + + public InlineTagContext inlineTag() { + return getRuleContext(InlineTagContext.class, 0); + } + + public DescriptionLineContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_descriptionLine; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).enterDescriptionLine(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).exitDescriptionLine(this); + } + } + + public final DescriptionLineContext descriptionLine() throws RecognitionException { + DescriptionLineContext _localctx = new DescriptionLineContext(_ctx, getState()); + enterRule(_localctx, 8, RULE_descriptionLine); + try { + int _alt; + setState(126); + _errHandler.sync(this); + switch (_input.LA(1)) { + case NAME: + case SPACE: + case TEXT_CONTENT: + case STAR: + case SLASH: + case BRACE_OPEN: + case BRACE_CLOSE: + enterOuterAlt(_localctx, 1); + { + setState(112); + descriptionLineStart(); + setState(116); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 10, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(113); + descriptionLineElement(); + } + } + } + setState(118); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 10, _ctx); + } + } + break; + case INLINE_TAG_START: + enterOuterAlt(_localctx, 2); + { + setState(119); + inlineTag(); + setState(123); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 11, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(120); + descriptionLineElement(); + } + } + } + setState(125); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 11, _ctx); + } + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class DescriptionLineStartContext extends ParserRuleContext { + public List SPACE() { + return getTokens(JavadocParser.SPACE); + } + + public TerminalNode SPACE(int i) { + return getToken(JavadocParser.SPACE, i); + } + + public List descriptionLineNoSpaceNoAt() { + return getRuleContexts(DescriptionLineNoSpaceNoAtContext.class); + } + + public DescriptionLineNoSpaceNoAtContext descriptionLineNoSpaceNoAt(int i) { + return getRuleContext(DescriptionLineNoSpaceNoAtContext.class, i); + } + + public List AT() { + return getTokens(JavadocParser.AT); + } + + public TerminalNode AT(int i) { + return getToken(JavadocParser.AT, i); + } + + public DescriptionLineStartContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_descriptionLineStart; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).enterDescriptionLineStart(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).exitDescriptionLineStart(this); + } + } + + public final DescriptionLineStartContext descriptionLineStart() throws RecognitionException { + DescriptionLineStartContext _localctx = new DescriptionLineStartContext(_ctx, getState()); + enterRule(_localctx, 10, RULE_descriptionLineStart); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(129); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == SPACE) { + { + setState(128); + match(SPACE); + } + } + + setState(132); + _errHandler.sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + { + setState(131); + descriptionLineNoSpaceNoAt(); + } + } + break; + default: + throw new NoViableAltException(this); + } + setState(134); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 14, _ctx); + } while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER); + setState(141); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 16, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + setState(139); + _errHandler.sync(this); + switch (_input.LA(1)) { + case NAME: + case TEXT_CONTENT: + case STAR: + case SLASH: + case BRACE_OPEN: + case BRACE_CLOSE: + { + setState(136); + descriptionLineNoSpaceNoAt(); + } + break; + case SPACE: + { + setState(137); + match(SPACE); + } + break; + case AT: + { + setState(138); + match(AT); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + setState(143); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 16, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class DescriptionLineNoSpaceNoAtContext extends ParserRuleContext { + public TerminalNode TEXT_CONTENT() { + return getToken(JavadocParser.TEXT_CONTENT, 0); + } + + public TerminalNode NAME() { + return getToken(JavadocParser.NAME, 0); + } + + public TerminalNode STAR() { + return getToken(JavadocParser.STAR, 0); + } + + public TerminalNode SLASH() { + return getToken(JavadocParser.SLASH, 0); + } + + public TerminalNode BRACE_OPEN() { + return getToken(JavadocParser.BRACE_OPEN, 0); + } + + public TerminalNode BRACE_CLOSE() { + return getToken(JavadocParser.BRACE_CLOSE, 0); + } + + public DescriptionLineNoSpaceNoAtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_descriptionLineNoSpaceNoAt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).enterDescriptionLineNoSpaceNoAt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).exitDescriptionLineNoSpaceNoAt(this); + } + } + + public final DescriptionLineNoSpaceNoAtContext descriptionLineNoSpaceNoAt() throws RecognitionException { + DescriptionLineNoSpaceNoAtContext _localctx = new DescriptionLineNoSpaceNoAtContext(_ctx, getState()); + enterRule(_localctx, 12, RULE_descriptionLineNoSpaceNoAt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(144); + _la = _input.LA(1); + if (!((((_la) & ~0x3f) == 0 && ((1L << _la) & 6354L) != 0))) { + _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class DescriptionLineElementContext extends ParserRuleContext { + public InlineTagContext inlineTag() { + return getRuleContext(InlineTagContext.class, 0); + } + + public DescriptionLineTextContext descriptionLineText() { + return getRuleContext(DescriptionLineTextContext.class, 0); + } + + public DescriptionLineElementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_descriptionLineElement; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).enterDescriptionLineElement(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).exitDescriptionLineElement(this); + } + } + + public final DescriptionLineElementContext descriptionLineElement() throws RecognitionException { + DescriptionLineElementContext _localctx = new DescriptionLineElementContext(_ctx, getState()); + enterRule(_localctx, 14, RULE_descriptionLineElement); + try { + setState(148); + _errHandler.sync(this); + switch (_input.LA(1)) { + case INLINE_TAG_START: + enterOuterAlt(_localctx, 1); + { + setState(146); + inlineTag(); + } + break; + case NAME: + case SPACE: + case TEXT_CONTENT: + case AT: + case STAR: + case SLASH: + case BRACE_OPEN: + case BRACE_CLOSE: + enterOuterAlt(_localctx, 2); + { + setState(147); + descriptionLineText(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class DescriptionLineTextContext extends ParserRuleContext { + public List descriptionLineNoSpaceNoAt() { + return getRuleContexts(DescriptionLineNoSpaceNoAtContext.class); + } + + public DescriptionLineNoSpaceNoAtContext descriptionLineNoSpaceNoAt(int i) { + return getRuleContext(DescriptionLineNoSpaceNoAtContext.class, i); + } + + public List SPACE() { + return getTokens(JavadocParser.SPACE); + } + + public TerminalNode SPACE(int i) { + return getToken(JavadocParser.SPACE, i); + } + + public List AT() { + return getTokens(JavadocParser.AT); + } + + public TerminalNode AT(int i) { + return getToken(JavadocParser.AT, i); + } + + public DescriptionLineTextContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_descriptionLineText; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).enterDescriptionLineText(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).exitDescriptionLineText(this); + } + } + + public final DescriptionLineTextContext descriptionLineText() throws RecognitionException { + DescriptionLineTextContext _localctx = new DescriptionLineTextContext(_ctx, getState()); + enterRule(_localctx, 16, RULE_descriptionLineText); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(153); + _errHandler.sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + setState(153); + _errHandler.sync(this); + switch (_input.LA(1)) { + case NAME: + case TEXT_CONTENT: + case STAR: + case SLASH: + case BRACE_OPEN: + case BRACE_CLOSE: + { + setState(150); + descriptionLineNoSpaceNoAt(); + } + break; + case SPACE: + { + setState(151); + match(SPACE); + } + break; + case AT: + { + setState(152); + match(AT); + } + break; + default: + throw new NoViableAltException(this); + } + } + break; + default: + throw new NoViableAltException(this); + } + setState(155); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 19, _ctx); + } while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class DescriptionNewlineContext extends ParserRuleContext { + public TerminalNode NEWLINE() { + return getToken(JavadocParser.NEWLINE, 0); + } + + public DescriptionNewlineContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_descriptionNewline; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).enterDescriptionNewline(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).exitDescriptionNewline(this); + } + } + + public final DescriptionNewlineContext descriptionNewline() throws RecognitionException { + DescriptionNewlineContext _localctx = new DescriptionNewlineContext(_ctx, getState()); + enterRule(_localctx, 18, RULE_descriptionNewline); + try { + enterOuterAlt(_localctx, 1); + { + setState(157); + match(NEWLINE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class TagSectionContext extends ParserRuleContext { + public List blockTag() { + return getRuleContexts(BlockTagContext.class); + } + + public BlockTagContext blockTag(int i) { + return getRuleContext(BlockTagContext.class, i); + } + + public TagSectionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_tagSection; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).enterTagSection(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).exitTagSection(this); + } + } + + public final TagSectionContext tagSection() throws RecognitionException { + TagSectionContext _localctx = new TagSectionContext(_ctx, getState()); + enterRule(_localctx, 20, RULE_tagSection); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(160); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(159); + blockTag(); + } + } + setState(162); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == SPACE || _la == AT); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class BlockTagContext extends ParserRuleContext { + public TerminalNode AT() { + return getToken(JavadocParser.AT, 0); + } + + public BlockTagNameContext blockTagName() { + return getRuleContext(BlockTagNameContext.class, 0); + } + + public List SPACE() { + return getTokens(JavadocParser.SPACE); + } + + public TerminalNode SPACE(int i) { + return getToken(JavadocParser.SPACE, i); + } + + public List blockTagContent() { + return getRuleContexts(BlockTagContentContext.class); + } + + public BlockTagContentContext blockTagContent(int i) { + return getRuleContext(BlockTagContentContext.class, i); + } + + public BlockTagContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_blockTag; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).enterBlockTag(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).exitBlockTag(this); + } + } + + public final BlockTagContext blockTag() throws RecognitionException { + BlockTagContext _localctx = new BlockTagContext(_ctx, getState()); + enterRule(_localctx, 22, RULE_blockTag); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(165); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la == SPACE) { + { + setState(164); + match(SPACE); + } + } + + setState(167); + match(AT); + setState(168); + blockTagName(); + setState(170); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 22, _ctx)) { + case 1: + { + setState(169); + match(SPACE); + } + break; + } + setState(175); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 23, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(172); + blockTagContent(); + } + } + } + setState(177); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 23, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class BlockTagNameContext extends ParserRuleContext { + public TerminalNode NAME() { + return getToken(JavadocParser.NAME, 0); + } + + public BlockTagNameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_blockTagName; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).enterBlockTagName(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).exitBlockTagName(this); + } + } + + public final BlockTagNameContext blockTagName() throws RecognitionException { + BlockTagNameContext _localctx = new BlockTagNameContext(_ctx, getState()); + enterRule(_localctx, 24, RULE_blockTagName); + try { + enterOuterAlt(_localctx, 1); + { + setState(178); + match(NAME); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class BlockTagContentContext extends ParserRuleContext { + public BlockTagTextContext blockTagText() { + return getRuleContext(BlockTagTextContext.class, 0); + } + + public InlineTagContext inlineTag() { + return getRuleContext(InlineTagContext.class, 0); + } + + public TerminalNode NEWLINE() { + return getToken(JavadocParser.NEWLINE, 0); + } + + public BlockTagContentContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_blockTagContent; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).enterBlockTagContent(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).exitBlockTagContent(this); + } + } + + public final BlockTagContentContext blockTagContent() throws RecognitionException { + BlockTagContentContext _localctx = new BlockTagContentContext(_ctx, getState()); + enterRule(_localctx, 26, RULE_blockTagContent); + try { + setState(183); + _errHandler.sync(this); + switch (_input.LA(1)) { + case NAME: + case SPACE: + case TEXT_CONTENT: + case STAR: + case SLASH: + case BRACE_OPEN: + case BRACE_CLOSE: + enterOuterAlt(_localctx, 1); + { + setState(180); + blockTagText(); + } + break; + case INLINE_TAG_START: + enterOuterAlt(_localctx, 2); + { + setState(181); + inlineTag(); + } + break; + case NEWLINE: + enterOuterAlt(_localctx, 3); + { + setState(182); + match(NEWLINE); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class BlockTagTextContext extends ParserRuleContext { + public List blockTagTextElement() { + return getRuleContexts(BlockTagTextElementContext.class); + } + + public BlockTagTextElementContext blockTagTextElement(int i) { + return getRuleContext(BlockTagTextElementContext.class, i); + } + + public BlockTagTextContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_blockTagText; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).enterBlockTagText(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).exitBlockTagText(this); + } + } + + public final BlockTagTextContext blockTagText() throws RecognitionException { + BlockTagTextContext _localctx = new BlockTagTextContext(_ctx, getState()); + enterRule(_localctx, 28, RULE_blockTagText); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(186); + _errHandler.sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + { + setState(185); + blockTagTextElement(); + } + } + break; + default: + throw new NoViableAltException(this); + } + setState(188); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 25, _ctx); + } while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class BlockTagTextElementContext extends ParserRuleContext { + public TerminalNode TEXT_CONTENT() { + return getToken(JavadocParser.TEXT_CONTENT, 0); + } + + public TerminalNode NAME() { + return getToken(JavadocParser.NAME, 0); + } + + public TerminalNode SPACE() { + return getToken(JavadocParser.SPACE, 0); + } + + public TerminalNode STAR() { + return getToken(JavadocParser.STAR, 0); + } + + public TerminalNode SLASH() { + return getToken(JavadocParser.SLASH, 0); + } + + public TerminalNode BRACE_OPEN() { + return getToken(JavadocParser.BRACE_OPEN, 0); + } + + public TerminalNode BRACE_CLOSE() { + return getToken(JavadocParser.BRACE_CLOSE, 0); + } + + public BlockTagTextElementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_blockTagTextElement; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).enterBlockTagTextElement(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).exitBlockTagTextElement(this); + } + } + + public final BlockTagTextElementContext blockTagTextElement() throws RecognitionException { + BlockTagTextElementContext _localctx = new BlockTagTextElementContext(_ctx, getState()); + enterRule(_localctx, 30, RULE_blockTagTextElement); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(190); + _la = _input.LA(1); + if (!((((_la) & ~0x3f) == 0 && ((1L << _la) & 6362L) != 0))) { + _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class InlineTagContext extends ParserRuleContext { + public TerminalNode INLINE_TAG_START() { + return getToken(JavadocParser.INLINE_TAG_START, 0); + } + + public InlineTagNameContext inlineTagName() { + return getRuleContext(InlineTagNameContext.class, 0); + } + + public TerminalNode BRACE_CLOSE() { + return getToken(JavadocParser.BRACE_CLOSE, 0); + } + + public List SPACE() { + return getTokens(JavadocParser.SPACE); + } + + public TerminalNode SPACE(int i) { + return getToken(JavadocParser.SPACE, i); + } + + public InlineTagContentContext inlineTagContent() { + return getRuleContext(InlineTagContentContext.class, 0); + } + + public InlineTagContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_inlineTag; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).enterInlineTag(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).exitInlineTag(this); + } + } + + public final InlineTagContext inlineTag() throws RecognitionException { + InlineTagContext _localctx = new InlineTagContext(_ctx, getState()); + enterRule(_localctx, 32, RULE_inlineTag); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(192); + match(INLINE_TAG_START); + setState(193); + inlineTagName(); + setState(197); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 26, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(194); + match(SPACE); + } + } + } + setState(199); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 26, _ctx); + } + setState(201); + _errHandler.sync(this); + _la = _input.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & 2270L) != 0)) { + { + setState(200); + inlineTagContent(); + } + } + + setState(203); + match(BRACE_CLOSE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class InlineTagNameContext extends ParserRuleContext { + public TerminalNode NAME() { + return getToken(JavadocParser.NAME, 0); + } + + public InlineTagNameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_inlineTagName; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).enterInlineTagName(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).exitInlineTagName(this); + } + } + + public final InlineTagNameContext inlineTagName() throws RecognitionException { + InlineTagNameContext _localctx = new InlineTagNameContext(_ctx, getState()); + enterRule(_localctx, 34, RULE_inlineTagName); + try { + enterOuterAlt(_localctx, 1); + { + setState(205); + match(NAME); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class InlineTagContentContext extends ParserRuleContext { + public List braceContent() { + return getRuleContexts(BraceContentContext.class); + } + + public BraceContentContext braceContent(int i) { + return getRuleContext(BraceContentContext.class, i); + } + + public InlineTagContentContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_inlineTagContent; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).enterInlineTagContent(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).exitInlineTagContent(this); + } + } + + public final InlineTagContentContext inlineTagContent() throws RecognitionException { + InlineTagContentContext _localctx = new InlineTagContentContext(_ctx, getState()); + enterRule(_localctx, 36, RULE_inlineTagContent); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(208); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(207); + braceContent(); + } + } + setState(210); + _errHandler.sync(this); + _la = _input.LA(1); + } while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 2270L) != 0)); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class BraceExpressionContext extends ParserRuleContext { + public TerminalNode BRACE_OPEN() { + return getToken(JavadocParser.BRACE_OPEN, 0); + } + + public TerminalNode BRACE_CLOSE() { + return getToken(JavadocParser.BRACE_CLOSE, 0); + } + + public List braceContent() { + return getRuleContexts(BraceContentContext.class); + } + + public BraceContentContext braceContent(int i) { + return getRuleContext(BraceContentContext.class, i); + } + + public BraceExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_braceExpression; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) + ((JavadocParserListener) listener).enterBraceExpression(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).exitBraceExpression(this); + } + } + + public final BraceExpressionContext braceExpression() throws RecognitionException { + BraceExpressionContext _localctx = new BraceExpressionContext(_ctx, getState()); + enterRule(_localctx, 38, RULE_braceExpression); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(212); + match(BRACE_OPEN); + setState(216); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 2270L) != 0)) { + { + { + setState(213); + braceContent(); + } + } + setState(218); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(219); + match(BRACE_CLOSE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class BraceContentContext extends ParserRuleContext { + public BraceExpressionContext braceExpression() { + return getRuleContext(BraceExpressionContext.class, 0); + } + + public List braceText() { + return getRuleContexts(BraceTextContext.class); + } + + public BraceTextContext braceText(int i) { + return getRuleContext(BraceTextContext.class, i); + } + + public List NEWLINE() { + return getTokens(JavadocParser.NEWLINE); + } + + public TerminalNode NEWLINE(int i) { + return getToken(JavadocParser.NEWLINE, i); + } + + public BraceContentContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_braceContent; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).enterBraceContent(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).exitBraceContent(this); + } + } + + public final BraceContentContext braceContent() throws RecognitionException { + BraceContentContext _localctx = new BraceContentContext(_ctx, getState()); + enterRule(_localctx, 40, RULE_braceContent); + try { + int _alt; + setState(235); + _errHandler.sync(this); + switch (_input.LA(1)) { + case BRACE_OPEN: + enterOuterAlt(_localctx, 1); + { + setState(221); + braceExpression(); + } + break; + case NAME: + case NEWLINE: + case SPACE: + case TEXT_CONTENT: + case STAR: + case SLASH: + enterOuterAlt(_localctx, 2); + { + setState(222); + braceText(); + setState(232); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 31, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(226); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 30, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt == 1) { + { + { + setState(223); + match(NEWLINE); + } + } + } + setState(228); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 30, _ctx); + } + setState(229); + braceText(); + } + } + } + setState(234); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 31, _ctx); + } + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class BraceTextContext extends ParserRuleContext { + public TerminalNode TEXT_CONTENT() { + return getToken(JavadocParser.TEXT_CONTENT, 0); + } + + public TerminalNode NAME() { + return getToken(JavadocParser.NAME, 0); + } + + public TerminalNode SPACE() { + return getToken(JavadocParser.SPACE, 0); + } + + public TerminalNode STAR() { + return getToken(JavadocParser.STAR, 0); + } + + public TerminalNode SLASH() { + return getToken(JavadocParser.SLASH, 0); + } + + public TerminalNode NEWLINE() { + return getToken(JavadocParser.NEWLINE, 0); + } + + public BraceTextContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_braceText; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).enterBraceText(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof JavadocParserListener) ((JavadocParserListener) listener).exitBraceText(this); + } + } + + public final BraceTextContext braceText() throws RecognitionException { + BraceTextContext _localctx = new BraceTextContext(_ctx, getState()); + enterRule(_localctx, 42, RULE_braceText); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(237); + _la = _input.LA(1); + if (!((((_la) & ~0x3f) == 0 && ((1L << _la) & 222L) != 0))) { + _errHandler.recoverInline(this); + } else { + if (_input.LA(1) == Token.EOF) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static final String _serializedATN = + "\u0004\u0001\f\u00f0\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001\u0002" + + "\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004\u0007\u0004\u0002" + + "\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007\u0007\u0007\u0002" + + "\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b\u0007\u000b\u0002" + + "\f\u0007\f\u0002\r\u0007\r\u0002\u000e\u0007\u000e\u0002\u000f\u0007\u000f" + + "\u0002\u0010\u0007\u0010\u0002\u0011\u0007\u0011\u0002\u0012\u0007\u0012" + + "\u0002\u0013\u0007\u0013\u0002\u0014\u0007\u0014\u0002\u0015\u0007\u0015" + + "\u0001\u0000\u0001\u0000\u0001\u0000\u0005\u00000\b\u0000\n\u0000\f\u0000" + + "3\t\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000" + + "\u0005\u0000:\b\u0000\n\u0000\f\u0000=\t\u0000\u0001\u0000\u0001\u0000" + + "\u0001\u0000\u0003\u0000B\b\u0000\u0001\u0001\u0001\u0001\u0005\u0001" + + "F\b\u0001\n\u0001\f\u0001I\t\u0001\u0001\u0001\u0005\u0001L\b\u0001\n" + + "\u0001\f\u0001O\t\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0004\u0001" + + "T\b\u0001\u000b\u0001\f\u0001U\u0001\u0001\u0005\u0001Y\b\u0001\n\u0001" + + "\f\u0001\\\t\u0001\u0001\u0001\u0001\u0001\u0003\u0001`\b\u0001\u0001" + + "\u0002\u0001\u0002\u0001\u0003\u0001\u0003\u0004\u0003f\b\u0003\u000b" + + "\u0003\f\u0003g\u0001\u0003\u0001\u0003\u0005\u0003l\b\u0003\n\u0003\f" + + "\u0003o\t\u0003\u0001\u0004\u0001\u0004\u0005\u0004s\b\u0004\n\u0004\f" + + "\u0004v\t\u0004\u0001\u0004\u0001\u0004\u0005\u0004z\b\u0004\n\u0004\f" + + "\u0004}\t\u0004\u0003\u0004\u007f\b\u0004\u0001\u0005\u0003\u0005\u0082" + + "\b\u0005\u0001\u0005\u0004\u0005\u0085\b\u0005\u000b\u0005\f\u0005\u0086" + + "\u0001\u0005\u0001\u0005\u0001\u0005\u0005\u0005\u008c\b\u0005\n\u0005" + + "\f\u0005\u008f\t\u0005\u0001\u0006\u0001\u0006\u0001\u0007\u0001\u0007" + + "\u0003\u0007\u0095\b\u0007\u0001\b\u0001\b\u0001\b\u0004\b\u009a\b\b\u000b" + + "\b\f\b\u009b\u0001\t\u0001\t\u0001\n\u0004\n\u00a1\b\n\u000b\n\f\n\u00a2" + + "\u0001\u000b\u0003\u000b\u00a6\b\u000b\u0001\u000b\u0001\u000b\u0001\u000b" + + "\u0003\u000b\u00ab\b\u000b\u0001\u000b\u0005\u000b\u00ae\b\u000b\n\u000b" + + "\f\u000b\u00b1\t\u000b\u0001\f\u0001\f\u0001\r\u0001\r\u0001\r\u0003\r" + + "\u00b8\b\r\u0001\u000e\u0004\u000e\u00bb\b\u000e\u000b\u000e\f\u000e\u00bc" + + "\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0001\u0010\u0005\u0010" + + "\u00c4\b\u0010\n\u0010\f\u0010\u00c7\t\u0010\u0001\u0010\u0003\u0010\u00ca" + + "\b\u0010\u0001\u0010\u0001\u0010\u0001\u0011\u0001\u0011\u0001\u0012\u0004" + + "\u0012\u00d1\b\u0012\u000b\u0012\f\u0012\u00d2\u0001\u0013\u0001\u0013" + + "\u0005\u0013\u00d7\b\u0013\n\u0013\f\u0013\u00da\t\u0013\u0001\u0013\u0001" + + "\u0013\u0001\u0014\u0001\u0014\u0001\u0014\u0005\u0014\u00e1\b\u0014\n" + + "\u0014\f\u0014\u00e4\t\u0014\u0001\u0014\u0005\u0014\u00e7\b\u0014\n\u0014" + + "\f\u0014\u00ea\t\u0014\u0003\u0014\u00ec\b\u0014\u0001\u0015\u0001\u0015" + + "\u0001\u0015\u0000\u0000\u0016\u0000\u0002\u0004\u0006\b\n\f\u000e\u0010" + + "\u0012\u0014\u0016\u0018\u001a\u001c\u001e \"$&(*\u0000\u0004\u0001\u0000" + + "\u0002\u0003\u0004\u0000\u0001\u0001\u0004\u0004\u0006\u0007\u000b\f\u0004" + + "\u0000\u0001\u0001\u0003\u0004\u0006\u0007\u000b\f\u0002\u0000\u0001\u0004" + + "\u0006\u0007\u00ff\u0000A\u0001\u0000\u0000\u0000\u0002_\u0001\u0000\u0000" + + "\u0000\u0004a\u0001\u0000\u0000\u0000\u0006c\u0001\u0000\u0000\u0000\b" + + "~\u0001\u0000\u0000\u0000\n\u0081\u0001\u0000\u0000\u0000\f\u0090\u0001" + + "\u0000\u0000\u0000\u000e\u0094\u0001\u0000\u0000\u0000\u0010\u0099\u0001" + + "\u0000\u0000\u0000\u0012\u009d\u0001\u0000\u0000\u0000\u0014\u00a0\u0001" + + "\u0000\u0000\u0000\u0016\u00a5\u0001\u0000\u0000\u0000\u0018\u00b2\u0001" + + "\u0000\u0000\u0000\u001a\u00b7\u0001\u0000\u0000\u0000\u001c\u00ba\u0001" + + "\u0000\u0000\u0000\u001e\u00be\u0001\u0000\u0000\u0000 \u00c0\u0001\u0000" + + "\u0000\u0000\"\u00cd\u0001\u0000\u0000\u0000$\u00d0\u0001\u0000\u0000" + + "\u0000&\u00d4\u0001\u0000\u0000\u0000(\u00eb\u0001\u0000\u0000\u0000*" + + "\u00ed\u0001\u0000\u0000\u0000,B\u0005\u0000\u0000\u0001-1\u0005\b\u0000" + + "\u0000.0\u0003\u0004\u0002\u0000/.\u0001\u0000\u0000\u000003\u0001\u0000" + + "\u0000\u00001/\u0001\u0000\u0000\u000012\u0001\u0000\u0000\u000024\u0001" + + "\u0000\u0000\u000031\u0001\u0000\u0000\u000045\u0003\u0002\u0001\u0000" + + "56\u0005\t\u0000\u000067\u0005\u0000\u0000\u00017B\u0001\u0000\u0000\u0000" + + "8:\u0003\u0004\u0002\u000098\u0001\u0000\u0000\u0000:=\u0001\u0000\u0000" + + "\u0000;9\u0001\u0000\u0000\u0000;<\u0001\u0000\u0000\u0000<>\u0001\u0000" + + "\u0000\u0000=;\u0001\u0000\u0000\u0000>?\u0003\u0002\u0001\u0000?@\u0005" + + "\u0000\u0000\u0001@B\u0001\u0000\u0000\u0000A,\u0001\u0000\u0000\u0000" + + "A-\u0001\u0000\u0000\u0000A;\u0001\u0000\u0000\u0000B\u0001\u0001\u0000" + + "\u0000\u0000CG\u0003\u0006\u0003\u0000DF\u0003\u0004\u0002\u0000ED\u0001" + + "\u0000\u0000\u0000FI\u0001\u0000\u0000\u0000GE\u0001\u0000\u0000\u0000" + + "GH\u0001\u0000\u0000\u0000H`\u0001\u0000\u0000\u0000IG\u0001\u0000\u0000" + + "\u0000JL\u0003\u0004\u0002\u0000KJ\u0001\u0000\u0000\u0000LO\u0001\u0000" + + "\u0000\u0000MK\u0001\u0000\u0000\u0000MN\u0001\u0000\u0000\u0000NP\u0001" + + "\u0000\u0000\u0000OM\u0001\u0000\u0000\u0000P`\u0003\u0014\n\u0000QS\u0003" + + "\u0006\u0003\u0000RT\u0005\u0002\u0000\u0000SR\u0001\u0000\u0000\u0000" + + "TU\u0001\u0000\u0000\u0000US\u0001\u0000\u0000\u0000UV\u0001\u0000\u0000" + + "\u0000VZ\u0001\u0000\u0000\u0000WY\u0003\u0004\u0002\u0000XW\u0001\u0000" + + "\u0000\u0000Y\\\u0001\u0000\u0000\u0000ZX\u0001\u0000\u0000\u0000Z[\u0001" + + "\u0000\u0000\u0000[]\u0001\u0000\u0000\u0000\\Z\u0001\u0000\u0000\u0000" + + "]^\u0003\u0014\n\u0000^`\u0001\u0000\u0000\u0000_C\u0001\u0000\u0000\u0000" + + "_M\u0001\u0000\u0000\u0000_Q\u0001\u0000\u0000\u0000`\u0003\u0001\u0000" + + "\u0000\u0000ab\u0007\u0000\u0000\u0000b\u0005\u0001\u0000\u0000\u0000" + + "cm\u0003\b\u0004\u0000df\u0003\u0012\t\u0000ed\u0001\u0000\u0000\u0000" + + "fg\u0001\u0000\u0000\u0000ge\u0001\u0000\u0000\u0000gh\u0001\u0000\u0000" + + "\u0000hi\u0001\u0000\u0000\u0000ij\u0003\b\u0004\u0000jl\u0001\u0000\u0000" + + "\u0000ke\u0001\u0000\u0000\u0000lo\u0001\u0000\u0000\u0000mk\u0001\u0000" + + "\u0000\u0000mn\u0001\u0000\u0000\u0000n\u0007\u0001\u0000\u0000\u0000" + + "om\u0001\u0000\u0000\u0000pt\u0003\n\u0005\u0000qs\u0003\u000e\u0007\u0000" + + "rq\u0001\u0000\u0000\u0000sv\u0001\u0000\u0000\u0000tr\u0001\u0000\u0000" + + "\u0000tu\u0001\u0000\u0000\u0000u\u007f\u0001\u0000\u0000\u0000vt\u0001" + + "\u0000\u0000\u0000w{\u0003 \u0010\u0000xz\u0003\u000e\u0007\u0000yx\u0001" + + "\u0000\u0000\u0000z}\u0001\u0000\u0000\u0000{y\u0001\u0000\u0000\u0000" + + "{|\u0001\u0000\u0000\u0000|\u007f\u0001\u0000\u0000\u0000}{\u0001\u0000" + + "\u0000\u0000~p\u0001\u0000\u0000\u0000~w\u0001\u0000\u0000\u0000\u007f" + + "\t\u0001\u0000\u0000\u0000\u0080\u0082\u0005\u0003\u0000\u0000\u0081\u0080" + + "\u0001\u0000\u0000\u0000\u0081\u0082\u0001\u0000\u0000\u0000\u0082\u0084" + + "\u0001\u0000\u0000\u0000\u0083\u0085\u0003\f\u0006\u0000\u0084\u0083\u0001" + + "\u0000\u0000\u0000\u0085\u0086\u0001\u0000\u0000\u0000\u0086\u0084\u0001" + + "\u0000\u0000\u0000\u0086\u0087\u0001\u0000\u0000\u0000\u0087\u008d\u0001" + + "\u0000\u0000\u0000\u0088\u008c\u0003\f\u0006\u0000\u0089\u008c\u0005\u0003" + + "\u0000\u0000\u008a\u008c\u0005\u0005\u0000\u0000\u008b\u0088\u0001\u0000" + + "\u0000\u0000\u008b\u0089\u0001\u0000\u0000\u0000\u008b\u008a\u0001\u0000" + + "\u0000\u0000\u008c\u008f\u0001\u0000\u0000\u0000\u008d\u008b\u0001\u0000" + + "\u0000\u0000\u008d\u008e\u0001\u0000\u0000\u0000\u008e\u000b\u0001\u0000" + + "\u0000\u0000\u008f\u008d\u0001\u0000\u0000\u0000\u0090\u0091\u0007\u0001" + + "\u0000\u0000\u0091\r\u0001\u0000\u0000\u0000\u0092\u0095\u0003 \u0010" + + "\u0000\u0093\u0095\u0003\u0010\b\u0000\u0094\u0092\u0001\u0000\u0000\u0000" + + "\u0094\u0093\u0001\u0000\u0000\u0000\u0095\u000f\u0001\u0000\u0000\u0000" + + "\u0096\u009a\u0003\f\u0006\u0000\u0097\u009a\u0005\u0003\u0000\u0000\u0098" + + "\u009a\u0005\u0005\u0000\u0000\u0099\u0096\u0001\u0000\u0000\u0000\u0099" + + "\u0097\u0001\u0000\u0000\u0000\u0099\u0098\u0001\u0000\u0000\u0000\u009a" + + "\u009b\u0001\u0000\u0000\u0000\u009b\u0099\u0001\u0000\u0000\u0000\u009b" + + "\u009c\u0001\u0000\u0000\u0000\u009c\u0011\u0001\u0000\u0000\u0000\u009d" + + "\u009e\u0005\u0002\u0000\u0000\u009e\u0013\u0001\u0000\u0000\u0000\u009f" + + "\u00a1\u0003\u0016\u000b\u0000\u00a0\u009f\u0001\u0000\u0000\u0000\u00a1" + + "\u00a2\u0001\u0000\u0000\u0000\u00a2\u00a0\u0001\u0000\u0000\u0000\u00a2" + + "\u00a3\u0001\u0000\u0000\u0000\u00a3\u0015\u0001\u0000\u0000\u0000\u00a4" + + "\u00a6\u0005\u0003\u0000\u0000\u00a5\u00a4\u0001\u0000\u0000\u0000\u00a5" + + "\u00a6\u0001\u0000\u0000\u0000\u00a6\u00a7\u0001\u0000\u0000\u0000\u00a7" + + "\u00a8\u0005\u0005\u0000\u0000\u00a8\u00aa\u0003\u0018\f\u0000\u00a9\u00ab" + + "\u0005\u0003\u0000\u0000\u00aa\u00a9\u0001\u0000\u0000\u0000\u00aa\u00ab" + + "\u0001\u0000\u0000\u0000\u00ab\u00af\u0001\u0000\u0000\u0000\u00ac\u00ae" + + "\u0003\u001a\r\u0000\u00ad\u00ac\u0001\u0000\u0000\u0000\u00ae\u00b1\u0001" + + "\u0000\u0000\u0000\u00af\u00ad\u0001\u0000\u0000\u0000\u00af\u00b0\u0001" + + "\u0000\u0000\u0000\u00b0\u0017\u0001\u0000\u0000\u0000\u00b1\u00af\u0001" + + "\u0000\u0000\u0000\u00b2\u00b3\u0005\u0001\u0000\u0000\u00b3\u0019\u0001" + + "\u0000\u0000\u0000\u00b4\u00b8\u0003\u001c\u000e\u0000\u00b5\u00b8\u0003" + + " \u0010\u0000\u00b6\u00b8\u0005\u0002\u0000\u0000\u00b7\u00b4\u0001\u0000" + + "\u0000\u0000\u00b7\u00b5\u0001\u0000\u0000\u0000\u00b7\u00b6\u0001\u0000" + + "\u0000\u0000\u00b8\u001b\u0001\u0000\u0000\u0000\u00b9\u00bb\u0003\u001e" + + "\u000f\u0000\u00ba\u00b9\u0001\u0000\u0000\u0000\u00bb\u00bc\u0001\u0000" + + "\u0000\u0000\u00bc\u00ba\u0001\u0000\u0000\u0000\u00bc\u00bd\u0001\u0000" + + "\u0000\u0000\u00bd\u001d\u0001\u0000\u0000\u0000\u00be\u00bf\u0007\u0002" + + "\u0000\u0000\u00bf\u001f\u0001\u0000\u0000\u0000\u00c0\u00c1\u0005\n\u0000" + + "\u0000\u00c1\u00c5\u0003\"\u0011\u0000\u00c2\u00c4\u0005\u0003\u0000\u0000" + + "\u00c3\u00c2\u0001\u0000\u0000\u0000\u00c4\u00c7\u0001\u0000\u0000\u0000" + + "\u00c5\u00c3\u0001\u0000\u0000\u0000\u00c5\u00c6\u0001\u0000\u0000\u0000" + + "\u00c6\u00c9\u0001\u0000\u0000\u0000\u00c7\u00c5\u0001\u0000\u0000\u0000" + + "\u00c8\u00ca\u0003$\u0012\u0000\u00c9\u00c8\u0001\u0000\u0000\u0000\u00c9" + + "\u00ca\u0001\u0000\u0000\u0000\u00ca\u00cb\u0001\u0000\u0000\u0000\u00cb" + + "\u00cc\u0005\f\u0000\u0000\u00cc!\u0001\u0000\u0000\u0000\u00cd\u00ce" + + "\u0005\u0001\u0000\u0000\u00ce#\u0001\u0000\u0000\u0000\u00cf\u00d1\u0003" + + "(\u0014\u0000\u00d0\u00cf\u0001\u0000\u0000\u0000\u00d1\u00d2\u0001\u0000" + + "\u0000\u0000\u00d2\u00d0\u0001\u0000\u0000\u0000\u00d2\u00d3\u0001\u0000" + + "\u0000\u0000\u00d3%\u0001\u0000\u0000\u0000\u00d4\u00d8\u0005\u000b\u0000" + + "\u0000\u00d5\u00d7\u0003(\u0014\u0000\u00d6\u00d5\u0001\u0000\u0000\u0000" + + "\u00d7\u00da\u0001\u0000\u0000\u0000\u00d8\u00d6\u0001\u0000\u0000\u0000" + + "\u00d8\u00d9\u0001\u0000\u0000\u0000\u00d9\u00db\u0001\u0000\u0000\u0000" + + "\u00da\u00d8\u0001\u0000\u0000\u0000\u00db\u00dc\u0005\f\u0000\u0000\u00dc" + + "\'\u0001\u0000\u0000\u0000\u00dd\u00ec\u0003&\u0013\u0000\u00de\u00e8" + + "\u0003*\u0015\u0000\u00df\u00e1\u0005\u0002\u0000\u0000\u00e0\u00df\u0001" + + "\u0000\u0000\u0000\u00e1\u00e4\u0001\u0000\u0000\u0000\u00e2\u00e0\u0001" + + "\u0000\u0000\u0000\u00e2\u00e3\u0001\u0000\u0000\u0000\u00e3\u00e5\u0001" + + "\u0000\u0000\u0000\u00e4\u00e2\u0001\u0000\u0000\u0000\u00e5\u00e7\u0003" + + "*\u0015\u0000\u00e6\u00e2\u0001\u0000\u0000\u0000\u00e7\u00ea\u0001\u0000" + + "\u0000\u0000\u00e8\u00e6\u0001\u0000\u0000\u0000\u00e8\u00e9\u0001\u0000" + + "\u0000\u0000\u00e9\u00ec\u0001\u0000\u0000\u0000\u00ea\u00e8\u0001\u0000" + + "\u0000\u0000\u00eb\u00dd\u0001\u0000\u0000\u0000\u00eb\u00de\u0001\u0000" + + "\u0000\u0000\u00ec)\u0001\u0000\u0000\u0000\u00ed\u00ee\u0007\u0003\u0000" + + "\u0000\u00ee+\u0001\u0000\u0000\u0000!1;AGMUZ_gmt{~\u0081\u0086\u008b" + + "\u008d\u0094\u0099\u009b\u00a2\u00a5\u00aa\u00af\u00b7\u00bc\u00c5\u00c9" + + "\u00d2\u00d8\u00e2\u00e8\u00eb"; + public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavadocParserBaseListener.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavadocParserBaseListener.java new file mode 100644 index 000000000000..7512d9f26bb9 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavadocParserBaseListener.java @@ -0,0 +1,367 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor.antlr.generated; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.TerminalNode; + +/** + * This class provides an empty implementation of {@link JavadocParserListener}, + * which can be extended to create a listener which only needs to handle a subset + * of the available methods. + */ +@SuppressWarnings("CheckReturnValue") +public class JavadocParserBaseListener implements JavadocParserListener { + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterDocumentation(JavadocParser.DocumentationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitDocumentation(JavadocParser.DocumentationContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterDocumentationContent(JavadocParser.DocumentationContentContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitDocumentationContent(JavadocParser.DocumentationContentContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterSkipWhitespace(JavadocParser.SkipWhitespaceContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitSkipWhitespace(JavadocParser.SkipWhitespaceContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterDescription(JavadocParser.DescriptionContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitDescription(JavadocParser.DescriptionContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterDescriptionLine(JavadocParser.DescriptionLineContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitDescriptionLine(JavadocParser.DescriptionLineContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterDescriptionLineStart(JavadocParser.DescriptionLineStartContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitDescriptionLineStart(JavadocParser.DescriptionLineStartContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterDescriptionLineNoSpaceNoAt(JavadocParser.DescriptionLineNoSpaceNoAtContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitDescriptionLineNoSpaceNoAt(JavadocParser.DescriptionLineNoSpaceNoAtContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterDescriptionLineElement(JavadocParser.DescriptionLineElementContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitDescriptionLineElement(JavadocParser.DescriptionLineElementContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterDescriptionLineText(JavadocParser.DescriptionLineTextContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitDescriptionLineText(JavadocParser.DescriptionLineTextContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterDescriptionNewline(JavadocParser.DescriptionNewlineContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitDescriptionNewline(JavadocParser.DescriptionNewlineContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterTagSection(JavadocParser.TagSectionContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitTagSection(JavadocParser.TagSectionContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterBlockTag(JavadocParser.BlockTagContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitBlockTag(JavadocParser.BlockTagContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterBlockTagName(JavadocParser.BlockTagNameContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitBlockTagName(JavadocParser.BlockTagNameContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterBlockTagContent(JavadocParser.BlockTagContentContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitBlockTagContent(JavadocParser.BlockTagContentContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterBlockTagText(JavadocParser.BlockTagTextContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitBlockTagText(JavadocParser.BlockTagTextContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterBlockTagTextElement(JavadocParser.BlockTagTextElementContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitBlockTagTextElement(JavadocParser.BlockTagTextElementContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterInlineTag(JavadocParser.InlineTagContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitInlineTag(JavadocParser.InlineTagContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterInlineTagName(JavadocParser.InlineTagNameContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitInlineTagName(JavadocParser.InlineTagNameContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterInlineTagContent(JavadocParser.InlineTagContentContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitInlineTagContent(JavadocParser.InlineTagContentContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterBraceExpression(JavadocParser.BraceExpressionContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitBraceExpression(JavadocParser.BraceExpressionContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterBraceContent(JavadocParser.BraceContentContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitBraceContent(JavadocParser.BraceContentContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterBraceText(JavadocParser.BraceTextContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitBraceText(JavadocParser.BraceTextContext ctx) {} + + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void enterEveryRule(ParserRuleContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void exitEveryRule(ParserRuleContext ctx) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void visitTerminal(TerminalNode node) {} + /** + * {@inheritDoc} + * + *

    The default implementation does nothing.

    + */ + @Override + public void visitErrorNode(ErrorNode node) {} +} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavadocParserListener.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavadocParserListener.java new file mode 100644 index 000000000000..be525d6e4b56 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/antlr/generated/JavadocParserListener.java @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor.antlr.generated; + +import org.antlr.v4.runtime.tree.ParseTreeListener; + +/** + * This interface defines a complete listener for a parse tree produced by + * {@link JavadocParser}. + */ +public interface JavadocParserListener extends ParseTreeListener { + /** + * Enter a parse tree produced by {@link JavadocParser#documentation}. + * @param ctx the parse tree + */ + void enterDocumentation(JavadocParser.DocumentationContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#documentation}. + * @param ctx the parse tree + */ + void exitDocumentation(JavadocParser.DocumentationContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#documentationContent}. + * @param ctx the parse tree + */ + void enterDocumentationContent(JavadocParser.DocumentationContentContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#documentationContent}. + * @param ctx the parse tree + */ + void exitDocumentationContent(JavadocParser.DocumentationContentContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#skipWhitespace}. + * @param ctx the parse tree + */ + void enterSkipWhitespace(JavadocParser.SkipWhitespaceContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#skipWhitespace}. + * @param ctx the parse tree + */ + void exitSkipWhitespace(JavadocParser.SkipWhitespaceContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#description}. + * @param ctx the parse tree + */ + void enterDescription(JavadocParser.DescriptionContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#description}. + * @param ctx the parse tree + */ + void exitDescription(JavadocParser.DescriptionContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#descriptionLine}. + * @param ctx the parse tree + */ + void enterDescriptionLine(JavadocParser.DescriptionLineContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#descriptionLine}. + * @param ctx the parse tree + */ + void exitDescriptionLine(JavadocParser.DescriptionLineContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#descriptionLineStart}. + * @param ctx the parse tree + */ + void enterDescriptionLineStart(JavadocParser.DescriptionLineStartContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#descriptionLineStart}. + * @param ctx the parse tree + */ + void exitDescriptionLineStart(JavadocParser.DescriptionLineStartContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#descriptionLineNoSpaceNoAt}. + * @param ctx the parse tree + */ + void enterDescriptionLineNoSpaceNoAt(JavadocParser.DescriptionLineNoSpaceNoAtContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#descriptionLineNoSpaceNoAt}. + * @param ctx the parse tree + */ + void exitDescriptionLineNoSpaceNoAt(JavadocParser.DescriptionLineNoSpaceNoAtContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#descriptionLineElement}. + * @param ctx the parse tree + */ + void enterDescriptionLineElement(JavadocParser.DescriptionLineElementContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#descriptionLineElement}. + * @param ctx the parse tree + */ + void exitDescriptionLineElement(JavadocParser.DescriptionLineElementContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#descriptionLineText}. + * @param ctx the parse tree + */ + void enterDescriptionLineText(JavadocParser.DescriptionLineTextContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#descriptionLineText}. + * @param ctx the parse tree + */ + void exitDescriptionLineText(JavadocParser.DescriptionLineTextContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#descriptionNewline}. + * @param ctx the parse tree + */ + void enterDescriptionNewline(JavadocParser.DescriptionNewlineContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#descriptionNewline}. + * @param ctx the parse tree + */ + void exitDescriptionNewline(JavadocParser.DescriptionNewlineContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#tagSection}. + * @param ctx the parse tree + */ + void enterTagSection(JavadocParser.TagSectionContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#tagSection}. + * @param ctx the parse tree + */ + void exitTagSection(JavadocParser.TagSectionContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#blockTag}. + * @param ctx the parse tree + */ + void enterBlockTag(JavadocParser.BlockTagContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#blockTag}. + * @param ctx the parse tree + */ + void exitBlockTag(JavadocParser.BlockTagContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#blockTagName}. + * @param ctx the parse tree + */ + void enterBlockTagName(JavadocParser.BlockTagNameContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#blockTagName}. + * @param ctx the parse tree + */ + void exitBlockTagName(JavadocParser.BlockTagNameContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#blockTagContent}. + * @param ctx the parse tree + */ + void enterBlockTagContent(JavadocParser.BlockTagContentContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#blockTagContent}. + * @param ctx the parse tree + */ + void exitBlockTagContent(JavadocParser.BlockTagContentContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#blockTagText}. + * @param ctx the parse tree + */ + void enterBlockTagText(JavadocParser.BlockTagTextContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#blockTagText}. + * @param ctx the parse tree + */ + void exitBlockTagText(JavadocParser.BlockTagTextContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#blockTagTextElement}. + * @param ctx the parse tree + */ + void enterBlockTagTextElement(JavadocParser.BlockTagTextElementContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#blockTagTextElement}. + * @param ctx the parse tree + */ + void exitBlockTagTextElement(JavadocParser.BlockTagTextElementContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#inlineTag}. + * @param ctx the parse tree + */ + void enterInlineTag(JavadocParser.InlineTagContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#inlineTag}. + * @param ctx the parse tree + */ + void exitInlineTag(JavadocParser.InlineTagContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#inlineTagName}. + * @param ctx the parse tree + */ + void enterInlineTagName(JavadocParser.InlineTagNameContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#inlineTagName}. + * @param ctx the parse tree + */ + void exitInlineTagName(JavadocParser.InlineTagNameContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#inlineTagContent}. + * @param ctx the parse tree + */ + void enterInlineTagContent(JavadocParser.InlineTagContentContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#inlineTagContent}. + * @param ctx the parse tree + */ + void exitInlineTagContent(JavadocParser.InlineTagContentContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#braceExpression}. + * @param ctx the parse tree + */ + void enterBraceExpression(JavadocParser.BraceExpressionContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#braceExpression}. + * @param ctx the parse tree + */ + void exitBraceExpression(JavadocParser.BraceExpressionContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#braceContent}. + * @param ctx the parse tree + */ + void enterBraceContent(JavadocParser.BraceContentContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#braceContent}. + * @param ctx the parse tree + */ + void exitBraceContent(JavadocParser.BraceContentContext ctx); + /** + * Enter a parse tree produced by {@link JavadocParser#braceText}. + * @param ctx the parse tree + */ + void enterBraceText(JavadocParser.BraceTextContext ctx); + /** + * Exit a parse tree produced by {@link JavadocParser#braceText}. + * @param ctx the parse tree + */ + void exitBraceText(JavadocParser.BraceTextContext ctx); +} diff --git a/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/package-info.java b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/package-info.java new file mode 100644 index 000000000000..0569b616be6e --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/com/swirlds/config/processor/package-info.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * 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. + * + */ + +/** + * Annotation processor for the config api that creates documentation and constants classes for all config data + * records. + */ +package com.swirlds.config.processor; diff --git a/platform-sdk/swirlds-config-processor/src/main/java/module-info.java b/platform-sdk/swirlds-config-processor/src/main/java/module-info.java new file mode 100644 index 000000000000..d714c9ba3608 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/main/java/module-info.java @@ -0,0 +1,11 @@ +module com.swirlds.config.processor { + provides javax.annotation.processing.Processor with + com.swirlds.config.processor.ConfigDataAnnotationProcessor; + + requires com.swirlds.config.api; + requires com.squareup.javapoet; + requires java.compiler; + requires transitive org.antlr.antlr4.runtime; + requires static com.github.spotbugs.annotations; + requires static com.google.auto.service; +} diff --git a/platform-sdk/swirlds-config-processor/src/test/java/com/swirlds/config/processor/DocumentationFactoryTest.java b/platform-sdk/swirlds-config-processor/src/test/java/com/swirlds/config/processor/DocumentationFactoryTest.java new file mode 100644 index 000000000000..b11a9d98e906 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/test/java/com/swirlds/config/processor/DocumentationFactoryTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.config.processor; + +import com.swirlds.config.processor.antlr.AntlrConfigRecordParser; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.stream.Collectors; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +public class DocumentationFactoryTest { + + @TempDir + Path tempDir; + + private final String RECORD_DEFINITION = + MarkdownSyntax.RECORD + MarkdownSyntax.asCode("com.swirlds.config.processor.TestConfig"); + + private final String JAVA_FILE = "TestConfig.java"; + + @Test + void testDocumentationCreation() throws Exception { + // given + final String docFileName = "test-config.md"; + final String javaFilePath = + DocumentationFactoryTest.class.getResource(JAVA_FILE).getPath(); + final String content = Files.readString(Path.of(javaFilePath)); + final ConfigDataRecordDefinition definition = + AntlrConfigRecordParser.parse(content).get(0); + final Path docFilePath = Path.of(tempDir.toString(), docFileName); + + // when + DocumentationFactory.doWork(definition, docFilePath); + + // then + Assertions.assertTrue(Files.exists(docFilePath)); + final List lines = Files.readAllLines(docFilePath); + final List nonEmptyLines = + lines.stream().filter(l -> !l.isEmpty()).collect(Collectors.toList()); + Assertions.assertEquals(MarkdownSyntax.H2_PREFIX + "test.saveStatePeriod", nonEmptyLines.get(0)); + Assertions.assertEquals(RECORD_DEFINITION, nonEmptyLines.get(1)); + Assertions.assertEquals(MarkdownSyntax.TYPE + MarkdownSyntax.asCode("int"), nonEmptyLines.get(2)); + Assertions.assertEquals(MarkdownSyntax.DEFAULT_VALUE + MarkdownSyntax.asCode("900"), nonEmptyLines.get(3)); + Assertions.assertEquals( + MarkdownSyntax.DESCRIPTION + + "The frequency of writes of a state to disk every this many seconds (0 to never write).", + nonEmptyLines.get(4)); + } +} diff --git a/platform-sdk/swirlds-config-processor/src/test/resources/com/swirlds/config/processor/TestConfig.java b/platform-sdk/swirlds-config-processor/src/test/resources/com/swirlds/config/processor/TestConfig.java new file mode 100644 index 000000000000..c78b7d15e307 --- /dev/null +++ b/platform-sdk/swirlds-config-processor/src/test/resources/com/swirlds/config/processor/TestConfig.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.swirlds.config.processor; + +import com.swirlds.config.api.ConfigData; +import com.swirlds.config.api.ConfigProperty; + +/** + * Config that control the SignedStateManager and SignedStateFileManager behaviors. + * + * @param saveStatePeriod The frequency of writes of a state to disk every this + * many seconds (0 to never write). + */ +@ConfigData("test") +public record TestConfig(@ConfigProperty(defaultValue = "900") int saveStatePeriod) { +} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/SwirldsPlatform.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/SwirldsPlatform.java index 63ae30fc3a9b..a1e1b7b670e1 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/SwirldsPlatform.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/SwirldsPlatform.java @@ -33,7 +33,6 @@ import com.swirlds.base.state.Startable; import com.swirlds.base.time.Time; import com.swirlds.base.utility.Pair; -import com.swirlds.common.config.BasicConfig; import com.swirlds.common.config.ConsensusConfig; import com.swirlds.common.config.EventConfig; import com.swirlds.common.config.StateConfig; @@ -77,6 +76,7 @@ import com.swirlds.common.threading.framework.QueueThread; import com.swirlds.common.threading.framework.config.QueueThreadConfiguration; import com.swirlds.common.threading.framework.config.QueueThreadMetricsConfiguration; +import com.swirlds.common.threading.interrupt.InterruptableConsumer; import com.swirlds.common.threading.manager.ThreadManager; import com.swirlds.common.utility.AutoCloseableWrapper; import com.swirlds.common.utility.Clearable; @@ -88,6 +88,7 @@ import com.swirlds.logging.legacy.LogMarker; import com.swirlds.logging.legacy.payload.FatalErrorPayload; import com.swirlds.platform.components.EventIntake; +import com.swirlds.platform.components.LinkedEventIntake; import com.swirlds.platform.components.SavedStateController; import com.swirlds.platform.components.appcomm.AppCommunicationComponent; import com.swirlds.platform.components.state.DefaultStateManagementComponent; @@ -106,9 +107,12 @@ import com.swirlds.platform.event.EventUtils; import com.swirlds.platform.event.GossipEvent; import com.swirlds.platform.event.creation.AsyncEventCreationManager; +import com.swirlds.platform.event.deduplication.EventDeduplicator; import com.swirlds.platform.event.linking.EventLinker; +import com.swirlds.platform.event.linking.InOrderLinker; import com.swirlds.platform.event.linking.OrphanBufferingLinker; import com.swirlds.platform.event.linking.ParentFinder; +import com.swirlds.platform.event.orphan.OrphanBuffer; import com.swirlds.platform.event.preconsensus.AsyncPreconsensusEventWriter; import com.swirlds.platform.event.preconsensus.NoOpPreconsensusEventWriter; import com.swirlds.platform.event.preconsensus.PreconsensusEventFileManager; @@ -117,11 +121,14 @@ import com.swirlds.platform.event.preconsensus.PreconsensusEventStreamSequencer; import com.swirlds.platform.event.preconsensus.PreconsensusEventWriter; import com.swirlds.platform.event.preconsensus.SyncPreconsensusEventWriter; +import com.swirlds.platform.event.validation.AddressBookUpdate; import com.swirlds.platform.event.validation.AncientValidator; import com.swirlds.platform.event.validation.EventDeduplication; +import com.swirlds.platform.event.validation.EventSignatureValidator; import com.swirlds.platform.event.validation.EventValidator; import com.swirlds.platform.event.validation.GossipEventValidator; import com.swirlds.platform.event.validation.GossipEventValidators; +import com.swirlds.platform.event.validation.InternalEventValidator; import com.swirlds.platform.event.validation.SignatureValidator; import com.swirlds.platform.event.validation.StaticValidators; import com.swirlds.platform.event.validation.TransactionSizeValidator; @@ -173,6 +180,7 @@ import com.swirlds.platform.system.Shutdown; import com.swirlds.platform.threading.PauseAndLoad; import com.swirlds.platform.util.PlatformComponents; +import com.swirlds.platform.wiring.PlatformWiring; import com.swirlds.platform.wiring.SignedStateFileManagerWiring; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; @@ -232,9 +240,10 @@ public class SwirldsPlatform implements Platform { private final EventLinker eventLinker; /** - * Validates events and passes valid events further down the pipeline. + * Validates events and passes valid events further down the intake pipeline. */ - private final EventValidator eventValidator; + private final InterruptableConsumer intakeHandler; + /** Contains all validators for events */ private final GossipEventValidators eventValidators; @@ -323,6 +332,11 @@ public class SwirldsPlatform implements Platform { /** Manages emergency recovery */ private final EmergencyRecoveryManager emergencyRecoveryManager; + /** + * Encapsulated wiring for the platform. + */ + private final PlatformWiring platformWiring; + /** * the browser gives the Platform what app to run. There can be multiple Platforms on one computer. * @@ -458,8 +472,6 @@ public class SwirldsPlatform implements Platform { roundToIgnore)); components.add(new IssHandler( - Time.getCurrent(), - dispatchBuilder, stateConfig, selfId, platformStatusManager, @@ -666,8 +678,6 @@ public class SwirldsPlatform implements Platform { preConsensusEventHandler::preconsensusEvent, intakeEventCounter); - final BasicConfig basicConfig = platformContext.getConfiguration().getConfigData(BasicConfig.class); - final List validators = new ArrayList<>(); // it is very important to discard ancient events, otherwise the deduplication will not work, since it // doesn't track ancient events @@ -685,14 +695,55 @@ public class SwirldsPlatform implements Platform { time)); eventValidators = new GossipEventValidators(validators); - eventValidator = new EventValidator( + + final EventValidator eventValidator = new EventValidator( eventValidators, eventIntake::addUnlinkedEvent, eventIntakePhaseTimer, intakeEventCounter); + if (eventConfig.useLegacyIntake()) { + intakeHandler = eventValidator::validateEvent; + platformWiring = null; + } else { + final InternalEventValidator internalEventValidator = new InternalEventValidator( + platformContext, time, currentAddressBook.getSize() == 1, intakeEventCounter); + final EventDeduplicator eventDeduplicator = + new EventDeduplicator(platformContext, intakeEventCounter, eventIntakeMetrics); + final EventSignatureValidator eventSignatureValidator = new EventSignatureValidator( + platformContext, + time, + CryptoStatic::verifySignature, + appVersion, + initialState.getState().getPlatformState().getPreviousAddressBook(), + currentAddressBook, + intakeEventCounter); + final OrphanBuffer orphanBuffer = new OrphanBuffer(platformContext, intakeEventCounter); + final InOrderLinker inOrderLinker = new InOrderLinker(intakeEventCounter); + final LinkedEventIntake linkedEventIntake = new LinkedEventIntake( + platformContext, + threadManager, + time, + consensusRef::get, + eventObserverDispatcher, + shadowGraph, + preConsensusEventHandler::preconsensusEvent, + intakeEventCounter); + + platformWiring = new PlatformWiring(platformContext, time); + platformWiring.bind( + internalEventValidator, + eventDeduplicator, + eventSignatureValidator, + orphanBuffer, + inOrderLinker, + linkedEventIntake); + + intakeHandler = platformWiring.getEventInput(); + } + intakeQueue = components.add(new QueueThreadConfiguration(threadManager) .setNodeId(selfId) .setComponent(PLATFORM_THREAD_POOL_NAME) .setThreadName("event-intake") - .setHandler(eventValidator::validateEvent) + .setHandler(intakeHandler) .setCapacity(eventConfig.eventIntakeQueueSize()) .setLogAfterPauseDuration(threadConfig.logStackTracePauseDuration()) .setMetricsConfiguration(new QueueThreadMetricsConfiguration(metrics).enableMaxSizeMetric()) @@ -761,7 +812,12 @@ public class SwirldsPlatform implements Platform { loadStateIntoConsensus(initialState); loadStateIntoEventCreator(initialState); - eventLinker.loadFromSignedState(initialState); + + if (eventConfig.useLegacyIntake()) { + eventLinker.loadFromSignedState(initialState); + } else { + platformWiring.updateMinimumGenerationNonAncient(initialMinimumGenerationNonAncient); + } // We don't want to invoke these callbacks until after we are starting up. final long round = initialState.getRound(); @@ -787,7 +843,8 @@ public class SwirldsPlatform implements Platform { Pair.of(gossip, "gossip"), Pair.of(preConsensusEventHandler, "preConsensusEventHandler"), Pair.of(consensusRoundHandler, "consensusRoundHandler"), - Pair.of(transactionPool, "transactionPool"))); + Pair.of(transactionPool, "transactionPool"), + Pair.of(platformWiring, "platformWiring"))); if (platformContext.getConfiguration().getConfigData(ThreadConfig.class).jvmAnchor()) { components.add(new JvmAnchor(threadManager)); @@ -1001,14 +1058,26 @@ private void loadReconnectState(final SignedState signedState) { // from the ones we had before the reconnect intakeQueue.pause(); try { - eventValidators.replaceValidator( - SignatureValidator.VALIDATOR_NAME, - new SignatureValidator( - signedState.getState().getPlatformState().getPreviousAddressBook(), - signedState.getState().getPlatformState().getAddressBook(), - appVersion, - CryptoStatic::verifySignature, - Time.getCurrent())); + if (platformContext + .getConfiguration() + .getConfigData(EventConfig.class) + .useLegacyIntake()) { + eventValidators.replaceValidator( + SignatureValidator.VALIDATOR_NAME, + new SignatureValidator( + signedState.getState().getPlatformState().getPreviousAddressBook(), + signedState.getState().getPlatformState().getAddressBook(), + appVersion, + CryptoStatic::verifySignature, + Time.getCurrent())); + } else { + platformWiring + .getAddressBookUpdateInput() + .accept(new AddressBookUpdate( + signedState.getState().getPlatformState().getPreviousAddressBook(), + signedState.getState().getPlatformState().getAddressBook())); + platformWiring.updateMinimumGenerationNonAncient(signedState.getMinRoundGeneration()); + } } finally { intakeQueue.resume(); } @@ -1176,7 +1245,7 @@ private void replayPreconsensusEvents() { Time.getCurrent(), preconsensusEventFileManager, preconsensusEventWriter, - eventValidator, + intakeHandler, intakeQueue, consensusRoundHandler, stateHashSignQueue, @@ -1275,8 +1344,6 @@ private void handleFatalError( new FatalErrorPayload("Fatal error, node will shut down. Reason: " + msg), StackTrace.getStackTrace().toString(), throwable); - // Let the state management component attempt to handle the fatal error - stateManagementComponent.onFatalError(); SystemExitUtils.exitSystem(exitCode, msg); } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/DiagramCommand.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/DiagramCommand.java new file mode 100644 index 000000000000..0b7261b3b3a1 --- /dev/null +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/cli/DiagramCommand.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.platform.cli; + +import com.swirlds.base.time.Time; +import com.swirlds.cli.PlatformCli; +import com.swirlds.cli.utility.AbstractCommand; +import com.swirlds.cli.utility.SubcommandOf; +import com.swirlds.common.context.DefaultPlatformContext; +import com.swirlds.common.context.PlatformContext; +import com.swirlds.common.crypto.CryptographyHolder; +import com.swirlds.common.metrics.noop.NoOpMetrics; +import com.swirlds.common.wiring.model.ModelGroup; +import com.swirlds.config.api.Configuration; +import com.swirlds.platform.config.DefaultConfiguration; +import com.swirlds.platform.wiring.PlatformWiring; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.io.IOException; +import java.util.Base64; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import picocli.CommandLine; + +@CommandLine.Command( + name = "diagram", + mixinStandardHelpOptions = true, + description = "Generate a mermaid style diagram of platform wiring.") +@SubcommandOf(PlatformCli.class) +public final class DiagramCommand extends AbstractCommand { + + private List groupStrings = List.of(); + private List collapsedGroupStrings = List.of(); + + private DiagramCommand() {} + + @CommandLine.Option( + names = {"-g", "--group"}, + description = "Specify an un-collapsed grouping. Format is 'GROUP_NAME:COMPONENT_NAME[,COMPONENT_NAME]*'.") + private void setGroupStrings(@NonNull final List groupStrings) { + this.groupStrings = groupStrings; + } + + @CommandLine.Option( + names = {"-c", "--collapsed-group"}, + description = "Specify a collapsed grouping. Format is 'GROUP_NAME:COMPONENT_NAME[,COMPONENT_NAME]*'.") + private void setCollapsedGroupStrings(@NonNull final List collapsedGroupStrings) { + this.collapsedGroupStrings = collapsedGroupStrings; + } + + /** + * Entry point. + */ + @Override + public Integer call() throws IOException { + final Configuration configuration = DefaultConfiguration.buildBasicConfiguration(); + final PlatformContext platformContext = + new DefaultPlatformContext(configuration, new NoOpMetrics(), CryptographyHolder.get()); + + final PlatformWiring platformWiring = new PlatformWiring(platformContext, Time.getCurrent()); + + final String diagramString = platformWiring.getModel().generateWiringDiagram(parseGroups()); + final String encodedDiagramString = Base64.getEncoder().encodeToString(diagramString.getBytes()); + + final String editorUrl = "https://mermaid.ink/svg/" + encodedDiagramString + "?bgColor=e8e8e8"; + + System.out.println(diagramString); + System.out.println(); + System.out.println(editorUrl); + return 0; + } + + /** + * Parse groups from the command line arguments. + * + * @return a set of zero or more groups + */ + @NonNull + private Set parseGroups() { + final Set groups = new HashSet<>(); + + for (final String group : groupStrings) { + final String[] parts = group.split(":"); + if (parts.length != 2) { + throw new IllegalArgumentException("Invalid group string: " + group); + } + final String groupName = parts[0]; + final String[] elements = parts[1].split(","); + groups.add(new ModelGroup(groupName, Set.of(elements), false)); + } + + for (final String group : collapsedGroupStrings) { + final String[] parts = group.split(":"); + if (parts.length != 2) { + throw new IllegalArgumentException("Invalid group string: " + group); + } + final String groupName = parts[0]; + final String[] elements = parts[1].split(","); + groups.add(new ModelGroup(groupName, Set.of(elements), true)); + } + + return groups; + } +} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/LinkedEventIntake.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/LinkedEventIntake.java index 7bbce513ac5a..72c78cc61308 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/LinkedEventIntake.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/LinkedEventIntake.java @@ -122,14 +122,16 @@ public LinkedEventIntake( * Add an event to the hashgraph * * @param event an event to be added + * @return a list of rounds that came to consensus as a result of adding the event */ - public void addEvent(@NonNull final EventImpl event) { + @NonNull + public List addEvent(@NonNull final EventImpl event) { Objects.requireNonNull(event); try { if (event.getGeneration() < consensusSupplier.get().getMinGenerationNonAncient()) { // ancient events *may* be discarded, and stale events *must* be discarded - return; + return List.of(); } dispatcher.preConsensusEvent(event); @@ -153,6 +155,8 @@ public void addEvent(@NonNull final EventImpl event) { // with no consensus events, so we check the diff in generations to look for stale events handleStale(minGenNonAncientBeforeAdding); } + + return Objects.requireNonNullElseGet(consensusRounds, List::of); } finally { intakeEventCounter.eventExitedIntakePipeline(event.getBaseEvent().getSenderId()); } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/PlatformComponent.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/PlatformComponent.java index aafcba457c1d..477f8b3eafc8 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/PlatformComponent.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/PlatformComponent.java @@ -25,12 +25,6 @@ */ public interface PlatformComponent extends Startable, Stoppable { - /** - * Invoked when a fatal error has occurred. This method gives the component a chance to take any final actions - * before operations are halted, such as cleaning up resources, writing data to disk, etc. - */ - default void onFatalError() {} - /** * {@inheritDoc} *

    diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/state/DefaultStateManagementComponent.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/state/DefaultStateManagementComponent.java index 3856a7fcb464..9c338b2f4786 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/state/DefaultStateManagementComponent.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/state/DefaultStateManagementComponent.java @@ -19,7 +19,6 @@ import static com.swirlds.common.metrics.Metrics.PLATFORM_CATEGORY; import static com.swirlds.logging.legacy.LogMarker.EXCEPTION; import static com.swirlds.logging.legacy.LogMarker.STATE_TO_DISK; -import static com.swirlds.platform.state.signed.StateToDiskReason.FATAL_ERROR; import com.swirlds.base.time.Time; import com.swirlds.common.config.StateConfig; @@ -35,8 +34,6 @@ import com.swirlds.platform.components.state.output.NewLatestCompleteStateConsumer; import com.swirlds.platform.crypto.PlatformSigner; import com.swirlds.platform.dispatch.DispatchBuilder; -import com.swirlds.platform.dispatch.Observer; -import com.swirlds.platform.dispatch.triggers.control.StateDumpRequestedTrigger; import com.swirlds.platform.dispatch.triggers.flow.StateHashedTrigger; import com.swirlds.platform.state.SignatureTransmitter; import com.swirlds.platform.state.signed.ReservedSignedState; @@ -106,8 +103,6 @@ public class DefaultStateManagementComponent implements StateManagementComponent private final SavedStateController savedStateController; private final Consumer stateDumpConsumer; - private final StateConfig stateConfig; - private static final RunningAverageMetric.Config AVG_ROUND_SUPERMAJORITY_CONFIG = new RunningAverageMetric.Config( PLATFORM_CATEGORY, "roundSup") .withDescription("latest round with state signed by a supermajority") @@ -150,12 +145,12 @@ public DefaultStateManagementComponent( // Various metrics about signed states final SignedStateMetrics signedStateMetrics = new SignedStateMetrics(platformContext.getMetrics()); this.signedStateGarbageCollector = new SignedStateGarbageCollector(threadManager, signedStateMetrics); - this.stateConfig = platformContext.getConfiguration().getConfigData(StateConfig.class); this.signedStateSentinel = new SignedStateSentinel(platformContext, threadManager, Time.getCurrent()); this.savedStateController = Objects.requireNonNull(savedStateController); this.stateDumpConsumer = Objects.requireNonNull(stateDumpConsumer); - hashLogger = new HashLogger(threadManager, stateConfig); + hashLogger = + new HashLogger(threadManager, platformContext.getConfiguration().getConfigData(StateConfig.class)); final StateHashedTrigger stateHashedTrigger = dispatchBuilder.getDispatcher(this, StateHashedTrigger.class)::dispatch; @@ -311,21 +306,6 @@ public void stop() { signedStateGarbageCollector.stop(); } - /** - * {@inheritDoc} - */ - @Override - public void onFatalError() { - if (stateConfig.dumpStateOnFatal()) { - try (final ReservedSignedState reservedState = - signedStateManager.getLatestSignedState("DefaultStateManagementComponent.onFatalError()")) { - if (reservedState.isNotNull()) { - dumpState(reservedState.get(), FATAL_ERROR, true); - } - } - } - } - /** * {@inheritDoc} */ @@ -335,46 +315,6 @@ public ReservedSignedState find(final @NonNull Predicate criteria, return signedStateManager.find(criteria, reason); } - /** - * This observer is called when a signed state is requested to be dumped to disk. - * - * @param round the round that should be dumped if available. If this parameter is null or if the requested round - * is unavailable then the latest immutable round should be dumped. - * @param reason reason why the state is being dumped - * @param blocking if this method should block until the operation has been completed - */ - @Observer(StateDumpRequestedTrigger.class) - public void stateDumpRequestedObserver( - @Nullable final Long round, @NonNull final StateToDiskReason reason, @NonNull final Boolean blocking) { - - Objects.requireNonNull(reason); - Objects.requireNonNull(blocking); - - if (round == null) { - // No round is specified, dump the latest immutable state. - dumpLatestImmutableState(reason, blocking); - return; - } - - try (final ReservedSignedState reservedState = - signedStateManager.find(state -> state.getRound() == round, "state dump requested for " + reason)) { - - if (reservedState.isNotNull()) { - // We were able to find the requested round. Dump it. - dumpState(reservedState.get(), reason, blocking); - return; - } - } - - // We weren't able to find the requested round, so the best we can do is the latest round. - logger.info( - STATE_TO_DISK.getMarker(), - "State dump for round {} requested, but round could not be " - + "found in the signed state manager. Dumping latest immutable round instead.", - round); - dumpLatestImmutableState(reason, blocking); - } - @Override public void dumpLatestImmutableState(@NonNull final StateToDiskReason reason, final boolean blocking) { Objects.requireNonNull(reason); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/dispatch/triggers/control/StateDumpRequestedTrigger.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/dispatch/triggers/control/StateDumpRequestedTrigger.java deleted file mode 100644 index e30172eba58d..000000000000 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/dispatch/triggers/control/StateDumpRequestedTrigger.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2016-2023 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swirlds.platform.dispatch.triggers.control; - -import com.swirlds.platform.dispatch.types.TriggerThree; -import com.swirlds.platform.state.signed.StateToDiskReason; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; - -/** - * Sends dispatches when a dump of a signed state is requested. - */ -@FunctionalInterface -public interface StateDumpRequestedTrigger extends TriggerThree { - - /** - * Request that a signed state be dumped to disk. - * - * @param desiredRound the round that should be dumped if still in memory. If the desired round is not in memory - * then the most recent immutable state will be dumped. If null, then the most recent state will - * be dumped. - * @param reason reason why the state is being dumped - * @param blocking if this method should block until the operation has been completed - */ - @Override - void dispatch( - @Nullable final Long desiredRound, - @NonNull final StateToDiskReason reason, - @NonNull final Boolean blocking); -} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/deduplication/EventDeduplicator.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/deduplication/EventDeduplicator.java index 317173c44b80..6e29c3d33c6e 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/deduplication/EventDeduplicator.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/deduplication/EventDeduplicator.java @@ -25,6 +25,7 @@ import com.swirlds.common.system.events.EventDescriptor; import com.swirlds.platform.event.GossipEvent; import com.swirlds.platform.gossip.IntakeEventCounter; +import com.swirlds.platform.metrics.EventIntakeMetrics; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import java.nio.ByteBuffer; @@ -66,12 +67,6 @@ public class EventDeduplicator { private final SequenceMap> observedEvents = new StandardSequenceMap<>(0, INITIAL_CAPACITY, true, EventDescriptor::getGeneration); - private static final LongAccumulator.Config DUPLICATE_EVENT_CONFIG = new LongAccumulator.Config( - PLATFORM_CATEGORY, "duplicateEvents") - .withDescription("Events received that exactly match a previous event") - .withUnit("events"); - private final LongAccumulator duplicateEventAccumulator; - private static final LongAccumulator.Config DISPARATE_SIGNATURE_CONFIG = new LongAccumulator.Config( PLATFORM_CATEGORY, "eventsWithDisparateSignature") .withDescription( @@ -79,18 +74,29 @@ public class EventDeduplicator { .withUnit("events"); private final LongAccumulator disparateSignatureAccumulator; + /** + * Keeps track of the number of events that are duplicates + *

    + * Future work: Duplicate event metrics should be created and managed by this class directly once the intake + * monolith is dismantled. + */ + private final EventIntakeMetrics eventIntakeMetrics; + /** * Constructor * * @param platformContext the platform context * @param intakeEventCounter keeps track of the number of events in the intake pipeline from each peer + * @param eventIntakeMetrics keeps track of the number of events that are duplicates */ public EventDeduplicator( - @NonNull final PlatformContext platformContext, @NonNull final IntakeEventCounter intakeEventCounter) { + @NonNull final PlatformContext platformContext, + @NonNull final IntakeEventCounter intakeEventCounter, + @NonNull final EventIntakeMetrics eventIntakeMetrics) { this.intakeEventCounter = Objects.requireNonNull(intakeEventCounter); + this.eventIntakeMetrics = Objects.requireNonNull(eventIntakeMetrics); - this.duplicateEventAccumulator = platformContext.getMetrics().getOrCreate(DUPLICATE_EVENT_CONFIG); this.disparateSignatureAccumulator = platformContext.getMetrics().getOrCreate(DISPARATE_SIGNATURE_CONFIG); } @@ -117,10 +123,12 @@ public GossipEvent handleEvent(@NonNull final GossipEvent event) { disparateSignatureAccumulator.update(1); } + eventIntakeMetrics.nonDuplicateEvent(); + return event; } else { // duplicate descriptor and signature - duplicateEventAccumulator.update(1); + eventIntakeMetrics.duplicateEvent(); intakeEventCounter.eventExitedIntakePipeline(event.getSenderId()); return null; diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/orphan/OrphanBuffer.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/orphan/OrphanBuffer.java index 1ccf3fda85b7..02eb5b40c219 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/orphan/OrphanBuffer.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/orphan/OrphanBuffer.java @@ -80,6 +80,15 @@ public class OrphanBuffer { private final SequenceMap> missingParentMap = new StandardSequenceMap<>(0, INITIAL_CAPACITY, true, EventDescriptor::getGeneration); + /** + * Whether or not the orphan buffer is paused. + *

    + * When the orphan buffer is paused, it will not process any updates to the minimum generation non-ancient. This + * guarantees that the orphan buffer cannot cyclically cause itself to receive additional input by emitting events + * that cause the minimum generation non-ancient to be updated, thus causing more events to be emitted. + */ + private boolean paused; + /** * Constructor * @@ -98,6 +107,8 @@ public OrphanBuffer( PLATFORM_CATEGORY, "orphanBufferSize", Integer.class, this::getCurrentOrphanCount) .withDescription("number of orphaned events currently in the orphan buffer") .withUnit("events")); + + this.paused = false; } /** @@ -140,6 +151,11 @@ public List handleEvent(@NonNull final GossipEvent event) { */ @NonNull public List setMinimumGenerationNonAncient(final long minimumGenerationNonAncient) { + if (paused) { + // If the orphan buffer is paused, don't process any updates to the minimum generation non-ancient. + return List.of(); + } + this.minimumGenerationNonAncient = minimumGenerationNonAncient; eventsWithParents.shiftWindow(minimumGenerationNonAncient); @@ -159,6 +175,18 @@ public List setMinimumGenerationNonAncient(final long minimumGenera return unorphanedEvents; } + /** + * Pause or unpause the orphan buffer. + *

    + * The orphan buffer must be paused prior to being flushed, since its output can cyclically cause it to receive + * additional input, via an update to minimum generation non ancient. + * + * @param paused whether or not the orphan buffer should be paused + */ + public void setPaused(final boolean paused) { + this.paused = paused; + } + /** * Called when a parent becomes ancient. *

    diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/preconsensus/BestEffortPreconsensusEventFileCopy.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/preconsensus/BestEffortPreconsensusEventFileCopy.java index e9a4c835be11..96e7f558e73e 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/preconsensus/BestEffortPreconsensusEventFileCopy.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/preconsensus/BestEffortPreconsensusEventFileCopy.java @@ -24,6 +24,7 @@ import com.swirlds.common.system.NodeId; import edu.umd.cs.findbugs.annotations.NonNull; import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -92,7 +93,9 @@ public static void copyPreconsensusEventStreamFilesRetryOnFailure( platformContext, selfId, temporaryDirectory, minimumGenerationNonAncient)); return; - } catch (final IOException e) { + } catch (final IOException | UncheckedIOException e) { + // Note: Files.walk() sometimes throws an UncheckedIOException (?!!), so we have to catch both. + if (triesRemaining > 0) { logger.warn(STATE_TO_DISK.getMarker(), "Unable to copy PCES files. Retrying."); } else { diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/preconsensus/PreconsensusEventReplayPipeline.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/preconsensus/PreconsensusEventReplayPipeline.java index 6480c11a6e16..aaf74ac36cfe 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/preconsensus/PreconsensusEventReplayPipeline.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/preconsensus/PreconsensusEventReplayPipeline.java @@ -22,9 +22,9 @@ import com.swirlds.common.threading.framework.QueueThread; import com.swirlds.common.threading.framework.config.QueueThreadConfiguration; import com.swirlds.common.threading.framework.config.ThreadConfiguration; +import com.swirlds.common.threading.interrupt.InterruptableConsumer; import com.swirlds.common.threading.manager.ThreadManager; import com.swirlds.platform.event.GossipEvent; -import com.swirlds.platform.event.validation.EventValidator; import edu.umd.cs.findbugs.annotations.NonNull; import java.io.IOException; import java.io.UncheckedIOException; @@ -62,7 +62,7 @@ private record EventBeingHashed(@NonNull GossipEvent event, @NonNull Future unhashedEventIterator; - private final EventValidator eventValidator; + private final InterruptableConsumer intakeHandler; /** * Create a new event replay pipeline. @@ -70,18 +70,18 @@ private record EventBeingHashed(@NonNull GossipEvent event, @NonNull Future unhashedEventIterator, - @NonNull final EventValidator eventValidator) { + @NonNull final InterruptableConsumer intakeHandler) { this.platformContext = Objects.requireNonNull(platformContext); Objects.requireNonNull(threadManager); this.unhashedEventIterator = Objects.requireNonNull(unhashedEventIterator); - this.eventValidator = Objects.requireNonNull(eventValidator); + this.intakeHandler = Objects.requireNonNull(intakeHandler); final PreconsensusEventStreamConfig config = platformContext.getConfiguration().getConfigData(PreconsensusEventStreamConfig.class); @@ -114,7 +114,7 @@ private void handleEvent(@NonNull final EventBeingHashed eventBeingHashed) { eventBeingHashed.hashFuture().get(); final GossipEvent gossipEvent = eventBeingHashed.event(); gossipEvent.buildDescriptor(); - eventValidator.validateEvent(gossipEvent); + intakeHandler.accept(gossipEvent); } catch (final InterruptedException e) { logger.error("Interrupted while handling event from PCES", e); Thread.currentThread().interrupt(); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/preconsensus/PreconsensusEventReplayWorkflow.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/preconsensus/PreconsensusEventReplayWorkflow.java index ea677040f94f..cefdea8d512b 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/preconsensus/PreconsensusEventReplayWorkflow.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/preconsensus/PreconsensusEventReplayWorkflow.java @@ -26,10 +26,10 @@ import com.swirlds.common.formatting.UnitFormatter; import com.swirlds.common.io.IOIterator; import com.swirlds.common.threading.framework.QueueThread; +import com.swirlds.common.threading.interrupt.InterruptableConsumer; import com.swirlds.common.threading.manager.ThreadManager; import com.swirlds.platform.components.state.StateManagementComponent; import com.swirlds.platform.event.GossipEvent; -import com.swirlds.platform.event.validation.EventValidator; import com.swirlds.platform.eventhandling.ConsensusRoundHandler; import com.swirlds.platform.state.signed.ReservedSignedState; import edu.umd.cs.findbugs.annotations.NonNull; @@ -55,7 +55,7 @@ private PreconsensusEventReplayWorkflow() {} * @param threadManager the thread manager for this node * @param preconsensusEventFileManager manages the preconsensus event files on disk * @param preconsensusEventWriter writes preconsensus events to disk - * @param eventValidator validates events and passes valid events further down the pipeline + * @param intakeHandler validates events and passes valid events further down the pipeline * @param intakeQueue the queue thread for the event intake component * @param consensusRoundHandler the object responsible for applying transactions to consensus rounds * @param stateHashSignQueue the queue thread for hashing and signing states @@ -68,7 +68,7 @@ public static void replayPreconsensusEvents( @NonNull final Time time, @NonNull final PreconsensusEventFileManager preconsensusEventFileManager, @NonNull final PreconsensusEventWriter preconsensusEventWriter, - @NonNull final EventValidator eventValidator, + @NonNull final InterruptableConsumer intakeHandler, @NonNull final QueueThread intakeQueue, @NonNull final ConsensusRoundHandler consensusRoundHandler, @NonNull final QueueThread stateHashSignQueue, @@ -80,7 +80,7 @@ public static void replayPreconsensusEvents( Objects.requireNonNull(time); Objects.requireNonNull(preconsensusEventFileManager); Objects.requireNonNull(preconsensusEventWriter); - Objects.requireNonNull(eventValidator); + Objects.requireNonNull(intakeHandler); Objects.requireNonNull(intakeQueue); Objects.requireNonNull(consensusRoundHandler); Objects.requireNonNull(stateHashSignQueue); @@ -98,7 +98,7 @@ public static void replayPreconsensusEvents( preconsensusEventFileManager.getEventIterator(initialMinimumGenerationNonAncient); final PreconsensusEventReplayPipeline eventReplayPipeline = - new PreconsensusEventReplayPipeline(platformContext, threadManager, iterator, eventValidator); + new PreconsensusEventReplayPipeline(platformContext, threadManager, iterator, intakeHandler); eventReplayPipeline.replayEvents(); waitForReplayToComplete(intakeQueue, consensusRoundHandler, stateHashSignQueue); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/validation/InternalEventValidator.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/validation/InternalEventValidator.java index aa1e2e6db020..d255dcaef1c3 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/validation/InternalEventValidator.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/event/validation/InternalEventValidator.java @@ -178,7 +178,7 @@ private boolean isTransactionByteCountValid(@NonNull final GossipEvent event) { totalTransactionBytes += transaction.getSerializedLength(); } - if (totalTransactionBytes > transactionConfig.transactionMaxBytes()) { + if (totalTransactionBytes > transactionConfig.maxTransactionBytesPerEvent()) { tooManyTransactionBytesLogger.error( INVALID_EVENT_ERROR.getMarker(), "Event %s has %s transaction bytes, which is more than permitted" diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/iss/IssHandler.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/iss/IssHandler.java index fc1a97def14b..009102723353 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/iss/IssHandler.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/iss/IssHandler.java @@ -16,9 +16,6 @@ package com.swirlds.platform.state.iss; -import static com.swirlds.platform.state.signed.StateToDiskReason.ISS; - -import com.swirlds.base.time.Time; import com.swirlds.common.config.StateConfig; import com.swirlds.common.crypto.Hash; import com.swirlds.common.merkle.utility.SerializableLong; @@ -28,27 +25,21 @@ import com.swirlds.common.system.state.notifications.IssNotification; import com.swirlds.common.system.status.StatusActionSubmitter; import com.swirlds.common.system.status.actions.CatastrophicFailureAction; -import com.swirlds.common.utility.throttle.RateLimiter; import com.swirlds.platform.components.common.output.FatalErrorConsumer; import com.swirlds.platform.components.state.output.IssConsumer; -import com.swirlds.platform.dispatch.DispatchBuilder; import com.swirlds.platform.dispatch.Observer; import com.swirlds.platform.dispatch.triggers.control.HaltRequestedConsumer; -import com.swirlds.platform.dispatch.triggers.control.StateDumpRequestedTrigger; import com.swirlds.platform.dispatch.triggers.error.CatastrophicIssTrigger; import com.swirlds.platform.dispatch.triggers.error.SelfIssTrigger; import com.swirlds.platform.dispatch.triggers.flow.StateHashValidityTrigger; import edu.umd.cs.findbugs.annotations.NonNull; -import java.time.Duration; import java.util.Objects; /** * This class is responsible for handling the response to an ISS event. */ public class IssHandler { - private final RateLimiter issDumpRateLimiter; private final StateConfig stateConfig; - private final StateDumpRequestedTrigger stateDumpRequestedDispatcher; private final HaltRequestedConsumer haltRequestedConsumer; private final IssConsumer issConsumer; private final FatalErrorConsumer fatalErrorConsumer; @@ -67,7 +58,6 @@ public class IssHandler { /** * Create an object responsible for handling ISS events. * - * @param dispatchBuilder builds dispatchers * @param stateConfig settings for the state * @param selfId the self ID of this node * @param statusActionSubmitter the object to use to submit status actions @@ -77,8 +67,6 @@ public class IssHandler { * @param issScratchpad scratchpad for ISS data, is persistent across restarts */ public IssHandler( - @NonNull final Time time, - @NonNull final DispatchBuilder dispatchBuilder, @NonNull final StateConfig stateConfig, @NonNull final NodeId selfId, @NonNull final StatusActionSubmitter statusActionSubmitter, @@ -91,11 +79,8 @@ public IssHandler( this.haltRequestedConsumer = Objects.requireNonNull(haltRequestedConsumer, "haltRequestedConsumer must not be null"); this.fatalErrorConsumer = Objects.requireNonNull(fatalErrorConsumer, "fatalErrorConsumer must not be null"); - this.stateDumpRequestedDispatcher = - dispatchBuilder.getDispatcher(this, StateDumpRequestedTrigger.class)::dispatch; this.stateConfig = Objects.requireNonNull(stateConfig, "stateConfig must not be null"); - this.issDumpRateLimiter = new RateLimiter(time, Duration.ofSeconds(stateConfig.secondsBetweenISSDumps())); this.selfId = Objects.requireNonNull(selfId, "selfId must not be null"); @@ -137,13 +122,8 @@ public void stateHashValidityObserver( issConsumer.iss(round, IssNotification.IssType.OTHER_ISS, nodeId); if (stateConfig.haltOnAnyIss()) { - // If we are halting then we always should dump. - stateDumpRequestedDispatcher.dispatch(round, ISS, false); - haltRequestedConsumer.haltRequested("other node observed with ISS"); halted = true; - } else if (stateConfig.dumpStateOnAnyISS() && issDumpRateLimiter.requestAndTrigger()) { - stateDumpRequestedDispatcher.dispatch(round, ISS, false); } } @@ -171,13 +151,12 @@ private void updateIssRoundInScratchpad(final long issRound) { /** * This method is called when there is a self ISS. * - * @param round the round of the ISS - * @param selfStateHash the incorrect hash computed by this node - * @param consensusHash the correct hash computed by the network + * @param round the round of the ISS + * @param ignored1 the incorrect hash computed by this node + * @param ignored2 the correct hash computed by the network */ @Observer(SelfIssTrigger.class) - public void selfIssObserver( - @NonNull final Long round, @NonNull final Hash selfStateHash, @NonNull final Hash consensusHash) { + public void selfIssObserver(@NonNull final Long round, @NonNull final Hash ignored1, @NonNull final Hash ignored2) { if (halted) { // don't take any action once halted @@ -190,17 +169,11 @@ public void selfIssObserver( issConsumer.iss(round, IssNotification.IssType.SELF_ISS, selfId); if (stateConfig.haltOnAnyIss()) { - // If configured to halt then always do a dump. - stateDumpRequestedDispatcher.dispatch(round, ISS, false); haltRequestedConsumer.haltRequested("self ISS observed"); halted = true; } else if (stateConfig.automatedSelfIssRecovery()) { // Automated recovery is a fancy way of saying "turn it off and on again". - // If we are powering down, always do a state dump. - stateDumpRequestedDispatcher.dispatch(round, ISS, true); fatalErrorConsumer.fatalError("Self ISS", null, SystemExitCode.ISS); - } else if (stateConfig.dumpStateOnAnyISS() && issDumpRateLimiter.requestAndTrigger()) { - stateDumpRequestedDispatcher.dispatch(round, ISS, false); } } @@ -259,11 +232,11 @@ public void selfIssObserver( /** * This method is called when there is a catastrophic ISS. * - * @param round the round of the ISS - * @param selfStateHash the hash computed by this node + * @param round the round of the ISS + * @param ignored the hash computed by this node */ @Observer(CatastrophicIssTrigger.class) - public void catastrophicIssObserver(@NonNull final Long round, @NonNull final Hash selfStateHash) { + public void catastrophicIssObserver(@NonNull final Long round, @NonNull final Hash ignored) { if (halted) { // don't take any action once halted @@ -276,12 +249,8 @@ public void catastrophicIssObserver(@NonNull final Long round, @NonNull final Ha issConsumer.iss(round, IssNotification.IssType.CATASTROPHIC_ISS, null); if (stateConfig.haltOnAnyIss() || stateConfig.haltOnCatastrophicIss()) { - // If configured to halt then always do a dump. - stateDumpRequestedDispatcher.dispatch(round, ISS, false); haltRequestedConsumer.haltRequested("catastrophic ISS observed"); halted = true; - } else if (stateConfig.dumpStateOnAnyISS() && issDumpRateLimiter.requestAndTrigger()) { - stateDumpRequestedDispatcher.dispatch(round, ISS, stateConfig.automatedSelfIssRecovery()); } } } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/ReservedSignedState.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/ReservedSignedState.java index a6d06e2adaa3..1259c0fdd2a4 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/ReservedSignedState.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/ReservedSignedState.java @@ -76,8 +76,34 @@ private ReservedSignedState() { ReservedSignedState(@NonNull final SignedState signedState, @NonNull final String reason) { this.signedState = Objects.requireNonNull(signedState); this.reason = Objects.requireNonNull(reason); + } - signedState.incrementReservationCount(reason, reservationId); + /** + * Create a new reserved signed state and increment the reservation count on the underlying signed state. + * + * @param signedState the signed state to reserve + * @param reason a short description of why this SignedState is being reserved. Each location where a + * SignedState is reserved should attempt to use a unique reason, as this makes debugging + * reservation bugs easier. + */ + static @NonNull ReservedSignedState createAndReserve( + @NonNull final SignedState signedState, @NonNull final String reason) { + final ReservedSignedState reservedSignedState = new ReservedSignedState(signedState, reason); + signedState.incrementReservationCount(reason, reservedSignedState.getReservationId()); + return reservedSignedState; + } + + /** + * Create a new reserved signed state. This method assumes that the reservation count will be incremented by the + * caller. + * + * @param signedState the signed state to reserve + * @param reason a short description of why this SignedState is being reserved. Each location where a + * SignedState is reserved should attempt to use a unique reason, as this makes debugging + * reservation bugs easier. + */ + static @NonNull ReservedSignedState create(@NonNull final SignedState signedState, @NonNull final String reason) { + return new ReservedSignedState(signedState, reason); } /** @@ -113,7 +139,25 @@ public boolean isNotNull() { if (signedState == null) { return new ReservedSignedState(); } - return new ReservedSignedState(signedState, reason); + return createAndReserve(signedState, reason); + } + + /** + * Try to get another reservation on the signed state. If the signed state is not closed, then a new reservation + * will be returned. If the signed state is closed, then null will be returned. + * + * @param reason a short description of why this SignedState is being reserved. Each location where a SignedState is + * reserved should attempt to use a unique reason, as this makes debugging reservation bugs easier. + * @return a new wrapper around the state that holds a new reservation, or null if the signed state is closed + */ + public @Nullable ReservedSignedState tryGetAndReserve(@NonNull final String reason) { + if (signedState == null) { + return new ReservedSignedState(); + } + if (!signedState.tryIncrementReservationCount(reason, reservationId)) { + return null; + } + return create(signedState, reason); } /** diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedState.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedState.java index 9e03fef6f143..819574bca5b0 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedState.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedState.java @@ -296,7 +296,7 @@ public void markAsRecoveryState() { * @return a wrapper that holds the state and the reservation */ public @NonNull ReservedSignedState reserve(@NonNull final String reason) { - return new ReservedSignedState(this, reason); + return ReservedSignedState.createAndReserve(this, reason); } /** @@ -309,6 +309,19 @@ void incrementReservationCount(@NonNull final String reason, final long reservat reservations.reserve(); } + /** + * Try to increment the reservation count. + */ + boolean tryIncrementReservationCount(@NonNull final String reason, final long reservationId) { + if (!reservations.tryReserve()) { + return false; + } + if (history != null) { + history.recordAction(RESERVE, getReservationCount(), reason, reservationId); + } + return true; + } + /** * Decrement reservation count. */ diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedStateMap.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedStateMap.java index fa89392090e3..89ce5376796b 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedStateMap.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedStateMap.java @@ -128,7 +128,7 @@ public void put(@NonNull final SignedState signedState, @NonNull final String re try (final Locked l = lock.lock()) { final ReservedSignedState previousState = - map.put(signedState.getRound(), new ReservedSignedState(signedState, reason)); + map.put(signedState.getRound(), ReservedSignedState.createAndReserve(signedState, reason)); if (previousState != null) { previousState.close(); } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedStateNexus.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedStateNexus.java new file mode 100644 index 000000000000..bcb1290dd6f6 --- /dev/null +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedStateNexus.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.platform.state.signed; + +import com.swirlds.common.utility.Clearable; +import com.swirlds.platform.consensus.ConsensusConstants; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +/** + * A thread-safe container that also manages reservations for a single signed state. + */ +public class SignedStateNexus implements Consumer, Clearable { + private final AtomicReference currentState = new AtomicReference<>(); + private final AtomicLong currentStateRound = new AtomicLong(ConsensusConstants.ROUND_UNDEFINED); + + /** + * Returns the current signed state and reserves it. If the current signed state is null, or cannot be reserved, + * then null is returned. + * + * @param reason a short description of why this SignedState is being reserved + * @return the current signed state, or null if there is no state set or if it cannot be reserved + */ + public @Nullable ReservedSignedState getState(@NonNull final String reason) { + ReservedSignedState state; + do { + state = currentState.get(); + if (state == null) { + return null; + } + + // between the get method on the atomic reference and the tryGetAndReserve method on the state, the state + // could have been closed. If this happens, tryGetAndReserve will return null + final ReservedSignedState newReservation = state.tryGetAndReserve(reason); + if (newReservation != null) { + return newReservation; + } + // if tryGetAndReserve returned null, then we should check if set() was called in the meantime + // if yes, then we should try again and reserve the new state + } while (state != currentState.get()); + // this means we cannot reserve the state we are holding, this is probably an error, since we should hold a + // reservation on it + return null; + } + + /** + * Sets the current signed state to the given state, and releases the previous state if it exists. + * + * @param reservedSignedState the new signed state + */ + public void setState(@Nullable final ReservedSignedState reservedSignedState) { + final ReservedSignedState oldState = currentState.getAndSet(reservedSignedState); + currentStateRound.set( + reservedSignedState == null + ? ConsensusConstants.ROUND_UNDEFINED + : reservedSignedState.get().getRound()); + if (oldState != null) { + oldState.close(); + } + } + + /** + * Returns the round of the current signed state + * + * @return the round of the current signed state, or {@link ConsensusConstants#ROUND_UNDEFINED} if there is no + * current signed state + */ + public long getRound() { + return currentStateRound.get(); + } + + /** + * Same as {@link #setState(ReservedSignedState)} with a null argument + */ + @Override + public void clear() { + setState(null); + } + + /** + * Same as {@link #setState(ReservedSignedState)} + */ + @Override + public void accept(@Nullable final ReservedSignedState reservedSignedState) { + setState(reservedSignedState); + } +} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedStateReference.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedStateReference.java index 3d4f083ff644..25ae69d42f05 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedStateReference.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/signed/SignedStateReference.java @@ -66,8 +66,9 @@ public void set(@Nullable final SignedState signedState, @NonNull final String r } reservedSignedState.close(); - reservedSignedState = - signedState == null ? createNullReservation() : new ReservedSignedState(signedState, reason); + reservedSignedState = signedState == null + ? createNullReservation() + : ReservedSignedState.createAndReserve(signedState, reason); } } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/EventDeduplicatorScheduler.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/EventDeduplicatorScheduler.java deleted file mode 100644 index fa7b19e70d7e..000000000000 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/EventDeduplicatorScheduler.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2023 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swirlds.platform.wiring; - -import com.swirlds.common.wiring.model.WiringModel; -import com.swirlds.common.wiring.schedulers.TaskScheduler; -import com.swirlds.common.wiring.schedulers.builders.TaskSchedulerType; -import com.swirlds.common.wiring.wires.input.BindableInputWire; -import com.swirlds.common.wiring.wires.input.InputWire; -import com.swirlds.common.wiring.wires.output.OutputWire; -import com.swirlds.platform.event.GossipEvent; -import com.swirlds.platform.event.deduplication.EventDeduplicator; -import edu.umd.cs.findbugs.annotations.NonNull; - -/** - * Wiring for the {@link EventDeduplicator}. - */ -public class EventDeduplicatorScheduler { - private final TaskScheduler taskScheduler; - private final BindableInputWire eventInput; - private final BindableInputWire minimumGenerationNonAncientInput; - - /** - * Constructor. - * - * @param model the wiring model - */ - public EventDeduplicatorScheduler(@NonNull final WiringModel model) { - taskScheduler = model.schedulerBuilder("eventDeduplicator") - .withType(TaskSchedulerType.SEQUENTIAL) - .withUnhandledTaskCapacity(500) - .withFlushingEnabled(true) - .withMetricsBuilder(model.metricsBuilder().withUnhandledTaskMetricEnabled(true)) - .build() - .cast(); - - eventInput = taskScheduler.buildInputWire("non-deduplicated events"); - minimumGenerationNonAncientInput = taskScheduler.buildInputWire("minimum generation non ancient"); - } - - /** - * Get the event input wire. - * - * @return the event input wire - */ - @NonNull - public InputWire getEventInput() { - return eventInput; - } - - /** - * Get the minimum generation non ancient input wire. - * - * @return the minimum generation non ancient input wire - */ - @NonNull - public InputWire getMinimumGenerationNonAncientInput() { - return minimumGenerationNonAncientInput; - } - - /** - * Get the output of the deduplicator, i.e. a stream of deduplicated events - * - * @return the event output channel - */ - @NonNull - public OutputWire getEventOutput() { - return taskScheduler.getOutputWire(); - } - - /** - * Bind a deduplicator to this wiring. - * - * @param deduplicator the deduplicator to bind - */ - public void bind(@NonNull final EventDeduplicator deduplicator) { - eventInput.bind(deduplicator::handleEvent); - minimumGenerationNonAncientInput.bind(deduplicator::setMinimumGenerationNonAncient); - } -} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/EventDeduplicatorWiring.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/EventDeduplicatorWiring.java new file mode 100644 index 000000000000..d3a5941d8e93 --- /dev/null +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/EventDeduplicatorWiring.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.platform.wiring; + +import com.swirlds.common.wiring.schedulers.TaskScheduler; +import com.swirlds.common.wiring.wires.input.BindableInputWire; +import com.swirlds.common.wiring.wires.input.InputWire; +import com.swirlds.common.wiring.wires.output.OutputWire; +import com.swirlds.platform.event.GossipEvent; +import com.swirlds.platform.event.deduplication.EventDeduplicator; +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * Wiring for the {@link EventDeduplicator}. + * + * @param eventInput the input wire for events to be deduplicated + * @param minimumGenerationNonAncientInput the input wire for the minimum generation non-ancient + * @param eventOutput the output wire for deduplicated events + * @param flushRunnable the runnable to flush the deduplicator + */ +public record EventDeduplicatorWiring( + @NonNull InputWire eventInput, + @NonNull InputWire minimumGenerationNonAncientInput, + @NonNull OutputWire eventOutput, + @NonNull Runnable flushRunnable) { + + /** + * Create a new instance of this wiring. + * + * @param taskScheduler the task scheduler for this deduplicator + * @return the new wiring instance + */ + public static EventDeduplicatorWiring create(@NonNull final TaskScheduler taskScheduler) { + return new EventDeduplicatorWiring( + taskScheduler.buildInputWire("non-deduplicated events"), + taskScheduler.buildInputWire("minimum generation non ancient"), + taskScheduler.getOutputWire(), + taskScheduler::flush); + } + + /** + * Bind a deduplicator to this wiring. + * + * @param deduplicator the deduplicator to bind + */ + public void bind(@NonNull final EventDeduplicator deduplicator) { + ((BindableInputWire) eventInput).bind(deduplicator::handleEvent); + ((BindableInputWire) minimumGenerationNonAncientInput) + .bind(deduplicator::setMinimumGenerationNonAncient); + } +} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/EventSignatureValidatorScheduler.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/EventSignatureValidatorScheduler.java deleted file mode 100644 index bcb5f8f136c1..000000000000 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/EventSignatureValidatorScheduler.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2023 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swirlds.platform.wiring; - -import com.swirlds.common.wiring.model.WiringModel; -import com.swirlds.common.wiring.schedulers.TaskScheduler; -import com.swirlds.common.wiring.schedulers.builders.TaskSchedulerType; -import com.swirlds.common.wiring.wires.input.BindableInputWire; -import com.swirlds.common.wiring.wires.input.InputWire; -import com.swirlds.common.wiring.wires.output.OutputWire; -import com.swirlds.platform.event.GossipEvent; -import com.swirlds.platform.event.validation.EventSignatureValidator; -import edu.umd.cs.findbugs.annotations.NonNull; - -/** - * Wiring for the event signature validator. - */ -public class EventSignatureValidatorScheduler { - - private final TaskScheduler taskScheduler; - - private final BindableInputWire eventInput; - private final BindableInputWire minimumGenerationNonAncientInput; - - /** - * Constructor. - * - * @param model the wiring model - */ - public EventSignatureValidatorScheduler(@NonNull final WiringModel model) { - taskScheduler = model.schedulerBuilder("eventSignatureValidator") - .withType(TaskSchedulerType.SEQUENTIAL) - .withUnhandledTaskCapacity(500) - .withFlushingEnabled(true) - .withMetricsBuilder(model.metricsBuilder().withUnhandledTaskMetricEnabled(true)) - .build() - .cast(); - - eventInput = taskScheduler.buildInputWire("events with unvalidated signatures"); - minimumGenerationNonAncientInput = taskScheduler.buildInputWire("minimum generation non ancient"); - } - - /** - * Get the input of the signature validator, i.e. a stream of events with unvalidated signatures. - * - * @return the event input wire - */ - @NonNull - public InputWire getEventInput() { - return eventInput; - } - - /** - * Get the input of the minimum generation non ancient - * - * @return the minimum generation non ancient input wire - */ - @NonNull - public InputWire getMinimumGenerationNonAncientInput() { - return minimumGenerationNonAncientInput; - } - - /** - * Get the output of the signature validator, i.e. a stream of events with valid signatures. - * - * @return the event output channel - */ - @NonNull - public OutputWire getEventOutput() { - return taskScheduler.getOutputWire(); - } - - /** - * Bind a signature validator to this wiring. - * - * @param eventSignatureValidator the event signature validator to bind - */ - public void bind(@NonNull final EventSignatureValidator eventSignatureValidator) { - eventInput.bind(eventSignatureValidator::validateSignature); - minimumGenerationNonAncientInput.bind(eventSignatureValidator::setMinimumGenerationNonAncient); - } -} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/EventSignatureValidatorWiring.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/EventSignatureValidatorWiring.java new file mode 100644 index 000000000000..fe5af6282fc5 --- /dev/null +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/EventSignatureValidatorWiring.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.platform.wiring; + +import com.swirlds.common.wiring.schedulers.TaskScheduler; +import com.swirlds.common.wiring.wires.input.BindableInputWire; +import com.swirlds.common.wiring.wires.input.InputWire; +import com.swirlds.common.wiring.wires.output.OutputWire; +import com.swirlds.platform.event.GossipEvent; +import com.swirlds.platform.event.validation.AddressBookUpdate; +import com.swirlds.platform.event.validation.EventSignatureValidator; +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * Wiring for the {@link EventSignatureValidator}. + * + * @param eventInput the input wire for events with unvalidated signatures + * @param minimumGenerationNonAncientInput the input wire for the minimum generation non-ancient + * @param addressBookUpdateInput the input wire for address book updates + * @param eventOutput the output wire for events with validated signatures + * @param flushRunnable the runnable to flush the validator + */ +public record EventSignatureValidatorWiring( + @NonNull InputWire eventInput, + @NonNull InputWire minimumGenerationNonAncientInput, + @NonNull InputWire addressBookUpdateInput, + @NonNull OutputWire eventOutput, + @NonNull Runnable flushRunnable) { + + /** + * Create a new instance of this wiring. + * + * @param taskScheduler the task scheduler for this validator + * @return the new wiring instance + */ + public static EventSignatureValidatorWiring create(@NonNull final TaskScheduler taskScheduler) { + return new EventSignatureValidatorWiring( + taskScheduler.buildInputWire("events with unvalidated signatures"), + taskScheduler.buildInputWire("minimum generation non ancient"), + taskScheduler.buildInputWire("address book update"), + taskScheduler.getOutputWire(), + taskScheduler::flush); + } + + /** + * Bind a signature validator to this wiring. + * + * @param eventSignatureValidator the event signature validator to bind + */ + public void bind(@NonNull final EventSignatureValidator eventSignatureValidator) { + ((BindableInputWire) eventInput).bind(eventSignatureValidator::validateSignature); + ((BindableInputWire) minimumGenerationNonAncientInput) + .bind(eventSignatureValidator::setMinimumGenerationNonAncient); + ((BindableInputWire) addressBookUpdateInput) + .bind(eventSignatureValidator::updateAddressBooks); + } +} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/InOrderLinkerScheduler.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/InOrderLinkerScheduler.java deleted file mode 100644 index 7efbc2318a73..000000000000 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/InOrderLinkerScheduler.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2023 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swirlds.platform.wiring; - -import com.swirlds.common.wiring.model.WiringModel; -import com.swirlds.common.wiring.schedulers.TaskScheduler; -import com.swirlds.common.wiring.schedulers.builders.TaskSchedulerType; -import com.swirlds.common.wiring.wires.input.BindableInputWire; -import com.swirlds.common.wiring.wires.input.InputWire; -import com.swirlds.common.wiring.wires.output.OutputWire; -import com.swirlds.platform.event.GossipEvent; -import com.swirlds.platform.event.linking.InOrderLinker; -import com.swirlds.platform.internal.EventImpl; -import edu.umd.cs.findbugs.annotations.NonNull; - -/** - * Wiring for the {@link com.swirlds.platform.event.linking.InOrderLinker InOrderLinker}. - */ -public class InOrderLinkerScheduler { - private final TaskScheduler taskScheduler; - - private final BindableInputWire eventInput; - private final BindableInputWire minimumGenerationNonAncientInput; - - /** - * Constructor. - * - * @param model the wiring model - */ - public InOrderLinkerScheduler(@NonNull final WiringModel model) { - taskScheduler = model.schedulerBuilder("inOrderLinker") - .withType(TaskSchedulerType.SEQUENTIAL) - .withUnhandledTaskCapacity(500) - .withFlushingEnabled(true) - .withMetricsBuilder(model.metricsBuilder().withUnhandledTaskMetricEnabled(true)) - .build() - .cast(); - - eventInput = taskScheduler.buildInputWire("unlinked events"); - minimumGenerationNonAncientInput = taskScheduler.buildInputWire("minimum generation non ancient"); - } - - /** - * Gets the event input wire. - * - * @return the event input wire - */ - @NonNull - public InputWire getEventInput() { - return eventInput; - } - - /** - * Gets the minimum generation non ancient input wire. - * - * @return the minimum generation non ancient input wire - */ - @NonNull - public InputWire getMinimumGenerationNonAncientInput() { - return minimumGenerationNonAncientInput; - } - - /** - * Get the output of the in order linker, i.e. a stream of linked events - * - * @return the event output wire - */ - @NonNull - public OutputWire getEventOutput() { - return taskScheduler.getOutputWire(); - } - - /** - * Bind an in order linker to this wiring. - * - * @param inOrderLinker the in order linker to bind - */ - public void bind(@NonNull final InOrderLinker inOrderLinker) { - eventInput.bind(inOrderLinker::linkEvent); - minimumGenerationNonAncientInput.bind(inOrderLinker::setMinimumGenerationNonAncient); - } -} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/InOrderLinkerWiring.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/InOrderLinkerWiring.java new file mode 100644 index 000000000000..265c8bb3b6d4 --- /dev/null +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/InOrderLinkerWiring.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.platform.wiring; + +import com.swirlds.common.wiring.schedulers.TaskScheduler; +import com.swirlds.common.wiring.wires.input.BindableInputWire; +import com.swirlds.common.wiring.wires.input.InputWire; +import com.swirlds.common.wiring.wires.output.OutputWire; +import com.swirlds.platform.event.GossipEvent; +import com.swirlds.platform.event.linking.InOrderLinker; +import com.swirlds.platform.internal.EventImpl; +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * Wiring for the {@link InOrderLinker}. + * + * @param eventInput the input wire for events to be linked + * @param minimumGenerationNonAncientInput the input wire for the minimum generation non-ancient + * @param eventOutput the output wire for linked events + * @param flushRunnable the runnable to flush the linker + */ +public record InOrderLinkerWiring( + @NonNull InputWire eventInput, + @NonNull InputWire minimumGenerationNonAncientInput, + @NonNull OutputWire eventOutput, + @NonNull Runnable flushRunnable) { + + /** + * Create a new instance of this wiring. + * + * @param taskScheduler the task scheduler for this linker + * @return the new wiring instance + */ + public static InOrderLinkerWiring create(@NonNull final TaskScheduler taskScheduler) { + return new InOrderLinkerWiring( + taskScheduler.buildInputWire("unlinked events"), + taskScheduler.buildInputWire("minimum generation non ancient"), + taskScheduler.getOutputWire(), + taskScheduler::flush); + } + + /** + * Bind an in order linker to this wiring. + * + * @param inOrderLinker the in order linker to bind + */ + public void bind(@NonNull final InOrderLinker inOrderLinker) { + ((BindableInputWire) eventInput).bind(inOrderLinker::linkEvent); + ((BindableInputWire) minimumGenerationNonAncientInput) + .bind(inOrderLinker::setMinimumGenerationNonAncient); + } +} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/InternalEventValidatorScheduler.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/InternalEventValidatorScheduler.java deleted file mode 100644 index e7349c33bfe0..000000000000 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/InternalEventValidatorScheduler.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2023 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swirlds.platform.wiring; - -import com.swirlds.common.wiring.model.WiringModel; -import com.swirlds.common.wiring.schedulers.TaskScheduler; -import com.swirlds.common.wiring.schedulers.builders.TaskSchedulerType; -import com.swirlds.common.wiring.wires.input.BindableInputWire; -import com.swirlds.common.wiring.wires.input.InputWire; -import com.swirlds.common.wiring.wires.output.OutputWire; -import com.swirlds.platform.event.GossipEvent; -import com.swirlds.platform.event.validation.InternalEventValidator; -import edu.umd.cs.findbugs.annotations.NonNull; - -/** - * Wiring for the {@link com.swirlds.platform.event.validation.InternalEventValidator InternalEventValidator}. - */ -public class InternalEventValidatorScheduler { - private final TaskScheduler taskScheduler; - private final BindableInputWire eventInput; - - /** - * Constructor. - * - * @param model the wiring model - */ - public InternalEventValidatorScheduler(@NonNull final WiringModel model) { - taskScheduler = model.schedulerBuilder("internalEventValidator") - .withType(TaskSchedulerType.SEQUENTIAL) - .withUnhandledTaskCapacity(500) - .withFlushingEnabled(true) - .withMetricsBuilder(model.metricsBuilder().withUnhandledTaskMetricEnabled(true)) - .build() - .cast(); - - eventInput = taskScheduler.buildInputWire("non-validated events"); - } - - /** - * Gets the event input wire - * - * @return the event input wire - */ - @NonNull - public InputWire getEventInput() { - return eventInput; - } - - /** - * Get the output of the internal validator, i.e. a stream of events with validated internal data. - * - * @return the event output channel - */ - @NonNull - public OutputWire getEventOutput() { - return taskScheduler.getOutputWire(); - } - - /** - * Bind an internal event validator to this wiring. - * - * @param internalEventValidator the validator to bind - */ - public void bind(@NonNull final InternalEventValidator internalEventValidator) { - eventInput.bind(internalEventValidator::validateEvent); - } -} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/InternalEventValidatorWiring.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/InternalEventValidatorWiring.java new file mode 100644 index 000000000000..240cc6e76366 --- /dev/null +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/InternalEventValidatorWiring.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.platform.wiring; + +import com.swirlds.common.wiring.schedulers.TaskScheduler; +import com.swirlds.common.wiring.wires.input.BindableInputWire; +import com.swirlds.common.wiring.wires.input.InputWire; +import com.swirlds.common.wiring.wires.output.OutputWire; +import com.swirlds.platform.event.GossipEvent; +import com.swirlds.platform.event.validation.InternalEventValidator; +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * Wiring for the {@link InternalEventValidator}. + * + * @param eventInput the input wire for events to be validated + * @param eventOutput the output wire for validated events + * @param flushRunnable the runnable to flush the validator + */ +public record InternalEventValidatorWiring( + @NonNull InputWire eventInput, + @NonNull OutputWire eventOutput, + @NonNull Runnable flushRunnable) { + + /** + * Create a new instance of this wiring. + * + * @param taskScheduler the task scheduler for this validator + * @return the new wiring instance + */ + public static InternalEventValidatorWiring create(@NonNull final TaskScheduler taskScheduler) { + return new InternalEventValidatorWiring( + taskScheduler.buildInputWire("non-validated events"), + taskScheduler.getOutputWire(), + taskScheduler::flush); + } + + /** + * Bind an internal event validator to this wiring. + * + * @param internalEventValidator the validator to bind + */ + public void bind(@NonNull final InternalEventValidator internalEventValidator) { + ((BindableInputWire) eventInput).bind(internalEventValidator::validateEvent); + } +} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/LinkedEventIntakeScheduler.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/LinkedEventIntakeScheduler.java deleted file mode 100644 index 4f64e72e91a1..000000000000 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/LinkedEventIntakeScheduler.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2023 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swirlds.platform.wiring; - -import com.swirlds.common.wiring.model.WiringModel; -import com.swirlds.common.wiring.schedulers.TaskScheduler; -import com.swirlds.common.wiring.schedulers.builders.TaskSchedulerType; -import com.swirlds.common.wiring.wires.input.BindableInputWire; -import com.swirlds.common.wiring.wires.input.InputWire; -import com.swirlds.platform.components.LinkedEventIntake; -import com.swirlds.platform.internal.EventImpl; -import edu.umd.cs.findbugs.annotations.NonNull; - -/** - * Wiring for the {@link LinkedEventIntakeScheduler}. - */ -public class LinkedEventIntakeScheduler { - private final BindableInputWire eventInput; - - /** - * Constructor. - * - * @param model the wiring model - */ - public LinkedEventIntakeScheduler(@NonNull final WiringModel model) { - final TaskScheduler taskScheduler = model.schedulerBuilder("linkedEventIntake") - .withType(TaskSchedulerType.SEQUENTIAL) - .withUnhandledTaskCapacity(500) - .withFlushingEnabled(true) - .withMetricsBuilder(model.metricsBuilder().withUnhandledTaskMetricEnabled(true)) - .build() - .cast(); - - eventInput = taskScheduler.buildInputWire("linked events"); - } - - /** - * Gets the event input wire - * - * @return the event input wire - */ - @NonNull - public InputWire getEventInput() { - return eventInput; - } - - /** - * Bind a linked event intake object to this scheduler. - * - * @param linkedEventIntake the linked event intake to bind - */ - public void bind(@NonNull final LinkedEventIntake linkedEventIntake) { - eventInput.bind(linkedEventIntake::addEvent); - } -} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/LinkedEventIntakeWiring.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/LinkedEventIntakeWiring.java new file mode 100644 index 000000000000..cf25f281eba9 --- /dev/null +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/LinkedEventIntakeWiring.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.platform.wiring; + +import com.swirlds.common.wiring.schedulers.TaskScheduler; +import com.swirlds.common.wiring.wires.input.BindableInputWire; +import com.swirlds.common.wiring.wires.input.InputWire; +import com.swirlds.common.wiring.wires.output.OutputWire; +import com.swirlds.platform.components.LinkedEventIntake; +import com.swirlds.platform.internal.ConsensusRound; +import com.swirlds.platform.internal.EventImpl; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.List; + +/** + * Wiring for the {@link LinkedEventIntake}. + * + * @param eventInput the input wire for events to be added to the hashgraph + * @param consensusRoundOutput the output wire for consensus rounds + * @param minimumGenerationNonAncientOutput the output wire for the minimum generation non-ancient. This output is + * transformed from the consensus round output + * @param flushRunnable the runnable to flush the intake + */ +public record LinkedEventIntakeWiring( + @NonNull InputWire eventInput, + @NonNull OutputWire consensusRoundOutput, + @NonNull OutputWire minimumGenerationNonAncientOutput, + @NonNull Runnable flushRunnable) { + + /** + * Create a new instance of this wiring. + * + * @param taskScheduler the task scheduler for this intake + * @return the new wiring instance + */ + public static LinkedEventIntakeWiring create(@NonNull final TaskScheduler> taskScheduler) { + final OutputWire consensusRoundOutput = + taskScheduler.getOutputWire().buildSplitter(); + + return new LinkedEventIntakeWiring( + taskScheduler.buildInputWire("linked events"), + consensusRoundOutput, + consensusRoundOutput.buildTransformer( + "getMinimumGenerationNonAncient", + consensusRound -> consensusRound.getGenerations().getMinGenerationNonAncient()), + taskScheduler::flush); + } + + /** + * Bind a linked event intake object to this scheduler. + * + * @param linkedEventIntake the linked event intake to bind + */ + public void bind(@NonNull final LinkedEventIntake linkedEventIntake) { + ((BindableInputWire>) eventInput).bind(linkedEventIntake::addEvent); + } +} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/OrphanBufferScheduler.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/OrphanBufferScheduler.java deleted file mode 100644 index c755228ad0a6..000000000000 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/OrphanBufferScheduler.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2023 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swirlds.platform.wiring; - -import com.swirlds.common.wiring.model.WiringModel; -import com.swirlds.common.wiring.schedulers.TaskScheduler; -import com.swirlds.common.wiring.schedulers.builders.TaskSchedulerType; -import com.swirlds.common.wiring.wires.input.BindableInputWire; -import com.swirlds.common.wiring.wires.input.InputWire; -import com.swirlds.common.wiring.wires.output.OutputWire; -import com.swirlds.platform.event.GossipEvent; -import com.swirlds.platform.event.orphan.OrphanBuffer; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.List; - -/** - * Wiring for the {@link OrphanBuffer}. - */ -public class OrphanBufferScheduler { - - private final BindableInputWire> eventInput; - private final BindableInputWire> minimumGenerationNonAncientInput; - - private final OutputWire eventOutput; - - /** - * Constructor. - * - * @param model the wiring model - */ - public OrphanBufferScheduler(@NonNull final WiringModel model) { - final TaskScheduler> taskScheduler = model.schedulerBuilder("orphanBuffer") - .withType(TaskSchedulerType.SEQUENTIAL) - .withUnhandledTaskCapacity(500) - .withFlushingEnabled(true) - .withMetricsBuilder(model.metricsBuilder().withUnhandledTaskMetricEnabled(true)) - .build() - .cast(); - - eventInput = taskScheduler.buildInputWire("unordered events"); - minimumGenerationNonAncientInput = taskScheduler.buildInputWire("minimum generation non ancient"); - - eventOutput = taskScheduler.getOutputWire().buildSplitter(); - } - - /** - * Gets the event input wire. - * - * @return the event input wire - */ - @NonNull - public InputWire getEventInput() { - return eventInput; - } - - /** - * Gets the minimum generation non ancient input wire. - * - * @return the minimum generation non ancient input wire - */ - @NonNull - public InputWire getMinimumGenerationNonAncientInput() { - return minimumGenerationNonAncientInput; - } - - /** - * Get the output of the orphan buffer, i.e. a stream of events in topological order. - * - * @return the event output wire - */ - @NonNull - public OutputWire getEventOutput() { - return eventOutput; - } - - /** - * Bind an orphan buffer to this wiring. - * - * @param orphanBuffer the orphan buffer to bind - */ - public void bind(@NonNull final OrphanBuffer orphanBuffer) { - eventInput.bind(orphanBuffer::handleEvent); - minimumGenerationNonAncientInput.bind(orphanBuffer::setMinimumGenerationNonAncient); - } -} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/OrphanBufferWiring.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/OrphanBufferWiring.java new file mode 100644 index 000000000000..c6e700b9d07f --- /dev/null +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/OrphanBufferWiring.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.platform.wiring; + +import com.swirlds.common.wiring.schedulers.TaskScheduler; +import com.swirlds.common.wiring.wires.input.BindableInputWire; +import com.swirlds.common.wiring.wires.input.InputWire; +import com.swirlds.common.wiring.wires.output.OutputWire; +import com.swirlds.platform.event.GossipEvent; +import com.swirlds.platform.event.orphan.OrphanBuffer; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.List; + +/** + * Wiring for the {@link OrphanBuffer}. + * + * @param eventInput the input wire for unordered events + * @param minimumGenerationNonAncientInput the input wire for the minimum generation non-ancient + * @param pauseInput the input wire for pausing the buffer + * @param eventOutput the output wire for topologically ordered events + * @param flushRunnable the runnable to flush the buffer + */ +public record OrphanBufferWiring( + @NonNull InputWire eventInput, + @NonNull InputWire minimumGenerationNonAncientInput, + @NonNull InputWire pauseInput, + @NonNull OutputWire eventOutput, + @NonNull Runnable flushRunnable) { + + /** + * Create a new instance of this wiring. + * + * @param taskScheduler the task scheduler for this buffer + * @return the new wiring instance + */ + public static OrphanBufferWiring create(@NonNull final TaskScheduler> taskScheduler) { + return new OrphanBufferWiring( + taskScheduler.buildInputWire("unordered events"), + taskScheduler.buildInputWire("minimum generation non ancient"), + taskScheduler.buildInputWire("pause"), + taskScheduler.getOutputWire().buildSplitter(), + taskScheduler::flush); + } + + /** + * Bind an orphan buffer to this wiring. + * + * @param orphanBuffer the orphan buffer to bind + */ + public void bind(@NonNull final OrphanBuffer orphanBuffer) { + ((BindableInputWire>) eventInput).bind(orphanBuffer::handleEvent); + ((BindableInputWire>) minimumGenerationNonAncientInput) + .bind(orphanBuffer::setMinimumGenerationNonAncient); + ((BindableInputWire>) pauseInput).bind(orphanBuffer::setPaused); + } +} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/PlatformSchedulers.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/PlatformSchedulers.java new file mode 100644 index 000000000000..f2d6bf3aa236 --- /dev/null +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/PlatformSchedulers.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.platform.wiring; + +import com.swirlds.common.config.PlatformSchedulersConfig; +import com.swirlds.common.context.PlatformContext; +import com.swirlds.common.wiring.model.WiringModel; +import com.swirlds.common.wiring.schedulers.TaskScheduler; +import com.swirlds.platform.event.GossipEvent; +import com.swirlds.platform.internal.ConsensusRound; +import com.swirlds.platform.internal.EventImpl; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.List; + +/** + * The {@link TaskScheduler}s used by the platform. + * + * @param internalEventValidatorScheduler the scheduler for the internal event validator + * @param eventDeduplicatorScheduler the scheduler for the event deduplicator + * @param eventSignatureValidatorScheduler the scheduler for the event signature validator + * @param orphanBufferScheduler the scheduler for the orphan buffer + * @param inOrderLinkerScheduler the scheduler for the in-order linker + * @param linkedEventIntakeScheduler the scheduler for the linked event intake + */ +public record PlatformSchedulers( + @NonNull TaskScheduler internalEventValidatorScheduler, + @NonNull TaskScheduler eventDeduplicatorScheduler, + @NonNull TaskScheduler eventSignatureValidatorScheduler, + @NonNull TaskScheduler> orphanBufferScheduler, + @NonNull TaskScheduler inOrderLinkerScheduler, + @NonNull TaskScheduler> linkedEventIntakeScheduler) { + + /** + * Instantiate the schedulers for the platform, for the given wiring model + * + * @param context the platform context + * @param model the wiring model + * @return the instantiated platform schedulers + */ + public static PlatformSchedulers create(@NonNull final PlatformContext context, @NonNull final WiringModel model) { + final PlatformSchedulersConfig config = + context.getConfiguration().getConfigData(PlatformSchedulersConfig.class); + + return new PlatformSchedulers( + model.schedulerBuilder("internalEventValidator") + .withType(config.getInternalEventValidatorSchedulerType()) + .withUnhandledTaskCapacity(config.internalEventValidatorUnhandledCapacity()) + .withFlushingEnabled(true) + .withMetricsBuilder(model.metricsBuilder().withUnhandledTaskMetricEnabled(true)) + .build() + .cast(), + model.schedulerBuilder("eventDeduplicator") + .withType(config.getEventDeduplicatorSchedulerType()) + .withUnhandledTaskCapacity(config.eventDeduplicatorUnhandledCapacity()) + .withFlushingEnabled(true) + .withMetricsBuilder(model.metricsBuilder().withUnhandledTaskMetricEnabled(true)) + .build() + .cast(), + model.schedulerBuilder("eventSignatureValidator") + .withType(config.getEventSignatureValidatorSchedulerType()) + .withUnhandledTaskCapacity(config.eventSignatureValidatorUnhandledCapacity()) + .withFlushingEnabled(true) + .withMetricsBuilder(model.metricsBuilder().withUnhandledTaskMetricEnabled(true)) + .build() + .cast(), + model.schedulerBuilder("orphanBuffer") + .withType(config.getOrphanBufferSchedulerType()) + .withUnhandledTaskCapacity(config.orphanBufferUnhandledCapacity()) + .withFlushingEnabled(true) + .withMetricsBuilder(model.metricsBuilder().withUnhandledTaskMetricEnabled(true)) + .build() + .cast(), + model.schedulerBuilder("inOrderLinker") + .withType(config.getInOrderLinkerSchedulerType()) + .withUnhandledTaskCapacity(config.inOrderLinkerUnhandledCapacity()) + .withFlushingEnabled(true) + .withMetricsBuilder(model.metricsBuilder().withUnhandledTaskMetricEnabled(true)) + .build() + .cast(), + model.schedulerBuilder("linkedEventIntake") + .withType(config.getLinkedEventIntakeSchedulerType()) + .withUnhandledTaskCapacity(config.linkedEventIntakeUnhandledCapacity()) + .withFlushingEnabled(true) + .withMetricsBuilder(model.metricsBuilder().withUnhandledTaskMetricEnabled(true)) + .build() + .cast()); + } +} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/PlatformWiring.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/PlatformWiring.java index f80cac8b05b8..24a4cfa1c73d 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/PlatformWiring.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/PlatformWiring.java @@ -16,35 +16,39 @@ package com.swirlds.platform.wiring; +import static com.swirlds.common.wiring.wires.SolderType.INJECT; + import com.swirlds.base.state.Startable; import com.swirlds.base.state.Stoppable; import com.swirlds.base.time.Time; import com.swirlds.common.context.PlatformContext; +import com.swirlds.common.threading.interrupt.InterruptableConsumer; +import com.swirlds.common.utility.Clearable; import com.swirlds.common.wiring.model.WiringModel; +import com.swirlds.common.wiring.wires.output.OutputWire; import com.swirlds.platform.components.LinkedEventIntake; +import com.swirlds.platform.event.GossipEvent; import com.swirlds.platform.event.deduplication.EventDeduplicator; import com.swirlds.platform.event.linking.InOrderLinker; import com.swirlds.platform.event.orphan.OrphanBuffer; +import com.swirlds.platform.event.validation.AddressBookUpdate; import com.swirlds.platform.event.validation.EventSignatureValidator; import com.swirlds.platform.event.validation.InternalEventValidator; import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.function.Consumer; /** * Encapsulates wiring for {@link com.swirlds.platform.SwirldsPlatform}. */ -public class PlatformWiring implements Startable, Stoppable { - +public class PlatformWiring implements Startable, Stoppable, Clearable { private final WiringModel model; - private final InternalEventValidatorScheduler internalEventValidatorScheduler; - private final EventDeduplicatorScheduler eventDeduplicatorScheduler; - private final EventSignatureValidatorScheduler eventSignatureValidatorScheduler; - private final OrphanBufferScheduler orphanBufferScheduler; - private final InOrderLinkerScheduler inOrderLinkerScheduler; - private final LinkedEventIntakeScheduler linkedEventIntakeScheduler; - - private final boolean cyclicalBackpressurePresent; - private final boolean illegalDirectSchedulerUsagePresent; + private final InternalEventValidatorWiring internalEventValidatorWiring; + private final EventDeduplicatorWiring eventDeduplicatorWiring; + private final EventSignatureValidatorWiring eventSignatureValidatorWiring; + private final OrphanBufferWiring orphanBufferWiring; + private final InOrderLinkerWiring inOrderLinkerWiring; + private final LinkedEventIntakeWiring linkedEventIntakeWiring; /** * Constructor. @@ -55,22 +59,18 @@ public class PlatformWiring implements Startable, Stoppable { public PlatformWiring(@NonNull final PlatformContext platformContext, @NonNull final Time time) { model = WiringModel.create(platformContext, time); - internalEventValidatorScheduler = new InternalEventValidatorScheduler(model); - eventDeduplicatorScheduler = new EventDeduplicatorScheduler(model); - eventSignatureValidatorScheduler = new EventSignatureValidatorScheduler(model); - orphanBufferScheduler = new OrphanBufferScheduler(model); - inOrderLinkerScheduler = new InOrderLinkerScheduler(model); - linkedEventIntakeScheduler = new LinkedEventIntakeScheduler(model); - - wire(); + final PlatformSchedulers schedulers = PlatformSchedulers.create(platformContext, model); - // Logs if there is cyclical back pressure. - // Do not throw -- in theory we might survive this, so no need to crash. - cyclicalBackpressurePresent = model.checkForCyclicalBackpressure(); + internalEventValidatorWiring = + InternalEventValidatorWiring.create(schedulers.internalEventValidatorScheduler()); + eventDeduplicatorWiring = EventDeduplicatorWiring.create(schedulers.eventDeduplicatorScheduler()); + eventSignatureValidatorWiring = + EventSignatureValidatorWiring.create(schedulers.eventSignatureValidatorScheduler()); + orphanBufferWiring = OrphanBufferWiring.create(schedulers.orphanBufferScheduler()); + inOrderLinkerWiring = InOrderLinkerWiring.create(schedulers.inOrderLinkerScheduler()); + linkedEventIntakeWiring = LinkedEventIntakeWiring.create(schedulers.linkedEventIntakeScheduler()); - // Logs if there is illegal direct scheduler usage. - // Do not throw -- in theory we might survive this, so no need to crash. - illegalDirectSchedulerUsagePresent = model.checkForIllegalDirectSchedulerUsage(); + wire(); } /** @@ -84,38 +84,36 @@ public WiringModel getModel() { } /** - * Check if cyclical backpressure is present in the model. - * - * @return true if cyclical backpressure is present, false otherwise - */ - public boolean isCyclicalBackpressurePresent() { - return cyclicalBackpressurePresent; - } - - /** - * Check if illegal direct scheduler usage is present in the model. - * - * @return true if illegal direct scheduler usage is present, false otherwise + * Solder the minimum generation non-ancient output to all components that need it. */ - public boolean isIllegalDirectSchedulerUsagePresent() { - return illegalDirectSchedulerUsagePresent; + private void solderMinimumGenerationNonAncient() { + final OutputWire minimumGenerationNonAncientOutput = + linkedEventIntakeWiring.minimumGenerationNonAncientOutput(); + + minimumGenerationNonAncientOutput.solderTo(eventDeduplicatorWiring.minimumGenerationNonAncientInput(), INJECT); + minimumGenerationNonAncientOutput.solderTo( + eventSignatureValidatorWiring.minimumGenerationNonAncientInput(), INJECT); + minimumGenerationNonAncientOutput.solderTo(orphanBufferWiring.minimumGenerationNonAncientInput(), INJECT); + minimumGenerationNonAncientOutput.solderTo(inOrderLinkerWiring.minimumGenerationNonAncientInput(), INJECT); } /** * Wire the components together. */ private void wire() { - internalEventValidatorScheduler.getEventOutput().solderTo(eventDeduplicatorScheduler.getEventInput()); - eventDeduplicatorScheduler.getEventOutput().solderTo(eventSignatureValidatorScheduler.getEventInput()); - eventSignatureValidatorScheduler.getEventOutput().solderTo(orphanBufferScheduler.getEventInput()); - orphanBufferScheduler.getEventOutput().solderTo(inOrderLinkerScheduler.getEventInput()); - inOrderLinkerScheduler.getEventOutput().solderTo(linkedEventIntakeScheduler.getEventInput()); + internalEventValidatorWiring.eventOutput().solderTo(eventDeduplicatorWiring.eventInput()); + eventDeduplicatorWiring.eventOutput().solderTo(eventSignatureValidatorWiring.eventInput()); + eventSignatureValidatorWiring.eventOutput().solderTo(orphanBufferWiring.eventInput()); + orphanBufferWiring.eventOutput().solderTo(inOrderLinkerWiring.eventInput()); + inOrderLinkerWiring.eventOutput().solderTo(linkedEventIntakeWiring.eventInput()); + + solderMinimumGenerationNonAncient(); // FUTURE WORK: solder all the things! } /** - * Bind schedulers to their components. + * Bind components to the wiring. * * @param internalEventValidator the internal event validator to bind * @param eventDeduplicator the event deduplicator to bind @@ -132,16 +130,54 @@ public void bind( @NonNull final InOrderLinker inOrderLinker, @NonNull final LinkedEventIntake linkedEventIntake) { - internalEventValidatorScheduler.bind(internalEventValidator); - eventDeduplicatorScheduler.bind(eventDeduplicator); - eventSignatureValidatorScheduler.bind(eventSignatureValidator); - orphanBufferScheduler.bind(orphanBuffer); - inOrderLinkerScheduler.bind(inOrderLinker); - linkedEventIntakeScheduler.bind(linkedEventIntake); + internalEventValidatorWiring.bind(internalEventValidator); + eventDeduplicatorWiring.bind(eventDeduplicator); + eventSignatureValidatorWiring.bind(eventSignatureValidator); + orphanBufferWiring.bind(orphanBuffer); + inOrderLinkerWiring.bind(inOrderLinker); + linkedEventIntakeWiring.bind(linkedEventIntake); // FUTURE WORK: bind all the things! } + /** + * Get the input method for the internal event validator. + *

    + * Future work: this is a temporary hook to allow events from gossip to use the new intake pipeline. This method + * will be removed once gossip is moved to the new framework + * + * @return the input method for the internal event validator, which is the first step in the intake pipeline + */ + public InterruptableConsumer getEventInput() { + return internalEventValidatorWiring.eventInput()::put; + } + + /** + * Get the input method for the address book update. + *

    + * Future work: this is a temporary hook to update the address book in the new intake pipeline. + * + * @return the input method for the address book update + */ + public Consumer getAddressBookUpdateInput() { + return eventSignatureValidatorWiring.addressBookUpdateInput()::inject; + } + + /** + * Inject a new minimum generation non-ancient on all components that need it. + *

    + * Future work: this is a temporary hook to allow the components to get the minimum generation non-ancient + * during startup. This method will be removed once the components are wired together. + * + * @param minimumGenerationNonAncient the new minimum generation non-ancient + */ + public void updateMinimumGenerationNonAncient(final long minimumGenerationNonAncient) { + eventDeduplicatorWiring.minimumGenerationNonAncientInput().inject(minimumGenerationNonAncient); + eventSignatureValidatorWiring.minimumGenerationNonAncientInput().inject(minimumGenerationNonAncient); + orphanBufferWiring.minimumGenerationNonAncientInput().inject(minimumGenerationNonAncient); + inOrderLinkerWiring.minimumGenerationNonAncientInput().inject(minimumGenerationNonAncient); + } + /** * {@inheritDoc} */ @@ -157,4 +193,35 @@ public void start() { public void stop() { model.stop(); } + + /** + * Flush all the wiring objects + */ + private void flushAll() { + internalEventValidatorWiring.flushRunnable().run(); + eventDeduplicatorWiring.flushRunnable().run(); + eventSignatureValidatorWiring.flushRunnable().run(); + orphanBufferWiring.flushRunnable().run(); + inOrderLinkerWiring.flushRunnable().run(); + linkedEventIntakeWiring.flushRunnable().run(); + } + + /** + * Clear all the wiring objects. + *

    + * This doesn't guarantee that all objects will have nothing in their internal storage, but it does guarantee + * that the objects will no longer be emitting any events or rounds. + */ + @Override + public void clear() { + // pause the orphan buffer to break the cycle, and flush the pause through + orphanBufferWiring.pauseInput().inject(true); + orphanBufferWiring.flushRunnable().run(); + + // now that no cycles exist, flush all the wiring objects + flushAll(); + + // once everything has been flushed through the system, it's safe to unpause the orphan buffer + orphanBufferWiring.pauseInput().inject(false); + } } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/SignedStateFileManagerWiring.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/SignedStateFileManagerWiring.java index 8d1b770b08c4..4f63b33e78cc 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/SignedStateFileManagerWiring.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/wiring/SignedStateFileManagerWiring.java @@ -33,14 +33,14 @@ /** * The wiring for the {@link SignedStateFileManager} * - * @param outputWire the output wire * @param saveStateToDisk the input wire for saving the state to disk * @param dumpStateToDisk the input wire for dumping the state to disk + * @param outputWire the output wire */ public record SignedStateFileManagerWiring( - @NonNull OutputWire outputWire, @NonNull InputWire saveStateToDisk, - @NonNull InputWire dumpStateToDisk) { + @NonNull InputWire dumpStateToDisk, + @NonNull OutputWire outputWire) { /** * Create a new instance of the wiring * @@ -48,9 +48,9 @@ public record SignedStateFileManagerWiring( */ public SignedStateFileManagerWiring(@NonNull final TaskScheduler scheduler) { this( - scheduler.getOutputWire(), scheduler.buildInputWire("save state to disk"), - scheduler.buildInputWire("dump state to disk")); + scheduler.buildInputWire("dump state to disk"), + scheduler.getOutputWire()); } /** diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/event/EventDeduplicatorTests.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/event/EventDeduplicatorTests.java index 2974373e5f12..8b7f6f3a6906 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/event/EventDeduplicatorTests.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/event/EventDeduplicatorTests.java @@ -33,6 +33,7 @@ import com.swirlds.common.system.events.EventDescriptor; import com.swirlds.platform.event.deduplication.EventDeduplicator; import com.swirlds.platform.gossip.IntakeEventCounter; +import com.swirlds.platform.metrics.EventIntakeMetrics; import com.swirlds.test.framework.context.TestPlatformContextBuilder; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; @@ -125,8 +126,8 @@ void standardOperation() { .when(intakeEventCounter) .eventExitedIntakePipeline(any()); - final EventDeduplicator deduplicator = - new EventDeduplicator(TestPlatformContextBuilder.create().build(), intakeEventCounter); + final EventDeduplicator deduplicator = new EventDeduplicator( + TestPlatformContextBuilder.create().build(), intakeEventCounter, mock(EventIntakeMetrics.class)); int duplicateEventCount = 0; int ancientEventCount = 0; diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/reconnect/RandomVirtualMapReconnectTests.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/reconnect/RandomVirtualMapReconnectTests.java index 585b48193e12..3d13268f1398 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/reconnect/RandomVirtualMapReconnectTests.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/reconnect/RandomVirtualMapReconnectTests.java @@ -27,10 +27,10 @@ import com.swirlds.common.crypto.DigestType; import com.swirlds.common.io.utility.TemporaryFileBuilder; import com.swirlds.common.merkle.MerkleInternal; +import com.swirlds.common.test.fixtures.set.RandomAccessHashSet; +import com.swirlds.common.test.fixtures.set.RandomAccessSet; import com.swirlds.common.test.merkle.dummy.DummyMerkleInternal; import com.swirlds.common.test.merkle.util.MerkleTestUtils; -import com.swirlds.common.test.set.RandomAccessHashSet; -import com.swirlds.common.test.set.RandomAccessSet; import com.swirlds.merkledb.MerkleDb; import com.swirlds.merkledb.MerkleDbDataSourceBuilder; import com.swirlds.merkledb.MerkleDbTableConfig; diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/signed/ReservedSignedStateTests.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/signed/ReservedSignedStateTests.java index 23a4ee5f6c44..31b7e1add21a 100644 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/signed/ReservedSignedStateTests.java +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/signed/ReservedSignedStateTests.java @@ -20,6 +20,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -63,7 +65,8 @@ void NonNullStateTest() { final SignedState signedState = new RandomSignedStateGenerator().build(); assertEquals(0, signedState.getReservationCount()); - try (final ReservedSignedState reservedSignedState = new ReservedSignedState(signedState, "reason")) { + try (final ReservedSignedState reservedSignedState = + ReservedSignedState.createAndReserve(signedState, "reason")) { assertSame(signedState, reservedSignedState.get()); assertSame(signedState, reservedSignedState.getNullable()); @@ -105,7 +108,7 @@ void nullBadLifecycleTest() { @DisplayName("Non-Null Bad Lifecycle Test") void nonNullBadLifecycleTest() { final ReservedSignedState reservedSignedState = - new ReservedSignedState(new RandomSignedStateGenerator().build(), "reason"); + ReservedSignedState.createAndReserve(new RandomSignedStateGenerator().build(), "reason"); reservedSignedState.close(); assertThrows(ReferenceCountException.class, reservedSignedState::get); @@ -115,4 +118,38 @@ void nonNullBadLifecycleTest() { assertThrows(ReferenceCountException.class, reservedSignedState::isNotNull); assertThrows(ReferenceCountException.class, reservedSignedState::close); } + + @Test + @DisplayName("Try-reserve Paradigm Test") + void tryReserveTest() { + final SignedState signedState = new RandomSignedStateGenerator().build(); + assertEquals(0, signedState.getReservationCount()); + + final ReservedSignedState reservedSignedState = ReservedSignedState.createAndReserve(signedState, "reason"); + try { + assertEquals(1, signedState.getReservationCount()); + + try (final ReservedSignedState reservedSignedState2 = + reservedSignedState.tryGetAndReserve("successful try")) { + assertNotNull(reservedSignedState2); + assertNotSame(reservedSignedState, reservedSignedState2); + assertSame(signedState, reservedSignedState2.get()); + assertSame(signedState, reservedSignedState2.getNullable()); + assertEquals("successful try", reservedSignedState2.getReason()); + assertFalse(reservedSignedState2.isNull()); + assertTrue(reservedSignedState2.isNotNull()); + assertEquals(2, signedState.getReservationCount()); + + assertNotEquals(reservedSignedState.getReservationId(), reservedSignedState2.getReservationId()); + } + assertEquals(1, signedState.getReservationCount()); + } finally { + reservedSignedState.close(); + } + assertEquals(-1, signedState.getReservationCount()); + try (final ReservedSignedState reservedSignedState2 = reservedSignedState.tryGetAndReserve("failed try")) { + assertNull(reservedSignedState2); + } + assertEquals(-1, signedState.getReservationCount()); + } } diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/signed/SignedStateNexusTest.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/signed/SignedStateNexusTest.java new file mode 100644 index 000000000000..78a75cf2c8e2 --- /dev/null +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/state/signed/SignedStateNexusTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.platform.state.signed; + +import static org.junit.jupiter.api.Assertions.*; + +import com.swirlds.platform.consensus.ConsensusConstants; +import com.swirlds.platform.state.RandomSignedStateGenerator; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +class SignedStateNexusTest { + @Test + void basicUsage() { + final int round = 123; + final ReservedSignedState original = + new RandomSignedStateGenerator().setRound(round).build().reserve("test"); + final SignedStateNexus nexus = new SignedStateNexus(); + + assertNull(nexus.getState("reason"), "Should be null when initialized"); + assertEquals(ConsensusConstants.ROUND_UNDEFINED, nexus.getRound(), "Should be undefined when initialized"); + nexus.setState(original); + + try (final ReservedSignedState get = nexus.getState("reason")) { + assertNotNull(get, "Should not be null"); + assertNotSame(original, get, "Should be a different instance"); + } + assertEquals(round, nexus.getRound(), "Should be set to the round of the state"); + + assertFalse(original.isClosed(), "Should not be closed since its still held by the nexus"); + nexus.setState(realState()); + assertTrue(original.isClosed(), "Should be closed once its replaced"); + + nexus.clear(); + assertNull(nexus.getState("reason")); + assertEquals(ConsensusConstants.ROUND_UNDEFINED, nexus.getRound(), "Should be undefined when cleared"); + } + + @Test + void closedStateTest() { + final SignedStateNexus nexus = new SignedStateNexus(); + final ReservedSignedState reservedSignedState = realState(); + nexus.setState(reservedSignedState); + reservedSignedState.close(); + assertNull( + nexus.getState("reason"), "The nexus has a state, but it cannot be reserved, so it should return null"); + } + + /** + * Tests a race condition where the state is replaced while a thread trying to reserve it. In this case, the nexus + * should reserve the replacement state instead. + */ + @Test + void raceConditionTest() throws InterruptedException { + final SignedStateNexus nexus = new SignedStateNexus(); + + final ReservedSignedState state1 = mockState(); + final CountDownLatch unblockThread = new CountDownLatch(1); + final CountDownLatch threadWaiting = new CountDownLatch(1); + Mockito.when(state1.tryGetAndReserve(Mockito.any())).then(i -> { + threadWaiting.countDown(); + unblockThread.await(); + return null; + }); + final ReservedSignedState state2 = mockState(); + final ReservedSignedState state2child = mockState(); + Mockito.when(state2.tryGetAndReserve(Mockito.any())).thenReturn(state2child); + + final CountDownLatch threadDone = new CountDownLatch(1); + final AtomicReference threadGetResult = new AtomicReference<>(); + + // the nexus should have state1 initially + nexus.setState(state1); + // the background thread will try to reserve state1, but will be blocked the unblockThread latch + new Thread(() -> { + threadGetResult.set(nexus.getState("reason")); + threadDone.countDown(); + }) + .start(); + + // wait for the thread to start trying to reserve the state, fail if it takes too long + assertTrue(threadWaiting.await(5, TimeUnit.SECONDS), "The thread should be waiting for the state"); + // while the thread is waiting to reserve state1, replace it with state2 + nexus.setState(state2); + // unblock the thread + // the nexus should then see that it cannot reserve state1, and that state1 is no longer the current state + // it should then reserve state2 and set the threadGetResult variable + unblockThread.countDown(); + // wait for the thread to finish, fail if it takes too long + assertTrue(threadDone.await(5, TimeUnit.SECONDS), "The thread should have finished"); + // check that the nexus returned the child of state2 + assertSame(state2child, threadGetResult.get(), "The nexus should have returned the child of state2"); + } + + private static ReservedSignedState mockState() { + final ReservedSignedState state = Mockito.mock(ReservedSignedState.class); + final SignedState ss = new RandomSignedStateGenerator().build(); + Mockito.when(state.get()).thenReturn(ss); + return state; + } + + private static ReservedSignedState realState() { + return new RandomSignedStateGenerator().build().reserve("test"); + } +} diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/wiring/PlatformWiringTests.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/wiring/PlatformWiringTests.java new file mode 100644 index 000000000000..99b6857cbf6c --- /dev/null +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/wiring/PlatformWiringTests.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.platform.wiring; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.mockito.Mockito.mock; + +import com.swirlds.base.test.fixtures.time.FakeTime; +import com.swirlds.platform.components.LinkedEventIntake; +import com.swirlds.platform.event.deduplication.EventDeduplicator; +import com.swirlds.platform.event.linking.InOrderLinker; +import com.swirlds.platform.event.orphan.OrphanBuffer; +import com.swirlds.platform.event.validation.EventSignatureValidator; +import com.swirlds.platform.event.validation.InternalEventValidator; +import com.swirlds.test.framework.context.TestPlatformContextBuilder; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {@link PlatformWiring} + */ +class PlatformWiringTests { + @Test + @DisplayName("Assert that all input wires are bound to something") + void testBindings() { + final PlatformWiring wiring = + new PlatformWiring(TestPlatformContextBuilder.create().build(), new FakeTime()); + + wiring.bind( + mock(InternalEventValidator.class), + mock(EventDeduplicator.class), + mock(EventSignatureValidator.class), + mock(OrphanBuffer.class), + mock(InOrderLinker.class), + mock(LinkedEventIntake.class)); + + assertFalse(wiring.getModel().checkForUnboundInputWires()); + } +} diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/wiring/WiringTests.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/wiring/WiringTests.java deleted file mode 100644 index e3f61c274490..000000000000 --- a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/wiring/WiringTests.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2023 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swirlds.platform.wiring; - -import static org.junit.jupiter.api.Assertions.assertFalse; - -import com.swirlds.base.time.Time; -import com.swirlds.common.context.PlatformContext; -import com.swirlds.test.framework.context.TestPlatformContextBuilder; -import org.junit.jupiter.api.Test; - -class WiringTests { - - @Test - void cyclicalBackpressureTest() { - final PlatformContext context = TestPlatformContextBuilder.create().build(); - final PlatformWiring wiring = new PlatformWiring(context, Time.getCurrent()); - - assertFalse(wiring.isCyclicalBackpressurePresent(), "cyclical back pressure detected"); - } - - @Test - void illegalDirectSchedulerAccessTest() { - final PlatformContext context = TestPlatformContextBuilder.create().build(); - final PlatformWiring wiring = new PlatformWiring(context, Time.getCurrent()); - - assertFalse(wiring.isIllegalDirectSchedulerUsagePresent(), "illegal direct scheduler usage detected"); - } -} diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/build.gradle.kts b/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/build.gradle.kts index 9a9e219a5e8f..47e68966f3d4 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/build.gradle.kts +++ b/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/build.gradle.kts @@ -24,7 +24,6 @@ testModuleInfo { requires("com.swirlds.common.test.fixtures") requires("com.swirlds.config.api") requires("com.swirlds.test.framework") - requires("org.assertj.core") requires("org.junit.jupiter.params") requires("org.mockito") requiresStatic("com.github.spotbugs.annotations") diff --git a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/module-info.java b/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/module-info.java index a8da5d711997..94d72a2c91f1 100644 --- a/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/module-info.java +++ b/platform-sdk/swirlds-unit-tests/common/swirlds-common-test/src/main/java/module-info.java @@ -1,10 +1,6 @@ open module com.swirlds.common.testing { exports com.swirlds.common.test.merkle.util; exports com.swirlds.common.test.merkle.dummy; - exports com.swirlds.common.test.dummy; - exports com.swirlds.common.test.benchmark; - exports com.swirlds.common.test.set; - exports com.swirlds.common.test.map; requires transitive com.swirlds.common; requires transitive org.apache.logging.log4j.core; diff --git a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/event/preconsensus/PreconsensusEventReplayPipelineTests.java b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/event/preconsensus/PreconsensusEventReplayPipelineTests.java index 43fabef042d0..dd20d8cc317f 100644 --- a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/event/preconsensus/PreconsensusEventReplayPipelineTests.java +++ b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/event/preconsensus/PreconsensusEventReplayPipelineTests.java @@ -197,7 +197,7 @@ void basicBehaviorTest() { .validateEvent(any()); final PreconsensusEventReplayPipeline pipeline = new PreconsensusEventReplayPipeline( - platformContext, threadManager, buildIOIterator(events), eventValidator); + platformContext, threadManager, buildIOIterator(events), eventValidator::validateEvent); pipeline.replayEvents(); @@ -265,7 +265,7 @@ void hashFailureTest() { .validateEvent(any()); final PreconsensusEventReplayPipeline pipeline = new PreconsensusEventReplayPipeline( - platformContext, threadManager, buildIOIterator(events), eventValidator); + platformContext, threadManager, buildIOIterator(events), eventValidator::validateEvent); assertThrows(IllegalStateException.class, pipeline::replayEvents); @@ -333,7 +333,7 @@ void ingestFailureTest() { .validateEvent(any()); final PreconsensusEventReplayPipeline pipeline = new PreconsensusEventReplayPipeline( - platformContext, threadManager, buildIOIterator(events), eventValidator); + platformContext, threadManager, buildIOIterator(events), eventValidator::validateEvent); assertThrows(IllegalStateException.class, pipeline::replayEvents); @@ -395,7 +395,10 @@ void parseFailureTest() { .validateEvent(any()); final PreconsensusEventReplayPipeline pipeline = new PreconsensusEventReplayPipeline( - platformContext, threadManager, buildThrowingIOIterator(events, eventCount / 2), eventValidator); + platformContext, + threadManager, + buildThrowingIOIterator(events, eventCount / 2), + eventValidator::validateEvent); assertThrows(UncheckedIOException.class, pipeline::replayEvents); diff --git a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/event/preconsensus/PreconsensusEventReplayWorkflowTests.java b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/event/preconsensus/PreconsensusEventReplayWorkflowTests.java index 4a993ec3385f..7a3bf0a521b5 100644 --- a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/event/preconsensus/PreconsensusEventReplayWorkflowTests.java +++ b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/event/preconsensus/PreconsensusEventReplayWorkflowTests.java @@ -170,7 +170,7 @@ void testBasicReplayWorkflow() throws InterruptedException { Time.getCurrent(), preconsensusEventFileManager, preconsensusEventWriter, - eventValidator, + eventValidator::validateEvent, eventIntakeTaskQueueThread, consensusRoundHandler, stateHashSignQueue, diff --git a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssHandlerTests.java b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssHandlerTests.java index e8f85f3536a0..c5d495ccc13d 100644 --- a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssHandlerTests.java +++ b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssHandlerTests.java @@ -17,16 +17,11 @@ package com.swirlds.platform.test.state; import static com.swirlds.common.test.fixtures.RandomUtils.randomHash; -import static com.swirlds.platform.state.signed.StateToDiskReason.ISS; -import static com.swirlds.platform.test.DispatchBuilderUtils.getDefaultDispatchConfiguration; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; -import com.swirlds.base.time.Time; import com.swirlds.common.config.StateConfig; import com.swirlds.common.crypto.Hash; import com.swirlds.common.merkle.utility.SerializableLong; @@ -36,12 +31,9 @@ import com.swirlds.config.api.Configuration; import com.swirlds.platform.components.common.output.FatalErrorConsumer; import com.swirlds.platform.components.state.output.IssConsumer; -import com.swirlds.platform.dispatch.DispatchBuilder; import com.swirlds.platform.dispatch.triggers.control.HaltRequestedConsumer; -import com.swirlds.platform.dispatch.triggers.control.StateDumpRequestedTrigger; import com.swirlds.platform.state.iss.IssHandler; import com.swirlds.platform.state.iss.IssScratchpad; -import com.swirlds.platform.state.signed.StateToDiskReason; import com.swirlds.platform.test.fixtures.SimpleScratchpad; import com.swirlds.test.framework.config.TestConfigBuilder; import java.util.concurrent.atomic.AtomicInteger; @@ -54,33 +46,21 @@ class IssHandlerTests { @Test @DisplayName("Hash Disagreement From Self") void hashDisagreementFromSelf() { - final DispatchBuilder dispatchBuilder = new DispatchBuilder(getDefaultDispatchConfiguration()); - final Configuration configuration = new TestConfigBuilder() - .withValue("state.haltOnAnyIss", true) - .withValue("state.dumpStateOnAnyISS", true) - .getOrCreateConfig(); + final Configuration configuration = + new TestConfigBuilder().withValue("state.haltOnAnyIss", true).getOrCreateConfig(); final StateConfig stateConfig = configuration.getConfigData(StateConfig.class); final long selfId = 0; - final AtomicInteger dumpCount = new AtomicInteger(); final AtomicInteger freezeCount = new AtomicInteger(); final AtomicInteger shutdownCount = new AtomicInteger(); - dispatchBuilder.registerObserver( - this, - StateDumpRequestedTrigger.class, - (final Long round, final StateToDiskReason reason, final Boolean blocking) -> - dumpCount.getAndIncrement()); - final HaltRequestedConsumer haltRequestedConsumer = (final String reason) -> freezeCount.getAndIncrement(); final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); final IssHandler handler = new IssHandler( - Time.getCurrent(), - dispatchBuilder, stateConfig, new NodeId(selfId), mock(StatusActionSubmitter.class), @@ -89,11 +69,8 @@ void hashDisagreementFromSelf() { (r, type, otherId) -> {}, simpleScratchpad); - dispatchBuilder.start(); - handler.stateHashValidityObserver(1234L, new NodeId(selfId), randomHash(), randomHash()); - assertEquals(0, dumpCount.get(), "unexpected dump count"); assertEquals(0, freezeCount.get(), "unexpected freeze count"); assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); assertNull(simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND)); @@ -102,36 +79,20 @@ void hashDisagreementFromSelf() { @Test @DisplayName("Hash Disagreement Always Freeze") void hashDisagreementAlwaysFreeze() { - final DispatchBuilder dispatchBuilder = new DispatchBuilder(getDefaultDispatchConfiguration()); - - final Configuration configuration = new TestConfigBuilder() - .withValue("state.haltOnAnyIss", true) - .withValue("state.dumpStateOnAnyISS", false) - .getOrCreateConfig(); + final Configuration configuration = + new TestConfigBuilder().withValue("state.haltOnAnyIss", true).getOrCreateConfig(); final StateConfig stateConfig = configuration.getConfigData(StateConfig.class); final long selfId = 0; - final AtomicInteger dumpCount = new AtomicInteger(); final AtomicInteger freezeCount = new AtomicInteger(); final AtomicInteger shutdownCount = new AtomicInteger(); - dispatchBuilder.registerObserver( - this, - StateDumpRequestedTrigger.class, - (final Long round, final StateToDiskReason reason, final Boolean blocking) -> { - assertEquals(ISS, reason, "state dump reason is important, effects file path"); - assertFalse(blocking, "no need to block if we are going to freeze"); - dumpCount.getAndIncrement(); - }); - final HaltRequestedConsumer haltRequestedConsumer = (final String reason) -> freezeCount.getAndIncrement(); final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); final IssHandler handler = new IssHandler( - Time.getCurrent(), - dispatchBuilder, stateConfig, new NodeId(selfId), mock(StatusActionSubmitter.class), @@ -140,18 +101,14 @@ void hashDisagreementAlwaysFreeze() { (r, type, otherId) -> {}, simpleScratchpad); - dispatchBuilder.start(); - handler.stateHashValidityObserver(1234L, new NodeId(selfId + 1), randomHash(), randomHash()); - assertEquals(1, dumpCount.get(), "unexpected dump count"); assertEquals(1, freezeCount.get(), "unexpected freeze count"); assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); // Once frozen, this should become a no-op handler.stateHashValidityObserver(1234L, new NodeId(selfId + 1), randomHash(), randomHash()); - assertEquals(1, dumpCount.get(), "unexpected dump count"); assertEquals(1, freezeCount.get(), "unexpected freeze count"); assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); @@ -159,94 +116,23 @@ void hashDisagreementAlwaysFreeze() { assertNull(simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND)); } - @Test - @DisplayName("Hash Disagreement Always Freeze") - void hashDisagreementAlwaysDump() { - final DispatchBuilder dispatchBuilder = new DispatchBuilder(getDefaultDispatchConfiguration()); - final Configuration configuration = new TestConfigBuilder() - .withValue("state.haltOnAnyIss", false) - .withValue("state.dumpStateOnAnyISS", true) - .getOrCreateConfig(); - final StateConfig stateConfig = configuration.getConfigData(StateConfig.class); - final long selfId = 0; - - final AtomicInteger dumpCount = new AtomicInteger(); - final AtomicInteger freezeCount = new AtomicInteger(); - final AtomicInteger shutdownCount = new AtomicInteger(); - - dispatchBuilder.registerObserver( - this, - StateDumpRequestedTrigger.class, - (final Long round, final StateToDiskReason reason, final Boolean blocking) -> { - assertEquals(ISS, reason, "state dump reason is important, effects file path"); - assertFalse(blocking, "no need to block"); - dumpCount.getAndIncrement(); - }); - - final HaltRequestedConsumer haltRequestedConsumer = (final String reason) -> freezeCount.getAndIncrement(); - - final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); - - final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); - final IssHandler handler = new IssHandler( - Time.getCurrent(), - dispatchBuilder, - stateConfig, - new NodeId(selfId), - mock(StatusActionSubmitter.class), - haltRequestedConsumer, - fatalErrorConsumer, - (r, type, otherId) -> {}, - simpleScratchpad); - - dispatchBuilder.start(); - - handler.stateHashValidityObserver(1234L, new NodeId(selfId + 1), randomHash(), randomHash()); - - assertEquals(1, dumpCount.get(), "unexpected dump count"); - assertEquals(0, freezeCount.get(), "unexpected freeze count"); - assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); - - // Throttle should prevent double dumping - handler.stateHashValidityObserver(1234L, new NodeId(selfId + 1), randomHash(), randomHash()); - - assertEquals(1, dumpCount.get(), "unexpected dump count"); - assertEquals(0, freezeCount.get(), "unexpected freeze count"); - assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); - - // Another node ISSed, we will not record that on the scratchpad. - assertNull(simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND)); - } - @Test @DisplayName("Hash Disagreement No Action") void hashDisagreementNoAction() { - final DispatchBuilder dispatchBuilder = new DispatchBuilder(getDefaultDispatchConfiguration()); - final Configuration configuration = new TestConfigBuilder() - .withValue("state.haltOnAnyIss", false) - .withValue("state.dumpStateOnAnyISS", false) - .getOrCreateConfig(); + final Configuration configuration = + new TestConfigBuilder().withValue("state.haltOnAnyIss", false).getOrCreateConfig(); final StateConfig stateConfig = configuration.getConfigData(StateConfig.class); final long selfId = 0; - final AtomicInteger dumpCount = new AtomicInteger(); final AtomicInteger freezeCount = new AtomicInteger(); final AtomicInteger shutdownCount = new AtomicInteger(); - dispatchBuilder.registerObserver( - this, - StateDumpRequestedTrigger.class, - (final Long round, final StateToDiskReason reason, final Boolean blocking) -> - dumpCount.getAndIncrement()); - final HaltRequestedConsumer haltRequestedConsumer = (final String reason) -> freezeCount.getAndIncrement(); final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); final IssHandler handler = new IssHandler( - Time.getCurrent(), - dispatchBuilder, stateConfig, new NodeId(selfId), mock(StatusActionSubmitter.class), @@ -255,109 +141,33 @@ void hashDisagreementNoAction() { (r, type, otherId) -> {}, simpleScratchpad); - dispatchBuilder.start(); - handler.stateHashValidityObserver(1234L, new NodeId(selfId + 1), randomHash(), randomHash()); - assertEquals(0, dumpCount.get(), "unexpected dump count"); assertEquals(0, freezeCount.get(), "unexpected freeze count"); assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); assertNull(simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND)); } - @Test - @DisplayName("Hash Disagreement Always Freeze") - void hashDisagreementFreezeAndDump() { - final DispatchBuilder dispatchBuilder = new DispatchBuilder(getDefaultDispatchConfiguration()); - final Configuration configuration = new TestConfigBuilder() - .withValue("state.haltOnAnyIss", true) - .withValue("state.dumpStateOnAnyISS", true) - .getOrCreateConfig(); - final StateConfig stateConfig = configuration.getConfigData(StateConfig.class); - final long selfId = 0; - - final AtomicInteger dumpCount = new AtomicInteger(); - final AtomicInteger freezeCount = new AtomicInteger(); - final AtomicInteger shutdownCount = new AtomicInteger(); - - dispatchBuilder.registerObserver( - this, - StateDumpRequestedTrigger.class, - (final Long round, final StateToDiskReason reason, final Boolean blocking) -> { - assertEquals(ISS, reason, "state dump reason is important, effects file path"); - assertFalse(blocking, "no need to block if we are going to freeze"); - dumpCount.getAndIncrement(); - }); - - final HaltRequestedConsumer haltRequestedConsumer = (final String reason) -> freezeCount.getAndIncrement(); - - final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); - - final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); - final IssHandler handler = new IssHandler( - Time.getCurrent(), - dispatchBuilder, - stateConfig, - new NodeId(selfId), - mock(StatusActionSubmitter.class), - haltRequestedConsumer, - fatalErrorConsumer, - (r, type, otherId) -> {}, - simpleScratchpad); - - dispatchBuilder.start(); - - handler.stateHashValidityObserver(1234L, new NodeId(selfId + 1), randomHash(), randomHash()); - - assertEquals(1, dumpCount.get(), "unexpected dump count"); - assertEquals(1, freezeCount.get(), "unexpected freeze count"); - assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); - - // Once frozen, this should become a no-op - handler.stateHashValidityObserver(1234L, new NodeId(selfId + 1), randomHash(), randomHash()); - - assertEquals(1, dumpCount.get(), "unexpected dump count"); - assertEquals(1, freezeCount.get(), "unexpected freeze count"); - assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); - - // Another node ISSed, we will not record that on the scratchpad. - assertNull(simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND)); - } - @Test @DisplayName("Self ISS Automated Recovery") void selfIssAutomatedRecovery() { - final DispatchBuilder dispatchBuilder = new DispatchBuilder(getDefaultDispatchConfiguration()); final Configuration configuration = new TestConfigBuilder() .withValue("state.haltOnAnyIss", false) - .withValue("state.dumpStateOnAnyISS", false) .withValue("state.automatedSelfIssRecovery", true) .getOrCreateConfig(); final StateConfig stateConfig = configuration.getConfigData(StateConfig.class); final long selfId = 0; - final AtomicInteger dumpCount = new AtomicInteger(); final AtomicInteger freezeCount = new AtomicInteger(); final AtomicInteger shutdownCount = new AtomicInteger(); - dispatchBuilder.registerObserver( - this, - StateDumpRequestedTrigger.class, - (final Long round, final StateToDiskReason reason, final Boolean blocking) -> { - assertEquals(ISS, reason, "state dump reason is important, effects file path"); - assertTrue(blocking, "should block before shutdown"); - dumpCount.getAndIncrement(); - }); - final HaltRequestedConsumer haltRequestedConsumer = (final String reason) -> freezeCount.getAndIncrement(); final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); final IssHandler handler = new IssHandler( - Time.getCurrent(), - dispatchBuilder, stateConfig, new NodeId(selfId), mock(StatusActionSubmitter.class), @@ -366,11 +176,8 @@ void selfIssAutomatedRecovery() { (r, type, otherId) -> {}, simpleScratchpad); - dispatchBuilder.start(); - handler.selfIssObserver(1234L, randomHash(), randomHash()); - assertEquals(1, dumpCount.get(), "unexpected dump count"); assertEquals(0, freezeCount.get(), "unexpected freeze count"); assertEquals(1, shutdownCount.get(), "unexpected shutdown count"); @@ -382,33 +189,22 @@ void selfIssAutomatedRecovery() { @Test @DisplayName("Self ISS No Action") void selfIssNoAction() { - final DispatchBuilder dispatchBuilder = new DispatchBuilder(getDefaultDispatchConfiguration()); final Configuration configuration = new TestConfigBuilder() .withValue("state.haltOnAnyIss", false) - .withValue("state.dumpStateOnAnyISS", false) .withValue("state.automatedSelfIssRecovery", false) .getOrCreateConfig(); final StateConfig stateConfig = configuration.getConfigData(StateConfig.class); final long selfId = 0; - final AtomicInteger dumpCount = new AtomicInteger(); final AtomicInteger freezeCount = new AtomicInteger(); final AtomicInteger shutdownCount = new AtomicInteger(); - dispatchBuilder.registerObserver( - this, - StateDumpRequestedTrigger.class, - (final Long round, final StateToDiskReason reason, final Boolean blocking) -> - dumpCount.getAndIncrement()); - final HaltRequestedConsumer haltRequestedConsumer = (final String reason) -> freezeCount.getAndIncrement(); final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); final IssHandler handler = new IssHandler( - Time.getCurrent(), - dispatchBuilder, stateConfig, new NodeId(selfId), mock(StatusActionSubmitter.class), @@ -417,11 +213,8 @@ void selfIssNoAction() { (r, type, otherId) -> {}, simpleScratchpad); - dispatchBuilder.start(); - handler.selfIssObserver(1234L, randomHash(), randomHash()); - assertEquals(0, dumpCount.get(), "unexpected dump count"); assertEquals(0, freezeCount.get(), "unexpected freeze count"); assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); @@ -433,36 +226,22 @@ void selfIssNoAction() { @Test @DisplayName("Self ISS Always Freeze") void selfIssAlwaysFreeze() { - final DispatchBuilder dispatchBuilder = new DispatchBuilder(getDefaultDispatchConfiguration()); final Configuration configuration = new TestConfigBuilder() .withValue("state.haltOnAnyIss", true) - .withValue("state.dumpStateOnAnyISS", false) .withValue("state.automatedSelfIssRecovery", false) .getOrCreateConfig(); final StateConfig stateConfig = configuration.getConfigData(StateConfig.class); final long selfId = 0; - final AtomicInteger dumpCount = new AtomicInteger(); final AtomicInteger freezeCount = new AtomicInteger(); final AtomicInteger shutdownCount = new AtomicInteger(); - dispatchBuilder.registerObserver( - this, - StateDumpRequestedTrigger.class, - (final Long round, final StateToDiskReason reason, final Boolean blocking) -> { - assertEquals(ISS, reason, "state dump reason is important, effects file path"); - assertFalse(blocking, "no need to block if we are going to freeze"); - dumpCount.getAndIncrement(); - }); - final HaltRequestedConsumer haltRequestedConsumer = (final String reason) -> freezeCount.getAndIncrement(); final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); final IssHandler handler = new IssHandler( - Time.getCurrent(), - dispatchBuilder, stateConfig, new NodeId(selfId), mock(StatusActionSubmitter.class), @@ -471,18 +250,14 @@ void selfIssAlwaysFreeze() { (r, type, otherId) -> {}, simpleScratchpad); - dispatchBuilder.start(); - handler.selfIssObserver(1234L, randomHash(), randomHash()); - assertEquals(1, dumpCount.get(), "unexpected dump count"); assertEquals(1, freezeCount.get(), "unexpected freeze count"); assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); // Once frozen, this should become a no-op handler.selfIssObserver(1234L, randomHash(), randomHash()); - assertEquals(1, dumpCount.get(), "unexpected dump count"); assertEquals(1, freezeCount.get(), "unexpected freeze count"); assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); @@ -491,97 +266,25 @@ void selfIssAlwaysFreeze() { assertEquals(issRound.getValue(), 1234L); } - @Test - @DisplayName("Self ISS Always Dump") - void selfIssAlwaysDump() { - final DispatchBuilder dispatchBuilder = new DispatchBuilder(getDefaultDispatchConfiguration()); - final Configuration configuration = new TestConfigBuilder() - .withValue("state.haltOnAnyIss", false) - .withValue("state.dumpStateOnAnyISS", true) - .withValue("state.automatedSelfIssRecovery", false) - .getOrCreateConfig(); - final StateConfig stateConfig = configuration.getConfigData(StateConfig.class); - final long selfId = 0; - - final AtomicInteger dumpCount = new AtomicInteger(); - final AtomicInteger freezeCount = new AtomicInteger(); - final AtomicInteger shutdownCount = new AtomicInteger(); - - dispatchBuilder.registerObserver( - this, - StateDumpRequestedTrigger.class, - (final Long round, final StateToDiskReason reason, final Boolean blocking) -> { - assertEquals(ISS, reason, "state dump reason is important, effects file path"); - assertFalse(blocking, "no need to block"); - dumpCount.getAndIncrement(); - }); - - final HaltRequestedConsumer haltRequestedConsumer = (final String reason) -> freezeCount.getAndIncrement(); - - final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); - - final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); - final IssHandler handler = new IssHandler( - Time.getCurrent(), - dispatchBuilder, - stateConfig, - new NodeId(selfId), - mock(StatusActionSubmitter.class), - haltRequestedConsumer, - fatalErrorConsumer, - (r, type, otherId) -> {}, - simpleScratchpad); - - dispatchBuilder.start(); - - handler.selfIssObserver(1234L, randomHash(), randomHash()); - - assertEquals(1, dumpCount.get(), "unexpected dump count"); - assertEquals(0, freezeCount.get(), "unexpected freeze count"); - assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); - - // Rate limiter should prevent double dump - handler.selfIssObserver(1234L, randomHash(), randomHash()); - - assertEquals(1, dumpCount.get(), "unexpected dump count"); - assertEquals(0, freezeCount.get(), "unexpected freeze count"); - assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); - - final SerializableLong issRound = simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND); - assertNotNull(issRound); - assertEquals(issRound.getValue(), 1234L); - } - @Test @DisplayName("Catastrophic ISS No Action") void catastrophicIssNoAction() { - final DispatchBuilder dispatchBuilder = new DispatchBuilder(getDefaultDispatchConfiguration()); final Configuration configuration = new TestConfigBuilder() .withValue("state.haltOnAnyIss", false) - .withValue("state.dumpStateOnAnyISS", false) .withValue("state.haltOnCatastrophicIss", false) .getOrCreateConfig(); final StateConfig stateConfig = configuration.getConfigData(StateConfig.class); final long selfId = 0; - final AtomicInteger dumpCount = new AtomicInteger(); final AtomicInteger freezeCount = new AtomicInteger(); final AtomicInteger shutdownCount = new AtomicInteger(); - dispatchBuilder.registerObserver( - this, - StateDumpRequestedTrigger.class, - (final Long round, final StateToDiskReason reason, final Boolean blocking) -> - dumpCount.getAndIncrement()); - final HaltRequestedConsumer haltRequestedConsumer = (final String reason) -> freezeCount.getAndIncrement(); final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); final IssHandler handler = new IssHandler( - Time.getCurrent(), - dispatchBuilder, stateConfig, new NodeId(selfId), mock(StatusActionSubmitter.class), @@ -590,11 +293,8 @@ void catastrophicIssNoAction() { (r, type, otherId) -> {}, simpleScratchpad); - dispatchBuilder.start(); - handler.catastrophicIssObserver(1234L, mock(Hash.class)); - assertEquals(0, dumpCount.get(), "unexpected dump count"); assertEquals(0, freezeCount.get(), "unexpected freeze count"); assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); @@ -606,36 +306,22 @@ void catastrophicIssNoAction() { @Test @DisplayName("Catastrophic ISS Always Freeze") void catastrophicIssAlwaysFreeze() { - final DispatchBuilder dispatchBuilder = new DispatchBuilder(getDefaultDispatchConfiguration()); final Configuration configuration = new TestConfigBuilder() .withValue("state.haltOnAnyIss", true) - .withValue("state.dumpStateOnAnyISS", false) .withValue("state.haltOnCatastrophicIss", false) .getOrCreateConfig(); final StateConfig stateConfig = configuration.getConfigData(StateConfig.class); final long selfId = 0; - final AtomicInteger dumpCount = new AtomicInteger(); final AtomicInteger freezeCount = new AtomicInteger(); final AtomicInteger shutdownCount = new AtomicInteger(); - dispatchBuilder.registerObserver( - this, - StateDumpRequestedTrigger.class, - (final Long round, final StateToDiskReason reason, final Boolean blocking) -> { - assertEquals(ISS, reason, "state dump reason is important, effects file path"); - assertFalse(blocking, "no need to block if we are going to freeze"); - dumpCount.getAndIncrement(); - }); - final HaltRequestedConsumer haltRequestedConsumer = (final String reason) -> freezeCount.getAndIncrement(); final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); final IssHandler handler = new IssHandler( - Time.getCurrent(), - dispatchBuilder, stateConfig, new NodeId(selfId), mock(StatusActionSubmitter.class), @@ -644,18 +330,14 @@ void catastrophicIssAlwaysFreeze() { (r, type, otherId) -> {}, simpleScratchpad); - dispatchBuilder.start(); - handler.catastrophicIssObserver(1234L, mock(Hash.class)); - assertEquals(1, dumpCount.get(), "unexpected dump count"); assertEquals(1, freezeCount.get(), "unexpected freeze count"); assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); // Once frozen, this should become a no-op handler.catastrophicIssObserver(1234L, mock(Hash.class)); - assertEquals(1, dumpCount.get(), "unexpected dump count"); assertEquals(1, freezeCount.get(), "unexpected freeze count"); assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); @@ -667,36 +349,22 @@ void catastrophicIssAlwaysFreeze() { @Test @DisplayName("Catastrophic ISS Freeze On Catastrophic") void catastrophicIssFreezeOnCatastrophic() { - final DispatchBuilder dispatchBuilder = new DispatchBuilder(getDefaultDispatchConfiguration()); final Configuration configuration = new TestConfigBuilder() .withValue("state.haltOnAnyIss", false) - .withValue("state.dumpStateOnAnyISS", false) .withValue("state.haltOnCatastrophicIss", true) .getOrCreateConfig(); final StateConfig stateConfig = configuration.getConfigData(StateConfig.class); final long selfId = 0; - final AtomicInteger dumpCount = new AtomicInteger(); final AtomicInteger freezeCount = new AtomicInteger(); final AtomicInteger shutdownCount = new AtomicInteger(); - dispatchBuilder.registerObserver( - this, - StateDumpRequestedTrigger.class, - (final Long round, final StateToDiskReason reason, final Boolean blocking) -> { - assertEquals(ISS, reason, "state dump reason is important, effects file path"); - assertFalse(blocking, "no need to block if we are going to freeze"); - dumpCount.getAndIncrement(); - }); - final HaltRequestedConsumer haltRequestedConsumer = (final String reason) -> freezeCount.getAndIncrement(); final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); final IssHandler handler = new IssHandler( - Time.getCurrent(), - dispatchBuilder, stateConfig, new NodeId(selfId), mock(StatusActionSubmitter.class), @@ -705,18 +373,14 @@ void catastrophicIssFreezeOnCatastrophic() { (r, type, otherId) -> {}, simpleScratchpad); - dispatchBuilder.start(); - handler.catastrophicIssObserver(1234L, mock(Hash.class)); - assertEquals(1, dumpCount.get(), "unexpected dump count"); assertEquals(1, freezeCount.get(), "unexpected freeze count"); assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); // Once frozen, this should become a no-op handler.catastrophicIssObserver(1234L, mock(Hash.class)); - assertEquals(1, dumpCount.get(), "unexpected dump count"); assertEquals(1, freezeCount.get(), "unexpected freeze count"); assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); @@ -725,67 +389,6 @@ void catastrophicIssFreezeOnCatastrophic() { assertEquals(issRound.getValue(), 1234L); } - @Test - @DisplayName("Catastrophic ISS Always Dump") - void catastrophicIssAlwaysDump() { - final DispatchBuilder dispatchBuilder = new DispatchBuilder(getDefaultDispatchConfiguration()); - final Configuration configuration = new TestConfigBuilder() - .withValue("state.haltOnAnyIss", false) - .withValue("state.dumpStateOnAnyISS", true) - .withValue("state.haltOnCatastrophicIss", false) - .getOrCreateConfig(); - final StateConfig stateConfig = configuration.getConfigData(StateConfig.class); - final long selfId = 0; - - final AtomicInteger dumpCount = new AtomicInteger(); - final AtomicInteger freezeCount = new AtomicInteger(); - final AtomicInteger shutdownCount = new AtomicInteger(); - - dispatchBuilder.registerObserver( - this, - StateDumpRequestedTrigger.class, - (final Long round, final StateToDiskReason reason, final Boolean blocking) -> { - assertEquals(ISS, reason, "state dump reason is important, effects file path"); - assertFalse(blocking, "no need to block"); - dumpCount.getAndIncrement(); - }); - - final HaltRequestedConsumer haltRequestedConsumer = (final String reason) -> freezeCount.getAndIncrement(); - - final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); - - final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); - final IssHandler handler = new IssHandler( - Time.getCurrent(), - dispatchBuilder, - stateConfig, - new NodeId(selfId), - mock(StatusActionSubmitter.class), - haltRequestedConsumer, - fatalErrorConsumer, - (r, type, otherId) -> {}, - simpleScratchpad); - - dispatchBuilder.start(); - - handler.catastrophicIssObserver(1234L, mock(Hash.class)); - - assertEquals(1, dumpCount.get(), "unexpected dump count"); - assertEquals(0, freezeCount.get(), "unexpected freeze count"); - assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); - - // Throttle should prevent double dump - handler.catastrophicIssObserver(1234L, mock(Hash.class)); - - assertEquals(1, dumpCount.get(), "unexpected dump count"); - assertEquals(0, freezeCount.get(), "unexpected freeze count"); - assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); - - final SerializableLong issRound = simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND); - assertNotNull(issRound); - assertEquals(issRound.getValue(), 1234L); - } - @Test @DisplayName("Notifications Test") void issConsumerTest() { @@ -800,12 +403,9 @@ void issConsumerTest() { } }; - final DispatchBuilder dispatchBuilder = new DispatchBuilder(getDefaultDispatchConfiguration()); final Configuration configuration = new TestConfigBuilder().getOrCreateConfig(); final StateConfig stateConfig = configuration.getConfigData(StateConfig.class); final IssHandler issHandler = new IssHandler( - Time.getCurrent(), - dispatchBuilder, stateConfig, new NodeId(0L), mock(StatusActionSubmitter.class), diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/build.gradle.kts b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/build.gradle.kts index 65793641439e..fe1a51fe8351 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/build.gradle.kts +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/build.gradle.kts @@ -18,6 +18,7 @@ plugins { id("com.hedera.hashgraph.sdk.conventions") } testModuleInfo { requires("com.swirlds.test.framework") + requires("com.swirlds.common.testing") requires("org.junit.jupiter.api") requires("org.junit.jupiter.params") } diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/MerkleMapBenchmarkMetadata.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/MerkleMapBenchmarkMetadata.java index 10288b2552b8..ddb7141537f1 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/MerkleMapBenchmarkMetadata.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/MerkleMapBenchmarkMetadata.java @@ -16,7 +16,7 @@ package com.swirlds.merkle.map.test.benchmark; -import com.swirlds.common.test.benchmark.BenchmarkMetadata; +import com.swirlds.common.test.fixtures.benchmark.BenchmarkMetadata; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedList; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/CreateAccountOperation.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/CreateAccountOperation.java index f2d93f4b02aa..6b36a6fd0c5d 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/CreateAccountOperation.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/CreateAccountOperation.java @@ -18,7 +18,7 @@ import static com.swirlds.common.test.fixtures.RandomUtils.randomByteArray; -import com.swirlds.common.test.benchmark.AbstractBenchmarkOperation; +import com.swirlds.common.test.fixtures.benchmark.AbstractBenchmarkOperation; import com.swirlds.merkle.map.MerkleMap; import com.swirlds.merkle.map.test.benchmark.AccountFactory; import com.swirlds.merkle.map.test.benchmark.BenchmarkAccount; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/DeleteAccountOperation.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/DeleteAccountOperation.java index da1a642fee78..c28c89adbd35 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/DeleteAccountOperation.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/DeleteAccountOperation.java @@ -16,7 +16,7 @@ package com.swirlds.merkle.map.test.benchmark.operations; -import com.swirlds.common.test.benchmark.AbstractBenchmarkOperation; +import com.swirlds.common.test.fixtures.benchmark.AbstractBenchmarkOperation; import com.swirlds.merkle.map.MerkleMap; import com.swirlds.merkle.map.test.benchmark.BenchmarkAccount; import com.swirlds.merkle.map.test.benchmark.BenchmarkKey; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/ReadBalanceOperation.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/ReadBalanceOperation.java index 3dab92d6d915..0933ff33e8bc 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/ReadBalanceOperation.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/ReadBalanceOperation.java @@ -16,7 +16,7 @@ package com.swirlds.merkle.map.test.benchmark.operations; -import com.swirlds.common.test.benchmark.AbstractBenchmarkOperation; +import com.swirlds.common.test.fixtures.benchmark.AbstractBenchmarkOperation; import com.swirlds.merkle.map.MerkleMap; import com.swirlds.merkle.map.test.benchmark.BenchmarkAccount; import com.swirlds.merkle.map.test.benchmark.BenchmarkKey; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/TransferOperation.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/TransferOperation.java index 65c223b5cfae..d999401baa0c 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/TransferOperation.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/benchmark/operations/TransferOperation.java @@ -16,7 +16,7 @@ package com.swirlds.merkle.map.test.benchmark.operations; -import com.swirlds.common.test.benchmark.AbstractBenchmarkOperation; +import com.swirlds.common.test.fixtures.benchmark.AbstractBenchmarkOperation; import com.swirlds.merkle.map.MerkleMap; import com.swirlds.merkle.map.test.benchmark.BenchmarkAccount; import com.swirlds.merkle.map.test.benchmark.BenchmarkKey; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/dummy/FCQValue.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/dummy/FCQValue.java index e03c89b15f87..6fde12cc9e27 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/dummy/FCQValue.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/dummy/FCQValue.java @@ -25,8 +25,8 @@ import com.swirlds.common.merkle.impl.PartialNaryMerkleInternal; import com.swirlds.common.merkle.utility.Keyed; import com.swirlds.common.merkle.utility.MerkleLong; -import com.swirlds.common.test.dummy.Key; -import com.swirlds.common.test.dummy.MerkleKey; +import com.swirlds.common.test.fixtures.dummy.Key; +import com.swirlds.common.test.fixtures.dummy.MerkleKey; import com.swirlds.fcqueue.FCQueue; import com.swirlds.merkle.map.test.pta.TransactionRecord; import com.swirlds.merkle.map.test.util.MerkleMapTestUtil; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/util/KeyValueProvider.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/util/KeyValueProvider.java index 4dbb68b0c3b5..65767ea4116b 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/util/KeyValueProvider.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/util/KeyValueProvider.java @@ -18,8 +18,8 @@ import com.swirlds.common.merkle.MerkleNode; import com.swirlds.common.merkle.utility.Keyed; -import com.swirlds.common.test.dummy.Key; -import com.swirlds.common.test.dummy.Value; +import com.swirlds.common.test.fixtures.dummy.Key; +import com.swirlds.common.test.fixtures.dummy.Value; import com.swirlds.merkle.map.test.dummy.FCQValue; import java.util.Map; import java.util.function.Function; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/util/MapMutatorSet.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/util/MapMutatorSet.java index 5ea5d1ff9ea6..f0c05b07f642 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/util/MapMutatorSet.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/util/MapMutatorSet.java @@ -18,8 +18,8 @@ import com.swirlds.common.FastCopyable; import com.swirlds.common.merkle.MerkleNode; -import com.swirlds.common.test.dummy.Key; -import com.swirlds.common.test.dummy.Value; +import com.swirlds.common.test.fixtures.dummy.Key; +import com.swirlds.common.test.fixtures.dummy.Value; import com.swirlds.merkle.map.test.dummy.FCQValue; import java.util.HashSet; import java.util.Map; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/util/MerkleMapTestUtil.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/util/MerkleMapTestUtil.java index 0cef393d13a2..a7f7ba3ce28c 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/util/MerkleMapTestUtil.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/com/swirlds/merkle/map/test/util/MerkleMapTestUtil.java @@ -18,8 +18,8 @@ import com.swirlds.common.merkle.MerkleNode; import com.swirlds.common.merkle.utility.Keyed; -import com.swirlds.common.test.dummy.Key; -import com.swirlds.common.test.dummy.Value; +import com.swirlds.common.test.fixtures.dummy.Key; +import com.swirlds.common.test.fixtures.dummy.Value; import com.swirlds.merkle.tree.MerkleBinaryTree; import java.io.File; import java.io.IOException; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/module-info.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/module-info.java index 24880c64f4af..b534b40becf1 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/module-info.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/main/java/module-info.java @@ -2,13 +2,12 @@ exports com.swirlds.merkle.map.test.pta; exports com.swirlds.merkle.map.test.lifecycle; - requires transitive com.swirlds.common.testing; + requires transitive com.swirlds.common.test.fixtures; requires transitive com.swirlds.common; requires transitive com.swirlds.merkle; requires transitive com.fasterxml.jackson.annotation; requires transitive com.fasterxml.jackson.databind; requires com.swirlds.base; - requires com.swirlds.common.test.fixtures; requires com.swirlds.fchashmap; requires com.swirlds.fcqueue; requires com.fasterxml.jackson.core; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/KeyTests.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/KeyTests.java index 6ebaf13e0373..ae257315c0d9 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/KeyTests.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/KeyTests.java @@ -22,7 +22,7 @@ import com.swirlds.common.constructable.ClassConstructorPair; import com.swirlds.common.constructable.ConstructableRegistry; import com.swirlds.common.constructable.ConstructableRegistryException; -import com.swirlds.common.test.dummy.Key; +import com.swirlds.common.test.fixtures.dummy.Key; import com.swirlds.common.test.fixtures.io.InputOutputStream; import com.swirlds.test.framework.TestComponentTags; import com.swirlds.test.framework.TestTypeTags; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/MMSerializeTests.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/MMSerializeTests.java index 54b13a343d64..c17fd0b06189 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/MMSerializeTests.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/MMSerializeTests.java @@ -23,8 +23,8 @@ import com.swirlds.common.constructable.ConstructableRegistryException; import com.swirlds.common.merkle.crypto.MerkleCryptoFactory; import com.swirlds.common.merkle.crypto.MerkleCryptography; -import com.swirlds.common.test.dummy.Key; -import com.swirlds.common.test.dummy.Value; +import com.swirlds.common.test.fixtures.dummy.Key; +import com.swirlds.common.test.fixtures.dummy.Value; import com.swirlds.common.test.fixtures.merkle.util.MerkleSerializeUtils; import com.swirlds.merkle.map.MerkleMap; import com.swirlds.merkle.map.test.util.KeyValueProvider; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/MerkleMapMemoryTests.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/MerkleMapMemoryTests.java index 27f0b71e0e2f..7f5b82b735aa 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/MerkleMapMemoryTests.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/MerkleMapMemoryTests.java @@ -21,8 +21,8 @@ import com.swirlds.common.constructable.ConstructableRegistry; import com.swirlds.common.constructable.ConstructableRegistryException; -import com.swirlds.common.test.dummy.Key; -import com.swirlds.common.test.dummy.Value; +import com.swirlds.common.test.fixtures.dummy.Key; +import com.swirlds.common.test.fixtures.dummy.Value; import com.swirlds.merkle.map.MerkleMap; import com.swirlds.test.framework.TestComponentTags; import com.swirlds.test.framework.TestTypeTags; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/MerkleMapTests.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/MerkleMapTests.java index 07ed206f99f3..71dc054f0178 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/MerkleMapTests.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/MerkleMapTests.java @@ -43,8 +43,8 @@ import com.swirlds.common.merkle.utility.KeyedMerkleLong; import com.swirlds.common.merkle.utility.MerkleLong; import com.swirlds.common.merkle.utility.SerializableLong; -import com.swirlds.common.test.dummy.Key; -import com.swirlds.common.test.dummy.Value; +import com.swirlds.common.test.fixtures.dummy.Key; +import com.swirlds.common.test.fixtures.dummy.Value; import com.swirlds.common.test.fixtures.io.InputOutputStream; import com.swirlds.common.test.merkle.dummy.DummyMerkleInternal; import com.swirlds.common.test.merkle.dummy.DummyMerkleNode; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/ValueTests.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/ValueTests.java index 0a7a3698b759..c5729191cd46 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/ValueTests.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/ValueTests.java @@ -20,7 +20,7 @@ import com.swirlds.common.constructable.ConstructableRegistry; import com.swirlds.common.constructable.ConstructableRegistryException; -import com.swirlds.common.test.dummy.Value; +import com.swirlds.common.test.fixtures.dummy.Value; import com.swirlds.common.test.fixtures.io.InputOutputStream; import java.io.IOException; import org.junit.jupiter.api.BeforeAll; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/benchmark/MerkleMapBenchmark.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/benchmark/MerkleMapBenchmark.java index bccbfd8fbae2..e64aefe99f6e 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/benchmark/MerkleMapBenchmark.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/map/test/benchmark/MerkleMapBenchmark.java @@ -21,10 +21,10 @@ import com.swirlds.common.constructable.ConstructableRegistry; import com.swirlds.common.constructable.ConstructableRegistryException; -import com.swirlds.common.test.benchmark.Benchmark; -import com.swirlds.common.test.benchmark.BenchmarkConfiguration; -import com.swirlds.common.test.benchmark.BenchmarkOperation; -import com.swirlds.common.test.benchmark.BenchmarkStatistic; +import com.swirlds.common.test.fixtures.benchmark.Benchmark; +import com.swirlds.common.test.fixtures.benchmark.BenchmarkConfiguration; +import com.swirlds.common.test.fixtures.benchmark.BenchmarkOperation; +import com.swirlds.common.test.fixtures.benchmark.BenchmarkStatistic; import com.swirlds.merkle.map.MerkleMap; import com.swirlds.merkle.map.test.benchmark.operations.CreateAccountOperation; import com.swirlds.merkle.map.test.benchmark.operations.DeleteAccountOperation; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/tree/test/MerkleBinaryTreeTests.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/tree/test/MerkleBinaryTreeTests.java index 9d64d8d8b8c5..fe58a4ef5eb2 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/tree/test/MerkleBinaryTreeTests.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/tree/test/MerkleBinaryTreeTests.java @@ -30,8 +30,8 @@ import com.swirlds.common.merkle.route.MerkleRoute; import com.swirlds.common.merkle.route.MerkleRouteIterator; import com.swirlds.common.merkle.utility.Keyed; -import com.swirlds.common.test.dummy.Key; -import com.swirlds.common.test.dummy.Value; +import com.swirlds.common.test.fixtures.dummy.Key; +import com.swirlds.common.test.fixtures.dummy.Value; import com.swirlds.common.test.fixtures.io.InputOutputStream; import com.swirlds.merkle.tree.MerkleBinaryTree; import com.swirlds.merkle.tree.MerkleTreeInternalNode; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/tree/test/MerkleMapEntryTests.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/tree/test/MerkleMapEntryTests.java index 301ff69ba0b3..04799a224f20 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/tree/test/MerkleMapEntryTests.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/tree/test/MerkleMapEntryTests.java @@ -31,8 +31,8 @@ import com.swirlds.common.io.streams.SerializableDataInputStream; import com.swirlds.common.io.streams.SerializableDataOutputStream; import com.swirlds.common.merkle.utility.MerkleLong; -import com.swirlds.common.test.dummy.Key; -import com.swirlds.common.test.dummy.Value; +import com.swirlds.common.test.fixtures.dummy.Key; +import com.swirlds.common.test.fixtures.dummy.Value; import com.swirlds.merkle.map.internal.MerkleMapEntry; import com.swirlds.test.framework.TestComponentTags; import com.swirlds.test.framework.TestTypeTags; diff --git a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/tree/test/MerkleTreeInternalNodeTests.java b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/tree/test/MerkleTreeInternalNodeTests.java index 7609eb73fd60..e41ad0e0931b 100644 --- a/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/tree/test/MerkleTreeInternalNodeTests.java +++ b/platform-sdk/swirlds-unit-tests/structures/swirlds-merkle-test/src/test/java/com/swirlds/merkle/tree/test/MerkleTreeInternalNodeTests.java @@ -30,8 +30,8 @@ import com.swirlds.common.merkle.MerkleNode; import com.swirlds.common.merkle.route.MerkleRoute; import com.swirlds.common.merkle.route.MerkleRouteIterator; -import com.swirlds.common.test.dummy.Key; -import com.swirlds.common.test.dummy.Value; +import com.swirlds.common.test.fixtures.dummy.Key; +import com.swirlds.common.test.fixtures.dummy.Value; import com.swirlds.merkle.tree.MerkleBinaryTree; import com.swirlds.merkle.tree.MerkleTreeInternalNode; import com.swirlds.test.framework.TestComponentTags; diff --git a/platform-sdk/swirlds-virtualmap/src/test/java/com/swirlds/virtualmap/internal/reconnect/RandomVirtualMapReconnectTests.java b/platform-sdk/swirlds-virtualmap/src/test/java/com/swirlds/virtualmap/internal/reconnect/RandomVirtualMapReconnectTests.java index ea2dedbb8ccc..b950a43fd3b9 100644 --- a/platform-sdk/swirlds-virtualmap/src/test/java/com/swirlds/virtualmap/internal/reconnect/RandomVirtualMapReconnectTests.java +++ b/platform-sdk/swirlds-virtualmap/src/test/java/com/swirlds/virtualmap/internal/reconnect/RandomVirtualMapReconnectTests.java @@ -22,10 +22,10 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import com.swirlds.common.merkle.MerkleInternal; +import com.swirlds.common.test.fixtures.set.RandomAccessHashSet; +import com.swirlds.common.test.fixtures.set.RandomAccessSet; import com.swirlds.common.test.merkle.dummy.DummyMerkleInternal; import com.swirlds.common.test.merkle.util.MerkleTestUtils; -import com.swirlds.common.test.set.RandomAccessHashSet; -import com.swirlds.common.test.set.RandomAccessSet; import com.swirlds.test.framework.TestQualifierTags; import com.swirlds.virtualmap.TestKey; import com.swirlds.virtualmap.TestValue; diff --git a/settings.gradle.kts b/settings.gradle.kts index 8001b3c915c3..476f02b2625b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -87,9 +87,9 @@ include(":swirlds-sign-tool", "platform-sdk/swirlds-sign-tool") include(":swirlds-config-api", "platform-sdk/swirlds-config-api") -include(":swirlds-config-impl", "platform-sdk/swirlds-config-impl") +include(":swirlds-config-processor", "platform-sdk/swirlds-config-processor") -include(":swirlds-config-benchmark", "platform-sdk/swirlds-config-benchmark") +include(":swirlds-config-impl", "platform-sdk/swirlds-config-impl") include(":swirlds-config-extensions", "platform-sdk/swirlds-config-extensions")