Skip to content

Commit

Permalink
Fork choice and store changes
Browse files Browse the repository at this point in the history
  • Loading branch information
StefanBratanov committed Jan 17, 2025
1 parent 2bc5b57 commit cb0705a
Show file tree
Hide file tree
Showing 36 changed files with 517 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import tech.pegasys.teku.networking.eth2.gossip.subnets.AttestationTopicSubscriber;
import tech.pegasys.teku.networking.eth2.gossip.subnets.SyncCommitteeSubscriptionManager;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.SpecVersion;
import tech.pegasys.teku.spec.datastructures.attestation.ValidatableAttestation;
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlock;
Expand Down Expand Up @@ -302,6 +303,10 @@ public SafeFuture<Optional<PayloadAttesterDuties>> getPayloadAttestationDuties(
if (isSyncActive()) {
return NodeSyncingException.failedFuture();
}
// post ePBS
if (!spec.atEpoch(epoch).getMilestone().isGreaterThanOrEqualTo(SpecMilestone.EIP7732)) {
return SafeFuture.completedFuture(Optional.empty());
}
if (epoch.isGreaterThan(
combinedChainDataClient
.getCurrentEpoch()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright Consensys Software Inc., 2025
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.dataproviders.lookup;

import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.spec.datastructures.execution.SignedExecutionPayloadEnvelope;

public interface ExecutionPayloadEnvelopeProvider {

ExecutionPayloadEnvelopeProvider NOOP =
(roots) -> SafeFuture.completedFuture(Collections.emptyMap());

SafeFuture<Map<Bytes32, SignedExecutionPayloadEnvelope>> getExecutionPayloadEnvelopes(
final Set<Bytes32> blockRoots);

default SafeFuture<Optional<SignedExecutionPayloadEnvelope>> getExecutionPayloadEnvelope(
final Bytes32 blockRoot) {
return getExecutionPayloadEnvelopes(Set.of(blockRoot))
.thenApply(
executionPayloadEnvelopes ->
Optional.ofNullable(executionPayloadEnvelopes.get(blockRoot)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright Consensys Software Inc., 2023
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.dataproviders.lookup;

import java.util.Optional;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.spec.datastructures.execution.SignedExecutionPayloadEnvelope;

public interface SingleExecutionPayloadEnvelopeProvider {
SingleExecutionPayloadEnvelopeProvider NOOP = (blockRoot) -> Optional.empty();

Optional<SignedExecutionPayloadEnvelope> getExecutionPayloadEnvelope(Bytes32 blockRoot);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState;
import tech.pegasys.teku.spec.datastructures.blocks.SignedExecutionPayloadEnvelopeAndState;
import tech.pegasys.teku.spec.datastructures.blocks.SlotAndBlockRoot;
import tech.pegasys.teku.spec.datastructures.execution.SignedExecutionPayloadEnvelope;
import tech.pegasys.teku.spec.datastructures.state.Checkpoint;
import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState;

Expand Down Expand Up @@ -68,8 +69,35 @@ default void putBlockAndState(
Optional.empty());
}

default void putExecutionPayloadEnvelopeAndState(
final SignedExecutionPayloadEnvelopeAndState executionPayloadEnvelopeAndState,
final List<BlobSidecar> blobSidecars,
final BlockCheckpoints checkpoints) {
putExecutionPayloadEnvelopeAndState(
executionPayloadEnvelopeAndState.getExecutionPayloadEnvelope(),
executionPayloadEnvelopeAndState.getState(),
checkpoints,
Optional.of(blobSidecars),
Optional.empty());
}

default void putExecutionPayloadEnvelopeAndState(
final SignedExecutionPayloadEnvelopeAndState executionPayloadEnvelopeAndState,
final BlockCheckpoints checkpoints) {
putExecutionPayloadEnvelopeAndState(
executionPayloadEnvelopeAndState.getExecutionPayloadEnvelope(),
executionPayloadEnvelopeAndState.getState(),
checkpoints,
Optional.empty(),
Optional.empty());
}

void putExecutionPayloadEnvelopeAndState(
final SignedExecutionPayloadEnvelopeAndState executionPayloadEnvelopeAndState);
SignedExecutionPayloadEnvelope executionPayloadEnvelope,
BeaconState state,
BlockCheckpoints blockCheckpoints,
Optional<List<BlobSidecar>> blobSidecars,
Optional<UInt64> earliestBlobSidecarSlot);

void putStateRoot(Bytes32 stateRoot, SlotAndBlockRoot slotAndBlockRoot);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ default UInt64 getGenesisTimeMillis() {

boolean containsBlock(Bytes32 blockRoot);

boolean containsExecutionPayloadEnvelope(Bytes32 blockRoot);

/**
* @return A collection of block roots ordered to guarantee that parent roots will be sorted
* earlier than child roots
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBody;
import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732.BeaconBlockBodyEip7732;
import tech.pegasys.teku.spec.datastructures.execution.SignedExecutionPayloadEnvelope;
import tech.pegasys.teku.spec.datastructures.execution.versions.eip7732.ExecutionPayloadHeaderEip7732;
import tech.pegasys.teku.spec.datastructures.forkchoice.ChildNode;
import tech.pegasys.teku.spec.datastructures.forkchoice.MutableStore;
Expand Down Expand Up @@ -433,6 +434,40 @@ public void applyBlockToStore(
signedBlock, postState, blockCheckpoints, blobSidecars, earliestBlobSidecarsSlot);
}

public void applyExecutionPayloadToStore(
final MutableStore store,
final UInt64 slot,
final SignedExecutionPayloadEnvelope executionPayloadEnvelope,
final BeaconState postState,
final boolean isBlockOptimistic,
final Optional<List<BlobSidecar>> blobSidecars,
final Optional<UInt64> earliestBlobSidecarsSlot) {
BlockCheckpoints blockCheckpoints = epochProcessor.calculateBlockCheckpoints(postState);

// If executionPayloadEnvelope is from a prior epoch, pull up the post-state to next epoch to
// realize new finality
// info
if (miscHelpers
.computeEpochAtSlot(slot)
.isLessThan(miscHelpers.computeEpochAtSlot(getCurrentSlot(store)))) {
blockCheckpoints = blockCheckpoints.realizeNextEpoch();
}

updateCheckpoints(
store,
blockCheckpoints.getJustifiedCheckpoint(),
blockCheckpoints.getFinalizedCheckpoint(),
isBlockOptimistic);

// Add new execution payload to store
store.putExecutionPayloadEnvelopeAndState(
executionPayloadEnvelope,
postState,
blockCheckpoints,
blobSidecars,
earliestBlobSidecarsSlot);
}

private UInt64 getFinalizedCheckpointStartSlot(final ReadOnlyStore store) {
final UInt64 finalizedEpoch = store.getFinalizedCheckpoint().getEpoch();
return miscHelpers.computeStartSlotAtEpoch(finalizedEpoch);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import tech.pegasys.teku.infrastructure.crypto.Hash;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.config.SpecConfig;
import tech.pegasys.teku.spec.config.SpecConfigEip7732;
import tech.pegasys.teku.spec.constants.ValidatorConstants;
import tech.pegasys.teku.spec.datastructures.state.CommitteeAssignment;
import tech.pegasys.teku.spec.datastructures.state.Validator;
Expand Down Expand Up @@ -134,14 +135,13 @@ public Int2ObjectMap<UInt64> getValidatorIndexToPtcAssignmentMap(

final int slotsPerEpoch = specConfig.getSlotsPerEpoch();
final int committeeCountPerSlot = getPtCommitteesPerSlot(state, epoch).intValue();
final BeaconStateAccessorsEip7732 beaconStateAccessorsEip7732 =
BeaconStateAccessorsEip7732.required(beaconStateAccessors);

final UInt64 startSlot = miscHelpers.computeStartSlotAtEpoch(epoch);
for (int slotOffset = 0; slotOffset < slotsPerEpoch; slotOffset++) {
final UInt64 slot = startSlot.plus(slotOffset);
for (int i = 0; i < committeeCountPerSlot; i++) {
final IntList committee = beaconStateAccessorsEip7732.getPtc(state, slot);
final IntList committee =
BeaconStateAccessorsEip7732.required(beaconStateAccessors).getPtc(state, slot);
committee.forEach(j -> assignmentMap.put(j, slot));
}
}
Expand All @@ -152,7 +152,7 @@ private UInt64 getPtCommitteesPerSlot(final BeaconState state, final UInt64 epoc
return MathHelpers.bitFloor(
BeaconStateAccessorsEip7732.required(beaconStateAccessors)
.getCommitteeCountPerSlot(state, epoch)
.min(specConfig.toVersionEip7732().orElseThrow().getPtcSize()));
.min(SpecConfigEip7732.required(specConfig).getPtcSize()));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ public static SpecLogicEip7732 create(
config, schemaDefinitions, beaconStateAccessors, beaconStateMutators);

// Execution payload processing
// EIP7732 TODO: dirty way to leverage Electra operations
// EIP-7732 TODO: dirty way to leverage Electra operations
final BlockProcessorElectra blockProcessorElectra =
new BlockProcessorElectra(
config,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ protected void processOperationsNoValidation(
protected void processExecutionRequests(
final MutableBeaconState state,
final BeaconBlockBody body,
final Supplier<ValidatorExitContext> validatorExitContextSupplier) {
final Supplier<ValidatorExitContext> validatorExitContextSupplier)
throws BlockProcessingException {
final ExecutionRequests executionRequests =
body.getOptionalExecutionRequests()
.orElseThrow(() -> new BlockProcessingException("Execution requests expected"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import tech.pegasys.teku.spec.datastructures.blocks.BlockCheckpoints;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState;
import tech.pegasys.teku.spec.datastructures.blocks.SignedExecutionPayloadEnvelopeAndState;
import tech.pegasys.teku.spec.datastructures.blocks.SlotAndBlockRoot;
import tech.pegasys.teku.spec.datastructures.blocks.StateAndBlockSummary;
import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayload;
Expand Down Expand Up @@ -167,6 +166,12 @@ public boolean containsBlock(final Bytes32 blockRoot) {
return blocks.containsKey(blockRoot);
}

// EIP-7732 TODO: implement
@Override
public boolean containsExecutionPayloadEnvelope(final Bytes32 blockRoot) {
return false;
}

@Override
public List<Bytes32> getOrderedBlockRoots() {
return blocks.values().stream()
Expand Down Expand Up @@ -204,11 +209,11 @@ public SafeFuture<Optional<SignedBeaconBlock>> retrieveSignedBlock(final Bytes32
return SafeFuture.completedFuture(getBlockIfAvailable(blockRoot));
}

// EIP7732 TODO: implement
// EIP-7732 TODO: implement
@Override
public SafeFuture<Optional<SignedExecutionPayloadEnvelope>> retrieveExecutionPayloadEnvelope(
final Bytes32 blockRoot) {
return null;
return SafeFuture.completedFuture(Optional.empty());
}

@Override
Expand Down Expand Up @@ -309,7 +314,11 @@ public void putBlockAndState(

@Override
public void putExecutionPayloadEnvelopeAndState(
final SignedExecutionPayloadEnvelopeAndState executionPayloadEnvelopeAndState) {
final SignedExecutionPayloadEnvelope executionPayloadEnvelope,
final BeaconState state,
final BlockCheckpoints blockCheckpoints,
final Optional<List<BlobSidecar>> blobSidecars,
final Optional<UInt64> earliestBlobSidecarSlot) {
// EIP-7732 TODO: implement
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public Optional<BlobSidecar> getBlobSidecar(final UInt64 index) {
}

public Stream<BlobIdentifier> getMissingBlobSidecars() {
final Optional<Integer> blockCommitmentsCount = getBlockKzgCommitmentsCount();
final Optional<Integer> blockCommitmentsCount = getBlobKzgCommitmentsCount();
checkState(blockCommitmentsCount.isPresent(), "Block must be known to call this method");

return UInt64.range(UInt64.ZERO, UInt64.valueOf(blockCommitmentsCount.get()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,29 @@

package tech.pegasys.teku.statetransition.execution;

import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock;
import tech.pegasys.teku.spec.datastructures.execution.SignedExecutionPayloadEnvelope;
import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannel;
import tech.pegasys.teku.statetransition.block.ReceivedBlockEventsChannel;
import tech.pegasys.teku.statetransition.forkchoice.ForkChoice;
import tech.pegasys.teku.statetransition.validation.ExecutionPayloadValidator;
import tech.pegasys.teku.statetransition.validation.InternalValidationResult;
import tech.pegasys.teku.storage.client.RecentChainData;

public class ExecutionPayloadManager {
public class ExecutionPayloadManager implements ReceivedBlockEventsChannel {
private static final Logger LOG = LogManager.getLogger();

private final Map<Bytes32, SignedExecutionPayloadEnvelope> validatedExecutionPayloadEnvelopes =
new ConcurrentHashMap<>();

private final ExecutionPayloadValidator executionPayloadValidator;
private final ForkChoice forkChoice;
private final RecentChainData recentChainData;
Expand Down Expand Up @@ -59,6 +67,9 @@ public SafeFuture<InternalValidationResult> validateAndImportExecutionPayload(
timestamp ->
recentChainData.onExecutionPayload(signedExecutionPayloadEnvelope, timestamp),
() -> LOG.error("arrivalTimestamp tracking must be enabled to support Eip7732"));
validatedExecutionPayloadEnvelopes.put(
signedExecutionPayloadEnvelope.getMessage().getBeaconBlockRoot(),
signedExecutionPayloadEnvelope);
forkChoice
.onExecutionPayload(signedExecutionPayloadEnvelope, executionLayerChannel)
.finish(err -> LOG.error("Failed to process received execution payload.", err));
Expand All @@ -68,4 +79,17 @@ public SafeFuture<InternalValidationResult> validateAndImportExecutionPayload(
});
return validationResult;
}

public Optional<SignedExecutionPayloadEnvelope> getValidatedExecutionPayloadEnvelope(
final Bytes32 blockRoot) {
return Optional.ofNullable(validatedExecutionPayloadEnvelopes.get(blockRoot));
}

@Override
public void onBlockValidated(final SignedBeaconBlock block) {}

@Override
public void onBlockImported(final SignedBeaconBlock block, final boolean executionOptimistic) {
validatedExecutionPayloadEnvelopes.remove(block.getRoot());
}
}
Loading

0 comments on commit cb0705a

Please sign in to comment.