From 78bc07de8d3100029c9877cfa2eb069d57d49d60 Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Tue, 4 Jun 2024 14:43:02 +0100 Subject: [PATCH] Add a cli option + not run validation only when it's gossip --- CHANGELOG.md | 5 ++++- .../ValidatorApiHandlerIntegrationTest.java | 3 ++- .../coordinator/ValidatorApiHandler.java | 14 ++++++++++---- .../coordinator/ValidatorApiHandlerTest.java | 9 ++++++--- .../beaconchain/BeaconChainController.java | 3 ++- .../teku/cli/options/ValidatorOptions.java | 15 +++++++++++++++ .../teku/validator/api/ValidatorConfig.java | 15 +++++++++++++++ 7 files changed, 54 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4263fe7f33d..a405257a774 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,11 @@ the [releases page](https://github.com/Consensys/teku/releases). ### Breaking Changes ### Additions and Improvements + - Added metadata fields to `/eth/v1/beacon/blob_sidecars/{block_id}` Beacon API response as per https://github.com/ethereum/beacon-APIs/pull/441 - Added rest api endpoint `/teku/v1/beacon/state/finalized/slot/before/{slot}` to return most recent stored state at or before a specified slot. -- The validator client will start using the `v2` variant of the beacon node block publishing endpoints which perform an additional gossip validation unless the block has been produced in the same beacon node. +- The validator client will start using the `v2` variant of the beacon node block publishing + endpoints. The beacon node would perform an additional gossip validation unless the block has been + produced in the same node. This behaviour can be changed by a new hidden CLI option: `--Xvalidate-locally-created-blocks` ### Bug Fixes diff --git a/beacon/validator/src/integrationTest/java/tech/pegasys/teku/validator/coordinator/ValidatorApiHandlerIntegrationTest.java b/beacon/validator/src/integrationTest/java/tech/pegasys/teku/validator/coordinator/ValidatorApiHandlerIntegrationTest.java index daf4898c9e4..3f044aac479 100644 --- a/beacon/validator/src/integrationTest/java/tech/pegasys/teku/validator/coordinator/ValidatorApiHandlerIntegrationTest.java +++ b/beacon/validator/src/integrationTest/java/tech/pegasys/teku/validator/coordinator/ValidatorApiHandlerIntegrationTest.java @@ -122,7 +122,8 @@ public class ValidatorApiHandlerIntegrationTest { syncCommitteeContributionPool, syncCommitteeSubscriptionManager, new BlockProductionAndPublishingPerformanceFactory( - new SystemTimeProvider(), __ -> UInt64.ZERO, true, 0, 0, 0, 0)); + new SystemTimeProvider(), __ -> UInt64.ZERO, true, 0, 0, 0, 0), + false); @BeforeEach public void setup() { diff --git a/beacon/validator/src/main/java/tech/pegasys/teku/validator/coordinator/ValidatorApiHandler.java b/beacon/validator/src/main/java/tech/pegasys/teku/validator/coordinator/ValidatorApiHandler.java index c3f96b14b3f..e2fab4de144 100644 --- a/beacon/validator/src/main/java/tech/pegasys/teku/validator/coordinator/ValidatorApiHandler.java +++ b/beacon/validator/src/main/java/tech/pegasys/teku/validator/coordinator/ValidatorApiHandler.java @@ -21,6 +21,8 @@ import static tech.pegasys.teku.infrastructure.metrics.Validator.ValidatorDutyMetricUtils.startTimer; import static tech.pegasys.teku.infrastructure.metrics.Validator.ValidatorDutyMetricsSteps.CREATE; import static tech.pegasys.teku.spec.config.SpecConfig.GENESIS_SLOT; +import static tech.pegasys.teku.spec.datastructures.validator.BroadcastValidationLevel.GOSSIP; +import static tech.pegasys.teku.spec.datastructures.validator.BroadcastValidationLevel.NOT_REQUIRED; import com.google.common.annotations.VisibleForTesting; import it.unimi.dsi.fastutil.ints.IntCollection; @@ -141,6 +143,7 @@ public class ValidatorApiHandler implements ValidatorApiChannel { private final SyncCommitteeContributionPool syncCommitteeContributionPool; private final ProposersDataManager proposersDataManager; private final BlockPublisher blockPublisher; + private final boolean validateLocallyCreatedBlocks; private final AttesterDutiesGenerator attesterDutiesGenerator; @@ -167,7 +170,8 @@ public ValidatorApiHandler( final SyncCommitteeContributionPool syncCommitteeContributionPool, final SyncCommitteeSubscriptionManager syncCommitteeSubscriptionManager, final BlockProductionAndPublishingPerformanceFactory - blockProductionAndPublishingPerformanceFactory) { + blockProductionAndPublishingPerformanceFactory, + final boolean validateLocallyCreatedBlocks) { this.blockProductionAndPublishingPerformanceFactory = blockProductionAndPublishingPerformanceFactory; this.chainDataProvider = chainDataProvider; @@ -187,6 +191,7 @@ public ValidatorApiHandler( this.syncCommitteeContributionPool = syncCommitteeContributionPool; this.syncCommitteeSubscriptionManager = syncCommitteeSubscriptionManager; this.proposersDataManager = proposersDataManager; + this.validateLocallyCreatedBlocks = validateLocallyCreatedBlocks; this.blockPublisher = new MilestoneBasedBlockPublisher( spec, @@ -647,9 +652,10 @@ public SafeFuture sendSignedBlock( return blockPublisher .sendSignedBlock( maybeBlindedBlockContainer, - // no validation required for locally created blocks - isLocallyCreatedBlock(maybeBlindedBlockContainer) - ? BroadcastValidationLevel.NOT_REQUIRED + !validateLocallyCreatedBlocks + && broadcastValidationLevel == GOSSIP + && isLocallyCreatedBlock(maybeBlindedBlockContainer) + ? NOT_REQUIRED : broadcastValidationLevel, blockPublishingPerformance) .exceptionally( diff --git a/beacon/validator/src/test/java/tech/pegasys/teku/validator/coordinator/ValidatorApiHandlerTest.java b/beacon/validator/src/test/java/tech/pegasys/teku/validator/coordinator/ValidatorApiHandlerTest.java index c5e2f0d0435..8b7b7179258 100644 --- a/beacon/validator/src/test/java/tech/pegasys/teku/validator/coordinator/ValidatorApiHandlerTest.java +++ b/beacon/validator/src/test/java/tech/pegasys/teku/validator/coordinator/ValidatorApiHandlerTest.java @@ -216,7 +216,8 @@ public void setUp() { syncCommitteeMessagePool, syncCommitteeContributionPool, syncCommitteeSubscriptionManager, - blockProductionPerformanceFactory); + blockProductionPerformanceFactory, + false); when(syncStateProvider.getCurrentSyncState()).thenReturn(SyncState.IN_SYNC); when(forkChoiceTrigger.prepareForBlockProduction(any(), any())).thenReturn(SafeFuture.COMPLETE); @@ -470,7 +471,8 @@ void getSyncCommitteeDuties_shouldNotUseEpochPriorToFork() { syncCommitteeMessagePool, syncCommitteeContributionPool, syncCommitteeSubscriptionManager, - blockProductionPerformanceFactory); + blockProductionPerformanceFactory, + false); // Best state is still in Phase0 final BeaconState state = dataStructureUtil.stateBuilderPhase0().slot(previousEpochStartSlot.minus(1)).build(); @@ -1379,7 +1381,8 @@ private void setupDeneb() { syncCommitteeMessagePool, syncCommitteeContributionPool, syncCommitteeSubscriptionManager, - blockProductionPerformanceFactory); + blockProductionPerformanceFactory, + false); // BlobSidecar builder doAnswer( diff --git a/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainController.java b/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainController.java index de1095789ea..e4e894010e5 100644 --- a/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainController.java +++ b/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainController.java @@ -972,7 +972,8 @@ public void initValidatorApiHandler() { syncCommitteeMessagePool, syncCommitteeContributionPool, syncCommitteeSubscriptionManager, - blockProductionPerformanceFactory); + blockProductionPerformanceFactory, + beaconConfig.validatorConfig().isValidateLocallyCreatedBlocksEnabled()); eventChannels .subscribe(SlotEventsChannel.class, activeValidatorTracker) .subscribe(ExecutionClientEventsChannel.class, executionClientVersionProvider) diff --git a/teku/src/main/java/tech/pegasys/teku/cli/options/ValidatorOptions.java b/teku/src/main/java/tech/pegasys/teku/cli/options/ValidatorOptions.java index 25415b71b32..aa99620bbda 100644 --- a/teku/src/main/java/tech/pegasys/teku/cli/options/ValidatorOptions.java +++ b/teku/src/main/java/tech/pegasys/teku/cli/options/ValidatorOptions.java @@ -145,6 +145,20 @@ public class ValidatorOptions { fallbackValue = "true") private boolean blockV3Enabled = ValidatorConfig.DEFAULT_BLOCK_V3_ENABLED; + @Option( + names = {"--Xvalidate-locally-created-blocks"}, + paramLabel = "", + description = + """ + Enable gossip validation when publishing a block which has been created locally. + This is only applicable when "gossip" broadcast validation level has been requested,""", + hidden = true, + showDefaultValue = CommandLine.Help.Visibility.ALWAYS, + arity = "0..1", + fallbackValue = "true") + private boolean validateLocallyCreatedBlocks = + ValidatorConfig.DEFAULT_VALIDATE_LOCALLY_CREATED_BLOCKS; + @Option( names = {"--exit-when-no-validator-keys-enabled"}, paramLabel = "", @@ -194,6 +208,7 @@ public void configure(final TekuConfiguration.Builder builder) { .doppelgangerDetectionEnabled(doppelgangerDetectionEnabled) .executorThreads(executorThreads) .blockV3enabled(blockV3Enabled) + .validateLocallyCreatedBlocks(validateLocallyCreatedBlocks) .exitWhenNoValidatorKeysEnabled(exitWhenNoValidatorKeysEnabled) .shutdownWhenValidatorSlashedEnabled(shutdownWhenValidatorSlashed)); validatorProposerOptions.configure(builder); diff --git a/validator/api/src/main/java/tech/pegasys/teku/validator/api/ValidatorConfig.java b/validator/api/src/main/java/tech/pegasys/teku/validator/api/ValidatorConfig.java index 03089b54b94..cf36589da7a 100644 --- a/validator/api/src/main/java/tech/pegasys/teku/validator/api/ValidatorConfig.java +++ b/validator/api/src/main/java/tech/pegasys/teku/validator/api/ValidatorConfig.java @@ -46,6 +46,7 @@ public class ValidatorConfig { public static final boolean DEFAULT_FAILOVERS_SEND_SUBNET_SUBSCRIPTIONS_ENABLED = true; public static final boolean DEFAULT_FAILOVERS_PUBLISH_SIGNED_DUTIES_ENABLED = true; public static final boolean DEFAULT_BLOCK_V3_ENABLED = false; + public static final boolean DEFAULT_VALIDATE_LOCALLY_CREATED_BLOCKS = false; public static final boolean DEFAULT_EXIT_WHEN_NO_VALIDATOR_KEYS_ENABLED = false; public static final boolean DEFAULT_VALIDATOR_CLIENT_SSZ_BLOCKS_ENABLED = true; public static final boolean DEFAULT_VALIDATOR_CLIENT_USE_POST_VALIDATORS_ENDPOINT_ENABLED = true; @@ -97,6 +98,7 @@ public class ValidatorConfig { private final boolean failoversSendSubnetSubscriptionsEnabled; private final boolean failoversPublishSignedDutiesEnabled; private final boolean blockV3Enabled; + private final boolean validateLocallyCreatedBlocks; private final boolean exitWhenNoValidatorKeysEnabled; private final boolean shutdownWhenValidatorSlashedEnabled; private final UInt64 builderRegistrationDefaultGasLimit; @@ -140,6 +142,7 @@ private ValidatorConfig( final boolean failoversSendSubnetSubscriptionsEnabled, final boolean failoversPublishSignedDutiesEnabled, final boolean blockV3Enabled, + final boolean validateLocallyCreatedBlocks, final boolean exitWhenNoValidatorKeysEnabled, final boolean shutdownWhenValidatorSlashedEnabled, final UInt64 builderRegistrationDefaultGasLimit, @@ -183,6 +186,7 @@ private ValidatorConfig( this.failoversSendSubnetSubscriptionsEnabled = failoversSendSubnetSubscriptionsEnabled; this.failoversPublishSignedDutiesEnabled = failoversPublishSignedDutiesEnabled; this.blockV3Enabled = blockV3Enabled; + this.validateLocallyCreatedBlocks = validateLocallyCreatedBlocks; this.exitWhenNoValidatorKeysEnabled = exitWhenNoValidatorKeysEnabled; this.shutdownWhenValidatorSlashedEnabled = shutdownWhenValidatorSlashedEnabled; this.builderRegistrationDefaultGasLimit = builderRegistrationDefaultGasLimit; @@ -324,6 +328,10 @@ public boolean isBlockV3Enabled() { return blockV3Enabled; } + public boolean isValidateLocallyCreatedBlocksEnabled() { + return validateLocallyCreatedBlocks; + } + public boolean isExitWhenNoValidatorKeysEnabled() { return exitWhenNoValidatorKeysEnabled; } @@ -404,6 +412,7 @@ public static final class Builder { private boolean failoversPublishSignedDutiesEnabled = DEFAULT_FAILOVERS_PUBLISH_SIGNED_DUTIES_ENABLED; private boolean blockV3Enabled = DEFAULT_BLOCK_V3_ENABLED; + private boolean validateLocallyCreatedBlocks = DEFAULT_VALIDATE_LOCALLY_CREATED_BLOCKS; private boolean exitWhenNoValidatorKeysEnabled = DEFAULT_EXIT_WHEN_NO_VALIDATOR_KEYS_ENABLED; private boolean shutdownWhenValidatorSlashedEnabled = DEFAULT_SHUTDOWN_WHEN_VALIDATOR_SLASHED_ENABLED; @@ -609,6 +618,11 @@ public Builder blockV3enabled(final boolean useBlockV3) { return this; } + public Builder validateLocallyCreatedBlocks(final boolean validateLocallyCreatedBlocks) { + this.validateLocallyCreatedBlocks = validateLocallyCreatedBlocks; + return this; + } + public Builder exitWhenNoValidatorKeysEnabled(final boolean exitWhenNoValidatorKeysEnabled) { this.exitWhenNoValidatorKeysEnabled = exitWhenNoValidatorKeysEnabled; return this; @@ -704,6 +718,7 @@ public ValidatorConfig build() { failoversSendSubnetSubscriptionsEnabled, failoversPublishSignedDutiesEnabled, blockV3Enabled, + validateLocallyCreatedBlocks, exitWhenNoValidatorKeysEnabled, shutdownWhenValidatorSlashedEnabled, builderRegistrationDefaultGasLimit,