From fac9ba1df22ea5ed575c11cd73a6d3774a57a45f Mon Sep 17 00:00:00 2001 From: Matthew Whitehead Date: Fri, 24 May 2024 16:10:21 +0100 Subject: [PATCH 01/23] Create a BFT-specific pivot block handler Signed-off-by: Matthew Whitehead --- .../controller/BesuControllerBuilder.java | 7 +- .../qbft/BFTPivotSelectorFromPeers.java | 105 ++++++++++++++++++ .../eth/sync/DefaultSynchronizer.java | 29 +++-- .../eth/sync/fastsync/FastSyncDownloader.java | 14 ++- .../fastsync/NoSyncRequiredException.java | 17 +++ .../sync/fastsync/NoSyncRequiredState.java | 17 +++ .../sync/fastsync/PivotSelectorFromPeers.java | 6 +- .../eth/sync/snapsync/SnapSyncDownloader.java | 2 +- 8 files changed, 176 insertions(+), 21 deletions(-) create mode 100644 consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/BFTPivotSelectorFromPeers.java create mode 100644 ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/NoSyncRequiredException.java create mode 100644 ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/NoSyncRequiredState.java 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 aab0000592f..a6823fd4fa6 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -22,6 +22,7 @@ import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.consensus.merge.MergeContext; import org.hyperledger.besu.consensus.merge.UnverifiedForkchoiceSupplier; +import org.hyperledger.besu.consensus.qbft.BFTPivotSelectorFromPeers; import org.hyperledger.besu.consensus.qbft.pki.PkiBlockCreationConfiguration; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.datatypes.Hash; @@ -839,7 +840,11 @@ private PivotBlockSelector createPivotSelector( final SyncState syncState, final MetricsSystem metricsSystem) { - if (genesisConfigOptions.getTerminalTotalDifficulty().isPresent()) { + if (genesisConfigOptions.isQbft() || genesisConfigOptions.isIbft2()) { + LOG.info("QBFT is configured, creating initial sync for BFT"); + return new BFTPivotSelectorFromPeers( + ethContext, syncConfig, syncState, metricsSystem, protocolContext, nodeKey); + } else if (genesisConfigOptions.getTerminalTotalDifficulty().isPresent()) { LOG.info("TTD difficulty is present, creating initial sync for PoS"); final MergeContext mergeContext = protocolContext.getConsensusContext(MergeContext.class); diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/BFTPivotSelectorFromPeers.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/BFTPivotSelectorFromPeers.java new file mode 100644 index 00000000000..05d08d20ba1 --- /dev/null +++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/BFTPivotSelectorFromPeers.java @@ -0,0 +1,105 @@ +/* + * 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.consensus.qbft; + +import org.hyperledger.besu.consensus.common.bft.BftContext; +import org.hyperledger.besu.consensus.common.validator.ValidatorProvider; +import org.hyperledger.besu.cryptoservices.NodeKey; +import org.hyperledger.besu.ethereum.ProtocolContext; +import org.hyperledger.besu.ethereum.core.Util; +import org.hyperledger.besu.ethereum.eth.manager.EthContext; +import org.hyperledger.besu.ethereum.eth.manager.EthPeer; +import org.hyperledger.besu.ethereum.eth.manager.EthPeers; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; +import org.hyperledger.besu.ethereum.eth.sync.fastsync.FastSyncState; +import org.hyperledger.besu.ethereum.eth.sync.fastsync.NoSyncRequiredException; +import org.hyperledger.besu.ethereum.eth.sync.fastsync.PivotSelectorFromPeers; +import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; +import org.hyperledger.besu.plugin.services.MetricsSystem; + +import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BFTPivotSelectorFromPeers extends PivotSelectorFromPeers { + + private static final Logger LOG = LoggerFactory.getLogger(BFTPivotSelectorFromPeers.class); + + private final ProtocolContext protocolContext; + private final NodeKey nodeKey; + + public BFTPivotSelectorFromPeers( + final EthContext ethContext, + final SynchronizerConfiguration syncConfig, + final SyncState syncState, + final MetricsSystem metricsSystem, + final ProtocolContext protocolContext, + final NodeKey nodeKey) { + super(ethContext, syncConfig, syncState, metricsSystem); + this.protocolContext = protocolContext; + this.nodeKey = nodeKey; + LOG.info("Creating BFTPivotSelectorFromPeers"); + } + + @Override + public Optional selectNewPivotBlock() { + + final BftContext bftContext = protocolContext.getConsensusContext(BftContext.class); + final ValidatorProvider validatorProvider = bftContext.getValidatorProvider(); + // See if we have a best peer + Optional bestPeer = selectBestPeer(); + + if (bestPeer.isPresent()) { + // For a recently created permissioned chain we can skip snap sync until we're past the + // pivot distance + if (bestPeer.get().chainState().getEstimatedHeight() + <= syncConfig.getFastSyncPivotDistance()) { + throw new NoSyncRequiredException(); + } + + return bestPeer.flatMap(this::fromBestPeer); + } else { + // Treat single-validator as a special case. We are the only node that can produce + // blocks so we won't wait to sync with a non-validator node that may or may not exist + if (validatorProvider.getValidatorsAtHead().size() == 1 + && validatorProvider + .getValidatorsAtHead() + .contains(Util.publicKeyToAddress(nodeKey.getPublicKey()))) { + throw new NoSyncRequiredException(); + } + + // Treat the case where we have min-peer-count peers who don't have a chain-head estimate but who are all validators as not needing to sync + // This is effectively handling the "new chain with N validators" case, but speaks more generally to the BFT case where a BFT chain + // prioritises information from other validators over waiting for non-validator peers to respond. + AtomicInteger peerValidatorCount = new AtomicInteger(); + EthPeers theList = ethContext.getEthPeers(); + theList.getAllActiveConnections().forEach(peer -> { + if (validatorProvider + .getValidatorsAtHead().contains(peer.getPeerInfo().getAddress())) { + peerValidatorCount.getAndIncrement(); + } + }); + if (peerValidatorCount.get() >= syncConfig.getFastSyncMinimumPeerCount()) { + // We have sync-min-peers x validators connected, all of whom have no head estimate. We'll assume this is a new chain + // and skip waiting for any more peers to sync with. + throw new NoSyncRequiredException(); + } + } + + return Optional.empty(); + } +} diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/DefaultSynchronizer.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/DefaultSynchronizer.java index af35898ac22..277e07035e3 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/DefaultSynchronizer.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/DefaultSynchronizer.java @@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.eth.sync.checkpointsync.CheckpointDownloaderFactory; import org.hyperledger.besu.ethereum.eth.sync.fastsync.FastSyncDownloader; import org.hyperledger.besu.ethereum.eth.sync.fastsync.FastSyncState; +import org.hyperledger.besu.ethereum.eth.sync.fastsync.NoSyncRequiredState; import org.hyperledger.besu.ethereum.eth.sync.fastsync.worldstate.FastDownloaderFactory; import org.hyperledger.besu.ethereum.eth.sync.fullsync.FullSyncDownloader; import org.hyperledger.besu.ethereum.eth.sync.fullsync.SyncTerminationCondition; @@ -242,16 +243,24 @@ private CompletableFuture handleSyncResult(final FastSyncState result) { // We've been shutdown which will have triggered the fast sync future to complete return CompletableFuture.completedFuture(null); } - fastSyncDownloader.ifPresent(FastSyncDownloader::deleteFastSyncState); - result - .getPivotBlockHeader() - .ifPresent( - blockHeader -> protocolContext.getWorldStateArchive().resetArchiveStateTo(blockHeader)); - LOG.info( - "Sync completed successfully with pivot block {}", - result.getPivotBlockNumber().getAsLong()); - pivotBlockSelector.close(); - syncState.markInitialSyncPhaseAsDone(); + + if (result instanceof NoSyncRequiredState) { + LOG.info("Sync completed (no sync required)"); + syncState.markInitialSyncPhaseAsDone(); + } else { + fastSyncDownloader.ifPresent(FastSyncDownloader::deleteFastSyncState); + result + .getPivotBlockHeader() + .ifPresent( + blockHeader -> + protocolContext.getWorldStateArchive().resetArchiveStateTo(blockHeader)); + if (result.hasPivotBlockHash()) + LOG.info( + "Sync completed successfully with pivot block {}", + result.getPivotBlockNumber().getAsLong()); + pivotBlockSelector.close(); + syncState.markInitialSyncPhaseAsDone(); + } if (terminationCondition.shouldContinueDownload()) { return startFullSync(); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloader.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloader.java index 7b64f885c29..d4cd0cf6c02 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloader.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloader.java @@ -1,5 +1,5 @@ /* - * Copyright ConsenSys AG. + * 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 @@ -80,7 +80,7 @@ public CompletableFuture start() { if (!running.compareAndSet(false, true)) { throw new IllegalStateException("SyncDownloader already running"); } - LOG.info("Starting sync"); + LOG.info("Starting fast sync"); return start(initialFastSyncState); } @@ -94,7 +94,7 @@ protected CompletableFuture start(final FastSyncState fastSyncSta onBonsai.clearFlatDatabase(); onBonsai.clearTrieLog(); }); - LOG.debug("Start sync with initial sync state {}", fastSyncState); + LOG.info("Start fast sync with initial sync state {}", fastSyncState); return findPivotBlock(fastSyncState, fss -> downloadChainAndWorldState(fastSyncActions, fss)); } @@ -114,15 +114,17 @@ public CompletableFuture findPivotBlock( protected CompletableFuture handleFailure(final Throwable error) { trailingPeerRequirements = Optional.empty(); Throwable rootCause = ExceptionUtils.rootCause(error); - if (rootCause instanceof SyncException) { + if (rootCause instanceof NoSyncRequiredException) { + return CompletableFuture.completedFuture(new NoSyncRequiredState()); + } else if (rootCause instanceof SyncException) { return CompletableFuture.failedFuture(error); } else if (rootCause instanceof StalledDownloadException) { - LOG.debug("Stalled sync re-pivoting to newer block."); + LOG.info("Stalled sync re-pivoting to newer block."); return start(FastSyncState.EMPTY_SYNC_STATE); } else if (rootCause instanceof CancellationException) { return CompletableFuture.failedFuture(error); } else if (rootCause instanceof MaxRetriesReachedException) { - LOG.debug( + LOG.info( "A download operation reached the max number of retries, re-pivoting to newer block"); return start(FastSyncState.EMPTY_SYNC_STATE); } else { diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/NoSyncRequiredException.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/NoSyncRequiredException.java new file mode 100644 index 00000000000..caa45abdc19 --- /dev/null +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/NoSyncRequiredException.java @@ -0,0 +1,17 @@ +/* + * 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.ethereum.eth.sync.fastsync; + +public class NoSyncRequiredException extends RuntimeException {} diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/NoSyncRequiredState.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/NoSyncRequiredState.java new file mode 100644 index 00000000000..9cefe78ed15 --- /dev/null +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/NoSyncRequiredState.java @@ -0,0 +1,17 @@ +/* + * 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.ethereum.eth.sync.fastsync; + +public class NoSyncRequiredState extends FastSyncState {} diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeers.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeers.java index 6402b58d1fd..3410ea3be12 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeers.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeers.java @@ -36,7 +36,7 @@ public class PivotSelectorFromPeers implements PivotBlockSelector { private static final Logger LOG = LoggerFactory.getLogger(PivotSelectorFromPeers.class); private final EthContext ethContext; - private final SynchronizerConfiguration syncConfig; + protected final SynchronizerConfiguration syncConfig; private final SyncState syncState; private final MetricsSystem metricsSystem; @@ -74,7 +74,7 @@ public long getBestChainHeight() { return syncState.bestChainHeight(); } - private Optional fromBestPeer(final EthPeer peer) { + protected Optional fromBestPeer(final EthPeer peer) { final long pivotBlockNumber = peer.chainState().getEstimatedHeight() - syncConfig.getFastSyncPivotDistance(); if (pivotBlockNumber <= BlockHeader.GENESIS_BLOCK_NUMBER) { @@ -86,7 +86,7 @@ private Optional fromBestPeer(final EthPeer peer) { return Optional.of(new FastSyncState(pivotBlockNumber)); } - private Optional selectBestPeer() { + protected Optional selectBestPeer() { return ethContext .getEthPeers() .bestPeerMatchingCriteria(this::canPeerDeterminePivotBlock) diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapSyncDownloader.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapSyncDownloader.java index 00c571f9840..88ea0114b91 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapSyncDownloader.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapSyncDownloader.java @@ -48,7 +48,7 @@ public SnapSyncDownloader( @Override protected CompletableFuture start(final FastSyncState fastSyncState) { - LOG.debug("Start snap sync with initial sync state {}", fastSyncState); + LOG.info("Start snap sync with initial sync state {}", fastSyncState); return findPivotBlock(fastSyncState, fss -> downloadChainAndWorldState(fastSyncActions, fss)); } From 93508552698442c4af267938458c04c2e1975a5c Mon Sep 17 00:00:00 2001 From: Matthew Whitehead Date: Mon, 3 Jun 2024 09:58:40 +0100 Subject: [PATCH 02/23] Change visibility Signed-off-by: Matthew Whitehead --- .../main/java/org/hyperledger/besu/cli/BesuCommand.java | 7 ++++--- .../ethereum/eth/sync/fastsync/PivotSelectorFromPeers.java | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 9e612fea3b2..d0b4d6306e9 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -1553,9 +1553,10 @@ private void validateOptions() { private void validateConsensusSyncCompatibilityOptions() { // snap and checkpoint can't be used with BFT but can for clique - if (genesisConfigOptionsSupplier.get().isIbftLegacy() - || genesisConfigOptionsSupplier.get().isIbft2() - || genesisConfigOptionsSupplier.get().isQbft()) { + if ((genesisConfigOptionsSupplier.get().isIbftLegacy() + || genesisConfigOptionsSupplier.get().isIbft2() + || genesisConfigOptionsSupplier.get().isQbft()) + && genesisConfigOptionsSupplier.get().isEthHash()) { final String errorSuffix = "can't be used with BFT networks"; if (SyncMode.CHECKPOINT.equals(syncMode) || SyncMode.X_CHECKPOINT.equals(syncMode)) { throw new ParameterException( diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeers.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeers.java index 3410ea3be12..a2572a9a880 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeers.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeers.java @@ -35,7 +35,7 @@ public class PivotSelectorFromPeers implements PivotBlockSelector { private static final Logger LOG = LoggerFactory.getLogger(PivotSelectorFromPeers.class); - private final EthContext ethContext; + protected final EthContext ethContext; protected final SynchronizerConfiguration syncConfig; private final SyncState syncState; private final MetricsSystem metricsSystem; From 7530d58939624c67f554fec256db140a1580a37b Mon Sep 17 00:00:00 2001 From: Matthew Whitehead Date: Fri, 7 Jun 2024 13:22:42 +0100 Subject: [PATCH 03/23] Refactor sync-peer-count internal variable to match name, add experimental flag to enabled snap + BFT Signed-off-by: Matthew Whitehead --- .../org/hyperledger/besu/cli/BesuCommand.java | 1 + .../cli/ConfigurationOverviewBuilder.java | 16 ++++++++ .../options/unstable/SynchronizerOptions.java | 25 ++++++++++- .../hyperledger/besu/cli/BesuCommandTest.java | 8 ++-- .../cli/CascadingDefaultProviderTest.java | 4 +- .../cli/options/SynchronizerOptionsTest.java | 2 +- .../qbft/BFTPivotSelectorFromPeers.java | 41 +++++++++++-------- .../eth/sync/SynchronizerConfiguration.java | 18 ++++---- .../eth/sync/fastsync/FastSyncActions.java | 2 +- .../sync/fastsync/PivotSelectorFromPeers.java | 4 +- .../sync/snapsync/SnapSyncConfiguration.java | 7 ++++ .../sync/fastsync/FastSyncActionsTest.java | 4 +- 12 files changed, 94 insertions(+), 38 deletions(-) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index d0b4d6306e9..8e77d1e4544 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -2814,6 +2814,7 @@ && getDataStorageConfiguration().getBonsaiLimitTrieLogsEnabled()) { } builder.setSnapServerEnabled(this.unstableSynchronizerOptions.isSnapsyncServerEnabled()); + builder.setSnapSyncBftEnabled(this.unstableSynchronizerOptions.isSnapSyncBftEnabled()); builder.setTxPoolImplementation(buildTransactionPoolConfiguration().getTxPoolImplementation()); builder.setWorldStateUpdateMode(unstableEvmOptions.toDomainObject().worldUpdaterMode()); diff --git a/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java b/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java index 2d74ae8d26f..b2f89a349e2 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java @@ -56,6 +56,7 @@ public class ConfigurationOverviewBuilder { private long trieLogRetentionLimit = 0; private Integer trieLogsPruningWindowSize = null; private boolean isSnapServerEnabled = false; + private boolean isSnapSyncBftEnabled = false; private TransactionPoolConfiguration.Implementation txPoolImplementation; private EvmConfiguration.WorldUpdaterMode worldStateUpdateMode; private Map environment; @@ -233,6 +234,17 @@ public ConfigurationOverviewBuilder setSnapServerEnabled(final boolean snapServe return this; } + /** + * Sets snap sync BFT enabled/disabled + * + * @param snapSyncBftEnabled bool to indicate if snap sync for BFT is enabled + * @return the builder + */ + public ConfigurationOverviewBuilder setSnapSyncBftEnabled(final boolean snapSyncBftEnabled) { + isSnapSyncBftEnabled = snapSyncBftEnabled; + return this; + } + /** * Sets trie logs pruning window size * @@ -357,6 +369,10 @@ public String build() { lines.add("Experimental Snap Sync server enabled"); } + if (isSnapSyncBftEnabled) { + lines.add("Experimental Snap Sync for BFT enabled"); + } + if (isBonsaiLimitTrieLogsEnabled) { final StringBuilder trieLogPruningString = new StringBuilder(); trieLogPruningString diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/SynchronizerOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/SynchronizerOptions.java index e52839cceb4..38870ec382b 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/SynchronizerOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/SynchronizerOptions.java @@ -85,6 +85,8 @@ public class SynchronizerOptions implements CLIOptions