@lodestar/state-transition 1.42.0 → 1.43.0-dev.07452fe3b7
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/processDepositRequest.d.ts +11 -2
- package/lib/block/processDepositRequest.d.ts.map +1 -1
- package/lib/block/processDepositRequest.js +34 -4
- package/lib/block/processDepositRequest.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 +10 -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/index.d.ts +4 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -1
- package/lib/index.js.map +1 -1
- package/lib/signatureSets/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/signatureSets/executionPayloadEnvelope.js +5 -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/signatureSets/voluntaryExits.d.ts +2 -2
- package/lib/signatureSets/voluntaryExits.d.ts.map +1 -1
- package/lib/signatureSets/voluntaryExits.js +4 -0
- package/lib/signatureSets/voluntaryExits.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.d.ts +1 -2
- package/lib/stateTransition.d.ts.map +1 -1
- package/lib/stateTransition.js +1 -2
- package/lib/stateTransition.js.map +1 -1
- package/lib/stateView/beaconStateView.d.ts +18 -12
- package/lib/stateView/beaconStateView.d.ts.map +1 -1
- package/lib/stateView/beaconStateView.js +69 -42
- package/lib/stateView/beaconStateView.js.map +1 -1
- package/lib/stateView/interface.d.ts +111 -54
- package/lib/stateView/interface.d.ts.map +1 -1
- package/lib/stateView/interface.js +22 -1
- package/lib/stateView/interface.js.map +1 -1
- package/lib/util/attestation.d.ts +12 -1
- package/lib/util/attestation.d.ts.map +1 -1
- package/lib/util/attestation.js +23 -8
- package/lib/util/attestation.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/execution.d.ts +4 -2
- package/lib/util/execution.d.ts.map +1 -1
- package/lib/util/execution.js +7 -0
- package/lib/util/execution.js.map +1 -1
- package/lib/util/gloas.d.ts +7 -2
- 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/processDepositRequest.ts +50 -5
- 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/index.ts +20 -2
- package/src/signatureSets/executionPayloadEnvelope.ts +6 -2
- package/src/signatureSets/index.ts +1 -0
- package/src/signatureSets/proposerPreferences.ts +12 -0
- package/src/signatureSets/voluntaryExits.ts +5 -2
- package/src/slot/upgradeStateToGloas.ts +5 -1
- package/src/stateTransition.ts +1 -2
- package/src/stateView/beaconStateView.ts +91 -56
- package/src/stateView/interface.ts +163 -79
- package/src/util/attestation.ts +37 -8
- package/src/util/computeAnchorCheckpoint.ts +6 -19
- package/src/util/execution.ts +11 -1
- package/src/util/gloas.ts +46 -3
- package/lib/block/processExecutionPayloadEnvelope.d.ts +0 -9
- package/lib/block/processExecutionPayloadEnvelope.d.ts.map +0 -1
- package/lib/block/processExecutionPayloadEnvelope.js +0 -102
- package/lib/block/processExecutionPayloadEnvelope.js.map +0 -1
- package/src/block/processExecutionPayloadEnvelope.ts +0 -170
package/lib/util/gloas.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BuilderIndex, Epoch, ValidatorIndex, gloas } from "@lodestar/types";
|
|
2
2
|
import { AttestationData } from "@lodestar/types/phase0";
|
|
3
|
-
import { CachedBeaconStateGloas } from "../types.js";
|
|
3
|
+
import { CachedBeaconStateFulu, CachedBeaconStateGloas } from "../types.js";
|
|
4
4
|
import { RootCache } from "./rootCache.js";
|
|
5
5
|
export declare function isBuilderWithdrawalCredential(withdrawalCredentials: Uint8Array): boolean;
|
|
6
6
|
export declare function getBuilderPaymentQuorumThreshold(state: CachedBeaconStateGloas): number;
|
|
@@ -48,5 +48,10 @@ export declare function initiateBuilderExit(state: CachedBeaconStateGloas, build
|
|
|
48
48
|
export declare function findBuilderIndexByPubkey(state: CachedBeaconStateGloas, pubkey: Uint8Array): BuilderIndex | null;
|
|
49
49
|
export declare function isAttestationSameSlot(state: CachedBeaconStateGloas, data: AttestationData): boolean;
|
|
50
50
|
export declare function isAttestationSameSlotRootCache(rootCache: RootCache, data: AttestationData): boolean;
|
|
51
|
-
export declare function
|
|
51
|
+
export declare function initializePtcWindow(state: CachedBeaconStateFulu): Uint32Array[];
|
|
52
|
+
export declare function getPtcWindowEpochCacheData(state: CachedBeaconStateGloas): {
|
|
53
|
+
previousPayloadTimelinessCommittees: Uint32Array[];
|
|
54
|
+
payloadTimelinessCommittees: Uint32Array[];
|
|
55
|
+
nextPayloadTimelinessCommittees: Uint32Array[];
|
|
56
|
+
};
|
|
52
57
|
//# sourceMappingURL=gloas.d.ts.map
|
package/lib/util/gloas.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gloas.d.ts","sourceRoot":"","sources":["../../src/util/gloas.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gloas.d.ts","sourceRoot":"","sources":["../../src/util/gloas.ts"],"names":[],"mappings":"AAYA,OAAO,EAAC,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAC,eAAe,EAAC,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAC,qBAAqB,EAAE,sBAAsB,EAAC,MAAM,aAAa,CAAC;AAI1E,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAIzC,wBAAgB,6BAA6B,CAAC,qBAAqB,EAAE,UAAU,GAAG,OAAO,CAExF;AAED,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAMtF;AAOD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAG9D;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CAAC,YAAY,EAAE,YAAY,GAAG,cAAc,CAG9F;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CAAC,cAAc,EAAE,cAAc,GAAG,YAAY,CAGhG;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,GAAG,OAAO,CAEtF;AAED;;;GAGG;AACH,wBAAgB,qCAAqC,CACnD,KAAK,EAAE,sBAAsB,EAC7B,YAAY,EAAE,YAAY,GACzB,MAAM,CAoBR;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,sBAAsB,EAC7B,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,MAAM,GAChB,OAAO,CAUT;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,sBAAsB,EAAE,YAAY,EAAE,YAAY,GAAG,IAAI,CAWnG;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,IAAI,CAO/G;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,sBAAsB,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAOnG;AAED,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAOnG;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,qBAAqB,GAAG,WAAW,EAAE,CAqB/E;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,sBAAsB,GAAG;IACzE,mCAAmC,EAAE,WAAW,EAAE,CAAC;IACnD,2BAA2B,EAAE,WAAW,EAAE,CAAC;IAC3C,+BAA+B,EAAE,WAAW,EAAE,CAAC;CAChD,CAaA"}
|
package/lib/util/gloas.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { BUILDER_INDEX_FLAG, BUILDER_PAYMENT_THRESHOLD_DENOMINATOR, BUILDER_PAYMENT_THRESHOLD_NUMERATOR, BUILDER_WITHDRAWAL_PREFIX, EFFECTIVE_BALANCE_INCREMENT, FAR_FUTURE_EPOCH, MIN_DEPOSIT_AMOUNT, SLOTS_PER_EPOCH, } from "@lodestar/params";
|
|
1
|
+
import { BUILDER_INDEX_FLAG, BUILDER_PAYMENT_THRESHOLD_DENOMINATOR, BUILDER_PAYMENT_THRESHOLD_NUMERATOR, BUILDER_WITHDRAWAL_PREFIX, EFFECTIVE_BALANCE_INCREMENT, FAR_FUTURE_EPOCH, MIN_DEPOSIT_AMOUNT, MIN_SEED_LOOKAHEAD, PTC_SIZE, SLOTS_PER_EPOCH, } from "@lodestar/params";
|
|
2
2
|
import { byteArrayEquals } from "@lodestar/utils";
|
|
3
3
|
import { getBlockRootAtSlot } from "./blockRoot.js";
|
|
4
4
|
import { computeEpochAtSlot } from "./epoch.js";
|
|
5
|
+
import { computeEpochShuffling } from "./epochShuffling.js";
|
|
6
|
+
import { computePayloadTimelinessCommitteesForEpoch } from "./seed.js";
|
|
7
|
+
import { getActiveValidatorIndices } from "./validator.js";
|
|
5
8
|
export function isBuilderWithdrawalCredential(withdrawalCredentials) {
|
|
6
9
|
return withdrawalCredentials[0] === BUILDER_WITHDRAWAL_PREFIX;
|
|
7
10
|
}
|
|
@@ -122,7 +125,26 @@ export function isAttestationSameSlotRootCache(rootCache, data) {
|
|
|
122
125
|
const isCurrentBlockRoot = !byteArrayEquals(data.beaconBlockRoot, rootCache.getBlockRootAtSlot(data.slot - 1));
|
|
123
126
|
return isMatchingBlockRoot && isCurrentBlockRoot;
|
|
124
127
|
}
|
|
125
|
-
export function
|
|
126
|
-
|
|
128
|
+
export function initializePtcWindow(state) {
|
|
129
|
+
const ptcWindow = Array.from({ length: SLOTS_PER_EPOCH }, () => new Uint32Array(PTC_SIZE));
|
|
130
|
+
const currentEpoch = state.epochCtx.epoch;
|
|
131
|
+
for (let epochOffset = 0; epochOffset <= MIN_SEED_LOOKAHEAD; epochOffset++) {
|
|
132
|
+
const epoch = currentEpoch + epochOffset;
|
|
133
|
+
const shuffling = state.epochCtx.getShufflingAtEpochOrNull(epoch) ??
|
|
134
|
+
computeEpochShuffling(state, getActiveValidatorIndices(state, epoch), epoch);
|
|
135
|
+
ptcWindow.push(...computePayloadTimelinessCommitteesForEpoch(state, epoch, shuffling.committees, state.epochCtx.effectiveBalanceIncrements));
|
|
136
|
+
}
|
|
137
|
+
return ptcWindow;
|
|
138
|
+
}
|
|
139
|
+
export function getPtcWindowEpochCacheData(state) {
|
|
140
|
+
const toUint32Arrays = (views) => views.map((v) => Uint32Array.from(v.getAll()));
|
|
141
|
+
const previousPtcWindow = state.ptcWindow.getReadonlyByRange(0, SLOTS_PER_EPOCH);
|
|
142
|
+
const currentPtcWindow = state.ptcWindow.getReadonlyByRange(SLOTS_PER_EPOCH, SLOTS_PER_EPOCH);
|
|
143
|
+
const nextPtcWindow = state.ptcWindow.getReadonlyByRange(2 * SLOTS_PER_EPOCH, SLOTS_PER_EPOCH);
|
|
144
|
+
return {
|
|
145
|
+
previousPayloadTimelinessCommittees: toUint32Arrays(previousPtcWindow),
|
|
146
|
+
payloadTimelinessCommittees: toUint32Arrays(currentPtcWindow),
|
|
147
|
+
nextPayloadTimelinessCommittees: toUint32Arrays(nextPtcWindow),
|
|
148
|
+
};
|
|
127
149
|
}
|
|
128
150
|
//# sourceMappingURL=gloas.js.map
|
package/lib/util/gloas.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gloas.js","sourceRoot":"","sources":["../../src/util/gloas.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,qCAAqC,EACrC,mCAAmC,EACnC,yBAAyB,EACzB,2BAA2B,EAC3B,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAC,eAAe,EAAC,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAC,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAC,kBAAkB,EAAC,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"gloas.js","sourceRoot":"","sources":["../../src/util/gloas.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"bugs": {
|
|
12
12
|
"url": "https://github.com/ChainSafe/lodestar/issues"
|
|
13
13
|
},
|
|
14
|
-
"version": "1.
|
|
14
|
+
"version": "1.43.0-dev.07452fe3b7",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
@@ -65,16 +65,16 @@
|
|
|
65
65
|
"@chainsafe/persistent-merkle-tree": "^1.2.1",
|
|
66
66
|
"@chainsafe/persistent-ts": "^1.0.0",
|
|
67
67
|
"@chainsafe/pubkey-index-map": "^3.0.0",
|
|
68
|
-
"@chainsafe/ssz": "^1.
|
|
68
|
+
"@chainsafe/ssz": "^1.4.0",
|
|
69
69
|
"@chainsafe/swap-or-not-shuffle": "^1.2.1",
|
|
70
|
-
"@lodestar/config": "^1.
|
|
71
|
-
"@lodestar/params": "^1.
|
|
72
|
-
"@lodestar/types": "^1.
|
|
73
|
-
"@lodestar/utils": "^1.
|
|
70
|
+
"@lodestar/config": "^1.43.0-dev.07452fe3b7",
|
|
71
|
+
"@lodestar/params": "^1.43.0-dev.07452fe3b7",
|
|
72
|
+
"@lodestar/types": "^1.43.0-dev.07452fe3b7",
|
|
73
|
+
"@lodestar/utils": "^1.43.0-dev.07452fe3b7",
|
|
74
74
|
"@vekexasia/bigint-buffer2": "^1.1.1"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
|
-
"@lodestar/api": "^1.
|
|
77
|
+
"@lodestar/api": "^1.43.0-dev.07452fe3b7"
|
|
78
78
|
},
|
|
79
79
|
"keywords": [
|
|
80
80
|
"ethereum",
|
|
@@ -82,5 +82,5 @@
|
|
|
82
82
|
"beacon",
|
|
83
83
|
"blockchain"
|
|
84
84
|
],
|
|
85
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "3f9cb0f15097b9d04a2ea9c7eee71c6103088f0f"
|
|
86
86
|
}
|
package/src/block/index.ts
CHANGED
|
@@ -14,8 +14,8 @@ import {processBlockHeader} from "./processBlockHeader.js";
|
|
|
14
14
|
import {processEth1Data} from "./processEth1Data.js";
|
|
15
15
|
import {processExecutionPayload} from "./processExecutionPayload.js";
|
|
16
16
|
import {processExecutionPayloadBid} from "./processExecutionPayloadBid.js";
|
|
17
|
-
import {processExecutionPayloadEnvelope} from "./processExecutionPayloadEnvelope.js";
|
|
18
17
|
import {processOperations} from "./processOperations.js";
|
|
18
|
+
import {processParentExecutionPayload} from "./processParentExecutionPayload.js";
|
|
19
19
|
import {processPayloadAttestation} from "./processPayloadAttestation.js";
|
|
20
20
|
import {processRandao} from "./processRandao.js";
|
|
21
21
|
import {processSyncAggregate} from "./processSyncCommittee.js";
|
|
@@ -32,7 +32,7 @@ export {
|
|
|
32
32
|
processWithdrawals,
|
|
33
33
|
processExecutionPayloadBid,
|
|
34
34
|
processPayloadAttestation,
|
|
35
|
-
|
|
35
|
+
processParentExecutionPayload,
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
export * from "./externalData.js";
|
|
@@ -51,10 +51,16 @@ export function processBlock(
|
|
|
51
51
|
): void {
|
|
52
52
|
const {verifySignatures = true} = opts ?? {};
|
|
53
53
|
|
|
54
|
+
// Apply the parent's deferred payload effects before everything else. Must run before
|
|
55
|
+
// processBlockHeader and processExecutionPayloadBid so subsequent steps see the updated state.
|
|
56
|
+
if (fork >= ForkSeq.gloas) {
|
|
57
|
+
processParentExecutionPayload(state as CachedBeaconStateGloas, block as BeaconBlock<ForkPostGloas>);
|
|
58
|
+
}
|
|
59
|
+
|
|
54
60
|
processBlockHeader(state, block);
|
|
55
61
|
|
|
56
62
|
if (fork >= ForkSeq.gloas) {
|
|
57
|
-
//
|
|
63
|
+
// Parent payload's execution requests were already applied by processParentExecutionPayload above
|
|
58
64
|
processWithdrawals(fork, state as CachedBeaconStateGloas);
|
|
59
65
|
} else if (fork >= ForkSeq.capella) {
|
|
60
66
|
const fullOrBlindedPayload = getFullOrBlindedPayload(block);
|
|
@@ -67,7 +73,9 @@ export function processBlock(
|
|
|
67
73
|
|
|
68
74
|
// The call to the process_execution_payload must happen before the call to the process_randao as the former depends
|
|
69
75
|
// on the randao_mix computed with the reveal of the previous block.
|
|
70
|
-
//
|
|
76
|
+
// Post-gloas: process_execution_payload is not part of block processing. The parent's payload
|
|
77
|
+
// effects are applied earlier via processParentExecutionPayload, and each execution payload is
|
|
78
|
+
// verified out-of-band via verifyExecutionPayloadEnvelope when it arrives.
|
|
71
79
|
if (
|
|
72
80
|
fork < ForkSeq.gloas &&
|
|
73
81
|
fork >= ForkSeq.bellatrix &&
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
1
2
|
import {FAR_FUTURE_EPOCH, ForkSeq, UNSET_DEPOSIT_REQUESTS_START_INDEX} from "@lodestar/params";
|
|
2
|
-
import {BLSPubkey, Bytes32, UintNum64, electra, ssz} from "@lodestar/types";
|
|
3
|
+
import {BLSPubkey, Bytes32, PubkeyHex, UintNum64, electra, ssz} from "@lodestar/types";
|
|
4
|
+
import {toPubkeyHex} from "@lodestar/utils";
|
|
3
5
|
import {CachedBeaconStateElectra, CachedBeaconStateGloas} from "../types.js";
|
|
4
6
|
import {findBuilderIndexByPubkey, isBuilderWithdrawalCredential} from "../util/gloas.js";
|
|
5
7
|
import {computeEpochAtSlot, isValidatorKnown} from "../util/index.js";
|
|
@@ -74,16 +76,24 @@ function addBuilderToRegistry(
|
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
78
|
|
|
79
|
+
// TODO GLOAS: pendingValidatorPubkeys cache is currently naive and has room for improvement.
|
|
80
|
+
// Currently the cache lives in process_block, but we should put it in epochCache or elsewhere that has longer
|
|
81
|
+
// lifetime to avoid duplicated deposit signature computation
|
|
82
|
+
// See https://github.com/ChainSafe/lodestar/issues/9181
|
|
77
83
|
export function processDepositRequest(
|
|
78
84
|
fork: ForkSeq,
|
|
79
85
|
state: CachedBeaconStateElectra | CachedBeaconStateGloas,
|
|
80
|
-
depositRequest: electra.DepositRequest
|
|
86
|
+
depositRequest: electra.DepositRequest,
|
|
87
|
+
pendingValidatorPubkeysCache?: Set<PubkeyHex>
|
|
81
88
|
): void {
|
|
82
89
|
const {pubkey, withdrawalCredentials, amount, signature} = depositRequest;
|
|
83
90
|
|
|
84
91
|
// Check if this is a builder or validator deposit
|
|
85
92
|
if (fork >= ForkSeq.gloas) {
|
|
86
93
|
const stateGloas = state as CachedBeaconStateGloas;
|
|
94
|
+
const pendingValidatorPubkeys =
|
|
95
|
+
pendingValidatorPubkeysCache ?? getPendingValidatorPubkeys(state.config, stateGloas);
|
|
96
|
+
const pubkeyHex = toPubkeyHex(pubkey);
|
|
87
97
|
const builderIndex = findBuilderIndexByPubkey(stateGloas, pubkey);
|
|
88
98
|
const validatorIndex = state.epochCtx.getValidatorIndex(pubkey);
|
|
89
99
|
|
|
@@ -91,14 +101,24 @@ export function processDepositRequest(
|
|
|
91
101
|
// already exists with this pubkey, apply the deposit to their balance
|
|
92
102
|
const isBuilder = builderIndex !== null;
|
|
93
103
|
const isValidator = isValidatorKnown(state, validatorIndex);
|
|
94
|
-
const
|
|
104
|
+
const isPendingValidator = pendingValidatorPubkeys.has(pubkeyHex);
|
|
95
105
|
|
|
96
|
-
|
|
97
|
-
if (isBuilder || (isBuilderPrefix && !isValidator)) {
|
|
106
|
+
if (isBuilder || (isBuilderWithdrawalCredential(withdrawalCredentials) && !isValidator && !isPendingValidator)) {
|
|
98
107
|
// Apply builder deposits immediately
|
|
99
108
|
applyDepositForBuilder(stateGloas, pubkey, withdrawalCredentials, amount, signature, state.slot);
|
|
100
109
|
return;
|
|
101
110
|
}
|
|
111
|
+
|
|
112
|
+
// Keep the shared cache in sync: if this deposit has a valid signature, subsequent
|
|
113
|
+
// deposit requests for the same pubkey in this envelope must see it as a pending validator
|
|
114
|
+
if (
|
|
115
|
+
pendingValidatorPubkeysCache &&
|
|
116
|
+
!isValidator &&
|
|
117
|
+
!isPendingValidator &&
|
|
118
|
+
isValidDepositSignature(state.config, pubkey, withdrawalCredentials, amount, signature)
|
|
119
|
+
) {
|
|
120
|
+
pendingValidatorPubkeys.add(pubkeyHex);
|
|
121
|
+
}
|
|
102
122
|
}
|
|
103
123
|
|
|
104
124
|
// Only set deposit_requests_start_index in Electra fork, not Gloas
|
|
@@ -116,3 +136,28 @@ export function processDepositRequest(
|
|
|
116
136
|
});
|
|
117
137
|
state.pendingDeposits.push(pendingDeposit);
|
|
118
138
|
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Build a set of pubkeys (hex-encoded) from pending deposits that have valid signatures.
|
|
142
|
+
* This is computed once and passed to each processDepositRequest call to avoid
|
|
143
|
+
* repeatedly iterating state.pendingDeposits.
|
|
144
|
+
*
|
|
145
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.3/specs/gloas/beacon-chain.md#new-is_pending_validator
|
|
146
|
+
*/
|
|
147
|
+
export function getPendingValidatorPubkeys(config: BeaconConfig, state: CachedBeaconStateGloas): Set<PubkeyHex> {
|
|
148
|
+
const result = new Set<PubkeyHex>();
|
|
149
|
+
for (const pendingDeposit of state.pendingDeposits.getAllReadonly()) {
|
|
150
|
+
if (
|
|
151
|
+
isValidDepositSignature(
|
|
152
|
+
config,
|
|
153
|
+
pendingDeposit.pubkey,
|
|
154
|
+
pendingDeposit.withdrawalCredentials,
|
|
155
|
+
pendingDeposit.amount,
|
|
156
|
+
pendingDeposit.signature
|
|
157
|
+
)
|
|
158
|
+
) {
|
|
159
|
+
result.add(toPubkeyHex(pendingDeposit.pubkey));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import {ForkPostGloas, SLOTS_PER_EPOCH, SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params";
|
|
2
|
+
import {BeaconBlock, electra, ssz} from "@lodestar/types";
|
|
3
|
+
import {byteArrayEquals, toRootHex} from "@lodestar/utils";
|
|
4
|
+
import {CachedBeaconStateGloas} from "../types.js";
|
|
5
|
+
import {computeEpochAtSlot} from "../util/epoch.js";
|
|
6
|
+
import {processConsolidationRequest} from "./processConsolidationRequest.js";
|
|
7
|
+
import {getPendingValidatorPubkeys, processDepositRequest} from "./processDepositRequest.js";
|
|
8
|
+
import {processWithdrawalRequest} from "./processWithdrawalRequest.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Process parent execution payload effects as the first step of processBlock.
|
|
12
|
+
*
|
|
13
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/beacon-chain.md#new-process_parent_execution_payload
|
|
14
|
+
*/
|
|
15
|
+
export function processParentExecutionPayload(state: CachedBeaconStateGloas, block: BeaconBlock<ForkPostGloas>): void {
|
|
16
|
+
const bid = block.body.signedExecutionPayloadBid.message;
|
|
17
|
+
const parentBid = state.latestExecutionPayloadBid;
|
|
18
|
+
const requests = block.body.parentExecutionRequests;
|
|
19
|
+
|
|
20
|
+
const isParentBlockFull = byteArrayEquals(bid.parentBlockHash, parentBid.blockHash);
|
|
21
|
+
if (!isParentBlockFull) {
|
|
22
|
+
// Parent was EMPTY -- no execution requests expected
|
|
23
|
+
assertEmptyExecutionRequests(requests);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Parent was FULL -- verify the bid commitment and apply the payload
|
|
28
|
+
const requestsRoot = ssz.electra.ExecutionRequests.hashTreeRoot(requests);
|
|
29
|
+
if (!byteArrayEquals(requestsRoot, parentBid.executionRequestsRoot)) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
`Parent execution requests root mismatch actual=${toRootHex(requestsRoot)} expected=${toRootHex(parentBid.executionRequestsRoot)}`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
applyParentExecutionPayload(state, requests);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Process the parent's execution requests, queue the builder payment, update payload availability,
|
|
40
|
+
* and update the latest block hash.
|
|
41
|
+
*
|
|
42
|
+
* Called from processParentExecutionPayload during block processing, and from the validator during
|
|
43
|
+
* block production before computing withdrawals.
|
|
44
|
+
*
|
|
45
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/beacon-chain.md#new-apply_parent_execution_payload
|
|
46
|
+
*/
|
|
47
|
+
export function applyParentExecutionPayload(state: CachedBeaconStateGloas, requests: electra.ExecutionRequests): void {
|
|
48
|
+
const fork = state.config.getForkSeq(state.slot);
|
|
49
|
+
const parentBid = state.latestExecutionPayloadBid;
|
|
50
|
+
const parentSlot = parentBid.slot;
|
|
51
|
+
const parentEpoch = computeEpochAtSlot(parentSlot);
|
|
52
|
+
const currentEpoch = computeEpochAtSlot(state.slot);
|
|
53
|
+
|
|
54
|
+
// Process execution requests from parent's payload. The execution
|
|
55
|
+
// requests are processed at state.slot (child's slot), not the parent's slot.
|
|
56
|
+
if (requests.deposits.length > 0) {
|
|
57
|
+
const pendingValidatorPubkeys = getPendingValidatorPubkeys(state.config, state);
|
|
58
|
+
for (const deposit of requests.deposits) {
|
|
59
|
+
processDepositRequest(fork, state, deposit, pendingValidatorPubkeys);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
for (const withdrawal of requests.withdrawals) {
|
|
64
|
+
processWithdrawalRequest(fork, state, withdrawal);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
for (const consolidation of requests.consolidations) {
|
|
68
|
+
processConsolidationRequest(state, consolidation);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Settle the builder payment
|
|
72
|
+
if (parentEpoch === currentEpoch) {
|
|
73
|
+
settleBuilderPayment(state, SLOTS_PER_EPOCH + (parentSlot % SLOTS_PER_EPOCH));
|
|
74
|
+
} else if (parentEpoch === currentEpoch - 1) {
|
|
75
|
+
settleBuilderPayment(state, parentSlot % SLOTS_PER_EPOCH);
|
|
76
|
+
} else if (parentBid.value > 0) {
|
|
77
|
+
// Parent is older than the previous epoch, its payment entry has been evicted from
|
|
78
|
+
// builder_pending_payments. Append the withdrawal directly.
|
|
79
|
+
state.builderPendingWithdrawals.push(
|
|
80
|
+
ssz.gloas.BuilderPendingWithdrawal.toViewDU({
|
|
81
|
+
feeRecipient: parentBid.feeRecipient,
|
|
82
|
+
amount: parentBid.value,
|
|
83
|
+
builderIndex: parentBid.builderIndex,
|
|
84
|
+
})
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Update parent payload availability and latest block hash
|
|
89
|
+
state.executionPayloadAvailability.set(parentSlot % SLOTS_PER_HISTORICAL_ROOT, true);
|
|
90
|
+
state.latestBlockHash = parentBid.blockHash;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Settle a builder payment at the given index: move its withdrawal (if any) to the
|
|
95
|
+
* pending withdrawals list and clear the payment slot.
|
|
96
|
+
*
|
|
97
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/beacon-chain.md#new-settle_builder_payment
|
|
98
|
+
*/
|
|
99
|
+
function settleBuilderPayment(state: CachedBeaconStateGloas, paymentIndex: number): void {
|
|
100
|
+
if (paymentIndex >= state.builderPendingPayments.length) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
`Invalid builder payment index paymentIndex=${paymentIndex} limit=${state.builderPendingPayments.length}`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
const payment = state.builderPendingPayments.get(paymentIndex).clone();
|
|
106
|
+
if (payment.withdrawal.amount > 0) {
|
|
107
|
+
state.builderPendingWithdrawals.push(payment.withdrawal);
|
|
108
|
+
}
|
|
109
|
+
state.builderPendingPayments.set(paymentIndex, ssz.gloas.BuilderPendingPayment.defaultViewDU());
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function assertEmptyExecutionRequests(requests: electra.ExecutionRequests): void {
|
|
113
|
+
if (requests.deposits.length !== 0 || requests.withdrawals.length !== 0 || requests.consolidations.length !== 0) {
|
|
114
|
+
throw new Error("Parent execution requests must be empty when parent block is EMPTY");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
convertBuilderIndexToValidatorIndex,
|
|
16
16
|
convertValidatorIndexToBuilderIndex,
|
|
17
17
|
isBuilderIndex,
|
|
18
|
-
isParentBlockFull,
|
|
19
18
|
} from "../util/gloas.js";
|
|
20
19
|
import {
|
|
21
20
|
decreaseBalance,
|
|
@@ -32,8 +31,15 @@ export function processWithdrawals(
|
|
|
32
31
|
payload?: capella.FullOrBlindedExecutionPayload
|
|
33
32
|
): void {
|
|
34
33
|
// Return early if the parent block is empty
|
|
35
|
-
if (fork >= ForkSeq.gloas
|
|
36
|
-
|
|
34
|
+
if (fork >= ForkSeq.gloas) {
|
|
35
|
+
const stateGloas = state as CachedBeaconStateGloas;
|
|
36
|
+
const isParentBlockEmpty = !byteArrayEquals(
|
|
37
|
+
stateGloas.latestBlockHash,
|
|
38
|
+
stateGloas.latestExecutionPayloadBid.blockHash
|
|
39
|
+
);
|
|
40
|
+
if (isParentBlockEmpty) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
// processedBuilderWithdrawalsCount is withdrawals coming from builder payment since gloas (EIP-7732)
|
|
@@ -48,7 +54,9 @@ export function processWithdrawals(
|
|
|
48
54
|
} = getExpectedWithdrawals(fork, state);
|
|
49
55
|
const numWithdrawals = expectedWithdrawals.length;
|
|
50
56
|
|
|
51
|
-
//
|
|
57
|
+
// Pre-gloas verifies the payload's withdrawals against expectedWithdrawals here.
|
|
58
|
+
// Post-gloas, the payload arrives later as an envelope and that consistency check
|
|
59
|
+
// happens in verifyExecutionPayloadEnvelope against state.payloadExpectedWithdrawals.
|
|
52
60
|
if (fork < ForkSeq.gloas) {
|
|
53
61
|
if (payload === undefined) {
|
|
54
62
|
throw Error("payload is required for pre-gloas processWithdrawals");
|
package/src/cache/epochCache.ts
CHANGED
|
@@ -32,10 +32,10 @@ import {
|
|
|
32
32
|
calculateShufflingDecisionRoot,
|
|
33
33
|
computeEpochShuffling,
|
|
34
34
|
} from "../util/epochShuffling.js";
|
|
35
|
+
import {getPtcWindowEpochCacheData} from "../util/gloas.js";
|
|
35
36
|
import {
|
|
36
37
|
computeActivationExitEpoch,
|
|
37
38
|
computeEpochAtSlot,
|
|
38
|
-
computePayloadTimelinessCommitteesForEpoch,
|
|
39
39
|
computeProposers,
|
|
40
40
|
computeSyncPeriodAtEpoch,
|
|
41
41
|
getActivationChurnLimit,
|
|
@@ -56,7 +56,7 @@ import {sumTargetUnslashedBalanceIncrements} from "../util/targetUnslashedBalanc
|
|
|
56
56
|
import {EffectiveBalanceIncrements, getEffectiveBalanceIncrementsWithLen} from "./effectiveBalanceIncrements.js";
|
|
57
57
|
import {EpochTransitionCache} from "./epochTransitionCache.js";
|
|
58
58
|
import {PubkeyCache, createPubkeyCache, syncPubkeys} from "./pubkeyCache.js";
|
|
59
|
-
import {CachedBeaconStateAllForks, CachedBeaconStateFulu} from "./stateCache.js";
|
|
59
|
+
import {CachedBeaconStateAllForks, CachedBeaconStateFulu, CachedBeaconStateGloas} from "./stateCache.js";
|
|
60
60
|
import {
|
|
61
61
|
SyncCommitteeCache,
|
|
62
62
|
SyncCommitteeCacheEmpty,
|
|
@@ -226,11 +226,12 @@ export class EpochCache {
|
|
|
226
226
|
/** TODO: Indexed SyncCommitteeCache */
|
|
227
227
|
nextSyncCommitteeIndexed: SyncCommitteeCache;
|
|
228
228
|
|
|
229
|
-
// TODO GLOAS: See if we need to cache PTC for next epoch
|
|
230
229
|
// PTC for previous epoch, required for slot N block validating slot N-1 attestations
|
|
231
230
|
previousPayloadTimelinessCommittees: Uint32Array[];
|
|
232
231
|
// PTC for current epoch, computed eagerly at epoch transition
|
|
233
232
|
payloadTimelinessCommittees: Uint32Array[];
|
|
233
|
+
// PTC for next epoch, precomputed from the ptc window for future duty serving
|
|
234
|
+
nextPayloadTimelinessCommittees: Uint32Array[];
|
|
234
235
|
|
|
235
236
|
// TODO: Helper stats
|
|
236
237
|
syncPeriod: SyncPeriod;
|
|
@@ -270,6 +271,7 @@ export class EpochCache {
|
|
|
270
271
|
nextSyncCommitteeIndexed: SyncCommitteeCache;
|
|
271
272
|
previousPayloadTimelinessCommittees: Uint32Array[];
|
|
272
273
|
payloadTimelinessCommittees: Uint32Array[];
|
|
274
|
+
nextPayloadTimelinessCommittees: Uint32Array[];
|
|
273
275
|
epoch: Epoch;
|
|
274
276
|
syncPeriod: SyncPeriod;
|
|
275
277
|
}) {
|
|
@@ -301,6 +303,7 @@ export class EpochCache {
|
|
|
301
303
|
this.nextSyncCommitteeIndexed = data.nextSyncCommitteeIndexed;
|
|
302
304
|
this.previousPayloadTimelinessCommittees = data.previousPayloadTimelinessCommittees;
|
|
303
305
|
this.payloadTimelinessCommittees = data.payloadTimelinessCommittees;
|
|
306
|
+
this.nextPayloadTimelinessCommittees = data.nextPayloadTimelinessCommittees;
|
|
304
307
|
this.epoch = data.epoch;
|
|
305
308
|
this.syncPeriod = data.syncPeriod;
|
|
306
309
|
}
|
|
@@ -451,25 +454,13 @@ export class EpochCache {
|
|
|
451
454
|
nextSyncCommitteeIndexed = new SyncCommitteeCacheEmpty();
|
|
452
455
|
}
|
|
453
456
|
|
|
454
|
-
//
|
|
457
|
+
// Copy previous/current epoch PTC slices from state.ptcWindow once, then serve hot-path lookups from epochCtx.
|
|
455
458
|
let previousPayloadTimelinessCommittees: Uint32Array[] = [];
|
|
456
459
|
let payloadTimelinessCommittees: Uint32Array[] = [];
|
|
460
|
+
let nextPayloadTimelinessCommittees: Uint32Array[] = [];
|
|
457
461
|
if (currentEpoch >= config.GLOAS_FORK_EPOCH) {
|
|
458
|
-
payloadTimelinessCommittees =
|
|
459
|
-
state
|
|
460
|
-
currentEpoch,
|
|
461
|
-
currentShuffling.committees,
|
|
462
|
-
effectiveBalanceIncrements
|
|
463
|
-
);
|
|
464
|
-
|
|
465
|
-
if (!isGenesis && previousEpoch >= config.GLOAS_FORK_EPOCH) {
|
|
466
|
-
previousPayloadTimelinessCommittees = computePayloadTimelinessCommitteesForEpoch(
|
|
467
|
-
state,
|
|
468
|
-
previousEpoch,
|
|
469
|
-
previousShuffling.committees,
|
|
470
|
-
effectiveBalanceIncrements
|
|
471
|
-
);
|
|
472
|
-
}
|
|
462
|
+
({previousPayloadTimelinessCommittees, payloadTimelinessCommittees, nextPayloadTimelinessCommittees} =
|
|
463
|
+
getPtcWindowEpochCacheData(state as CachedBeaconStateGloas));
|
|
473
464
|
}
|
|
474
465
|
|
|
475
466
|
// Precompute churnLimit for efficient initiateValidatorExit() during block proposing MUST be recompute everytime the
|
|
@@ -546,6 +537,7 @@ export class EpochCache {
|
|
|
546
537
|
nextSyncCommitteeIndexed,
|
|
547
538
|
previousPayloadTimelinessCommittees,
|
|
548
539
|
payloadTimelinessCommittees,
|
|
540
|
+
nextPayloadTimelinessCommittees,
|
|
549
541
|
epoch: currentEpoch,
|
|
550
542
|
syncPeriod: computeSyncPeriodAtEpoch(currentEpoch),
|
|
551
543
|
});
|
|
@@ -592,6 +584,7 @@ export class EpochCache {
|
|
|
592
584
|
nextSyncCommitteeIndexed: this.nextSyncCommitteeIndexed,
|
|
593
585
|
previousPayloadTimelinessCommittees: this.previousPayloadTimelinessCommittees,
|
|
594
586
|
payloadTimelinessCommittees: this.payloadTimelinessCommittees,
|
|
587
|
+
nextPayloadTimelinessCommittees: this.nextPayloadTimelinessCommittees,
|
|
595
588
|
epoch: this.epoch,
|
|
596
589
|
syncPeriod: this.syncPeriod,
|
|
597
590
|
});
|
|
@@ -695,21 +688,26 @@ export class EpochCache {
|
|
|
695
688
|
/**
|
|
696
689
|
* At fork boundary, this runs post-fork logic and it happens after `upgradeState*` is called.
|
|
697
690
|
*/
|
|
698
|
-
finalProcessEpoch(state: CachedBeaconStateAllForks): void {
|
|
691
|
+
finalProcessEpoch(state: CachedBeaconStateAllForks, epochTransitionCache: EpochTransitionCache): void {
|
|
699
692
|
// this.epoch was updated at the end of afterProcessEpoch()
|
|
700
693
|
const upcomingEpoch = this.epoch;
|
|
701
694
|
const epochAfterUpcoming = upcomingEpoch + 1;
|
|
702
695
|
|
|
703
696
|
this.proposersPrevEpoch = this.proposers;
|
|
704
697
|
if (upcomingEpoch >= this.config.GLOAS_FORK_EPOCH) {
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
698
|
+
if (epochTransitionCache.nextEpochPayloadTimelinessCommittees) {
|
|
699
|
+
// shift arrays from transition cache
|
|
700
|
+
this.previousPayloadTimelinessCommittees = this.payloadTimelinessCommittees;
|
|
701
|
+
this.payloadTimelinessCommittees = this.nextPayloadTimelinessCommittees;
|
|
702
|
+
this.nextPayloadTimelinessCommittees = epochTransitionCache.nextEpochPayloadTimelinessCommittees;
|
|
703
|
+
} else {
|
|
704
|
+
// Fork boundary: processPtcWindow didn't run, read from freshly initialized state.ptcWindow
|
|
705
|
+
({
|
|
706
|
+
previousPayloadTimelinessCommittees: this.previousPayloadTimelinessCommittees,
|
|
707
|
+
payloadTimelinessCommittees: this.payloadTimelinessCommittees,
|
|
708
|
+
nextPayloadTimelinessCommittees: this.nextPayloadTimelinessCommittees,
|
|
709
|
+
} = getPtcWindowEpochCacheData(state as CachedBeaconStateGloas));
|
|
710
|
+
}
|
|
713
711
|
}
|
|
714
712
|
if (upcomingEpoch >= this.config.FULU_FORK_EPOCH) {
|
|
715
713
|
// Populate proposer cache with lookahead from state
|
|
@@ -1034,12 +1032,16 @@ export class EpochCache {
|
|
|
1034
1032
|
throw new Error("Payload Timeliness Committee is not available before gloas fork");
|
|
1035
1033
|
}
|
|
1036
1034
|
|
|
1035
|
+
if (epoch === this.epoch - 1) {
|
|
1036
|
+
return this.previousPayloadTimelinessCommittees[slot % SLOTS_PER_EPOCH];
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1037
1039
|
if (epoch === this.epoch) {
|
|
1038
1040
|
return this.payloadTimelinessCommittees[slot % SLOTS_PER_EPOCH];
|
|
1039
1041
|
}
|
|
1040
1042
|
|
|
1041
|
-
if (epoch === this.epoch
|
|
1042
|
-
return this.
|
|
1043
|
+
if (epoch === this.epoch + 1) {
|
|
1044
|
+
return this.nextPayloadTimelinessCommittees[slot % SLOTS_PER_EPOCH];
|
|
1043
1045
|
}
|
|
1044
1046
|
|
|
1045
1047
|
throw new Error(`Payload Timeliness Committee is not available for slot=${slot}`);
|
|
@@ -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
|
}
|