From fdc753c2bade8fa69772e1eeba6178291a45fb02 Mon Sep 17 00:00:00 2001 From: Mehdi AOUADI Date: Mon, 24 Feb 2025 19:39:51 +0100 Subject: [PATCH] apply inclsuion lists to store --- .../forkchoice/MutableStore.java | 5 +++++ .../forkchoice/TestStoreImpl.java | 10 ++++++++++ .../forkchoice/ForkChoice.java | 11 ++++++---- .../teku/storage/store/CacheableStore.java | 8 ++------ .../pegasys/teku/storage/store/Store.java | 20 ++++++++++--------- .../teku/storage/store/StoreTransaction.java | 12 +++++++++++ .../store/StoreTransactionUpdates.java | 9 +++++++++ .../store/StoreTransactionUpdatesFactory.java | 7 +++++++ 8 files changed, 63 insertions(+), 19 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/forkchoice/MutableStore.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/forkchoice/MutableStore.java index ccfcbe2a246..333ecfeb783 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/forkchoice/MutableStore.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/forkchoice/MutableStore.java @@ -22,6 +22,7 @@ import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState; import tech.pegasys.teku.spec.datastructures.blocks.SlotAndBlockRoot; +import tech.pegasys.teku.spec.datastructures.operations.InclusionList; import tech.pegasys.teku.spec.datastructures.state.Checkpoint; import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState; @@ -67,6 +68,10 @@ default void putBlockAndState( Optional.empty()); } + void putInclusionList(InclusionList inclusionList); + + void putEquivocatedInclusionList(InclusionList equivocatedInclusionList); + void putStateRoot(Bytes32 stateRoot, SlotAndBlockRoot slotAndBlockRoot); void pullUpBlockCheckpoints(Bytes32 blockRoot); diff --git a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/datastructures/forkchoice/TestStoreImpl.java b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/datastructures/forkchoice/TestStoreImpl.java index 3a76b68f27f..b271e25987e 100644 --- a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/datastructures/forkchoice/TestStoreImpl.java +++ b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/datastructures/forkchoice/TestStoreImpl.java @@ -318,6 +318,16 @@ public void putBlockAndState( } } + @Override + public void putInclusionList(final InclusionList inclusionList) { + // NO-OP + } + + @Override + public void putEquivocatedInclusionList(final InclusionList equivocatedInclusionList) { + // NO-OP + } + @Override public void putStateRoot(final Bytes32 stateRoot, final SlotAndBlockRoot slotAndBlockRoot) { // NO-OP diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoice.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoice.java index 2f9063b4ea2..774432d441d 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoice.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoice.java @@ -339,8 +339,8 @@ public SafeFuture onInclusionList( final SlotAndInclusionListCommitteeRoot slotAndInclusionListCommitteeRoot = new SlotAndInclusionListCommitteeRoot( inclusionListSlot, inclusionList.getInclusionListCommitteeRoot()); - final UInt64 validatorIndex = inclusionList.getValidatorIndex(); + if (!store.isInclusionListEquivocator( slotAndInclusionListCommitteeRoot, validatorIndex)) { final Optional> maybeInclusionLists = @@ -350,12 +350,15 @@ public SafeFuture onInclusionList( .filter(il -> il.getValidatorIndex().equals(validatorIndex)) .toList(); if (!inclusionLists.isEmpty() && !inclusionLists.getFirst().equals(inclusionList)) { - // TODO EIP7805 record equivocator in store + final StoreTransaction transaction = recentChainData.startStoreTransaction(); + transaction.putEquivocatedInclusionList(inclusionList); + transaction.commit().join(); } else if (isBeforeFreezeDeadline) { - // TODO EIP7805 record IL in store + final StoreTransaction transaction = recentChainData.startStoreTransaction(); + transaction.putInclusionList(inclusionList); + transaction.commit().join(); } } - return InclusionListImportResult.success(signedInclusionList); }); } diff --git a/storage/src/main/java/tech/pegasys/teku/storage/store/CacheableStore.java b/storage/src/main/java/tech/pegasys/teku/storage/store/CacheableStore.java index 3126545df4c..0a9ca03a3b3 100644 --- a/storage/src/main/java/tech/pegasys/teku/storage/store/CacheableStore.java +++ b/storage/src/main/java/tech/pegasys/teku/storage/store/CacheableStore.java @@ -27,7 +27,6 @@ import tech.pegasys.teku.spec.datastructures.execution.SlotAndExecutionPayloadSummary; import tech.pegasys.teku.spec.datastructures.forkchoice.VoteTracker; import tech.pegasys.teku.spec.datastructures.operations.InclusionList; -import tech.pegasys.teku.spec.datastructures.operations.SlotAndInclusionListCommitteeRoot; /** Store extension dedicated to keep unsafe updates package-private */ public abstract class CacheableStore implements UpdatableStore { @@ -42,12 +41,9 @@ public abstract class CacheableStore implements UpdatableStore { abstract void cacheUnsatisfiedInclusionListBlock(Bytes32 blockRoot); - abstract void cacheInclusionListEquivocator( - SlotAndInclusionListCommitteeRoot slotAndInclusionListCommitteeRoot, UInt64 validatorIndex); + abstract void cacheInclusionListEquivocator(InclusionList inclusionList); - abstract void cacheInclusionList( - SlotAndInclusionListCommitteeRoot slotAndInclusionListCommitteeRoot, - InclusionList inclusionList); + abstract void cacheInclusionList(InclusionList inclusionList); abstract void cacheStates(Map stateAndBlockSummaries); diff --git a/storage/src/main/java/tech/pegasys/teku/storage/store/Store.java b/storage/src/main/java/tech/pegasys/teku/storage/store/Store.java index 24a6dc9bc85..6da501713ba 100644 --- a/storage/src/main/java/tech/pegasys/teku/storage/store/Store.java +++ b/storage/src/main/java/tech/pegasys/teku/storage/store/Store.java @@ -802,21 +802,23 @@ void cacheUnsatisfiedInclusionListBlock(final Bytes32 blockRoot) { /** Non-synchronized, no lock, unsafe if Store is not locked externally */ @Override - void cacheInclusionListEquivocator( - final SlotAndInclusionListCommitteeRoot slotAndInclusionListCommitteeRoot, - final UInt64 validatorIndex) { + void cacheInclusionListEquivocator(final InclusionList inclusionList) { inclusionListEquivocators - .computeIfAbsent(slotAndInclusionListCommitteeRoot, key -> new HashSet<>()) - .add(validatorIndex); + .computeIfAbsent( + new SlotAndInclusionListCommitteeRoot( + inclusionList.getSlot(), inclusionList.getInclusionListCommitteeRoot()), + key -> new HashSet<>()) + .add(inclusionList.getValidatorIndex()); } /** Non-synchronized, no lock, unsafe if Store is not locked externally */ @Override - void cacheInclusionList( - final SlotAndInclusionListCommitteeRoot slotAndInclusionListCommitteeRoot, - final InclusionList inclusionList) { + void cacheInclusionList(final InclusionList inclusionList) { inclusionLists - .computeIfAbsent(slotAndInclusionListCommitteeRoot, key -> new ArrayList<>()) + .computeIfAbsent( + new SlotAndInclusionListCommitteeRoot( + inclusionList.getSlot(), inclusionList.getInclusionListCommitteeRoot()), + key -> new ArrayList<>()) .add(inclusionList); } diff --git a/storage/src/main/java/tech/pegasys/teku/storage/store/StoreTransaction.java b/storage/src/main/java/tech/pegasys/teku/storage/store/StoreTransaction.java index d9cea2eda06..c801e520ae7 100644 --- a/storage/src/main/java/tech/pegasys/teku/storage/store/StoreTransaction.java +++ b/storage/src/main/java/tech/pegasys/teku/storage/store/StoreTransaction.java @@ -74,6 +74,8 @@ class StoreTransaction implements UpdatableStore.StoreTransaction { Set pulledUpBlockCheckpoints = new HashSet<>(); Map blockData = new HashMap<>(); Map> blobSidecars = new HashMap<>(); + Optional maybeInclusionList = Optional.empty(); + Optional maybeEquivocatedInclusionList = Optional.empty(); Optional maybeEarliestBlobSidecarTransactionSlot = Optional.empty(); private final UpdatableStore.StoreUpdateHandler updateHandler; @@ -106,6 +108,16 @@ public void putBlockAndState( putStateRoot(state.hashTreeRoot(), block.getSlotAndBlockRoot()); } + @Override + public void putInclusionList(final InclusionList inclusionList) { + this.maybeInclusionList = Optional.of(inclusionList); + } + + @Override + public void putEquivocatedInclusionList(final InclusionList equivocatedInclusionList) { + this.maybeEquivocatedInclusionList = Optional.of(equivocatedInclusionList); + } + private boolean needToUpdateEarliestBlobSidecarSlot( final Optional maybeNewEarliestBlobSidecarSlot) { // New value is absent - false diff --git a/storage/src/main/java/tech/pegasys/teku/storage/store/StoreTransactionUpdates.java b/storage/src/main/java/tech/pegasys/teku/storage/store/StoreTransactionUpdates.java index ba6c478eb45..9ae517cab23 100644 --- a/storage/src/main/java/tech/pegasys/teku/storage/store/StoreTransactionUpdates.java +++ b/storage/src/main/java/tech/pegasys/teku/storage/store/StoreTransactionUpdates.java @@ -26,6 +26,7 @@ import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState; import tech.pegasys.teku.spec.datastructures.blocks.SlotAndBlockRoot; import tech.pegasys.teku.spec.datastructures.blocks.StateAndBlockSummary; +import tech.pegasys.teku.spec.datastructures.operations.InclusionList; import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState; import tech.pegasys.teku.storage.api.FinalizedChainData; import tech.pegasys.teku.storage.api.StorageUpdate; @@ -43,6 +44,8 @@ class StoreTransactionUpdates { private final Optional maybeEarliestBlobSidecarSlot; private final Map stateRoots; private final Map prunedHotBlockRoots; + private final Optional maybeInclusionList; + private final Optional maybeEquivocatedInclusionList; private final boolean optimisticTransitionBlockRootSet; private final Optional optimisticTransitionBlockRoot; private final boolean blobSidecarsEnabled; @@ -57,6 +60,8 @@ class StoreTransactionUpdates { final Optional maybeEarliestBlobSidecarSlot, final Map prunedHotBlockRoots, final Map stateRoots, + final Optional maybeInclusionList, + final Optional maybeEquivocatedInclusionList, final boolean optimisticTransitionBlockRootSet, final Optional optimisticTransitionBlockRoot, final boolean blobSidecarsEnabled) { @@ -79,6 +84,8 @@ class StoreTransactionUpdates { this.maybeEarliestBlobSidecarSlot = maybeEarliestBlobSidecarSlot; this.prunedHotBlockRoots = prunedHotBlockRoots; this.stateRoots = stateRoots; + this.maybeInclusionList = maybeInclusionList; + this.maybeEquivocatedInclusionList = maybeEquivocatedInclusionList; this.optimisticTransitionBlockRootSet = optimisticTransitionBlockRootSet; this.optimisticTransitionBlockRoot = optimisticTransitionBlockRoot; this.blobSidecarsEnabled = blobSidecarsEnabled; @@ -110,6 +117,8 @@ public void applyToStore(final Store store, final UpdateResult updateResult) { store.cacheBlocks(hotBlocks.values()); store.cacheStates(Maps.transformValues(hotBlockAndStates, this::blockAndStateAsSummary)); store.cacheBlobSidecars(blobSidecars); + maybeInclusionList.ifPresent(store::cacheInclusionList); + maybeEquivocatedInclusionList.ifPresent(store::cacheInclusionListEquivocator); if (optimisticTransitionBlockRootSet) { store.cacheFinalizedOptimisticTransitionPayload( updateResult.getFinalizedOptimisticTransitionPayload()); diff --git a/storage/src/main/java/tech/pegasys/teku/storage/store/StoreTransactionUpdatesFactory.java b/storage/src/main/java/tech/pegasys/teku/storage/store/StoreTransactionUpdatesFactory.java index c1e8d90832f..92538f2b2bf 100644 --- a/storage/src/main/java/tech/pegasys/teku/storage/store/StoreTransactionUpdatesFactory.java +++ b/storage/src/main/java/tech/pegasys/teku/storage/store/StoreTransactionUpdatesFactory.java @@ -33,6 +33,7 @@ import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState; import tech.pegasys.teku.spec.datastructures.blocks.SlotAndBlockRoot; +import tech.pegasys.teku.spec.datastructures.operations.InclusionList; import tech.pegasys.teku.spec.datastructures.state.AnchorPoint; import tech.pegasys.teku.spec.datastructures.state.Checkpoint; import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState; @@ -49,6 +50,8 @@ class StoreTransactionUpdatesFactory { private final Map hotBlockAndStates; private final Map> blobSidecars; private final Optional maybeEarliestBlobSidecarSlot; + private final Optional maybeInclusionList; + private final Optional maybeEquivocatedInclusionList; private final Map stateRoots; private final AnchorPoint latestFinalized; private final Map prunedHotBlockRoots = new ConcurrentHashMap<>(); @@ -72,6 +75,8 @@ public StoreTransactionUpdatesFactory( stateRoots = new ConcurrentHashMap<>(tx.stateRoots); blobSidecars = new ConcurrentHashMap<>(tx.blobSidecars); maybeEarliestBlobSidecarSlot = tx.maybeEarliestBlobSidecarTransactionSlot; + maybeInclusionList = tx.maybeInclusionList; + maybeEquivocatedInclusionList = tx.maybeEquivocatedInclusionList; } public static StoreTransactionUpdates create( @@ -255,6 +260,8 @@ private StoreTransactionUpdates createStoreTransactionUpdates( maybeEarliestBlobSidecarSlot, prunedHotBlockRoots, stateRoots, + maybeInclusionList, + maybeEquivocatedInclusionList, optimisticTransitionBlockRootSet, optimisticTransitionBlockRoot, spec.isMilestoneSupported(SpecMilestone.DENEB));