Skip to content
Closed
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
import org.hyperledger.besu.ethereum.mainnet.BalConfiguration;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.config.SubProtocolConfiguration;
import org.hyperledger.besu.ethereum.p2p.network.ProtocolManager;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.SubProtocol;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
Expand Down Expand Up @@ -225,9 +227,37 @@ protected JsonRpcMethods createAdditionalJsonRpcMethodFactory(
protected SubProtocolConfiguration createSubProtocolConfiguration(
final EthProtocolManager ethProtocolManager,
final Optional<SnapProtocolManager> maybeSnapProtocolManager) {
return besuControllerBuilderSchedule
.get(besuControllerBuilderSchedule.keySet().stream().skip(1).findFirst().orElseThrow())
.createSubProtocolConfiguration(ethProtocolManager, maybeSnapProtocolManager);
// During consensus migration, we need BOTH wire protocols registered.
// This allows nodes to communicate before AND after the migration block.
// Previously used .skip(1) which was non-deterministic with HashMap ordering.
//
// We merge all sub-protocol configurations, which registers both:
// - IBF/1 (IBFT2) for pre-migration communication
// - istanbul/100 (QBFT) for post-migration communication
final SubProtocolConfiguration mergedConfig = new SubProtocolConfiguration();
final java.util.Set<String> addedProtocolNames = new java.util.HashSet<>();

// Add sub-protocols from each consensus builder (sorted by block number for determinism)
besuControllerBuilderSchedule.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(
entry -> {
final SubProtocolConfiguration builderConfig =
entry.getValue().createSubProtocolConfiguration(ethProtocolManager, maybeSnapProtocolManager);
final List<SubProtocol> subProtocols = builderConfig.getSubProtocols();
final List<ProtocolManager> protocolManagers = builderConfig.getProtocolManagers();
for (int i = 0; i < subProtocols.size(); i++) {
final SubProtocol subProtocol = subProtocols.get(i);
final ProtocolManager protocolManager = protocolManagers.get(i);
// Only add if not already present (avoid duplicates like EthProtocol)
if (!addedProtocolNames.contains(subProtocol.getName())) {
mergedConfig.withSubProtocol(subProtocol, protocolManager);
addedProtocolNames.add(subProtocol.getName());
}
}
});

return mergedConfig;
}

@Override
Expand Down