@lodestar/state-transition 1.43.0-dev.9fa9f08ef6 → 1.43.0-dev.a140dd987e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/block/index.d.ts +2 -2
- package/lib/block/index.d.ts.map +1 -1
- package/lib/block/index.js +11 -4
- package/lib/block/index.js.map +1 -1
- package/lib/block/processParentExecutionPayload.d.ts +20 -0
- package/lib/block/processParentExecutionPayload.d.ts.map +1 -0
- package/lib/block/processParentExecutionPayload.js +100 -0
- package/lib/block/processParentExecutionPayload.js.map +1 -0
- package/lib/block/processWithdrawals.d.ts.map +1 -1
- package/lib/block/processWithdrawals.js +12 -4
- package/lib/block/processWithdrawals.js.map +1 -1
- package/lib/cache/epochCache.d.ts +3 -1
- package/lib/cache/epochCache.d.ts.map +1 -1
- package/lib/cache/epochCache.js +31 -13
- package/lib/cache/epochCache.js.map +1 -1
- package/lib/cache/epochTransitionCache.d.ts +5 -0
- package/lib/cache/epochTransitionCache.d.ts.map +1 -1
- package/lib/cache/epochTransitionCache.js +1 -0
- package/lib/cache/epochTransitionCache.js.map +1 -1
- package/lib/epoch/index.d.ts +3 -1
- package/lib/epoch/index.d.ts.map +1 -1
- package/lib/epoch/index.js +8 -1
- package/lib/epoch/index.js.map +1 -1
- package/lib/epoch/processPtcWindow.d.ts +11 -0
- package/lib/epoch/processPtcWindow.d.ts.map +1 -0
- package/lib/epoch/processPtcWindow.js +28 -0
- package/lib/epoch/processPtcWindow.js.map +1 -0
- package/lib/signatureSets/executionPayloadEnvelope.js +1 -1
- package/lib/signatureSets/executionPayloadEnvelope.js.map +1 -1
- package/lib/slot/upgradeStateToGloas.d.ts.map +1 -1
- package/lib/slot/upgradeStateToGloas.js +3 -1
- package/lib/slot/upgradeStateToGloas.js.map +1 -1
- package/lib/stateTransition.js +1 -1
- package/lib/stateTransition.js.map +1 -1
- package/lib/stateView/beaconStateView.d.ts +7 -3
- package/lib/stateView/beaconStateView.d.ts.map +1 -1
- package/lib/stateView/beaconStateView.js +20 -13
- package/lib/stateView/beaconStateView.js.map +1 -1
- package/lib/stateView/interface.d.ts +11 -3
- package/lib/stateView/interface.d.ts.map +1 -1
- package/lib/stateView/interface.js.map +1 -1
- package/lib/util/computeAnchorCheckpoint.d.ts +1 -1
- package/lib/util/computeAnchorCheckpoint.d.ts.map +1 -1
- package/lib/util/computeAnchorCheckpoint.js +6 -19
- package/lib/util/computeAnchorCheckpoint.js.map +1 -1
- package/lib/util/gloas.d.ts +7 -1
- package/lib/util/gloas.d.ts.map +1 -1
- package/lib/util/gloas.js +27 -1
- package/lib/util/gloas.js.map +1 -1
- package/package.json +8 -8
- package/src/block/index.ts +12 -4
- package/src/block/processParentExecutionPayload.ts +116 -0
- package/src/block/processWithdrawals.ts +12 -4
- package/src/cache/epochCache.ts +32 -30
- package/src/cache/epochTransitionCache.ts +7 -0
- package/src/epoch/index.ts +9 -0
- package/src/epoch/processPtcWindow.ts +38 -0
- package/src/signatureSets/executionPayloadEnvelope.ts +1 -1
- package/src/slot/upgradeStateToGloas.ts +5 -1
- package/src/stateTransition.ts +1 -1
- package/src/stateView/beaconStateView.ts +24 -20
- package/src/stateView/interface.ts +13 -6
- package/src/util/computeAnchorCheckpoint.ts +6 -19
- package/src/util/gloas.ts +49 -1
- package/lib/block/processExecutionPayloadEnvelope.d.ts +0 -9
- package/lib/block/processExecutionPayloadEnvelope.d.ts.map +0 -1
- package/lib/block/processExecutionPayloadEnvelope.js +0 -106
- package/lib/block/processExecutionPayloadEnvelope.js.map +0 -1
- package/src/block/processExecutionPayloadEnvelope.ts +0 -175
|
@@ -158,6 +158,12 @@ export interface EpochTransitionCache {
|
|
|
158
158
|
*/
|
|
159
159
|
nextShuffling: EpochShuffling | null;
|
|
160
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Pre-computed PTC for epoch N + MIN_SEED_LOOKAHEAD + 1, populated by processPtcWindow (Gloas+).
|
|
163
|
+
* Used by finalProcessEpoch to shift PTC arrays in epoch cache without reading from state.
|
|
164
|
+
*/
|
|
165
|
+
nextEpochPayloadTimelinessCommittees: Uint32Array[] | null;
|
|
166
|
+
|
|
161
167
|
/**
|
|
162
168
|
* Altair specific, this is total active balances for the next epoch.
|
|
163
169
|
* This is only used in `afterProcessEpoch` to compute base reward and sync participant reward.
|
|
@@ -502,6 +508,7 @@ export function beforeProcessEpoch(
|
|
|
502
508
|
indicesToEject,
|
|
503
509
|
nextShufflingActiveIndices,
|
|
504
510
|
nextShuffling: null,
|
|
511
|
+
nextEpochPayloadTimelinessCommittees: null,
|
|
505
512
|
// to be updated in processEffectiveBalanceUpdates
|
|
506
513
|
nextEpochTotalActiveBalanceByIncrement: 0,
|
|
507
514
|
isActivePrevEpoch,
|
package/src/epoch/index.ts
CHANGED
|
@@ -28,6 +28,7 @@ import {processParticipationRecordUpdates} from "./processParticipationRecordUpd
|
|
|
28
28
|
import {processPendingConsolidations} from "./processPendingConsolidations.js";
|
|
29
29
|
import {processPendingDeposits} from "./processPendingDeposits.js";
|
|
30
30
|
import {processProposerLookahead} from "./processProposerLookahead.js";
|
|
31
|
+
import {processPtcWindow} from "./processPtcWindow.js";
|
|
31
32
|
import {processRandaoMixesReset} from "./processRandaoMixesReset.js";
|
|
32
33
|
import {processRegistryUpdates} from "./processRegistryUpdates.js";
|
|
33
34
|
import {processRewardsAndPenalties} from "./processRewardsAndPenalties.js";
|
|
@@ -55,6 +56,7 @@ export {
|
|
|
55
56
|
processPendingDeposits,
|
|
56
57
|
processPendingConsolidations,
|
|
57
58
|
processProposerLookahead,
|
|
59
|
+
processPtcWindow,
|
|
58
60
|
processBuilderPendingPayments,
|
|
59
61
|
};
|
|
60
62
|
|
|
@@ -81,6 +83,7 @@ export enum EpochTransitionStep {
|
|
|
81
83
|
processPendingDeposits = "processPendingDeposits",
|
|
82
84
|
processPendingConsolidations = "processPendingConsolidations",
|
|
83
85
|
processProposerLookahead = "processProposerLookahead",
|
|
86
|
+
processPtcWindow = "processPtcWindow",
|
|
84
87
|
processBuilderPendingPayments = "processBuilderPendingPayments",
|
|
85
88
|
}
|
|
86
89
|
|
|
@@ -211,4 +214,10 @@ export function processEpoch(
|
|
|
211
214
|
processProposerLookahead(fork, state as CachedBeaconStateFulu, cache);
|
|
212
215
|
timer?.();
|
|
213
216
|
}
|
|
217
|
+
|
|
218
|
+
if (fork >= ForkSeq.gloas) {
|
|
219
|
+
const timer = metrics?.epochTransitionStepTime.startTimer({step: EpochTransitionStep.processPtcWindow});
|
|
220
|
+
processPtcWindow(state as CachedBeaconStateGloas, cache);
|
|
221
|
+
timer?.();
|
|
222
|
+
}
|
|
214
223
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {MIN_SEED_LOOKAHEAD} from "@lodestar/params";
|
|
2
|
+
import {ssz} from "@lodestar/types";
|
|
3
|
+
import {CachedBeaconStateGloas, EpochTransitionCache} from "../types.js";
|
|
4
|
+
import {computeEpochShuffling} from "../util/epochShuffling.js";
|
|
5
|
+
import {computePayloadTimelinessCommitteesForEpoch} from "../util/seed.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Update the `ptc_window` field in the beacon state by shifting out the oldest epoch's
|
|
9
|
+
* PTC entries and appending newly computed entries for the next lookahead epoch.
|
|
10
|
+
* Stashes the computed PTCs in the transition cache for finalProcessEpoch to shift
|
|
11
|
+
* into the epoch cache without reading from state.
|
|
12
|
+
*
|
|
13
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.4/specs/gloas/beacon-chain.md#new-process_ptc_window
|
|
14
|
+
*/
|
|
15
|
+
export function processPtcWindow(state: CachedBeaconStateGloas, cache: EpochTransitionCache): void {
|
|
16
|
+
const nextEpoch = state.epochCtx.epoch + MIN_SEED_LOOKAHEAD + 1;
|
|
17
|
+
const nextEpochShuffling =
|
|
18
|
+
cache.nextShuffling ?? computeEpochShuffling(state, cache.nextShufflingActiveIndices, nextEpoch);
|
|
19
|
+
cache.nextShuffling = nextEpochShuffling;
|
|
20
|
+
|
|
21
|
+
const newNextPayloadTimelinessCommittees = computePayloadTimelinessCommitteesForEpoch(
|
|
22
|
+
state,
|
|
23
|
+
nextEpoch,
|
|
24
|
+
nextEpochShuffling.committees,
|
|
25
|
+
state.epochCtx.effectiveBalanceIncrements
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// Stash for finalProcessEpoch to shift into epoch cache
|
|
29
|
+
cache.nextEpochPayloadTimelinessCommittees = newNextPayloadTimelinessCommittees;
|
|
30
|
+
|
|
31
|
+
// Write shifted window to state: current(N) + next(N+1) + newlyComputed(N+2)
|
|
32
|
+
// From the perspective of upcoming epoch N+1, this is previous + current + next
|
|
33
|
+
state.ptcWindow = ssz.gloas.PtcWindow.toViewDU([
|
|
34
|
+
...state.epochCtx.payloadTimelinessCommittees,
|
|
35
|
+
...state.epochCtx.nextPayloadTimelinessCommittees,
|
|
36
|
+
...newNextPayloadTimelinessCommittees,
|
|
37
|
+
]);
|
|
38
|
+
}
|
|
@@ -11,7 +11,7 @@ export function getExecutionPayloadEnvelopeSigningRoot(
|
|
|
11
11
|
config: BeaconConfig,
|
|
12
12
|
envelope: gloas.ExecutionPayloadEnvelope
|
|
13
13
|
): Uint8Array {
|
|
14
|
-
const domain = config.getDomain(envelope.
|
|
14
|
+
const domain = config.getDomain(envelope.payload.slotNumber, DOMAIN_BEACON_BUILDER);
|
|
15
15
|
|
|
16
16
|
return computeSigningRoot(ssz.gloas.ExecutionPayloadEnvelope, envelope, domain);
|
|
17
17
|
}
|
|
@@ -5,7 +5,7 @@ import {isValidDepositSignature} from "../block/processDeposit.js";
|
|
|
5
5
|
import {applyDepositForBuilder} from "../block/processDepositRequest.js";
|
|
6
6
|
import {getCachedBeaconState} from "../cache/stateCache.js";
|
|
7
7
|
import {CachedBeaconStateFulu, CachedBeaconStateGloas} from "../types.js";
|
|
8
|
-
import {isBuilderWithdrawalCredential} from "../util/gloas.js";
|
|
8
|
+
import {initializePtcWindow, isBuilderWithdrawalCredential} from "../util/gloas.js";
|
|
9
9
|
import {isValidatorKnown} from "../util/index.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -48,6 +48,9 @@ export function upgradeStateToGloas(stateFulu: CachedBeaconStateFulu): CachedBea
|
|
|
48
48
|
stateGloasView.currentSyncCommittee = stateGloasCloned.currentSyncCommittee;
|
|
49
49
|
stateGloasView.nextSyncCommittee = stateGloasCloned.nextSyncCommittee;
|
|
50
50
|
stateGloasView.latestExecutionPayloadBid.blockHash = stateFulu.latestExecutionPayloadHeader.blockHash;
|
|
51
|
+
stateGloasView.latestExecutionPayloadBid.executionRequestsRoot = ssz.electra.ExecutionRequests.hashTreeRoot(
|
|
52
|
+
ssz.electra.ExecutionRequests.defaultValue()
|
|
53
|
+
);
|
|
51
54
|
stateGloasView.nextWithdrawalIndex = stateGloasCloned.nextWithdrawalIndex;
|
|
52
55
|
stateGloasView.nextWithdrawalValidatorIndex = stateGloasCloned.nextWithdrawalValidatorIndex;
|
|
53
56
|
stateGloasView.historicalSummaries = stateGloasCloned.historicalSummaries;
|
|
@@ -61,6 +64,7 @@ export function upgradeStateToGloas(stateFulu: CachedBeaconStateFulu): CachedBea
|
|
|
61
64
|
stateGloasView.pendingPartialWithdrawals = stateGloasCloned.pendingPartialWithdrawals;
|
|
62
65
|
stateGloasView.pendingConsolidations = stateGloasCloned.pendingConsolidations;
|
|
63
66
|
stateGloasView.proposerLookahead = stateGloasCloned.proposerLookahead;
|
|
67
|
+
stateGloasView.ptcWindow = ssz.gloas.PtcWindow.toViewDU(initializePtcWindow(stateFulu));
|
|
64
68
|
|
|
65
69
|
for (let i = 0; i < SLOTS_PER_HISTORICAL_ROOT; i++) {
|
|
66
70
|
stateGloasView.executionPayloadAvailability.set(i, true);
|
package/src/stateTransition.ts
CHANGED
|
@@ -282,7 +282,7 @@ function processSlotsWithTransientCache(
|
|
|
282
282
|
{
|
|
283
283
|
const timer = metrics?.epochTransitionStepTime.startTimer({step: EpochTransitionStep.finalProcessEpoch});
|
|
284
284
|
// last step to prepare epoch data that depends on the upgraded state, for example proposerLookahead of BeaconStateFulu
|
|
285
|
-
postState.epochCtx.finalProcessEpoch(postState);
|
|
285
|
+
postState.epochCtx.finalProcessEpoch(postState, epochTransitionCache);
|
|
286
286
|
timer?.();
|
|
287
287
|
}
|
|
288
288
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {CompactMultiProof, ProofType, Tree, createProof} from "@chainsafe/persistent-merkle-tree";
|
|
2
2
|
import {BitArray, ByteViews} from "@chainsafe/ssz";
|
|
3
3
|
import {BeaconConfig} from "@lodestar/config";
|
|
4
|
-
import {ForkName, ForkSeq, SLOTS_PER_HISTORICAL_ROOT
|
|
4
|
+
import {ForkName, ForkSeq, SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params";
|
|
5
5
|
import {
|
|
6
6
|
BeaconBlock,
|
|
7
7
|
BeaconState,
|
|
@@ -28,8 +28,7 @@ import {
|
|
|
28
28
|
rewards,
|
|
29
29
|
} from "@lodestar/types";
|
|
30
30
|
import {Checkpoint, Fork} from "@lodestar/types/phase0";
|
|
31
|
-
import {
|
|
32
|
-
import {ProcessExecutionPayloadEnvelopeOpts} from "../block/processExecutionPayloadEnvelope.js";
|
|
31
|
+
import {applyParentExecutionPayload} from "../block/processParentExecutionPayload.js";
|
|
33
32
|
import {VoluntaryExitValidity, getVoluntaryExitValidity} from "../block/processVoluntaryExit.js";
|
|
34
33
|
import {getExpectedWithdrawals} from "../block/processWithdrawals.js";
|
|
35
34
|
import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js";
|
|
@@ -704,7 +703,11 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
|
|
|
704
703
|
|
|
705
704
|
// Serialization
|
|
706
705
|
|
|
707
|
-
loadOtherState(
|
|
706
|
+
loadOtherState(
|
|
707
|
+
stateBytes: Uint8Array,
|
|
708
|
+
seedValidatorsBytes?: Uint8Array,
|
|
709
|
+
opts?: {preloadValidatorsAndBalances?: boolean}
|
|
710
|
+
): IBeaconStateView {
|
|
708
711
|
const {state} = loadState(this.config, this.cachedState, stateBytes, seedValidatorsBytes);
|
|
709
712
|
|
|
710
713
|
const cachedState = createCachedBeaconState(
|
|
@@ -719,9 +722,10 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
|
|
|
719
722
|
}
|
|
720
723
|
);
|
|
721
724
|
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
+
if (opts?.preloadValidatorsAndBalances) {
|
|
726
|
+
cachedState.validators.getAllReadonlyValues();
|
|
727
|
+
cachedState.balances.getAll();
|
|
728
|
+
}
|
|
725
729
|
|
|
726
730
|
return new BeaconStateView(cachedState);
|
|
727
731
|
}
|
|
@@ -779,19 +783,19 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
|
|
|
779
783
|
return new BeaconStateView(newState);
|
|
780
784
|
}
|
|
781
785
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
):
|
|
786
|
-
const fork = this.config.
|
|
787
|
-
if (
|
|
788
|
-
throw Error(
|
|
786
|
+
/**
|
|
787
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.5/specs/gloas/validator.md#executionpayload
|
|
788
|
+
*/
|
|
789
|
+
getExpectedWithdrawalsForFullParent(executionRequests: electra.ExecutionRequests): capella.Withdrawal[] {
|
|
790
|
+
const fork = this.config.getForkSeq(this.cachedState.slot);
|
|
791
|
+
if (fork < ForkSeq.gloas) {
|
|
792
|
+
throw new Error("getExpectedWithdrawalsForFullParent is not available before Gloas");
|
|
789
793
|
}
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
return
|
|
794
|
+
// Make a copy of the state to avoid mutability issues
|
|
795
|
+
const stateCopy = this.cachedState.clone(true) as CachedBeaconStateGloas;
|
|
796
|
+
// Apply parent payload before computing withdrawals
|
|
797
|
+
applyParentExecutionPayload(stateCopy, executionRequests);
|
|
798
|
+
|
|
799
|
+
return getExpectedWithdrawals(fork, stateCopy).expectedWithdrawals;
|
|
796
800
|
}
|
|
797
801
|
}
|
|
@@ -41,7 +41,6 @@ import {
|
|
|
41
41
|
rewards,
|
|
42
42
|
} from "@lodestar/types";
|
|
43
43
|
import {Checkpoint, Fork} from "@lodestar/types/phase0";
|
|
44
|
-
import {ProcessExecutionPayloadEnvelopeOpts} from "../block/processExecutionPayloadEnvelope.js";
|
|
45
44
|
import {VoluntaryExitValidity} from "../block/processVoluntaryExit.js";
|
|
46
45
|
import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js";
|
|
47
46
|
import {EpochTransitionCacheOpts} from "../cache/epochTransitionCache.js";
|
|
@@ -138,7 +137,13 @@ export interface IBeaconStateView {
|
|
|
138
137
|
isStateValidatorsNodesPopulated(): boolean;
|
|
139
138
|
|
|
140
139
|
// Serialization
|
|
141
|
-
|
|
140
|
+
/** Set `preloadValidatorsAndBalances` only when the whole state will be consumed
|
|
141
|
+
* immediately (e.g. CP reload before block replay). */
|
|
142
|
+
loadOtherState(
|
|
143
|
+
stateBytes: Uint8Array,
|
|
144
|
+
seedValidatorsBytes?: Uint8Array,
|
|
145
|
+
opts?: {preloadValidatorsAndBalances?: boolean}
|
|
146
|
+
): IBeaconStateView;
|
|
142
147
|
toValue(): BeaconState;
|
|
143
148
|
serialize(): Uint8Array;
|
|
144
149
|
serializedSize(): number;
|
|
@@ -248,10 +253,12 @@ export interface IBeaconStateViewGloas extends IBeaconStateViewFulu {
|
|
|
248
253
|
getBuilder(index: BuilderIndex): gloas.Builder;
|
|
249
254
|
canBuilderCoverBid(builderIndex: BuilderIndex, bidAmount: number): boolean;
|
|
250
255
|
getIndexInPayloadTimelinessCommittee(validatorIndex: ValidatorIndex, slot: Slot): number;
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
256
|
+
/**
|
|
257
|
+
* Compute expected withdrawals as if the parent was FULL.
|
|
258
|
+
* Clones the state, applies parent payload effects, then computes withdrawals.
|
|
259
|
+
* Used by prepare_execution_payload when building on FULL parent.
|
|
260
|
+
*/
|
|
261
|
+
getExpectedWithdrawalsForFullParent(executionRequests: electra.ExecutionRequests): capella.Withdrawal[];
|
|
255
262
|
}
|
|
256
263
|
|
|
257
264
|
/**
|
|
@@ -1,34 +1,21 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {
|
|
2
|
+
import {ZERO_HASH} from "@lodestar/params";
|
|
3
3
|
import {phase0, ssz} from "@lodestar/types";
|
|
4
4
|
import {BeaconStateAllForks} from "../types.js";
|
|
5
|
-
import {blockToHeader} from "./blockRoot.js";
|
|
6
5
|
import {computeCheckpointEpochAtStateSlot} from "./epoch.js";
|
|
7
6
|
|
|
8
7
|
export function computeAnchorCheckpoint(
|
|
9
|
-
|
|
8
|
+
_config: ChainForkConfig,
|
|
10
9
|
anchorState: BeaconStateAllForks
|
|
11
10
|
): {checkpoint: phase0.Checkpoint; blockHeader: phase0.BeaconBlockHeader} {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (anchorState.latestBlockHeader.slot === GENESIS_SLOT) {
|
|
17
|
-
const block = blockTypes.BeaconBlock.defaultValue();
|
|
18
|
-
block.stateRoot = anchorState.hashTreeRoot();
|
|
19
|
-
blockHeader = blockToHeader(config, block);
|
|
20
|
-
root = ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader);
|
|
21
|
-
} else {
|
|
22
|
-
blockHeader = ssz.phase0.BeaconBlockHeader.clone(anchorState.latestBlockHeader);
|
|
23
|
-
if (ssz.Root.equals(blockHeader.stateRoot, ZERO_HASH)) {
|
|
24
|
-
blockHeader.stateRoot = anchorState.hashTreeRoot();
|
|
25
|
-
}
|
|
26
|
-
root = ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader);
|
|
11
|
+
const blockHeader = ssz.phase0.BeaconBlockHeader.clone(anchorState.latestBlockHeader);
|
|
12
|
+
if (ssz.Root.equals(blockHeader.stateRoot, ZERO_HASH)) {
|
|
13
|
+
blockHeader.stateRoot = anchorState.hashTreeRoot();
|
|
27
14
|
}
|
|
28
15
|
|
|
29
16
|
return {
|
|
30
17
|
checkpoint: {
|
|
31
|
-
root,
|
|
18
|
+
root: ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader),
|
|
32
19
|
// the checkpoint epoch = computeEpochAtSlot(anchorState.slot) + 1 if slot is not at epoch boundary
|
|
33
20
|
// this is similar to a process_slots() call
|
|
34
21
|
epoch: computeCheckpointEpochAtStateSlot(anchorState.slot),
|
package/src/util/gloas.ts
CHANGED
|
@@ -6,15 +6,20 @@ import {
|
|
|
6
6
|
EFFECTIVE_BALANCE_INCREMENT,
|
|
7
7
|
FAR_FUTURE_EPOCH,
|
|
8
8
|
MIN_DEPOSIT_AMOUNT,
|
|
9
|
+
MIN_SEED_LOOKAHEAD,
|
|
10
|
+
PTC_SIZE,
|
|
9
11
|
SLOTS_PER_EPOCH,
|
|
10
12
|
} from "@lodestar/params";
|
|
11
13
|
import {BuilderIndex, Epoch, ValidatorIndex, gloas} from "@lodestar/types";
|
|
12
14
|
import {AttestationData} from "@lodestar/types/phase0";
|
|
13
15
|
import {byteArrayEquals} from "@lodestar/utils";
|
|
14
|
-
import {CachedBeaconStateGloas} from "../types.js";
|
|
16
|
+
import {CachedBeaconStateFulu, CachedBeaconStateGloas} from "../types.js";
|
|
15
17
|
import {getBlockRootAtSlot} from "./blockRoot.js";
|
|
16
18
|
import {computeEpochAtSlot} from "./epoch.js";
|
|
19
|
+
import {computeEpochShuffling} from "./epochShuffling.js";
|
|
17
20
|
import {RootCache} from "./rootCache.js";
|
|
21
|
+
import {computePayloadTimelinessCommitteesForEpoch} from "./seed.js";
|
|
22
|
+
import {getActiveValidatorIndices} from "./validator.js";
|
|
18
23
|
|
|
19
24
|
export function isBuilderWithdrawalCredential(withdrawalCredentials: Uint8Array): boolean {
|
|
20
25
|
return withdrawalCredentials[0] === BUILDER_WITHDRAWAL_PREFIX;
|
|
@@ -167,6 +172,49 @@ export function isAttestationSameSlotRootCache(rootCache: RootCache, data: Attes
|
|
|
167
172
|
return isMatchingBlockRoot && isCurrentBlockRoot;
|
|
168
173
|
}
|
|
169
174
|
|
|
175
|
+
// TODO GLOAS: This function no longer exists in v1.7.0-alpha.5 specs. Remove it when appropriate to do so
|
|
170
176
|
export function isParentBlockFull(state: CachedBeaconStateGloas): boolean {
|
|
171
177
|
return byteArrayEquals(state.latestExecutionPayloadBid.blockHash, state.latestBlockHash);
|
|
172
178
|
}
|
|
179
|
+
|
|
180
|
+
export function initializePtcWindow(state: CachedBeaconStateFulu): Uint32Array[] {
|
|
181
|
+
const ptcWindow: Uint32Array[] = Array.from({length: SLOTS_PER_EPOCH}, () => new Uint32Array(PTC_SIZE));
|
|
182
|
+
const currentEpoch = state.epochCtx.epoch;
|
|
183
|
+
|
|
184
|
+
for (let epochOffset = 0; epochOffset <= MIN_SEED_LOOKAHEAD; epochOffset++) {
|
|
185
|
+
const epoch = currentEpoch + epochOffset;
|
|
186
|
+
const shuffling =
|
|
187
|
+
state.epochCtx.getShufflingAtEpochOrNull(epoch) ??
|
|
188
|
+
computeEpochShuffling(state, getActiveValidatorIndices(state, epoch), epoch);
|
|
189
|
+
|
|
190
|
+
ptcWindow.push(
|
|
191
|
+
...computePayloadTimelinessCommitteesForEpoch(
|
|
192
|
+
state,
|
|
193
|
+
epoch,
|
|
194
|
+
shuffling.committees,
|
|
195
|
+
state.epochCtx.effectiveBalanceIncrements
|
|
196
|
+
)
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return ptcWindow;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function getPtcWindowEpochCacheData(state: CachedBeaconStateGloas): {
|
|
204
|
+
previousPayloadTimelinessCommittees: Uint32Array[];
|
|
205
|
+
payloadTimelinessCommittees: Uint32Array[];
|
|
206
|
+
nextPayloadTimelinessCommittees: Uint32Array[];
|
|
207
|
+
} {
|
|
208
|
+
const toUint32Arrays = (views: ReturnType<typeof state.ptcWindow.getReadonlyByRange>) =>
|
|
209
|
+
views.map((v) => Uint32Array.from(v.getAll()));
|
|
210
|
+
|
|
211
|
+
const previousPtcWindow = state.ptcWindow.getReadonlyByRange(0, SLOTS_PER_EPOCH);
|
|
212
|
+
const currentPtcWindow = state.ptcWindow.getReadonlyByRange(SLOTS_PER_EPOCH, SLOTS_PER_EPOCH);
|
|
213
|
+
const nextPtcWindow = state.ptcWindow.getReadonlyByRange(2 * SLOTS_PER_EPOCH, SLOTS_PER_EPOCH);
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
previousPayloadTimelinessCommittees: toUint32Arrays(previousPtcWindow),
|
|
217
|
+
payloadTimelinessCommittees: toUint32Arrays(currentPtcWindow),
|
|
218
|
+
nextPayloadTimelinessCommittees: toUint32Arrays(nextPtcWindow),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { gloas } from "@lodestar/types";
|
|
2
|
-
import { CachedBeaconStateGloas } from "../types.js";
|
|
3
|
-
export type ProcessExecutionPayloadEnvelopeOpts = {
|
|
4
|
-
verifySignature?: boolean;
|
|
5
|
-
verifyStateRoot?: boolean;
|
|
6
|
-
dontTransferCache?: boolean;
|
|
7
|
-
};
|
|
8
|
-
export declare function processExecutionPayloadEnvelope(state: CachedBeaconStateGloas, signedEnvelope: gloas.SignedExecutionPayloadEnvelope, opts?: ProcessExecutionPayloadEnvelopeOpts): CachedBeaconStateGloas;
|
|
9
|
-
//# sourceMappingURL=processExecutionPayloadEnvelope.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"processExecutionPayloadEnvelope.d.ts","sourceRoot":"","sources":["../../src/block/processExecutionPayloadEnvelope.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,EAAM,MAAM,iBAAiB,CAAC;AAI3C,OAAO,EAAC,sBAAsB,EAAC,MAAM,aAAa,CAAC;AAOnD,MAAM,MAAM,mCAAmC,GAAG;IAChD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAKF,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,sBAAsB,EAC7B,cAAc,EAAE,KAAK,CAAC,8BAA8B,EACpD,IAAI,CAAC,EAAE,mCAAmC,GACzC,sBAAsB,CA0DxB"}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { SLOTS_PER_EPOCH, SLOTS_PER_HISTORICAL_ROOT } from "@lodestar/params";
|
|
2
|
-
import { ssz } from "@lodestar/types";
|
|
3
|
-
import { byteArrayEquals, toHex, toRootHex } from "@lodestar/utils";
|
|
4
|
-
import { getExecutionPayloadEnvelopeSignatureSet } from "../signatureSets/executionPayloadEnvelope.js";
|
|
5
|
-
import { BeaconStateView } from "../stateView/beaconStateView.js";
|
|
6
|
-
import { computeTimeAtSlot } from "../util/index.js";
|
|
7
|
-
import { verifySignatureSet } from "../util/signatureSets.js";
|
|
8
|
-
import { processConsolidationRequest } from "./processConsolidationRequest.js";
|
|
9
|
-
import { getPendingValidatorPubkeys, processDepositRequest } from "./processDepositRequest.js";
|
|
10
|
-
import { processWithdrawalRequest } from "./processWithdrawalRequest.js";
|
|
11
|
-
// Unlike other block processing functions which mutate state in-place, this function
|
|
12
|
-
// clones the state and returns the post-state, similar to stateTransition().
|
|
13
|
-
// This function does not call execution engine to verify payload. Need to call it from other place.
|
|
14
|
-
export function processExecutionPayloadEnvelope(state, signedEnvelope, opts) {
|
|
15
|
-
const { verifySignature = true, verifyStateRoot = true } = opts ?? {};
|
|
16
|
-
const envelope = signedEnvelope.message;
|
|
17
|
-
const payload = envelope.payload;
|
|
18
|
-
const fork = state.config.getForkSeq(envelope.slot);
|
|
19
|
-
if (verifySignature && !verifyExecutionPayloadEnvelopeSignature(state, signedEnvelope)) {
|
|
20
|
-
throw Error(`Execution payload envelope has invalid signature builderIndex=${envelope.builderIndex}`);
|
|
21
|
-
}
|
|
22
|
-
// .clone() before mutating state, similar to stateTransition()
|
|
23
|
-
const postState = state.clone(opts?.dontTransferCache);
|
|
24
|
-
validateExecutionPayloadEnvelope(postState, envelope);
|
|
25
|
-
const requests = envelope.executionRequests;
|
|
26
|
-
if (requests.deposits.length > 0) {
|
|
27
|
-
// Build cache of pending validator pubkeys once, shared across all deposit requests
|
|
28
|
-
const pendingValidatorPubkeys = getPendingValidatorPubkeys(postState.config, postState);
|
|
29
|
-
for (const deposit of requests.deposits) {
|
|
30
|
-
processDepositRequest(fork, postState, deposit, pendingValidatorPubkeys);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
for (const withdrawal of requests.withdrawals) {
|
|
34
|
-
processWithdrawalRequest(fork, postState, withdrawal);
|
|
35
|
-
}
|
|
36
|
-
for (const consolidation of requests.consolidations) {
|
|
37
|
-
processConsolidationRequest(postState, consolidation);
|
|
38
|
-
}
|
|
39
|
-
// Queue the builder payment
|
|
40
|
-
const paymentIndex = SLOTS_PER_EPOCH + (postState.slot % SLOTS_PER_EPOCH);
|
|
41
|
-
const payment = postState.builderPendingPayments.get(paymentIndex).clone();
|
|
42
|
-
const amount = payment.withdrawal.amount;
|
|
43
|
-
if (amount > 0) {
|
|
44
|
-
postState.builderPendingWithdrawals.push(payment.withdrawal);
|
|
45
|
-
}
|
|
46
|
-
postState.builderPendingPayments.set(paymentIndex, ssz.gloas.BuilderPendingPayment.defaultViewDU());
|
|
47
|
-
// Cache the execution payload hash
|
|
48
|
-
postState.executionPayloadAvailability.set(postState.slot % SLOTS_PER_HISTORICAL_ROOT, true);
|
|
49
|
-
postState.latestBlockHash = payload.blockHash;
|
|
50
|
-
postState.commit();
|
|
51
|
-
if (verifyStateRoot && !byteArrayEquals(envelope.stateRoot, postState.hashTreeRoot())) {
|
|
52
|
-
throw new Error(`Envelope's state root does not match state envelope=${toRootHex(envelope.stateRoot)} state=${toRootHex(postState.hashTreeRoot())}`);
|
|
53
|
-
}
|
|
54
|
-
return postState;
|
|
55
|
-
}
|
|
56
|
-
function validateExecutionPayloadEnvelope(state, envelope) {
|
|
57
|
-
const payload = envelope.payload;
|
|
58
|
-
// Cache latest block header state root
|
|
59
|
-
if (byteArrayEquals(state.latestBlockHeader.stateRoot, ssz.Root.defaultValue())) {
|
|
60
|
-
const previousStateRoot = state.hashTreeRoot();
|
|
61
|
-
state.latestBlockHeader.stateRoot = previousStateRoot;
|
|
62
|
-
}
|
|
63
|
-
// Verify consistency with the beacon block
|
|
64
|
-
if (!byteArrayEquals(envelope.beaconBlockRoot, state.latestBlockHeader.hashTreeRoot())) {
|
|
65
|
-
throw new Error(`Envelope's block is not the latest block header envelope=${toRootHex(envelope.beaconBlockRoot)} latestBlockHeader=${toRootHex(state.latestBlockHeader.hashTreeRoot())}`);
|
|
66
|
-
}
|
|
67
|
-
if (envelope.slot !== state.slot) {
|
|
68
|
-
throw new Error(`Slot mismatch between envelope and state envelope=${envelope.slot} state=${state.slot}`);
|
|
69
|
-
}
|
|
70
|
-
// Verify consistency with the committed bid
|
|
71
|
-
const committedBid = state.latestExecutionPayloadBid;
|
|
72
|
-
if (envelope.builderIndex !== committedBid.builderIndex) {
|
|
73
|
-
throw new Error(`Builder index mismatch between envelope and committed bid envelope=${envelope.builderIndex} committedBid=${committedBid.builderIndex}`);
|
|
74
|
-
}
|
|
75
|
-
if (!byteArrayEquals(committedBid.prevRandao, payload.prevRandao)) {
|
|
76
|
-
throw new Error(`Prev randao mismatch between committed bid and payload committedBid=${toHex(committedBid.prevRandao)} payload=${toHex(payload.prevRandao)}`);
|
|
77
|
-
}
|
|
78
|
-
// Verify consistency with expected withdrawals
|
|
79
|
-
const payloadWithdrawalsRoot = ssz.capella.Withdrawals.hashTreeRoot(payload.withdrawals);
|
|
80
|
-
const expectedWithdrawalsRoot = state.payloadExpectedWithdrawals.hashTreeRoot();
|
|
81
|
-
if (!byteArrayEquals(payloadWithdrawalsRoot, expectedWithdrawalsRoot)) {
|
|
82
|
-
throw new Error(`Withdrawals mismatch between payload and expected withdrawals payload=${toRootHex(payloadWithdrawalsRoot)} expected=${toRootHex(expectedWithdrawalsRoot)}`);
|
|
83
|
-
}
|
|
84
|
-
// Verify the gas_limit
|
|
85
|
-
if (Number(committedBid.gasLimit) !== payload.gasLimit) {
|
|
86
|
-
throw new Error(`Gas limit mismatch between envelope's payload and committed bid envelope=${payload.gasLimit} committedBid=${Number(committedBid.gasLimit)}`);
|
|
87
|
-
}
|
|
88
|
-
// Verify the block hash
|
|
89
|
-
if (!byteArrayEquals(committedBid.blockHash, payload.blockHash)) {
|
|
90
|
-
throw new Error(`Block hash mismatch between envelope's payload and committed bid envelope=${toRootHex(payload.blockHash)} committedBid=${toRootHex(committedBid.blockHash)}`);
|
|
91
|
-
}
|
|
92
|
-
// Verify consistency of the parent hash with respect to the previous execution payload
|
|
93
|
-
if (!byteArrayEquals(payload.parentHash, state.latestBlockHash)) {
|
|
94
|
-
throw new Error(`Parent hash mismatch between envelope's payload and state envelope=${toRootHex(payload.parentHash)} state=${toRootHex(state.latestBlockHash)}`);
|
|
95
|
-
}
|
|
96
|
-
// Verify timestamp
|
|
97
|
-
if (payload.timestamp !== computeTimeAtSlot(state.config, state.slot, state.genesisTime)) {
|
|
98
|
-
throw new Error(`Timestamp mismatch between envelope's payload and state envelope=${payload.timestamp} state=${computeTimeAtSlot(state.config, state.slot, state.genesisTime)}`);
|
|
99
|
-
}
|
|
100
|
-
// Skipped: Verify the execution payload is valid
|
|
101
|
-
}
|
|
102
|
-
function verifyExecutionPayloadEnvelopeSignature(state, signedEnvelope) {
|
|
103
|
-
const signatureSet = getExecutionPayloadEnvelopeSignatureSet(state.config, state.epochCtx.pubkeyCache, new BeaconStateView(state), signedEnvelope, state.latestBlockHeader.proposerIndex);
|
|
104
|
-
return verifySignatureSet(signatureSet);
|
|
105
|
-
}
|
|
106
|
-
//# sourceMappingURL=processExecutionPayloadEnvelope.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"processExecutionPayloadEnvelope.js","sourceRoot":"","sources":["../../src/block/processExecutionPayloadEnvelope.ts"],"names":[],"mappings":"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"}
|