Skip to content

Commit 70b7980

Browse files
DVT integration for attestation aggregation (Consensys#8032)
1 parent af80f3c commit 70b7980

File tree

11 files changed

+466
-17
lines changed

11 files changed

+466
-17
lines changed

Diff for: ethereum/json-types/src/main/java/tech/pegasys/teku/ethereum/json/types/validator/BeaconCommitteeSelectionProof.java

+6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
package tech.pegasys.teku.ethereum.json.types.validator;
1515

1616
import java.util.Objects;
17+
import org.apache.tuweni.bytes.Bytes;
18+
import tech.pegasys.teku.bls.BLSSignature;
1719
import tech.pegasys.teku.infrastructure.json.types.CoreTypes;
1820
import tech.pegasys.teku.infrastructure.json.types.DeserializableTypeDefinition;
1921
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
@@ -67,6 +69,10 @@ public String getSelectionProof() {
6769
return selectionProof;
6870
}
6971

72+
public BLSSignature getSelectionProofSignature() {
73+
return BLSSignature.fromBytesCompressed(Bytes.fromHexString(getSelectionProof()));
74+
}
75+
7076
public static BeaconCommitteeSelectionProof.Builder builder() {
7177
return new BeaconCommitteeSelectionProof.Builder();
7278
}

Diff for: teku/src/main/java/tech/pegasys/teku/cli/options/ValidatorClientOptions.java

+16-4
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313

1414
package tech.pegasys.teku.cli.options;
1515

16-
import static tech.pegasys.teku.validator.api.ValidatorConfig.DEFAULT_VALIDATOR_CLIENT_SSZ_BLOCKS_ENABLED;
17-
1816
import java.net.URI;
1917
import java.net.URISyntaxException;
2018
import java.util.List;
@@ -62,7 +60,8 @@ public class ValidatorClientOptions {
6260
showDefaultValue = CommandLine.Help.Visibility.ALWAYS,
6361
arity = "0..1",
6462
fallbackValue = "true")
65-
private boolean validatorClientSszBlocksEnabled = DEFAULT_VALIDATOR_CLIENT_SSZ_BLOCKS_ENABLED;
63+
private boolean validatorClientSszBlocksEnabled =
64+
ValidatorConfig.DEFAULT_VALIDATOR_CLIENT_SSZ_BLOCKS_ENABLED;
6665

6766
@CommandLine.Option(
6867
names = {"--Xuse-post-validators-endpoint-enabled"},
@@ -75,6 +74,18 @@ public class ValidatorClientOptions {
7574
private boolean validatorClientUsePostValidatorsEndpointEnabled =
7675
ValidatorConfig.DEFAULT_VALIDATOR_CLIENT_USE_POST_VALIDATORS_ENDPOINT_ENABLED;
7776

77+
@Option(
78+
names = {"--Xdvt-integration-enabled"},
79+
paramLabel = "<BOOLEAN>",
80+
description =
81+
"Use DVT endpoints to determine if a distributed validator has aggregation duties.",
82+
arity = "0..1",
83+
showDefaultValue = CommandLine.Help.Visibility.ALWAYS,
84+
hidden = true,
85+
fallbackValue = "true")
86+
private boolean dvtSelectionsEndpointEnabled =
87+
ValidatorConfig.DEFAULT_DVT_SELECTIONS_ENDPOINT_ENABLED;
88+
7889
public void configure(TekuConfiguration.Builder builder) {
7990
configureBeaconNodeApiEndpoints();
8091

@@ -87,7 +98,8 @@ public void configure(TekuConfiguration.Builder builder) {
8798
validatorClientUsePostValidatorsEndpointEnabled)
8899
.failoversSendSubnetSubscriptionsEnabled(failoversSendSubnetSubscriptionsEnabled)
89100
.failoversPublishSignedDutiesEnabled(failoversPublishSignedDutiesEnabled)
90-
.sentryNodeConfigurationFile(exclusiveParams.sentryConfigFile));
101+
.sentryNodeConfigurationFile(exclusiveParams.sentryConfigFile)
102+
.dvtSelectionsEndpointEnabled(dvtSelectionsEndpointEnabled));
91103
}
92104

93105
private void configureBeaconNodeApiEndpoints() {

Diff for: teku/src/test/java/tech/pegasys/teku/cli/options/ValidatorOptionsTest.java

+8
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,12 @@ public void shouldSetShutdownWhenValidatorSlashedEnabled() {
234234
.getValidatorConfig();
235235
assertThat(config.isShutdownWhenValidatorSlashedEnabled()).isTrue();
236236
}
237+
238+
@Test
239+
public void shouldNotUseDvtSelectionsEndpointByDefault() {
240+
final String[] args = {};
241+
final TekuConfiguration config = getTekuConfigurationFromArguments(args);
242+
assertThat(config.validatorClient().getValidatorConfig().isDvtSelectionsEndpointEnabled())
243+
.isFalse();
244+
}
237245
}

Diff for: teku/src/test/java/tech/pegasys/teku/cli/subcommand/ValidatorClientCommandTest.java

+17
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,23 @@ public void clientExecutorThreadsShouldThrowOverLimit() {
210210
"--Xvalidator-client-executor-threads must be greater than 0 and less than 5000.");
211211
}
212212

213+
@Test
214+
public void shouldSetUseDvtSelectionsEndpoint() {
215+
final String[] args = {"vc", "--network", "minimal", "--Xdvt-integration-enabled"};
216+
final TekuConfiguration config = getTekuConfigurationFromArguments(args);
217+
218+
assertThat(config.validatorClient().getValidatorConfig().isDvtSelectionsEndpointEnabled())
219+
.isTrue();
220+
}
221+
222+
@Test
223+
public void shouldNotUseDvtSelectionsEndpointByDefault() {
224+
final String[] args = {"vc", "--network", "minimal"};
225+
final TekuConfiguration config = getTekuConfigurationFromArguments(args);
226+
assertThat(config.validatorClient().getValidatorConfig().isDvtSelectionsEndpointEnabled())
227+
.isFalse();
228+
}
229+
213230
private String pathFor(final String filename) {
214231
return Resources.getResource(ValidatorClientCommandTest.class, filename).toString();
215232
}

Diff for: validator/api/src/main/java/tech/pegasys/teku/validator/api/ValidatorConfig.java

+17-4
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public class ValidatorConfig {
6565
public static final boolean DEFAULT_VALIDATOR_BLINDED_BLOCKS_ENABLED = false;
6666
public static final int DEFAULT_VALIDATOR_REGISTRATION_SENDING_BATCH_SIZE = 100;
6767
public static final UInt64 DEFAULT_BUILDER_REGISTRATION_GAS_LIMIT = UInt64.valueOf(30_000_000);
68+
public static final boolean DEFAULT_DVT_SELECTIONS_ENDPOINT_ENABLED = false;
6869

6970
private final List<String> validatorKeys;
7071
private final List<String> validatorExternalSignerPublicKeySources;
@@ -105,6 +106,7 @@ public class ValidatorConfig {
105106
private final int executorThreads;
106107

107108
private final boolean isLocalSlashingProtectionSynchronizedModeEnabled;
109+
private final boolean dvtSelectionsEndpointEnabled;
108110

109111
private ValidatorConfig(
110112
final List<String> validatorKeys,
@@ -143,7 +145,8 @@ private ValidatorConfig(
143145
final int executorMaxQueueSize,
144146
final int executorThreads,
145147
final Optional<String> sentryNodeConfigurationFile,
146-
boolean isLocalSlashingProtectionSynchronizedModeEnabled) {
148+
boolean isLocalSlashingProtectionSynchronizedModeEnabled,
149+
boolean dvtSelectionsEndpointEnabled) {
147150
this.validatorKeys = validatorKeys;
148151
this.validatorExternalSignerPublicKeySources = validatorExternalSignerPublicKeySources;
149152
this.validatorExternalSignerUrl = validatorExternalSignerUrl;
@@ -186,6 +189,7 @@ private ValidatorConfig(
186189
this.sentryNodeConfigurationFile = sentryNodeConfigurationFile;
187190
this.isLocalSlashingProtectionSynchronizedModeEnabled =
188191
isLocalSlashingProtectionSynchronizedModeEnabled;
192+
this.dvtSelectionsEndpointEnabled = dvtSelectionsEndpointEnabled;
189193
}
190194

191195
public static Builder builder() {
@@ -348,6 +352,10 @@ public boolean isLocalSlashingProtectionSynchronizedModeEnabled() {
348352
return isLocalSlashingProtectionSynchronizedModeEnabled;
349353
}
350354

355+
public boolean isDvtSelectionsEndpointEnabled() {
356+
return dvtSelectionsEndpointEnabled;
357+
}
358+
351359
public static final class Builder {
352360
private List<String> validatorKeys = new ArrayList<>();
353361
private List<String> validatorExternalSignerPublicKeySources = new ArrayList<>();
@@ -395,11 +403,10 @@ public static final class Builder {
395403
private Optional<BLSPublicKey> builderRegistrationPublicKeyOverride = Optional.empty();
396404
private int executorMaxQueueSize = DEFAULT_EXECUTOR_MAX_QUEUE_SIZE;
397405
private Optional<String> sentryNodeConfigurationFile = Optional.empty();
398-
399406
private int executorThreads = DEFAULT_VALIDATOR_EXECUTOR_THREADS;
400-
401407
private boolean isLocalSlashingProtectionSynchronizedModeEnabled =
402408
DEFAULT_VALIDATOR_IS_LOCAL_SLASHING_PROTECTION_SYNCHRONIZED_ENABLED;
409+
private boolean dvtSelectionsEndpointEnabled = DEFAULT_DVT_SELECTIONS_ENDPOINT_ENABLED;
403410

404411
private Builder() {}
405412

@@ -640,6 +647,11 @@ public Builder isLocalSlashingProtectionSynchronizedModeEnabled(
640647
return this;
641648
}
642649

650+
public Builder dvtSelectionsEndpointEnabled(final boolean dvtSelectionsEndpointEnabled) {
651+
this.dvtSelectionsEndpointEnabled = dvtSelectionsEndpointEnabled;
652+
return this;
653+
}
654+
643655
public ValidatorConfig build() {
644656
validateExternalSignerUrlAndPublicKeys();
645657
validateExternalSignerKeystoreAndPasswordFileConfig();
@@ -683,7 +695,8 @@ public ValidatorConfig build() {
683695
executorMaxQueueSize,
684696
executorThreads,
685697
sentryNodeConfigurationFile,
686-
isLocalSlashingProtectionSynchronizedModeEnabled);
698+
isLocalSlashingProtectionSynchronizedModeEnabled,
699+
dvtSelectionsEndpointEnabled);
687700
}
688701

689702
private void validateExternalSignerUrlAndPublicKeys() {

Diff for: validator/client/src/main/java/tech/pegasys/teku/validator/client/AttestationDutyLoader.java

+28-5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public class AttestationDutyLoader
4545
scheduledDutiesFactory;
4646
private final BeaconCommitteeSubscriptions beaconCommitteeSubscriptions;
4747
private final Spec spec;
48+
private final boolean useDvtEndpoint;
4849

4950
public AttestationDutyLoader(
5051
final ValidatorApiChannel validatorApiChannel,
@@ -54,13 +55,15 @@ public AttestationDutyLoader(
5455
final OwnedValidators validators,
5556
final ValidatorIndexProvider validatorIndexProvider,
5657
final BeaconCommitteeSubscriptions beaconCommitteeSubscriptions,
57-
final Spec spec) {
58+
final Spec spec,
59+
final boolean useDvtEndpoint) {
5860
super(validators, validatorIndexProvider);
5961
this.validatorApiChannel = validatorApiChannel;
6062
this.forkProvider = forkProvider;
6163
this.scheduledDutiesFactory = scheduledDutiesFactory;
6264
this.beaconCommitteeSubscriptions = beaconCommitteeSubscriptions;
6365
this.spec = spec;
66+
this.useDvtEndpoint = useDvtEndpoint;
6467
}
6568

6669
@Override
@@ -77,17 +80,27 @@ protected SafeFuture<Optional<AttesterDuties>> requestDuties(
7780
final UInt64 epoch, final AttesterDuties duties) {
7881
final SlotBasedScheduledDuties<AttestationProductionDuty, AggregationDuty> scheduledDuties =
7982
scheduledDutiesFactory.apply(duties.getDependentRoot());
83+
84+
final Optional<DvtAttestationAggregations> dvtAttestationAggregationsForEpoch =
85+
useDvtEndpoint
86+
? Optional.of(
87+
new DvtAttestationAggregations(validatorApiChannel, duties.getDuties().size()))
88+
: Optional.empty();
89+
8090
return SafeFuture.allOf(
8191
duties.getDuties().stream()
82-
.map(duty -> scheduleDuties(scheduledDuties, duty))
92+
.map(
93+
duty ->
94+
scheduleDuties(scheduledDuties, duty, dvtAttestationAggregationsForEpoch))
8395
.toArray(SafeFuture[]::new))
8496
.<SlotBasedScheduledDuties<?, ?>>thenApply(__ -> scheduledDuties)
8597
.alwaysRun(beaconCommitteeSubscriptions::sendRequests);
8698
}
8799

88100
private SafeFuture<Void> scheduleDuties(
89101
final SlotBasedScheduledDuties<AttestationProductionDuty, AggregationDuty> scheduledDuties,
90-
final AttesterDuty duty) {
102+
final AttesterDuty duty,
103+
final Optional<DvtAttestationAggregations> dvtAttestationAggregationLoader) {
91104
final Optional<Validator> maybeValidator = validators.getValidator(duty.getPublicKey());
92105
if (maybeValidator.isEmpty()) {
93106
return SafeFuture.COMPLETE;
@@ -116,7 +129,8 @@ private SafeFuture<Void> scheduleDuties(
116129
validator,
117130
duty.getSlot(),
118131
aggregatorModulo,
119-
unsignedAttestationFuture);
132+
unsignedAttestationFuture,
133+
dvtAttestationAggregationLoader);
120134
}
121135

122136
private SafeFuture<Optional<AttestationData>> scheduleAttestationProduction(
@@ -147,10 +161,19 @@ private SafeFuture<Void> scheduleAggregation(
147161
final Validator validator,
148162
final UInt64 slot,
149163
final int aggregatorModulo,
150-
final SafeFuture<Optional<AttestationData>> unsignedAttestationFuture) {
164+
final SafeFuture<Optional<AttestationData>> unsignedAttestationFuture,
165+
final Optional<DvtAttestationAggregations> dvtAttestationAggregation) {
151166
return forkProvider
152167
.getForkInfo(slot)
153168
.thenCompose(forkInfo -> validator.getSigner().signAggregationSlot(slot, forkInfo))
169+
.thenCompose(
170+
slotSignature ->
171+
dvtAttestationAggregation
172+
.map(
173+
dvt ->
174+
dvt.getCombinedSelectionProofFuture(
175+
validatorIndex, slot, slotSignature))
176+
.orElse(SafeFuture.completedFuture(slotSignature)))
154177
.thenAccept(
155178
slotSignature -> {
156179
final SpecVersion specVersion = spec.atSlot(slot);

0 commit comments

Comments
 (0)