Skip to content

Commit

Permalink
add caffeine cache for stateroot -> blockHash in CachedTrieLogManager…
Browse files Browse the repository at this point in the history
…, add getByteCodes test for SnapServer

Signed-off-by: garyschulte <[email protected]>
  • Loading branch information
garyschulte committed Oct 3, 2023
1 parent 487095a commit 8381c58
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 12 deletions.
1 change: 1 addition & 0 deletions ethereum/core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ dependencies {

implementation 'com.fasterxml.jackson.core:jackson-databind'
implementation 'com.google.guava:guava'
implementation 'com.github.ben-manes.caffeine:caffeine'
implementation 'com.google.dagger:dagger'
annotationProcessor 'com.google.dagger:dagger-compiler'
implementation 'io.opentelemetry:opentelemetry-api'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
*/
package org.hyperledger.besu.ethereum.bonsai.cache;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiSnapshotWorldStateKeyValueStorage;
Expand All @@ -38,6 +40,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.LongStream;
import java.util.stream.Stream;
Expand All @@ -52,6 +55,10 @@ public class CachedWorldStorageManager extends AbstractTrieLogManager
private static final Logger LOG = LoggerFactory.getLogger(CachedWorldStorageManager.class);
private final BonsaiWorldStateProvider archive;
private final ObservableMetricsSystem metricsSystem;
private final Cache<Hash, Hash> stateRootToBlockHashCache = Caffeine.newBuilder()
.maximumSize(512)
.expireAfterWrite(100, TimeUnit.MINUTES)
.build();

CachedWorldStorageManager(
final BonsaiWorldStateProvider archive,
Expand Down Expand Up @@ -128,6 +135,8 @@ public synchronized void addCachedLayer(
blockHeader,
((BonsaiWorldStateLayerStorage) forWorldState.getWorldStateStorage()).clone()));
}
// add stateroot -> blockHeader cache entry
stateRootToBlockHashCache.put(blockHeader.getStateRoot(), blockHeader.getBlockHash());
}
scrubCachedLayers(blockHeader.getNumber());
}
Expand Down Expand Up @@ -205,7 +214,7 @@ public Optional<BonsaiWorldState> getHeadWorldState(

@Override
public Optional<CachedBonsaiWorldView> getStorageByRootHash(final Optional<Hash> rootHash) {
return rootHash
return rootHash.map(stateRootToBlockHashCache::getIfPresent)
.map(Optional::of)
.orElseGet(rootWorldStateStorage::getWorldStateBlockHash)
.map(cachedWorldStatesByHash::get);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,13 @@ class SnapServer {
worldStateStorageProvider;

SnapServer(final EthMessages snapMessages, final WorldStateArchive archive) {
this.snapMessages = snapMessages;
// TODO remove dirty bonsai cast:
this.worldStateStorageProvider =
this(snapMessages,
rootHash ->
// TODO remove dirty bonsai cast:
((BonsaiWorldStateProvider) archive)
.getTrieLogManager()
.getStorageByRootHash(rootHash)
.map(CachedBonsaiWorldView::getWorldStateStorage);
.map(CachedBonsaiWorldView::getWorldStateStorage));
}

SnapServer(
Expand All @@ -90,6 +89,7 @@ class SnapServer {
worldStateStorageProvider) {
this.snapMessages = snapMessages;
this.worldStateStorageProvider = worldStateStorageProvider;
registerResponseConstructors();
}

private void registerResponseConstructors() {
Expand All @@ -109,10 +109,12 @@ MessageData constructGetAccountRangeResponse(final MessageData message) {
final int maxResponseBytes = Math.min(range.responseBytes().intValue(), MAX_RESPONSE_SIZE);

// TODO: drop to TRACE
LOGGER.info(
"Receive get account range message from {} to {}",
range.startKeyHash().toHexString(),
range.endKeyHash().toHexString());
LOGGER.atInfo()
.setMessage("Receive getAccountRangeMessage for {} from {} to {}")
.addArgument(range.worldStateRootHash()::toHexString)
.addArgument(range.startKeyHash()::toHexString)
.addArgument(range.endKeyHash()::toHexString)
.log();

var worldStateHash = getAccountRangeMessage.range(true).worldStateRootHash();

Expand Down Expand Up @@ -141,9 +143,15 @@ MessageData constructGetAccountRangeResponse(final MessageData message) {
worldStateProof.getAccountProofRelatedNodes(
range.worldStateRootHash(), Hash.wrap(accounts.lastKey())));
}
return AccountRangeMessage.create(accounts, proof);
var resp = AccountRangeMessage.create(accounts, proof);
LOGGER.info("returned message with {} accounts and {} proofs",
accounts.size(), proof.size());
return resp;
})
.orElse(EMPTY_ACCOUNT_RANGE);
.orElseGet(() -> {
LOGGER.info("returned empty account range due to worldstate not present");
return EMPTY_ACCOUNT_RANGE;
});
}

MessageData constructGetStorageRangeResponse(final MessageData message) {
Expand Down Expand Up @@ -211,10 +219,15 @@ MessageData constructGetStorageRangeResponse(final MessageData message) {
.orElse(EMPTY_STORAGE_RANGE);
}

private MessageData constructGetBytecodesResponse(final MessageData message) {
MessageData constructGetBytecodesResponse(final MessageData message) {
// TODO implement once code is stored by hash
final GetByteCodesMessage getByteCodesMessage = GetByteCodesMessage.readFrom(message);
final GetByteCodesMessage.CodeHashes codeHashes = getByteCodesMessage.codeHashes(true);
// TODO: drop to TRACE
LOGGER.atInfo()
.setMessage("Receive get bytecodes message for {} hashes")
.addArgument(codeHashes.hashes()::size)
.log();

// there is no worldstate root or block header for us to use, so default to head. This
// can cause problems for self-destructed contracts pre-shanghai. for now since this impl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
import org.hyperledger.besu.ethereum.eth.manager.EthMessages;
import org.hyperledger.besu.ethereum.eth.messages.snap.AccountRangeMessage;
import org.hyperledger.besu.ethereum.eth.messages.snap.ByteCodesMessage;
import org.hyperledger.besu.ethereum.eth.messages.snap.GetAccountRangeMessage;
import org.hyperledger.besu.ethereum.eth.messages.snap.GetByteCodesMessage;
import org.hyperledger.besu.ethereum.eth.messages.snap.GetStorageRangeMessage;
import org.hyperledger.besu.ethereum.eth.messages.snap.GetTrieNodesMessage;
import org.hyperledger.besu.ethereum.eth.messages.snap.StorageRangeMessage;
Expand Down Expand Up @@ -202,6 +204,19 @@ public void assertStorageTriePathRequest() {
assertThat(trieNodes.size()).isEqualTo(4);
}

@Test
public void assertCodePresent() {
insertTestAccounts(acct1, acct2, acct3, acct4);
var codeRequest = requestByteCodes(
List.of(
acct3.accountValue.getCodeHash(),
acct4.accountValue.getCodeHash()));
assertThat(codeRequest).isNotNull();
ByteCodesMessage.ByteCodes codes = codeRequest.bytecodes(false);
assertThat(codes).isNotNull();
assertThat(codes.codes().size()).isEqualTo(2);
}

static SnapTestAccount createTestAccount(final String hexAddr) {
return new SnapTestAccount(
Hash.wrap(Bytes32.rightPad(Bytes.fromHexString(hexAddr))),
Expand All @@ -225,6 +240,7 @@ static SnapTestAccount createTestContractAccount(
// mock some storage data
var flatdb = storage.getFlatDbStrategy();
var updater = storage.updater();
updater.putCode(Hash.hash(mockCode), mockCode);
IntStream.range(10, 20)
.boxed()
.forEach(
Expand Down Expand Up @@ -314,6 +330,13 @@ TrieNodesMessage requestTrieNodes(final Bytes32 rootHash, final List<List<Bytes>
.wrapMessageData(BigInteger.ONE));
}

ByteCodesMessage requestByteCodes(final List<Bytes32> codeHashes) {
return (ByteCodesMessage)
snapServer.constructGetBytecodesResponse(GetByteCodesMessage.create(
codeHashes)
.wrapMessageData(BigInteger.ONE));
}

AccountRangeMessage.AccountRangeData getAndVerifyAcountRangeData(
final AccountRangeMessage range, final int expectedSize) {
assertThat(range).isNotNull();
Expand Down

0 comments on commit 8381c58

Please sign in to comment.