Skip to content

Commit cc2a360

Browse files
committed
Merge branch 'main' of github.com:hyperledger/besu into HeadersBackward
2 parents c2f1b01 + 4e088d6 commit cc2a360

76 files changed

Lines changed: 5603 additions & 611 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22

33
## Unreleased
44

5+
### Breaking Changes
6+
7+
### Upcoming Breaking Changes
8+
- ETC Classic and Mordor network support in Besu is deprecated [#9437](https://github.com/hyperledger/besu/pull/9437)
9+
- Holesky network is deprecated [#9437](https://github.com/hyperledger/besu/pull/9437)
10+
- Sunsetting features - for more context on the reasoning behind the deprecation of these features, including alternative options, read [this blog post](https://www.lfdecentralizedtrust.org/blog/sunsetting-tessera-and-simplifying-hyperledger-besu)
11+
- ETC (Ethereum Classic) network support
12+
- Proof of Work consensus (PoW)
13+
- Clique Block Production (mining) - you will still be able to sync existing Clique networks, but not be a validator or create new Clique networks.
14+
- Fast Sync
15+
16+
### Additions and Improvements
17+
18+
## 25.12.0-RC1
19+
520
### Breaking Changes
621
- Remove these deprecated CLI options [#9385](https://github.com/hyperledger/besu/pull/9385)
722
- Remove`--Xbonsai-parallel-tx-processing-enabled` deprecated since 25.7.0. Use `--bonsai-parallel-tx-processing-enabled` instead.
@@ -32,11 +47,17 @@
3247
- Performance: Optimise `engine_getPayload*` methods and `engine_getBlobsV2` [#9445](https://github.com/hyperledger/besu/pull/9445)
3348
- Add Linea named networks for `linea_mainnet` and `linea_sepolia` [#9436](https://github.com/hyperledger/besu/pull/9436), [#9518](https://github.com/hyperledger/besu/pull/9518)
3449
- Add `eth_subscribe` and `eth_unsubscribe` support to IPC service [#9504](https://github.com/hyperledger/besu/pull/9504)
50+
- Add experimental `callTracer` tracer option to `debug_trace*` methods. Enabled using `--Xenable-extra-debug-tracers=true` option. Issue [#8326][issue_8326] implemented via PR [#8960][PR_8960] and [#9072][PR_9072].
3551

3652
### Bug fixes
53+
- Fix non-deterministic sub-protocol registration during IBFT2 to QBFT consensus migration [#9516](https://github.com/hyperledger/besu/pull/9516)
3754
- Fix loss of colored output in terminal when using `--color-enabled=true` option [#8908](https://github.com/hyperledger/besu/issues/8908)
3855
- Fix an issue where Besu does not support `0x80` as transaction type when decoding eth/69 receipts [#9520](https://github.com/hyperledger/besu/issues/9520)
3956

57+
[issue_8326]: https://github.com/hyperledger/besu/issues/8326
58+
[PR_9072]: https://github.com/hyperledger/besu/pull/9072
59+
[PR_8960]: https://github.com/hyperledger/besu/pull/8960
60+
4061
## 25.11.0
4162

4263
### Breaking Changes
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright contributors to Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.tests.acceptance;
16+
17+
import static org.assertj.core.api.Assertions.assertThat;
18+
19+
import org.hyperledger.besu.plugin.BesuPlugin;
20+
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
21+
import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils;
22+
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
23+
import org.hyperledger.besu.util.BesuVersionUtils;
24+
25+
import java.io.IOException;
26+
import java.util.List;
27+
import java.util.ServiceLoader;
28+
import java.util.stream.Collectors;
29+
30+
import org.junit.jupiter.api.Test;
31+
32+
public class RunVersionTest extends AcceptanceTestBase {
33+
34+
@Test
35+
public void testShowsVersionAndExits() throws IOException {
36+
final BesuNode node =
37+
besu.createPluginsNode(
38+
"run --version",
39+
List.of("testPlugins"),
40+
besuNodeConfigurationBuilder -> besuNodeConfigurationBuilder.run("--version"));
41+
cluster.startConsoleCapture();
42+
cluster.runNodeStart(node);
43+
44+
final var serviceLoader = ServiceLoader.load(BesuPlugin.class);
45+
final var plugins = serviceLoader.stream().map(ServiceLoader.Provider::get).toList();
46+
47+
final var versionOutput =
48+
BesuVersionUtils.version()
49+
+ System.lineSeparator()
50+
+ plugins.stream()
51+
.map(
52+
bp ->
53+
bp.getName().orElseThrow()
54+
+ "/test-plugins/"
55+
+ BesuVersionUtils.shortVersion())
56+
.collect(Collectors.joining(System.lineSeparator()));
57+
58+
WaitUtils.waitFor(5000, () -> node.verify(exitedSuccessfully));
59+
60+
final String consoleContents = cluster.getConsoleContents();
61+
assertThat(consoleContents).startsWith(versionOutput);
62+
}
63+
}

app/src/main/java/org/hyperledger/besu/cli/BesuCommand.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,10 @@
257257
import io.vertx.core.VertxOptions;
258258
import io.vertx.core.json.DecodeException;
259259
import io.vertx.core.json.jackson.DatabindCodec;
260+
import org.apache.logging.log4j.Level;
261+
import org.apache.logging.log4j.LogManager;
262+
import org.apache.logging.log4j.core.LoggerContext;
263+
import org.apache.logging.log4j.core.impl.Log4jContextFactory;
260264
import org.apache.tuweni.bytes.Bytes;
261265
import org.apache.tuweni.units.bigints.UInt256;
262266
import org.slf4j.Logger;
@@ -853,13 +857,40 @@ private IExecutionStrategy createExecuteTask(final IExecutionStrategy nextStep)
853857

854858
private IExecutionStrategy createPluginRegistrationTask(final IExecutionStrategy nextStep) {
855859
return parseResult -> {
860+
if (parseResult.isUsageHelpRequested() || parseResult.isVersionHelpRequested()) {
861+
// suppressing the info log to avoid that plugin registrations logs are printed
862+
// before the help or the version information
863+
suppressInfoLog();
864+
}
856865
besuPluginContext.initialize(PluginsConfigurationOptions.fromCommandLine(commandLine));
857866
besuPluginContext.registerPlugins();
858867
commandLine.setExecutionStrategy(nextStep);
859868
return commandLine.execute(parseResult.originalArgs().toArray(new String[0]));
860869
};
861870
}
862871

872+
@SuppressWarnings("BannedMethod")
873+
private void suppressInfoLog() {
874+
// this is specific for Log4j2, in case we switch to another logging framework,
875+
// this need to be adapted for it
876+
877+
// silence already created loggers
878+
LoggerContext.getContext(false).getLoggers().forEach(logger -> logger.setLevel(Level.WARN));
879+
880+
// silence future loggers by configuration
881+
if (LogManager.getFactory() instanceof Log4jContextFactory log4jContextFactory) {
882+
final var selector = log4jContextFactory.getSelector();
883+
selector
884+
.getLoggerContexts()
885+
.forEach(
886+
ctx ->
887+
ctx.getConfiguration()
888+
.getLoggers()
889+
.values()
890+
.forEach(loggerConfig -> loggerConfig.setLevel(Level.WARN)));
891+
}
892+
}
893+
863894
private IExecutionStrategy createDefaultValueProviderTask(final IExecutionStrategy nextStep) {
864895
return new ConfigDefaultValueProviderStrategy(nextStep, environment);
865896
}

app/src/main/java/org/hyperledger/besu/cli/util/VersionProvider.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ public String[] getVersion() {
3939
// the PluginVersionsProvider has registered plugins and their versions by this time.
4040
return Stream.concat(
4141
Stream.of(BesuVersionUtils.version()),
42-
pluginVersionsProvider.getPluginVersions().stream())
42+
pluginVersionsProvider.getPluginVersions().entrySet().stream()
43+
.map(e -> e.getKey() + "/" + e.getValue()))
4344
.toArray(String[]::new);
4445
}
4546
}

app/src/main/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilder.java

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
import org.hyperledger.besu.ethereum.mainnet.BalConfiguration;
5050
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
5151
import org.hyperledger.besu.ethereum.p2p.config.SubProtocolConfiguration;
52+
import org.hyperledger.besu.ethereum.p2p.network.ProtocolManager;
53+
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.SubProtocol;
5254
import org.hyperledger.besu.ethereum.storage.StorageProvider;
5355
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
5456
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
@@ -61,10 +63,12 @@
6163
import java.nio.file.Path;
6264
import java.time.Clock;
6365
import java.util.HashMap;
66+
import java.util.HashSet;
6467
import java.util.List;
6568
import java.util.Map;
6669
import java.util.NavigableSet;
6770
import java.util.Optional;
71+
import java.util.Set;
6872
import java.util.TreeSet;
6973
import java.util.function.BiFunction;
7074
import java.util.stream.Collectors;
@@ -225,9 +229,39 @@ protected JsonRpcMethods createAdditionalJsonRpcMethodFactory(
225229
protected SubProtocolConfiguration createSubProtocolConfiguration(
226230
final EthProtocolManager ethProtocolManager,
227231
final Optional<SnapProtocolManager> maybeSnapProtocolManager) {
228-
return besuControllerBuilderSchedule
229-
.get(besuControllerBuilderSchedule.keySet().stream().skip(1).findFirst().orElseThrow())
230-
.createSubProtocolConfiguration(ethProtocolManager, maybeSnapProtocolManager);
232+
// During consensus migration, we need BOTH wire protocols registered.
233+
// This allows nodes to communicate before AND after the migration block.
234+
// Previously used .skip(1) which was non-deterministic with HashMap ordering.
235+
//
236+
// We merge all sub-protocol configurations, which registers both:
237+
// - IBF/1 (IBFT2) for pre-migration communication
238+
// - istanbul/100 (QBFT) for post-migration communication
239+
final SubProtocolConfiguration mergedConfig = new SubProtocolConfiguration();
240+
final Set<String> addedProtocolNames = new HashSet<>();
241+
242+
// Add sub-protocols from each consensus builder (sorted by block number for determinism)
243+
besuControllerBuilderSchedule.entrySet().stream()
244+
.sorted(Map.Entry.comparingByKey())
245+
.forEach(
246+
entry -> {
247+
final SubProtocolConfiguration builderConfig =
248+
entry
249+
.getValue()
250+
.createSubProtocolConfiguration(ethProtocolManager, maybeSnapProtocolManager);
251+
final List<SubProtocol> subProtocols = builderConfig.getSubProtocols();
252+
final List<ProtocolManager> protocolManagers = builderConfig.getProtocolManagers();
253+
for (int i = 0; i < subProtocols.size(); i++) {
254+
final SubProtocol subProtocol = subProtocols.get(i);
255+
final ProtocolManager protocolManager = protocolManagers.get(i);
256+
// Only add if not already present (avoid duplicates like EthProtocol)
257+
if (!addedProtocolNames.contains(subProtocol.getName())) {
258+
mergedConfig.withSubProtocol(subProtocol, protocolManager);
259+
addedProtocolNames.add(subProtocol.getName());
260+
}
261+
}
262+
});
263+
264+
return mergedConfig;
231265
}
232266

233267
@Override

app/src/main/java/org/hyperledger/besu/services/BesuPluginContextImpl.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@
3030
import java.nio.file.Files;
3131
import java.nio.file.Path;
3232
import java.util.ArrayList;
33-
import java.util.Collection;
3433
import java.util.Collections;
3534
import java.util.HashMap;
3635
import java.util.Iterator;
36+
import java.util.LinkedHashMap;
3737
import java.util.List;
3838
import java.util.Map;
3939
import java.util.NoSuchElementException;
@@ -84,7 +84,7 @@ private enum Lifecycle {
8484

8585
private final List<BesuPlugin> registeredPlugins = new ArrayList<>();
8686

87-
private final List<String> pluginVersions = new ArrayList<>();
87+
private final Map<String, String> pluginVersions = new LinkedHashMap<>();
8888
private PluginConfiguration config;
8989

9090
/** Instantiates a new Besu plugin context. */
@@ -206,7 +206,7 @@ private void registerPlugins(final List<BesuPlugin> pluginsToRegister) {
206206
private boolean registerPlugin(final BesuPlugin plugin) {
207207
try {
208208
plugin.register(this);
209-
pluginVersions.add(plugin.getVersion());
209+
pluginVersions.put(plugin.getName().orElse("<Unnamed Plugin>"), plugin.getVersion());
210210
LOG.info("Registered plugin of type {}.", plugin.getClass().getName());
211211
} catch (final Exception e) {
212212
if (config.isContinueOnPluginError()) {
@@ -378,8 +378,8 @@ private Optional<ClassLoader> pluginDirectoryLoader(final Path pluginsDir) {
378378
}
379379

380380
@Override
381-
public Collection<String> getPluginVersions() {
382-
return Collections.unmodifiableList(pluginVersions);
381+
public Map<String, String> getPluginVersions() {
382+
return Collections.unmodifiableMap(pluginVersions);
383383
}
384384

385385
/**

app/src/test/java/org/hyperledger/besu/cli/util/BesuCommandCustomFactoryTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
import org.hyperledger.besu.plugin.services.PluginVersionsProvider;
2121
import org.hyperledger.besu.util.BesuVersionUtils;
2222

23-
import java.util.Arrays;
24-
23+
import com.google.common.collect.ImmutableMap;
2524
import org.junit.jupiter.api.BeforeEach;
2625
import org.junit.jupiter.api.Test;
2726
import org.junit.jupiter.api.extension.ExtendWith;
@@ -35,7 +34,8 @@ public class BesuCommandCustomFactoryTest {
3534

3635
@BeforeEach
3736
public void initMocks() {
38-
when(pluginVersionsProvider.getPluginVersions()).thenReturn(Arrays.asList("v1", "v2"));
37+
when(pluginVersionsProvider.getPluginVersions())
38+
.thenReturn(ImmutableMap.of("plugin1", "v1", "plugin2", "v2"));
3939
}
4040

4141
@Test
@@ -44,6 +44,6 @@ public void testCreateVersionProviderInstance() throws Exception {
4444
new BesuCommandCustomFactory(pluginVersionsProvider);
4545
final VersionProvider versionProvider = besuCommandCustomFactory.create(VersionProvider.class);
4646
assertThat(versionProvider.getVersion())
47-
.containsExactly(BesuVersionUtils.version(), "v1", "v2");
47+
.containsExactly(BesuVersionUtils.version(), "plugin1/v1", "plugin2/v2");
4848
}
4949
}

app/src/test/java/org/hyperledger/besu/cli/util/VersionProviderTest.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*/
1515
package org.hyperledger.besu.cli.util;
1616

17-
import static java.util.Collections.emptyList;
17+
import static java.util.Collections.emptyMap;
1818
import static org.assertj.core.api.Assertions.assertThat;
1919
import static org.mockito.Mockito.when;
2020

@@ -35,15 +35,17 @@ public class VersionProviderTest {
3535

3636
@Test
3737
public void validateEmptyListGenerateBesuInfoVersionOnly() {
38-
when(pluginVersionsProvider.getPluginVersions()).thenReturn(emptyList());
38+
when(pluginVersionsProvider.getPluginVersions()).thenReturn(emptyMap());
3939
final VersionProvider versionProvider = new VersionProvider(pluginVersionsProvider);
4040
assertThat(versionProvider.getVersion()).containsOnly(BesuVersionUtils.version());
4141
}
4242

4343
@Test
4444
public void validateVersionListGenerateValidValues() {
45-
when(pluginVersionsProvider.getPluginVersions()).thenReturn(Collections.singletonList("test"));
45+
when(pluginVersionsProvider.getPluginVersions())
46+
.thenReturn(Collections.singletonMap("plugin", "test"));
4647
final VersionProvider versionProvider = new VersionProvider(pluginVersionsProvider);
47-
assertThat(versionProvider.getVersion()).containsExactly(BesuVersionUtils.version(), "test");
48+
assertThat(versionProvider.getVersion())
49+
.containsExactly(BesuVersionUtils.version(), "plugin/test");
4850
}
4951
}

app/src/test/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilderTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
3838
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
3939
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
40+
import org.hyperledger.besu.ethereum.p2p.config.SubProtocolConfiguration;
41+
import org.hyperledger.besu.ethereum.p2p.network.ProtocolManager;
42+
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.SubProtocol;
4043
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
4144

4245
import java.math.BigInteger;
@@ -201,4 +204,35 @@ public void createsMigratingContext() {
201204
assertThat(contextSchedule.getFork(10).getValue()).isSameAs(context2);
202205
assertThat(contextSchedule.getFork(11).getValue()).isSameAs(context2);
203206
}
207+
208+
@Test
209+
public void createsSubProtocolConfigurationWithAllSubProtocols() {
210+
final Map<Long, BesuControllerBuilder> consensusSchedule =
211+
Map.of(0L, besuControllerBuilder1, 50L, besuControllerBuilder2);
212+
213+
final SubProtocol subProtocol1 = mock(SubProtocol.class);
214+
final SubProtocol subProtocol2 = mock(SubProtocol.class);
215+
when(subProtocol1.getName()).thenReturn("IBF");
216+
when(subProtocol2.getName()).thenReturn("istanbul");
217+
218+
final SubProtocolConfiguration config1 = new SubProtocolConfiguration();
219+
config1.withSubProtocol(subProtocol1, mock(ProtocolManager.class));
220+
221+
final SubProtocolConfiguration config2 = new SubProtocolConfiguration();
222+
config2.withSubProtocol(subProtocol2, mock(ProtocolManager.class));
223+
224+
when(besuControllerBuilder1.createSubProtocolConfiguration(any(), any())).thenReturn(config1);
225+
when(besuControllerBuilder2.createSubProtocolConfiguration(any(), any())).thenReturn(config2);
226+
227+
final ConsensusScheduleBesuControllerBuilder builder =
228+
new ConsensusScheduleBesuControllerBuilder(consensusSchedule);
229+
230+
final SubProtocolConfiguration result =
231+
builder.createSubProtocolConfiguration(mock(EthProtocolManager.class), Optional.empty());
232+
233+
assertThat(result.getSubProtocols()).hasSize(2);
234+
assertThat(result.getSubProtocols())
235+
.extracting(SubProtocol::getName)
236+
.containsExactlyInAnyOrder("IBF", "istanbul");
237+
}
204238
}

0 commit comments

Comments
 (0)