From 74aa0579de02afadb677bd0b2a0aaa1146e92e3c Mon Sep 17 00:00:00 2001 From: Matthew Whitehead Date: Fri, 19 Jan 2024 11:46:07 +0000 Subject: [PATCH] NO PUSH --- .../tests/acceptance/dsl/node/BesuNode.java | 5 + .../node/configuration/BesuNodeFactory.java | 6 +- acceptance-tests/tests/build.gradle | 27 ++ .../BftAcceptanceTestParameterization.java | 8 +- .../bft/ParameterizedBftTestBase.java | 3 + .../bft/pki/ParameterizedPkiQbftTestBase.java | 29 -- .../bft/pki/PkiQbftAcceptanceTest.java | 130 ------- ...PkiQbftAcceptanceTestParameterization.java | 120 ------- .../acceptance/bftsoak/BftMiningSoakTest.java | 326 ++++++++++++++---- besu/VERSION_METADATA.json | 1 + .../controller/BesuControllerBuilder.java | 8 + .../ethereum/chain/DefaultBlockchain.java | 4 + .../besu/ethereum/chain/GenesisState.java | 12 + .../mainnet/DefaultProtocolSchedule.java | 2 +- 14 files changed, 332 insertions(+), 349 deletions(-) delete mode 100644 acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/ParameterizedPkiQbftTestBase.java delete mode 100644 acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTest.java delete mode 100644 acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java create mode 100644 besu/VERSION_METADATA.json 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 ba00ac8f22f..a9522b8b4cd 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 @@ -556,6 +556,7 @@ public void awaitPeerDiscovery(final Condition condition) { private void loadPortsFile() { try (final FileInputStream fis = new FileInputStream(new File(homeDirectory.toFile(), "besu.ports"))) { + System.out.println("MRW: Loading ports from " + new File(homeDirectory.toFile(), "besu.ports").getPath()); portsProperties.load(fis); LOG.info("Ports for node {}: {}", name, portsProperties); } catch (final IOException e) { @@ -797,11 +798,15 @@ public GenesisConfigurationProvider getGenesisConfigProvider() { @Override public Optional getGenesisConfig() { + //System.out.println("MRW: Getting genesis config: " + genesisConfig); return genesisConfig; } @Override public void setGenesisConfig(final String config) { + //System.out.println("MRW: Setting genesis config. Was: " + genesisConfig); + //System.out.println("MRW: Setting genesis config. Is now: " + config); + //new Exception().printStackTrace(); this.genesisConfig = Optional.of(config); } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java index ed26587812c..e822900d9c9 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java @@ -494,14 +494,18 @@ public BesuNode createQbftNodeWithTLSPKCS11(final String name) throws IOExceptio } public BesuNode createQbftNode(final String name) throws IOException { + JsonRpcConfiguration rpcConfig = node.createJsonRpcWithQbftEnabledConfig(false); + rpcConfig.setPort(Math.abs(name.hashCode() % 60000) + 1024); // Generate a consistent port for p2p based on node name + rpcConfig.addRpcApi("ADMIN,TXPOOL"); return create( new BesuNodeConfigurationBuilder() .name(name) .miningEnabled() - .jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false)) + .jsonRpcConfiguration(rpcConfig) .webSocketConfiguration(node.createWebSocketEnabledConfig()) .devMode(false) .genesisConfigProvider(GenesisConfigurationFactory::createQbftGenesisConfig) + .p2pPort(Math.abs(name.hashCode() % 60000) + 1024 + 500) // Generate a consistent port for p2p based on node name (+ 500 to avoid clashing with RPC port or other nodes with a similar name) .build()); } diff --git a/acceptance-tests/tests/build.gradle b/acceptance-tests/tests/build.gradle index 668463383b7..617226f754a 100644 --- a/acceptance-tests/tests/build.gradle +++ b/acceptance-tests/tests/build.gradle @@ -210,6 +210,33 @@ task acceptanceTestCliqueBft(type: Test) { doFirst { mkdir "${buildDir}/jvmErrorLogs" } } +task acceptanceTestBftSoak(type: Test) { + inputs.property "integration.date", LocalTime.now() // so it runs at every invocation + include '**/bftsoak/**' + + useJUnitPlatform {} + + dependsOn(rootProject.installDist) + setSystemProperties(test.getSystemProperties()) + systemProperty 'acctests.runBesuAsProcess', 'true' + systemProperty 'java.security.properties', "${buildDir}/resources/test/acceptanceTesting.security" + mustRunAfter rootProject.subprojects*.test + description = 'Runs BFT soak test.' + group = 'verification' + + jvmArgs "-XX:ErrorFile=${buildDir}/jvmErrorLogs/java_err_pid%p.log" + + testLogging { + exceptionFormat = 'full' + showStackTraces = true + showStandardStreams = true + showExceptions = true + showCauses = true + } + + doFirst { mkdir "${buildDir}/jvmErrorLogs" } +} + task acceptanceTestPrivacy(type: Test) { inputs.property "integration.date", LocalTime.now() // so it runs at every invocation include '**/privacy/**' 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 c9fcf364840..8b23a6c546c 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 @@ -25,10 +25,10 @@ public class BftAcceptanceTestParameterization { public static Stream getFactories() { return Stream.of( - Arguments.of( - "ibft2", - new BftAcceptanceTestParameterization( - BesuNodeFactory::createIbft2Node, BesuNodeFactory::createIbft2NodeWithValidators)), + //Arguments.of( + // "ibft2", + // new BftAcceptanceTestParameterization( + // BesuNodeFactory::createIbft2Node, BesuNodeFactory::createIbft2NodeWithValidators)), Arguments.of( "qbft", new BftAcceptanceTestParameterization( 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 b3d1e321aea..24b5a6a27f7 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 @@ -18,6 +18,9 @@ import java.util.stream.Stream; +import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster; +import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfiguration; +import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.provider.Arguments; 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 deleted file mode 100644 index b1ffcff3712..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/ParameterizedPkiQbftTestBase.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2020 ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.bft.pki; - -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5; - -import java.util.stream.Stream; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.params.provider.Arguments; - -@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(); - } -} 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 deleted file mode 100644 index 12ae887a510..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTest.java +++ /dev/null @@ -1,130 +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.pki; - -import org.hyperledger.besu.tests.acceptance.dsl.account.Account; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; - -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -public class PkiQbftAcceptanceTest extends ParameterizedPkiQbftTestBase { - - @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); - - 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 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"); - 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 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"); - final BesuNode minerNode4 = nodeFactory.createNode(besu, "miner4"); - final BesuNode minerNode5 = nodeFactory.createNode(besu, "miner5"); - final BesuNode minerNode6 = nodeFactory.createNode(besu, "miner6"); - try { - cluster.start(minerNode1, minerNode2, minerNode3, minerNode4); - - cluster.startNode(minerNode5); - cluster.startNode(minerNode6); - - cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85)); - - final Account sender = accounts.createAccount("account1"); - final Account receiver = accounts.createAccount("account2"); - - minerNode1.execute(accountTransactions.createTransfer(sender, 50)); - cluster.verify(sender.balanceEquals(50)); - - minerNode2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); - cluster.verify(receiver.balanceEquals(1)); - - minerNode3.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); - cluster.verify(receiver.balanceEquals(3)); - - minerNode4.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 3)); - cluster.verify(receiver.balanceEquals(6)); - - if (minerNode1.getTLSConfiguration().isEmpty()) { - minerNode1.verify(net.awaitPeerCount(5)); - minerNode5.verify(net.awaitPeerCount(5)); - minerNode6.verify(net.awaitPeerCount(5)); - } else { - minerNode1.verify(net.awaitPeerCount(3)); - minerNode5.verify(net.awaitPeerCount(0)); - minerNode6.verify(net.awaitPeerCount(0)); - } - } finally { - cluster.stopNode(minerNode5); - cluster.stopNode(minerNode6); - minerNode5.close(); - minerNode6.close(); - } - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java deleted file mode 100644 index 7bcf09afd38..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2020 ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See - * the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.bft.pki; - -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; -import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeFactory; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Stream; - -import org.junit.jupiter.params.provider.Arguments; - -public class PkiQbftAcceptanceTestParameterization { - - public static Stream getFactories() { - List args = new ArrayList<>(); - - /* - BLOCK CREATION - */ - - args.add( - Arguments.of( - "qbft-pki-jks", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createPkiQbftJKSNode, - BesuNodeFactory::createPkiQbftJKSNodeWithValidators))); - - args.add( - Arguments.of( - "qbft-pki-pkcs12", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createPkiQbftPKCS12Node, - BesuNodeFactory::createPkiQbftPKCS12NodeWithValidators))); - - if (Boolean.getBoolean("acctests.runBesuAsProcess")) { - args.add( - Arguments.of( - "qbft-pki-pkcs11", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createPkiQbftPKCS11Node, - BesuNodeFactory::createPkiQbftPKCS11NodeWithValidators))); - } - - /* - TLS - */ - - args.add( - Arguments.of( - "qbft-tls-jks", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createQbftNodeWithTLSJKS, - BesuNodeFactory::createQbftTLSJKSNodeWithValidators))); - - args.add( - Arguments.of( - "qbft-tls-pkcs12", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createQbftNodeWithTLSPKCS12, - BesuNodeFactory::createQbftTLSPKCS12NodeWithValidators))); - - if (Boolean.getBoolean("acctests.runBesuAsProcess")) { - args.add( - Arguments.of( - "qbft-tls-pkcs11", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createQbftNodeWithTLSPKCS11, - BesuNodeFactory::createQbftTLSPKCS11NodeWithValidators))); - } - - return args.stream(); - } - - @FunctionalInterface - public interface NodeCreator { - - BesuNode create(BesuNodeFactory factory, String name) throws Exception; - } - - @FunctionalInterface - public interface NodeWithValidatorsCreator { - - BesuNode create(BesuNodeFactory factory, String name, String[] validators) throws Exception; - } - - private final NodeCreator creatorFn; - private final NodeWithValidatorsCreator createorWithValidatorFn; - - public PkiQbftAcceptanceTestParameterization( - final NodeCreator creatorFn, final NodeWithValidatorsCreator createorWithValidatorFn) { - this.creatorFn = creatorFn; - this.createorWithValidatorFn = createorWithValidatorFn; - } - - public BesuNode createNode(BesuNodeFactory factory, String name) throws Exception { - return creatorFn.create(factory, name); - } - - public BesuNode createNodeWithValidators( - BesuNodeFactory factory, String name, String[] validators) throws Exception { - return createorWithValidatorFn.create(factory, name, validators); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bftsoak/BftMiningSoakTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bftsoak/BftMiningSoakTest.java index 33b9437e0b4..41d8f750ec8 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bftsoak/BftMiningSoakTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bftsoak/BftMiningSoakTest.java @@ -14,26 +14,43 @@ */ package org.hyperledger.besu.tests.acceptance.bftsoak; +import static org.assertj.core.api.Assertions.assertThat; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.tests.acceptance.bft.BftAcceptanceTestParameterization; import org.hyperledger.besu.tests.acceptance.bft.ParameterizedBftTestBase; import org.hyperledger.besu.tests.acceptance.dsl.account.Account; import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.math.BigInteger; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.List; +import java.util.Optional; +import java.util.Properties; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; public class BftMiningSoakTest extends ParameterizedBftTestBase { + private final int TEST_STEP_MINUTES = 2; + @ParameterizedTest(name = "{index}: {0}") @MethodSource("factoryFunctions") - public void shouldMineOnMultipleNodes() throws Exception { + public void shouldBeStableDuringLongTest( + 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)); @@ -42,24 +59,12 @@ public void shouldMineOnMultipleNodes() throws Exception { final Account receiver = accounts.createAccount("account2"); receiver.balanceEquals(20); - BigInteger currentReceiverBalance = - minerNode1.execute(ethTransactions.getBalanceAtBlock(receiver, BigInteger.valueOf(0))); - System.out.println("MRW: Rich donor balance at the beginning: " + currentReceiverBalance); - BigInteger chainHeight = minerNode1.execute(ethTransactions.blockNumber()); - System.out.println("MRW: Current chain height: " + chainHeight); + /*********************************************************************/ + /* Setup */ + /*********************************************************************/ for (int i = 0; i < 5; i++) { - BigInteger currentSenderBalance = - minerNode1.execute(ethTransactions.getBalanceAtBlock(sender, BigInteger.valueOf(0))); - System.out.println("MRW: Rich donor balance: " + currentSenderBalance); minerNode1.execute(accountTransactions.createTransfer(sender, 50)); - chainHeight = minerNode1.execute(ethTransactions.blockNumber()); - System.out.println("MRW: Current chain height: " + chainHeight); } - currentReceiverBalance = - minerNode1.execute(ethTransactions.getBalanceAtBlock(receiver, BigInteger.valueOf(0))); - System.out.println("MRW: Rich donor balance at the end: " + currentReceiverBalance); - chainHeight = minerNode1.execute(ethTransactions.blockNumber()); - System.out.println("MRW: Current chain height: " + chainHeight); cluster.verify(sender.balanceEquals(150)); minerNode2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); @@ -71,56 +76,249 @@ public void shouldMineOnMultipleNodes() throws Exception { minerNode4.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 3)); cluster.verify(receiver.balanceEquals(6)); - Thread.sleep(5000); - chainHeight = minerNode1.execute(ethTransactions.blockNumber()); - System.out.println("MRW: Current chain height: " + chainHeight); - currentReceiverBalance = - minerNode1.execute(ethTransactions.getBalanceAtBlock(receiver, BigInteger.valueOf(0))); - System.out.println("MRW: Rich donor balance at the end: " + currentReceiverBalance); - Thread.sleep(5000); - chainHeight = minerNode1.execute(ethTransactions.blockNumber()); - System.out.println("MRW: Current chain height: " + chainHeight); - currentReceiverBalance = - minerNode1.execute(ethTransactions.getBalanceAtBlock(receiver, BigInteger.valueOf(0))); - System.out.println("MRW: Rich donor balance at the end: " + currentReceiverBalance); - Thread.sleep(5000); - chainHeight = minerNode1.execute(ethTransactions.blockNumber()); - System.out.println("MRW: Current chain height: " + chainHeight); - currentReceiverBalance = - minerNode1.execute(ethTransactions.getBalanceAtBlock(receiver, BigInteger.valueOf(0))); - System.out.println("MRW: Rich donor balance at the end: " + currentReceiverBalance); - Thread.sleep(5000); - chainHeight = minerNode1.execute(ethTransactions.blockNumber()); - System.out.println("MRW: Current chain height: " + chainHeight); - currentReceiverBalance = - minerNode1.execute(ethTransactions.getBalanceAtBlock(receiver, BigInteger.valueOf(0))); - System.out.println("MRW: Rich donor balance at the end: " + currentReceiverBalance); - Thread.sleep(5000); + /*********************************************************************/ + /* Step 1 */ + /* Run for the configured time period, periodically checking that */ + /* the chain is progressing as expected */ + /*********************************************************************/ + BigInteger chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + assertThat(chainHeight.compareTo(BigInteger.ZERO)).isGreaterThanOrEqualTo(1); + BigInteger lastChainHeight = chainHeight; + + Instant startTime = Instant.now(); + Instant nextStepEndTime = startTime.plus(TEST_STEP_MINUTES, ChronoUnit.MINUTES); + + while (System.currentTimeMillis() < nextStepEndTime.toEpochMilli()) { + try { + Thread.sleep(60000); + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + + // With 1-second block period chain height should have moved on by at least 50 blocks + assertThat(chainHeight.compareTo(lastChainHeight.add(BigInteger.valueOf(50)))) + .isGreaterThanOrEqualTo(1); + lastChainHeight = chainHeight; + } catch (InterruptedException e) { + Assertions.fail(e); + break; + } + } + Instant previousStepEndTime = Instant.now(); + + /*********************************************************************/ + /* Step 2 */ + /* Stop one of the nodes, check that the chain continues mining */ + /* blocks */ + /*********************************************************************/ + cluster.stopNode(minerNode4); + + nextStepEndTime = previousStepEndTime.plus(TEST_STEP_MINUTES, ChronoUnit.MINUTES); + while (System.currentTimeMillis() < nextStepEndTime.toEpochMilli()) { + try { + Thread.sleep(60000); + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + + // Chain height should have moved on by at least 5 blocks + assertThat(chainHeight.compareTo(lastChainHeight.add(BigInteger.valueOf(20)))) + .isGreaterThanOrEqualTo(1); + lastChainHeight = chainHeight; + } catch (InterruptedException e) { + Assertions.fail(e); + break; + } + } + previousStepEndTime = Instant.now(); + + /*********************************************************************/ + /* Step 3 */ + /* Stop another one of the nodes, check that the chain now stops */ + /* mining blocks */ + /*********************************************************************/ + cluster.stopNode(minerNode3); + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + Assertions.fail(e); + } chainHeight = minerNode1.execute(ethTransactions.blockNumber()); - System.out.println("MRW: Current chain height: " + chainHeight); - currentReceiverBalance = - minerNode1.execute(ethTransactions.getBalanceAtBlock(receiver, BigInteger.valueOf(0))); - System.out.println("MRW: Rich donor balance at the end: " + currentReceiverBalance); - Thread.sleep(5000); + lastChainHeight = chainHeight; + + nextStepEndTime = previousStepEndTime.plus(TEST_STEP_MINUTES, ChronoUnit.MINUTES); + while (System.currentTimeMillis() < nextStepEndTime.toEpochMilli()) { + try { + Thread.sleep(60000); + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + + // Chain height should not have moved on + assertThat(chainHeight.equals(lastChainHeight)).isTrue(); + } catch (InterruptedException e) { + Assertions.fail(e); + break; + } + } + previousStepEndTime = Instant.now(); + + /*********************************************************************/ + /* Step 4 */ + /* Restart both of the stopped nodes. Check that the chain resumes */ + /* mining blocks */ + /*********************************************************************/ + cluster.startNode(minerNode4); + cluster.startNode(minerNode3); + + // Give them time to sync + try { + Thread.sleep(180000); + } catch (InterruptedException e) { + Assertions.fail(e); + } + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); - System.out.println("MRW: Current chain height: " + chainHeight); - currentReceiverBalance = - minerNode1.execute(ethTransactions.getBalanceAtBlock(receiver, BigInteger.valueOf(0))); - System.out.println("MRW: Rich donor balance at the end: " + currentReceiverBalance); - Thread.sleep(5000); + nextStepEndTime = previousStepEndTime.plus(TEST_STEP_MINUTES, ChronoUnit.MINUTES); + lastChainHeight = chainHeight; + + // This loop gives it time to sync + while (System.currentTimeMillis() < nextStepEndTime.toEpochMilli()) { + try { + Thread.sleep(60000); + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + lastChainHeight = chainHeight; + } catch (InterruptedException e) { + Assertions.fail(e); + break; + } + } + previousStepEndTime = Instant.now(); + + // By this loop it should be producing blocks again + nextStepEndTime = previousStepEndTime.plus(TEST_STEP_MINUTES, ChronoUnit.MINUTES); + while (System.currentTimeMillis() < nextStepEndTime.toEpochMilli()) { + try { + Thread.sleep(60000); + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + + // Chain height should have moved on by at least 5 blocks + assertThat(chainHeight.compareTo(lastChainHeight.add(BigInteger.valueOf(50)))) + .isGreaterThanOrEqualTo(1); + lastChainHeight = chainHeight; + } catch (InterruptedException e) { + Assertions.fail(e); + break; + } + } + + /*********************************************************************/ + /* Upgrade the chain from berlin to london */ + /*********************************************************************/ + cluster.stopNode(minerNode1); + + // Give it time to stop + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + Assertions.fail(e); + } + + updateGenesisConfigToLondon(minerNode1, true, 200); + + cluster.startNode(minerNode1); + + // Give it time to start + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + Assertions.fail(e); + } + + cluster.stopNode(minerNode2); + + // Give it time to stop + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + Assertions.fail(e); + } + + updateGenesisConfigToLondon(minerNode2, true, 200); + + cluster.startNode(minerNode2); + + // Give it time to start + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + Assertions.fail(e); + } + + cluster.stopNode(minerNode3); + + // Give it time to stop + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + Assertions.fail(e); + } + + updateGenesisConfigToLondon(minerNode3, true, 200); + + cluster.startNode(minerNode3); + + // Give it time to start + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + Assertions.fail(e); + } + + cluster.stopNode(minerNode4); + + // Give it time to stop + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + Assertions.fail(e); + } + + updateGenesisConfigToLondon(minerNode4, true, 200); + + cluster.startNode(minerNode4); + + // Give it time to start + try { + Thread.sleep(60000); + } catch (InterruptedException e) { + Assertions.fail(e); + } + previousStepEndTime = Instant.now(); + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); - System.out.println("MRW: Current chain height: " + chainHeight); + nextStepEndTime = previousStepEndTime.plus(TEST_STEP_MINUTES, ChronoUnit.MINUTES); + lastChainHeight = chainHeight; + + while (System.currentTimeMillis() < nextStepEndTime.toEpochMilli()) { + try { + Thread.sleep(60000); + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + + // Chain height should have moved on by at least 5 blocks + assertThat(chainHeight.compareTo(lastChainHeight.add(BigInteger.valueOf(50)))) + .isGreaterThanOrEqualTo(1); + lastChainHeight = chainHeight; + } catch (InterruptedException e) { + Assertions.fail(e); + break; + } + } } - /* 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 updateGenesisConfigToLondon( + final BesuNode minerNode, final boolean zeroBaseFeeEnabled, final int blockNumber) { + + if (minerNode.getGenesisConfig().isPresent()) { + final ObjectNode genesisConfigNode3 = JsonUtil.objectNodeFromString(minerNode.getGenesisConfig().get()); + final ObjectNode config1 = (ObjectNode) genesisConfigNode3.get("config"); + config1.put("londonBlock", blockNumber); + config1.put("zeroBaseFee", zeroBaseFeeEnabled); + minerNode.setGenesisConfig(genesisConfigNode3.toString()); + } + } } diff --git a/besu/VERSION_METADATA.json b/besu/VERSION_METADATA.json new file mode 100644 index 00000000000..eb4db236cc6 --- /dev/null +++ b/besu/VERSION_METADATA.json @@ -0,0 +1 @@ +{"besuVersion":"24.2.0-dev-a728e490"} \ No newline at end of file diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java index 7110a8d88a6..01b07648276 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -582,6 +582,14 @@ public BesuController build() { final GenesisState genesisState = GenesisState.fromConfig(dataStorageConfiguration, genesisConfig, protocolSchedule); + // System.out.println("MRW: Protocol schedule for state generation: " + protocolSchedule.listMilestones()); + + //System.out.println("MRW: Genesis config block numbers for state generation: " + genesisConfig.getForkBlockNumbers()); + + //System.out.println("MRW: Building besu controller. The genesis config is: " + genesisConfig.getConfigOptions()); + + //System.out.println("MRW: Building besu controller. The genesis state is: " + genesisState); + final VariablesStorage variablesStorage = storageProvider.createVariablesStorage(); final WorldStateStorage worldStateStorage = diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java index a92be73bf7c..794d6a4a522 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java @@ -760,6 +760,8 @@ Set getForks() { } private void setGenesis(final Block genesisBlock, final String dataDirectory) { + //new Exception().printStackTrace(); + //System.out.println("MRW: Setting genesis block to " + genesisBlock); checkArgument( genesisBlock.getHeader().getNumber() == BlockHeader.GENESIS_BLOCK_NUMBER, "Invalid genesis block."); @@ -781,6 +783,8 @@ private void setGenesis(final Block genesisBlock, final String dataDirectory) { if (genesisHash.isEmpty()) { throw new IllegalStateException("Blockchain is missing genesis block data."); } + //System.out.println("MRW: Genesis hash from the chain: " + genesisHash.get()); + //System.out.println("MRW: Genesis hash from the file: " + genesisBlock.getHash()); if (!genesisHash.get().equals(genesisBlock.getHash())) { throw new InvalidConfigurationException( "Supplied genesis block does not match chain data stored in " diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java index ccf47b17f59..2f49eee2175 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java @@ -19,6 +19,7 @@ import org.hyperledger.besu.config.GenesisAllocation; import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BlobGas; import org.hyperledger.besu.datatypes.Hash; @@ -117,6 +118,14 @@ public static GenesisState fromConfig( final GenesisConfigFile config, final ProtocolSchedule protocolSchedule) { final List genesisAccounts = parseAllocations(config).toList(); + //try { + //System.out.println("MRW: Config for state generation" + JsonUtil.getJson(config, true)); + //} catch (Exception e) { + // System.out.println("Got an error: " + e); + // } + //System.out.println("MRW: Genesis accounts: " + genesisAccounts); + //System.out.println("MRW: Genesis state hash from calculation: " + calculateGenesisStateHash(dataStorageConfiguration, genesisAccounts)); + //System.out.println("MRW: Config extra data: " + config.getExtraData()); final Block block = new Block( buildHeader( @@ -124,6 +133,9 @@ public static GenesisState fromConfig( calculateGenesisStateHash(dataStorageConfiguration, genesisAccounts), protocolSchedule), buildBody(config)); + //System.out.println("MRW: Block header: " + block.getHeader()); + //System.out.println("MRW: Block hash: " + block.getHash()); + //System.out.println("MRW: Block body: " + block.getBody()); return new GenesisState(block, genesisAccounts); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/DefaultProtocolSchedule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/DefaultProtocolSchedule.java index a92446630dd..9cb9e92c38f 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/DefaultProtocolSchedule.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/DefaultProtocolSchedule.java @@ -103,7 +103,7 @@ public boolean isOnMilestoneBoundary(final BlockHeader blockHeader) { @Override public void putBlockNumberMilestone(final long blockNumber, final ProtocolSpec protocolSpec) { if (protocolSpec.getName().equals("Shanghai")) { - System.err.println("MRW: ERROR - WE SHOULD NOT ADD SHANGHAI AS A BLOCK NUMBER MILESTONE"); + // System.err.println("MRW: ERROR - WE SHOULD NOT ADD SHANGHAI AS A BLOCK NUMBER MILESTONE"); new Exception().printStackTrace(); } putMilestone(BlockNumberProtocolSpec.create(blockNumber, protocolSpec));