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: implement EIP-6110 #6042

Merged
merged 167 commits into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
167 commits
Select commit Hold shift + click to select a range
87c40ec
Add immutable in the dependencies
ensi321 Aug 8, 2023
a9311ad
Initial change to pubkeyCache
ensi321 Aug 18, 2023
eaca169
Added todos
ensi321 Aug 18, 2023
cfb0052
Moved unfinalized cache to epochCache
ensi321 Aug 23, 2023
6988d8e
Move populating finalized cache to afterProcessEpoch
ensi321 Aug 23, 2023
4c96aa9
Specify unfinalized cache during state cloning
ensi321 Aug 23, 2023
32d5f1b
Move from unfinalized to finalized cache in afterProcessEpoch
ensi321 Aug 23, 2023
efbfe73
Confused myself
ensi321 Aug 23, 2023
b8068ba
Clean up
ensi321 Aug 23, 2023
bc842e6
Change logic
ensi321 Aug 23, 2023
bb25132
Fix cloning issue
ensi321 Sep 5, 2023
c0757b4
Clean up redundant code
ensi321 Sep 5, 2023
3cf72e3
Add CarryoverData in epochCtx.createFromState
ensi321 Sep 5, 2023
12e0a13
Fix typo
ensi321 Sep 5, 2023
f4cdc92
Update usage of pubkeyCache
ensi321 Sep 5, 2023
fb3efff
Update pubkeyCache usage
ensi321 Sep 5, 2023
bc3dc21
Fix lint
ensi321 Sep 5, 2023
b611312
Fix lint
ensi321 Sep 5, 2023
0318473
Add 6110 to ChainConfig
ensi321 Sep 14, 2023
7319af5
Add 6110 to BeaconPreset
ensi321 Sep 14, 2023
a6d0440
Define 6110 fork and container
ensi321 Sep 14, 2023
77a9d74
Add V6110 api to execution engine
ensi321 Sep 14, 2023
480c472
Update test
ensi321 Sep 14, 2023
8ce4605
Add depositReceiptsRoot to process_execution_payload
ensi321 Sep 14, 2023
582d39c
State transitioning to EIP6110
ensi321 Sep 18, 2023
273795c
State transitioning to EIP6110
ensi321 Sep 18, 2023
598bbdb
Light client change in EIP-6110
ensi321 Sep 18, 2023
3d3cf06
Update tests
ensi321 Sep 18, 2023
a73a7e5
produceBlock
ensi321 Sep 18, 2023
80c77bf
Refactor processDeposit to match the spec
ensi321 Sep 18, 2023
2e86109
Implement processDepositReceipt
ensi321 Sep 18, 2023
a9c0752
Implement 6110 fork guard for pubkeyCache
ensi321 Sep 12, 2023
4997d9a
Handle changes in eth1 deposit
ensi321 Sep 19, 2023
ef5024a
Update eth1 deposit test
ensi321 Sep 19, 2023
d468312
Fix typo
ensi321 Sep 19, 2023
cc1a1ef
Merge branch 'unstable' into 6110
ensi321 Sep 19, 2023
bba353d
Lint
ensi321 Sep 19, 2023
1029aba
Remove embarassing comments
ensi321 Sep 20, 2023
c830b0c
Address comments
ensi321 Sep 20, 2023
3dbccd8
Modify applyDeposit signature
ensi321 Sep 20, 2023
5bb5dca
Update packages/state-transition/src/cache/epochCache.ts
ensi321 Sep 20, 2023
3cb55ba
Update packages/state-transition/src/cache/epochCache.ts
ensi321 Sep 20, 2023
7e4f5d7
Update packages/state-transition/src/cache/pubkeyCache.ts
ensi321 Sep 20, 2023
22d9081
Remove old code
ensi321 Sep 20, 2023
6b3d39b
Rename fields in epochCache and immutableData
ensi321 Sep 20, 2023
7610db8
Remove CarryoverData
ensi321 Sep 20, 2023
1899581
Move isAfter6110 from var to method
ensi321 Sep 20, 2023
fcfaf5a
Fix cyclic import
ensi321 Sep 24, 2023
b867807
Fix operations spec runner
ensi321 Sep 24, 2023
7587f05
Fix for spec test
ensi321 Sep 25, 2023
f1f5019
Fix spec test
ensi321 Sep 25, 2023
57b526d
state.depositReceiptsStartIndex to BigInt
ensi321 Sep 25, 2023
6494309
getDeposit requires cached state
ensi321 Sep 25, 2023
a8638e2
default depositReceiptsStartIndex value in genesis
ensi321 Sep 25, 2023
8aafcb9
Fix pubkeyCache bug
ensi321 Sep 25, 2023
1730ebe
newUnfinalizedPubkeyIndexMap in createCachedBeaconState
ensi321 Sep 26, 2023
6af01cb
Lint
ensi321 Sep 26, 2023
c2393c8
Pass epochCache instead of pubkey2IndexFn in apis
ensi321 Sep 26, 2023
680816b
Address comments
ensi321 Sep 27, 2023
f0ef629
Add unit test on pubkey cache cloning
ensi321 Sep 27, 2023
b0b5dfd
Add unfinalizedPubkeyCacheSize to metrics
ensi321 Sep 28, 2023
f44098c
Add unfinalizedPubkeyCacheSize to metrics
ensi321 Sep 28, 2023
64facbf
Clean up code
ensi321 Sep 28, 2023
f7d0f05
Add besu to el-interop
ensi321 Sep 29, 2023
1e00e75
Add 6110 genesis file
ensi321 Sep 29, 2023
aba9505
Template for sim test
ensi321 Sep 29, 2023
e951cf1
Add unit test for getEth1DepositCount
ensi321 Oct 7, 2023
e55dc5b
Update sim test
ensi321 Oct 9, 2023
5731382
Update besudocker
ensi321 Oct 10, 2023
7abc6b2
Finish beacon api calls in sim test
ensi321 Oct 10, 2023
63231a8
Update epochCache.createFromState()
ensi321 Oct 11, 2023
eb13145
Fix bug unfinalized validators are not finalized
ensi321 Oct 12, 2023
e2442f2
Add sim test to run a few blocks
ensi321 Oct 12, 2023
960a5bb
Lint
ensi321 Oct 12, 2023
5aab322
Merge branch 'unstable' into 6110
ensi321 Oct 13, 2023
30ef951
Merge branch 'unstable' into 611
ensi321 Oct 13, 2023
9c45121
Add more check to sim test
ensi321 Oct 13, 2023
8e4fb25
Update besu docker image instruction
ensi321 Oct 13, 2023
0abcf9f
Update sim test with correct tx
ensi321 Oct 16, 2023
dc71603
Address comment + cleanup
ensi321 Oct 16, 2023
755d23a
Clean up code
ensi321 Oct 16, 2023
973b80b
Properly handle promise rejection
ensi321 Oct 16, 2023
6a160d3
Lint
ensi321 Oct 16, 2023
ad61461
Update packages/beacon-node/src/execution/engine/types.ts
ensi321 Oct 17, 2023
c6d29eb
Update comments
ensi321 Oct 17, 2023
38b3a71
Accept type undefined in ExecutionPayloadBodyRpc
ensi321 Oct 17, 2023
adac370
Update comment and semantic
ensi321 Oct 17, 2023
3a8e76f
Remove if statement when adding finalized validator
ensi321 Oct 17, 2023
8e3b1b6
Comment on repeated insert on finalized cache
ensi321 Oct 17, 2023
1e283b3
Merge branch 'unstable' into 6110
ensi321 Oct 17, 2023
c024a00
rename createFromState
ensi321 Oct 18, 2023
ce377f6
Add comment on getPubkey()
ensi321 Oct 18, 2023
db0b8cb
Merge branch 'unstable' into 6110
ensi321 Oct 23, 2023
29a1fa4
Stash change to reduce diffs
ensi321 Oct 23, 2023
385fca6
Stash change to reduce diffs
ensi321 Oct 23, 2023
fb97206
Lint
ensi321 Oct 23, 2023
4c60789
addFinalizedPubkey on finalized checkpoint
ensi321 Oct 26, 2023
902e0bb
Update comment
ensi321 Oct 28, 2023
6c87025
Use OrderedMap for unfinalized cache
ensi321 Oct 28, 2023
cdcc5d6
Pull out logic of deleting pubkeys for batch op
ensi321 Oct 28, 2023
c811411
Add updateUnfinalizedPubkeys in regen
ensi321 Oct 30, 2023
51bb3bb
Update updateUnfinalizedPubkeys logic
ensi321 Oct 30, 2023
836b96f
Add comment
ensi321 Oct 30, 2023
aa818a4
Add metrics for state context caches
ensi321 Oct 31, 2023
d545bc4
Address comment
ensi321 Oct 31, 2023
dfa0d67
Address comment
ensi321 Nov 1, 2023
75cedd8
Deprecate eth1Data polling when condition is reached
ensi321 Nov 2, 2023
666280d
Merge branch 'unstable' into 6110
ensi321 Nov 2, 2023
3a7574b
Fix conflicts
ensi321 Nov 2, 2023
871de7b
Fix sim test
ensi321 Nov 2, 2023
884ec35
Lint
ensi321 Nov 2, 2023
9d92e2c
Fix type
ensi321 Nov 3, 2023
9c03611
Fix test
ensi321 Nov 6, 2023
38560a0
Fix test
ensi321 Nov 6, 2023
e365e9b
Lint
ensi321 Nov 6, 2023
0a8d07a
Update packages/light-client/src/spec/utils.ts
ensi321 Nov 9, 2023
4996cb3
Fix spec test
ensi321 Nov 11, 2023
a2494e9
Address comments
ensi321 Nov 11, 2023
9822a12
Improve cache logic on checkpoint finalized
ensi321 Nov 11, 2023
d6d1aed
Update sim test according to new cache logic
ensi321 Nov 11, 2023
f0eb5d6
Update comment
ensi321 Nov 11, 2023
d55039e
Lint
ensi321 Nov 11, 2023
a331868
Finalized pubkey cache only update once per checkpoint
ensi321 Nov 12, 2023
9c46eb9
Add perf test for updateUnfinalizedPubkeys
ensi321 Nov 17, 2023
e28506e
Add perf test for updateUnfinalizedPubkeys
ensi321 Nov 17, 2023
ad642d7
Tweak params for perf test
ensi321 Nov 20, 2023
f8a5350
Freeze besu docker image version for 6110
ensi321 Nov 20, 2023
d1a36ba
Add benchmark result
ensi321 Nov 20, 2023
757b41e
Use Map instead of OrderedMap. Update benchmark
ensi321 Nov 20, 2023
d68819d
Minor optimization
ensi321 Nov 20, 2023
0d3f641
Minor optimization
ensi321 Nov 21, 2023
e90743d
Add memory test for immutable.js
ensi321 Nov 22, 2023
f5fb361
Update test
ensi321 Nov 23, 2023
15e62cc
Reduce code duplication
ensi321 Nov 23, 2023
6d85788
Lint
ensi321 Nov 23, 2023
ce484c8
Merge branch 'unstable' into 6110
ensi321 Dec 4, 2023
7db9b2a
Remove try/catch in updateUnfinalizedPubkeys
ensi321 Dec 8, 2023
f4f8e0d
Introduce EpochCache metric
ensi321 Dec 8, 2023
d0a769d
Merge branch 'unstable' into 6110
ensi321 Dec 8, 2023
006c26b
Add historicalValidatorLengths
ensi321 Dec 12, 2023
ff702f8
Polish code
ensi321 Dec 15, 2023
45325e6
Merge branch 'unstable' into 6110
ensi321 Dec 18, 2023
598024e
Migrate state-transition unit tests to vitest
ensi321 Dec 18, 2023
75cb384
Fix calculation of pivot index
ensi321 Dec 22, 2023
da84a19
`historicalValidatorLengths` only activate post 6110
ensi321 Dec 22, 2023
ad50d55
Update sim test
ensi321 Dec 22, 2023
63f20dd
Lint
ensi321 Dec 22, 2023
4f2174b
Update packages/state-transition/src/cache/epochCache.ts
ensi321 Jan 10, 2024
cd9d659
Improve readability on historicalValidatorLengths
ensi321 Jan 10, 2024
c817632
Merge branch 'unstable' into 6110
ensi321 Jan 10, 2024
6162ee6
Update types
ensi321 Jan 10, 2024
a1b7e0c
Fix calculation
ensi321 Jan 10, 2024
feb8732
Add eth1data poll todo
ensi321 Jan 10, 2024
86899b8
Add epochCache.getValidatorCountAtEpoch
ensi321 Jan 18, 2024
091181b
Add todo
ensi321 Jan 18, 2024
6673f7e
Add getStateIterator for state cache
ensi321 Jan 18, 2024
b07a7f3
Partial commit
ensi321 Jan 22, 2024
ad914fa
Update perf test
ensi321 Jan 22, 2024
5841771
updateUnfinalizedPubkeys directly modify states from regen
ensi321 Jan 22, 2024
35c97da
Update sim test. Lint
ensi321 Jan 22, 2024
7da3598
Add todo
ensi321 Jan 22, 2024
3d23eab
Merge branch 'unstable' into 6110
ensi321 Jan 23, 2024
3c83bb1
Merge branch 'unstable' into 6110
ensi321 Jan 23, 2024
bcb9919
some improvements and a fix for effectiveBalanceIncrements fork safeness
g11tech Feb 10, 2024
d6d281e
Merge remote-tracking branch 'origin/electra-fork' into 6110
g11tech Feb 10, 2024
661df6e
rename eip6110 to elctra
g11tech Feb 15, 2024
2f10313
fix electra-interop.test.ts
g11tech Feb 16, 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
37 changes: 37 additions & 0 deletions packages/beacon-node/src/chain/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,9 @@ export class BeaconChain implements IBeaconChain {
metrics.forkChoice.balancesLength.set(forkChoiceMetrics.balancesLength);
metrics.forkChoice.nodes.set(forkChoiceMetrics.nodes);
metrics.forkChoice.indices.set(forkChoiceMetrics.indices);

const headState = this.getHeadState();
metrics.headState.unfinalizedPubkeyCacheSize.set(headState.epochCtx.unfinalizedPubkey2index.size);
}

private onClockSlot(slot: Slot): void {
Expand Down Expand Up @@ -959,6 +962,40 @@ export class BeaconChain implements IBeaconChain {
if (headState) {
this.opPool.pruneAll(headBlock, headState);
}

const cpEpoch = cp.epoch;
const electraEpoch = headState?.config.ELECTRA_FORK_EPOCH ?? Infinity;

if (headState === null) {
this.logger.verbose("Head state is null");
} else if (cpEpoch >= electraEpoch) {
// Get the validator.length from the state at cpEpoch
// We are confident the last element in the list is from headEpoch
// Thus we query from the end of the list. (cpEpoch - headEpoch - 1) is negative number
const pivotValidatorIndex = headState.epochCtx.getValidatorCountAtEpoch(cpEpoch);

if (pivotValidatorIndex !== undefined) {
// Note EIP-6914 will break this logic
const newFinalizedValidators = headState.epochCtx.unfinalizedPubkey2index.filter(
(index, _pubkey) => index < pivotValidatorIndex
);

// Populate finalized pubkey cache and remove unfinalized pubkey cache
if (!newFinalizedValidators.isEmpty()) {
this.regen.updateUnfinalizedPubkeys(newFinalizedValidators);
}
}
}

// TODO-Electra: Deprecating eth1Data poll requires a check on a finalized checkpoint state.
// Will resolve this later
// if (cpEpoch >= (this.config.ELECTRA_FORK_EPOCH ?? Infinity)) {
// // finalizedState can be safely casted to Electra state since cp is already post-Electra
// if (finalizedState.eth1DepositIndex >= (finalizedState as CachedBeaconStateElectra).depositReceiptsStartIndex) {
// // Signal eth1 to stop polling eth1Data
// this.eth1.stopPollingEth1Data();
// }
// }
}

async updateBeaconProposerData(epoch: Epoch, proposers: ProposerPreparationData[]): Promise<void> {
Expand Down
50 changes: 49 additions & 1 deletion packages/beacon-node/src/chain/regen/queued.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {toHexString} from "@chainsafe/ssz";
import {phase0, Slot, allForks, RootHex, Epoch} from "@lodestar/types";
import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
import {CachedBeaconStateAllForks, computeEpochAtSlot} from "@lodestar/state-transition";
import {CachedBeaconStateAllForks, UnfinalizedPubkeyIndexMap, computeEpochAtSlot} from "@lodestar/state-transition";
import {Logger} from "@lodestar/utils";
import {routes} from "@lodestar/api";
import {CheckpointHex, toCheckpointHex} from "../stateCache/index.js";
Expand Down Expand Up @@ -125,6 +125,54 @@ export class QueuedStateRegenerator implements IStateRegenerator {
return this.checkpointStateCache.updatePreComputedCheckpoint(rootHex, epoch);
}

/**
* Remove `validators` from all unfinalized cache's epochCtx.UnfinalizedPubkey2Index,
* and add them to epochCtx.pubkey2index and epochCtx.index2pubkey
*/
updateUnfinalizedPubkeys(validators: UnfinalizedPubkeyIndexMap): void {
let numStatesUpdated = 0;
const states = this.stateCache.getStates();
const cpStates = this.checkpointStateCache.getStates();

// Add finalized pubkeys to all states.
const addTimer = this.metrics?.regenFnAddPubkeyTime.startTimer();

// We only need to add pubkeys to any one of the states since the finalized caches is shared globally across all states
const firstState = (states.next().value ?? cpStates.next().value) as CachedBeaconStateAllForks | undefined;

if (firstState !== undefined) {
firstState.epochCtx.addFinalizedPubkeys(validators, this.metrics?.epochCache ?? undefined);
} else {
this.logger.warn("Attempt to delete finalized pubkey from unfinalized pubkey cache. But no state is available");
}

addTimer?.();

// Delete finalized pubkeys from unfinalized pubkey cache for all states
const deleteTimer = this.metrics?.regenFnDeletePubkeyTime.startTimer();
const pubkeysToDelete = Array.from(validators.keys());

for (const s of states) {
s.epochCtx.deleteUnfinalizedPubkeys(pubkeysToDelete);
numStatesUpdated++;
}

for (const s of cpStates) {
s.epochCtx.deleteUnfinalizedPubkeys(pubkeysToDelete);
numStatesUpdated++;
}

// Since first state is consumed from the iterator. Will need to perform delete explicitly
if (firstState !== undefined) {
firstState?.epochCtx.deleteUnfinalizedPubkeys(pubkeysToDelete);
numStatesUpdated++;
}

deleteTimer?.();

this.metrics?.regenFnNumStatesUpdated.observe(numStatesUpdated);
}

/**
* Get the state to run with `block`.
* - State after `block.parentRoot` dialed forward to block.slot
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ export class FIFOBlockStateCache implements BlockStateCache {
}));
}

getStates(): IterableIterator<CachedBeaconStateAllForks> {
throw new Error("Method not implemented.");
}

/**
* For unit test only.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,10 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
});
}

getStates(): IterableIterator<CachedBeaconStateAllForks> {
throw new Error("Method not implemented.");
}

/** ONLY FOR DEBUGGING PURPOSES. For spec tests on error */
dumpCheckpointKeys(): string[] {
return Array.from(this.cache.keys());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class StateContextCache implements BlockStateCache {
this.maxStates = maxStates;
this.cache = new MapTracker(metrics?.stateCache);
if (metrics) {
this.metrics = metrics.stateCache;
this.metrics = {...metrics.stateCache, ...metrics.epochCache};
metrics.stateCache.size.addCollect(() => metrics.stateCache.size.set(this.cache.size));
}
}
Expand Down Expand Up @@ -127,6 +127,10 @@ export class StateContextCache implements BlockStateCache {
}));
}

getStates(): IterableIterator<CachedBeaconStateAllForks> {
return this.cache.values();
}

private deleteAllEpochItems(epoch: Epoch): void {
for (const rootHex of this.epochIndex.get(epoch) || []) {
this.cache.delete(rootHex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ export class CheckpointStateCache implements CheckpointStateCacheInterface {
}));
}

getStates(): IterableIterator<CachedBeaconStateAllForks> {
return this.cache.values();
}

/** ONLY FOR DEBUGGING PURPOSES. For spec tests on error */
dumpCheckpointKeys(): string[] {
return Array.from(this.cache.keys());
Expand Down
2 changes: 2 additions & 0 deletions packages/beacon-node/src/chain/stateCache/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export interface BlockStateCache {
prune(headStateRootHex: RootHex): void;
deleteAllBeforeEpoch(finalizedEpoch: Epoch): void;
dumpSummary(): routes.lodestar.StateCacheItem[];
getStates(): IterableIterator<CachedBeaconStateAllForks>; // Expose beacon states stored in cache. Use with caution
}

/**
Expand Down Expand Up @@ -65,6 +66,7 @@ export interface CheckpointStateCache {
processState(blockRootHex: RootHex, state: CachedBeaconStateAllForks): Promise<number>;
clear(): void;
dumpSummary(): routes.lodestar.StateCacheItem[];
getStates(): IterableIterator<CachedBeaconStateAllForks>; // Expose beacon states stored in cache. Use with caution
}

export enum CacheItemType {
Expand Down
32 changes: 28 additions & 4 deletions packages/beacon-node/src/eth1/eth1DepositDataTracker.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import {phase0, ssz} from "@lodestar/types";
import {ChainForkConfig} from "@lodestar/config";
import {BeaconStateAllForks, becomesNewEth1Data} from "@lodestar/state-transition";
import {
BeaconStateAllForks,
CachedBeaconStateAllForks,
CachedBeaconStateElectra,
becomesNewEth1Data,
} from "@lodestar/state-transition";
import {ErrorAborted, TimeoutError, fromHex, Logger, isErrorAborted, sleep} from "@lodestar/utils";

import {IBeaconDb} from "../db/index.js";
Expand Down Expand Up @@ -67,6 +72,8 @@ export class Eth1DepositDataTracker {
/** Dynamically adjusted batch size to fetch deposit logs */
private eth1GetLogsBatchSizeDynamic = MAX_BLOCKS_PER_LOG_QUERY;
private readonly forcedEth1DataVote: phase0.Eth1Data | null;
/** To stop `runAutoUpdate()` in addition to AbortSignal */
private stopPolling: boolean;

constructor(
opts: Eth1Options,
Expand All @@ -81,6 +88,8 @@ export class Eth1DepositDataTracker {
this.depositsCache = new Eth1DepositsCache(opts, config, db);
this.eth1DataCache = new Eth1DataCache(config, db);
this.eth1FollowDistance = config.ETH1_FOLLOW_DISTANCE;
// TODO Electra: fix scenario where node starts post-Electra and `stopPolling` will always be false
this.stopPolling = false;

this.forcedEth1DataVote = opts.forcedEth1DataVote
? ssz.phase0.Eth1Data.deserialize(fromHex(opts.forcedEth1DataVote))
Expand Down Expand Up @@ -109,10 +118,22 @@ export class Eth1DepositDataTracker {
}
}

// TODO Electra: Figure out how an elegant way to stop eth1data polling
stopPollingEth1Data(): void {
ensi321 marked this conversation as resolved.
Show resolved Hide resolved
this.stopPolling = true;
}

/**
* Return eth1Data and deposits ready for block production for a given state
*/
async getEth1DataAndDeposits(state: BeaconStateAllForks): Promise<Eth1DataAndDeposits> {
async getEth1DataAndDeposits(state: CachedBeaconStateAllForks): Promise<Eth1DataAndDeposits> {
ensi321 marked this conversation as resolved.
Show resolved Hide resolved
if (
state.epochCtx.isAfterElectra() &&
state.eth1DepositIndex >= (state as CachedBeaconStateElectra).depositReceiptsStartIndex
) {
// No need to poll eth1Data since Electra deprecates the mechanism after depositReceiptsStartIndex is reached
return {eth1Data: state.eth1Data, deposits: []};
}
const eth1Data = this.forcedEth1DataVote ?? (await this.getEth1Data(state));
const deposits = await this.getDeposits(state, eth1Data);
return {eth1Data, deposits};
Expand Down Expand Up @@ -141,7 +162,10 @@ export class Eth1DepositDataTracker {
* Returns deposits to be included for a given state and eth1Data vote.
* Requires internal caches to be updated regularly to return good results
*/
private async getDeposits(state: BeaconStateAllForks, eth1DataVote: phase0.Eth1Data): Promise<phase0.Deposit[]> {
private async getDeposits(
state: CachedBeaconStateAllForks,
eth1DataVote: phase0.Eth1Data
): Promise<phase0.Deposit[]> {
// No new deposits have to be included, continue
if (eth1DataVote.depositCount === state.eth1DepositIndex) {
return [];
Expand All @@ -162,7 +186,7 @@ export class Eth1DepositDataTracker {
private async runAutoUpdate(): Promise<void> {
let lastRunMs = 0;

while (!this.signal.aborted) {
while (!this.signal.aborted && !this.stopPolling) {
lastRunMs = Date.now();

try {
Expand Down
8 changes: 8 additions & 0 deletions packages/beacon-node/src/eth1/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ export class Eth1ForBlockProduction implements IEth1ForBlockProduction {
startPollingMergeBlock(): void {
return this.eth1MergeBlockTracker.startPollingMergeBlock();
}

stopPollingEth1Data(): void {
return this.eth1DepositDataTracker?.stopPollingEth1Data();
}
}

/**
Expand Down Expand Up @@ -140,4 +144,8 @@ export class Eth1ForBlockProductionDisabled implements IEth1ForBlockProduction {
startPollingMergeBlock(): void {
// Ignore
}

stopPollingEth1Data(): void {
// Ignore
}
}
5 changes: 5 additions & 0 deletions packages/beacon-node/src/eth1/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ export interface IEth1ForBlockProduction {
* - head state not isMergeTransitionComplete
*/
startPollingMergeBlock(): void;

/**
* Should stop polling eth1Data after a Electra block is finalized AND deposit_receipts_start_index is reached
*/
stopPollingEth1Data(): void;
}

/** Different Eth1Block from phase0.Eth1Block with blockHash */
Expand Down
14 changes: 8 additions & 6 deletions packages/beacon-node/src/eth1/utils/deposits.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import {toGindex, Tree} from "@chainsafe/persistent-merkle-tree";
import {toHexString} from "@chainsafe/ssz";
import {MAX_DEPOSITS} from "@lodestar/params";
import {BeaconStateAllForks} from "@lodestar/state-transition";
import {CachedBeaconStateAllForks} from "@lodestar/state-transition";
import {phase0, ssz} from "@lodestar/types";
import {FilterOptions} from "@lodestar/db";
import {getEth1DepositCount} from "@lodestar/state-transition";
import {Eth1Error, Eth1ErrorCode} from "../errors.js";
import {DepositTree} from "../../db/repositories/depositDataRoot.js";

export type DepositGetter<T> = (indexRange: FilterOptions<number>, eth1Data: phase0.Eth1Data) => Promise<T[]>;

export async function getDeposits<T>(
// eth1_deposit_index represents the next deposit index to be added
state: BeaconStateAllForks,
state: CachedBeaconStateAllForks,
eth1Data: phase0.Eth1Data,
depositsGetter: DepositGetter<T>
): Promise<T[]> {
Expand All @@ -22,9 +22,11 @@ export async function getDeposits<T>(
throw new Eth1Error({code: Eth1ErrorCode.DEPOSIT_INDEX_TOO_HIGH, depositIndex, depositCount});
}

// Spec v0.12.2
// assert len(body.deposits) == min(MAX_DEPOSITS, state.eth1_data.deposit_count - state.eth1_deposit_index)
const depositsLen = Math.min(MAX_DEPOSITS, depositCount - depositIndex);
const depositsLen = getEth1DepositCount(state, eth1Data);

if (depositsLen === 0) {
return []; // If depositsLen === 0, we can return early since no deposit with be returned from depositsGetter
}

const indexRange = {gte: depositIndex, lt: depositIndex + depositsLen};
const deposits = await depositsGetter(indexRange, eth1Data);
Expand Down
10 changes: 7 additions & 3 deletions packages/beacon-node/src/execution/engine/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,9 @@ export class ExecutionEngineHttp implements IExecutionEngine {
parentBlockRoot?: Root
): Promise<ExecutePayloadResponse> {
const method =
ForkSeq[fork] >= ForkSeq.deneb
ForkSeq[fork] >= ForkSeq.electra
? "engine_newPayloadV6110"
: ForkSeq[fork] >= ForkSeq.deneb
? "engine_newPayloadV3"
: ForkSeq[fork] >= ForkSeq.capella
? "engine_newPayloadV2"
Expand All @@ -196,7 +198,7 @@ export class ExecutionEngineHttp implements IExecutionEngine {
const serializedVersionedHashes = serializeVersionedHashes(versionedHashes);
const parentBeaconBlockRoot = serializeBeaconBlockRoot(parentBlockRoot);

const method = "engine_newPayloadV3";
const method = ForkSeq[fork] >= ForkSeq.electra ? "engine_newPayloadV6110" : "engine_newPayloadV3";
engineRequest = {
method,
params: [serializedExecutionPayload, serializedVersionedHashes, parentBeaconBlockRoot],
Expand Down Expand Up @@ -370,7 +372,9 @@ export class ExecutionEngineHttp implements IExecutionEngine {
shouldOverrideBuilder?: boolean;
}> {
const method =
ForkSeq[fork] >= ForkSeq.deneb
ForkSeq[fork] >= ForkSeq.electra
? "engine_getPayloadV6110"
: ForkSeq[fork] >= ForkSeq.deneb
? "engine_getPayloadV3"
: ForkSeq[fork] >= ForkSeq.capella
? "engine_getPayloadV2"
Expand Down
4 changes: 2 additions & 2 deletions packages/beacon-node/src/execution/engine/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import {KZGCommitment, Blob, KZGProof} from "@lodestar/types/deneb";
import {Root, RootHex, allForks, capella, Wei} from "@lodestar/types";

import {DATA} from "../../eth1/provider/utils.js";
import {PayloadIdCache, PayloadId, WithdrawalV1} from "./payloadIdCache.js";
import {PayloadIdCache, PayloadId, WithdrawalV1, DepositReceiptV1} from "./payloadIdCache.js";
import {ExecutionPayloadBody} from "./types.js";

export {PayloadIdCache, type PayloadId, type WithdrawalV1};
export {PayloadIdCache, type PayloadId, type WithdrawalV1, type DepositReceiptV1};

export enum ExecutionPayloadStatus {
/** given payload is valid */
Expand Down
Loading
Loading