Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import tech.pegasys.teku.infrastructure.logging.LogFormatter;
import tech.pegasys.teku.infrastructure.ssz.containers.Container2;
import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.datastructures.blocks.SlotAndBlockRoot;
import tech.pegasys.teku.spec.datastructures.type.SszSignature;

public class SignedExecutionPayloadEnvelope
Expand Down Expand Up @@ -47,6 +49,14 @@ public SignedExecutionPayloadEnvelopeSchema getSchema() {
return (SignedExecutionPayloadEnvelopeSchema) super.getSchema();
}

public UInt64 getSlot() {
return getMessage().getSlot();
}

public SlotAndBlockRoot getSlotAndBlockRoot() {
return getMessage().getSlotAndBlockRoot();
}

public String toLogString() {
return LogFormatter.formatExecutionPayload(
getMessage().getSlot(), getMessage().getBeaconBlockRoot(), getMessage().getBuilderIndex());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@

import static tech.pegasys.teku.spec.logic.common.statetransition.availability.DataAndValidationResult.notRequiredResultFuture;

import java.util.Optional;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar;
import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader;
import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof;
import tech.pegasys.teku.spec.datastructures.execution.NewPayloadRequest;
import tech.pegasys.teku.spec.logic.versions.bellatrix.block.OptimisticExecutionPayloadExecutor;
Expand Down Expand Up @@ -56,8 +56,8 @@ public SafeFuture<DataAndValidationResult<ExecutionProof>> getAvailabilityCheckR
};

/**
* Similar to {@link OptimisticExecutionPayloadExecutor#optimisticallyExecute(
* ExecutionPayloadHeader, NewPayloadRequest)}
* Similar to {@link OptimisticExecutionPayloadExecutor#optimisticallyExecute(Optional,
* NewPayloadRequest)}
*
* @return true if data availability check is initiated or false to immediately fail the
* validation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,32 @@

public interface ExecutionPayloadImportResult {

ExecutionPayloadImportResult FAILED_UNKNOWN_BEACON_BLOCK_ROOT =
new FailedExecutionPayloadImportResult(
FailureReason.UNKNOWN_BEACON_BLOCK_ROOT, Optional.empty());

static ExecutionPayloadImportResult failedStateTransition(final Exception cause) {
return new FailedExecutionPayloadImportResult(
FailureReason.FAILED_STATE_TRANSITION, Optional.of(cause));
}

static ExecutionPayloadImportResult failedExecution(final Throwable cause) {
return new FailedExecutionPayloadImportResult(
FailureReason.FAILED_EXECUTION, Optional.of(cause));
}

static ExecutionPayloadImportResult failedDataAvailabilityCheckInvalid(
final Optional<Throwable> cause) {
return new FailedExecutionPayloadImportResult(
FailureReason.FAILED_DATA_AVAILABILITY_CHECK_INVALID, cause);
}

static ExecutionPayloadImportResult failedDataAvailabilityCheckNotAvailable(
final Optional<Throwable> cause) {
return new FailedExecutionPayloadImportResult(
FailureReason.FAILED_DATA_AVAILABILITY_CHECK_NOT_AVAILABLE, cause);
}

static ExecutionPayloadImportResult internalError(final Throwable cause) {
return new FailedExecutionPayloadImportResult(FailureReason.INTERNAL_ERROR, Optional.of(cause));
}
Expand All @@ -28,7 +54,9 @@ static ExecutionPayloadImportResult successful(
}

enum FailureReason {
UNKNOWN_BEACON_BLOCK_ROOT,
FAILED_STATE_TRANSITION,
FAILED_EXECUTION,
FAILED_DATA_AVAILABILITY_CHECK_INVALID,
FAILED_DATA_AVAILABILITY_CHECK_NOT_AVAILABLE,
INTERNAL_ERROR // A catch-all category for unexpected errors (bugs)
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.BlockCheckpoints;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBody;
import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadEnvelope;
import tech.pegasys.teku.spec.datastructures.forkchoice.MutableStore;
import tech.pegasys.teku.spec.datastructures.forkchoice.ProtoNodeData;
import tech.pegasys.teku.spec.datastructures.forkchoice.ReadOnlyForkChoiceStrategy;
Expand Down Expand Up @@ -397,6 +398,13 @@
signedBlock, postState, blockCheckpoints, blobSidecars, earliestBlobSidecarsSlot);
}

public void applyExecutionPayloadToStore(
final MutableStore store,

Check notice

Code scanning / CodeQL

Useless parameter Note test

The parameter 'store' is never used.
final SignedExecutionPayloadEnvelope signedEnvelope,

Check notice

Code scanning / CodeQL

Useless parameter Note test

The parameter 'signedEnvelope' is never used.
final BeaconState postState) {

Check notice

Code scanning / CodeQL

Useless parameter Note test

The parameter 'postState' is never used.
// NO-OP until Gloas
}

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 @@ -165,8 +165,7 @@ public void validateExecutionPayload(
final boolean optimisticallyAccept =
payloadExecutor
.get()
.optimisticallyExecute(
state.getLatestExecutionPayloadHeaderRequired(), payloadToExecute);
.optimisticallyExecute(state.getLatestExecutionPayloadHeader(), payloadToExecute);
if (!optimisticallyAccept) {
throw new BlockProcessingException("Execution payload was not optimistically accepted");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

package tech.pegasys.teku.spec.logic.versions.bellatrix.block;

import java.util.Optional;
import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader;
import tech.pegasys.teku.spec.datastructures.execution.NewPayloadRequest;

Expand All @@ -29,5 +30,6 @@ public interface OptimisticExecutionPayloadExecutor {
* invalidate the payload
*/
boolean optimisticallyExecute(
ExecutionPayloadHeader latestExecutionPayloadHeader, NewPayloadRequest payloadToExecute);
Optional<ExecutionPayloadHeader> latestExecutionPayloadHeader,
NewPayloadRequest payloadToExecute);
}
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,7 @@ public void processUnsignedExecutionPayload(
if (payloadExecutor.isPresent()) {
final NewPayloadRequest payloadToExecute = computeNewPayloadRequest(state, envelope);
final boolean optimisticallyAccept =
// TODO-GLOAS: https://github.com/Consensys/teku/issues/9878
payloadExecutor.get().optimisticallyExecute(null, payloadToExecute);
payloadExecutor.get().optimisticallyExecute(Optional.empty(), payloadToExecute);
if (!optimisticallyAccept) {
throw new ExecutionPayloadProcessingException(
"Execution payload was not optimistically accepted");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,36 @@

package tech.pegasys.teku.spec.logic.versions.gloas.util;

import tech.pegasys.teku.spec.config.SpecConfig;
import tech.pegasys.teku.spec.config.SpecConfigGloas;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock;
import tech.pegasys.teku.spec.logic.common.helpers.BeaconStateAccessors;
import tech.pegasys.teku.spec.logic.common.helpers.MiscHelpers;
import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadEnvelope;
import tech.pegasys.teku.spec.datastructures.forkchoice.MutableStore;
import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState;
import tech.pegasys.teku.spec.logic.common.statetransition.availability.AvailabilityChecker;
import tech.pegasys.teku.spec.logic.common.statetransition.epoch.EpochProcessor;
import tech.pegasys.teku.spec.logic.common.util.AttestationUtil;
import tech.pegasys.teku.spec.logic.versions.fulu.util.ForkChoiceUtilFulu;
import tech.pegasys.teku.spec.logic.versions.gloas.helpers.BeaconStateAccessorsGloas;
import tech.pegasys.teku.spec.logic.versions.gloas.helpers.MiscHelpersGloas;
import tech.pegasys.teku.spec.logic.versions.gloas.statetransition.epoch.EpochProcessorGloas;

public class ForkChoiceUtilGloas extends ForkChoiceUtilFulu {

public ForkChoiceUtilGloas(
final SpecConfig specConfig,
final BeaconStateAccessors beaconStateAccessors,
final EpochProcessor epochProcessor,
final AttestationUtil attestationUtil,
final MiscHelpers miscHelpers) {
final SpecConfigGloas specConfig,
final BeaconStateAccessorsGloas beaconStateAccessors,
final EpochProcessorGloas epochProcessor,
final AttestationUtilGloas attestationUtil,
final MiscHelpersGloas miscHelpers) {
super(specConfig, beaconStateAccessors, epochProcessor, attestationUtil, miscHelpers);
}

@Override
public void applyExecutionPayloadToStore(
final MutableStore store,
final SignedExecutionPayloadEnvelope signedEnvelope,
final BeaconState postState) {
// TODO-GLOAS: https://github.com/Consensys/teku/issues/9878
}

@Override
public AvailabilityChecker<?> createAvailabilityChecker(final SignedBeaconBlock block) {
// TODO-GLOAS: in ePBS, data availability is delayed until the processing of the execution
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,13 @@ public SafeFuture<BlockImportResult> onBlock(
executionLayer));
}

// TODO-GLOAS: https://github.com/Consensys/teku/issues/9878
/** Import an execution payload to the store. */
public SafeFuture<ExecutionPayloadImportResult> onExecutionPayload(
final SignedExecutionPayloadEnvelope signedEnvelope,
final ExecutionLayerChannel executionLayer) {
// just for local interop temporarily return successful import
return SafeFuture.completedFuture(ExecutionPayloadImportResult.successful(signedEnvelope));
return recentChainData
.retrieveStateAtSlot(signedEnvelope.getSlotAndBlockRoot())
.thenCompose(blockState -> onExecutionPayload(signedEnvelope, blockState, executionLayer));
}

public SafeFuture<AttestationProcessingResult> onAttestation(
Expand Down Expand Up @@ -519,6 +519,70 @@ private SafeFuture<BlockImportResult> onBlock(
});
}

/**
* Import an execution payload to the store. The supplied {@code blockState} must be the
* post-state after processing the block whose root is the beacon block root of the execution
* payload
*/
private SafeFuture<ExecutionPayloadImportResult> onExecutionPayload(
final SignedExecutionPayloadEnvelope signedEnvelope,
final Optional<BeaconState> blockState,
final ExecutionLayerChannel executionLayer) {
if (blockState.isEmpty()) {
return SafeFuture.completedFuture(
ExecutionPayloadImportResult.FAILED_UNKNOWN_BEACON_BLOCK_ROOT);
}

final ForkChoiceUtil forkChoiceUtil = spec.atSlot(signedEnvelope.getSlot()).getForkChoiceUtil();

// TODO-GLOAS: https://github.com/Consensys/teku/issues/9878 add a real data availability check
// (not required for devnet-0)
final AvailabilityChecker<?> availabilityChecker = AvailabilityChecker.NOOP_DATACOLUMN_SIDECAR;

availabilityChecker.initiateDataAvailabilityCheck();

final ForkChoicePayloadExecutorGloas payloadExecutor =
ForkChoicePayloadExecutorGloas.create(signedEnvelope, executionLayer);

final BeaconState postState;
try {
postState =
spec.getExecutionPayloadProcessor(signedEnvelope.getSlot())
.processAndVerifyExecutionPayload(
signedEnvelope, blockState.get(), Optional.of(payloadExecutor));
} catch (final StateTransitionException ex) {
final ExecutionPayloadImportResult result =
ExecutionPayloadImportResult.failedStateTransition(ex);
reportInvalidExecutionPayload(signedEnvelope, result);
return SafeFuture.completedFuture(result);
}

final SafeFuture<? extends DataAndValidationResult<?>> dataAndValidationResultFuture =
availabilityChecker
.getAvailabilityCheckResult()
.thenPeek(
result ->
LOG.debug(
"Data availability check for slot: {}, builder: {}, block_root: {} result: {}",
signedEnvelope.getSlot(),
signedEnvelope.getMessage().getBuilderIndex(),
signedEnvelope.getMessage().getBeaconBlockRoot(),
result.toLogString()));

return payloadExecutor
.getExecutionResult()
.thenCombineAsync(
dataAndValidationResultFuture,
(payloadResult, dataAndValidationResult) ->
importExecutionPayloadAndState(
signedEnvelope,
forkChoiceUtil,
postState,
payloadResult,
dataAndValidationResult),
forkChoiceExecutor);
}

private BlockImportResult importBlockAndState(
final SignedBeaconBlock block,
final BeaconState blockSlotState,
Expand Down Expand Up @@ -562,15 +626,11 @@ private BlockImportResult importBlockAndState(
}

switch (dataAndValidationResult.validationResult()) {
case VALID, NOT_REQUIRED ->
LOG.debug("Sidecars validation result: {}", dataAndValidationResult::toLogString);
case NOT_AVAILABLE -> {
LOG.debug("Sidecars validation result: {}", dataAndValidationResult::toLogString);
return BlockImportResult.failedDataAvailabilityCheckNotAvailable(
dataAndValidationResult.cause());
}
case INVALID -> {
LOG.debug("Sidecars validation result: {}", dataAndValidationResult::toLogString);
debugDataDumper.saveInvalidSidecars(dataAndValidationResult.data(), block);
return BlockImportResult.failedDataAvailabilityCheckInvalid(
dataAndValidationResult.cause());
Expand Down Expand Up @@ -640,6 +700,53 @@ private BlockImportResult importBlockAndState(
return result;
}

// TODO-GLOAS: https://github.com/Consensys/teku/issues/9878 it requires potentially more
// validations and more interactions with the store
private ExecutionPayloadImportResult importExecutionPayloadAndState(
final SignedExecutionPayloadEnvelope signedEnvelope,
final ForkChoiceUtil forkChoiceUtil,
final BeaconState postState,
final PayloadValidationResult payloadResult,
final DataAndValidationResult<?> dataAndValidationResult) {
final PayloadStatus payloadStatus = payloadResult.getStatus();

if (payloadStatus.hasInvalidStatus()) {
final ExecutionPayloadImportResult result =
ExecutionPayloadImportResult.failedStateTransition(
new IllegalStateException(
"Invalid ExecutionPayload: "
+ payloadStatus.getValidationError().orElse("No reason provided")));
reportInvalidExecutionPayload(signedEnvelope, result);
return result;
}

if (payloadStatus.hasFailedExecution()) {
return ExecutionPayloadImportResult.failedExecution(
payloadStatus.getFailureCause().orElseThrow());
}

switch (dataAndValidationResult.validationResult()) {
case NOT_AVAILABLE -> {
return ExecutionPayloadImportResult.failedDataAvailabilityCheckNotAvailable(
dataAndValidationResult.cause());
}
case INVALID -> {
return ExecutionPayloadImportResult.failedDataAvailabilityCheckInvalid(
dataAndValidationResult.cause());
}
default -> {}
}

final StoreTransaction transaction = recentChainData.startStoreTransaction();

forkChoiceUtil.applyExecutionPayloadToStore(transaction, signedEnvelope, postState);

// Note: not using thenRun here because we want to ensure each step is on the event thread
transaction.commit().join();

return ExecutionPayloadImportResult.successful(signedEnvelope);
}

// from consensus-specs/fork-choice:
private boolean shouldApplyProposerBoost(
final SignedBeaconBlock block, final StoreTransaction transaction) {
Expand Down Expand Up @@ -806,6 +913,20 @@ private void reportInvalidBlock(final SignedBeaconBlock block, final BlockImport
result.getFailureCause());
}

private void reportInvalidExecutionPayload(
final SignedExecutionPayloadEnvelope signedEnvelope,
final ExecutionPayloadImportResult result) {
debugDataDumper.saveInvalidExecutionPayload(
signedEnvelope, result.getFailureReason().name(), result.getFailureCause());
P2P_LOG.onInvalidExecutionPayload(
signedEnvelope.getSlot(),
signedEnvelope.getMessage().getBuilderIndex(),
signedEnvelope.getMessage().getBeaconBlockRoot(),
signedEnvelope.sszSerialize(),
result.getFailureReason().name(),
result.getFailureCause());
}

private void notifyForkChoiceUpdatedAndOptimisticSyncingChanged(
final Optional<UInt64> proposingSlot) {
final ForkChoiceState forkChoiceState = forkChoiceStateProvider.getForkChoiceStateSync();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class ForkChoicePayloadExecutor implements OptimisticExecutionPayloadExecutor {
private final ExecutionLayerChannel executionLayer;
private final SignedBeaconBlock block;
private final MergeTransitionBlockValidator transitionBlockValidator;

private Optional<SafeFuture<PayloadValidationResult>> result = Optional.empty();

ForkChoicePayloadExecutor(
Expand Down Expand Up @@ -60,7 +61,7 @@ public SafeFuture<PayloadValidationResult> getExecutionResult() {

@Override
public boolean optimisticallyExecute(
final ExecutionPayloadHeader latestExecutionPayloadHeader,
final Optional<ExecutionPayloadHeader> latestExecutionPayloadHeader,
final NewPayloadRequest payloadToExecute) {
final ExecutionPayload executionPayload = payloadToExecute.getExecutionPayload();
if (executionPayload.isDefault()) {
Expand All @@ -77,7 +78,7 @@ public boolean optimisticallyExecute(
result -> {
if (result.hasValidStatus()) {
return transitionBlockValidator.verifyTransitionBlock(
latestExecutionPayloadHeader, block);
latestExecutionPayloadHeader.orElseThrow(), block);
} else {
return SafeFuture.completedFuture(new PayloadValidationResult(result));
}
Expand Down
Loading
Loading