-
Notifications
You must be signed in to change notification settings - Fork 985
feat(history-expiry): save only headers for pre-merge blocks #8582
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
Changes from 16 commits
cd5beb4
c35fe15
9a7258c
0d1b0a1
c61d998
1f85856
a99c86c
b6d1823
6c6c461
ba6e11b
6212a9f
8b46403
5995e0f
3ef30f1
7b61541
d5692e9
6c3f076
74e6aba
d7fac60
71e8fcc
6b4c69a
600bb7b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| /* | ||
| * 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; | ||
|
|
||
| import static org.hyperledger.besu.util.log.LogUtil.throttledLog; | ||
|
|
||
| import org.hyperledger.besu.ethereum.chain.MutableBlockchain; | ||
| import org.hyperledger.besu.ethereum.core.BlockHeader; | ||
| import org.hyperledger.besu.ethereum.core.Difficulty; | ||
|
|
||
| import java.util.concurrent.atomic.AtomicBoolean; | ||
| import java.util.function.Function; | ||
| import java.util.stream.Stream; | ||
|
|
||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
| /** A step in the synchronization process that saves historical block headers. */ | ||
| public class SavePreMergeHeadersStep implements Function<BlockHeader, Stream<BlockHeader>> { | ||
| private static final Logger LOG = LoggerFactory.getLogger(SavePreMergeHeadersStep.class); | ||
| private final MutableBlockchain blockchain; | ||
| private final long preMergeBlockNumber; | ||
|
|
||
| private final AtomicBoolean shouldLog = new AtomicBoolean(true); | ||
| private static final int LOG_REPEAT_DELAY_SECONDS = 30; | ||
| private static final int LOG_PROGRESS_INTERVAL = 1000; | ||
|
|
||
| public SavePreMergeHeadersStep( | ||
| final MutableBlockchain blockchain, final long preMergeBlockNumber) { | ||
siladu marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| this.blockchain = blockchain; | ||
| this.preMergeBlockNumber = preMergeBlockNumber; | ||
| } | ||
|
|
||
| @Override | ||
| public Stream<BlockHeader> apply(final BlockHeader blockHeader) { | ||
| long blockNumber = blockHeader.getNumber(); | ||
| if (isPostMergeBlock(blockNumber)) { | ||
| return Stream.of(blockHeader); | ||
| } | ||
| storeBlockHeader(blockHeader); | ||
| logProgress(blockHeader); | ||
| return Stream.empty(); | ||
| } | ||
|
|
||
| private boolean isPostMergeBlock(final long blockNumber) { | ||
| return preMergeBlockNumber <= 0 || blockNumber > preMergeBlockNumber; | ||
siladu marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| private void storeBlockHeader(final BlockHeader blockHeader) { | ||
| Difficulty difficulty = blockchain.calculateTotalDifficulty(blockHeader); | ||
| blockchain.unsafeStoreHeader(blockHeader, difficulty, true); | ||
| } | ||
|
|
||
| private void logProgress(final BlockHeader blockHeader) { | ||
| if (blockHeader.getNumber() == preMergeBlockNumber) { | ||
| LOG.info("Pre-merge headers import completed at block {}", blockHeader.toLogString()); | ||
| } else { | ||
| long blockNumber = blockHeader.getNumber(); | ||
| if (blockNumber % LOG_PROGRESS_INTERVAL == 0) { | ||
| double importPercent = (double) (100 * blockNumber) / preMergeBlockNumber; | ||
| throttledLog( | ||
| LOG::info, | ||
| String.format( | ||
| "Pre-merge headers import progress: %d of %d (%.2f%%)", | ||
| blockNumber, preMergeBlockNumber, importPercent), | ||
| shouldLog, | ||
| LOG_REPEAT_DELAY_SECONDS); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,7 @@ | |
| import org.hyperledger.besu.ethereum.eth.sync.DownloadBodiesStep; | ||
| import org.hyperledger.besu.ethereum.eth.sync.DownloadHeadersStep; | ||
| import org.hyperledger.besu.ethereum.eth.sync.DownloadPipelineFactory; | ||
| import org.hyperledger.besu.ethereum.eth.sync.SavePreMergeHeadersStep; | ||
| import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; | ||
| import org.hyperledger.besu.ethereum.eth.sync.fullsync.SyncTerminationCondition; | ||
| import org.hyperledger.besu.ethereum.eth.sync.range.RangeHeadersFetcher; | ||
|
|
@@ -112,8 +113,8 @@ public CompletionStage<Void> startPipeline( | |
| } | ||
|
|
||
| @Override | ||
| public Pipeline<SyncTargetRange> createDownloadPipelineForSyncTarget(final SyncTarget target) { | ||
|
|
||
| public Pipeline<SyncTargetRange> createDownloadPipelineForSyncTarget( | ||
| final SyncState syncState, final SyncTarget target) { | ||
| final int downloaderParallelism = syncConfig.getDownloaderParallelism(); | ||
| final int headerRequestSize = syncConfig.getDownloaderHeaderRequestSize(); | ||
| final int singleHeaderBufferSize = headerRequestSize * downloaderParallelism; | ||
|
|
@@ -139,6 +140,9 @@ public Pipeline<SyncTargetRange> createDownloadPipelineForSyncTarget(final SyncT | |
| metricsSystem); | ||
| final RangeHeadersValidationStep validateHeadersJoinUpStep = | ||
| new RangeHeadersValidationStep(protocolSchedule, protocolContext, detachedValidationPolicy); | ||
| final SavePreMergeHeadersStep savePreMergeHeadersStep = | ||
| new SavePreMergeHeadersStep( | ||
| protocolContext.getBlockchain(), getPreMergeHeaderBlockNumber(syncState)); | ||
| final DownloadBodiesStep downloadBodiesStep = | ||
| new DownloadBodiesStep(protocolSchedule, ethContext, syncConfig, metricsSystem); | ||
| final DownloadReceiptsStep downloadReceiptsStep = | ||
|
|
@@ -167,6 +171,7 @@ public Pipeline<SyncTargetRange> createDownloadPipelineForSyncTarget(final SyncT | |
| "fastSync") | ||
| .thenProcessAsyncOrdered("downloadHeaders", downloadHeadersStep, downloaderParallelism) | ||
| .thenFlatMap("validateHeadersJoin", validateHeadersJoinUpStep, singleHeaderBufferSize) | ||
| .thenFlatMap("savePreMergeHeadersStep", savePreMergeHeadersStep, singleHeaderBufferSize) | ||
jframe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| .inBatches(headerRequestSize) | ||
| .thenProcessAsyncOrdered("downloadBodies", downloadBodiesStep, downloaderParallelism) | ||
| .thenProcessAsyncOrdered("downloadReceipts", downloadReceiptsStep, downloaderParallelism) | ||
|
|
@@ -194,4 +199,10 @@ protected boolean shouldContinueDownloadingFromPeer( | |
| } | ||
| return shouldContinue; | ||
| } | ||
|
|
||
| private long getPreMergeHeaderBlockNumber(final SyncState syncState) { | ||
| return syncConfig.isSavePreMergeHeadersOnlyEnabled() | ||
| ? syncState.getCheckpoint().map(checkpoint -> checkpoint.blockNumber() - 1).orElse(0L) | ||
|
||
| : 0L; | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.