Skip to content

Commit

Permalink
Process attestations when the state from their target block state is …
Browse files Browse the repository at this point in the history
…available in cache. (#7142)

Co-authored-by: Paul Harris <[email protected]>
  • Loading branch information
ajsutton and rolfyone authored May 13, 2023
1 parent 771dd88 commit 32a8074
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ public void removeIf(final Predicate<K> removalCondition) {
cache.keySet().removeIf(removalCondition);
}

public void clear() {
cache.clear();
}

public interface CacheableTask<K, V> {
/**
* The key that uniquely identifies this task. Two tasks with equal keys should also have
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ public SafeFuture<Optional<BeaconState>> getStateToValidate(
return completedFuture(Optional.empty());
}

// Check if the attestations head block state is already available in cache and usable
if (targetBlockSlot.get().isGreaterThanOrEqualTo(earliestSlot)) {
final Optional<BeaconState> maybeState =
recentChainData.getStore().getBlockStateIfAvailable(targetBlockRoot);
if (maybeState.isPresent()) {
return SafeFuture.completedFuture(maybeState);
}
}

if (isJustificationTooOld(targetBlockRoot, targetBlockSlot.get())) {
// we already justified a more recent slot on all compatible heads
LOG.debug(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,38 @@ void shouldIgnoreAttestationsWithTargetWhichIsAlreadyJustified() {
assertThat(selectedState).isEmpty();
}

@Test
void shouldNotRegenerateStateForAttestationsWithTargetWhichIsAlreadyJustified() {
// Advance the chain far enough that the finalized checkpoint isn't usable
chainUpdater.updateBestBlock(
chainUpdater.advanceChainUntil(spec.computeStartSlotAtEpoch(UInt64.valueOf(3))));

final ChainBuilder forkBuilder = chainBuilder.fork();

final SignedBlockAndState forkBlock =
forkBuilder.generateBlockAtSlot(spec.computeStartSlotAtEpoch(UInt64.valueOf(3)).plus(1));

chainUpdater.saveBlock(forkBlock);

// advance chain head to epoch 5 and justify epoch 4
chainUpdater.advanceChainUntil(spec.computeStartSlotAtEpoch(UInt64.valueOf(5)));
chainUpdater.justifyEpoch(4);

// Attestation slot of the fork block is before an already justified checkpoint
final UInt64 attestationSlot = forkBlock.getSlot();
final Bytes32 blockRoot = forkBlock.getRoot();

final SafeFuture<Optional<BeaconState>> resultWithCache =
selectStateFor(attestationSlot, blockRoot);
assertThatSafeFuture(resultWithCache).isCompletedWithOptionalContaining(forkBlock.getState());

recentChainData.getStore().clearCaches();

final SafeFuture<Optional<BeaconState>> resultWithNoCache =
selectStateFor(attestationSlot, blockRoot);
assertThatSafeFuture(resultWithNoCache).isCompletedWithEmptyOptional();
}

private SafeFuture<Optional<BeaconState>> selectStateFor(
final UInt64 attestationSlot, final Bytes32 blockRoot) {
final AttestationData attestationData = attestationFor(attestationSlot, blockRoot);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,13 @@ public ForkChoiceStrategy getForkChoiceStrategy() {
return forkChoiceStrategy;
}

@Override
public void clearCaches() {
states.clear();
checkpointStates.clear();
blocks.clear();
}

@Override
public StoreTransaction startTransaction(final StorageUpdateChannel storageUpdateChannel) {
return startTransaction(storageUpdateChannel, StoreUpdateHandler.NOOP);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ StoreTransaction startTransaction(
@Override
ForkChoiceStrategy getForkChoiceStrategy();

/** Clears in-memory caches. This is not something you'll want to do in production codee... */
void clearCaches();

interface StoreTransaction extends MutableStore {
SafeFuture<Void> commit();

Expand Down

0 comments on commit 32a8074

Please sign in to comment.