From ba2ecc01ba55b659f1377f06fd61f7d064513b44 Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Fri, 26 May 2023 14:56:43 +1000 Subject: [PATCH 01/35] Prepare for next version (#5504) Signed-off-by: Simon Dudley --- CHANGELOG.md | 15 +++++++++++++++ gradle.properties | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fbf1b4cd0a..0cee84b546e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## 23.4.2 + +### Breaking Changes + +### Additions and Improvements + +### Bug Fixes + +### Download Links + +--- + ## 23.4.1 ### Breaking Changes @@ -22,6 +34,9 @@ ### Download Links +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.4.1/besu-23.4.1.tar.gz / sha256: 49d3a7a069cae307497093d834f873ce7804a46dd59207d5e8321459532d318e +https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/23.4.1/besu-23.4.1.zip / sha256: 1d82ed83a816968aa9366d9310b275ca6438100f5d3eb1ec03d3474b2a5f5e76 + ## 23.4.0 ### Breaking Changes diff --git a/gradle.properties b/gradle.properties index ae7f5fcd5a9..5c073d6a895 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=23.4.1 +version=23.4.2-SNAPSHOT org.gradle.welcome=never # Set exports/opens flags required by Google Java Format and ErrorProne plugins. (JEP-396) From 21992b7a5cdcb6b4f6fe1775393483e992c89552 Mon Sep 17 00:00:00 2001 From: Sally MacFarlane Date: Fri, 26 May 2023 15:36:19 +1000 Subject: [PATCH 02/35] run non-mainnet ATs on PRs, split into sub groups (#5502) * run non-mainnet ATs on PRs, split into sets * split privacy and permissioning Signed-off-by: Sally MacFarlane --------- Signed-off-by: Sally MacFarlane --- .circleci/config.yml | 58 +++++++++++++++++++++++++++-- acceptance-tests/tests/build.gradle | 58 +++++++++++++++++++++++++++-- 2 files changed, 110 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6a48f22929b..c044ed85083 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -240,7 +240,7 @@ jobs: - capture_test_results - capture_test_logs - acceptanceTestsNonMainnet: + acceptanceTestsCliqueBft: parallelism: 6 executor: xl_machine_executor steps: @@ -258,7 +258,51 @@ jobs: | circleci tests split --split-by=timings --timings-type=classname) # Format the arguments to "./gradlew test" GRADLE_ARGS=$(echo $CLASSNAMES | awk '{for (i=1; i<=NF; i++) print "--tests",$i}') - ./gradlew --no-daemon acceptanceTestNonMainnet $GRADLE_ARGS + ./gradlew --no-daemon acceptanceTestCliqueBft $GRADLE_ARGS + - capture_test_results + - capture_test_logs + + acceptanceTestsPrivacy: + parallelism: 6 + executor: xl_machine_executor + steps: + - prepare + - attach_workspace: + at: ~/project + - run: + name: AcceptanceTests (Non-Mainnet) + no_output_timeout: 20m + command: | + CLASSNAMES=$(circleci tests glob "acceptance-tests/tests/src/test/java/**/*.java" \ + | sed 's@.*/src/test/java/@@' \ + | sed 's@/@.@g' \ + | sed 's/.\{5\}$//' \ + | circleci tests split --split-by=timings --timings-type=classname) + # Format the arguments to "./gradlew test" + GRADLE_ARGS=$(echo $CLASSNAMES | awk '{for (i=1; i<=NF; i++) print "--tests",$i}') + ./gradlew --no-daemon acceptanceTestPrivacy $GRADLE_ARGS + - capture_test_results + - capture_test_logs + + acceptanceTestsPermissioning: + parallelism: 6 + executor: xl_machine_executor + steps: + - prepare + - attach_workspace: + at: ~/project + - run: + name: AcceptanceTests (Non-Mainnet) + no_output_timeout: 20m + command: | + CLASSNAMES=$(circleci tests glob "acceptance-tests/tests/src/test/java/**/*.java" \ + | sed 's@.*/src/test/java/@@' \ + | sed 's@/@.@g' \ + | sed 's/.\{5\}$//' \ + | circleci tests split --split-by=timings --timings-type=classname) + # Format the arguments to "./gradlew test" + GRADLE_ARGS=$(echo $CLASSNAMES | awk '{for (i=1; i<=NF; i++) print "--tests",$i}') + ./gradlew --no-daemon acceptanceTestPermissioning $GRADLE_ARGS - capture_test_results - capture_test_logs @@ -401,6 +445,15 @@ workflows: - acceptanceTests: requires: - assemble + - acceptanceTestsCliqueBft: + requires: + - assemble + - acceptanceTestsPrivacy: + requires: + - assemble + - acceptanceTestsPermissioning: + requires: + - assemble - buildDocker: requires: - assemble @@ -472,4 +525,3 @@ workflows: jobs: - assemble - dockerScan - - acceptanceTestsNonMainnet diff --git a/acceptance-tests/tests/build.gradle b/acceptance-tests/tests/build.gradle index d05636204a0..8b23195361d 100644 --- a/acceptance-tests/tests/build.gradle +++ b/acceptance-tests/tests/build.gradle @@ -155,11 +155,36 @@ task acceptanceTestMainnet(type: Test) { doFirst { mkdir "${buildDir}/jvmErrorLogs" } } -task acceptanceTestNonMainnet(type: Test) { +task acceptanceTestCliqueBft(type: Test) { inputs.property "integration.date", LocalTime.now() // so it runs at every invocation include '**/bft/**' include '**/clique/**' - include '**/permissioning/**' + + useJUnitPlatform {} + + dependsOn(rootProject.installDist) + setSystemProperties(test.getSystemProperties()) + systemProperty 'acctests.runBesuAsProcess', 'true' + systemProperty 'java.security.properties', "${buildDir}/resources/test/acceptanceTesting.security" + mustRunAfter rootProject.subprojects*.test + description = 'Runs Clique and BFT Besu acceptance tests.' + group = 'verification' + + jvmArgs "-XX:ErrorFile=${buildDir}/jvmErrorLogs/java_err_pid%p.log" + + testLogging { + exceptionFormat = 'full' + showStackTraces = true + showStandardStreams = Boolean.getBoolean('acctests.showStandardStreams') + showExceptions = true + showCauses = true + } + + doFirst { mkdir "${buildDir}/jvmErrorLogs" } +} + +task acceptanceTestPrivacy(type: Test) { + inputs.property "integration.date", LocalTime.now() // so it runs at every invocation include '**/privacy/**' useJUnitPlatform {} @@ -169,7 +194,34 @@ task acceptanceTestNonMainnet(type: Test) { systemProperty 'acctests.runBesuAsProcess', 'true' systemProperty 'java.security.properties', "${buildDir}/resources/test/acceptanceTesting.security" mustRunAfter rootProject.subprojects*.test - description = 'Runs NON-MAINNET Besu acceptance tests for permissioning and privacy (excluding mainnet features).' + description = 'Runs Privacy Besu acceptance tests.' + group = 'verification' + + jvmArgs "-XX:ErrorFile=${buildDir}/jvmErrorLogs/java_err_pid%p.log" + + testLogging { + exceptionFormat = 'full' + showStackTraces = true + showStandardStreams = Boolean.getBoolean('acctests.showStandardStreams') + showExceptions = true + showCauses = true + } + + doFirst { mkdir "${buildDir}/jvmErrorLogs" } +} + +task acceptanceTestPermissioning(type: Test) { + inputs.property "integration.date", LocalTime.now() // so it runs at every invocation + include '**/permissioning/**' + + useJUnitPlatform {} + + dependsOn(rootProject.installDist) + setSystemProperties(test.getSystemProperties()) + systemProperty 'acctests.runBesuAsProcess', 'true' + systemProperty 'java.security.properties', "${buildDir}/resources/test/acceptanceTesting.security" + mustRunAfter rootProject.subprojects*.test + description = 'Runs Permissioning Besu acceptance tests.' group = 'verification' jvmArgs "-XX:ErrorFile=${buildDir}/jvmErrorLogs/java_err_pid%p.log" From df5599172e41e1a8fa91e86bb4526471e7e19f0d Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Fri, 26 May 2023 17:10:16 +1000 Subject: [PATCH 03/35] Acceptance Test for Shanghai EVM changes (push0) (#5424) Add a new version of engine Shanghai ATs with a modified genesis that allows for calling a push0 contract Remove shanghai test cases from Paris and rename to ExecutionEngineParisAcceptanceTest Signed-off-by: Simon Dudley --- ...> ExecutionEngineParisAcceptanceTest.java} | 8 +-- ...ExecutionEngineShanghaiAcceptanceTest.java | 51 +++++++++++++++ .../jsonrpc/engine/{ => paris}/genesis.json | 0 .../test-cases/01_prepare_payload.json | 0 .../test-cases/02_get_payload.json | 0 .../test-cases/03_execute_payload.json | 0 .../test-cases/04_invalid_safeblock_hash.json | 0 .../05_invalid_finalized_block_hash.json | 0 ...forkchoice_invalid_payload_attributes.json | 0 .../test-cases/07_update_forkchoice.json | 0 .../test-cases/08_unknown_payload.json | 0 .../test-cases/09_invalid_head.json | 0 .../jsonrpc/engine/shanghai/genesis.json | 65 +++++++++++++++++++ .../test-cases/01_paris_prepare_payload.json | 32 +++++++++ .../test-cases/02_paris_getPayloadV1.json | 31 +++++++++ .../test-cases/03_paris_newPayloadV1.json | 35 ++++++++++ .../04_paris_forkchoiceUpdatedV1.json | 28 ++++++++ ...are_payload_invalid_null_withdrawals.json} | 4 +- .../06_shanghai_prepare_payload.json} | 8 +-- ...payload_replay_different_withdrawals.json} | 8 +-- .../test-cases/08_shanghai_getPayloadV2.json} | 12 ++-- ...ewPayloadV2_invalid_null_withdrawals.json} | 6 +- .../test-cases/10_shanghai_newPayloadV2.json} | 8 +-- .../11_shanghai_forkchoiceUpdatedV2.json | 28 ++++++++ ..._withdrawals_address1_latest_balance.json} | 0 ..._withdrawals_address2_latest_balance.json} | 0 .../14_shanghai_newPayloadV2_push0_tx.json | 38 +++++++++++ .../16_shanghai_update_forkchoice.json | 28 -------- 28 files changed, 335 insertions(+), 55 deletions(-) rename acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/{ExecutionEngineAcceptanceTest.java => ExecutionEngineParisAcceptanceTest.java} (84%) create mode 100644 acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineShanghaiAcceptanceTest.java rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{ => paris}/genesis.json (100%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{ => paris}/test-cases/01_prepare_payload.json (100%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{ => paris}/test-cases/02_get_payload.json (100%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{ => paris}/test-cases/03_execute_payload.json (100%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{ => paris}/test-cases/04_invalid_safeblock_hash.json (100%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{ => paris}/test-cases/05_invalid_finalized_block_hash.json (100%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{ => paris}/test-cases/06_update_forkchoice_invalid_payload_attributes.json (100%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{ => paris}/test-cases/07_update_forkchoice.json (100%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{ => paris}/test-cases/08_unknown_payload.json (100%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{ => paris}/test-cases/09_invalid_head.json (100%) create mode 100644 acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/genesis.json create mode 100644 acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/01_paris_prepare_payload.json create mode 100644 acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/02_paris_getPayloadV1.json create mode 100644 acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/03_paris_newPayloadV1.json create mode 100644 acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/04_paris_forkchoiceUpdatedV1.json rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{test-cases/10_shanghai_invalid_null_withdrawals_prepare_payload.json => shanghai/test-cases/05_shanghai_prepare_payload_invalid_null_withdrawals.json} (76%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{test-cases/12_shanghai_prepare_payload_replay.json => shanghai/test-cases/06_shanghai_prepare_payload.json} (76%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{test-cases/11_shanghai_prepare_payload.json => shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json} (76%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{test-cases/13_shanghai_get_payload.json => shanghai/test-cases/08_shanghai_getPayloadV2.json} (82%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{test-cases/14_shanghai_invalid_null_withdrawals_execute_payload.json => shanghai/test-cases/09_shanghai_newPayloadV2_invalid_null_withdrawals.json} (82%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{test-cases/15_shanghai_execute_payload.json => shanghai/test-cases/10_shanghai_newPayloadV2.json} (82%) create mode 100644 acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/11_shanghai_forkchoiceUpdatedV2.json rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{test-cases/17_shanghai_withdrawals_address1_latest_balance.json => shanghai/test-cases/12_shanghai_withdrawals_address1_latest_balance.json} (100%) rename acceptance-tests/tests/src/test/resources/jsonrpc/engine/{test-cases/18_shanghai_withdrawals_address2_latest_balance.json => shanghai/test-cases/13_shanghai_withdrawals_address2_latest_balance.json} (100%) create mode 100644 acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/14_shanghai_newPayloadV2_push0_tx.json delete mode 100644 acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/16_shanghai_update_forkchoice.json diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineParisAcceptanceTest.java similarity index 84% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineAcceptanceTest.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineParisAcceptanceTest.java index 3e32955eb6f..c6cb8a62ea4 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineParisAcceptanceTest.java @@ -24,13 +24,13 @@ import org.junit.runners.Parameterized; @RunWith(Parameterized.class) -public class ExecutionEngineAcceptanceTest extends AbstractJsonRpcTest { - private static final String GENESIS_FILE = "/jsonrpc/engine/genesis.json"; - private static final String TEST_CASE_PATH = "/jsonrpc/engine/test-cases/"; +public class ExecutionEngineParisAcceptanceTest extends AbstractJsonRpcTest { + private static final String GENESIS_FILE = "/jsonrpc/engine/paris/genesis.json"; + private static final String TEST_CASE_PATH = "/jsonrpc/engine/paris/test-cases/"; private static JsonRpcTestsContext testsContext; - public ExecutionEngineAcceptanceTest(final String ignored, final URI testCaseFileURI) { + public ExecutionEngineParisAcceptanceTest(final String ignored, final URI testCaseFileURI) { super(ignored, testsContext, testCaseFileURI); } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineShanghaiAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineShanghaiAcceptanceTest.java new file mode 100644 index 00000000000..c676af5922b --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineShanghaiAcceptanceTest.java @@ -0,0 +1,51 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.jsonrpc; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class ExecutionEngineShanghaiAcceptanceTest extends AbstractJsonRpcTest { + private static final String GENESIS_FILE = "/jsonrpc/engine/shanghai/genesis.json"; + private static final String TEST_CASE_PATH = "/jsonrpc/engine/shanghai/test-cases/"; + + private static JsonRpcTestsContext testsContext; + + public ExecutionEngineShanghaiAcceptanceTest(final String ignored, final URI testCaseFileURI) { + super(ignored, testsContext, testCaseFileURI); + } + + @BeforeClass + public static void init() throws IOException { + testsContext = new JsonRpcTestsContext(GENESIS_FILE); + } + + @Parameterized.Parameters(name = "{0}") + public static Iterable testCases() throws URISyntaxException { + return testCases(TEST_CASE_PATH); + } + + @AfterClass + public static void tearDown() { + testsContext.cluster.close(); + } +} diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/genesis.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/genesis.json similarity index 100% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/genesis.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/genesis.json diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/01_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/01_prepare_payload.json similarity index 100% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/01_prepare_payload.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/01_prepare_payload.json diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/02_get_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/02_get_payload.json similarity index 100% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/02_get_payload.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/02_get_payload.json diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/03_execute_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/03_execute_payload.json similarity index 100% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/03_execute_payload.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/03_execute_payload.json diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/04_invalid_safeblock_hash.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/04_invalid_safeblock_hash.json similarity index 100% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/04_invalid_safeblock_hash.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/04_invalid_safeblock_hash.json diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/05_invalid_finalized_block_hash.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/05_invalid_finalized_block_hash.json similarity index 100% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/05_invalid_finalized_block_hash.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/05_invalid_finalized_block_hash.json diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/06_update_forkchoice_invalid_payload_attributes.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/06_update_forkchoice_invalid_payload_attributes.json similarity index 100% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/06_update_forkchoice_invalid_payload_attributes.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/06_update_forkchoice_invalid_payload_attributes.json diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/07_update_forkchoice.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/07_update_forkchoice.json similarity index 100% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/07_update_forkchoice.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/07_update_forkchoice.json diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/08_unknown_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/08_unknown_payload.json similarity index 100% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/08_unknown_payload.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/08_unknown_payload.json diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/09_invalid_head.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/09_invalid_head.json similarity index 100% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/09_invalid_head.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/test-cases/09_invalid_head.json diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/genesis.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/genesis.json new file mode 100644 index 00000000000..9e9ecaeabe3 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/genesis.json @@ -0,0 +1,65 @@ +{ + "config": { + "chainId":1, + "homesteadBlock":0, + "eip150Block":0, + "eip155Block":0, + "eip158Block":0, + "byzantiumBlock":0, + "constantinopleBlock":0, + "petersburgBlock":0, + "istanbulBlock":0, + "muirGlacierBlock":0, + "berlinBlock":0, + "londonBlock":0, + "shanghaiTime":10, + "clique": { + "period": 5, + "epoch": 30000 + }, + "terminalTotalDifficulty":0 + }, + "nonce":"0x42", + "timestamp":"0x0", + "extraData":"0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit":"0x1C9C380", + "difficulty":"0x400000000", + "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase":"0x0000000000000000000000000000000000000000", + "alloc":{ + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b":{"balance":"0x6d6172697573766477000000"}, + "0x0000000000000000000000000000000000000100" : { + "balance" : "0x00", + "code" : "0x60015f55", + "nonce" : "0x00", + "storage" : { + } + }, + "0x0000000000000000000000000000000000000200" : { + "balance" : "0x00", + "code" : "0x5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f17171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171760019055", + "nonce" : "0x00", + "storage" : { + } + }, + "0x0000000000000000000000000000000000000300" : { + "balance" : "0x00", + "code" : "0x5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f", + "nonce" : "0x00", + "storage" : { + } + }, + "0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x00", + "code" : "0x6000806000806000803560601c620186a0f160005560018055", + "nonce" : "0x00", + "storage" : { + "0x01" : "0x01" + } + } + }, + "number":"0x0", + "gasUsed":"0x0", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas":"0x7" +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/01_paris_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/01_paris_prepare_payload.json new file mode 100644 index 00000000000..0963be92f92 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/01_paris_prepare_payload.json @@ -0,0 +1,32 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV1", + "params": [ + { + "headBlockHash": "0x7de476d27c2977a4f04c6cd29f7b8a26444c3a8efbc339ce24a9150e0f6ecb6e", + "safeBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "timestamp": "0x5", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0x7de476d27c2977a4f04c6cd29f7b8a26444c3a8efbc339ce24a9150e0f6ecb6e", + "validationError": null + }, + "payloadId": "0x0065bd0f33f00bfb" + } + }, + "statusCode" : 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/02_paris_getPayloadV1.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/02_paris_getPayloadV1.json new file mode 100644 index 00000000000..139f6b4849d --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/02_paris_getPayloadV1.json @@ -0,0 +1,31 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_getPayloadV1", + "params": [ + "0x0065bd0f33f00bfb" + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "parentHash": "0x7de476d27c2977a4f04c6cd29f7b8a26444c3a8efbc339ce24a9150e0f6ecb6e", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0x5afd1528d9c9051e96a41fd77be366428a9fd6ea0bd6670720c1ff32c9484b47", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x1", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x5", + "extraData": "0x", + "baseFeePerGas": "0x7", + "blockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "transactions": [] + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/03_paris_newPayloadV1.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/03_paris_newPayloadV1.json new file mode 100644 index 00000000000..8fbe4d9039b --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/03_paris_newPayloadV1.json @@ -0,0 +1,35 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV1", + "params": [ + { + "parentHash": "0x7de476d27c2977a4f04c6cd29f7b8a26444c3a8efbc339ce24a9150e0f6ecb6e", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0x5afd1528d9c9051e96a41fd77be366428a9fd6ea0bd6670720c1ff32c9484b47", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x1", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x5", + "extraData": "0x", + "baseFeePerGas": "0x7", + "blockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "transactions": [] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/04_paris_forkchoiceUpdatedV1.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/04_paris_forkchoiceUpdatedV1.json new file mode 100644 index 00000000000..92833b37c4e --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/04_paris_forkchoiceUpdatedV1.json @@ -0,0 +1,28 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV1", + "params": [ + { + "headBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "safeBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "finalizedBlockHash": "0x7de476d27c2977a4f04c6cd29f7b8a26444c3a8efbc339ce24a9150e0f6ecb6e" + }, + null + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "validationError": null + }, + "payloadId": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/10_shanghai_invalid_null_withdrawals_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/05_shanghai_prepare_payload_invalid_null_withdrawals.json similarity index 76% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/10_shanghai_invalid_null_withdrawals_prepare_payload.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/05_shanghai_prepare_payload_invalid_null_withdrawals.json index 6b9cd90c959..f6da7401ad6 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/10_shanghai_invalid_null_withdrawals_prepare_payload.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/05_shanghai_prepare_payload_invalid_null_withdrawals.json @@ -4,8 +4,8 @@ "method": "engine_forkchoiceUpdatedV2", "params": [ { - "headBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", - "safeBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "headBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "safeBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" }, { diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/12_shanghai_prepare_payload_replay.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/06_shanghai_prepare_payload.json similarity index 76% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/12_shanghai_prepare_payload_replay.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/06_shanghai_prepare_payload.json index 41fde7c262a..caf4fe3ebdd 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/12_shanghai_prepare_payload_replay.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/06_shanghai_prepare_payload.json @@ -4,8 +4,8 @@ "method": "engine_forkchoiceUpdatedV2", "params": [ { - "headBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", - "safeBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "headBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "safeBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" }, { @@ -36,10 +36,10 @@ "result": { "payloadStatus": { "status": "VALID", - "latestValidHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "latestValidHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", "validationError": null }, - "payloadId": "0x0065bd329c251d59" + "payloadId": "0x0065bd547ba05c59" } }, "statusCode" : 200 diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/11_shanghai_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json similarity index 76% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/11_shanghai_prepare_payload.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json index e7eb5f26a8b..457a3452794 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/11_shanghai_prepare_payload.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json @@ -4,8 +4,8 @@ "method": "engine_forkchoiceUpdatedV2", "params": [ { - "headBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", - "safeBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "headBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "safeBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" }, { @@ -36,10 +36,10 @@ "result": { "payloadStatus": { "status": "VALID", - "latestValidHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "latestValidHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", "validationError": null }, - "payloadId": "0x0065bd329c251cd9" + "payloadId": "0x0065bd547ba05dd9" } }, "statusCode" : 200 diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/13_shanghai_get_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/08_shanghai_getPayloadV2.json similarity index 82% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/13_shanghai_get_payload.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/08_shanghai_getPayloadV2.json index 84f6cba6cf2..1d1ad35eba0 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/13_shanghai_get_payload.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/08_shanghai_getPayloadV2.json @@ -3,7 +3,7 @@ "jsonrpc": "2.0", "method": "engine_getPayloadV2", "params": [ - "0x0065bd329c251d59" + "0x0065bd547ba05dd9" ], "id": 67 }, @@ -12,9 +12,9 @@ "id": 67, "result": { "executionPayload": { - "parentHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "parentHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "stateRoot": "0xc8c8e840369eac89a610bfe2ec21fcdee4c9c43bec4876f0129fcd4b5311f6dd", + "stateRoot": "0xb478b6884d890760bb1abc5e0c4df9973df70c39f32c8e7a9e7d11cf4b0a0c7e", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", "gasLimit": "0x1c9c380", @@ -28,17 +28,17 @@ "index": "0x0", "validatorIndex": "0x0", "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "amount": "0x3" + "amount": "0x1" }, { "index": "0x1", "validatorIndex": "0x1", "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", - "amount": "0x4" + "amount": "0x2" } ], "blockNumber": "0x2", - "blockHash": "0x4a7b0e390d320a07150daa9c3b9dddfc6b7f6ca7d7a2971ef2f53ac1f29f24dc", + "blockHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" }, "blockValue": "0x0" diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/14_shanghai_invalid_null_withdrawals_execute_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/09_shanghai_newPayloadV2_invalid_null_withdrawals.json similarity index 82% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/14_shanghai_invalid_null_withdrawals_execute_payload.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/09_shanghai_newPayloadV2_invalid_null_withdrawals.json index 94d75c28f6e..25cd2b295a2 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/14_shanghai_invalid_null_withdrawals_execute_payload.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/09_shanghai_newPayloadV2_invalid_null_withdrawals.json @@ -4,9 +4,9 @@ "method": "engine_newPayloadV2", "params": [ { - "parentHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "parentHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "stateRoot": "0x1a10dba514dc4faff7ec13edd9b5ef653c1cd14eb26608bfc2b37717730a55a4", + "stateRoot": "0xb478b6884d890760bb1abc5e0c4df9973df70c39f32c8e7a9e7d11cf4b0a0c7e", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", "gasLimit": "0x1c9c380", @@ -17,7 +17,7 @@ "transactions": [], "withdrawals": null, "blockNumber": "0x2", - "blockHash": "0x2126c2080357c74ace7ceba4777a37ba3c74cf0135f55afea048327b333ad7b4", + "blockHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" } ], diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/15_shanghai_execute_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/10_shanghai_newPayloadV2.json similarity index 82% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/15_shanghai_execute_payload.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/10_shanghai_newPayloadV2.json index 0b5238ba34b..3b68eba4b63 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/15_shanghai_execute_payload.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/10_shanghai_newPayloadV2.json @@ -4,9 +4,9 @@ "method": "engine_newPayloadV2", "params": [ { - "parentHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", + "parentHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "stateRoot": "0x7a6f2e03f2348dc75731e6e767c97a88da50430748a030874e27f7c3fac3d49d", + "stateRoot": "0xb478b6884d890760bb1abc5e0c4df9973df70c39f32c8e7a9e7d11cf4b0a0c7e", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", "gasLimit": "0x1c9c380", @@ -30,7 +30,7 @@ } ], "blockNumber": "0x2", - "blockHash": "0x4f88d512a0045bc6d447ba74a18eac0ed2ebb8d9faca325f5f55b2ca84be0705", + "blockHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" } ], @@ -41,7 +41,7 @@ "id": 67, "result": { "status": "VALID", - "latestValidHash": "0x4f88d512a0045bc6d447ba74a18eac0ed2ebb8d9faca325f5f55b2ca84be0705", + "latestValidHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", "validationError": null } }, diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/11_shanghai_forkchoiceUpdatedV2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/11_shanghai_forkchoiceUpdatedV2.json new file mode 100644 index 00000000000..3c2bfc96a2a --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/11_shanghai_forkchoiceUpdatedV2.json @@ -0,0 +1,28 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV2", + "params": [ + { + "headBlockHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", + "safeBlockHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", + "finalizedBlockHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8" + }, + null + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", + "validationError": null + }, + "payloadId": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/17_shanghai_withdrawals_address1_latest_balance.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/12_shanghai_withdrawals_address1_latest_balance.json similarity index 100% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/17_shanghai_withdrawals_address1_latest_balance.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/12_shanghai_withdrawals_address1_latest_balance.json diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/18_shanghai_withdrawals_address2_latest_balance.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/13_shanghai_withdrawals_address2_latest_balance.json similarity index 100% rename from acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/18_shanghai_withdrawals_address2_latest_balance.json rename to acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/13_shanghai_withdrawals_address2_latest_balance.json diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/14_shanghai_newPayloadV2_push0_tx.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/14_shanghai_newPayloadV2_push0_tx.json new file mode 100644 index 00000000000..1a3e8fcdb92 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/14_shanghai_newPayloadV2_push0_tx.json @@ -0,0 +1,38 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV2", + "params": [ + { + "parentHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0x4705976c675e1e7bd50e8a13aab940a35f805475a5f74d0394801ae1151e7521", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x111f8", + "timestamp": "0x11", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [ + "0xf874800a830aae6094b94f5374fce5edbc8e2a8697c15331677e6ebf0b809400000000000000000000000000000000000001001ba040c30479d1f1f7ac729145a6e98ff0bc4882cc21930cc283db84f42f1852d9fba0567ecfa0b8daeedfd9ab8d520bcf44f06d682be47dac7d64a6865cec4ec33cef" + ], + "withdrawals": [], + "blockNumber": "0x3", + "blockHash": "0x3aa97e152d34227654a4bab1bd5018fcebb06acb82b2af2754a3a98eff3a03cb", + "receiptsRoot": "0x1668c1a230c3e0aaa4c52af3bada02571dabb4e1743ebd6eaf4bbe8008e8cc3e" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0x3aa97e152d34227654a4bab1bd5018fcebb06acb82b2af2754a3a98eff3a03cb", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/16_shanghai_update_forkchoice.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/16_shanghai_update_forkchoice.json deleted file mode 100644 index 72850cbde5c..00000000000 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/test-cases/16_shanghai_update_forkchoice.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "request": { - "jsonrpc": "2.0", - "method": "engine_forkchoiceUpdatedV2", - "params": [ - { - "headBlockHash": "0x4f88d512a0045bc6d447ba74a18eac0ed2ebb8d9faca325f5f55b2ca84be0705", - "safeBlockHash": "0x4f88d512a0045bc6d447ba74a18eac0ed2ebb8d9faca325f5f55b2ca84be0705", - "finalizedBlockHash": "0x4f88d512a0045bc6d447ba74a18eac0ed2ebb8d9faca325f5f55b2ca84be0705" - }, - null - ], - "id": 67 - }, - "response": { - "jsonrpc": "2.0", - "id": 67, - "result": { - "payloadStatus": { - "status": "VALID", - "latestValidHash": "0x4f88d512a0045bc6d447ba74a18eac0ed2ebb8d9faca325f5f55b2ca84be0705", - "validationError": null - }, - "payloadId": null - } - }, - "statusCode": 200 -} \ No newline at end of file From 610812c84113725f5fe3d63234990c52bd12b8ee Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Fri, 26 May 2023 10:25:19 +0200 Subject: [PATCH 04/35] Ignore min-block-occupancy-ratio option when on PoS (#5491) Signed-off-by: Fabio Di Fabio Co-authored-by: Sally MacFarlane --- CHANGELOG.md | 2 + .../blockcreation/MergeBlockCreator.java | 12 +- .../merge/blockcreation/MergeCoordinator.java | 1 - .../blockcreation/MergeCoordinatorTest.java | 1 - .../BlockTransactionSelector.java | 30 +++- .../AbstractBlockTransactionSelectorTest.java | 170 ++++++++++++++++-- ...FeeMarketBlockTransactionSelectorTest.java | 7 + ...FeeMarketBlockTransactionSelectorTest.java | 35 +++- .../gascalculator/FrontierGasCalculator.java | 5 + .../besu/evm/gascalculator/GasCalculator.java | 7 + 10 files changed, 245 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cee84b546e..7c02322dd59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ ### Breaking Changes - Add request content length limit for the JSON-RPC API (5MB) [#5467](https://github.com/hyperledger/besu/pull/5467) +- `min-block-occupancy-ratio` options is now ignored on PoS networks [#5491](https://github.com/hyperledger/besu/pull/5491) ### Additions and Improvements - Set the retention policy for RocksDB log files to maintain only the logs from the last week [#5428](https://github.com/hyperledger/besu/pull/5428) @@ -27,6 +28,7 @@ - Early access - layered transaction pool implementation [#5290](https://github.com/hyperledger/besu/pull/5290) - New RPC method `debug_getRawReceipts` [#5476](https://github.com/hyperledger/besu/pull/5476) - Add TrieLogFactory plugin support [#5440](https://github.com/hyperledger/besu/pull/5440) +- Ignore `min-block-occupancy-ratio` option when on PoS networks, since in some cases, it prevents to have full blocks even if enough transactions are present [#5491](https://github.com/hyperledger/besu/pull/5491) ### Bug Fixes - Fix eth_feeHistory response for the case in which blockCount is higher than highestBlock requested. [#5397](https://github.com/hyperledger/besu/pull/5397) diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java index fcfb639d975..52f5900d375 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java @@ -36,6 +36,14 @@ /** The Merge block creator. */ class MergeBlockCreator extends AbstractBlockCreator { + /** + * On PoS you do not need to compete with other nodes for block production, since you have an + * allocated slot for that, so in this case make sense to always try to fill the block, if there + * are enough pending transactions, until the remaining gas is less than the minimum needed for + * the smaller transaction. So for PoS the min-block-occupancy-ratio option is set to always try + * to fill 100% of the block. + */ + private static final double TRY_FILL_BLOCK = 1.0; /** * Instantiates a new Merge block creator. @@ -48,7 +56,6 @@ class MergeBlockCreator extends AbstractBlockCreator { * @param protocolSchedule the protocol schedule * @param minTransactionGasPrice the min transaction gas price * @param miningBeneficiary the mining beneficiary - * @param minBlockOccupancyRatio the min block occupancy ratio * @param parentHeader the parent header */ public MergeBlockCreator( @@ -60,7 +67,6 @@ public MergeBlockCreator( final ProtocolSchedule protocolSchedule, final Wei minTransactionGasPrice, final Address miningBeneficiary, - final Double minBlockOccupancyRatio, final BlockHeader parentHeader) { super( miningBeneficiary, @@ -71,7 +77,7 @@ public MergeBlockCreator( protocolContext, protocolSchedule, minTransactionGasPrice, - minBlockOccupancyRatio, + TRY_FILL_BLOCK, parentHeader); } diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java index 5069191b3c4..19ed8e2afb4 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java @@ -136,7 +136,6 @@ public MergeCoordinator( protocolSchedule, this.miningParameters.getMinTransactionGasPrice(), address.or(miningParameters::getCoinbase).orElse(Address.ZERO), - this.miningParameters.getMinBlockOccupancyRatio(), parentHeader); this.backwardSyncContext.subscribeBadChainListener(this); diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java index 932b8130760..30f7709d59e 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java @@ -254,7 +254,6 @@ public void exceptionDuringBuildingBlockShouldNotBeInvalid() protocolSchedule, this.miningParameters.getMinTransactionGasPrice(), address.or(miningParameters::getCoinbase).orElse(Address.ZERO), - this.miningParameters.getMinBlockOccupancyRatio(), parentHeader)); doCallRealMethod() diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java index 9cc17b601d8..c14ed788d17 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java @@ -307,6 +307,9 @@ private TransactionSelectionResult evaluateTransaction( if (blockOccupancyAboveThreshold()) { LOG.trace("Block occupancy above threshold, completing operation"); return TransactionSelectionResult.COMPLETE_OPERATION; + } else if (blockFull()) { + LOG.trace("Block full, completing operation"); + return TransactionSelectionResult.COMPLETE_OPERATION; } else { return TransactionSelectionResult.CONTINUE; } @@ -458,15 +461,34 @@ private boolean transactionTooLargeForBlock(final Transaction transaction) { } private boolean blockOccupancyAboveThreshold() { - final double gasAvailable = processableBlockHeader.getGasLimit(); - final double gasUsed = transactionSelectionResult.getCumulativeGasUsed(); - final double occupancyRatio = gasUsed / gasAvailable; + final long gasAvailable = processableBlockHeader.getGasLimit(); + final long gasUsed = transactionSelectionResult.getCumulativeGasUsed(); + final long gasRemaining = gasAvailable - gasUsed; + + final double occupancyRatio = (double) gasUsed / (double) gasAvailable; LOG.trace( - "Min block occupancy ratio {}, gas used {}, available {}, used/available {}", + "Min block occupancy ratio {}, gas used {}, available {}, remaining {}, used/available {}", minBlockOccupancyRatio, gasUsed, gasAvailable, + gasRemaining, occupancyRatio); + return occupancyRatio >= minBlockOccupancyRatio; } + + private boolean blockFull() { + final long gasAvailable = processableBlockHeader.getGasLimit(); + final long gasUsed = transactionSelectionResult.getCumulativeGasUsed(); + final long gasRemaining = gasAvailable - gasUsed; + + if (gasRemaining < gasCalculator.getMinimumTransactionCost()) { + LOG.trace( + "Block full, remaining gas {} is less than minimum transaction gas cost {}", + gasRemaining, + gasCalculator.getMinimumTransactionCost()); + return true; + } + return false; + } } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java index b52cdab9a8e..c7528cd5775 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java @@ -52,6 +52,7 @@ import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; import org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain; import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; +import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.worldstate.WorldState; @@ -78,6 +79,8 @@ @RunWith(MockitoJUnitRunner.class) public abstract class AbstractBlockTransactionSelectorTest { + protected static final double MIN_OCCUPANCY_80_PERCENT = 0.8; + protected static final double MIN_OCCUPANCY_100_PERCENT = 1; protected static final KeyPair keyPair = SignatureAlgorithmFactory.getInstance().generateKeyPair(); protected final MetricsSystem metricsSystem = new NoOpMetricsSystem(); @@ -131,7 +134,12 @@ public void emptyPendingTransactionsResultsInEmptyVettingResult() { final BlockTransactionSelector selector = createBlockSelector( - mainnetTransactionProcessor, blockHeader, Wei.ZERO, miningBeneficiary, Wei.ZERO); + mainnetTransactionProcessor, + blockHeader, + Wei.ZERO, + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_80_PERCENT); final BlockTransactionSelector.TransactionSelectionResults results = selector.buildTransactionListForBlock(); @@ -155,7 +163,12 @@ public void failedTransactionsAreIncludedInTheBlock() { final BlockTransactionSelector selector = createBlockSelector( - transactionProcessor, blockHeader, Wei.ZERO, miningBeneficiary, Wei.ZERO); + transactionProcessor, + blockHeader, + Wei.ZERO, + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_80_PERCENT); final BlockTransactionSelector.TransactionSelectionResults results = selector.buildTransactionListForBlock(); @@ -187,7 +200,12 @@ public void invalidTransactionsTransactionProcessingAreSkippedButBlockStillFills final BlockTransactionSelector selector = createBlockSelector( - transactionProcessor, blockHeader, Wei.ZERO, miningBeneficiary, Wei.ZERO); + transactionProcessor, + blockHeader, + Wei.ZERO, + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_80_PERCENT); final BlockTransactionSelector.TransactionSelectionResults results = selector.buildTransactionListForBlock(); @@ -215,7 +233,12 @@ public void subsetOfPendingTransactionsIncludedWhenBlockGasLimitHit() { final BlockTransactionSelector selector = createBlockSelector( - transactionProcessor, blockHeader, Wei.ZERO, miningBeneficiary, Wei.ZERO); + transactionProcessor, + blockHeader, + Wei.ZERO, + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_80_PERCENT); final BlockTransactionSelector.TransactionSelectionResults results = selector.buildTransactionListForBlock(); @@ -306,12 +329,17 @@ public void useSingleGasSpaceForAllTransactions() { @Test public void transactionTooLargeForBlockDoesNotPreventMoreBeingAddedIfBlockOccupancyNotReached() { - final ProcessableBlockHeader blockHeader = createBlock(300); + final ProcessableBlockHeader blockHeader = createBlock(300_000); final Address miningBeneficiary = AddressHelpers.ofValue(1); final BlockTransactionSelector selector = createBlockSelector( - transactionProcessor, blockHeader, Wei.ZERO, miningBeneficiary, Wei.ZERO); + transactionProcessor, + blockHeader, + Wei.ZERO, + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_80_PERCENT); final TransactionTestFixture txTestFixture = new TransactionTestFixture(); // Add 3 transactions to the Pending Transactions, 79% of block, 100% of block and 10% of block @@ -351,7 +379,12 @@ public void transactionSelectionStopsWhenSufficientBlockOccupancyIsReached() { final Address miningBeneficiary = AddressHelpers.ofValue(1); final BlockTransactionSelector selector = createBlockSelector( - transactionProcessor, blockHeader, Wei.ZERO, miningBeneficiary, Wei.ZERO); + transactionProcessor, + blockHeader, + Wei.ZERO, + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_80_PERCENT); final TransactionTestFixture txTestFixture = new TransactionTestFixture(); // Add 4 transactions to the Pending Transactions 15% (ok), 79% (ok), 25% (too large), 10% @@ -393,6 +426,106 @@ public void transactionSelectionStopsWhenSufficientBlockOccupancyIsReached() { assertThat(results.getTransactions().contains(txs[2])).isFalse(); } + @Test + public void transactionSelectionStopsWhenBlockIsFull() { + final ProcessableBlockHeader blockHeader = createBlock(3_000_000); + + final Address miningBeneficiary = AddressHelpers.ofValue(1); + final BlockTransactionSelector selector = + createBlockSelector( + transactionProcessor, + blockHeader, + Wei.ZERO, + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_100_PERCENT); + + final long minTxGasCost = getGasCalculator().getMinimumTransactionCost(); + + // Add 4 transactions to the Pending Transactions + // 0) 90% of block (selected) + // 1) 90% of block (skipped since too large) + // 2) enough gas to only leave space for a transaction with the min gas cost (selected) + // 3) min gas cost (selected and 100% block gas used) + // 4) min gas cost (not selected since selection stopped after tx 3) + // NOTE - PendingTransactions outputs these in nonce order + + final long gasLimit0 = (long) (blockHeader.getGasLimit() * 0.9); + final long gasLimit1 = (long) (blockHeader.getGasLimit() * 0.9); + final long gasLimit2 = blockHeader.getGasLimit() - gasLimit0 - minTxGasCost; + final long gasLimit3 = minTxGasCost; + final long gasLimit4 = minTxGasCost; + + final TransactionTestFixture txTestFixture = new TransactionTestFixture(); + final List transactionsToInject = Lists.newArrayList(); + transactionsToInject.add(txTestFixture.gasLimit(gasLimit0).nonce(0).createTransaction(keyPair)); + transactionsToInject.add(txTestFixture.gasLimit(gasLimit1).nonce(1).createTransaction(keyPair)); + transactionsToInject.add(txTestFixture.gasLimit(gasLimit2).nonce(2).createTransaction(keyPair)); + transactionsToInject.add(txTestFixture.gasLimit(gasLimit3).nonce(3).createTransaction(keyPair)); + transactionsToInject.add(txTestFixture.gasLimit(gasLimit4).nonce(4).createTransaction(keyPair)); + + for (final Transaction tx : transactionsToInject) { + pendingTransactions.addRemoteTransaction(tx, Optional.empty()); + ensureTransactionIsValid(tx); + } + + final BlockTransactionSelector.TransactionSelectionResults results = + selector.buildTransactionListForBlock(); + + assertThat(results.getTransactions()) + .containsExactly( + transactionsToInject.get(0), transactionsToInject.get(2), transactionsToInject.get(3)); + assertThat(results.getCumulativeGasUsed()).isEqualTo(blockHeader.getGasLimit()); + } + + @Test + public void transactionSelectionStopsWhenRemainingGasIsNotEnoughForAnyMoreTransaction() { + final ProcessableBlockHeader blockHeader = createBlock(3_000_000); + + final Address miningBeneficiary = AddressHelpers.ofValue(1); + final BlockTransactionSelector selector = + createBlockSelector( + transactionProcessor, + blockHeader, + Wei.ZERO, + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_100_PERCENT); + + final long minTxGasCost = getGasCalculator().getMinimumTransactionCost(); + + // Add 4 transactions to the Pending Transactions + // 0) 90% of block (selected) + // 1) 90% of block (skipped since too large) + // 2) do not fill the block, but leaves less gas than the min for a tx (selected) + // 3) min gas cost (skipped since not enough gas remaining) + // NOTE - PendingTransactions outputs these in nonce order + + final long gasLimit0 = (long) (blockHeader.getGasLimit() * 0.9); + final long gasLimit1 = (long) (blockHeader.getGasLimit() * 0.9); + final long gasLimit2 = blockHeader.getGasLimit() - gasLimit0 - (minTxGasCost - 1); + final long gasLimit3 = minTxGasCost; + + final TransactionTestFixture txTestFixture = new TransactionTestFixture(); + final List transactionsToInject = Lists.newArrayList(); + transactionsToInject.add(txTestFixture.gasLimit(gasLimit0).nonce(0).createTransaction(keyPair)); + transactionsToInject.add(txTestFixture.gasLimit(gasLimit1).nonce(1).createTransaction(keyPair)); + transactionsToInject.add(txTestFixture.gasLimit(gasLimit2).nonce(2).createTransaction(keyPair)); + transactionsToInject.add(txTestFixture.gasLimit(gasLimit3).nonce(3).createTransaction(keyPair)); + + for (final Transaction tx : transactionsToInject) { + pendingTransactions.addRemoteTransaction(tx, Optional.empty()); + ensureTransactionIsValid(tx); + } + + final BlockTransactionSelector.TransactionSelectionResults results = + selector.buildTransactionListForBlock(); + + assertThat(results.getTransactions()) + .containsExactly(transactionsToInject.get(0), transactionsToInject.get(2)); + assertThat(blockHeader.getGasLimit() - results.getCumulativeGasUsed()).isLessThan(minTxGasCost); + } + @Test public void shouldDiscardTransactionsThatFailValidation() { final ProcessableBlockHeader blockHeader = createBlock(300); @@ -400,7 +533,12 @@ public void shouldDiscardTransactionsThatFailValidation() { final Address miningBeneficiary = AddressHelpers.ofValue(1); final BlockTransactionSelector selector = createBlockSelector( - transactionProcessor, blockHeader, Wei.ZERO, miningBeneficiary, Wei.ZERO); + transactionProcessor, + blockHeader, + Wei.ZERO, + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_80_PERCENT); final TransactionTestFixture txTestFixture = new TransactionTestFixture(); final Transaction validTransaction = @@ -436,7 +574,12 @@ public void transactionWithIncorrectNonceRemainsInPoolAndNotSelected() { final Address miningBeneficiary = AddressHelpers.ofValue(1); final BlockTransactionSelector selector = createBlockSelector( - transactionProcessor, blockHeader, Wei.ZERO, miningBeneficiary, Wei.ZERO); + transactionProcessor, + blockHeader, + Wei.ZERO, + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_80_PERCENT); final BlockTransactionSelector.TransactionSelectionResults results = selector.buildTransactionListForBlock(); @@ -451,7 +594,8 @@ protected BlockTransactionSelector createBlockSelector( final ProcessableBlockHeader blockHeader, final Wei minGasPrice, final Address miningBeneficiary, - final Wei dataGasPrice) { + final Wei dataGasPrice, + final double minBlockOccupancyRatio) { final BlockTransactionSelector selector = new BlockTransactionSelector( transactionProcessor, @@ -461,16 +605,18 @@ protected BlockTransactionSelector createBlockSelector( blockHeader, this::createReceipt, minGasPrice, - 0.8, + minBlockOccupancyRatio, this::isCancelled, miningBeneficiary, dataGasPrice, getFeeMarket(), - new LondonGasCalculator(), + getGasCalculator(), GasLimitCalculator.constant()); return selector; } + protected abstract GasCalculator getGasCalculator(); + protected abstract FeeMarket getFeeMarket(); private Transaction createTransaction(final int transactionNumber) { diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java index 10c01333f38..195c25b6634 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java @@ -22,6 +22,8 @@ import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions; import org.hyperledger.besu.ethereum.eth.transactions.sorter.GasPricePendingTransactionsSorter; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; +import org.hyperledger.besu.evm.gascalculator.BerlinGasCalculator; +import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.testutil.TestClock; import java.time.ZoneId; @@ -53,4 +55,9 @@ private static BlockHeader mockBlockHeader() { protected FeeMarket getFeeMarket() { return FeeMarket.legacy(); } + + @Override + protected GasCalculator getGasCalculator() { + return new BerlinGasCalculator(); + } } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java index c47e2b8b301..0b4308341ee 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java @@ -29,6 +29,8 @@ import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions; import org.hyperledger.besu.ethereum.eth.transactions.sorter.BaseFeePendingTransactionsSorter; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; +import org.hyperledger.besu.evm.gascalculator.GasCalculator; +import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator; import org.hyperledger.besu.plugin.data.TransactionType; import org.hyperledger.besu.testutil.TestClock; @@ -54,6 +56,11 @@ protected PendingTransactions createPendingTransactions() { LondonFeeMarketBlockTransactionSelectorTest::mockBlockHeader); } + @Override + protected GasCalculator getGasCalculator() { + return new LondonGasCalculator(); + } + private static BlockHeader mockBlockHeader() { final BlockHeader blockHeader = mock(BlockHeader.class); when(blockHeader.getBaseFee()).thenReturn(Optional.of(Wei.ONE)); @@ -72,7 +79,12 @@ public void eip1559TransactionCurrentGasPriceLessThanMinimumIsSkippedAndKeptInTh final Address miningBeneficiary = AddressHelpers.ofValue(1); final BlockTransactionSelector selector = createBlockSelector( - transactionProcessor, blockHeader, Wei.of(6), miningBeneficiary, Wei.ZERO); + transactionProcessor, + blockHeader, + Wei.of(6), + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_80_PERCENT); // tx is willing to pay max 6 wei for gas, but current network condition (baseFee == 1) // result in it paying 2 wei, that is below the minimum accepted by the node, so it is skipped @@ -93,7 +105,12 @@ public void eip1559TransactionCurrentGasPriceGreaterThanMinimumIsSelected() { final Address miningBeneficiary = AddressHelpers.ofValue(1); final BlockTransactionSelector selector = createBlockSelector( - transactionProcessor, blockHeader, Wei.of(6), miningBeneficiary, Wei.ZERO); + transactionProcessor, + blockHeader, + Wei.of(6), + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_80_PERCENT); // tx is willing to pay max 6 wei for gas, and current network condition (baseFee == 5) // result in it paying the max, that is >= the minimum accepted by the node, so it is selected @@ -116,7 +133,12 @@ public void eip1559LocalTransactionCurrentGasPriceLessThanMinimumIsSelected() { final Address miningBeneficiary = AddressHelpers.ofValue(1); final BlockTransactionSelector selector = createBlockSelector( - transactionProcessor, blockHeader, Wei.of(6), miningBeneficiary, Wei.ZERO); + transactionProcessor, + blockHeader, + Wei.of(6), + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_80_PERCENT); // tx is willing to pay max 6 wei for gas, but current network condition (baseFee == 1) // result in it paying 2 wei, that is below the minimum accepted by the node, but since it is @@ -168,7 +190,12 @@ public void transactionFromSameSenderWithMixedTypes() { final Address miningBeneficiary = AddressHelpers.ofValue(1); final BlockTransactionSelector selector = createBlockSelector( - transactionProcessor, blockHeader, Wei.ZERO, miningBeneficiary, Wei.ZERO); + transactionProcessor, + blockHeader, + Wei.ZERO, + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_80_PERCENT); final BlockTransactionSelector.TransactionSelectionResults results = selector.buildTransactionListForBlock(); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java index 1915f275f18..ed0c3c90d93 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java @@ -489,4 +489,9 @@ static long memoryCost(final long length) { public long getMaximumTransactionCost(final int size) { return TX_BASE_COST + TX_DATA_NON_ZERO_COST * size; } + + @Override + public long getMinimumTransactionCost() { + return TX_BASE_COST; + } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java index 417b89ca8cf..cd8b659051d 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java @@ -488,6 +488,13 @@ default long getMaxRefundQuotient() { // what would be the gas for a PMT with hash of all non-zeros long getMaximumTransactionCost(int size); + /** + * Minimum gas cost of a transaction. + * + * @return the minimum gas cost + */ + long getMinimumTransactionCost(); + /** * Returns the cost of a loading from Transient Storage * From f19fb6494229c5c4a54134ddab1ca148c15b10b1 Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Sun, 28 May 2023 20:28:47 +1000 Subject: [PATCH 05/35] Specify optional scheme (ws or wss) in Ethstats url (#5500) * Allow scheme (ws or wss) to be specified in ethstats url * Start ethstat service after main ethereum loop is up Signed-off-by: Usman Saleem --- CHANGELOG.md | 3 +- .../java/org/hyperledger/besu/Runner.java | 6 ++ .../cli/options/stable/EthstatsOptions.java | 4 +- .../besu/ethstats/EthStatsService.java | 28 +++++++--- .../ethstats/util/EthStatsConnectOptions.java | 56 +++++++++++++------ .../util/EthStatsConnectOptionsTest.java | 38 +++++++++++-- 6 files changed, 102 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c02322dd59..2821eab3388 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ ### Breaking Changes ### Additions and Improvements - +- Allow Ethstats connection url to specify ws:// or wss:// scheme. [#5494](https://github.com/hyperledger/besu/issues/5494) +- ### Bug Fixes ### Download Links diff --git a/besu/src/main/java/org/hyperledger/besu/Runner.java b/besu/src/main/java/org/hyperledger/besu/Runner.java index e6f39c08482..cff29e6dd0c 100644 --- a/besu/src/main/java/org/hyperledger/besu/Runner.java +++ b/besu/src/main/java/org/hyperledger/besu/Runner.java @@ -154,6 +154,9 @@ public void startExternalServices() { waitForServiceToStart( "stratum", server.start().toCompletionStage().toCompletableFuture())); autoTransactionLogBloomCachingService.ifPresent(AutoTransactionLogBloomCachingService::start); + } + + private void startExternalServicePostMainLoop() { ethStatsService.ifPresent(EthStatsService::start); } @@ -174,6 +177,9 @@ public void startEthereumMainLoop() { writeBesuPortsToFile(); writeBesuNetworksToFile(); writePidFile(); + + // start external service that depends on information from main loop + startExternalServicePostMainLoop(); } catch (final Exception ex) { LOG.error("unable to start main loop", ex); throw new IllegalStateException("Startup failed", ex); diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/EthstatsOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/EthstatsOptions.java index b4a59f32bdf..a6e939fdf0e 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/EthstatsOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/EthstatsOptions.java @@ -33,8 +33,8 @@ public class EthstatsOptions implements CLIOptions { @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) @CommandLine.Option( names = {ETHSTATS}, - paramLabel = "", - description = "Reporting URL of a ethstats server", + paramLabel = "<[ws://|wss://]nodename:secret@host:[port]>", + description = "Reporting URL of a ethstats server. Scheme and port can be omitted.", arity = "1") private String ethstatsUrl = ""; diff --git a/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/EthStatsService.java b/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/EthStatsService.java index 148b61f1f16..a3ab50d700e 100644 --- a/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/EthStatsService.java +++ b/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/EthStatsService.java @@ -164,11 +164,16 @@ private static HttpClientOptions buildHttpClientOptions( private static WebSocketConnectOptions buildWebSocketConnectOptions( final EthStatsConnectOptions ethStatsConnectOptions) { + // if user specified scheme is null, default ssl to true, otherwise set ssl to true for wss + // scheme. + final boolean isSSL = + ethStatsConnectOptions.getScheme() == null + || ethStatsConnectOptions.getScheme().equalsIgnoreCase("wss"); return new WebSocketConnectOptions() .setURI("/api") - .setSsl(true) + .setSsl(isSSL) .setHost(ethStatsConnectOptions.getHost()) - .setPort(getWsPort(ethStatsConnectOptions, true)); + .setPort(getWsPort(ethStatsConnectOptions, isSSL)); } private static int getWsPort( @@ -181,7 +186,7 @@ private static int getWsPort( /** Start. */ public void start() { - LOG.debug("Connecting to EthStats: {}", getEthStatsHost()); + LOG.debug("Connecting to EthStats: {}", getEthStatsURI()); try { enodeURL = p2PNetwork.getLocalEnode().orElseThrow(); vertx @@ -229,7 +234,7 @@ public void start() { } } - private String getEthStatsHost() { + private String getEthStatsURI() { return String.format( "%s://%s:%s", webSocketConnectOptions.isSsl() ? "wss" : "ws", @@ -237,11 +242,17 @@ private String getEthStatsHost() { getWsPort(ethStatsConnectOptions, webSocketConnectOptions.isSsl())); } - /** Switch from ssl to non-ssl and vice-versa. Sets port to 443 or 80 if not specified. */ + /** + * Switch from ssl to non-ssl and vice-versa if user specified scheme is null. Sets port to 443 or + * 80 if not specified. + */ private void updateSSLProtocol() { - final boolean updatedSSL = !webSocketConnectOptions.isSsl(); - webSocketConnectOptions.setSsl(updatedSSL); - webSocketConnectOptions.setPort(getWsPort(ethStatsConnectOptions, updatedSSL)); + if (ethStatsConnectOptions.getScheme() == null) { + final boolean updatedSSL = !webSocketConnectOptions.isSsl(); + webSocketConnectOptions.setSsl(updatedSSL); + } + webSocketConnectOptions.setPort( + getWsPort(ethStatsConnectOptions, webSocketConnectOptions.isSsl())); } /** Ends the current web socket connection, observers and schedulers */ @@ -259,6 +270,7 @@ private void retryConnect() { if (retryInProgress.getAndSet(true) == FALSE) { stop(); updateSSLProtocol(); // switch from ssl:true to ssl:false and vice-versa + LOG.info("Attempting to reconnect to ethstats server in approximately 10 seconds."); protocolManager .ethContext() .getScheduler() diff --git a/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/util/EthStatsConnectOptions.java b/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/util/EthStatsConnectOptions.java index b46fa8be004..7f020adf452 100644 --- a/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/util/EthStatsConnectOptions.java +++ b/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/util/EthStatsConnectOptions.java @@ -16,10 +16,8 @@ import static com.google.common.base.Preconditions.checkArgument; +import java.net.URI; import java.nio.file.Path; -import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import javax.annotation.Nullable; import org.immutables.value.Value; @@ -27,8 +25,8 @@ @Value.Immutable public interface EthStatsConnectOptions { - - Pattern NETSTATS_URL_REGEX = Pattern.compile("([-\\w]+):([-\\w]+)?@([-.\\w]+)(:([\\d]+))?"); + @Nullable + String getScheme(); String getNodeName(); @@ -48,22 +46,48 @@ static EthStatsConnectOptions fromParams( try { checkArgument(url != null && !url.trim().isEmpty(), "Invalid empty value."); - final Matcher netStatsUrl = NETSTATS_URL_REGEX.matcher(url); - if (netStatsUrl.matches()) { - return ImmutableEthStatsConnectOptions.builder() - .nodeName(netStatsUrl.group(1)) - .secret(netStatsUrl.group(2)) - .host(netStatsUrl.group(3)) - .port(Integer.parseInt(Optional.ofNullable(netStatsUrl.group(5)).orElse("-1"))) - .contact(contact) - .caCert(caCert) - .build(); + // if scheme is not specified in the URI, user info (nodename) gets converted to scheme. + final URI uri; + final String scheme; + if (url.matches("^.*://.*$")) { + // construct URI + uri = URI.create(url); + scheme = uri.getScheme(); + } else { + // prepend ws:// to make a valid URI while keeping scheme as null + uri = URI.create("ws://" + url); + scheme = null; + } + + if (scheme != null) { + // make sure that scheme is either ws or wss + if (!scheme.equalsIgnoreCase("ws") && !scheme.equalsIgnoreCase("wss")) { + throw new IllegalArgumentException("Ethstats URI only support ws:// or wss:// scheme."); + } + } + + final String userInfo = uri.getUserInfo(); + + // make sure user info is specified + if (userInfo == null || !userInfo.contains(":")) { + throw new IllegalArgumentException("Ethstats URI missing user info."); } + final String nodeName = userInfo.substring(0, userInfo.indexOf(":")); + final String secret = userInfo.substring(userInfo.indexOf(":") + 1); + return ImmutableEthStatsConnectOptions.builder() + .scheme(scheme) + .nodeName(nodeName) + .secret(secret) + .host(uri.getHost()) + .port(uri.getPort()) + .contact(contact) + .caCert(caCert) + .build(); } catch (IllegalArgumentException e) { LoggerFactory.getLogger(EthStatsConnectOptions.class).error(e.getMessage()); } throw new IllegalArgumentException( - "Invalid netstats URL syntax. Netstats URL should have the following format 'nodename:secret@host:port' or 'nodename:secret@host'."); + "Invalid ethstats URL syntax. Ethstats URL should have the following format '[ws://|wss://]nodename:secret@host[:port]'."); } } diff --git a/ethereum/ethstats/src/test/java/org/hyperledger/besu/ethstats/util/EthStatsConnectOptionsTest.java b/ethereum/ethstats/src/test/java/org/hyperledger/besu/ethstats/util/EthStatsConnectOptionsTest.java index d352cccb81d..577ac5b3c41 100644 --- a/ethereum/ethstats/src/test/java/org/hyperledger/besu/ethstats/util/EthStatsConnectOptionsTest.java +++ b/ethereum/ethstats/src/test/java/org/hyperledger/besu/ethstats/util/EthStatsConnectOptionsTest.java @@ -30,13 +30,14 @@ public class EthStatsConnectOptionsTest { private final String CONTACT = "contact@mail.fr"; private final String ERROR_MESSAGE = - "Invalid netstats URL syntax. Netstats URL should have the following format 'nodename:secret@host:port' or 'nodename:secret@host'."; + "Invalid ethstats URL syntax. Ethstats URL should have the following format '[ws://|wss://]nodename:secret@host[:port]'."; @Test public void buildWithValidParams() { final Path caCert = Path.of("./test.pem"); final EthStatsConnectOptions ethStatsConnectOptions = EthStatsConnectOptions.fromParams(VALID_NETSTATS_URL, CONTACT, caCert); + assertThat(ethStatsConnectOptions.getScheme()).isNull(); assertThat(ethStatsConnectOptions.getHost()).isEqualTo("127.0.0.1"); assertThat(ethStatsConnectOptions.getNodeName()).isEqualTo("Dev-Node-1"); assertThat(ethStatsConnectOptions.getPort()).isEqualTo(3001); @@ -50,7 +51,9 @@ public void buildWithValidParams() { public void buildWithValidHost(final String host) { final EthStatsConnectOptions ethStatsConnectOptions = EthStatsConnectOptions.fromParams("Dev-Node-1:secret@" + host + ":3001", CONTACT, null); + assertThat(ethStatsConnectOptions.getScheme()).isNull(); assertThat(ethStatsConnectOptions.getHost()).isEqualTo(host); + assertThat(ethStatsConnectOptions.getPort()).isEqualTo(3001); } @ParameterizedTest(name = "#{index} - With Host {0}") @@ -58,10 +61,34 @@ public void buildWithValidHost(final String host) { public void buildWithValidHostWithoutPort(final String host) { final EthStatsConnectOptions ethStatsConnectOptions = EthStatsConnectOptions.fromParams("Dev-Node-1:secret@" + host, CONTACT, null); + assertThat(ethStatsConnectOptions.getScheme()).isNull(); assertThat(ethStatsConnectOptions.getHost()).isEqualTo(host); assertThat(ethStatsConnectOptions.getPort()).isEqualTo(-1); } + @ParameterizedTest(name = "#{index} - With Scheme {0}") + @ValueSource(strings = {"ws", "wss", "WSS", "WS"}) + public void buildWithValidScheme(final String scheme) { + final EthStatsConnectOptions ethStatsConnectOptions = + EthStatsConnectOptions.fromParams( + scheme + "://Dev-Node-1:secret@url-test.test.com:3001", CONTACT, null); + assertThat(ethStatsConnectOptions.getScheme()).isEqualTo(scheme); + assertThat(ethStatsConnectOptions.getHost()).isEqualTo("url-test.test.com"); + assertThat(ethStatsConnectOptions.getPort()).isEqualTo(3001); + } + + @ParameterizedTest(name = "#{index} - With Scheme {0}") + @ValueSource(strings = {"http", "https", "ftp"}) + public void shouldRaiseErrorOnInvalidScheme(final String scheme) { + // missing node name + assertThatThrownBy( + () -> + EthStatsConnectOptions.fromParams( + scheme + "://Dev-Node-1:secret@url-test.test.com:3001", CONTACT, null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageEndingWith(ERROR_MESSAGE); + } + @Test public void shouldDetectEmptyParams() { assertThatThrownBy(() -> EthStatsConnectOptions.fromParams("", CONTACT, null)) @@ -82,11 +109,10 @@ public void shouldDetectMissingParams() { .isInstanceOf(IllegalArgumentException.class) .hasMessageEndingWith(ERROR_MESSAGE); - // missing port - assertThatThrownBy( - () -> EthStatsConnectOptions.fromParams("Dev-Node-1:secret@127.0.0.1:", CONTACT, null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageEndingWith(ERROR_MESSAGE); + // missing port in URL should default to -1 + EthStatsConnectOptions ethStatsConnectOptions = + EthStatsConnectOptions.fromParams("Dev-Node-1:secret@127.0.0.1:", CONTACT, null); + assertThat(ethStatsConnectOptions.getPort()).isEqualTo(-1); } @Test From 925b915cd91f072d874006a3fb50d19ecf47b2b5 Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Tue, 30 May 2023 10:35:48 +0200 Subject: [PATCH 06/35] Detailed transaction selection stats for layered txpool (#5492) Signed-off-by: Fabio Di Fabio --- .../blockcreation/AbstractBlockCreator.java | 10 +- .../BlockTransactionSelector.java | 105 +++++------ .../AbstractBlockTransactionSelectorTest.java | 1 + .../eth/transactions/PendingTransactions.java | 6 - .../layered/LayeredPendingTransactions.java | 39 ++--- .../AbstractPendingTransactionsSorter.java | 24 ++- .../LayeredPendingTransactionsTest.java | 20 ++- .../AbstractPendingTransactionsTestBase.java | 20 ++- plugin-api/build.gradle | 2 +- .../TransactionSelectionResult.java | 163 ++++++++++++++++++ 10 files changed, 277 insertions(+), 113 deletions(-) create mode 100644 plugin-api/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionSelectionResult.java diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java index d5e693220a9..6948140de4c 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java @@ -19,6 +19,7 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; +import org.hyperledger.besu.ethereum.blockcreation.BlockTransactionSelector.TransactionSelectionResults; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockHeader; @@ -172,7 +173,7 @@ protected BlockCreationResult createBlock( final List ommers = maybeOmmers.orElse(selectOmmers()); throwIfStopped(); - final BlockTransactionSelector.TransactionSelectionResults transactionResults = + final TransactionSelectionResults transactionResults = selectTransactions( processableBlockHeader, disposableWorldState, @@ -181,6 +182,8 @@ protected BlockCreationResult createBlock( dataGasPrice, newProtocolSpec); + transactionResults.logSelectionStats(); + throwIfStopped(); final Optional maybeWithdrawalsProcessor = @@ -257,8 +260,7 @@ protected BlockCreationResult createBlock( } private DataGas computeExcessDataGas( - BlockTransactionSelector.TransactionSelectionResults transactionResults, - ProtocolSpec newProtocolSpec) { + TransactionSelectionResults transactionResults, ProtocolSpec newProtocolSpec) { if (newProtocolSpec.getFeeMarket().implementsDataFee()) { final var gasCalculator = newProtocolSpec.getGasCalculator(); @@ -276,7 +278,7 @@ private DataGas computeExcessDataGas( return null; } - private BlockTransactionSelector.TransactionSelectionResults selectTransactions( + private TransactionSelectionResults selectTransactions( final ProcessableBlockHeader processableBlockHeader, final MutableWorldState disposableWorldState, final Optional> transactions, diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java index c14ed788d17..bd3a836e26c 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java @@ -23,7 +23,7 @@ import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions; -import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions.TransactionSelectionResult; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult; import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor; import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; @@ -43,6 +43,7 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.CancellationException; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -71,43 +72,9 @@ * not cleared between executions of buildTransactionListForBlock(). */ public class BlockTransactionSelector { - public static class TransactionValidationResult { - private final Transaction transaction; - private final ValidationResult validationResult; - public TransactionValidationResult( - final Transaction transaction, - final ValidationResult validationResult) { - this.transaction = transaction; - this.validationResult = validationResult; - } - - public Transaction getTransaction() { - return transaction; - } - - public ValidationResult getValidationResult() { - return validationResult; - } - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - TransactionValidationResult that = (TransactionValidationResult) o; - return Objects.equals(transaction, that.transaction) - && Objects.equals(validationResult, that.validationResult); - } - - @Override - public int hashCode() { - return Objects.hash(transaction, validationResult); - } - } + public record TransactionValidationResult( + Transaction transaction, ValidationResult validationResult) {} public static class TransactionSelectionResults { private final List transactions = Lists.newArrayList(); @@ -115,6 +82,7 @@ public static class TransactionSelectionResults { new EnumMap<>(TransactionType.class); private final List receipts = Lists.newArrayList(); private final List invalidTransactions = Lists.newArrayList(); + private final List selectionResults = Lists.newArrayList(); private long cumulativeGasUsed = 0; private long cumulativeDataGasUsed = 0; @@ -170,6 +138,41 @@ public List getInvalidTransactions() { return invalidTransactions; } + public void addSelectionResult(final TransactionSelectionResult res) { + selectionResults.add(res); + } + + public void logSelectionStats() { + if (LOG.isDebugEnabled()) { + final Map selectionStats = + selectionResults.stream() + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + LOG.debug( + "Selection stats: Totals[Evaluated={}, Selected={}, Skipped={}, Dropped={}]; Detailed[{}]", + selectionResults.size(), + selectionStats.entrySet().stream() + .filter(e -> e.getKey().selected()) + .map(Map.Entry::getValue) + .mapToInt(Long::intValue) + .sum(), + selectionStats.entrySet().stream() + .filter(e -> !e.getKey().selected()) + .map(Map.Entry::getValue) + .mapToInt(Long::intValue) + .sum(), + selectionStats.entrySet().stream() + .filter(e -> e.getKey().discard()) + .map(Map.Entry::getValue) + .mapToInt(Long::intValue) + .sum(), + selectionStats.entrySet().stream() + .map(e -> e.getKey().toString() + "=" + e.getValue()) + .sorted() + .collect(Collectors.joining(", "))); + } + } + @Override public boolean equals(final Object o) { if (this == o) { @@ -265,9 +268,13 @@ public TransactionSelectionResults buildTransactionListForBlock() { .addArgument(pendingTransactions.logStats()) .log(); pendingTransactions.selectTransactions( - pendingTransaction -> evaluateTransaction(pendingTransaction, false)); + pendingTransaction -> { + final var res = evaluateTransaction(pendingTransaction, false); + transactionSelectionResult.addSelectionResult(res); + return res; + }); LOG.atTrace() - .setMessage("Transaction selection result result {}") + .setMessage("Transaction selection result {}") .addArgument(transactionSelectionResult::toTraceLog) .log(); return transactionSelectionResult; @@ -280,7 +287,9 @@ public TransactionSelectionResults buildTransactionListForBlock() { * @return The {@code TransactionSelectionResults} results of transaction evaluation. */ public TransactionSelectionResults evaluateTransactions(final List transactions) { - transactions.forEach(transaction -> evaluateTransaction(transaction, true)); + transactions.forEach( + transaction -> + transactionSelectionResult.addSelectionResult(evaluateTransaction(transaction, true))); return transactionSelectionResult; } @@ -306,20 +315,20 @@ private TransactionSelectionResult evaluateTransaction( .log(); if (blockOccupancyAboveThreshold()) { LOG.trace("Block occupancy above threshold, completing operation"); - return TransactionSelectionResult.COMPLETE_OPERATION; + return TransactionSelectionResult.BLOCK_OCCUPANCY_ABOVE_THRESHOLD; } else if (blockFull()) { LOG.trace("Block full, completing operation"); - return TransactionSelectionResult.COMPLETE_OPERATION; + return TransactionSelectionResult.BLOCK_FULL; } else { - return TransactionSelectionResult.CONTINUE; + return TransactionSelectionResult.TX_TOO_LARGE_FOR_REMAINING_GAS; } } if (transactionCurrentPriceBelowMin(transaction)) { - return TransactionSelectionResult.CONTINUE; + return TransactionSelectionResult.CURRENT_TX_PRICE_BELOW_MIN; } if (transactionDataPriceBelowMin(transaction)) { - return TransactionSelectionResult.CONTINUE; + return TransactionSelectionResult.DATA_PRICE_BELOW_CURRENT_MIN; } final WorldUpdater worldStateUpdater = worldState.updater(); @@ -354,7 +363,7 @@ private TransactionSelectionResult evaluateTransaction( return transactionSelectionResultForInvalidResult( transaction, effectiveResult.getValidationResult()); } - return TransactionSelectionResult.CONTINUE; + return TransactionSelectionResult.SELECTED; } private boolean transactionDataPriceBelowMin(final Transaction transaction) { @@ -405,7 +414,7 @@ private TransactionSelectionResult transactionSelectionResultForInvalidResult( .addArgument(invalidReason) .addArgument(transaction::toTraceLog) .log(); - return TransactionSelectionResult.CONTINUE; + return TransactionSelectionResult.invalidTransient(invalidReason.name()); } // If the transaction was invalid for any other reason, delete it, and continue. LOG.atTrace() @@ -413,7 +422,7 @@ private TransactionSelectionResult transactionSelectionResultForInvalidResult( .addArgument(transaction::toTraceLog) .addArgument(invalidReason) .log(); - return TransactionSelectionResult.DELETE_TRANSACTION_AND_CONTINUE; + return TransactionSelectionResult.invalid(invalidReason.name()); } private boolean isTransientValidationError(final TransactionInvalidReason invalidReason) { diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java index c7528cd5775..0c3d07333bd 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java @@ -83,6 +83,7 @@ public abstract class AbstractBlockTransactionSelectorTest { protected static final double MIN_OCCUPANCY_100_PERCENT = 1; protected static final KeyPair keyPair = SignatureAlgorithmFactory.getInstance().generateKeyPair(); + protected final MetricsSystem metricsSystem = new NoOpMetricsSystem(); protected final Blockchain blockchain = new ReferenceTestBlockchain(); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactions.java index 1b00e82f64d..338abdb8bbc 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactions.java @@ -85,12 +85,6 @@ default void signalInvalidAndRemoveDependentTransactions(final Transaction trans boolean isLocalSender(Address sender); - enum TransactionSelectionResult { - DELETE_TRANSACTION_AND_CONTINUE, - CONTINUE, - COMPLETE_OPERATION - } - @FunctionalInterface interface TransactionSelector { TransactionSelectionResult evaluateTransaction(Transaction transaction); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java index 9699e13604d..f9ed91e3a14 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java @@ -349,29 +349,22 @@ public synchronized void selectTransactions( .forEach( candidatePendingTx -> { alreadyChecked.add(candidatePendingTx.getHash()); - switch (selector.evaluateTransaction( - candidatePendingTx.getTransaction())) { - case CONTINUE: - LOG.atTrace() - .setMessage("CONTINUE: Transaction {}") - .addArgument(candidatePendingTx::toTraceLog) - .log(); - break; - case DELETE_TRANSACTION_AND_CONTINUE: - invalidTransactions.add(candidatePendingTx); - LOG.atTrace() - .setMessage("DELETE_TRANSACTION_AND_CONTINUE: Transaction {}") - .addArgument(candidatePendingTx::toTraceLog) - .log(); - logTransactionForReplayDelete(candidatePendingTx); - break; - case COMPLETE_OPERATION: - completed.set(true); - LOG.atTrace() - .setMessage("COMPLETE_OPERATION: Transaction {}") - .addArgument(candidatePendingTx::toTraceLog) - .log(); - break; + final var res = + selector.evaluateTransaction(candidatePendingTx.getTransaction()); + + LOG.atTrace() + .setMessage("Selection result {} for transaction {}") + .addArgument(res) + .addArgument(candidatePendingTx::toTraceLog) + .log(); + + if (res.discard()) { + invalidTransactions.add(candidatePendingTx); + logTransactionForReplayDelete(candidatePendingTx); + } + + if (res.stop()) { + completed.set(true); } })); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java index 530175934ed..c020882c76f 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java @@ -32,6 +32,7 @@ import org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolReplacementHandler; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.account.AccountState; @@ -263,19 +264,16 @@ public void selectTransactions(final TransactionSelector selector) { highestPriorityPendingTransaction.getTransaction())) { final TransactionSelectionResult result = selector.evaluateTransaction(transactionToProcess); - switch (result) { - case DELETE_TRANSACTION_AND_CONTINUE: - transactionsToRemove.add(transactionToProcess); - transactionsToRemove.addAll( - signalInvalidAndGetDependentTransactions(transactionToProcess)); - break; - case CONTINUE: - break; - case COMPLETE_OPERATION: - transactionsToRemove.forEach(this::removeTransaction); - return; - default: - throw new RuntimeException("Illegal value for TransactionSelectionResult."); + + if (result.discard()) { + transactionsToRemove.add(transactionToProcess); + transactionsToRemove.addAll( + signalInvalidAndGetDependentTransactions(transactionToProcess)); + } + + if (result.stop()) { + transactionsToRemove.forEach(this::removeTransaction); + return; } } } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java index f864eb1dc25..e4a27470935 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java @@ -15,13 +15,12 @@ package org.hyperledger.besu.ethereum.eth.transactions.layered; import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions.TransactionSelectionResult.COMPLETE_OPERATION; -import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions.TransactionSelectionResult.CONTINUE; -import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions.TransactionSelectionResult.DELETE_TRANSACTION_AND_CONTINUE; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.ADDED; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.ALREADY_KNOWN; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.NONCE_TOO_FAR_IN_FUTURE_FOR_SENDER; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.REJECTED_UNDERPRICED_REPLACEMENT; +import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.BLOCK_OCCUPANCY_ABOVE_THRESHOLD; +import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.SELECTED; import static org.hyperledger.besu.ethereum.eth.transactions.layered.TransactionsLayer.RemovalReason.DROPPED; import static org.hyperledger.besu.ethereum.eth.transactions.layered.TransactionsLayer.RemovalReason.REPLACED; import static org.mockito.Mockito.mock; @@ -42,7 +41,9 @@ import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolMetrics; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolReplacementHandler; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; +import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; import org.hyperledger.besu.evm.account.Account; import java.util.ArrayList; @@ -292,7 +293,7 @@ public void selectTransactionsUntilSelectorRequestsNoMore() { pendingTransactions.selectTransactions( transaction -> { parsedTransactions.add(transaction); - return COMPLETE_OPERATION; + return BLOCK_OCCUPANCY_ABOVE_THRESHOLD; }); assertThat(parsedTransactions.size()).isEqualTo(1); @@ -308,7 +309,7 @@ public void selectTransactionsUntilPendingIsEmpty() { pendingTransactions.selectTransactions( transaction -> { parsedTransactions.add(transaction); - return CONTINUE; + return SELECTED; }); assertThat(parsedTransactions.size()).isEqualTo(2); @@ -328,7 +329,7 @@ public void notSelectReplacedTransaction() { pendingTransactions.selectTransactions( transaction -> { parsedTransactions.add(transaction); - return CONTINUE; + return SELECTED; }); assertThat(parsedTransactions).containsExactly(transaction1b); @@ -349,7 +350,7 @@ public void selectTransactionsFromSameSenderInNonceOrder() { pendingTransactions.selectTransactions( transaction -> { iterationOrder.add(transaction); - return CONTINUE; + return SELECTED; }); assertThat(iterationOrder).containsExactly(transaction0, transaction1, transaction2); @@ -370,7 +371,7 @@ public void notForceNonceOrderWhenSendersDiffer() { pendingTransactions.selectTransactions( transaction -> { iterationOrder.add(transaction); - return CONTINUE; + return SELECTED; }); assertThat(iterationOrder).containsExactly(transactionSender2, transactionSender1); @@ -385,7 +386,8 @@ public void invalidTransactionIsDeletedFromPendingTransactions() { pendingTransactions.selectTransactions( transaction -> { parsedTransactions.add(transaction); - return DELETE_TRANSACTION_AND_CONTINUE; + return TransactionSelectionResult.invalid( + TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE.name()); }); assertThat(parsedTransactions.size()).isEqualTo(2); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsTestBase.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsTestBase.java index c138779373d..45008d8bd5f 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsTestBase.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsTestBase.java @@ -15,11 +15,10 @@ package org.hyperledger.besu.ethereum.eth.transactions.sorter; import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions.TransactionSelectionResult.CONTINUE; -import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions.TransactionSelectionResult.DELETE_TRANSACTION_AND_CONTINUE; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.ADDED; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.ALREADY_KNOWN; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.REJECTED_UNDERPRICED_REPLACEMENT; +import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.SELECTED; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; @@ -41,6 +40,8 @@ import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactionDroppedListener; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult; +import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.metrics.StubMetricsSystem; import org.hyperledger.besu.testutil.TestClock; @@ -314,7 +315,7 @@ public void selectTransactionsUntilSelectorRequestsNoMore() { transactions.selectTransactions( transaction -> { parsedTransactions.add(transaction); - return PendingTransactions.TransactionSelectionResult.COMPLETE_OPERATION; + return TransactionSelectionResult.BLOCK_OCCUPANCY_ABOVE_THRESHOLD; }); assertThat(parsedTransactions.size()).isEqualTo(1); @@ -330,7 +331,7 @@ public void selectTransactionsUntilPendingIsEmpty() { transactions.selectTransactions( transaction -> { parsedTransactions.add(transaction); - return CONTINUE; + return SELECTED; }); assertThat(parsedTransactions.size()).isEqualTo(2); @@ -350,7 +351,7 @@ public void shouldNotSelectReplacedTransaction() { transactions.selectTransactions( transaction -> { parsedTransactions.add(transaction); - return CONTINUE; + return SELECTED; }); assertThat(parsedTransactions).containsExactly(transaction2); @@ -365,7 +366,8 @@ public void invalidTransactionIsDeletedFromPendingTransactions() { transactions.selectTransactions( transaction -> { parsedTransactions.add(transaction); - return DELETE_TRANSACTION_AND_CONTINUE; + return TransactionSelectionResult.invalid( + TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE.name()); }); assertThat(parsedTransactions.size()).isEqualTo(2); @@ -533,7 +535,7 @@ public void shouldIterateTransactionsFromSameSenderInNonceOrder() { transactions.selectTransactions( transaction -> { iterationOrder.add(transaction); - return CONTINUE; + return SELECTED; }); assertThat(iterationOrder).containsExactly(transaction1, transaction2, transaction3); @@ -551,7 +553,7 @@ public void shouldNotForceNonceOrderWhenSendersDiffer() { transactions.selectTransactions( transaction -> { iterationOrder.add(transaction); - return CONTINUE; + return SELECTED; }); assertThat(iterationOrder).containsExactly(transaction2, transaction1); @@ -573,7 +575,7 @@ public void shouldNotIncreasePriorityOfTransactionsBecauseOfNonceOrder() { transactions.selectTransactions( transaction -> { iterationOrder.add(transaction); - return CONTINUE; + return SELECTED; }); // Ignoring nonces, the order would be 3, 2, 4, 1 but we have to delay 3 and 2 until after 1. diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index a465d64b0f6..442dd5f7856 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -69,7 +69,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = '3/qsZ9+jA10YbctpPtQ5Rn7cvYHwKRWBv6jXa+7WQMY=' + knownHash = 'WC7tcTTrQg//+cIarm7NSabnxm6nY0lLkHWOH6+7Rmo=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionSelectionResult.java b/plugin-api/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionSelectionResult.java new file mode 100644 index 00000000000..94e0b214f55 --- /dev/null +++ b/plugin-api/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionSelectionResult.java @@ -0,0 +1,163 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.ethereum.eth.transactions; + +import java.util.Objects; +import java.util.Optional; + +/** + * Represent the result of the selection process of a candidate transaction, during the block + * creation phase. + */ +public class TransactionSelectionResult { + + private enum Status { + SELECTED, + BLOCK_FULL(true, false), + BLOCK_OCCUPANCY_ABOVE_THRESHOLD(true, false), + INVALID_TRANSIENT(false, false), + INVALID(false, true); + + private final boolean stop; + private final boolean discard; + + Status() { + this.stop = false; + this.discard = false; + } + + Status(final boolean stop, final boolean discard) { + this.stop = stop; + this.discard = discard; + } + + @Override + public String toString() { + return name() + " (stop=" + stop + ", discard=" + discard + ")"; + } + } + + /** The transaction has been selected to be included in the new block */ + public static final TransactionSelectionResult SELECTED = + new TransactionSelectionResult(Status.SELECTED); + /** The transaction has not been selected since the block is full. */ + public static final TransactionSelectionResult BLOCK_FULL = + new TransactionSelectionResult(Status.BLOCK_FULL); + /** + * The transaction has not been selected since too large and the occupancy of the block is enough + * to stop the selection. + */ + public static final TransactionSelectionResult BLOCK_OCCUPANCY_ABOVE_THRESHOLD = + new TransactionSelectionResult(Status.BLOCK_OCCUPANCY_ABOVE_THRESHOLD); + /** + * The transaction has not been selected since its gas limit is greater than the block remaining + * gas, but the selection should continue. + */ + public static final TransactionSelectionResult TX_TOO_LARGE_FOR_REMAINING_GAS = + TransactionSelectionResult.invalidTransient("TX_TOO_LARGE_FOR_REMAINING_GAS"); + /** + * The transaction has not been selected since its current price is below the configured min + * price, but the selection should continue. + */ + public static final TransactionSelectionResult CURRENT_TX_PRICE_BELOW_MIN = + TransactionSelectionResult.invalidTransient("CURRENT_TX_PRICE_BELOW_MIN"); + /** + * The transaction has not been selected since its data price is below the current network data + * price, but the selection should continue. + */ + public static final TransactionSelectionResult DATA_PRICE_BELOW_CURRENT_MIN = + TransactionSelectionResult.invalidTransient("DATA_PRICE_BELOW_CURRENT_MIN"); + + private final Status status; + private final Optional maybeInvalidReason; + + private TransactionSelectionResult(final Status status) { + this(status, null); + } + + private TransactionSelectionResult(final Status status, final String invalidReason) { + this.status = status; + this.maybeInvalidReason = Optional.ofNullable(invalidReason); + } + + /** + * Return a selection result that identify the candidate transaction as temporarily invalid, this + * means that the transaction could become valid at a later time. + * + * @param invalidReason the reason why transaction is invalid + * @return the selection result + */ + public static TransactionSelectionResult invalidTransient(final String invalidReason) { + return new TransactionSelectionResult(Status.INVALID_TRANSIENT, invalidReason); + } + + /** + * Return a selection result that identify the candidate transaction as permanently invalid, this + * means that it could be removed safely from the transaction pool. + * + * @param invalidReason the reason why transaction is invalid + * @return the selection result + */ + public static TransactionSelectionResult invalid(final String invalidReason) { + return new TransactionSelectionResult(Status.INVALID, invalidReason); + } + + /** + * Is the block creation done and the selection process should stop? + * + * @return true if the selection process should stop, false otherwise + */ + public boolean stop() { + return status.stop; + } + + /** + * Should the candidate transaction removed from the transaction pool? + * + * @return true if the candidate transaction should be removed from transaction pool, false + * otherwise + */ + public boolean discard() { + return status.discard; + } + + /** + * Is the candidate transaction selected for block inclusion? + * + * @return true if the candidate transaction is included in the new block, false otherwise + */ + public boolean selected() { + return Status.SELECTED.equals(status); + } + + @Override + public String toString() { + return status.name() + maybeInvalidReason.map(ir -> "(" + ir + ")").orElse(""); + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final TransactionSelectionResult that = (TransactionSelectionResult) o; + return status == that.status && Objects.equals(maybeInvalidReason, that.maybeInvalidReason); + } + + @Override + public int hashCode() { + return Objects.hash(status, maybeInvalidReason); + } +} From cc2150d5376cbdb15b0cef58c6d3144e66359910 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Tue, 30 May 2023 05:38:21 -0600 Subject: [PATCH 07/35] GraphQL Support for withdrawals (#5496) Add support for withdrawals in GraphQL, including needed changes to testing infrastructure for shanghai-era blocks. Also align existing adapters with graphql schema optionality. Signed-off-by: Danno Ferrin --- CHANGELOG.md | 3 +- .../api/graphql/internal/Scalars.java | 166 ++++++++++++------ .../internal/pojoadapter/AccountAdapter.java | 22 +-- .../pojoadapter/BlockAdapterBase.java | 121 +++++++------ .../pojoadapter/EmptyAccountAdapter.java | 22 ++- .../internal/pojoadapter/LogAdapter.java | 20 ++- .../pojoadapter/NormalBlockAdapter.java | 8 +- .../pojoadapter/PendingStateAdapter.java | 25 ++- .../pojoadapter/SyncStateAdapter.java | 14 +- .../pojoadapter/TransactionAdapter.java | 50 +++--- .../pojoadapter/UncleBlockAdapter.java | 4 +- .../pojoadapter/WithdrawalAdapter.java | 43 +++++ .../api/src/main/resources/schema.graphqls | 61 +++++-- .../AbstractEthGraphQLHttpServiceTest.java | 75 ++------ .../api/graphql/BlockDataFetcherTest.java | 25 +-- .../api/graphql/EthGraphQLHttpBySpecTest.java | 12 +- .../api/graphql/scalar/AddressScalarTest.java | 59 ++++++- .../api/graphql/scalar/BigIntScalarTest.java | 55 ++++-- .../api/graphql/scalar/Bytes32ScalarTest.java | 56 +++++- .../api/graphql/scalar/BytesScalarTest.java | 56 +++++- .../api/graphql/scalar/LongScalarTest.java | 76 ++++++-- .../api/graphql/block_withdrawals.json | 20 +++ .../block_withdrawals_pre_shanghai.json | 15 ++ .../ethereum/api/graphql/eth_blockNumber.json | 2 +- .../api/graphql/eth_call_BlockLatest.json | 2 +- .../api/graphql/eth_call_from_contract.json | 2 +- .../eth_estimateGas_contractDeploy.json | 2 +- .../eth_estimateGas_from_contract.json | 2 +- .../api/graphql/eth_estimateGas_noParams.json | 2 +- .../eth_getBalance_invalidAccountLatest.json | 4 +- .../api/graphql/eth_getBalance_toobig_bn.json | 4 +- .../api/graphql/eth_getBlock_shanghai.json | 29 +++ .../api/graphql/eth_getTransactionCount.json | 2 +- .../api/graphql/eth_getTransaction_type2.json | 19 ++ .../api/graphql/graphql_blocks_byFrom.json | 3 + .../ethereum/api/graphql/graphql_pending.json | 2 +- .../besu/testutil/BlockTestUtil.java | 24 +++ .../main/resources/hive/testBlockchain.blocks | Bin 0 -> 24039 bytes .../src/main/resources/hive/testGenesis.json | 22 +++ 39 files changed, 793 insertions(+), 336 deletions(-) create mode 100644 ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/WithdrawalAdapter.java create mode 100644 ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals.json create mode 100644 ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals_pre_shanghai.json create mode 100644 ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json create mode 100644 ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json create mode 100644 testutil/src/main/resources/hive/testBlockchain.blocks create mode 100644 testutil/src/main/resources/hive/testGenesis.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 2821eab3388..17bd4f09ee7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ ### Additions and Improvements - Allow Ethstats connection url to specify ws:// or wss:// scheme. [#5494](https://github.com/hyperledger/besu/issues/5494) -- +- Add support for Shanghai changes to the GraphQL service [#5496](https://github.com/hyperledger/besu/pull/5496) + ### Bug Fixes ### Download Links diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/Scalars.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/Scalars.java index bfaf092b3d7..251f4815bf2 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/Scalars.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/Scalars.java @@ -17,8 +17,13 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity; +import java.util.Locale; + +import graphql.GraphQLContext; +import graphql.execution.CoercedVariables; import graphql.language.IntValue; import graphql.language.StringValue; +import graphql.language.Value; import graphql.schema.Coercing; import graphql.schema.CoercingParseLiteralException; import graphql.schema.CoercingParseValueException; @@ -35,19 +40,19 @@ private Scalars() {} private static final Coercing ADDRESS_COERCING = new Coercing() { Address convertImpl(final Object input) { - if (input instanceof Address) { - return (Address) input; - } else if (input instanceof Bytes) { + if (input instanceof Address address) { + return address; + } else if (input instanceof Bytes bytes) { if (((Bytes) input).size() <= 20) { - return Address.wrap((Bytes) input); + return Address.wrap(bytes); } else { return null; } - } else if (input instanceof StringValue) { - return convertImpl(((StringValue) input).getValue()); - } else if (input instanceof String) { + } else if (input instanceof StringValue stringValue) { + return convertImpl(stringValue.getValue()); + } else if (input instanceof String string) { try { - return Address.fromHexStringStrict((String) input); + return Address.fromHexStringStrict(string); } catch (IllegalArgumentException iae) { return null; } @@ -57,7 +62,9 @@ Address convertImpl(final Object input) { } @Override - public String serialize(final Object input) throws CoercingSerializeException { + public String serialize( + final Object input, final GraphQLContext graphQLContext, final Locale locale) + throws CoercingSerializeException { Address result = convertImpl(input); if (result != null) { return result.toHexString(); @@ -67,7 +74,9 @@ public String serialize(final Object input) throws CoercingSerializeException { } @Override - public Address parseValue(final Object input) throws CoercingParseValueException { + public Address parseValue( + final Object input, final GraphQLContext graphQLContext, final Locale locale) + throws CoercingParseValueException { Address result = convertImpl(input); if (result != null) { return result; @@ -78,7 +87,12 @@ public Address parseValue(final Object input) throws CoercingParseValueException } @Override - public Address parseLiteral(final Object input) throws CoercingParseLiteralException { + public Address parseLiteral( + final Value input, + final CoercedVariables variables, + final GraphQLContext graphQLContext, + final Locale locale) + throws CoercingParseLiteralException { Address result = convertImpl(input); if (result != null) { return result; @@ -92,25 +106,27 @@ public Address parseLiteral(final Object input) throws CoercingParseLiteralExcep new Coercing() { String convertImpl(final Object input) { - if (input instanceof String) { + if (input instanceof String string) { try { - return Bytes.fromHexStringLenient((String) input).toShortHexString(); + return Bytes.fromHexStringLenient(string).toShortHexString(); } catch (IllegalArgumentException iae) { return null; } - } else if (input instanceof Bytes) { - return ((Bytes) input).toShortHexString(); - } else if (input instanceof StringValue) { - return convertImpl(((StringValue) input).getValue()); - } else if (input instanceof IntValue) { - return UInt256.valueOf(((IntValue) input).getValue()).toShortHexString(); + } else if (input instanceof Bytes bytes) { + return bytes.toShortHexString(); + } else if (input instanceof StringValue stringValue) { + return convertImpl(stringValue.getValue()); + } else if (input instanceof IntValue intValue) { + return UInt256.valueOf(intValue.getValue()).toShortHexString(); } else { return null; } } @Override - public String serialize(final Object input) throws CoercingSerializeException { + public String serialize( + final Object input, final GraphQLContext graphQLContext, final Locale locale) + throws CoercingSerializeException { var result = convertImpl(input); if (result != null) { return result; @@ -120,7 +136,9 @@ public String serialize(final Object input) throws CoercingSerializeException { } @Override - public String parseValue(final Object input) throws CoercingParseValueException { + public String parseValue( + final Object input, final GraphQLContext graphQLContext, final Locale locale) + throws CoercingParseValueException { var result = convertImpl(input); if (result != null) { return result; @@ -131,7 +149,12 @@ public String parseValue(final Object input) throws CoercingParseValueException } @Override - public String parseLiteral(final Object input) throws CoercingParseLiteralException { + public String parseLiteral( + final Value input, + final CoercedVariables variables, + final GraphQLContext graphQLContext, + final Locale locale) + throws CoercingParseLiteralException { var result = convertImpl(input); if (result != null) { return result; @@ -145,12 +168,12 @@ public String parseLiteral(final Object input) throws CoercingParseLiteralExcept new Coercing() { Bytes convertImpl(final Object input) { - if (input instanceof Bytes) { - return (Bytes) input; - } else if (input instanceof StringValue) { - return convertImpl(((StringValue) input).getValue()); - } else if (input instanceof String) { - if (!Quantity.isValid((String) input)) { + if (input instanceof Bytes bytes) { + return bytes; + } else if (input instanceof StringValue stringValue) { + return convertImpl(stringValue.getValue()); + } else if (input instanceof String string) { + if (!Quantity.isValid(string)) { throw new CoercingParseLiteralException( "Bytes value '" + input + "' is not prefixed with 0x"); } @@ -165,7 +188,9 @@ Bytes convertImpl(final Object input) { } @Override - public String serialize(final Object input) throws CoercingSerializeException { + public String serialize( + final Object input, final GraphQLContext graphQLContext, final Locale locale) + throws CoercingSerializeException { var result = convertImpl(input); if (result != null) { return result.toHexString(); @@ -175,7 +200,9 @@ public String serialize(final Object input) throws CoercingSerializeException { } @Override - public Bytes parseValue(final Object input) throws CoercingParseValueException { + public Bytes parseValue( + final Object input, final GraphQLContext graphQLContext, final Locale locale) + throws CoercingParseValueException { var result = convertImpl(input); if (result != null) { return result; @@ -186,7 +213,12 @@ public Bytes parseValue(final Object input) throws CoercingParseValueException { } @Override - public Bytes parseLiteral(final Object input) throws CoercingParseLiteralException { + public Bytes parseLiteral( + final Value input, + final CoercedVariables variables, + final GraphQLContext graphQLContext, + final Locale locale) + throws CoercingParseLiteralException { var result = convertImpl(input); if (result != null) { return result; @@ -200,18 +232,18 @@ public Bytes parseLiteral(final Object input) throws CoercingParseLiteralExcepti new Coercing() { Bytes32 convertImpl(final Object input) { - if (input instanceof Bytes32) { - return (Bytes32) input; - } else if (input instanceof Bytes) { - if (((Bytes) input).size() <= 32) { + if (input instanceof Bytes32 bytes32) { + return bytes32; + } else if (input instanceof Bytes bytes) { + if (bytes.size() <= 32) { return Bytes32.leftPad((Bytes) input); } else { return null; } - } else if (input instanceof StringValue) { - return convertImpl((((StringValue) input).getValue())); - } else if (input instanceof String) { - if (!Quantity.isValid((String) input)) { + } else if (input instanceof StringValue stringValue) { + return convertImpl(stringValue.getValue()); + } else if (input instanceof String string) { + if (!Quantity.isValid(string)) { throw new CoercingParseLiteralException( "Bytes32 value '" + input + "' is not prefixed with 0x"); } else { @@ -227,7 +259,9 @@ Bytes32 convertImpl(final Object input) { } @Override - public String serialize(final Object input) throws CoercingSerializeException { + public String serialize( + final Object input, final GraphQLContext graphQLContext, final Locale locale) + throws CoercingSerializeException { var result = convertImpl(input); if (result == null) { throw new CoercingSerializeException("Unable to serialize " + input + " as an Bytes32"); @@ -237,7 +271,9 @@ public String serialize(final Object input) throws CoercingSerializeException { } @Override - public Bytes32 parseValue(final Object input) throws CoercingParseValueException { + public Bytes32 parseValue( + final Object input, final GraphQLContext graphQLContext, final Locale locale) + throws CoercingParseValueException { var result = convertImpl(input); if (result == null) { throw new CoercingParseValueException( @@ -248,7 +284,12 @@ public Bytes32 parseValue(final Object input) throws CoercingParseValueException } @Override - public Bytes32 parseLiteral(final Object input) throws CoercingParseLiteralException { + public Bytes32 parseLiteral( + final Value input, + final CoercedVariables variables, + final GraphQLContext graphQLContext, + final Locale locale) + throws CoercingParseLiteralException { var result = convertImpl(input); if (result == null) { throw new CoercingParseLiteralException("Value is not any Bytes32 : '" + input + "'"); @@ -259,13 +300,15 @@ public Bytes32 parseLiteral(final Object input) throws CoercingParseLiteralExcep }; private static final Coercing LONG_COERCING = - new Coercing() { + new Coercing<>() { @Override - public Number serialize(final Object input) throws CoercingSerializeException { - if (input instanceof Number) { - return (Number) input; - } else if (input instanceof String) { - final String value = ((String) input).toLowerCase(); + public Number serialize( + final Object input, final GraphQLContext graphQLContext, final Locale locale) + throws CoercingSerializeException { + if (input instanceof Number number) { + return number; + } else if (input instanceof String string) { + final String value = string.toLowerCase(); if (value.startsWith("0x")) { return Bytes.fromHexStringLenient(value).toLong(); } else { @@ -276,11 +319,13 @@ public Number serialize(final Object input) throws CoercingSerializeException { } @Override - public Number parseValue(final Object input) throws CoercingParseValueException { - if (input instanceof Number) { - return (Number) input; - } else if (input instanceof String) { - final String value = ((String) input).toLowerCase(); + public Number parseValue( + final Object input, final GraphQLContext graphQLContext, final Locale locale) + throws CoercingParseValueException { + if (input instanceof Number number) { + return number; + } else if (input instanceof String string) { + final String value = string.toLowerCase(); if (value.startsWith("0x")) { return Bytes.fromHexStringLenient(value).toLong(); } else { @@ -292,12 +337,17 @@ public Number parseValue(final Object input) throws CoercingParseValueException } @Override - public Number parseLiteral(final Object input) throws CoercingParseLiteralException { + public Number parseLiteral( + final Value input, + final CoercedVariables variables, + final GraphQLContext graphQLContext, + final Locale locale) + throws CoercingParseLiteralException { try { - if (input instanceof IntValue) { - return ((IntValue) input).getValue().longValue(); - } else if (input instanceof StringValue) { - final String value = ((StringValue) input).getValue().toLowerCase(); + if (input instanceof IntValue intValue) { + return intValue.getValue().longValue(); + } else if (input instanceof StringValue stringValue) { + final String value = stringValue.getValue().toLowerCase(); if (value.startsWith("0x")) { return Bytes.fromHexStringLenient(value).toLong(); } else { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccountAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccountAdapter.java index f49d709b227..c8acb708ac8 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccountAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccountAdapter.java @@ -41,24 +41,26 @@ public AccountAdapter(final Address address, final Account account) { this.address = address; } - public Optional
getAddress() { - return Optional.of(address); + public Address getAddress() { + return address; } - public Optional getBalance() { - return account.map(AccountState::getBalance).or(() -> Optional.of(Wei.ZERO)); + public Wei getBalance() { + return account.map(AccountState::getBalance).orElse(Wei.ZERO); } - public Optional getTransactionCount() { - return account.map(AccountState::getNonce).or(() -> Optional.of(0L)); + public Long getTransactionCount() { + return account.map(AccountState::getNonce).orElse(0L); } - public Optional getCode() { - return account.map(AccountState::getCode); + public Bytes getCode() { + return account.map(AccountState::getCode).orElse(Bytes.EMPTY); } - public Optional getStorage(final DataFetchingEnvironment environment) { + public Bytes32 getStorage(final DataFetchingEnvironment environment) { final Bytes32 slot = environment.getArgument("slot"); - return account.map(account -> account.getStorageValue(UInt256.fromBytes(slot))); + return account + .map(a -> (Bytes32) a.getStorageValue(UInt256.fromBytes(slot))) + .orElse(Bytes32.ZERO); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java index 9a22dedd55c..2b8251ce858 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java @@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.LogWithMetadata; +import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; @@ -39,7 +40,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.stream.Collectors; +import java.util.function.Function; import com.google.common.primitives.Longs; import graphql.schema.DataFetchingEnvironment; @@ -64,29 +65,29 @@ public Optional getParent(final DataFetchingEnvironment envi return block.map(NormalBlockAdapter::new); } - public Optional getHash() { - return Optional.of(header.getHash()); + public Bytes32 getHash() { + return header.getHash(); } - public Optional getNonce() { + public Bytes getNonce() { final long nonce = header.getNonce(); final byte[] bytes = Longs.toByteArray(nonce); - return Optional.of(Bytes.wrap(bytes)); + return Bytes.wrap(bytes); } - public Optional getTransactionsRoot() { - return Optional.of(header.getTransactionsRoot()); + public Bytes32 getTransactionsRoot() { + return header.getTransactionsRoot(); } - public Optional getStateRoot() { - return Optional.of(header.getStateRoot()); + public Bytes32 getStateRoot() { + return header.getStateRoot(); } - public Optional getReceiptsRoot() { - return Optional.of(header.getReceiptsRoot()); + public Bytes32 getReceiptsRoot() { + return header.getReceiptsRoot(); } - public Optional getMiner(final DataFetchingEnvironment environment) { + public AdapterBase getMiner(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); long blockNumber = header.getNumber(); @@ -98,60 +99,61 @@ public Optional getMiner(final DataFetchingEnvironment environment) return query .getAndMapWorldState(blockNumber, ws -> Optional.ofNullable(ws.get(header.getCoinbase()))) .map(account -> (AdapterBase) new AccountAdapter(account)) - .or(() -> Optional.of(new EmptyAccountAdapter(header.getCoinbase()))); + .orElseGet(() -> new EmptyAccountAdapter(header.getCoinbase())); } - public Optional getExtraData() { - return Optional.of(header.getExtraData()); + public Bytes getExtraData() { + return header.getExtraData(); } public Optional getBaseFeePerGas() { return header.getBaseFee(); } - public Optional getGasLimit() { - return Optional.of(header.getGasLimit()); + public Long getGasLimit() { + return header.getGasLimit(); } - public Optional getGasUsed() { - return Optional.of(header.getGasUsed()); + public Long getGasUsed() { + return header.getGasUsed(); } - public Optional getTimestamp() { - return Optional.of(header.getTimestamp()); + public Long getTimestamp() { + return header.getTimestamp(); } - public Optional getLogsBloom() { - return Optional.of(header.getLogsBloom()); + public Bytes getLogsBloom() { + return header.getLogsBloom(); } - public Optional getMixHash() { - return Optional.of(header.getMixHash()); + public Bytes32 getMixHash() { + return header.getMixHash(); } - public Optional getDifficulty() { - return Optional.of(header.getDifficulty()); + public Difficulty getDifficulty() { + return header.getDifficulty(); } - public Optional getOmmerHash() { - return Optional.of(header.getOmmersHash()); + public Bytes32 getOmmerHash() { + return header.getOmmersHash(); } - public Optional getNumber() { - final long bn = header.getNumber(); - return Optional.of(bn); + public Long getNumber() { + return header.getNumber(); } - public Optional getAccount(final DataFetchingEnvironment environment) { + public AccountAdapter getAccount(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); final long bn = header.getNumber(); - return query.getAndMapWorldState( - bn, - ws -> { - final Address address = environment.getArgument("address"); - return Optional.of(new AccountAdapter(ws.get(address))); - }); + return query + .getAndMapWorldState( + bn, + ws -> { + final Address address = environment.getArgument("address"); + return Optional.of(new AccountAdapter(ws.get(address))); + }) + .get(); } public List getLogs(final DataFetchingEnvironment environment) { @@ -168,7 +170,7 @@ public List getLogs(final DataFetchingEnvironment environment) { if (topic.isEmpty()) { transformedTopics.add(Collections.singletonList(null)); } else { - transformedTopics.add(topic.stream().map(LogTopic::of).collect(Collectors.toList())); + transformedTopics.add(topic.stream().map(LogTopic::of).toList()); } } final LogsQuery query = @@ -185,9 +187,9 @@ public List getLogs(final DataFetchingEnvironment environment) { return results; } - public Optional getEstimateGas(final DataFetchingEnvironment environment) { + public Long getEstimateGas(final DataFetchingEnvironment environment) { final Optional result = executeCall(environment); - return result.map(CallResult::getGasUsed); + return result.map(CallResult::getGasUsed).orElse(0L); } public Optional getCall(final DataFetchingEnvironment environment) { @@ -240,12 +242,14 @@ private Optional executeCall(final DataFetchingEnvironment environme data, Optional.empty()); + ImmutableTransactionValidationParams.Builder transactionValidationParams = + ImmutableTransactionValidationParams.builder() + .from(TransactionValidationParams.transactionSimulator()); + transactionValidationParams.isAllowExceedingBalance(true); + final Optional opt = transactionSimulator.process( - param, - TransactionValidationParams.transactionSimulator(), - OperationTracer.NO_TRACING, - bn); + param, transactionValidationParams.build(), OperationTracer.NO_TRACING, bn); if (opt.isPresent()) { final TransactionSimulatorResult result = opt.get(); long status = 0; @@ -259,13 +263,13 @@ private Optional executeCall(final DataFetchingEnvironment environme return Optional.empty(); } - Optional getRawHeader() { + Bytes getRawHeader() { final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput(); header.writeTo(rlpOutput); - return Optional.of(rlpOutput.encoded()); + return rlpOutput.encoded(); } - Optional getRaw(final DataFetchingEnvironment environment) { + Bytes getRaw(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); return query .getBlockchain() @@ -275,6 +279,23 @@ Optional getRaw(final DataFetchingEnvironment environment) { final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput(); blockBody.writeWrappedBodyTo(rlpOutput); return rlpOutput.encoded(); - }); + }) + .orElse(Bytes.EMPTY); + } + + Optional getWithdrawalsRoot() { + return header.getWithdrawalsRoot().map(Function.identity()); + } + + Optional> getWithdrawals(final DataFetchingEnvironment environment) { + final BlockchainQueries query = getBlockchainQueries(environment); + return query + .getBlockchain() + .getBlockBody(header.getBlockHash()) + .flatMap( + blockBody -> + blockBody + .getWithdrawals() + .map(wl -> wl.stream().map(WithdrawalAdapter::new).toList())); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/EmptyAccountAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/EmptyAccountAdapter.java index ecb16a82a23..7fc6d7695ae 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/EmptyAccountAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/EmptyAccountAdapter.java @@ -17,8 +17,6 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; -import java.util.Optional; - import graphql.schema.DataFetchingEnvironment; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; @@ -32,27 +30,27 @@ public EmptyAccountAdapter(final Address address) { } @Override - public Optional
getAddress() { - return Optional.of(address); + public Address getAddress() { + return address; } @Override - public Optional getBalance() { - return Optional.of(Wei.ZERO); + public Wei getBalance() { + return Wei.ZERO; } @Override - public Optional getTransactionCount() { - return Optional.of(0L); + public Long getTransactionCount() { + return 0L; } @Override - public Optional getCode() { - return Optional.of(Bytes.EMPTY); + public Bytes getCode() { + return Bytes.EMPTY; } @Override - public Optional getStorage(final DataFetchingEnvironment environment) { - return Optional.of(Bytes32.ZERO); + public Bytes32 getStorage(final DataFetchingEnvironment environment) { + return Bytes32.ZERO; } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/LogAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/LogAdapter.java index 20c1e31feba..10357de0cca 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/LogAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/LogAdapter.java @@ -35,8 +35,8 @@ public LogAdapter(final LogWithMetadata logWithMetadata) { this.logWithMetadata = logWithMetadata; } - public Optional getIndex() { - return Optional.of(logWithMetadata.getLogIndex()); + public Integer getIndex() { + return logWithMetadata.getLogIndex(); } public List getTopics() { @@ -44,18 +44,18 @@ public List getTopics() { return new ArrayList<>(topics); } - public Optional getData() { - return Optional.of(logWithMetadata.getData()); + public Bytes getData() { + return logWithMetadata.getData(); } - public Optional getTransaction(final DataFetchingEnvironment environment) { + public TransactionAdapter getTransaction(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); final Hash hash = logWithMetadata.getTransactionHash(); final Optional tran = query.transactionByHash(hash); - return tran.map(TransactionAdapter::new); + return tran.map(TransactionAdapter::new).orElseThrow(); } - public Optional getAccount(final DataFetchingEnvironment environment) { + public AccountAdapter getAccount(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); long blockNumber = logWithMetadata.getBlockNumber(); final Long bn = environment.getArgument("block"); @@ -63,7 +63,9 @@ public Optional getAccount(final DataFetchingEnvironment environ blockNumber = bn; } - return query.getAndMapWorldState( - blockNumber, ws -> Optional.of(new AccountAdapter(ws.get(logWithMetadata.getLogger())))); + return query + .getAndMapWorldState( + blockNumber, ws -> Optional.of(new AccountAdapter(ws.get(logWithMetadata.getLogger())))) + .get(); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/NormalBlockAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/NormalBlockAdapter.java index 0245b404cc4..f54b3f0da04 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/NormalBlockAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/NormalBlockAdapter.java @@ -42,8 +42,8 @@ public Optional getTransactionCount() { return Optional.of(blockWithMetaData.getTransactions().size()); } - public Optional getTotalDifficulty() { - return Optional.of(blockWithMetaData.getTotalDifficulty()); + public Difficulty getTotalDifficulty() { + return blockWithMetaData.getTotalDifficulty(); } public Optional getOmmerCount() { @@ -65,7 +65,7 @@ public List getOmmers(final DataFetchingEnvironment environme public Optional getOmmerAt(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); - final int index = environment.getArgument("index"); + final int index = ((Number) environment.getArgument("index")).intValue(); final List ommers = blockWithMetaData.getOmmers(); if (ommers.size() > index) { final Hash hash = blockWithMetaData.getHeader().getHash(); @@ -85,7 +85,7 @@ public List getTransactions() { } public Optional getTransactionAt(final DataFetchingEnvironment environment) { - final int index = environment.getArgument("index"); + final int index = ((Number) environment.getArgument("index")).intValue(); final List trans = blockWithMetaData.getTransactions(); if (trans.size() > index) { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java index f3462f4209d..fbdfb54ae2c 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java @@ -21,15 +21,17 @@ import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions; +import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.transaction.CallParameter; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult; +import org.hyperledger.besu.evm.tracing.OperationTracer; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.stream.Collectors; import graphql.schema.DataFetchingEnvironment; import org.apache.tuweni.bytes.Bytes; @@ -53,13 +55,12 @@ public List getTransactions() { .map(PendingTransaction::getTransaction) .map(TransactionWithMetadata::new) .map(TransactionAdapter::new) - .collect(Collectors.toList()); + .toList(); } // until the miner can expose the current "proposed block" we have no // speculative environment, so estimate against latest. - public Optional getAccount( - final DataFetchingEnvironment dataFetchingEnvironment) { + public AccountAdapter getAccount(final DataFetchingEnvironment dataFetchingEnvironment) { final BlockchainQueries blockchainQuery = dataFetchingEnvironment.getGraphQlContext().get(GraphQLContextType.BLOCKCHAIN_QUERIES); final Address addr = dataFetchingEnvironment.getArgument("address"); @@ -67,7 +68,8 @@ public Optional getAccount( final long latestBlockNumber = blockchainQuery.latestBlock().get().getHeader().getNumber(); return blockchainQuery .getAndMapWorldState(latestBlockNumber, ws -> Optional.ofNullable(ws.get(addr))) - .map(AccountAdapter::new); + .map(AccountAdapter::new) + .orElseGet(() -> new AccountAdapter(null)); } // until the miner can expose the current "proposed block" we have no @@ -111,7 +113,18 @@ public Optional getCall(final DataFetchingEnvironment environment) { final CallParameter param = new CallParameter(from, to, gasParam, gasPriceParam, valueParam, data); - final Optional opt = transactionSimulator.processAtHead(param); + ImmutableTransactionValidationParams.Builder transactionValidationParams = + ImmutableTransactionValidationParams.builder() + .from(TransactionValidationParams.transactionSimulator()); + transactionValidationParams.isAllowExceedingBalance(true); + + final Optional opt = + transactionSimulator.process( + param, + transactionValidationParams.build(), + OperationTracer.NO_TRACING, + query.getBlockchain().getChainHeadHeader()); + if (opt.isPresent()) { final TransactionSimulatorResult result = opt.get(); long status = 0; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/SyncStateAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/SyncStateAdapter.java index ddbad14bfef..0a8dcbbf97e 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/SyncStateAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/SyncStateAdapter.java @@ -16,8 +16,6 @@ import org.hyperledger.besu.plugin.data.SyncStatus; -import java.util.Optional; - @SuppressWarnings("unused") // reflected by GraphQL public class SyncStateAdapter { private final SyncStatus syncStatus; @@ -26,15 +24,15 @@ public SyncStateAdapter(final SyncStatus syncStatus) { this.syncStatus = syncStatus; } - public Optional getStartingBlock() { - return Optional.of(syncStatus.getStartingBlock()); + public Long getStartingBlock() { + return syncStatus.getStartingBlock(); } - public Optional getCurrentBlock() { - return Optional.of(syncStatus.getCurrentBlock()); + public Long getCurrentBlock() { + return syncStatus.getCurrentBlock(); } - public Optional getHighestBlock() { - return Optional.of(syncStatus.getHighestBlock()); + public Long getHighestBlock() { + return syncStatus.getHighestBlock(); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java index f77c5f72442..49c1da5da65 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java @@ -28,7 +28,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import javax.annotation.Nonnull; import graphql.schema.DataFetchingEnvironment; @@ -58,35 +57,37 @@ private Optional getReceipt( return transactionReceiptWithMetadata; } - public Optional getHash() { - return Optional.of(transactionWithMetadata.getTransaction().getHash()); + public Hash getHash() { + return transactionWithMetadata.getTransaction().getHash(); } public Optional getType() { return Optional.of(transactionWithMetadata.getTransaction().getType().ordinal()); } - public Optional getNonce() { - final long nonce = transactionWithMetadata.getTransaction().getNonce(); - return Optional.of(nonce); + public Long getNonce() { + return transactionWithMetadata.getTransaction().getNonce(); } public Optional getIndex() { return transactionWithMetadata.getTransactionIndex(); } - public Optional getFrom(final DataFetchingEnvironment environment) { + public AccountAdapter getFrom(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); Long blockNumber = environment.getArgument("block"); if (blockNumber == null) { blockNumber = transactionWithMetadata.getBlockNumber().orElseGet(query::headBlockNumber); } - return query.getAndMapWorldState( - blockNumber, - mutableWorldState -> - Optional.of( - new AccountAdapter( - mutableWorldState.get(transactionWithMetadata.getTransaction().getSender())))); + return query + .getAndMapWorldState( + blockNumber, + mutableWorldState -> + Optional.of( + new AccountAdapter( + mutableWorldState.get( + transactionWithMetadata.getTransaction().getSender())))) + .get(); } public Optional getTo(final DataFetchingEnvironment environment) { @@ -105,12 +106,12 @@ public Optional getTo(final DataFetchingEnvironment environment) .map(address -> new AccountAdapter(address, ws.get(address)))); } - public Optional getValue() { - return Optional.of(transactionWithMetadata.getTransaction().getValue()); + public Wei getValue() { + return transactionWithMetadata.getTransaction().getValue(); } - public Optional getGasPrice() { - return transactionWithMetadata.getTransaction().getGasPrice(); + public Wei getGasPrice() { + return transactionWithMetadata.getTransaction().getGasPrice().orElse(Wei.ZERO); } public Optional getMaxPriorityFeePerGas() { @@ -126,12 +127,17 @@ public Optional getEffectiveGasPrice(final DataFetchingEnvironment environm .map(rwm -> rwm.getTransaction().getEffectiveGasPrice(rwm.getBaseFee())); } - public Optional getGas() { - return Optional.of(transactionWithMetadata.getTransaction().getGasLimit()); + public Optional getEffectiveTip(final DataFetchingEnvironment environment) { + return getReceipt(environment) + .map(rwm -> rwm.getTransaction().getEffectivePriorityFeePerGas(rwm.getBaseFee())); + } + + public Long getGas() { + return transactionWithMetadata.getTransaction().getGasLimit(); } - public Optional getInputData() { - return Optional.of(transactionWithMetadata.getTransaction().getPayload()); + public Bytes getInputData() { + return transactionWithMetadata.getTransaction().getPayload(); } public Optional getBlock(final DataFetchingEnvironment environment) { @@ -212,7 +218,7 @@ public List getAccessList() { return transactionWithMetadata .getTransaction() .getAccessList() - .map(l -> l.stream().map(AccessListEntryAdapter::new).collect(Collectors.toList())) + .map(l -> l.stream().map(AccessListEntryAdapter::new).toList()) .orElse(List.of()); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/UncleBlockAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/UncleBlockAdapter.java index c0e2736820e..8d9e947ee2d 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/UncleBlockAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/UncleBlockAdapter.java @@ -33,8 +33,8 @@ public Optional getTransactionCount() { return Optional.of(0); } - public Optional getTotalDifficulty() { - return Optional.of(UInt256.ZERO); + public UInt256 getTotalDifficulty() { + return UInt256.ZERO; } public Optional getOmmerCount() { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/WithdrawalAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/WithdrawalAdapter.java new file mode 100644 index 00000000000..86782b6afcb --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/WithdrawalAdapter.java @@ -0,0 +1,43 @@ +/* + * Copyright contributors to Hyperledger Besu + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.plugin.data.Withdrawal; + +public class WithdrawalAdapter { + + Withdrawal withdrawal; + + public WithdrawalAdapter(final Withdrawal withdrawal) { + this.withdrawal = withdrawal; + } + + public Long getIndex() { + return withdrawal.getIndex().toLong(); + } + + public Long getValidator() { + return withdrawal.getValidatorIndex().toLong(); + } + + public Address getAddress() { + return withdrawal.getAddress(); + } + + public Long getAmount() { + return withdrawal.getAmount().getAsBigInteger().longValue(); + } +} diff --git a/ethereum/api/src/main/resources/schema.graphqls b/ethereum/api/src/main/resources/schema.graphqls index 01e20f95d83..183bce31e9d 100644 --- a/ethereum/api/src/main/resources/schema.graphqls +++ b/ethereum/api/src/main/resources/schema.graphqls @@ -69,7 +69,7 @@ type Block { TransactionCount is the number of transactions in this block. if transactions are not available for this block, this field will be null. """ - transactionCount: Int + transactionCount: Long """ StateRoot is the keccak256 hash of the state trie after this block was processed. @@ -132,7 +132,7 @@ type Block { OmmerCount is the number of ommers (AKA uncles) associated with this block. If ommers are unavailable, this field will be null. """ - ommerCount: Int + ommerCount: Long """ Ommers is a list of ommer (AKA uncle) blocks associated with this block. @@ -146,7 +146,7 @@ type Block { OmmerAt returns the ommer (AKA uncle) at the specified index. If ommers are unavailable, or the index is out of bounds, this field will be null. """ - ommerAt(index: Int!): Block + ommerAt(index: Long!): Block """ OmmerHash is the keccak256 hash of all the ommers (AKA uncles) @@ -165,13 +165,13 @@ type Block { transactions are unavailable for this block, or if the index is out of bounds, this field will be null. """ - transactionAt(index: Int!): Transaction + transactionAt(index: Long!): Transaction """Logs returns a filtered set of logs from this block.""" logs(filter: BlockFilterCriteria!): [Log!]! """Account fetches an Ethereum account at the current block's state.""" - account(address: Address!): Account + account(address: Address!): Account! """Call executes a local call operation at the current block's state.""" call(data: CallData!): CallResult @@ -187,6 +187,18 @@ type Block { """Raw is the RLP encoding of the block.""" raw: Bytes! + + """ + WithdrawalsRoot is the keccak256 hash of the root of the trie of withdrawals in this block. + If withdrawals are unavailable for this block, this field will be null. + """ + withdrawalsRoot: Bytes32 + + """ + Withdrawals is a list of withdrawals associated with this block. If + withdrawals are unavailable for this block, this field will be null. + """ + withdrawals: [Withdrawal!] } """ @@ -205,7 +217,7 @@ input BlockFilterCriteria { of topics. Topics matches a prefix of that list. An empty element array matches any topic. Non-empty elements represent an alternative that matches any of the contained topics. - + Examples: - [] or nil matches any topic list - [[A]] matches topic A in first position @@ -296,7 +308,7 @@ input FilterCriteria { of topics. Topics matches a prefix of that list. An empty element array matches any topic. Non-empty elements represent an alternative that matches any of the contained topics. - + Examples: - [] or nil matches any topic list - [[A]] matches topic A in first position @@ -310,7 +322,7 @@ input FilterCriteria { """Log is an Ethereum event log.""" type Log { """Index is the index of this log in the block.""" - index: Int! + index: Long! """ Account is the account which generated this log - this will always @@ -328,7 +340,11 @@ type Log { transaction: Transaction! } -"""Long is a 64 bit unsigned integer.""" +""" +Long is a 64 bit unsigned integer. Input is accepted as either a JSON number or as a string. +Strings may be either decimal or 0x-prefixed hexadecimal. Output values are all +0x-prefixed hexadecimal. +""" scalar Long type Mutation { @@ -339,13 +355,13 @@ type Mutation { """Pending represents the current pending state.""" type Pending { """TransactionCount is the number of transactions in the pending state.""" - transactionCount: Int! + transactionCount: Long! """Transactions is a list of transactions in the current pending state.""" transactions: [Transaction!] """Account fetches an Ethereum account for the pending state.""" - account(address: Address!): Account + account(address: Address!): Account! """Call executes a local call operation for the pending state.""" call(data: CallData!): CallResult @@ -426,7 +442,7 @@ type Transaction { Index is the index of this transaction in the parent block. This will be null if the transaction has not yet been mined. """ - index: Int + index: Long """ From is the account that sent this transaction - this will always be @@ -521,7 +537,7 @@ type Transaction { v: BigInt! """Envelope transaction support""" - type: Int + type: Long accessList: [AccessTuple!] """ @@ -536,10 +552,21 @@ type Transaction { this is equivalent to TxType || ReceiptEncoding. """ rawReceipt: Bytes! +} - """ IsPrivate is an indicator of a GoQuorum private transaction""" - isPrivate: Boolean - """ PrivateInputData is the actual payload of a GoQuorum private transaction""" - privateInputData: Bytes +"""EIP-4895""" +type Withdrawal { + """ + Index is a monotonically increasing identifier issued by consensus layer. + """ + index: Long! + + """Validator is index of the validator associated with withdrawal.""" + validator: Long! + + """Address recipient of the withdrawn amount.""" + address: Address! + """Amount is the withdrawal value in Gwei.""" + amount: Long! } \ No newline at end of file diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java index cb8c253ad3d..7f41af9ab17 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java @@ -14,21 +14,14 @@ */ package org.hyperledger.besu.ethereum.api.graphql; -import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryWorldStateArchive; - import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator; -import org.hyperledger.besu.ethereum.chain.GenesisState; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; -import org.hyperledger.besu.ethereum.core.Block; -import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; -import org.hyperledger.besu.ethereum.core.BlockImporter; +import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; import org.hyperledger.besu.ethereum.core.DefaultSyncStatus; -import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; -import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture; import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.eth.EthProtocol; @@ -36,31 +29,20 @@ import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; -import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; -import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; -import org.hyperledger.besu.ethereum.util.RawBlockIterator; -import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; +import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; import org.hyperledger.besu.plugin.data.SyncStatus; import org.hyperledger.besu.plugin.data.TransactionType; import org.hyperledger.besu.testutil.BlockTestUtil; -import java.net.URL; -import java.nio.file.Paths; -import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; -import com.google.common.base.Charsets; -import com.google.common.io.Resources; import graphql.GraphQL; import io.vertx.core.Vertx; import okhttp3.MediaType; @@ -76,13 +58,7 @@ public abstract class AbstractEthGraphQLHttpServiceTest { @ClassRule public static final TemporaryFolder folder = new TemporaryFolder(); - private static ProtocolSchedule PROTOCOL_SCHEDULE; - - static List BLOCKS; - - private static Block GENESIS_BLOCK; - - private static GenesisState GENESIS_CONFIG; + private static BlockchainSetupUtil blockchainSetupUtil; private final Vertx vertx = Vertx.vertx(); @@ -95,29 +71,12 @@ public abstract class AbstractEthGraphQLHttpServiceTest { final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); protected static final MediaType GRAPHQL = MediaType.parse("application/graphql; charset=utf-8"); - private ProtocolContext context; - @BeforeClass - public static void setupConstants() throws Exception { - PROTOCOL_SCHEDULE = ProtocolScheduleFixture.MAINNET; - - final URL blocksUrl = BlockTestUtil.getTestBlockchainUrl(); - - final URL genesisJsonUrl = BlockTestUtil.getTestGenesisUrl(); - - final BlockHeaderFunctions blockHeaderFunctions = new MainnetBlockHeaderFunctions(); - BLOCKS = new ArrayList<>(); - try (final RawBlockIterator iterator = - new RawBlockIterator(Paths.get(blocksUrl.toURI()), blockHeaderFunctions)) { - while (iterator.hasNext()) { - BLOCKS.add(iterator.next()); - } - } - - final String genesisJson = Resources.toString(genesisJsonUrl, Charsets.UTF_8); - - GENESIS_BLOCK = BLOCKS.get(0); - GENESIS_CONFIG = GenesisState.fromJson(genesisJson, PROTOCOL_SCHEDULE); + public static void setupConstants() { + blockchainSetupUtil = + BlockchainSetupUtil.createForEthashChain( + BlockTestUtil.getHiveTestChainResources(), DataStorageFormat.FOREST); + blockchainSetupUtil.importAllBlocks(); } @Before @@ -151,12 +110,9 @@ public void setupTest() throws Exception { .gasPrice(Wei.ONE) .build()))); - final WorldStateArchive stateArchive = createInMemoryWorldStateArchive(); - GENESIS_CONFIG.writeStateTo(stateArchive.getMutable()); - - final MutableBlockchain blockchain = - InMemoryKeyValueStorageProvider.createInMemoryBlockchain(GENESIS_BLOCK); - context = new ProtocolContext(blockchain, stateArchive, null); + final MutableBlockchain blockchain = blockchainSetupUtil.getBlockchain(); + ProtocolContext context = + new ProtocolContext(blockchain, blockchainSetupUtil.getWorldArchive(), null); final BlockchainQueries blockchainQueries = new BlockchainQueries( context.getBlockchain(), @@ -185,7 +141,7 @@ public void setupTest() throws Exception { GraphQLContextType.BLOCKCHAIN_QUERIES, blockchainQueries, GraphQLContextType.PROTOCOL_SCHEDULE, - PROTOCOL_SCHEDULE, + blockchainSetupUtil.getProtocolSchedule(), GraphQLContextType.TRANSACTION_POOL, transactionPoolMock, GraphQLContextType.MINING_COORDINATOR, @@ -206,11 +162,4 @@ public void shutdownServer() { service.stop().join(); vertx.close(); } - - void importBlock(final int n) { - final Block block = BLOCKS.get(n); - final ProtocolSpec protocolSpec = PROTOCOL_SCHEDULE.getByBlockHeader(block.getHeader()); - final BlockImporter blockImporter = protocolSpec.getBlockImporter(); - blockImporter.importBlock(context, block, HeaderValidationMode.FULL); - } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/BlockDataFetcherTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/BlockDataFetcherTest.java index fbce733017d..b41bb17547c 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/BlockDataFetcherTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/BlockDataFetcherTest.java @@ -20,6 +20,7 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter.EmptyAccountAdapter; import org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter.NormalBlockAdapter; import org.hyperledger.besu.ethereum.api.query.BlockWithMetadata; @@ -36,10 +37,10 @@ public class BlockDataFetcherTest extends AbstractDataFetcherTest { @Test - public void bothNumberAndHashThrows() throws Exception { + public void bothNumberAndHashThrows() { final Hash fakedHash = Hash.hash(Bytes.of(1)); - when(environment.getArgument(ArgumentMatchers.eq("number"))).thenReturn(1L); - when(environment.getArgument(ArgumentMatchers.eq("hash"))).thenReturn(fakedHash); + when(environment.getArgument("number")).thenReturn(1L); + when(environment.getArgument("hash")).thenReturn(fakedHash); assertThatThrownBy(() -> fetcher.get(environment)).isInstanceOf(GraphQLException.class); } @@ -47,8 +48,8 @@ public void bothNumberAndHashThrows() throws Exception { @Test public void onlyNumber() throws Exception { - when(environment.getArgument(ArgumentMatchers.eq("number"))).thenReturn(1L); - when(environment.getArgument(ArgumentMatchers.eq("hash"))).thenReturn(null); + when(environment.getArgument("number")).thenReturn(1L); + when(environment.getArgument("hash")).thenReturn(null); when(environment.getGraphQlContext()).thenReturn(graphQLContext); when(graphQLContext.get(GraphQLContextType.BLOCKCHAIN_QUERIES)).thenReturn(query); @@ -64,8 +65,8 @@ public void ibftMiner() throws Exception { // as null. The compromise is to report zeros and empty on query from a block. final Address testAddress = Address.fromHexString("0xdeadbeef"); - when(environment.getArgument(ArgumentMatchers.eq("number"))).thenReturn(1L); - when(environment.getArgument(ArgumentMatchers.eq("hash"))).thenReturn(null); + when(environment.getArgument("number")).thenReturn(1L); + when(environment.getArgument("hash")).thenReturn(null); when(environment.getGraphQlContext()).thenReturn(graphQLContext); when(graphQLContext.get(GraphQLContextType.BLOCKCHAIN_QUERIES)).thenReturn(query); @@ -75,10 +76,10 @@ public void ibftMiner() throws Exception { final Optional maybeBlock = fetcher.get(environment); assertThat(maybeBlock).isPresent(); - assertThat(maybeBlock.get().getMiner(environment)).isPresent(); - assertThat(((EmptyAccountAdapter) maybeBlock.get().getMiner(environment).get()).getBalance()) - .isPresent(); - assertThat(((EmptyAccountAdapter) maybeBlock.get().getMiner(environment).get()).getAddress()) - .contains(testAddress); + assertThat(maybeBlock.get().getMiner(environment)).isNotNull(); + assertThat(((EmptyAccountAdapter) maybeBlock.get().getMiner(environment)).getBalance()) + .isGreaterThanOrEqualTo(Wei.ZERO); + assertThat(((EmptyAccountAdapter) maybeBlock.get().getMiner(environment)).getAddress()) + .isEqualTo(testAddress); } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/EthGraphQLHttpBySpecTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/EthGraphQLHttpBySpecTest.java index a2280923d9c..7beef9c5251 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/EthGraphQLHttpBySpecTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/EthGraphQLHttpBySpecTest.java @@ -118,6 +118,11 @@ public static Collection specs() { specs.add("graphql_variable_bytes32"); specs.add("graphql_variable_long"); + specs.add("block_withdrawals_pre_shanghai"); + specs.add("block_withdrawals"); + specs.add("eth_getTransaction_type2"); + specs.add("eth_getBlock_shanghai"); + return specs; } @@ -142,7 +147,6 @@ private void graphQLCall(final String name) throws IOException { JSON); final Request request = new Request.Builder().post(requestBody).url(baseUrl).build(); - importBlocks(1, BLOCKS.size()); try (final Response resp = client.newCall(request).execute()) { final JsonObject expectedRespBody = spec.getJsonObject("response"); final String resultStr = resp.body().string(); @@ -154,10 +158,4 @@ private void graphQLCall(final String name) throws IOException { Assertions.assertThat(resp.code()).isEqualTo(expectedStatusCode); } } - - private void importBlocks(final int from, final int to) { - for (int i = from; i < to; ++i) { - importBlock(i); - } - } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/AddressScalarTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/AddressScalarTest.java index 87153b49087..b6f97889264 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/AddressScalarTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/AddressScalarTest.java @@ -20,6 +20,11 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.api.graphql.internal.Scalars; +import java.util.Locale; + +import graphql.GraphQLContext; +import graphql.execution.CoercedVariables; +import graphql.language.FloatValue; import graphql.language.StringValue; import graphql.schema.CoercingParseLiteralException; import graphql.schema.CoercingParseValueException; @@ -40,43 +45,83 @@ public class AddressScalarTest { @Test public void parseValueTest() { - final Address result = (Address) scalar.getCoercing().parseValue(addrStr); + final Address result = + (Address) + scalar + .getCoercing() + .parseValue(addrStr, GraphQLContext.newContext().build(), Locale.ENGLISH); assertThat(result).isEqualTo(addr); } @Test public void parseValueErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().parseValue(3.4f)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .parseValue(3.4f, GraphQLContext.newContext().build(), Locale.ENGLISH)) .isInstanceOf(CoercingParseValueException.class); } @Test public void serializeTest() { - final String result = (String) scalar.getCoercing().serialize(addr); + final String result = + (String) + scalar + .getCoercing() + .serialize(addr, GraphQLContext.newContext().build(), Locale.ENGLISH); assertThat(result).isEqualTo(addrStr); } @Test public void serializeErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().serialize(3.4f)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .serialize(3.4f, GraphQLContext.newContext().build(), Locale.ENGLISH)) .isInstanceOf(CoercingSerializeException.class); } @Test public void parseLiteralTest() { - final Address result = (Address) scalar.getCoercing().parseLiteral(addrValue); + final Address result = + (Address) + scalar + .getCoercing() + .parseLiteral( + addrValue, + CoercedVariables.emptyVariables(), + GraphQLContext.newContext().build(), + Locale.ENGLISH); assertThat(result).isEqualTo(addr); } @Test public void parseLiteralErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(3.4f)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .parseLiteral( + FloatValue.of(3.4f), + CoercedVariables.emptyVariables(), + GraphQLContext.newContext().build(), + Locale.ENGLISH)) .isInstanceOf(CoercingParseLiteralException.class); } @Test public void parseLiteralErrorTest2() { - assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(invalidAddrValue)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .parseLiteral( + invalidAddrValue, + CoercedVariables.emptyVariables(), + GraphQLContext.newContext().build(), + Locale.ENGLISH)) .isInstanceOf(CoercingParseLiteralException.class); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BigIntScalarTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BigIntScalarTest.java index 06fcfa42c2f..d1c4751bd94 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BigIntScalarTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BigIntScalarTest.java @@ -19,6 +19,11 @@ import org.hyperledger.besu.ethereum.api.graphql.internal.Scalars; +import java.util.Locale; + +import graphql.GraphQLContext; +import graphql.execution.CoercedVariables; +import graphql.language.FloatValue; import graphql.language.StringValue; import graphql.schema.CoercingParseLiteralException; import graphql.schema.CoercingParseValueException; @@ -38,43 +43,69 @@ public class BigIntScalarTest { @Test public void parseValueTest() { - final String result = (String) scalar.getCoercing().parseValue(value); + final String result = + (String) + scalar + .getCoercing() + .parseValue(value, GraphQLContext.newContext().build(), Locale.ENGLISH); assertThat(result).isEqualTo(str); } @Test public void parseValueErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().parseValue(3.2)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .parseValue(3.2, GraphQLContext.newContext().build(), Locale.ENGLISH)) .isInstanceOf(CoercingParseValueException.class); } @Test public void serializeTest() { - final String result = (String) scalar.getCoercing().serialize(value); + final String result = + (String) + scalar + .getCoercing() + .serialize(value, GraphQLContext.newContext().build(), Locale.ENGLISH); assertThat(result).isEqualTo(str); } @Test public void serializeErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().serialize(3.2)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .serialize(3.2, GraphQLContext.newContext().build(), Locale.ENGLISH)) .isInstanceOf(CoercingSerializeException.class); } - @Test - public void parseLiteralTest() { - final String result = (String) scalar.getCoercing().parseLiteral(value); - assertThat(result).isEqualTo(str); - } - @Test public void parseLiteralErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(3.2)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .parseLiteral( + FloatValue.of(3.2), + CoercedVariables.emptyVariables(), + GraphQLContext.newContext().build(), + Locale.ENGLISH)) .isInstanceOf(CoercingParseLiteralException.class); } @Test public void parseLiteralErrorTest2() { - assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(invalidStrValue)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .parseLiteral( + invalidStrValue, + CoercedVariables.emptyVariables(), + GraphQLContext.newContext().build(), + Locale.ENGLISH)) .isInstanceOf(CoercingParseLiteralException.class); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/Bytes32ScalarTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/Bytes32ScalarTest.java index 47e516c3b52..4583ecac365 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/Bytes32ScalarTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/Bytes32ScalarTest.java @@ -19,6 +19,11 @@ import org.hyperledger.besu.ethereum.api.graphql.internal.Scalars; +import java.util.Locale; + +import graphql.GraphQLContext; +import graphql.execution.CoercedVariables; +import graphql.language.FloatValue; import graphql.language.StringValue; import graphql.schema.CoercingParseLiteralException; import graphql.schema.CoercingParseValueException; @@ -39,43 +44,80 @@ public class Bytes32ScalarTest { @Test public void pareValueTest() { - final var result = scalar.getCoercing().parseValue(str); + final var result = + scalar.getCoercing().parseValue(str, GraphQLContext.newContext().build(), Locale.ENGLISH); assertThat(result).isEqualTo(value); } @Test public void parseValueErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().parseValue(3.2f)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .parseValue(3.2f, GraphQLContext.newContext().build(), Locale.ENGLISH)) .isInstanceOf(CoercingParseValueException.class); } @Test public void serializeTest() { - final String result = (String) scalar.getCoercing().serialize(value); + final String result = + (String) + scalar + .getCoercing() + .serialize(value, GraphQLContext.newContext().build(), Locale.ENGLISH); assertThat(result).isEqualTo(str); } @Test public void serializeErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().serialize(3.2f)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .serialize(3.2f, GraphQLContext.newContext().build(), Locale.ENGLISH)) .isInstanceOf(CoercingSerializeException.class); } @Test public void parseLiteralTest() { - final Bytes32 result = (Bytes32) scalar.getCoercing().parseLiteral(strValue); + final Bytes32 result = + (Bytes32) + scalar + .getCoercing() + .parseLiteral( + strValue, + CoercedVariables.emptyVariables(), + GraphQLContext.newContext().build(), + Locale.ENGLISH); assertThat(result).isEqualTo(value); } @Test public void parseLiteralErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(3.2f)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .parseLiteral( + FloatValue.of(3.2f), + CoercedVariables.emptyVariables(), + GraphQLContext.newContext().build(), + Locale.ENGLISH)) .isInstanceOf(CoercingParseLiteralException.class); } @Test public void parseLiteralErrorTest2() { - assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(invalidStrValue)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .parseLiteral( + invalidStrValue, + CoercedVariables.emptyVariables(), + GraphQLContext.newContext().build(), + Locale.ENGLISH)) .isInstanceOf(CoercingParseLiteralException.class); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BytesScalarTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BytesScalarTest.java index 39ca321c3a5..ae7204833b6 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BytesScalarTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/BytesScalarTest.java @@ -19,6 +19,11 @@ import org.hyperledger.besu.ethereum.api.graphql.internal.Scalars; +import java.util.Locale; + +import graphql.GraphQLContext; +import graphql.execution.CoercedVariables; +import graphql.language.FloatValue; import graphql.language.StringValue; import graphql.schema.CoercingParseLiteralException; import graphql.schema.CoercingParseValueException; @@ -39,43 +44,80 @@ public class BytesScalarTest { @Test public void parseValueTest() { - final var result = scalar.getCoercing().parseValue(str); + final var result = + scalar.getCoercing().parseValue(str, GraphQLContext.newContext().build(), Locale.ENGLISH); assertThat(result).isEqualTo(value); } @Test public void parseValueErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().parseValue(3.2f)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .parseValue(3.2f, GraphQLContext.newContext().build(), Locale.ENGLISH)) .isInstanceOf(CoercingParseValueException.class); } @Test public void serializeTest() { - final String result = (String) scalar.getCoercing().serialize(value); + final String result = + (String) + scalar + .getCoercing() + .serialize(value, GraphQLContext.newContext().build(), Locale.ENGLISH); assertThat(result).isEqualTo(str); } @Test public void serializeErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().serialize(3.2f)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .serialize(3.2f, GraphQLContext.newContext().build(), Locale.ENGLISH)) .isInstanceOf(CoercingSerializeException.class); } @Test public void parseLiteralTest() { - final Bytes result = (Bytes) scalar.getCoercing().parseLiteral(strValue); + final Bytes result = + (Bytes) + scalar + .getCoercing() + .parseLiteral( + strValue, + CoercedVariables.emptyVariables(), + GraphQLContext.newContext().build(), + Locale.ENGLISH); assertThat(result).isEqualTo(value); } @Test public void parseLiteralErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(3.2f)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .parseLiteral( + FloatValue.of(3.2f), + CoercedVariables.emptyVariables(), + GraphQLContext.newContext().build(), + Locale.ENGLISH)) .isInstanceOf(CoercingParseLiteralException.class); } @Test public void parseLiteralErrorTest2() { - assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(invalidStrValue)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .parseLiteral( + invalidStrValue, + CoercedVariables.emptyVariables(), + GraphQLContext.newContext().build(), + Locale.ENGLISH)) .isInstanceOf(CoercingParseLiteralException.class); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/LongScalarTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/LongScalarTest.java index d693d6e2c95..119ce81ce0d 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/LongScalarTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/LongScalarTest.java @@ -19,6 +19,10 @@ import org.hyperledger.besu.ethereum.api.graphql.internal.Scalars; +import java.util.Locale; + +import graphql.GraphQLContext; +import graphql.execution.CoercedVariables; import graphql.language.StringValue; import graphql.schema.CoercingParseLiteralException; import graphql.schema.CoercingParseValueException; @@ -38,51 +42,101 @@ public class LongScalarTest { @Test public void parseLongValueTest() { - assertThat(scalar.getCoercing().parseValue(value)).isEqualTo(value); + assertThat( + scalar + .getCoercing() + .parseValue(value, GraphQLContext.newContext().build(), Locale.ENGLISH)) + .isEqualTo(value); } @Test public void parseStringValueTest() { - assertThat(scalar.getCoercing().parseValue(str)).isEqualTo(value); + assertThat( + scalar + .getCoercing() + .parseValue(str, GraphQLContext.newContext().build(), Locale.ENGLISH)) + .isEqualTo(value); } @Test public void parseValueErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().parseValue(invalidStrValue)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .parseValue( + invalidStrValue, GraphQLContext.newContext().build(), Locale.ENGLISH)) .isInstanceOf(CoercingParseValueException.class); } @Test public void serializeLongTest() { - assertThat(scalar.getCoercing().serialize(value)).isEqualTo(value); + assertThat( + scalar + .getCoercing() + .serialize(value, GraphQLContext.newContext().build(), Locale.ENGLISH)) + .isEqualTo(value); } @Test public void serializeStringTest() { - assertThat(scalar.getCoercing().serialize(str)).isEqualTo(value); + assertThat( + scalar + .getCoercing() + .serialize(str, GraphQLContext.newContext().build(), Locale.ENGLISH)) + .isEqualTo(value); } @Test public void serializeErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().serialize(invalidStrValue)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .serialize( + invalidStrValue, GraphQLContext.newContext().build(), Locale.ENGLISH)) .isInstanceOf(CoercingSerializeException.class); } @Test public void parseLiteralTest() { - final Long result = (Long) scalar.getCoercing().parseLiteral(strValue); + final Long result = + (Long) + scalar + .getCoercing() + .parseLiteral( + strValue, + CoercedVariables.emptyVariables(), + GraphQLContext.newContext().build(), + Locale.ENGLISH); assertThat(result).isEqualTo(value); } @Test - public void parseLiteralErrorTest() { - assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(str)) - .isInstanceOf(CoercingParseLiteralException.class); + public void parseLiteralStringTest() { + final Long result = + (Long) + scalar + .getCoercing() + .parseLiteral( + strValue, + CoercedVariables.emptyVariables(), + GraphQLContext.newContext().build(), + Locale.ENGLISH); + assertThat(result).isEqualTo(value); } @Test public void parseLiteralErrorTest2() { - assertThatThrownBy(() -> scalar.getCoercing().parseLiteral(invalidStrValue)) + assertThatThrownBy( + () -> + scalar + .getCoercing() + .parseLiteral( + invalidStrValue, + CoercedVariables.emptyVariables(), + GraphQLContext.newContext().build(), + Locale.ENGLISH)) .isInstanceOf(CoercingParseLiteralException.class); } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals.json new file mode 100644 index 00000000000..024f465a3b3 --- /dev/null +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals.json @@ -0,0 +1,20 @@ +{ + "request": + "{ block (number: 33) { number withdrawalsRoot withdrawals { index amount validator address } } }", + + "response": { + "data" : { + "block" : { + "number" : 33, + "withdrawalsRoot": "0x37945ab58d2712a26df2a38d217e822694927e29b30d5993d7a53ccea618d1f3", + "withdrawals": [{ + "index": 0, + "amount": 10000000000, + "validator": 10, + "address": "0x0000000000000000000000000000000000000dad" + }] + } + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals_pre_shanghai.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals_pre_shanghai.json new file mode 100644 index 00000000000..dd50acb5fe0 --- /dev/null +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals_pre_shanghai.json @@ -0,0 +1,15 @@ +{ + "request": + "{ block (number: 32) { number withdrawalsRoot withdrawals { index amount } } }", + + "response": { + "data" : { + "block" : { + "number" : 32, + "withdrawalsRoot": null, + "withdrawals": null + } + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_blockNumber.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_blockNumber.json index b3b73618509..b061e7e656f 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_blockNumber.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_blockNumber.json @@ -5,7 +5,7 @@ "response": { "data" : { "block" : { - "number" : 32 + "number" : 33 } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_BlockLatest.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_BlockLatest.json index 7478c29a74f..7c4a16df7c7 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_BlockLatest.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_BlockLatest.json @@ -4,7 +4,7 @@ "response":{ "data" : { "block" : { - "number" : 32, + "number" : 33, "call" : { "data" : "0x0000000000000000000000000000000000000000000000000000000000000001", "status" : 1 diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_from_contract.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_from_contract.json index 1bafc66fd3f..9904c248c4c 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_from_contract.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_from_contract.json @@ -4,7 +4,7 @@ "response":{ "data" : { "block" : { - "number" : 32, + "number" : 33, "call" : { "data" : "0x", "status" : 1 diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_contractDeploy.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_contractDeploy.json index 816ab74aa36..fda2392515b 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_contractDeploy.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_contractDeploy.json @@ -4,7 +4,7 @@ "response":{ "data" : { "block" : { - "estimateGas" : 111953 + "estimateGas" : 127129 } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_from_contract.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_from_contract.json index 4c3135d727a..776b5e0bec8 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_from_contract.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_from_contract.json @@ -3,7 +3,7 @@ "response":{ "data" : { "block" : { - "estimateGas" : 21204 + "estimateGas" : 21048 } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_noParams.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_noParams.json index 251bd7ebe5b..60a6408aeb3 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_noParams.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_noParams.json @@ -3,7 +3,7 @@ "response":{ "data" : { "block" : { - "estimateGas" : 21000 + "estimateGas" : 53000 } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_invalidAccountLatest.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_invalidAccountLatest.json index b5e1f90cc99..90c59996777 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_invalidAccountLatest.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_invalidAccountLatest.json @@ -3,7 +3,9 @@ "response": { "data": { "pending": { - "account": null + "account": { + "balance": "0x0" + } } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_toobig_bn.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_toobig_bn.json index bd1260f84c0..cbc24c848e1 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_toobig_bn.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_toobig_bn.json @@ -1,9 +1,9 @@ { - "request": "{ block(number:\"0x21\") { account(address: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { balance } } }", + "request": "{ block(number:\"0x22\") { account(address: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { balance } } }", "response": { "errors": [ { - "message": "Exception while fetching data (/block) : Block number 33 was not found", + "message": "Exception while fetching data (/block) : Block number 34 was not found", "locations": [ { "line": 1, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json new file mode 100644 index 00000000000..099460a8e83 --- /dev/null +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json @@ -0,0 +1,29 @@ +{ + "request": "{block (number : 33) { baseFeePerGas difficulty extraData miner { address } mixHash nonce stateRoot totalDifficulty withdrawalsRoot withdrawals { address amount index validator } }} ", + "response":{ + "data" : { + "block" : { + "baseFeePerGas": "0x3b9aca00", + "difficulty": "0x0", + "extraData": "0x", + "miner": { + "address": "0x0000000000000000000000000000000000000000" + }, + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "stateRoot": "0x0d3c456bb68669bad05da3a1a766daab236c9df1da8f74edf5ebe9383f00084c", + "totalDifficulty": "0x427c00", + "withdrawalsRoot": "0x37945ab58d2712a26df2a38d217e822694927e29b30d5993d7a53ccea618d1f3", + "withdrawals": [ + { + "address": "0x0000000000000000000000000000000000000dad", + "amount": 10000000000, + "index": 0, + "validator": 10 + } + ] + } + } + }, + "statusCode": 200 +} diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionCount.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionCount.json index ab563cf8a53..990fbf74773 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionCount.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionCount.json @@ -5,7 +5,7 @@ "data" : { "pending": { "account" :{ - "transactionCount" : 32 + "transactionCount" : 33 } } } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json new file mode 100644 index 00000000000..b910e159cc6 --- /dev/null +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json @@ -0,0 +1,19 @@ +{ + "request": "{transaction (hash : \"0x3ecd2ca6cf26c864d0ea5f038a58d4cd4a46a3e242fe92f446f392fdc232dd98\") { accessList { address storageKeys } maxFeePerGas maxPriorityFeePerGas nonce type status } } ", + "response": { + "data": { + "transaction": { + "accessList": [{ + "address": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f", + "storageKeys": ["0x0000000000000000000000000000000000000000000000000000000000000000"] + }], + "maxFeePerGas": "0xb2d05e00", + "maxPriorityFeePerGas": "0x3b9aca00", + "nonce": 32, + "type": 2, + "status": 1 + } + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byFrom.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byFrom.json index 4e6c33d3f51..7ba8b74a41c 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byFrom.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byFrom.json @@ -11,6 +11,9 @@ }, { "number": 32 + }, + { + "number": 33 } ] } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_pending.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_pending.json index 46cad8c1c74..c12410e10af 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_pending.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_pending.json @@ -15,7 +15,7 @@ "account": { "balance": "0x140" }, - "estimateGas": 21000, + "estimateGas": 53000, "call": { "data": "0x0000000000000000000000000000000000000000000000000000000000000001", "status": 1 diff --git a/testutil/src/main/java/org/hyperledger/besu/testutil/BlockTestUtil.java b/testutil/src/main/java/org/hyperledger/besu/testutil/BlockTestUtil.java index 4975cbee008..d2909a84f3b 100644 --- a/testutil/src/main/java/org/hyperledger/besu/testutil/BlockTestUtil.java +++ b/testutil/src/main/java/org/hyperledger/besu/testutil/BlockTestUtil.java @@ -32,8 +32,14 @@ /** The Block test util. */ public final class BlockTestUtil { + private BlockTestUtil() { + throw new RuntimeException("Utility Class"); + } + private static final Supplier testChainSupplier = Suppliers.memoize(BlockTestUtil::supplyTestChainResources); + private static final Supplier hiveTestChainSupplier = + Suppliers.memoize(BlockTestUtil::supplyHiveTestChainResources); private static final Supplier testChainLondonSupplier = Suppliers.memoize(BlockTestUtil::supplyTestChainLondonResources); private static final Supplier mainnetChainSupplier = @@ -92,6 +98,15 @@ public static ChainResources getTestChainResources() { return testChainSupplier.get(); } + /** + * Gets test chain resources for hive tests. + * + * @return the test chain resources + */ + public static ChainResources getHiveTestChainResources() { + return hiveTestChainSupplier.get(); + } + /** * Gets test chain london resources. * @@ -148,6 +163,15 @@ private static ChainResources supplyTestChainResources() { return new ChainResources(genesisURL, blocksURL); } + private static ChainResources supplyHiveTestChainResources() { + final URL genesisURL = + ensureFileUrl(BlockTestUtil.class.getClassLoader().getResource("hive/testGenesis.json")); + final URL blocksURL = + ensureFileUrl( + BlockTestUtil.class.getClassLoader().getResource("hive/testBlockchain.blocks")); + return new ChainResources(genesisURL, blocksURL); + } + private static ChainResources supplyTestChainLondonResources() { final URL genesisURL = ensureFileUrl( diff --git a/testutil/src/main/resources/hive/testBlockchain.blocks b/testutil/src/main/resources/hive/testBlockchain.blocks new file mode 100644 index 0000000000000000000000000000000000000000..480efc87d9fcf4bb02cebf943897e5fec7d18226 GIT binary patch literal 24039 zcmeI4cT^P1y0>SBC^-m{B&&cRL84@kAO=7{au_lKl5-mJfReKcG$0^JKtMo22@)g= zf@Dxhl7k>9;ZEaWt9yIc=VRY>@4DZz{wRL+R&{lC*E3bs-7mET-QI$J1|WYEfRk-k zXGWWJ-SYy=%$~Hpq3R)#p^go8BwbFE+L3q@BNvNAuB^lrrbTxy24N;@TtOqel3WaU zJ;mxPl}`)$2tTLq;6)Re+#x5XLYV~3fYo5i_A=E1H)iNgP`9aN?fJ`0Mb~WJ(v}~m zPO>Vfff{m_eK0Cz_}c=N(7$Q<|Nq(kFbD+U&$-l(2vB`>$5#qq53H)1G-f5jWxzgl zxy%Cdl#}11!qz^&s=FKRsalJ&NY^&<&!roxfi*Q-$IP~%Ux3YJQonU0YuG}*&z{*` zn>lxN4uOog!Q65;!QCgj3_eHf{zY}Q#JG$1!m4qOS+XW|CX}6cA~PRWBI2XT>k?#t zS_}|rtqcIN`3)3WKAahNBE31S>rQ7sl+1F)`nwYAm9)p1Bj3T zWDQ~f;qyH7Cl-m0Fd|}Wt33{fva2JENU|%BqvQpYJmEMci;`DRlJ@k@d6d*eNxDcb z0hGLjlDrp!bx{(5l7emW+$b4`lGogO%uuo#CDmIwU!r6yN}8zLaX`s&lr#^~bVJES zlyt6Q7&s1xK~VB8WsV9;5};&qUGq9h(xGIgFbyqAa-d|EE4DgHilO8a8Vod)1Y1^D z%!aBLriGH-EF29eX^D~_Aie-fdZOga^CfMR3`5Da+n5lPyoZwOWnw2#G6yAhB!W@x zg*{V;Xv3kraP+<#+6JiGwuVYc!O`yB&_)MqgroIjzRZFK8$j|!IR$&XW*DI-&2D77l^uof87I^EF3-HdrB3K{zGAt{la12vz_-1 zO5Y8^`v$%5hB!Dz>GxCy97FDVsu+&8^mEhe;h2zvd{j3WK;Tdaj<2e(!5)l~JklR_ zB2rCB8+AG`5BhVS&!N<#W|c@^82V2Yz<#dahdihOM9KG$Q^9^pq5aXQU-spn+ll_e z!QcfMKq6Hm!4pTKqX3Cif}^2sPvp02Hh_N5gW!UBUElLy-}Am5H-C@^wpJA^y?bB* zTMSyzi4H8NR{wGQFWU_^1zr50IN0j_3Y7OPJ|?g75ybCjg)1OQRP}sk36t@RAD??1(gLQbDM2;RX;C|-(io!-; zZyckX7~O>_{U1*D;GdrChq}NE{AUgCUCto5Jl^r`PMh#tCC z6naWAl>fA440}GXv1V%6)Z2cM%WPeFAXt$&XY5sd=UXP^^WqePvcQ--z(?Yf+?g!r z!pvVkFQj0Q&`KbuICs_+$Nn0vrEBA{#qqlO#8pbVBD_Zv{ z$vJaIUu)<0JTdzs0w(}mI8g%&=Lqfe+Hy~7Ggdryh6iuo9##*?Iu$k~KS7@rgR@?;zBOvoD@J&n5C$bSgAD$Qx(`m} zI7yZWUN^Xn48dkhP#rUsJhU&M?vm0Igsi?2?d#e9dG5$qARaaSTN zBD}639FPEHo4GzhqEhq-ZpptPEfA-3!)#pMRc`1B;9lD`He`^l*}~KY$1_pi3xwPE zyDsv-^A@|$l}d{kL&w4jSK`wd@3k$Hk|zO{EW6QjgXn{siLfc=i`YpVRyMCpp?%G1 zf?c9n;GahS^@{^@ggOK3HGU=f{4~8@D}Masx=ys#rOhk%0xBMLF})}Q5;9}@-@emU zUvGSNs>+H-)o3Yc)3FLWJLpDzp3Y+)L%_QqX7%}8*T-<1-V3FelXN@0LSD%L26OD5 zq=3z!hyHKQK+bB=zj3AkayE+q;`hp6 zB2T4UfOlqzVu75Y9mW~>a7P2YH!J1E>d_6G7rCshz)3N%_|jh_o~QQp@yqX=C0giD z0P=pC+oH$gN^YQu1TqAfEPLu_>s512j`g_ET<95`S>HnY1iqj8=hJ46qKf18UyYh?#y52j zv_IJ{mC%Jd(_P4lG{zvfHBq0&sRTe4`hirW18mV;Zr@> zl3;Pnnb|{jCDj|@3D<;d7$b`{dF{T~#`gYewS4Wa*%PC!ym2w_)Lt3(*n}j10W3Sl zPuHeHWo>RcXpA0l6@%w~srV7M;G^^Xw;6g>g~QmxnOv&RYD|k(%!V)v>3;(H%{XOV zAFCUG?A~d+0~0uM2q;|303A<0Q3d<_Kb}E?i2aRHF@unC&rqOUFcPV=tRJkF4Pwu)&F`)52dW3Y# zQ#Za>@J7*6t#f=!7J zwjuM8?G)}-k`e=t__T;tDd6HP);w~P9do7SbPJA@k6d%cSsUYag7%D;vPg)>MXdwQ zOs({cdf62t%FMaQ!UI|&xqLrqvOXG8l4-nTtSyP9e8lmrC~KicPH?*tdp_+w^zLOb z;cI*s0u1V~28~~LYl>d>1l~vc;^fM?xyQP6xjW@F&Ze5$WM*~IWdR#% z)_#NR&)e_M%GVGnN_{OxP{lYylIjO7A5Sw~Kk4+FGmtX`);G?KLC#hXz)orG4Q(w3 zI#%W;LO-rTH6e*E7ESMGwiuUky;O(Jhay9elNRT=)?b61VIIaA`2B+#cxr7TG%ZPd zHJQdToX$m*f#~*AA&k)540AhE*D))`Zvd8}q#dX9w4bp~P4l<&Q5SeIA>s(Mg&tg1 zd`+K6;ckAw*`kD z7twr8CV^pLexHeRa%NH4*MiFO&o+B|WHYgeXO&&ODfaRhH)ZQ@&Opv;u)lFe3Uc-d z0Z^Lss#N!!Y)7w%?CcF4Su^^m)&F&~dxLhwB|9LSI28F1Tl_Yir_v(G8P;K(fnVQf z0Q_qwW++zBSR|k7wTE0SdgFhN20JvmByS51v*wlUv6FzEx*XSH`5Azpt!9hO|8$Vp zSHnEwt75fj?)EL%7fpIUKq_Wx@1jUWu5)C2#25U=-Gh&dU$pmYQSgmmU@2 z>EiR5|z{6gb114G!>xWvTZ`|F?3teoEqGL`e1$q9!+j%TdhG3kNr~)X#j*5^SMUh!MkAs!^|Str{Xn7{3^l- zy=OHv%FPlHOzfIBgp&kzCc>XDtQ_Y!0`=e35? zaN!KoG>y?g0JEDNa#_kJ_`D~WrjJqOGxMv&#gv(q>|PCbY@UMT&Hw-$XD(qnEKdKm z3vLY(mxC0t))E1K&+hq>lguD|s_!?4AcqLteGcu=Kn}kk0M{_fYC+BFQqMUSpz~o_ zOGifT7k|BXo=N%mYc+jmZX+>Y<+CujrI~;n;vB{y=$*26c=$pMsF3MR+i1A7sK~sp zd?7|5=cw4%PN+Qpu&*)4-mA}v3Ai+ot~h0at?_F08OzNfIjOq}Cr4bjCj5(s^I$3+ zY|jrk)YNo%-xjOP;?4aeXMI;vX@}Qtt$VCFh;BsjMeSK~r6Y2fCqR}>MzT|*KkI!X z9}sYhBQAZVc3tVN_!++72|1Tf!1R_Q?1~X!&(LZ$$h>qryImH7CA=`u#S^p;TW4Q9 z3T)qX>P-_#k9Rl^dw@%2vZiCd0x5AK_~JVC&VI62s6mZ9s`E$0{Wk+Q{n}sjAl0Y3iX^| zRK}WF<)n<07$;~}D>e@}WT)s#D1kw9uVX(Q;-?EH7*1jQj5 z1b?5yylWtbdkCPTJ$U_9njxQRqSDw-!#m@6A9}_(DXzwhFV~;5liLU)4GKq>I2%Hj zKo0Q^;}G=AJA63YTciexv`*{^w5fONHh-p@x6et?y+tjT8?z*8Nb1||qpmswT>H`@ zeBA71?$TJw$9S1@g|Sv|+^?M#d>fxqr_P!AQuu(w`p0Z6xaMRK=b*JB{_b?mLB?oy zF3%Vr<~Nl7EI8FVN952oOe3rzUa6+m>{HCPNBt}wW4gjU@wF;tk&8>w!ouRfy$~OL zs~1$eop7{=UG`W-%*q$~WbQA>>5p2i!x&FT0QSy4!`#vhx!T)^}AaHYB0eMFLkxUl_>Q$&gp zt442$Xg)GKCDksFo|ypT5dSa^L7&gRY{zW$4I48Dn1Z6$eEzK+Wn2x!inw`xuOdcff@eg)-)45&5n zcK_3GNXT#(#%5rhFxGs6u+2o>;#HR;a_E=shz?&Ccfar;z165cU-^*;xtOF|T9j=8 z0&`rVr4mp)Ki$}{T43vjwl3=Bm9Hqi{p1x@_F{MCR+A3{Rx1?f!HsYT4iZ?+p0%XA zUeW7lBg??I@QK&a>O%b^L8@%Y-yDJ*A_%{6*bj1ujsTu+SyL{hK~;uM`s>`CSztsn zB8-3V*$}eP_rfT=?dt_3B%VWb+dpX@{^a~)98^83Vx)Sknsya~UD;68?O|C`z^xyve`}1-Q(KikwK@PDHK!!$U z+2of6+2nY%3Dx{b=PQkaCY+3mz1+7Y5?LMk8IfZRIJKl#ofSb22@m5Cbcg?Y4$)%2 z+?P(5O_r~WQ1lMl`CKjHUY$}nQ_EapsHsrc&<7B7@<;nGr0HL|T9gn_#%R4O4?HB? zq7ClX*eG~LO0$LHaNiq}!nJYL&h-?bs2ashmf#}i7?Y$mtO4u1&hylq%NY@PN953J zX@`XOv*g+xBsgz2a6&cqc(*vV(g|bn?1x8kRtIZ0+`_j%O_#( zXnfB#@h_g|n}6J?n;I9=ytMZqzxqLb;p_otU)bA4(EG33$eT!}h|{M(NU`(186iKV z)LJzkf1m5s=Oc2)#*3%NF-LuN{+J`9wEyb0>x+a{OqtBC&Bur2C+tv@F*l6{d3Bfy*om zs%s-9WUYHDlxCwq&WI1=?37l@t0_YYW8$v(nN6 zwxd-KP7(wp#~F`E$d9UJ9Fa5DHL7L--5aI&{D9>A5JwNyCf_ZN_0Ra|^~XZhZwh_} zfTxv-_`6}}#tYta>rk)yk77M-D{C#o2i`Ll2pE674N&D?HhLRqHJi9l0GG>tXbL;2 z=|pAzxi{MCSxi0^ROB~jAZG~Dea`m%RqBZlfDX3LLwurhNf+bE7fsYYcRRS9F?4AE z=s{d%E1$3{PJyJ>_8Oa&y0rh@jpQ)SKz|i#AmL$|7`6TgRxg>0EcICC%ZclSQm{hq zuMTF9O&({KlL4&GtS1q^i9yzb!%A~<3rOtKe0-*WB9nwSUOi=l3)2B-((J|Q($7pk z1iLz&@fxOSe(A-cI8~zV>w}rT5z*PWa74~>(gW$GFq(buwRsw5=nYK!`f(_~_IkW) zbDm&KcDg?sU=p~R7djS7Z$PTK{j$}GMHrXvHDkeWZ`Bjl;67vBX~3&0ajbTx^J4Dn zzNNF+w{I`Oq#yE1e`>kKto>}|&Pe-j&Opv;j(;1^K!25bQUp+)8)=VVGfmkjnswhw zp2fGpElYHH)fi#e*{i7jAK4AE+_L5ebn!=biaQt5U$jTtZZ1IRH(_JR&+n$ z%v1tNk{FX|&HntFM+8^i_=#7Esh zJ&*LfRZk@xCeKa4{4{@x2!kb2w5r+_vWs0BS)BWuGZbeS5VCKaf&MD>WC(z*Y0sCV zIiqvgtmaY<(LFTLW7;YK=RFX7&yB`(HEijSURyM1q6wV-AZN!9;|%myp#gN%XxR&^ zM`tdyQ)~>xwG~V56m`P=?Jexf>#6vqJx&1V7uU@0&fZjUtR}gqTxm(GVx;w9!U9i7 zW6e$qha$T9fU_4>wOw9)6c5aG9EXh`6I^wk=%ql55;=L0s z!pPek7b5{pFDb$24?lhJ4rjkSvlW%A-HF(#nKe(eoXESVUjAnIH)kMc66D`F1N~L% zDG|Ub(c>*zU8p-_#hR+j$cZa@UqsJt2dwEcLwSZ6-3L^VpRgJPm&*;Wf}D{Z#u@0Z zLJe2}lo#5L%T?LHnry!Y)FyRtjzWw&(-KdHW4F>S6^jFGHl>ewn%NzwDXRz^ds19A zG`8tr#Rl?4=uSc(m(GIU#rB^!)3bFfZ*DRYwqCUs#xpSx>pdTydXZuFjJgj&-=5}< z`4Pu6))rwQo~E!XT@OQvPC7@uyJPXZG*H;@t?*-=uj`XIJixuW!5jvwC6?zDYEniN z^mE-~F1|HM+b`R9x5#A1nr;A*(}Hs4-HFl!(*3J9)joak<0@Ofd>L5v8>qh_gl#wb z17{L{^Zn+3Ci@qyp#RI6e^KZ!Wl(!p{KEE=3AUd?afUdt&zZ(KkTYrokSh?xae<;N znNwb>#wO@yo2kxdV*1_CB2US(b%7VEO2}p3FBLDpHa-J6BR`BYaC-q7;C#$k6^(3i zG*$L^>)_U6!{Ot)5g1i>g!*MR*>2E_Rstk=>XTlzoe$s?1HH99x7s+J0Lkqa=`Z?8 zX)b3B2%J3NOhhtOs6^sHy-uA+ge#)lZJ6p=;_(8~^vq0cq)ziZ#}PSGuB0+Bg)ps# zZHb>zxWoHie}vN@QWkBCae;cse3KEjXd*9Z@`w!VT-Nsdm<+>Nw9RnU7s> zDnm}JCUIFdo^J*@J8>9i;3gE*faFw}v*EO3h~(0Xx&1 zo`6c?^B5VD7bOB`?u2~3Kh?k;J}xCu7M=SsE!n|~GFkh8Gim~QEkPrG5BPY-F}7j% z`{XlvOhXkj+4Tw!Y^&=TNRP-_XS}7jOA{~u-0LN~ek~dJcoy8+pN8Y?7u93Pis(^A zpk%^XjqA-~))gG6ZKYu_o$(p7&?`@f%{)`(h-baO<^f|>dU9A+0;OUuWA$6_Yy2!G zbJo+nqom3eD(!A)754s9&d~o&U;aD$-}b%4Un`{li|N2Z^p~6;4G1tH0Y--ge;6i& za-TCTDUdS;1W;20V0^%!?b;JJ3G(spWPDoD9n#qwOVsSzv3H**BnL_H&Mm7~+~Net z8O33ofjgW~1EC%UXmj((`3)ZCTJ%dR{|TGB9_*S-Hp}jM>VDC!bIziFYOnR@V`EHU6ezU7pdg z`giD+tw-d{K9@P8v~|V7=)*o_~S@i;58$VsoYGC~E{_L(cp#C>0Mivm1_|HWx?_|;yJ_kBXaf_VPLTsp(vC`o^yAl zn_|GDh&z3AKZVbXye`gJ})vB<#7uPr9v%5q3jvFK%QMQfMkk|)@BEo$d@h?yTL z0^PPMNG;C2aJf~(#o-JextHS+c7@&B_h#${Qq2+x02w>}4xGarFlgTG& z3|unC(SX|iJ(cGR3qjn(_>&{1o07<^?W!_)4EQR@8P#E&fjdm0zJHbsq*BY2JTtcz z?T0GscCq8S9N+EGC=u(wKz=);!WrO5^}gMKxjsrB#Oeth>^OJTBCbx$lKRQ<7c1-! zkob59oO$WVd=W2qc(_Vn?fM+!-E$p(adEY#aG_1>4;P<`JTN^XXFch{>zAd*I1TEU z6SfGE!iEnrpWf%5Yd+P$(Ed49O%qtYkQ{O=A)-HkK*7K=IYdR(Y%WMIuZ-`JN};l* z@{%Ob?#@J}oE+d97$HEr1Q;C} zP@L7!>~p3$0CL8K0FJA8HHnYbXE?rko){v>MUu>r=v`JItlFadnPHl_f)xqLmAhXV zYL^0XMtvA(;D%z3zMh> z8*W96io21f(p4UjGei4+`E(qfM$d^TuD0uPN=4LnaS>pv*z67eI?yWdI zqi&Ao7Pk91Wn^NC1C%WrxnX+1^>qYGd=Vp)_7v#SDdcET)`9J%kak z?LV7l6)|@!L*(|*4o(Bdx;-Y{n20WKbJ2C{Jz3Ky2b^toX1G*4Ta7U;lpsg2+m5FM zb}OEVH@oAnFQS?kgN=4X&W2?Bo{{@Bd{izdKL$E~Qj+js?j+?5sLP*5l$>9*sWZGzfKIK|l;`HA zqJw;^h(XOBF9-fV+awN>-|gSkLEf+a{8AeD>!O8tOZs-^2<(B(qA?e7r^dSVHYN{Gqz(`Dz{h2Y z6_B%&hj9k(UPuEFGqLA$#%NWH=xW+aM~p^}>*Dv(2jNN~Z+WQ>>nPv>qHoN~zGO`T zYjtcY@w;EN(U!e@kM~PoBRC%8aI+wc;DEE{F*;1DXIJrvJkCFmWP zwLB(+2DGz|$l1eV37rTji#|nWx2NlToe`0d<%BPk)g>E~)QnfAT&n>=`qggPytm>3 z=t+ZtDYKbL9sc+ROcNj39~i0QWaZid%n~mZ#GMLmqo2wa^LW2OrEEvcY|{Dqn&C8G znYEqk)c-Zkej?;2eCU5lfe8c{Nq`Xqx*z`$eXm6V^c%uL(Cu@kw*+!_0kzvpeS_5F zAsNl&fsLun>Y5g@0SkrbK0UbS#lFDBK`&Hbrcho=HZ;v^|uZAOqf3*eEcz4`pcVuAw7LX<=Rct23?c1KFhZdVWv2ffOi?C zE&~#ly5#}v2b>W)D+N1hrE3mM<_p!EH8}F5-5LlN#`kR~J4v(#9lmr#&NlQ#UyIwX zf4PB`$tW8onPgG=>FG3pV>J{g&YrVa{2VZF8WE!T9Mz;)aT?@|?l8{4tzD@BTWtuN*9I0=k08l7 zYXGr5^?QQM^!4+$_HoDYLrx330j@CVNLNK>ax5VgVUfjj3%?M6ZRdWIxdydDM(?L$ z3>0SzTQC~Ht~c@0$UvZU_178I2)zZhdsr2@EAjlPLZmW~*(c#Df6v*UZv~hJ@I_=S zp9EPv?b6Li%QhX%W3ozK8H{jTSfBeSC=S8C0&piA6{9tgz7)HbMB+f3VS$MimoOuL_*GB*XhR+(0)+3jKmdVQt+KE)B5_&d7k5eML_l( aDR{qTbOeDDdvJx{|Kb+}!c=i5ApZpceM=Sq literal 0 HcmV?d00001 diff --git a/testutil/src/main/resources/hive/testGenesis.json b/testutil/src/main/resources/hive/testGenesis.json new file mode 100644 index 00000000000..248f0933ddd --- /dev/null +++ b/testutil/src/main/resources/hive/testGenesis.json @@ -0,0 +1,22 @@ +{ + "config": { + "chainId": 1, + "ethash": { + }, + "londonBlock": 33, + "shanghaiTime": 1444660030 + }, + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020000", + "gasLimit" : "0x2fefd8", + "timestamp" : "0x54c98c81", + "extraData" : "0x42", + "mixHash" : "0x2c85bcbce56429100b2108254bb56906257582aeafcbd682bc9af67a9f5aee46", + "nonce" : "0x78cc16f7b4f65485", + "alloc" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance" : "0x09184e72a000" + } + } +} \ No newline at end of file From 4c3565300af1c902a93550ba2a1b21eec487ba05 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Tue, 30 May 2023 09:03:22 -0600 Subject: [PATCH 08/35] GraphQL: Migrate Long types to strings (#5505) Migrate from EIP specified numeric values to execution-spec specified string values. Signed-off-by: Danno Ferrin --- .../api/graphql/internal/Scalars.java | 13 ++-- .../api/graphql/GraphQLHttpServiceTest.java | 34 ++++----- .../api/graphql/scalar/LongScalarTest.java | 4 +- .../api/graphql/block_withdrawals.json | 24 +++---- .../block_withdrawals_pre_shanghai.json | 10 ++- .../ethereum/api/graphql/eth_blockNumber.json | 12 ++-- .../ethereum/api/graphql/eth_call_Block8.json | 17 +++-- .../eth_call_Block8_invalidHexBytesData.json | 3 +- .../api/graphql/eth_call_BlockLatest.json | 17 +++-- .../api/graphql/eth_call_from_contract.json | 17 +++-- .../eth_estimateGas_contractDeploy.json | 11 ++- .../eth_estimateGas_from_contract.json | 10 +-- .../api/graphql/eth_estimateGas_noParams.json | 11 ++- .../api/graphql/eth_estimateGas_transfer.json | 10 +-- .../ethereum/api/graphql/eth_gasPrice.json | 8 +-- .../api/graphql/eth_getBalance_0x19.json | 6 +- .../eth_getBalance_invalidAccountLatest.json | 2 +- .../api/graphql/eth_getBalance_latest.json | 4 +- .../eth_getBlockTransactionCount_byHash.json | 14 ++-- ...eth_getBlockTransactionCount_byNumber.json | 52 +++++++------- .../api/graphql/eth_getBlock_byHash.json | 54 +++++++------- .../graphql/eth_getBlock_byHashInvalid.json | 4 +- .../api/graphql/eth_getBlock_byNumber.json | 68 +++++++++--------- .../api/graphql/eth_getBlock_shanghai.json | 12 ++-- .../ethereum/api/graphql/eth_getCode.json | 6 +- .../api/graphql/eth_getCode_noCode.json | 11 ++- .../graphql/eth_getLogs_emptyListParam.json | 35 +++++----- .../graphql/eth_getLogs_matchAnyTopic.json | 29 ++++---- .../api/graphql/eth_getLogs_matchTopic.json | 29 ++++---- .../api/graphql/eth_getLogs_range.json | 8 +-- .../api/graphql/eth_getStorageAt.json | 10 ++- ..._getStorageAt_illegalRangeGreaterThan.json | 12 ++-- .../api/graphql/eth_getTransactionCount.json | 10 ++- .../graphql/eth_getTransactionReceipt.json | 40 +++++------ ...th_getTransaction_byBlockHashAndIndex.json | 20 +++--- ..._getTransaction_byBlockNumberAndIndex.json | 20 +++--- ...nsaction_byBlockNumberAndInvalidIndex.json | 13 ++-- .../graphql/eth_getTransaction_byHash.json | 47 +++++++------ .../eth_getTransaction_byHashNull.json | 10 +-- .../api/graphql/eth_getTransaction_type2.json | 18 +++-- ...h_sendRawTransaction_contractCreation.json | 8 +-- .../eth_sendRawTransaction_messageCall.json | 9 ++- .../eth_sendRawTransaction_transferEther.json | 8 +-- .../ethereum/api/graphql/eth_syncing.json | 14 ++-- .../api/graphql/graphql_blocks_byFrom.json | 8 +-- .../api/graphql/graphql_blocks_byRange.json | 70 +++++++++---------- .../ethereum/api/graphql/graphql_pending.json | 14 ++-- .../api/graphql/graphql_variable_bytes.json | 10 +-- .../api/graphql/graphql_variable_bytes32.json | 2 +- 49 files changed, 419 insertions(+), 459 deletions(-) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/Scalars.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/Scalars.java index 251f4815bf2..45f9ffb6fce 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/Scalars.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/Scalars.java @@ -299,20 +299,19 @@ public Bytes32 parseLiteral( } }; - private static final Coercing LONG_COERCING = + private static final Coercing LONG_COERCING = new Coercing<>() { @Override - public Number serialize( + public String serialize( final Object input, final GraphQLContext graphQLContext, final Locale locale) throws CoercingSerializeException { if (input instanceof Number number) { - return number; + return Bytes.ofUnsignedLong(number.longValue()).toQuantityHexString(); } else if (input instanceof String string) { - final String value = string.toLowerCase(); - if (value.startsWith("0x")) { - return Bytes.fromHexStringLenient(value).toLong(); + if (string.startsWith("0x")) { + return string; } else { - return Long.parseLong(value); + return "0x" + string; } } throw new CoercingSerializeException("Unable to serialize " + input + " as an Long"); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpServiceTest.java index 55eed120eb0..59aaff11d32 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpServiceTest.java @@ -280,8 +280,8 @@ public void query_untypedPost() throws Exception { @Test public void getSocketAddressWhenActive() { final InetSocketAddress socketAddress = service.socketAddress(); - Assertions.assertThat("127.0.0.1").isEqualTo(socketAddress.getAddress().getHostAddress()); - Assertions.assertThat(socketAddress.getPort() > 0).isTrue(); + Assertions.assertThat(socketAddress.getAddress().getHostAddress()).isEqualTo("127.0.0.1"); + Assertions.assertThat(socketAddress.getPort()).isPositive(); } @Test @@ -289,9 +289,9 @@ public void getSocketAddressWhenStoppedIsEmpty() throws Exception { final GraphQLHttpService service = createGraphQLHttpService(); final InetSocketAddress socketAddress = service.socketAddress(); - Assertions.assertThat("0.0.0.0").isEqualTo(socketAddress.getAddress().getHostAddress()); - Assertions.assertThat(0).isEqualTo(socketAddress.getPort()); - Assertions.assertThat("").isEqualTo(service.url()); + Assertions.assertThat(socketAddress.getAddress().getHostAddress()).isEqualTo("0.0.0.0"); + Assertions.assertThat(socketAddress.getPort()).isZero(); + Assertions.assertThat(service.url()).isEmpty(); } @Test @@ -303,8 +303,8 @@ public void getSocketAddressWhenBindingToAllInterfaces() throws Exception { try { final InetSocketAddress socketAddress = service.socketAddress(); - Assertions.assertThat("0.0.0.0").isEqualTo(socketAddress.getAddress().getHostAddress()); - Assertions.assertThat(socketAddress.getPort() > 0).isTrue(); + Assertions.assertThat(socketAddress.getAddress().getHostAddress()).isEqualTo("0.0.0.0"); + Assertions.assertThat(socketAddress.getPort()).isPositive(); Assertions.assertThat(!service.url().contains("0.0.0.0")).isTrue(); } finally { service.stop().join(); @@ -331,12 +331,11 @@ public void ethGetUncleCountByBlockHash() throws Exception { @SuppressWarnings("unchecked") final List list = Mockito.mock(List.class); - Mockito.when(blockchainQueries.blockByHash(ArgumentMatchers.eq(blockHash))) - .thenReturn(Optional.of(block)); + Mockito.when(blockchainQueries.blockByHash(blockHash)).thenReturn(Optional.of(block)); Mockito.when(block.getOmmers()).thenReturn(list); Mockito.when(list.size()).thenReturn(uncleCount); - final String query = "{block(hash:\"" + blockHash.toString() + "\") {ommerCount}}"; + final String query = "{block(hash:\"" + blockHash + "\") {ommerCount}}"; final RequestBody body = RequestBody.create(query, GRAPHQL); try (final Response resp = client.newCall(buildPostRequest(body)).execute()) { @@ -344,8 +343,9 @@ public void ethGetUncleCountByBlockHash() throws Exception { final String jsonStr = resp.body().string(); final JsonObject json = new JsonObject(jsonStr); testHelper.assertValidGraphQLResult(json); - final int result = json.getJsonObject("data").getJsonObject("block").getInteger("ommerCount"); - Assertions.assertThat(result).isEqualTo(uncleCount); + final String result = + json.getJsonObject("data").getJsonObject("block").getString("ommerCount"); + Assertions.assertThat(Bytes.fromHexStringLenient(result).toInt()).isEqualTo(uncleCount); } } @@ -370,8 +370,9 @@ public void ethGetUncleCountByBlockNumber() throws Exception { final String jsonStr = resp.body().string(); final JsonObject json = new JsonObject(jsonStr); testHelper.assertValidGraphQLResult(json); - final int result = json.getJsonObject("data").getJsonObject("block").getInteger("ommerCount"); - Assertions.assertThat(result).isEqualTo(uncleCount); + final String result = + json.getJsonObject("data").getJsonObject("block").getString("ommerCount"); + Assertions.assertThat(Bytes.fromHexStringLenient(result).toInt()).isEqualTo(uncleCount); } } @@ -395,8 +396,9 @@ public void ethGetUncleCountByBlockLatest() throws Exception { final String jsonStr = resp.body().string(); final JsonObject json = new JsonObject(jsonStr); testHelper.assertValidGraphQLResult(json); - final int result = json.getJsonObject("data").getJsonObject("block").getInteger("ommerCount"); - Assertions.assertThat(result).isEqualTo(uncleCount); + final String result = + json.getJsonObject("data").getJsonObject("block").getString("ommerCount"); + Assertions.assertThat(Bytes.fromHexStringLenient(result).toInt()).isEqualTo(uncleCount); } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/LongScalarTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/LongScalarTest.java index 119ce81ce0d..3a0861fa84e 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/LongScalarTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/scalar/LongScalarTest.java @@ -75,7 +75,7 @@ public void serializeLongTest() { scalar .getCoercing() .serialize(value, GraphQLContext.newContext().build(), Locale.ENGLISH)) - .isEqualTo(value); + .isEqualTo(str); } @Test @@ -84,7 +84,7 @@ public void serializeStringTest() { scalar .getCoercing() .serialize(str, GraphQLContext.newContext().build(), Locale.ENGLISH)) - .isEqualTo(value); + .isEqualTo(str); } @Test diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals.json index 024f465a3b3..d24ae7f6a17 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals.json @@ -1,18 +1,18 @@ { - "request": - "{ block (number: 33) { number withdrawalsRoot withdrawals { index amount validator address } } }", - + "request": "{ block (number: 33) { number withdrawalsRoot withdrawals { index amount validator address } } }", "response": { - "data" : { - "block" : { - "number" : 33, + "data": { + "block": { + "number": "0x21", "withdrawalsRoot": "0x37945ab58d2712a26df2a38d217e822694927e29b30d5993d7a53ccea618d1f3", - "withdrawals": [{ - "index": 0, - "amount": 10000000000, - "validator": 10, - "address": "0x0000000000000000000000000000000000000dad" - }] + "withdrawals": [ + { + "index": "0x0", + "amount": "0x2540be400", + "validator": "0xa", + "address": "0x0000000000000000000000000000000000000dad" + } + ] } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals_pre_shanghai.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals_pre_shanghai.json index dd50acb5fe0..dcd0b1834c3 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals_pre_shanghai.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/block_withdrawals_pre_shanghai.json @@ -1,11 +1,9 @@ { - "request": - "{ block (number: 32) { number withdrawalsRoot withdrawals { index amount } } }", - + "request": "{ block (number: 32) { number withdrawalsRoot withdrawals { index amount } } }", "response": { - "data" : { - "block" : { - "number" : 32, + "data": { + "block": { + "number": "0x20", "withdrawalsRoot": null, "withdrawals": null } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_blockNumber.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_blockNumber.json index b061e7e656f..247ec0146e5 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_blockNumber.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_blockNumber.json @@ -1,11 +1,9 @@ { - "request": - "{ block { number } }", - - "response": { - "data" : { - "block" : { - "number" : 33 + "request": "{ block { number } }", + "response": { + "data": { + "block": { + "number": "0x21" } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_Block8.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_Block8.json index 26a2eb4a457..ce54a411f62 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_Block8.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_Block8.json @@ -1,13 +1,12 @@ { - "request": "{block(number :\"0x8\") {number call (data : {from : \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"0x12a7b914\"}){data status}}}" - , - "response":{ - "data" : { - "block" : { - "number" : 8, - "call" : { - "data" : "0x0000000000000000000000000000000000000000000000000000000000000000", - "status" : 1 + "request": "{block(number :\"0x8\") {number call (data : {from : \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"0x12a7b914\"}){data status}}}", + "response": { + "data": { + "block": { + "number": "0x8", + "call": { + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "status": "0x1" } } } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_Block8_invalidHexBytesData.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_Block8_invalidHexBytesData.json index 4693fc3df57..942849e3339 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_Block8_invalidHexBytesData.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_Block8_invalidHexBytesData.json @@ -1,6 +1,5 @@ { - "request": "{block(number :\"0x8\") {number call (data : {from : \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"12a7b914\"}){data status}}}" - , + "request": "{block(number :\"0x8\") {number call (data : {from : \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"12a7b914\"}){data status}}}", "response": { "errors": [ { diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_BlockLatest.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_BlockLatest.json index 7c4a16df7c7..9b5bb2fd89c 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_BlockLatest.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_BlockLatest.json @@ -1,13 +1,12 @@ { - "request": "{block {number call (data : {from : \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"0x12a7b914\"}){data status}}}" - , - "response":{ - "data" : { - "block" : { - "number" : 33, - "call" : { - "data" : "0x0000000000000000000000000000000000000000000000000000000000000001", - "status" : 1 + "request": "{block {number call (data : {from : \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"0x12a7b914\"}){data status}}}", + "response": { + "data": { + "block": { + "number": "0x21", + "call": { + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "status": "0x1" } } } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_from_contract.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_from_contract.json index 9904c248c4c..211a97be18f 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_from_contract.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_from_contract.json @@ -1,13 +1,12 @@ { - "request": "{block {number call (data : {from : \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", to: \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", data :\"0x123456\"}){data status}}}" - , - "response":{ - "data" : { - "block" : { - "number" : 33, - "call" : { - "data" : "0x", - "status" : 1 + "request": "{block {number call (data : {from : \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", to: \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", data :\"0x123456\"}){data status}}}", + "response": { + "data": { + "block": { + "number": "0x21", + "call": { + "data": "0x", + "status": "0x1" } } } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_contractDeploy.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_contractDeploy.json index fda2392515b..664a0e0135d 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_contractDeploy.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_contractDeploy.json @@ -1,10 +1,9 @@ { - - "request" :"{block{estimateGas (data: {from :\"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", data :\"0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029\"})}}", - "response":{ - "data" : { - "block" : { - "estimateGas" : 127129 + "request": "{block{estimateGas (data: {from :\"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", data :\"0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029\"})}}", + "response": { + "data": { + "block": { + "estimateGas": "0x1f099" } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_from_contract.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_from_contract.json index 776b5e0bec8..0836cf0dc3c 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_from_contract.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_from_contract.json @@ -1,9 +1,9 @@ { - "request" :"{block{estimateGas (data : {from : \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", to: \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", data :\"0x123456\"})}}", - "response":{ - "data" : { - "block" : { - "estimateGas" : 21048 + "request": "{block{estimateGas (data : {from : \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", to: \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", data :\"0x123456\"})}}", + "response": { + "data": { + "block": { + "estimateGas": "0x5238" } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_noParams.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_noParams.json index 60a6408aeb3..54a84b893e6 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_noParams.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_noParams.json @@ -1,12 +1,11 @@ { - "request" :"{block{ estimateGas(data:{}) }}", - "response":{ - "data" : { - "block" : { - "estimateGas" : 53000 + "request": "{block{ estimateGas(data:{}) }}", + "response": { + "data": { + "block": { + "estimateGas": "0xcf08" } } }, - "statusCode": 200 } \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_transfer.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_transfer.json index 6bf9c20f9ed..e30ffcf607c 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_transfer.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_estimateGas_transfer.json @@ -1,9 +1,9 @@ { - "request" :"{block{estimateGas (data: {from :\"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to :\"0x8888f1f195afa192cfee860698584c030f4c9db1\"})}}", - "response":{ - "data" : { - "block" : { - "estimateGas" : 21000 + "request": "{block{estimateGas (data: {from :\"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to :\"0x8888f1f195afa192cfee860698584c030f4c9db1\"})}}", + "response": { + "data": { + "block": { + "estimateGas": "0x5208" } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_gasPrice.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_gasPrice.json index 8961bc6b582..744e7ea98b9 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_gasPrice.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_gasPrice.json @@ -1,10 +1,8 @@ { - "request": - "{ gasPrice maxPriorityFeePerGas }", - + "request": "{ gasPrice maxPriorityFeePerGas }", "response": { - "data" : { - "gasPrice" : "0x1", + "data": { + "gasPrice": "0x1", "maxPriorityFeePerGas": "0x0" } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_0x19.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_0x19.json index a7633f591d6..ffb6f29b19c 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_0x19.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_0x19.json @@ -1,10 +1,10 @@ { "request": "{ block(number:\"0x19\") { account(address: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { balance } } }", "response": { - "data" : { + "data": { "block": { - "account" : { - "balance" : "0xfa" + "account": { + "balance": "0xfa" } } } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_invalidAccountLatest.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_invalidAccountLatest.json index 90c59996777..f8a30f59f0f 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_invalidAccountLatest.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_invalidAccountLatest.json @@ -4,7 +4,7 @@ "data": { "pending": { "account": { - "balance": "0x0" + "balance": "0x0" } } } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_latest.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_latest.json index be18be251bb..018772a9e8a 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_latest.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_latest.json @@ -1,8 +1,8 @@ { "request": "{ pending { account(address: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { balance } } }", "response": { - "data" : { - "pending" : { + "data": { + "pending": { "account": { "balance": "0x140" } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlockTransactionCount_byHash.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlockTransactionCount_byHash.json index 9ee5053e36a..a744313b7e8 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlockTransactionCount_byHash.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlockTransactionCount_byHash.json @@ -1,13 +1,9 @@ { - "request": - - "{block (hash : \"0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6\") {transactionCount}} ", - - - "response": { - "data" : { - "block" : { - "transactionCount" : 1 + "request": "{block (hash : \"0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6\") {transactionCount}} ", + "response": { + "data": { + "block": { + "transactionCount": "0x1" } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlockTransactionCount_byNumber.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlockTransactionCount_byNumber.json index 5bdbe5ba596..fa694a254a8 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlockTransactionCount_byNumber.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlockTransactionCount_byNumber.json @@ -1,31 +1,29 @@ { - "request": - - "{block (number : \"0x1e\") {transactions{hash} timestamp difficulty totalDifficulty gasUsed gasLimit hash nonce ommerCount logsBloom mixHash ommerHash extraData stateRoot receiptsRoot transactionCount transactionsRoot}} ", - - - "response": { - "data" : { - "block" : { - "transactions" : [ { - "hash" : "0x9cc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4" - } ], - "timestamp" : 1444660022, - "difficulty" : "0x20740", - "totalDifficulty" : "0x3e6cc0", - "gasUsed" : 23585, - "gasLimit" : 3141592, - "hash" : "0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6", - "nonce" : "0x5c321bd9e9f040f1", - "ommerCount" : 0, - "logsBloom" : "0x00000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000080000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000400000000000000000200000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000800000000040000000000000000000000000000000000000000010000000000000000000000000", - "mixHash" : "0x6ce1c4afb4f85fefd1b0ed966b20cd248f08d9a5b0df773f75c6c2f5cc237b7c", - "ommerHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "extraData" : "0x", - "stateRoot" : "0xdb46d6bb168130fe2cb60b4b24346137b5741f11283e0d7edace65c5f5466b2e", - "receiptsRoot" : "0x88b3b304b058b39791c26fdb94a05cc16ce67cf8f84f7348cb3c60c0ff342d0d", - "transactionCount" : 1, - "transactionsRoot" : "0x5a8d5d966b48e1331ae19eb459eb28882cdc7654e615d37774b79204e875dc01" + "request": "{block (number : \"0x1e\") {transactions{hash} timestamp difficulty totalDifficulty gasUsed gasLimit hash nonce ommerCount logsBloom mixHash ommerHash extraData stateRoot receiptsRoot transactionCount transactionsRoot}} ", + "response": { + "data": { + "block": { + "transactions": [ + { + "hash": "0x9cc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4" + } + ], + "timestamp": "0x561bc336", + "difficulty": "0x20740", + "totalDifficulty": "0x3e6cc0", + "gasUsed": "0x5c21", + "gasLimit": "0x2fefd8", + "hash": "0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6", + "nonce": "0x5c321bd9e9f040f1", + "ommerCount": "0x0", + "logsBloom": "0x00000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000080000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000400000000000000000200000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000800000000040000000000000000000000000000000000000000010000000000000000000000000", + "mixHash": "0x6ce1c4afb4f85fefd1b0ed966b20cd248f08d9a5b0df773f75c6c2f5cc237b7c", + "ommerHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "extraData": "0x", + "stateRoot": "0xdb46d6bb168130fe2cb60b4b24346137b5741f11283e0d7edace65c5f5466b2e", + "receiptsRoot": "0x88b3b304b058b39791c26fdb94a05cc16ce67cf8f84f7348cb3c60c0ff342d0d", + "transactionCount": "0x1", + "transactionsRoot": "0x5a8d5d966b48e1331ae19eb459eb28882cdc7654e615d37774b79204e875dc01" } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_byHash.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_byHash.json index 94b8df0ea58..2c88617ee68 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_byHash.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_byHash.json @@ -1,32 +1,30 @@ { - "request": - - "{block (hash : \"0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6\") {number transactions{hash} timestamp difficulty totalDifficulty gasUsed gasLimit hash nonce ommerCount logsBloom mixHash ommerHash extraData stateRoot receiptsRoot transactionCount transactionsRoot}} ", - - - "response": { - "data" : { - "block" : { - "number" : 30, - "transactions" : [ { - "hash" : "0x9cc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4" - } ], - "timestamp" : 1444660022, - "difficulty" : "0x20740", - "totalDifficulty" : "0x3e6cc0", - "gasUsed" : 23585, - "gasLimit" : 3141592, - "hash" : "0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6", - "nonce" : "0x5c321bd9e9f040f1", - "ommerCount" : 0, - "logsBloom" : "0x00000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000080000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000400000000000000000200000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000800000000040000000000000000000000000000000000000000010000000000000000000000000", - "mixHash" : "0x6ce1c4afb4f85fefd1b0ed966b20cd248f08d9a5b0df773f75c6c2f5cc237b7c", - "ommerHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "extraData" : "0x", - "stateRoot" : "0xdb46d6bb168130fe2cb60b4b24346137b5741f11283e0d7edace65c5f5466b2e", - "receiptsRoot" : "0x88b3b304b058b39791c26fdb94a05cc16ce67cf8f84f7348cb3c60c0ff342d0d", - "transactionCount" : 1, - "transactionsRoot" : "0x5a8d5d966b48e1331ae19eb459eb28882cdc7654e615d37774b79204e875dc01" + "request": "{block (hash : \"0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6\") {number transactions{hash} timestamp difficulty totalDifficulty gasUsed gasLimit hash nonce ommerCount logsBloom mixHash ommerHash extraData stateRoot receiptsRoot transactionCount transactionsRoot}} ", + "response": { + "data": { + "block": { + "number": "0x1e", + "transactions": [ + { + "hash": "0x9cc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4" + } + ], + "timestamp": "0x561bc336", + "difficulty": "0x20740", + "totalDifficulty": "0x3e6cc0", + "gasUsed": "0x5c21", + "gasLimit": "0x2fefd8", + "hash": "0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6", + "nonce": "0x5c321bd9e9f040f1", + "ommerCount": "0x0", + "logsBloom": "0x00000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000080000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000400000000000000000200000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000800000000040000000000000000000000000000000000000000010000000000000000000000000", + "mixHash": "0x6ce1c4afb4f85fefd1b0ed966b20cd248f08d9a5b0df773f75c6c2f5cc237b7c", + "ommerHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "extraData": "0x", + "stateRoot": "0xdb46d6bb168130fe2cb60b4b24346137b5741f11283e0d7edace65c5f5466b2e", + "receiptsRoot": "0x88b3b304b058b39791c26fdb94a05cc16ce67cf8f84f7348cb3c60c0ff342d0d", + "transactionCount": "0x1", + "transactionsRoot": "0x5a8d5d966b48e1331ae19eb459eb28882cdc7654e615d37774b79204e875dc01" } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_byHashInvalid.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_byHashInvalid.json index 1824755037a..a1ec74511c3 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_byHashInvalid.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_byHashInvalid.json @@ -18,7 +18,9 @@ } } ], - "data": {"block": null} + "data": { + "block": null + } }, "statusCode": 400 } \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_byNumber.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_byNumber.json index d6c2481117f..f9c9c7ece8c 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_byNumber.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_byNumber.json @@ -1,41 +1,39 @@ { - "request": - - "{block (number : \"0x1e\") {transactions{hash} timestamp difficulty totalDifficulty gasUsed gasLimit hash nonce ommerCount logsBloom mixHash ommerHash extraData stateRoot receiptsRoot transactionCount transactionsRoot ommers{hash} ommerAt(index : 1){hash} miner{address} account(address: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\"){balance} parent{hash} }} ", - - - "response":{ - "data" : { - "block" : { - "transactions" : [ { - "hash" : "0x9cc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4" - } ], - "timestamp" : 1444660022, - "difficulty" : "0x20740", - "totalDifficulty" : "0x3e6cc0", - "gasUsed" : 23585, - "gasLimit" : 3141592, - "hash" : "0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6", - "nonce" : "0x5c321bd9e9f040f1", - "ommerCount" : 0, - "logsBloom" : "0x00000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000080000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000400000000000000000200000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000800000000040000000000000000000000000000000000000000010000000000000000000000000", - "mixHash" : "0x6ce1c4afb4f85fefd1b0ed966b20cd248f08d9a5b0df773f75c6c2f5cc237b7c", - "ommerHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "extraData" : "0x", - "stateRoot" : "0xdb46d6bb168130fe2cb60b4b24346137b5741f11283e0d7edace65c5f5466b2e", - "receiptsRoot" : "0x88b3b304b058b39791c26fdb94a05cc16ce67cf8f84f7348cb3c60c0ff342d0d", - "transactionCount" : 1, - "transactionsRoot" : "0x5a8d5d966b48e1331ae19eb459eb28882cdc7654e615d37774b79204e875dc01", - "ommers" : [ ], - "ommerAt" : null, - "miner" : { - "address" : "0x8888f1f195afa192cfee860698584c030f4c9db1" + "request": "{block (number : \"0x1e\") {transactions{hash} timestamp difficulty totalDifficulty gasUsed gasLimit hash nonce ommerCount logsBloom mixHash ommerHash extraData stateRoot receiptsRoot transactionCount transactionsRoot ommers{hash} ommerAt(index : 1){hash} miner{address} account(address: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\"){balance} parent{hash} }} ", + "response": { + "data": { + "block": { + "transactions": [ + { + "hash": "0x9cc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4" + } + ], + "timestamp": "0x561bc336", + "difficulty": "0x20740", + "totalDifficulty": "0x3e6cc0", + "gasUsed": "0x5c21", + "gasLimit": "0x2fefd8", + "hash": "0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6", + "nonce": "0x5c321bd9e9f040f1", + "ommerCount": "0x0", + "logsBloom": "0x00000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000080000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000400000000000000000200000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000800000000040000000000000000000000000000000000000000010000000000000000000000000", + "mixHash": "0x6ce1c4afb4f85fefd1b0ed966b20cd248f08d9a5b0df773f75c6c2f5cc237b7c", + "ommerHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "extraData": "0x", + "stateRoot": "0xdb46d6bb168130fe2cb60b4b24346137b5741f11283e0d7edace65c5f5466b2e", + "receiptsRoot": "0x88b3b304b058b39791c26fdb94a05cc16ce67cf8f84f7348cb3c60c0ff342d0d", + "transactionCount": "0x1", + "transactionsRoot": "0x5a8d5d966b48e1331ae19eb459eb28882cdc7654e615d37774b79204e875dc01", + "ommers": [], + "ommerAt": null, + "miner": { + "address": "0x8888f1f195afa192cfee860698584c030f4c9db1" }, - "account" : { - "balance" : "0x12c" + "account": { + "balance": "0x12c" }, - "parent" : { - "hash" : "0xf8cfa377bd766cdf22edb388dd08cc149e85d24f2796678c835f3c54ab930803" + "parent": { + "hash": "0xf8cfa377bd766cdf22edb388dd08cc149e85d24f2796678c835f3c54ab930803" } } } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json index 099460a8e83..3e98251971b 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json @@ -1,8 +1,8 @@ { "request": "{block (number : 33) { baseFeePerGas difficulty extraData miner { address } mixHash nonce stateRoot totalDifficulty withdrawalsRoot withdrawals { address amount index validator } }} ", - "response":{ - "data" : { - "block" : { + "response": { + "data": { + "block": { "baseFeePerGas": "0x3b9aca00", "difficulty": "0x0", "extraData": "0x", @@ -17,9 +17,9 @@ "withdrawals": [ { "address": "0x0000000000000000000000000000000000000dad", - "amount": 10000000000, - "index": 0, - "validator": 10 + "amount": "0x2540be400", + "index": "0x0", + "validator": "0xa" } ] } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getCode.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getCode.json index 94a3eea09a1..e9e1ea45576 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getCode.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getCode.json @@ -1,8 +1,7 @@ { - "request" : "{ pending { account(address: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { code } } }", - + "request": "{ pending { account(address: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { code } } }", "response": { - "data" : { + "data": { "pending": { "account": { "code": "0x6000357c010000000000000000000000000000000000000000000000000000000090048063102accc11461012c57806312a7b9141461013a5780631774e6461461014c5780631e26fd331461015d5780631f9030371461016e578063343a875d1461018057806338cc4831146101955780634e7ad367146101bd57806357cb2fc4146101cb57806365538c73146101e057806368895979146101ee57806376bc21d9146102005780639a19a9531461020e5780639dc2c8f51461021f578063a53b1c1e1461022d578063a67808571461023e578063b61c05031461024c578063c2b12a731461025a578063d2282dc51461026b578063e30081a01461027c578063e8beef5b1461028d578063f38b06001461029b578063f5b53e17146102a9578063fd408767146102bb57005b6101346104d6565b60006000f35b61014261039b565b8060005260206000f35b610157600435610326565b60006000f35b6101686004356102c9565b60006000f35b610176610442565b8060005260206000f35b6101886103d3565b8060ff1660005260206000f35b61019d610413565b8073ffffffffffffffffffffffffffffffffffffffff1660005260206000f35b6101c56104c5565b60006000f35b6101d36103b7565b8060000b60005260206000f35b6101e8610454565b60006000f35b6101f6610401565b8060005260206000f35b61020861051f565b60006000f35b6102196004356102e5565b60006000f35b610227610693565b60006000f35b610238600435610342565b60006000f35b610246610484565b60006000f35b610254610493565b60006000f35b61026560043561038d565b60006000f35b610276600435610350565b60006000f35b61028760043561035e565b60006000f35b6102956105b4565b60006000f35b6102a3610547565b60006000f35b6102b16103ef565b8060005260206000f35b6102c3610600565b60006000f35b80600060006101000a81548160ff021916908302179055505b50565b80600060016101000a81548160ff02191690837f01000000000000000000000000000000000000000000000000000000000000009081020402179055505b50565b80600060026101000a81548160ff021916908302179055505b50565b806001600050819055505b50565b806002600050819055505b50565b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b50565b806004600050819055505b50565b6000600060009054906101000a900460ff1690506103b4565b90565b6000600060019054906101000a900460000b90506103d0565b90565b6000600060029054906101000a900460ff1690506103ec565b90565b600060016000505490506103fe565b90565b60006002600050549050610410565b90565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061043f565b90565b60006004600050549050610451565b90565b7f65c9ac8011e286e89d02a269890f41d67ca2cc597b2c76c7c69321ff492be5806000602a81526020016000a15b565b6000602a81526020016000a05b565b60017f81933b308056e7e85668661dcd102b1f22795b4431f9cf4625794f381c271c6b6000602a81526020016000a25b565b60016000602a81526020016000a15b565b3373ffffffffffffffffffffffffffffffffffffffff1660017f0e216b62efbb97e751a2ce09f607048751720397ecfb9eef1e48a6644948985b6000602a81526020016000a35b565b3373ffffffffffffffffffffffffffffffffffffffff1660016000602a81526020016000a25b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001023373ffffffffffffffffffffffffffffffffffffffff1660017f317b31292193c2a4f561cc40a95ea0d97a2733f14af6d6d59522473e1f3ae65f6000602a81526020016000a45b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001023373ffffffffffffffffffffffffffffffffffffffff1660016000602a81526020016000a35b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001023373ffffffffffffffffffffffffffffffffffffffff1660017fd5f0a30e4be0c6be577a71eceb7464245a796a7e6a55c0d971837b250de05f4e60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe98152602001602a81526020016000a45b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001023373ffffffffffffffffffffffffffffffffffffffff16600160007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe98152602001602a81526020016000a35b56" @@ -10,6 +9,5 @@ } } }, - "statusCode": 200 } \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getCode_noCode.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getCode_noCode.json index 16f50cd8195..55dad6d0ffa 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getCode_noCode.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getCode_noCode.json @@ -1,16 +1,13 @@ { - "request" : "{ pending { account(address: \"0x8888f1f195afa192cfee860698584c030f4c9db1\") { code } } }", - + "request": "{ pending { account(address: \"0x8888f1f195afa192cfee860698584c030f4c9db1\") { code } } }", "response": { - "data" : { + "data": { "pending": { - "account" :{ - "code" :"0x" + "account": { + "code": "0x" } } } }, - "statusCode": 200 - } \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_emptyListParam.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_emptyListParam.json index 5a8b9756206..f4d645018d9 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_emptyListParam.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_emptyListParam.json @@ -1,26 +1,27 @@ { "request": "{ block(number: \"0x20\") { logs( filter: { topics : [[], [\"0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b\"]]}) { index topics data account{address} transaction{hash} } } }", "response": { - "data" : { - "block" : { - "logs" : [ { - "index" : 0, - "topics": [ - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ], - "data" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9000000000000000000000000000000000000000000000000000000000000002a", - "account" : { - "address" : "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f" - }, - "transaction" : { - "hash" : "0xcef53f2311d7c80e9086d661e69ac11a5f3d081e28e02a9ba9b66749407ac310" + "data": { + "block": { + "logs": [ + { + "index": "0x0", + "topics": [ + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9000000000000000000000000000000000000000000000000000000000000002a", + "account": { + "address": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f" + }, + "transaction": { + "hash": "0xcef53f2311d7c80e9086d661e69ac11a5f3d081e28e02a9ba9b66749407ac310" + } } - } ] + ] } } }, - "statusCode": 200 } \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_matchAnyTopic.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_matchAnyTopic.json index b8d897bee79..eb56dccac12 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_matchAnyTopic.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_matchAnyTopic.json @@ -1,22 +1,25 @@ { "request": "{ block(number: \"0x17\") { logs( filter: { topics : []}) { index topics data account{address} transaction{hash} } } }", "response": { - "data" : { - "block" : { - "logs" : [ { - "index" : 0, - "topics" : [ "0x65c9ac8011e286e89d02a269890f41d67ca2cc597b2c76c7c69321ff492be580" ], - "data" : "0x000000000000000000000000000000000000000000000000000000000000002a", - "account" : { - "address" : "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f" - }, - "transaction" : { - "hash" : "0x97a385bf570ced7821c6495b3877ddd2afd5c452f350f0d4876e98d9161389c6" + "data": { + "block": { + "logs": [ + { + "index": "0x0", + "topics": [ + "0x65c9ac8011e286e89d02a269890f41d67ca2cc597b2c76c7c69321ff492be580" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000002a", + "account": { + "address": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f" + }, + "transaction": { + "hash": "0x97a385bf570ced7821c6495b3877ddd2afd5c452f350f0d4876e98d9161389c6" + } } - } ] + ] } } }, - "statusCode": 200 } \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_matchTopic.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_matchTopic.json index 46f79ccd757..7a674cd57b8 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_matchTopic.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_matchTopic.json @@ -1,22 +1,25 @@ { "request": "{ block(number: \"0x17\") { logs( filter: { topics : [[\"0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b\", \"0x65c9ac8011e286e89d02a269890f41d67ca2cc597b2c76c7c69321ff492be580\"]]}) { index topics data account{address} transaction{hash} } } }", "response": { - "data" : { - "block" : { - "logs" : [ { - "index" : 0, - "topics" : [ "0x65c9ac8011e286e89d02a269890f41d67ca2cc597b2c76c7c69321ff492be580" ], - "data" : "0x000000000000000000000000000000000000000000000000000000000000002a", - "account" : { - "address" : "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f" - }, - "transaction" : { - "hash" : "0x97a385bf570ced7821c6495b3877ddd2afd5c452f350f0d4876e98d9161389c6" + "data": { + "block": { + "logs": [ + { + "index": "0x0", + "topics": [ + "0x65c9ac8011e286e89d02a269890f41d67ca2cc597b2c76c7c69321ff492be580" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000002a", + "account": { + "address": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f" + }, + "transaction": { + "hash": "0x97a385bf570ced7821c6495b3877ddd2afd5c452f350f0d4876e98d9161389c6" + } } - } ] + ] } } }, - "statusCode": 200 } \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_range.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_range.json index 34416ddb867..1d54cdf6285 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_range.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getLogs_range.json @@ -4,7 +4,7 @@ "data": { "logs": [ { - "index": 0, + "index": "0x0", "topics": [ "0x65c9ac8011e286e89d02a269890f41d67ca2cc597b2c76c7c69321ff492be580" ], @@ -15,12 +15,12 @@ "transaction": { "hash": "0x97a385bf570ced7821c6495b3877ddd2afd5c452f350f0d4876e98d9161389c6", "block": { - "number": 23 + "number": "0x17" } } }, { - "index": 0, + "index": "0x0", "topics": [], "data": "0x000000000000000000000000000000000000000000000000000000000000002a", "account": { @@ -29,7 +29,7 @@ "transaction": { "hash": "0x5ecd942096ab3f70c5bcc8f3a98f88c4ff0a3bd986417df9948eb1819db76d0e", "block": { - "number": 24 + "number": "0x18" } } } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getStorageAt.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getStorageAt.json index 09d2569e80b..591be7bfd5b 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getStorageAt.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getStorageAt.json @@ -1,15 +1,13 @@ { - "request" :"{ pending { account(address: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { storage(slot: \"0x00000000000000000000000000000004\") } } }", - + "request": "{ pending { account(address: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { storage(slot: \"0x00000000000000000000000000000004\") } } }", "response": { - "data" : { + "data": { "pending": { - "account" :{ - "storage" :"0xaabbccffffffffffffffffffffffffffffffffffffffffffffffffffffffffee" + "account": { + "storage": "0xaabbccffffffffffffffffffffffffffffffffffffffffffffffffffffffffee" } } } }, - "statusCode": 200 } \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getStorageAt_illegalRangeGreaterThan.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getStorageAt_illegalRangeGreaterThan.json index 77155a8d264..85d7d8ce9d7 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getStorageAt_illegalRangeGreaterThan.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getStorageAt_illegalRangeGreaterThan.json @@ -1,15 +1,13 @@ { - "request" :"{ pending { account(address: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { storage(slot: \"0x00000000000000000000000000000021\") } } }", - - "response":{ - "data" : { + "request": "{ pending { account(address: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { storage(slot: \"0x00000000000000000000000000000021\") } } }", + "response": { + "data": { "pending": { - "account" : { - "storage" : "0x0000000000000000000000000000000000000000000000000000000000000000" + "account": { + "storage": "0x0000000000000000000000000000000000000000000000000000000000000000" } } } }, - "statusCode": 200 } \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionCount.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionCount.json index 990fbf74773..a1fc9e307c2 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionCount.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionCount.json @@ -1,15 +1,13 @@ { - "request" :"{ pending { account(address: \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\") { transactionCount } } }", - + "request": "{ pending { account(address: \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\") { transactionCount } } }", "response": { - "data" : { + "data": { "pending": { - "account" :{ - "transactionCount" : 33 + "account": { + "transactionCount": "0x21" } } } }, - "statusCode": 200 } \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionReceipt.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionReceipt.json index 4d58d0a8a4a..983b460f617 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionReceipt.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransactionReceipt.json @@ -1,29 +1,27 @@ -{ - "request" : "{ transaction(hash: \"0x812742182a79a8e67733edc58cfa3767aa2d7ad06439d156ddbbb33e3403b4ed\") {block{hash logsBloom} hash createdContract{address} cumulativeGasUsed gas gasUsed logs{topics} from{address} to{address} index } }", - - "response":{ - "data" : { - "transaction" : { - "block" : { - "hash" : "0x10aaf14a53caf27552325374429d3558398a36d3682ede6603c2c6511896e9f9", - "logsBloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +{ + "request": "{ transaction(hash: \"0x812742182a79a8e67733edc58cfa3767aa2d7ad06439d156ddbbb33e3403b4ed\") {block{hash logsBloom} hash createdContract{address} cumulativeGasUsed gas gasUsed logs{topics} from{address} to{address} index } }", + "response": { + "data": { + "transaction": { + "block": { + "hash": "0x10aaf14a53caf27552325374429d3558398a36d3682ede6603c2c6511896e9f9", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" }, - "hash" : "0x812742182a79a8e67733edc58cfa3767aa2d7ad06439d156ddbbb33e3403b4ed", - "createdContract" : { - "address":"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f" + "hash": "0x812742182a79a8e67733edc58cfa3767aa2d7ad06439d156ddbbb33e3403b4ed", + "createdContract": { + "address": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f" }, - "cumulativeGasUsed" : 493172, - "gas" : 3141592, - "gasUsed" : 493172, - "logs" : [ ], - "from" : { - "address" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + "cumulativeGasUsed": "0x78674", + "gas": "0x2fefd8", + "gasUsed": "0x78674", + "logs": [], + "from": { + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" }, - "to" : null, - "index" : 0 + "to": null, + "index": "0x0" } } }, - "statusCode": 200 } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byBlockHashAndIndex.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byBlockHashAndIndex.json index 50c82e95365..649015ff2c7 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byBlockHashAndIndex.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byBlockHashAndIndex.json @@ -1,20 +1,16 @@ { - "request": - - "{ block(hash: \"0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6\") { transactionAt(index: 0) {block{hash} hash } } }", - - "response":{ - "data" : { - "block" : { - "transactionAt" : { - "block" : { - "hash" : "0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6" + "request": "{ block(hash: \"0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6\") { transactionAt(index: 0) {block{hash} hash } } }", + "response": { + "data": { + "block": { + "transactionAt": { + "block": { + "hash": "0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6" }, - "hash" : "0x9cc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4" + "hash": "0x9cc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4" } } } }, - "statusCode": 200 } \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byBlockNumberAndIndex.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byBlockNumberAndIndex.json index 84f8b19b323..c6cfbfcf7ec 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byBlockNumberAndIndex.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byBlockNumberAndIndex.json @@ -1,20 +1,16 @@ { - "request": - - "{ block(number: \"0x1e\") { transactionAt(index: 0) {block{hash} hash} } }", - - "response":{ - "data" : { - "block" : { - "transactionAt" : { - "block" : { - "hash" : "0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6" + "request": "{ block(number: \"0x1e\") { transactionAt(index: 0) {block{hash} hash} } }", + "response": { + "data": { + "block": { + "transactionAt": { + "block": { + "hash": "0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6" }, - "hash" : "0x9cc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4" + "hash": "0x9cc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4" } } } }, - "statusCode": 200 } \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byBlockNumberAndInvalidIndex.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byBlockNumberAndInvalidIndex.json index b15fe8df6d6..1fd7694f7db 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byBlockNumberAndInvalidIndex.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byBlockNumberAndInvalidIndex.json @@ -1,12 +1,9 @@ { - "request": - - "{ block(number: \"0x1e\") { transactionAt(index: 1) {block{hash} hash} } }", - - "response":{ - "data" : { - "block" : { - "transactionAt" : null + "request": "{ block(number: \"0x1e\") { transactionAt(index: 1) {block{hash} hash} } }", + "response": { + "data": { + "block": { + "transactionAt": null } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byHash.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byHash.json index 307a94cdd3a..63623394019 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byHash.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byHash.json @@ -1,30 +1,31 @@ { - "request": - "{transaction (hash : \"0x9cc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4\") { block{hash} gas gasPrice hash inputData nonce index value from {address} to {address} logs{index} status createdContract{address} } } ", - "response": { - "data" : { - "transaction" : { - "block" : { - "hash" : "0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6" + "request": "{transaction (hash : \"0x9cc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4\") { block{hash} gas gasPrice hash inputData nonce index value from {address} to {address} logs{index} status createdContract{address} } } ", + "response": { + "data": { + "transaction": { + "block": { + "hash": "0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6" }, - "gas" : 314159, - "gasPrice" : "0x1", - "hash" : "0x9cc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4", - "inputData" : "0xe8beef5b", - "nonce" : 29, - "index" : 0, - "value" : "0xa", - "from" : { - "address" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + "gas": "0x4cb2f", + "gasPrice": "0x1", + "hash": "0x9cc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4", + "inputData": "0xe8beef5b", + "nonce": "0x1d", + "index": "0x0", + "value": "0xa", + "from": { + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" }, - "to" : { - "address" : "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f" + "to": { + "address": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f" }, - "logs" : [ { - "index" : 0 - } ], - "status" : null, - "createdContract" : null + "logs": [ + { + "index": "0x0" + } + ], + "status": null, + "createdContract": null } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byHashNull.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byHashNull.json index d7386982f4a..85fcda84846 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byHashNull.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_byHashNull.json @@ -1,12 +1,8 @@ { - "request": - - "{transaction (hash : \"0xffc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4\") { block{hash} gas gasPrice hash inputData nonce index value }} ", - - + "request": "{transaction (hash : \"0xffc6c7e602c56aa30c554bb691377f8703d778cec8845f4b88c0f72516b304f4\") { block{hash} gas gasPrice hash inputData nonce index value }} ", "response": { - "data" : { - "transaction" : null + "data": { + "transaction": null } }, "statusCode": 200 diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json index b910e159cc6..d88f5f51554 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json @@ -3,15 +3,19 @@ "response": { "data": { "transaction": { - "accessList": [{ - "address": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f", - "storageKeys": ["0x0000000000000000000000000000000000000000000000000000000000000000"] - }], + "accessList": [ + { + "address": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + } + ], "maxFeePerGas": "0xb2d05e00", "maxPriorityFeePerGas": "0x3b9aca00", - "nonce": 32, - "type": 2, - "status": 1 + "nonce": "0x20", + "type": "0x2", + "status": "0x1" } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_sendRawTransaction_contractCreation.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_sendRawTransaction_contractCreation.json index 12370766ba0..dfa916e71c5 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_sendRawTransaction_contractCreation.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_sendRawTransaction_contractCreation.json @@ -1,8 +1,8 @@ { - "request" : "mutation { sendRawTransaction(data: \"0xf901ca0685174876e800830fffff8080b90177608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb00291ca00297f7489c9e70447d917f7069a145c9fd0543633bec0a17ac072f1e07ab7f24a0185bd6435c17603b85fd84b8b45605988e855238fe2bbc6ea1f7e9ee6a5fc15f\") }", - "response":{ - "data" : { - "sendRawTransaction" : "0x84df486b376e7eaf35792d710fc38ce110e62ab9cdb73a45d191da74c2190617" + "request": "mutation { sendRawTransaction(data: \"0xf901ca0685174876e800830fffff8080b90177608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb00291ca00297f7489c9e70447d917f7069a145c9fd0543633bec0a17ac072f1e07ab7f24a0185bd6435c17603b85fd84b8b45605988e855238fe2bbc6ea1f7e9ee6a5fc15f\") }", + "response": { + "data": { + "sendRawTransaction": "0x84df486b376e7eaf35792d710fc38ce110e62ab9cdb73a45d191da74c2190617" } }, "statusCode": 200 diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_sendRawTransaction_messageCall.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_sendRawTransaction_messageCall.json index 3ef2372b3f8..cccd1cd4d56 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_sendRawTransaction_messageCall.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_sendRawTransaction_messageCall.json @@ -1,10 +1,9 @@ { - "request" : "mutation { sendRawTransaction(data: \"0xf8690885174876e800830fffff94450b61224a7df4d8a70f3e20d4fd6a6380b920d180843bdab8bf1ba0efcd6b9df2054a4e8599c0967f8e1e45bca79e2998ed7e8bafb4d29aba7dd5c2a01097184ba24f20dc097f1915fbb5f6ac955bbfc014f181df4d80bf04f4a1cfa5\") }", - "response":{ - "data" : { - "sendRawTransaction" : "0xaa6e6646456c576edcd712dbb3f30bf46c3d8310b203960c1e675534553b2daf" + "request": "mutation { sendRawTransaction(data: \"0xf8690885174876e800830fffff94450b61224a7df4d8a70f3e20d4fd6a6380b920d180843bdab8bf1ba0efcd6b9df2054a4e8599c0967f8e1e45bca79e2998ed7e8bafb4d29aba7dd5c2a01097184ba24f20dc097f1915fbb5f6ac955bbfc014f181df4d80bf04f4a1cfa5\") }", + "response": { + "data": { + "sendRawTransaction": "0xaa6e6646456c576edcd712dbb3f30bf46c3d8310b203960c1e675534553b2daf" } }, - "statusCode": 200 } \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_sendRawTransaction_transferEther.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_sendRawTransaction_transferEther.json index 4b19d37e46c..df0ffba5ec7 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_sendRawTransaction_transferEther.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_sendRawTransaction_transferEther.json @@ -1,8 +1,8 @@ { - "request" : "mutation { sendRawTransaction(data: \"0xf86d0485174876e800830222e0945aae326516b4f8fe08074b7e972e40a713048d62880de0b6b3a7640000801ba05d4e7998757264daab67df2ce6f7e7a0ae36910778a406ca73898c9899a32b9ea0674700d5c3d1d27f2e6b4469957dfd1a1c49bf92383d80717afc84eb05695d5b\") }", - "response":{ - "data" : { - "sendRawTransaction" : "0xbaabcc1bd699e7378451e4ce5969edb9bdcae76cb79bdacae793525c31e423c7" + "request": "mutation { sendRawTransaction(data: \"0xf86d0485174876e800830222e0945aae326516b4f8fe08074b7e972e40a713048d62880de0b6b3a7640000801ba05d4e7998757264daab67df2ce6f7e7a0ae36910778a406ca73898c9899a32b9ea0674700d5c3d1d27f2e6b4469957dfd1a1c49bf92383d80717afc84eb05695d5b\") }", + "response": { + "data": { + "sendRawTransaction": "0xbaabcc1bd699e7378451e4ce5969edb9bdcae76cb79bdacae793525c31e423c7" } }, "statusCode": 200 diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_syncing.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_syncing.json index b1f420a0b64..8bc752caa36 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_syncing.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_syncing.json @@ -1,13 +1,11 @@ { - "request": - "{ syncing {startingBlock currentBlock highestBlock } }", - + "request": "{ syncing {startingBlock currentBlock highestBlock } }", "response": { - "data" : { - "syncing" : { - "startingBlock" : 1, - "currentBlock" : 2, - "highestBlock" : 3 + "data": { + "syncing": { + "startingBlock": "0x1", + "currentBlock": "0x2", + "highestBlock": "0x3" } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byFrom.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byFrom.json index 7ba8b74a41c..800542adbc0 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byFrom.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byFrom.json @@ -4,16 +4,16 @@ "data": { "blocks": [ { - "number": 30 + "number": "0x1e" }, { - "number": 31 + "number": "0x1f" }, { - "number": 32 + "number": "0x20" }, { - "number": 33 + "number": "0x21" } ] } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byRange.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byRange.json index 10f3e100224..b61f27e85ae 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byRange.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_blocks_byRange.json @@ -1,39 +1,39 @@ { - "request": - - "{blocks (from : \"0x1e\", to: \"0x20\") { number gasUsed gasLimit hash nonce stateRoot receiptsRoot transactionCount }} ", - - - "response":{ - "data" : { - "blocks" : [ { - "number" : 30, - "gasUsed" : 23585, - "gasLimit" : 3141592, - "hash" : "0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6", - "nonce" : "0x5c321bd9e9f040f1", - "stateRoot" : "0xdb46d6bb168130fe2cb60b4b24346137b5741f11283e0d7edace65c5f5466b2e", - "receiptsRoot" : "0x88b3b304b058b39791c26fdb94a05cc16ce67cf8f84f7348cb3c60c0ff342d0d", - "transactionCount" : 1 - }, { - "number" : 31, - "gasUsed" : 24303, - "gasLimit" : 3141592, - "hash" : "0x0f765087745aa259d9e5ac39c367c57432a16ed98e3b0d81c5b51d10f301dc49", - "nonce" : "0xd3a27a3001616468", - "stateRoot" : "0xa80997cf804269d64f2479baf535cf8f9090b70fbf515741c6995564f1e678bd", - "receiptsRoot" : "0x2440c44a3f75ad8b0425a73e7be2f61a5171112465cfd14e62e735b56d7178e6", - "transactionCount" : 1 - }, { - "number" : 32, - "gasUsed" : 23705, - "gasLimit" : 3141592, - "hash" : "0x71d59849ddd98543bdfbe8548f5eed559b07b8aaf196369f39134500eab68e53", - "nonce" : "0xdb063000b00e8026", - "stateRoot" : "0xf65f3dd13f72f5fa5607a5224691419969b4f4bae7a00a6cdb853f2ca9eeb1be", - "receiptsRoot" : "0xa50a7e67e833f4502524371ee462ccbcc6c6cabd2aeb1555c56150007a53183c", - "transactionCount" : 1 - } ] + "request": "{blocks (from : \"0x1e\", to: \"0x20\") { number gasUsed gasLimit hash nonce stateRoot receiptsRoot transactionCount }} ", + "response": { + "data": { + "blocks": [ + { + "number": "0x1e", + "gasUsed": "0x5c21", + "gasLimit": "0x2fefd8", + "hash": "0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6", + "nonce": "0x5c321bd9e9f040f1", + "stateRoot": "0xdb46d6bb168130fe2cb60b4b24346137b5741f11283e0d7edace65c5f5466b2e", + "receiptsRoot": "0x88b3b304b058b39791c26fdb94a05cc16ce67cf8f84f7348cb3c60c0ff342d0d", + "transactionCount": "0x1" + }, + { + "number": "0x1f", + "gasUsed": "0x5eef", + "gasLimit": "0x2fefd8", + "hash": "0x0f765087745aa259d9e5ac39c367c57432a16ed98e3b0d81c5b51d10f301dc49", + "nonce": "0xd3a27a3001616468", + "stateRoot": "0xa80997cf804269d64f2479baf535cf8f9090b70fbf515741c6995564f1e678bd", + "receiptsRoot": "0x2440c44a3f75ad8b0425a73e7be2f61a5171112465cfd14e62e735b56d7178e6", + "transactionCount": "0x1" + }, + { + "number": "0x20", + "gasUsed": "0x5c99", + "gasLimit": "0x2fefd8", + "hash": "0x71d59849ddd98543bdfbe8548f5eed559b07b8aaf196369f39134500eab68e53", + "nonce": "0xdb063000b00e8026", + "stateRoot": "0xf65f3dd13f72f5fa5607a5224691419969b4f4bae7a00a6cdb853f2ca9eeb1be", + "receiptsRoot": "0xa50a7e67e833f4502524371ee462ccbcc6c6cabd2aeb1555c56150007a53183c", + "transactionCount": "0x1" + } + ] } }, "statusCode": 200 diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_pending.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_pending.json index c12410e10af..e4a13259d10 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_pending.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_pending.json @@ -1,24 +1,22 @@ { - "request": - "{ pending { transactionCount transactions { nonce gas } account(address:\"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { balance} estimateGas(data:{}) call (data : {from : \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"0x12a7b914\"}){data status}} }", - + "request": "{ pending { transactionCount transactions { nonce gas } account(address:\"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { balance} estimateGas(data:{}) call (data : {from : \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"0x12a7b914\"}){data status}} }", "response": { "data": { "pending": { - "transactionCount": 0, + "transactionCount": "0x0", "transactions": [ { - "nonce": 42, - "gas": 654321 + "nonce": "0x2a", + "gas": "0x9fbf1" } ], "account": { "balance": "0x140" }, - "estimateGas": 53000, + "estimateGas": "0xcf08", "call": { "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "status": 1 + "status": "0x1" } } } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_variable_bytes.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_variable_bytes.json index c65dc75e41c..a5d0a0d2676 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_variable_bytes.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_variable_bytes.json @@ -1,9 +1,9 @@ { - "variables" : "{ \"data\": \"0xf86d0485174876e800830222e0945aae326516b4f8fe08074b7e972e40a713048d62880de0b6b3a7640000801ba05d4e7998757264daab67df2ce6f7e7a0ae36910778a406ca73898c9899a32b9ea0674700d5c3d1d27f2e6b4469957dfd1a1c49bf92383d80717afc84eb05695d5b\"}", - "request" : "mutation postTransaction($data: Bytes!) { sendRawTransaction(data: $data) }", - "response":{ - "data" : { - "sendRawTransaction" : "0xbaabcc1bd699e7378451e4ce5969edb9bdcae76cb79bdacae793525c31e423c7" + "variables": "{ \"data\": \"0xf86d0485174876e800830222e0945aae326516b4f8fe08074b7e972e40a713048d62880de0b6b3a7640000801ba05d4e7998757264daab67df2ce6f7e7a0ae36910778a406ca73898c9899a32b9ea0674700d5c3d1d27f2e6b4469957dfd1a1c49bf92383d80717afc84eb05695d5b\"}", + "request": "mutation postTransaction($data: Bytes!) { sendRawTransaction(data: $data) }", + "response": { + "data": { + "sendRawTransaction": "0xbaabcc1bd699e7378451e4ce5969edb9bdcae76cb79bdacae793525c31e423c7" } }, "statusCode": 200 diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_variable_bytes32.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_variable_bytes32.json index 1512cbdc402..80ea297f164 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_variable_bytes32.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_variable_bytes32.json @@ -4,7 +4,7 @@ "response": { "data": { "block": { - "number": 30 + "number": "0x1e" } } }, From b612ee29d1d03de1bb55d6fac0411ebbef1840a8 Mon Sep 17 00:00:00 2001 From: garyschulte Date: Tue, 30 May 2023 13:08:23 -0700 Subject: [PATCH 09/35] Log worldstate availability (#5517) * log mods for investigation of blockchain queries Signed-off-by: garyschulte * remove additional debug logging from log4j2.xml Signed-off-by: garyschulte --------- Signed-off-by: garyschulte --- .../ethereum/api/query/BlockchainQueries.java | 4 ++ .../cache/CachedWorldStorageManager.java | 17 +++++++++ ...nsaiSnapshotWorldStateKeyValueStorage.java | 37 ++++++++++++------- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java index 7a636c94e87..96e01fdb1b2 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java @@ -875,6 +875,10 @@ public Optional getAndMapWorldState( } catch (Exception ex) { LOG.error("failed worldstate query for " + blockHash.toShortHexString(), ex); } + LOG.atDebug() + .setMessage("Failed to find worldstate for {}") + .addArgument(blockHeader.toLogString()) + .log(); return Optional.empty(); }); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/cache/CachedWorldStorageManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/cache/CachedWorldStorageManager.java index 7dbf701724b..5ade72748d6 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/cache/CachedWorldStorageManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/cache/CachedWorldStorageManager.java @@ -143,17 +143,32 @@ public Optional getWorldState(final Hash blockHash) { new BonsaiWorldState( archive, new BonsaiWorldStateLayerStorage(cached.getWorldStateStorage()))); } + LOG.atDebug() + .setMessage("did not find worldstate in cache for {}") + .addArgument(blockHash.toShortHexString()) + .log(); + return Optional.empty(); } @Override public Optional getNearestWorldState(final BlockHeader blockHeader) { + LOG.atDebug() + .setMessage("getting nearest worldstate for {}") + .addArgument(blockHeader.toLogString()) + .log(); + return Optional.ofNullable( cachedWorldStatesByHash.get(blockHeader.getParentHash())) // search parent block .map(CachedBonsaiWorldView::getWorldStateStorage) .or( () -> { // or else search the nearest state in the cache + LOG.atDebug() + .setMessage("searching cache for nearest worldstate for {}") + .addArgument(blockHeader.toLogString()) + .log(); + final List cachedBonsaiWorldViews = new ArrayList<>(cachedWorldStatesByHash.values()); return cachedBonsaiWorldViews.stream() @@ -173,6 +188,8 @@ public Optional getNearestWorldState(final BlockHeader blockHe public Optional getHeadWorldState( final Function> hashBlockHeaderFunction) { + LOG.atDebug().setMessage("getting head worldstate").log(); + return rootWorldStateStorage .getWorldStateBlockHash() .flatMap(hashBlockHeaderFunction) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java index 978d3712e4a..c2627d72e40 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java @@ -29,12 +29,15 @@ import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKeyValueStorage implements BonsaiStorageSubscriber { protected final BonsaiWorldStateKeyValueStorage parentWorldStateStorage; - + private static final Logger LOG = + LoggerFactory.getLogger(BonsaiSnapshotWorldStateKeyValueStorage.class); private final long subscribeParentId; public BonsaiSnapshotWorldStateKeyValueStorage( @@ -69,6 +72,14 @@ public BonsaiSnapshotWorldStateKeyValueStorage( metricsSystem); } + private boolean isClosedGet() { + if (isClosed.get()) { + Throwable t = new Throwable("Attempting to access closed worldstate"); + LOG.warn(t.getMessage(), t); + } + return isClosed.get(); + } + @Override public BonsaiUpdater updater() { return new Updater( @@ -81,51 +92,51 @@ public BonsaiUpdater updater() { @Override public Optional getAccount(final Hash accountHash) { - return isClosed.get() ? Optional.empty() : super.getAccount(accountHash); + return isClosedGet() ? Optional.empty() : super.getAccount(accountHash); } @Override public Optional getCode(final Bytes32 codeHash, final Hash accountHash) { - return isClosed.get() ? Optional.empty() : super.getCode(codeHash, accountHash); + return isClosedGet() ? Optional.empty() : super.getCode(codeHash, accountHash); } @Override public Optional getAccountStateTrieNode(final Bytes location, final Bytes32 nodeHash) { - return isClosed.get() ? Optional.empty() : super.getAccountStateTrieNode(location, nodeHash); + return isClosedGet() ? Optional.empty() : super.getAccountStateTrieNode(location, nodeHash); } @Override public Optional getAccountStorageTrieNode( final Hash accountHash, final Bytes location, final Bytes32 nodeHash) { - return isClosed.get() + return isClosedGet() ? Optional.empty() : super.getAccountStorageTrieNode(accountHash, location, nodeHash); } @Override public Optional getTrieLog(final Hash blockHash) { - return isClosed.get() ? Optional.empty() : super.getTrieLog(blockHash); + return isClosedGet() ? Optional.empty() : super.getTrieLog(blockHash); } @Override public Optional getStateTrieNode(final Bytes location) { - return isClosed.get() ? Optional.empty() : super.getStateTrieNode(location); + return isClosedGet() ? Optional.empty() : super.getStateTrieNode(location); } @Override public Optional getWorldStateRootHash() { - return isClosed.get() ? Optional.empty() : super.getWorldStateRootHash(); + return isClosedGet() ? Optional.empty() : super.getWorldStateRootHash(); } @Override public Optional getWorldStateBlockHash() { - return isClosed.get() ? Optional.empty() : super.getWorldStateBlockHash(); + return isClosedGet() ? Optional.empty() : super.getWorldStateBlockHash(); } @Override public Optional getStorageValueByStorageSlotKey( final Hash accountHash, final StorageSlotKey storageSlotKey) { - return isClosed.get() + return isClosedGet() ? Optional.empty() : super.getStorageValueByStorageSlotKey(accountHash, storageSlotKey); } @@ -135,14 +146,14 @@ public Optional getStorageValueByStorageSlotKey( final Supplier> storageRootSupplier, final Hash accountHash, final StorageSlotKey storageSlotKey) { - return isClosed.get() + return isClosedGet() ? Optional.empty() : super.getStorageValueByStorageSlotKey(storageRootSupplier, accountHash, storageSlotKey); } @Override public boolean isWorldStateAvailable(final Bytes32 rootHash, final Hash blockHash) { - return !isClosed.get() && super.isWorldStateAvailable(rootHash, blockHash); + return !isClosedGet() && super.isWorldStateAvailable(rootHash, blockHash); } @Override @@ -205,7 +216,7 @@ public void onClearTrieLog() { @Override protected synchronized void doClose() throws Exception { - if (!isClosed.get()) { + if (!isClosedGet()) { // alert any subscribers we are closing: subscribers.forEach(BonsaiStorageSubscriber::onCloseStorage); From db410621b0b6c1e424bd92a6878a02cbd93f487a Mon Sep 17 00:00:00 2001 From: Sally MacFarlane Date: Wed, 31 May 2023 06:52:44 +1000 Subject: [PATCH 10/35] PR checklist - remove checkbox for non-mainnet ATs (#5514) * removed non-mainnetATs line Signed-off-by: Sally MacFarlane --------- Signed-off-by: Sally MacFarlane --- .github/workflows/pr-checklist-on-open.yml | 2 +- .../besu/ethereum/api/jsonrpc/internal/methods/EthCall.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-checklist-on-open.yml b/.github/workflows/pr-checklist-on-open.yml index e068d0147df..d89748a9437 100644 --- a/.github/workflows/pr-checklist-on-open.yml +++ b/.github/workflows/pr-checklist-on-open.yml @@ -16,5 +16,5 @@ jobs: issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, - body: '- [ ] I thought about documentation and added the `doc-change-required` label to this PR if [updates are required](https://wiki.hyperledger.org/display/BESU/Documentation).\n- [ ] I have considered running `./gradlew acceptanceTestNonMainnet` locally if my PR affects non-mainnet modules.\n- [ ] I thought about the changelog and included a [changelog update if required](https://wiki.hyperledger.org/display/BESU/Changelog).\n- [ ] If my PR includes database changes (e.g. KeyValueSegmentIdentifier) I have thought about compatibility and performed forwards and backwards compatibility tests' + body: '- [ ] I thought about documentation and added the `doc-change-required` label to this PR if [updates are required](https://wiki.hyperledger.org/display/BESU/Documentation).\n- [ ] I thought about the changelog and included a [changelog update if required](https://wiki.hyperledger.org/display/BESU/Changelog).\n- [ ] If my PR includes database changes (e.g. KeyValueSegmentIdentifier) I have thought about compatibility and performed forwards and backwards compatibility tests' }) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java index ee1a540f640..fe8550fc665 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java @@ -140,7 +140,7 @@ private TransactionValidationParams buildTransactionValidationParams( // be decided according to the provided parameters if (callParams.isMaybeStrict().isEmpty()) { transactionValidationParams.isAllowExceedingBalance( - isAllowExeedingBalanceAutoSelection(header, callParams)); + isAllowExceedingBalanceAutoSelection(header, callParams)); } else { transactionValidationParams.isAllowExceedingBalance( !callParams.isMaybeStrict().orElse(Boolean.FALSE)); @@ -148,7 +148,7 @@ private TransactionValidationParams buildTransactionValidationParams( return transactionValidationParams.build(); } - private boolean isAllowExeedingBalanceAutoSelection( + private boolean isAllowExceedingBalanceAutoSelection( final BlockHeader header, final JsonCallParameter callParams) { boolean isZeroGasPrice = From cb3e13450b04d90e63d7bd708b76dde1737991b4 Mon Sep 17 00:00:00 2001 From: George Tebrean <99179176+gtebrean@users.noreply.github.com> Date: Wed, 31 May 2023 00:11:19 +0300 Subject: [PATCH 11/35] refactor txpool options (#5512) * refactor txpool options * move options in BesuCommand Signed-off-by: George Tebrean --------- Signed-off-by: George Tebrean Co-authored-by: Sally MacFarlane --- CHANGELOG.md | 1 + .../org/hyperledger/besu/cli/BesuCommand.java | 52 +++++++- .../unstable/TransactionPoolOptions.java | 69 ---------- .../hyperledger/besu/cli/BesuCommandTest.java | 113 ++++++++++++++++ .../options/TransactionPoolOptionsTest.java | 125 ------------------ 5 files changed, 164 insertions(+), 196 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17bd4f09ee7..bc11f9f18f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Additions and Improvements - Allow Ethstats connection url to specify ws:// or wss:// scheme. [#5494](https://github.com/hyperledger/besu/issues/5494) - Add support for Shanghai changes to the GraphQL service [#5496](https://github.com/hyperledger/besu/pull/5496) +- Unite the tx-pool CLI options under the same Tx Pool Options group in UX. [#5466](https://github.com/hyperledger/besu/issues/5466) ### Bug Fixes diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 193ec5b2a81..8f6ad126dd3 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -46,6 +46,7 @@ import org.hyperledger.besu.chainimport.RlpBlockImporter; import org.hyperledger.besu.cli.config.EthNetworkConfig; import org.hyperledger.besu.cli.config.NetworkName; +import org.hyperledger.besu.cli.converter.FractionConverter; import org.hyperledger.besu.cli.converter.MetricCategoryConverter; import org.hyperledger.besu.cli.converter.PercentageConverter; import org.hyperledger.besu.cli.custom.CorsAllowedOriginsProperty; @@ -1202,6 +1203,42 @@ static class PermissionsOptionGroup { TxPoolOptionGroup txPoolOptionGroup = new TxPoolOptionGroup(); static class TxPoolOptionGroup { + @CommandLine.Option( + names = {"--tx-pool-disable-locals"}, + paramLabel = "", + description = + "Set to true if transactions sent via RPC should have the same checks and not be prioritized over remote ones (default: ${DEFAULT-VALUE})", + fallbackValue = "true", + arity = "0..1") + private Boolean disableLocalTxs = TransactionPoolConfiguration.DEFAULT_DISABLE_LOCAL_TXS; + + @CommandLine.Option( + names = {"--tx-pool-enable-save-restore"}, + paramLabel = "", + description = + "Set to true to enable saving the txpool content to file on shutdown and reloading it on startup (default: ${DEFAULT-VALUE})", + fallbackValue = "true", + arity = "0..1") + private Boolean saveRestoreEnabled = TransactionPoolConfiguration.DEFAULT_ENABLE_SAVE_RESTORE; + + @CommandLine.Option( + names = {"--tx-pool-limit-by-account-percentage"}, + paramLabel = "", + converter = FractionConverter.class, + description = + "Maximum portion of the transaction pool which a single account may occupy with future transactions (default: ${DEFAULT-VALUE})", + arity = "1") + private Float txPoolLimitByAccountPercentage = + TransactionPoolConfiguration.DEFAULT_LIMIT_TX_POOL_BY_ACCOUNT_PERCENTAGE; + + @CommandLine.Option( + names = {"--tx-pool-save-file"}, + paramLabel = "", + description = + "If saving the txpool content is enabled, define a custom path for the save file (default: ${DEFAULT-VALUE} in the data-dir)", + arity = "1") + private File saveFile = TransactionPoolConfiguration.DEFAULT_SAVE_FILE; + @Option( names = {"--tx-pool-max-size"}, paramLabel = MANDATORY_INTEGER_FORMAT_HELP, @@ -2935,17 +2972,28 @@ private SynchronizerConfiguration buildSyncConfig() { } private TransactionPoolConfiguration buildTransactionPoolConfiguration() { - final File saveFile = unstableTransactionPoolOptions.getSaveFile(); return unstableTransactionPoolOptions .toDomainObject() + .enableSaveRestore(txPoolOptionGroup.saveRestoreEnabled) + .disableLocalTransactions(txPoolOptionGroup.disableLocalTxs) + .txPoolLimitByAccountPercentage(txPoolOptionGroup.txPoolLimitByAccountPercentage) .txPoolMaxSize(txPoolOptionGroup.txPoolMaxSize) .pendingTxRetentionPeriod(txPoolOptionGroup.pendingTxRetentionPeriod) .priceBump(Percentage.fromInt(txPoolOptionGroup.priceBump)) .txFeeCap(txFeeCap) - .saveFile(dataPath.resolve(saveFile.getPath()).toFile()) + .saveFile(dataPath.resolve(txPoolOptionGroup.saveFile.getPath()).toFile()) .build(); } + /** + * Return the file where to save txpool content if the relative option is enabled. + * + * @return the save file + */ + public File getSaveFile() { + return txPoolOptionGroup.saveFile; + } + private boolean isPruningEnabled() { return pruningEnabled; } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/TransactionPoolOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/TransactionPoolOptions.java index a6fdd55f849..e199966c25f 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/TransactionPoolOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/TransactionPoolOptions.java @@ -14,13 +14,11 @@ */ package org.hyperledger.besu.cli.options.unstable; -import org.hyperledger.besu.cli.converter.FractionConverter; import org.hyperledger.besu.cli.options.CLIOptions; import org.hyperledger.besu.cli.options.OptionParser; import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; -import java.io.File; import java.time.Duration; import java.util.Arrays; import java.util.List; @@ -43,14 +41,6 @@ public class TransactionPoolOptions private static final String STRICT_TX_REPLAY_PROTECTION_ENABLED_FLAG = "--strict-tx-replay-protection-enabled"; - private static final String TX_POOL_LIMIT_BY_ACCOUNT_PERCENTAGE = - "--tx-pool-limit-by-account-percentage"; - - private static final String DISABLE_LOCAL_TXS_FLAG = "--tx-pool-disable-locals"; - - private static final String SAVE_RESTORE_FLAG = "--tx-pool-enable-save-restore"; - private static final String SAVE_FILE = "--tx-pool-save-file"; - private static final String LAYERED_TX_POOL_ENABLED_FLAG = "--Xlayered-tx-pool"; private static final String LAYERED_TX_POOL_LAYER_MAX_CAPACITY = "--Xlayered-tx-pool-layer-max-capacity"; @@ -88,16 +78,6 @@ public class TransactionPoolOptions private long eth65TrxAnnouncedBufferingPeriod = TransactionPoolConfiguration.ETH65_TRX_ANNOUNCED_BUFFERING_PERIOD.toMillis(); - @CommandLine.Option( - names = {TX_POOL_LIMIT_BY_ACCOUNT_PERCENTAGE}, - paramLabel = "", - converter = FractionConverter.class, - description = - "Maximum portion of the transaction pool which a single account may occupy with future transactions (default: ${DEFAULT-VALUE})", - arity = "1") - private Float txPoolLimitByAccountPercentage = - TransactionPoolConfiguration.DEFAULT_LIMIT_TX_POOL_BY_ACCOUNT_PERCENTAGE; - @CommandLine.Option( names = {LAYERED_TX_POOL_ENABLED_FLAG}, paramLabel = "", @@ -137,32 +117,6 @@ public class TransactionPoolOptions private int layeredTxPoolMaxFutureBySender = TransactionPoolConfiguration.DEFAULT_MAX_FUTURE_BY_SENDER; - @CommandLine.Option( - names = {DISABLE_LOCAL_TXS_FLAG}, - paramLabel = "", - description = - "Set to true if transactions sent via RPC should have the same checks and not be prioritized over remote ones (default: ${DEFAULT-VALUE})", - fallbackValue = "true", - arity = "0..1") - private Boolean disableLocalTxs = TransactionPoolConfiguration.DEFAULT_DISABLE_LOCAL_TXS; - - @CommandLine.Option( - names = {SAVE_RESTORE_FLAG}, - paramLabel = "", - description = - "Set to true to enable saving the txpool content to file on shutdown and reloading it on startup (default: ${DEFAULT-VALUE})", - fallbackValue = "true", - arity = "0..1") - private Boolean saveRestoreEnabled = TransactionPoolConfiguration.DEFAULT_ENABLE_SAVE_RESTORE; - - @CommandLine.Option( - names = {SAVE_FILE}, - paramLabel = "", - description = - "If saving the txpool content is enabled, define a custom path for the save file (default: ${DEFAULT-VALUE} in the data-dir)", - arity = "1") - private File saveFile = TransactionPoolConfiguration.DEFAULT_SAVE_FILE; - private TransactionPoolOptions() {} /** @@ -186,10 +140,6 @@ public static TransactionPoolOptions fromConfig(final TransactionPoolConfigurati options.eth65TrxAnnouncedBufferingPeriod = config.getEth65TrxAnnouncedBufferingPeriod().toMillis(); options.strictTxReplayProtectionEnabled = config.getStrictTransactionReplayProtectionEnabled(); - options.txPoolLimitByAccountPercentage = config.getTxPoolLimitByAccountPercentage(); - options.disableLocalTxs = config.getDisableLocalTransactions(); - options.saveRestoreEnabled = config.getEnableSaveRestore(); - options.saveFile = config.getSaveFile(); options.layeredTxPoolEnabled = config.getLayeredTxPoolEnabled(); options.layeredTxPoolLayerMaxCapacity = config.getPendingTransactionsLayerMaxCapacityBytes(); options.layeredTxPoolMaxPrioritized = config.getMaxPrioritizedTransactions(); @@ -209,11 +159,6 @@ public ImmutableTransactionPoolConfiguration.Builder toDomainObject() { .strictTransactionReplayProtectionEnabled(strictTxReplayProtectionEnabled) .txMessageKeepAliveSeconds(txMessageKeepAliveSeconds) .eth65TrxAnnouncedBufferingPeriod(Duration.ofMillis(eth65TrxAnnouncedBufferingPeriod)) - .txPoolLimitByAccountPercentage(txPoolLimitByAccountPercentage) - .disableLocalTransactions(disableLocalTxs) - .enableSaveRestore(saveRestoreEnabled) - .saveFile(saveFile) - .txPoolLimitByAccountPercentage(txPoolLimitByAccountPercentage) .layeredTxPoolEnabled(layeredTxPoolEnabled) .pendingTransactionsLayerMaxCapacityBytes(layeredTxPoolLayerMaxCapacity) .maxPrioritizedTransactions(layeredTxPoolMaxPrioritized) @@ -224,11 +169,6 @@ public ImmutableTransactionPoolConfiguration.Builder toDomainObject() { public List getCLIOptions() { return Arrays.asList( STRICT_TX_REPLAY_PROTECTION_ENABLED_FLAG + "=" + strictTxReplayProtectionEnabled, - DISABLE_LOCAL_TXS_FLAG + "=" + disableLocalTxs, - SAVE_RESTORE_FLAG + "=" + saveRestoreEnabled, - SAVE_FILE + "=" + saveFile, - TX_POOL_LIMIT_BY_ACCOUNT_PERCENTAGE, - OptionParser.format(txPoolLimitByAccountPercentage), TX_MESSAGE_KEEP_ALIVE_SEC_FLAG, OptionParser.format(txMessageKeepAliveSeconds), ETH65_TX_ANNOUNCED_BUFFERING_PERIOD_FLAG, @@ -241,13 +181,4 @@ public List getCLIOptions() { LAYERED_TX_POOL_MAX_FUTURE_BY_SENDER, OptionParser.format(layeredTxPoolMaxFutureBySender)); } - - /** - * Return the file where to save txpool content if the relative option is enabled. - * - * @return the save file - */ - public File getSaveFile() { - return saveFile; - } } diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index 997af020a57..6bae8aa7150 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -61,6 +61,7 @@ import org.hyperledger.besu.BesuInfo; import org.hyperledger.besu.cli.config.EthNetworkConfig; +import org.hyperledger.besu.cli.options.unstable.TransactionPoolOptions; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.MergeConfigOptions; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; @@ -4569,6 +4570,118 @@ public void errorIsRaisedIfStaticNodesAreNotAllowed() throws IOException { .contains(staticNodeURI.toString(), "not in nodes-allowlist"); } + @Test + public void disableLocalsDefault() { + parseCommand(); + verify(mockControllerBuilder) + .transactionPoolConfiguration(transactionPoolConfigCaptor.capture()); + assertThat(transactionPoolConfigCaptor.getValue().getDisableLocalTransactions()).isFalse(); + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + + @Test + public void disableLocalsOn() { + parseCommand("--tx-pool-disable-locals=true"); + + verify(mockControllerBuilder) + .transactionPoolConfiguration(transactionPoolConfigCaptor.capture()); + assertThat(transactionPoolConfigCaptor.getValue().getDisableLocalTransactions()).isTrue(); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + + @Test + public void disableLocalsOff() { + parseCommand("--tx-pool-disable-locals=false"); + + verify(mockControllerBuilder) + .transactionPoolConfiguration(transactionPoolConfigCaptor.capture()); + assertThat(transactionPoolConfigCaptor.getValue().getDisableLocalTransactions()).isFalse(); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + + @Test + public void saveToFileDisabledByDefault() { + parseCommand(); + verify(mockControllerBuilder) + .transactionPoolConfiguration(transactionPoolConfigCaptor.capture()); + assertThat(transactionPoolConfigCaptor.getValue().getEnableSaveRestore()).isFalse(); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + + @Test + public void saveToFileEnabledDefaultPath() { + parseCommand("--tx-pool-enable-save-restore=true"); + + verify(mockControllerBuilder) + .transactionPoolConfiguration(transactionPoolConfigCaptor.capture()); + assertThat(transactionPoolConfigCaptor.getValue().getEnableSaveRestore()).isTrue(); + assertThat(transactionPoolConfigCaptor.getValue().getSaveFile()) + .hasName(TransactionPoolConfiguration.DEFAULT_SAVE_FILE_NAME); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + + @Test + public void saveToFileEnabledCustomPath() { + parseCommand("--tx-pool-enable-save-restore=true", "--tx-pool-save-file=my.save.file"); + + verify(mockControllerBuilder) + .transactionPoolConfiguration(transactionPoolConfigCaptor.capture()); + assertThat(transactionPoolConfigCaptor.getValue().getEnableSaveRestore()).isTrue(); + assertThat(transactionPoolConfigCaptor.getValue().getSaveFile()).hasName("my.save.file"); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + + @Test + public void senderLimitedTxPool_derived() { + parseCommand("--tx-pool-limit-by-account-percentage=0.002"); + + verify(mockControllerBuilder) + .transactionPoolConfiguration(transactionPoolConfigCaptor.capture()); + assertThat(transactionPoolConfigCaptor.getValue().getTxPoolMaxFutureTransactionByAccount()) + .isEqualTo(9); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + + @Test + public void senderLimitedTxPoolFloor_derived() { + parseCommand("--tx-pool-limit-by-account-percentage=0.0001"); + + verify(mockControllerBuilder) + .transactionPoolConfiguration(transactionPoolConfigCaptor.capture()); + assertThat(transactionPoolConfigCaptor.getValue().getTxPoolMaxFutureTransactionByAccount()) + .isEqualTo(1); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + + @Test + public void senderLimitedTxPoolCeiling_violated() { + TestBesuCommand commandTest = parseCommand("--tx-pool-limit-by-account-percentage=1.00002341"); + + TransactionPoolOptions txPoolOption = commandTest.getTransactionPoolOptions(); + + final TransactionPoolConfiguration config = txPoolOption.toDomainObject().build(); + assertThat(config.getTxPoolLimitByAccountPercentage()) + .isEqualTo(TransactionPoolConfiguration.DEFAULT_LIMIT_TX_POOL_BY_ACCOUNT_PERCENTAGE); + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)) + .contains("Invalid value for option '--tx-pool-limit-by-account-percentage'"); + } + @Test public void pendingTransactionRetentionPeriod() { final int pendingTxRetentionHours = 999; diff --git a/besu/src/test/java/org/hyperledger/besu/cli/options/TransactionPoolOptionsTest.java b/besu/src/test/java/org/hyperledger/besu/cli/options/TransactionPoolOptionsTest.java index 2f44c2d145e..5a235524c6a 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/options/TransactionPoolOptionsTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/options/TransactionPoolOptionsTest.java @@ -16,13 +16,11 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration.DEFAULT_LIMIT_TX_POOL_BY_ACCOUNT_PERCENTAGE; import org.hyperledger.besu.cli.options.unstable.TransactionPoolOptions; import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; -import java.io.File; import java.time.Duration; import org.junit.Test; @@ -70,44 +68,6 @@ public void strictTxReplayProtection_disabled() { assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); } - @Test - public void senderLimitedTxPool_derived() { - final TestBesuCommand cmd = parseCommand("--tx-pool-limit-by-account-percentage=0.002"); - - final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd); - final TransactionPoolConfiguration config = options.toDomainObject().build(); - assertThat(config.getTxPoolMaxFutureTransactionByAccount()).isEqualTo(9); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - - @Test - public void senderLimitedTxPoolFloor_derived() { - final TestBesuCommand cmd = parseCommand("--tx-pool-limit-by-account-percentage=0.0001"); - - final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd); - final TransactionPoolConfiguration config = options.toDomainObject().build(); - assertThat(config.getTxPoolMaxFutureTransactionByAccount()).isEqualTo(1); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - - @Test - public void senderLimitedTxPoolCeiling_violated() { - final TestBesuCommand cmd = parseCommand("--tx-pool-limit-by-account-percentage=1.00002341"); - - final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd); - final TransactionPoolConfiguration config = options.toDomainObject().build(); - assertThat(config.getTxPoolLimitByAccountPercentage()) - .isEqualTo(DEFAULT_LIMIT_TX_POOL_BY_ACCOUNT_PERCENTAGE); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)) - .contains("Invalid value for option '--tx-pool-limit-by-account-percentage'"); - } - @Test public void strictTxReplayProtection_default() { final TestBesuCommand cmd = parseCommand(); @@ -153,81 +113,6 @@ public void eth65TrxAnnouncedBufferingPeriod() { assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); } - @Test - public void disableLocalsDefault() { - final TestBesuCommand cmd = parseCommand(); - - final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd); - final TransactionPoolConfiguration config = options.toDomainObject().build(); - assertThat(config.getDisableLocalTransactions()).isFalse(); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - - @Test - public void disableLocalsOn() { - final TestBesuCommand cmd = parseCommand("--tx-pool-disable-locals=true"); - - final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd); - final TransactionPoolConfiguration config = options.toDomainObject().build(); - assertThat(config.getDisableLocalTransactions()).isTrue(); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - - @Test - public void disableLocalsOff() { - final TestBesuCommand cmd = parseCommand("--tx-pool-disable-locals=false"); - - final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd); - final TransactionPoolConfiguration config = options.toDomainObject().build(); - assertThat(config.getDisableLocalTransactions()).isFalse(); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - - @Test - public void saveToFileDisabledByDefault() { - final TestBesuCommand cmd = parseCommand(); - - final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd); - final TransactionPoolConfiguration config = options.toDomainObject().build(); - assertThat(config.getEnableSaveRestore()).isFalse(); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - - @Test - public void saveToFileEnabledDefaultPath() { - final TestBesuCommand cmd = parseCommand("--tx-pool-enable-save-restore=true"); - - final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd); - final TransactionPoolConfiguration config = options.toDomainObject().build(); - assertThat(config.getEnableSaveRestore()).isTrue(); - assertThat(config.getSaveFile()).hasName(TransactionPoolConfiguration.DEFAULT_SAVE_FILE_NAME); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - - @Test - public void saveToFileEnabledCustomPath() { - final TestBesuCommand cmd = - parseCommand("--tx-pool-enable-save-restore=true", "--tx-pool-save-file=my.save.file"); - - final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd); - final TransactionPoolConfiguration config = options.toDomainObject().build(); - assertThat(config.getEnableSaveRestore()).isTrue(); - assertThat(config.getSaveFile()).hasName("my.save.file"); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - @Override ImmutableTransactionPoolConfiguration.Builder createDefaultDomainObject() { final ImmutableTransactionPoolConfiguration defaultValue = @@ -236,11 +121,6 @@ ImmutableTransactionPoolConfiguration.Builder createDefaultDomainObject() { .strictTransactionReplayProtectionEnabled(false) .txMessageKeepAliveSeconds(defaultValue.getTxMessageKeepAliveSeconds()) .eth65TrxAnnouncedBufferingPeriod(defaultValue.getEth65TrxAnnouncedBufferingPeriod()) - .txPoolLimitByAccountPercentage(defaultValue.getTxPoolLimitByAccountPercentage()) - .disableLocalTransactions(defaultValue.getDisableLocalTransactions()) - .enableSaveRestore(defaultValue.getEnableSaveRestore()) - .saveFile(defaultValue.getSaveFile()) - .txPoolLimitByAccountPercentage(defaultValue.getTxPoolLimitByAccountPercentage()) .layeredTxPoolEnabled(defaultValue.getLayeredTxPoolEnabled()) .pendingTransactionsLayerMaxCapacityBytes( defaultValue.getPendingTransactionsLayerMaxCapacityBytes()) @@ -256,11 +136,6 @@ ImmutableTransactionPoolConfiguration.Builder createCustomizedDomainObject() { .eth65TrxAnnouncedBufferingPeriod( TransactionPoolConfiguration.ETH65_TRX_ANNOUNCED_BUFFERING_PERIOD.plus( Duration.ofMillis(100))) - .txPoolLimitByAccountPercentage(0.5f) - .disableLocalTransactions(true) - .enableSaveRestore(true) - .saveFile(new File("abc.xyz")) - .txPoolLimitByAccountPercentage(0.5f) .layeredTxPoolEnabled(true) .pendingTransactionsLayerMaxCapacityBytes(1_000_000L) .maxPrioritizedTransactions(1000) From 5fe53cf95c636c02e02d42137d8391b602010b8f Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Wed, 31 May 2023 09:20:06 +0200 Subject: [PATCH 12/35] Stop evaluating txs for sender after the first skipped one (#5498) Signed-off-by: Fabio Di Fabio --- .../layered/LayeredPendingTransactions.java | 42 ++++++--- .../LayeredPendingTransactionsTest.java | 91 ++++++++++++++++--- 2 files changed, 107 insertions(+), 26 deletions(-) diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java index f9ed91e3a14..0a802a7dd7d 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java @@ -321,31 +321,24 @@ public synchronized void selectTransactions( final PendingTransactions.TransactionSelector selector) { final List invalidTransactions = new ArrayList<>(); final Set alreadyChecked = new HashSet<>(); + final Set
skipSenders = new HashSet<>(); final AtomicBoolean completed = new AtomicBoolean(false); prioritizedTransactions.stream() .takeWhile(unused -> !completed.get()) - .peek( - highPrioPendingTx -> - LOG.atTrace() - .setMessage("highPrioPendingTx {}, senderTxs {}") - .addArgument(highPrioPendingTx::toTraceLog) - .addArgument( - () -> - prioritizedTransactions.stream(highPrioPendingTx.getSender()) - .map(PendingTransaction::toTraceLog) - .collect(Collectors.joining(", "))) - .log()) + .filter(highPrioPendingTx -> !skipSenders.contains(highPrioPendingTx.getSender())) + .peek(this::logSenderTxs) .forEach( highPrioPendingTx -> prioritizedTransactions.stream(highPrioPendingTx.getSender()) - .takeWhile(unused -> !completed.get()) - .filter( + .takeWhile( candidatePendingTx -> - !alreadyChecked.contains(candidatePendingTx.getHash())) + !skipSenders.contains(candidatePendingTx.getSender()) + && !completed.get()) .filter( candidatePendingTx -> - candidatePendingTx.getNonce() <= highPrioPendingTx.getNonce()) + !alreadyChecked.contains(candidatePendingTx.getHash()) + && candidatePendingTx.getNonce() <= highPrioPendingTx.getNonce()) .forEach( candidatePendingTx -> { alreadyChecked.add(candidatePendingTx.getHash()); @@ -366,12 +359,31 @@ public synchronized void selectTransactions( if (res.stop()) { completed.set(true); } + + if (!res.selected()) { + // avoid processing other txs from this sender if this one is skipped + // since the following will not be selected due to the nonce gap + skipSenders.add(candidatePendingTx.getSender()); + LOG.trace("Skipping tx from sender {}", candidatePendingTx.getSender()); + } })); invalidTransactions.forEach( invalidTx -> prioritizedTransactions.remove(invalidTx, INVALIDATED)); } + private void logSenderTxs(final PendingTransaction highPrioPendingTx) { + LOG.atTrace() + .setMessage("highPrioPendingTx {}, senderTxs {}") + .addArgument(highPrioPendingTx::toTraceLog) + .addArgument( + () -> + prioritizedTransactions.stream(highPrioPendingTx.getSender()) + .map(PendingTransaction::toTraceLog) + .collect(Collectors.joining(", "))) + .log(); + } + @Override public long maxSize() { return -1; diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java index e4a27470935..294ddd7d0f0 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java @@ -19,10 +19,16 @@ import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.ALREADY_KNOWN; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.NONCE_TOO_FAR_IN_FUTURE_FOR_SENDER; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.REJECTED_UNDERPRICED_REPLACEMENT; +import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.BLOCK_FULL; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.BLOCK_OCCUPANCY_ABOVE_THRESHOLD; +import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.CURRENT_TX_PRICE_BELOW_MIN; +import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.DATA_PRICE_BELOW_CURRENT_MIN; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.SELECTED; +import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.TX_TOO_LARGE_FOR_REMAINING_GAS; import static org.hyperledger.besu.ethereum.eth.transactions.layered.TransactionsLayer.RemovalReason.DROPPED; import static org.hyperledger.besu.ethereum.eth.transactions.layered.TransactionsLayer.RemovalReason.REPLACED; +import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.GAS_PRICE_BELOW_CURRENT_BASE_FEE; +import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; @@ -43,7 +49,6 @@ import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolReplacementHandler; import org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; -import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; import org.hyperledger.besu.evm.account.Account; import java.util.ArrayList; @@ -51,9 +56,12 @@ import java.util.Optional; import java.util.OptionalLong; import java.util.function.BiFunction; +import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class LayeredPendingTransactionsTest extends BaseTransactionPoolTest { @@ -284,8 +292,10 @@ public void notNotifyListenerAfterUnsubscribe() { verifyNoMoreInteractions(listener); } - @Test - public void selectTransactionsUntilSelectorRequestsNoMore() { + @ParameterizedTest + @MethodSource + public void selectTransactionsUntilSelectorRequestsNoMore( + final TransactionSelectionResult selectionResult) { pendingTransactions.addRemoteTransaction(transaction0, Optional.empty()); pendingTransactions.addRemoteTransaction(transaction1, Optional.empty()); @@ -293,13 +303,17 @@ public void selectTransactionsUntilSelectorRequestsNoMore() { pendingTransactions.selectTransactions( transaction -> { parsedTransactions.add(transaction); - return BLOCK_OCCUPANCY_ABOVE_THRESHOLD; + return selectionResult; }); assertThat(parsedTransactions.size()).isEqualTo(1); assertThat(parsedTransactions.get(0)).isEqualTo(transaction0); } + static Stream selectTransactionsUntilSelectorRequestsNoMore() { + return Stream.of(BLOCK_OCCUPANCY_ABOVE_THRESHOLD, BLOCK_FULL); + } + @Test public void selectTransactionsUntilPendingIsEmpty() { pendingTransactions.addRemoteTransaction(transaction0, Optional.empty()); @@ -356,6 +370,42 @@ public void selectTransactionsFromSameSenderInNonceOrder() { assertThat(iterationOrder).containsExactly(transaction0, transaction1, transaction2); } + @ParameterizedTest + @MethodSource + public void ignoreSenderTransactionsAfterASkippedOne( + final TransactionSelectionResult skipSelectionResult) { + final Transaction transaction0a = createTransaction(0, Wei.of(20), KEYS1); + final Transaction transaction1a = createTransaction(1, Wei.of(20), KEYS1); + final Transaction transaction2a = createTransaction(2, Wei.of(20), KEYS1); + final Transaction transaction0b = createTransaction(0, Wei.of(10), KEYS2); + + pendingTransactions.addLocalTransaction(transaction0a, Optional.empty()); + pendingTransactions.addLocalTransaction(transaction1a, Optional.empty()); + pendingTransactions.addLocalTransaction(transaction2a, Optional.empty()); + pendingTransactions.addLocalTransaction(transaction0b, Optional.empty()); + + final List iterationOrder = new ArrayList<>(3); + pendingTransactions.selectTransactions( + transaction -> { + iterationOrder.add(transaction); + // pretending that the 2nd tx of the 1st sender is not selected + return transaction.getNonce() == 1 ? skipSelectionResult : SELECTED; + }); + + // the 3rd tx of the 1st must not be processed, since the 2nd is skipped + // but the 2nd sender must not be affected + assertThat(iterationOrder).containsExactly(transaction0a, transaction1a, transaction0b); + } + + static Stream ignoreSenderTransactionsAfterASkippedOne() { + return Stream.of( + CURRENT_TX_PRICE_BELOW_MIN, + DATA_PRICE_BELOW_CURRENT_MIN, + TX_TOO_LARGE_FOR_REMAINING_GAS, + TransactionSelectionResult.invalidTransient(GAS_PRICE_BELOW_CURRENT_BASE_FEE.name()), + TransactionSelectionResult.invalid(UPFRONT_COST_EXCEEDS_BALANCE.name())); + } + @Test public void notForceNonceOrderWhenSendersDiffer() { final Account sender2 = mock(Account.class); @@ -382,19 +432,38 @@ public void invalidTransactionIsDeletedFromPendingTransactions() { pendingTransactions.addRemoteTransaction(transaction0, Optional.empty()); pendingTransactions.addRemoteTransaction(transaction1, Optional.empty()); - final List parsedTransactions = new ArrayList<>(2); + final List parsedTransactions = new ArrayList<>(1); pendingTransactions.selectTransactions( transaction -> { parsedTransactions.add(transaction); - return TransactionSelectionResult.invalid( - TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE.name()); + return TransactionSelectionResult.invalid(UPFRONT_COST_EXCEEDS_BALANCE.name()); }); - assertThat(parsedTransactions.size()).isEqualTo(2); - assertThat(parsedTransactions.get(0)).isEqualTo(transaction0); - assertThat(parsedTransactions.get(1)).isEqualTo(transaction1); + // only the first is processed since not being selected will automatically skip the processing + // all the other txs from the same sender + + assertThat(parsedTransactions).containsExactly(transaction0); + assertThat(pendingTransactions.getPendingTransactions()) + .map(PendingTransaction::getTransaction) + .containsExactly(transaction1); + } - assertThat(pendingTransactions.size()).isZero(); + @Test + public void temporarilyInvalidTransactionIsKeptInPendingTransactions() { + pendingTransactions.addRemoteTransaction(transaction0, Optional.empty()); + + final List parsedTransactions = new ArrayList<>(1); + pendingTransactions.selectTransactions( + transaction -> { + parsedTransactions.add(transaction); + return TransactionSelectionResult.invalidTransient( + GAS_PRICE_BELOW_CURRENT_BASE_FEE.name()); + }); + + assertThat(parsedTransactions).containsExactly(transaction0); + assertThat(pendingTransactions.getPendingTransactions()) + .map(PendingTransaction::getTransaction) + .containsExactly(transaction0); } @Test From 890e8cde1496030f4786ab9a3531836fbfb79588 Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Thu, 1 Jun 2023 14:30:43 +1000 Subject: [PATCH 13/35] Make docker commands easier to debug during upload and manifest creation (#5522) - Print docker commands during upload and manifest creation - Separate out docker push and docker manifest push commands for release Signed-off-by: Simon Dudley --- build.gradle | 56 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index dccd40edd70..54a87bc5050 100644 --- a/build.gradle +++ b/build.gradle @@ -751,6 +751,7 @@ task dockerUpload { def archVariantImage = "${variantImage}-${architecture}" def cmd = "docker tag '${variantImage}' '${archVariantImage}' && docker push '${archVariantImage}'" additionalTags.each { tag -> cmd += " && docker tag '${variantImage}' '${dockerImageName}:${tag.trim()}-${variant}-${architecture}' && docker push '${dockerImageName}:${tag.trim()}-${variant}-${architecture}'" } + println "Executing '${cmd}'" executable "sh" args "-c", cmd } @@ -760,6 +761,7 @@ task dockerUpload { def archImage = "${image}-${architecture}" def cmd = "docker tag ${image} ${archImage} && docker push '${archImage}'" additionalTags.each { tag -> cmd += " && docker tag '${image}' '${dockerImageName}:${tag.trim()}-${architecture}' && docker push '${dockerImageName}:${tag.trim()}-${architecture}'" } + println "Executing '${cmd}'" executable "sh" args "-c", cmd } @@ -775,7 +777,14 @@ task dockerUploadRelease { for (def variant in dockerVariants) { def variantImage = "${image}-${variant}" exec { - def cmd = "docker pull '${variantImage}-${architecture}' && docker tag '${variantImage}-${architecture}' '${dockerImageName}:latest-${variant}-${architecture}' && docker push '${dockerImageName}:latest-${variant}-${architecture}'" + def cmd = "docker pull '${variantImage}-${architecture}' && docker tag '${variantImage}-${architecture}' '${dockerImageName}:latest-${variant}-${architecture}'" + println "Executing '${cmd}'" + executable "sh" + args "-c", cmd + } + exec { + def cmd = "docker push '${dockerImageName}:latest-${variant}-${architecture}'" + println "Executing '${cmd}'" executable "sh" args "-c", cmd } @@ -783,7 +792,14 @@ task dockerUploadRelease { exec { def archImage = "${image}-${architecture}" - def cmd = "docker pull '${archImage}' && docker tag ${archImage} '${dockerImageName}:latest-${architecture}' && docker push '${dockerImageName}:latest-${architecture}'" + def cmd = "docker pull '${archImage}' && docker tag ${archImage} '${dockerImageName}:latest-${architecture}'" + println "Executing '${cmd}'" + executable "sh" + args "-c", cmd + } + exec { + def cmd = "docker push '${dockerImageName}:latest-${architecture}'" + println "Executing '${cmd}'" executable "sh" args "-c", cmd } @@ -812,7 +828,14 @@ task manifestDocker { archs.forEach { arch -> targets += "'${variantImage}-${arch}' " } exec { - def cmd = "docker manifest create '${variantImage}' ${targets} && docker manifest push '${variantImage}'" + def cmd = "docker manifest create '${variantImage}' ${targets}" + println "Executing '${cmd}'" + executable "sh" + args "-c", cmd + } + exec { + def cmd = "docker manifest push '${variantImage}'" + println "Executing '${cmd}'" executable "sh" args "-c", cmd } @@ -821,7 +844,14 @@ task manifestDocker { exec { def targets = "" archs.forEach { arch -> targets += "'${baseTag}-${arch}' " } - def cmd = "docker manifest create '${baseTag}' ${targets} && docker manifest push '${baseTag}'" + def cmd = "docker manifest create '${baseTag}' ${targets}" + println "Executing '${cmd}'" + executable "sh" + args "-c", cmd + } + exec { + def cmd = "docker manifest push '${baseTag}'" + println "Executing '${cmd}'" executable "sh" args "-c", cmd } @@ -840,7 +870,14 @@ task manifestDockerRelease { archs.forEach { arch -> targets += "'${variantImage}-${arch}' " } exec { - def cmd = "docker manifest create '${variantImage}' ${targets} && docker manifest push '${variantImage}'" + def cmd = "docker manifest create '${variantImage}' ${targets}" + println "Executing '${cmd}'" + executable "sh" + args "-c", cmd + } + exec { + def cmd = "docker manifest push '${variantImage}'" + println "Executing '${cmd}'" executable "sh" args "-c", cmd } @@ -849,7 +886,14 @@ task manifestDockerRelease { exec { def targets = "" archs.forEach { arch -> targets += "'${baseTag}-${arch}' " } - def cmd = "docker manifest create '${baseTag}' ${targets} && docker manifest push '${baseTag}'" + def cmd = "docker manifest create '${baseTag}' ${targets}" + println "Executing '${cmd}'" + executable "sh" + args "-c", cmd + } + exec { + def cmd = "docker manifest push '${baseTag}'" + println "Executing '${cmd}'" executable "sh" args "-c", cmd } From 186d38b81d7d0947d0317e73e98cb4873c12a0d9 Mon Sep 17 00:00:00 2001 From: Sally MacFarlane Date: Fri, 2 Jun 2023 10:34:04 +1000 Subject: [PATCH 14/35] [MINOR] switch QBFT tests to Junit5 (#5525) * junit5 Signed-off-by: Sally MacFarlane * lenient mocking Signed-off-by: Sally MacFarlane * remove junit4 Signed-off-by: Sally MacFarlane --------- Signed-off-by: Sally MacFarlane --- consensus/qbft/build.gradle | 2 +- .../qbft/MutableQbftConfigOptionsTest.java | 2 +- ...ockHeaderValidationRulesetFactoryTest.java | 2 +- .../qbft/QbftExtraDataCodecTest.java | 2 +- .../qbft/QbftProtocolScheduleTest.java | 2 +- .../PkiQbftBlockCreatorTest.java | 6 ++--- .../QbftBlockCreatorFactoryTest.java | 6 ++--- .../QbftValidatorsValidationRuleTest.java | 2 +- .../methods/QbftDiscardValidatorVoteTest.java | 6 ++--- .../methods/QbftGetSignerMetricsTest.java | 6 ++--- .../QbftGetValidatorsByBlockHashTest.java | 12 ++++----- .../QbftGetValidatorsByBlockNumberTest.java | 12 ++++----- .../methods/QbftProposeValidatorVoteTest.java | 6 ++--- .../qbft/messagewrappers/CommitTest.java | 2 +- .../qbft/messagewrappers/PrepareTest.java | 2 +- .../qbft/messagewrappers/ProposalTest.java | 2 +- .../qbft/messagewrappers/RoundChangeTest.java | 2 +- .../qbft/payload/QbftPayloadTest.java | 2 +- .../DefaultKeyStoreWrapperProviderTest.java | 8 +++--- ...lockCreationConfigurationProviderTest.java | 8 +++--- .../qbft/pki/PkiQbftBlockHashingTest.java | 6 ++--- .../qbft/pki/PkiQbftExtraDataCodecTest.java | 2 +- .../protocol/Istanbul100SubProtocolTest.java | 2 +- .../QbftBlockHeightManagerTest.java | 15 ++++++----- .../qbft/statemachine/QbftControllerTest.java | 17 +++++++----- .../qbft/statemachine/QbftRoundTest.java | 15 ++++++----- .../qbft/statemachine/RoundStateTest.java | 12 ++++----- .../qbft/validation/CommitValidatorTest.java | 2 +- .../qbft/validation/PrepareValidatorTest.java | 2 +- .../ProposalPayloadValidatorTest.java | 12 ++++----- .../validation/ProposalValidatorTest.java | 14 +++++----- .../RoundChangeMessageValidatorTest.java | 12 ++++----- .../RoundChangePayloadValidatorTest.java | 2 +- .../ForkingValidatorProviderTest.java | 26 ++++++++++++------- .../QbftForksSchedulesFactoryTest.java | 2 +- .../TransactionValidatorProviderTest.java | 12 ++++----- .../ValidatorContractControllerTest.java | 6 ++--- .../ValidatorModeTransitionLoggerTest.java | 8 +++--- 38 files changed, 138 insertions(+), 121 deletions(-) diff --git a/consensus/qbft/build.gradle b/consensus/qbft/build.gradle index e2511ef3126..90e9a45deed 100644 --- a/consensus/qbft/build.gradle +++ b/consensus/qbft/build.gradle @@ -63,11 +63,11 @@ dependencies { testImplementation project(':metrics:core') testImplementation project(':testutil') - testImplementation 'junit:junit' testImplementation 'org.assertj:assertj-core' testImplementation 'org.awaitility:awaitility' testImplementation 'org.junit.jupiter:junit-jupiter' testImplementation 'org.mockito:mockito-core' + testImplementation 'org.mockito:mockito-junit-jupiter' testRuntimeOnly 'org.junit.vintage:junit-vintage-engine' diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/MutableQbftConfigOptionsTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/MutableQbftConfigOptionsTest.java index 8bf61d96a11..d41996d11db 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/MutableQbftConfigOptionsTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/MutableQbftConfigOptionsTest.java @@ -26,7 +26,7 @@ import java.util.Optional; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class MutableQbftConfigOptionsTest { diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactoryTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactoryTest.java index 8c310d9700d..8e7b1be6940 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactoryTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactoryTest.java @@ -36,7 +36,7 @@ import java.util.List; import java.util.Optional; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class QbftBlockHeaderValidationRulesetFactoryTest { diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftExtraDataCodecTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftExtraDataCodecTest.java index 7a7ca5ebee5..018f0f9113d 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftExtraDataCodecTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftExtraDataCodecTest.java @@ -40,7 +40,7 @@ import com.google.common.base.Suppliers; import com.google.common.collect.Lists; import org.apache.tuweni.bytes.Bytes; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class QbftExtraDataCodecTest { diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftProtocolScheduleTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftProtocolScheduleTest.java index e090b0e6501..bb91477f795 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftProtocolScheduleTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftProtocolScheduleTest.java @@ -44,7 +44,7 @@ import java.util.List; import java.util.Optional; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class QbftProtocolScheduleTest { private final BftExtraDataCodec bftExtraDataCodec = mock(BftExtraDataCodec.class); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/PkiQbftBlockCreatorTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/PkiQbftBlockCreatorTest.java index a36da3758f1..32d55e7f22e 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/PkiQbftBlockCreatorTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/PkiQbftBlockCreatorTest.java @@ -42,8 +42,8 @@ import java.util.Collections; import org.apache.tuweni.bytes.Bytes; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class PkiQbftBlockCreatorTest { @@ -54,7 +54,7 @@ public class PkiQbftBlockCreatorTest { private PkiQbftBlockCreator pkiQbftBlockCreator; private BlockHeaderTestFixture blockHeaderBuilder; - @Before + @BeforeEach public void before() { blockCreator = mock(BlockCreator.class); cmsCreator = mock(CmsCreator.class); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/QbftBlockCreatorFactoryTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/QbftBlockCreatorFactoryTest.java index 372b7668a99..e9345606963 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/QbftBlockCreatorFactoryTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/QbftBlockCreatorFactoryTest.java @@ -37,14 +37,14 @@ import java.util.Optional; import org.apache.tuweni.bytes.Bytes; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class QbftBlockCreatorFactoryTest { private final QbftExtraDataCodec extraDataCodec = new QbftExtraDataCodec(); private QbftBlockCreatorFactory qbftBlockCreatorFactory; - @Before + @BeforeEach @SuppressWarnings("unchecked") public void setUp() throws Exception { final MiningParameters miningParams = mock(MiningParameters.class); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/QbftValidatorsValidationRuleTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/QbftValidatorsValidationRuleTest.java index 105e94af024..b225348f7f6 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/QbftValidatorsValidationRuleTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/QbftValidatorsValidationRuleTest.java @@ -32,7 +32,7 @@ import java.util.Optional; import com.google.common.collect.Lists; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class QbftValidatorsValidationRuleTest { private final BftExtraData bftExtraData = mock(BftExtraData.class); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftDiscardValidatorVoteTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftDiscardValidatorVoteTest.java index c74f4132bfa..4e0c30dea7b 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftDiscardValidatorVoteTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftDiscardValidatorVoteTest.java @@ -33,8 +33,8 @@ import java.util.Optional; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class QbftDiscardValidatorVoteTest { private final ValidatorProvider validatorProvider = mock(ValidatorProvider.class); @@ -43,7 +43,7 @@ public class QbftDiscardValidatorVoteTest { private final String JSON_RPC_VERSION = "2.0"; private QbftDiscardValidatorVote method; - @Before + @BeforeEach public void setup() { method = new QbftDiscardValidatorVote(validatorProvider); when(validatorProvider.getVoteProviderAtHead()).thenReturn(Optional.of(voteProvider)); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftGetSignerMetricsTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftGetSignerMetricsTest.java index 343f4f1adf8..d070ba47cc3 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftGetSignerMetricsTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftGetSignerMetricsTest.java @@ -41,8 +41,8 @@ import java.util.Optional; import java.util.stream.LongStream; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class QbftGetSignerMetricsTest { @@ -58,7 +58,7 @@ public class QbftGetSignerMetricsTest { private BlockchainQueries blockchainQueries; private BlockInterface blockInterface; - @Before + @BeforeEach public void setup() { validatorProvider = mock(ValidatorProvider.class); blockchainQueries = mock(BlockchainQueries.class); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftGetValidatorsByBlockHashTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftGetValidatorsByBlockHashTest.java index bfc81438871..0eb8eb823a1 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftGetValidatorsByBlockHashTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftGetValidatorsByBlockHashTest.java @@ -31,13 +31,13 @@ import java.util.Optional; import org.assertj.core.api.Assertions; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class QbftGetValidatorsByBlockHashTest { private static final String ETH_METHOD = "qbft_getValidatorsByBlockHash"; @@ -51,7 +51,7 @@ public class QbftGetValidatorsByBlockHashTest { private QbftGetValidatorsByBlockHash method; - @Before + @BeforeEach public void setUp() { method = new QbftGetValidatorsByBlockHash(blockchain, validatorProvider); } diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftGetValidatorsByBlockNumberTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftGetValidatorsByBlockNumberTest.java index 46b1697ac60..b2e1c2b3d4d 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftGetValidatorsByBlockNumberTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftGetValidatorsByBlockNumberTest.java @@ -30,13 +30,13 @@ import java.util.List; import java.util.Optional; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class QbftGetValidatorsByBlockNumberTest { @Mock private BlockchainQueries blockchainQueries; @@ -46,7 +46,7 @@ public class QbftGetValidatorsByBlockNumberTest { private QbftGetValidatorsByBlockNumber method; - @Before + @BeforeEach public void setUp() { method = new QbftGetValidatorsByBlockNumber(blockchainQueries, validatorProvider); } diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftProposeValidatorVoteTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftProposeValidatorVoteTest.java index f9b771584e4..b9f2f9c2660 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftProposeValidatorVoteTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftProposeValidatorVoteTest.java @@ -33,8 +33,8 @@ import java.util.Optional; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class QbftProposeValidatorVoteTest { private final ValidatorProvider validatorProvider = mock(ValidatorProvider.class); @@ -43,7 +43,7 @@ public class QbftProposeValidatorVoteTest { private final String JSON_RPC_VERSION = "2.0"; private QbftProposeValidatorVote method; - @Before + @BeforeEach public void setup() { method = new QbftProposeValidatorVote(validatorProvider); when(validatorProvider.getVoteProviderAtHead()).thenReturn(Optional.of(voteProvider)); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/CommitTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/CommitTest.java index 71fa8eb64dc..87d3a46abe5 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/CommitTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/CommitTest.java @@ -29,7 +29,7 @@ import java.math.BigInteger; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class CommitTest { diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/PrepareTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/PrepareTest.java index eb84a1ae669..0aed7ed554e 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/PrepareTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/PrepareTest.java @@ -26,7 +26,7 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.Util; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class PrepareTest { diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/ProposalTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/ProposalTest.java index 47f8eb2c120..46a079ef00a 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/ProposalTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/ProposalTest.java @@ -39,7 +39,7 @@ import java.util.Optional; import org.apache.tuweni.bytes.Bytes32; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class ProposalTest { private static final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/RoundChangeTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/RoundChangeTest.java index 33c6df8ff58..23de31417c6 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/RoundChangeTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/RoundChangeTest.java @@ -38,7 +38,7 @@ import java.util.Optional; import org.apache.tuweni.bytes.Bytes32; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class RoundChangeTest { private static final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/payload/QbftPayloadTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/payload/QbftPayloadTest.java index 65612275b7a..820b0f976f9 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/payload/QbftPayloadTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/payload/QbftPayloadTest.java @@ -22,7 +22,7 @@ import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.ethereum.rlp.RLPOutput; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class QbftPayloadTest { diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/DefaultKeyStoreWrapperProviderTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/DefaultKeyStoreWrapperProviderTest.java index e0289759970..f5c91305cda 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/DefaultKeyStoreWrapperProviderTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/DefaultKeyStoreWrapperProviderTest.java @@ -28,13 +28,13 @@ import java.nio.file.Path; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class DefaultKeyStoreWrapperProviderTest { @Mock private HardwareKeyStoreWrapperProvider hardwareKeyStoreWrapperProvider; diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiBlockCreationConfigurationProviderTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiBlockCreationConfigurationProviderTest.java index c740d2825e0..27ccfe1bcfe 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiBlockCreationConfigurationProviderTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiBlockCreationConfigurationProviderTest.java @@ -28,12 +28,12 @@ import java.nio.file.Path; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class PkiBlockCreationConfigurationProviderTest { @Mock KeyStoreWrapperProvider keyStoreWrapperProvider; diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftBlockHashingTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftBlockHashingTest.java index 5780ca573d3..45ec1a780df 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftBlockHashingTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftBlockHashingTest.java @@ -32,15 +32,15 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.apache.tuweni.bytes.Bytes; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class PkiQbftBlockHashingTest { private PkiQbftExtraDataCodec pkiExtraDataCodec = new PkiQbftExtraDataCodec(); private PkiQbftBlockHashing pkiQbftBlockHashing; - @Before + @BeforeEach public void before() { pkiExtraDataCodec = spy(new PkiQbftExtraDataCodec()); pkiQbftBlockHashing = new PkiQbftBlockHashing(pkiExtraDataCodec); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftExtraDataCodecTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftExtraDataCodecTest.java index e344bdf36cc..32fc034b8e8 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftExtraDataCodecTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftExtraDataCodecTest.java @@ -35,7 +35,7 @@ import com.google.common.base.Suppliers; import org.apache.tuweni.bytes.Bytes; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class PkiQbftExtraDataCodecTest { diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/protocol/Istanbul100SubProtocolTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/protocol/Istanbul100SubProtocolTest.java index b600cdc4ef0..f3de01b77e9 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/protocol/Istanbul100SubProtocolTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/protocol/Istanbul100SubProtocolTest.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class Istanbul100SubProtocolTest { diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java index daf083c8fbe..da260140bff 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java @@ -78,15 +78,18 @@ import com.google.common.collect.Lists; import org.apache.tuweni.bytes.Bytes; import org.assertj.core.api.Assertions; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) public class QbftBlockHeightManagerTest { private final NodeKey nodeKey = NodeKeyUtils.generate(); @@ -126,7 +129,7 @@ private void buildCreatedBlock() { createdBlock = new Block(header, new BlockBody(emptyList(), emptyList())); } - @Before + @BeforeEach public void setup() { for (int i = 0; i < 3; i++) { final NodeKey nodeKey = NodeKeyUtils.generate(); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftControllerTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftControllerTest.java index 4ea2dd843a8..3e3a38af824 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftControllerTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftControllerTest.java @@ -57,13 +57,16 @@ import java.util.List; import com.google.common.collect.ImmutableList; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) public class QbftControllerTest { private static final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); @@ -100,7 +103,7 @@ public class QbftControllerTest { @Mock private FutureMessageBuffer futureMessageBuffer; private QbftController qbftController; - @Before + @BeforeEach public void setup() { when(blockChain.getChainHeadHeader()).thenReturn(chainHeadBlockHeader); when(blockChain.getChainHeadBlockNumber()).thenReturn(3L); @@ -111,7 +114,7 @@ public void setup() { when(chainHeadBlockHeader.getHash()).thenReturn(Hash.ZERO); when(blockHeightManager.getParentBlockHeader()).thenReturn(chainHeadBlockHeader); - when(blockHeightManager.getChainHeight()).thenReturn(4L); // one great than blockchain + when(blockHeightManager.getChainHeight()).thenReturn(4L); // one greater than blockchain when(nextBlock.getNumber()).thenReturn(5L); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java index 3459e9110c9..e3f58d5a7b6 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java @@ -69,15 +69,18 @@ import java.util.Optional; import org.apache.tuweni.bytes.Bytes; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) public class QbftRoundTest { private final NodeKey nodeKey = NodeKeyUtils.generate(); @@ -107,7 +110,7 @@ public class QbftRoundTest { SignatureAlgorithmFactory.getInstance() .createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 1); - @Before + @BeforeEach public void setup() { protocolContext = new ProtocolContext( diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundStateTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundStateTest.java index 26205adf59f..ff76a19b8ad 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundStateTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundStateTest.java @@ -47,13 +47,13 @@ import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.Lists; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class RoundStateTest { private static final Supplier SIGNATURE_ALGORITHM = @@ -70,7 +70,7 @@ public class RoundStateTest { @Mock private Block block; - @Before + @BeforeEach public void setup() { for (int i = 0; i < 3; i++) { final NodeKey newNodeKey = NodeKeyUtils.generate(); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/CommitValidatorTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/CommitValidatorTest.java index fb2a1d3095d..02ca653f2a3 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/CommitValidatorTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/CommitValidatorTest.java @@ -22,7 +22,7 @@ import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.datatypes.Hash; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class CommitValidatorTest { diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/PrepareValidatorTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/PrepareValidatorTest.java index 6a2d49af22a..b6c63b5598b 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/PrepareValidatorTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/PrepareValidatorTest.java @@ -21,7 +21,7 @@ import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; import org.hyperledger.besu.datatypes.Hash; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class PrepareValidatorTest { diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidatorTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidatorTest.java index 5e117cc6cf3..f2359019bdf 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidatorTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidatorTest.java @@ -54,13 +54,13 @@ import java.util.Optional; import org.apache.tuweni.bytes.Bytes; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ProposalPayloadValidatorTest { @Mock private BlockValidator blockValidator; @@ -80,7 +80,7 @@ public class ProposalPayloadValidatorTest { ConsensusRoundHelpers.createFrom(targetRound, 1, 0); final QbftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); - @Before + @BeforeEach public void setup() { protocolContext = new ProtocolContext( diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidatorTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidatorTest.java index e173208e7f2..e63b59bb0fe 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidatorTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidatorTest.java @@ -21,6 +21,7 @@ import static org.hyperledger.besu.consensus.qbft.validation.ValidationTestHelpers.createPreparePayloads; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.when; import org.hyperledger.besu.consensus.common.bft.BftHelpers; @@ -50,13 +51,13 @@ import java.util.Map; import java.util.Optional; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ProposalValidatorTest { private enum ROUND_ID { @@ -90,7 +91,7 @@ public RoundSpecificItems( private final Map roundItems = new HashMap<>(); final QbftExtraDataCodec bftExtraDataEncoder = new QbftExtraDataCodec(); - @Before + @BeforeEach public void setup() { protocolContext = new ProtocolContext( @@ -152,6 +153,7 @@ public void validationFailsIfBlockIsInvalid() { final RoundSpecificItems roundItem = roundItems.get(ROUND_ID.ZERO); final Proposal proposal = createProposal(roundItem, emptyList(), emptyList()); + reset(blockValidator); when(blockValidator.validateAndProcessBlock( eq(protocolContext), any(), diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidatorTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidatorTest.java index fe000758a40..2777f24b670 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidatorTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidatorTest.java @@ -49,13 +49,13 @@ import java.util.Optional; import java.util.stream.Collectors; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class RoundChangeMessageValidatorTest { @Mock private RoundChangePayloadValidator payloadValidator; @@ -74,7 +74,7 @@ public class RoundChangeMessageValidatorTest { ConsensusRoundHelpers.createFrom(targetRound, 0, -1); private final QbftExtraDataCodec bftExtraDataEncoder = new QbftExtraDataCodec(); - @Before + @BeforeEach public void setup() { protocolContext = new ProtocolContext( diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangePayloadValidatorTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangePayloadValidatorTest.java index ae403fe0f5f..f4a91024b4a 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangePayloadValidatorTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangePayloadValidatorTest.java @@ -27,7 +27,7 @@ import java.util.Optional; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class RoundChangePayloadValidatorTest { diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ForkingValidatorProviderTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ForkingValidatorProviderTest.java index d44af1b6151..023e195e350 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ForkingValidatorProviderTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ForkingValidatorProviderTest.java @@ -43,14 +43,14 @@ import org.apache.tuweni.bytes.Bytes; import org.assertj.core.api.SoftAssertions; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ForkingValidatorProviderTest { private static final Address CONTRACT_ADDRESS_1 = Address.fromHexString("0x888"); @@ -71,7 +71,7 @@ public class ForkingValidatorProviderTest { private BlockHeader header2; private final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); - @Before + @BeforeEach public void setup() { headerBuilder.extraData(Bytes.wrap(new byte[32])); Block genesisBlock = createEmptyBlock(0, Hash.ZERO); @@ -84,10 +84,6 @@ public void setup() { blockChain = createInMemoryBlockchain(genesisBlock); blockChain.appendBlock(block_1, emptyList()); blockChain.appendBlock(block_2, emptyList()); - - when(blockValidatorProvider.getValidatorsForBlock(any())).thenReturn(BLOCK_ADDRESSES); - when(contractValidatorProvider.getValidatorsForBlock(header1)).thenReturn(CONTRACT_ADDRESSES_1); - when(contractValidatorProvider.getValidatorsForBlock(header2)).thenReturn(CONTRACT_ADDRESSES_2); } private Block createEmptyBlock(final long blockNumber, final Hash parentHash) { @@ -106,6 +102,7 @@ public void usesInitialValidatorProviderWhenNoForks() { when(blockValidatorProvider.getValidatorsAfterBlock(header2)).thenReturn(BLOCK_ADDRESSES); when(blockValidatorProvider.getValidatorsAfterBlock(header1)).thenReturn(BLOCK_ADDRESSES); + when(blockValidatorProvider.getValidatorsForBlock(any())).thenReturn(BLOCK_ADDRESSES); assertThat(validatorProvider.getValidatorsAtHead()).isEqualTo(BLOCK_ADDRESSES); assertThat(validatorProvider.getValidatorsForBlock(header1)).isEqualTo(BLOCK_ADDRESSES); @@ -114,6 +111,9 @@ public void usesInitialValidatorProviderWhenNoForks() { @Test public void migratesFromBlockToContractValidatorProvider() { + when(blockValidatorProvider.getValidatorsForBlock(any())).thenReturn(BLOCK_ADDRESSES); + when(contractValidatorProvider.getValidatorsForBlock(header1)).thenReturn(CONTRACT_ADDRESSES_1); + final ForksSchedule forksSchedule = new ForksSchedule<>( List.of(createBlockForkSpec(0), createContractForkSpec(1L, CONTRACT_ADDRESS_1))); @@ -127,6 +127,8 @@ public void migratesFromBlockToContractValidatorProvider() { @Test public void migratesFromContractToBlockValidatorProvider() { + when(blockValidatorProvider.getValidatorsForBlock(any())).thenReturn(BLOCK_ADDRESSES); + final ForksSchedule forksSchedule = new ForksSchedule<>( List.of(createContractForkSpec(0, CONTRACT_ADDRESS_1), createBlockForkSpec(1))); @@ -145,6 +147,10 @@ public void migratesFromContractToBlockValidatorProvider() { @Test public void migratesFromContractToContractValidatorProvider() { + when(blockValidatorProvider.getValidatorsForBlock(any())).thenReturn(BLOCK_ADDRESSES); + when(contractValidatorProvider.getValidatorsForBlock(header1)).thenReturn(CONTRACT_ADDRESSES_1); + when(contractValidatorProvider.getValidatorsForBlock(header2)).thenReturn(CONTRACT_ADDRESSES_2); + final ForksSchedule forksSchedule = new ForksSchedule<>( List.of( diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/QbftForksSchedulesFactoryTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/QbftForksSchedulesFactoryTest.java index 9b0927bc79a..abb75426d0a 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/QbftForksSchedulesFactoryTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/QbftForksSchedulesFactoryTest.java @@ -44,7 +44,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class QbftForksSchedulesFactoryTest extends BaseForksSchedulesFactoryTest { diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/TransactionValidatorProviderTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/TransactionValidatorProviderTest.java index 8844cd6d90e..516566417f6 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/TransactionValidatorProviderTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/TransactionValidatorProviderTest.java @@ -39,13 +39,13 @@ import com.google.common.collect.Lists; import org.apache.tuweni.bytes.Bytes; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class TransactionValidatorProviderTest { @Mock private ValidatorContractController validatorContractController; @@ -59,7 +59,7 @@ public class TransactionValidatorProviderTest { private final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); private static final Address CONTRACT_ADDRESS = Address.fromHexString("1"); - @Before + @BeforeEach public void setup() { forksSchedule = new ForksSchedule<>(List.of(createContractForkSpec(0L, CONTRACT_ADDRESS))); genesisBlock = createEmptyBlock(0, Hash.ZERO); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorContractControllerTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorContractControllerTest.java index 4702a4eee84..6f4adf3a286 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorContractControllerTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorContractControllerTest.java @@ -38,8 +38,8 @@ import org.apache.tuweni.bytes.Bytes; import org.assertj.core.api.Assertions; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.web3j.abi.FunctionEncoder; import org.web3j.abi.TypeReference; @@ -64,7 +64,7 @@ public class ValidatorContractControllerTest { private final Transaction transaction = Mockito.mock(Transaction.class); private CallParameter callParameter; - @Before + @BeforeEach public void setup() { final Function getValidatorsFunction = new Function( diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorModeTransitionLoggerTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorModeTransitionLoggerTest.java index c7c854e7b98..d6219c6e754 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorModeTransitionLoggerTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorModeTransitionLoggerTest.java @@ -32,13 +32,13 @@ import java.util.Optional; import java.util.function.Consumer; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ValidatorModeTransitionLoggerTest { @Mock private ForksSchedule forksSchedule; From b97c9350b44c9f8e1a96af9e663e8968800bcdc5 Mon Sep 17 00:00:00 2001 From: Stefan Pingel <16143240+pinges@users.noreply.github.com> Date: Fri, 2 Jun 2023 15:06:03 +1000 Subject: [PATCH 15/35] Revert the revert of the tx selection commit (#5507) * Revert "Revert "Add plugin API to select Transactions (#5396)" (#5499)" This reverts commit a0c605277841984d8d18a7a826ad97a70d734f2c. * fix receipt root bug Signed-off-by: Stefan Signed-off-by: Simon Dudley Signed-off-by: Usman Saleem Signed-off-by: Stefan Pingel <16143240+pinges@users.noreply.github.com> Co-authored-by: Simon Dudley Co-authored-by: Usman Saleem --- .../tests/acceptance/dsl/node/BesuNode.java | 2 +- .../dsl/node/ThreadBesuNodeRunner.java | 39 +++++-- .../node/configuration/BesuNodeFactory.java | 23 ++++ .../org/hyperledger/besu/cli/BesuCommand.java | 26 ++++- .../controller/BesuControllerBuilder.java | 30 ++++- ...onsensusScheduleBesuControllerBuilder.java | 10 +- .../TransitionBesuControllerBuilder.java | 10 +- .../TransactionSelectionServiceImpl.java | 37 ++++++ .../besu/cli/CommandTestAbstract.java | 5 +- .../CliqueDifficultyCalculatorTest.java | 3 +- .../clique/NodeCanProduceNextBlockTest.java | 15 +-- .../blockcreation/CliqueBlockCreatorTest.java | 3 +- .../CliqueMinerExecutorTest.java | 2 +- .../CliqueDifficultyValidationRuleTest.java | 3 +- .../CliqueExtraDataValidationRuleTest.java | 3 +- .../common/MigratingProtocolContext.java | 18 ++- .../common/MigratingProtocolContextTest.java | 4 +- .../BftCoinbaseValidationRuleTest.java | 5 +- .../BftCommitSealsValidationRuleTest.java | 11 +- .../BftValidatorsValidationRuleTest.java | 12 +- .../BftVanityDataValidationRuleTest.java | 5 +- .../ibft/support/TestContextBuilder.java | 3 +- .../tests/round/IbftRoundIntegrationTest.java | 3 +- ...ockHeaderValidationRulesetFactoryTest.java | 5 +- .../ibft/IbftProtocolScheduleTest.java | 4 +- .../blockcreation/BftBlockCreatorTest.java | 3 +- .../IbftBlockHeightManagerTest.java | 3 +- .../ibft/statemachine/IbftRoundTest.java | 3 +- .../ibft/validation/MessageValidatorTest.java | 5 +- .../blockcreation/MergeCoordinatorTest.java | 3 +- .../merge/blockcreation/MergeReorgTest.java | 3 +- .../qbft/support/TestContextBuilder.java | 3 +- .../test/round/QbftRoundIntegrationTest.java | 4 +- ...ockHeaderValidationRulesetFactoryTest.java | 3 +- .../qbft/QbftProtocolScheduleTest.java | 3 +- .../QbftValidatorsValidationRuleTest.java | 16 ++- .../QbftBlockHeightManagerTest.java | 3 +- .../qbft/statemachine/QbftRoundTest.java | 3 +- .../ProposalPayloadValidatorTest.java | 7 +- .../validation/ProposalValidatorTest.java | 3 +- .../RoundChangeMessageValidatorTest.java | 3 +- .../jsonrpc/JsonRpcTestMethodsFactory.java | 2 +- ...ckByNumberLatestDesyncIntegrationTest.java | 2 +- .../AbstractEthGraphQLHttpServiceTest.java | 3 +- .../blockcreation/AbstractBlockCreator.java | 3 +- .../BlockTransactionSelector.java | 110 +++++++++++------- .../AbstractBlockTransactionSelectorTest.java | 110 +++++++++++++++++- .../blockcreation/BlockMinerTest.java | 4 +- .../besu/ethereum/ProtocolContext.java | 21 +++- .../besu/ethereum/core/LogsWrapper.java | 48 ++++++++ .../ethereum/core/TransactionReceipt.java | 26 ----- .../ethereum/core/BlockchainSetupUtil.java | 4 +- .../core/ExecutionContextTestFixture.java | 3 +- .../bonsai/AbstractIsolationTests.java | 2 +- .../eth/transactions/PendingTransactions.java | 1 + .../AbstractPendingTransactionsSorter.java | 2 +- .../AbstractBlockPropagationManagerTest.java | 4 +- .../fullsync/FullSyncTargetManagerTest.java | 3 +- ...neCommonAncestorTaskParameterizedTest.java | 3 +- .../DetermineCommonAncestorTaskTest.java | 4 +- .../ethereum/eth/transactions/TestNode.java | 2 +- .../LayeredPendingTransactionsTest.java | 16 +-- .../AbstractPendingTransactionsTestBase.java | 4 +- ethereum/evmtool/txs.rlp | 1 + .../BlockchainReferenceTestCaseSpec.java | 3 +- .../ethereum/retesteth/RetestethContext.java | 2 +- plugin-api/build.gradle | 2 +- .../data}/TransactionSelectionResult.java | 2 +- .../services/TransactionSelectionService.java | 40 +++++++ .../txselection/TransactionSelector.java | 44 +++++++ .../TransactionSelectorFactory.java | 30 +++++ 71 files changed, 672 insertions(+), 178 deletions(-) create mode 100644 besu/src/main/java/org/hyperledger/besu/services/TransactionSelectionServiceImpl.java create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/LogsWrapper.java create mode 100644 ethereum/evmtool/txs.rlp rename plugin-api/src/main/java/org/hyperledger/besu/{ethereum/eth/transactions => plugin/data}/TransactionSelectionResult.java (99%) create mode 100644 plugin-api/src/main/java/org/hyperledger/besu/plugin/services/TransactionSelectionService.java create mode 100644 plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txselection/TransactionSelector.java create mode 100644 plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txselection/TransactionSelectorFactory.java diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java index c336192b2b1..d822a21fb18 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java @@ -386,7 +386,7 @@ public String getHostName() { return LOCALHOST; } - private NodeRequests nodeRequests() { + public NodeRequests nodeRequests() { Optional websocketService = Optional.empty(); if (nodeRequests == null) { final Web3jService web3jService; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java index bfa0ae2cbcf..29ce00b175f 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java @@ -45,7 +45,9 @@ import org.hyperledger.besu.plugin.services.PicoCLIOptions; import org.hyperledger.besu.plugin.services.SecurityModuleService; import org.hyperledger.besu.plugin.services.StorageService; +import org.hyperledger.besu.plugin.services.TransactionSelectionService; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin; +import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory; import org.hyperledger.besu.services.BesuConfigurationImpl; import org.hyperledger.besu.services.BesuEventsImpl; import org.hyperledger.besu.services.BesuPluginContextImpl; @@ -54,6 +56,7 @@ import org.hyperledger.besu.services.RpcEndpointServiceImpl; import org.hyperledger.besu.services.SecurityModuleServiceImpl; import org.hyperledger.besu.services.StorageServiceImpl; +import org.hyperledger.besu.services.TransactionSelectionServiceImpl; import java.io.File; import java.nio.file.Path; @@ -63,6 +66,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -91,14 +95,22 @@ private BesuPluginContextImpl buildPluginContext( besuPluginContext.addService(StorageService.class, storageService); besuPluginContext.addService(SecurityModuleService.class, securityModuleService); besuPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine)); - - final Path pluginsPath = node.homeDirectory().resolve("plugins"); - final File pluginsDirFile = pluginsPath.toFile(); - if (!pluginsDirFile.isDirectory()) { - pluginsDirFile.mkdirs(); - pluginsDirFile.deleteOnExit(); + besuPluginContext.addService( + TransactionSelectionService.class, new TransactionSelectionServiceImpl()); + + final Path pluginsPath; + final String pluginDir = System.getProperty("besu.plugins.dir"); + if (pluginDir == null || pluginDir.isEmpty()) { + pluginsPath = node.homeDirectory().resolve("plugins"); + final File pluginsDirFile = pluginsPath.toFile(); + if (!pluginsDirFile.isDirectory()) { + pluginsDirFile.mkdirs(); + pluginsDirFile.deleteOnExit(); + } + System.setProperty("besu.plugins.dir", pluginsPath.toString()); + } else { + pluginsPath = Path.of(pluginDir); } - System.setProperty("besu.plugins.dir", pluginsPath.toString()); besuPluginContext.registerPlugins(pluginsPath); commandLine.parseArgs(node.getConfiguration().getExtraCLIOptions().toArray(new String[0])); @@ -169,6 +181,9 @@ public void startNode(final BesuNode node) { final int maxPeers = 25; + final Optional transactionSelectorFactory = + getTransactionSelectorFactory(besuPluginContext); + builder .synchronizerConfiguration(new SynchronizerConfiguration.Builder().build()) .dataDirectory(node.homeDirectory()) @@ -190,7 +205,8 @@ public void startNode(final BesuNode node) { .lowerBoundPeers(maxPeers) .maxRemotelyInitiatedPeers(15) .networkConfiguration(node.getNetworkingConfiguration()) - .randomPeerPriority(false); + .randomPeerPriority(false) + .transactionSelectorFactory(transactionSelectorFactory); node.getGenesisConfig() .map(GenesisConfigFile::fromConfig) @@ -299,4 +315,11 @@ public void startConsoleCapture() { public String getConsoleContents() { throw new RuntimeException("Console contents can only be captured in process execution"); } + + private Optional getTransactionSelectorFactory( + final BesuPluginContextImpl besuPluginContext) { + final Optional txSelectionService = + besuPluginContext.getService(TransactionSelectionService.class); + return txSelectionService.isPresent() ? txSelectionService.get().get() : Optional.empty(); + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java index 6f3c601fa37..fb6ac5f1014 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java @@ -107,10 +107,33 @@ public BesuNode createMinerNode( return create(config); } + public BesuNode createMinerNodeWithExtraCliOptions( + final String name, + final UnaryOperator configModifier, + final List extraCliOptions) + throws IOException { + BesuNodeConfigurationBuilder builder = + new BesuNodeConfigurationBuilder() + .name(name) + .miningEnabled() + .jsonRpcEnabled() + .webSocketEnabled() + .extraCLIOptions(extraCliOptions); + builder = configModifier.apply(builder); + final BesuNodeConfiguration config = builder.build(); + + return create(config); + } + public BesuNode createMinerNode(final String name) throws IOException { return createMinerNode(name, UnaryOperator.identity()); } + public BesuNode createMinerNodeWithExtraCliOptions( + final String name, final List extraCliOptions) throws IOException { + return createMinerNodeWithExtraCliOptions(name, UnaryOperator.identity(), extraCliOptions); + } + public BesuNode createMinerNodeWithRevertReasonEnabled(final String name) throws IOException { return createMinerNode(name, BesuNodeConfigurationBuilder::revertReasonEnabled); } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 8f6ad126dd3..764f33ce1b9 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -168,12 +168,14 @@ import org.hyperledger.besu.plugin.services.SecurityModuleService; import org.hyperledger.besu.plugin.services.StorageService; import org.hyperledger.besu.plugin.services.TraceService; +import org.hyperledger.besu.plugin.services.TransactionSelectionService; import org.hyperledger.besu.plugin.services.exception.StorageException; import org.hyperledger.besu.plugin.services.metrics.MetricCategory; import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry; import org.hyperledger.besu.plugin.services.securitymodule.SecurityModule; import org.hyperledger.besu.plugin.services.storage.PrivacyKeyValueStorageFactory; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin; +import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory; import org.hyperledger.besu.services.BesuEventsImpl; import org.hyperledger.besu.services.BesuPluginContextImpl; import org.hyperledger.besu.services.BlockchainServiceImpl; @@ -184,6 +186,7 @@ import org.hyperledger.besu.services.SecurityModuleServiceImpl; import org.hyperledger.besu.services.StorageServiceImpl; import org.hyperledger.besu.services.TraceServiceImpl; +import org.hyperledger.besu.services.TransactionSelectionServiceImpl; import org.hyperledger.besu.services.kvstore.InMemoryStoragePlugin; import org.hyperledger.besu.util.InvalidConfigurationException; import org.hyperledger.besu.util.LogConfigurator; @@ -235,6 +238,7 @@ import io.vertx.core.metrics.MetricsOptions; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.units.bigints.UInt256; +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import picocli.AutoComplete; import picocli.CommandLine; @@ -361,6 +365,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable { @CommandLine.ArgGroup(validate = false, heading = "@|bold P2P Discovery Options|@%n") P2PDiscoveryOptionGroup p2PDiscoveryOptionGroup = new P2PDiscoveryOptionGroup(); + private final TransactionSelectionServiceImpl transactionSelectionServiceImpl; + static class P2PDiscoveryOptionGroup { // Public IP stored to prevent having to research it each time we need it. @@ -1417,7 +1423,8 @@ public BesuCommand( new PermissioningServiceImpl(), new PrivacyPluginServiceImpl(), new PkiBlockCreationConfigurationProvider(), - new RpcEndpointServiceImpl()); + new RpcEndpointServiceImpl(), + new TransactionSelectionServiceImpl()); } /** @@ -1437,6 +1444,7 @@ public BesuCommand( * @param privacyPluginService instance of PrivacyPluginServiceImpl * @param pkiBlockCreationConfigProvider instance of PkiBlockCreationConfigurationProvider * @param rpcEndpointServiceImpl instance of RpcEndpointServiceImpl + * @param transactionSelectionServiceImpl instance of TransactionSelectionServiceImpl */ @VisibleForTesting protected BesuCommand( @@ -1453,7 +1461,8 @@ protected BesuCommand( final PermissioningServiceImpl permissioningService, final PrivacyPluginServiceImpl privacyPluginService, final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider, - final RpcEndpointServiceImpl rpcEndpointServiceImpl) { + final RpcEndpointServiceImpl rpcEndpointServiceImpl, + final TransactionSelectionServiceImpl transactionSelectionServiceImpl) { this.besuComponent = besuComponent; this.logger = besuComponent.getBesuCommandLogger(); this.rlpBlockImporter = rlpBlockImporter; @@ -1471,6 +1480,7 @@ protected BesuCommand( besuPluginContext.addService(BesuConfiguration.class, pluginCommonConfiguration); this.pkiBlockCreationConfigProvider = pkiBlockCreationConfigProvider; this.rpcEndpointServiceImpl = rpcEndpointServiceImpl; + this.transactionSelectionServiceImpl = transactionSelectionServiceImpl; } /** @@ -1651,6 +1661,8 @@ private void preparePlugins() { besuPluginContext.addService(PermissioningService.class, permissioningService); besuPluginContext.addService(PrivacyPluginService.class, privacyPluginService); besuPluginContext.addService(RpcEndpointService.class, rpcEndpointServiceImpl); + besuPluginContext.addService( + TransactionSelectionService.class, transactionSelectionServiceImpl); // register built-in plugins rocksDBPlugin = new RocksDBPlugin(); @@ -2278,12 +2290,15 @@ public BesuController buildController() { */ public BesuControllerBuilder getControllerBuilder() { final KeyValueStorageProvider storageProvider = keyValueStorageProvider(keyValueStorageName); + final Optional transactionSelectorFactory = + getTransactionSelectorFactory(); return controllerBuilderFactory .fromEthNetworkConfig( updateNetworkConfig(network), genesisConfigOverrides, getDefaultSyncModeIfNotSet()) .synchronizerConfiguration(buildSyncConfig()) .ethProtocolConfiguration(unstableEthProtocolOptions.toDomainObject()) .networkConfiguration(unstableNetworkingOptions.toDomainObject()) + .transactionSelectorFactory(transactionSelectorFactory) .dataDirectory(dataDir()) .miningParameters( new MiningParameters.Builder() @@ -2333,6 +2348,13 @@ public BesuControllerBuilder getControllerBuilder() { .chainPruningConfiguration(unstableChainPruningOptions.toDomainObject()); } + @NotNull + private Optional getTransactionSelectorFactory() { + final Optional txSelectionService = + besuPluginContext.getService(TransactionSelectionService.class); + return txSelectionService.isPresent() ? txSelectionService.get().get() : Optional.empty(); + } + private GraphQLConfiguration graphQLConfiguration() { CommandLineUtils.checkOptionDependencies( diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java index 7e66dda25d4..4b7bff0234f 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -94,6 +94,7 @@ import org.hyperledger.besu.metrics.ObservableMetricsSystem; import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.permissioning.NodeMessagePermissioningProvider; +import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory; import java.io.Closeable; import java.math.BigInteger; @@ -179,6 +180,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides private NetworkingConfiguration networkingConfiguration; private Boolean randomPeerPriority; + private Optional transactionSelectorFactory = Optional.empty(); /** the Dagger configured context that can provide dependencies */ protected Optional besuComponent = Optional.empty(); @@ -522,6 +524,18 @@ public BesuControllerBuilder randomPeerPriority(final Boolean randomPeerPriority return this; } + /** + * sets the transactionSelectorFactory in the builder + * + * @param transactionSelectorFactory the optional transaction selector factory + * @return the besu controller builder + */ + public BesuControllerBuilder transactionSelectorFactory( + final Optional transactionSelectorFactory) { + this.transactionSelectorFactory = transactionSelectorFactory; + return this; + } + /** * Build besu controller. * @@ -575,7 +589,11 @@ public BesuController build() { final ProtocolContext protocolContext = createProtocolContext( - blockchain, worldStateArchive, protocolSchedule, this::createConsensusContext); + blockchain, + worldStateArchive, + protocolSchedule, + this::createConsensusContext, + transactionSelectorFactory); validateContext(protocolContext); if (chainPrunerConfiguration.getChainPruningEnabled()) { @@ -991,15 +1009,21 @@ protected EthProtocolManager createEthProtocolManager( * @param worldStateArchive the world state archive * @param protocolSchedule the protocol schedule * @param consensusContextFactory the consensus context factory + * @param transactionSelectorFactory optional transaction selector factory * @return the protocol context */ protected ProtocolContext createProtocolContext( final MutableBlockchain blockchain, final WorldStateArchive worldStateArchive, final ProtocolSchedule protocolSchedule, - final ConsensusContextFactory consensusContextFactory) { + final ConsensusContextFactory consensusContextFactory, + final Optional transactionSelectorFactory) { return ProtocolContext.init( - blockchain, worldStateArchive, protocolSchedule, consensusContextFactory); + blockchain, + worldStateArchive, + protocolSchedule, + consensusContextFactory, + transactionSelectorFactory); } private Optional createSnapProtocolManager( diff --git a/besu/src/main/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilder.java index e4d5761dbf1..6d0d02b22f0 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilder.java @@ -62,6 +62,7 @@ import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.metrics.ObservableMetricsSystem; import org.hyperledger.besu.plugin.services.permissioning.NodeMessagePermissioningProvider; +import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory; import java.math.BigInteger; import java.nio.file.Path; @@ -174,9 +175,14 @@ protected ProtocolContext createProtocolContext( final MutableBlockchain blockchain, final WorldStateArchive worldStateArchive, final ProtocolSchedule protocolSchedule, - final ConsensusContextFactory consensusContextFactory) { + final ConsensusContextFactory consensusContextFactory, + final Optional transactionSelectorFactory) { return MigratingProtocolContext.init( - blockchain, worldStateArchive, protocolSchedule, consensusContextFactory); + blockchain, + worldStateArchive, + protocolSchedule, + consensusContextFactory, + transactionSelectorFactory); } @Override diff --git a/besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java index b159992e0bf..9323f3b81d6 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java @@ -60,6 +60,7 @@ import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.metrics.ObservableMetricsSystem; import org.hyperledger.besu.plugin.services.permissioning.NodeMessagePermissioningProvider; +import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory; import java.math.BigInteger; import java.nio.file.Path; @@ -188,10 +189,15 @@ protected ProtocolContext createProtocolContext( final MutableBlockchain blockchain, final WorldStateArchive worldStateArchive, final ProtocolSchedule protocolSchedule, - final ConsensusContextFactory consensusContextFactory) { + final ConsensusContextFactory consensusContextFactory, + final Optional transactionSelectorFactory) { final ProtocolContext protocolContext = super.createProtocolContext( - blockchain, worldStateArchive, protocolSchedule, consensusContextFactory); + blockchain, + worldStateArchive, + protocolSchedule, + consensusContextFactory, + transactionSelectorFactory); transitionProtocolSchedule.setProtocolContext(protocolContext); return protocolContext; } diff --git a/besu/src/main/java/org/hyperledger/besu/services/TransactionSelectionServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/TransactionSelectionServiceImpl.java new file mode 100644 index 00000000000..42b1ae88a76 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/services/TransactionSelectionServiceImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.services; + +import org.hyperledger.besu.plugin.services.TransactionSelectionService; +import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory; + +import java.util.Optional; + +/** The Transaction Selection service implementation. */ +public class TransactionSelectionServiceImpl implements TransactionSelectionService { + + private Optional factory = Optional.empty(); + + @Override + public Optional get() { + return factory; + } + + @Override + public void registerTransactionSelectorFactory( + final TransactionSelectorFactory transactionSelectorFactory) { + factory = Optional.ofNullable(transactionSelectorFactory); + } +} diff --git a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java index fcce5353adc..b5c31a34dee 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java @@ -79,6 +79,7 @@ import org.hyperledger.besu.services.RpcEndpointServiceImpl; import org.hyperledger.besu.services.SecurityModuleServiceImpl; import org.hyperledger.besu.services.StorageServiceImpl; +import org.hyperledger.besu.services.TransactionSelectionServiceImpl; import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; import java.io.ByteArrayOutputStream; @@ -237,6 +238,7 @@ public void initMocks() throws Exception { when(mockControllerBuilder.lowerBoundPeers(anyInt())).thenReturn(mockControllerBuilder); when(mockControllerBuilder.maxRemotelyInitiatedPeers(anyInt())) .thenReturn(mockControllerBuilder); + when(mockControllerBuilder.transactionSelectorFactory(any())).thenReturn(mockControllerBuilder); when(mockControllerBuilder.besuComponent(any(BesuComponent.class))) .thenReturn(mockControllerBuilder); // doReturn used because of generic BesuController @@ -484,7 +486,8 @@ public static class TestBesuCommand extends BesuCommand { new PermissioningServiceImpl(), privacyPluginService, pkiBlockCreationConfigProvider, - rpcEndpointServiceImpl); + rpcEndpointServiceImpl, + new TransactionSelectionServiceImpl()); } @Override diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueDifficultyCalculatorTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueDifficultyCalculatorTest.java index 6297ec6b6eb..6f9c5c53e0e 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueDifficultyCalculatorTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueDifficultyCalculatorTest.java @@ -31,6 +31,7 @@ import java.math.BigInteger; import java.util.List; +import java.util.Optional; import com.google.common.collect.Lists; import org.junit.jupiter.api.BeforeEach; @@ -57,7 +58,7 @@ public void setup() { when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList); final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface); - cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext); + cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext, Optional.empty()); blockHeaderBuilder = new BlockHeaderTestFixture(); } diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/NodeCanProduceNextBlockTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/NodeCanProduceNextBlockTest.java index 0018f3d9e17..486c1840fc9 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/NodeCanProduceNextBlockTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/NodeCanProduceNextBlockTest.java @@ -37,6 +37,7 @@ import org.hyperledger.besu.ethereum.core.Util; import java.util.List; +import java.util.Optional; import com.google.common.collect.Lists; import org.junit.jupiter.api.BeforeEach; @@ -79,7 +80,7 @@ public void networkWithOneValidatorIsAllowedToCreateConsecutiveBlocks() { final ValidatorProvider validatorProvider = mock(ValidatorProvider.class); when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList); final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface); - cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext); + cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext, Optional.empty()); headerBuilder.number(1).parentHash(genesisBlock.getHash()); final Block block_1 = createEmptyBlock(proposerKeyPair); @@ -103,7 +104,7 @@ public void networkWithTwoValidatorsIsAllowedToProduceBlockIfNotPreviousBlockPro final ValidatorProvider validatorProvider = mock(ValidatorProvider.class); when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList); final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface); - cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext); + cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext, Optional.empty()); headerBuilder.number(1).parentHash(genesisBlock.getHash()); final Block block_1 = createEmptyBlock(proposerKeyPair); @@ -136,7 +137,7 @@ public void networkWithTwoValidatorsIsNotAllowedToProduceBlockIfIsPreviousBlockP final ValidatorProvider validatorProvider = mock(ValidatorProvider.class); when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList); final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface); - cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext); + cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext, Optional.empty()); headerBuilder.parentHash(genesisBlock.getHash()).number(1); final Block block_1 = createEmptyBlock(proposerKeyPair); @@ -165,7 +166,7 @@ public void withThreeValidatorsMustHaveOneBlockBetweenSignings() { final ValidatorProvider validatorProvider = mock(ValidatorProvider.class); when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList); final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface); - cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext); + cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext, Optional.empty()); headerBuilder.parentHash(genesisBlock.getHash()).number(1); final Block block_1 = createEmptyBlock(proposerKeyPair); @@ -209,7 +210,7 @@ public void signerIsValidIfInsufficientBlocksExistInHistory() { final ValidatorProvider validatorProvider = mock(ValidatorProvider.class); when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList); final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface); - cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext); + cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext, Optional.empty()); headerBuilder.parentHash(genesisBlock.getHash()).number(1); final Block block_1 = createEmptyBlock(otherNodeKeyPair); @@ -237,7 +238,7 @@ public void exceptionIsThrownIfOnAnOrphanedChain() { final ValidatorProvider validatorProvider = mock(ValidatorProvider.class); when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList); final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface); - cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext); + cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext, Optional.empty()); headerBuilder.parentHash(Hash.ZERO).number(3); final BlockHeader parentHeader = @@ -260,7 +261,7 @@ public void nonValidatorIsNotAllowedToCreateABlock() { final ValidatorProvider validatorProvider = mock(ValidatorProvider.class); when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList); final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface); - cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext); + cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext, Optional.empty()); headerBuilder.parentHash(Hash.ZERO).number(3); final BlockHeader parentHeader = headerBuilder.buildHeader(); diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java index 8f3709b1605..76741501dc2 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java @@ -105,7 +105,8 @@ public void setup() { final Block genesis = GenesisState.fromConfig(GenesisConfigFile.mainnet(), protocolSchedule).getBlock(); blockchain = createInMemoryBlockchain(genesis); - protocolContext = new ProtocolContext(blockchain, stateArchive, cliqueContext); + protocolContext = + new ProtocolContext(blockchain, stateArchive, cliqueContext, Optional.empty()); epochManager = new EpochManager(10); // Add a block above the genesis diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java index 76caf56f5d9..ab3e45abc59 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java @@ -81,7 +81,7 @@ public void setup() { when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList); final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface); - cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext); + cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext, Optional.empty()); blockHeaderBuilder = new BlockHeaderTestFixture(); } diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueDifficultyValidationRuleTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueDifficultyValidationRuleTest.java index 56d511b4be1..7f7daf4eeab 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueDifficultyValidationRuleTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueDifficultyValidationRuleTest.java @@ -34,6 +34,7 @@ import org.hyperledger.besu.ethereum.core.Util; import java.util.List; +import java.util.Optional; import com.google.common.collect.Lists; import org.junit.jupiter.api.BeforeEach; @@ -57,7 +58,7 @@ public void setup() { when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList); final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface); - cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext); + cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext, Optional.empty()); blockHeaderBuilder = new BlockHeaderTestFixture(); } diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueExtraDataValidationRuleTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueExtraDataValidationRuleTest.java index 04657661776..72043c9cb9a 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueExtraDataValidationRuleTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueExtraDataValidationRuleTest.java @@ -35,6 +35,7 @@ import org.hyperledger.besu.ethereum.core.Util; import java.util.List; +import java.util.Optional; import com.google.common.collect.Lists; import org.apache.tuweni.bytes.Bytes; @@ -61,7 +62,7 @@ public void setup() { when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList); final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface); - cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext); + cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext, Optional.empty()); } @Test diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/MigratingProtocolContext.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/MigratingProtocolContext.java index 95ac7a010ca..e4304a3dbd0 100644 --- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/MigratingProtocolContext.java +++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/MigratingProtocolContext.java @@ -20,6 +20,9 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; +import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory; + +import java.util.Optional; /** The Migrating protocol context. */ public class MigratingProtocolContext extends ProtocolContext { @@ -32,12 +35,14 @@ public class MigratingProtocolContext extends ProtocolContext { * @param blockchain the blockchain * @param worldStateArchive the world state archive * @param consensusContextSchedule the consensus context schedule + * @param transactionSelectorFactory the optional transaction selector factory */ public MigratingProtocolContext( final MutableBlockchain blockchain, final WorldStateArchive worldStateArchive, - final ForksSchedule consensusContextSchedule) { - super(blockchain, worldStateArchive, null); + final ForksSchedule consensusContextSchedule, + final Optional transactionSelectorFactory) { + super(blockchain, worldStateArchive, null, transactionSelectorFactory); this.consensusContextSchedule = consensusContextSchedule; } @@ -48,18 +53,23 @@ public MigratingProtocolContext( * @param worldStateArchive the world state archive * @param protocolSchedule the protocol schedule * @param consensusContextFactory the consensus context factory + * @param transactionSelectorFactory the optional transaction selector factory * @return the protocol context */ public static ProtocolContext init( final MutableBlockchain blockchain, final WorldStateArchive worldStateArchive, final ProtocolSchedule protocolSchedule, - final ConsensusContextFactory consensusContextFactory) { + final ConsensusContextFactory consensusContextFactory, + final Optional transactionSelectorFactory) { final ConsensusContext consensusContext = consensusContextFactory.create(blockchain, worldStateArchive, protocolSchedule); final MigratingContext migratingContext = consensusContext.as(MigratingContext.class); return new MigratingProtocolContext( - blockchain, worldStateArchive, migratingContext.getConsensusContextSchedule()); + blockchain, + worldStateArchive, + migratingContext.getConsensusContextSchedule(), + transactionSelectorFactory); } @Override diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/MigratingProtocolContextTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/MigratingProtocolContextTest.java index 84fc82da67c..21ba7638c40 100644 --- a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/MigratingProtocolContextTest.java +++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/MigratingProtocolContextTest.java @@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import java.util.List; +import java.util.Optional; import org.junit.Test; import org.mockito.Mockito; @@ -43,7 +44,8 @@ public void returnsContextForSpecificChainHeight() { final ForksSchedule contextSchedule = new ForksSchedule<>(List.of(new ForkSpec<>(0L, context1), new ForkSpec<>(10L, context2))); final MigratingProtocolContext migratingProtocolContext = - new MigratingProtocolContext(blockchain, worldStateArchive, contextSchedule); + new MigratingProtocolContext( + blockchain, worldStateArchive, contextSchedule, Optional.empty()); assertThat(migratingProtocolContext.getConsensusContext(ConsensusContext.class)) .isSameAs(context1); diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftCoinbaseValidationRuleTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftCoinbaseValidationRuleTest.java index d268c514467..fcbea4954d8 100644 --- a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftCoinbaseValidationRuleTest.java +++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftCoinbaseValidationRuleTest.java @@ -27,6 +27,7 @@ import org.hyperledger.besu.ethereum.core.Util; import java.util.List; +import java.util.Optional; import com.google.common.collect.Lists; import org.junit.Test; @@ -50,7 +51,7 @@ public void proposerInValidatorListPassesValidation() { final List
validators = Lists.newArrayList(proposerAddress); final ProtocolContext context = - new ProtocolContext(null, null, setupContextWithValidators(validators)); + new ProtocolContext(null, null, setupContextWithValidators(validators), Optional.empty()); final BftCoinbaseValidationRule coinbaseValidationRule = new BftCoinbaseValidationRule(); @@ -70,7 +71,7 @@ public void proposerNotInValidatorListFailsValidation() { final List
validators = Lists.newArrayList(otherValidatorNodeAddress); final ProtocolContext context = - new ProtocolContext(null, null, setupContextWithValidators(validators)); + new ProtocolContext(null, null, setupContextWithValidators(validators), Optional.empty()); final BftCoinbaseValidationRule coinbaseValidationRule = new BftCoinbaseValidationRule(); diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftCommitSealsValidationRuleTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftCommitSealsValidationRuleTest.java index cae209bd662..453b28a601c 100644 --- a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftCommitSealsValidationRuleTest.java +++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftCommitSealsValidationRuleTest.java @@ -33,6 +33,7 @@ import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -57,7 +58,7 @@ public void correctlyConstructedHeaderPassesValidation() { .collect(Collectors.toList()); final BftContext bftContext = setupContextWithValidators(committerAddresses); - final ProtocolContext context = new ProtocolContext(null, null, bftContext); + final ProtocolContext context = new ProtocolContext(null, null, bftContext, Optional.empty()); when(bftContext.getBlockInterface().getCommitters(any())).thenReturn(committerAddresses); assertThat(commitSealsValidationRule.validate(blockHeader, null, context)).isTrue(); @@ -71,7 +72,7 @@ public void insufficientCommitSealsFailsValidation() { final List
validators = singletonList(committerAddress); final BftContext bftContext = setupContextWithValidators(validators); - final ProtocolContext context = new ProtocolContext(null, null, bftContext); + final ProtocolContext context = new ProtocolContext(null, null, bftContext, Optional.empty()); when(bftContext.getBlockInterface().getCommitters(any())).thenReturn(emptyList()); assertThat(commitSealsValidationRule.validate(blockHeader, null, context)).isFalse(); @@ -88,7 +89,7 @@ public void committerNotInValidatorListFailsValidation() { final NodeKey nonValidatorNodeKey = NodeKeyUtils.generate(); final BftContext bftContext = setupContextWithValidators(validators); - final ProtocolContext context = new ProtocolContext(null, null, bftContext); + final ProtocolContext context = new ProtocolContext(null, null, bftContext, Optional.empty()); when(bftContext.getBlockInterface().getCommitters(any())) .thenReturn(singletonList(Util.publicKeyToAddress(nonValidatorNodeKey.getPublicKey()))); @@ -135,7 +136,7 @@ public void headerContainsDuplicateSealsFailsValidation() { final List
validators = singletonList(committerAddress); final BftContext bftContext = setupContextWithValidators(validators); - final ProtocolContext context = new ProtocolContext(null, null, bftContext); + final ProtocolContext context = new ProtocolContext(null, null, bftContext, Optional.empty()); when(bftContext.getBlockInterface().getCommitters(any())) .thenReturn(List.of(committerAddress, committerAddress)); @@ -154,7 +155,7 @@ private boolean subExecution(final int validatorCount, final int committerCount) Collections.sort(validators); final BftContext bftContext = setupContextWithValidators(validators); - final ProtocolContext context = new ProtocolContext(null, null, bftContext); + final ProtocolContext context = new ProtocolContext(null, null, bftContext, Optional.empty()); when(bftContext.getBlockInterface().getCommitters(any())) .thenReturn(validators.subList(0, committerCount)); diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftValidatorsValidationRuleTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftValidatorsValidationRuleTest.java index 048faa3ad88..00b994295ca 100644 --- a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftValidatorsValidationRuleTest.java +++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftValidatorsValidationRuleTest.java @@ -26,6 +26,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import java.util.List; +import java.util.Optional; import com.google.common.collect.Lists; import org.junit.Test; @@ -44,7 +45,8 @@ public void correctlyConstructedHeaderPassesValidation() { AddressHelpers.ofValue(1), AddressHelpers.ofValue(2), AddressHelpers.ofValue(3)); final ProtocolContext context = - new ProtocolContext(null, null, setupContextWithBftExtraData(validators, bftExtraData)); + new ProtocolContext( + null, null, setupContextWithBftExtraData(validators, bftExtraData), Optional.empty()); when(bftExtraData.getValidators()).thenReturn(validators); assertThat(validatorsValidationRule.validate(blockHeader, null, context)).isTrue(); @@ -58,7 +60,8 @@ public void validatorsInNonAscendingOrderFailValidation() { AddressHelpers.ofValue(1), AddressHelpers.ofValue(2), AddressHelpers.ofValue(3)); final ProtocolContext context = - new ProtocolContext(null, null, setupContextWithBftExtraData(validators, bftExtraData)); + new ProtocolContext( + null, null, setupContextWithBftExtraData(validators, bftExtraData), Optional.empty()); when(bftExtraData.getValidators()).thenReturn(Lists.reverse(validators)); assertThat(validatorsValidationRule.validate(blockHeader, null, context)).isFalse(); @@ -76,7 +79,10 @@ public void mismatchingReportedValidatorsVsLocallyStoredListFailsValidation() { final ProtocolContext context = new ProtocolContext( - null, null, setupContextWithBftExtraData(storedValidators, bftExtraData)); + null, + null, + setupContextWithBftExtraData(storedValidators, bftExtraData), + Optional.empty()); when(bftExtraData.getValidators()).thenReturn(Lists.reverse(reportedValidators)); assertThat(validatorsValidationRule.validate(blockHeader, null, context)).isFalse(); diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftVanityDataValidationRuleTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftVanityDataValidationRuleTest.java index 548084f81cb..cd148f8787a 100644 --- a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftVanityDataValidationRuleTest.java +++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftVanityDataValidationRuleTest.java @@ -24,6 +24,8 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.BlockHeader; +import java.util.Optional; + import org.apache.tuweni.bytes.Bytes; import org.junit.Test; @@ -44,7 +46,8 @@ public boolean headerWithVanityDataOfSize(final int extraDataSize) { new BftExtraData(Bytes.wrap(new byte[extraDataSize]), emptyList(), empty(), 0, emptyList()); final ProtocolContext context = - new ProtocolContext(null, null, setupContextWithBftExtraData(emptyList(), extraData)); + new ProtocolContext( + null, null, setupContextWithBftExtraData(emptyList(), extraData), Optional.empty()); return validationRule.validate(blockHeader, null, context); } } diff --git a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java index c0b85a434bf..7d7778410cb 100644 --- a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java +++ b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java @@ -328,7 +328,8 @@ private static ControllerAndState createControllerAndFinalState( new ProtocolContext( blockChain, worldStateArchive, - new BftContext(validatorProvider, epochManager, blockInterface)); + new BftContext(validatorProvider, epochManager, blockInterface), + Optional.empty()); final GasPricePendingTransactionsSorter pendingTransactions = new GasPricePendingTransactionsSorter( diff --git a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/tests/round/IbftRoundIntegrationTest.java b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/tests/round/IbftRoundIntegrationTest.java index 88669b91504..ff9c47ab38c 100644 --- a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/tests/round/IbftRoundIntegrationTest.java +++ b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/tests/round/IbftRoundIntegrationTest.java @@ -118,7 +118,8 @@ public void setup() { new ProtocolContext( blockChain, worldStateArchive, - setupContextWithBftExtraDataEncoder(emptyList(), bftExtraDataEncoder)); + setupContextWithBftExtraDataEncoder(emptyList(), bftExtraDataEncoder), + Optional.empty()); } @Test diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/IbftBlockHeaderValidationRulesetFactoryTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/IbftBlockHeaderValidationRulesetFactoryTest.java index 6c1bf8ed5db..40ad127eb5b 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/IbftBlockHeaderValidationRulesetFactoryTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/IbftBlockHeaderValidationRulesetFactoryTest.java @@ -48,7 +48,10 @@ public class IbftBlockHeaderValidationRulesetFactoryTest { private ProtocolContext protocolContext(final Collection
validators) { return new ProtocolContext( - null, null, setupContextWithBftExtraDataEncoder(validators, new IbftExtraDataCodec())); + null, + null, + setupContextWithBftExtraDataEncoder(validators, new IbftExtraDataCodec()), + Optional.empty()); } @Test diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/IbftProtocolScheduleTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/IbftProtocolScheduleTest.java index 562d441d4d8..1ca3c0269a8 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/IbftProtocolScheduleTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/IbftProtocolScheduleTest.java @@ -47,6 +47,7 @@ import java.math.BigInteger; import java.util.Collection; import java.util.List; +import java.util.Optional; import org.junit.Before; import org.junit.Test; @@ -119,6 +120,7 @@ private ProtocolContext protocolContext(final Collection
validators) { return new ProtocolContext( null, null, - setupContextWithBftExtraDataEncoder(BftContext.class, validators, bftExtraDataCodec)); + setupContextWithBftExtraDataEncoder(BftContext.class, validators, bftExtraDataCodec), + Optional.empty()); } } diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java index 7ebfda0294f..c83f747f701 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java @@ -113,7 +113,8 @@ public BlockHeaderValidator.Builder createBlockHeaderRuleset( new ProtocolContext( blockchain, createInMemoryWorldStateArchive(), - setupContextWithBftExtraDataEncoder(initialValidatorList, bftExtraDataEncoder)); + setupContextWithBftExtraDataEncoder(initialValidatorList, bftExtraDataEncoder), + Optional.empty()); final GasPricePendingTransactionsSorter pendingTransactions = new GasPricePendingTransactionsSorter( diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java index 1fd93d61d97..54142aa8b4b 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java @@ -151,7 +151,8 @@ public void setup() { .thenReturn(futureRoundProposalMessageValidator); when(messageValidatorFactory.createMessageValidator(any(), any())).thenReturn(messageValidator); - protocolContext = new ProtocolContext(null, null, setupContextWithValidators(validators)); + protocolContext = + new ProtocolContext(null, null, setupContextWithValidators(validators), Optional.empty()); // Ensure the created IbftRound has the valid ConsensusRoundIdentifier; when(roundFactory.createNewRound(any(), anyInt())) diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundTest.java index 8023ff0a822..af5156e531e 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundTest.java @@ -106,7 +106,8 @@ public void setup() { new ProtocolContext( blockChain, worldStateArchive, - setupContextWithBftExtraDataEncoder(emptyList(), new IbftExtraDataCodec())); + setupContextWithBftExtraDataEncoder(emptyList(), new IbftExtraDataCodec()), + Optional.empty()); when(messageValidator.validateProposal(any())).thenReturn(true); when(messageValidator.validatePrepare(any())).thenReturn(true); diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/validation/MessageValidatorTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/validation/MessageValidatorTest.java index 909d30b73cb..9296f0419c8 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/validation/MessageValidatorTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/validation/MessageValidatorTest.java @@ -95,7 +95,10 @@ public void setup() { protocolContext = new ProtocolContext( - mock(MutableBlockchain.class), mock(WorldStateArchive.class), mockBftCtx); + mock(MutableBlockchain.class), + mock(WorldStateArchive.class), + mockBftCtx, + Optional.empty()); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java index 30f7709d59e..eaf83c3cef3 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java @@ -183,7 +183,8 @@ public void setUp() { .when(protocolSchedule) .getByBlockHeader(any(BlockHeader.class)); - protocolContext = new ProtocolContext(blockchain, worldStateArchive, mergeContext); + protocolContext = + new ProtocolContext(blockchain, worldStateArchive, mergeContext, Optional.empty()); var mutable = worldStateArchive.getMutable(); genesisState.writeStateTo(mutable); mutable.persist(null); diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java index de75bffd145..e4a1d7a4144 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java @@ -45,6 +45,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import org.junit.Before; @@ -69,7 +70,7 @@ public class MergeReorgTest implements MergeGenesisConfigHelper { private final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock()); private final ProtocolContext protocolContext = - new ProtocolContext(blockchain, worldStateArchive, mergeContext); + new ProtocolContext(blockchain, worldStateArchive, mergeContext, Optional.empty()); private final Address coinbase = genesisAllocations(getPowGenesisConfigFile()).findFirst().get(); private final BlockHeaderTestFixture headerGenerator = new BlockHeaderTestFixture(); diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java index 0a6337de71f..76c429d2124 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java +++ b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java @@ -456,7 +456,8 @@ private static ControllerAndState createControllerAndFinalState( new ProtocolContext( blockChain, worldStateArchive, - new QbftContext(validatorProvider, epochManager, blockInterface, Optional.empty())); + new QbftContext(validatorProvider, epochManager, blockInterface, Optional.empty()), + Optional.empty()); final GasPricePendingTransactionsSorter pendingTransactions = new GasPricePendingTransactionsSorter( diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java index 549717c59dc..cd3af6ac15b 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java +++ b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java @@ -55,6 +55,7 @@ import org.hyperledger.besu.util.Subscribers; import java.math.BigInteger; +import java.util.Optional; import org.apache.tuweni.bytes.Bytes; import org.junit.jupiter.api.BeforeEach; @@ -121,7 +122,8 @@ public void setup() { blockChain, worldStateArchive, setupContextWithBftExtraDataEncoder( - QbftContext.class, emptyList(), qbftExtraDataEncoder)); + QbftContext.class, emptyList(), qbftExtraDataEncoder), + Optional.empty()); } @Test diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactoryTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactoryTest.java index 8e7b1be6940..641e23db6fa 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactoryTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactoryTest.java @@ -45,7 +45,8 @@ private ProtocolContext protocolContext(final Collection
validators) { null, null, setupContextWithBftExtraDataEncoder( - QbftContext.class, validators, new QbftExtraDataCodec())); + QbftContext.class, validators, new QbftExtraDataCodec()), + Optional.empty()); } @Test diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftProtocolScheduleTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftProtocolScheduleTest.java index bb91477f795..b0fe45ed562 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftProtocolScheduleTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftProtocolScheduleTest.java @@ -57,7 +57,8 @@ private ProtocolContext protocolContext(final Collection
validators) { null, null, setupContextWithBftExtraDataEncoder( - QbftContext.class, validators, new QbftExtraDataCodec())); + QbftContext.class, validators, new QbftExtraDataCodec()), + Optional.empty()); } @Test diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/QbftValidatorsValidationRuleTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/QbftValidatorsValidationRuleTest.java index b225348f7f6..b006ccd3be0 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/QbftValidatorsValidationRuleTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/QbftValidatorsValidationRuleTest.java @@ -46,7 +46,8 @@ public void validationPassesIfValidatorsAndVoteAreEmpty() { new ProtocolContext( null, null, - setupContextWithBftExtraData(QbftContext.class, Collections.emptyList(), bftExtraData)); + setupContextWithBftExtraData(QbftContext.class, Collections.emptyList(), bftExtraData), + Optional.empty()); when(bftExtraData.getValidators()).thenReturn(Collections.emptyList()); when(bftExtraData.getVote()).thenReturn(Optional.empty()); assertThat(qbftValidatorsValidationRule.validate(blockHeader, null, context)).isTrue(); @@ -62,7 +63,10 @@ public void validationIsDelegatedWhenConstructorFlagIsFalse() { final ProtocolContext context = new ProtocolContext( - null, null, setupContextWithBftExtraData(QbftContext.class, validators, bftExtraData)); + null, + null, + setupContextWithBftExtraData(QbftContext.class, validators, bftExtraData), + Optional.empty()); when(bftExtraData.getValidators()).thenReturn(validators); assertThat(qbftValidatorsValidationRule.validate(blockHeader, null, context)).isTrue(); } @@ -77,7 +81,10 @@ public void validationFailsIfValidatorsAreNotEmpty() { final ProtocolContext context = new ProtocolContext( - null, null, setupContextWithBftExtraData(QbftContext.class, validators, bftExtraData)); + null, + null, + setupContextWithBftExtraData(QbftContext.class, validators, bftExtraData), + Optional.empty()); when(bftExtraData.getValidators()).thenReturn(validators); assertThat(qbftValidatorsValidationRule.validate(blockHeader, null, context)).isFalse(); } @@ -90,7 +97,8 @@ public void validationFailsIfVoteIsPresent() { new ProtocolContext( null, null, - setupContextWithBftExtraData(QbftContext.class, Collections.emptyList(), bftExtraData)); + setupContextWithBftExtraData(QbftContext.class, Collections.emptyList(), bftExtraData), + Optional.empty()); when(bftExtraData.getValidators()).thenReturn(Collections.emptyList()); when(bftExtraData.getVote()).thenReturn(Optional.of(mock(Vote.class))); assertThat(qbftValidatorsValidationRule.validate(blockHeader, null, context)).isFalse(); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java index da260140bff..669ed154e97 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java @@ -160,7 +160,8 @@ public void setup() { null, null, setupContextWithBftExtraDataEncoder( - QbftContext.class, validators, new QbftExtraDataCodec())); + QbftContext.class, validators, new QbftExtraDataCodec()), + Optional.empty()); // Ensure the created QbftRound has the valid ConsensusRoundIdentifier; when(roundFactory.createNewRound(any(), anyInt())) diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java index e3f58d5a7b6..2ac14e79b55 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java @@ -117,7 +117,8 @@ public void setup() { blockChain, worldStateArchive, setupContextWithBftExtraDataEncoder( - QbftContext.class, emptyList(), new QbftExtraDataCodec())); + QbftContext.class, emptyList(), new QbftExtraDataCodec()), + Optional.empty()); when(messageValidator.validateProposal(any())).thenReturn(true); when(messageValidator.validatePrepare(any())).thenReturn(true); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidatorTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidatorTest.java index f2359019bdf..fb8b67393d6 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidatorTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidatorTest.java @@ -86,7 +86,8 @@ public void setup() { new ProtocolContext( blockChain, worldStateArchive, - setupContextWithBftExtraDataEncoder(QbftContext.class, emptyList(), bftExtraDataCodec)); + setupContextWithBftExtraDataEncoder(QbftContext.class, emptyList(), bftExtraDataCodec), + Optional.empty()); } @Test @@ -239,7 +240,7 @@ public void validationForCmsFailsWhenCmsFailsValidation() { setupContextWithBftExtraDataEncoder(QbftContext.class, emptyList(), pkiQbftExtraDataCodec); final Bytes cms = Bytes.fromHexStringLenient("0x1"); final ProtocolContext protocolContext = - new ProtocolContext(blockChain, worldStateArchive, qbftContext); + new ProtocolContext(blockChain, worldStateArchive, qbftContext, Optional.empty()); final ProposalPayloadValidator payloadValidator = new ProposalPayloadValidator( @@ -274,7 +275,7 @@ public void validationForCmsPassesWhenCmsIsValid() { setupContextWithBftExtraDataEncoder(QbftContext.class, emptyList(), pkiQbftExtraDataCodec); final Bytes cms = Bytes.fromHexStringLenient("0x1"); final ProtocolContext protocolContext = - new ProtocolContext(blockChain, worldStateArchive, qbftContext); + new ProtocolContext(blockChain, worldStateArchive, qbftContext, Optional.empty()); final ProposalPayloadValidator payloadValidator = new ProposalPayloadValidator( diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidatorTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidatorTest.java index e63b59bb0fe..2c0b40c9d44 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidatorTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidatorTest.java @@ -98,7 +98,8 @@ public void setup() { blockChain, worldStateArchive, setupContextWithBftExtraDataEncoder( - QbftContext.class, emptyList(), bftExtraDataEncoder)); + QbftContext.class, emptyList(), bftExtraDataEncoder), + Optional.empty()); // typically tests require the blockValidation to be successful when(blockValidator.validateAndProcessBlock( diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidatorTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidatorTest.java index 2777f24b670..a604acc9026 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidatorTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidatorTest.java @@ -81,7 +81,8 @@ public void setup() { blockChain, worldStateArchive, setupContextWithBftExtraDataEncoder( - QbftContext.class, emptyList(), bftExtraDataEncoder)); + QbftContext.class, emptyList(), bftExtraDataEncoder), + Optional.empty()); } @Test diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java index 5df625a4a82..2a4021c7e96 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java @@ -76,7 +76,7 @@ public JsonRpcTestMethodsFactory(final BlockchainImporter importer) { this.blockchain = createInMemoryBlockchain(importer.getGenesisBlock()); this.stateArchive = createInMemoryWorldStateArchive(); this.importer.getGenesisState().writeStateTo(stateArchive.getMutable()); - this.context = new ProtocolContext(blockchain, stateArchive, null); + this.context = new ProtocolContext(blockchain, stateArchive, null, Optional.empty()); final ProtocolSchedule protocolSchedule = importer.getProtocolSchedule(); this.synchronizer = mock(Synchronizer.class); diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthGetBlockByNumberLatestDesyncIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthGetBlockByNumberLatestDesyncIntegrationTest.java index b9293d25de0..6d723844a2d 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthGetBlockByNumberLatestDesyncIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthGetBlockByNumberLatestDesyncIntegrationTest.java @@ -67,7 +67,7 @@ public static void setUpOnce() throws Exception { InMemoryKeyValueStorageProvider.createInMemoryBlockchain(importer.getGenesisBlock()); WorldStateArchive state = InMemoryKeyValueStorageProvider.createInMemoryWorldStateArchive(); importer.getGenesisState().writeStateTo(state.getMutable()); - ProtocolContext context = new ProtocolContext(chain, state, null); + ProtocolContext context = new ProtocolContext(chain, state, null, Optional.empty()); for (final Block block : importer.getBlocks()) { final ProtocolSchedule protocolSchedule = importer.getProtocolSchedule(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java index 7f41af9ab17..710c08f5558 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java @@ -112,7 +112,8 @@ public void setupTest() throws Exception { final MutableBlockchain blockchain = blockchainSetupUtil.getBlockchain(); ProtocolContext context = - new ProtocolContext(blockchain, blockchainSetupUtil.getWorldArchive(), null); + new ProtocolContext( + blockchain, blockchainSetupUtil.getWorldArchive(), null, Optional.empty()); final BlockchainQueries blockchainQueries = new BlockchainQueries( context.getBlockchain(), diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java index 6948140de4c..95736130b6f 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java @@ -306,7 +306,8 @@ private TransactionSelectionResults selectTransactions( dataGasPrice, protocolSpec.getFeeMarket(), protocolSpec.getGasCalculator(), - protocolSpec.getGasLimitCalculator()); + protocolSpec.getGasLimitCalculator(), + protocolContext.getTransactionSelectorFactory()); if (transactions.isPresent()) { return selector.evaluateTransactions(transactions.get()); diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java index bd3a836e26c..88a2fc4573d 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java @@ -18,12 +18,12 @@ import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.GasLimitCalculator; import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.core.LogsWrapper; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions; -import org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult; import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor; import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; @@ -34,14 +34,19 @@ import org.hyperledger.besu.ethereum.vm.BlockHashLookup; import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; import org.hyperledger.besu.evm.gascalculator.GasCalculator; +import org.hyperledger.besu.evm.log.Log; import org.hyperledger.besu.evm.worldstate.WorldUpdater; +import org.hyperledger.besu.plugin.data.TransactionSelectionResult; import org.hyperledger.besu.plugin.data.TransactionType; +import org.hyperledger.besu.plugin.services.txselection.TransactionSelector; +import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory; import java.util.ArrayList; import java.util.EnumMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.concurrent.CancellationException; import java.util.function.Function; import java.util.function.Supplier; @@ -221,8 +226,9 @@ public String toTraceLog() { private final FeeMarket feeMarket; private final GasCalculator gasCalculator; private final GasLimitCalculator gasLimitCalculator; + private final TransactionSelector transactionSelector; - private final TransactionSelectionResults transactionSelectionResult = + private final TransactionSelectionResults transactionSelectionResults = new TransactionSelectionResults(); public BlockTransactionSelector( @@ -239,7 +245,8 @@ public BlockTransactionSelector( final Wei dataGasPrice, final FeeMarket feeMarket, final GasCalculator gasCalculator, - final GasLimitCalculator gasLimitCalculator) { + final GasLimitCalculator gasLimitCalculator, + final Optional transactionSelectorFactory) { this.transactionProcessor = transactionProcessor; this.blockchain = blockchain; this.worldState = worldState; @@ -254,6 +261,8 @@ public BlockTransactionSelector( this.feeMarket = feeMarket; this.gasCalculator = gasCalculator; this.gasLimitCalculator = gasLimitCalculator; + this.transactionSelector = + transactionSelectorFactory.map(TransactionSelectorFactory::create).orElse(null); } /* @@ -270,14 +279,14 @@ public TransactionSelectionResults buildTransactionListForBlock() { pendingTransactions.selectTransactions( pendingTransaction -> { final var res = evaluateTransaction(pendingTransaction, false); - transactionSelectionResult.addSelectionResult(res); + transactionSelectionResults.addSelectionResult(res); return res; }); LOG.atTrace() - .setMessage("Transaction selection result {}") - .addArgument(transactionSelectionResult::toTraceLog) + .setMessage("Transaction selection result result {}") + .addArgument(transactionSelectionResults::toTraceLog) .log(); - return transactionSelectionResult; + return transactionSelectionResults; } /** @@ -289,8 +298,8 @@ public TransactionSelectionResults buildTransactionListForBlock() { public TransactionSelectionResults evaluateTransactions(final List transactions) { transactions.forEach( transaction -> - transactionSelectionResult.addSelectionResult(evaluateTransaction(transaction, true))); - return transactionSelectionResult; + transactionSelectionResults.addSelectionResult(evaluateTransaction(transaction, true))); + return transactionSelectionResults; } /* @@ -348,22 +357,55 @@ private TransactionSelectionResult evaluateTransaction( dataGasPrice); if (!effectiveResult.isInvalid()) { - worldStateUpdater.commit(); - LOG.atTrace() - .setMessage("Selected {} for block creation") - .addArgument(transaction::toTraceLog) - .log(); - updateTransactionResultTracking(transaction, effectiveResult); + + final long gasUsedByTransaction = + transaction.getGasLimit() - effectiveResult.getGasRemaining(); + + final long cumulativeGasUsed = + transactionSelectionResults.getCumulativeGasUsed() + gasUsedByTransaction; + + TransactionSelectionResult txSelectionResult = TransactionSelectionResult.SELECTED; + + if (transactionSelector != null) { + txSelectionResult = + transactionSelector.selectTransaction( + transaction, + effectiveResult.getStatus() == TransactionProcessingResult.Status.SUCCESSFUL, + getLogs(effectiveResult.getLogs()), + cumulativeGasUsed); + } + + if (txSelectionResult.equals(TransactionSelectionResult.SELECTED)) { + + worldStateUpdater.commit(); + final TransactionReceipt receipt = + transactionReceiptFactory.create( + transaction.getType(), effectiveResult, worldState, cumulativeGasUsed); + + final long dataGasUsed = gasCalculator.dataGasCost(transaction.getBlobCount()); + + transactionSelectionResults.update(transaction, receipt, gasUsedByTransaction, dataGasUsed); + + LOG.atTrace() + .setMessage("Selected {} for block creation") + .addArgument(transaction::toTraceLog) + .log(); + } + return txSelectionResult; } else { + final boolean isIncorrectNonce = isIncorrectNonce(effectiveResult.getValidationResult()); if (!isIncorrectNonce || reportFutureNonceTransactionsAsInvalid) { - transactionSelectionResult.updateWithInvalidTransaction( + transactionSelectionResults.updateWithInvalidTransaction( transaction, effectiveResult.getValidationResult()); } return transactionSelectionResultForInvalidResult( transaction, effectiveResult.getValidationResult()); } - return TransactionSelectionResult.SELECTED; + } + + private List getLogs(final List logs) { + return logs.stream().map(LogsWrapper::new).collect(Collectors.toList()); } private boolean transactionDataPriceBelowMin(final Transaction transaction) { @@ -430,28 +472,6 @@ private boolean isTransientValidationError(final TransactionInvalidReason invali || invalidReason.equals(TransactionInvalidReason.NONCE_TOO_HIGH); } - /* - Responsible for updating the state maintained between transaction validation (i.e. receipts, - cumulative gas, world state root hash.). - */ - private void updateTransactionResultTracking( - final Transaction transaction, final TransactionProcessingResult result) { - - final long gasUsedByTransaction = transaction.getGasLimit() - result.getGasRemaining(); - - final long cumulativeGasUsed = - transactionSelectionResult.getCumulativeGasUsed() + gasUsedByTransaction; - - final long dataGasUsed = gasCalculator.dataGasCost(transaction.getBlobCount()); - - transactionSelectionResult.update( - transaction, - transactionReceiptFactory.create( - transaction.getType(), result, worldState, cumulativeGasUsed), - gasUsedByTransaction, - dataGasUsed); - } - private boolean isIncorrectNonce(final ValidationResult result) { return result.getInvalidReason().equals(TransactionInvalidReason.NONCE_TOO_HIGH); } @@ -461,20 +481,21 @@ private boolean transactionTooLargeForBlock(final Transaction transaction) { if (dataGasUsed > gasLimitCalculator.currentDataGasLimit() - - transactionSelectionResult.getCumulativeDataGasUsed()) { + - transactionSelectionResults.getCumulativeDataGasUsed()) { return true; } return transaction.getGasLimit() + dataGasUsed - > processableBlockHeader.getGasLimit() - transactionSelectionResult.getCumulativeGasUsed(); + > processableBlockHeader.getGasLimit() - transactionSelectionResults.getCumulativeGasUsed(); } private boolean blockOccupancyAboveThreshold() { final long gasAvailable = processableBlockHeader.getGasLimit(); - final long gasUsed = transactionSelectionResult.getCumulativeGasUsed(); - final long gasRemaining = gasAvailable - gasUsed; + final long gasUsed = transactionSelectionResults.getCumulativeGasUsed(); + final long gasRemaining = gasAvailable - gasUsed; final double occupancyRatio = (double) gasUsed / (double) gasAvailable; + LOG.trace( "Min block occupancy ratio {}, gas used {}, available {}, remaining {}, used/available {}", minBlockOccupancyRatio, @@ -488,7 +509,8 @@ private boolean blockOccupancyAboveThreshold() { private boolean blockFull() { final long gasAvailable = processableBlockHeader.getGasLimit(); - final long gasUsed = transactionSelectionResult.getCumulativeGasUsed(); + final long gasUsed = transactionSelectionResults.getCumulativeGasUsed(); + final long gasRemaining = gasAvailable - gasUsed; if (gasRemaining < gasCalculator.getMinimumTransactionCost()) { diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java index 0c3d07333bd..cd7bdb87f6f 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java @@ -45,7 +45,6 @@ import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions; import org.hyperledger.besu.ethereum.eth.transactions.sorter.BaseFeePendingTransactionsSorter; import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; -import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionValidator; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; @@ -57,8 +56,10 @@ import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.worldstate.WorldState; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; +import org.hyperledger.besu.plugin.data.TransactionSelectionResult; import org.hyperledger.besu.plugin.data.TransactionType; import org.hyperledger.besu.plugin.services.MetricsSystem; +import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory; import org.hyperledger.besu.testutil.TestClock; import java.math.BigInteger; @@ -90,7 +91,6 @@ public abstract class AbstractBlockTransactionSelectorTest { protected PendingTransactions pendingTransactions; protected MutableWorldState worldState; @Mock protected MainnetTransactionProcessor transactionProcessor; - @Mock protected MainnetTransactionValidator transactionValidator; @Before public void setup() { @@ -286,7 +286,8 @@ public void useSingleGasSpaceForAllTransactions() { Wei.ZERO, FeeMarket.london(0L), new LondonGasCalculator(), - GasLimitCalculator.constant()); + GasLimitCalculator.constant(), + Optional.empty()); // this should fill up all the block space final Transaction fillingLegacyTx = @@ -561,6 +562,74 @@ public void shouldDiscardTransactionsThatFailValidation() { .isNotPresent(); } + @Test + public void transactionSelectionPluginShouldWork() { + final ProcessableBlockHeader blockHeader = createBlock(300); + + final TransactionTestFixture txTestFixture = new TransactionTestFixture(); + final Transaction selected = + txTestFixture + .nonce(1) + .gasLimit(1) + .createTransaction(SignatureAlgorithmFactory.getInstance().generateKeyPair()); + ensureTransactionIsValid(selected, 2000, 10000); + + final Transaction notSelectedTransient = + txTestFixture + .nonce(1) + .gasLimit(1) + .createTransaction(SignatureAlgorithmFactory.getInstance().generateKeyPair()); + ensureTransactionIsValid(notSelectedTransient, 2000, 10000); + + final Transaction notSelectedInvalid = + txTestFixture + .nonce(1) + .gasLimit(1) + .createTransaction(SignatureAlgorithmFactory.getInstance().generateKeyPair()); + ensureTransactionIsValid(notSelectedInvalid, 2000, 10000); + + final TransactionSelectorFactory transactionSelectorFactory = + (TransactionSelectorFactory) + () -> + (tx, s, logs, cg) -> { + if (tx.equals(notSelectedTransient)) + return TransactionSelectionResult.invalidTransient("transient"); + if (tx.equals(notSelectedInvalid)) + return TransactionSelectionResult.invalid("invalid"); + return TransactionSelectionResult.SELECTED; + }; + + final Address miningBeneficiary = AddressHelpers.ofValue(1); + final BlockTransactionSelector selector = + createBlockSelectorWithTxSelPlugin( + transactionProcessor, + blockHeader, + Wei.ZERO, + miningBeneficiary, + Wei.ZERO, + MIN_OCCUPANCY_80_PERCENT, + transactionSelectorFactory); + + pendingTransactions.addRemoteTransaction(selected, Optional.empty()); + pendingTransactions.addRemoteTransaction(notSelectedTransient, Optional.empty()); + pendingTransactions.addRemoteTransaction(notSelectedInvalid, Optional.empty()); + + final BlockTransactionSelector.TransactionSelectionResults transactionSelectionResults = + selector.buildTransactionListForBlock(); + + Assertions.assertThat(pendingTransactions.getTransactionByHash(notSelectedTransient.getHash())) + .isPresent(); + Assertions.assertThat(pendingTransactions.getTransactionByHash(notSelectedInvalid.getHash())) + .isNotPresent(); + // Assertions.assertThat(pendingTransactions.getTransactionByHash(selected.getHash())) + // .isNotPresent(); // TODO check with Fabio what should happen with selected txs + Assertions.assertThat(transactionSelectionResults.getTransactions()).contains(selected); + Assertions.assertThat(transactionSelectionResults.getTransactions()) + .doesNotContain(notSelectedTransient); + Assertions.assertThat(transactionSelectionResults.getTransactions()) + .doesNotContain(notSelectedInvalid); + } + @Test public void transactionWithIncorrectNonceRemainsInPoolAndNotSelected() { final ProcessableBlockHeader blockHeader = createBlock(5000); @@ -611,8 +680,39 @@ protected BlockTransactionSelector createBlockSelector( miningBeneficiary, dataGasPrice, getFeeMarket(), - getGasCalculator(), - GasLimitCalculator.constant()); + new LondonGasCalculator(), + GasLimitCalculator.constant(), + Optional.empty()); + + return selector; + } + + protected BlockTransactionSelector createBlockSelectorWithTxSelPlugin( + final MainnetTransactionProcessor transactionProcessor, + final ProcessableBlockHeader blockHeader, + final Wei minGasPrice, + final Address miningBeneficiary, + final Wei dataGasPrice, + final double minBlockOccupancyRatio, + final TransactionSelectorFactory transactionSelectorFactory) { + final BlockTransactionSelector selector = + new BlockTransactionSelector( + transactionProcessor, + blockchain, + worldState, + pendingTransactions, + blockHeader, + this::createReceipt, + minGasPrice, + minBlockOccupancyRatio, + this::isCancelled, + miningBeneficiary, + dataGasPrice, + getFeeMarket(), + new LondonGasCalculator(), + GasLimitCalculator.constant(), + Optional.of(transactionSelectorFactory)); + return selector; } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java index e687ab0b8b2..feb784f89e0 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java @@ -54,7 +54,7 @@ public void blockCreatedIsAddedToBlockChain() throws InterruptedException { new Block( headerBuilder.buildHeader(), new BlockBody(Lists.newArrayList(), Lists.newArrayList())); - final ProtocolContext protocolContext = new ProtocolContext(null, null, null); + final ProtocolContext protocolContext = new ProtocolContext(null, null, null, Optional.empty()); final PoWBlockCreator blockCreator = mock(PoWBlockCreator.class); final Function blockCreatorSupplier = @@ -95,7 +95,7 @@ public void failureToImportDoesNotTriggerObservers() throws InterruptedException new Block( headerBuilder.buildHeader(), new BlockBody(Lists.newArrayList(), Lists.newArrayList())); - final ProtocolContext protocolContext = new ProtocolContext(null, null, null); + final ProtocolContext protocolContext = new ProtocolContext(null, null, null, Optional.empty()); final PoWBlockCreator blockCreator = mock(PoWBlockCreator.class); final Function blockCreatorSupplier = diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/ProtocolContext.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/ProtocolContext.java index 1a8a80a8e25..8c0fc460dc2 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/ProtocolContext.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/ProtocolContext.java @@ -18,6 +18,7 @@ import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; +import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory; import java.util.Optional; @@ -30,6 +31,7 @@ public class ProtocolContext { private final MutableBlockchain blockchain; private final WorldStateArchive worldStateArchive; private final ConsensusContext consensusContext; + private final Optional transactionSelectorFactory; private Optional synchronizer; @@ -37,21 +39,32 @@ public ProtocolContext( final MutableBlockchain blockchain, final WorldStateArchive worldStateArchive, final ConsensusContext consensusContext) { + this(blockchain, worldStateArchive, consensusContext, Optional.empty()); + } + + public ProtocolContext( + final MutableBlockchain blockchain, + final WorldStateArchive worldStateArchive, + final ConsensusContext consensusContext, + final Optional transactionSelectorFactory) { this.blockchain = blockchain; this.worldStateArchive = worldStateArchive; this.consensusContext = consensusContext; this.synchronizer = Optional.empty(); + this.transactionSelectorFactory = transactionSelectorFactory; } public static ProtocolContext init( final MutableBlockchain blockchain, final WorldStateArchive worldStateArchive, final ProtocolSchedule protocolSchedule, - final ConsensusContextFactory consensusContextFactory) { + final ConsensusContextFactory consensusContextFactory, + final Optional transactionSelectorFactory) { return new ProtocolContext( blockchain, worldStateArchive, - consensusContextFactory.create(blockchain, worldStateArchive, protocolSchedule)); + consensusContextFactory.create(blockchain, worldStateArchive, protocolSchedule), + transactionSelectorFactory); } public Optional getSynchronizer() { @@ -79,4 +92,8 @@ public Optional safeConsensusContext(final Class .filter(c -> klass.isAssignableFrom(c.getClass())) .map(klass::cast); } + + public Optional getTransactionSelectorFactory() { + return transactionSelectorFactory; + } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/LogsWrapper.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/LogsWrapper.java new file mode 100644 index 00000000000..7ff9af5374d --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/LogsWrapper.java @@ -0,0 +1,48 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.ethereum.core; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.evm.log.Log; + +import java.util.List; + +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; + +public class LogsWrapper implements org.hyperledger.besu.plugin.data.Log { + + final Log delegate; + + public LogsWrapper(final Log delegate) { + this.delegate = delegate; + } + + @Override + public Address getLogger() { + return delegate.getLogger(); + } + + @Override + public List getTopics() { + return delegate.getTopics(); + } + + @Override + public Bytes getData() { + return delegate.getData(); + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java index a3a08c45a0d..cdb7a8829d1 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.core; -import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.mainnet.TransactionReceiptType; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; @@ -33,7 +32,6 @@ import com.google.common.base.MoreObjects; import org.apache.tuweni.bytes.Bytes; -import org.apache.tuweni.bytes.Bytes32; /** * A transaction receipt, containing information pertaining a transaction execution. @@ -370,27 +368,3 @@ public String toString() { .toString(); } } - -class LogsWrapper implements org.hyperledger.besu.plugin.data.Log { - - final Log delegate; - - LogsWrapper(final Log delegate) { - this.delegate = delegate; - } - - @Override - public Address getLogger() { - return delegate.getLogger(); - } - - @Override - public List getTopics() { - return delegate.getTopics(); - } - - @Override - public Bytes getData() { - return delegate.getData(); - } -} diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java index e2f40e81280..5b9fc1fb01a 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java @@ -48,6 +48,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; import com.google.common.base.Charsets; import com.google.common.io.Resources; @@ -151,7 +152,8 @@ private static ProtocolContext mainnetProtocolContextProvider( public C as(final Class klass) { return null; } - }); + }, + Optional.empty()); } private static BlockchainSetupUtil create( diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java index c2903e92fef..e712139f29c 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java @@ -34,6 +34,7 @@ import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; import java.math.BigInteger; +import java.util.Optional; import java.util.function.Function; public class ExecutionContextTestFixture { @@ -61,7 +62,7 @@ keyValueStorage, new MainnetBlockHeaderFunctions()), 0); this.stateArchive = createInMemoryWorldStateArchive(); this.protocolSchedule = protocolSchedule; - this.protocolContext = new ProtocolContext(blockchain, stateArchive, null); + this.protocolContext = new ProtocolContext(blockchain, stateArchive, null, Optional.empty()); genesisState.writeStateTo(stateArchive.getMutable()); } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java index 9e6bef815d8..79c11099e52 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java @@ -143,7 +143,7 @@ public void createStorage() { null); var ws = archive.getMutable(); genesisState.writeStateTo(ws); - protocolContext = new ProtocolContext(blockchain, archive, null); + protocolContext = new ProtocolContext(blockchain, archive, null, Optional.empty()); } // storage provider which uses a temporary directory based rocksdb diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactions.java index 338abdb8bbc..b8474d3d50b 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactions.java @@ -20,6 +20,7 @@ import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; import org.hyperledger.besu.evm.account.Account; +import org.hyperledger.besu.plugin.data.TransactionSelectionResult; import java.util.Collection; import java.util.List; diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java index c020882c76f..b936e3ce25a 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java @@ -32,11 +32,11 @@ import org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolReplacementHandler; -import org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.account.AccountState; import org.hyperledger.besu.metrics.BesuMetricCategory; +import org.hyperledger.besu.plugin.data.TransactionSelectionResult; import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.metrics.Counter; import org.hyperledger.besu.plugin.services.metrics.LabelledMetric; diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/AbstractBlockPropagationManagerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/AbstractBlockPropagationManagerTest.java index a2cc12dc329..25ff8ab4b46 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/AbstractBlockPropagationManagerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/AbstractBlockPropagationManagerTest.java @@ -65,6 +65,7 @@ import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; @@ -104,7 +105,8 @@ protected void setup(final DataStorageFormat dataStorageFormat) { new ProtocolContext( blockchain, tempProtocolContext.getWorldStateArchive(), - tempProtocolContext.getConsensusContext(ConsensusContext.class)); + tempProtocolContext.getConsensusContext(ConsensusContext.class), + Optional.empty()); ethProtocolManager = EthProtocolManagerTestUtil.create( protocolSchedule, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncTargetManagerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncTargetManagerTest.java index 495cbfd203d..29d9baca5e0 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncTargetManagerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncTargetManagerTest.java @@ -40,6 +40,7 @@ import java.util.Arrays; import java.util.Collection; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import org.junit.After; @@ -80,7 +81,7 @@ public void setup() { final ProtocolSchedule protocolSchedule = ProtocolScheduleFixture.MAINNET; final ProtocolContext protocolContext = - new ProtocolContext(localBlockchain, localWorldState, null); + new ProtocolContext(localBlockchain, localWorldState, null, Optional.empty()); ethProtocolManager = EthProtocolManagerTestUtil.create( protocolSchedule, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskParameterizedTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskParameterizedTest.java index b3abf90364a..74cddc5e569 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskParameterizedTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskParameterizedTest.java @@ -45,6 +45,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @@ -160,7 +161,7 @@ public void searchesAgainstNetwork() { final EthContext ethContext = ethProtocolManager.ethContext(); final ProtocolContext protocolContext = - new ProtocolContext(localBlockchain, worldStateArchive, null); + new ProtocolContext(localBlockchain, worldStateArchive, null, Optional.empty()); final EthTask task = DetermineCommonAncestorTask.create( diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskTest.java index 2976facbe6c..8e2fd6cbae0 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskTest.java @@ -54,6 +54,7 @@ import org.hyperledger.besu.util.ExceptionUtils; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; @@ -86,7 +87,8 @@ public void setup() { mock(TransactionPool.class), EthProtocolConfiguration.defaultConfig()); ethContext = ethProtocolManager.ethContext(); - protocolContext = new ProtocolContext(localBlockchain, worldStateArchive, null); + protocolContext = + new ProtocolContext(localBlockchain, worldStateArchive, null, Optional.empty()); } @Test diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java index 914536960e5..111fa072297 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java @@ -123,7 +123,7 @@ public TestNode( final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); genesisState.writeStateTo(worldStateArchive.getMutable()); final ProtocolContext protocolContext = - new ProtocolContext(blockchain, worldStateArchive, null); + new ProtocolContext(blockchain, worldStateArchive, null, Optional.empty()); final SyncState syncState = mock(SyncState.class); final SynchronizerConfiguration syncConfig = mock(SynchronizerConfiguration.class); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java index 294ddd7d0f0..4573a00b124 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java @@ -19,16 +19,16 @@ import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.ALREADY_KNOWN; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.NONCE_TOO_FAR_IN_FUTURE_FOR_SENDER; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.REJECTED_UNDERPRICED_REPLACEMENT; -import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.BLOCK_FULL; -import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.BLOCK_OCCUPANCY_ABOVE_THRESHOLD; -import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.CURRENT_TX_PRICE_BELOW_MIN; -import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.DATA_PRICE_BELOW_CURRENT_MIN; -import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.SELECTED; -import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.TX_TOO_LARGE_FOR_REMAINING_GAS; import static org.hyperledger.besu.ethereum.eth.transactions.layered.TransactionsLayer.RemovalReason.DROPPED; import static org.hyperledger.besu.ethereum.eth.transactions.layered.TransactionsLayer.RemovalReason.REPLACED; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.GAS_PRICE_BELOW_CURRENT_BASE_FEE; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE; +import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.BLOCK_FULL; +import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.BLOCK_OCCUPANCY_ABOVE_THRESHOLD; +import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.CURRENT_TX_PRICE_BELOW_MIN; +import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.DATA_PRICE_BELOW_CURRENT_MIN; +import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.SELECTED; +import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.TX_TOO_LARGE_FOR_REMAINING_GAS; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; @@ -47,9 +47,9 @@ import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolMetrics; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolReplacementHandler; -import org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; import org.hyperledger.besu.evm.account.Account; +import org.hyperledger.besu.plugin.data.TransactionSelectionResult; import java.util.ArrayList; import java.util.List; @@ -311,7 +311,7 @@ public void selectTransactionsUntilSelectorRequestsNoMore( } static Stream selectTransactionsUntilSelectorRequestsNoMore() { - return Stream.of(BLOCK_OCCUPANCY_ABOVE_THRESHOLD, BLOCK_FULL); + return Stream.of(BLOCK_OCCUPANCY_ABOVE_THRESHOLD, BLOCK_OCCUPANCY_ABOVE_THRESHOLD, BLOCK_FULL); } @Test diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsTestBase.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsTestBase.java index 45008d8bd5f..4c7b352f6cf 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsTestBase.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsTestBase.java @@ -18,7 +18,7 @@ import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.ADDED; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.ALREADY_KNOWN; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.REJECTED_UNDERPRICED_REPLACEMENT; -import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.SELECTED; +import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.SELECTED; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; @@ -40,10 +40,10 @@ import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactionDroppedListener; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; -import org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult; import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.metrics.StubMetricsSystem; +import org.hyperledger.besu.plugin.data.TransactionSelectionResult; import org.hyperledger.besu.testutil.TestClock; import java.time.Clock; diff --git a/ethereum/evmtool/txs.rlp b/ethereum/evmtool/txs.rlp new file mode 100644 index 00000000000..aee64da4068 --- /dev/null +++ b/ethereum/evmtool/txs.rlp @@ -0,0 +1 @@ +"0xf90620f860800a8307a12094000000000000000000000000000000000000010080801ca0f73b923883495dc2174285c8fa4176de3d45accfb11cc8034ea1dd09831a4ddfa01c6bccbcd655b4022bcc27de4b9d5cee9ce999cdb8459b0afec4f5054ea02243f860010a8307a12094000000000000000000000000000000000000010180801ba0bffca3f433f61c957d822af37f2b49c57700ff338588d51ea82dc9f720c91d9da0168bb65cc72d586384383f8ceef3a6a60e54b7f4aaa978a6dad271ced54b2ebff860020a8307a12094000000000000000000000000000000000000010280801ba03d9f110bcf0c44be552d4d0ec8387b705604f7d3bb3794dcef4004c38963103ea013bda734f3b5987b8c855f6aab046754506266ff32352ba0898c4eba4acaec8bf860030a8307a12094000000000000000000000000000000000000010380801ba0ecb276d2486664ea779813e599b6f07b7b0df746626d7fdddf60ea425efcb324a0739841682e79a8302dc2e146dfd1eecbdc611d386d42287bcdd94a39bf536020f860040a8307a12094000000000000000000000000000000000000010480801ba002866b5c5fa5dbfa3d88b71a49b82a779c2d508cda631893176782dbcd7435aaa003c380a9af9bfdb3503abcfd5037d3c66f39bb7a19011a3291712d22292c5236f860050a8307a12094000000000000000000000000000000000000010580801ca0c70d2e000e503933d0f1a9a923dc647924811a912adf77692ff7d8f6808d5617a04ad82c92b980580a4a67e4c405e83d560a14201c3fd4b3a42d34dcc19336479af860060a8307a12094000000000000000000000000000000000000010680801ca07f2527f8cbe14e021d270dd214a1820355c7af128001889f57b7f9bba46a6c5da03033308de0d39b9d1b47d28f81df39ceaff330349298c65deb836efe8bce273ff860070a8307a12094000000000000000000000000000000000000010780801ba0ecb720a8764f8967b95dc66e961c6261fceb392c0e90461d7d66113d3c8bbd12a02655e28b751cc2e03a835aa817d884b540765dba12968bc53f53737b4234ee21f860080a8307a12094000000000000000000000000000000000000010880801ba095a2e27c0b296679141c0ad61be112f689b134c04d1773814ddae67fefb2dfbda02955f126d57d8b9777f47c520ffe4285890ca2dd1189e67b3407d6369997e7ecf860090a8307a12094000000000000000000000000000000000000010980801ca02468a120d0ee8c57caac354f56842a1db10813169a328f9f852279668b573907a03971f4c2e6bc0aa666812712719199df6fe37c0e1e122131cdb47d6c0c77b371f8600a0a8307a12094000000000000000000000000000000000000010a80801ba0a3a2018ab0bc2695b94bb85d710f4d07132a94f8c3e0f385824da5fee11899a5a00d2dfe430ea5aaff3de8bbb9339e7485474c8e4e34636f787124a7a91e4d6d6af8600b0a8307a12094000000000000000000000000000000000000010b80801ba0b91968fdb3aecea26094ec30649daa4de81a875bcb1a123e732b8f3f112ce232a02ef8cd85969d8bcef5f4ee1f5d20783b8d9b7466726c15ebf911565825187665f8600c0a8307a12094000000000000000000000000000000000000010c80801ca0dd27e75aa990793205805c22265b04be8299b208fad4f37a7f652ecf32b67390a05aa8cda18521548ff8f95e88f49f309d05cab32de28a0942b8a7a824c50df459f8600d0a8307a12094000000000000000000000000000000000000010d80801ba0fad07ce7139dd4e00266194e6a51c048f74eaba3c0a1b03ece378a810abfaa63a04fec880dafaa5382797b4f88b16138b1f0c4e084817072c77ff9bf17ddd4ac26f8600e0a8307a12094000000000000000000000000000000000000010e80801ca0208b22ab245221bdc5cae6586d2ef019a2c37be41166e04b8abe354c41a8f5b6a032d5d6ef07731cd1684531c775c1727ef6ba75de18cda96d998aaa0c1db0bd68f8600f0a8307a12094000000000000000000000000000000000000010f80801ba0055225ffd3d8b2d19c32aa68cb46e7b52c1d99844fb8b7a53b922ea1649e9c5ba06ae2a1e3b9712354b706d0f4da6ea76ed2f8f75277a51a14a3e0ccf25b85c626" diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java index 55eec26fd2f..0cdb6854853 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java @@ -106,7 +106,8 @@ public BlockchainReferenceTestCaseSpec( this.worldStateArchive = buildWorldStateArchive(accounts); this.blockchain = buildBlockchain(genesisBlockHeader); this.sealEngine = sealEngine; - this.protocolContext = new ProtocolContext(this.blockchain, this.worldStateArchive, null); + this.protocolContext = + new ProtocolContext(this.blockchain, this.worldStateArchive, null, Optional.empty()); } public String getNetwork() { diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java index 62c8b031a2c..bbfb1fba786 100644 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java +++ b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java @@ -168,7 +168,7 @@ private boolean buildContext( genesisState.writeStateTo(worldState); blockchain = createInMemoryBlockchain(genesisState.getBlock()); - protocolContext = new ProtocolContext(blockchain, worldStateArchive, null); + protocolContext = new ProtocolContext(blockchain, worldStateArchive, null, Optional.empty()); blockchainQueries = new BlockchainQueries(blockchain, worldStateArchive, ethScheduler); diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index 442dd5f7856..76752c66f74 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -69,7 +69,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'WC7tcTTrQg//+cIarm7NSabnxm6nY0lLkHWOH6+7Rmo=' + knownHash = 'gfED3Pzd/+CSSrTtDo1X+lkc7qwffDqF98EZIDMCOIc=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionSelectionResult.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/TransactionSelectionResult.java similarity index 99% rename from plugin-api/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionSelectionResult.java rename to plugin-api/src/main/java/org/hyperledger/besu/plugin/data/TransactionSelectionResult.java index 94e0b214f55..73e31176f81 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionSelectionResult.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/TransactionSelectionResult.java @@ -13,7 +13,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.ethereum.eth.transactions; +package org.hyperledger.besu.plugin.data; import java.util.Objects; import java.util.Optional; diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/TransactionSelectionService.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/TransactionSelectionService.java new file mode 100644 index 00000000000..1a46e71f306 --- /dev/null +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/TransactionSelectionService.java @@ -0,0 +1,40 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.plugin.services; + +import org.hyperledger.besu.plugin.Unstable; +import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory; + +import java.util.Optional; + +/** Transaction selection service interface */ +@Unstable +public interface TransactionSelectionService extends BesuService { + + /** + * Returns the (Optional) transaction selector factory + * + * @return the transaction selector factory + */ + Optional get(); + + /** + * Registers the transaction selector factory with the service + * + * @param transactionSelectorFactory transaction selector factory to be used + */ + void registerTransactionSelectorFactory(TransactionSelectorFactory transactionSelectorFactory); +} diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txselection/TransactionSelector.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txselection/TransactionSelector.java new file mode 100644 index 00000000000..e48684640c0 --- /dev/null +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txselection/TransactionSelector.java @@ -0,0 +1,44 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.plugin.services.txselection; + +import org.hyperledger.besu.plugin.Unstable; +import org.hyperledger.besu.plugin.data.Log; +import org.hyperledger.besu.plugin.data.Transaction; +import org.hyperledger.besu.plugin.data.TransactionSelectionResult; + +import java.util.List; + +/** Interface for the transaction selector */ +@Unstable +public interface TransactionSelector { + + /** + * Method called to decide whether a transaction is added to a block. The method can also indicate + * that no further transactions can be added to the block. + * + * @param transaction candidate transaction + * @param success true, if the transaction executed successfully + * @param logs the logs created by this transaction + * @param cumulativeGasUsed gas used by this and all previous transaction in the block + * @return TransactionSelectionResult that indicates whether to include the transaction + */ + TransactionSelectionResult selectTransaction( + final Transaction transaction, + final boolean success, + final List logs, + final long cumulativeGasUsed); +} diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txselection/TransactionSelectorFactory.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txselection/TransactionSelectorFactory.java new file mode 100644 index 00000000000..1d4234acc9e --- /dev/null +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txselection/TransactionSelectorFactory.java @@ -0,0 +1,30 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.plugin.services.txselection; + +import org.hyperledger.besu.plugin.Unstable; + +/** Interface for a factory that creates transaction selectors */ +@Unstable +public interface TransactionSelectorFactory { + + /** + * Create a transaction selector + * + * @return the transaction selector + */ + TransactionSelector create(); +} From b401963a117d0bcb64436b72deae059d71529878 Mon Sep 17 00:00:00 2001 From: garyschulte Date: Fri, 2 Jun 2023 11:38:41 -0700 Subject: [PATCH 16/35] Prevent rocksdb segfaults when accessing closed storage (#5527) * add isClosed check to Transaction decorator to prevent segfaults on shutdown Signed-off-by: garyschulte --- CHANGELOG.md | 1 + .../methods/ExecutionEngineJsonRpcMethod.java | 17 +++++++--- plugin-api/build.gradle | 2 +- .../services/storage/KeyValueStorage.java | 7 ++++ ...imisticRocksDBColumnarKeyValueStorage.java | 2 +- .../RocksDBColumnarKeyValueSnapshot.java | 5 +++ .../RocksDBColumnarKeyValueStorage.java | 9 ++++- .../segmented/RocksDBSnapshotTransaction.java | 33 ++++++++++--------- ...ctionDBRocksDBColumnarKeyValueStorage.java | 2 +- .../unsegmented/RocksDBKeyValueStorage.java | 8 +++++ .../kvstore/InMemoryKeyValueStorage.java | 5 +++ .../kvstore/LayeredKeyValueStorage.java | 24 ++++++++++++++ .../LimitedInMemoryKeyValueStorage.java | 5 +++ .../kvstore/SegmentedKeyValueStorage.java | 7 ++++ .../SegmentedKeyValueStorageAdapter.java | 27 +++++++++++++++ ...ansactionTransitionValidatorDecorator.java | 11 ++++++- 16 files changed, 141 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc11f9f18f9..771b5799006 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Unite the tx-pool CLI options under the same Tx Pool Options group in UX. [#5466](https://github.com/hyperledger/besu/issues/5466) ### Bug Fixes +- check to ensure storage and transactions are not closed prior to reading/writing [#5527](https://github.com/hyperledger/besu/pull/5527) ### Download Links diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecutionEngineJsonRpcMethod.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecutionEngineJsonRpcMethod.java index a4e439db566..78442732c0c 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecutionEngineJsonRpcMethod.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecutionEngineJsonRpcMethod.java @@ -77,14 +77,23 @@ public final JsonRpcResponse response(final JsonRpcRequestContext request) { cf.complete( resp.otherwise( t -> { - LOG.error( - String.format("failed to exec consensus method %s", this.getName()), - t); + if (LOG.isDebugEnabled()) { + LOG.atDebug() + .setMessage("failed to exec consensus method {}") + .addArgument(this.getName()) + .setCause(t) + .log(); + } else { + LOG.atError() + .setMessage("failed to exec consensus method {}, error: {}") + .addArgument(this.getName()) + .addArgument(t.getMessage()) + .log(); + } return new JsonRpcErrorResponse( request.getRequest().getId(), JsonRpcError.INVALID_REQUEST); }) .result())); - try { return cf.get(); } catch (InterruptedException e) { diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index 76752c66f74..04784c42482 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -69,7 +69,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'gfED3Pzd/+CSSrTtDo1X+lkc7qwffDqF98EZIDMCOIc=' + knownHash = 'V3sh575rrexPv+Ywe8mURT4Z3fREDCDd79PpAISFx8A=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/KeyValueStorage.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/KeyValueStorage.java index a4917a07fc7..71fc65d6988 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/KeyValueStorage.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/KeyValueStorage.java @@ -114,4 +114,11 @@ public interface KeyValueStorage extends Closeable { * @throws StorageException problem encountered when starting a new transaction. */ KeyValueStorageTransaction startTransaction() throws StorageException; + + /** + * Return Whether the underlying storage is closed. + * + * @return boolean indicating whether the storage is closed. + */ + boolean isClosed(); } diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/OptimisticRocksDBColumnarKeyValueStorage.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/OptimisticRocksDBColumnarKeyValueStorage.java index 4713bb01eb0..5fc8b3c1790 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/OptimisticRocksDBColumnarKeyValueStorage.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/OptimisticRocksDBColumnarKeyValueStorage.java @@ -81,7 +81,7 @@ public Transaction startTransaction() throws StorageEx final WriteOptions writeOptions = new WriteOptions(); writeOptions.setIgnoreMissingColumnFamilies(true); return new SegmentedKeyValueStorageTransactionTransitionValidatorDecorator<>( - new RocksDbTransaction(db.beginTransaction(writeOptions), writeOptions)); + new RocksDbTransaction(db.beginTransaction(writeOptions), writeOptions), this.closed::get); } /** diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueSnapshot.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueSnapshot.java index 1c40716f43a..574ece91762 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueSnapshot.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueSnapshot.java @@ -108,6 +108,11 @@ public KeyValueStorageTransaction startTransaction() throws StorageException { return snapTx; } + @Override + public boolean isClosed() { + return closed.get(); + } + @Override public void clear() { throw new UnsupportedOperationException( diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java index 0e98c31c4d3..cdca868a27e 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java @@ -87,7 +87,9 @@ public abstract class RocksDBColumnarKeyValueStorage RocksDbUtil.loadNativeLibrary(); } - private final AtomicBoolean closed = new AtomicBoolean(false); + /** atomic boolean to track if the storage is closed */ + protected final AtomicBoolean closed = new AtomicBoolean(false); + private final WriteOptions tryDeleteOptions = new WriteOptions().setNoSlowdown(true).setIgnoreMissingColumnFamilies(true); private final ReadOptions readOptions = new ReadOptions().setVerifyChecksums(false); @@ -328,6 +330,11 @@ public void close() { } } + @Override + public boolean isClosed() { + return closed.get(); + } + void throwIfClosed() { if (closed.get()) { LOG.error("Attempting to use a closed RocksDbKeyValueStorage"); diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBSnapshotTransaction.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBSnapshotTransaction.java index a3d31cb2a41..dbe460b3ffb 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBSnapshotTransaction.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBSnapshotTransaction.java @@ -93,10 +93,7 @@ private RocksDBSnapshotTransaction( * @return the optional data */ public Optional get(final byte[] key) { - if (isClosed.get()) { - LOG.debug("Attempted to access closed snapshot"); - return Optional.empty(); - } + throwIfClosed(); try (final OperationTimer.TimingContext ignored = metrics.getReadLatency().startTimer()) { return Optional.ofNullable(snapTx.get(columnFamilyHandle, readOptions, key)); @@ -107,10 +104,7 @@ public Optional get(final byte[] key) { @Override public void put(final byte[] key, final byte[] value) { - if (isClosed.get()) { - LOG.debug("Attempted to access closed snapshot"); - return; - } + throwIfClosed(); try (final OperationTimer.TimingContext ignored = metrics.getWriteLatency().startTimer()) { snapTx.put(columnFamilyHandle, key, value); @@ -125,10 +119,8 @@ public void put(final byte[] key, final byte[] value) { @Override public void remove(final byte[] key) { - if (isClosed.get()) { - LOG.debug("Attempted to access closed snapshot"); - return; - } + throwIfClosed(); + try (final OperationTimer.TimingContext ignored = metrics.getRemoveLatency().startTimer()) { snapTx.delete(columnFamilyHandle, key); } catch (final RocksDBException e) { @@ -146,6 +138,8 @@ public void remove(final byte[] key) { * @return the stream */ public Stream> stream() { + throwIfClosed(); + final RocksIterator rocksIterator = db.newIterator(columnFamilyHandle, readOptions); rocksIterator.seekToFirst(); return RocksDbIterator.create(rocksIterator).toStream(); @@ -157,6 +151,8 @@ public Stream> stream() { * @return the stream */ public Stream streamKeys() { + throwIfClosed(); + final RocksIterator rocksIterator = db.newIterator(columnFamilyHandle, readOptions); rocksIterator.seekToFirst(); return RocksDbIterator.create(rocksIterator).toStreamKeys(); @@ -169,6 +165,8 @@ public void commit() throws StorageException { @Override public void rollback() { + throwIfClosed(); + try { snapTx.rollback(); metrics.getRollbackCount().inc(); @@ -189,9 +187,7 @@ public void rollback() { * @return the rocks db snapshot transaction */ public RocksDBSnapshotTransaction copy() { - if (isClosed.get()) { - throw new StorageException("Snapshot already closed"); - } + throwIfClosed(); try { var copyReadOptions = new ReadOptions().setSnapshot(snapshot.markAndUseSnapshot()); var copySnapTx = db.beginTransaction(writeOptions); @@ -213,4 +209,11 @@ public void close() { snapshot.unMarkSnapshot(); isClosed.set(true); } + + private void throwIfClosed() { + if (isClosed.get()) { + LOG.error("Attempting to use a closed RocksDBSnapshotTransaction"); + throw new StorageException("Storage has already been closed"); + } + } } diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/TransactionDBRocksDBColumnarKeyValueStorage.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/TransactionDBRocksDBColumnarKeyValueStorage.java index 9dc0cfb6ba7..b6433ad19e7 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/TransactionDBRocksDBColumnarKeyValueStorage.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/TransactionDBRocksDBColumnarKeyValueStorage.java @@ -86,6 +86,6 @@ public Transaction startTransaction() throws StorageEx final WriteOptions writeOptions = new WriteOptions(); writeOptions.setIgnoreMissingColumnFamilies(true); return new SegmentedKeyValueStorageTransactionTransitionValidatorDecorator<>( - new RocksDbTransaction(db.beginTransaction(writeOptions), writeOptions)); + new RocksDbTransaction(db.beginTransaction(writeOptions), writeOptions), this.closed::get); } } diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/unsegmented/RocksDBKeyValueStorage.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/unsegmented/RocksDBKeyValueStorage.java index e75a1b969cc..579c8324997 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/unsegmented/RocksDBKeyValueStorage.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/unsegmented/RocksDBKeyValueStorage.java @@ -97,6 +97,7 @@ public RocksDBKeyValueStorage( @Override public void clear() throws StorageException { throwIfClosed(); + try (final RocksIterator rocksIterator = db.newIterator()) { rocksIterator.seekToFirst(); if (rocksIterator.isValid()) { @@ -141,6 +142,7 @@ public Set getAllKeysThat(final Predicate returnCondition) { @Override public Stream> stream() { throwIfClosed(); + final RocksIterator rocksIterator = db.newIterator(); rocksIterator.seekToFirst(); return RocksDbIterator.create(rocksIterator).toStream(); @@ -149,6 +151,7 @@ public Stream> stream() { @Override public Stream streamKeys() { throwIfClosed(); + final RocksIterator rocksIterator = db.newIterator(); rocksIterator.seekToFirst(); return RocksDbIterator.create(rocksIterator).toStreamKeys(); @@ -186,6 +189,11 @@ public KeyValueStorageTransaction startTransaction() throws StorageException { new RocksDBTransaction(db.beginTransaction(options), options, rocksDBMetrics)); } + @Override + public boolean isClosed() { + return closed.get(); + } + @Override public void close() { if (closed.compareAndSet(false, true)) { diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java index 627313f71b5..d5b5fdaed9e 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/InMemoryKeyValueStorage.java @@ -154,6 +154,11 @@ public KeyValueStorageTransaction startTransaction() { return new KeyValueStorageTransactionTransitionValidatorDecorator(new InMemoryTransaction()); } + @Override + public boolean isClosed() { + return false; + } + /** * Key set. * diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorage.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorage.java index b8144e8bba9..1c12dc4c949 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorage.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LayeredKeyValueStorage.java @@ -30,11 +30,15 @@ import com.google.common.collect.Streams; import org.apache.commons.lang3.tuple.Pair; import org.apache.tuweni.bytes.Bytes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** Key value storage which stores in memory all updates to a parent worldstate storage. */ public class LayeredKeyValueStorage extends InMemoryKeyValueStorage implements SnappedKeyValueStorage { + private static final Logger LOG = LoggerFactory.getLogger(LayeredKeyValueStorage.class); + private final KeyValueStorage parent; /** @@ -65,6 +69,8 @@ public boolean containsKey(final byte[] key) throws StorageException { @Override public Optional get(final byte[] key) throws StorageException { + throwIfClosed(); + final Lock lock = rwLock.readLock(); lock.lock(); try { @@ -82,6 +88,8 @@ public Optional get(final byte[] key) throws StorageException { @Override public Stream> stream() { + throwIfClosed(); + final Lock lock = rwLock.readLock(); lock.lock(); try { @@ -104,6 +112,8 @@ public Stream> stream() { @Override public Stream streamKeys() { + throwIfClosed(); + final Lock lock = rwLock.readLock(); lock.lock(); try { @@ -131,6 +141,8 @@ public boolean tryDelete(final byte[] key) { @Override public KeyValueStorageTransaction startTransaction() { + throwIfClosed(); + return new KeyValueStorageTransactionTransitionValidatorDecorator( new InMemoryTransaction() { @Override @@ -151,8 +163,20 @@ public void commit() throws StorageException { }); } + @Override + public boolean isClosed() { + return parent.isClosed(); + } + @Override public SnappedKeyValueStorage clone() { return new LayeredKeyValueStorage(hashValueStore, parent); } + + private void throwIfClosed() { + if (parent.isClosed()) { + LOG.error("Attempting to use a closed RocksDBKeyValueStorage"); + throw new StorageException("Storage has been closed"); + } + } } diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LimitedInMemoryKeyValueStorage.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LimitedInMemoryKeyValueStorage.java index cca8d84cc48..19ee9868e36 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LimitedInMemoryKeyValueStorage.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/LimitedInMemoryKeyValueStorage.java @@ -144,6 +144,11 @@ public KeyValueStorageTransaction startTransaction() throws StorageException { return new KeyValueStorageTransactionTransitionValidatorDecorator(new MemoryTransaction()); } + @Override + public boolean isClosed() { + return false; + } + private class MemoryTransaction implements KeyValueStorageTransaction { private Map updatedValues = new HashMap<>(); diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorage.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorage.java index 90af6053853..54e8564d88f 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorage.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorage.java @@ -123,6 +123,13 @@ default boolean containsKey(final S segment, final byte[] key) throws StorageExc */ void clear(S segmentHandle); + /** + * Whether the underlying storage is closed. + * + * @return boolean indicating whether the underlying storage is closed. + */ + boolean isClosed(); + /** * Represents a set of changes to be committed atomically. A single transaction is not * thread-safe, but multiple transactions can execute concurrently. diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorageAdapter.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorageAdapter.java index 2f92805350c..6504b188508 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorageAdapter.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorageAdapter.java @@ -26,6 +26,8 @@ import java.util.stream.Stream; import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The type Segmented key value storage adapter. @@ -34,6 +36,7 @@ */ public class SegmentedKeyValueStorageAdapter implements KeyValueStorage { + private static final Logger LOG = LoggerFactory.getLogger(SegmentedKeyValueStorageAdapter.class); private final S segmentHandle; private final SegmentedKeyValueStorage storage; @@ -51,41 +54,49 @@ public SegmentedKeyValueStorageAdapter( @Override public void clear() { + throwIfClosed(); storage.clear(segmentHandle); } @Override public boolean containsKey(final byte[] key) throws StorageException { + throwIfClosed(); return storage.containsKey(segmentHandle, key); } @Override public Optional get(final byte[] key) throws StorageException { + throwIfClosed(); return storage.get(segmentHandle, key); } @Override public Set getAllKeysThat(final Predicate returnCondition) { + throwIfClosed(); return storage.getAllKeysThat(segmentHandle, returnCondition); } @Override public Set getAllValuesFromKeysThat(final Predicate returnCondition) { + throwIfClosed(); return storage.getAllValuesFromKeysThat(segmentHandle, returnCondition); } @Override public Stream> stream() { + throwIfClosed(); return storage.stream(segmentHandle); } @Override public Stream streamKeys() { + throwIfClosed(); return storage.streamKeys(segmentHandle); } @Override public boolean tryDelete(final byte[] key) { + throwIfClosed(); return storage.tryDelete(segmentHandle, key); } @@ -101,23 +112,39 @@ public KeyValueStorageTransaction startTransaction() throws StorageException { @Override public void put(final byte[] key, final byte[] value) { + throwIfClosed(); transaction.put(segmentHandle, key, value); } @Override public void remove(final byte[] key) { + throwIfClosed(); transaction.remove(segmentHandle, key); } @Override public void commit() throws StorageException { + throwIfClosed(); transaction.commit(); } @Override public void rollback() { + throwIfClosed(); transaction.rollback(); } }; } + + @Override + public boolean isClosed() { + return storage.isClosed(); + } + + private void throwIfClosed() { + if (storage.isClosed()) { + LOG.error("Attempting to use a closed Storage instance."); + throw new StorageException("Storage has been closed"); + } + } } diff --git a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorageTransactionTransitionValidatorDecorator.java b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorageTransactionTransitionValidatorDecorator.java index fd9bb4de952..53cacb13e1b 100644 --- a/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorageTransactionTransitionValidatorDecorator.java +++ b/services/kvstore/src/main/java/org/hyperledger/besu/services/kvstore/SegmentedKeyValueStorageTransactionTransitionValidatorDecorator.java @@ -19,6 +19,8 @@ import org.hyperledger.besu.plugin.services.exception.StorageException; import org.hyperledger.besu.services.kvstore.SegmentedKeyValueStorage.Transaction; +import java.util.function.Supplier; + /** * The Segmented key value storage transaction transition validator decorator. * @@ -28,33 +30,39 @@ public class SegmentedKeyValueStorageTransactionTransitionValidatorDecorator implements Transaction { private final Transaction transaction; + private final Supplier isClosed; private boolean active = true; /** * Instantiates a new Segmented key value storage transaction transition validator decorator. * * @param toDecorate the to decorate + * @param isClosed supplier that returns true if the storage is closed */ public SegmentedKeyValueStorageTransactionTransitionValidatorDecorator( - final Transaction toDecorate) { + final Transaction toDecorate, final Supplier isClosed) { this.transaction = toDecorate; + this.isClosed = isClosed; } @Override public final void put(final S segment, final byte[] key, final byte[] value) { checkState(active, "Cannot invoke put() on a completed transaction."); + checkState(!isClosed.get(), "Cannot invoke put() on a closed storage."); transaction.put(segment, key, value); } @Override public final void remove(final S segment, final byte[] key) { checkState(active, "Cannot invoke remove() on a completed transaction."); + checkState(!isClosed.get(), "Cannot invoke remove() on a closed storage."); transaction.remove(segment, key); } @Override public final void commit() throws StorageException { checkState(active, "Cannot commit a completed transaction."); + checkState(!isClosed.get(), "Cannot invoke commit() on a closed storage."); active = false; transaction.commit(); } @@ -62,6 +70,7 @@ public final void commit() throws StorageException { @Override public final void rollback() { checkState(active, "Cannot rollback a completed transaction."); + checkState(!isClosed.get(), "Cannot invoke rollback() on a closed storage."); active = false; transaction.rollback(); } From bacef2809e799e4ee443cddeb82ff94791b1673c Mon Sep 17 00:00:00 2001 From: matkt Date: Sat, 3 Jun 2023 18:43:24 +0200 Subject: [PATCH 17/35] Update get account method in the bonsai accumulator (#5330) Signed-off-by: Karim TAAM --- .../pojoadapter/BlockAdapterBase.java | 29 ++++---- .../pojoadapter/PendingStateAdapter.java | 33 ++++----- .../methods/AbstractTraceByBlock.java | 4 +- .../api/jsonrpc/internal/methods/EthCall.java | 31 ++++---- .../jsonrpc/internal/methods/TraceCall.java | 53 +++++++------- .../internal/methods/TraceCallMany.java | 2 +- .../internal/methods/TraceRawTransaction.java | 59 ++++++++------- .../jsonrpc/internal/methods/EthCallTest.java | 73 +++++++++++++------ .../BonsaiWorldStateUpdateAccumulator.java | 2 +- .../transaction/PreCloseStateHandler.java | 54 ++++++++++++++ .../transaction/TransactionSimulator.java | 61 +++++++++++----- 11 files changed, 250 insertions(+), 151 deletions(-) create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/PreCloseStateHandler.java diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java index 2b8251ce858..c0f5c320ec8 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java @@ -31,7 +31,6 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.transaction.CallParameter; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; -import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult; import org.hyperledger.besu.evm.log.LogTopic; import org.hyperledger.besu.evm.tracing.OperationTracer; @@ -247,20 +246,20 @@ private Optional executeCall(final DataFetchingEnvironment environme .from(TransactionValidationParams.transactionSimulator()); transactionValidationParams.isAllowExceedingBalance(true); - final Optional opt = - transactionSimulator.process( - param, transactionValidationParams.build(), OperationTracer.NO_TRACING, bn); - if (opt.isPresent()) { - final TransactionSimulatorResult result = opt.get(); - long status = 0; - if (result.isSuccessful()) { - status = 1; - } - final CallResult callResult = - new CallResult(status, result.getGasEstimate(), result.getOutput()); - return Optional.of(callResult); - } - return Optional.empty(); + return transactionSimulator.process( + param, + transactionValidationParams.build(), + OperationTracer.NO_TRACING, + (mutableWorldState, transactionSimulatorResult) -> + transactionSimulatorResult.map( + result -> { + long status = 0; + if (result.isSuccessful()) { + status = 1; + } + return new CallResult(status, result.getGasEstimate(), result.getOutput()); + }), + header); } Bytes getRawHeader() { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java index fbdfb54ae2c..d6eb3ae64d6 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java @@ -26,7 +26,6 @@ import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.transaction.CallParameter; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; -import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult; import org.hyperledger.besu.evm.tracing.OperationTracer; import java.util.List; @@ -118,23 +117,19 @@ public Optional getCall(final DataFetchingEnvironment environment) { .from(TransactionValidationParams.transactionSimulator()); transactionValidationParams.isAllowExceedingBalance(true); - final Optional opt = - transactionSimulator.process( - param, - transactionValidationParams.build(), - OperationTracer.NO_TRACING, - query.getBlockchain().getChainHeadHeader()); - - if (opt.isPresent()) { - final TransactionSimulatorResult result = opt.get(); - long status = 0; - if (result.isSuccessful()) { - status = 1; - } - final CallResult callResult = - new CallResult(status, result.getGasEstimate(), result.getOutput()); - return Optional.of(callResult); - } - return Optional.empty(); + return transactionSimulator.process( + param, + transactionValidationParams.build(), + OperationTracer.NO_TRACING, + (mutableWorldState, transactionSimulatorResult) -> + transactionSimulatorResult.map( + result -> { + long status = 0; + if (result.isSuccessful()) { + status = 1; + } + return new CallResult(status, result.getGasEstimate(), result.getOutput()); + }), + query.getBlockchain().getChainHeadHeader()); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractTraceByBlock.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractTraceByBlock.java index f40e37d1f1e..92bfa099c9c 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractTraceByBlock.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractTraceByBlock.java @@ -75,7 +75,7 @@ protected BlockParameter blockParameter(final JsonRpcRequestContext request) { protected JsonNode getTraceCallResult( final ProtocolSchedule protocolSchedule, final Set traceTypes, - final Optional maybeSimulatorResult, + final TransactionSimulatorResult simulatorResult, final TransactionTrace transactionTrace, final Block block) { final TraceCallResult.Builder builder = TraceCallResult.builder(); @@ -85,7 +85,7 @@ protected JsonNode getTraceCallResult( .getRevertReason() .ifPresentOrElse( revertReason -> builder.output(revertReason.toHexString()), - () -> builder.output(maybeSimulatorResult.get().getOutput().toString())); + () -> builder.output(simulatorResult.getOutput().toString())); if (traceTypes.contains(TraceType.STATE_DIFF)) { new StateDiffGenerator() diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java index fe8550fc665..71737fbab9e 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java @@ -79,21 +79,24 @@ protected Object resultByBlockHeader( callParams, buildTransactionValidationParams(header, callParams), OperationTracer.NO_TRACING, + (mutableWorldState, transactionSimulatorResult) -> + transactionSimulatorResult.map( + result -> + result + .getValidationResult() + .either( + (() -> + result.isSuccessful() + ? new JsonRpcSuccessResponse( + request.getRequest().getId(), + result.getOutput().toString()) + : errorResponse(request, result)), + reason -> + new JsonRpcErrorResponse( + request.getRequest().getId(), + JsonRpcErrorConverter.convertTransactionInvalidReason( + reason)))), header) - .map( - result -> - result - .getValidationResult() - .either( - (() -> - result.isSuccessful() - ? new JsonRpcSuccessResponse( - request.getRequest().getId(), result.getOutput().toString()) - : errorResponse(request, result)), - reason -> - new JsonRpcErrorResponse( - request.getRequest().getId(), - JsonRpcErrorConverter.convertTransactionInvalidReason(reason)))) .orElse(errorResponse(request, INTERNAL_ERROR)); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCall.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCall.java index 60dadde9c22..c29aba8d30a 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCall.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCall.java @@ -28,7 +28,6 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; -import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult; import org.hyperledger.besu.ethereum.vm.DebugOperationTracer; import java.util.Optional; @@ -78,31 +77,31 @@ protected Object resultByBlockNumber( final Set traceTypes = traceTypeParameter.getTraceTypes(); final DebugOperationTracer tracer = new DebugOperationTracer(buildTraceOptions(traceTypes)); - final Optional maybeSimulatorResult = - transactionSimulator.process( - callParams, buildTransactionValidationParams(), tracer, maybeBlockHeader.get()); - - if (maybeSimulatorResult.isEmpty()) { - LOG.error( - "Empty simulator result. call params: {}, blockHeader: {} ", - callParams, - maybeBlockHeader.get()); - return new JsonRpcErrorResponse(requestContext.getRequest().getId(), INTERNAL_ERROR); - } - final TransactionSimulatorResult simulatorResult = maybeSimulatorResult.get(); - - if (simulatorResult.isInvalid()) { - LOG.error(String.format("Invalid simulator result %s", maybeSimulatorResult)); - return new JsonRpcErrorResponse(requestContext.getRequest().getId(), INTERNAL_ERROR); - } - - final TransactionTrace transactionTrace = - new TransactionTrace( - simulatorResult.getTransaction(), simulatorResult.getResult(), tracer.getTraceFrames()); - - final Block block = blockchainQueriesSupplier.get().getBlockchain().getChainHeadBlock(); - - return getTraceCallResult( - protocolSchedule, traceTypes, maybeSimulatorResult, transactionTrace, block); + return transactionSimulator + .process( + callParams, + buildTransactionValidationParams(), + tracer, + (mutableWorldState, maybeSimulatorResult) -> + maybeSimulatorResult.map( + result -> { + if (result.isInvalid()) { + LOG.error(String.format("Invalid simulator result %s", result)); + return new JsonRpcErrorResponse( + requestContext.getRequest().getId(), INTERNAL_ERROR); + } + + final TransactionTrace transactionTrace = + new TransactionTrace( + result.getTransaction(), result.getResult(), tracer.getTraceFrames()); + + final Block block = + blockchainQueriesSupplier.get().getBlockchain().getChainHeadBlock(); + + return getTraceCallResult( + protocolSchedule, traceTypes, result, transactionTrace, block); + }), + maybeBlockHeader.get()) + .orElse(new JsonRpcErrorResponse(requestContext.getRequest().getId(), INTERNAL_ERROR)); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCallMany.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCallMany.java index d863caf0caf..ded4ff2b08e 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCallMany.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCallMany.java @@ -174,7 +174,7 @@ private JsonNode getSingleCallResult( final Block block = blockchainQueriesSupplier.get().getBlockchain().getChainHeadBlock(); return getTraceCallResult( - protocolSchedule, traceTypes, maybeSimulatorResult, transactionTrace, block); + protocolSchedule, traceTypes, maybeSimulatorResult.get(), transactionTrace, block); } private static class TransactionInvalidException extends RuntimeException { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceRawTransaction.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceRawTransaction.java index 89ac39cfa07..db06b293c5e 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceRawTransaction.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceRawTransaction.java @@ -27,12 +27,12 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.util.DomainObjectDecodeUtils; import org.hyperledger.besu.ethereum.core.Block; +import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.rlp.RLPException; import org.hyperledger.besu.ethereum.transaction.CallParameter; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; -import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult; import org.hyperledger.besu.ethereum.vm.DebugOperationTracer; import java.util.Optional; @@ -90,35 +90,38 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { final Set traceTypes = traceTypeParameter.getTraceTypes(); final DebugOperationTracer tracer = new DebugOperationTracer(buildTraceOptions(traceTypes)); - final long headBlockNumber = blockchainQueriesSupplier.get().headBlockNumber(); - final Optional maybeSimulatorResult = - transactionSimulator.process( + final BlockHeader headBlock = blockchainQueriesSupplier.get().headBlockHeader(); + return transactionSimulator + .process( CallParameter.fromTransaction(transaction), buildTransactionValidationParams(), tracer, - headBlockNumber); - - if (maybeSimulatorResult.isEmpty()) { - return new JsonRpcErrorResponse(requestContext.getRequest().getId(), INTERNAL_ERROR); - } - - final TransactionTrace transactionTrace = - new TransactionTrace( - maybeSimulatorResult.get().getTransaction(), - maybeSimulatorResult.get().getResult(), - tracer.getTraceFrames()); - final Optional maybeBlock = - blockchainQueriesSupplier.get().getBlockchain().getBlockByNumber(headBlockNumber); - - if (maybeBlock.isEmpty()) { - return new JsonRpcErrorResponse(requestContext.getRequest().getId(), INTERNAL_ERROR); - } - - final Block block = maybeBlock.get(); - final Object response = - getTraceCallResult( - protocolSchedule, traceTypes, maybeSimulatorResult, transactionTrace, block); - - return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), response); + (mutableWorldState, transactionSimulatorResult) -> + transactionSimulatorResult.map( + result -> { + final TransactionTrace transactionTrace = + new TransactionTrace( + result.getTransaction(), result.getResult(), tracer.getTraceFrames()); + final Optional maybeBlock = + blockchainQueriesSupplier + .get() + .getBlockchain() + .getBlockByNumber(headBlock.getNumber()); + + if (maybeBlock.isEmpty()) { + return new JsonRpcErrorResponse( + requestContext.getRequest().getId(), INTERNAL_ERROR); + } + + final Block block = maybeBlock.get(); + final Object response = + getTraceCallResult( + protocolSchedule, traceTypes, result, transactionTrace, block); + + return new JsonRpcSuccessResponse( + requestContext.getRequest().getId(), response); + }), + headBlock) + .orElse(new JsonRpcErrorResponse(requestContext.getRequest().getId(), INTERNAL_ERROR)); } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java index 526434a35ec..5bdda906415 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java @@ -40,10 +40,12 @@ import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.ChainHead; import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.transaction.CallParameter; +import org.hyperledger.besu.ethereum.transaction.PreCloseStateHandler; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult; @@ -53,6 +55,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; @@ -68,6 +72,8 @@ public class EthCallTest { @Mock private BlockHeader blockHeader; + @Captor ArgumentCaptor>> mapperCaptor; + @Before public void setUp() { method = new EthCall(blockchainQueries, transactionSimulator); @@ -87,7 +93,8 @@ public void shouldReturnInternalErrorWhenProcessorReturnsEmpty() { when(blockchainQueries.getBlockchain()).thenReturn(blockchain); when(blockchain.getChainHead()).thenReturn(chainHead); - when(transactionSimulator.process(any(), any(), any(), any())).thenReturn(Optional.empty()); + when(transactionSimulator.process(any(), any(), any(), any(), any())) + .thenReturn(Optional.empty()); final BlockHeader blockHeader = mock(BlockHeader.class); when(blockHeader.getBaseFee()).thenReturn(Optional.of(Wei.ZERO)); @@ -96,7 +103,7 @@ public void shouldReturnInternalErrorWhenProcessorReturnsEmpty() { final JsonRpcResponse response = method.response(request); assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse); - verify(transactionSimulator).process(any(), any(), any(), any()); + verify(transactionSimulator).process(any(), any(), any(), any(), any()); } @Test @@ -107,14 +114,22 @@ public void shouldAcceptRequestWhenMissingOptionalFields() { final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, Bytes.of().toString()); - mockTransactionProcessorSuccessResult(Bytes.of()); + mockTransactionProcessorSuccessResult(expectedResponse); when(blockchainQueries.getBlockchain()).thenReturn(blockchain); when(blockchain.getChainHead()).thenReturn(chainHead); final JsonRpcResponse response = method.response(request); + final TransactionSimulatorResult result = mock(TransactionSimulatorResult.class); + when(result.isSuccessful()).thenReturn(true); + when(result.getValidationResult()).thenReturn(ValidationResult.valid()); + when(result.getOutput()).thenReturn(Bytes.of()); + verify(transactionSimulator).process(any(), any(), any(), mapperCaptor.capture(), any()); + assertThat(mapperCaptor.getValue().apply(mock(MutableWorldState.class), Optional.of(result))) + .isEqualTo(Optional.of(expectedResponse)); + assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse); - verify(transactionSimulator).process(eq(callParameter), any(), any(), any()); + verify(transactionSimulator).process(eq(callParameter), any(), any(), any(), any()); } @Test @@ -122,7 +137,7 @@ public void shouldReturnExecutionResultWhenExecutionIsSuccessful() { final JsonRpcRequestContext request = ethCallRequest(callParameter(), "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, Bytes.of(1).toString()); - mockTransactionProcessorSuccessResult(Bytes.of(1)); + mockTransactionProcessorSuccessResult(expectedResponse); when(blockchainQueries.getBlockchain()).thenReturn(blockchain); when(blockchain.getChainHead()).thenReturn(chainHead); @@ -132,8 +147,16 @@ public void shouldReturnExecutionResultWhenExecutionIsSuccessful() { final JsonRpcResponse response = method.response(request); + final TransactionSimulatorResult result = mock(TransactionSimulatorResult.class); + when(result.isSuccessful()).thenReturn(true); + when(result.getValidationResult()).thenReturn(ValidationResult.valid()); + when(result.getOutput()).thenReturn(Bytes.of(1)); + verify(transactionSimulator).process(any(), any(), any(), mapperCaptor.capture(), any()); + assertThat(mapperCaptor.getValue().apply(mock(MutableWorldState.class), Optional.of(result))) + .isEqualTo(Optional.of(expectedResponse)); + assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse); - verify(transactionSimulator).process(eq(callParameter()), any(), any(), any()); + verify(transactionSimulator).process(eq(callParameter()), any(), any(), any(), any()); verify(blockchainQueries, atLeastOnce()).getBlockchain(); verifyNoMoreInteractions(blockchainQueries); } @@ -143,7 +166,8 @@ public void shouldUseCorrectBlockNumberWhenLatest() { final JsonRpcRequestContext request = ethCallRequest(callParameter(), "latest"); when(blockchainQueries.getBlockchain()).thenReturn(blockchain); when(blockchain.getChainHead()).thenReturn(chainHead); - when(transactionSimulator.process(any(), any(), any(), any())).thenReturn(Optional.empty()); + when(transactionSimulator.process(any(), any(), any(), any(), any())) + .thenReturn(Optional.empty()); final BlockHeader blockHeader = mock(BlockHeader.class); when(blockHeader.getBaseFee()).thenReturn(Optional.of(Wei.ZERO)); @@ -152,20 +176,21 @@ public void shouldUseCorrectBlockNumberWhenLatest() { method.response(request); verify(blockchainQueries, atLeastOnce()).getBlockchain(); - verify(transactionSimulator).process(any(), any(), any(), any()); + verify(transactionSimulator).process(any(), any(), any(), any(), any()); } @Test public void shouldUseCorrectBlockNumberWhenEarliest() { final JsonRpcRequestContext request = ethCallRequest(callParameter(), "earliest"); when(blockchainQueries.getBlockHashByNumber(anyLong())).thenReturn(Optional.of(Hash.ZERO)); - when(transactionSimulator.process(any(), any(), any(), any())).thenReturn(Optional.empty()); + when(transactionSimulator.process(any(), any(), any(), any(), any())) + .thenReturn(Optional.empty()); when(blockchainQueries.getBlockHeaderByHash(Hash.ZERO)) .thenReturn(Optional.of(mock(BlockHeader.class))); method.response(request); verify(blockchainQueries).getBlockHeaderByHash(eq(Hash.ZERO)); - verify(transactionSimulator).process(any(), any(), any(), any()); + verify(transactionSimulator).process(any(), any(), any(), any(), any()); } @Test @@ -173,12 +198,13 @@ public void shouldUseCorrectBlockNumberWhenSafe() { final JsonRpcRequestContext request = ethCallRequest(callParameter(), "safe"); when(blockchainQueries.getBlockHeaderByHash(Hash.ZERO)).thenReturn(Optional.of(blockHeader)); when(blockchainQueries.safeBlockHeader()).thenReturn(Optional.of(blockHeader)); - when(transactionSimulator.process(any(), any(), any(), any())).thenReturn(Optional.empty()); + when(transactionSimulator.process(any(), any(), any(), any(), any())) + .thenReturn(Optional.empty()); method.response(request); verify(blockchainQueries).getBlockHeaderByHash(Hash.ZERO); verify(blockchainQueries).safeBlockHeader(); - verify(transactionSimulator).process(any(), any(), any(), any()); + verify(transactionSimulator).process(any(), any(), any(), any(), any()); } @Test @@ -186,12 +212,13 @@ public void shouldUseCorrectBlockNumberWhenFinalized() { final JsonRpcRequestContext request = ethCallRequest(callParameter(), "finalized"); when(blockchainQueries.getBlockHeaderByHash(Hash.ZERO)).thenReturn(Optional.of(blockHeader)); when(blockchainQueries.finalizedBlockHeader()).thenReturn(Optional.of(blockHeader)); - when(transactionSimulator.process(any(), any(), any(), any())).thenReturn(Optional.empty()); + when(transactionSimulator.process(any(), any(), any(), any(), any())) + .thenReturn(Optional.empty()); method.response(request); verify(blockchainQueries).getBlockHeaderByHash(Hash.ZERO); verify(blockchainQueries).finalizedBlockHeader(); - verify(transactionSimulator).process(any(), any(), any(), any()); + verify(transactionSimulator).process(any(), any(), any(), any(), any()); } @Test @@ -201,12 +228,13 @@ public void shouldUseCorrectBlockNumberWhenSpecified() { when(blockchainQueries.getBlockHashByNumber(anyLong())).thenReturn(Optional.of(Hash.ZERO)); when(blockchainQueries.getBlockHeaderByHash(Hash.ZERO)) .thenReturn(Optional.of(mock(BlockHeader.class))); - when(transactionSimulator.process(any(), any(), any(), any())).thenReturn(Optional.empty()); + when(transactionSimulator.process(any(), any(), any(), any(), any())) + .thenReturn(Optional.empty()); method.response(request); verify(blockchainQueries).getBlockHeaderByHash(eq(Hash.ZERO)); - verify(transactionSimulator).process(any(), any(), any(), any()); + verify(transactionSimulator).process(any(), any(), any(), any(), any()); } @Test @@ -277,7 +305,8 @@ private void internalAutoSelectIsAllowedExceedingBalance( .isAllowExceedingBalance(isAllowedExceedingBalance) .build(); - verify(transactionSimulator).process(any(), eq(transactionValidationParams), any(), any()); + verify(transactionSimulator) + .process(any(), eq(transactionValidationParams), any(), any(), any()); } private JsonCallParameter callParameter() { @@ -305,12 +334,8 @@ private JsonRpcRequestContext ethCallRequest( new JsonRpcRequest("2.0", "eth_call", new Object[] {callParameter, blockNumberInHex})); } - private void mockTransactionProcessorSuccessResult(final Bytes output) { - final TransactionSimulatorResult result = mock(TransactionSimulatorResult.class); - - when(result.isSuccessful()).thenReturn(true); - when(result.getValidationResult()).thenReturn(ValidationResult.valid()); - when(result.getOutput()).thenReturn(output); - when(transactionSimulator.process(any(), any(), any(), any())).thenReturn(Optional.of(result)); + private void mockTransactionProcessorSuccessResult(final JsonRpcResponse jsonRpcResponse) { + when(transactionSimulator.process(any(), any(), any(), any(), any())) + .thenReturn(Optional.of(jsonRpcResponse)); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/worldview/BonsaiWorldStateUpdateAccumulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/worldview/BonsaiWorldStateUpdateAccumulator.java index 24023c8a7e4..24ae04037bb 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/worldview/BonsaiWorldStateUpdateAccumulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/worldview/BonsaiWorldStateUpdateAccumulator.java @@ -105,7 +105,7 @@ void cloneFromUpdater(final BonsaiWorldStateUpdateAccumulator source) { @Override public Account get(final Address address) { - return super.getAccount(address); + return super.get(address); } @Override diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/PreCloseStateHandler.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/PreCloseStateHandler.java new file mode 100644 index 00000000000..7bae8c100ea --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/PreCloseStateHandler.java @@ -0,0 +1,54 @@ +/* + * + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * + */ +package org.hyperledger.besu.ethereum.transaction; + +import org.hyperledger.besu.ethereum.core.MutableWorldState; + +import java.util.Optional; +import java.util.function.BiFunction; + +/** + * This class is passed to the transaction simulator and allows executing code before the copy of + * the worldstate is closed. When processing a transaction with the simulator, a copy of the + * worldstate is created, and once the simulation process is complete, the copy is closed. In some + * cases the simulator fills a Tracer that requires updates from the worldstate. If we want to + * generate a trace after the execution, it would fail. This interface allows us to execute our code + * before the worldstate is closed, ensuring that we can generate our objects without any issues. + * Then, the simulator will properly close the copy of the worldstate. + */ +public interface PreCloseStateHandler + extends BiFunction< + MutableWorldState, Optional, Optional> { + + /** + * This method executes code before the worldstate is closed. It takes two parameters: + * mutableWorldState, which represents the worldstate before it is closed, and + * transactionSimulatorResult, which holds the result of the transaction simulation. The method + * returns an Optional object containing the created object. The specific type of the object can + * vary based on the implementation and is determined by the caller's needs. The purpose of this + * method is to provide a hook for executing custom code or generating objects before the + * worldstate is closed, allowing for any necessary processing or operations to be performed. + * + * @param mutableWorldState The worldstate before it is closed. + * @param transactionSimulatorResult The result of the transaction simulation. + * @return The object that has been created. + */ + @Override + Optional apply( + final MutableWorldState mutableWorldState, + final Optional transactionSimulatorResult); +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java index c85836ab7f8..bc457e87e5d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java @@ -89,40 +89,39 @@ public Optional process( final OperationTracer operationTracer, final long blockNumber) { final BlockHeader header = blockchain.getBlockHeader(blockNumber).orElse(null); - return process(callParams, transactionValidationParams, operationTracer, header); - } - - public Optional process( - final CallParameter callParams, final Hash blockHeaderHash) { - final BlockHeader header = blockchain.getBlockHeader(blockHeaderHash).orElse(null); return process( callParams, - TransactionValidationParams.transactionSimulator(), - OperationTracer.NO_TRACING, + transactionValidationParams, + operationTracer, + (mutableWorldState, transactionSimulatorResult) -> transactionSimulatorResult, header); } - public Optional process( - final CallParameter callParams, final long blockNumber) { - return process( - callParams, - TransactionValidationParams.transactionSimulator(), - OperationTracer.NO_TRACING, - blockNumber); - } - public Optional processAtHead(final CallParameter callParams) { return process( callParams, TransactionValidationParams.transactionSimulator(), OperationTracer.NO_TRACING, + (mutableWorldState, transactionSimulatorResult) -> transactionSimulatorResult, blockchain.getChainHeadHeader()); } - public Optional process( + /** + * Processes a transaction simulation with the provided parameters and executes pre-worldstate + * close actions. + * + * @param callParams The call parameters for the transaction. + * @param transactionValidationParams The validation parameters for the transaction. + * @param operationTracer The tracer for capturing operations during processing. + * @param preWorldStateCloseGuard The pre-worldstate close guard for executing pre-close actions. + * @param header The block header. + * @return An Optional containing the result of the processing. + */ + public Optional process( final CallParameter callParams, final TransactionValidationParams transactionValidationParams, final OperationTracer operationTracer, + final PreCloseStateHandler preWorldStateCloseGuard, final BlockHeader header) { if (header == null) { return Optional.empty(); @@ -138,14 +137,36 @@ public Optional process( updater = updater.parentUpdater().isPresent() ? updater : updater.updater(); } - return processWithWorldUpdater( - callParams, transactionValidationParams, operationTracer, header, updater); + return preWorldStateCloseGuard.apply( + ws, + processWithWorldUpdater( + callParams, transactionValidationParams, operationTracer, header, updater)); } catch (final Exception e) { return Optional.empty(); } } + public Optional process( + final CallParameter callParams, final Hash blockHeaderHash) { + final BlockHeader header = blockchain.getBlockHeader(blockHeaderHash).orElse(null); + return process( + callParams, + TransactionValidationParams.transactionSimulator(), + OperationTracer.NO_TRACING, + (mutableWorldState, transactionSimulatorResult) -> transactionSimulatorResult, + header); + } + + public Optional process( + final CallParameter callParams, final long blockNumber) { + return process( + callParams, + TransactionValidationParams.transactionSimulator(), + OperationTracer.NO_TRACING, + blockNumber); + } + private MutableWorldState getWorldState(final BlockHeader header) { return worldStateArchive .getMutable(header, false) From 688d2dd3b4fe55fa9580c058666e16aabf102a6c Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Mon, 5 Jun 2023 08:48:48 +1000 Subject: [PATCH 18/35] Move ethstats server request to trace (#5531) Signed-off-by: Simon Dudley --- .../java/org/hyperledger/besu/ethstats/EthStatsService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/EthStatsService.java b/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/EthStatsService.java index a3ab50d700e..873fad9324d 100644 --- a/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/EthStatsService.java +++ b/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/EthStatsService.java @@ -439,7 +439,7 @@ private void sendMessage( final EthStatsRequest message, final Consumer handlerResult) { try { - LOG.debug("Send ethstats request {}", message.generateCommand()); + LOG.trace("Send ethstats request {}", message.generateCommand()); webSocket.writeTextMessage( message.generateCommand(), handler -> { From 18157d1a1d602bfdbf7ea14e63c8b22752ea917d Mon Sep 17 00:00:00 2001 From: Matt Nelson <85905982+non-fungible-nelson@users.noreply.github.com> Date: Sun, 4 Jun 2023 19:15:28 -0400 Subject: [PATCH 19/35] logging cleanup, giant new payload. (#5529) * logging cleanup, giant new payload. Signed-off-by: Matt Nelson <85905982+non-fungible-nelson@users.noreply.github.com> --------- Signed-off-by: Matt Nelson <85905982+non-fungible-nelson@users.noreply.github.com> --- CHANGELOG.md | 1 + .../jsonrpc/internal/methods/ExecutionEngineJsonRpcMethod.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 771b5799006..58cc4865d2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Allow Ethstats connection url to specify ws:// or wss:// scheme. [#5494](https://github.com/hyperledger/besu/issues/5494) - Add support for Shanghai changes to the GraphQL service [#5496](https://github.com/hyperledger/besu/pull/5496) - Unite the tx-pool CLI options under the same Tx Pool Options group in UX. [#5466](https://github.com/hyperledger/besu/issues/5466) +- Tidy DEBUG logs by moving engine API full logging to TRACE [#5529](https://github.com/hyperledger/besu/pull/5529) ### Bug Fixes - check to ensure storage and transactions are not closed prior to reading/writing [#5527](https://github.com/hyperledger/besu/pull/5527) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecutionEngineJsonRpcMethod.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecutionEngineJsonRpcMethod.java index 78442732c0c..9e22bc1b999 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecutionEngineJsonRpcMethod.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecutionEngineJsonRpcMethod.java @@ -66,7 +66,7 @@ public final JsonRpcResponse response(final JsonRpcRequestContext request) { syncVertx.executeBlocking( z -> { - LOG.debug( + LOG.trace( "execution engine JSON-RPC request {} {}", this.getName(), request.getRequest().getParams()); From a920a1c02033daf61632b6a5190d9be590dacd97 Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Mon, 5 Jun 2023 10:04:58 +1000 Subject: [PATCH 20/35] Remove push metrics port from effective ports (#5532) This results in a port conflict check however the push metrics port refers to a push gateway for besu to connect to rather than a port it is serving itself Signed-off-by: Simon Dudley --- besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 764f33ce1b9..6aa087b5229 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -3409,10 +3409,6 @@ private List getEffectivePorts() { addPortIfEnabled(effectivePorts, engineRPCOptionGroup.engineRpcPort, isEngineApiEnabled()); addPortIfEnabled( effectivePorts, metricsOptionGroup.metricsPort, metricsOptionGroup.isMetricsEnabled); - addPortIfEnabled( - effectivePorts, - metricsOptionGroup.metricsPushPort, - metricsOptionGroup.isMetricsPushEnabled); addPortIfEnabled( effectivePorts, minerOptionGroup.stratumPort, minerOptionGroup.iStratumMiningEnabled); return effectivePorts; From debd53ccc9b53fe06a0d7373d746a8723d16b6e4 Mon Sep 17 00:00:00 2001 From: garyschulte Date: Tue, 6 Jun 2023 10:30:15 -0700 Subject: [PATCH 21/35] remove PoW header validation if merge is enabled (#5538) * remove PoW header validation if merge is enabled Signed-off-by: garyschulte --- CHANGELOG.md | 1 + .../mainnet/MainnetBlockHeaderValidator.java | 19 +++++++------------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58cc4865d2c..dfbf80dd5e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Add support for Shanghai changes to the GraphQL service [#5496](https://github.com/hyperledger/besu/pull/5496) - Unite the tx-pool CLI options under the same Tx Pool Options group in UX. [#5466](https://github.com/hyperledger/besu/issues/5466) - Tidy DEBUG logs by moving engine API full logging to TRACE [#5529](https://github.com/hyperledger/besu/pull/5529) +- remove PoW validation if merge is enabled as it is not needed anymore [#5538](https://github.com/hyperledger/besu/pull/5538) ### Bug Fixes - check to ensure storage and transactions are not closed prior to reading/writing [#5527](https://github.com/hyperledger/besu/pull/5527) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidator.java index 16e8399843d..0f0d53d565e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidator.java @@ -19,7 +19,6 @@ import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.AncestryValidationRule; -import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.AttachedComposedFromDetachedRule; import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.BaseFeeMarketBlockHeaderGasPriceValidationRule; import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.CalculatedDifficultyValidationRule; import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.ConstantFieldValidationRule; @@ -148,17 +147,13 @@ public static BlockHeaderValidator.Builder createBaseFeeMarketValidator( .addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES)) .addRule((new BaseFeeMarketBlockHeaderGasPriceValidationRule(baseFeeMarket))); - // if merge is enabled, use the attached version of the proof of work validation rule - var powValidationRule = - new ProofOfWorkValidationRule( - new EpochCalculator.DefaultEpochCalculator(), - PoWHasher.ETHASH_LIGHT, - Optional.of(baseFeeMarket)); - - if (isMergeEnabled) { - builder.addRule(new AttachedComposedFromDetachedRule(powValidationRule)); - } else { - builder.addRule(powValidationRule); + // if this is not a merged PoS network, add the proof of work validation rule: + if (!isMergeEnabled) { + builder.addRule( + new ProofOfWorkValidationRule( + new EpochCalculator.DefaultEpochCalculator(), + PoWHasher.ETHASH_LIGHT, + Optional.of(baseFeeMarket))); } return builder; } From 8bc939d236de92bcb5a015be2ba8dea06d94f9a9 Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Wed, 7 Jun 2023 11:02:55 +0200 Subject: [PATCH 22/35] Introduce variables storage (#5471) Signed-off-by: Fabio Di Fabio --- CHANGELOG.md | 2 + .../org/hyperledger/besu/cli/BesuCommand.java | 13 ++ .../storage/StorageSubCommand.java | 172 ++++++++++++++++++ .../besu/controller/BesuController.java | 15 +- .../controller/BesuControllerBuilder.java | 9 +- .../hyperledger/besu/RunnerBuilderTest.java | 15 +- .../storage/StorageSubCommandTest.java | 117 ++++++++++++ .../controller/BesuControllerBuilderTest.java | 7 +- .../MergeBesuControllerBuilderTest.java | 7 +- .../QbftBesuControllerBuilderTest.java | 7 +- .../besu/services/BesuEventsImplTest.java | 5 +- ...ewBlockHeadersSubscriptionServiceTest.java | 5 +- .../operations/OperationBenchmarkHelper.java | 2 +- .../besu/ethereum/chain/VariablesStorage.java | 88 +++++++++ .../ethereum/storage/StorageProvider.java | 6 +- .../keyvalue/KeyValueSegmentIdentifier.java | 2 +- ...ueStoragePrefixedKeyBlockchainStorage.java | 140 ++++++++++---- .../keyvalue/KeyValueStorageProvider.java | 23 +-- .../keyvalue/VariablesKeyValueStorage.java | 145 +++++++++++++++ .../core/ExecutionContextTestFixture.java | 46 +++-- .../core/InMemoryKeyValueStorageProvider.java | 25 ++- .../ethereum/core/VariablesStorageHelper.java | 153 ++++++++++++++++ .../ethereum/chain/ChainDataPrunerTest.java | 9 +- .../ethereum/chain/DefaultBlockchainTest.java | 134 ++++++++++---- ...oragePrefixedKeyBlockchainStorageTest.java | 103 +++++++++++ .../besu/ethereum/worldstate/PrunerTest.java | 17 +- .../CheckPointBlockImportStepTest.java | 5 +- .../besu/evmtool/DataStoreModule.java | 19 +- .../p2p/discovery/PeerDiscoveryAgent.java | 27 +-- .../ethereum/retesteth/RetestethContext.java | 7 +- .../RocksDBColumnarKeyValueStorage.java | 21 +-- 31 files changed, 1177 insertions(+), 169 deletions(-) create mode 100644 besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/StorageSubCommand.java create mode 100644 besu/src/test/java/org/hyperledger/besu/cli/subcommands/storage/StorageSubCommandTest.java create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/VariablesStorage.java create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/VariablesKeyValueStorage.java create mode 100644 ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/VariablesStorageHelper.java create mode 100644 ethereum/core/src/test/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStoragePrefixedKeyBlockchainStorageTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index dfbf80dd5e9..a43fe5c2fa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ ## 23.4.2 ### Breaking Changes +- Move blockchain related variables in a dedicated storage, to pave the way to future optimizations [#5471](https://github.com/hyperledger/besu/pull/5471). The migration is performed automatically at startup, +and in case a rollback is needed, before installing a previous version, the migration can be reverted, using the subcommand `storage revert-variables` with the same configuration use to run Besu. ### Additions and Improvements - Allow Ethstats connection url to specify ws:// or wss:// scheme. [#5494](https://github.com/hyperledger/besu/issues/5494) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 6aa087b5229..d77dac0ce9d 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -83,6 +83,7 @@ import org.hyperledger.besu.cli.subcommands.blocks.BlocksSubCommand; import org.hyperledger.besu.cli.subcommands.operator.OperatorSubCommand; import org.hyperledger.besu.cli.subcommands.rlp.RLPSubCommand; +import org.hyperledger.besu.cli.subcommands.storage.StorageSubCommand; import org.hyperledger.besu.cli.util.BesuCommandCustomFactory; import org.hyperledger.besu.cli.util.CommandLineUtils; import org.hyperledger.besu.cli.util.ConfigOptionSearchAndRunHandler; @@ -140,6 +141,7 @@ import org.hyperledger.besu.ethereum.permissioning.SmartContractPermissioningConfiguration; import org.hyperledger.besu.ethereum.privacy.storage.keyvalue.PrivacyKeyValueStorageProvider; import org.hyperledger.besu.ethereum.privacy.storage.keyvalue.PrivacyKeyValueStorageProviderBuilder; +import org.hyperledger.besu.ethereum.storage.StorageProvider; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder; @@ -1598,6 +1600,8 @@ private void addSubCommands(final InputStream in) { commandLine.addSubcommand( ValidateConfigSubCommand.COMMAND_NAME, new ValidateConfigSubCommand(commandLine, commandLine.getOut())); + commandLine.addSubcommand( + StorageSubCommand.COMMAND_NAME, new StorageSubCommand(commandLine.getOut())); final String generateCompletionSubcommandName = "generate-completion"; commandLine.addSubcommand( generateCompletionSubcommandName, AutoComplete.GenerateCompletion.class); @@ -2979,6 +2983,15 @@ private KeyValueStorageProvider keyValueStorageProvider(final String name) { return this.keyValueStorageProvider; } + /** + * Get the storage provider + * + * @return the storage provider + */ + public StorageProvider getStorageProvider() { + return keyValueStorageProvider(keyValueStorageName); + } + private Optional maybePkiBlockCreationConfiguration() { return pkiBlockCreationOptions .asDomainConfig(commandLine) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/StorageSubCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/StorageSubCommand.java new file mode 100644 index 00000000000..f7a1a6eca11 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/StorageSubCommand.java @@ -0,0 +1,172 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.cli.subcommands.storage; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.hyperledger.besu.cli.subcommands.storage.StorageSubCommand.COMMAND_NAME; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.CHAIN_HEAD_HASH; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.FINALIZED_BLOCK_HASH; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.FORK_HEADS; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.SAFE_BLOCK_HASH; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.SEQ_NO_STORE; + +import org.hyperledger.besu.cli.BesuCommand; +import org.hyperledger.besu.cli.util.VersionProvider; +import org.hyperledger.besu.ethereum.rlp.RLP; +import org.hyperledger.besu.ethereum.storage.StorageProvider; +import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; +import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction; + +import java.io.PrintWriter; + +import org.apache.tuweni.bytes.Bytes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import picocli.CommandLine.Command; +import picocli.CommandLine.Model.CommandSpec; +import picocli.CommandLine.ParentCommand; +import picocli.CommandLine.Spec; + +/** The Storage sub command. */ +@Command( + name = COMMAND_NAME, + description = "This command provides storage related actions.", + mixinStandardHelpOptions = true, + versionProvider = VersionProvider.class, + subcommands = {StorageSubCommand.RevertVariablesStorage.class}) +public class StorageSubCommand implements Runnable { + + /** The constant COMMAND_NAME. */ + public static final String COMMAND_NAME = "storage"; + + @SuppressWarnings("unused") + @ParentCommand + private BesuCommand parentCommand; + + @SuppressWarnings("unused") + @Spec + private CommandSpec spec; + + private final PrintWriter out; + + /** + * Instantiates a new Storage sub command. + * + * @param out The PrintWriter where the usage will be reported. + */ + public StorageSubCommand(final PrintWriter out) { + this.out = out; + } + + @Override + public void run() { + spec.commandLine().usage(out); + } + + /** The Hash sub command for password. */ + @Command( + name = "revert-variables", + description = "This command revert the modifications done by the variables storage feature.", + mixinStandardHelpOptions = true, + versionProvider = VersionProvider.class) + static class RevertVariablesStorage implements Runnable { + private static final Logger LOG = LoggerFactory.getLogger(RevertVariablesStorage.class); + private static final Bytes VARIABLES_PREFIX = Bytes.of(1); + + @SuppressWarnings("unused") + @ParentCommand + private StorageSubCommand parentCommand; + + @Override + public void run() { + checkNotNull(parentCommand); + + final var storageProvider = getStorageProvider(); + + revert(storageProvider); + } + + private StorageProvider getStorageProvider() { + return parentCommand.parentCommand.getStorageProvider(); + } + + private void revert(final StorageProvider storageProvider) { + final var variablesStorage = storageProvider.createVariablesStorage(); + final var blockchainStorage = + getStorageProvider().getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.BLOCKCHAIN); + final var blockchainUpdater = blockchainStorage.startTransaction(); + final var variablesUpdater = variablesStorage.updater(); + + variablesStorage + .getChainHead() + .ifPresent( + v -> { + setBlockchainVariable( + blockchainUpdater, VARIABLES_PREFIX, CHAIN_HEAD_HASH.getBytes(), v); + LOG.info("Reverted variable storage for key {}", CHAIN_HEAD_HASH); + }); + + variablesStorage + .getFinalized() + .ifPresent( + v -> { + setBlockchainVariable( + blockchainUpdater, VARIABLES_PREFIX, FINALIZED_BLOCK_HASH.getBytes(), v); + LOG.info("Reverted variable storage for key {}", FINALIZED_BLOCK_HASH); + }); + + variablesStorage + .getSafeBlock() + .ifPresent( + v -> { + setBlockchainVariable( + blockchainUpdater, VARIABLES_PREFIX, SAFE_BLOCK_HASH.getBytes(), v); + LOG.info("Reverted variable storage for key {}", SAFE_BLOCK_HASH); + }); + + final var forkHeads = variablesStorage.getForkHeads(); + if (!forkHeads.isEmpty()) { + setBlockchainVariable( + blockchainUpdater, + VARIABLES_PREFIX, + FORK_HEADS.getBytes(), + RLP.encode(o -> o.writeList(forkHeads, (val, out) -> out.writeBytes(val)))); + LOG.info("Reverted variable storage for key {}", FORK_HEADS); + } + + variablesStorage + .getLocalEnrSeqno() + .ifPresent( + v -> { + setBlockchainVariable(blockchainUpdater, Bytes.EMPTY, SEQ_NO_STORE.getBytes(), v); + LOG.info("Reverted variable storage for key {}", SEQ_NO_STORE); + }); + + variablesUpdater.removeAll(); + + variablesUpdater.commit(); + blockchainUpdater.commit(); + } + + private void setBlockchainVariable( + final KeyValueStorageTransaction blockchainTransaction, + final Bytes prefix, + final Bytes key, + final Bytes value) { + blockchainTransaction.put( + Bytes.concatenate(prefix, key).toArrayUnsafe(), value.toArrayUnsafe()); + } + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java index 71c6d80fce5..bb46003b24b 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java @@ -36,6 +36,7 @@ import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.p2p.config.SubProtocolConfiguration; +import org.hyperledger.besu.ethereum.storage.StorageProvider; import java.io.Closeable; import java.io.IOException; @@ -75,6 +76,7 @@ public class BesuController implements java.io.Closeable { private final PluginServiceFactory additionalPluginServices; private final SyncState syncState; private final EthPeers ethPeers; + private final StorageProvider storageProvider; /** * Instantiates a new Besu controller. @@ -111,7 +113,8 @@ public class BesuController implements java.io.Closeable { final NodeKey nodeKey, final List closeables, final PluginServiceFactory additionalPluginServices, - final EthPeers ethPeers) { + final EthPeers ethPeers, + final StorageProvider storageProvider) { this.protocolSchedule = protocolSchedule; this.protocolContext = protocolContext; this.ethProtocolManager = ethProtocolManager; @@ -128,6 +131,7 @@ public class BesuController implements java.io.Closeable { this.miningParameters = miningParameters; this.additionalPluginServices = additionalPluginServices; this.ethPeers = ethPeers; + this.storageProvider = storageProvider; } /** @@ -220,6 +224,15 @@ public EthPeers getEthPeers() { return ethPeers; } + /** + * Get the storage provider + * + * @return the storage provider + */ + public StorageProvider getStorageProvider() { + return storageProvider; + } + @Override public void close() { closeables.forEach(this::tryClose); diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java index 4b7bff0234f..656d39b01e0 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -42,6 +42,7 @@ import org.hyperledger.besu.ethereum.chain.DefaultBlockchain; import org.hyperledger.besu.ethereum.chain.GenesisState; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; +import org.hyperledger.besu.ethereum.chain.VariablesStorage; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters; @@ -561,11 +562,14 @@ public BesuController build() { final ProtocolSchedule protocolSchedule = createProtocolSchedule(); final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule); + + final VariablesStorage variablesStorage = storageProvider.createVariablesStorage(); + final WorldStateStorage worldStateStorage = storageProvider.createWorldStateStorage(dataStorageConfiguration.getDataStorageFormat()); final BlockchainStorage blockchainStorage = - storageProvider.createBlockchainStorage(protocolSchedule); + storageProvider.createBlockchainStorage(protocolSchedule, variablesStorage); final MutableBlockchain blockchain = DefaultBlockchain.createMutable( @@ -773,7 +777,8 @@ public BesuController build() { nodeKey, closeables, additionalPluginServices, - ethPeers); + ethPeers, + storageProvider); } /** diff --git a/besu/src/test/java/org/hyperledger/besu/RunnerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/RunnerBuilderTest.java index df050af0489..d4c0a79a316 100644 --- a/besu/src/test/java/org/hyperledger/besu/RunnerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/RunnerBuilderTest.java @@ -16,8 +16,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryBlockchain; -import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.BLOCKCHAIN; +import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.VARIABLES; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -163,7 +164,7 @@ public void enodeUrlShouldHaveAdvertisedHostWhenDiscoveryDisabled() { .metricsConfiguration(mock(MetricsConfiguration.class)) .vertx(vertx) .dataDir(dataDir.getRoot()) - .storageProvider(mock(KeyValueStorageProvider.class)) + .storageProvider(mock(KeyValueStorageProvider.class, RETURNS_DEEP_STUBS)) .rpcEndpointService(new RpcEndpointServiceImpl()) .build(); runner.startEthereumMainLoop(); @@ -223,7 +224,7 @@ public void movingAcrossProtocolSpecsUpdatesNodeRecord() { inMemoryBlockchain.appendBlock(block, gen.receipts(block)); assertThat( storageProvider - .getStorageBySegmentIdentifier(BLOCKCHAIN) + .getStorageBySegmentIdentifier(VARIABLES) .get("local-enr-seqno".getBytes(StandardCharsets.UTF_8)) .map(Bytes::of) .map(NodeRecordFactory.DEFAULT::fromBytes) @@ -265,7 +266,7 @@ public void whenEngineApiAddedListensOnDefaultPort() { .metricsConfiguration(mock(MetricsConfiguration.class)) .vertx(Vertx.vertx()) .dataDir(dataDir.getRoot()) - .storageProvider(mock(KeyValueStorageProvider.class)) + .storageProvider(mock(KeyValueStorageProvider.class, RETURNS_DEEP_STUBS)) .rpcEndpointService(new RpcEndpointServiceImpl()) .besuPluginContext(mock(BesuPluginContextImpl.class)) .build(); @@ -307,7 +308,7 @@ public void whenEngineApiAddedWebSocketReadyOnSamePort() { .metricsConfiguration(mock(MetricsConfiguration.class)) .vertx(Vertx.vertx()) .dataDir(dataDir.getRoot()) - .storageProvider(mock(KeyValueStorageProvider.class)) + .storageProvider(mock(KeyValueStorageProvider.class, RETURNS_DEEP_STUBS)) .rpcEndpointService(new RpcEndpointServiceImpl()) .besuPluginContext(mock(BesuPluginContextImpl.class)) .build(); @@ -348,7 +349,7 @@ public void whenEngineApiAddedEthSubscribeAvailable() { .metricsConfiguration(mock(MetricsConfiguration.class)) .vertx(Vertx.vertx()) .dataDir(dataDir.getRoot()) - .storageProvider(mock(KeyValueStorageProvider.class)) + .storageProvider(mock(KeyValueStorageProvider.class, RETURNS_DEEP_STUBS)) .rpcEndpointService(new RpcEndpointServiceImpl()) .besuPluginContext(mock(BesuPluginContextImpl.class)) .build(); @@ -390,7 +391,7 @@ public void noEngineApiNoServiceForMethods() { .metricsConfiguration(mock(MetricsConfiguration.class)) .vertx(Vertx.vertx()) .dataDir(dataDir.getRoot()) - .storageProvider(mock(KeyValueStorageProvider.class)) + .storageProvider(mock(KeyValueStorageProvider.class, RETURNS_DEEP_STUBS)) .rpcEndpointService(new RpcEndpointServiceImpl()) .besuPluginContext(mock(BesuPluginContextImpl.class)) .networkingConfiguration(NetworkingConfiguration.create()) diff --git a/besu/src/test/java/org/hyperledger/besu/cli/subcommands/storage/StorageSubCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/subcommands/storage/StorageSubCommandTest.java new file mode 100644 index 00000000000..a8a1bedc649 --- /dev/null +++ b/besu/src/test/java/org/hyperledger/besu/cli/subcommands/storage/StorageSubCommandTest.java @@ -0,0 +1,117 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.cli.subcommands.storage; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.FINALIZED_BLOCK_HASH; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.SAFE_BLOCK_HASH; +import static org.hyperledger.besu.ethereum.core.VariablesStorageHelper.assertNoVariablesInStorage; +import static org.hyperledger.besu.ethereum.core.VariablesStorageHelper.assertVariablesPresentInBlockchainStorage; +import static org.hyperledger.besu.ethereum.core.VariablesStorageHelper.getSampleVariableValues; +import static org.hyperledger.besu.ethereum.core.VariablesStorageHelper.populateBlockchainStorage; +import static org.hyperledger.besu.ethereum.core.VariablesStorageHelper.populateVariablesStorage; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +import org.hyperledger.besu.cli.CommandTestAbstract; +import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; +import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class StorageSubCommandTest extends CommandTestAbstract { + + @Test + public void storageSubCommandExists() { + parseCommand("storage"); + + assertThat(commandOutput.toString(UTF_8)) + .contains("This command provides storage related actions"); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + + @Test + public void storageRevertVariablesSubCommandExists() { + parseCommand("storage", "revert-variables", "--help"); + + assertThat(commandOutput.toString(UTF_8)) + .contains("This command revert the modifications done by the variables storage feature"); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + + @Test + public void revertVariables() { + final var kvVariables = new InMemoryKeyValueStorage(); + final var kvBlockchain = new InMemoryKeyValueStorage(); + when(rocksDBStorageFactory.create(eq(KeyValueSegmentIdentifier.VARIABLES), any(), any())) + .thenReturn(kvVariables); + when(rocksDBStorageFactory.create(eq(KeyValueSegmentIdentifier.BLOCKCHAIN), any(), any())) + .thenReturn(kvBlockchain); + + final var variableValues = getSampleVariableValues(); + assertNoVariablesInStorage(kvBlockchain); + populateVariablesStorage(kvVariables, variableValues); + + parseCommand("storage", "revert-variables"); + + assertNoVariablesInStorage(kvVariables); + assertVariablesPresentInBlockchainStorage(kvBlockchain, variableValues); + } + + @Test + public void revertVariablesWhenSomeVariablesDoNotExist() { + final var kvVariables = new InMemoryKeyValueStorage(); + final var kvBlockchain = new InMemoryKeyValueStorage(); + when(rocksDBStorageFactory.create(eq(KeyValueSegmentIdentifier.VARIABLES), any(), any())) + .thenReturn(kvVariables); + when(rocksDBStorageFactory.create(eq(KeyValueSegmentIdentifier.BLOCKCHAIN), any(), any())) + .thenReturn(kvBlockchain); + + final var variableValues = getSampleVariableValues(); + variableValues.remove(FINALIZED_BLOCK_HASH); + variableValues.remove(SAFE_BLOCK_HASH); + assertNoVariablesInStorage(kvBlockchain); + populateVariablesStorage(kvVariables, variableValues); + + parseCommand("storage", "revert-variables"); + + assertNoVariablesInStorage(kvVariables); + assertVariablesPresentInBlockchainStorage(kvBlockchain, variableValues); + } + + @Test + public void doesNothingWhenVariablesAlreadyReverted() { + final var kvVariables = new InMemoryKeyValueStorage(); + final var kvBlockchain = new InMemoryKeyValueStorage(); + when(rocksDBStorageFactory.create(eq(KeyValueSegmentIdentifier.VARIABLES), any(), any())) + .thenReturn(kvVariables); + when(rocksDBStorageFactory.create(eq(KeyValueSegmentIdentifier.BLOCKCHAIN), any(), any())) + .thenReturn(kvBlockchain); + + final var variableValues = getSampleVariableValues(); + assertNoVariablesInStorage(kvVariables); + populateBlockchainStorage(kvBlockchain, variableValues); + + parseCommand("storage", "revert-variables"); + + assertNoVariablesInStorage(kvVariables); + assertVariablesPresentInBlockchainStorage(kvBlockchain, variableValues); + } +} diff --git a/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java index edae51a7c95..bd8d06d2a5e 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java @@ -45,6 +45,7 @@ import org.hyperledger.besu.ethereum.storage.StorageProvider; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; +import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration; @@ -114,10 +115,12 @@ public void setup() { when(ethashConfigOptions.getFixedDifficulty()).thenReturn(OptionalLong.empty()); when(storageProvider.getStorageBySegmentIdentifier(any())) .thenReturn(new InMemoryKeyValueStorage()); - when(storageProvider.createBlockchainStorage(any())) + when(storageProvider.createBlockchainStorage(any(), any())) .thenReturn( new KeyValueStoragePrefixedKeyBlockchainStorage( - new InMemoryKeyValueStorage(), new MainnetBlockHeaderFunctions())); + new InMemoryKeyValueStorage(), + new VariablesKeyValueStorage(new InMemoryKeyValueStorage()), + new MainnetBlockHeaderFunctions())); when(synchronizerConfiguration.getDownloaderParallelism()).thenReturn(1); when(synchronizerConfiguration.getTransactionsParallelism()).thenReturn(1); when(synchronizerConfiguration.getComputationParallelism()).thenReturn(1); diff --git a/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java index 515ec018e66..15fb3fd3ec2 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java @@ -51,6 +51,7 @@ import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; import org.hyperledger.besu.ethereum.storage.StorageProvider; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; +import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage; @@ -119,10 +120,12 @@ public void setup() { when(genesisConfigOptions.getThanosBlockNumber()).thenReturn(OptionalLong.empty()); when(genesisConfigOptions.getTerminalBlockHash()).thenReturn(Optional.of(Hash.ZERO)); when(genesisConfigOptions.getTerminalBlockNumber()).thenReturn(OptionalLong.of(1L)); - when(storageProvider.createBlockchainStorage(any())) + when(storageProvider.createBlockchainStorage(any(), any())) .thenReturn( new KeyValueStoragePrefixedKeyBlockchainStorage( - new InMemoryKeyValueStorage(), new MainnetBlockHeaderFunctions())); + new InMemoryKeyValueStorage(), + new VariablesKeyValueStorage(new InMemoryKeyValueStorage()), + new MainnetBlockHeaderFunctions())); when(storageProvider.getStorageBySegmentIdentifier(any())) .thenReturn(new InMemoryKeyValueStorage()); when(synchronizerConfiguration.getDownloaderParallelism()).thenReturn(1); diff --git a/besu/src/test/java/org/hyperledger/besu/controller/QbftBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/QbftBesuControllerBuilderTest.java index cb2f8080fec..395abeb22d6 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/QbftBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/QbftBesuControllerBuilderTest.java @@ -47,6 +47,7 @@ import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; import org.hyperledger.besu.ethereum.storage.StorageProvider; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; +import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage; @@ -103,10 +104,12 @@ public void setup() { when(genesisConfigFile.getConfigOptions(any())).thenReturn(genesisConfigOptions); when(genesisConfigFile.getConfigOptions()).thenReturn(genesisConfigOptions); when(genesisConfigOptions.getCheckpointOptions()).thenReturn(checkpointConfigOptions); - when(storageProvider.createBlockchainStorage(any())) + when(storageProvider.createBlockchainStorage(any(), any())) .thenReturn( new KeyValueStoragePrefixedKeyBlockchainStorage( - new InMemoryKeyValueStorage(), new MainnetBlockHeaderFunctions())); + new InMemoryKeyValueStorage(), + new VariablesKeyValueStorage(new InMemoryKeyValueStorage()), + new MainnetBlockHeaderFunctions())); when(storageProvider.createWorldStateStorage(DataStorageFormat.FOREST)) .thenReturn(worldStateStorage); when(worldStateStorage.isWorldStateAvailable(any(), any())).thenReturn(true); diff --git a/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java b/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java index 85607973509..4ce430e787d 100644 --- a/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java +++ b/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java @@ -54,6 +54,7 @@ import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; +import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.plugin.data.AddedBlockContext; @@ -114,7 +115,9 @@ public void setUp() { DefaultBlockchain.createMutable( gen.genesisBlock(), new KeyValueStoragePrefixedKeyBlockchainStorage( - new InMemoryKeyValueStorage(), new MainnetBlockHeaderFunctions()), + new InMemoryKeyValueStorage(), + new VariablesKeyValueStorage(new InMemoryKeyValueStorage()), + new MainnetBlockHeaderFunctions()), new NoOpMetricsSystem(), 0); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/blockheaders/NewBlockHeadersSubscriptionServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/blockheaders/NewBlockHeadersSubscriptionServiceTest.java index 3259d873ab7..0628cefadbf 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/blockheaders/NewBlockHeadersSubscriptionServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/blockheaders/NewBlockHeadersSubscriptionServiceTest.java @@ -35,6 +35,7 @@ import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; +import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; @@ -60,7 +61,9 @@ public class NewBlockHeadersSubscriptionServiceTest { private final BlockDataGenerator gen = new BlockDataGenerator(); private final BlockchainStorage blockchainStorage = new KeyValueStoragePrefixedKeyBlockchainStorage( - new InMemoryKeyValueStorage(), new MainnetBlockHeaderFunctions()); + new InMemoryKeyValueStorage(), + new VariablesKeyValueStorage(new InMemoryKeyValueStorage()), + new MainnetBlockHeaderFunctions()); private final Block genesisBlock = gen.genesisBlock(); private final MutableBlockchain blockchain = DefaultBlockchain.createMutable(genesisBlock, blockchainStorage, new NoOpMetricsSystem(), 0); diff --git a/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java b/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java index f6bba6a165f..81796f89f29 100644 --- a/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java +++ b/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java @@ -65,7 +65,7 @@ public static OperationBenchmarkHelper create() throws IOException { RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS); final ExecutionContextTestFixture executionContext = - ExecutionContextTestFixture.builder().keyValueStorage(keyValueStorage).build(); + ExecutionContextTestFixture.builder().blockchainKeyValueStorage(keyValueStorage).build(); final MutableBlockchain blockchain = executionContext.getBlockchain(); for (int i = 1; i < 256; i++) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/VariablesStorage.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/VariablesStorage.java new file mode 100644 index 00000000000..43a4361a0e4 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/VariablesStorage.java @@ -0,0 +1,88 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.chain; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import org.hyperledger.besu.datatypes.Hash; + +import java.util.Collection; +import java.util.Optional; + +import org.apache.tuweni.bytes.Bytes; + +public interface VariablesStorage { + enum Keys { + CHAIN_HEAD_HASH("chainHeadHash"), + FORK_HEADS("forkHeads"), + FINALIZED_BLOCK_HASH("finalizedBlockHash"), + SAFE_BLOCK_HASH("safeBlockHash"), + SEQ_NO_STORE("local-enr-seqno"); + + private final String key; + private final byte[] byteArray; + private final Bytes bytes; + + Keys(final String key) { + this.key = key; + this.byteArray = key.getBytes(UTF_8); + this.bytes = Bytes.wrap(byteArray); + } + + public byte[] toByteArray() { + return byteArray; + } + + public Bytes getBytes() { + return bytes; + } + + @Override + public String toString() { + return key; + } + } + + Optional getChainHead(); + + Collection getForkHeads(); + + Optional getFinalized(); + + Optional getSafeBlock(); + + Optional getLocalEnrSeqno(); + + Updater updater(); + + interface Updater { + + void setChainHead(Hash blockHash); + + void setForkHeads(Collection forkHeadHashes); + + void setFinalized(Hash blockHash); + + void setSafeBlock(Hash blockHash); + + void setLocalEnrSeqno(Bytes nodeRecord); + + void removeAll(); + + void commit(); + + void rollback(); + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/StorageProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/StorageProvider.java index 74faf91ec10..fea099d5769 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/StorageProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/StorageProvider.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.storage; import org.hyperledger.besu.ethereum.chain.BlockchainStorage; +import org.hyperledger.besu.ethereum.chain.VariablesStorage; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage; @@ -27,7 +28,10 @@ public interface StorageProvider extends Closeable { - BlockchainStorage createBlockchainStorage(ProtocolSchedule protocolSchedule); + VariablesStorage createVariablesStorage(); + + BlockchainStorage createBlockchainStorage( + ProtocolSchedule protocolSchedule, VariablesStorage variablesStorage); WorldStateStorage createWorldStateStorage(DataStorageFormat dataStorageFormat); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueSegmentIdentifier.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueSegmentIdentifier.java index 559f1880c8a..43b02f224de 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueSegmentIdentifier.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueSegmentIdentifier.java @@ -29,10 +29,10 @@ public enum KeyValueSegmentIdentifier implements SegmentIdentifier { ACCOUNT_STORAGE_STORAGE(new byte[] {8}, new int[] {2}), TRIE_BRANCH_STORAGE(new byte[] {9}, new int[] {2}), TRIE_LOG_STORAGE(new byte[] {10}, new int[] {2}), + VARIABLES(new byte[] {11}), // formerly GOQUORUM_PRIVATE_WORLD_STATE // previously supported GoQuorum private states // no longer used but need to be retained for db backward compatibility - GOQUORUM_PRIVATE_WORLD_STATE(new byte[] {11}), GOQUORUM_PRIVATE_STORAGE(new byte[] {12}), BACKWARD_SYNC_HEADERS(new byte[] {13}), diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStoragePrefixedKeyBlockchainStorage.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStoragePrefixedKeyBlockchainStorage.java index ee3a9d5790c..e5c1f11889b 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStoragePrefixedKeyBlockchainStorage.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStoragePrefixedKeyBlockchainStorage.java @@ -14,9 +14,16 @@ */ package org.hyperledger.besu.ethereum.storage.keyvalue; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.CHAIN_HEAD_HASH; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.FINALIZED_BLOCK_HASH; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.FORK_HEADS; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.SAFE_BLOCK_HASH; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.SEQ_NO_STORE; + import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.chain.BlockchainStorage; import org.hyperledger.besu.ethereum.chain.TransactionLocation; +import org.hyperledger.besu.ethereum.chain.VariablesStorage; import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; @@ -26,64 +33,61 @@ import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction; -import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.List; import java.util.Optional; -import com.google.common.collect.Lists; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt256; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class KeyValueStoragePrefixedKeyBlockchainStorage implements BlockchainStorage { + private static final Logger LOG = + LoggerFactory.getLogger(KeyValueStoragePrefixedKeyBlockchainStorage.class); - private static final Bytes CHAIN_HEAD_KEY = - Bytes.wrap("chainHeadHash".getBytes(StandardCharsets.UTF_8)); - private static final Bytes FORK_HEADS_KEY = - Bytes.wrap("forkHeads".getBytes(StandardCharsets.UTF_8)); - private static final Bytes FINALIZED_BLOCK_HASH_KEY = - Bytes.wrap("finalizedBlockHash".getBytes(StandardCharsets.UTF_8)); - private static final Bytes SAFE_BLOCK_HASH_KEY = - Bytes.wrap("safeBlockHash".getBytes(StandardCharsets.UTF_8)); - + @Deprecated(since = "23.4.2", forRemoval = true) private static final Bytes VARIABLES_PREFIX = Bytes.of(1); - static final Bytes BLOCK_HEADER_PREFIX = Bytes.of(2); + + private static final Bytes BLOCK_HEADER_PREFIX = Bytes.of(2); private static final Bytes BLOCK_BODY_PREFIX = Bytes.of(3); private static final Bytes TRANSACTION_RECEIPTS_PREFIX = Bytes.of(4); private static final Bytes BLOCK_HASH_PREFIX = Bytes.of(5); private static final Bytes TOTAL_DIFFICULTY_PREFIX = Bytes.of(6); private static final Bytes TRANSACTION_LOCATION_PREFIX = Bytes.of(7); - - final KeyValueStorage storage; + final KeyValueStorage blockchainStorage; + final VariablesStorage variablesStorage; final BlockHeaderFunctions blockHeaderFunctions; public KeyValueStoragePrefixedKeyBlockchainStorage( - final KeyValueStorage storage, final BlockHeaderFunctions blockHeaderFunctions) { - this.storage = storage; + final KeyValueStorage blockchainStorage, + final VariablesStorage variablesStorage, + final BlockHeaderFunctions blockHeaderFunctions) { + this.blockchainStorage = blockchainStorage; + this.variablesStorage = variablesStorage; this.blockHeaderFunctions = blockHeaderFunctions; + migrateVariables(); } @Override public Optional getChainHead() { - return get(VARIABLES_PREFIX, CHAIN_HEAD_KEY).map(this::bytesToHash); + return variablesStorage.getChainHead(); } @Override public Collection getForkHeads() { - return get(VARIABLES_PREFIX, FORK_HEADS_KEY) - .map(bytes -> RLP.input(bytes).readList(in -> this.bytesToHash(in.readBytes32()))) - .orElse(Lists.newArrayList()); + return variablesStorage.getForkHeads(); } @Override public Optional getFinalized() { - return get(VARIABLES_PREFIX, FINALIZED_BLOCK_HASH_KEY).map(this::bytesToHash); + return variablesStorage.getFinalized(); } @Override public Optional getSafeBlock() { - return get(VARIABLES_PREFIX, SAFE_BLOCK_HASH_KEY).map(this::bytesToHash); + return variablesStorage.getSafeBlock(); } @Override @@ -121,7 +125,7 @@ public Optional getTransactionLocation(final Hash transacti @Override public Updater updater() { - return new Updater(storage.startTransaction()); + return new Updater(blockchainStorage.startTransaction(), variablesStorage.updater()); } private List rlpDecodeTransactionReceipts(final Bytes bytes) { @@ -133,15 +137,68 @@ private Hash bytesToHash(final Bytes bytes) { } Optional get(final Bytes prefix, final Bytes key) { - return storage.get(Bytes.concatenate(prefix, key).toArrayUnsafe()).map(Bytes::wrap); + return blockchainStorage.get(Bytes.concatenate(prefix, key).toArrayUnsafe()).map(Bytes::wrap); + } + + public void migrateVariables() { + final var blockchainUpdater = updater(); + final var variablesUpdater = variablesStorage.updater(); + + get(VARIABLES_PREFIX, CHAIN_HEAD_HASH.getBytes()) + .map(this::bytesToHash) + .ifPresent( + ch -> { + variablesUpdater.setChainHead(ch); + LOG.info("Migrated key {} to variables storage", CHAIN_HEAD_HASH); + }); + + get(VARIABLES_PREFIX, FINALIZED_BLOCK_HASH.getBytes()) + .map(this::bytesToHash) + .ifPresent( + fh -> { + variablesUpdater.setFinalized(fh); + LOG.info("Migrated key {} to variables storage", FINALIZED_BLOCK_HASH); + }); + + get(VARIABLES_PREFIX, SAFE_BLOCK_HASH.getBytes()) + .map(this::bytesToHash) + .ifPresent( + sh -> { + variablesUpdater.setSafeBlock(sh); + LOG.info("Migrated key {} to variables storage", SAFE_BLOCK_HASH); + }); + + get(VARIABLES_PREFIX, FORK_HEADS.getBytes()) + .map(bytes -> RLP.input(bytes).readList(in -> this.bytesToHash(in.readBytes32()))) + .ifPresent( + fh -> { + variablesUpdater.setForkHeads(fh); + LOG.info("Migrated key {} to variables storage", FORK_HEADS); + }); + + get(Bytes.EMPTY, SEQ_NO_STORE.getBytes()) + .ifPresent( + sns -> { + variablesUpdater.setLocalEnrSeqno(sns); + LOG.info("Migrated key {} to variables storage", SEQ_NO_STORE); + }); + + blockchainUpdater.removeVariables(); + + variablesUpdater.commit(); + blockchainUpdater.commit(); } public static class Updater implements BlockchainStorage.Updater { - private final KeyValueStorageTransaction transaction; + private final KeyValueStorageTransaction blockchainTransaction; + private final VariablesStorage.Updater variablesUpdater; - Updater(final KeyValueStorageTransaction transaction) { - this.transaction = transaction; + Updater( + final KeyValueStorageTransaction blockchainTransaction, + final VariablesStorage.Updater variablesUpdater) { + this.blockchainTransaction = blockchainTransaction; + this.variablesUpdater = variablesUpdater; } @Override @@ -178,24 +235,22 @@ public void putTotalDifficulty(final Hash blockHash, final Difficulty totalDiffi @Override public void setChainHead(final Hash blockHash) { - set(VARIABLES_PREFIX, CHAIN_HEAD_KEY, blockHash); + variablesUpdater.setChainHead(blockHash); } @Override public void setForkHeads(final Collection forkHeadHashes) { - final Bytes data = - RLP.encode(o -> o.writeList(forkHeadHashes, (val, out) -> out.writeBytes(val))); - set(VARIABLES_PREFIX, FORK_HEADS_KEY, data); + variablesUpdater.setForkHeads(forkHeadHashes); } @Override public void setFinalized(final Hash blockHash) { - set(VARIABLES_PREFIX, FINALIZED_BLOCK_HASH_KEY, blockHash); + variablesUpdater.setFinalized(blockHash); } @Override public void setSafeBlock(final Hash blockHash) { - set(VARIABLES_PREFIX, SAFE_BLOCK_HASH_KEY, blockHash); + variablesUpdater.setSafeBlock(blockHash); } @Override @@ -230,24 +285,35 @@ public void removeTotalDifficulty(final Hash blockHash) { @Override public void commit() { - transaction.commit(); + blockchainTransaction.commit(); + variablesUpdater.commit(); } @Override public void rollback() { - transaction.rollback(); + variablesUpdater.rollback(); + blockchainTransaction.rollback(); } void set(final Bytes prefix, final Bytes key, final Bytes value) { - transaction.put(Bytes.concatenate(prefix, key).toArrayUnsafe(), value.toArrayUnsafe()); + blockchainTransaction.put( + Bytes.concatenate(prefix, key).toArrayUnsafe(), value.toArrayUnsafe()); } private void remove(final Bytes prefix, final Bytes key) { - transaction.remove(Bytes.concatenate(prefix, key).toArrayUnsafe()); + blockchainTransaction.remove(Bytes.concatenate(prefix, key).toArrayUnsafe()); } private Bytes rlpEncode(final List receipts) { return RLP.encode(o -> o.writeList(receipts, TransactionReceipt::writeToWithRevertReason)); } + + private void removeVariables() { + remove(VARIABLES_PREFIX, CHAIN_HEAD_HASH.getBytes()); + remove(VARIABLES_PREFIX, FINALIZED_BLOCK_HASH.getBytes()); + remove(VARIABLES_PREFIX, SAFE_BLOCK_HASH.getBytes()); + remove(VARIABLES_PREFIX, FORK_HEADS.getBytes()); + remove(Bytes.EMPTY, SEQ_NO_STORE.getBytes()); + } } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProvider.java index 77b181b0072..13ad3270f01 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProvider.java @@ -16,6 +16,7 @@ import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.chain.BlockchainStorage; +import org.hyperledger.besu.ethereum.chain.VariablesStorage; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions; import org.hyperledger.besu.ethereum.storage.StorageProvider; @@ -44,18 +45,6 @@ public class KeyValueStorageProvider implements StorageProvider { protected final Map storageInstances = new HashMap<>(); private final ObservableMetricsSystem metricsSystem; - public KeyValueStorageProvider( - final Function storageCreator, - final KeyValueStorage worldStatePreimageStorage, - final boolean segmentIsolationSupported, - final ObservableMetricsSystem metricsSystem) { - this.storageCreator = storageCreator; - this.worldStatePreimageStorage = worldStatePreimageStorage; - this.isWorldStateIterable = segmentIsolationSupported; - this.isWorldStateSnappable = SNAPSHOT_ISOLATION_UNSUPPORTED; - this.metricsSystem = metricsSystem; - } - public KeyValueStorageProvider( final Function storageCreator, final KeyValueStorage worldStatePreimageStorage, @@ -70,9 +59,17 @@ public KeyValueStorageProvider( } @Override - public BlockchainStorage createBlockchainStorage(final ProtocolSchedule protocolSchedule) { + public VariablesStorage createVariablesStorage() { + return new VariablesKeyValueStorage( + getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.VARIABLES)); + } + + @Override + public BlockchainStorage createBlockchainStorage( + final ProtocolSchedule protocolSchedule, final VariablesStorage variablesStorage) { return new KeyValueStoragePrefixedKeyBlockchainStorage( getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.BLOCKCHAIN), + variablesStorage, ScheduleBasedBlockHeaderFunctions.create(protocolSchedule)); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/VariablesKeyValueStorage.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/VariablesKeyValueStorage.java new file mode 100644 index 00000000000..28e6648a82d --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/VariablesKeyValueStorage.java @@ -0,0 +1,145 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.storage.keyvalue; + +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.CHAIN_HEAD_HASH; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.FINALIZED_BLOCK_HASH; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.FORK_HEADS; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.SAFE_BLOCK_HASH; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.SEQ_NO_STORE; + +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.ethereum.chain.VariablesStorage; +import org.hyperledger.besu.ethereum.rlp.RLP; +import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; +import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction; + +import java.util.Collection; +import java.util.Optional; + +import com.google.common.collect.Lists; +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; + +public class VariablesKeyValueStorage implements VariablesStorage { + final KeyValueStorage variables; + + public VariablesKeyValueStorage(final KeyValueStorage variables) { + this.variables = variables; + } + + @Override + public Optional getChainHead() { + return getVariable(CHAIN_HEAD_HASH).map(this::bytesToHash); + } + + @Override + public Collection getForkHeads() { + return getVariable(FORK_HEADS) + .map(bytes -> RLP.input(bytes).readList(in -> this.bytesToHash(in.readBytes32()))) + .orElse(Lists.newArrayList()); + } + + @Override + public Optional getFinalized() { + return getVariable(FINALIZED_BLOCK_HASH).map(this::bytesToHash); + } + + @Override + public Optional getSafeBlock() { + return getVariable(SAFE_BLOCK_HASH).map(this::bytesToHash); + } + + @Override + public Optional getLocalEnrSeqno() { + return getVariable(SEQ_NO_STORE).map(Bytes::wrap); + } + + @Override + public Updater updater() { + return new Updater(variables.startTransaction()); + } + + private Hash bytesToHash(final Bytes bytes) { + return Hash.wrap(Bytes32.wrap(bytes, 0)); + } + + Optional getVariable(final Keys key) { + return variables.get(key.toByteArray()).map(Bytes::wrap); + } + + public static class Updater implements VariablesStorage.Updater { + + private final KeyValueStorageTransaction variablesTransaction; + + Updater(final KeyValueStorageTransaction variablesTransaction) { + this.variablesTransaction = variablesTransaction; + } + + @Override + public void setChainHead(final Hash blockHash) { + setVariable(CHAIN_HEAD_HASH, blockHash); + } + + @Override + public void setForkHeads(final Collection forkHeadHashes) { + final Bytes data = + RLP.encode(o -> o.writeList(forkHeadHashes, (val, out) -> out.writeBytes(val))); + setVariable(FORK_HEADS, data); + } + + @Override + public void setFinalized(final Hash blockHash) { + setVariable(FINALIZED_BLOCK_HASH, blockHash); + } + + @Override + public void setSafeBlock(final Hash blockHash) { + setVariable(SAFE_BLOCK_HASH, blockHash); + } + + @Override + public void setLocalEnrSeqno(final Bytes nodeRecord) { + setVariable(SEQ_NO_STORE, nodeRecord); + } + + @Override + public void removeAll() { + removeVariable(CHAIN_HEAD_HASH); + removeVariable(FINALIZED_BLOCK_HASH); + removeVariable(SAFE_BLOCK_HASH); + removeVariable(FORK_HEADS); + removeVariable(SEQ_NO_STORE); + } + + @Override + public void commit() { + variablesTransaction.commit(); + } + + @Override + public void rollback() { + variablesTransaction.rollback(); + } + + void setVariable(final Keys key, final Bytes value) { + variablesTransaction.put(key.toByteArray(), value.toArrayUnsafe()); + } + + void removeVariable(final Keys key) { + variablesTransaction.remove(key.toByteArray()); + } + } +} diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java index e712139f29c..bd3b77798ff 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java @@ -27,6 +27,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; +import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; @@ -40,7 +41,8 @@ public class ExecutionContextTestFixture { private final Block genesis; - private final KeyValueStorage keyValueStorage; + private final KeyValueStorage blockchainKeyValueStorage; + private final KeyValueStorage variablesKeyValueStorage; private final MutableBlockchain blockchain; private final WorldStateArchive stateArchive; @@ -49,15 +51,20 @@ public class ExecutionContextTestFixture { private static final GenesisConfigFile genesisConfigFile = GenesisConfigFile.mainnet(); private ExecutionContextTestFixture( - final ProtocolSchedule protocolSchedule, final KeyValueStorage keyValueStorage) { + final ProtocolSchedule protocolSchedule, + final KeyValueStorage blockchainKeyValueStorage, + final KeyValueStorage variablesKeyValueStorage) { final GenesisState genesisState = GenesisState.fromConfig(genesisConfigFile, protocolSchedule); this.genesis = genesisState.getBlock(); - this.keyValueStorage = keyValueStorage; + this.blockchainKeyValueStorage = blockchainKeyValueStorage; + this.variablesKeyValueStorage = variablesKeyValueStorage; this.blockchain = DefaultBlockchain.createMutable( genesis, new KeyValueStoragePrefixedKeyBlockchainStorage( - keyValueStorage, new MainnetBlockHeaderFunctions()), + blockchainKeyValueStorage, + new VariablesKeyValueStorage(variablesKeyValueStorage), + new MainnetBlockHeaderFunctions()), new NoOpMetricsSystem(), 0); this.stateArchive = createInMemoryWorldStateArchive(); @@ -78,8 +85,12 @@ public Block getGenesis() { return genesis; } - public KeyValueStorage getKeyValueStorage() { - return keyValueStorage; + public KeyValueStorage getBlockchainKeyValueStorage() { + return blockchainKeyValueStorage; + } + + public KeyValueStorage getVariablesKeyValueStorage() { + return variablesKeyValueStorage; } public MutableBlockchain getBlockchain() { @@ -99,12 +110,17 @@ public ProtocolContext getProtocolContext() { } public static class Builder { - - private KeyValueStorage keyValueStorage; + private KeyValueStorage variablesKeyValueStorage; + private KeyValueStorage blockchainKeyValueStorage; private ProtocolSchedule protocolSchedule; - public Builder keyValueStorage(final KeyValueStorage keyValueStorage) { - this.keyValueStorage = keyValueStorage; + public Builder variablesKeyValueStorage(final KeyValueStorage keyValueStorage) { + this.variablesKeyValueStorage = keyValueStorage; + return this; + } + + public Builder blockchainKeyValueStorage(final KeyValueStorage keyValueStorage) { + this.blockchainKeyValueStorage = keyValueStorage; return this; } @@ -125,10 +141,14 @@ public ExecutionContextTestFixture build() { EvmConfiguration.DEFAULT) .createProtocolSchedule(); } - if (keyValueStorage == null) { - keyValueStorage = new InMemoryKeyValueStorage(); + if (blockchainKeyValueStorage == null) { + blockchainKeyValueStorage = new InMemoryKeyValueStorage(); + } + if (variablesKeyValueStorage == null) { + variablesKeyValueStorage = new InMemoryKeyValueStorage(); } - return new ExecutionContextTestFixture(protocolSchedule, keyValueStorage); + return new ExecutionContextTestFixture( + protocolSchedule, variablesKeyValueStorage, blockchainKeyValueStorage); } } } diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java index 58852f3b0ba..7c1dd689bcf 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java @@ -19,11 +19,13 @@ import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.DefaultBlockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; +import org.hyperledger.besu.ethereum.chain.VariablesStorage; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateKeyValueStorage; import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider; +import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStatePreimageKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; @@ -44,15 +46,30 @@ public InMemoryKeyValueStorageProvider() { } public static MutableBlockchain createInMemoryBlockchain(final Block genesisBlock) { - return createInMemoryBlockchain(genesisBlock, new MainnetBlockHeaderFunctions()); + return createInMemoryBlockchain(genesisBlock, createInMemoryVariablesStorage()); + } + + public static MutableBlockchain createInMemoryBlockchain( + final Block genesisBlock, final VariablesStorage variablesStorage) { + return createInMemoryBlockchain( + genesisBlock, new MainnetBlockHeaderFunctions(), variablesStorage); } public static MutableBlockchain createInMemoryBlockchain( final Block genesisBlock, final BlockHeaderFunctions blockHeaderFunctions) { + return createInMemoryBlockchain( + genesisBlock, blockHeaderFunctions, createInMemoryVariablesStorage()); + } + + public static MutableBlockchain createInMemoryBlockchain( + final Block genesisBlock, + final BlockHeaderFunctions blockHeaderFunctions, + final VariablesStorage variablesStorage) { final InMemoryKeyValueStorage keyValueStorage = new InMemoryKeyValueStorage(); return DefaultBlockchain.createMutable( genesisBlock, - new KeyValueStoragePrefixedKeyBlockchainStorage(keyValueStorage, blockHeaderFunctions), + new KeyValueStoragePrefixedKeyBlockchainStorage( + keyValueStorage, variablesStorage, blockHeaderFunctions), new NoOpMetricsSystem(), 0); } @@ -87,4 +104,8 @@ public static MutableWorldState createInMemoryWorldState() { public static PrivateStateStorage createInMemoryPrivateStateStorage() { return new PrivateStateKeyValueStorage(new InMemoryKeyValueStorage()); } + + public static VariablesStorage createInMemoryVariablesStorage() { + return new VariablesKeyValueStorage(new InMemoryKeyValueStorage()); + } } diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/VariablesStorageHelper.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/VariablesStorageHelper.java new file mode 100644 index 00000000000..9744748ef1f --- /dev/null +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/VariablesStorageHelper.java @@ -0,0 +1,153 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.core; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.CHAIN_HEAD_HASH; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.FINALIZED_BLOCK_HASH; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.FORK_HEADS; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.SAFE_BLOCK_HASH; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.SEQ_NO_STORE; + +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys; +import org.hyperledger.besu.ethereum.rlp.RLP; +import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; +import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; +import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction; + +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; + +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; + +public class VariablesStorageHelper { + public static final Bytes VARIABLES_PREFIX = Bytes.of(1); + public static final Hash SAMPLE_CHAIN_HEAD = Hash.fromHexStringLenient("0x01234"); + public static final Hash SAMPLE_FINALIZED = Hash.fromHexStringLenient("0x56789"); + public static final Hash SAMPLE_SAFE = Hash.fromHexStringLenient("0xabcde"); + public static final Hash FORK1 = Hash.fromHexStringLenient("0xf1357"); + public static final Hash FORK2 = Hash.fromHexStringLenient("0xf2468"); + public static final Bytes SAMPLE_FORK_HEADS = + RLP.encode(o -> o.writeList(List.of(FORK1, FORK2), (val, out) -> out.writeBytes(val))); + public static final Bytes SAMPLE_ERN_SEQNO = Bytes.fromHexStringLenient("0xabc123"); + public static final EnumSet NOT_PREFIXED_KEYS = EnumSet.of(SEQ_NO_STORE); + + public static Map getSampleVariableValues() { + final var variableValues = new EnumMap(Keys.class); + variableValues.put(CHAIN_HEAD_HASH, SAMPLE_CHAIN_HEAD); + variableValues.put(FINALIZED_BLOCK_HASH, SAMPLE_FINALIZED); + variableValues.put(SAFE_BLOCK_HASH, SAMPLE_SAFE); + variableValues.put(FORK_HEADS, SAMPLE_FORK_HEADS); + variableValues.put(SEQ_NO_STORE, SAMPLE_ERN_SEQNO); + return variableValues; + } + + public static void assertNoVariablesInStorage(final KeyValueStorage kvStorage) { + assertThat(kvStorage.streamKeys()).isEmpty(); + } + + public static void assertVariablesPresentInVariablesStorage( + final KeyValueStorage kvVariables, final Map variableValues) { + assertVariablesPresentInStorage(kvVariables, Bytes.EMPTY, variableValues); + } + + public static void assertVariablesPresentInBlockchainStorage( + final KeyValueStorage kvBlockchain, final Map variableValues) { + assertVariablesPresentInStorage(kvBlockchain, VARIABLES_PREFIX, variableValues); + } + + public static void assertVariablesPresentInStorage( + final KeyValueStorage kvStorage, final Bytes prefix, final Map variableValues) { + variableValues.forEach( + (k, v) -> + assertThat( + kvStorage.get( + Bytes.concatenate( + (NOT_PREFIXED_KEYS.contains(k) ? Bytes.EMPTY : prefix), + k.getBytes()) + .toArrayUnsafe())) + .contains(v.toArrayUnsafe())); + } + + public static void assertVariablesReturnedByBlockchainStorage( + final KeyValueStoragePrefixedKeyBlockchainStorage blockchainStorage, + final Map variableValues) { + variableValues.computeIfPresent( + CHAIN_HEAD_HASH, + (k, v) -> { + assertThat(blockchainStorage.getChainHead()).isPresent().contains(bytesToHash(v)); + return v; + }); + + variableValues.computeIfPresent( + FINALIZED_BLOCK_HASH, + (k, v) -> { + assertThat(blockchainStorage.getFinalized()).isPresent().contains(bytesToHash(v)); + return v; + }); + + variableValues.computeIfPresent( + SAFE_BLOCK_HASH, + (k, v) -> { + assertThat(blockchainStorage.getSafeBlock()).isPresent().contains(bytesToHash(v)); + return v; + }); + + variableValues.computeIfPresent( + FORK_HEADS, + (k, v) -> { + assertThat(blockchainStorage.getForkHeads()) + .containsExactlyElementsOf( + RLP.input(v).readList(in -> bytesToHash(in.readBytes32()))); + return v; + }); + } + + public static void populateBlockchainStorage( + final KeyValueStorage storage, final Map variableValues) { + populateStorage(storage, VARIABLES_PREFIX, variableValues); + } + + public static void populateVariablesStorage( + final KeyValueStorage storage, final Map variableValues) { + populateStorage(storage, Bytes.EMPTY, variableValues); + } + + public static void populateStorage( + final KeyValueStorage storage, final Bytes prefix, final Map variableValues) { + populateVariables(storage, prefix, variableValues); + } + + public static void populateVariables( + final KeyValueStorage storage, final Bytes prefix, final Map variableValues) { + final var tx = storage.startTransaction(); + variableValues.forEach( + (k, v) -> putVariable(tx, (NOT_PREFIXED_KEYS.contains(k) ? Bytes.EMPTY : prefix), k, v)); + tx.commit(); + } + + public static void putVariable( + final KeyValueStorageTransaction tx, final Bytes prefix, final Keys key, final Bytes value) { + tx.put(Bytes.concatenate(prefix, key.getBytes()).toArrayUnsafe(), value.toArrayUnsafe()); + } + + public static Hash bytesToHash(final Bytes bytes) { + return Hash.wrap(Bytes32.wrap(bytes, 0)); + } +} diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/ChainDataPrunerTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/ChainDataPrunerTest.java index 79609bb3000..00d0797d39b 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/ChainDataPrunerTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/ChainDataPrunerTest.java @@ -21,6 +21,7 @@ import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; +import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; @@ -38,7 +39,9 @@ public void singleChainPruning() { final BlockDataGenerator gen = new BlockDataGenerator(); final BlockchainStorage blockchainStorage = new KeyValueStoragePrefixedKeyBlockchainStorage( - new InMemoryKeyValueStorage(), new MainnetBlockHeaderFunctions()); + new InMemoryKeyValueStorage(), + new VariablesKeyValueStorage(new InMemoryKeyValueStorage()), + new MainnetBlockHeaderFunctions()); final ChainDataPruner chainDataPruner = new ChainDataPruner( blockchainStorage, @@ -74,7 +77,9 @@ public void forkPruning() { final BlockDataGenerator gen = new BlockDataGenerator(); final BlockchainStorage blockchainStorage = new KeyValueStoragePrefixedKeyBlockchainStorage( - new InMemoryKeyValueStorage(), new MainnetBlockHeaderFunctions()); + new InMemoryKeyValueStorage(), + new VariablesKeyValueStorage(new InMemoryKeyValueStorage()), + new MainnetBlockHeaderFunctions()); final ChainDataPruner chainDataPruner = new ChainDataPruner( blockchainStorage, diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchainTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchainTest.java index 5fece9c6359..b3523e1d9b7 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchainTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchainTest.java @@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; +import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.metrics.MetricsSystemFactory; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; @@ -52,8 +53,10 @@ public void initializeNew() { final BlockDataGenerator gen = new BlockDataGenerator(); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, genesisBlock); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, genesisBlock); assertBlockDataIsStored(blockchain, genesisBlock, Collections.emptyList()); assertBlockIsHead(blockchain, genesisBlock); @@ -67,11 +70,13 @@ public void initializeExisting() { // Write to kv store final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); - createMutableBlockchain(kvStore, genesisBlock); + createMutableBlockchain(kvStore, kvStoreVariables, genesisBlock); // Initialize a new blockchain store with kvStore that already contains data - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, genesisBlock); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, genesisBlock); assertBlockDataIsStored(blockchain, genesisBlock, Collections.emptyList()); assertBlockIsHead(blockchain, genesisBlock); @@ -85,11 +90,15 @@ public void initializeExistingWithWrongGenesisBlock() { // Write to kv store final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); - createMutableBlockchain(kvStore, genesisBlock); + createMutableBlockchain(kvStore, kvStoreVariables, genesisBlock); // Initialize a new blockchain store with same kvStore, but different genesis block - assertThatThrownBy(() -> createMutableBlockchain(kvStore, gen.genesisBlock(), "/test/path")) + assertThatThrownBy( + () -> + createMutableBlockchain( + kvStore, kvStoreVariables, gen.genesisBlock(), "/test/path")) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining( "Supplied genesis block does not match chain data stored in /test/path.\n" @@ -101,13 +110,14 @@ public void initializeExistingWithWrongGenesisBlock() { public void initializeReadOnly_withGenesisBlock() { final BlockDataGenerator gen = new BlockDataGenerator(); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); // Write genesis block to storage - createMutableBlockchain(kvStore, genesisBlock); + createMutableBlockchain(kvStore, kvStoreVariables, genesisBlock); // Create read only chain - final Blockchain blockchain = createBlockchain(kvStore); + final Blockchain blockchain = createBlockchain(kvStore, kvStoreVariables); assertBlockDataIsStored(blockchain, genesisBlock, Collections.emptyList()); assertBlockIsHead(blockchain, genesisBlock); @@ -118,12 +128,14 @@ public void initializeReadOnly_withGenesisBlock() { public void initializeReadOnly_withSmallChain() { final BlockDataGenerator gen = new BlockDataGenerator(); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final List blocks = gen.blockSequence(10); final List> blockReceipts = new ArrayList<>(blocks.size()); blockReceipts.add(Collections.emptyList()); // Write small chain to storage - final MutableBlockchain mutableBlockchain = createMutableBlockchain(kvStore, blocks.get(0)); + final MutableBlockchain mutableBlockchain = + createMutableBlockchain(kvStore, kvStoreVariables, blocks.get(0)); for (int i = 1; i < blocks.size(); i++) { final Block block = blocks.get(i); final List receipts = gen.receipts(block); @@ -132,7 +144,7 @@ public void initializeReadOnly_withSmallChain() { } // Create read only chain - final Blockchain blockchain = createBlockchain(kvStore); + final Blockchain blockchain = createBlockchain(kvStore, kvStoreVariables); for (int i = 0; i < blocks.size(); i++) { assertBlockDataIsStored(blockchain, blocks.get(i), blockReceipts.get(i)); @@ -148,12 +160,14 @@ public void initializeReadOnly_withGiantDifficultyAndLiveMetrics() { gen.setBlockOptionsSupplier( () -> BlockOptions.create().setDifficulty(Difficulty.of(Long.MAX_VALUE))); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final List blocks = gen.blockSequence(10); final List> blockReceipts = new ArrayList<>(blocks.size()); blockReceipts.add(Collections.emptyList()); // Write small chain to storage - final MutableBlockchain mutableBlockchain = createMutableBlockchain(kvStore, blocks.get(0)); + final MutableBlockchain mutableBlockchain = + createMutableBlockchain(kvStore, kvStoreVariables, blocks.get(0)); for (int i = 1; i < blocks.size(); i++) { final Block block = blocks.get(i); final List receipts = gen.receipts(block); @@ -164,7 +178,7 @@ public void initializeReadOnly_withGiantDifficultyAndLiveMetrics() { // Create read only chain final Blockchain blockchain = DefaultBlockchain.create( - createStorage(kvStore), + createStorage(kvStore, kvStoreVariables), MetricsSystemFactory.create(MetricsConfiguration.builder().enabled(true).build()), 0); @@ -179,8 +193,8 @@ public void initializeReadOnly_withGiantDifficultyAndLiveMetrics() { @Test public void initializeReadOnly_emptyStorage() { final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); - - assertThatThrownBy(() -> createBlockchain(kvStore)) + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); + assertThatThrownBy(() -> createBlockchain(kvStore, kvStoreVariables)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("Cannot create Blockchain from empty storage"); } @@ -190,8 +204,10 @@ public void appendBlock() { final BlockDataGenerator gen = new BlockDataGenerator(); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, genesisBlock); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, genesisBlock); final BlockDataGenerator.BlockOptions options = new BlockDataGenerator.BlockOptions() @@ -218,8 +234,10 @@ public void appendUnconnectedBlock() { final BlockDataGenerator gen = new BlockDataGenerator(); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, genesisBlock); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, genesisBlock); final BlockDataGenerator.BlockOptions options = new BlockDataGenerator.BlockOptions().setBlockNumber(1L).setParentHash(Hash.ZERO); @@ -234,8 +252,10 @@ public void appendBlockWithMismatchedReceipts() { final BlockDataGenerator gen = new BlockDataGenerator(); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, genesisBlock); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, genesisBlock); final BlockDataGenerator.BlockOptions options = new BlockDataGenerator.BlockOptions() @@ -256,7 +276,9 @@ public void createSmallChain() { chain.stream().map(gen::receipts).collect(Collectors.toList()); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, chain.get(0)); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, chain.get(0)); for (int i = 1; i < chain.size(); i++) { blockchain.appendBlock(chain.get(i), blockReceipts.get(i)); } @@ -281,7 +303,9 @@ public void appendBlockWithReorgToChainAtEqualHeight() { final List> blockReceipts = chain.stream().map(gen::receipts).collect(Collectors.toList()); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, chain.get(0)); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, chain.get(0)); // Listen to block events and add the Logs here List logsWithMetadata = new ArrayList<>(); @@ -358,7 +382,9 @@ public void appendBlockWithReorgToShorterChain() { final List> blockReceipts = chain.stream().map(gen::receipts).collect(Collectors.toList()); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, chain.get(0)); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, chain.get(0)); // Listen to block events and add the Logs here List logsWithMetadata = new ArrayList<>(); blockchain.observeBlockAdded(event -> logsWithMetadata.addAll(event.getLogsWithMetadata())); @@ -477,7 +503,9 @@ public void appendBlockWithReorgToLongerChain() { final List> blockReceipts = chain.stream().map(gen::receipts).collect(Collectors.toList()); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, chain.get(0)); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, chain.get(0)); // Listen to block events and add the Logs here List logsWithMetadata = new ArrayList<>(); blockchain.observeBlockAdded(event -> logsWithMetadata.addAll(event.getLogsWithMetadata())); @@ -587,7 +615,9 @@ public void reorgWithOverlappingTransactions() { final List> blockReceipts = chain.stream().map(gen::receipts).collect(Collectors.toList()); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, chain.get(0)); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, chain.get(0)); // Listen to block events and add the Logs here List logsWithMetadata = new ArrayList<>(); blockchain.observeBlockAdded(event -> logsWithMetadata.addAll(event.getLogsWithMetadata())); @@ -658,7 +688,9 @@ public void rewindChain() { final List> blockReceipts = chain.stream().map(gen::receipts).collect(Collectors.toList()); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, chain.get(0)); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, chain.get(0)); for (int i = 1; i < chain.size(); i++) { blockchain.appendBlock(chain.get(i), blockReceipts.get(i)); } @@ -697,7 +729,9 @@ public void appendBlockForFork() { final List> blockReceipts = chain.stream().map(gen::receipts).collect(Collectors.toList()); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, chain.get(0)); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, chain.get(0)); // Listen to block events and add the Logs here List logsWithMetadata = new ArrayList<>(); blockchain.observeBlockAdded(event -> logsWithMetadata.addAll(event.getLogsWithMetadata())); @@ -782,8 +816,10 @@ public void appendBlockForFork() { public void blockAddedObserver_removeNonexistentObserver() { final BlockDataGenerator gen = new BlockDataGenerator(); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, genesisBlock); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, genesisBlock); assertThat(blockchain.removeObserver(7)).isFalse(); } @@ -793,8 +829,10 @@ public void blockAddedObserver_addRemoveSingle() { final BlockDataGenerator gen = new BlockDataGenerator(); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, genesisBlock); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, genesisBlock); final long observerId = blockchain.observeBlockAdded(__ -> {}); assertThat(blockchain.observerCount()).isEqualTo(1); @@ -808,8 +846,10 @@ public void blockAddedObserver_nullObserver() { final BlockDataGenerator gen = new BlockDataGenerator(); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, genesisBlock); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, genesisBlock); assertThatThrownBy(() -> blockchain.observeBlockAdded(null)) .isInstanceOf(NullPointerException.class); @@ -820,8 +860,10 @@ public void blockAddedObserver_addRemoveMultiple() { final BlockDataGenerator gen = new BlockDataGenerator(); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, genesisBlock); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, genesisBlock); final long observerId1 = blockchain.observeBlockAdded(__ -> {}); assertThat(blockchain.observerCount()).isEqualTo(1); @@ -847,8 +889,10 @@ public void blockAddedObserver_invokedSingle() { final BlockDataGenerator gen = new BlockDataGenerator(); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, genesisBlock); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, genesisBlock); final BlockDataGenerator.BlockOptions options = new BlockDataGenerator.BlockOptions() @@ -870,8 +914,10 @@ public void blockAddedObserver_invokedMultiple() { final BlockDataGenerator gen = new BlockDataGenerator(); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); + final KeyValueStorage kvStoreVariables = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); - final DefaultBlockchain blockchain = createMutableBlockchain(kvStore, genesisBlock); + final DefaultBlockchain blockchain = + createMutableBlockchain(kvStore, kvStoreVariables, genesisBlock); final BlockDataGenerator.BlockOptions options = new BlockDataGenerator.BlockOptions() @@ -944,26 +990,40 @@ private void assertTotalDifficultiesAreConsistent(final Blockchain blockchain, f assertThat(blockchain.getChainHead().getTotalDifficulty()).isEqualTo(td); } - private BlockchainStorage createStorage(final KeyValueStorage kvStore) { + private BlockchainStorage createStorage( + final KeyValueStorage kvStoreChain, final KeyValueStorage kvStorageVariables) { return new KeyValueStoragePrefixedKeyBlockchainStorage( - kvStore, new MainnetBlockHeaderFunctions()); + kvStoreChain, + new VariablesKeyValueStorage(kvStorageVariables), + new MainnetBlockHeaderFunctions()); } private DefaultBlockchain createMutableBlockchain( - final KeyValueStorage kvStore, final Block genesisBlock) { + final KeyValueStorage kvStore, + final KeyValueStorage kvStorageVariables, + final Block genesisBlock) { return (DefaultBlockchain) DefaultBlockchain.createMutable( - genesisBlock, createStorage(kvStore), new NoOpMetricsSystem(), 0); + genesisBlock, createStorage(kvStore, kvStorageVariables), new NoOpMetricsSystem(), 0); } private DefaultBlockchain createMutableBlockchain( - final KeyValueStorage kvStore, final Block genesisBlock, final String dataDirectory) { + final KeyValueStorage kvStore, + final KeyValueStorage kvStorageVariables, + final Block genesisBlock, + final String dataDirectory) { return (DefaultBlockchain) DefaultBlockchain.createMutable( - genesisBlock, createStorage(kvStore), new NoOpMetricsSystem(), 0, dataDirectory); + genesisBlock, + createStorage(kvStore, kvStorageVariables), + new NoOpMetricsSystem(), + 0, + dataDirectory); } - private Blockchain createBlockchain(final KeyValueStorage kvStore) { - return DefaultBlockchain.create(createStorage(kvStore), new NoOpMetricsSystem(), 0); + private Blockchain createBlockchain( + final KeyValueStorage kvStore, final KeyValueStorage kvStorageVariables) { + return DefaultBlockchain.create( + createStorage(kvStore, kvStorageVariables), new NoOpMetricsSystem(), 0); } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStoragePrefixedKeyBlockchainStorageTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStoragePrefixedKeyBlockchainStorageTest.java new file mode 100644 index 00000000000..cd072780cfc --- /dev/null +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStoragePrefixedKeyBlockchainStorageTest.java @@ -0,0 +1,103 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.storage.keyvalue; + +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.FINALIZED_BLOCK_HASH; +import static org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys.SAFE_BLOCK_HASH; +import static org.hyperledger.besu.ethereum.core.VariablesStorageHelper.assertNoVariablesInStorage; +import static org.hyperledger.besu.ethereum.core.VariablesStorageHelper.assertVariablesPresentInVariablesStorage; +import static org.hyperledger.besu.ethereum.core.VariablesStorageHelper.assertVariablesReturnedByBlockchainStorage; +import static org.hyperledger.besu.ethereum.core.VariablesStorageHelper.getSampleVariableValues; +import static org.hyperledger.besu.ethereum.core.VariablesStorageHelper.populateBlockchainStorage; +import static org.hyperledger.besu.ethereum.core.VariablesStorageHelper.populateVariablesStorage; +import static org.mockito.Mockito.mock; + +import org.hyperledger.besu.ethereum.chain.VariablesStorage; +import org.hyperledger.besu.ethereum.chain.VariablesStorage.Keys; +import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; +import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; +import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; + +import java.util.Map; + +import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class KeyValueStoragePrefixedKeyBlockchainStorageTest { + private final BlockHeaderFunctions blockHeaderFunctions = mock(BlockHeaderFunctions.class); + private KeyValueStorage kvBlockchain; + private KeyValueStorage kvVariables; + private VariablesStorage variablesStorage; + private Map variableValues; + + @BeforeEach + public void setup() { + kvBlockchain = new InMemoryKeyValueStorage(); + kvVariables = new InMemoryKeyValueStorage(); + variablesStorage = new VariablesKeyValueStorage(kvVariables); + variableValues = getSampleVariableValues(); + } + + @Test + public void migrationToVariablesStorage() { + populateBlockchainStorage(kvBlockchain, variableValues); + + assertNoVariablesInStorage(kvVariables); + + final var blockchainStorage = + new KeyValueStoragePrefixedKeyBlockchainStorage( + kvBlockchain, variablesStorage, blockHeaderFunctions); + + assertNoVariablesInStorage(kvBlockchain); + assertVariablesPresentInVariablesStorage(kvVariables, variableValues); + + assertVariablesReturnedByBlockchainStorage(blockchainStorage, variableValues); + } + + @Test + public void migrationToVariablesStorageWhenSomeVariablesDoNotExist() { + variableValues.remove(FINALIZED_BLOCK_HASH); + variableValues.remove(SAFE_BLOCK_HASH); + populateBlockchainStorage(kvBlockchain, variableValues); + + assertNoVariablesInStorage(kvVariables); + + final var blockchainStorage = + new KeyValueStoragePrefixedKeyBlockchainStorage( + kvBlockchain, variablesStorage, blockHeaderFunctions); + + assertNoVariablesInStorage(kvBlockchain); + assertVariablesPresentInVariablesStorage(kvVariables, variableValues); + + assertVariablesReturnedByBlockchainStorage(blockchainStorage, variableValues); + } + + @Test + public void doesNothingIfVariablesAlreadyMigrated() { + populateVariablesStorage(kvVariables, variableValues); + + assertNoVariablesInStorage(kvBlockchain); + + final var blockchainStorage = + new KeyValueStoragePrefixedKeyBlockchainStorage( + kvBlockchain, variablesStorage, blockHeaderFunctions); + + assertNoVariablesInStorage(kvBlockchain); + assertVariablesPresentInVariablesStorage(kvVariables, variableValues); + + assertVariablesReturnedByBlockchainStorage(blockchainStorage, variableValues); + } +} diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/worldstate/PrunerTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/worldstate/PrunerTest.java index dfaef9fae1d..fa90bf6a8e2 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/worldstate/PrunerTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/worldstate/PrunerTest.java @@ -31,6 +31,7 @@ import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; +import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; import org.hyperledger.besu.testutil.MockExecutorService; @@ -60,7 +61,9 @@ public class PrunerTest { public void shouldMarkCorrectBlockAndSweep() throws ExecutionException, InterruptedException { final BlockchainStorage blockchainStorage = new KeyValueStoragePrefixedKeyBlockchainStorage( - new InMemoryKeyValueStorage(), new MainnetBlockHeaderFunctions()); + new InMemoryKeyValueStorage(), + new VariablesKeyValueStorage(new InMemoryKeyValueStorage()), + new MainnetBlockHeaderFunctions()); final MutableBlockchain blockchain = DefaultBlockchain.createMutable(genesisBlock, blockchainStorage, metricsSystem, 0); @@ -81,7 +84,9 @@ public void shouldMarkCorrectBlockAndSweep() throws ExecutionException, Interrup public void shouldOnlySweepAfterBlockConfirmationPeriodAndRetentionPeriodEnds() { final BlockchainStorage blockchainStorage = new KeyValueStoragePrefixedKeyBlockchainStorage( - new InMemoryKeyValueStorage(), new MainnetBlockHeaderFunctions()); + new InMemoryKeyValueStorage(), + new VariablesKeyValueStorage(new InMemoryKeyValueStorage()), + new MainnetBlockHeaderFunctions()); final MutableBlockchain blockchain = DefaultBlockchain.createMutable(genesisBlock, blockchainStorage, metricsSystem, 0); @@ -107,7 +112,9 @@ public void shouldOnlySweepAfterBlockConfirmationPeriodAndRetentionPeriodEnds() public void abortsPruningWhenFullyMarkedBlockNoLongerOnCanonicalChain() { final BlockchainStorage blockchainStorage = new KeyValueStoragePrefixedKeyBlockchainStorage( - new InMemoryKeyValueStorage(), new MainnetBlockHeaderFunctions()); + new InMemoryKeyValueStorage(), + new VariablesKeyValueStorage(new InMemoryKeyValueStorage()), + new MainnetBlockHeaderFunctions()); final MutableBlockchain blockchain = DefaultBlockchain.createMutable(genesisBlock, blockchainStorage, metricsSystem, 0); @@ -177,7 +184,9 @@ public void shouldRejectInvalidArguments() { public void shouldCleanUpPruningStrategyOnShutdown() throws InterruptedException { final BlockchainStorage blockchainStorage = new KeyValueStoragePrefixedKeyBlockchainStorage( - new InMemoryKeyValueStorage(), new MainnetBlockHeaderFunctions()); + new InMemoryKeyValueStorage(), + new VariablesKeyValueStorage(new InMemoryKeyValueStorage()), + new MainnetBlockHeaderFunctions()); final MutableBlockchain blockchain = DefaultBlockchain.createMutable(genesisBlock, blockchainStorage, metricsSystem, 0); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckPointBlockImportStepTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckPointBlockImportStepTest.java index e57a8f87a29..1520edb0679 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckPointBlockImportStepTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckPointBlockImportStepTest.java @@ -27,6 +27,7 @@ import org.hyperledger.besu.ethereum.eth.sync.fastsync.checkpoint.Checkpoint; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; +import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; @@ -49,7 +50,9 @@ public class CheckPointBlockImportStepTest { public void setup() { blockchainStorage = new KeyValueStoragePrefixedKeyBlockchainStorage( - new InMemoryKeyValueStorage(), new MainnetBlockHeaderFunctions()); + new InMemoryKeyValueStorage(), + new VariablesKeyValueStorage(new InMemoryKeyValueStorage()), + new MainnetBlockHeaderFunctions()); blockchain = DefaultBlockchain.createMutable( generateBlock(0), blockchainStorage, mock(MetricsSystem.class), 0); diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/DataStoreModule.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/DataStoreModule.java index a2ce12caa55..fd8f7a8c375 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/DataStoreModule.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/DataStoreModule.java @@ -19,6 +19,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; +import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.plugin.services.BesuConfiguration; import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; @@ -53,6 +54,20 @@ public class DataStoreModule { List.of(KeyValueSegmentIdentifier.values()), RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS)); + @Provides + @Singleton + @Named("variables") + KeyValueStorage provideVariablesKeyValueStorage( + @Named("KeyValueStorageName") final String keyValueStorageName, + final BesuConfiguration commonConfiguration, + final MetricsSystem metricsSystem) { + return constructKeyValueStorage( + keyValueStorageName, + commonConfiguration, + metricsSystem, + KeyValueSegmentIdentifier.VARIABLES); + } + @Provides @Singleton @Named("blockchain") @@ -127,7 +142,9 @@ private KeyValueStorage constructKeyValueStorage( @Singleton static BlockchainStorage provideBlockchainStorage( @Named("blockchain") final KeyValueStorage keyValueStorage, + @Named("variables") final KeyValueStorage variablesKeyValueStorage, final BlockHeaderFunctions blockHashFunction) { - return new KeyValueStoragePrefixedKeyBlockchainStorage(keyValueStorage, blockHashFunction); + return new KeyValueStoragePrefixedKeyBlockchainStorage( + keyValueStorage, new VariablesKeyValueStorage(variablesKeyValueStorage), blockHashFunction); } } diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/PeerDiscoveryAgent.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/PeerDiscoveryAgent.java index 6c1812335cd..8af596018a1 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/PeerDiscoveryAgent.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/PeerDiscoveryAgent.java @@ -15,12 +15,12 @@ package org.hyperledger.besu.ethereum.p2p.discovery; import static com.google.common.base.Preconditions.checkArgument; -import static java.nio.charset.StandardCharsets.UTF_8; import org.hyperledger.besu.crypto.Hash; import org.hyperledger.besu.crypto.SignatureAlgorithm; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.cryptoservices.NodeKey; +import org.hyperledger.besu.ethereum.chain.VariablesStorage; import org.hyperledger.besu.ethereum.forkid.ForkIdManager; import org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration; import org.hyperledger.besu.ethereum.p2p.discovery.internal.Packet; @@ -34,12 +34,9 @@ import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissions; import org.hyperledger.besu.ethereum.p2p.rlpx.RlpxAgent; import org.hyperledger.besu.ethereum.storage.StorageProvider; -import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.nat.NatService; import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.plugin.services.MetricsSystem; -import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; -import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction; import org.hyperledger.besu.util.NetworkUtility; import java.net.InetSocketAddress; @@ -70,7 +67,6 @@ */ public abstract class PeerDiscoveryAgent { private static final Logger LOG = LoggerFactory.getLogger(PeerDiscoveryAgent.class); - private static final String SEQ_NO_STORE_KEY = "local-enr-seqno"; private static final com.google.common.base.Supplier SIGNATURE_ALGORITHM = Suppliers.memoize(SignatureAlgorithmFactory::getInstance); @@ -101,7 +97,7 @@ public abstract class PeerDiscoveryAgent { /* Is discovery enabled? */ private boolean isActive = false; - private final StorageProvider storageProvider; + private final VariablesStorage variablesStorage; private final Supplier> forkIdSupplier; private String advertisedAddress; @@ -130,7 +126,7 @@ protected PeerDiscoveryAgent( this.id = nodeKey.getPublicKey().getEncodedBytes(); - this.storageProvider = storageProvider; + this.variablesStorage = storageProvider.createVariablesStorage(); this.forkIdManager = forkIdManager; this.forkIdSupplier = () -> forkIdManager.getForkIdForChainHead().getForkIdAsBytesList(); this.rlpxAgent = rlpxAgent; @@ -187,14 +183,9 @@ public void updateNodeRecord() { return; } - final KeyValueStorage keyValueStorage = - storageProvider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.BLOCKCHAIN); final NodeRecordFactory nodeRecordFactory = NodeRecordFactory.DEFAULT; final Optional existingNodeRecord = - keyValueStorage - .get(Bytes.of(SEQ_NO_STORE_KEY.getBytes(UTF_8)).toArray()) - .map(Bytes::of) - .map(nodeRecordFactory::fromBytes); + variablesStorage.getLocalEnrSeqno().map(nodeRecordFactory::fromBytes); final Bytes addressBytes = Bytes.of(InetAddresses.forString(advertisedAddress).getAddress()); final Optional maybeEnodeURL = localNode.map(DiscoveryPeer::getEnodeURL); @@ -236,12 +227,10 @@ public void updateNodeRecord() { .slice(0, 64)); LOG.info("Writing node record to disk. {}", nodeRecord); - final KeyValueStorageTransaction keyValueStorageTransaction = - keyValueStorage.startTransaction(); - keyValueStorageTransaction.put( - Bytes.wrap(SEQ_NO_STORE_KEY.getBytes(UTF_8)).toArray(), - nodeRecord.serialize().toArray()); - keyValueStorageTransaction.commit(); + final var variablesUpdater = variablesStorage.updater(); + variablesUpdater.setLocalEnrSeqno(nodeRecord.serialize()); + variablesUpdater.commit(); + return nodeRecord; }); localNode diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java index bbfb1fba786..95cb744ace4 100644 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java +++ b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java @@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.chain.DefaultBlockchain; import org.hyperledger.besu.ethereum.chain.GenesisState; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; +import org.hyperledger.besu.ethereum.chain.VariablesStorage; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; @@ -55,6 +56,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; +import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStatePreimageKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.DefaultWorldStateArchive; @@ -254,9 +256,12 @@ private static MutableBlockchain createInMemoryBlockchain(final Block genesisBlo private static MutableBlockchain createInMemoryBlockchain( final Block genesisBlock, final BlockHeaderFunctions blockHeaderFunctions) { final InMemoryKeyValueStorage keyValueStorage = new InMemoryKeyValueStorage(); + final VariablesStorage variablesStorage = + new VariablesKeyValueStorage(new InMemoryKeyValueStorage()); return DefaultBlockchain.createMutable( genesisBlock, - new KeyValueStoragePrefixedKeyBlockchainStorage(keyValueStorage, blockHeaderFunctions), + new KeyValueStoragePrefixedKeyBlockchainStorage( + keyValueStorage, variablesStorage, blockHeaderFunctions), new NoOpMetricsSystem(), 100); } diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java index cdca868a27e..32075f364ae 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java @@ -218,24 +218,9 @@ void initColumnHandler() throws RocksDBException { } BlockBasedTableConfig createBlockBasedTableConfig(final RocksDBConfiguration config) { - if (config.isHighSpec()) return createBlockBasedTableConfigHighSpec(); - else return createBlockBasedTableConfigDefault(config); - } - - private BlockBasedTableConfig createBlockBasedTableConfigHighSpec() { - final LRUCache cache = new LRUCache(ROCKSDB_BLOCKCACHE_SIZE_HIGH_SPEC); - return new BlockBasedTableConfig() - .setFormatVersion(ROCKSDB_FORMAT_VERSION) - .setBlockCache(cache) - .setFilterPolicy(new BloomFilter(10, false)) - .setPartitionFilters(true) - .setCacheIndexAndFilterBlocks(false) - .setBlockSize(ROCKSDB_BLOCK_SIZE); - } - - private BlockBasedTableConfig createBlockBasedTableConfigDefault( - final RocksDBConfiguration config) { - final LRUCache cache = new LRUCache(config.getCacheCapacity()); + final LRUCache cache = + new LRUCache( + config.isHighSpec() ? ROCKSDB_BLOCKCACHE_SIZE_HIGH_SPEC : config.getCacheCapacity()); return new BlockBasedTableConfig() .setFormatVersion(ROCKSDB_FORMAT_VERSION) .setBlockCache(cache) From 9ae1b535a09bbc83276211b0260c1079d3daa5c1 Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Wed, 7 Jun 2023 19:06:59 +0200 Subject: [PATCH 23/35] Blobdb for static data (#5475) Signed-off-by: Fabio Di Fabio --- CHANGELOG.md | 1 + .../keyvalue/KeyValueSegmentIdentifier.java | 18 +++++++++++- plugin-api/build.gradle | 2 +- .../services/storage/SegmentIdentifier.java | 9 ++++++ .../RocksDBColumnarKeyValueStorage.java | 29 ++++++++++++------- .../RocksDBColumnarKeyValueStorageTest.java | 15 +++++++++- 6 files changed, 61 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a43fe5c2fa4..6cedd09b322 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and in case a rollback is needed, before installing a previous version, the migr - Unite the tx-pool CLI options under the same Tx Pool Options group in UX. [#5466](https://github.com/hyperledger/besu/issues/5466) - Tidy DEBUG logs by moving engine API full logging to TRACE [#5529](https://github.com/hyperledger/besu/pull/5529) - remove PoW validation if merge is enabled as it is not needed anymore [#5538](https://github.com/hyperledger/besu/pull/5538) +- Use BlobDB for blockchain storage to reduce initial sync time and write amplification [#5475](https://github.com/hyperledger/besu/pull/5475) ### Bug Fixes - check to ensure storage and transactions are not closed prior to reading/writing [#5527](https://github.com/hyperledger/besu/pull/5527) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueSegmentIdentifier.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueSegmentIdentifier.java index 43b02f224de..9cce0230cdb 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueSegmentIdentifier.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueSegmentIdentifier.java @@ -19,7 +19,7 @@ import org.bouncycastle.util.Arrays; public enum KeyValueSegmentIdentifier implements SegmentIdentifier { - BLOCKCHAIN(new byte[] {1}), + BLOCKCHAIN(new byte[] {1}, true), WORLD_STATE(new byte[] {2}, new int[] {0, 1}), PRIVATE_TRANSACTIONS(new byte[] {3}), PRIVATE_STATE(new byte[] {4}), @@ -44,14 +44,25 @@ public enum KeyValueSegmentIdentifier implements SegmentIdentifier { private final byte[] id; private final int[] versionList; + private final boolean containsStaticData; KeyValueSegmentIdentifier(final byte[] id) { this(id, new int[] {0, 1, 2}); } + KeyValueSegmentIdentifier(final byte[] id, final boolean containsStaticData) { + this(id, new int[] {0, 1, 2}, containsStaticData); + } + KeyValueSegmentIdentifier(final byte[] id, final int[] versionList) { + this(id, versionList, false); + } + + KeyValueSegmentIdentifier( + final byte[] id, final int[] versionList, final boolean containsStaticData) { this.id = id; this.versionList = versionList; + this.containsStaticData = containsStaticData; } @Override @@ -64,6 +75,11 @@ public byte[] getId() { return id; } + @Override + public boolean containsStaticData() { + return containsStaticData; + } + @Override public boolean includeInDatabaseVersion(final int version) { return Arrays.contains(versionList, version); diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index 04784c42482..3966e03751e 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -69,7 +69,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'V3sh575rrexPv+Ywe8mURT4Z3fREDCDd79PpAISFx8A=' + knownHash = '5qYaRONxsvjtA3/9OOX4B1GEaOVEXLyU2zBFU0Kpu0E=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/SegmentIdentifier.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/SegmentIdentifier.java index 9daf97fdeb9..c535966876f 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/SegmentIdentifier.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/storage/SegmentIdentifier.java @@ -47,4 +47,13 @@ public interface SegmentIdentifier { default boolean includeInDatabaseVersion(final int version) { return true; } + + /** + * Define if this segment contains data that is never updated, but only added and optionally + * deleted. Example is append only data like the blockchain. This information can be used by the + * underlying implementation to apply specific optimization for this use case. + * + * @return true if the segment contains only static data + */ + boolean containsStaticData(); } diff --git a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java index 32075f364ae..c7b1b862ffc 100644 --- a/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java +++ b/plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java @@ -153,16 +153,7 @@ public RocksDBColumnarKeyValueStorage( .noneMatch(existed -> Arrays.equals(existed, ignorableSegment.getId()))) .forEach(trimmedSegments::remove); columnDescriptors = - trimmedSegments.stream() - .map( - segment -> - new ColumnFamilyDescriptor( - segment.getId(), - new ColumnFamilyOptions() - .setTtl(0) - .setCompressionType(CompressionType.LZ4_COMPRESSION) - .setTableFormatConfig(createBlockBasedTableConfig(configuration)))) - .collect(Collectors.toList()); + trimmedSegments.stream().map(this::createColumnDescriptor).collect(Collectors.toList()); columnDescriptors.add( new ColumnFamilyDescriptor( DEFAULT_COLUMN.getBytes(StandardCharsets.UTF_8), @@ -180,6 +171,24 @@ public RocksDBColumnarKeyValueStorage( } } + private ColumnFamilyDescriptor createColumnDescriptor(final SegmentIdentifier segment) { + final var options = + new ColumnFamilyOptions() + .setTtl(0) + .setCompressionType(CompressionType.LZ4_COMPRESSION) + .setTableFormatConfig(createBlockBasedTableConfig(configuration)); + + if (segment.containsStaticData()) { + options + .setEnableBlobFiles(true) + .setEnableBlobGarbageCollection(false) + .setMinBlobSize(100) + .setBlobCompressionType(CompressionType.LZ4_COMPRESSION); + } + + return new ColumnFamilyDescriptor(segment.getId(), options); + } + private void setGlobalOptions(final RocksDBConfiguration configuration, final Statistics stats) { options = new DBOptions(); options diff --git a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorageTest.java b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorageTest.java index deb88797122..d58da12ce2f 100644 --- a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorageTest.java +++ b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorageTest.java @@ -261,14 +261,22 @@ public void dbWillBeBackwardIncompatibleAfterExperimentalSegmentsAreAdded() thro public enum TestSegment implements SegmentIdentifier { FOO(new byte[] {1}), BAR(new byte[] {2}), - EXPERIMENTAL(new byte[] {3}); + EXPERIMENTAL(new byte[] {3}), + + STATIC_DATA(new byte[] {4}, true); private final byte[] id; private final String nameAsUtf8; + private final boolean containsStaticData; TestSegment(final byte[] id) { + this(id, false); + } + + TestSegment(final byte[] id, final boolean containsStaticData) { this.id = id; this.nameAsUtf8 = new String(id, StandardCharsets.UTF_8); + this.containsStaticData = containsStaticData; } @Override @@ -280,6 +288,11 @@ public String getName() { public byte[] getId() { return id; } + + @Override + public boolean containsStaticData() { + return containsStaticData; + } } protected abstract SegmentedKeyValueStorage createSegmentedStore() From c1cfaf462ac6324bc874635e4f1a8dcca41a9452 Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Thu, 8 Jun 2023 10:59:02 +0200 Subject: [PATCH 24/35] Remove deprecated Rinkeby network (#5540) Signed-off-by: Fabio Di Fabio --- CHANGELOG.md | 3 +- .../besu/cli/config/NetworkName.java | 19 +- .../besu/ForkIdsNetworkConfigTest.java | 15 - .../hyperledger/besu/cli/BesuCommandTest.java | 44 +- .../cli/NetworkDeprecationMessageTest.java | 4 +- .../besu/cli/config/EthNetworkConfigTest.java | 10 - .../config/DefaultDiscoveryConfiguration.java | 10 - config/src/main/resources/rinkeby.json | 806 ------------------ .../consensus/clique/CliqueExtraDataTest.java | 21 - .../besu/ethereum/forkid/ForkIdTest.java | 139 --- .../besu/ethereum/forkid/ForkIdTestUtil.java | 15 - .../mainnet/MainnetProtocolScheduleTest.java | 31 - 12 files changed, 8 insertions(+), 1109 deletions(-) delete mode 100644 config/src/main/resources/rinkeby.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cedd09b322..274918ccf0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ ### Breaking Changes - Move blockchain related variables in a dedicated storage, to pave the way to future optimizations [#5471](https://github.com/hyperledger/besu/pull/5471). The migration is performed automatically at startup, -and in case a rollback is needed, before installing a previous version, the migration can be reverted, using the subcommand `storage revert-variables` with the same configuration use to run Besu. +and in case a rollback is needed, before installing a previous version, the migration can be reverted, using the subcommand `storage revert-variables` with the same configuration use to run Besu. +- Remove deprecated Rinkeby named network. [#5540](https://github.com/hyperledger/besu/pull/5540) ### Additions and Improvements - Allow Ethstats connection url to specify ws:// or wss:// scheme. [#5494](https://github.com/hyperledger/besu/issues/5494) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java b/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java index 833fe35e362..9d949b08ae3 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java @@ -23,8 +23,6 @@ public enum NetworkName { /** Mainnet network name. */ MAINNET("/mainnet.json", BigInteger.valueOf(1)), - /** Rinkeby network name. */ - RINKEBY("/rinkeby.json", BigInteger.valueOf(4)), /** Sepolia network name. */ SEPOLIA("/sepolia.json", BigInteger.valueOf(11155111)), /** Goerli network name. */ @@ -55,21 +53,8 @@ public enum NetworkName { this.genesisFile = genesisFile; this.networkId = networkId; this.canFastSync = canFastSync; - - // https://blog.ethereum.org/2022/06/21/testnet-deprecation/ - switch (networkId.intValue()) { - case 3: - deprecationDate = "in Q4 2022"; - break; - case 4: - deprecationDate = "in Q2/Q3 2023"; - break; - case 1337802: - deprecationDate = "after the Mainnet Merge"; - break; - default: - deprecationDate = null; - } + // no deprecations planned + this.deprecationDate = null; } /** diff --git a/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java b/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java index a811d2d2246..94ed79a8bf4 100644 --- a/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java +++ b/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java @@ -81,21 +81,6 @@ public static Collection parameters() { new ForkId(Bytes.ofUnsignedInt(0xf7f9bc08L), 0L), new ForkId(Bytes.ofUnsignedInt(0xf7f9bc08L), 0L)) }, - new Object[] { - NetworkName.RINKEBY, - List.of( - new ForkId(Bytes.ofUnsignedInt(0x3b8e0691L), 1L), - new ForkId(Bytes.ofUnsignedInt(0x60949295L), 2L), - new ForkId(Bytes.ofUnsignedInt(0x8bde40ddL), 3L), - new ForkId(Bytes.ofUnsignedInt(0xcb3a64bbL), 1035301L), - new ForkId(Bytes.ofUnsignedInt(0x8d748b57L), 3660663L), - new ForkId(Bytes.ofUnsignedInt(0xe49cab14L), 4321234L), - new ForkId(Bytes.ofUnsignedInt(0xafec6b27L), 5435345L), - new ForkId(Bytes.ofUnsignedInt(0xcbdb8838L), 8290928L), - new ForkId(Bytes.ofUnsignedInt(0x6910c8bdL), 8897988L), - new ForkId(Bytes.ofUnsignedInt(0x8e29f2f3L), 0L), - new ForkId(Bytes.ofUnsignedInt(0x8e29f2f3L), 0L)) - }, new Object[] { NetworkName.GOERLI, List.of( diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index 6bae8aa7150..0b25e919eb7 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -27,7 +27,6 @@ import static org.hyperledger.besu.cli.config.NetworkName.KOTTI; import static org.hyperledger.besu.cli.config.NetworkName.MAINNET; import static org.hyperledger.besu.cli.config.NetworkName.MORDOR; -import static org.hyperledger.besu.cli.config.NetworkName.RINKEBY; import static org.hyperledger.besu.cli.config.NetworkName.SEPOLIA; import static org.hyperledger.besu.cli.util.CommandLineUtils.DEPENDENCY_WARNING_MSG; import static org.hyperledger.besu.cli.util.CommandLineUtils.DEPRECATION_WARNING_MSG; @@ -41,8 +40,6 @@ import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.GOERLI_DISCOVERY_URL; import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.MAINNET_BOOTSTRAP_NODES; import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.MAINNET_DISCOVERY_URL; -import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.RINKEBY_BOOTSTRAP_NODES; -import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.RINKEBY_DISCOVERY_URL; import static org.hyperledger.besu.ethereum.worldstate.DataStorageFormat.BONSAI; import static org.hyperledger.besu.nat.kubernetes.KubernetesNatManager.DEFAULT_BESU_SERVICE_NAME_FILTER; import static org.junit.Assume.assumeThat; @@ -1061,27 +1058,11 @@ public void testGenesisPathExperimentalEipsEthConfig() { assertThat(config.getNetworkId()).isEqualTo(BigInteger.valueOf(2023)); } - @Test - public void testGenesisPathRinkebyEthConfig() { - final ArgumentCaptor networkArg = - ArgumentCaptor.forClass(EthNetworkConfig.class); - - parseCommand("--network", "rinkeby"); - - verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any(), any()); - verify(mockControllerBuilder).build(); - - final EthNetworkConfig config = networkArg.getValue(); - assertThat(config.getBootNodes()).isEqualTo(RINKEBY_BOOTSTRAP_NODES); - assertThat(config.getDnsDiscoveryUrl()).isEqualTo(RINKEBY_DISCOVERY_URL); - assertThat(config.getNetworkId()).isEqualTo(BigInteger.valueOf(4)); - } - @Test public void genesisAndNetworkMustNotBeUsedTogether() throws Exception { final Path genesisFile = createFakeGenesisFile(GENESIS_VALID_JSON); - parseCommand("--genesis-file", genesisFile.toString(), "--network", "rinkeby"); + parseCommand("--genesis-file", genesisFile.toString(), "--network", "mainnet"); Mockito.verifyNoInteractions(mockRunnerBuilder); @@ -3941,24 +3922,6 @@ public void devModeOptionMustBeUsed() throws Exception { assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); } - @Test - public void rinkebyValuesAreUsed() { - parseCommand("--network", "rinkeby"); - - final ArgumentCaptor networkArg = - ArgumentCaptor.forClass(EthNetworkConfig.class); - - verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any(), any()); - verify(mockControllerBuilder).build(); - - assertThat(networkArg.getValue()).isEqualTo(EthNetworkConfig.getNetworkConfig(RINKEBY)); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - - verify(mockLogger, times(1)).warn(contains("Rinkeby is deprecated and will be shutdown")); - } - @Test public void goerliValuesAreUsed() { parseCommand("--network", "goerli"); @@ -4076,11 +4039,6 @@ public void mordorValuesAreUsed() throws Exception { assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); } - @Test - public void rinkebyValuesCanBeOverridden() throws Exception { - networkValuesCanBeOverridden("rinkeby"); - } - @Test public void goerliValuesCanBeOverridden() throws Exception { networkValuesCanBeOverridden("goerli"); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/NetworkDeprecationMessageTest.java b/besu/src/test/java/org/hyperledger/besu/cli/NetworkDeprecationMessageTest.java index b6cb1ae5a24..bd73c2670ee 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/NetworkDeprecationMessageTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/NetworkDeprecationMessageTest.java @@ -19,15 +19,17 @@ import org.hyperledger.besu.cli.config.NetworkName; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; class NetworkDeprecationMessageTest { + @Disabled("There are no deprecation planned at this time, but keeping for reference") @ParameterizedTest @EnumSource( value = NetworkName.class, - names = {"RINKEBY"}) + names = {"A_DEPRECATED_NETWORK_NAME"}) void shouldGenerateDeprecationMessageForDeprecatedNetworks(final NetworkName network) { assertThat(NetworkDeprecationMessage.generate(network)) .contains(network.normalize() + " is deprecated and will be shutdown"); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/config/EthNetworkConfigTest.java b/besu/src/test/java/org/hyperledger/besu/cli/config/EthNetworkConfigTest.java index 7dfc2d5d4cf..66e8592b5e4 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/config/EthNetworkConfigTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/config/EthNetworkConfigTest.java @@ -20,8 +20,6 @@ import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.GOERLI_DISCOVERY_URL; import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.MAINNET_BOOTSTRAP_NODES; import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.MAINNET_DISCOVERY_URL; -import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.RINKEBY_BOOTSTRAP_NODES; -import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.RINKEBY_DISCOVERY_URL; import java.math.BigInteger; @@ -40,14 +38,6 @@ public void testDefaultMainnetConfig() { assertThat(config.getNetworkId()).isEqualTo(BigInteger.ONE); } - @Test - public void testDefaultRinkebyConfig() { - EthNetworkConfig config = EthNetworkConfig.getNetworkConfig(NetworkName.RINKEBY); - assertThat(config.getDnsDiscoveryUrl()).isEqualTo(RINKEBY_DISCOVERY_URL); - assertThat(config.getBootNodes()).isEqualTo(RINKEBY_BOOTSTRAP_NODES); - assertThat(config.getNetworkId()).isEqualTo(BigInteger.valueOf(4)); - } - @Test public void testDefaultGoerliConfig() { EthNetworkConfig config = EthNetworkConfig.getNetworkConfig(NetworkName.GOERLI); diff --git a/besu/src/test/java/org/hyperledger/besu/ethereum/p2p/config/DefaultDiscoveryConfiguration.java b/besu/src/test/java/org/hyperledger/besu/ethereum/p2p/config/DefaultDiscoveryConfiguration.java index 28772492891..3a63648bcbb 100644 --- a/besu/src/test/java/org/hyperledger/besu/ethereum/p2p/config/DefaultDiscoveryConfiguration.java +++ b/besu/src/test/java/org/hyperledger/besu/ethereum/p2p/config/DefaultDiscoveryConfiguration.java @@ -28,8 +28,6 @@ public class DefaultDiscoveryConfiguration { "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.goerli.ethdisco.net"; public static final String MAINNET_DISCOVERY_URL = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.mainnet.ethdisco.net"; - public static final String RINKEBY_DISCOVERY_URL = - "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.rinkeby.ethdisco.net"; public static final List MAINNET_BOOTSTRAP_NODES = Collections.unmodifiableList( @@ -42,14 +40,6 @@ public class DefaultDiscoveryConfiguration { ) .map(EnodeURLImpl::fromString) .collect(toList())); - public static final List RINKEBY_BOOTSTRAP_NODES = - Collections.unmodifiableList( - Stream.of( - "enode://a24ac7c5484ef4ed0c5eb2d36620ba4e4aa13b8c84684e1b4aab0cebea2ae45cb4d375b77eab56516d34bfbd3c1a833fc51296ff084b770b94fb9028c4d25ccf@52.169.42.101:30303", - "enode://343149e4feefa15d882d9fe4ac7d88f885bd05ebb735e547f12e12080a9fa07c8014ca6fd7f373123488102fe5e34111f8509cf0b7de3f5b44339c9f25e87cb8@52.3.158.184:30303", - "enode://b6b28890b006743680c52e64e0d16db57f28124885595fa03a562be1d2bf0f3a1da297d56b13da25fb992888fd556d4c1a27b1f39d531bde7de1921c90061cc6@159.89.28.211:30303") - .map(EnodeURLImpl::fromString) - .collect(toList())); public static final List GOERLI_BOOTSTRAP_NODES = Collections.unmodifiableList( Stream.of( diff --git a/config/src/main/resources/rinkeby.json b/config/src/main/resources/rinkeby.json deleted file mode 100644 index ca05655bcfb..00000000000 --- a/config/src/main/resources/rinkeby.json +++ /dev/null @@ -1,806 +0,0 @@ -{ - "config": { - "chainId": 4, - "homesteadBlock": 1, - "eip150Block": 2, - "eip158Block": 3, - "byzantiumBlock": 1035301, - "constantinopleBlock": 3660663, - "petersburgBlock": 4321234, - "istanbulBlock": 5435345, - "berlinBlock": 8290928, - "londonBlock": 8897988, - "clique": { - "blockperiodseconds": 15, - "epochlength": 30000 - }, - "discovery": { - "dns": "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.rinkeby.ethdisco.net", - "bootnodes": [ - "enode://a24ac7c5484ef4ed0c5eb2d36620ba4e4aa13b8c84684e1b4aab0cebea2ae45cb4d375b77eab56516d34bfbd3c1a833fc51296ff084b770b94fb9028c4d25ccf@52.169.42.101:30303", - "enode://343149e4feefa15d882d9fe4ac7d88f885bd05ebb735e547f12e12080a9fa07c8014ca6fd7f373123488102fe5e34111f8509cf0b7de3f5b44339c9f25e87cb8@52.3.158.184:30303", - "enode://b6b28890b006743680c52e64e0d16db57f28124885595fa03a562be1d2bf0f3a1da297d56b13da25fb992888fd556d4c1a27b1f39d531bde7de1921c90061cc6@159.89.28.211:30303" - ] - } - }, - "nonce": "0x0", - "timestamp": "0x58ee40ba", - "extraData": "0x52657370656374206d7920617574686f7269746168207e452e436172746d616e42eb768f2244c8811c63729a21a3569731535f067ffc57839b00206d1ad20c69a1981b489f772031b279182d99e65703f0076e4812653aab85fca0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "gasLimit": "0x47b760", - "difficulty": "0x1", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "0000000000000000000000000000000000000000": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000001": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000002": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000003": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000004": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000005": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000006": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000007": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000008": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000009": { - "balance": "0x1" - }, - "000000000000000000000000000000000000000a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000000b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000000c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000000d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000000e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000000f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000010": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000011": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000012": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000013": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000014": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000015": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000016": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000017": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000018": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000019": { - "balance": "0x1" - }, - "000000000000000000000000000000000000001a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000001b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000001c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000001d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000001e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000001f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000020": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000021": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000022": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000023": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000024": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000025": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000026": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000027": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000028": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000029": { - "balance": "0x1" - }, - "000000000000000000000000000000000000002a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000002b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000002c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000002d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000002e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000002f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000030": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000031": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000032": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000033": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000034": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000035": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000036": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000037": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000038": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000039": { - "balance": "0x1" - }, - "000000000000000000000000000000000000003a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000003b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000003c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000003d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000003e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000003f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000040": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000041": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000042": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000043": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000044": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000045": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000046": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000047": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000048": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000049": { - "balance": "0x1" - }, - "000000000000000000000000000000000000004a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000004b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000004c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000004d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000004e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000004f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000050": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000051": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000052": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000053": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000054": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000055": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000056": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000057": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000058": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000059": { - "balance": "0x1" - }, - "000000000000000000000000000000000000005a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000005b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000005c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000005d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000005e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000005f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000060": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000061": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000062": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000063": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000064": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000065": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000066": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000067": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000068": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000069": { - "balance": "0x1" - }, - "000000000000000000000000000000000000006a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000006b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000006c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000006d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000006e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000006f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000070": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000071": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000072": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000073": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000074": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000075": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000076": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000077": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000078": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000079": { - "balance": "0x1" - }, - "000000000000000000000000000000000000007a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000007b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000007c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000007d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000007e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000007f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000080": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000081": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000082": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000083": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000084": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000085": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000086": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000087": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000088": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000089": { - "balance": "0x1" - }, - "000000000000000000000000000000000000008a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000008b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000008c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000008d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000008e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000008f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000090": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000091": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000092": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000093": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000094": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000095": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000096": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000097": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000098": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000099": { - "balance": "0x1" - }, - "000000000000000000000000000000000000009a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000009b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000009c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000009d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000009e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000009f": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a0": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a1": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a2": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a3": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a4": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a5": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a6": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a7": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a8": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a9": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000aa": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ab": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ac": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ad": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ae": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000af": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b0": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b1": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b2": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b3": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b4": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b5": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b6": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b7": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b8": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b9": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ba": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000bb": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000bc": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000bd": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000be": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000bf": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c0": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c1": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c2": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c3": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c4": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c5": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c6": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c7": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c8": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c9": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ca": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000cb": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000cc": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000cd": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ce": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000cf": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d0": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d1": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d2": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d3": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d4": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d5": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d6": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d7": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d8": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d9": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000da": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000db": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000dc": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000dd": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000de": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000df": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e0": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e1": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e2": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e3": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e4": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e5": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e6": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e7": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e8": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e9": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ea": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000eb": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ec": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ed": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ee": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ef": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f0": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f1": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f2": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f3": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f4": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f5": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f6": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f7": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f8": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f9": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000fa": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000fb": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000fc": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000fd": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000fe": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ff": { - "balance": "0x1" - }, - "31b98d14007bdee637298086988a0bbd31184523": { - "balance": "0x200000000000000000000000000000000000000000000000000000000000000" - } - } -} diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueExtraDataTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueExtraDataTest.java index 6888a2397db..a03fe07a4a5 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueExtraDataTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueExtraDataTest.java @@ -36,7 +36,6 @@ import com.google.common.base.Suppliers; import com.google.common.collect.Lists; import org.apache.tuweni.bytes.Bytes; -import org.bouncycastle.util.encoders.Hex; import org.junit.jupiter.api.Test; public class CliqueExtraDataTest { @@ -67,26 +66,6 @@ public void encodeAndDecodingDoNotAlterData() { assertThat(decodedExtraData.getVanityData()).isEqualTo(vanityData); } - @Test - public void parseRinkebyGenesisBlockExtraData() { - // Rinkeby genesis block extra data text found @ rinkeby.io - final byte[] genesisBlockExtraData = - Hex.decode( - "52657370656374206d7920617574686f7269746168207e452e436172746d616e42eb768f2244c8811c63729a21a3569731535f067ffc57839b00206d1ad20c69a1981b489f772031b279182d99e65703f0076e4812653aab85fca0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - - final Bytes bufferToInject = Bytes.wrap(genesisBlockExtraData); - - final CliqueExtraData extraData = - CliqueExtraData.decodeRaw( - new BlockHeaderTestFixture() - .number(BlockHeader.GENESIS_BLOCK_NUMBER) - .blockHeaderFunctions(new CliqueBlockHeaderFunctions()) - .extraData(bufferToInject) - .buildHeader()); - assertThat(extraData.getProposerSeal()).isEmpty(); - assertThat(extraData.getValidators().size()).isEqualTo(3); - } - @Test public void insufficientDataResultsInAnIllegalArgumentException() { final Bytes illegalData = diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTest.java index ba9837e01dd..6a4a4503b7f 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTest.java @@ -330,124 +330,6 @@ public static Collection data() { Optional.of(ForkIds.SEPOLIA), empty() }, - // Rinkeby test cases - { - "Rinkeby // Unsynced, last Frontier block", - Network.RINKEBY, - 0L, - 0L, - ForkIdTestUtil.wantForkId("0x3b8e0691", 1L), - Optional.of(ForkIds.RINKEBY), - empty() - }, - { - "Rinkeby // First and last Homestead block", - Network.RINKEBY, - 1L, - 0L, - ForkIdTestUtil.wantForkId("0x60949295", 2L), - Optional.of(ForkIds.RINKEBY), - empty() - }, - { - "Rinkeby // First and last Tangerine block", - Network.RINKEBY, - 2L, - 0L, - ForkIdTestUtil.wantForkId("0x8bde40dd", 3L), - Optional.of(ForkIds.RINKEBY), - empty() - }, - { - "Rinkeby // First Spurious block", - Network.RINKEBY, - 3L, - 0L, - ForkIdTestUtil.wantForkId("0xcb3a64bb", 1035301L), - Optional.of(ForkIds.RINKEBY), - empty() - }, - { - "Rinkeby // Last Spurious block", - Network.RINKEBY, - 1035300L, - 0L, - ForkIdTestUtil.wantForkId("0xcb3a64bb", 1035301L), - Optional.of(ForkIds.RINKEBY), - empty() - }, - { - "Rinkeby // First Byzantium block", - Network.RINKEBY, - 1035301L, - 0L, - ForkIdTestUtil.wantForkId("0x8d748b57", 3660663L), - Optional.of(ForkIds.RINKEBY), - empty() - }, - { - "Rinkeby // Last Byzantium block", - Network.RINKEBY, - 3660662L, - 0L, - ForkIdTestUtil.wantForkId("0x8d748b57", 3660663L), - Optional.of(ForkIds.RINKEBY), - empty() - }, - { - "Rinkeby // First Constantinople block", - Network.RINKEBY, - 3660663L, - 0L, - ForkIdTestUtil.wantForkId("0xe49cab14", 4321234L), - Optional.of(ForkIds.RINKEBY), - empty() - }, - { - "Rinkeby // Last Constantinople block", - Network.RINKEBY, - 4321233L, - 0L, - ForkIdTestUtil.wantForkId("0xe49cab14", 4321234L), - Optional.of(ForkIds.RINKEBY), - empty() - }, - { - "Rinkeby // First Petersburg block", - Network.RINKEBY, - 4321234L, - 0L, - ForkIdTestUtil.wantForkId("0xafec6b27", 5435345L), - Optional.of(ForkIds.RINKEBY), - empty() - }, - { - "Rinkeby // Last Petersburg block", - Network.RINKEBY, - 5435344L, - 0L, - ForkIdTestUtil.wantForkId("0xafec6b27", 5435345L), - Optional.of(ForkIds.RINKEBY), - empty() - }, - { - "Rinkeby // First Istanbul block", - Network.RINKEBY, - 5435345L, - 0L, - ForkIdTestUtil.wantForkId("0xcbdb8838", 0L), - Optional.of(ForkIds.RINKEBY), - empty() - }, - { - "Rinkeby // Future Istanbul block", - Network.RINKEBY, - 6000000L, - 0L, - ForkIdTestUtil.wantForkId("0xcbdb8838", 0L), - Optional.of(ForkIds.RINKEBY), - empty() - }, // Goerli test cases { "Goerli // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block", @@ -631,18 +513,6 @@ public static Collection data() { empty(), wantPeerCheck("0x5cddc0e1", 0L, false) }, - { - "check13ByzantiumWithRemoteAnnouncingRinkebyPetersburg", - Network.network( - GenesisHash.MAINNET, - asList(1150000L, 1920000L, 2463000L, 2675000L, 4370000L, 7280000L), - emptyList()), - 7987396L, - 0L, - empty(), - empty(), - wantPeerCheck("0xafec6b27", 0L, false) - }, // Timestamp based peer check cases adapted from EIP-6122 test cases { "withdrawalsCheck1ShanghaiWithRemoteAnnouncingTheSame", @@ -752,15 +622,6 @@ public static Collection data() { empty(), wantPeerCheck("0x5cddc0e1", 0L, false) }, - { - "withdrawalsCheck13ShanghaiWithRemoteAnnouncingRinkebyPetersburg", - Network.MAINNET_WITH_SHANGHAI, - 20000000L, - 1668000001L, - empty(), - empty(), - wantPeerCheck("0xafec6b27", 0L, false) - }, { "withdrawalsCheck14ShanghaiWithRemoteAnnouncingUnknownFork", Network.MAINNET_WITH_SHANGHAI, diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTestUtil.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTestUtil.java index 62503177b08..d88d0fcd027 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTestUtil.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/forkid/ForkIdTestUtil.java @@ -60,8 +60,6 @@ public static class GenesisHash { "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"; public static final String SEPOLIA = "0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9"; - public static final String RINKEBY = - "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177"; public static final String GOERLI = "0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a"; public static final String PRIVATE = @@ -78,8 +76,6 @@ public static class Forks { public static final List SEPOLIA_TIMESTAMPS = Arrays.asList(1677557088L); - public static final List RINKEBY = - Arrays.asList(1L, 2L, 3L, 3L, 1035301L, 3660663L, 4321234L, 5435345L); public static final List GOERLI = Arrays.asList(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1561651L); public static final List PRIVATE = Arrays.asList(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L); @@ -111,16 +107,6 @@ public static class ForkIds { new ForkId(Bytes.fromHexString("0xfe3366e7"), 1735371L), new ForkId(Bytes.fromHexString("0xb96cbd13"), 1677557088L), new ForkId(Bytes.fromHexString("0xf7f9bc08"), 0L)); // First Shanghai block (timestamp) - public static final List RINKEBY = - Arrays.asList( - new ForkId(Bytes.fromHexString("0x3b8e0691"), 1L), - new ForkId(Bytes.fromHexString("0x60949295"), 2L), - new ForkId(Bytes.fromHexString("0x8bde40dd"), 3L), - new ForkId(Bytes.fromHexString("0xcb3a64bb"), 1035301L), - new ForkId(Bytes.fromHexString("0x8d748b57"), 3660663L), - new ForkId(Bytes.fromHexString("0xe49cab14"), 4321234L), - new ForkId(Bytes.fromHexString("0xafec6b27"), 5435345L), - new ForkId(Bytes.fromHexString("0xcbdb8838"), 0L)); public static final List GOERLI = Arrays.asList( new ForkId(Bytes.fromHexString("0xa3f5ab08"), 1561651L), @@ -151,7 +137,6 @@ public static class Network { public static final Network MAINNET = network(GenesisHash.MAINNET, Forks.MAINNET, emptyList()); public static final Network SEPOLIA = network(GenesisHash.SEPOLIA, Forks.SEPOLIA_BLOCKNUMBERS, Forks.SEPOLIA_TIMESTAMPS); - public static final Network RINKEBY = network(GenesisHash.RINKEBY, Forks.RINKEBY, emptyList()); public static final Network GOERLI = network(GenesisHash.GOERLI, Forks.GOERLI, emptyList()); public static final Network PRIVATE = network(GenesisHash.PRIVATE, Forks.PRIVATE, emptyList()); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolScheduleTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolScheduleTest.java index 9dd73036f8b..7c4b1bde529 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolScheduleTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolScheduleTest.java @@ -137,37 +137,6 @@ public void shouldCreateGoerliConfig() throws Exception { .isEqualTo("London"); } - @Test - public void shouldCreateRinkebyConfig() throws Exception { - final ProtocolSchedule sched = - MainnetProtocolSchedule.fromConfig( - GenesisConfigFile.fromConfig( - Resources.toString( - this.getClass().getResource("/rinkeby.json"), StandardCharsets.UTF_8)) - .getConfigOptions(), - EvmConfiguration.DEFAULT); - Assertions.assertThat(sched.getByBlockHeader(blockHeader(0L)).getName()).isEqualTo("Frontier"); - Assertions.assertThat(sched.getByBlockHeader(blockHeader(1L)).getName()).isEqualTo("Homestead"); - Assertions.assertThat(sched.getByBlockHeader(blockHeader(2L)).getName()) - .isEqualTo("TangerineWhistle"); - Assertions.assertThat(sched.getByBlockHeader(blockHeader(3L)).getName()) - .isEqualTo("SpuriousDragon"); - Assertions.assertThat(sched.getByBlockHeader(blockHeader(1_035_301L)).getName()) - .isEqualTo("Byzantium"); - Assertions.assertThat(sched.getByBlockHeader(blockHeader(3_660_663L)).getName()) - .isEqualTo("Constantinople"); - Assertions.assertThat(sched.getByBlockHeader(blockHeader(4_321_234L)).getName()) - .isEqualTo("Petersburg"); - Assertions.assertThat(sched.getByBlockHeader(blockHeader(5_435_345L)).getName()) - .isEqualTo("Istanbul"); - Assertions.assertThat(sched.getByBlockHeader(blockHeader(8_290_928L)).getName()) - .isEqualTo("Berlin"); - Assertions.assertThat(sched.getByBlockHeader(blockHeader(8_897_988L)).getName()) - .isEqualTo("London"); - Assertions.assertThat(sched.getByBlockHeader(blockHeader(Long.MAX_VALUE)).getName()) - .isEqualTo("London"); - } - private BlockHeader blockHeader(final long number) { return new BlockHeaderTestFixture().number(number).buildHeader(); } From 4407abd37f6e4b9bbfa9cfce4256b1d7cae44899 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Thu, 8 Jun 2023 16:31:20 -0600 Subject: [PATCH 25/35] EIP-5656 MCOPY (#5493) Add the MCOPY operation targeting cancun. Adding EVM memory to the text fixture so memory ops can be tested better. Signed-off-by: Danno Ferrin --- evm/build.gradle | 1 + .../org/hyperledger/besu/evm/MainnetEVMs.java | 8 +- .../besu/evm/operation/MCopyOperation.java | 56 +++++++ .../evm/operations/MCopyOperationTest.java | 137 ++++++++++++++++++ .../testutils/TestMessageFrameBuilder.java | 7 + 5 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 evm/src/main/java/org/hyperledger/besu/evm/operation/MCopyOperation.java create mode 100644 evm/src/test/java/org/hyperledger/besu/evm/operations/MCopyOperationTest.java diff --git a/evm/build.gradle b/evm/build.gradle index 639cf7e61bb..1bbc061a0c1 100644 --- a/evm/build.gradle +++ b/evm/build.gradle @@ -54,6 +54,7 @@ dependencies { testImplementation 'org.assertj:assertj-core' testImplementation 'org.junit.jupiter:junit-jupiter' testImplementation 'org.mockito:mockito-core' + testImplementation 'org.mockito:mockito-junit-jupiter' testRuntimeOnly 'org.junit.vintage:junit-vintage-engine' } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java b/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java index e2c9cf9ae12..a7f4ee21b83 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java @@ -71,6 +71,7 @@ import org.hyperledger.besu.evm.operation.Keccak256Operation; import org.hyperledger.besu.evm.operation.LogOperation; import org.hyperledger.besu.evm.operation.LtOperation; +import org.hyperledger.besu.evm.operation.MCopyOperation; import org.hyperledger.besu.evm.operation.MLoadOperation; import org.hyperledger.besu.evm.operation.MSizeOperation; import org.hyperledger.besu.evm.operation.MStore8Operation; @@ -793,12 +794,15 @@ public static void registerCancunOperations( final BigInteger chainID) { registerShanghaiOperations(registry, gasCalculator, chainID); - // EIP-4844 + // EIP-4844 DATAHASH registry.put(new DataHashOperation(gasCalculator)); - // TSTORE/TLOAD + // EIP-1153 TSTORE/TLOAD registry.put(new TStoreOperation(gasCalculator)); registry.put(new TLoadOperation(gasCalculator)); + + // EIP-5656 MCOPY + registry.put(new MCopyOperation(gasCalculator)); } /** diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/MCopyOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/MCopyOperation.java new file mode 100644 index 00000000000..b10be7f925c --- /dev/null +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/MCopyOperation.java @@ -0,0 +1,56 @@ +/* + * Copyright contributors to Hyperledger Besu + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.evm.operation; + +import static org.hyperledger.besu.evm.internal.Words.clampedToLong; + +import org.hyperledger.besu.evm.EVM; +import org.hyperledger.besu.evm.frame.ExceptionalHaltReason; +import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.gascalculator.GasCalculator; + +import org.apache.tuweni.bytes.Bytes; + +/** The Memory copy operation. */ +public class MCopyOperation extends AbstractOperation { + + /** + * Instantiates a new Memory Copy operation. + * + * @param gasCalculator the gas calculator + */ + public MCopyOperation(final GasCalculator gasCalculator) { + super(0x5e, "MCOPY", 3, 0, gasCalculator); + } + + @Override + public OperationResult execute(final MessageFrame frame, final EVM evm) { + final long dst = clampedToLong(frame.popStackItem()); + final long src = clampedToLong(frame.popStackItem()); + final long length = clampedToLong(frame.popStackItem()); + + final long cost = gasCalculator().dataCopyOperationGasCost(frame, Math.max(src, dst), length); + if (frame.getRemainingGas() < cost) { + return new OperationResult(cost, ExceptionalHaltReason.INSUFFICIENT_GAS); + } + + // read memory copies into a new buffer, no need to copy here. + final Bytes callData = frame.readMemory(src, length); + + frame.writeMemory(dst, length, callData, true); + + return new OperationResult(cost, null); + } +} diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/MCopyOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operations/MCopyOperationTest.java new file mode 100644 index 00000000000..bdae1238d5c --- /dev/null +++ b/evm/src/test/java/org/hyperledger/besu/evm/operations/MCopyOperationTest.java @@ -0,0 +1,137 @@ +/* + * Copyright contributors to Hyperledger Besu + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.evm.operations; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.evm.EVM; +import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator; +import org.hyperledger.besu.evm.operation.MCopyOperation; +import org.hyperledger.besu.evm.operation.Operation; +import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder; + +import java.util.Arrays; +import java.util.Collection; + +import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class MCopyOperationTest { + + @Mock EVM evm; + + static Collection mcopyTestVector() { + return Arrays.asList( + new Object[][] { + { + "Copy after, no overlap", + Bytes.fromHexString("0123456789abcdef000000000000000000000000000000000000000000000000"), + 32, + 0, + 8, + Bytes.fromHexString( + "0123456789abcdef0000000000000000000000000000000000000000000000000123456789abcdef"), + 9L + }, + { + "copy from uninitialized memory", + Bytes.EMPTY, + 0, + 24, + 16, + Bytes.fromHexString( + "0x000000000000000000000000000000000000000000000000000000000000000000"), + 12L + }, + { + "copy from initialized + uninitialized memory", + Bytes.fromHexString( + "0x0000000000000000000000000000000000000000000000000123456789abcdef"), + 64, + 24, + 16, + Bytes.fromHexString( + "0x0000000000000000000000000000000000000000000000000123456789abcdef00000000000000000000000000000000000000000000000000000000000000000123456789abcdef000000000000000000000000000000000000000000000000"), + 12L + }, + { + "overlapping src < dst", + Bytes.fromHexString( + "0x0123456789abcdef000000000000000000000000000000000000000000000000"), + 4, + 0, + 8, + Bytes.fromHexString( + "0x012345670123456789abcdef0000000000000000000000000000000000000000"), + 6L + }, + { + "overlapping src > dst", + Bytes.fromHexString( + "0x00112233445566778899aabbccddeeff00000000000000000000000000000000"), + 0, + 4, + 8, + Bytes.fromHexString( + "0x445566778899aabb8899aabbccddeeff00000000000000000000000000000000"), + 6L + }, + { + "overlapping src == dst", + Bytes.fromHexString( + "0x00112233445566778899aabbccddeeff00000000000000000000000000000000"), + 4, + 4, + 8, + Bytes.fromHexString( + "0x00112233445566778899aabbccddeeff00000000000000000000000000000000"), + 6L + } + }); + } + + @SuppressWarnings("unused") + @ParameterizedTest(name = "{0}") + @MethodSource("mcopyTestVector") + void testMCopy( + final String name, + final Bytes memory, + final long dst, + final long src, + final long len, + final Bytes expected, + final long gasCost) { + MCopyOperation subject = new MCopyOperation(new CancunGasCalculator()); + MessageFrame frame = + new TestMessageFrameBuilder() + .pushStackItem(Bytes.ofUnsignedLong(len)) + .pushStackItem(Bytes.ofUnsignedLong(src)) + .pushStackItem(Bytes.ofUnsignedLong(dst)) + .memory(memory) + .build(); + + Operation.OperationResult result = subject.execute(frame, evm); + + assertThat(frame.memoryWordSize()).isEqualTo((expected.size() + 31) / 32); + assertThat(frame.readMemory(0, expected.size())).isEqualTo(expected); + assertThat(result.getGasCost()).isEqualTo(gasCost); + } +} diff --git a/evm/src/test/java/org/hyperledger/besu/evm/testutils/TestMessageFrameBuilder.java b/evm/src/test/java/org/hyperledger/besu/evm/testutils/TestMessageFrameBuilder.java index 5fe9cf27afe..dfceccaf4f8 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/testutils/TestMessageFrameBuilder.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/testutils/TestMessageFrameBuilder.java @@ -58,6 +58,7 @@ public class TestMessageFrameBuilder { private final List stackItems = new ArrayList<>(); private int depth = 0; private Optional> blockHashLookup = Optional.empty(); + private Bytes memory = Bytes.EMPTY; TestMessageFrameBuilder messageFrameStack(final Deque messageFrameStack) { this.messageFrameStack = messageFrameStack; @@ -144,6 +145,11 @@ public TestMessageFrameBuilder blockHashLookup(final Function blockH return this; } + public TestMessageFrameBuilder memory(final Bytes memory) { + this.memory = memory; + return this; + } + public MessageFrame build() { final MessageFrame frame = MessageFrame.builder() @@ -170,6 +176,7 @@ public MessageFrame build() { frame.setPC(pc); frame.setSection(section); stackItems.forEach(frame::pushStackItem); + frame.writeMemory(0, memory.size(), memory); return frame; } From 287cfd1f22c8e6fdbbae48d9891d4cc8d4178001 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Fri, 9 Jun 2023 09:52:09 +1000 Subject: [PATCH 26/35] Fix code availability in graphQL (#5523) * Load code when WS snapshot still available Signed-off-by: Gabriel Fukushima * Handle invalid account address Signed-off-by: Gabriel Fukushima --------- Signed-off-by: Gabriel Fukushima --- .../api/graphql/internal/pojoadapter/BlockAdapterBase.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java index c0f5c320ec8..25e7e91c8ea 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java @@ -31,6 +31,7 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.transaction.CallParameter; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; +import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.log.LogTopic; import org.hyperledger.besu.evm.tracing.OperationTracer; @@ -144,13 +145,15 @@ public Long getNumber() { public AccountAdapter getAccount(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); + final Address address = environment.getArgument("address"); final long bn = header.getNumber(); return query .getAndMapWorldState( bn, ws -> { - final Address address = environment.getArgument("address"); - return Optional.of(new AccountAdapter(ws.get(address))); + Account account = ws.get(address); + if (account != null) account.getCode(); + return Optional.of(new AccountAdapter(account)); }) .get(); } From 39577fd799f3374b4176b0e032b1a69d4bfa4af3 Mon Sep 17 00:00:00 2001 From: Matt Whitehead Date: Fri, 9 Jun 2023 03:04:09 +0100 Subject: [PATCH 27/35] Remove TOML table headings before checking for valid config parameters (#5483) * Remove TOML table headings before checking for valid config parameters * Use dotted paths to find parameters under table headings Signed-off-by: Matthew Whitehead --------- Signed-off-by: Matthew Whitehead Co-authored-by: Matthew Whitehead Co-authored-by: Sally MacFarlane --- .../util/TomlConfigFileDefaultProvider.java | 70 ++++++++++++++++-- .../TomlConfigFileDefaultProviderTest.java | 74 +++++++++++++++++++ 2 files changed, 137 insertions(+), 7 deletions(-) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/util/TomlConfigFileDefaultProvider.java b/besu/src/main/java/org/hyperledger/besu/cli/util/TomlConfigFileDefaultProvider.java index aaeb80fc729..ec9ee7d593f 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/util/TomlConfigFileDefaultProvider.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/util/TomlConfigFileDefaultProvider.java @@ -19,7 +19,9 @@ import java.io.File; import java.io.IOException; import java.math.BigInteger; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; @@ -102,11 +104,49 @@ private String getEntryAsString(final OptionSpec spec) { private Optional getKeyName(final OptionSpec spec) { // If any of the names of the option are used as key in the toml results // then returns the value of first one. - return Arrays.stream(spec.names()) - // remove leading dashes on option name as we can have "--" or "-" options - .map(name -> name.replaceFirst("^-+", "")) - .filter(result::contains) - .findFirst(); + Optional keyName = + Arrays.stream(spec.names()) + // remove leading dashes on option name as we can have "--" or "-" options + .map(name -> name.replaceFirst("^-+", "")) + .filter(result::contains) + .findFirst(); + + if (keyName.isEmpty()) { + // If the base key name doesn't exist in the file it may be under a TOML table heading + // e.g. TxPool.tx-pool-max-size + keyName = getDottedKeyName(spec); + } + + return keyName; + } + + /* + For all spec names, look to see if any of the TOML keyPathSet entries contain + the name. A key path set might look like ["TxPool", "tx-max-pool-size"] where + "TxPool" is the TOML table heading (which we ignore) and "tx-max-pool-size" is + the name of the option being requested. For a request for "tx-max-pool-size" this + function will return "TxPool.tx-max-pool-size" which can then be used directly + as a query on the TOML result structure. + */ + private Optional getDottedKeyName(final OptionSpec spec) { + List foundNames = new ArrayList<>(); + + Arrays.stream(spec.names()) + .forEach( + nextSpecName -> { + String specName = + result.keyPathSet().stream() + .filter(option -> option.contains(nextSpecName.replaceFirst("^-+", ""))) + .findFirst() + .orElse(new ArrayList<>()) + .stream() + .collect(Collectors.joining(".")); + if (specName.length() > 0) { + foundNames.add(specName); + } + }); + + return foundNames.stream().findFirst(); } private String getListEntryAsString(final OptionSpec spec) { @@ -142,7 +182,8 @@ private String getNumericEntryAsString(final OptionSpec spec) { // return the string representation of the numeric value corresponding to the option in toml // file - this works for integer, double, and float // or null if not present in the config - return getKeyName(spec).map(result::get).map(String::valueOf).orElse(null); + + return getKeyName(spec).map(result::get).map(Object::toString).orElse(null); } private void checkConfigurationValidity() { @@ -184,8 +225,23 @@ public void loadConfigurationFromFile() { private void checkUnknownOptions(final TomlParseResult result) { final CommandSpec commandSpec = commandLine.getCommandSpec(); + // Besu ignores TOML table headings (e.g. [TxPool]) so we use keyPathSet() and take the + // last element in each one. For a TOML parameter that's not defined inside a table, the lists + // returned in keyPathSet() will contain a single entry - the config parameter itself. For a + // TOML + // entry that is in a table the list will contain N entries, the last one being the config + // parameter itself. + final Set optionsWithoutTables = new HashSet(); + result.keyPathSet().stream() + .forEach( + strings -> { + optionsWithoutTables.add(strings.get(strings.size() - 1)); + }); + + // Once we've stripped TOML table headings from the lists, we can check that the remaining + // options are valid final Set unknownOptionsList = - result.keySet().stream() + optionsWithoutTables.stream() .filter(option -> !commandSpec.optionsMap().containsKey("--" + option)) .collect(Collectors.toSet()); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/TomlConfigFileDefaultProviderTest.java b/besu/src/test/java/org/hyperledger/besu/cli/TomlConfigFileDefaultProviderTest.java index d764aab06d0..1481db9526d 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/TomlConfigFileDefaultProviderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/TomlConfigFileDefaultProviderTest.java @@ -298,4 +298,78 @@ public void unknownOptionMustThrow() throws IOException { .isInstanceOf(ParameterException.class) .hasMessage("Unknown option in TOML configuration file: invalid_option"); } + + @Test + public void tomlTableHeadingsMustBeIgnored() throws IOException { + + when(mockCommandLine.getCommandSpec()).thenReturn(mockCommandSpec); + + Map validOptionsMap = new HashMap<>(); + validOptionsMap.put("--a-valid-option", null); + validOptionsMap.put("--another-valid-option", null); + validOptionsMap.put("--onemore-valid-option", null); + when(mockCommandSpec.optionsMap()).thenReturn(validOptionsMap); + + final File tempConfigFile = temp.newFile("config.toml"); + final BufferedWriter fileWriter = Files.newBufferedWriter(tempConfigFile.toPath(), UTF_8); + + fileWriter.write("a-valid-option=123"); + fileWriter.newLine(); + fileWriter.write("[ignoreme]"); + fileWriter.newLine(); + fileWriter.write("another-valid-option=456"); + fileWriter.newLine(); + fileWriter.write("onemore-valid-option=789"); + fileWriter.newLine(); + fileWriter.flush(); + + final TomlConfigFileDefaultProvider providerUnderTest = + new TomlConfigFileDefaultProvider(mockCommandLine, tempConfigFile); + + assertThat( + providerUnderTest.defaultValue( + OptionSpec.builder("a-valid-option").type(Integer.class).build())) + .isEqualTo("123"); + + assertThat( + providerUnderTest.defaultValue( + OptionSpec.builder("another-valid-option").type(Integer.class).build())) + .isEqualTo("456"); + + assertThat( + providerUnderTest.defaultValue( + OptionSpec.builder("onemore-valid-option").type(Integer.class).build())) + .isEqualTo("789"); + } + + @Test + public void tomlTableHeadingsMustNotSkipValidationOfUnknownOptions() throws IOException { + + when(mockCommandLine.getCommandSpec()).thenReturn(mockCommandSpec); + + Map validOptionsMap = new HashMap<>(); + validOptionsMap.put("--a-valid-option", null); + when(mockCommandSpec.optionsMap()).thenReturn(validOptionsMap); + + final File tempConfigFile = temp.newFile("config.toml"); + final BufferedWriter fileWriter = Files.newBufferedWriter(tempConfigFile.toPath(), UTF_8); + + fileWriter.write("[ignoreme]"); + fileWriter.newLine(); + fileWriter.write("a-valid-option=123"); + fileWriter.newLine(); + fileWriter.write("invalid-option=789"); + fileWriter.newLine(); + fileWriter.flush(); + + final TomlConfigFileDefaultProvider providerUnderTest = + new TomlConfigFileDefaultProvider(mockCommandLine, tempConfigFile); + + assertThatThrownBy( + () -> + providerUnderTest.defaultValue( + OptionSpec.builder("an-option").type(String.class).build())) + .isInstanceOf(ParameterException.class) + .hasMessage("Unknown option in TOML configuration file: invalid-option"); + } } From b96418143c9f1fdc5805add283edc48ea5c645a7 Mon Sep 17 00:00:00 2001 From: Antoine Toulme Date: Thu, 8 Jun 2023 19:31:20 -0700 Subject: [PATCH 28/35] Update Tuweni to 2.4.1 (#5513) * update to 2.4.1 * update use of DNS daemon with Vertx * fix issue with Bytes.repeat * update antlr version * fix dns tests Signed-off-by: Antoine Toulme --------- Signed-off-by: Antoine Toulme Co-authored-by: Sally MacFarlane --- CHANGELOG.md | 1 + acceptance-tests/dsl/build.gradle | 6 +- acceptance-tests/tests/build.gradle | 2 +- besu/build.gradle | 12 +- config/build.gradle | 4 +- consensus/clique/build.gradle | 4 +- consensus/common/build.gradle | 2 +- consensus/ibft/build.gradle | 4 +- consensus/merge/build.gradle | 4 +- consensus/qbft/build.gradle | 4 +- crypto/algorithms/build.gradle | 4 +- datatypes/build.gradle | 4 +- enclave/build.gradle | 2 +- ethereum/api/build.gradle | 8 +- ethereum/blockcreation/build.gradle | 4 +- ethereum/core/build.gradle | 14 +- .../ethereum/core/TransactionTestFixture.java | 3 +- .../core/encoding/WithdrawalEncoderTest.java | 3 +- ethereum/eth/build.gradle | 6 +- .../layered/BaseTransactionPoolTest.java | 2 +- ethereum/ethstats/build.gradle | 2 +- ethereum/mock-p2p/build.gradle | 2 +- ethereum/p2p/build.gradle | 14 +- .../p2p/network/DefaultP2PNetwork.java | 12 +- .../p2p/network/DefaultP2PNetworkTest.java | 14 +- ethereum/permissioning/build.gradle | 6 +- ethereum/referencetests/build.gradle | 4 +- ethereum/retesteth/build.gradle | 4 +- ethereum/rlp/build.gradle | 4 +- ethereum/stratum/build.gradle | 4 +- ethereum/trie/build.gradle | 4 +- ethereum/verkletrie/build.gradle | 6 +- evm/build.gradle | 4 +- gradle/verification-metadata.xml | 280 ++++++++++++++++++ gradle/versions.gradle | 9 +- pki/build.gradle | 2 +- plugin-api/build.gradle | 4 +- plugins/rocksdb/build.gradle | 2 +- privacy-contracts/build.gradle | 6 +- services/tasks/build.gradle | 2 +- testutil/build.gradle | 6 +- 41 files changed, 388 insertions(+), 96 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 274918ccf0b..4bd3f65517f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and in case a rollback is needed, before installing a previous version, the migr - Tidy DEBUG logs by moving engine API full logging to TRACE [#5529](https://github.com/hyperledger/besu/pull/5529) - remove PoW validation if merge is enabled as it is not needed anymore [#5538](https://github.com/hyperledger/besu/pull/5538) - Use BlobDB for blockchain storage to reduce initial sync time and write amplification [#5475](https://github.com/hyperledger/besu/pull/5475) +- Update to Tuweni 2.4.1. [#5513](https://github.com/hyperledger/besu/pull/5513) ### Bug Fixes - check to ensure storage and transactions are not closed prior to reading/writing [#5527](https://github.com/hyperledger/besu/pull/5527) diff --git a/acceptance-tests/dsl/build.gradle b/acceptance-tests/dsl/build.gradle index d65de08b954..7aff9aaffb5 100644 --- a/acceptance-tests/dsl/build.gradle +++ b/acceptance-tests/dsl/build.gradle @@ -36,9 +36,9 @@ dependencies { implementation 'io.vertx:vertx-core' implementation 'junit:junit' implementation 'io.opentelemetry:opentelemetry-api' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-io' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-io' + implementation 'io.tmio:tuweni-units' implementation 'org.assertj:assertj-core' implementation 'org.awaitility:awaitility' implementation 'org.java-websocket:Java-WebSocket' diff --git a/acceptance-tests/tests/build.gradle b/acceptance-tests/tests/build.gradle index 8b23195361d..cc4a54b009b 100644 --- a/acceptance-tests/tests/build.gradle +++ b/acceptance-tests/tests/build.gradle @@ -76,7 +76,7 @@ dependencies { testImplementation 'junit:junit' testImplementation 'org.apache.commons:commons-compress' testImplementation 'org.apache.logging.log4j:log4j-core' - testImplementation 'org.apache.tuweni:tuweni-crypto' + testImplementation 'io.tmio:tuweni-crypto' testImplementation 'org.assertj:assertj-core' testImplementation 'org.awaitility:awaitility' testImplementation 'org.junit.jupiter:junit-jupiter' diff --git a/besu/build.gradle b/besu/build.gradle index 969571b565c..73977d81ba7 100644 --- a/besu/build.gradle +++ b/besu/build.gradle @@ -70,10 +70,10 @@ dependencies { implementation 'io.vertx:vertx-web' implementation 'org.apache.commons:commons-lang3' implementation 'org.apache.logging.log4j:log4j-core' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-config' - implementation 'org.apache.tuweni:tuweni-toml' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-config' + implementation 'io.tmio:tuweni-toml' + implementation 'io.tmio:tuweni-units' implementation 'org.springframework.security:spring-security-crypto' implementation 'org.xerial.snappy:snappy-java' implementation 'tech.pegasys:jc-kzg-4844' @@ -92,8 +92,8 @@ dependencies { testImplementation 'io.opentelemetry:opentelemetry-api' testImplementation 'junit:junit' testImplementation 'org.apache.commons:commons-text' - testImplementation 'org.apache.tuweni:tuweni-bytes' - testImplementation 'org.apache.tuweni:tuweni-units' + testImplementation 'io.tmio:tuweni-bytes' + testImplementation 'io.tmio:tuweni-units' testImplementation 'org.assertj:assertj-core' testImplementation 'org.awaitility:awaitility' testImplementation 'org.junit.jupiter:junit-jupiter' diff --git a/config/build.gradle b/config/build.gradle index 8e7f197d134..f30e2848f1a 100644 --- a/config/build.gradle +++ b/config/build.gradle @@ -36,8 +36,8 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-databind' implementation 'com.google.guava:guava' implementation 'info.picocli:picocli' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-units' testImplementation project(':testutil') diff --git a/consensus/clique/build.gradle b/consensus/clique/build.gradle index b6c39a703ae..4c5634f17c2 100644 --- a/consensus/clique/build.gradle +++ b/consensus/clique/build.gradle @@ -47,8 +47,8 @@ dependencies { implementation 'com.google.guava:guava' implementation 'io.vertx:vertx-core' implementation 'com.fasterxml.jackson.core:jackson-databind' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-units' testImplementation project(path: ':consensus:common', configuration: 'testArtifacts') testImplementation project(path: ':crypto:services', configuration: 'testSupportArtifacts') diff --git a/consensus/common/build.gradle b/consensus/common/build.gradle index 540cd788315..49c73e7d176 100644 --- a/consensus/common/build.gradle +++ b/consensus/common/build.gradle @@ -44,7 +44,7 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-databind' implementation 'com.google.guava:guava' - implementation 'org.apache.tuweni:tuweni-bytes' + implementation 'io.tmio:tuweni-bytes' testImplementation project(':config') testImplementation project(':crypto:algorithms') diff --git a/consensus/ibft/build.gradle b/consensus/ibft/build.gradle index d5d76a1a2c4..3f7b1bf0ac6 100644 --- a/consensus/ibft/build.gradle +++ b/consensus/ibft/build.gradle @@ -44,8 +44,8 @@ dependencies { implementation 'com.google.guava:guava' implementation 'io.vertx:vertx-core' implementation 'com.fasterxml.jackson.core:jackson-databind' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-units' integrationTestImplementation project(path: ':config', configuration: 'testSupportArtifacts') integrationTestImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts') diff --git a/consensus/merge/build.gradle b/consensus/merge/build.gradle index 1c52ee104fe..fb8589123c6 100644 --- a/consensus/merge/build.gradle +++ b/consensus/merge/build.gradle @@ -46,8 +46,8 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-databind' implementation 'com.google.guava:guava' implementation 'io.vertx:vertx-core' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-units' testImplementation project(path: ':consensus:common', configuration: 'testArtifacts') testImplementation project(':crypto:algorithms') diff --git a/consensus/qbft/build.gradle b/consensus/qbft/build.gradle index 90e9a45deed..6c7640466cf 100644 --- a/consensus/qbft/build.gradle +++ b/consensus/qbft/build.gradle @@ -45,8 +45,8 @@ dependencies { implementation 'com.google.guava:guava' implementation 'io.vertx:vertx-core' implementation 'com.fasterxml.jackson.core:jackson-databind' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-units' implementation 'org.web3j:abi' integrationTestImplementation project(path: ':config', configuration: 'testSupportArtifacts') diff --git a/crypto/algorithms/build.gradle b/crypto/algorithms/build.gradle index 3421c990bf3..7bd630566d5 100644 --- a/crypto/algorithms/build.gradle +++ b/crypto/algorithms/build.gradle @@ -33,8 +33,8 @@ dependencies { api 'org.slf4j:slf4j-api' implementation 'net.java.dev.jna:jna' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-units' implementation 'org.hyperledger.besu:secp256k1' implementation 'org.hyperledger.besu:secp256r1' implementation 'org.hyperledger.besu:blake2bf' diff --git a/datatypes/build.gradle b/datatypes/build.gradle index dd03c225d77..b44a18540ff 100644 --- a/datatypes/build.gradle +++ b/datatypes/build.gradle @@ -34,8 +34,8 @@ dependencies { implementation project(':crypto:algorithms') implementation project(':ethereum:rlp') implementation 'com.google.guava:guava' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-units' testImplementation 'junit:junit' testImplementation 'org.assertj:assertj-core' diff --git a/enclave/build.gradle b/enclave/build.gradle index ff3343462c9..a282e01a7ff 100644 --- a/enclave/build.gradle +++ b/enclave/build.gradle @@ -7,7 +7,7 @@ dependencies { implementation 'com.google.guava:guava' implementation 'io.vertx:vertx-core' implementation 'io.vertx:vertx-web' - implementation 'org.apache.tuweni:tuweni-net' + implementation 'io.tmio:tuweni-net' runtimeOnly('org.bouncycastle:bcpkix-jdk15on') diff --git a/ethereum/api/build.gradle b/ethereum/api/build.gradle index 68b53a3b76a..110c0ba4070 100644 --- a/ethereum/api/build.gradle +++ b/ethereum/api/build.gradle @@ -64,10 +64,10 @@ dependencies { implementation 'io.vertx:vertx-web' implementation 'io.vertx:vertx-codegen' implementation 'com.fasterxml.jackson.core:jackson-databind' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-net' - implementation 'org.apache.tuweni:tuweni-toml' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-net' + implementation 'io.tmio:tuweni-toml' + implementation 'io.tmio:tuweni-units' implementation 'org.antlr:antlr4-runtime' implementation 'org.bouncycastle:bcprov-jdk15on' implementation 'org.springframework.security:spring-security-crypto' diff --git a/ethereum/blockcreation/build.gradle b/ethereum/blockcreation/build.gradle index 6ab57e51315..d813869db6a 100644 --- a/ethereum/blockcreation/build.gradle +++ b/ethereum/blockcreation/build.gradle @@ -24,8 +24,8 @@ dependencies { implementation 'com.google.guava:guava' implementation 'io.vertx:vertx-core' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-units' testImplementation project(path: ':config', configuration: 'testSupportArtifacts') testImplementation project(path: ':ethereum:core', configuration: 'testArtifacts') diff --git a/ethereum/core/build.gradle b/ethereum/core/build.gradle index 690aad04106..a03dafd7d9e 100644 --- a/ethereum/core/build.gradle +++ b/ethereum/core/build.gradle @@ -53,10 +53,10 @@ dependencies { implementation 'net.java.dev.jna:jna' implementation 'org.apache.commons:commons-lang3' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-concurrent' - implementation 'org.apache.tuweni:tuweni-units' - implementation 'org.apache.tuweni:tuweni-rlp' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-concurrent' + implementation 'io.tmio:tuweni-units' + implementation 'io.tmio:tuweni-rlp' implementation 'org.hyperledger.besu:bls12-381' implementation 'org.immutables:value-annotations' @@ -77,9 +77,9 @@ dependencies { testImplementation 'junit:junit' testImplementation 'org.apache.logging.log4j:log4j-core' - testImplementation 'org.apache.tuweni:tuweni-bytes' - testImplementation 'org.apache.tuweni:tuweni-io' - testImplementation 'org.apache.tuweni:tuweni-units' + testImplementation 'io.tmio:tuweni-bytes' + testImplementation 'io.tmio:tuweni-io' + testImplementation 'io.tmio:tuweni-units' testImplementation 'org.assertj:assertj-core' testImplementation 'org.junit.jupiter:junit-jupiter' testImplementation 'org.junit.jupiter:junit-jupiter-params' diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java index d766abf1017..79307d2ebdc 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java @@ -32,7 +32,8 @@ public class TransactionTestFixture { private static final Hash DEFAULT_VERSIONED_HASH = Hash.wrap( Bytes32.wrap( - Bytes.concatenate(Bytes.fromHexString("0x01"), Bytes.repeat((byte) 42, 31)))); + Bytes.concatenate( + Bytes.fromHexString("0x01"), Bytes.fromHexString("2a".repeat(31))))); private TransactionType transactionType = TransactionType.FRONTIER; diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/WithdrawalEncoderTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/WithdrawalEncoderTest.java index 3c80cd78712..7dd79e229a0 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/WithdrawalEncoderTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/WithdrawalEncoderTest.java @@ -29,8 +29,7 @@ class WithdrawalEncoderTest { "0xd8808094000000000000000000000000000000000000000080"; public static final String WITHDRAWAL_MAX_VALUE = "0xf088ffffffffffffffff88ffffffffffffffff94ffffffffffffffffffffffffffffffffffffffff88ffffffffffffffff"; - public static final Address MAX_ADDRESS = - Address.fromHexString(Bytes.repeat((byte) 0xff, 20).toHexString()); + public static final Address MAX_ADDRESS = Address.fromHexString("ff".repeat(20)); @Test void shouldEncodeWithdrawalForZeroCase() { diff --git a/ethereum/eth/build.gradle b/ethereum/eth/build.gradle index 0f68fc521d3..68a40750b7c 100644 --- a/ethereum/eth/build.gradle +++ b/ethereum/eth/build.gradle @@ -55,9 +55,9 @@ dependencies { implementation 'com.google.guava:guava' implementation 'io.vertx:vertx-core' implementation 'org.apache.commons:commons-lang3' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-units' - implementation 'org.apache.tuweni:tuweni-rlp' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-units' + implementation 'io.tmio:tuweni-rlp' annotationProcessor "org.immutables:value" implementation "org.immutables:value-annotations" diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseTransactionPoolTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseTransactionPoolTest.java index defafb1b369..b594d7a258b 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseTransactionPoolTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseTransactionPoolTest.java @@ -110,7 +110,7 @@ protected TransactionTestFixture prepareTransaction( .nonce(nonce) .type(type); if (payloadSize > 0) { - var payloadBytes = Bytes.repeat((byte) 1, payloadSize); + var payloadBytes = Bytes.fromHexString("01".repeat(payloadSize)); tx.payload(payloadBytes); } if (type.supports1559FeeMarket()) { diff --git a/ethereum/ethstats/build.gradle b/ethereum/ethstats/build.gradle index c361c16c860..52fe38473ce 100644 --- a/ethereum/ethstats/build.gradle +++ b/ethereum/ethstats/build.gradle @@ -34,7 +34,7 @@ dependencies { implementation 'com.google.guava:guava' implementation 'com.squareup.okhttp3:okhttp' implementation 'io.vertx:vertx-core' - implementation 'org.apache.tuweni:tuweni-bytes' + implementation 'io.tmio:tuweni-bytes' implementation project(':consensus:clique') implementation project(':config') diff --git a/ethereum/mock-p2p/build.gradle b/ethereum/mock-p2p/build.gradle index b73c0a051fd..bfab38e98c7 100644 --- a/ethereum/mock-p2p/build.gradle +++ b/ethereum/mock-p2p/build.gradle @@ -35,7 +35,7 @@ dependencies { implementation project(':util') implementation 'io.vertx:vertx-core' - implementation 'org.apache.tuweni:tuweni-bytes' + implementation 'io.tmio:tuweni-bytes' testImplementation 'junit:junit' testImplementation 'org.assertj:assertj-core' diff --git a/ethereum/p2p/build.gradle b/ethereum/p2p/build.gradle index 7de85f6d836..1fc228fa2ac 100644 --- a/ethereum/p2p/build.gradle +++ b/ethereum/p2p/build.gradle @@ -45,17 +45,17 @@ dependencies { implementation 'io.prometheus:simpleclient' implementation 'io.vertx:vertx-core' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-crypto' - implementation('org.apache.tuweni:tuweni-devp2p') { + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-crypto' + implementation('io.tmio:tuweni-devp2p') { exclude group:'ch.qos.logback', module:'logback-classic' } - implementation('org.apache.tuweni:tuweni-dns-discovery'){ + implementation('io.tmio:tuweni-dns-discovery'){ exclude group:'ch.qos.logback', module:'logback-classic' } - implementation 'org.apache.tuweni:tuweni-io' - implementation 'org.apache.tuweni:tuweni-rlp' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-io' + implementation 'io.tmio:tuweni-rlp' + implementation 'io.tmio:tuweni-units' implementation 'org.jetbrains.kotlin:kotlin-stdlib' implementation 'org.xerial.snappy:snappy-java' diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java index 427093cb599..ec65934b297 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java @@ -145,6 +145,7 @@ public class DefaultP2PNetwork implements P2PNetwork { private final AtomicBoolean stopped = new AtomicBoolean(false); private final CountDownLatch shutdownLatch = new CountDownLatch(2); private final Duration shutdownTimeout = Duration.ofSeconds(15); + private final Vertx vertx; private DNSDaemon dnsDaemon; /** @@ -163,6 +164,7 @@ public class DefaultP2PNetwork implements P2PNetwork { * @param maintainedPeers A collection of peers for which we are expected to maintain connections * @param reputationManager An object that inspect disconnections for misbehaving peers that can * then be blacklisted. + * @param vertx the Vert.x instance managing network resources */ DefaultP2PNetwork( final MutableLocalNode localNode, @@ -173,7 +175,8 @@ public class DefaultP2PNetwork implements P2PNetwork { final PeerPermissions peerPermissions, final NatService natService, final MaintainedPeers maintainedPeers, - final PeerDenylistManager reputationManager) { + final PeerDenylistManager reputationManager, + final Vertx vertx) { this.localNode = localNode; this.peerDiscoveryAgent = peerDiscoveryAgent; this.rlpxAgent = rlpxAgent; @@ -183,6 +186,7 @@ public class DefaultP2PNetwork implements P2PNetwork { this.nodeId = nodeKey.getPublicKey().getEncodedBytes(); this.peerPermissions = peerPermissions; + this.vertx = vertx; // set the requirement here that the number of peers be greater than the lower bound final int peerLowerBound = rlpxAgent.getPeerLowerBound(); @@ -229,7 +233,8 @@ public void start() { createDaemonListener(), 0L, 600000L, - config.getDnsDiscoveryServerOverride().orElse(null)); + config.getDnsDiscoveryServerOverride().orElse(null), + vertx); dnsDaemon.start(); }); @@ -535,7 +540,8 @@ private P2PNetwork doBuild() { peerPermissions, natService, maintainedPeers, - reputationManager); + reputationManager, + vertx); } private void validate() { diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetworkTest.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetworkTest.java index ffc1c84431b..5b61d4946a4 100644 --- a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetworkTest.java +++ b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetworkTest.java @@ -58,6 +58,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import io.vertx.core.Vertx; +import io.vertx.core.dns.DnsClient; import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.crypto.SECP256K1; import org.assertj.core.api.Assertions; @@ -348,8 +350,12 @@ public void shouldStartDnsDiscoveryWhenDnsURLIsConfigured() { final NetworkingConfiguration dnsConfig = when(spy(config).getDiscovery()).thenReturn(disco).getMock(); + Vertx vertx = mock(Vertx.class); + when(vertx.createDnsClient(any())).thenReturn(mock(DnsClient.class)); + // spy on DefaultP2PNetwork - final DefaultP2PNetwork testClass = (DefaultP2PNetwork) builder().config(dnsConfig).build(); + final DefaultP2PNetwork testClass = + (DefaultP2PNetwork) builder().vertx(vertx).config(dnsConfig).build(); testClass.start(); assertThat(testClass.getDnsDaemon()).isPresent(); @@ -366,7 +372,11 @@ public void shouldUseDnsServerOverrideIfPresent() { doReturn(disco).when(dnsConfig).getDiscovery(); doReturn(Optional.of("localhost")).when(dnsConfig).getDnsDiscoveryServerOverride(); - final DefaultP2PNetwork testClass = (DefaultP2PNetwork) builder().config(dnsConfig).build(); + Vertx vertx = mock(Vertx.class); + when(vertx.createDnsClient(any())).thenReturn(mock(DnsClient.class)); + + final DefaultP2PNetwork testClass = + (DefaultP2PNetwork) builder().config(dnsConfig).vertx(vertx).build(); testClass.start(); // ensure we used the dns server override config when building DNSDaemon: diff --git a/ethereum/permissioning/build.gradle b/ethereum/permissioning/build.gradle index 5b10e216ecf..a0493360a15 100644 --- a/ethereum/permissioning/build.gradle +++ b/ethereum/permissioning/build.gradle @@ -41,9 +41,9 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-databind' implementation 'com.google.guava:guava' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-toml' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-toml' + implementation 'io.tmio:tuweni-units' implementation 'org.web3j:abi' testImplementation project(':config') diff --git a/ethereum/referencetests/build.gradle b/ethereum/referencetests/build.gradle index 49dc6109074..1aa1e2a2651 100644 --- a/ethereum/referencetests/build.gradle +++ b/ethereum/referencetests/build.gradle @@ -138,8 +138,8 @@ dependencies { referenceTestImplementation 'ethereum:execution-spec-tests:0.2.3:fixtures@tar.gz' referenceTestImplementation 'com.fasterxml.jackson.core:jackson-databind' referenceTestImplementation 'com.google.guava:guava' - referenceTestImplementation 'org.apache.tuweni:tuweni-bytes' - referenceTestImplementation 'org.apache.tuweni:tuweni-units' + referenceTestImplementation 'io.tmio:tuweni-bytes' + referenceTestImplementation 'io.tmio:tuweni-units' referenceTestImplementation 'org.assertj:assertj-core' referenceTestImplementation 'org.junit.jupiter:junit-jupiter-api' referenceTestImplementation 'org.junit.jupiter:junit-jupiter-params' diff --git a/ethereum/retesteth/build.gradle b/ethereum/retesteth/build.gradle index 08d06932905..5bb9b1d8559 100644 --- a/ethereum/retesteth/build.gradle +++ b/ethereum/retesteth/build.gradle @@ -47,8 +47,8 @@ dependencies { implementation 'io.vertx:vertx-core' implementation 'io.vertx:vertx-web' implementation 'com.fasterxml.jackson.core:jackson-databind' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-units' testImplementation 'junit:junit' testImplementation 'org.assertj:assertj-core' diff --git a/ethereum/rlp/build.gradle b/ethereum/rlp/build.gradle index 678918d7cef..17303480e92 100644 --- a/ethereum/rlp/build.gradle +++ b/ethereum/rlp/build.gradle @@ -31,8 +31,8 @@ jar { dependencies { annotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-units' implementation 'com.google.guava:guava' diff --git a/ethereum/stratum/build.gradle b/ethereum/stratum/build.gradle index d462fb3f32d..5c7dfaed20d 100644 --- a/ethereum/stratum/build.gradle +++ b/ethereum/stratum/build.gradle @@ -41,8 +41,8 @@ dependencies { implementation 'com.google.guava:guava' implementation 'io.vertx:vertx-core' implementation 'com.fasterxml.jackson.core:jackson-databind' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-units' testImplementation project(path: ':metrics:core', configuration: 'testSupportArtifacts') testImplementation project(':testutil') diff --git a/ethereum/trie/build.gradle b/ethereum/trie/build.gradle index c671a75bf0f..6f1b78cb90a 100644 --- a/ethereum/trie/build.gradle +++ b/ethereum/trie/build.gradle @@ -36,7 +36,7 @@ dependencies { implementation 'org.immutables:value-annotations' implementation 'com.google.guava:guava' implementation 'io.opentelemetry:opentelemetry-api' - implementation 'org.apache.tuweni:tuweni-bytes' + implementation 'io.tmio:tuweni-bytes' implementation 'org.bouncycastle:bcprov-jdk15on' annotationProcessor 'org.immutables:value' @@ -46,7 +46,7 @@ dependencies { testImplementation 'com.fasterxml.jackson.core:jackson-databind' testImplementation 'junit:junit' - testImplementation 'org.apache.tuweni:tuweni-units' + testImplementation 'io.tmio:tuweni-units' testImplementation 'org.assertj:assertj-core' testImplementation 'org.junit.jupiter:junit-jupiter' testImplementation 'org.mockito:mockito-core' diff --git a/ethereum/verkletrie/build.gradle b/ethereum/verkletrie/build.gradle index 0ca780ba88d..df0ba0e5119 100644 --- a/ethereum/verkletrie/build.gradle +++ b/ethereum/verkletrie/build.gradle @@ -35,8 +35,8 @@ dependencies { implementation "org.immutables:value-annotations" implementation 'com.google.guava:guava' implementation 'io.opentelemetry:opentelemetry-api' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-units' implementation 'org.bouncycastle:bcprov-jdk15on' implementation 'org.hyperledger.besu:ipa-multipoint' @@ -48,7 +48,7 @@ dependencies { testImplementation 'com.fasterxml.jackson.core:jackson-databind' testImplementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml' testImplementation 'junit:junit' - testImplementation 'org.apache.tuweni:tuweni-units' + testImplementation 'io.tmio:tuweni-units' testImplementation 'org.assertj:assertj-core' testImplementation 'org.junit.jupiter:junit-jupiter' testImplementation 'org.mockito:mockito-core' diff --git a/evm/build.gradle b/evm/build.gradle index 1bbc061a0c1..2c7a92b3c19 100644 --- a/evm/build.gradle +++ b/evm/build.gradle @@ -40,8 +40,8 @@ dependencies { implementation 'com.github.ben-manes.caffeine:caffeine' implementation 'com.google.guava:guava' implementation 'net.java.dev.jna:jna' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-units' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-units' implementation 'org.hyperledger.besu:arithmetic' implementation 'org.hyperledger.besu:bls12-381' implementation 'tech.pegasys:jc-kzg-4844' diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 951ad1c9577..60cd327f988 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -467,6 +467,17 @@ + + + + + + + + + + + @@ -518,6 +529,14 @@ + + + + + + + + @@ -808,6 +827,9 @@ + + + @@ -2549,6 +2571,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2604,6 +2746,11 @@ + + + + + @@ -2630,6 +2777,14 @@ + + + + + + + + @@ -2638,11 +2793,24 @@ + + + + + + + + + + + + + @@ -2980,6 +3148,14 @@ + + + + + + + + @@ -2990,6 +3166,11 @@ + + + + + @@ -3006,6 +3187,14 @@ + + + + + + + + @@ -3354,6 +3543,14 @@ + + + + + + + + @@ -3386,6 +3583,14 @@ + + + + + + + + @@ -3410,6 +3615,14 @@ + + + + + + + + @@ -3450,6 +3663,14 @@ + + + + + + + + @@ -3466,6 +3687,14 @@ + + + + + + + + @@ -4492,6 +4721,14 @@ + + + + + + + + @@ -4529,11 +4766,24 @@ + + + + + + + + + + + + + @@ -4542,6 +4792,14 @@ + + + + + + + + @@ -4553,6 +4811,17 @@ + + + + + + + + + + + @@ -4564,6 +4833,17 @@ + + + + + + + + + + + diff --git a/gradle/versions.gradle b/gradle/versions.gradle index 8abdc6c6191..fbbfd880381 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -16,7 +16,7 @@ dependencyManagement { dependencies { - dependencySet(group: 'org.antlr', version: '4.10.1') { + dependencySet(group: 'org.antlr', version: '4.11.1') { entry 'antlr4' entry 'antlr4-runtime' } @@ -133,7 +133,7 @@ dependencyManagement { entry 'log4j-slf4j2-impl' } - dependencySet(group: 'org.apache.tuweni', version: '2.3.1') { + dependencySet(group: 'io.tmio', version: '2.4.1') { entry 'tuweni-bytes' entry 'tuweni-config' entry 'tuweni-concurrent' @@ -147,11 +147,6 @@ dependencyManagement { entry 'tuweni-units' } - // commons-net is a transitive dependency of tuweni. - // Tuweni 2.3.1 has commons-net:3.8.0 which we force here to 3.9.0 - // Once tuweni is updated, can remove this line - dependency 'commons-net:commons-net:3.9.0' - dependency 'org.assertj:assertj-core:3.24.2' dependency 'org.awaitility:awaitility:4.2.0' diff --git a/pki/build.gradle b/pki/build.gradle index a3edd47ce74..9df2a09381c 100644 --- a/pki/build.gradle +++ b/pki/build.gradle @@ -31,7 +31,7 @@ dependencies { api 'org.slf4j:slf4j-api' implementation 'com.google.guava:guava' - implementation 'org.apache.tuweni:tuweni-bytes' + implementation 'io.tmio:tuweni-bytes' implementation 'org.bouncycastle:bcpkix-jdk15on' testImplementation 'junit:junit' diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index 3966e03751e..961801e866d 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -30,8 +30,8 @@ jar { dependencies { api project(':datatypes') api 'org.apache.commons:commons-lang3' - api 'org.apache.tuweni:tuweni-bytes' - api 'org.apache.tuweni:tuweni-units' + api 'io.tmio:tuweni-bytes' + api 'io.tmio:tuweni-units' implementation 'com.google.guava:guava' implementation project(':evm') } diff --git a/plugins/rocksdb/build.gradle b/plugins/rocksdb/build.gradle index dc5438f86c9..7cf2cb95041 100644 --- a/plugins/rocksdb/build.gradle +++ b/plugins/rocksdb/build.gradle @@ -45,7 +45,7 @@ dependencies { implementation 'info.picocli:picocli' implementation 'io.opentelemetry:opentelemetry-api' implementation 'io.prometheus:simpleclient' - implementation 'org.apache.tuweni:tuweni-bytes' + implementation 'io.tmio:tuweni-bytes' implementation 'org.rocksdb:rocksdbjni' implementation project(path: ':ethereum:core') diff --git a/privacy-contracts/build.gradle b/privacy-contracts/build.gradle index 65401fd753b..33e3176ce05 100644 --- a/privacy-contracts/build.gradle +++ b/privacy-contracts/build.gradle @@ -15,9 +15,9 @@ jar { enabled = true } dependencies { - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-io' - implementation 'org.apache.tuweni:tuweni-toml' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-io' + implementation 'io.tmio:tuweni-toml' implementation 'org.web3j:abi' implementation 'org.web3j:besu' } diff --git a/services/tasks/build.gradle b/services/tasks/build.gradle index f398248c730..7b9ea1b18a4 100644 --- a/services/tasks/build.gradle +++ b/services/tasks/build.gradle @@ -38,7 +38,7 @@ dependencies { implementation 'com.google.guava:guava' implementation 'io.vertx:vertx-core' - implementation 'org.apache.tuweni:tuweni-bytes' + implementation 'io.tmio:tuweni-bytes' testImplementation 'junit:junit' testImplementation 'org.assertj:assertj-core' diff --git a/testutil/build.gradle b/testutil/build.gradle index 193569c72c1..931730c2622 100644 --- a/testutil/build.gradle +++ b/testutil/build.gradle @@ -37,9 +37,9 @@ dependencies { implementation 'com.squareup.okhttp3:okhttp' implementation 'io.vertx:vertx-core' implementation 'junit:junit' - implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.apache.tuweni:tuweni-io' - implementation 'org.apache.tuweni:tuweni-toml' + implementation 'io.tmio:tuweni-bytes' + implementation 'io.tmio:tuweni-io' + implementation 'io.tmio:tuweni-toml' implementation 'org.assertj:assertj-core' implementation 'org.mockito:mockito-core' implementation 'org.web3j:core' From 35ce57fa77480d8f746f21bfe2fd8cd32b0ec7be Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Fri, 9 Jun 2023 13:13:22 +1000 Subject: [PATCH 29/35] Fix graphql storageAt for bonsai (#5548) * Fix code and storage retrieve for bonsai getting a new world state snapshot to fetch code/storage from in the AccountAdapter Signed-off-by: Gabriel Fukushima --------- Signed-off-by: Gabriel Fukushima --- .../internal/pojoadapter/AccountAdapter.java | 45 ++++++++++++++++--- .../pojoadapter/BlockAdapterBase.java | 11 +---- .../pojoadapter/EmptyAccountAdapter.java | 2 +- .../AbstractEthGraphQLHttpServiceTest.java | 2 +- 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccountAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccountAdapter.java index c8acb708ac8..f9098089e42 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccountAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccountAdapter.java @@ -16,6 +16,8 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; +import org.hyperledger.besu.ethereum.bonsai.BonsaiAccount; import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.account.AccountState; @@ -31,14 +33,25 @@ public class AccountAdapter extends AdapterBase { private final Optional account; private final Address address; + private final Optional blockNumber; public AccountAdapter(final Account account) { - this(account == null ? null : account.getAddress(), account); + this(account == null ? null : account.getAddress(), account, Optional.empty()); + } + + public AccountAdapter(final Account account, final Optional blockNumber) { + this(account == null ? null : account.getAddress(), account, blockNumber); } public AccountAdapter(final Address address, final Account account) { + this(address, account, Optional.empty()); + } + + public AccountAdapter( + final Address address, final Account account, final Optional blockNumber) { this.account = Optional.ofNullable(account); this.address = address; + this.blockNumber = blockNumber; } public Address getAddress() { @@ -53,14 +66,34 @@ public Long getTransactionCount() { return account.map(AccountState::getNonce).orElse(0L); } - public Bytes getCode() { - return account.map(AccountState::getCode).orElse(Bytes.EMPTY); + public Bytes getCode(final DataFetchingEnvironment environment) { + + if (account.get() instanceof BonsaiAccount) { + final BlockchainQueries query = getBlockchainQueries(environment); + return query + .getAndMapWorldState( + blockNumber.orElse(query.headBlockNumber()), + ws -> Optional.of(ws.get(account.get().getAddress()).getCode())) + .get(); + } else { + return account.map(AccountState::getCode).orElse(Bytes.EMPTY); + } } public Bytes32 getStorage(final DataFetchingEnvironment environment) { + final BlockchainQueries query = getBlockchainQueries(environment); final Bytes32 slot = environment.getArgument("slot"); - return account - .map(a -> (Bytes32) a.getStorageValue(UInt256.fromBytes(slot))) - .orElse(Bytes32.ZERO); + + if (account.get() instanceof BonsaiAccount) { + return query + .getAndMapWorldState( + blockNumber.orElse(query.headBlockNumber()), + ws -> Optional.of((Bytes32) ws.get(address).getStorageValue(UInt256.fromBytes(slot)))) + .get(); + } else { + return account + .map(a -> (Bytes32) a.getStorageValue(UInt256.fromBytes(slot))) + .orElse(Bytes32.ZERO); + } } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java index 25e7e91c8ea..4d10aa53a8c 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java @@ -31,7 +31,6 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.transaction.CallParameter; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; -import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.log.LogTopic; import org.hyperledger.besu.evm.tracing.OperationTracer; @@ -143,18 +142,12 @@ public Long getNumber() { } public AccountAdapter getAccount(final DataFetchingEnvironment environment) { - final BlockchainQueries query = getBlockchainQueries(environment); - final Address address = environment.getArgument("address"); final long bn = header.getNumber(); + final Address address = environment.getArgument("address"); return query .getAndMapWorldState( - bn, - ws -> { - Account account = ws.get(address); - if (account != null) account.getCode(); - return Optional.of(new AccountAdapter(account)); - }) + bn, ws -> Optional.of(new AccountAdapter(ws.get(address), Optional.of(bn)))) .get(); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/EmptyAccountAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/EmptyAccountAdapter.java index 7fc6d7695ae..4c19b997b6e 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/EmptyAccountAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/EmptyAccountAdapter.java @@ -45,7 +45,7 @@ public Long getTransactionCount() { } @Override - public Bytes getCode() { + public Bytes getCode(final DataFetchingEnvironment environment) { return Bytes.EMPTY; } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java index 710c08f5558..01cf7d3bafe 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java @@ -75,7 +75,7 @@ public abstract class AbstractEthGraphQLHttpServiceTest { public static void setupConstants() { blockchainSetupUtil = BlockchainSetupUtil.createForEthashChain( - BlockTestUtil.getHiveTestChainResources(), DataStorageFormat.FOREST); + BlockTestUtil.getHiveTestChainResources(), DataStorageFormat.BONSAI); blockchainSetupUtil.importAllBlocks(); } From c3ab8e017d913b46c1fd0996f56994d4a214ad39 Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Fri, 9 Jun 2023 06:38:41 +0200 Subject: [PATCH 30/35] Improve log of p2p messages (#5542) * Improve log of p2p messages Signed-off-by: Fabio Di Fabio * [skip ci] Update ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/AbstractMessageData.java Co-authored-by: Gabriel Fukushima Signed-off-by: Fabio Di Fabio * Use a more flexible way to trim logged data Signed-off-by: Fabio Di Fabio * Sanitize user input before printing it in logs Signed-off-by: Fabio Di Fabio --------- Signed-off-by: Fabio Di Fabio Co-authored-by: Gabriel Fukushima Co-authored-by: Sally MacFarlane --- besu/src/main/resources/log4j2.xml | 10 +++++ .../eth/messages/NewBlockHashesMessage.java | 4 +- .../ethereum/eth/messages/StatusMessage.java | 4 +- .../messages/snap/GetAccountRangeMessage.java | 5 --- .../eth/messages/StatusMessageTest.java | 8 ++-- ethereum/p2p/build.gradle | 1 + .../connections/AbstractPeerConnection.java | 14 ++++++- .../rlpx/connections/netty/ApiHandler.java | 13 ++++++ .../p2p/rlpx/wire/AbstractMessageData.java | 5 +++ .../ethereum/p2p/rlpx/wire/Capability.java | 5 ++- .../p2p/rlpx/wire/CapabilityMultiplexer.java | 5 +++ .../ethereum/p2p/rlpx/wire/MessageData.java | 10 ++++- .../besu/ethereum/p2p/rlpx/wire/PeerInfo.java | 14 +++++-- .../ethereum/p2p/rlpx/wire/RawMessage.java | 5 --- .../rlpx/wire/messages/DisconnectMessage.java | 5 --- .../p2p/rlpx/wire/messages/EmptyMessage.java | 5 +++ .../p2p/rlpx/wire/messages/HelloMessage.java | 5 --- .../ethereum/p2p/rlpx/wire/PeerInfoTest.java | 40 +++++++++++++++++++ gradle/verification-metadata.xml | 13 ++++++ gradle/versions.gradle | 2 + testutil/src/main/resources/log4j2.xml | 9 ++++- 21 files changed, 145 insertions(+), 37 deletions(-) create mode 100644 ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/PeerInfoTest.java diff --git a/besu/src/main/resources/log4j2.xml b/besu/src/main/resources/log4j2.xml index 6bf83a973f7..7b46fcf6cc8 100644 --- a/besu/src/main/resources/log4j2.xml +++ b/besu/src/main/resources/log4j2.xml @@ -13,11 +13,21 @@ ${env:SPLUNK_BATCH_SIZE_COUNT:-1000} ${env:SPLUNK_BATCH_INTERVAL:-500} ${env:SPLUNK_SKIPTLSVERIFY:-false} + %d{yyyy-MM-dd HH:mm:ss.SSSZZZ} | %t | %-5level | %c{1} | %msg + 1000 + + + + + + + + getNewHashes() { } @Override - public String toString() { - return String.format("NewBlockHashesMessage: [%s]", Iterators.toString(getNewHashes())); + public String toStringDecoded() { + return Iterators.toString(getNewHashes()); } public static final class NewBlockHash { diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessage.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessage.java index 64be5b280a0..9e8af4b0e57 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessage.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessage.java @@ -218,7 +218,7 @@ public static EthStatus readFrom(final RLPInput in) { @Override public String toString() { - return "EthStatus{" + return "{" + "protocolVersion=" + protocolVersion + ", networkId=" @@ -236,7 +236,7 @@ public String toString() { } @Override - public String toString() { + public String toStringDecoded() { return status().toString(); } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/snap/GetAccountRangeMessage.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/snap/GetAccountRangeMessage.java index 9d1eccce984..66aae554d48 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/snap/GetAccountRangeMessage.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/snap/GetAccountRangeMessage.java @@ -92,11 +92,6 @@ public Range range(final boolean withRequestId) { return range; } - @Override - public String toString() { - return "GetAccountRangeMessage{" + "data=" + data + '}'; - } - @Value.Immutable public interface Range { diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessageTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessageTest.java index 2fa6acd9c2e..8458c990768 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessageTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/StatusMessageTest.java @@ -91,7 +91,7 @@ public void serializeDeserializeWithForkId() { } @Test - public void toStringHasExpectedInfo() { + public void toStringDecodedHasExpectedInfo() { final int version = EthProtocolVersion.V64; final BigInteger networkId = BigInteger.ONE; final Difficulty td = Difficulty.of(1000L); @@ -103,10 +103,10 @@ public void toStringHasExpectedInfo() { StatusMessage.create(version, networkId, td, bestHash, genesisHash, forkId); final StatusMessage copy = new StatusMessage(msg.getData()); - final String copyToString = copy.toString(); + final String copyToStringDecoded = copy.toStringDecoded(); - assertThat(copyToString).contains("bestHash=" + bestHash); - assertThat(copyToString).contains("genesisHash=" + genesisHash); + assertThat(copyToStringDecoded).contains("bestHash=" + bestHash); + assertThat(copyToStringDecoded).contains("genesisHash=" + genesisHash); } private Hash randHash(final long seed) { diff --git a/ethereum/p2p/build.gradle b/ethereum/p2p/build.gradle index 1fc228fa2ac..0775a51d2a9 100644 --- a/ethereum/p2p/build.gradle +++ b/ethereum/p2p/build.gradle @@ -57,6 +57,7 @@ dependencies { implementation 'io.tmio:tuweni-rlp' implementation 'io.tmio:tuweni-units' implementation 'org.jetbrains.kotlin:kotlin-stdlib' + implementation 'org.owasp.encoder:encoder' implementation 'org.xerial.snappy:snappy-java' annotationProcessor "org.immutables:value" diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/AbstractPeerConnection.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/AbstractPeerConnection.java index 82798da74ea..fbd183b9ed0 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/AbstractPeerConnection.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/AbstractPeerConnection.java @@ -35,10 +35,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; public abstract class AbstractPeerConnection implements PeerConnection { private static final Logger LOG = LoggerFactory.getLogger(AbstractPeerConnection.class); - + private static final Marker P2P_MESSAGE_MARKER = MarkerFactory.getMarker("P2PMSG"); private final Peer peer; private final PeerInfo peerInfo; private final InetSocketAddress localAddress; @@ -120,7 +122,15 @@ private void doSend(final Capability capability, final MessageData message) { .inc(); } - LOG.trace("Writing {} to {} via protocol {}", message, peerInfo, capability); + LOG.atTrace() + .addMarker(P2P_MESSAGE_MARKER) + .setMessage("Writing {} to {} via protocol {}") + .addArgument(message) + .addArgument(peerInfo) + .addArgument(capability) + .addKeyValue("rawData", message.getData()) + .addKeyValue("decodedData", message::toStringDecoded) + .log(); doSendMessage(capability, message); } diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/ApiHandler.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/ApiHandler.java index c5793df074f..d0a689a0521 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/ApiHandler.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/ApiHandler.java @@ -29,10 +29,13 @@ import io.netty.channel.SimpleChannelInboundHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; final class ApiHandler extends SimpleChannelInboundHandler { private static final Logger LOG = LoggerFactory.getLogger(ApiHandler.class); + private static final Marker P2P_MESSAGE_MARKER = MarkerFactory.getMarker("P2PMSG"); private final CapabilityMultiplexer multiplexer; private final AtomicBoolean waitingForPong; @@ -96,6 +99,16 @@ protected void channelRead0(final ChannelHandlerContext ctx, final MessageData o } return; } + LOG.atTrace() + .addMarker(P2P_MESSAGE_MARKER) + .setMessage("Received {} from {} via protocol {}") + .addArgument(message) + .addArgument(connection.getPeerInfo()) + .addArgument(demultiplexed.getCapability()) + .addKeyValue("rawData", message.getData()) + .addKeyValue("decodedData", message::toStringDecoded) + .log(); + connectionEventDispatcher.dispatchMessage(demultiplexed.getCapability(), connection, message); } diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/AbstractMessageData.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/AbstractMessageData.java index 0640905ab72..c6c613b90b0 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/AbstractMessageData.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/AbstractMessageData.java @@ -52,4 +52,9 @@ public boolean equals(final Object o) { public int hashCode() { return Objects.hashCode(data); } + + @Override + public String toString() { + return getClass().getSimpleName() + "{code=" + getCode() + ", size=" + getSize() + "}"; + } } diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/Capability.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/Capability.java index f0ea843cee9..5a3a57df46d 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/Capability.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/Capability.java @@ -22,6 +22,8 @@ import java.nio.charset.StandardCharsets; import java.util.Objects; +import org.owasp.encoder.Encode; + /** * Represents a client capability. * @@ -82,7 +84,8 @@ public int hashCode() { } @Override + /** Returned string is sanitized since it contains user input */ public String toString() { - return name + "/" + version; + return Encode.forJava(name) + "/" + version; } } diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/CapabilityMultiplexer.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/CapabilityMultiplexer.java index 2df84e5eb62..c21d531aeca 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/CapabilityMultiplexer.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/CapabilityMultiplexer.java @@ -107,6 +107,11 @@ public int getCode() { public Bytes getData() { return originalMessage.getData(); } + + @Override + public String toString() { + return "Message{ code=" + getCode() + ", size=" + getSize() + "}"; + } }; } diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/MessageData.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/MessageData.java index 9b627e0c28d..043ca05baad 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/MessageData.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/MessageData.java @@ -26,7 +26,6 @@ /** A P2P Network Message's Data. */ public interface MessageData { - /** * Returns the size of the message. * @@ -65,4 +64,13 @@ default Map.Entry unwrapMessageData() { messageDataRLP.leaveList(); return new AbstractMap.SimpleImmutableEntry<>(requestId, new RawMessage(getCode(), message)); } + + /** + * Subclasses can implement this method to return a human-readable version of the raw data. + * + * @return return a human-readable version of the raw data + */ + default String toStringDecoded() { + return "N/A"; + } } diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/PeerInfo.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/PeerInfo.java index df25746837e..bd98270e020 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/PeerInfo.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/PeerInfo.java @@ -30,6 +30,7 @@ import javax.annotation.Nonnull; import org.apache.tuweni.bytes.Bytes; +import org.owasp.encoder.Encode; /** * Encapsulates information about a peer, including their protocol version, client ID, capabilities @@ -43,6 +44,7 @@ public class PeerInfo implements Comparable { private final List capabilities; private final int port; private final Bytes nodeId; + private Address address = null; public PeerInfo( final int version, @@ -97,9 +99,12 @@ public Bytes getNodeId() { } public Address getAddress() { - final SECPPublicKey remotePublicKey = - SignatureAlgorithmFactory.getInstance().createPublicKey(nodeId); - return Util.publicKeyToAddress(remotePublicKey); + if (address == null) { + final SECPPublicKey remotePublicKey = + SignatureAlgorithmFactory.getInstance().createPublicKey(nodeId); + address = Util.publicKeyToAddress(remotePublicKey); + } + return address; } public void writeTo(final RLPOutput out) { @@ -113,10 +118,11 @@ public void writeTo(final RLPOutput out) { } @Override + /** Returned string is sanitized since it contains user input */ public String toString() { final StringBuilder sb = new StringBuilder("PeerInfo{"); sb.append("version=").append(version); - sb.append(", clientId='").append(clientId).append('\''); + sb.append(", clientId='").append(Encode.forJava(clientId)).append('\''); sb.append(", capabilities=").append(capabilities); sb.append(", port=").append(port); sb.append(", nodeId=").append(nodeId); diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/RawMessage.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/RawMessage.java index 0ab21723901..b4b0bc20c59 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/RawMessage.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/RawMessage.java @@ -29,9 +29,4 @@ public RawMessage(final int code, final Bytes data) { public int getCode() { return code; } - - @Override - public String toString() { - return "RawMessage{" + "code=" + code + ", data=" + data + '}'; - } } diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/DisconnectMessage.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/DisconnectMessage.java index 3871939ea3a..d81520f1ddc 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/DisconnectMessage.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/DisconnectMessage.java @@ -61,11 +61,6 @@ public DisconnectReason getReason() { return Data.readFrom(RLP.input(data)).getReason(); } - @Override - public String toString() { - return "DisconnectMessage{" + "data=" + data + '}'; - } - public static class Data { private final DisconnectReason reason; diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/EmptyMessage.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/EmptyMessage.java index 2bb40ff6111..4611dc4b207 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/EmptyMessage.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/EmptyMessage.java @@ -30,4 +30,9 @@ public final int getSize() { public Bytes getData() { return Bytes.EMPTY; } + + @Override + public String toString() { + return getClass().getSimpleName() + "{ code=" + getCode() + ", size=0}"; + } } diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/HelloMessage.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/HelloMessage.java index 1a18fa42064..d22513d3348 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/HelloMessage.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/HelloMessage.java @@ -55,9 +55,4 @@ public int getCode() { public PeerInfo getPeerInfo() { return PeerInfo.readFrom(RLP.input(data)); } - - @Override - public String toString() { - return "HelloMessage{" + "data=" + data + '}'; - } } diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/PeerInfoTest.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/PeerInfoTest.java new file mode 100644 index 00000000000..3217f23fcbb --- /dev/null +++ b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/PeerInfoTest.java @@ -0,0 +1,40 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.p2p.rlpx.wire; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.Test; + +class PeerInfoTest { + + @Test + public void toStringIsSanitized() { + final PeerInfo maliciousPeer = + new PeerInfo( + 1, + "ab\nc", + List.of(Capability.create("c\ba\rp", 4)), + 30303, + Bytes.fromHexStringLenient("0x1234")); + + final String toString = maliciousPeer.toString(); + + assertThat(toString).doesNotContain(List.of("\n", "\b", "\r")); + } +} diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 60cd327f988..cc41d3d6638 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -5458,6 +5458,19 @@ + + + + + + + + + + + + + diff --git a/gradle/versions.gradle b/gradle/versions.gradle index fbbfd880381..fc3c2338164 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -204,6 +204,8 @@ dependencyManagement { entry 'jmh-generator-annprocess' } + dependency 'org.owasp.encoder:encoder:1.2.3' + dependency 'org.rocksdb:rocksdbjni:8.0.0' dependencySet(group: 'org.slf4j', version:'2.0.7') { diff --git a/testutil/src/main/resources/log4j2.xml b/testutil/src/main/resources/log4j2.xml index 8bc25bfd5be..85a454f1c9b 100644 --- a/testutil/src/main/resources/log4j2.xml +++ b/testutil/src/main/resources/log4j2.xml @@ -2,11 +2,18 @@ INFO + %d{yyyy-MM-dd HH:mm:ss.SSSZZZ} | %t | %-5level | %c{1} | %msg + 1000 - + + + + + + From 46009213b11de3dca0b17c15465d644b43ddfea5 Mon Sep 17 00:00:00 2001 From: Sally MacFarlane Date: Fri, 9 Jun 2023 15:01:47 +1000 Subject: [PATCH 31/35] migrate to junit5 (#5572) Signed-off-by: Sally MacFarlane --- datatypes/build.gradle | 1 - .../src/test/java/org/hyperledger/besu/datatypes/HashTest.java | 2 +- .../src/test/java/org/hyperledger/besu/datatypes/WeiTest.java | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/datatypes/build.gradle b/datatypes/build.gradle index b44a18540ff..a55bf4e45c5 100644 --- a/datatypes/build.gradle +++ b/datatypes/build.gradle @@ -37,7 +37,6 @@ dependencies { implementation 'io.tmio:tuweni-bytes' implementation 'io.tmio:tuweni-units' - testImplementation 'junit:junit' testImplementation 'org.assertj:assertj-core' testImplementation 'org.junit.jupiter:junit-jupiter' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' diff --git a/datatypes/src/test/java/org/hyperledger/besu/datatypes/HashTest.java b/datatypes/src/test/java/org/hyperledger/besu/datatypes/HashTest.java index 10172b69cf2..1ae3b8c14e7 100644 --- a/datatypes/src/test/java/org/hyperledger/besu/datatypes/HashTest.java +++ b/datatypes/src/test/java/org/hyperledger/besu/datatypes/HashTest.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class HashTest { diff --git a/datatypes/src/test/java/org/hyperledger/besu/datatypes/WeiTest.java b/datatypes/src/test/java/org/hyperledger/besu/datatypes/WeiTest.java index aa9a82b9110..1d1b38819a7 100644 --- a/datatypes/src/test/java/org/hyperledger/besu/datatypes/WeiTest.java +++ b/datatypes/src/test/java/org/hyperledger/besu/datatypes/WeiTest.java @@ -19,7 +19,7 @@ import java.math.BigInteger; import java.util.Arrays; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class WeiTest { From 479530dbcc0b316d08e53e58f034d376b4412a44 Mon Sep 17 00:00:00 2001 From: Sally MacFarlane Date: Fri, 9 Jun 2023 15:44:35 +1000 Subject: [PATCH 32/35] migrate to junit5 (#5573) Signed-off-by: Sally MacFarlane --- errorprone-checks/build.gradle | 1 - .../org/hyperledger/errorpronechecks/BannedMethodTest.java | 6 +++--- .../DoNotCreateSecureRandomDirectlyTest.java | 6 +++--- .../DoNotInvokeMessageDigestDirectlyTest.java | 6 +++--- .../errorpronechecks/DoNotReturnNullOptionalsTest.java | 6 +++--- .../ExperimentalCliOptionMustBeCorrectlyDisplayedTest.java | 6 +++--- .../MethodInputParametersMustBeFinalTest.java | 6 +++--- .../errorpronechecks/PrivateStaticFinalLoggersTest.java | 6 +++--- 8 files changed, 21 insertions(+), 22 deletions(-) diff --git a/errorprone-checks/build.gradle b/errorprone-checks/build.gradle index 805e513d2e0..1aff3a23b23 100644 --- a/errorprone-checks/build.gradle +++ b/errorprone-checks/build.gradle @@ -35,7 +35,6 @@ dependencies { implementation 'info.picocli:picocli' testImplementation 'com.google.errorprone:error_prone_test_helpers' - testImplementation 'junit:junit' testImplementation 'org.assertj:assertj-core' testImplementation 'org.junit.jupiter:junit-jupiter' diff --git a/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/BannedMethodTest.java b/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/BannedMethodTest.java index 66e29f370dd..48f382946d8 100644 --- a/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/BannedMethodTest.java +++ b/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/BannedMethodTest.java @@ -15,14 +15,14 @@ package org.hyperledger.errorpronechecks; import com.google.errorprone.CompilationTestHelper; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class BannedMethodTest { private CompilationTestHelper compilationHelper; - @Before + @BeforeEach public void setup() { compilationHelper = CompilationTestHelper.newInstance(BannedMethod.class, getClass()); } diff --git a/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/DoNotCreateSecureRandomDirectlyTest.java b/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/DoNotCreateSecureRandomDirectlyTest.java index 60e86751feb..525f5a8689a 100644 --- a/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/DoNotCreateSecureRandomDirectlyTest.java +++ b/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/DoNotCreateSecureRandomDirectlyTest.java @@ -15,14 +15,14 @@ package org.hyperledger.errorpronechecks; import com.google.errorprone.CompilationTestHelper; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class DoNotCreateSecureRandomDirectlyTest { private CompilationTestHelper compilationHelper; - @Before + @BeforeEach public void setup() { compilationHelper = CompilationTestHelper.newInstance(DoNotCreateSecureRandomDirectly.class, getClass()); diff --git a/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/DoNotInvokeMessageDigestDirectlyTest.java b/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/DoNotInvokeMessageDigestDirectlyTest.java index 0b045bcd954..986aedb63c2 100644 --- a/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/DoNotInvokeMessageDigestDirectlyTest.java +++ b/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/DoNotInvokeMessageDigestDirectlyTest.java @@ -15,14 +15,14 @@ package org.hyperledger.errorpronechecks; import com.google.errorprone.CompilationTestHelper; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class DoNotInvokeMessageDigestDirectlyTest { private CompilationTestHelper compilationHelper; - @Before + @BeforeEach public void setup() { compilationHelper = CompilationTestHelper.newInstance(DoNotInvokeMessageDigestDirectly.class, getClass()); diff --git a/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/DoNotReturnNullOptionalsTest.java b/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/DoNotReturnNullOptionalsTest.java index e8d6227061e..0055c9fc1ed 100644 --- a/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/DoNotReturnNullOptionalsTest.java +++ b/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/DoNotReturnNullOptionalsTest.java @@ -15,14 +15,14 @@ package org.hyperledger.errorpronechecks; import com.google.errorprone.CompilationTestHelper; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class DoNotReturnNullOptionalsTest { private CompilationTestHelper compilationHelper; - @Before + @BeforeEach public void setup() { compilationHelper = CompilationTestHelper.newInstance(DoNotReturnNullOptionals.class, getClass()); diff --git a/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/ExperimentalCliOptionMustBeCorrectlyDisplayedTest.java b/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/ExperimentalCliOptionMustBeCorrectlyDisplayedTest.java index edfcded0d20..159c3905eab 100644 --- a/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/ExperimentalCliOptionMustBeCorrectlyDisplayedTest.java +++ b/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/ExperimentalCliOptionMustBeCorrectlyDisplayedTest.java @@ -15,14 +15,14 @@ package org.hyperledger.errorpronechecks; import com.google.errorprone.CompilationTestHelper; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class ExperimentalCliOptionMustBeCorrectlyDisplayedTest { private CompilationTestHelper compilationHelper; - @Before + @BeforeEach public void setup() { compilationHelper = CompilationTestHelper.newInstance( diff --git a/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/MethodInputParametersMustBeFinalTest.java b/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/MethodInputParametersMustBeFinalTest.java index 2c1802d7dae..f94fa2d606c 100644 --- a/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/MethodInputParametersMustBeFinalTest.java +++ b/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/MethodInputParametersMustBeFinalTest.java @@ -15,14 +15,14 @@ package org.hyperledger.errorpronechecks; import com.google.errorprone.CompilationTestHelper; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class MethodInputParametersMustBeFinalTest { private CompilationTestHelper compilationHelper; - @Before + @BeforeEach public void setup() { compilationHelper = CompilationTestHelper.newInstance(MethodInputParametersMustBeFinal.class, getClass()); diff --git a/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/PrivateStaticFinalLoggersTest.java b/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/PrivateStaticFinalLoggersTest.java index c8f246c38d9..f15dabca1d6 100644 --- a/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/PrivateStaticFinalLoggersTest.java +++ b/errorprone-checks/src/test/java/org/hyperledger/errorpronechecks/PrivateStaticFinalLoggersTest.java @@ -15,14 +15,14 @@ package org.hyperledger.errorpronechecks; import com.google.errorprone.CompilationTestHelper; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class PrivateStaticFinalLoggersTest { private CompilationTestHelper compilationHelper; - @Before + @BeforeEach public void setup() { compilationHelper = CompilationTestHelper.newInstance(PrivateStaticFinalLoggers.class, getClass()); From b702063ed6b8a5c339e65846c39f0359fb0b1bf0 Mon Sep 17 00:00:00 2001 From: Matt Whitehead Date: Tue, 20 Jun 2023 07:47:49 +0100 Subject: [PATCH 33/35] Use the node's configuration to decide if adding a peer with DNS in the enode is allowed (#5584) * Use the node's configuration to decide if adding a peer with DNS in the enode is allowed Signed-off-by: Matthew Whitehead * Update command test mocks Signed-off-by: Matthew Whitehead * Update besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java Co-authored-by: Sally MacFarlane Signed-off-by: Matt Whitehead * Address PR comments. Add a reference in the change log. Fix failing integration test. Signed-off-by: Matthew Whitehead * Add the same DNS-config checking logic to admin_removePeer, along with a unit test file for it Signed-off-by: Matthew Whitehead * Tweak the change log Signed-off-by: Matthew Whitehead * Add clearer error messages for the cases where enode DNS is disabled (but a hostname one has been specified in the URL) or where DNS name resolution failed Signed-off-by: Matthew Whitehead * Spotless Java fixes Signed-off-by: Matthew Whitehead * Fix copyright for new file Co-authored-by: Sally MacFarlane Signed-off-by: Matt Whitehead * Address PR comments (mainly copyright & constant renaming) Signed-off-by: Matthew Whitehead * move changelog entry to 23.4.4 Signed-off-by: Sally MacFarlane --------- Signed-off-by: Matthew Whitehead Signed-off-by: Matt Whitehead Signed-off-by: Sally MacFarlane Co-authored-by: Matthew Whitehead Co-authored-by: Sally MacFarlane --- CHANGELOG.md | 19 +- .../org/hyperledger/besu/RunnerBuilder.java | 17 +- .../org/hyperledger/besu/cli/BesuCommand.java | 1 + .../besu/cli/CommandTestAbstract.java | 1 + .../jsonrpc/JsonRpcTestMethodsFactory.java | 1 + .../internal/methods/AdminAddPeer.java | 13 +- .../internal/methods/AdminModifyPeer.java | 20 +- .../internal/methods/AdminRemovePeer.java | 13 +- .../internal/response/JsonRpcError.java | 2 + .../jsonrpc/methods/AdminJsonRpcMethods.java | 11 +- .../methods/JsonRpcMethodsFactory.java | 9 +- .../AbstractJsonRpcHttpServiceTest.java | 1 + .../JsonRpcHttpServiceHostAllowlistTest.java | 1 + .../jsonrpc/JsonRpcHttpServiceLoginTest.java | 1 + .../JsonRpcHttpServiceRpcApisTest.java | 2 + .../jsonrpc/JsonRpcHttpServiceTestBase.java | 1 + .../JsonRpcHttpServiceTlsClientAuthTest.java | 1 + ...RpcHttpServiceTlsMisconfigurationTest.java | 1 + .../jsonrpc/JsonRpcHttpServiceTlsTest.java | 1 + .../internal/methods/AdminAddPeerTest.java | 78 +++++- .../internal/methods/AdminRemovePeerTest.java | 258 ++++++++++++++++++ .../websocket/WebSocketServiceLoginTest.java | 1 + 22 files changed, 434 insertions(+), 19 deletions(-) create mode 100644 ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminRemovePeerTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bd3f65517f..80864d6bbe7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,19 @@ # Changelog -## 23.4.2 +## 23.4.4 + +### Breaking Changes + +### Additions and Improvements + +### Bug Fixes +- Use the node's configuration to determine if DNS enode URLs are allowed in calls to `admin_addPeer` and `admin_removePeer` [#5584](https://github.com/hyperledger/besu/pull/5584) + +### Download Links + +--- + +## 23.4.3 ### Breaking Changes - Move blockchain related variables in a dedicated storage, to pave the way to future optimizations [#5471](https://github.com/hyperledger/besu/pull/5471). The migration is performed automatically at startup, @@ -21,6 +34,10 @@ and in case a rollback is needed, before installing a previous version, the migr ### Download Links +## 23.4.2 + +- Was not released (failed burn-in test) + --- ## 23.4.1 diff --git a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java index 96df5e7252f..d54a9149429 100644 --- a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java @@ -87,6 +87,7 @@ import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; import org.hyperledger.besu.ethereum.p2p.network.ProtocolManager; import org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration; import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissions; import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissionsDenylist; import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; @@ -191,6 +192,7 @@ public class RunnerBuilder { private JsonRpcIpcConfiguration jsonRpcIpcConfiguration; private boolean legacyForkIdEnabled; private Optional rpcMaxLogsRange; + private Optional enodeDnsConfiguration; /** * Add Vertx. @@ -584,6 +586,18 @@ public RunnerBuilder rpcMaxLogsRange(final Long rpcMaxLogsRange) { return this; } + /** + * Add enode DNS configuration + * + * @param enodeDnsConfiguration the DNS configuration for enodes + * @return the runner builder + */ + public RunnerBuilder enodeDnsConfiguration(final EnodeDnsConfiguration enodeDnsConfiguration) { + this.enodeDnsConfiguration = + enodeDnsConfiguration != null ? Optional.of(enodeDnsConfiguration) : Optional.empty(); + return this; + } + /** * Build Runner instance. * @@ -1224,7 +1238,8 @@ private Map jsonRpcMethods( dataDir, besuController.getProtocolManager().ethContext().getEthPeers(), consensusEngineServer, - rpcMaxLogsRange); + rpcMaxLogsRange, + enodeDnsConfiguration); methods.putAll(besuController.getAdditionalJsonRpcMethods(jsonRpcApis)); final var pluginMethods = diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index d77dac0ce9d..8c2ed7fdc5e 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -3095,6 +3095,7 @@ private Runner synchronize( .storageProvider(keyValueStorageProvider(keyValueStorageName)) .rpcEndpointService(rpcEndpointServiceImpl) .rpcMaxLogsRange(rpcMaxLogsRange) + .enodeDnsConfiguration(getEnodeDnsConfiguration()) .build(); addShutdownHook(runner); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java index b5c31a34dee..3b9aafe35dc 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java @@ -291,6 +291,7 @@ public void initMocks() throws Exception { when(mockRunnerBuilder.rpcEndpointService(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.legacyForkId(anyBoolean())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.rpcMaxLogsRange(any())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.enodeDnsConfiguration(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.build()).thenReturn(mockRunner); final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance(); diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java index 2a4021c7e96..518d5b8c364 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java @@ -184,6 +184,7 @@ public Map methods() { dataDir, ethPeers, Vertx.vertx(new VertxOptions().setWorkerPoolSize(1)), + Optional.empty(), Optional.empty()); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminAddPeer.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminAddPeer.java index ddaa577fd19..4bd352aaa26 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminAddPeer.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminAddPeer.java @@ -19,10 +19,13 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; import org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration; import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.ethereum.p2p.peers.Peer; import org.hyperledger.besu.plugin.data.EnodeURL; +import java.util.Optional; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,8 +33,9 @@ public class AdminAddPeer extends AdminModifyPeer { private static final Logger LOG = LoggerFactory.getLogger(AdminAddPeer.class); - public AdminAddPeer(final P2PNetwork peerNetwork) { - super(peerNetwork); + public AdminAddPeer( + final P2PNetwork peerNetwork, final Optional enodeDnsConfiguration) { + super(peerNetwork, enodeDnsConfiguration); } @Override @@ -42,7 +46,10 @@ public String getName() { @Override protected JsonRpcResponse performOperation(final Object id, final String enode) { LOG.debug("Adding ({}) to peers", enode); - final EnodeURL enodeURL = EnodeURLImpl.fromString(enode); + final EnodeURL enodeURL = + this.enodeDnsConfiguration.isEmpty() + ? EnodeURLImpl.fromString(enode) + : EnodeURLImpl.fromString(enode, enodeDnsConfiguration.get()); final Peer peer = DefaultPeer.fromEnodeURL(enodeURL); final boolean addedToNetwork = peerNetwork.addMaintainedConnectionPeer(peer); return new JsonRpcSuccessResponse(id, addedToNetwork); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminModifyPeer.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminModifyPeer.java index ca0fc91b748..8cb11b9dcb5 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminModifyPeer.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminModifyPeer.java @@ -21,13 +21,19 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; import org.hyperledger.besu.ethereum.p2p.network.exceptions.P2PDisabledException; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration; + +import java.util.Optional; public abstract class AdminModifyPeer implements JsonRpcMethod { protected final P2PNetwork peerNetwork; + protected final Optional enodeDnsConfiguration; - protected AdminModifyPeer(final P2PNetwork peerNetwork) { + protected AdminModifyPeer( + final P2PNetwork peerNetwork, final Optional enodeDnsConfiguration) { this.peerNetwork = peerNetwork; + this.enodeDnsConfiguration = enodeDnsConfiguration; } @Override @@ -49,8 +55,16 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { return new JsonRpcErrorResponse( requestContext.getRequest().getId(), JsonRpcError.ENODE_ID_INVALID); } else { - return new JsonRpcErrorResponse( - requestContext.getRequest().getId(), JsonRpcError.PARSE_ERROR); + if (e.getMessage().endsWith("Invalid ip address.")) { + return new JsonRpcErrorResponse( + requestContext.getRequest().getId(), JsonRpcError.DNS_NOT_ENABLED); + } else if (e.getMessage().endsWith("dns-update-enabled flag is false.")) { + return new JsonRpcErrorResponse( + requestContext.getRequest().getId(), JsonRpcError.CANT_RESOLVE_PEER_ENODE_DNS); + } else { + return new JsonRpcErrorResponse( + requestContext.getRequest().getId(), JsonRpcError.PARSE_ERROR); + } } } catch (final P2PDisabledException e) { return new JsonRpcErrorResponse( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminRemovePeer.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminRemovePeer.java index 248024c3982..0cb654bb129 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminRemovePeer.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminRemovePeer.java @@ -19,9 +19,12 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; import org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration; import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.plugin.data.EnodeURL; +import java.util.Optional; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,8 +32,9 @@ public class AdminRemovePeer extends AdminModifyPeer { private static final Logger LOG = LoggerFactory.getLogger(AdminRemovePeer.class); - public AdminRemovePeer(final P2PNetwork peerNetwork) { - super(peerNetwork); + public AdminRemovePeer( + final P2PNetwork peerNetwork, final Optional enodeDnsConfiguration) { + super(peerNetwork, enodeDnsConfiguration); } @Override @@ -41,7 +45,10 @@ public String getName() { @Override protected JsonRpcResponse performOperation(final Object id, final String enode) { LOG.debug("Remove ({}) from peer cache", enode); - final EnodeURL enodeURL = EnodeURLImpl.fromString(enode); + final EnodeURL enodeURL = + this.enodeDnsConfiguration.isEmpty() + ? EnodeURLImpl.fromString(enode) + : EnodeURLImpl.fromString(enode, enodeDnsConfiguration.get()); final boolean result = peerNetwork.removeMaintainedConnectionPeer(DefaultPeer.fromEnodeURL(enodeURL)); return new JsonRpcSuccessResponse(id, result); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/JsonRpcError.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/JsonRpcError.java index bc633fdeff2..8b7da6bb7a6 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/JsonRpcError.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/JsonRpcError.java @@ -162,6 +162,8 @@ public enum JsonRpcError { VALUE_NOT_ZERO(-50100, "We cannot transfer ether in a private transaction yet."), CANT_CONNECT_TO_LOCAL_PEER(-32100, "Cannot add local node as peer."), + CANT_RESOLVE_PEER_ENODE_DNS(-32100, "Cannot resolve enode DNS hostname"), + DNS_NOT_ENABLED(-32100, "Enode DNS support is disabled"), // Invalid input errors ENODE_ID_INVALID( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/AdminJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/AdminJsonRpcMethods.java index 61109f73c84..286758cb762 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/AdminJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/AdminJsonRpcMethods.java @@ -29,11 +29,13 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.eth.manager.EthPeers; import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration; import org.hyperledger.besu.nat.NatService; import org.hyperledger.besu.plugin.BesuPlugin; import java.math.BigInteger; import java.util.Map; +import java.util.Optional; public class AdminJsonRpcMethods extends ApiGroupJsonRpcMethods { @@ -45,6 +47,7 @@ public class AdminJsonRpcMethods extends ApiGroupJsonRpcMethods { private final NatService natService; private final Map namedPlugins; private final EthPeers ethPeers; + private final Optional enodeDnsConfiguration; public AdminJsonRpcMethods( final String clientVersion, @@ -54,7 +57,8 @@ public AdminJsonRpcMethods( final BlockchainQueries blockchainQueries, final Map namedPlugins, final NatService natService, - final EthPeers ethPeers) { + final EthPeers ethPeers, + final Optional enodeDnsConfiguration) { this.clientVersion = clientVersion; this.networkId = networkId; this.genesisConfigOptions = genesisConfigOptions; @@ -63,6 +67,7 @@ public AdminJsonRpcMethods( this.namedPlugins = namedPlugins; this.natService = natService; this.ethPeers = ethPeers; + this.enodeDnsConfiguration = enodeDnsConfiguration; } @Override @@ -73,8 +78,8 @@ protected String getApiGroup() { @Override protected Map create() { return mapOf( - new AdminAddPeer(p2pNetwork), - new AdminRemovePeer(p2pNetwork), + new AdminAddPeer(p2pNetwork, enodeDnsConfiguration), + new AdminRemovePeer(p2pNetwork, enodeDnsConfiguration), new AdminNodeInfo( clientVersion, networkId, diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java index e0b1eb7b6ae..5effa4dd5da 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java @@ -29,6 +29,7 @@ import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; +import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.permissioning.AccountLocalConfigPermissioningController; import org.hyperledger.besu.ethereum.permissioning.NodeLocalConfigPermissioningController; @@ -76,13 +77,12 @@ public Map methods( final Path dataDir, final EthPeers ethPeers, final Vertx consensusEngineServer, - final Optional maxLogRange) { + final Optional maxLogRange, + final Optional enodeDnsConfiguration) { final Map enabled = new HashMap<>(); - if (!rpcApis.isEmpty()) { final JsonRpcMethod modules = new RpcModules(rpcApis); enabled.put(modules.getName(), modules); - final List availableApiGroups = List.of( new AdminJsonRpcMethods( @@ -93,7 +93,8 @@ public Map methods( blockchainQueries, namedPlugins, natService, - ethPeers), + ethPeers, + enodeDnsConfiguration), new DebugJsonRpcMethods( blockchainQueries, protocolContext, diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java index d2979a1bf6f..1b7a536d0b5 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java @@ -191,6 +191,7 @@ protected Map getRpcMethods( folder.getRoot().toPath(), mock(EthPeers.class), syncVertx, + Optional.empty(), Optional.empty()); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java index af10a62833b..226197c5deb 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java @@ -124,6 +124,7 @@ public void initServerAndClient() throws Exception { folder.getRoot().toPath(), mock(EthPeers.class), vertx, + Optional.empty(), Optional.empty())); service = createJsonRpcHttpService(); service.start().join(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java index 081d91a8f86..5d7e3391d04 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java @@ -154,6 +154,7 @@ public static void initServerAndClient() throws Exception { folder.getRoot().toPath(), mock(EthPeers.class), vertx, + Optional.empty(), Optional.empty())); service = createJsonRpcHttpService(); jwtAuth = service.authenticationService.get().getJwtAuthProvider(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java index 7a61d5ce9ae..06d428ab348 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java @@ -227,6 +227,7 @@ private JsonRpcHttpService createJsonRpcHttpServiceWithRpcApis(final JsonRpcConf folder, mock(EthPeers.class), vertx, + Optional.empty(), Optional.empty())); final JsonRpcHttpService jsonRpcHttpService = new JsonRpcHttpService( @@ -335,6 +336,7 @@ private JsonRpcHttpService createJsonRpcHttpService( folder, mock(EthPeers.class), vertx, + Optional.empty(), Optional.empty())); final JsonRpcHttpService jsonRpcHttpService = new JsonRpcHttpService( diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java index 29cc186c6e6..0b3b9441dc8 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java @@ -133,6 +133,7 @@ public static void initServerAndClient() throws Exception { folder.getRoot().toPath(), ethPeersMock, vertx, + Optional.empty(), Optional.empty())); service = createJsonRpcHttpService(createLimitedJsonRpcConfig()); service.start().join(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java index 389bb83d2a4..fcbfb399d16 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java @@ -139,6 +139,7 @@ public void initServer() throws Exception { folder.getRoot().toPath(), mock(EthPeers.class), vertx, + Optional.empty(), Optional.empty())); System.setProperty("javax.net.ssl.trustStore", CLIENT_AS_CA_CERT.getKeyStoreFile().toString()); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java index e1710b4a886..1e6d1f169cf 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java @@ -127,6 +127,7 @@ public void beforeEach() { tempDir.getRoot(), mock(EthPeers.class), vertx, + Optional.empty(), Optional.empty())); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java index 0b051e935ef..f45410cc9c8 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java @@ -129,6 +129,7 @@ public void initServer() throws Exception { folder.getRoot().toPath(), mock(EthPeers.class), vertx, + Optional.empty(), Optional.empty())); service = createJsonRpcHttpService(createJsonRpcConfig()); service.start().join(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminAddPeerTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminAddPeerTest.java index 24ca1482b66..8c476722d3d 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminAddPeerTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminAddPeerTest.java @@ -26,6 +26,9 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; import org.hyperledger.besu.ethereum.p2p.network.exceptions.P2PDisabledException; +import org.hyperledger.besu.ethereum.p2p.peers.ImmutableEnodeDnsConfiguration; + +import java.util.Optional; import org.junit.Before; import org.junit.Test; @@ -39,6 +42,8 @@ public class AdminAddPeerTest { @Mock private P2PNetwork p2pNetwork; private AdminAddPeer method; + private AdminAddPeer methodDNSDisabled; + private AdminAddPeer methodDNSUpdateDisabled; final String validEnode = "enode://" @@ -48,13 +53,48 @@ public class AdminAddPeerTest { + "00000000000000000000000000000000" + "@127.0.0.1:30303"; + final String validDNSEnode = + "enode://" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "@node.acme.com:30303"; + final JsonRpcRequestContext validRequest = new JsonRpcRequestContext( new JsonRpcRequest("2.0", "admin_addPeer", new String[] {validEnode})); + final JsonRpcRequestContext validDNSRequest = + new JsonRpcRequestContext( + new JsonRpcRequest("2.0", "admin_addPeer", new String[] {validDNSEnode})); + @Before public void setup() { - method = new AdminAddPeer(p2pNetwork); + method = + new AdminAddPeer( + p2pNetwork, + Optional.of( + ImmutableEnodeDnsConfiguration.builder() + .dnsEnabled(true) + .updateEnabled(true) + .build())); + methodDNSDisabled = + new AdminAddPeer( + p2pNetwork, + Optional.of( + ImmutableEnodeDnsConfiguration.builder() + .dnsEnabled(false) + .updateEnabled(true) + .build())); + methodDNSUpdateDisabled = + new AdminAddPeer( + p2pNetwork, + Optional.of( + ImmutableEnodeDnsConfiguration.builder() + .dnsEnabled(true) + .updateEnabled(false) + .build())); } @Test @@ -138,6 +178,42 @@ public void requestAddsValidEnode() { assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); } + @Test + public void requestAddsValidDNSEnode() { + when(p2pNetwork.addMaintainedConnectionPeer(any())).thenReturn(true); + + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse( + validRequest.getRequest().getId(), + true); // DNS is mapped to an IP address, so we expect the non-DNS response + + final JsonRpcResponse actualResponse = method.response(validDNSRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void requestAddsDNSEnodeButDNSDisabled() { + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse( + validDNSRequest.getRequest().getId(), JsonRpcError.DNS_NOT_ENABLED); + + final JsonRpcResponse actualResponse = methodDNSDisabled.response(validDNSRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void requestAddsDNSEnodeButDNSNotResolved() { + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse( + validDNSRequest.getRequest().getId(), JsonRpcError.CANT_RESOLVE_PEER_ENODE_DNS); + + final JsonRpcResponse actualResponse = methodDNSUpdateDisabled.response(validDNSRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + @Test public void requestRefusesListOfNodes() { final JsonRpcRequestContext request = diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminRemovePeerTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminRemovePeerTest.java new file mode 100644 index 00000000000..21c2cf2462f --- /dev/null +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminRemovePeerTest.java @@ -0,0 +1,258 @@ +/* + * Copyright Hyperledger Besu contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; +import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; +import org.hyperledger.besu.ethereum.p2p.network.exceptions.P2PDisabledException; +import org.hyperledger.besu.ethereum.p2p.peers.ImmutableEnodeDnsConfiguration; + +import java.util.Optional; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.StrictStubs.class) +public class AdminRemovePeerTest { + + @Mock private P2PNetwork p2pNetwork; + + private AdminRemovePeer method; + private AdminRemovePeer methodDNSDisabled; + private AdminRemovePeer methodDNSUpdateDisabled; + + final String validEnode = + "enode://" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "@127.0.0.1:30303"; + + final String validDNSEnode = + "enode://" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "@node.acme.com:30303"; + + final JsonRpcRequestContext validRequest = + new JsonRpcRequestContext( + new JsonRpcRequest("2.0", "admin_removePeer", new String[] {validEnode})); + + final JsonRpcRequestContext validDNSRequest = + new JsonRpcRequestContext( + new JsonRpcRequest("2.0", "admin_removePeer", new String[] {validDNSEnode})); + + @Before + public void setup() { + method = + new AdminRemovePeer( + p2pNetwork, + Optional.of( + ImmutableEnodeDnsConfiguration.builder() + .dnsEnabled(true) + .updateEnabled(true) + .build())); + methodDNSDisabled = + new AdminRemovePeer( + p2pNetwork, + Optional.of( + ImmutableEnodeDnsConfiguration.builder() + .dnsEnabled(false) + .updateEnabled(true) + .build())); + methodDNSUpdateDisabled = + new AdminRemovePeer( + p2pNetwork, + Optional.of( + ImmutableEnodeDnsConfiguration.builder() + .dnsEnabled(true) + .updateEnabled(false) + .build())); + } + + @Test + public void requestIsMissingParameter() { + final JsonRpcRequestContext request = + new JsonRpcRequestContext(new JsonRpcRequest("2.0", "admin_removePeer", new String[] {})); + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.INVALID_PARAMS); + + final JsonRpcResponse actualResponse = method.response(request); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void requestHasNullObjectParameter() { + final JsonRpcRequestContext request = + new JsonRpcRequestContext(new JsonRpcRequest("2.0", "admin_removePeer", null)); + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.INVALID_PARAMS); + + final JsonRpcResponse actualResponse = method.response(request); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void requestHasNullArrayParameter() { + final JsonRpcRequestContext request = + new JsonRpcRequestContext( + new JsonRpcRequest("2.0", "admin_removePeer", new String[] {null})); + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.INVALID_PARAMS); + + final JsonRpcResponse actualResponse = method.response(request); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void requestHasInvalidEnode() { + final JsonRpcRequestContext request = + new JsonRpcRequestContext( + new JsonRpcRequest("2.0", "admin_removePeer", new String[] {"asdf"})); + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.PARSE_ERROR); + + final JsonRpcResponse actualResponse = method.response(request); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void requestHasInvalidEnodeLength() { + String invalidLengthEnode = + "enode://" + + "0000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "@127.0.0.1:30303"; + final JsonRpcRequestContext request = + new JsonRpcRequestContext( + new JsonRpcRequest("2.0", "admin_removePeer", new String[] {invalidLengthEnode})); + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.ENODE_ID_INVALID); + + final JsonRpcResponse actualResponse = method.response(request); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void requestRemovesValidEnode() { + when(p2pNetwork.removeMaintainedConnectionPeer(any())).thenReturn(true); + + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse(validRequest.getRequest().getId(), true); + + final JsonRpcResponse actualResponse = method.response(validRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void requestRemovesValidDNSEnode() { + when(p2pNetwork.removeMaintainedConnectionPeer(any())).thenReturn(true); + + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse( + validRequest.getRequest().getId(), + true); // DNS is mapped to an IP address, so we expect the non-DNS response + + final JsonRpcResponse actualResponse = method.response(validDNSRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void requestRemovesDNSEnodeButDNSDisabled() { + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse( + validDNSRequest.getRequest().getId(), JsonRpcError.DNS_NOT_ENABLED); + + final JsonRpcResponse actualResponse = methodDNSDisabled.response(validDNSRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void requestRemovesDNSEnodeButDNSNotResolved() { + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse( + validDNSRequest.getRequest().getId(), JsonRpcError.CANT_RESOLVE_PEER_ENODE_DNS); + + final JsonRpcResponse actualResponse = methodDNSUpdateDisabled.response(validDNSRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void requestRefusesListOfNodes() { + final JsonRpcRequestContext request = + new JsonRpcRequestContext( + new JsonRpcRequest("2.0", "admin_removePeer", new String[] {validEnode, validEnode})); + + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.INVALID_PARAMS); + + final JsonRpcResponse actualResponse = method.response(request); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void requestReturnsFalseIfRemoveFails() { + when(p2pNetwork.removeMaintainedConnectionPeer(any())).thenReturn(false); + + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse(validRequest.getRequest().getId(), false); + + final JsonRpcResponse actualResponse = method.response(validRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void requestReturnsErrorWhenP2pDisabled() { + when(p2pNetwork.removeMaintainedConnectionPeer(any())) + .thenThrow( + new P2PDisabledException( + "P2P networking disabled. Unable to connect to remove peer.")); + + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse(validRequest.getRequest().getId(), JsonRpcError.P2P_DISABLED); + + final JsonRpcResponse actualResponse = method.response(validRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } +} diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceLoginTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceLoginTest.java index 0da62372a56..4b9dc5e384a 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceLoginTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceLoginTest.java @@ -186,6 +186,7 @@ public void before() throws URISyntaxException { folder.getRoot().toPath(), mock(EthPeers.class), vertx, + Optional.empty(), Optional.empty())); websocketMethods.putAll(rpcMethods); From c4c953482ed6eeda14c29db6a65a1686e904e154 Mon Sep 17 00:00:00 2001 From: Matt Whitehead Date: Mon, 26 Jun 2023 10:36:07 +0100 Subject: [PATCH 34/35] Add lock to creation of pending transaction stream (#5612) * Add lock to creation of pending transaction stream Signed-off-by: Matthew Whitehead * Alternative synchonization of signalInvalidAndRemoveDependentTransactions Signed-off-by: Fabio Di Fabio --------- Signed-off-by: Matthew Whitehead Signed-off-by: Fabio Di Fabio Co-authored-by: Matthew Whitehead Co-authored-by: Fabio Di Fabio --- .../sorter/AbstractPendingTransactionsSorter.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java index b936e3ce25a..83424ae22fd 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java @@ -541,7 +541,9 @@ public List signalInvalidAndGetDependentTransactions(final Transact @Override public void signalInvalidAndRemoveDependentTransactions(final Transaction transaction) { - signalInvalidAndGetDependentTransactions(transaction).forEach(this::removeTransaction); + synchronized (lock) { + signalInvalidAndGetDependentTransactions(transaction).forEach(this::removeTransaction); + } } @Override From e96026c73c6b4d0183fc84630ff54cbf54201610 Mon Sep 17 00:00:00 2001 From: Matt Whitehead Date: Tue, 11 Jul 2023 08:59:14 +0100 Subject: [PATCH 35/35] Only validate `--miner-enabled` option for ethash networks (#5669) * Modify the min-gas-price option validation * Check for whether ethash is in use, either from genesis or network config, and use that for miner checks * Add genesis configuration isPoa() convenience function --------- Signed-off-by: Matthew Whitehead Signed-off-by: Matt Whitehead Co-authored-by: Simon Dudley Signed-off-by: Simon Dudley --- CHANGELOG.md | 3 + .../org/hyperledger/besu/cli/BesuCommand.java | 23 ++--- .../hyperledger/besu/cli/BesuCommandTest.java | 85 ++++++++++++++++++- .../besu/config/GenesisConfigOptions.java | 7 ++ .../besu/config/JsonGenesisConfigOptions.java | 5 ++ .../besu/config/StubGenesisConfigOptions.java | 5 ++ .../besu/config/GenesisConfigOptionsTest.java | 11 +++ 7 files changed, 126 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80864d6bbe7..c0cb0751ef3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ ### Bug Fixes - Use the node's configuration to determine if DNS enode URLs are allowed in calls to `admin_addPeer` and `admin_removePeer` [#5584](https://github.com/hyperledger/besu/pull/5584) +- Align the implementation of Eth/68 `NewPooledTransactionHashes` to other clients, using unsigned int for encoding size. [#5640](https://github.com/hyperledger/besu/pull/5640) +- Failure at startup when enabling layered txpool before initial sync done [#5636](https://github.com/hyperledger/besu/issues/5636) +- Remove miner-related option warnings if the change isn't using Ethash consensus algorithm [#5669](https://github.com/hyperledger/besu/pull/5669) ### Download Links diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 8c2ed7fdc5e..94a292ae828 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -2133,7 +2133,7 @@ private void issueOptionWarnings() { "--remote-connections-max-percentage")); // Check that block producer options work - if (!isMergeEnabled()) { + if (!isMergeEnabled() && getActualGenesisConfigOptions().isEthHash()) { CommandLineUtils.checkOptionDependencies( logger, commandLine, @@ -2144,17 +2144,18 @@ private void issueOptionWarnings() { "--min-gas-price", "--min-block-occupancy-ratio", "--miner-extra-data")); + + // Check that mining options are able to work + CommandLineUtils.checkOptionDependencies( + logger, + commandLine, + "--miner-enabled", + !minerOptionGroup.isMiningEnabled, + asList( + "--miner-stratum-enabled", + "--Xminer-remote-sealers-limit", + "--Xminer-remote-sealers-hashrate-ttl")); } - // Check that mining options are able to work - CommandLineUtils.checkOptionDependencies( - logger, - commandLine, - "--miner-enabled", - !minerOptionGroup.isMiningEnabled, - asList( - "--miner-stratum-enabled", - "--Xminer-remote-sealers-limit", - "--Xminer-remote-sealers-hashrate-ttl")); CommandLineUtils.failIfOptionDoesntMeetRequirement( commandLine, diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index 0b25e919eb7..6476674fe68 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -168,6 +168,20 @@ public class BesuCommandTest extends CommandTestAbstract { (new JsonObject()).put("config", new JsonObject().put("ecCurve", "secp256k1")); private static final String ENCLAVE_PUBLIC_KEY_PATH = BesuCommand.class.getResource("/orion_publickey.pub").getPath(); + private static final JsonObject VALID_GENESIS_QBFT_POST_LONDON = + (new JsonObject()) + .put( + "config", + new JsonObject() + .put("londonBlock", 0) + .put("qbft", new JsonObject().put("blockperiodseconds", 5))); + private static final JsonObject VALID_GENESIS_IBFT2_POST_LONDON = + (new JsonObject()) + .put( + "config", + new JsonObject() + .put("londonBlock", 0) + .put("ibft2", new JsonObject().put("blockperiodseconds", 5))); private static final String[] VALID_ENODE_STRINGS = { "enode://" + VALID_NODE_ID + "@192.168.0.1:4567", @@ -3684,7 +3698,7 @@ public void stratumMiningIsEnabledWhenSpecified() throws Exception { @Test public void stratumMiningOptionsRequiresServiceToBeEnabled() { - parseCommand("--miner-stratum-enabled"); + parseCommand("--network", "dev", "--miner-stratum-enabled"); verifyOptionsConstraintLoggerCall("--miner-enabled", "--miner-stratum-enabled"); @@ -3698,7 +3712,7 @@ public void stratumMiningOptionsRequiresServiceToBeEnabled() { public void stratumMiningOptionsRequiresServiceToBeEnabledToml() throws IOException { final Path toml = createTempFile("toml", "miner-stratum-enabled=true\n"); - parseCommand("--config-file", toml.toString()); + parseCommand("--network", "dev", "--config-file", toml.toString()); verifyOptionsConstraintLoggerCall("--miner-enabled", "--miner-stratum-enabled"); @@ -3753,6 +3767,46 @@ public void blockProducingOptionsWarnsMinerShouldBeEnabledToml() throws IOExcept assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); } + @Test + public void blockProducingOptionsDoNotWarnWhenPoA() throws IOException { + + final Path genesisFileQBFT = createFakeGenesisFile(VALID_GENESIS_QBFT_POST_LONDON); + parseCommand( + "--genesis-file", + genesisFileQBFT.toString(), + "--min-gas-price", + "42", + "--miner-extra-data", + "0x1122334455667788990011223344556677889900112233445566778899001122"); + + verify(mockLogger, atMost(0)) + .warn( + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture()); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + + final Path genesisFileIBFT2 = createFakeGenesisFile(VALID_GENESIS_IBFT2_POST_LONDON); + parseCommand( + "--genesis-file", + genesisFileIBFT2.toString(), + "--min-gas-price", + "42", + "--miner-extra-data", + "0x1122334455667788990011223344556677889900112233445566778899001122"); + + verify(mockLogger, atMost(0)) + .warn( + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture()); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + @Test public void blockProducingOptionsDoNotWarnWhenMergeEnabled() { @@ -3801,6 +3855,33 @@ public void minGasPriceRequiresMainOptionToml() throws IOException { assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); } + @Test + public void minGasPriceDoesNotRequireMainOptionWhenPoA() throws IOException { + final Path genesisFileQBFT = createFakeGenesisFile(VALID_GENESIS_QBFT_POST_LONDON); + parseCommand("--genesis-file", genesisFileQBFT.toString(), "--min-gas-price", "0"); + + verify(mockLogger, atMost(0)) + .warn( + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture()); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + + final Path genesisFileIBFT2 = createFakeGenesisFile(VALID_GENESIS_IBFT2_POST_LONDON); + parseCommand("--genesis-file", genesisFileIBFT2.toString(), "--min-gas-price", "0"); + + verify(mockLogger, atMost(0)) + .warn( + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture(), + stringArgumentCaptor.capture()); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + @Test public void miningParametersAreCaptured() { final Address requestedCoinbase = Address.fromHexString("0000011111222223333344444"); diff --git a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java index d5acee99fb4..921d179993a 100644 --- a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java @@ -64,6 +64,13 @@ public interface GenesisConfigOptions { */ boolean isClique(); + /** + * Is a Proof of Authority network. + * + * @return the boolean + */ + boolean isPoa(); + /** * Is consensus migration boolean. * diff --git a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java index 7db62667776..6f7c76c65b5 100644 --- a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java @@ -144,6 +144,11 @@ public boolean isQbft() { return configRoot.has(QBFT_CONFIG_KEY); } + @Override + public boolean isPoa() { + return isQbft() || isClique() || isIbft2() || isIbftLegacy(); + } + @Override public BftConfigOptions getBftConfigOptions() { final String fieldKey = isIbft2() ? IBFT2_CONFIG_KEY : QBFT_CONFIG_KEY; diff --git a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java index 0288392545f..6fad16904cf 100644 --- a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java @@ -115,6 +115,11 @@ public boolean isQbft() { return false; } + @Override + public boolean isPoa() { + return false; + } + @Override public CheckpointConfigOptions getCheckpointOptions() { return CheckpointConfigOptions.DEFAULT; diff --git a/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java b/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java index 9e60a40db80..0cffcf5d247 100644 --- a/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java +++ b/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java @@ -46,13 +46,22 @@ public void shouldNotUseEthHashIfEthHashNotPresent() { public void shouldUseIbft2WhenIbft2InConfig() { final GenesisConfigOptions config = fromConfigOptions(singletonMap("ibft2", emptyMap())); assertThat(config.isIbft2()).isTrue(); + assertThat(config.isPoa()).isTrue(); assertThat(config.getConsensusEngine()).isEqualTo("ibft2"); } + public void shouldUseQbftWhenQbftInConfig() { + final GenesisConfigOptions config = fromConfigOptions(singletonMap("qbft", emptyMap())); + assertThat(config.isQbft()).isTrue(); + assertThat(config.isPoa()).isTrue(); + assertThat(config.getConsensusEngine()).isEqualTo("qbft"); + } + @Test public void shouldUseCliqueWhenCliqueInConfig() { final GenesisConfigOptions config = fromConfigOptions(singletonMap("clique", emptyMap())); assertThat(config.isClique()).isTrue(); + assertThat(config.isPoa()).isTrue(); assertThat(config.getCliqueConfigOptions()).isNotSameAs(CliqueConfigOptions.DEFAULT); assertThat(config.getConsensusEngine()).isEqualTo("clique"); } @@ -61,6 +70,7 @@ public void shouldUseCliqueWhenCliqueInConfig() { public void shouldNotUseCliqueIfCliqueNotPresent() { final GenesisConfigOptions config = fromConfigOptions(emptyMap()); assertThat(config.isClique()).isFalse(); + assertThat(config.isPoa()).isFalse(); assertThat(config.getCliqueConfigOptions()).isSameAs(CliqueConfigOptions.DEFAULT); } @@ -228,6 +238,7 @@ public void shouldSupportEmptyGenesisConfig() { final GenesisConfigOptions config = GenesisConfigFile.fromConfig("{}").getConfigOptions(); assertThat(config.isEthHash()).isFalse(); assertThat(config.isClique()).isFalse(); + assertThat(config.isPoa()).isFalse(); assertThat(config.getHomesteadBlockNumber()).isEmpty(); }