Skip to content

Commit

Permalink
Merge 4f800e5 into a074310
Browse files Browse the repository at this point in the history
  • Loading branch information
g11tech authored Jun 21, 2024
2 parents a074310 + 4f800e5 commit b475aa2
Show file tree
Hide file tree
Showing 193 changed files with 5,489 additions and 965 deletions.
2 changes: 1 addition & 1 deletion packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
},
"dependencies": {
"@chainsafe/persistent-merkle-tree": "^0.7.1",
"@chainsafe/ssz": "^0.15.1",
"@chainsafe/ssz": "^0.16.0",
"@lodestar/config": "^1.19.0",
"@lodestar/params": "^1.19.0",
"@lodestar/types": "^1.19.0",
Expand Down
73 changes: 62 additions & 11 deletions packages/api/src/beacon/routes/beacon/pool.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/naming-convention */
import {ValueOf} from "@chainsafe/ssz";
import {ChainForkConfig} from "@lodestar/config";
import {ForkSeq} from "@lodestar/params";
import {phase0, capella, CommitteeIndex, Slot, ssz} from "@lodestar/types";
import {Schema, Endpoint, RouteDefinitions} from "../../../utils/index.js";
import {
Expand All @@ -12,18 +13,25 @@ import {
EmptyRequest,
EmptyResponseCodec,
EmptyResponseData,
WithVersion,
} from "../../../utils/codecs.js";
import {MetaHeader, VersionCodec, VersionMeta} from "../../../utils/metadata.js";
import {toForkName} from "../../../utils/fork.js";
import {fromHeaders} from "../../../utils/headers.js";

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

const AttestationListType = ArrayOf(ssz.phase0.Attestation);
const AttestationListTypePhase0 = ArrayOf(ssz.phase0.Attestation);
const AttestationListTypeElectra = ArrayOf(ssz.electra.Attestation);
const AttesterSlashingListType = ArrayOf(ssz.phase0.AttesterSlashing);
const ProposerSlashingListType = ArrayOf(ssz.phase0.ProposerSlashing);
const SignedVoluntaryExitListType = ArrayOf(ssz.phase0.SignedVoluntaryExit);
const SignedBLSToExecutionChangeListType = ArrayOf(ssz.capella.SignedBLSToExecutionChange);
const SyncCommitteeMessageListType = ArrayOf(ssz.altair.SyncCommitteeMessage);

type AttestationList = ValueOf<typeof AttestationListType>;
type AttestationListPhase0 = ValueOf<typeof AttestationListTypePhase0>;
type AttestationListElectra = ValueOf<typeof AttestationListTypeElectra>;
type AttestationList = AttestationListPhase0 | AttestationListElectra;
type AttesterSlashingList = ValueOf<typeof AttesterSlashingListType>;
type ProposerSlashingList = ValueOf<typeof ProposerSlashingListType>;
type SignedVoluntaryExitList = ValueOf<typeof SignedVoluntaryExitListType>;
Expand All @@ -40,7 +48,7 @@ export type Endpoints = {
{slot?: Slot; committeeIndex?: CommitteeIndex},
{query: {slot?: number; committee_index?: number}},
AttestationList,
EmptyMeta
VersionMeta
>;

/**
Expand Down Expand Up @@ -106,7 +114,7 @@ export type Endpoints = {
submitPoolAttestations: Endpoint<
"POST",
{signedAttestations: AttestationList},
{body: unknown},
{body: unknown; headers: {[MetaHeader.Version]: string}},
EmptyResponseData,
EmptyMeta
>;
Expand Down Expand Up @@ -172,7 +180,7 @@ export type Endpoints = {
>;
};

export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpoints> {
export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoints> {
return {
getPoolAttestations: {
url: "/eth/v1/beacon/pool/attestations",
Expand All @@ -183,8 +191,10 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpo
schema: {query: {slot: Schema.Uint, committee_index: Schema.Uint}},
},
resp: {
data: AttestationListType,
meta: EmptyMetaCodec,
data: WithVersion((fork) =>
ForkSeq[fork] >= ForkSeq.electra ? AttestationListTypeElectra : AttestationListTypePhase0
),
meta: VersionCodec,
},
},
getPoolAttesterSlashings: {
Expand Down Expand Up @@ -227,12 +237,53 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpo
url: "/eth/v1/beacon/pool/attestations",
method: "POST",
req: {
writeReqJson: ({signedAttestations}) => ({body: AttestationListType.toJson(signedAttestations)}),
parseReqJson: ({body}) => ({signedAttestations: AttestationListType.fromJson(body)}),
writeReqSsz: ({signedAttestations}) => ({body: AttestationListType.serialize(signedAttestations)}),
parseReqSsz: ({body}) => ({signedAttestations: AttestationListType.deserialize(body)}),
writeReqJson: ({signedAttestations}) => {
const fork = config.getForkName(signedAttestations[0].data.slot);
return {
body:
ForkSeq[fork] >= ForkSeq.electra
? AttestationListTypeElectra.toJson(signedAttestations as AttestationListElectra)
: AttestationListTypePhase0.toJson(signedAttestations as AttestationListPhase0),
headers: {[MetaHeader.Version]: fork},
};
},
parseReqJson: ({body, headers}) => {
const versionHeader = fromHeaders(headers, MetaHeader.Version, false);
const fork =
versionHeader !== undefined
? toForkName(versionHeader)
: config.getForkName(Number((body as {data: {slot: string}}[])[0]?.data.slot ?? 0));

return {
signedAttestations:
ForkSeq[fork] >= ForkSeq.electra
? AttestationListTypeElectra.fromJson(body)
: AttestationListTypePhase0.fromJson(body),
};
},
writeReqSsz: ({signedAttestations}) => {
const fork = config.getForkName(signedAttestations[0].data.slot);
return {
body:
ForkSeq[fork] >= ForkSeq.electra
? AttestationListTypeElectra.serialize(signedAttestations as AttestationListElectra)
: AttestationListTypePhase0.serialize(signedAttestations as AttestationListPhase0),
headers: {[MetaHeader.Version]: fork},
};
},
parseReqSsz: ({body, headers}) => {
const versionHeader = fromHeaders(headers, MetaHeader.Version, true);
const fork = toForkName(versionHeader);
return {
signedAttestations:
ForkSeq[fork] >= ForkSeq.electra
? AttestationListTypeElectra.deserialize(body)
: AttestationListTypePhase0.deserialize(body),
};
},
schema: {
body: Schema.ObjectArray,
headers: {[MetaHeader.Version]: Schema.String},
},
},
resp: EmptyResponseCodec,
Expand Down
8 changes: 4 additions & 4 deletions packages/api/src/beacon/routes/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ export type EventData = {
block: RootHex;
executionOptimistic: boolean;
};
[EventType.attestation]: phase0.Attestation;
[EventType.attestation]: {version: ForkName; data: allForks.Attestation};
[EventType.voluntaryExit]: phase0.SignedVoluntaryExit;
[EventType.proposerSlashing]: phase0.ProposerSlashing;
[EventType.attesterSlashing]: phase0.AttesterSlashing;
[EventType.attesterSlashing]: {version: ForkName; data: allForks.AttesterSlashing};
[EventType.blsToExecutionChange]: capella.SignedBLSToExecutionChange;
[EventType.finalizedCheckpoint]: {
block: RootHex;
Expand Down Expand Up @@ -212,10 +212,10 @@ export function getTypeByEvent(): {[K in EventType]: TypeJson<EventData[K]>} {
{jsonCase: "eth2"}
),

[EventType.attestation]: ssz.phase0.Attestation,
[EventType.attestation]: WithVersion((fork) => (ssz.allForks[fork] as allForks.AllForksSSZTypes).Attestation),
[EventType.voluntaryExit]: ssz.phase0.SignedVoluntaryExit,
[EventType.proposerSlashing]: ssz.phase0.ProposerSlashing,
[EventType.attesterSlashing]: ssz.phase0.AttesterSlashing,
[EventType.attesterSlashing]: WithVersion((fork) => ssz.allForks[fork].AttesterSlashing),
[EventType.blsToExecutionChange]: ssz.capella.SignedBLSToExecutionChange,

[EventType.finalizedCheckpoint]: new ContainerType(
Expand Down
108 changes: 86 additions & 22 deletions packages/api/src/beacon/routes/validator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/naming-convention */
import {ContainerType, fromHexString, toHexString, Type, ValueOf} from "@chainsafe/ssz";
import {ChainForkConfig} from "@lodestar/config";
import {isForkBlobs} from "@lodestar/params";
import {isForkBlobs, ForkSeq} from "@lodestar/params";
import {
allForks,
altair,
Expand Down Expand Up @@ -40,6 +40,7 @@ import {
VersionMeta,
VersionType,
} from "../../utils/metadata.js";
import {fromHeaders} from "../../utils/headers.js";

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

Expand Down Expand Up @@ -207,7 +208,8 @@ export const ValidatorIndicesType = ArrayOf(ssz.ValidatorIndex);
export const AttesterDutyListType = ArrayOf(AttesterDutyType);
export const ProposerDutyListType = ArrayOf(ProposerDutyType);
export const SyncDutyListType = ArrayOf(SyncDutyType);
export const SignedAggregateAndProofListType = ArrayOf(ssz.phase0.SignedAggregateAndProof);
export const SignedAggregateAndProofListPhase0Type = ArrayOf(ssz.phase0.SignedAggregateAndProof);
export const SignedAggregateAndProofListElectaType = ArrayOf(ssz.electra.SignedAggregateAndProof);
export const SignedContributionAndProofListType = ArrayOf(ssz.altair.SignedContributionAndProof);
export const BeaconCommitteeSubscriptionListType = ArrayOf(BeaconCommitteeSubscriptionType);
export const SyncCommitteeSubscriptionListType = ArrayOf(SyncCommitteeSubscriptionType);
Expand All @@ -224,7 +226,9 @@ export type ProposerDuty = ValueOf<typeof ProposerDutyType>;
export type ProposerDutyList = ValueOf<typeof ProposerDutyListType>;
export type SyncDuty = ValueOf<typeof SyncDutyType>;
export type SyncDutyList = ValueOf<typeof SyncDutyListType>;
export type SignedAggregateAndProofList = ValueOf<typeof SignedAggregateAndProofListType>;
export type SignedAggregateAndProofListPhase0 = ValueOf<typeof SignedAggregateAndProofListPhase0Type>;
export type SignedAggregateAndProofListElecta = ValueOf<typeof SignedAggregateAndProofListElectaType>;
export type SignedAggregateAndProofList = SignedAggregateAndProofListPhase0 | SignedAggregateAndProofListElecta;
export type SignedContributionAndProofList = ValueOf<typeof SignedContributionAndProofListType>;
export type BeaconCommitteeSubscription = ValueOf<typeof BeaconCommitteeSubscriptionType>;
export type BeaconCommitteeSubscriptionList = ValueOf<typeof BeaconCommitteeSubscriptionListType>;
Expand Down Expand Up @@ -424,10 +428,11 @@ export type Endpoints = {
/** HashTreeRoot of AttestationData that validator want's aggregated */
attestationDataRoot: Root;
slot: Slot;
committeeIndex: number;
},
{query: {attestation_data_root: string; slot: number}},
phase0.Attestation,
EmptyMeta
{query: {attestation_data_root: string; slot: number; committeeIndex: number}},
allForks.Attestation,
VersionMeta
>;

/**
Expand All @@ -437,7 +442,7 @@ export type Endpoints = {
publishAggregateAndProofs: Endpoint<
"POST",
{signedAggregateAndProofs: SignedAggregateAndProofList},
{body: unknown},
{body: unknown; headers: {[MetaHeader.Version]: string}},
EmptyResponseData,
EmptyMeta
>;
Expand Down Expand Up @@ -554,7 +559,7 @@ export type Endpoints = {
>;
};

export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpoints> {
export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoints> {
return {
getAttesterDuties: {
url: "/eth/v1/validator/duties/attester/{epoch}",
Expand Down Expand Up @@ -846,33 +851,92 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpo
url: "/eth/v1/validator/aggregate_attestation",
method: "GET",
req: {
writeReq: ({attestationDataRoot, slot}) => ({
query: {attestation_data_root: toHexString(attestationDataRoot), slot},
writeReq: ({attestationDataRoot, slot, committeeIndex}) => ({
query: {attestation_data_root: toHexString(attestationDataRoot), slot, committeeIndex},
}),
parseReq: ({query}) => ({
attestationDataRoot: fromHexString(query.attestation_data_root),
slot: query.slot,
committeeIndex: query.committeeIndex,
}),
parseReq: ({query}) => ({attestationDataRoot: fromHexString(query.attestation_data_root), slot: query.slot}),
schema: {
query: {attestation_data_root: Schema.StringRequired, slot: Schema.UintRequired},
query: {
attestation_data_root: Schema.StringRequired,
slot: Schema.UintRequired,
committeeIndex: Schema.UintRequired,
},
},
},
resp: {
data: ssz.phase0.Attestation,
meta: EmptyMetaCodec,
data: WithVersion((fork) =>
ForkSeq[fork] >= ForkSeq.electra ? ssz.electra.Attestation : ssz.phase0.Attestation
),
meta: VersionCodec,
},
},
publishAggregateAndProofs: {
url: "/eth/v1/validator/aggregate_and_proofs",
method: "POST",
req: {
writeReqJson: ({signedAggregateAndProofs}) => ({
body: SignedAggregateAndProofListType.toJson(signedAggregateAndProofs),
}),
parseReqJson: ({body}) => ({signedAggregateAndProofs: SignedAggregateAndProofListType.fromJson(body)}),
writeReqSsz: ({signedAggregateAndProofs}) => ({
body: SignedAggregateAndProofListType.serialize(signedAggregateAndProofs),
}),
parseReqSsz: ({body}) => ({signedAggregateAndProofs: SignedAggregateAndProofListType.deserialize(body)}),
writeReqJson: ({signedAggregateAndProofs}) => {
const fork = config.getForkName(signedAggregateAndProofs[0]?.message.aggregate.data.slot ?? 0);
return {
body:
ForkSeq[fork] >= ForkSeq.electra
? SignedAggregateAndProofListElectaType.toJson(
signedAggregateAndProofs as SignedAggregateAndProofListElecta
)
: SignedAggregateAndProofListPhase0Type.toJson(
signedAggregateAndProofs as SignedAggregateAndProofListPhase0
),
headers: {[MetaHeader.Version]: fork},
};
},
parseReqJson: ({body, headers}) => {
const versionHeader = fromHeaders(headers, MetaHeader.Version, false);
const fork =
versionHeader !== undefined
? toForkName(versionHeader)
: config.getForkName(
Number(
(body as {message: {aggregate: {data: {slot: string}}}}[])[0]?.message.aggregate.data.slot ?? 0
)
);

return {
signedAggregateAndProofs:
ForkSeq[fork] >= ForkSeq.electra
? SignedAggregateAndProofListElectaType.fromJson(body)
: SignedAggregateAndProofListPhase0Type.fromJson(body),
};
},
writeReqSsz: ({signedAggregateAndProofs}) => {
const fork = config.getForkName(signedAggregateAndProofs[0]?.message.aggregate.data.slot ?? 0);
return {
body:
ForkSeq[fork] >= ForkSeq.electra
? SignedAggregateAndProofListElectaType.serialize(
signedAggregateAndProofs as SignedAggregateAndProofListElecta
)
: SignedAggregateAndProofListPhase0Type.serialize(
signedAggregateAndProofs as SignedAggregateAndProofListPhase0
),
headers: {[MetaHeader.Version]: fork},
};
},
parseReqSsz: ({body, headers}) => {
const versionHeader = fromHeaders(headers, MetaHeader.Version, true);
const fork = toForkName(versionHeader);
return {
signedAggregateAndProofs:
ForkSeq[fork] >= ForkSeq.electra
? SignedAggregateAndProofListElectaType.deserialize(body)
: SignedAggregateAndProofListPhase0Type.deserialize(body),
};
},
schema: {
body: Schema.ObjectArray,
headers: {[MetaHeader.Version]: Schema.String},
},
},
resp: EmptyResponseCodec,
Expand Down
2 changes: 1 addition & 1 deletion packages/api/test/unit/beacon/testData/beacon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const testData: GenericServerTestCases<Endpoints> = {

getPoolAttestations: {
args: {slot: 1, committeeIndex: 2},
res: {data: [ssz.phase0.Attestation.defaultValue()]},
res: {data: [ssz.phase0.Attestation.defaultValue()], meta: {version: ForkName.deneb}},
},
getPoolAttesterSlashings: {
args: undefined,
Expand Down
Loading

0 comments on commit b475aa2

Please sign in to comment.