Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: placeholder PR for electra #6352

Draft
wants to merge 57 commits into
base: unstable
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
08884f8
feat: placeholder PR for electra
g11tech Jan 24, 2024
3d2b69b
feat: implement EIP-6110 (#6042)
ensi321 Feb 19, 2024
7cb27fa
chore: fix CI failure due to recent merge from `unstable` (#6646)
ensi321 Apr 12, 2024
3a8a4be
feat: implement execution layer exits eip 7002 (#6651)
g11tech Apr 22, 2024
0155bdd
chore: update spec test version for electra fork (#6717)
ensi321 May 1, 2024
768f42b
feat: add presets and ssz types for EIP-7549 (#6715)
ensi321 May 4, 2024
62d401c
chore: fix the rebase build (#6735)
g11tech May 4, 2024
a6e21b2
feat: upgrade 7002 exits to withdrawal request (#6736)
g11tech May 5, 2024
3fede47
feat: implement maxEB EIP-7251 (#6539)
ensi321 May 7, 2024
fbd7feb
feat: beacon node process electra attestations EIP-7549 (#6738)
ensi321 May 7, 2024
93f0876
feat: handle the EL payload sending data in deposit requests instead …
g11tech May 8, 2024
838c6d8
feat: implement EIP-7549 (#6689)
ensi321 May 8, 2024
aaca7a7
fix: attestation pool for electra (#6744)
twoeths May 8, 2024
c1286d3
feat: update engineapi endpoints to v4 (#6747)
g11tech May 8, 2024
1cc9cbd
feat: rename deposit receipt to deposit request for Pectra (#6748)
ensi321 May 8, 2024
176f452
test: enable spec tests related to eip-7549 (#6741)
nazarhussain May 8, 2024
06fcec2
fix: fix e2e test in electra-fork (#6751)
ensi321 May 8, 2024
2e4ee0e
feat: get the basic integration working with the ethereumjs electra b…
g11tech May 8, 2024
8a5f1a5
feat: apply some fixes and hacks to get the single node devnet workin…
g11tech May 9, 2024
f11e09c
fix: get aggregate and proofs signature sets (#6757)
twoeths May 10, 2024
44fb7e8
test(spec): fix attestors slashing specs for electra fork (#6758)
nazarhussain May 10, 2024
5bbe347
chore: fix types and lint (#6750)
g11tech May 13, 2024
0d2c477
fix: fix electra genesis spec test (#6764)
ensi321 May 14, 2024
7c1a355
feat: support missing electra spec test (#6765)
ensi321 May 14, 2024
3c17e73
test: fix ssz types in fork_choice spec tests (#6767)
nflaig May 14, 2024
f4d2ce7
chore: update EffectiveBalanceIncrements type (#6763)
jeluard May 14, 2024
98c9350
Fix ssz_static
ensi321 May 14, 2024
5a6bf85
fix: inline sourcemaps to help with debugging (#6768)
matthewkeil May 14, 2024
c516c42
fix: additional epoch calculation logic for consolidation churn (#6770)
nazarhussain May 14, 2024
005b639
fix: electra fork transition spec tests (#6769)
twoeths May 14, 2024
82d0692
test: fix ssz_static spec tests for all forks (#6771)
nflaig May 14, 2024
ef907bc
chore(spec): remove the skip specs for electra (#6772)
nazarhussain May 14, 2024
fcd3dd6
fix: use mutable validator object (#6774)
ensi321 May 14, 2024
5af1b12
test: fix balance spec tests (#6777)
matthewkeil May 14, 2024
eeff0f8
fix: effective balance cache is not in sync with validator effective …
ensi321 May 14, 2024
aa7cc39
fix: make electra-fork passes lint and check-types (#6785)
ensi321 May 16, 2024
7131216
fix: update data format of WithdrawalRequestV1 (#6789)
nflaig May 16, 2024
c1c1b26
fix: publish attestations with non-zero committee index (#6790)
ensi321 May 16, 2024
64d13ed
fix: validator monitor summaries should not render during epoch 0 (#6…
ensi321 May 16, 2024
0646136
fix: attestation duty validation (#6792)
ensi321 May 16, 2024
274f629
fix: align BeaconBlockBody and BlindedBeaconBlockBody (#6782)
wemeetagain May 16, 2024
c015abc
test: improve ssz tests consistency (#6776)
jeluard May 16, 2024
d80cfb5
fix: batch validation for electra attestations (#6788)
twoeths May 16, 2024
bd6cbe5
fix: update withdrawal request container to match consensus spec (#6797)
nflaig May 16, 2024
9b04953
fix: get seen AttData key from SignedAggregateAndProof electra (#6802)
twoeths May 17, 2024
5a53c6c
test: only skip ssz_static tests associated to missing type (#6798)
nflaig May 23, 2024
602218f
chore: types and lint fixes (#6819)
g11tech May 25, 2024
9b8fc05
feat: add engine_getPayloadBodiesByHash and ByRange V2 (#6852)
ensi321 Jun 8, 2024
e311409
fix: align WithdrawalRequestV1 field names with latest spec (#6877)
nflaig Jun 12, 2024
04c68cd
feat: move attestation committee at the end of attestation (#6883)
ensi321 Jun 14, 2024
3016acf
rebase fixes
g11tech Jun 19, 2024
d5f8549
feat: handle exited/exiting validators during top up (#6880)
ensi321 Jun 21, 2024
fdc8ac2
feat: add EL triggered consolidation and remove `ExecutionLayer` pref…
ensi321 Jun 21, 2024
f74b706
feat: support electra devnet-1 (#6892)
ensi321 Jun 25, 2024
63586af
fix: electra rebase fixes on the new generic typing model
g11tech Jun 25, 2024
0330d03
feat: add and parse consolidation requests from engine api
g11tech Jul 1, 2024
68cefff
feat: make produce block/signed block contents api multifork
g11tech Jul 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
84 changes: 36 additions & 48 deletions packages/api/src/beacon/routes/beacon/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import {
BeaconBlockBody,
SignedBeaconBlockOrContents,
SignedBlindedBeaconBlock,
SignedBlockContents,
sszTypesFor,
} from "@lodestar/types";
import {ForkName, ForkPreExecution, ForkSeq, isForkExecution} from "@lodestar/params";
import {ForkName, ForkPreExecution, isForkBlobs, isForkExecution} from "@lodestar/params";
import {Endpoint, RequestCodec, RouteDefinitions, Schema} from "../../../utils/index.js";
import {EmptyMeta, EmptyResponseCodec, EmptyResponseData, WithVersion} from "../../../utils/codecs.js";
import {
Expand All @@ -37,19 +39,10 @@ export const BlockHeadersResponseType = new ListCompositeType(BlockHeaderRespons
export const RootResponseType = new ContainerType({
root: ssz.Root,
});
export const SignedBlockContentsType = new ContainerType(
{
signedBlock: ssz.deneb.SignedBeaconBlock,
kzgProofs: ssz.deneb.KZGProofs,
blobs: ssz.deneb.Blobs,
},
{jsonCase: "eth2"}
);

export type BlockHeaderResponse = ValueOf<typeof BlockHeaderResponseType>;
export type BlockHeadersResponse = ValueOf<typeof BlockHeadersResponseType>;
export type RootResponse = ValueOf<typeof RootResponseType>;
export type SignedBlockContents = ValueOf<typeof SignedBlockContentsType>;

export type BlockId = RootHex | Slot | "head" | "genesis" | "finalized" | "justified";

Expand Down Expand Up @@ -297,11 +290,12 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoi
const slot = isSignedBlockContents(signedBlockOrContents)
? signedBlockOrContents.signedBlock.message.slot
: signedBlockOrContents.message.slot;
const fork = config.getForkName(slot);

return {
body:
config.getForkSeq(slot) < ForkSeq.deneb
? config.getForkTypes(slot).SignedBeaconBlock.toJson(signedBlockOrContents as SignedBeaconBlock)
: SignedBlockContentsType.toJson(signedBlockOrContents as SignedBlockContents),
body: isForkBlobs(fork)
? ssz.allForksBlobs[fork].SignedBlockContents.toJson(signedBlockOrContents as SignedBlockContents)
: sszTypesFor(fork).SignedBeaconBlock.toJson(signedBlockOrContents as SignedBeaconBlock),
headers: {
[MetaHeader.Version]: config.getForkName(slot),
},
Expand All @@ -321,36 +315,33 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoi
: (body as SignedBeaconBlock).message.slot
);
}
const forkSeq = config.forks[forkName].seq;
return {
signedBlockOrContents:
forkSeq < ForkSeq.deneb
? ssz[forkName].SignedBeaconBlock.fromJson(body)
: SignedBlockContentsType.fromJson(body),
signedBlockOrContents: isForkBlobs(forkName)
? ssz.allForksBlobs[forkName].SignedBlockContents.fromJson(body)
: ssz[forkName].SignedBeaconBlock.fromJson(body),
};
},
writeReqSsz: ({signedBlockOrContents}) => {
const slot = isSignedBlockContents(signedBlockOrContents)
? signedBlockOrContents.signedBlock.message.slot
: signedBlockOrContents.message.slot;
const fork = config.getForkName(slot);

return {
body:
config.getForkSeq(slot) < ForkSeq.deneb
? config.getForkTypes(slot).SignedBeaconBlock.serialize(signedBlockOrContents as SignedBeaconBlock)
: SignedBlockContentsType.serialize(signedBlockOrContents as SignedBlockContents),
body: isForkBlobs(fork)
? ssz.allForksBlobs[fork].SignedBlockContents.serialize(signedBlockOrContents as SignedBlockContents)
: sszTypesFor(fork).SignedBeaconBlock.serialize(signedBlockOrContents as SignedBeaconBlock),
headers: {
[MetaHeader.Version]: config.getForkName(slot),
},
};
},
parseReqSsz: ({body, headers}) => {
const forkName = toForkName(fromHeaders(headers, MetaHeader.Version));
const forkSeq = config.forks[forkName].seq;
return {
signedBlockOrContents:
forkSeq < ForkSeq.deneb
? ssz[forkName].SignedBeaconBlock.deserialize(body)
: SignedBlockContentsType.deserialize(body),
signedBlockOrContents: isForkBlobs(forkName)
? ssz.allForksBlobs[forkName].SignedBlockContents.deserialize(body)
: ssz[forkName].SignedBeaconBlock.deserialize(body),
};
},
schema: {
Expand All @@ -371,51 +362,48 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoi
const slot = isSignedBlockContents(signedBlockOrContents)
? signedBlockOrContents.signedBlock.message.slot
: signedBlockOrContents.message.slot;
const fork = config.getForkName(slot);
return {
body:
config.getForkSeq(slot) < ForkSeq.deneb
? config.getForkTypes(slot).SignedBeaconBlock.toJson(signedBlockOrContents as SignedBeaconBlock)
: SignedBlockContentsType.toJson(signedBlockOrContents as SignedBlockContents),
body: isForkBlobs(fork)
? ssz.allForksBlobs[fork].SignedBlockContents.toJson(signedBlockOrContents as SignedBlockContents)
: sszTypesFor(fork).SignedBeaconBlock.toJson(signedBlockOrContents as SignedBeaconBlock),
headers: {
[MetaHeader.Version]: config.getForkName(slot),
[MetaHeader.Version]: fork,
},
query: {broadcast_validation: broadcastValidation},
};
},
parseReqJson: ({body, headers, query}) => {
const forkName = toForkName(fromHeaders(headers, MetaHeader.Version));
const forkSeq = config.forks[forkName].seq;
return {
signedBlockOrContents:
forkSeq < ForkSeq.deneb
? ssz[forkName].SignedBeaconBlock.fromJson(body)
: SignedBlockContentsType.fromJson(body),
signedBlockOrContents: isForkBlobs(forkName)
? ssz.allForksBlobs[forkName].SignedBlockContents.fromJson(body)
: ssz[forkName].SignedBeaconBlock.fromJson(body),
broadcastValidation: query.broadcast_validation as BroadcastValidation,
};
},
writeReqSsz: ({signedBlockOrContents, broadcastValidation}) => {
const slot = isSignedBlockContents(signedBlockOrContents)
? signedBlockOrContents.signedBlock.message.slot
: signedBlockOrContents.message.slot;
const fork = config.getForkName(slot);

return {
body:
config.getForkSeq(slot) < ForkSeq.deneb
? config.getForkTypes(slot).SignedBeaconBlock.serialize(signedBlockOrContents as SignedBeaconBlock)
: SignedBlockContentsType.serialize(signedBlockOrContents as SignedBlockContents),
body: isForkBlobs(fork)
? ssz.allForksBlobs[fork].SignedBlockContents.serialize(signedBlockOrContents as SignedBlockContents)
: sszTypesFor(fork).SignedBeaconBlock.serialize(signedBlockOrContents as SignedBeaconBlock),
headers: {
[MetaHeader.Version]: config.getForkName(slot),
[MetaHeader.Version]: fork,
},
query: {broadcast_validation: broadcastValidation},
};
},
parseReqSsz: ({body, headers, query}) => {
const forkName = toForkName(fromHeaders(headers, MetaHeader.Version));
const forkSeq = config.forks[forkName].seq;
return {
signedBlockOrContents:
forkSeq < ForkSeq.deneb
? ssz[forkName].SignedBeaconBlock.deserialize(body)
: SignedBlockContentsType.deserialize(body),
signedBlockOrContents: isForkBlobs(forkName)
? ssz.allForksBlobs[forkName].SignedBlockContents.deserialize(body)
: ssz[forkName].SignedBeaconBlock.deserialize(body),
broadcastValidation: query.broadcast_validation as BroadcastValidation,
};
},
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
11 changes: 7 additions & 4 deletions packages/api/src/beacon/routes/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import {
LightClientOptimisticUpdate,
LightClientFinalityUpdate,
SSEPayloadAttributes,
Attestation,
AttesterSlashing,
sszTypesFor,
} from "@lodestar/types";
import {ForkName} from "@lodestar/params";

Expand Down Expand Up @@ -104,10 +107,10 @@ export type EventData = {
block: RootHex;
executionOptimistic: boolean;
};
[EventType.attestation]: phase0.Attestation;
[EventType.attestation]: {version: ForkName; data: Attestation};
[EventType.voluntaryExit]: phase0.SignedVoluntaryExit;
[EventType.proposerSlashing]: phase0.ProposerSlashing;
[EventType.attesterSlashing]: phase0.AttesterSlashing;
[EventType.attesterSlashing]: {version: ForkName; data: AttesterSlashing};
[EventType.blsToExecutionChange]: capella.SignedBLSToExecutionChange;
[EventType.finalizedCheckpoint]: {
block: RootHex;
Expand Down Expand Up @@ -225,10 +228,10 @@ export function getTypeByEvent(): {[K in EventType]: TypeJson<EventData[K]>} {
{jsonCase: "eth2"}
),

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

[EventType.finalizedCheckpoint]: new ContainerType(
Expand Down
Loading