@lodestar/state-transition 1.43.0-dev.433e692fd9 → 1.43.0-dev.4358217e12
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 +13 -5
- 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/signatureSets/index.d.ts +1 -0
- package/lib/signatureSets/index.d.ts.map +1 -1
- package/lib/signatureSets/index.js +1 -0
- package/lib/signatureSets/index.js.map +1 -1
- package/lib/signatureSets/proposerPreferences.d.ts +4 -0
- package/lib/signatureSets/proposerPreferences.d.ts.map +1 -0
- package/lib/signatureSets/proposerPreferences.js +8 -0
- package/lib/signatureSets/proposerPreferences.js.map +1 -0
- 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 +8 -10
- package/lib/stateView/beaconStateView.d.ts.map +1 -1
- package/lib/stateView/beaconStateView.js +31 -36
- package/lib/stateView/beaconStateView.js.map +1 -1
- package/lib/stateView/interface.d.ts +19 -11
- 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 -3
- package/lib/util/gloas.d.ts.map +1 -1
- package/lib/util/gloas.js +25 -3
- 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 +15 -5
- 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/signatureSets/index.ts +1 -0
- package/src/signatureSets/proposerPreferences.ts +12 -0
- package/src/slot/upgradeStateToGloas.ts +5 -1
- package/src/stateTransition.ts +1 -1
- package/src/stateView/beaconStateView.ts +36 -47
- package/src/stateView/interface.ts +26 -14
- package/src/util/computeAnchorCheckpoint.ts +6 -19
- package/src/util/gloas.ts +46 -4
- 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
|
@@ -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;
|
|
@@ -187,13 +192,6 @@ export interface IBeaconStateViewAltair extends IBeaconStateView {
|
|
|
187
192
|
export interface IBeaconStateViewBellatrix extends IBeaconStateViewAltair {
|
|
188
193
|
forkName: ForkPostBellatrix;
|
|
189
194
|
latestExecutionPayloadHeader: ExecutionPayloadHeader;
|
|
190
|
-
/**
|
|
191
|
-
* Cross-fork accessor for the execution block hash of the most recently included payload.
|
|
192
|
-
* Pre-gloas: returns latestExecutionPayloadHeader.blockHash (bellatrix–fulu).
|
|
193
|
-
* Gloas+: returns the dedicated latestBlockHash state field (EIP-7732).
|
|
194
|
-
* Throws before bellatrix.
|
|
195
|
-
*/
|
|
196
|
-
latestBlockHash: Bytes32;
|
|
197
195
|
/**
|
|
198
196
|
* The execution block number of the most recently included payload.
|
|
199
197
|
* Named payloadBlockNumber (not latestBlockNumber) to mirror ExecutionPayloadHeader.blockNumber pre-gloas.
|
|
@@ -244,16 +242,23 @@ export interface IBeaconStateViewFulu extends IBeaconStateViewElectra {
|
|
|
244
242
|
/** Gloas+ state fields — use isStatePostGloas() guard */
|
|
245
243
|
export interface IBeaconStateViewGloas extends IBeaconStateViewFulu {
|
|
246
244
|
forkName: ForkPostGloas;
|
|
245
|
+
/** Removed from BeaconState in gloas. Use `latestBlockHash` instead. */
|
|
246
|
+
latestExecutionPayloadHeader: never;
|
|
247
|
+
/** Removed from BeaconState in gloas. */
|
|
248
|
+
payloadBlockNumber: never;
|
|
249
|
+
latestBlockHash: Bytes32;
|
|
247
250
|
executionPayloadAvailability: BitArray;
|
|
248
251
|
latestExecutionPayloadBid: ExecutionPayloadBid;
|
|
249
252
|
payloadExpectedWithdrawals: capella.Withdrawal[];
|
|
250
253
|
getBuilder(index: BuilderIndex): gloas.Builder;
|
|
251
254
|
canBuilderCoverBid(builderIndex: BuilderIndex, bidAmount: number): boolean;
|
|
252
255
|
getIndexInPayloadTimelinessCommittee(validatorIndex: ValidatorIndex, slot: Slot): number;
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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[];
|
|
257
262
|
}
|
|
258
263
|
|
|
259
264
|
/**
|
|
@@ -262,7 +267,14 @@ export interface IBeaconStateViewGloas extends IBeaconStateViewFulu {
|
|
|
262
267
|
* forkName as ForkName since the class wraps any fork's state.
|
|
263
268
|
* Sub-interfaces retain their narrowed forkName discriminants for caller-side type guards.
|
|
264
269
|
*/
|
|
265
|
-
export type IBeaconStateViewLatestFork = Omit<
|
|
270
|
+
export type IBeaconStateViewLatestFork = Omit<
|
|
271
|
+
IBeaconStateViewGloas,
|
|
272
|
+
"forkName" | "latestExecutionPayloadHeader" | "payloadBlockNumber"
|
|
273
|
+
> & {
|
|
274
|
+
forkName: ForkName;
|
|
275
|
+
latestExecutionPayloadHeader: ExecutionPayloadHeader;
|
|
276
|
+
payloadBlockNumber: number;
|
|
277
|
+
};
|
|
266
278
|
export function isStatePostAltair(state: IBeaconStateView): state is IBeaconStateViewAltair {
|
|
267
279
|
return isForkPostAltair(state.forkName);
|
|
268
280
|
}
|
|
@@ -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,16 +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 {
|
|
15
|
-
import {CachedBeaconStateGloas} from "../types.js";
|
|
16
|
+
import {CachedBeaconStateFulu, CachedBeaconStateGloas} from "../types.js";
|
|
16
17
|
import {getBlockRootAtSlot} from "./blockRoot.js";
|
|
17
18
|
import {computeEpochAtSlot} from "./epoch.js";
|
|
19
|
+
import {computeEpochShuffling} from "./epochShuffling.js";
|
|
18
20
|
import {RootCache} from "./rootCache.js";
|
|
21
|
+
import {computePayloadTimelinessCommitteesForEpoch} from "./seed.js";
|
|
22
|
+
import {getActiveValidatorIndices} from "./validator.js";
|
|
19
23
|
|
|
20
24
|
export function isBuilderWithdrawalCredential(withdrawalCredentials: Uint8Array): boolean {
|
|
21
25
|
return withdrawalCredentials[0] === BUILDER_WITHDRAWAL_PREFIX;
|
|
@@ -168,6 +172,44 @@ export function isAttestationSameSlotRootCache(rootCache: RootCache, data: Attes
|
|
|
168
172
|
return isMatchingBlockRoot && isCurrentBlockRoot;
|
|
169
173
|
}
|
|
170
174
|
|
|
171
|
-
export function
|
|
172
|
-
|
|
175
|
+
export function initializePtcWindow(state: CachedBeaconStateFulu): Uint32Array[] {
|
|
176
|
+
const ptcWindow: Uint32Array[] = Array.from({length: SLOTS_PER_EPOCH}, () => new Uint32Array(PTC_SIZE));
|
|
177
|
+
const currentEpoch = state.epochCtx.epoch;
|
|
178
|
+
|
|
179
|
+
for (let epochOffset = 0; epochOffset <= MIN_SEED_LOOKAHEAD; epochOffset++) {
|
|
180
|
+
const epoch = currentEpoch + epochOffset;
|
|
181
|
+
const shuffling =
|
|
182
|
+
state.epochCtx.getShufflingAtEpochOrNull(epoch) ??
|
|
183
|
+
computeEpochShuffling(state, getActiveValidatorIndices(state, epoch), epoch);
|
|
184
|
+
|
|
185
|
+
ptcWindow.push(
|
|
186
|
+
...computePayloadTimelinessCommitteesForEpoch(
|
|
187
|
+
state,
|
|
188
|
+
epoch,
|
|
189
|
+
shuffling.committees,
|
|
190
|
+
state.epochCtx.effectiveBalanceIncrements
|
|
191
|
+
)
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return ptcWindow;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function getPtcWindowEpochCacheData(state: CachedBeaconStateGloas): {
|
|
199
|
+
previousPayloadTimelinessCommittees: Uint32Array[];
|
|
200
|
+
payloadTimelinessCommittees: Uint32Array[];
|
|
201
|
+
nextPayloadTimelinessCommittees: Uint32Array[];
|
|
202
|
+
} {
|
|
203
|
+
const toUint32Arrays = (views: ReturnType<typeof state.ptcWindow.getReadonlyByRange>) =>
|
|
204
|
+
views.map((v) => Uint32Array.from(v.getAll()));
|
|
205
|
+
|
|
206
|
+
const previousPtcWindow = state.ptcWindow.getReadonlyByRange(0, SLOTS_PER_EPOCH);
|
|
207
|
+
const currentPtcWindow = state.ptcWindow.getReadonlyByRange(SLOTS_PER_EPOCH, SLOTS_PER_EPOCH);
|
|
208
|
+
const nextPtcWindow = state.ptcWindow.getReadonlyByRange(2 * SLOTS_PER_EPOCH, SLOTS_PER_EPOCH);
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
previousPayloadTimelinessCommittees: toUint32Arrays(previousPtcWindow),
|
|
212
|
+
payloadTimelinessCommittees: toUint32Arrays(currentPtcWindow),
|
|
213
|
+
nextPayloadTimelinessCommittees: toUint32Arrays(nextPtcWindow),
|
|
214
|
+
};
|
|
173
215
|
}
|
|
@@ -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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"}
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import {SLOTS_PER_EPOCH, SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params";
|
|
2
|
-
import {gloas, 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 {CachedBeaconStateGloas} from "../types.js";
|
|
7
|
-
import {computeTimeAtSlot} from "../util/index.js";
|
|
8
|
-
import {verifySignatureSet} from "../util/signatureSets.js";
|
|
9
|
-
import {processConsolidationRequest} from "./processConsolidationRequest.js";
|
|
10
|
-
import {getPendingValidatorPubkeys, processDepositRequest} from "./processDepositRequest.js";
|
|
11
|
-
import {processWithdrawalRequest} from "./processWithdrawalRequest.js";
|
|
12
|
-
|
|
13
|
-
export type ProcessExecutionPayloadEnvelopeOpts = {
|
|
14
|
-
verifySignature?: boolean;
|
|
15
|
-
verifyStateRoot?: boolean;
|
|
16
|
-
dontTransferCache?: boolean;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
// Unlike other block processing functions which mutate state in-place, this function
|
|
20
|
-
// clones the state and returns the post-state, similar to stateTransition().
|
|
21
|
-
// This function does not call execution engine to verify payload. Need to call it from other place.
|
|
22
|
-
export function processExecutionPayloadEnvelope(
|
|
23
|
-
state: CachedBeaconStateGloas,
|
|
24
|
-
signedEnvelope: gloas.SignedExecutionPayloadEnvelope,
|
|
25
|
-
opts?: ProcessExecutionPayloadEnvelopeOpts
|
|
26
|
-
): CachedBeaconStateGloas {
|
|
27
|
-
const {verifySignature = true, verifyStateRoot = true} = opts ?? {};
|
|
28
|
-
const envelope = signedEnvelope.message;
|
|
29
|
-
const payload = envelope.payload;
|
|
30
|
-
const fork = state.config.getForkSeq(envelope.slot);
|
|
31
|
-
|
|
32
|
-
if (verifySignature && !verifyExecutionPayloadEnvelopeSignature(state, signedEnvelope)) {
|
|
33
|
-
throw Error(`Execution payload envelope has invalid signature builderIndex=${envelope.builderIndex}`);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// .clone() before mutating state, similar to stateTransition()
|
|
37
|
-
const postState = state.clone(opts?.dontTransferCache) as CachedBeaconStateGloas;
|
|
38
|
-
|
|
39
|
-
validateExecutionPayloadEnvelope(postState, envelope);
|
|
40
|
-
|
|
41
|
-
const requests = envelope.executionRequests;
|
|
42
|
-
|
|
43
|
-
if (requests.deposits.length > 0) {
|
|
44
|
-
// Build cache of pending validator pubkeys once, shared across all deposit requests
|
|
45
|
-
const pendingValidatorPubkeys = getPendingValidatorPubkeys(postState.config, postState);
|
|
46
|
-
|
|
47
|
-
for (const deposit of requests.deposits) {
|
|
48
|
-
processDepositRequest(fork, postState, deposit, pendingValidatorPubkeys);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
for (const withdrawal of requests.withdrawals) {
|
|
53
|
-
processWithdrawalRequest(fork, postState, withdrawal);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
for (const consolidation of requests.consolidations) {
|
|
57
|
-
processConsolidationRequest(postState, consolidation);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Queue the builder payment
|
|
61
|
-
const paymentIndex = SLOTS_PER_EPOCH + (postState.slot % SLOTS_PER_EPOCH);
|
|
62
|
-
const payment = postState.builderPendingPayments.get(paymentIndex).clone();
|
|
63
|
-
const amount = payment.withdrawal.amount;
|
|
64
|
-
|
|
65
|
-
if (amount > 0) {
|
|
66
|
-
postState.builderPendingWithdrawals.push(payment.withdrawal);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
postState.builderPendingPayments.set(paymentIndex, ssz.gloas.BuilderPendingPayment.defaultViewDU());
|
|
70
|
-
|
|
71
|
-
// Cache the execution payload hash
|
|
72
|
-
postState.executionPayloadAvailability.set(postState.slot % SLOTS_PER_HISTORICAL_ROOT, true);
|
|
73
|
-
postState.latestBlockHash = payload.blockHash;
|
|
74
|
-
|
|
75
|
-
postState.commit();
|
|
76
|
-
|
|
77
|
-
if (verifyStateRoot && !byteArrayEquals(envelope.stateRoot, postState.hashTreeRoot())) {
|
|
78
|
-
throw new Error(
|
|
79
|
-
`Envelope's state root does not match state envelope=${toRootHex(envelope.stateRoot)} state=${toRootHex(postState.hashTreeRoot())}`
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return postState;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function validateExecutionPayloadEnvelope(
|
|
87
|
-
state: CachedBeaconStateGloas,
|
|
88
|
-
envelope: gloas.ExecutionPayloadEnvelope
|
|
89
|
-
): void {
|
|
90
|
-
const payload = envelope.payload;
|
|
91
|
-
|
|
92
|
-
// Cache latest block header state root
|
|
93
|
-
if (byteArrayEquals(state.latestBlockHeader.stateRoot, ssz.Root.defaultValue())) {
|
|
94
|
-
const previousStateRoot = state.hashTreeRoot();
|
|
95
|
-
state.latestBlockHeader.stateRoot = previousStateRoot;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Verify consistency with the beacon block
|
|
99
|
-
if (!byteArrayEquals(envelope.beaconBlockRoot, state.latestBlockHeader.hashTreeRoot())) {
|
|
100
|
-
throw new Error(
|
|
101
|
-
`Envelope's block is not the latest block header envelope=${toRootHex(envelope.beaconBlockRoot)} latestBlockHeader=${toRootHex(state.latestBlockHeader.hashTreeRoot())}`
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (envelope.slot !== state.slot) {
|
|
106
|
-
throw new Error(`Slot mismatch between envelope and state envelope=${envelope.slot} state=${state.slot}`);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Verify consistency with the committed bid
|
|
110
|
-
const committedBid = state.latestExecutionPayloadBid;
|
|
111
|
-
if (envelope.builderIndex !== committedBid.builderIndex) {
|
|
112
|
-
throw new Error(
|
|
113
|
-
`Builder index mismatch between envelope and committed bid envelope=${envelope.builderIndex} committedBid=${committedBid.builderIndex}`
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (!byteArrayEquals(committedBid.prevRandao, payload.prevRandao)) {
|
|
118
|
-
throw new Error(
|
|
119
|
-
`Prev randao mismatch between committed bid and payload committedBid=${toHex(committedBid.prevRandao)} payload=${toHex(payload.prevRandao)}`
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Verify consistency with expected withdrawals
|
|
124
|
-
const payloadWithdrawalsRoot = ssz.capella.Withdrawals.hashTreeRoot(payload.withdrawals);
|
|
125
|
-
const expectedWithdrawalsRoot = state.payloadExpectedWithdrawals.hashTreeRoot();
|
|
126
|
-
if (!byteArrayEquals(payloadWithdrawalsRoot, expectedWithdrawalsRoot)) {
|
|
127
|
-
throw new Error(
|
|
128
|
-
`Withdrawals mismatch between payload and expected withdrawals payload=${toRootHex(payloadWithdrawalsRoot)} expected=${toRootHex(expectedWithdrawalsRoot)}`
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Verify the gas_limit
|
|
133
|
-
if (Number(committedBid.gasLimit) !== payload.gasLimit) {
|
|
134
|
-
throw new Error(
|
|
135
|
-
`Gas limit mismatch between envelope's payload and committed bid envelope=${payload.gasLimit} committedBid=${Number(committedBid.gasLimit)}`
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Verify the block hash
|
|
140
|
-
if (!byteArrayEquals(committedBid.blockHash, payload.blockHash)) {
|
|
141
|
-
throw new Error(
|
|
142
|
-
`Block hash mismatch between envelope's payload and committed bid envelope=${toRootHex(payload.blockHash)} committedBid=${toRootHex(committedBid.blockHash)}`
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Verify consistency of the parent hash with respect to the previous execution payload
|
|
147
|
-
if (!byteArrayEquals(payload.parentHash, state.latestBlockHash)) {
|
|
148
|
-
throw new Error(
|
|
149
|
-
`Parent hash mismatch between envelope's payload and state envelope=${toRootHex(payload.parentHash)} state=${toRootHex(state.latestBlockHash)}`
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Verify timestamp
|
|
154
|
-
if (payload.timestamp !== computeTimeAtSlot(state.config, state.slot, state.genesisTime)) {
|
|
155
|
-
throw new Error(
|
|
156
|
-
`Timestamp mismatch between envelope's payload and state envelope=${payload.timestamp} state=${computeTimeAtSlot(state.config, state.slot, state.genesisTime)}`
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Skipped: Verify the execution payload is valid
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function verifyExecutionPayloadEnvelopeSignature(
|
|
164
|
-
state: CachedBeaconStateGloas,
|
|
165
|
-
signedEnvelope: gloas.SignedExecutionPayloadEnvelope
|
|
166
|
-
): boolean {
|
|
167
|
-
const signatureSet = getExecutionPayloadEnvelopeSignatureSet(
|
|
168
|
-
state.config,
|
|
169
|
-
state.epochCtx.pubkeyCache,
|
|
170
|
-
new BeaconStateView(state),
|
|
171
|
-
signedEnvelope,
|
|
172
|
-
state.latestBlockHeader.proposerIndex
|
|
173
|
-
);
|
|
174
|
-
return verifySignatureSet(signatureSet);
|
|
175
|
-
}
|