From 46e74d1949170eeb8b986994f8ca90bc8ed0fe65 Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Thu, 13 Feb 2025 23:33:14 +0100 Subject: [PATCH] Stop all sub processes spawn by acceptance tests (#8284) * Stop all sub processes spawn by acceptance tests Signed-off-by: Fabio Di Fabio * Reduce memory used by Gradle Signed-off-by: Fabio Di Fabio --------- Signed-off-by: Fabio Di Fabio --- .github/workflows/acceptance-tests.yml | 4 +- .../tests/acceptance/dsl/node/BesuNode.java | 14 + .../dsl/node/ProcessBesuNodeRunner.java | 9 +- .../bft/BftMiningAcceptanceTest.java | 290 ------------------ .../bft/BftMiningAcceptanceTest_Part1.java | 117 +++++++ .../bft/BftMiningAcceptanceTest_Part2.java | 114 +++++++ .../bft/BftMiningAcceptanceTest_Part3.java | 81 +++++ .../bft/ParameterizedBftTestBase.java | 29 ++ 8 files changed, 363 insertions(+), 295 deletions(-) delete mode 100644 acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java create mode 100644 acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest_Part1.java create mode 100644 acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest_Part2.java create mode 100644 acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest_Part3.java diff --git a/.github/workflows/acceptance-tests.yml b/.github/workflows/acceptance-tests.yml index 94c6d0b84..47da30e0c 100644 --- a/.github/workflows/acceptance-tests.yml +++ b/.github/workflows/acceptance-tests.yml @@ -12,7 +12,7 @@ concurrency: cancel-in-progress: true env: - GRADLE_OPTS: "-Xmx7g" + GRADLE_OPTS: "-Xmx1g" total-runners: 14 jobs: @@ -78,7 +78,7 @@ jobs: name: test-args-${{ matrix.runner_index }}.txt path: '*.txt' - name: run acceptance tests - run: ./gradlew acceptanceTestNotPrivacy `cat gradleArgs.txt` -Dorg.gradle.parallel=true -Dorg.gradle.caching=true + run: ./gradlew --max-workers 1 acceptanceTestNotPrivacy `cat gradleArgs.txt` -Dorg.gradle.caching=true - name: Remove downloaded test results run: rm -rf tmp/junit-xml-reports-downloaded - name: Upload Acceptance Test Results diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java index 0724ee51a..17c64b4bb 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java @@ -790,6 +790,20 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable nodeRequests.shutdown(); nodeRequests = null; } + deleteRuntimeFiles(); + } + + private void deleteRuntimeFiles() { + try { + Files.deleteIfExists(homeDirectory.resolve("besu.networks")); + } catch (IOException e) { + LOG.error("Failed to clean up besu.networks file in {}", homeDirectory, e); + } + try { + Files.deleteIfExists(homeDirectory.resolve("besu.ports")); + } catch (IOException e) { + LOG.error("Failed to clean up besu.ports file in {}", homeDirectory, e); + } } @Override diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java index 33a9a1cfb..2aa1d3e81 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java @@ -529,9 +529,12 @@ public class ProcessBesuNodeRunner implements BesuNodeRunner { return; } - LOG.info("Killing {} process, pid {}", name, process.pid()); - - process.destroy(); + process + .descendants() + .peek( + processHandle -> + LOG.info("Killing {} process, pid {}", processHandle.info(), processHandle.pid())) + .forEach(ProcessHandle::destroy); try { process.waitFor(30, TimeUnit.SECONDS); } catch (final InterruptedException e) { 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 deleted file mode 100644 index 177987aaa..000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.bft; - -import org.hyperledger.besu.config.JsonUtil; -import org.hyperledger.besu.datatypes.Wei; -import org.hyperledger.besu.ethereum.core.AddressHelpers; -import org.hyperledger.besu.ethereum.core.ImmutableMiningConfiguration; -import org.hyperledger.besu.ethereum.core.ImmutableMiningConfiguration.MutableInitValues; -import org.hyperledger.besu.ethereum.core.MiningConfiguration; -import org.hyperledger.besu.tests.acceptance.dsl.account.Account; -import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; - -import java.util.List; -import java.util.Optional; - -import com.fasterxml.jackson.databind.node.ObjectNode; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -public class BftMiningAcceptanceTest extends ParameterizedBftTestBase { - - @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); - - cluster.verify(blockchain.reachesHeight(minerNode, 1)); - - final Account sender = accounts.createAccount("account1"); - final Account receiver = accounts.createAccount("account2"); - - minerNode.execute(accountTransactions.createTransfer(sender, 50)); - cluster.verify(sender.balanceEquals(50)); - - minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); - cluster.verify(receiver.balanceEquals(1)); - - minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); - cluster.verify(receiver.balanceEquals(3)); - } - - @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 MiningConfiguration zeroGasMiningParams = - ImmutableMiningConfiguration.builder() - .mutableInitValues( - MutableInitValues.builder() - .isMiningEnabled(true) - .minTransactionGasPrice(Wei.ZERO) - .coinbase(AddressHelpers.ofValue(1)) - .build()) - .build(); - minerNode.setMiningParameters(zeroGasMiningParams); - - cluster.start(minerNode); - - cluster.verify(blockchain.reachesHeight(minerNode, 1)); - - final Account sender = accounts.createAccount("account1"); - final Account receiver = accounts.createAccount("account2"); - - minerNode.execute(accountTransactions.createTransfer(sender, 50, Amount.ZERO)); - cluster.verify(sender.balanceEquals(50)); - - minerNode.execute( - accountTransactions.createIncrementalTransfers(sender, receiver, 1, Amount.ZERO)); - cluster.verify(receiver.balanceEquals(1)); - - minerNode.execute( - accountTransactions.createIncrementalTransfers(sender, receiver, 2, Amount.ZERO)); - cluster.verify(receiver.balanceEquals(3)); - } - - @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); - - cluster.start(minerNode); - - cluster.verify(blockchain.reachesHeight(minerNode, 1)); - - final Account sender = accounts.createAccount("account1"); - final Account receiver = accounts.createAccount("account2"); - - minerNode.execute(accountTransactions.createTransfer(sender, 50)); - cluster.verify(sender.balanceEquals(50)); - - minerNode.execute(accountTransactions.create1559Transfer(sender, 50, 4)); - cluster.verify(sender.balanceEquals(100)); - - minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); - cluster.verify(receiver.balanceEquals(1)); - - minerNode.execute(accountTransactions.create1559IncrementalTransfers(sender, receiver, 2, 4)); - cluster.verify(receiver.balanceEquals(3)); - } - - @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); - - cluster.start(minerNode); - - cluster.verify(blockchain.reachesHeight(minerNode, 1)); - - final Account sender = accounts.createAccount("account1"); - final Account receiver = accounts.createAccount("account2"); - - minerNode.execute(accountTransactions.createTransfer(sender, 50, Amount.ZERO)); - cluster.verify(sender.balanceEquals(50)); - - minerNode.execute(accountTransactions.create1559Transfer(sender, 50, 4, Amount.ZERO)); - cluster.verify(sender.balanceEquals(100)); - - minerNode.execute( - accountTransactions.createIncrementalTransfers(sender, receiver, 1, Amount.ZERO)); - cluster.verify(receiver.balanceEquals(1)); - - minerNode.execute( - accountTransactions.create1559IncrementalTransfers(sender, receiver, 2, 4, Amount.ZERO)); - cluster.verify(receiver.balanceEquals(3)); - } - - @ParameterizedTest(name = "{index}: {0}") - @MethodSource("factoryFunctions") - public void shouldMineOnSingleNodeWithFreeGas_Shanghai( - final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { - setUp(testName, nodeFactory); - final BesuNode minerNode = nodeFactory.createNode(besu, "miner1"); - updateGenesisConfigToShanghai(minerNode, true); - - cluster.start(minerNode); - - cluster.verify(blockchain.reachesHeight(minerNode, 1)); - - final Account sender = accounts.createAccount("account1"); - final Account receiver = accounts.createAccount("account2"); - - minerNode.execute(accountTransactions.createTransfer(sender, 50, Amount.ZERO)); - cluster.verify(sender.balanceEquals(50)); - - minerNode.execute(accountTransactions.create1559Transfer(sender, 50, 4, Amount.ZERO)); - cluster.verify(sender.balanceEquals(100)); - - minerNode.execute( - accountTransactions.createIncrementalTransfers(sender, receiver, 1, Amount.ZERO)); - cluster.verify(receiver.balanceEquals(1)); - - minerNode.execute( - accountTransactions.create1559IncrementalTransfers(sender, receiver, 2, 4, Amount.ZERO)); - cluster.verify(receiver.balanceEquals(3)); - } - - @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"); - final BesuNode minerNode4 = nodeFactory.createNode(besu, "miner4"); - cluster.start(minerNode1, minerNode2, minerNode3, minerNode4); - - cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85)); - - final Account sender = accounts.createAccount("account1"); - final Account receiver = accounts.createAccount("account2"); - - minerNode1.execute(accountTransactions.createTransfer(sender, 50)); - cluster.verify(sender.balanceEquals(50)); - - minerNode2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); - cluster.verify(receiver.balanceEquals(1)); - - minerNode3.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); - cluster.verify(receiver.balanceEquals(3)); - - minerNode4.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 3)); - cluster.verify(receiver.balanceEquals(6)); - } - - @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); - final BesuNode validator2 = - nodeFactory.createNodeWithValidators(besu, "validator2", validators); - final BesuNode validator3 = - nodeFactory.createNodeWithValidators(besu, "validator3", validators); - final BesuNode nonValidatorNode = - nodeFactory.createNodeWithValidators(besu, "non-validator", validators); - cluster.start(validator1, validator2, validator3, nonValidatorNode); - - cluster.verify(blockchain.reachesHeight(validator1, 1, 85)); - - final Account sender = accounts.createAccount("account1"); - final Account receiver = accounts.createAccount("account2"); - - validator1.execute(accountTransactions.createTransfer(sender, 50)); - cluster.verify(sender.balanceEquals(50)); - - validator2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); - cluster.verify(receiver.balanceEquals(1)); - - nonValidatorNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); - cluster.verify(receiver.balanceEquals(3)); - } - - @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"); - final BesuNode minerNode4 = nodeFactory.createNode(besu, "miner4"); - final List validators = - bft.validators(new BesuNode[] {minerNode1, minerNode2, minerNode3, minerNode4}); - final BesuNode nonProposerNode = validators.get(validators.size() - 1); - cluster.start(validators); - - cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85)); - - final Account receiver = accounts.createAccount("account2"); - - cluster.stopNode(nonProposerNode); - validators.get(0).execute(accountTransactions.createTransfer(receiver, 80)); - - cluster.verifyOnActiveNodes(receiver.balanceEquals(80)); - } - - private static void updateGenesisConfigToLondon( - final BesuNode minerNode, final boolean zeroBaseFeeEnabled) { - final Optional genesisConfig = - minerNode.getGenesisConfigProvider().create(List.of(minerNode)); - final ObjectNode genesisConfigNode = JsonUtil.objectNodeFromString(genesisConfig.orElseThrow()); - final ObjectNode config = (ObjectNode) genesisConfigNode.get("config"); - config.remove("berlinBlock"); - config.put("londonBlock", 0); - config.put("zeroBaseFee", zeroBaseFeeEnabled); - minerNode.setGenesisConfig(genesisConfigNode.toString()); - } - - private static void updateGenesisConfigToShanghai( - final BesuNode minerNode, final boolean zeroBaseFeeEnabled) { - final Optional genesisConfig = - minerNode.getGenesisConfigProvider().create(List.of(minerNode)); - final ObjectNode genesisConfigNode = JsonUtil.objectNodeFromString(genesisConfig.orElseThrow()); - final ObjectNode config = (ObjectNode) genesisConfigNode.get("config"); - config.remove("berlinBlock"); - config.put("shanghaiTime", 100); - config.put("zeroBaseFee", zeroBaseFeeEnabled); - minerNode.setGenesisConfig(genesisConfigNode.toString()); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest_Part1.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest_Part1.java new file mode 100644 index 000000000..4d38accc6 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest_Part1.java @@ -0,0 +1,117 @@ +/* + * Copyright contributors to 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.bft; + +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.core.AddressHelpers; +import org.hyperledger.besu.ethereum.core.ImmutableMiningConfiguration; +import org.hyperledger.besu.ethereum.core.ImmutableMiningConfiguration.MutableInitValues; +import org.hyperledger.besu.ethereum.core.MiningConfiguration; +import org.hyperledger.besu.tests.acceptance.dsl.account.Account; +import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class BftMiningAcceptanceTest_Part1 extends ParameterizedBftTestBase { + + @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); + + cluster.verify(blockchain.reachesHeight(minerNode, 1)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + minerNode.execute(accountTransactions.createTransfer(sender, 50)); + cluster.verify(sender.balanceEquals(50)); + + minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); + cluster.verify(receiver.balanceEquals(1)); + + minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); + cluster.verify(receiver.balanceEquals(3)); + } + + @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 MiningConfiguration zeroGasMiningParams = + ImmutableMiningConfiguration.builder() + .mutableInitValues( + MutableInitValues.builder() + .isMiningEnabled(true) + .minTransactionGasPrice(Wei.ZERO) + .coinbase(AddressHelpers.ofValue(1)) + .build()) + .build(); + minerNode.setMiningParameters(zeroGasMiningParams); + + cluster.start(minerNode); + + cluster.verify(blockchain.reachesHeight(minerNode, 1)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + minerNode.execute(accountTransactions.createTransfer(sender, 50, Amount.ZERO)); + cluster.verify(sender.balanceEquals(50)); + + minerNode.execute( + accountTransactions.createIncrementalTransfers(sender, receiver, 1, Amount.ZERO)); + cluster.verify(receiver.balanceEquals(1)); + + minerNode.execute( + accountTransactions.createIncrementalTransfers(sender, receiver, 2, Amount.ZERO)); + cluster.verify(receiver.balanceEquals(3)); + } + + @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); + + cluster.start(minerNode); + + cluster.verify(blockchain.reachesHeight(minerNode, 1)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + minerNode.execute(accountTransactions.createTransfer(sender, 50)); + cluster.verify(sender.balanceEquals(50)); + + minerNode.execute(accountTransactions.create1559Transfer(sender, 50, 4)); + cluster.verify(sender.balanceEquals(100)); + + minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); + cluster.verify(receiver.balanceEquals(1)); + + minerNode.execute(accountTransactions.create1559IncrementalTransfers(sender, receiver, 2, 4)); + cluster.verify(receiver.balanceEquals(3)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest_Part2.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest_Part2.java new file mode 100644 index 000000000..9c04405f3 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest_Part2.java @@ -0,0 +1,114 @@ +/* + * Copyright contributors to 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.bft; + +import org.hyperledger.besu.tests.acceptance.dsl.account.Account; +import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class BftMiningAcceptanceTest_Part2 extends ParameterizedBftTestBase { + + @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); + + cluster.start(minerNode); + + cluster.verify(blockchain.reachesHeight(minerNode, 1)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + minerNode.execute(accountTransactions.createTransfer(sender, 50, Amount.ZERO)); + cluster.verify(sender.balanceEquals(50)); + + minerNode.execute(accountTransactions.create1559Transfer(sender, 50, 4, Amount.ZERO)); + cluster.verify(sender.balanceEquals(100)); + + minerNode.execute( + accountTransactions.createIncrementalTransfers(sender, receiver, 1, Amount.ZERO)); + cluster.verify(receiver.balanceEquals(1)); + + minerNode.execute( + accountTransactions.create1559IncrementalTransfers(sender, receiver, 2, 4, Amount.ZERO)); + cluster.verify(receiver.balanceEquals(3)); + } + + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void shouldMineOnSingleNodeWithFreeGas_Shanghai( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); + final BesuNode minerNode = nodeFactory.createNode(besu, "miner1"); + updateGenesisConfigToShanghai(minerNode, true); + + cluster.start(minerNode); + + cluster.verify(blockchain.reachesHeight(minerNode, 1)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + minerNode.execute(accountTransactions.createTransfer(sender, 50, Amount.ZERO)); + cluster.verify(sender.balanceEquals(50)); + + minerNode.execute(accountTransactions.create1559Transfer(sender, 50, 4, Amount.ZERO)); + cluster.verify(sender.balanceEquals(100)); + + minerNode.execute( + accountTransactions.createIncrementalTransfers(sender, receiver, 1, Amount.ZERO)); + cluster.verify(receiver.balanceEquals(1)); + + minerNode.execute( + accountTransactions.create1559IncrementalTransfers(sender, receiver, 2, 4, Amount.ZERO)); + cluster.verify(receiver.balanceEquals(3)); + } + + @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"); + final BesuNode minerNode4 = nodeFactory.createNode(besu, "miner4"); + cluster.start(minerNode1, minerNode2, minerNode3, minerNode4); + + cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + minerNode1.execute(accountTransactions.createTransfer(sender, 50)); + cluster.verify(sender.balanceEquals(50)); + + minerNode2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); + cluster.verify(receiver.balanceEquals(1)); + + minerNode3.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); + cluster.verify(receiver.balanceEquals(3)); + + minerNode4.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 3)); + cluster.verify(receiver.balanceEquals(6)); + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest_Part3.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest_Part3.java new file mode 100644 index 000000000..bae672de0 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest_Part3.java @@ -0,0 +1,81 @@ +/* + * Copyright contributors to 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.bft; + +import org.hyperledger.besu.tests.acceptance.dsl.account.Account; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import java.util.List; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class BftMiningAcceptanceTest_Part3 extends ParameterizedBftTestBase { + + @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); + final BesuNode validator2 = + nodeFactory.createNodeWithValidators(besu, "validator2", validators); + final BesuNode validator3 = + nodeFactory.createNodeWithValidators(besu, "validator3", validators); + final BesuNode nonValidatorNode = + nodeFactory.createNodeWithValidators(besu, "non-validator", validators); + cluster.start(validator1, validator2, validator3, nonValidatorNode); + + cluster.verify(blockchain.reachesHeight(validator1, 1, 85)); + + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + + validator1.execute(accountTransactions.createTransfer(sender, 50)); + cluster.verify(sender.balanceEquals(50)); + + validator2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); + cluster.verify(receiver.balanceEquals(1)); + + nonValidatorNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); + cluster.verify(receiver.balanceEquals(3)); + } + + @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"); + final BesuNode minerNode4 = nodeFactory.createNode(besu, "miner4"); + final List validators = + bft.validators(new BesuNode[] {minerNode1, minerNode2, minerNode3, minerNode4}); + final BesuNode nonProposerNode = validators.get(validators.size() - 1); + cluster.start(validators); + + cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85)); + + final Account receiver = accounts.createAccount("account2"); + + cluster.stopNode(nonProposerNode); + validators.get(0).execute(accountTransactions.createTransfer(receiver, 80)); + + cluster.verifyOnActiveNodes(receiver.balanceEquals(80)); + } +} 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 76a1a4a6b..29e06c28c 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,10 +14,15 @@ */ package org.hyperledger.besu.tests.acceptance.bft; +import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; +import java.util.List; +import java.util.Optional; import java.util.stream.Stream; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.provider.Arguments; @@ -30,6 +35,30 @@ public abstract class ParameterizedBftTestBase extends AcceptanceTestBase { return BftAcceptanceTestParameterization.getFactories(); } + protected static void updateGenesisConfigToLondon( + final BesuNode minerNode, final boolean zeroBaseFeeEnabled) { + final Optional genesisConfig = + minerNode.getGenesisConfigProvider().create(List.of(minerNode)); + final ObjectNode genesisConfigNode = JsonUtil.objectNodeFromString(genesisConfig.orElseThrow()); + final ObjectNode config = (ObjectNode) genesisConfigNode.get("config"); + config.remove("berlinBlock"); + config.put("londonBlock", 0); + config.put("zeroBaseFee", zeroBaseFeeEnabled); + minerNode.setGenesisConfig(genesisConfigNode.toString()); + } + + static void updateGenesisConfigToShanghai( + final BesuNode minerNode, final boolean zeroBaseFeeEnabled) { + final Optional genesisConfig = + minerNode.getGenesisConfigProvider().create(List.of(minerNode)); + final ObjectNode genesisConfigNode = JsonUtil.objectNodeFromString(genesisConfig.orElseThrow()); + final ObjectNode config = (ObjectNode) genesisConfigNode.get("config"); + config.remove("berlinBlock"); + config.put("shanghaiTime", 100); + config.put("zeroBaseFee", zeroBaseFeeEnabled); + minerNode.setGenesisConfig(genesisConfigNode.toString()); + } + protected void setUp(final String bftType, final BftAcceptanceTestParameterization input) { this.bftType = bftType; this.nodeFactory = input;