Skip to content

Commit

Permalink
feat: allow validator to request blinded versions for locally produce…
Browse files Browse the repository at this point in the history
…d and selected blocks (#6227)

* feat: allow validator to request blinded versions for locally produced and selected blocks

lint

fix the types and tests

* add blinded local combinations to sim

* debug and fix issues
  • Loading branch information
g11tech authored Dec 31, 2023
1 parent 5408bab commit c86a669
Show file tree
Hide file tree
Showing 11 changed files with 378 additions and 186 deletions.
29 changes: 24 additions & 5 deletions packages/api/src/beacon/routes/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
SubcommitteeIndex,
Wei,
Gwei,
ProducedBlockSource,
} from "@lodestar/types";
import {ApiClientResponse} from "../../interfaces.js";
import {HttpStatusCode} from "../../utils/client/httpStatusCode.js";
Expand Down Expand Up @@ -53,6 +54,7 @@ export type ExtraProduceBlockOps = {
feeRecipient?: string;
builderSelection?: BuilderSelection;
strictFeeRecipientCheck?: boolean;
blindedLocal?: boolean;
};

export type ProduceBlockOrContentsRes = {executionPayloadValue: Wei; consensusBlockValue: Gwei} & (
Expand All @@ -64,9 +66,10 @@ export type ProduceBlindedBlockRes = {executionPayloadValue: Wei; consensusBlock
version: ForkExecution;
};

export type ProduceFullOrBlindedBlockOrContentsRes =
export type ProduceFullOrBlindedBlockOrContentsRes = {executionPayloadSource: ProducedBlockSource} & (
| (ProduceBlockOrContentsRes & {executionPayloadBlinded: false})
| (ProduceBlindedBlockRes & {executionPayloadBlinded: true});
| (ProduceBlindedBlockRes & {executionPayloadBlinded: true})
);

// See /packages/api/src/routes/index.ts for reasoning and instructions to add new routes

Expand Down Expand Up @@ -485,6 +488,7 @@ export type ReqTypes = {
fee_recipient?: string;
builder_selection?: string;
strict_fee_recipient_check?: boolean;
blinded_local?: boolean;
};
};
produceBlindedBlock: {params: {slot: number}; query: {randao_reveal: string; graffiti: string}};
Expand Down Expand Up @@ -552,6 +556,7 @@ export function getReqSerializers(): ReqSerializers<Api, ReqTypes> {
skip_randao_verification: skipRandaoVerification,
builder_selection: opts?.builderSelection,
strict_fee_recipient_check: opts?.strictFeeRecipientCheck,
blinded_local: opts?.blindedLocal,
},
}),
parseReq: ({params, query}) => [
Expand All @@ -563,6 +568,7 @@ export function getReqSerializers(): ReqSerializers<Api, ReqTypes> {
feeRecipient: query.fee_recipient,
builderSelection: query.builder_selection as BuilderSelection,
strictFeeRecipientCheck: query.strict_fee_recipient_check,
blindedLocal: query.blinded_local,
},
],
schema: {
Expand All @@ -574,6 +580,7 @@ export function getReqSerializers(): ReqSerializers<Api, ReqTypes> {
skip_randao_verification: Schema.Boolean,
builder_selection: Schema.String,
strict_fee_recipient_check: Schema.Boolean,
blinded_local: Schema.Boolean,
},
},
};
Expand Down Expand Up @@ -739,20 +746,32 @@ export function getReturnTypes(): ReturnTypes<Api> {
if (data.executionPayloadBlinded) {
return {
execution_payload_blinded: true,
execution_payload_source: data.executionPayloadSource,
...(produceBlindedBlock.toJson(data) as Record<string, unknown>),
};
} else {
return {
execution_payload_blinded: false,
execution_payload_source: data.executionPayloadSource,
...(produceBlockOrContents.toJson(data) as Record<string, unknown>),
};
}
},
fromJson: (data) => {
if ((data as {execution_payload_blinded: true}).execution_payload_blinded) {
return {executionPayloadBlinded: true, ...produceBlindedBlock.fromJson(data)};
const executionPayloadBlinded = (data as {execution_payload_blinded: boolean}).execution_payload_blinded;
if (executionPayloadBlinded === undefined) {
throw Error(`Invalid executionPayloadBlinded=${executionPayloadBlinded} for fromJson deserialization`);
}

// extract source from the data and assign defaults in the spec complaint manner if not present in response
const executionPayloadSource =
(data as {execution_payload_source: ProducedBlockSource}).execution_payload_source ??
(executionPayloadBlinded ? ProducedBlockSource.builder : ProducedBlockSource.engine);

if (executionPayloadBlinded) {
return {executionPayloadBlinded, executionPayloadSource, ...produceBlindedBlock.fromJson(data)};
} else {
return {executionPayloadBlinded: false, ...produceBlockOrContents.fromJson(data)};
return {executionPayloadBlinded, executionPayloadSource, ...produceBlockOrContents.fromJson(data)};
}
},
},
Expand Down
3 changes: 2 additions & 1 deletion packages/api/test/unit/beacon/testData/validator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {ForkName} from "@lodestar/params";
import {ssz} from "@lodestar/types";
import {ssz, ProducedBlockSource} from "@lodestar/types";
import {Api} from "../../../../src/beacon/routes/validator.js";
import {GenericServerTestCases} from "../../../utils/genericServerTest.js";

Expand Down Expand Up @@ -83,6 +83,7 @@ export const testData: GenericServerTestCases<Api> = {
executionPayloadValue: ssz.Wei.defaultValue(),
consensusBlockValue: ssz.Gwei.defaultValue(),
executionPayloadBlinded: false,
executionPayloadSource: ProducedBlockSource.engine,
},
},
produceBlindedBlock: {
Expand Down
Loading

0 comments on commit c86a669

Please sign in to comment.