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: add electra support for light client #7038

Closed
wants to merge 69 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
99896f2
feat: placeholder PR for electra
g11tech Jan 24, 2024
a250008
feat: implement EIP-6110 (#6042)
ensi321 Feb 19, 2024
55f9978
chore: fix CI failure due to recent merge from `unstable` (#6646)
ensi321 Apr 12, 2024
d2d4959
feat: implement execution layer exits eip 7002 (#6651)
g11tech Apr 22, 2024
b43184e
chore: update spec test version for electra fork (#6717)
ensi321 May 1, 2024
54220d8
feat: add presets and ssz types for EIP-7549 (#6715)
ensi321 May 4, 2024
b744cb0
chore: fix the rebase build (#6735)
g11tech May 4, 2024
34a3d60
feat: upgrade 7002 exits to withdrawal request (#6736)
g11tech May 5, 2024
0f77e97
feat: implement maxEB EIP-7251 (#6539)
ensi321 May 7, 2024
6b1e194
feat: beacon node process electra attestations EIP-7549 (#6738)
ensi321 May 7, 2024
bbb7e31
feat: handle the EL payload sending data in deposit requests instead …
g11tech May 8, 2024
fd2f18b
feat: implement EIP-7549 (#6689)
ensi321 May 8, 2024
dc6aaee
fix: attestation pool for electra (#6744)
twoeths May 8, 2024
0516438
feat: update engineapi endpoints to v4 (#6747)
g11tech May 8, 2024
60832a2
feat: rename deposit receipt to deposit request for Pectra (#6748)
ensi321 May 8, 2024
e82ac1f
test: enable spec tests related to eip-7549 (#6741)
nazarhussain May 8, 2024
c72791c
fix: fix e2e test in electra-fork (#6751)
ensi321 May 8, 2024
2afb854
feat: get the basic integration working with the ethereumjs electra b…
g11tech May 8, 2024
26f6c95
feat: apply some fixes and hacks to get the single node devnet workin…
g11tech May 9, 2024
c65ac59
fix: get aggregate and proofs signature sets (#6757)
twoeths May 10, 2024
40a476b
test(spec): fix attestors slashing specs for electra fork (#6758)
nazarhussain May 10, 2024
58a8e89
chore: fix types and lint (#6750)
g11tech May 13, 2024
26e1a79
fix: fix electra genesis spec test (#6764)
ensi321 May 14, 2024
8751004
feat: support missing electra spec test (#6765)
ensi321 May 14, 2024
b196ab0
test: fix ssz types in fork_choice spec tests (#6767)
nflaig May 14, 2024
f42ba08
chore: update EffectiveBalanceIncrements type (#6763)
jeluard May 14, 2024
54f3e59
Fix ssz_static
ensi321 May 14, 2024
c29c6e4
fix: inline sourcemaps to help with debugging (#6768)
matthewkeil May 14, 2024
512a1bb
fix: additional epoch calculation logic for consolidation churn (#6770)
nazarhussain May 14, 2024
b008cf4
fix: electra fork transition spec tests (#6769)
twoeths May 14, 2024
89a0151
test: fix ssz_static spec tests for all forks (#6771)
nflaig May 14, 2024
4f131b7
chore(spec): remove the skip specs for electra (#6772)
nazarhussain May 14, 2024
33c6216
fix: use mutable validator object (#6774)
ensi321 May 14, 2024
3c87abb
test: fix balance spec tests (#6777)
matthewkeil May 14, 2024
87b25aa
fix: effective balance cache is not in sync with validator effective …
ensi321 May 14, 2024
7accebe
fix: make electra-fork passes lint and check-types (#6785)
ensi321 May 16, 2024
6449e27
fix: update data format of WithdrawalRequestV1 (#6789)
nflaig May 16, 2024
3d3efae
fix: publish attestations with non-zero committee index (#6790)
ensi321 May 16, 2024
467e9aa
fix: validator monitor summaries should not render during epoch 0 (#6…
ensi321 May 16, 2024
e0160b8
fix: attestation duty validation (#6792)
ensi321 May 16, 2024
81a1b56
fix: align BeaconBlockBody and BlindedBeaconBlockBody (#6782)
wemeetagain May 16, 2024
1f97284
test: improve ssz tests consistency (#6776)
jeluard May 16, 2024
8495608
fix: batch validation for electra attestations (#6788)
twoeths May 16, 2024
d0ecb63
fix: update withdrawal request container to match consensus spec (#6797)
nflaig May 16, 2024
d4469c3
fix: get seen AttData key from SignedAggregateAndProof electra (#6802)
twoeths May 17, 2024
803387c
test: only skip ssz_static tests associated to missing type (#6798)
nflaig May 23, 2024
707158f
chore: types and lint fixes (#6819)
g11tech May 25, 2024
d6615d2
feat: add engine_getPayloadBodiesByHash and ByRange V2 (#6852)
ensi321 Jun 8, 2024
84a9af1
fix: align WithdrawalRequestV1 field names with latest spec (#6877)
nflaig Jun 12, 2024
2aea1c6
feat: move attestation committee at the end of attestation (#6883)
ensi321 Jun 14, 2024
7ade322
rebase fixes
g11tech Jun 19, 2024
eca6ce0
feat: handle exited/exiting validators during top up (#6880)
ensi321 Jun 21, 2024
cb47ae9
feat: add EL triggered consolidation and remove `ExecutionLayer` pref…
ensi321 Jun 21, 2024
3dc5d30
feat: support electra devnet-1 (#6892)
ensi321 Jun 25, 2024
28d6995
fix: electra rebase fixes on the new generic typing model
g11tech Jun 25, 2024
909e234
feat: add and parse consolidation requests from engine api
g11tech Jul 1, 2024
5981f18
feat: make produce block/signed block contents api multifork
g11tech Jul 1, 2024
d6bf215
fix: electra rebase fixes on the allforks type refactor
g11tech Jul 1, 2024
49349ab
chore: rebase fixes
g11tech Jul 30, 2024
122a211
feat: add Electra attestation V2 endpoints (#6951)
ensi321 Aug 5, 2024
73b2112
Update packages/beacon-node/src/chain/validation/aggregateAndProof.ts
ensi321 Aug 6, 2024
e88a1e3
fix: fix the devnet2 bug of invalid stateroot calc post consolidation
g11tech Aug 7, 2024
72b8074
chore: further rebase fixes to unstable
g11tech Aug 9, 2024
c5bab83
lint
g11tech Aug 9, 2024
0a33b9a
Add constant
ensi321 Aug 16, 2024
7a92a4e
Use constants
ensi321 Aug 19, 2024
a3bf280
Remove ZERO_NEXT_SYNC_COMMITTEE_BRANCH
ensi321 Aug 19, 2024
b836ce5
Add normalizeMerkleBranch
ensi321 Aug 19, 2024
d2c4626
add getId to CheckpointHeaderRepository
ensi321 Aug 19, 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
27 changes: 24 additions & 3 deletions packages/api/src/beacon/routes/beacon/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import {
deneb,
isSignedBlockContents,
SignedBeaconBlock,
BeaconBlockBody,
SignedBeaconBlockOrContents,
SignedBlindedBeaconBlock,
SignedBlockContents,
sszTypesFor,
BeaconBlockBody,
} from "@lodestar/types";
import {ForkName, ForkPreExecution, isForkBlobs, isForkExecution} from "@lodestar/params";
import {ForkName, ForkPreElectra, 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 Down Expand Up @@ -101,10 +101,22 @@ export type Endpoints = {
"GET",
BlockArgs,
{params: {block_id: string}},
BeaconBlockBody["attestations"],
BeaconBlockBody<ForkPreElectra>["attestations"],
ExecutionOptimisticAndFinalizedMeta
>;

/**
* Get block attestations
* Retrieves attestation included in requested block.
*/
getBlockAttestationsV2: Endpoint<
"GET",
BlockArgs,
{params: {block_id: string}},
BeaconBlockBody["attestations"],
ExecutionOptimisticFinalizedAndVersionMeta
>;

/**
* Get block header
* Retrieves block header for given block id.
Expand Down Expand Up @@ -251,6 +263,15 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoi
meta: ExecutionOptimisticAndFinalizedCodec,
},
},
getBlockAttestationsV2: {
url: "/eth/v2/beacon/blocks/{block_id}/attestations",
method: "GET",
req: blockIdOnlyReq,
resp: {
data: WithVersion((fork) => ssz[fork].BeaconBlockBody.fields.attestations),
meta: ExecutionOptimisticFinalizedAndVersionCodec,
},
},
getBlockHeader: {
url: "/eth/v1/beacon/headers/{block_id}",
method: "GET",
Expand Down
212 changes: 197 additions & 15 deletions packages/api/src/beacon/routes/beacon/pool.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/naming-convention */
import {ValueOf} from "@chainsafe/ssz";
import {ChainForkConfig} from "@lodestar/config";
import {phase0, capella, CommitteeIndex, Slot, ssz} from "@lodestar/types";
import {isForkPostElectra} from "@lodestar/params";
import {phase0, capella, CommitteeIndex, Slot, ssz, electra, AttesterSlashing} from "@lodestar/types";
import {Schema, Endpoint, RouteDefinitions} from "../../../utils/index.js";
import {
ArrayOf,
Expand All @@ -12,19 +13,31 @@ 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 AttesterSlashingListType = ArrayOf(ssz.phase0.AttesterSlashing);
const AttestationListTypePhase0 = ArrayOf(ssz.phase0.Attestation);
const AttestationListTypeElectra = ArrayOf(ssz.electra.Attestation);
const AttesterSlashingListTypePhase0 = ArrayOf(ssz.phase0.AttesterSlashing);
const AttesterSlashingListTypeElectra = ArrayOf(ssz.electra.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 AttesterSlashingList = ValueOf<typeof AttesterSlashingListType>;
type AttestationListPhase0 = ValueOf<typeof AttestationListTypePhase0>;
type AttestationListElectra = ValueOf<typeof AttestationListTypeElectra>;
type AttestationList = AttestationListPhase0 | AttestationListElectra;

type AttesterSlashingListPhase0 = ValueOf<typeof AttesterSlashingListTypePhase0>;
type AttesterSlashingListElectra = ValueOf<typeof AttesterSlashingListTypeElectra>;
type AttesterSlashingList = AttesterSlashingListPhase0 | AttesterSlashingListElectra;

type ProposerSlashingList = ValueOf<typeof ProposerSlashingListType>;
type SignedVoluntaryExitList = ValueOf<typeof SignedVoluntaryExitListType>;
type SignedBLSToExecutionChangeList = ValueOf<typeof SignedBLSToExecutionChangeListType>;
Expand All @@ -39,10 +52,22 @@ export type Endpoints = {
"GET",
{slot?: Slot; committeeIndex?: CommitteeIndex},
{query: {slot?: number; committee_index?: number}},
AttestationList,
AttestationListPhase0,
EmptyMeta
>;

/**
* Get Attestations from operations pool
* Retrieves attestations known by the node but not necessarily incorporated into any block
*/
getPoolAttestationsV2: Endpoint<
"GET",
{slot?: Slot; committeeIndex?: CommitteeIndex},
{query: {slot?: number; committee_index?: number}},
AttestationList,
VersionMeta
>;

/**
* Get AttesterSlashings from operations pool
* Retrieves attester slashings known by the node but not necessarily incorporated into any block
Expand All @@ -52,10 +77,23 @@ export type Endpoints = {
"GET",
EmptyArgs,
EmptyRequest,
AttesterSlashingList,
AttesterSlashingListPhase0,
EmptyMeta
>;

/**
* Get AttesterSlashings from operations pool
* Retrieves attester slashings known by the node but not necessarily incorporated into any block
*/
getPoolAttesterSlashingsV2: Endpoint<
// ⏎
"GET",
EmptyArgs,
EmptyRequest,
AttesterSlashingList,
VersionMeta
>;

/**
* Get ProposerSlashings from operations pool
* Retrieves proposer slashings known by the node but not necessarily incorporated into any block
Expand Down Expand Up @@ -105,12 +143,28 @@ export type Endpoints = {
*/
submitPoolAttestations: Endpoint<
"POST",
{signedAttestations: AttestationList},
{signedAttestations: AttestationListPhase0},
{body: unknown},
EmptyResponseData,
EmptyMeta
>;

/**
* Submit Attestation objects to node
* Submits Attestation objects to the node. Each attestation in the request body is processed individually.
*
* If an attestation is validated successfully the node MUST publish that attestation on the appropriate subnet.
*
* If one or more attestations fail validation the node MUST return a 400 error with details of which attestations have failed, and why.
*/
submitPoolAttestationsV2: Endpoint<
"POST",
{signedAttestations: AttestationList},
{body: unknown; headers: {[MetaHeader.Version]: string}},
EmptyResponseData,
EmptyMeta
>;

/**
* Submit AttesterSlashing object to node's pool
* Submits AttesterSlashing object to node's pool and if passes validation node MUST broadcast it to network.
Expand All @@ -123,6 +177,18 @@ export type Endpoints = {
EmptyMeta
>;

/**
* Submit AttesterSlashing object to node's pool
* Submits AttesterSlashing object to node's pool and if passes validation node MUST broadcast it to network.
*/
submitPoolAttesterSlashingsV2: Endpoint<
"POST",
{attesterSlashing: AttesterSlashing},
{body: unknown; headers: {[MetaHeader.Version]: string}},
EmptyResponseData,
EmptyMeta
>;

/**
* Submit ProposerSlashing object to node's pool
* Submits ProposerSlashing object to node's pool and if passes validation node MUST broadcast it to network.
Expand Down Expand Up @@ -172,7 +238,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,19 +249,43 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpo
schema: {query: {slot: Schema.Uint, committee_index: Schema.Uint}},
},
resp: {
data: AttestationListType,
data: AttestationListTypePhase0,
meta: EmptyMetaCodec,
},
},
getPoolAttestationsV2: {
url: "/eth/v2/beacon/pool/attestations",
method: "GET",
req: {
writeReq: ({slot, committeeIndex}) => ({query: {slot, committee_index: committeeIndex}}),
parseReq: ({query}) => ({slot: query.slot, committeeIndex: query.committee_index}),
schema: {query: {slot: Schema.Uint, committee_index: Schema.Uint}},
},
resp: {
data: WithVersion((fork) => (isForkPostElectra(fork) ? AttestationListTypeElectra : AttestationListTypePhase0)),
meta: VersionCodec,
},
},
getPoolAttesterSlashings: {
url: "/eth/v1/beacon/pool/attester_slashings",
method: "GET",
req: EmptyRequestCodec,
resp: {
data: AttesterSlashingListType,
data: AttesterSlashingListTypePhase0,
meta: EmptyMetaCodec,
},
},
getPoolAttesterSlashingsV2: {
url: "/eth/v2/beacon/pool/attester_slashings",
method: "GET",
req: EmptyRequestCodec,
resp: {
data: WithVersion((fork) =>
isForkPostElectra(fork) ? AttesterSlashingListTypeElectra : AttesterSlashingListTypePhase0
),
meta: VersionCodec,
},
},
getPoolProposerSlashings: {
url: "/eth/v1/beacon/pool/proposer_slashings",
method: "GET",
Expand Down Expand Up @@ -227,12 +317,59 @@ 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}) => ({
body: AttestationListTypePhase0.toJson(signedAttestations),
}),
parseReqJson: ({body}) => ({signedAttestations: AttestationListTypePhase0.fromJson(body)}),
writeReqSsz: ({signedAttestations}) => ({body: AttestationListTypePhase0.serialize(signedAttestations)}),
parseReqSsz: ({body}) => ({signedAttestations: AttestationListTypePhase0.deserialize(body)}),
schema: {
body: Schema.ObjectArray,
},
},
resp: EmptyResponseCodec,
},
submitPoolAttestationsV2: {
url: "/eth/v2/beacon/pool/attestations",
method: "POST",
req: {
writeReqJson: ({signedAttestations}) => {
const fork = config.getForkName(signedAttestations[0]?.data.slot ?? 0);
return {
body: isForkPostElectra(fork)
? AttestationListTypeElectra.toJson(signedAttestations as AttestationListElectra)
: AttestationListTypePhase0.toJson(signedAttestations as AttestationListPhase0),
headers: {[MetaHeader.Version]: fork},
};
},
parseReqJson: ({body, headers}) => {
const fork = toForkName(fromHeaders(headers, MetaHeader.Version));
return {
signedAttestations: isForkPostElectra(fork)
? AttestationListTypeElectra.fromJson(body)
: AttestationListTypePhase0.fromJson(body),
};
},
writeReqSsz: ({signedAttestations}) => {
const fork = config.getForkName(signedAttestations[0]?.data.slot ?? 0);
return {
body: isForkPostElectra(fork)
? AttestationListTypeElectra.serialize(signedAttestations as AttestationListElectra)
: AttestationListTypePhase0.serialize(signedAttestations as AttestationListPhase0),
headers: {[MetaHeader.Version]: fork},
};
},
parseReqSsz: ({body, headers}) => {
const fork = toForkName(fromHeaders(headers, MetaHeader.Version));
return {
signedAttestations: isForkPostElectra(fork)
? AttestationListTypeElectra.deserialize(body)
: AttestationListTypePhase0.deserialize(body),
};
},
schema: {
body: Schema.ObjectArray,
headers: {[MetaHeader.Version]: Schema.String},
},
},
resp: EmptyResponseCodec,
Expand All @@ -251,6 +388,51 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpo
},
resp: EmptyResponseCodec,
},
submitPoolAttesterSlashingsV2: {
url: "/eth/v2/beacon/pool/attester_slashings",
method: "POST",
req: {
writeReqJson: ({attesterSlashing}) => {
const fork = config.getForkName(Number(attesterSlashing.attestation1.data.slot));
return {
body: isForkPostElectra(fork)
? ssz.electra.AttesterSlashing.toJson(attesterSlashing)
: ssz.phase0.AttesterSlashing.toJson(attesterSlashing),
headers: {[MetaHeader.Version]: fork},
};
},
parseReqJson: ({body, headers}) => {
const fork = toForkName(fromHeaders(headers, MetaHeader.Version));
return {
attesterSlashing: isForkPostElectra(fork)
? ssz.electra.AttesterSlashing.fromJson(body)
: ssz.phase0.AttesterSlashing.fromJson(body),
};
},
writeReqSsz: ({attesterSlashing}) => {
const fork = config.getForkName(Number(attesterSlashing.attestation1.data.slot));
return {
body: isForkPostElectra(fork)
? ssz.electra.AttesterSlashing.serialize(attesterSlashing as electra.AttesterSlashing)
: ssz.electra.AttesterSlashing.serialize(attesterSlashing as phase0.AttesterSlashing),
headers: {[MetaHeader.Version]: fork},
};
},
parseReqSsz: ({body, headers}) => {
const fork = toForkName(fromHeaders(headers, MetaHeader.Version));
return {
attesterSlashing: isForkPostElectra(fork)
? ssz.electra.AttesterSlashing.deserialize(body)
: ssz.phase0.AttesterSlashing.deserialize(body),
};
},
schema: {
body: Schema.Object,
headers: {[MetaHeader.Version]: Schema.String},
},
},
resp: EmptyResponseCodec,
},
submitPoolProposerSlashings: {
url: "/eth/v1/beacon/pool/proposer_slashings",
method: "POST",
Expand Down
Loading
Loading