Skip to content

Commit 3013b76

Browse files
authored
history-expiry: Prune fast by skipping pruning the transaction locations (#8596)
- Also skip pruning the totalDifficulty, for consistency with how the history expiry sync works - Improve UX - more flexible number of threads default - logging to show settings and remaining blocks estimate Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
1 parent bf6fe36 commit 3013b76

File tree

2 files changed

+31
-34
lines changed

2 files changed

+31
-34
lines changed

besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/PrunePreMergeBlockDataSubCommand.java

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@
1717
import org.hyperledger.besu.cli.config.NetworkName;
1818
import org.hyperledger.besu.cli.util.VersionProvider;
1919
import org.hyperledger.besu.controller.BesuController;
20-
import org.hyperledger.besu.datatypes.Transaction;
20+
import org.hyperledger.besu.datatypes.Hash;
2121
import org.hyperledger.besu.ethereum.chain.BlockchainStorage;
2222

2323
import java.nio.file.Path;
2424
import java.util.List;
25+
import java.util.Optional;
2526
import java.util.concurrent.ExecutorService;
2627
import java.util.concurrent.Executors;
2728

@@ -45,7 +46,7 @@ public class PrunePreMergeBlockDataSubCommand implements Runnable {
4546
private static final long MAINNET_MERGE_BLOCK_NUMBER = 15_537_393;
4647
private static final long SEPOLIA_MERGE_BLOCK_NUMBER = 1_735_371;
4748

48-
private static final int DEFAULT_THREADS = 4;
49+
private static final int DEFAULT_THREADS = Runtime.getRuntime().availableProcessors() - 1;
4950
private static final int DEFAULT_PRUNE_RANGE_SIZE = 10000;
5051

5152
@SuppressWarnings("unused")
@@ -85,6 +86,9 @@ public void run() {
8586
network,
8687
dataPath);
8788
final long mergeBlockNumber = getMergeBlockNumber(network);
89+
LOG.info("Parallelizing with number of threads: {}", threads);
90+
LOG.info("Merge block number: {}", mergeBlockNumber);
91+
LOG.info("Prune range size: {}", pruneRangeSize);
8892

8993
try (BesuController besuController = storageSubCommand.besuCommand.buildController()) {
9094

@@ -97,13 +101,22 @@ public void run() {
97101
besuController.getDataStorageConfiguration());
98102

99103
try (ExecutorService executor = Executors.newFixedThreadPool(threads)) {
104+
// cannot prune genesis block so start at 1
100105
for (long i = 1; i < mergeBlockNumber; i += pruneRangeSize) {
101-
final long headerNumber = i;
106+
LOG.info(
107+
"Starting pruning of block range {} to {}...",
108+
i,
109+
Math.min(i + pruneRangeSize, mergeBlockNumber));
110+
final long startBlockNumber = i;
111+
final long endBlockNumber = Math.min(startBlockNumber + pruneRangeSize, mergeBlockNumber);
102112
executor.submit(
103-
() -> deleteBlockRange(headerNumber, mergeBlockNumber, blockchainStorage));
113+
() ->
114+
deleteBlockRange(
115+
startBlockNumber, endBlockNumber, mergeBlockNumber, blockchainStorage));
104116
}
105117
}
106118
}
119+
LOG.info("Pruning pre-merge blocks and transaction receipts completed");
107120
}
108121

109122
private static long getMergeBlockNumber(final NetworkName network) {
@@ -116,31 +129,25 @@ private static long getMergeBlockNumber(final NetworkName network) {
116129

117130
private void deleteBlockRange(
118131
final long startBlockNumber,
132+
final long endBlockNumber,
119133
final long mergeBlockNumber,
120134
final BlockchainStorage blockchainStorage) {
121135
BlockchainStorage.Updater updater = blockchainStorage.updater();
122136
long headerNumber = startBlockNumber;
123-
final long endBlockNumber = Math.min(startBlockNumber + pruneRangeSize, mergeBlockNumber);
124137
do {
125-
blockchainStorage
126-
.getBlockHash(headerNumber)
127-
.filter((h) -> blockchainStorage.getBlockBody(h).isPresent())
128-
.ifPresent(
129-
(h) -> {
130-
updater.removeTransactionReceipts(h);
131-
updater.removeTotalDifficulty(h);
132-
blockchainStorage
133-
.getBlockBody(h)
134-
.map((bb) -> bb.getTransactions())
135-
.ifPresent(
136-
(transactions) ->
137-
transactions.stream()
138-
.map(Transaction::getHash)
139-
.forEach((th) -> updater.removeTransactionLocation(th)));
140-
updater.removeBlockBody(h);
141-
});
138+
final Optional<Hash> maybeBlockHash = blockchainStorage.getBlockHash(headerNumber);
139+
if (maybeBlockHash.isEmpty()) {
140+
continue;
141+
}
142+
final Hash h = maybeBlockHash.get();
143+
updater.removeTransactionReceipts(h);
144+
updater.removeBlockBody(h);
142145
} while (++headerNumber < endBlockNumber);
143146
updater.commit();
144-
LOG.info("Completed deletion of block range {} to {}", startBlockNumber, endBlockNumber);
147+
LOG.info(
148+
"...completed pruning of block range {} to {}; estimated {} blocks remaining",
149+
startBlockNumber,
150+
endBlockNumber,
151+
mergeBlockNumber - endBlockNumber);
145152
}
146153
}

ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueSegmentIdentifier.java

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
public enum KeyValueSegmentIdentifier implements SegmentIdentifier {
2727
DEFAULT("default".getBytes(StandardCharsets.UTF_8)),
28-
BLOCKCHAIN(new byte[] {1}, true, true),
28+
BLOCKCHAIN(new byte[] {1}, EnumSet.allOf(DataStorageFormat.class), true, true, false),
2929
WORLD_STATE(new byte[] {2}, EnumSet.of(FOREST), false, true, false),
3030
PRIVATE_TRANSACTIONS(new byte[] {3}),
3131
PRIVATE_STATE(new byte[] {4}),
@@ -58,16 +58,6 @@ public enum KeyValueSegmentIdentifier implements SegmentIdentifier {
5858
this(id, EnumSet.allOf(DataStorageFormat.class));
5959
}
6060

61-
KeyValueSegmentIdentifier(
62-
final byte[] id, final boolean containsStaticData, final boolean eligibleToHighSpecFlag) {
63-
this(
64-
id,
65-
EnumSet.allOf(DataStorageFormat.class),
66-
containsStaticData,
67-
eligibleToHighSpecFlag,
68-
false);
69-
}
70-
7161
KeyValueSegmentIdentifier(final byte[] id, final EnumSet<DataStorageFormat> formats) {
7262
this(id, formats, false, false, false);
7363
}

0 commit comments

Comments
 (0)