8000 Enable Quorum/IBFT1 to Besu migration by pullurib · Pull Request #8262 · hyperledger/besu · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Enable Quorum/IBFT1 to Besu migration #8262

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Mar 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
14c401d
Enable Quorum/IBFT1 to Besu migration
Feb 6, 2025
d5cf8fd
Fix BftMining acceptance test
Feb 10, 2025
c79cf36
Merge branch 'main' into quorum-ibft1-migration
pullurib Feb 10, 2025
1112fab
Introduce delay after London fork update in BFT mining test to preven…
Feb 10, 2025
9c35bb6
Merge branch 'quorum-ibft1-migration' of github.com:pullurib/besu int…
Feb 10, 2025
c78c53d
Update besu/src/main/java/org/hyperledger/besu/controller/IbftLegacyB…
pullurib Feb 13, 2025
828b257
Review changes
Feb 13, 2025
9a10a01
Merge branch 'quorum-ibft1-migration' of github.com:pullurib/besu int…
Feb 13, 2025
58d2563
update creating additional JSON RPC methods for all controllerbuidler…
Feb 22, 2025
ca49542
Create ethprotocol manager and plugin factory for both consensus cont…
Feb 26, 2025
6b8c5db
merge main
Feb 26, 2025
cdeb2e0
Refactor resource files
Feb 26, 2025
1906973
fix verification metadata
Feb 26, 2025
e013749
fix regression
Feb 27, 2025
f8511da
Merge branch 'main' into quorum-ibft1-migration
matthew1001 Feb 27, 2025
996dffd
update changelog
Feb 27, 2025
4269f49
Merge branch 'main' into quorum-ibft1-migration
pullurib Mar 3, 2025
0851661
Fix controller selection at the transition block
Mar 5, 2025
2ab9f6c
Merge branch 'quorum-ibft1-migration' of github.com:pullurib/besu int…
Mar 5, 2025
74575e0
Review changes
Mar 7, 2025
c566e41
Revert BftExtraData changes
Mar 7, 2025
60a5ab4
Merge branch 'main' into quorum-ibft1-migration
pullurib Mar 7, 2025
7ecdb22
Merge branch 'main' into quorum-ibft1-migration
pullurib Mar 12, 2025
c0a32bb
Merge branch 'main' into quorum-ibft1-migration
macfarla Mar 12, 2025
67ecec6
Merge branch 'main' into quorum-ibft1-migration
pullurib Mar 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
- Add TLS/mTLS options and configure the GraphQL HTTP service[#7910](https://github.com/hyperledger/besu/pull/7910)
- Update `eth_getLogs` to return a `Block not found` error when the requested block is not found. [#8290](https://github.com/hyperledger/besu/pull/8290)
- Change `Invalid block, unable to parse RLP` RPC error message to `Invalid block param (block not found)` [#8328](https://github.com/hyperledger/besu/pull/8328)
- Add IBFT1 to QBFT migration capability [#8262](https://github.com/hyperledger/besu/pull/8262)
- Support pending transaction score when saving and restoring txpool [#8363](https://github.com/hyperledger/besu/pull/8363)
- Upgrade to execution-spec-tests v4.1.0 including better EIP-2537 coverage for BLS [#8402](https://github.com/hyperledger/besu/pull/8402)
- Add era1 format to blocks import subcommand [#7935](https://github.com/hyperledger/besu/issues/7935)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ public AwaitNetPeerCount(

@Override
public void verify(final Node node) {
WaitUtils.waitFor(() -> assertThat(node.execute(transaction)).isEqualTo(expectedPeerCount));
WaitUtils.waitFor(50, () -> assertThat(node.execute(transaction)).isEqualTo(expectedPeerCount));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,39 @@ public BesuNode createQbftNode(
return create(builder.build());
}

public BesuNode createQbftMigrationNode(
final String name, final boolean fixedPort, final DataStorageFormat storageFormat)
throws IOException {
JsonRpcConfiguration rpcConfig = node.createJsonRpcWithQbftEnabledConfig(false);
rpcConfig.addRpcApi("ADMIN,TXPOOL");
if (fixedPort) {
rpcConfig.setPort(
Math.abs(name.hashCode() % 60000)
+ 1024); // Generate a consistent port for p2p based on node name
}

BesuNodeConfigurationBuilder builder =
new BesuNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcConfiguration(rpcConfig)
.webSocketConfiguration(node.createWebSocketEnabledConfig())
.devMode(false)
.dataStorageConfiguration(
storageFormat == DataStorageFormat.FOREST
? DataStorageConfiguration.DEFAULT_FOREST_CONFIG
: DataStorageConfiguration.DEFAULT_BONSAI_CONFIG)
.genesisConfigProvider(GenesisConfigurationFactory::createQbftMigrationGenesisConfig);
if (fixedPort) {
builder.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)
}
return create(builder.build());
}

public BesuNode createCustomGenesisNode(
final String name, final String genesisPath, final boolean canBeBootnode) throws IOException {
return createCustomGenesisNode(name, genesisPath, canBeBootnode, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ public static Optional<String> createQbftGenesisConfig(
validators, template, QbftExtraDataCodec::createGenesisExtraDataString);
}

public static Optional<String> createQbftMigrationGenesisConfig(
final Collection<? extends RunnableNode> validators) {
final String template = readGenesisFile("/qbft/migration-ibft1/qbft-migration.json");
return updateGenesisExtraData(
validators, template, QbftExtraDataCodec::createGenesisExtraDataString);
}

@SuppressWarnings("unchecked")
public static Optional<String> createQbftValidatorContractGenesisConfig(
final Collection<? extends RunnableNode> validators) throws UncheckedIOException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* 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;

import static org.apache.logging.log4j.util.LoaderUtil.getClassLoader;

import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

import org.junit.jupiter.api.Test;

public class QuorumIBFTMigrationTest extends AcceptanceTestBase {

public static void copyKeyFilesToNodeDataDirs(final BesuNode... nodes) throws IOException {
for (BesuNode node : nodes) {
copyKeyFile(node, "key");
copyKeyFile(node, "key.pub");
}
}

private static void copyKeyFile(final BesuNode node, final String keyFileName)
throws IOException {
String resourceFileName = "qbft/migration-ibft1/" + node.getName() + keyFileName;
try (InputStream keyFileStream = getClassLoader().getResourceAsStream(resourceFileName)) {
if (keyFileStream == null) {
throw new IOException("Resource not found: " + resourceFileName);
}
Path targetPath = node.homeDirectory().resolve(keyFileName);
Files.createDirectories(targetPath.getParent());
Files.copy(keyFileStream, targetPath, StandardCopyOption.REPLACE_EXISTING);
}
}

public static void runBesuCommand(final Path dataPath) throws IOException, InterruptedException {
ProcessBuilder processBuilder =
new ProcessBuilder(
" 10000 ../../build/install/besu/bin/besu",
"--genesis-file",
"src/test/resources/qbft/migration-ibft1/qbft-migration.json",
"--data-path",
dataPath.toString(),
"--data-storage-format",
"FOREST",
"blocks",
"import",
"src/test/resources/qbft/migration-ibft1/ibft.blocks");

processBuilder.directory(new File(System.getProperty("user.dir")));
processBuilder.inheritIO(); // This will redirect the output to the console

Process process = processBuilder.start();
int exitCode = process.waitFor();
if (exitCode == 0) {
System.out.println("Import command executed successfully.");
} else {
throw new RuntimeException("Import command execution failed with exit code: " + exitCode);
}
}

@Test
public void shouldImportIBFTBlocksAndTransitionToQBFT() throws Exception {

// Create a mix of Bonsai and Forest DB nodes
final BesuNode minerNode1 =
besu.createQbftMigrationNode("miner1", false, DataStorageFormat.FOREST);
final BesuNode minerNode2 =
besu.createQbftMigrationNode("miner2", false, DataStorageFormat.FOREST);
final BesuNode minerNode3 =
besu.createQbftMigrationNode("miner3", false, DataStorageFormat.FOREST);
final BesuNode minerNode4 =
besu.createQbftMigrationNode("miner4", false, DataStorageFormat.FOREST);
final BesuNode minerNode5 =
besu.createQbftMigrationNode("miner5", false, DataStorageFormat.FOREST);

// Copy key files to the node datadirs
// Use the key files saved in resources directory
copyKeyFilesToNodeDataDirs(minerNode1, minerNode2, minerNode3, minerNode4, minerNode5);

// start one node and import blocks from import file
// Use import file, genesis saved in resources directory

runBesuCommand(minerNode1.homeDirectory());

// After the import is done, start the rest of the nodes using the same genesis and respective
// node keys

cluster.start(minerNode1, minerNode2, minerNode3, minerNode4, minerNode5);

// Check that the chain is progressing as expected
cluster.verify(blockchain.reachesHeight(minerNode2, 1, 120));
}

@Override
public void tearDownAcceptanceTestBase() {
cluster.stop();
super.tearDownAcceptanceTestBase();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ public class BftMiningSoakTest extends ParameterizedBftTestBase {

private static final long ONE_MINUTE = Duration.of(1, ChronoUnit.MINUTES).toMillis();

private static final long THREE_MINUTES = Duration.of(3, ChronoUnit.MINUTES).toMillis();

private static final long TEN_SECONDS = Duration.of(10, ChronoUnit.SECONDS).toMillis();

static int getTestDurationMins() {
Expand Down Expand Up @@ -213,6 +211,8 @@ public void shouldBeStableDuringLongTest(
upgradeToLondon(
minerNode1, minerNode2, minerNode3, minerNode4, lastChainHeight.intValue() + 120);

cluster.verify(blockchain.reachesHeight(minerNode4, 1, 180));

previousStepEndTime = Instant.now();

chainHeight = minerNode1.execute(ethTransactions.blockNumber());
Expand Down Expand Up @@ -241,7 +241,7 @@ public void shouldBeStableDuringLongTest(
upgradeToShanghai(
minerNode1, minerNode2, minerNode3, minerNode4, Instant.now().getEpochSecond() + 120);

Thread.sleep(THREE_MINUTES);
cluster.verify(blockchain.reachesHeight(minerNode4, 1, 180));

SimpleStorageShanghai simpleStorageContractShanghai =
minerNode1.execute(contractTransactions.createSmartContract(SimpleStorageShanghai.class));
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0a46b91fe0c770a4355d1fec9ccd72d39264f46a74ed67a69a12ed4c265aa768
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8093fb3200c783555ed487b8b5210ef3369b062a1f3ce5762d83d7a62205693d1e4f253e840ca48ec98d8f20c5b41bbbd43f34f87a1f68324ab51afe73732b96
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
17c2aacfdf1f6defde20e6ae7132c6d3991e758af3799a307a75b38135678a48
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
d81f65976ccc44c5e7e6ca859c5ede06b0f484f72c52d35dd8f7bd7581a8b7020d9ef45878696b4593daf5575b48dda5259f78f192a3445d5cc97c032660642f
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
917fb1b03034e5d7156b89bc2a3bc2aae1d146d2640d75e095f07110b0871bc1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
67785a2ac328648d94245abb25bdcfab853d06e68c70026d90f2fd5c8338b65c19235398eac205e4bbdb3fc1de9669ad6309e43ab203c8e7430664cea6451f56
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3b3cbae8c034c4ba2d5f4df44faa013888216a6eabb7fffa0b224003ea770ba7
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ec403552908986b5d9e4def3be9ddcb26d5b03def3b44ef2d5d728bb9a3028603405e7379c3e185cb2bc3e784548fcdd0e7616162029c3f407155b2fb25ba0ca
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
4ddfb30d4fcd6f5a9f959961f734e4c1469af223bc16b217eef0d3796e64973d
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
28c02b375d62b0adef8213b76882dfec264d5dcbb0a8ba73f167bc718a6d02f1833af80ab9f51a5f007e5f3b8320e8fc5ab287d4bd59ad497f8949bf4abb9e80
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"nonce": "0x0",
"timestamp": "0x58ee40ba",
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000f86df86994a18182ee8ca476f2f0fb8170a1d4620edb39c5e194065541903bf3bb8c088a18046b441f5d286288c994d1e106d68cac92668b100f6f43791ddcb2c7588094d156777a1e1539fe654fc82266f41fd5d4aa548494efbbd8900222d7b2f75d081c3e7446a1f4fe10ce80c0",
"gasLimit": "700000000",
"gasUsed": "0x0",
"number": "0x0",
"difficulty": "0x1",
"coinbase": "0x0000000000000000000000000000000000000000",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"config": {
"chainId": 1337,
"homesteadBlock": 10,
"eip150Block": 20,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"eip155Block": 25,
"eip158Block": 30,
"byzantiumBlock": 50,
"constantinopleBlock": 60,
"petersburgBlock": 70,
"istanbulBlock": 80,
"ibft": {
"epochlength": 100,
"blockperiodseconds": 5,
"requesttimeoutseconds": 10,
"policy": 0,
"ceil2Nby3Block": 0,
"validatorcontractaddress": "0x0000000000000000000000000000000000000000"
},
"qbft": {
"epochLength": 30000,
"blockPeriodSeconds" : 1,
"requestTimeoutSeconds": 10,
"startBlock": 101
},
"txnSizeLimit": 64,
"maxCodeSize": 0,
"maxCodeSizeConfig": [
{
"block": 0,
"size": 64
}
]
},
"alloc": {
"0xde8e2ae09f2ee2c6c282c054b2384f8b5f9debee": {
"balance": "1000000000000000000000000000"
},
"0x23bcbca17fc4978909ab44ac82559c7d379aa006": {
"balance": "1000000000000000000000000000"
},
"0x870276532cca9f33e66273cfa494cf41e04b5a66": {
"balance": "1000000000000000000000000000"
},
"0x7d7fc9fdfa49e2db22fc6ebab593dcf3aeffbde8": {
"balance": "1000000000000000000000000000"
},
"0x4df76ad0678513846699056e0070c5f587580eb5": {
"balance": "1000000000000000000000000000"
}
}
}
2 changes: 1 addition & 1 deletion acceptance-tests/tests/src/test/resources/qbft/qbft.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
}
1 change: 1 addition & 0 deletions besu/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dependencies {
implementation project(':consensus:clique')
implementation project(':consensus:common')
implementation project(':consensus:ibft')
implementation project(':consensus:ibftlegacy')
implementation project(':consensus:merge')
implementation project(':consensus:qbft')
implementation project(':consensus:qbft-core')
Expand Down
1 change: 1 addition & 0 deletions besu/src/main/java/org/hyperledger/besu/Runner.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ public void startEthereumMainLoop() {
LOG.info("Starting Ethereum main loop ... ");
natService.start();
networkRunner.start();
besuController.getMiningCoordinator().subscribe();
if (networkRunner.getNetwork().isP2pEnabled()) {
besuController.getSynchronizer().start();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,14 +267,19 @@ private void logProgress(final long blockNum) {

private BlockHeader lookupPreviousHeader(
final MutableBlockchain blockchain, final BlockHeader header) {
return blockchain
.getBlockHeader(header.getParentHash())
.orElseThrow(
() ->
new IllegalStateException(
String.format(
"Block %s does not connect to the existing chain. Current chain head %s",
header.getNumber(), blockchain.getChainHeadBlockNumber())));
try {
return blockchain
.getBlockHeader(header.getParentHash())
.orElseThrow(
() ->
new IllegalStateException(
String.format(
"Block %s does not connect to the existing chain. Current chain head %s",
header.getNumber(), blockchain.getChainHeadBlockNumber())));
} catch (IllegalStateException e) {
LOG.info("Block {} does not connect to the existing chain.", header.getNumber());
}
return null;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,7 @@ private BesuControllerBuilder createConsensusScheduleBesuControllerBuilder(
if (configOptions.isIbft2()) {
originalControllerBuilder = new IbftBesuControllerBuilder();
} else if (configOptions.isIbftLegacy()) {
throw new IllegalStateException(
"IBFT1 (legacy) is no longer supported. Consider using IBFT2 or QBFT.");
originalControllerBuilder = new IbftLegacyBesuControllerBuilder();
} else {
throw new IllegalStateException(
"Invalid genesis migration config. Migration is supported from IBFT (legacy) or IBFT2 to QBFT)");
Expand Down
Loading
0