Skip to content
Draft
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 @@ -167,7 +167,8 @@ public static SyncingNodeManager create(
blockValidator,
timeProvider,
EVENT_LOG,
Optional.empty());
Optional.empty(),
spec);

eventChannels
.subscribe(SlotEventsChannel.class, blockManager)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public SafeFuture<SendSignedBlockResult> sendSignedBlock(
final BroadcastValidationLevel broadcastValidationLevel,
final BlockPublishingPerformance blockPublishingPerformance) {

LOG.info("BroadcastValidationLevel:{}", broadcastValidationLevel);
if (broadcastValidationLevel == BroadcastValidationLevel.NOT_REQUIRED) {
// when broadcast validation is disabled, we can publish the block (and blob sidecars)
// immediately and then import
Expand Down Expand Up @@ -118,6 +119,7 @@ public SafeFuture<SendSignedBlockResult> sendSignedBlock(
.thenAccept(
broadcastValidationResult -> {
if (broadcastValidationResult == BroadcastValidationResult.SUCCESS) {
LOG.info("Publishing block, {}", broadcastValidationResult);
publishBlockAndBlobs(block, blobSidecars, blockPublishingPerformance);
LOG.debug("Block (and blob sidecars) publishing initiated");
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,18 @@

import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.regex.Pattern;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
import tech.pegasys.teku.ethereum.execution.types.Eth1Address;
import tech.pegasys.teku.infrastructure.collections.Interval;
import tech.pegasys.teku.infrastructure.exceptions.InvalidConfigurationException;
import tech.pegasys.teku.infrastructure.http.UrlSanitizer;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
Expand Down Expand Up @@ -380,6 +383,7 @@ public static class Builder {
private Optional<UInt64> terminalBlockHashEpochOverride = Optional.empty();
private int safeSlotsToImportOptimistically = DEFAULT_SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY;
private String epochsStoreBlobs;
private String incidentIntervals = "";
private Spec spec;
private boolean forkChoiceLateBlockReorgEnabled = DEFAULT_FORK_CHOICE_LATE_BLOCK_REORG_ENABLED;
private boolean forkChoiceUpdatedAlwaysSendPayloadAttributes =
Expand All @@ -390,11 +394,27 @@ public void spec(final Spec spec) {
}

public Eth2NetworkConfiguration build() {
return build(false);
}

// TODO: remove unchecked and param
@SuppressWarnings("unchecked")
public Eth2NetworkConfiguration build(final boolean isDbExists) {
checkNotNull(constants, "Missing constants");
validateCommandLineParameters();

final Optional<Integer> maybeEpochsStoreBlobs =
validateAndParseEpochsStoreBlobs(epochsStoreBlobs);

// TODO: remove hack, parameters should be always parsed
final Interval<UInt64>[] intervals;
if (isDbExists) {
intervals = parseIntervals();
} else {
intervals = (Interval<UInt64>[]) new Interval<?>[] {};
}
Interval.checkIntervalsIntersection(intervals);

if (spec == null) {
spec =
SpecFactory.create(
Expand Down Expand Up @@ -428,6 +448,10 @@ public Eth2NetworkConfiguration build() {
if (maybeEpochsStoreBlobs.isPresent()) {
denebBuilder.epochsStoreBlobs(maybeEpochsStoreBlobs);
}
if (intervals.length > 0) {
denebBuilder.incidentIntervals(Arrays.asList(intervals));
LOG.warn("Using incident intervals: {}", Arrays.asList(intervals));
}
if (trustedSetup.isEmpty()) {
LOG.warn(
"Setting a default for trusted setup as nothing was set explicitly");
Expand Down Expand Up @@ -482,6 +506,25 @@ public Eth2NetworkConfiguration build() {
forkChoiceUpdatedAlwaysSendPayloadAttributes);
}

@SuppressWarnings({"unchecked", "StringSplitter"})
private Interval<UInt64>[] parseIntervals() {
return (Interval<UInt64>[])
Arrays.stream(incidentIntervals.split(","))
.filter(s -> !s.isEmpty())
.map(
intervalString -> {
final String[] intervalParts = intervalString.split(Pattern.quote("-"));
if (intervalParts.length != 2) {
throw new IllegalArgumentException(
String.format("Cannot parse interval: %s", intervalString));
}
final long start = Long.parseLong(intervalParts[0]);
final long end = Long.parseLong(intervalParts[1]);
return new Interval<>(UInt64.valueOf(start), UInt64.valueOf(end));
})
.toArray(Interval<?>[]::new);
}

private void validateCommandLineParameters() {
checkArgument(
safeSlotsToImportOptimistically >= 0, "Safe slots to import optimistically must be >= 0");
Expand Down Expand Up @@ -710,6 +753,11 @@ public Builder epochsStoreBlobs(final String epochsStoreBlobs) {
return this;
}

public Builder incidentIntervals(final String incidentIntervals) {
this.incidentIntervals = incidentIntervals;
return this;
}

public Builder applyNetworkDefaults(final String networkName) {
Eth2Network.fromStringLenient(networkName)
.ifPresentOrElse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@

package tech.pegasys.teku.spec.config;

import java.util.List;
import java.util.Optional;
import tech.pegasys.teku.infrastructure.bytes.Bytes4;
import tech.pegasys.teku.infrastructure.collections.Interval;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;

public class DelegatingSpecConfigDeneb extends DelegatingSpecConfigCapella
Expand Down Expand Up @@ -71,6 +73,11 @@ public int getEpochsStoreBlobs() {
return specConfigDeneb.getEpochsStoreBlobs();
}

@Override
public List<Interval<UInt64>> getIncidentIntervals() {
return specConfigDeneb.getIncidentIntervals();
}

@Override
public int getMaxRequestBlocksDeneb() {
return specConfigDeneb.getMaxRequestBlocksDeneb();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
package tech.pegasys.teku.spec.config;

import java.math.BigInteger;
import java.util.List;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import tech.pegasys.teku.infrastructure.bytes.Bytes4;
import tech.pegasys.teku.infrastructure.collections.Interval;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;

public interface SpecConfigDeneb extends SpecConfigCapella, NetworkingSpecConfigDeneb {
Expand Down Expand Up @@ -58,6 +60,8 @@ static SpecConfigDeneb required(final SpecConfig specConfig) {

int getEpochsStoreBlobs();

List<Interval<UInt64>> getIncidentIntervals();

@Override
Optional<SpecConfigDeneb> toVersionDeneb();
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@

package tech.pegasys.teku.spec.config;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import tech.pegasys.teku.infrastructure.bytes.Bytes4;
import tech.pegasys.teku.infrastructure.collections.Interval;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.SpecMilestone;

Expand All @@ -34,6 +36,7 @@ public class SpecConfigDenebImpl extends DelegatingSpecConfigCapella implements
private final int minEpochsForBlobSidecarsRequests;
private final int blobSidecarSubnetCount;
private final Optional<Integer> maybeEpochsStoreBlobs;
private final List<Interval<UInt64>> incidentIntervals;

public SpecConfigDenebImpl(
final SpecConfigCapella specConfig,
Expand All @@ -48,7 +51,8 @@ public SpecConfigDenebImpl(
final int maxRequestBlobSidecars,
final int minEpochsForBlobSidecarsRequests,
final int blobSidecarSubnetCount,
final Optional<Integer> maybeEpochsStoreBlobs) {
final Optional<Integer> maybeEpochsStoreBlobs,
final List<Interval<UInt64>> incidentIntervals) {
super(specConfig);
this.denebForkVersion = denebForkVersion;
this.denebForkEpoch = denebForkEpoch;
Expand All @@ -62,6 +66,7 @@ public SpecConfigDenebImpl(
this.minEpochsForBlobSidecarsRequests = minEpochsForBlobSidecarsRequests;
this.blobSidecarSubnetCount = blobSidecarSubnetCount;
this.maybeEpochsStoreBlobs = maybeEpochsStoreBlobs;
this.incidentIntervals = incidentIntervals;
}

@Override
Expand Down Expand Up @@ -126,6 +131,11 @@ public int getEpochsStoreBlobs() {
.orElse(minEpochsForBlobSidecarsRequests);
}

@Override
public List<Interval<UInt64>> getIncidentIntervals() {
return incidentIntervals;
}

@Override
public Optional<SpecConfigDeneb> toVersionDeneb() {
return Optional.of(this);
Expand All @@ -149,6 +159,7 @@ public boolean equals(final Object o) {
&& Objects.equals(denebForkVersion, that.denebForkVersion)
&& Objects.equals(denebForkEpoch, that.denebForkEpoch)
&& Objects.equals(maybeEpochsStoreBlobs, that.maybeEpochsStoreBlobs)
&& Objects.equals(incidentIntervals, that.incidentIntervals)
&& fieldElementsPerBlob == that.fieldElementsPerBlob
&& maxBlobCommitmentsPerBlock == that.maxBlobCommitmentsPerBlock
&& maxBlobsPerBlock == that.maxBlobsPerBlock
Expand All @@ -173,6 +184,7 @@ public int hashCode() {
maxRequestBlobSidecars,
minEpochsForBlobSidecarsRequests,
blobSidecarSubnetCount,
maybeEpochsStoreBlobs);
maybeEpochsStoreBlobs,
incidentIntervals);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
import static tech.pegasys.teku.spec.config.SpecConfig.FAR_FUTURE_EPOCH;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import tech.pegasys.teku.infrastructure.bytes.Bytes4;
import tech.pegasys.teku.infrastructure.collections.Interval;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.config.SpecConfig;
import tech.pegasys.teku.spec.config.SpecConfigAndParent;
Expand All @@ -43,6 +45,7 @@ public class DenebBuilder implements ForkConfigBuilder<SpecConfigCapella, SpecCo
private Integer minEpochsForBlobSidecarsRequests;
private Integer blobSidecarSubnetCount;
private Optional<Integer> epochsStoreBlobs = Optional.empty();
private List<Interval<UInt64>> incidentIntervals = List.of();

DenebBuilder() {}

Expand All @@ -63,7 +66,8 @@ public SpecConfigAndParent<SpecConfigDeneb> build(
maxRequestBlobSidecars,
minEpochsForBlobSidecarsRequests,
blobSidecarSubnetCount,
epochsStoreBlobs),
epochsStoreBlobs,
incidentIntervals),
specConfigAndParent);
}

Expand Down Expand Up @@ -133,6 +137,11 @@ public DenebBuilder epochsStoreBlobs(final Optional<Integer> epochsStoreBlobs) {
return this;
}

public DenebBuilder incidentIntervals(final List<Interval<UInt64>> incidentIntervals) {
this.incidentIntervals = incidentIntervals;
return this;
}

@Override
public void validate() {
if (denebForkEpoch == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,10 @@ public boolean isFormerDepositMechanismDisabled(final BeaconState state) {
return false;
}

public boolean isEpochInIncidentInterval(final UInt64 epoch) {
return false;
}

public Optional<MiscHelpersDeneb> toVersionDeneb() {
return Optional.empty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public interface BlockImportResult {

BlockImportResult FAILED_BROADCAST_VALIDATION =
new FailedBlockImportResult(FailureReason.FAILED_BROADCAST_VALIDATION, Optional.empty());
BlockImportResult FAILED_INCIDENT_INTERVAL =
new FailedBlockImportResult(FailureReason.FAILED_INCIDENT_INTERVAL, Optional.empty());

static BlockImportResult failedDataAvailabilityCheckInvalid(final Optional<Throwable> cause) {
return new FailedBlockImportResult(FailureReason.FAILED_DATA_AVAILABILITY_CHECK_INVALID, cause);
Expand Down Expand Up @@ -87,6 +89,7 @@ enum FailureReason {
FAILED_DATA_AVAILABILITY_CHECK_INVALID,
FAILED_DATA_AVAILABILITY_CHECK_NOT_AVAILABLE,
FAILED_BROADCAST_VALIDATION,
FAILED_INCIDENT_INTERVAL,
INTERNAL_ERROR // A catch-all category for unexpected errors (bugs)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ public boolean isSlashableAttestationData(
return (
// case 1: double vote || case 2: surround vote
(!data1.equals(data2) && data1.getTarget().getEpoch().equals(data2.getTarget().getEpoch()))
|| (data1.getSource().getEpoch().compareTo(data2.getSource().getEpoch()) < 0
&& data2.getTarget().getEpoch().compareTo(data1.getTarget().getEpoch()) < 0));
|| (data1.getSource().getEpoch().isLessThan(data2.getSource().getEpoch())
&& data2.getTarget().getEpoch().isLessThan(data1.getTarget().getEpoch())));
}

/**
Expand Down Expand Up @@ -234,6 +234,16 @@ public SafeFuture<AttestationProcessingResult> isValidIndexedAttestationAsync(
final BeaconState state,
final IndexedAttestation indexedAttestation,
final AsyncBLSSignatureVerifier signatureVerifier) {
if (miscHelpers.isEpochInIncidentInterval(indexedAttestation.getData().getSource().getEpoch())
|| miscHelpers.isEpochInIncidentInterval(
indexedAttestation.getData().getTarget().getEpoch())
// TODO: check slot too. Could we? Should we?
// miscHelpers.isEpochInIncidentInterval(indexedAttestation.getData().getSlot())
) {
return completedFuture(
AttestationProcessingResult.invalid("Attestation couldn't be from incident intervals"));
}

final SszUInt64List indices = indexedAttestation.getAttestingIndices();

if (indices.isEmpty()) {
Expand Down Expand Up @@ -314,6 +324,12 @@ public AttestationData getGenericAttestationData(
: beaconStateAccessors.getBlockRootAtSlot(state, startSlot);
final Checkpoint source = state.getCurrentJustifiedCheckpoint();
final Checkpoint target = new Checkpoint(epoch, epochBoundaryBlockRoot);
if (miscHelpers.isEpochInIncidentInterval(source.getEpoch())
|| miscHelpers.isEpochInIncidentInterval(target.getEpoch())) {
// TODO: dropping incident interval on any attestation production is not part of the proposed
// spec
throw new IllegalStateException("Attempt to produce attestation during incident interval");
}

// Set attestation data
return new AttestationData(slot, committeeIndex, beaconBlockRoot, source, target);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,10 @@ public Optional<UInt64> getEarliestAvailabilityWindowSlotBeforeBlock(
return Optional.empty();
}

public boolean isEpochInIncidentInterval(final UInt64 epoch) {
return miscHelpers.isEpochInIncidentInterval(epoch);
}

private boolean isBellatrixBlockOld(final ReadOnlyStore store, final UInt64 blockSlot) {
final Optional<SpecConfigBellatrix> maybeConfig = specConfig.toVersionBellatrix();
if (maybeConfig.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,12 @@ public int getBlobKzgCommitmentsCount(final SignedBeaconBlock signedBeaconBlock)
.orElse(0);
}

@Override
public boolean isEpochInIncidentInterval(final UInt64 epoch) {
return SpecConfigDeneb.required(specConfig).getIncidentIntervals().stream()
.anyMatch(interval -> interval.contains(epoch));
}

public int getBlobSidecarKzgCommitmentGeneralizedIndex(final UInt64 blobSidecarIndex) {
final long blobKzgCommitmentsGeneralizedIndex =
beaconBlockBodySchema.getBlobKzgCommitmentsGeneralizedIndex();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import static org.assertj.core.api.Assertions.assertThat;

import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import tech.pegasys.teku.spec.Spec;
Expand Down Expand Up @@ -97,6 +98,7 @@ private SpecConfigDeneb createRandomDenebConfig(
dataStructureUtil.randomPositiveInt(),
dataStructureUtil.randomPositiveInt(),
dataStructureUtil.randomPositiveInt(),
Optional.empty());
Optional.empty(),
List.of());
}
}
Loading