Skip to content

Commit 3fc3fb1

Browse files
gfukushimasiladu
andauthored
Trie log prune async using TrieLogEvent (#6394)
* Change TrieLogPruner to implement a trieLogObserver * Remove TrieLogPruner from TrieLogManager * Remove NoOpTrieLogPruner now it is conditionally added as an observer * Prune async using EthScheduler.servicesExecutor --------- Signed-off-by: Gabriel Fukushima <gabrielfukushima@gmail.com> Signed-off-by: Simon Dudley <simon.dudley@consensys.net> Co-authored-by: Simon Dudley <simon.dudley@consensys.net>
1 parent 1c1f538 commit 3fc3fb1

File tree

11 files changed

+129
-86
lines changed

11 files changed

+129
-86
lines changed

besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
8484
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
8585
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
86+
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
8687
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner;
8788
import org.hyperledger.besu.ethereum.trie.forest.ForestWorldStateArchive;
8889
import org.hyperledger.besu.ethereum.trie.forest.pruner.MarkSweepPruner;
@@ -781,6 +782,15 @@ public BesuController build() {
781782
final JsonRpcMethods additionalJsonRpcMethodFactory =
782783
createAdditionalJsonRpcMethodFactory(protocolContext);
783784

785+
if (dataStorageConfiguration.getUnstable().getBonsaiTrieLogPruningEnabled()
786+
&& DataStorageFormat.BONSAI.equals(dataStorageConfiguration.getDataStorageFormat())) {
787+
final TrieLogManager trieLogManager =
788+
((BonsaiWorldStateProvider) worldStateArchive).getTrieLogManager();
789+
final TrieLogPruner trieLogPruner =
790+
createTrieLogPruner(worldStateStorage, blockchain, scheduler);
791+
trieLogManager.subscribe(trieLogPruner);
792+
}
793+
784794
final List<Closeable> closeables = new ArrayList<>();
785795
closeables.add(protocolContext.getWorldStateArchive());
786796
closeables.add(storageProvider);
@@ -809,6 +819,26 @@ public BesuController build() {
809819
dataStorageConfiguration);
810820
}
811821

822+
private TrieLogPruner createTrieLogPruner(
823+
final WorldStateStorage worldStateStorage,
824+
final Blockchain blockchain,
825+
final EthScheduler scheduler) {
826+
final GenesisConfigOptions genesisConfigOptions = configOptionsSupplier.get();
827+
final boolean isProofOfStake = genesisConfigOptions.getTerminalTotalDifficulty().isPresent();
828+
829+
final TrieLogPruner trieLogPruner =
830+
new TrieLogPruner(
831+
(BonsaiWorldStateKeyValueStorage) worldStateStorage,
832+
blockchain,
833+
scheduler::executeServiceTask,
834+
dataStorageConfiguration.getUnstable().getBonsaiTrieLogRetentionThreshold(),
835+
dataStorageConfiguration.getUnstable().getBonsaiTrieLogPruningLimit(),
836+
isProofOfStake);
837+
trieLogPruner.initialize();
838+
839+
return trieLogPruner;
840+
}
841+
812842
/**
813843
* Create synchronizer synchronizer.
814844
*
@@ -1069,29 +1099,13 @@ WorldStateArchive createWorldStateArchive(
10691099
final Blockchain blockchain,
10701100
final CachedMerkleTrieLoader cachedMerkleTrieLoader) {
10711101
return switch (dataStorageConfiguration.getDataStorageFormat()) {
1072-
case BONSAI -> {
1073-
final GenesisConfigOptions genesisConfigOptions = configOptionsSupplier.get();
1074-
final boolean isProofOfStake =
1075-
genesisConfigOptions.getTerminalTotalDifficulty().isPresent();
1076-
final TrieLogPruner trieLogPruner =
1077-
dataStorageConfiguration.getUnstable().getBonsaiTrieLogPruningEnabled()
1078-
? new TrieLogPruner(
1079-
(BonsaiWorldStateKeyValueStorage) worldStateStorage,
1080-
blockchain,
1081-
dataStorageConfiguration.getUnstable().getBonsaiTrieLogRetentionThreshold(),
1082-
dataStorageConfiguration.getUnstable().getBonsaiTrieLogPruningLimit(),
1083-
isProofOfStake)
1084-
: TrieLogPruner.noOpTrieLogPruner();
1085-
trieLogPruner.initialize();
1086-
yield new BonsaiWorldStateProvider(
1087-
(BonsaiWorldStateKeyValueStorage) worldStateStorage,
1088-
blockchain,
1089-
Optional.of(dataStorageConfiguration.getBonsaiMaxLayersToLoad()),
1090-
cachedMerkleTrieLoader,
1091-
besuComponent.map(BesuComponent::getBesuPluginContext).orElse(null),
1092-
evmConfiguration,
1093-
trieLogPruner);
1094-
}
1102+
case BONSAI -> new BonsaiWorldStateProvider(
1103+
(BonsaiWorldStateKeyValueStorage) worldStateStorage,
1104+
blockchain,
1105+
Optional.of(dataStorageConfiguration.getBonsaiMaxLayersToLoad()),
1106+
cachedMerkleTrieLoader,
1107+
besuComponent.map(BesuComponent::getBesuPluginContext).orElse(null),
1108+
evmConfiguration);
10951109
case FOREST -> {
10961110
final WorldStatePreimageStorage preimageStorage =
10971111
storageProvider.createWorldStatePreimageStorage();

ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/BonsaiWorldStateProvider.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager;
3232
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
3333
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
34-
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner;
3534
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
3635
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
3736
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
@@ -73,18 +72,13 @@ public BonsaiWorldStateProvider(
7372
final Optional<Long> maxLayersToLoad,
7473
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
7574
final BesuContext pluginContext,
76-
final EvmConfiguration evmConfiguration,
77-
final TrieLogPruner trieLogPruner) {
75+
final EvmConfiguration evmConfiguration) {
7876

7977
this.cachedWorldStorageManager = new CachedWorldStorageManager(this, worldStateStorage);
8078
// TODO: de-dup constructors
8179
this.trieLogManager =
8280
new TrieLogManager(
83-
blockchain,
84-
worldStateStorage,
85-
maxLayersToLoad.orElse(RETAINED_LAYERS),
86-
pluginContext,
87-
trieLogPruner);
81+
blockchain, worldStateStorage, maxLayersToLoad.orElse(RETAINED_LAYERS), pluginContext);
8882
this.blockchain = blockchain;
8983
this.worldStateStorage = worldStateStorage;
9084
this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;

ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/trielog/NoOpTrieLogManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
public class NoOpTrieLogManager extends TrieLogManager {
2626

2727
public NoOpTrieLogManager() {
28-
super(null, null, 0, null, TrieLogPruner.noOpTrieLogPruner());
28+
super(null, null, 0, null);
2929
}
3030

3131
@Override

ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/trielog/TrieLogManager.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,16 @@ public class TrieLogManager {
4747
protected final Subscribers<TrieLogEvent.TrieLogObserver> trieLogObservers = Subscribers.create();
4848

4949
protected final TrieLogFactory trieLogFactory;
50-
private final TrieLogPruner trieLogPruner;
5150

5251
public TrieLogManager(
5352
final Blockchain blockchain,
5453
final BonsaiWorldStateKeyValueStorage worldStateStorage,
5554
final long maxLayersToLoad,
56-
final BesuContext pluginContext,
57-
final TrieLogPruner trieLogPruner) {
55+
final BesuContext pluginContext) {
5856
this.blockchain = blockchain;
5957
this.rootWorldStateStorage = worldStateStorage;
6058
this.maxLayersToLoad = maxLayersToLoad;
6159
this.trieLogFactory = setupTrieLogFactory(pluginContext);
62-
this.trieLogPruner = trieLogPruner;
6360
}
6461

6562
public synchronized void saveTrieLog(
@@ -85,8 +82,6 @@ public synchronized void saveTrieLog(
8582
} finally {
8683
if (success) {
8784
stateUpdater.commit();
88-
trieLogPruner.addToPruneQueue(forBlockHeader.getNumber(), forBlockHeader.getBlockHash());
89-
trieLogPruner.pruneFromQueue();
9085
} else {
9186
stateUpdater.rollback();
9287
}

ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/bonsai/trielog/TrieLogPruner.java

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020
import org.hyperledger.besu.ethereum.core.BlockHeader;
2121
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
2222
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
23+
import org.hyperledger.besu.plugin.services.trielogs.TrieLogEvent;
2324

2425
import java.util.Comparator;
2526
import java.util.Optional;
2627
import java.util.concurrent.atomic.AtomicLong;
28+
import java.util.function.Consumer;
2729
import java.util.stream.Stream;
2830

2931
import com.google.common.collect.ArrayListMultimap;
@@ -33,14 +35,15 @@
3335
import org.slf4j.Logger;
3436
import org.slf4j.LoggerFactory;
3537

36-
public class TrieLogPruner {
38+
public class TrieLogPruner implements TrieLogEvent.TrieLogObserver {
3739

3840
private static final Logger LOG = LoggerFactory.getLogger(TrieLogPruner.class);
3941

4042
private final int pruningLimit;
4143
private final int loadingLimit;
4244
private final BonsaiWorldStateKeyValueStorage rootWorldStateStorage;
4345
private final Blockchain blockchain;
46+
private final Consumer<Runnable> executeAsync;
4447
private final long numBlocksToRetain;
4548
private final boolean requireFinalizedBlock;
4649

@@ -50,11 +53,13 @@ public class TrieLogPruner {
5053
public TrieLogPruner(
5154
final BonsaiWorldStateKeyValueStorage rootWorldStateStorage,
5255
final Blockchain blockchain,
56+
final Consumer<Runnable> executeAsync,
5357
final long numBlocksToRetain,
5458
final int pruningLimit,
5559
final boolean requireFinalizedBlock) {
5660
this.rootWorldStateStorage = rootWorldStateStorage;
5761
this.blockchain = blockchain;
62+
this.executeAsync = executeAsync;
5863
this.numBlocksToRetain = numBlocksToRetain;
5964
this.pruningLimit = pruningLimit;
6065
this.loadingLimit = pruningLimit; // same as pruningLimit for now
@@ -166,34 +171,18 @@ int pruneFromQueue() {
166171
return wasPruned.size();
167172
}
168173

169-
public static TrieLogPruner noOpTrieLogPruner() {
170-
return new NoOpTrieLogPruner(null, null, 0, 0);
171-
}
172-
173-
public static class NoOpTrieLogPruner extends TrieLogPruner {
174-
private NoOpTrieLogPruner(
175-
final BonsaiWorldStateKeyValueStorage rootWorldStateStorage,
176-
final Blockchain blockchain,
177-
final long numBlocksToRetain,
178-
final int pruningLimit) {
179-
super(rootWorldStateStorage, blockchain, numBlocksToRetain, pruningLimit, true);
180-
}
181-
182-
@Override
183-
public int initialize() {
184-
// no-op
185-
return -1;
186-
}
187-
188-
@Override
189-
void addToPruneQueue(final long blockNumber, final Hash blockHash) {
190-
// no-op
191-
}
192-
193-
@Override
194-
int pruneFromQueue() {
195-
// no-op
196-
return -1;
174+
@Override
175+
public void onTrieLogAdded(final TrieLogEvent event) {
176+
if (TrieLogEvent.Type.ADDED.equals(event.getType())) {
177+
final Hash blockHash = event.layer().getBlockHash();
178+
final Optional<Long> blockNumber = event.layer().getBlockNumber();
179+
blockNumber.ifPresent(
180+
blockNum ->
181+
executeAsync.accept(
182+
() -> {
183+
addToPruneQueue(blockNum, blockHash);
184+
pruneFromQueue();
185+
}));
197186
}
198187
}
199188
}

ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
3131
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
3232
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
33-
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner;
3433
import org.hyperledger.besu.ethereum.trie.forest.ForestWorldStateArchive;
3534
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
3635
import org.hyperledger.besu.ethereum.trie.forest.worldview.ForestMutableWorldState;
@@ -113,8 +112,7 @@ public static BonsaiWorldStateProvider createBonsaiInMemoryWorldStateArchive(
113112
Optional.empty(),
114113
cachedMerkleTrieLoader,
115114
null,
116-
evmConfiguration,
117-
TrieLogPruner.noOpTrieLogPruner());
115+
evmConfiguration);
118116
}
119117

120118
public static MutableWorldState createInMemoryWorldState() {

ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/bonsai/AbstractIsolationTests.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@
6767
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder;
6868
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
6969
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
70-
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner;
7170
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
7271
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
7372
import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration;
@@ -163,8 +162,7 @@ public void createStorage() {
163162
Optional.of(16L),
164163
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
165164
null,
166-
EvmConfiguration.DEFAULT,
167-
TrieLogPruner.noOpTrieLogPruner());
165+
EvmConfiguration.DEFAULT);
168166
var ws = archive.getMutable();
169167
genesisState.writeStateTo(ws);
170168
protocolContext = new ProtocolContext(blockchain, archive, null, Optional.empty());

ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/bonsai/BonsaiWorldStateArchiveTest.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl;
4343
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer;
4444
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
45-
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner;
4645
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
4746
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
4847
import org.hyperledger.besu.evm.internal.EvmConfiguration;
@@ -127,8 +126,7 @@ storageProvider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_CONFI
127126
Optional.of(512L),
128127
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
129128
null,
130-
EvmConfiguration.DEFAULT,
131-
TrieLogPruner.noOpTrieLogPruner());
129+
EvmConfiguration.DEFAULT);
132130
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
133131
final BlockHeader chainHead = blockBuilder.number(512).buildHeader();
134132
when(blockchain.getChainHeadHeader()).thenReturn(chainHead);

ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/bonsai/trielog/TrieLogManagerTests.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
1717

1818
import static org.assertj.core.api.Assertions.assertThat;
19-
import static org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner.noOpTrieLogPruner;
2019
import static org.mockito.Mockito.spy;
2120

2221
import org.hyperledger.besu.datatypes.Hash;
@@ -57,9 +56,7 @@ class TrieLogManagerTests {
5756

5857
@BeforeEach
5958
public void setup() {
60-
trieLogManager =
61-
new TrieLogManager(
62-
blockchain, bonsaiWorldStateKeyValueStorage, 512, null, noOpTrieLogPruner());
59+
trieLogManager = new TrieLogManager(blockchain, bonsaiWorldStateKeyValueStorage, 512, null);
6360
}
6461

6562
@Test

0 commit comments

Comments
 (0)