Skip to content

Commit

Permalink
feat: allow configuring broadcast validation on validator for proposals
Browse files Browse the repository at this point in the history
  • Loading branch information
g11tech committed Dec 1, 2023
1 parent 6208e2d commit 45e9fc0
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 11 deletions.
16 changes: 16 additions & 0 deletions packages/cli/src/cmds/validator/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ export async function validatorHandler(args: IValidatorCliArgs & GlobalArgs): Pr
valProposerConfig,
distributed: args.distributed,
useProduceBlockV3: args.useProduceBlockV3,
broadcastValidation: parseBroadcastValidation(args.broadcastValidation),
},
metrics
);
Expand Down Expand Up @@ -268,3 +269,18 @@ function parseBuilderSelection(builderSelection?: string): routes.validator.Buil
}
return builderSelection as routes.validator.BuilderSelection;
}

function parseBroadcastValidation(broadcastValidation?: string): routes.beacon.BroadcastValidation | undefined {
if (broadcastValidation) {
switch (broadcastValidation) {
case "gossip":
case "consensus":
case "consensus_and_equivocation":
break;
default:
throw Error("Invalid input for broadcastValidation, check help");
}
}

return broadcastValidation as routes.beacon.BroadcastValidation;
}
7 changes: 7 additions & 0 deletions packages/cli/src/cmds/validator/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export type IValidatorCliArgs = AccountValidatorArgs &
"builder.selection"?: string;

useProduceBlockV3?: boolean;
broadcastValidation?: string;

importKeystores?: string[];
importKeystoresPassword?: string;
Expand Down Expand Up @@ -250,6 +251,12 @@ export const validatorOptions: CliCommandOptions<IValidatorCliArgs> = {
defaultDescription: `${defaultOptions.useProduceBlockV3}`,
},

broadcastValidation: {
type: "string",
description: "Validations to be run by beacon node for the signed block prior to publishing",
defaultDescription: `${defaultOptions.broadcastValidation}`,
},

importKeystores: {
alias: ["keystore"], // Backwards compatibility with old `validator import` cmdx
description: "Path(s) to a directory or single file path to validator keystores, i.e. Launchpad validators",
Expand Down
29 changes: 19 additions & 10 deletions packages/validator/src/services/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class BlockProposingService {
private readonly clock: IClock,
private readonly validatorStore: ValidatorStore,
private readonly metrics: Metrics | null,
private readonly opts: {useProduceBlockV3: boolean}
private readonly opts: {useProduceBlockV3: boolean; broadcastValidation: routes.beacon.BroadcastValidation}
) {
this.dutiesService = new BlockDutiesService(
config,
Expand Down Expand Up @@ -158,7 +158,9 @@ export class BlockProposingService {
signedBlobs = undefined;
}

await this.publishBlockWrapper(signedBlock, signedBlobs).catch((e: Error) => {
await this.publishBlockWrapper(signedBlock, signedBlobs, {
broadcastValidation: this.opts.broadcastValidation,
}).catch((e: Error) => {
this.metrics?.blockProposingErrors.inc({error: "publish"});
throw extendError(e, "Failed to publish block");
});
Expand All @@ -172,22 +174,29 @@ export class BlockProposingService {

private publishBlockWrapper = async (
signedBlock: allForks.FullOrBlindedSignedBeaconBlock,
signedBlobSidecars?: allForks.FullOrBlindedSignedBlobSidecar[]
signedBlobSidecars?: allForks.FullOrBlindedSignedBlobSidecar[],
opts: {broadcastValidation?: routes.beacon.BroadcastValidation} = {}
): Promise<void> => {
if (signedBlobSidecars === undefined) {
ApiError.assert(
isBlindedBeaconBlock(signedBlock.message)
? await this.api.beacon.publishBlindedBlock(signedBlock as allForks.SignedBlindedBeaconBlock)
: await this.api.beacon.publishBlockV2(signedBlock as allForks.SignedBeaconBlock)
? await this.api.beacon.publishBlindedBlockV2(signedBlock as allForks.SignedBlindedBeaconBlock, opts)
: await this.api.beacon.publishBlockV2(signedBlock as allForks.SignedBeaconBlock, opts)
);
} else {
ApiError.assert(
isBlindedBeaconBlock(signedBlock.message)
? await this.api.beacon.publishBlindedBlock({
signedBlindedBlock: signedBlock,
signedBlindedBlobSidecars: signedBlobSidecars,
} as allForks.SignedBlindedBlockContents)
: await this.api.beacon.publishBlockV2({signedBlock, signedBlobSidecars} as allForks.SignedBlockContents)
? await this.api.beacon.publishBlindedBlockV2(
{
signedBlindedBlock: signedBlock,
signedBlindedBlobSidecars: signedBlobSidecars,
} as allForks.SignedBlindedBlockContents,
opts
)
: await this.api.beacon.publishBlockV2(
{signedBlock, signedBlobSidecars} as allForks.SignedBlockContents,
opts
)
);
}
};
Expand Down
2 changes: 2 additions & 0 deletions packages/validator/src/services/validatorStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ export const defaultOptions = {
builderAliasSelection: routes.validator.BuilderSelection.MaxProfit,
// turn it off by default, turn it back on once other clients support v3 api
useProduceBlockV3: false,
// spec asks for gossip validation by default
broadcastValidation: routes.beacon.BroadcastValidation.gossip,
};

/**
Expand Down
10 changes: 9 additions & 1 deletion packages/validator/src/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export type ValidatorOptions = {
valProposerConfig?: ValidatorProposerConfig;
distributed?: boolean;
useProduceBlockV3?: boolean;
broadcastValidation?: routes.beacon.BroadcastValidation;
};

// TODO: Extend the timeout, and let it be customizable
Expand Down Expand Up @@ -208,6 +209,7 @@ export class Validator {

const blockProposingService = new BlockProposingService(config, loggerVc, api, clock, validatorStore, metrics, {
useProduceBlockV3: opts.useProduceBlockV3 ?? defaultOptions.useProduceBlockV3,
broadcastValidation: opts.broadcastValidation ?? defaultOptions.broadcastValidation,
});

const attestationService = new AttestationService(
Expand Down Expand Up @@ -285,13 +287,19 @@ export class Validator {
await assertEqualGenesis(opts, genesis);
logger.info("Verified connected beacon node and validator have the same genesisValidatorRoot");

const {useProduceBlockV3 = defaultOptions.useProduceBlockV3, valProposerConfig} = opts;
const {
useProduceBlockV3 = defaultOptions.useProduceBlockV3,
broadcastValidation = defaultOptions.broadcastValidation,
valProposerConfig,
} = opts;
const defaultBuilderSelection =
valProposerConfig?.defaultConfig.builder?.selection ?? defaultOptions.builderSelection;
const strictFeeRecipientCheck = valProposerConfig?.defaultConfig.strictFeeRecipientCheck ?? false;
const suggestedFeeRecipient = valProposerConfig?.defaultConfig.feeRecipient ?? defaultOptions.suggestedFeeRecipient;

logger.info("Initializing validator", {
useProduceBlockV3,
broadcastValidation,
defaultBuilderSelection,
suggestedFeeRecipient,
strictFeeRecipientCheck,
Expand Down
1 change: 1 addition & 0 deletions packages/validator/test/unit/services/block.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ describe("BlockDutiesService", function () {
// use produceBlockV3
const blockService = new BlockProposingService(config, loggerVc, api, clock, validatorStore, null, {
useProduceBlockV3: true,
broadcastValidation: "consensus",
});

const signedBlock = ssz.phase0.SignedBeaconBlock.defaultValue();
Expand Down

0 comments on commit 45e9fc0

Please sign in to comment.