From 99b9ab3f3f876f59bea29b5ba569957fefa604d7 Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Mon, 8 Jan 2024 15:18:10 +0100 Subject: [PATCH] Merge Besu main (#32) * mark deleted slot during clear storage step (#6305) Signed-off-by: Karim Taam Co-authored-by: garyschulte * made directory structure of tests match source; fixed one typo (#6337) Signed-off-by: Sally MacFarlane * migrate controller tests to junit 5 (#6338) Signed-off-by: Sally MacFarlane * add new forkids for testnets, update forkid test to Junit5, no longer need named network specific trusted setups (#6322) Signed-off-by: jflo * Fix trielog shipping issue during self destruct (#6340) * fix trielog shipping issue Signed-off-by: Karim Taam * bump gradle properties version and adjust changelog to match release (#6347) Signed-off-by: garyschulte * finalized cancun spec (#6351) * finalized cancun spec Signed-off-by: jflo * finalized cancun spec Signed-off-by: jflo --------- Signed-off-by: jflo * Optimize RocksDB WAL file (#6328) Signed-off-by: Fabio Di Fabio * Make RPC reason settable, pass execution failure reason in RPC error message (#6343) * Make RPC reason settable, pass execution failure reason in RPC error message Signed-off-by: Matthew Whitehead * Update unit tests Signed-off-by: Matthew Whitehead * Update tests Signed-off-by: Matthew Whitehead * Update change log Signed-off-by: Matthew Whitehead * Update integration tests Signed-off-by: Matthew Whitehead --------- Signed-off-by: Matthew Whitehead * TestWatcher junit5 (#6339) * TestWatcher junit5 * add test class and method name to context * moved the testwatcher junit5 function to a new junit5 superclass * one qbft test to junit5 superclass Signed-off-by: Sally MacFarlane --------- Signed-off-by: Sally MacFarlane Co-authored-by: Stefan Pingel <16143240+pinges@users.noreply.github.com> * Migrate BFT tests to junit 5 (#6350) * bft tests to junit 5 * base class for pki extend AcceptanceTestBaseJunit5 * try/catch in case of empty optionals * fixed parameterization method Signed-off-by: Sally MacFarlane --------- Signed-off-by: Sally MacFarlane * fixing on selfdestruct (#6359) Signed-off-by: Karim Taam * migrate clique tests fully to junit5 (#6362) * migrate clique tests fully to junit5 Signed-off-by: Sally MacFarlane --------- Signed-off-by: Sally MacFarlane * fixed link to logging docs (#6366) Signed-off-by: Sally MacFarlane * Move logging to RunnerBuilder (#6367) Signed-off-by: Gabriel-Trintinalia * Use synchronized call to access the chain head block in `eth_estimateGas` (#6345) * Use synchronized call to access the chain head block in estimateGas() Signed-off-by: Matthew Whitehead * Add error log entries when throwing internal error from estimateGas() Signed-off-by: Matthew Whitehead * Update unit tests Signed-off-by: Matthew Whitehead * Update changelog Signed-off-by: Matthew Whitehead --------- Signed-off-by: Matthew Whitehead --------- Signed-off-by: Karim Taam Signed-off-by: Sally MacFarlane Signed-off-by: jflo Signed-off-by: garyschulte Signed-off-by: Fabio Di Fabio Signed-off-by: Matthew Whitehead Signed-off-by: Gabriel-Trintinalia Co-authored-by: Karim TAAM Co-authored-by: garyschulte Co-authored-by: Sally MacFarlane Co-authored-by: Justin Florentine Co-authored-by: Matt Whitehead Co-authored-by: Stefan Pingel <16143240+pinges@users.noreply.github.com> Co-authored-by: Gabriel-Trintinalia --- CHANGELOG.md | 17 +- README.md | 2 +- acceptance-tests/dsl/build.gradle | 1 + .../acceptance/dsl/AcceptanceTestBase.java | 57 +---- .../dsl/AcceptanceTestBaseJunit5.java | 200 ++++++++++++++++++ .../dsl/AcceptanceTestBaseTestWatcher.java | 58 +++++ .../BftAcceptanceTestParameterization.java | 30 ++- .../BftBlockRewardPaymentAcceptanceTest.java | 38 ++-- .../bft/BftDiscardRpcAcceptanceTest.java | 15 +- .../bft/BftMiningAcceptanceTest.java | 58 +++-- .../bft/BftProposalRpcAcceptanceTest.java | 15 +- .../bft/BftProposeRpcAcceptanceTest.java | 15 +- ...a => BftZeroValidatorsAcceptanceTest.java} | 17 +- .../bft/ParameterizedBftTestBase.java | 26 +-- .../bft/pki/ParameterizedPkiQbftTestBase.java | 26 +-- .../bft/pki/PkiQbftAcceptanceTest.java | 29 +-- ...PkiQbftAcceptanceTestParameterization.java | 91 ++++---- .../bft/qbft/QbftContractAcceptanceTest.java | 6 +- .../CliqueDiscardRpcAcceptanceTest.java | 6 +- ...=> CliqueGetSignersRpcAcceptanceTest.java} | 14 +- .../clique/CliqueMiningAcceptanceTest.java | 6 +- .../CliqueProposalRpcAcceptanceTest.java | 6 +- .../CliqueProposeRpcAcceptanceTest.java | 6 +- ...> CliqueZeroValidatorsAcceptanceTest.java} | 6 +- .../plugins/BadCLIOptionsPluginTest.java | 4 +- .../plugins/BesuEventsPluginTest.java | 4 +- .../plugins/PermissioningPluginTest.java | 4 +- .../org/hyperledger/besu/RunnerBuilder.java | 2 + .../org/hyperledger/besu/cli/BesuCommand.java | 6 - .../EthEstimateGasIntegrationTest.java | 9 +- .../api/jsonrpc/JsonRpcErrorConverter.java | 2 + .../internal/methods/AbstractEstimateGas.java | 21 +- .../internal/methods/EthEstimateGas.java | 7 + .../internal/response/JsonRpcError.java | 4 + .../internal/response/RpcErrorType.java | 1 + .../methods/EthCreateAccessListTest.java | 12 +- .../internal/methods/EthEstimateGasTest.java | 61 ++++-- .../jsonrpc/eth/eth_estimateGas_invalid.json | 4 +- .../mainnet/MainnetTransactionProcessor.java | 7 + .../transaction/TransactionInvalidReason.java | 1 + .../bonsai/worldview/BonsaiWorldState.java | 101 +++++---- .../hyperledger/besu/evm/EvmSpecVersion.java | 2 +- .../besu/evm/fluent/EVMExecutorTest.java | 2 +- gradle.properties | 4 +- .../RocksDBColumnarKeyValueStorage.java | 7 + 45 files changed, 655 insertions(+), 355 deletions(-) create mode 100644 acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBaseJunit5.java create mode 100644 acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBaseTestWatcher.java rename acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/{BftZeroValidators.java => BftZeroValidatorsAcceptanceTest.java} (73%) rename acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/{CliqueGetSignersRpcTest.java => CliqueGetSignersRpcAcceptanceTest.java} (88%) rename acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/{CliqueZeroValidators.java => CliqueZeroValidatorsAcceptanceTest.java} (90%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0275bd837a5..ea4b5f915e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,9 @@ # Changelog -## 23.10.4 +## 24.1.0-SNAPSHOT ### Breaking Changes +- New `EXECUTION_HALTED` error returned if there is an error executing or simulating a transaction, with the reason for execution being halted. Replaces the generic `INTERNAL_ERROR` return code in certain cases which some applications may be checking for [#6343](https://github.com/hyperledger/besu/pull/6343) ### Deprecations - Forest pruning (`pruning-enabled` options) is deprecated and will be removed soon. To save disk space consider switching to Bonsai data storage format [#6230](https://github.com/hyperledger/besu/pull/6230) @@ -13,16 +14,13 @@ - Set Ethereum Classic mainnet activation block for Spiral network upgrade [#6267](https://github.com/hyperledger/besu/pull/6267) - Add custom genesis file name to config overview if specified [#6297](https://github.com/hyperledger/besu/pull/6297) - Update Gradle plugins and replace unmaintained License Gradle Plugin with the actively maintained Gradle License Report [#6275](https://github.com/hyperledger/besu/pull/6275) +- Optimize RocksDB WAL files, allows for faster restart and a more linear disk space utilization [#6328](https://github.com/hyperledger/besu/pull/6328) ### Bug fixes - +- INTERNAL_ERROR from `eth_estimateGas` JSON/RPC calls [#6344](https://github.com/hyperledger/besu/issues/6344) ## 23.10.3 -### Breaking Changes - -### Deprecations - ### Additions and Improvements - Implement debug_traceCall [#5885](https://github.com/hyperledger/besu/pull/5885) - Transactions that takes too long to evaluate, during block creation, are dropped from the txpool [#6163](https://github.com/hyperledger/besu/pull/6163) @@ -34,11 +32,18 @@ - Update OpenJ9 Docker image to latest version [#6226](https://github.com/hyperledger/besu/pull/6226) - Add error messages on authentication failures with username and password [#6212](https://github.com/hyperledger/besu/pull/6212) - Add `rocksdb usage` to the `storage` subcommand to allow users and dev to check columns families usage [#6185](https://github.com/hyperledger/besu/pull/6185) +- Ethereum Classic Spiral network upgrade [#6078](https://github.com/hyperledger/besu/pull/6078) +- Fix self destruct collision [#6205](https://github.com/hyperledger/besu/pull/6205) +- Mark deleted storage on cleared [#6305](https://github.com/hyperledger/besu/pull/6305) ### Bug fixes - Fix Docker image name clash between Besu and evmtool [#6194](https://github.com/hyperledger/besu/pull/6194) - Fix `logIndex` in `eth_getTransactionReceipt` JSON RPC method [#6206](https://github.com/hyperledger/besu/pull/6206) +### Download Links +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/23.10.3/besu-23.10.3.zip / sha256 da7ef8a6ceb88d3e327cacddcdb32218d1750b464c14165a74068f6dc6e0871a +https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/23.10.3/besu-23.10.3.tar.gz / sha256 73c834cf32c7bbe255d7d8cc7ca5d1eb0df8430b9114935c8dcf3a675b2acbc2 + ## 23.10.2 ### Breaking Changes diff --git a/README.md b/README.md index f0a8690d0f2..81d836836ff 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Instructions for how to get started with developing on the Besu codebase. Please * [Checking Out and Building](https://wiki.hyperledger.org/display/BESU/Building+from+source) * [Running Developer Builds](https://wiki.hyperledger.org/display/BESU/Building+from+source#running-developer-builds) * [Code Coverage](https://wiki.hyperledger.org/display/BESU/Code+coverage) -* [Logging](https://wiki.hyperledger.org/display/BESU/Logging) or the [Documentation's Logging section](https://besu.hyperledger.org/en/stable/HowTo/Monitor/Logging/) +* [Logging](https://wiki.hyperledger.org/display/BESU/Logging) or the [Documentation's Logging section](https://besu.hyperledger.org/public-networks/how-to/monitor/logging) ## Release Notes diff --git a/acceptance-tests/dsl/build.gradle b/acceptance-tests/dsl/build.gradle index 7aff9aaffb5..96a6a1c1bc0 100644 --- a/acceptance-tests/dsl/build.gradle +++ b/acceptance-tests/dsl/build.gradle @@ -47,4 +47,5 @@ dependencies { implementation 'org.web3j:crypto' implementation 'org.testcontainers:testcontainers' + implementation 'org.junit.jupiter:junit-jupiter' } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBase.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBase.java index 617e0e534cb..cac4deb9d9b 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBase.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBase.java @@ -49,7 +49,6 @@ import org.hyperledger.besu.tests.acceptance.dsl.transaction.web3.Web3Transactions; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.lang.ProcessBuilder.Redirect; @@ -58,14 +57,15 @@ import java.util.concurrent.Executors; import org.junit.After; -import org.junit.Rule; -import org.junit.rules.TestName; -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; +import org.junit.jupiter.api.extension.ExtendWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.slf4j.MDC; +/** + * Superclass for acceptance tests. For now (transition to junit5 is ongoing) this class supports + * junit4 format. + */ +@ExtendWith(AcceptanceTestBaseTestWatcher.class) public class AcceptanceTestBase { private static final Logger LOG = LoggerFactory.getLogger(AcceptanceTestBase.class); @@ -131,8 +131,6 @@ protected AcceptanceTestBase() { exitedSuccessfully = new ExitedWithCode(0); } - @Rule public final TestName name = new TestName(); - @After public void tearDownAcceptanceTestBase() { reportMemory(); @@ -178,49 +176,6 @@ private void printOutput(final Process process) { } } - @Rule - public TestWatcher logEraser = - new TestWatcher() { - - @Override - protected void starting(final Description description) { - MDC.put("test", description.getMethodName()); - MDC.put("class", description.getClassName()); - - final String errorMessage = "Uncaught exception in thread \"{}\""; - Thread.currentThread() - .setUncaughtExceptionHandler( - (thread, error) -> LOG.error(errorMessage, thread.getName(), error)); - Thread.setDefaultUncaughtExceptionHandler( - (thread, error) -> LOG.error(errorMessage, thread.getName(), error)); - } - - @Override - protected void failed(final Throwable e, final Description description) { - // add the result at the end of the log so it is self-sufficient - LOG.error( - "=========================================================================================="); - LOG.error("Test failed. Reported Throwable at the point of failure:", e); - LOG.error(e.getMessage()); - } - - @Override - protected void succeeded(final Description description) { - // if so configured, delete logs of successful tests - if (!Boolean.getBoolean("acctests.keepLogsOfPassingTests")) { - String pathname = - "build/acceptanceTestLogs/" - + description.getClassName() - + "." - + description.getMethodName() - + ".log"; - LOG.info("Test successful, deleting log at {}", pathname); - File file = new File(pathname); - file.delete(); - } - } - }; - protected void waitForBlockHeight(final Node node, final long blockchainHeight) { WaitUtils.waitFor( 120, diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBaseJunit5.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBaseJunit5.java new file mode 100644 index 00000000000..39b45d6e327 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBaseJunit5.java @@ -0,0 +1,200 @@ +/* + * 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.dsl; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts; +import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Blockchain; +import org.hyperledger.besu.tests.acceptance.dsl.condition.admin.AdminConditions; +import org.hyperledger.besu.tests.acceptance.dsl.condition.bft.BftConditions; +import org.hyperledger.besu.tests.acceptance.dsl.condition.clique.CliqueConditions; +import org.hyperledger.besu.tests.acceptance.dsl.condition.eth.EthConditions; +import org.hyperledger.besu.tests.acceptance.dsl.condition.login.LoginConditions; +import org.hyperledger.besu.tests.acceptance.dsl.condition.net.NetConditions; +import org.hyperledger.besu.tests.acceptance.dsl.condition.perm.PermissioningConditions; +import org.hyperledger.besu.tests.acceptance.dsl.condition.priv.PrivConditions; +import org.hyperledger.besu.tests.acceptance.dsl.condition.process.ExitedWithCode; +import org.hyperledger.besu.tests.acceptance.dsl.condition.txpool.TxPoolConditions; +import org.hyperledger.besu.tests.acceptance.dsl.condition.web3.Web3Conditions; +import org.hyperledger.besu.tests.acceptance.dsl.contract.ContractVerifier; +import org.hyperledger.besu.tests.acceptance.dsl.node.Node; +import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeFactory; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.permissioning.PermissionedNodeBuilder; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.account.AccountTransactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.admin.AdminTransactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.bft.BftTransactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.clique.CliqueTransactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.contract.ContractTransactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.eth.EthTransactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.miner.MinerTransactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.net.NetTransactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.perm.PermissioningTransactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyTransactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.txpool.TxPoolTransactions; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.web3.Web3Transactions; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.math.BigInteger; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.apache.logging.log4j.ThreadContext; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.api.extension.ExtendWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Superclass for acceptance tests. For now (transition to junit5 is ongoing) this class supports + * junit5 format. Once the transition is complete, this class can be removed and recombined with + * AcceptanceTestBase (original). + */ +@ExtendWith(AcceptanceTestBaseTestWatcher.class) +public class AcceptanceTestBaseJunit5 { + + private static final Logger LOG = LoggerFactory.getLogger(AcceptanceTestBaseJunit5.class); + + protected final Accounts accounts; + protected final AccountTransactions accountTransactions; + protected final AdminConditions admin; + protected final AdminTransactions adminTransactions; + protected final Blockchain blockchain; + protected final CliqueConditions clique; + protected final CliqueTransactions cliqueTransactions; + protected final Cluster cluster; + protected final ContractVerifier contractVerifier; + protected final ContractTransactions contractTransactions; + protected final EthConditions eth; + protected final EthTransactions ethTransactions; + protected final BftTransactions bftTransactions; + protected final BftConditions bft; + protected final LoginConditions login; + protected final NetConditions net; + protected final BesuNodeFactory besu; + protected final PermissioningConditions perm; + protected final PermissionedNodeBuilder permissionedNodeBuilder; + protected final PermissioningTransactions permissioningTransactions; + protected final MinerTransactions minerTransactions; + protected final Web3Conditions web3; + protected final PrivConditions priv; + protected final PrivacyTransactions privacyTransactions; + protected final TxPoolConditions txPoolConditions; + protected final TxPoolTransactions txPoolTransactions; + protected final ExitedWithCode exitedSuccessfully; + + private final ExecutorService outputProcessorExecutor = Executors.newCachedThreadPool(); + + protected AcceptanceTestBaseJunit5() { + ethTransactions = new EthTransactions(); + accounts = new Accounts(ethTransactions); + adminTransactions = new AdminTransactions(); + cliqueTransactions = new CliqueTransactions(); + bftTransactions = new BftTransactions(); + accountTransactions = new AccountTransactions(accounts); + permissioningTransactions = new PermissioningTransactions(); + privacyTransactions = new PrivacyTransactions(); + contractTransactions = new ContractTransactions(); + minerTransactions = new MinerTransactions(); + + blockchain = new Blockchain(ethTransactions); + clique = new CliqueConditions(ethTransactions, cliqueTransactions); + eth = new EthConditions(ethTransactions); + bft = new BftConditions(bftTransactions); + login = new LoginConditions(); + net = new NetConditions(new NetTransactions()); + cluster = new Cluster(net); + perm = new PermissioningConditions(permissioningTransactions); + priv = new PrivConditions(privacyTransactions); + admin = new AdminConditions(adminTransactions); + web3 = new Web3Conditions(new Web3Transactions()); + besu = new BesuNodeFactory(); + txPoolTransactions = new TxPoolTransactions(); + txPoolConditions = new TxPoolConditions(txPoolTransactions); + contractVerifier = new ContractVerifier(accounts.getPrimaryBenefactor()); + permissionedNodeBuilder = new PermissionedNodeBuilder(); + exitedSuccessfully = new ExitedWithCode(0); + } + + @BeforeEach + public void setUp(final TestInfo testInfo) { + // log4j is configured to create a file per test + // build/acceptanceTestLogs/${ctx:class}.${ctx:test}.log + ThreadContext.put("class", this.getClass().getSimpleName()); + ThreadContext.put("test", testInfo.getTestMethod().get().getName()); + } + + @AfterEach + public void tearDownAcceptanceTestBase() { + reportMemory(); + cluster.close(); + } + + public void reportMemory() { + String os = System.getProperty("os.name"); + String[] command = null; + if (os.contains("Linux")) { + command = new String[] {"/usr/bin/top", "-n", "1", "-o", "%MEM", "-b", "-c", "-w", "180"}; + } + if (os.contains("Mac")) { + command = new String[] {"/usr/bin/top", "-l", "1", "-o", "mem", "-n", "20"}; + } + if (command != null) { + LOG.info("Memory usage at end of test:"); + final ProcessBuilder processBuilder = + new ProcessBuilder(command) + .redirectErrorStream(true) + .redirectInput(ProcessBuilder.Redirect.INHERIT); + try { + final Process memInfoProcess = processBuilder.start(); + outputProcessorExecutor.execute(() -> printOutput(memInfoProcess)); + memInfoProcess.waitFor(); + LOG.debug("Memory info process exited with code {}", memInfoProcess.exitValue()); + } catch (final Exception e) { + LOG.warn("Error running memory information process", e); + } + } else { + LOG.info("Don't know how to report memory for OS {}", os); + } + } + + private void printOutput(final Process process) { + try (final BufferedReader in = + new BufferedReader(new InputStreamReader(process.getInputStream(), UTF_8))) { + String line = in.readLine(); + while (line != null) { + LOG.info(line); + line = in.readLine(); + } + } catch (final IOException e) { + LOG.warn("Failed to read output from memory information process: ", e); + } + } + + protected void waitForBlockHeight(final Node node, final long blockchainHeight) { + WaitUtils.waitFor( + 120, + () -> + assertThat(node.execute(ethTransactions.blockNumber())) + .isGreaterThanOrEqualTo(BigInteger.valueOf(blockchainHeight))); + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBaseTestWatcher.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBaseTestWatcher.java new file mode 100644 index 00000000000..ec50920403c --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBaseTestWatcher.java @@ -0,0 +1,58 @@ +/* + * 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.dsl; + +import java.io.File; + +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.TestWatcher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AcceptanceTestBaseTestWatcher implements TestWatcher { + private static final Logger LOG = LoggerFactory.getLogger(AcceptanceTestBaseTestWatcher.class); + + @Override + public void testFailed(final ExtensionContext extensionContext, final Throwable e) { + // add the result at the end of the log, so it is self-sufficient + LOG.error( + "=========================================================================================="); + LOG.error("Test failed. Reported Throwable at the point of failure:", e); + LOG.error(e.getMessage()); + } + + @Override + public void testSuccessful(final ExtensionContext extensionContext) { + // if so configured, delete logs of successful tests + if (!Boolean.getBoolean("acctests.keepLogsOfPassingTests")) { + try { + // log4j is configured to create a file per test + // build/acceptanceTestLogs/${ctx:class}.${ctx:test}.log + String pathname = + "build/acceptanceTestLogs/" + + extensionContext.getTestClass().get().getSimpleName() + + "." + + extensionContext.getTestMethod().get().getName() + + ".log"; + LOG.info("Test successful, deleting log at {}", pathname); + final File file = new File(pathname); + file.delete(); + } catch (final Exception e) { + LOG.error("could not delete test file", e); + } + } + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftAcceptanceTestParameterization.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftAcceptanceTestParameterization.java index b7464190abe..c9fcf364840 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftAcceptanceTestParameterization.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftAcceptanceTestParameterization.java @@ -17,26 +17,22 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeFactory; -import java.util.ArrayList; -import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.params.provider.Arguments; public class BftAcceptanceTestParameterization { - public static List getFactories() { - final List ret = new ArrayList<>(); - ret.addAll( - List.of( - new Object[] { - "ibft2", - new BftAcceptanceTestParameterization( - BesuNodeFactory::createIbft2Node, BesuNodeFactory::createIbft2NodeWithValidators) - }, - new Object[] { - "qbft", - new BftAcceptanceTestParameterization( - BesuNodeFactory::createQbftNode, BesuNodeFactory::createQbftNodeWithValidators) - })); - return ret; + public static Stream getFactories() { + return Stream.of( + Arguments.of( + "ibft2", + new BftAcceptanceTestParameterization( + BesuNodeFactory::createIbft2Node, BesuNodeFactory::createIbft2NodeWithValidators)), + Arguments.of( + "qbft", + new BftAcceptanceTestParameterization( + BesuNodeFactory::createQbftNode, BesuNodeFactory::createQbftNodeWithValidators))); } @FunctionalInterface diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftBlockRewardPaymentAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftBlockRewardPaymentAcceptanceTest.java index 4225035b7ff..86978ae0b0e 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftBlockRewardPaymentAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftBlockRewardPaymentAcceptanceTest.java @@ -32,19 +32,18 @@ import java.util.Optional; import java.util.TreeMap; -import org.junit.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class BftBlockRewardPaymentAcceptanceTest extends ParameterizedBftTestBase { private static final Amount BLOCK_REWARD = Amount.wei(new BigInteger("5000000000000000000", 10)); - public BftBlockRewardPaymentAcceptanceTest( - final String testName, final BftAcceptanceTestParameterization nodeFactory) { - super(testName, nodeFactory); - } - - @Test - public void validatorsArePaidBlockReward() throws Exception { + @ParameterizedTest(name = "{0} bft node factory type") + @MethodSource("factoryFunctions") + public void validatorsArePaidBlockReward( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final String[] validators = {"validator"}; final BesuNode validator = nodeFactory.createNodeWithValidators(besu, "validator", validators); final BesuNode nonValidator = @@ -61,8 +60,11 @@ public void validatorsArePaidBlockReward() throws Exception { Amount.ether(blockRewardEth * blockToCheck), BigInteger.valueOf(blockToCheck))); } - @Test - public void payBlockRewardToConfiguredNode() throws Exception { + @ParameterizedTest(name = "{0} bft node factory type") + @MethodSource("factoryFunctions") + public void payBlockRewardToConfiguredNode( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final String[] validators = {"validator1"}; final BesuNode validator1 = nodeFactory.createNodeWithValidators(besu, "validator1", validators); @@ -90,9 +92,11 @@ public void payBlockRewardToConfiguredNode() throws Exception { Amount.ether(blockRewardEth * blockToCheck), BigInteger.valueOf(blockToCheck))); } - @Test - public void payBlockRewardAccordingToTransitions_defaultInitialMiningBeneficiary() - throws Exception { + @ParameterizedTest(name = "{0} bft node factory type") + @MethodSource("factoryFunctions") + public void payBlockRewardAccordingToTransitions_defaultInitialMiningBeneficiary( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final List
addresses = generateAddresses(2); final Map> transitions = Map.of( @@ -103,9 +107,11 @@ public void payBlockRewardAccordingToTransitions_defaultInitialMiningBeneficiary testMiningBeneficiaryTransitions(Optional.empty(), transitions); } - @Test - public void payBlockRewardAccordingToTransitions_customInitialMiningBeneficiary() - throws Exception { + @ParameterizedTest(name = "{0} bft node factory type") + @MethodSource("factoryFunctions") + public void payBlockRewardAccordingToTransitions_customInitialMiningBeneficiary( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final List
addresses = generateAddresses(4); final Map> transitions = Map.of( diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftDiscardRpcAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftDiscardRpcAcceptanceTest.java index 40d0e881459..0e7484529fe 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftDiscardRpcAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftDiscardRpcAcceptanceTest.java @@ -16,17 +16,16 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; -import org.junit.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class BftDiscardRpcAcceptanceTest extends ParameterizedBftTestBase { - public BftDiscardRpcAcceptanceTest( - final String testName, final BftAcceptanceTestParameterization nodeFactory) { - super(testName, nodeFactory); - } - - @Test - public void shouldDiscardVotes() throws Exception { + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void shouldDiscardVotes( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final String[] validators = {"validator1", "validator3"}; final BesuNode validator1 = nodeFactory.createNodeWithValidators(besu, "validator1", validators); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java index a109a3b8567..71eb3908a7c 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java @@ -28,17 +28,16 @@ import java.util.Optional; import com.fasterxml.jackson.databind.node.ObjectNode; -import org.junit.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class BftMiningAcceptanceTest extends ParameterizedBftTestBase { - public BftMiningAcceptanceTest( - final String testName, final BftAcceptanceTestParameterization nodeFactory) { - super(testName, nodeFactory); - } - - @Test - public void shouldMineOnSingleNodeWithPaidGas_Berlin() throws Exception { + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void shouldMineOnSingleNodeWithPaidGas_Berlin( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final BesuNode minerNode = nodeFactory.createNode(besu, "miner1"); cluster.start(minerNode); @@ -57,8 +56,11 @@ public void shouldMineOnSingleNodeWithPaidGas_Berlin() throws Exception { cluster.verify(receiver.balanceEquals(3)); } - @Test - public void shouldMineOnSingleNodeWithFreeGas_Berlin() throws Exception { + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void shouldMineOnSingleNodeWithFreeGas_Berlin( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final BesuNode minerNode = nodeFactory.createNode(besu, "miner1"); final MiningParameters zeroGasMiningParams = ImmutableMiningParameters.builder() @@ -90,8 +92,11 @@ public void shouldMineOnSingleNodeWithFreeGas_Berlin() throws Exception { cluster.verify(receiver.balanceEquals(3)); } - @Test - public void shouldMineOnSingleNodeWithPaidGas_London() throws Exception { + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void shouldMineOnSingleNodeWithPaidGas_London( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final BesuNode minerNode = nodeFactory.createNode(besu, "miner1"); updateGenesisConfigToLondon(minerNode, false); @@ -115,8 +120,11 @@ public void shouldMineOnSingleNodeWithPaidGas_London() throws Exception { cluster.verify(receiver.balanceEquals(3)); } - @Test - public void shouldMineOnSingleNodeWithFreeGas_London() throws Exception { + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void shouldMineOnSingleNodeWithFreeGas_London( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final BesuNode minerNode = nodeFactory.createNode(besu, "miner1"); updateGenesisConfigToLondon(minerNode, true); @@ -142,8 +150,11 @@ public void shouldMineOnSingleNodeWithFreeGas_London() throws Exception { cluster.verify(receiver.balanceEquals(3)); } - @Test - public void shouldMineOnMultipleNodes() throws Exception { + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void shouldMineOnMultipleNodes( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final BesuNode minerNode1 = nodeFactory.createNode(besu, "miner1"); final BesuNode minerNode2 = nodeFactory.createNode(besu, "miner2"); final BesuNode minerNode3 = nodeFactory.createNode(besu, "miner3"); @@ -168,8 +179,11 @@ public void shouldMineOnMultipleNodes() throws Exception { cluster.verify(receiver.balanceEquals(6)); } - @Test - public void shouldMineOnMultipleNodesEvenWhenClusterContainsNonValidator() throws Exception { + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void shouldMineOnMultipleNodesEvenWhenClusterContainsNonValidator( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final String[] validators = {"validator1", "validator2", "validator3"}; final BesuNode validator1 = nodeFactory.createNodeWithValidators(besu, "validator1", validators); @@ -196,9 +210,11 @@ public void shouldMineOnMultipleNodesEvenWhenClusterContainsNonValidator() throw cluster.verify(receiver.balanceEquals(3)); } - @Test - public void shouldStillMineWhenANonProposerNodeFailsAndHasSufficientValidators() - throws Exception { + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void shouldStillMineWhenANonProposerNodeFailsAndHasSufficientValidators( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final BesuNode minerNode1 = nodeFactory.createNode(besu, "miner1"); final BesuNode minerNode2 = nodeFactory.createNode(besu, "miner2"); final BesuNode minerNode3 = nodeFactory.createNode(besu, "miner3"); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftProposalRpcAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftProposalRpcAcceptanceTest.java index 7fccf33fa27..eecd383003f 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftProposalRpcAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftProposalRpcAcceptanceTest.java @@ -16,17 +16,16 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; -import org.junit.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class BftProposalRpcAcceptanceTest extends ParameterizedBftTestBase { - public BftProposalRpcAcceptanceTest( - final String testName, final BftAcceptanceTestParameterization nodeFactory) { - super(testName, nodeFactory); - } - - @Test - public void shouldReturnProposals() throws Exception { + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void shouldReturnProposals( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final String[] validators = {"validator1", "validator2", "validator3"}; final BesuNode validator1 = nodeFactory.createNodeWithValidators(besu, "validator1", validators); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftProposeRpcAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftProposeRpcAcceptanceTest.java index 7db3d6a5b9f..191884f41a2 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftProposeRpcAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftProposeRpcAcceptanceTest.java @@ -17,19 +17,18 @@ import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; -import org.junit.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; // These tests prove the ibft_proposeValidatorVote and ibft_getValidatorsByBlockNumber (implicitly) // JSON RPC calls. public class BftProposeRpcAcceptanceTest extends ParameterizedBftTestBase { - public BftProposeRpcAcceptanceTest( - final String testName, final BftAcceptanceTestParameterization nodeFactory) { - super(testName, nodeFactory); - } - - @Test - public void validatorsCanBeAddedAndThenRemoved() throws Exception { + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void validatorsCanBeAddedAndThenRemoved( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final String[] validators = {"validator1", "validator2", "validator3"}; final BesuNode validator1 = nodeFactory.createNodeWithValidators(besu, "validator1", validators); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftZeroValidators.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftZeroValidatorsAcceptanceTest.java similarity index 73% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftZeroValidators.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftZeroValidatorsAcceptanceTest.java index 898ad47b3f8..2b107937b88 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftZeroValidators.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftZeroValidatorsAcceptanceTest.java @@ -16,17 +16,16 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; -import org.junit.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; -public class BftZeroValidators extends ParameterizedBftTestBase { +public class BftZeroValidatorsAcceptanceTest extends ParameterizedBftTestBase { - public BftZeroValidators( - final String testName, final BftAcceptanceTestParameterization nodeFactory) { - super(testName, nodeFactory); - } - - @Test - public void zeroValidatorsFormValidCluster() throws Exception { + @ParameterizedTest(name = "{0} bft node factory type") + @MethodSource("factoryFunctions") + public void zeroValidatorsFormValidCluster( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); final String[] validators = {}; final BesuNode node1 = nodeFactory.createNodeWithValidators(besu, "node1", validators); final BesuNode node2 = nodeFactory.createNodeWithValidators(besu, "node2", validators); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/ParameterizedBftTestBase.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/ParameterizedBftTestBase.java index e08d4a5c206..b3d1e321aea 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/ParameterizedBftTestBase.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/ParameterizedBftTestBase.java @@ -14,29 +14,23 @@ */ package org.hyperledger.besu.tests.acceptance.bft; -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5; -import java.util.Collection; +import java.util.stream.Stream; -import org.junit.Ignore; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.params.provider.Arguments; -@RunWith(Parameterized.class) -@Ignore("This is not a test class, it offers BFT parameterization only.") -public abstract class ParameterizedBftTestBase extends AcceptanceTestBase { +@Disabled("This is not a test class, it offers BFT parameterization only.") +public abstract class ParameterizedBftTestBase extends AcceptanceTestBaseJunit5 { + protected String bftType; + protected BftAcceptanceTestParameterization nodeFactory; - protected final String bftType; - protected final BftAcceptanceTestParameterization nodeFactory; - - @Parameters(name = "{0}") - public static Collection factoryFunctions() { + public static Stream factoryFunctions() { return BftAcceptanceTestParameterization.getFactories(); } - protected ParameterizedBftTestBase( - final String bftType, final BftAcceptanceTestParameterization input) { + protected void setUp(final String bftType, final BftAcceptanceTestParameterization input) { this.bftType = bftType; this.nodeFactory = input; } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/ParameterizedPkiQbftTestBase.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/ParameterizedPkiQbftTestBase.java index 29c00b65d96..b1ffcff3712 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/ParameterizedPkiQbftTestBase.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/ParameterizedPkiQbftTestBase.java @@ -14,28 +14,16 @@ */ package org.hyperledger.besu.tests.acceptance.bft.pki; -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5; -import java.util.Collection; +import java.util.stream.Stream; -import org.junit.Ignore; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.params.provider.Arguments; -@RunWith(Parameterized.class) -@Ignore("This is not a test class, it offers PKI QBFT parameterization only.") -public abstract class ParameterizedPkiQbftTestBase extends AcceptanceTestBase { - - protected final PkiQbftAcceptanceTestParameterization nodeFactory; - - @Parameters(name = "{0}") - public static Collection factoryFunctions() { +@Disabled("This is not a test class, it offers PKI QBFT parameterization only.") +public abstract class ParameterizedPkiQbftTestBase extends AcceptanceTestBaseJunit5 { + public static Stream factoryFunctions() { return PkiQbftAcceptanceTestParameterization.getFactories(); } - - protected ParameterizedPkiQbftTestBase( - final String testName, final PkiQbftAcceptanceTestParameterization input) { - this.nodeFactory = input; - } } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTest.java index 8fecb5f6779..12ae887a510 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTest.java @@ -20,17 +20,16 @@ import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; -import org.junit.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class PkiQbftAcceptanceTest extends ParameterizedPkiQbftTestBase { - public PkiQbftAcceptanceTest( - final String testName, final PkiQbftAcceptanceTestParameterization input) { - super(testName, input); - } - - @Test - public void shouldMineOnSingleNode() throws Exception { + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void shouldMineOnSingleNode( + final String testName, final PkiQbftAcceptanceTestParameterization nodeFactory) + throws Exception { final BesuNode minerNode = nodeFactory.createNode(besu, "miner1"); cluster.start(minerNode); @@ -49,8 +48,11 @@ public void shouldMineOnSingleNode() throws Exception { cluster.verify(receiver.balanceEquals(3)); } - @Test - public void shouldMineOnMultipleNodes() throws Exception { + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void shouldMineOnMultipleNodes( + final String testName, final PkiQbftAcceptanceTestParameterization nodeFactory) + throws Exception { final BesuNode minerNode1 = nodeFactory.createNode(besu, "miner1"); final BesuNode minerNode2 = nodeFactory.createNode(besu, "miner2"); final BesuNode minerNode3 = nodeFactory.createNode(besu, "miner3"); @@ -75,8 +77,11 @@ public void shouldMineOnMultipleNodes() throws Exception { cluster.verify(receiver.balanceEquals(6)); } - @Test - public void shouldMineWithIgnoringANodeInCRL() throws Exception { + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void shouldMineWithIgnoringANodeInCRL( + final String testName, final PkiQbftAcceptanceTestParameterization nodeFactory) + throws Exception { final BesuNode minerNode1 = nodeFactory.createNode(besu, "miner1"); final BesuNode minerNode2 = nodeFactory.createNode(besu, "miner2"); final BesuNode minerNode3 = nodeFactory.createNode(besu, "miner3"); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java index 10d4866fef7..7bcf09afd38 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java @@ -22,73 +22,70 @@ import java.util.ArrayList; import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.params.provider.Arguments; public class PkiQbftAcceptanceTestParameterization { - public static List getFactories() { - final List ret = new ArrayList<>(); + public static Stream getFactories() { + List args = new ArrayList<>(); /* BLOCK CREATION */ - ret.add( - new Object[] { - "qbft-pki-jks", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createPkiQbftJKSNode, - BesuNodeFactory::createPkiQbftJKSNodeWithValidators) - }); - - ret.add( - new Object[] { - "qbft-pki-pkcs12", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createPkiQbftPKCS12Node, - BesuNodeFactory::createPkiQbftPKCS12NodeWithValidators) - }); + args.add( + Arguments.of( + "qbft-pki-jks", + new PkiQbftAcceptanceTestParameterization( + BesuNodeFactory::createPkiQbftJKSNode, + BesuNodeFactory::createPkiQbftJKSNodeWithValidators))); - if (Boolean.getBoolean("acctests.runBesuAsProcess")) { - ret.add( - new Object[] { - "qbft-pki-pkcs11", + args.add( + Arguments.of( + "qbft-pki-pkcs12", new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createPkiQbftPKCS11Node, - BesuNodeFactory::createPkiQbftPKCS11NodeWithValidators) - }); + BesuNodeFactory::createPkiQbftPKCS12Node, + BesuNodeFactory::createPkiQbftPKCS12NodeWithValidators))); + + if (Boolean.getBoolean("acctests.runBesuAsProcess")) { + args.add( + Arguments.of( + "qbft-pki-pkcs11", + new PkiQbftAcceptanceTestParameterization( + BesuNodeFactory::createPkiQbftPKCS11Node, + BesuNodeFactory::createPkiQbftPKCS11NodeWithValidators))); } /* TLS */ - ret.add( - new Object[] { - "qbft-tls-jks", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createQbftNodeWithTLSJKS, - BesuNodeFactory::createQbftTLSJKSNodeWithValidators) - }); - - ret.add( - new Object[] { - "qbft-tls-pkcs12", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createQbftNodeWithTLSPKCS12, - BesuNodeFactory::createQbftTLSPKCS12NodeWithValidators) - }); + args.add( + Arguments.of( + "qbft-tls-jks", + new PkiQbftAcceptanceTestParameterization( + BesuNodeFactory::createQbftNodeWithTLSJKS, + BesuNodeFactory::createQbftTLSJKSNodeWithValidators))); - if (Boolean.getBoolean("acctests.runBesuAsProcess")) { - ret.add( - new Object[] { - "qbft-tls-pkcs11", + args.add( + Arguments.of( + "qbft-tls-pkcs12", new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createQbftNodeWithTLSPKCS11, - BesuNodeFactory::createQbftTLSPKCS11NodeWithValidators) - }); + BesuNodeFactory::createQbftNodeWithTLSPKCS12, + BesuNodeFactory::createQbftTLSPKCS12NodeWithValidators))); + + if (Boolean.getBoolean("acctests.runBesuAsProcess")) { + args.add( + Arguments.of( + "qbft-tls-pkcs11", + new PkiQbftAcceptanceTestParameterization( + BesuNodeFactory::createQbftNodeWithTLSPKCS11, + BesuNodeFactory::createQbftTLSPKCS11NodeWithValidators))); } - return ret; + return args.stream(); } @FunctionalInterface diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/qbft/QbftContractAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/qbft/QbftContractAcceptanceTest.java index e3b2878b052..51500bb1490 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/qbft/QbftContractAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/qbft/QbftContractAcceptanceTest.java @@ -14,13 +14,13 @@ */ package org.hyperledger.besu.tests.acceptance.bft.qbft; -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class QbftContractAcceptanceTest extends AcceptanceTestBase { +public class QbftContractAcceptanceTest extends AcceptanceTestBaseJunit5 { @Test public void shouldMineOnMultipleNodesEvenWhenClusterContainsNonValidator() throws Exception { diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueDiscardRpcAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueDiscardRpcAcceptanceTest.java index 9dbf376aac5..6ea274b6991 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueDiscardRpcAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueDiscardRpcAcceptanceTest.java @@ -14,14 +14,14 @@ */ package org.hyperledger.besu.tests.acceptance.clique; -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import java.io.IOException; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class CliqueDiscardRpcAcceptanceTest extends AcceptanceTestBase { +public class CliqueDiscardRpcAcceptanceTest extends AcceptanceTestBaseJunit5 { @Test public void shouldDiscardVotes() throws IOException { diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueGetSignersRpcTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueGetSignersRpcAcceptanceTest.java similarity index 88% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueGetSignersRpcTest.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueGetSignersRpcAcceptanceTest.java index 92987595dfd..ba848b0052c 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueGetSignersRpcTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueGetSignersRpcAcceptanceTest.java @@ -16,19 +16,19 @@ import static org.hyperledger.besu.tests.acceptance.dsl.transaction.clique.CliqueTransactions.LATEST; -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; -@Ignore -public class CliqueGetSignersRpcTest extends AcceptanceTestBase { +@Disabled("flaky test due to hardcoded block numbers") +public class CliqueGetSignersRpcAcceptanceTest extends AcceptanceTestBaseJunit5 { private BesuNode minerNode1; private BesuNode minerNode2; - @Before + @BeforeEach public void setUp() throws Exception { final String[] validators = {"miner1"}; minerNode1 = besu.createCliqueNodeWithValidators("miner1", validators); diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueMiningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueMiningAcceptanceTest.java index 4ac728dec73..c2048c61d9c 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueMiningAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueMiningAcceptanceTest.java @@ -14,16 +14,16 @@ */ package org.hyperledger.besu.tests.acceptance.clique; -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory.CliqueOptions; import java.io.IOException; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class CliqueMiningAcceptanceTest extends AcceptanceTestBase { +public class CliqueMiningAcceptanceTest extends AcceptanceTestBaseJunit5 { @Test public void shouldMineTransactionsOnSingleNode() throws IOException { diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueProposalRpcAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueProposalRpcAcceptanceTest.java index 65340c57d27..a7e8ebb9c9c 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueProposalRpcAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueProposalRpcAcceptanceTest.java @@ -14,14 +14,14 @@ */ package org.hyperledger.besu.tests.acceptance.clique; -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import java.io.IOException; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class CliqueProposalRpcAcceptanceTest extends AcceptanceTestBase { +public class CliqueProposalRpcAcceptanceTest extends AcceptanceTestBaseJunit5 { @Test public void shouldReturnProposals() throws IOException { diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueProposeRpcAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueProposeRpcAcceptanceTest.java index 4767f6267b8..d4fb71c36b4 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueProposeRpcAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueProposeRpcAcceptanceTest.java @@ -14,16 +14,16 @@ */ package org.hyperledger.besu.tests.acceptance.clique; -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.condition.clique.ExpectNonceVote.CLIQUE_NONCE_VOTE; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import java.io.IOException; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class CliqueProposeRpcAcceptanceTest extends AcceptanceTestBase { +public class CliqueProposeRpcAcceptanceTest extends AcceptanceTestBaseJunit5 { @Test public void shouldAddValidators() throws IOException { diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueZeroValidators.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueZeroValidatorsAcceptanceTest.java similarity index 90% rename from acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueZeroValidators.java rename to acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueZeroValidatorsAcceptanceTest.java index 3f8ed7b5e9c..b0c6afd93fc 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueZeroValidators.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueZeroValidatorsAcceptanceTest.java @@ -14,14 +14,14 @@ */ package org.hyperledger.besu.tests.acceptance.clique; -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import java.io.IOException; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class CliqueZeroValidators extends AcceptanceTestBase { +public class CliqueZeroValidatorsAcceptanceTest extends AcceptanceTestBaseJunit5 { @Test public void zeroValidatorsFormValidCluster() throws IOException { diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BadCLIOptionsPluginTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BadCLIOptionsPluginTest.java index 02299f4fdb8..9cee5dde6e7 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BadCLIOptionsPluginTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BadCLIOptionsPluginTest.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import java.io.File; @@ -33,7 +33,7 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -public class BadCLIOptionsPluginTest extends AcceptanceTestBase { +public class BadCLIOptionsPluginTest extends AcceptanceTestBaseJunit5 { private BesuNode node; @BeforeEach diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BesuEventsPluginTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BesuEventsPluginTest.java index 4906193362c..a35309ef6f0 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BesuEventsPluginTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BesuEventsPluginTest.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.tests.acceptance.plugins; -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; import java.io.File; @@ -28,7 +28,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class BesuEventsPluginTest extends AcceptanceTestBase { +public class BesuEventsPluginTest extends AcceptanceTestBaseJunit5 { private BesuNode pluginNode; private BesuNode minerNode; diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/PermissioningPluginTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/PermissioningPluginTest.java index af6a3f7a16f..146110237da 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/PermissioningPluginTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/PermissioningPluginTest.java @@ -16,7 +16,7 @@ package org.hyperledger.besu.tests.acceptance.plugins; import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; @@ -28,7 +28,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class PermissioningPluginTest extends AcceptanceTestBase { +public class PermissioningPluginTest extends AcceptanceTestBaseJunit5 { private BesuNode minerNode; private BesuNode aliceNode; diff --git a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java index d75d119cdea..bb3172b7dee 100644 --- a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java @@ -608,6 +608,8 @@ public Runner build() { bootstrap = ethNetworkConfig.getBootNodes(); } discoveryConfiguration.setBootnodes(bootstrap); + LOG.info("Resolved {} bootnodes.", bootstrap.size()); + LOG.debug("Bootnodes = {}", bootstrap); discoveryConfiguration.setDnsDiscoveryURL(ethNetworkConfig.getDnsDiscoveryUrl()); discoveryConfiguration.setDiscoveryV5Enabled( networkingConfiguration.getDiscovery().isDiscoveryV5Enabled()); 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 48dbe52da23..9fa41f31354 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -1438,7 +1438,6 @@ public void run() { if (network != null && network.isDeprecated()) { logger.warn(NetworkDeprecationMessage.generate(network)); } - try { configureLogging(true); @@ -3121,14 +3120,9 @@ private EthNetworkConfig updateNetworkConfig(final NetworkName network) { if (listBootNodes != null) { if (!p2PDiscoveryOptionGroup.peerDiscoveryEnabled) { logger.warn("Discovery disabled: bootnodes will be ignored."); - } else { - logger.info("Configured {} bootnodes.", listBootNodes.size()); - logger.debug("Bootnodes = {}", listBootNodes); } DiscoveryConfiguration.assertValidBootnodes(listBootNodes); builder.setBootNodes(listBootNodes); - } else { - logger.info("0 Bootnodes configured"); } return builder.build(); } diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthEstimateGasIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthEstimateGasIntegrationTest.java index 5bc57774c2b..8717fe05600 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthEstimateGasIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthEstimateGasIntegrationTest.java @@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallParameter; +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; @@ -161,8 +162,12 @@ public void shouldNotIgnoreSenderBalanceAccountWhenStrictModeDisabledAndThrowErr true, null); final JsonRpcRequestContext request = requestWithParams(callParameter); - final JsonRpcResponse expectedResponse = - new JsonRpcErrorResponse(null, RpcErrorType.TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE); + + final RpcErrorType rpcErrorType = RpcErrorType.TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE; + final JsonRpcError rpcError = new JsonRpcError(rpcErrorType); + rpcError.setReason( + "transaction up-front cost 0x1cc31b3333167018 exceeds transaction sender account balance 0x140"); + final JsonRpcResponse expectedResponse = new JsonRpcErrorResponse(null, rpcError); final JsonRpcResponse response = method.response(request); assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcErrorConverter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcErrorConverter.java index 89107497d51..202759c18e7 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcErrorConverter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcErrorConverter.java @@ -79,6 +79,8 @@ public static RpcErrorType convertTransactionInvalidReason( return RpcErrorType.PLUGIN_TX_VALIDATOR; case INVALID_BLOBS: return RpcErrorType.INVALID_BLOBS; + case EXECUTION_HALTED: + return RpcErrorType.EXECUTION_HALTED; default: return RpcErrorType.INTERNAL_ERROR; } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractEstimateGas.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractEstimateGas.java index ddfd522c8f7..b3de5094c8f 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractEstimateGas.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractEstimateGas.java @@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; +import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; @@ -48,8 +49,16 @@ public AbstractEstimateGas( } protected BlockHeader blockHeader() { - final long headBlockNumber = blockchainQueries.headBlockNumber(); - return blockchainQueries.getBlockchain().getBlockHeader(headBlockNumber).orElse(null); + final Blockchain theChain = blockchainQueries.getBlockchain(); + + // Optimistically get the block header for the chain head without taking a lock, + // but revert to the safe implementation if it returns an empty optional. (It's + // possible the chain head has been updated but the block is still being persisted + // to storage/cache under the lock). + return theChain + .getBlockHeader(theChain.getChainHeadHash()) + .or(() -> theChain.getBlockHeaderSafe(theChain.getChainHeadHash())) + .orElse(null); } protected CallParameter overrideGasLimitAndPrice( @@ -101,6 +110,14 @@ protected JsonRpcErrorResponse errorResponse( final ValidationResult validationResult = result.getValidationResult(); if (validationResult != null && !validationResult.isValid()) { + if (validationResult.getErrorMessage().length() > 0) { + final RpcErrorType rpcErrorType = + JsonRpcErrorConverter.convertTransactionInvalidReason( + validationResult.getInvalidReason()); + final JsonRpcError rpcError = new JsonRpcError(rpcErrorType); + rpcError.setReason(validationResult.getErrorMessage()); + return errorResponse(request, rpcError); + } return errorResponse( request, JsonRpcErrorConverter.convertTransactionInvalidReason( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGas.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGas.java index ea69ad9d381..9a382d6441b 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGas.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGas.java @@ -32,8 +32,13 @@ import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class EthEstimateGas extends AbstractEstimateGas { + private static final Logger LOG = LoggerFactory.getLogger(EthEstimateGas.class); + public EthEstimateGas( final BlockchainQueries blockchainQueries, final TransactionSimulator transactionSimulator) { super(blockchainQueries, transactionSimulator); @@ -50,6 +55,7 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { final BlockHeader blockHeader = blockHeader(); if (blockHeader == null) { + LOG.error("Chain head block not found"); return errorResponse(requestContext, RpcErrorType.INTERNAL_ERROR); } if (!blockchainQueries @@ -70,6 +76,7 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { blockHeader, modifiedCallParams, operationTracer, isAllowExceedingBalance); if (gasUsed.isEmpty()) { + LOG.error("gasUsed is empty after simulating transaction."); return errorResponse(requestContext, RpcErrorType.INTERNAL_ERROR); } 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 73c8a20519f..a3a3427de2b 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 @@ -73,6 +73,10 @@ public String getData() { return data; } + public void setReason(final String reason) { + this.reason = reason; + } + @Override public boolean equals(final Object o) { if (this == o) { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/RpcErrorType.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/RpcErrorType.java index f025b4177a1..7e49ed9387e 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/RpcErrorType.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/RpcErrorType.java @@ -75,6 +75,7 @@ public enum RpcErrorType { -32000, "An invalid transaction with a lower nonce exists"), TOTAL_BLOB_GAS_TOO_HIGH(-32000, "Total blob gas too high"), PLUGIN_TX_VALIDATOR(-32000, "Plugin has marked the transaction as invalid"), + EXECUTION_HALTED(-32000, "Transaction processing could not be completed due to an exception"), // Execution engine failures UNKNOWN_PAYLOAD(-32001, "Payload does not exist / is not available"), diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessListTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessListTest.java index ec74d82991a..674617b4b57 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessListTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessListTest.java @@ -17,7 +17,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -25,6 +24,7 @@ import org.hyperledger.besu.datatypes.AccessListEntry; import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; @@ -78,10 +78,16 @@ public class EthCreateAccessListTest { @BeforeEach public void setUp() { - when(blockchainQueries.headBlockNumber()).thenReturn(1L); when(blockchainQueries.getBlockchain()).thenReturn(blockchain); when(blockchainQueries.getWorldStateArchive()).thenReturn(worldStateArchive); - when(blockchain.getBlockHeader(eq(1L))).thenReturn(Optional.of(blockHeader)); + when(blockchain.getChainHeadHash()) + .thenReturn( + Hash.fromHexString( + "0x3f07a9c83155594c000642e7d60e8a8a00038d03e9849171a05ed0e2d47acbb3")); + when(blockchain.getBlockHeader( + Hash.fromHexString( + "0x3f07a9c83155594c000642e7d60e8a8a00038d03e9849171a05ed0e2d47acbb3"))) + .thenReturn(Optional.of(blockHeader)); when(blockHeader.getGasLimit()).thenReturn(Long.MAX_VALUE); when(blockHeader.getNumber()).thenReturn(1L); when(worldStateArchive.isWorldStateAvailable(any(), any())).thenReturn(true); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGasTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGasTest.java index 6f1d748030f..44b3bb9ba04 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGasTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGasTest.java @@ -22,6 +22,7 @@ import static org.mockito.Mockito.when; import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; @@ -73,10 +74,16 @@ public class EthEstimateGasTest { @BeforeEach public void setUp() { - when(blockchainQueries.headBlockNumber()).thenReturn(1L); when(blockchainQueries.getBlockchain()).thenReturn(blockchain); when(blockchainQueries.getWorldStateArchive()).thenReturn(worldStateArchive); - when(blockchain.getBlockHeader(eq(1L))).thenReturn(Optional.of(blockHeader)); + when(blockchain.getChainHeadHash()) + .thenReturn( + Hash.fromHexString( + "0x3f07a9c83155594c000642e7d60e8a8a00038d03e9849171a05ed0e2d47acbb3")); + when(blockchain.getBlockHeader( + Hash.fromHexString( + "0x3f07a9c83155594c000642e7d60e8a8a00038d03e9849171a05ed0e2d47acbb3"))) + .thenReturn(Optional.of(blockHeader)); when(blockHeader.getGasLimit()).thenReturn(Long.MAX_VALUE); when(blockHeader.getNumber()).thenReturn(1L); when(worldStateArchive.isWorldStateAvailable(any(), any())).thenReturn(true); @@ -209,10 +216,13 @@ public void shouldReturnErrorWhenLegacyTransactionProcessorReturnsTxInvalidReaso final JsonRpcRequestContext request = ethEstimateGasRequest(defaultLegacyTransactionCallParameter(Wei.ZERO)); mockTransientProcessorResultTxInvalidReason( - TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE); + TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE, + "transaction up-front cost 10 exceeds transaction sender account balance 5"); - final JsonRpcResponse expectedResponse = - new JsonRpcErrorResponse(null, RpcErrorType.TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE); + final RpcErrorType rpcErrorType = RpcErrorType.TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE; + final JsonRpcError rpcError = new JsonRpcError(rpcErrorType); + rpcError.setReason("transaction up-front cost 10 exceeds transaction sender account balance 5"); + final JsonRpcResponse expectedResponse = new JsonRpcErrorResponse(null, rpcError); Assertions.assertThat(method.response(request)) .usingRecursiveComparison() @@ -223,10 +233,13 @@ public void shouldReturnErrorWhenLegacyTransactionProcessorReturnsTxInvalidReaso public void shouldReturnErrorWhenEip1559TransactionProcessorReturnsTxInvalidReason() { final JsonRpcRequestContext request = ethEstimateGasRequest(eip1559TransactionCallParameter()); mockTransientProcessorResultTxInvalidReason( - TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE); + TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE, + "transaction up-front cost 10 exceeds transaction sender account balance 5"); - final JsonRpcResponse expectedResponse = - new JsonRpcErrorResponse(null, RpcErrorType.TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE); + final RpcErrorType rpcErrorType = RpcErrorType.TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE; + final JsonRpcError rpcError = new JsonRpcError(rpcErrorType); + rpcError.setReason("transaction up-front cost 10 exceeds transaction sender account balance 5"); + final JsonRpcResponse expectedResponse = new JsonRpcErrorResponse(null, rpcError); Assertions.assertThat(method.response(request)) .usingRecursiveComparison() @@ -243,9 +256,9 @@ public void shouldReturnErrorWhenWorldStateIsNotAvailable() { final JsonRpcResponse expectedResponse = new JsonRpcErrorResponse(null, RpcErrorType.WORLD_STATE_UNAVAILABLE); - Assertions.assertThat(method.response(request)) - .usingRecursiveComparison() - .isEqualTo(expectedResponse); + JsonRpcResponse theResponse = method.response(request); + + Assertions.assertThat(theResponse).usingRecursiveComparison().isEqualTo(expectedResponse); } @Test @@ -364,10 +377,32 @@ public void shouldNotIgnoreSenderBalanceAccountWhenStrictModeDisabled() { eq(1L)); } - private void mockTransientProcessorResultTxInvalidReason(final TransactionInvalidReason reason) { + @Test + public void shouldIncludeHaltReasonWhenExecutionHalts() { + final JsonRpcRequestContext request = + ethEstimateGasRequest(defaultLegacyTransactionCallParameter(Wei.ZERO)); + mockTransientProcessorResultTxInvalidReason( + TransactionInvalidReason.EXECUTION_HALTED, "INVALID_OPERATION"); + + final RpcErrorType rpcErrorType = RpcErrorType.EXECUTION_HALTED; + final JsonRpcError rpcError = new JsonRpcError(rpcErrorType); + rpcError.setReason("INVALID_OPERATION"); + final JsonRpcResponse expectedResponse = new JsonRpcErrorResponse(null, rpcError); + + Assertions.assertThat(method.response(request)) + .usingRecursiveComparison() + .isEqualTo(expectedResponse); + } + + private void mockTransientProcessorResultTxInvalidReason( + final TransactionInvalidReason reason, final String validationFailedErrorMessage) { final TransactionSimulatorResult mockTxSimResult = getMockTransactionSimulatorResult(false, 0, Wei.ZERO, Optional.empty()); - when(mockTxSimResult.getValidationResult()).thenReturn(ValidationResult.invalid(reason)); + when(mockTxSimResult.getValidationResult()) + .thenReturn( + validationFailedErrorMessage == null + ? ValidationResult.invalid(reason) + : ValidationResult.invalid(reason, validationFailedErrorMessage)); } private void mockTransientProcessorTxReverted( diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_estimateGas_invalid.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_estimateGas_invalid.json index 21f5ffb3bcb..7c78f47000f 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_estimateGas_invalid.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_estimateGas_invalid.json @@ -14,8 +14,8 @@ "jsonrpc": "2.0", "id": 3, "error": { - "code": -32603, - "message": "Internal error" + "code": -32000, + "message": "Transaction processing could not be completed due to an exception: INVALID_OPERATION" } }, "statusCode": 200 diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java index 876fa65d298..931388b3878 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java @@ -426,6 +426,13 @@ public TransactionProcessingResult processTransaction( if (initialFrame.getState() == MessageFrame.State.COMPLETED_SUCCESS) { worldUpdater.commit(); + } else { + if (initialFrame.getExceptionalHaltReason().isPresent()) { + validationResult = + ValidationResult.invalid( + TransactionInvalidReason.EXECUTION_HALTED, + initialFrame.getExceptionalHaltReason().get().toString()); + } } if (LOG.isTraceEnabled()) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionInvalidReason.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionInvalidReason.java index 780020162ea..d3348599c1e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionInvalidReason.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionInvalidReason.java @@ -50,6 +50,7 @@ public enum TransactionInvalidReason { TX_POOL_DISABLED, INVALID_BLOBS, PLUGIN_TX_VALIDATOR, + EXECUTION_HALTED, // Private Transaction Invalid Reasons PRIVATE_TRANSACTION_INVALID, PRIVATE_TRANSACTION_FAILED, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/worldview/BonsaiWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/worldview/BonsaiWorldState.java index 323a9e510e5..129e3f291f0 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/worldview/BonsaiWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/worldview/BonsaiWorldState.java @@ -340,60 +340,55 @@ private void updateAccountStorageState( private void clearStorage( final Optional maybeStateUpdater, final BonsaiWorldStateUpdateAccumulator worldStateUpdater) { - - maybeStateUpdater.ifPresent( - bonsaiUpdater -> { - for (final Address address : worldStateUpdater.getStorageToClear()) { - // because we are clearing persisted values we need the account root as persisted - final BonsaiAccount oldAccount = - worldStateStorage - .getAccount(address.addressHash()) - .map( - bytes -> BonsaiAccount.fromRLP(BonsaiWorldState.this, address, bytes, true)) - .orElse(null); - if (oldAccount == null) { - // This is when an account is both created and deleted within the scope of the same - // block. A not-uncommon DeFi bot pattern. - continue; - } - final Hash addressHash = address.addressHash(); - final MerkleTrie storageTrie = - createTrie( - (location, key) -> getStorageTrieNode(addressHash, location, key), - oldAccount.getStorageRoot()); - try { - - final StorageConsumingMap> storageToDelete = - worldStateUpdater.getStorageToUpdate().get(address); - Map entriesToDelete = storageTrie.entriesFrom(Bytes32.ZERO, 256); - while (!entriesToDelete.isEmpty()) { - entriesToDelete.forEach( - (k, v) -> { - final StorageSlotKey storageSlotKey = - new StorageSlotKey(Hash.wrap(k), Optional.empty()); - final UInt256 slotValue = - UInt256.fromBytes(Bytes32.leftPad(RLP.decodeValue(v))); - bonsaiUpdater.removeStorageValueBySlotHash( - address.addressHash(), storageSlotKey.getSlotHash()); - storageToDelete - .computeIfAbsent( - storageSlotKey, key -> new BonsaiValue<>(slotValue, null, true)) - .setPrior(slotValue); - }); - entriesToDelete.keySet().forEach(storageTrie::remove); - if (entriesToDelete.size() == 256) { - entriesToDelete = storageTrie.entriesFrom(Bytes32.ZERO, 256); - } else { - break; - } - } - } catch (MerkleTrieException e) { - // need to throw to trigger the heal - throw new MerkleTrieException( - e.getMessage(), Optional.of(Address.wrap(address)), e.getHash(), e.getLocation()); - } + for (final Address address : worldStateUpdater.getStorageToClear()) { + // because we are clearing persisted values we need the account root as persisted + final BonsaiAccount oldAccount = + worldStateStorage + .getAccount(address.addressHash()) + .map(bytes -> BonsaiAccount.fromRLP(BonsaiWorldState.this, address, bytes, true)) + .orElse(null); + if (oldAccount == null) { + // This is when an account is both created and deleted within the scope of the same + // block. A not-uncommon DeFi bot pattern. + continue; + } + final Hash addressHash = address.addressHash(); + final MerkleTrie storageTrie = + createTrie( + (location, key) -> getStorageTrieNode(addressHash, location, key), + oldAccount.getStorageRoot()); + try { + final StorageConsumingMap> storageToDelete = + worldStateUpdater.getStorageToUpdate().get(address); + Map entriesToDelete = storageTrie.entriesFrom(Bytes32.ZERO, 256); + while (!entriesToDelete.isEmpty()) { + entriesToDelete.forEach( + (k, v) -> { + final StorageSlotKey storageSlotKey = + new StorageSlotKey(Hash.wrap(k), Optional.empty()); + final UInt256 slotValue = UInt256.fromBytes(Bytes32.leftPad(RLP.decodeValue(v))); + maybeStateUpdater.ifPresent( + bonsaiUpdater -> + bonsaiUpdater.removeStorageValueBySlotHash( + address.addressHash(), storageSlotKey.getSlotHash())); + storageToDelete + .computeIfAbsent( + storageSlotKey, key -> new BonsaiValue<>(slotValue, null, true)) + .setPrior(slotValue); + }); + entriesToDelete.keySet().forEach(storageTrie::remove); + if (entriesToDelete.size() == 256) { + entriesToDelete = storageTrie.entriesFrom(Bytes32.ZERO, 256); + } else { + break; } - }); + } + } catch (MerkleTrieException e) { + // need to throw to trigger the heal + throw new MerkleTrieException( + e.getMessage(), Optional.of(Address.wrap(address)), e.getHash(), e.getLocation()); + } + } } @Override diff --git a/evm/src/main/java/org/hyperledger/besu/evm/EvmSpecVersion.java b/evm/src/main/java/org/hyperledger/besu/evm/EvmSpecVersion.java index 803fcae5b60..76961c56500 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/EvmSpecVersion.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/EvmSpecVersion.java @@ -48,7 +48,7 @@ public enum EvmSpecVersion { /** Shanghai evm spec version. */ SHANGHAI(0, true, "Shanghai", "Finalized"), /** Cancun evm spec version. */ - CANCUN(0, false, "Cancun", "In Development"), + CANCUN(0, true, "Cancun", "Finalized"), /** Prague evm spec version. */ PRAGUE(0, false, "Prague", "Placeholder"), /** Osaka evm spec version. */ diff --git a/evm/src/test/java/org/hyperledger/besu/evm/fluent/EVMExecutorTest.java b/evm/src/test/java/org/hyperledger/besu/evm/fluent/EVMExecutorTest.java index 176f0070980..9356ab8bec4 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/fluent/EVMExecutorTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/fluent/EVMExecutorTest.java @@ -50,7 +50,7 @@ class EVMExecutorTest { @Test void currentEVM() { var subject = EVMExecutor.evm(); - assertThat(subject.getEVMVersion()).isEqualTo(EvmSpecVersion.SHANGHAI); + assertThat(subject.getEVMVersion()).isEqualTo(EvmSpecVersion.CANCUN); } @ParameterizedTest diff --git a/gradle.properties b/gradle.properties index 4cb4c57da2c..98a6a7c73f0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=23.10.4-SNAPSHOT +version=24.1.0-SNAPSHOT dockerOrgName=consensys dockerArtifactName=linea-besu dockerVariants=openjdk-17 @@ -20,4 +20,4 @@ org.gradle.jvmargs=-Xmx4g \ # Could be moved to sonar properties after https://sonarsource.atlassian.net/browse/SONARGRADL-134 systemProp.sonar.gradle.skipCompile=true -besu.run.args="--network=linea" \ No newline at end of file +besu.run.args="--network=linea" 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 952da71f0bc..c6157217e3d 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 @@ -77,6 +77,11 @@ public abstract class RocksDBColumnarKeyValueStorage implements SegmentedKeyValu protected static final long ROCKSDB_BLOCKCACHE_SIZE_HIGH_SPEC = 1_073_741_824L; /** RocksDb memtable size when using the high spec option */ protected static final long ROCKSDB_MEMTABLE_SIZE_HIGH_SPEC = 1_073_741_824L; + /** Max total size of all WAL file, after which a flush is triggered */ + protected static final long WAL_MAX_TOTAL_SIZE = 1_073_741_824L; + /** Expected size of a single WAL file, to determine how many WAL files to keep around */ + protected static final long EXPECTED_WAL_FILE_SIZE = 67_108_864L; + /** RocksDb number of log files to keep on disk */ private static final long NUMBER_OF_LOG_FILES_TO_KEEP = 7; /** RocksDb Time to roll a log file (1 day = 3600 * 24 seconds) */ @@ -237,6 +242,8 @@ private void setGlobalOptions(final RocksDBConfiguration configuration, final St options .setCreateIfMissing(true) .setMaxOpenFiles(configuration.getMaxOpenFiles()) + .setMaxTotalWalSize(WAL_MAX_TOTAL_SIZE) + .setRecycleLogFileNum(WAL_MAX_TOTAL_SIZE / EXPECTED_WAL_FILE_SIZE) .setStatistics(stats) .setCreateMissingColumnFamilies(true) .setLogFileTimeToRoll(TIME_TO_ROLL_LOG_FILE)