Skip to content

Commit f5f694b

Browse files
jtragliatbenr
andauthored
Add a hidden flag for configuring data column sidecar recovery delay (#9678)
* Add a hidden flag for configuring the recovery delay * add tests --------- Co-authored-by: Enrico Del Fante <[email protected]>
1 parent d29842e commit f5f694b

File tree

6 files changed

+94
-2
lines changed

6 files changed

+94
-2
lines changed

ethereum/networks/src/main/java/tech/pegasys/teku/networks/Eth2NetworkConfiguration.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.Objects;
3737
import java.util.Optional;
3838
import java.util.OptionalInt;
39+
import java.util.OptionalLong;
3940
import org.apache.logging.log4j.LogManager;
4041
import org.apache.logging.log4j.Logger;
4142
import org.apache.tuweni.bytes.Bytes32;
@@ -128,6 +129,7 @@ public class Eth2NetworkConfiguration {
128129
private final int pendingAttestationsMaxQueue;
129130
private final boolean rustKzgEnabled;
130131
private final int kzgPrecompute;
132+
private final OptionalLong dataColumnSidecarRecoveryMaxDelayMillis;
131133
private final boolean aggregatingAttestationPoolV2Enabled;
132134
private final boolean aggregatingAttestationPoolProfilingEnabled;
133135
private final int aggregatingAttestationPoolV2BlockAggregationTimeLimit;
@@ -163,6 +165,7 @@ private Eth2NetworkConfiguration(
163165
final int pendingAttestationsMaxQueue,
164166
final boolean rustKzgEnabled,
165167
final int kzgPrecompute,
168+
final OptionalLong dataColumnSidecarRecoveryMaxDelayMillis,
166169
final boolean aggregatingAttestationPoolV2Enabled,
167170
final boolean aggregatingAttestationPoolProfilingEnabled,
168171
final int aggregatingAttestationPoolV2BlockAggregationTimeLimit,
@@ -200,6 +203,7 @@ private Eth2NetworkConfiguration(
200203
this.pendingAttestationsMaxQueue = pendingAttestationsMaxQueue;
201204
this.rustKzgEnabled = rustKzgEnabled;
202205
this.kzgPrecompute = kzgPrecompute;
206+
this.dataColumnSidecarRecoveryMaxDelayMillis = dataColumnSidecarRecoveryMaxDelayMillis;
203207
this.aggregatingAttestationPoolV2Enabled = aggregatingAttestationPoolV2Enabled;
204208
this.aggregatingAttestationPoolProfilingEnabled = aggregatingAttestationPoolProfilingEnabled;
205209
this.aggregatingAttestationPoolV2BlockAggregationTimeLimit =
@@ -352,6 +356,10 @@ public int getKzgPrecompute() {
352356
return kzgPrecompute;
353357
}
354358

359+
public OptionalLong getDataColumnSidecarRecoveryMaxDelayMillis() {
360+
return dataColumnSidecarRecoveryMaxDelayMillis;
361+
}
362+
355363
@Override
356364
public String toString() {
357365
return constants;
@@ -472,6 +480,7 @@ public static class Builder {
472480
private OptionalInt pendingAttestationsMaxQueue = OptionalInt.empty();
473481
private boolean rustKzgEnabled = DEFAULT_RUST_KZG_ENABLED;
474482
private int kzgPrecompute = DEFAULT_KZG_PRECOMPUTE;
483+
private OptionalLong dataColumnSidecarRecoveryMaxDelayMillis = OptionalLong.empty();
475484
private boolean strictConfigLoadingEnabled;
476485
private boolean aggregatingAttestationPoolV2Enabled =
477486
DEFAULT_AGGREGATING_ATTESTATION_POOL_V2_ENABLED;
@@ -584,6 +593,7 @@ public Eth2NetworkConfiguration build() {
584593
pendingAttestationsMaxQueue.orElse(DEFAULT_MAX_QUEUE_PENDING_ATTESTATIONS),
585594
rustKzgEnabled,
586595
kzgPrecompute,
596+
dataColumnSidecarRecoveryMaxDelayMillis,
587597
aggregatingAttestationPoolV2Enabled,
588598
aggregatingAttestationPoolProfilingEnabled,
589599
aggregatingAttestationPoolV2BlockAggregationTimeLimit,
@@ -836,6 +846,13 @@ public Builder kzgPrecompute(final int kzgPrecompute) {
836846
return this;
837847
}
838848

849+
public Builder dataColumnSidecarRecoveryMaxDelayMillis(
850+
final Long dataColumnSidecarRecoveryMaxDelayMillis) {
851+
this.dataColumnSidecarRecoveryMaxDelayMillis =
852+
OptionalLong.of(dataColumnSidecarRecoveryMaxDelayMillis);
853+
return this;
854+
}
855+
839856
public Builder applyNetworkDefaults(final String networkName) {
840857
Eth2Network.fromStringLenient(networkName)
841858
.ifPresentOrElse(

ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/datacolumns/DataColumnSidecarRecoveringCustodyImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ private void initiateRecovery(
250250
list.thenAccept(
251251
sidecars -> {
252252
LOG.debug(
253-
"Recovery for block: {}. DatacolumnSidecars found: {}",
253+
"Recovery for block: {}. DataColumnSidecars found: {}",
254254
block.getSlotAndBlockRoot(),
255255
sidecars.size());
256256
final List<DataColumnSidecar> recoveredSidecars =

services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainController.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,14 @@ protected void initDasCustody() {
820820
custodyGroupCountManagerLateInit,
821821
specConfigFulu.getNumberOfColumns(),
822822
specConfigFulu.getNumberOfCustodyGroups(),
823-
slot -> Duration.ofMillis(spec.getMillisPerSlot(slot).dividedBy(3).longValue()),
823+
slot -> {
824+
final long dataColumnSidecarRecoveryMaxDelayMillis =
825+
beaconConfig
826+
.eth2NetworkConfig()
827+
.getDataColumnSidecarRecoveryMaxDelayMillis()
828+
.orElse(spec.getMillisPerSlot(slot).dividedBy(3).longValue());
829+
return Duration.ofMillis(dataColumnSidecarRecoveryMaxDelayMillis);
830+
},
824831
metricsSystem,
825832
timeProvider);
826833
eventChannels.subscribe(SlotEventsChannel.class, dataColumnSidecarRecoveringCustody);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright Consensys Software Inc., 2025
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package tech.pegasys.teku.cli.converter;
15+
16+
import java.util.OptionalLong;
17+
import picocli.CommandLine;
18+
19+
public class OptionalLongConverter implements CommandLine.ITypeConverter<OptionalLong> {
20+
21+
@Override
22+
public OptionalLong convert(final String s) throws Exception {
23+
return OptionalLong.of(Long.parseLong(s));
24+
}
25+
}

teku/src/main/java/tech/pegasys/teku/cli/options/Eth2NetworkOptions.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static tech.pegasys.teku.spec.constants.NetworkConstants.DEFAULT_SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY;
1919

2020
import java.util.OptionalInt;
21+
import java.util.OptionalLong;
2122
import java.util.function.Consumer;
2223
import org.apache.commons.lang3.StringUtils;
2324
import org.apache.tuweni.bytes.Bytes32;
@@ -27,6 +28,7 @@
2728
import picocli.CommandLine.Option;
2829
import tech.pegasys.teku.cli.converter.Bytes32Converter;
2930
import tech.pegasys.teku.cli.converter.OptionalIntConverter;
31+
import tech.pegasys.teku.cli.converter.OptionalLongConverter;
3032
import tech.pegasys.teku.cli.converter.UInt256Converter;
3133
import tech.pegasys.teku.config.TekuConfiguration;
3234
import tech.pegasys.teku.infrastructure.exceptions.InvalidConfigurationException;
@@ -118,6 +120,16 @@ public class Eth2NetworkOptions {
118120
hidden = true)
119121
private int kzgPrecompute = Eth2NetworkConfiguration.DEFAULT_KZG_PRECOMPUTE;
120122

123+
@Option(
124+
names = {"--Xdata-column-sidecar-recovery-max-delay"},
125+
paramLabel = "<MILLISECONDS>",
126+
description =
127+
"Maximum delay in milliseconds for a supernode to begin data column sidecar recovery.",
128+
arity = "1",
129+
converter = OptionalLongConverter.class,
130+
hidden = true)
131+
private OptionalLong dataColumnSidecarRecoveryMaxDelayMillis = OptionalLong.empty();
132+
121133
@Option(
122134
names = {"--Xfork-choice-late-block-reorg-enabled"},
123135
paramLabel = "<BOOLEAN>",
@@ -466,6 +478,8 @@ private void configureEth2Network(final Eth2NetworkConfiguration.Builder builder
466478
.forkChoiceUpdatedAlwaysSendPayloadAttributes(forkChoiceUpdatedAlwaysSendPayloadAttributes)
467479
.rustKzgEnabled(rustKzgEnabled)
468480
.kzgPrecompute(kzgPrecompute);
481+
dataColumnSidecarRecoveryMaxDelayMillis.ifPresent(
482+
builder::dataColumnSidecarRecoveryMaxDelayMillis);
469483
asyncP2pMaxQueue.ifPresent(builder::asyncP2pMaxQueue);
470484
pendingAttestationsMaxQueue.ifPresent(builder::pendingAttestationsMaxQueue);
471485
asyncBeaconChainMaxQueue.ifPresent(builder::asyncBeaconChainMaxQueue);

teku/src/test/java/tech/pegasys/teku/cli/options/Eth2NetworkOptionsTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import java.math.BigInteger;
2323
import java.util.Optional;
24+
import java.util.OptionalLong;
2425
import org.apache.tuweni.bytes.Bytes32;
2526
import org.apache.tuweni.units.bigints.UInt256;
2627
import org.junit.jupiter.api.Test;
@@ -272,4 +273,32 @@ public void rustKzgFlagCanBeUsedToToggleRustKzgOn() {
272273
final TekuConfiguration config = getTekuConfigurationFromArguments("--Xrust-kzg-enabled");
273274
assertThat(config.eth2NetworkConfiguration().isRustKzgEnabled()).isTrue();
274275
}
276+
277+
@Test
278+
void shouldUseSetDataColumnSidecarRecoveryDelay() {
279+
final TekuConfiguration config =
280+
getTekuConfigurationFromArguments("--Xdata-column-sidecar-recovery-max-delay", "2300");
281+
final OptionalLong maxDelayMillis =
282+
config.eth2NetworkConfiguration().getDataColumnSidecarRecoveryMaxDelayMillis();
283+
assertThat(maxDelayMillis).hasValue(2300L);
284+
}
285+
286+
@Test
287+
void dataColumnSidecarRecoveryDelayEmptyByDefault() {
288+
final TekuConfiguration config = getTekuConfigurationFromArguments();
289+
final OptionalLong maxDelayMillis =
290+
config.eth2NetworkConfiguration().getDataColumnSidecarRecoveryMaxDelayMillis();
291+
assertThat(maxDelayMillis).isEmpty();
292+
}
293+
294+
@Test
295+
void invalidDataColumnSidecarRecoveryDelayShouldThrow() {
296+
assertThatThrownBy(
297+
() ->
298+
getTekuConfigurationFromArguments(
299+
"--Xdata-column-sidecar-recovery-max-delay", "invalid"))
300+
.isInstanceOf(AssertionError.class)
301+
.hasMessageContaining(
302+
"Invalid value for option '--Xdata-column-sidecar-recovery-max-delay'");
303+
}
275304
}

0 commit comments

Comments
 (0)