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 82393adbcf5..367e5bc58de 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 @@ -416,6 +416,7 @@ public SynchronizerConfiguration.Builder toDomainObject() { .localFlatAccountCountToHealPerRequest(snapsyncFlatAccountHealedCountPerRequest) .localFlatStorageCountToHealPerRequest(snapsyncFlatStorageHealedCountPerRequest) .isFlatDbHealingEnabled(snapsyncFlatDbHealingEnabled) + .isSnapServerEnabled(snapsyncServerEnabled) .build()); builder.checkpointPostMergeEnabled(checkpointPostMergeSyncEnabled); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapServer.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapServer.java index ff2173ebcce..75fc863a100 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapServer.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/snap/SnapServer.java @@ -99,6 +99,15 @@ class SnapServer implements BesuEvents.InitialSyncCompletionListener { this.worldStateStorageCoordinator = worldStateStorageCoordinator; this.protocolContext = Optional.of(protocolContext); registerResponseConstructors(); + + // subscribe to initial sync completed events to start/stop snap server: + this.protocolContext + .flatMap(ProtocolContext::getSynchronizer) + .filter(z -> z instanceof DefaultSynchronizer) + .map(DefaultSynchronizer.class::cast) + .ifPresentOrElse( + z -> this.listenerId.set(z.subscribeInitialSync(this)), + () -> LOGGER.warn("SnapServer created without reference to sync status")); } /** @@ -128,50 +137,43 @@ public void onInitialSyncRestart() { } public synchronized SnapServer start() { - - // if we are bonsai and full flat, we can provide a worldstate storage: - var worldStateKeyValueStorage = worldStateStorageCoordinator.worldStateKeyValueStorage(); - if (worldStateKeyValueStorage.getDataStorageFormat().equals(DataStorageFormat.BONSAI) - && worldStateStorageCoordinator.isMatchingFlatMode(FlatDbMode.FULL)) { - LOGGER.debug("Starting snap server with Bonsai full flat db"); - var bonsaiArchive = - protocolContext - .map(ProtocolContext::getWorldStateArchive) - .map(BonsaiWorldStateProvider.class::cast); - var cachedStorageManagerOpt = - bonsaiArchive.map(archive -> archive.getCachedWorldStorageManager()); - - if (cachedStorageManagerOpt.isPresent()) { - var cachedStorageManager = cachedStorageManagerOpt.get(); - this.worldStateStorageProvider = cachedStorageManager::getStorageByRootHash; - - // when we start we need to build the cache of latest 128 worldstates trielogs-to-root-hash: - var blockchain = protocolContext.map(ProtocolContext::getBlockchain).orElse(null); - - // at startup, prime the latest worldstates by roothash: - cachedStorageManager.primeRootToBlockHashCache(blockchain, PRIME_STATE_ROOT_CACHE_LIMIT); - - // subscribe to initial sync completed events to start/stop snap server: - protocolContext - .flatMap(ProtocolContext::getSynchronizer) - .filter(z -> z instanceof DefaultSynchronizer) - .map(DefaultSynchronizer.class::cast) - .ifPresentOrElse( - z -> this.listenerId.set(z.subscribeInitialSync(this)), - () -> LOGGER.warn("SnapServer created without reference to sync status")); - - var flatDbStrategy = - ((BonsaiWorldStateKeyValueStorage) - worldStateStorageCoordinator.worldStateKeyValueStorage()) - .getFlatDbStrategy(); - if (!flatDbStrategy.isCodeByCodeHash()) { - LOGGER.warn("SnapServer requires code stored by codehash, but it is not enabled"); + if (!isStarted.get()) { + // if we are bonsai and full flat, we can provide a worldstate storage: + var worldStateKeyValueStorage = worldStateStorageCoordinator.worldStateKeyValueStorage(); + if (worldStateKeyValueStorage.getDataStorageFormat().equals(DataStorageFormat.BONSAI) + && worldStateStorageCoordinator.isMatchingFlatMode(FlatDbMode.FULL)) { + LOGGER.debug("Starting snap server with Bonsai full flat db"); + var bonsaiArchive = + protocolContext + .map(ProtocolContext::getWorldStateArchive) + .map(BonsaiWorldStateProvider.class::cast); + var cachedStorageManagerOpt = + bonsaiArchive.map(archive -> archive.getCachedWorldStorageManager()); + + if (cachedStorageManagerOpt.isPresent()) { + var cachedStorageManager = cachedStorageManagerOpt.get(); + this.worldStateStorageProvider = cachedStorageManager::getStorageByRootHash; + + // when we start we need to build the cache of latest 128 worldstates + // trielogs-to-root-hash: + var blockchain = protocolContext.map(ProtocolContext::getBlockchain).orElse(null); + + // at startup, prime the latest worldstates by roothash: + cachedStorageManager.primeRootToBlockHashCache(blockchain, PRIME_STATE_ROOT_CACHE_LIMIT); + + var flatDbStrategy = + ((BonsaiWorldStateKeyValueStorage) + worldStateStorageCoordinator.worldStateKeyValueStorage()) + .getFlatDbStrategy(); + if (!flatDbStrategy.isCodeByCodeHash()) { + LOGGER.warn("SnapServer requires code stored by codehash, but it is not enabled"); + } + } else { + LOGGER.warn( + "SnapServer started without cached storage manager, this should only happen in tests"); } - } else { - LOGGER.warn( - "SnapServer started without cached storage manager, this should only happen in tests"); + isStarted.set(true); } - isStarted.set(true); } return this; } @@ -563,9 +565,9 @@ public boolean test(final Pair pair) { .addArgument(byteLimit::get) .addArgument(recordLimit::get) .log(); - if (stopWatch.getSplitTime() > MAX_MILLIS_PER_REQUEST) { + if (stopWatch.getTime() > MAX_MILLIS_PER_REQUEST) { shouldContinue.set(false); - LOGGER.debug("{} took too long, stopped at {} ms", forWhat, stopWatch.formatSplitTime()); + LOGGER.debug("{} took too long, stopped at {} ms", forWhat, stopWatch.formatTime()); return false; }