Skip to content

Commit

Permalink
feat: allow builder only proposal flow for benefit of DVT protocols (#…
Browse files Browse the repository at this point in the history
…5669)

* feat: allow builder only proposal flow for benefit of DVT protocols

* fix typo

* apply feedback

* update descp

* add suggestion

Co-authored-by: Nico Flaig <nflaig@protonmail.com>

---------

Co-authored-by: Nico Flaig <nflaig@protonmail.com>
  • Loading branch information
g11tech and nflaig authored Jun 19, 2023
1 parent c8f94b7 commit 7c54a7b
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 9 deletions.
2 changes: 2 additions & 0 deletions packages/cli/src/cmds/validator/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ function parseBuilderSelection(builderSelection?: string): BuilderSelection | un
break;
case "builderalways":
break;
case "builderonly":
break;
default:
throw Error("Invalid input for builder selection, check help.");
}
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/cmds/validator/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ export const validatorOptions: CliCommandOptions<IValidatorCliArgs> = {

"builder.selection": {
type: "string",
description: "Default builder block selection strategy: maxprofit or builderalways",
description: "Default builder block selection strategy: maxprofit, builderalways, or builderonly",
defaultDescription: `${defaultOptions.builderSelection}`,
group: "builder",
},
Expand Down
39 changes: 31 additions & 8 deletions packages/validator/src/services/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,20 @@ export class BlockProposingService {

const debugLogCtx = {...logCtx, validator: pubkeyHex};

this.logger.debug("Producing block", debugLogCtx);
this.metrics?.proposerStepCallProduceBlock.observe(this.clock.secFromSlot(slot));

const strictFeeRecipientCheck = this.validatorStore.strictFeeRecipientCheck(pubkeyHex);
const isBuilderEnabled = this.validatorStore.isBuilderEnabled(pubkeyHex);
const builderSelection = this.validatorStore.getBuilderSelection(pubkeyHex);
const expectedFeeRecipient = this.validatorStore.getFeeRecipient(pubkeyHex);

this.logger.debug("Producing block", {
...debugLogCtx,
isBuilderEnabled,
builderSelection,
expectedFeeRecipient,
strictFeeRecipientCheck,
});
this.metrics?.proposerStepCallProduceBlock.observe(this.clock.secFromSlot(slot));

const blockContents = await this.produceBlockWrapper(slot, randaoReveal, graffiti, {
expectedFeeRecipient,
strictFeeRecipientCheck,
Expand Down Expand Up @@ -190,10 +196,20 @@ export class BlockProposingService {
> => {
// Start calls for building execution and builder blocks
const blindedBlockPromise = isBuilderEnabled ? this.produceBlindedBlock(slot, randaoReveal, graffiti) : null;
const fullBlockPromise = this.produceBlock(slot, randaoReveal, graffiti);
const fullBlockPromise =
// At any point either the builder or execution or both flows should be active.
//
// Ideally such a scenario should be prevented on startup, but proposerSettingsFile or keymanager
// configurations could cause a validator pubkey to have builder disabled with builder selection builder only
// (TODO: independently make sure such an options update is not successful for a validator pubkey)
//
// So if builder is disabled ignore builder selection of builderonly if caused by user mistake
!isBuilderEnabled || builderSelection !== BuilderSelection.BuilderOnly
? this.produceBlock(slot, randaoReveal, graffiti)
: null;

let blindedBlock, fullBlock;
if (blindedBlockPromise !== null) {
if (blindedBlockPromise !== null && fullBlockPromise !== null) {
// reference index of promises in the race
const promisesOrder = [ProducedBlockSource.builder, ProducedBlockSource.engine];
[blindedBlock, fullBlock] = await racePromisesWithCutoff<{
Expand Down Expand Up @@ -225,9 +241,16 @@ export class BlockProposingService {
this.logger.error("Failed to produce execution block", {}, fullBlock);
fullBlock = null;
}
} else {
fullBlock = await fullBlockPromise;
} else if (blindedBlockPromise !== null && fullBlockPromise === null) {
blindedBlock = await blindedBlockPromise;
fullBlock = null;
} else if (blindedBlockPromise === null && fullBlockPromise !== null) {
blindedBlock = null;
fullBlock = await fullBlockPromise;
} else {
throw Error(
`Internal Error: Neither builder nor execution proposal flow activated isBuilderEnabled=${isBuilderEnabled} builderSelection=${builderSelection}`
);
}

const builderBlockValue = blindedBlock?.blockValue ?? BigInt(0);
Expand All @@ -252,7 +275,7 @@ export class BlockProposingService {
break;
}

case BuilderSelection.BuilderAlways:
// For everything else just select the builder
default: {
selectedSource = ProducedBlockSource.builder;
selectedBlock = blindedBlock;
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 @@ -67,6 +67,8 @@ export type SignerRemote = {
export enum BuilderSelection {
BuilderAlways = "builderalways",
MaxProfit = "maxprofit",
/** Only activate builder flow for DVT block proposal protocols */
BuilderOnly = "builderonly",
}

type DefaultProposerConfig = {
Expand Down

0 comments on commit 7c54a7b

Please sign in to comment.