@lodestar/beacon-node 1.38.0-dev.8475d71f09 → 1.38.0-dev.889b1c4475
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/README.md +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js +5 -3
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +1 -21
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +1 -6
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +10 -131
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts +2 -2
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js +2 -2
- package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +3 -13
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +3 -3
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +3 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/options.d.ts +0 -4
- package/lib/chain/options.d.ts.map +1 -1
- package/lib/chain/options.js +0 -2
- package/lib/chain/options.js.map +1 -1
- package/lib/chain/prepareNextSlot.js +1 -1
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +2 -21
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +24 -87
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/rewards/syncCommitteeRewards.d.ts +2 -2
- package/lib/chain/rewards/syncCommitteeRewards.d.ts.map +1 -1
- package/lib/chain/rewards/syncCommitteeRewards.js +1 -2
- package/lib/chain/rewards/syncCommitteeRewards.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.js +2 -2
- package/lib/chain/validation/attesterSlashing.js.map +1 -1
- package/lib/chain/validation/blobSidecar.d.ts.map +1 -1
- package/lib/chain/validation/blobSidecar.js +2 -2
- package/lib/chain/validation/blobSidecar.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +3 -3
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +2 -2
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/proposerSlashing.js +1 -1
- package/lib/chain/validation/proposerSlashing.js.map +1 -1
- package/lib/chain/validation/signatureSets/contributionAndProof.d.ts +2 -2
- package/lib/chain/validation/signatureSets/contributionAndProof.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/contributionAndProof.js +2 -3
- package/lib/chain/validation/signatureSets/contributionAndProof.js.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommittee.d.ts +2 -2
- package/lib/chain/validation/signatureSets/syncCommittee.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommittee.js +2 -2
- package/lib/chain/validation/signatureSets/syncCommittee.js.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts +2 -2
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js +3 -3
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js.map +1 -1
- package/lib/chain/validation/syncCommittee.js +1 -1
- package/lib/chain/validation/syncCommittee.js.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.d.ts.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.js +4 -3
- package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
- package/lib/chain/validation/voluntaryExit.js +1 -1
- package/lib/chain/validation/voluntaryExit.js.map +1 -1
- package/lib/eth1/index.d.ts +2 -17
- package/lib/eth1/index.d.ts.map +1 -1
- package/lib/eth1/index.js +0 -50
- package/lib/eth1/index.js.map +1 -1
- package/lib/eth1/interface.d.ts +1 -39
- package/lib/eth1/interface.d.ts.map +1 -1
- package/lib/execution/engine/http.d.ts +4 -12
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +4 -12
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/execution/engine/mock.d.ts +2 -6
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +3 -14
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +0 -14
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +0 -44
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/encoding.d.ts.map +1 -1
- package/lib/network/gossip/encoding.js +17 -7
- package/lib/network/gossip/encoding.js.map +1 -1
- package/lib/node/notifier.d.ts.map +1 -1
- package/lib/node/notifier.js +6 -22
- package/lib/node/notifier.js.map +1 -1
- package/lib/sync/backfill/backfill.d.ts.map +1 -1
- package/lib/sync/backfill/backfill.js +4 -2
- package/lib/sync/backfill/backfill.js.map +1 -1
- package/lib/sync/backfill/verify.d.ts +2 -2
- package/lib/sync/backfill/verify.d.ts.map +1 -1
- package/lib/sync/backfill/verify.js +3 -3
- package/lib/sync/backfill/verify.js.map +1 -1
- package/package.json +15 -16
- package/src/api/impl/beacon/state/utils.ts +5 -3
- package/src/chain/blocks/verifyBlock.ts +2 -24
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +11 -170
- package/src/chain/blocks/verifyBlocksSignatures.ts +3 -2
- package/src/chain/chain.ts +3 -14
- package/src/chain/forkChoice/index.ts +2 -3
- package/src/chain/opPools/aggregatedAttestationPool.ts +5 -1
- package/src/chain/options.ts +0 -6
- package/src/chain/prepareNextSlot.ts +1 -1
- package/src/chain/produceBlock/produceBlockBody.ts +25 -120
- package/src/chain/rewards/syncCommitteeRewards.ts +2 -2
- package/src/chain/validation/attesterSlashing.ts +2 -2
- package/src/chain/validation/blobSidecar.ts +10 -2
- package/src/chain/validation/block.ts +2 -3
- package/src/chain/validation/dataColumnSidecar.ts +6 -1
- package/src/chain/validation/proposerSlashing.ts +1 -1
- package/src/chain/validation/signatureSets/contributionAndProof.ts +3 -2
- package/src/chain/validation/signatureSets/syncCommittee.ts +3 -1
- package/src/chain/validation/signatureSets/syncCommitteeSelectionProof.ts +4 -2
- package/src/chain/validation/syncCommittee.ts +1 -1
- package/src/chain/validation/syncCommitteeContributionAndProof.ts +4 -5
- package/src/chain/validation/voluntaryExit.ts +1 -1
- package/src/eth1/index.ts +2 -65
- package/src/eth1/interface.ts +1 -45
- package/src/execution/engine/http.ts +4 -12
- package/src/execution/engine/mock.ts +3 -15
- package/src/metrics/metrics/lodestar.ts +0 -52
- package/src/network/gossip/encoding.ts +19 -7
- package/src/node/notifier.ts +7 -29
- package/src/sync/backfill/backfill.ts +9 -2
- package/src/sync/backfill/verify.ts +8 -2
- package/lib/eth1/eth1MergeBlockTracker.d.ts +0 -65
- package/lib/eth1/eth1MergeBlockTracker.d.ts.map +0 -1
- package/lib/eth1/eth1MergeBlockTracker.js +0 -262
- package/lib/eth1/eth1MergeBlockTracker.js.map +0 -1
- package/src/eth1/eth1MergeBlockTracker.ts +0 -328
|
@@ -6,19 +6,11 @@ import {
|
|
|
6
6
|
LVHValidResponse,
|
|
7
7
|
MaybeValidExecutionStatus,
|
|
8
8
|
ProtoBlock,
|
|
9
|
-
assertValidTerminalPowBlock,
|
|
10
9
|
} from "@lodestar/fork-choice";
|
|
11
|
-
import {ForkSeq
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
isExecutionBlockBodyType,
|
|
15
|
-
isExecutionEnabled,
|
|
16
|
-
isExecutionStateType,
|
|
17
|
-
isMergeTransitionBlock as isMergeTransitionBlockFn,
|
|
18
|
-
} from "@lodestar/state-transition";
|
|
19
|
-
import {Slot, bellatrix, electra} from "@lodestar/types";
|
|
10
|
+
import {ForkSeq} from "@lodestar/params";
|
|
11
|
+
import {CachedBeaconStateAllForks, isExecutionBlockBodyType, isExecutionStateType} from "@lodestar/state-transition";
|
|
12
|
+
import {bellatrix, electra} from "@lodestar/types";
|
|
20
13
|
import {ErrorAborted, Logger, toRootHex} from "@lodestar/utils";
|
|
21
|
-
import {IEth1ForBlockProduction} from "../../eth1/index.js";
|
|
22
14
|
import {ExecutionPayloadStatus, IExecutionEngine} from "../../execution/engine/interface.js";
|
|
23
15
|
import {Metrics} from "../../metrics/metrics.js";
|
|
24
16
|
import {IClock} from "../../util/clock.js";
|
|
@@ -29,7 +21,6 @@ import {IBlockInput} from "./blockInput/types.js";
|
|
|
29
21
|
import {ImportBlockOpts} from "./types.js";
|
|
30
22
|
|
|
31
23
|
export type VerifyBlockExecutionPayloadModules = {
|
|
32
|
-
eth1: IEth1ForBlockProduction;
|
|
33
24
|
executionEngine: IExecutionEngine;
|
|
34
25
|
clock: IClock;
|
|
35
26
|
logger: Logger;
|
|
@@ -44,9 +35,8 @@ export type SegmentExecStatus =
|
|
|
44
35
|
execAborted: null;
|
|
45
36
|
executionStatuses: MaybeValidExecutionStatus[];
|
|
46
37
|
executionTime: number;
|
|
47
|
-
mergeBlockFound: bellatrix.BeaconBlock | null;
|
|
48
38
|
}
|
|
49
|
-
| {execAborted: ExecAbortType; invalidSegmentLVH?: LVHInvalidResponse
|
|
39
|
+
| {execAborted: ExecAbortType; invalidSegmentLVH?: LVHInvalidResponse};
|
|
50
40
|
|
|
51
41
|
type VerifyExecutionErrorResponse =
|
|
52
42
|
| {executionStatus: ExecutionStatus.Invalid; lvhResponse: LVHInvalidResponse; execError: BlockError}
|
|
@@ -72,7 +62,6 @@ export async function verifyBlocksExecutionPayload(
|
|
|
72
62
|
opts: BlockProcessOpts & ImportBlockOpts
|
|
73
63
|
): Promise<SegmentExecStatus> {
|
|
74
64
|
const executionStatuses: MaybeValidExecutionStatus[] = [];
|
|
75
|
-
let mergeBlockFound: bellatrix.BeaconBlock | null = null;
|
|
76
65
|
const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000);
|
|
77
66
|
const lastBlock = blockInputs.at(-1);
|
|
78
67
|
|
|
@@ -96,57 +85,9 @@ export async function verifyBlocksExecutionPayload(
|
|
|
96
85
|
// will either validate or prune invalid blocks
|
|
97
86
|
//
|
|
98
87
|
// We need to track and keep updating if its safe to optimistically import these blocks.
|
|
99
|
-
// The following is how we determine for a block if its safe:
|
|
100
|
-
//
|
|
101
|
-
// (but we need to modify this check for this segment of blocks because it checks if the
|
|
102
|
-
// parent of any block imported in forkchoice is post-merge and currently we could only
|
|
103
|
-
// have blocks[0]'s parent imported in the chain as this is no longer one by one verify +
|
|
104
|
-
// import.)
|
|
105
|
-
//
|
|
106
88
|
//
|
|
107
89
|
// When to import such blocks:
|
|
108
90
|
// From: https://github.com/ethereum/consensus-specs/pull/2844
|
|
109
|
-
// A block MUST NOT be optimistically imported, unless either of the following
|
|
110
|
-
// conditions are met:
|
|
111
|
-
//
|
|
112
|
-
// 1. Parent of the block has execution
|
|
113
|
-
//
|
|
114
|
-
// Since with the sync optimizations, the previous block might not have been in the
|
|
115
|
-
// forkChoice yet, so the below check could fail for safeSlotsToImportOptimistically
|
|
116
|
-
//
|
|
117
|
-
// Luckily, we can depend on the preState0 to see if we are already post merge w.r.t
|
|
118
|
-
// the blocks we are importing.
|
|
119
|
-
//
|
|
120
|
-
// Or in other words if
|
|
121
|
-
// - block status is syncing
|
|
122
|
-
// - and we are not in a post merge world and is parent is not optimistically safe
|
|
123
|
-
// - and we are syncing close to the chain head i.e. clock slot
|
|
124
|
-
// - and parent is optimistically safe
|
|
125
|
-
//
|
|
126
|
-
// then throw error
|
|
127
|
-
//
|
|
128
|
-
//
|
|
129
|
-
// - if we haven't yet imported a post merge ancestor in forkchoice i.e.
|
|
130
|
-
// - and we are syncing close to the clockSlot, i.e. merge Transition could be underway
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
// 2. The current slot (as per the system clock) is at least
|
|
134
|
-
// SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY ahead of the slot of the block being
|
|
135
|
-
// imported.
|
|
136
|
-
// This means that the merge transition could be underway and we can't afford to import
|
|
137
|
-
// a block which is not fully validated as it could affect liveliness of the network.
|
|
138
|
-
//
|
|
139
|
-
//
|
|
140
|
-
// For this segment of blocks:
|
|
141
|
-
// We are optimistically safe with respect to this entire block segment if:
|
|
142
|
-
// - all the blocks are way behind the current slot
|
|
143
|
-
// - or we have already imported a post-merge parent of first block of this chain in forkchoice
|
|
144
|
-
const currentSlot = chain.clock.currentSlot;
|
|
145
|
-
const safeSlotsToImportOptimistically = opts.safeSlotsToImportOptimistically ?? SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY;
|
|
146
|
-
let isOptimisticallySafe =
|
|
147
|
-
parentBlock.executionStatus !== ExecutionStatus.PreMerge ||
|
|
148
|
-
lastBlock.slot + safeSlotsToImportOptimistically < currentSlot;
|
|
149
|
-
|
|
150
91
|
for (let blockIndex = 0; blockIndex < blockInputs.length; blockIndex++) {
|
|
151
92
|
const blockInput = blockInputs[blockIndex];
|
|
152
93
|
// If blocks are invalid in consensus the main promise could resolve before this loop ends.
|
|
@@ -154,14 +95,7 @@ export async function verifyBlocksExecutionPayload(
|
|
|
154
95
|
if (signal.aborted) {
|
|
155
96
|
throw new ErrorAborted("verifyBlockExecutionPayloads");
|
|
156
97
|
}
|
|
157
|
-
const verifyResponse = await verifyBlockExecutionPayload(
|
|
158
|
-
chain,
|
|
159
|
-
blockInput,
|
|
160
|
-
preState0,
|
|
161
|
-
opts,
|
|
162
|
-
isOptimisticallySafe,
|
|
163
|
-
currentSlot
|
|
164
|
-
);
|
|
98
|
+
const verifyResponse = await verifyBlockExecutionPayload(chain, blockInput, preState0);
|
|
165
99
|
|
|
166
100
|
// If execError has happened, then we need to extract the segmentExecStatus and return
|
|
167
101
|
if (verifyResponse.execError !== null) {
|
|
@@ -170,75 +104,7 @@ export async function verifyBlocksExecutionPayload(
|
|
|
170
104
|
|
|
171
105
|
// If we are here then its because executionStatus is one of MaybeValidExecutionStatus
|
|
172
106
|
const {executionStatus} = verifyResponse;
|
|
173
|
-
// It becomes optimistically safe for following blocks if a post-merge block is deemed fit
|
|
174
|
-
// for import. If it would not have been safe verifyBlockExecutionPayload would have
|
|
175
|
-
// returned execError and loop would have been aborted
|
|
176
|
-
if (executionStatus !== ExecutionStatus.PreMerge) {
|
|
177
|
-
isOptimisticallySafe = true;
|
|
178
|
-
}
|
|
179
107
|
executionStatuses.push(executionStatus);
|
|
180
|
-
|
|
181
|
-
const blockBody = blockInput.getBlock().message.body;
|
|
182
|
-
const isMergeTransitionBlock =
|
|
183
|
-
// If the merge block is found, stop the search as the isMergeTransitionBlockFn condition
|
|
184
|
-
// will still evaluate to true for the following blocks leading to errors (while syncing)
|
|
185
|
-
// as the preState0 still belongs to the pre state of the first block on segment
|
|
186
|
-
mergeBlockFound === null &&
|
|
187
|
-
isExecutionStateType(preState0) &&
|
|
188
|
-
isExecutionBlockBodyType(blockBody) &&
|
|
189
|
-
isMergeTransitionBlockFn(preState0, blockBody);
|
|
190
|
-
|
|
191
|
-
// If this is a merge transition block, check to ensure if it references
|
|
192
|
-
// a valid terminal PoW block.
|
|
193
|
-
//
|
|
194
|
-
// However specs define this check to be run inside forkChoice's onBlock
|
|
195
|
-
// (https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/fork-choice.md#on_block)
|
|
196
|
-
// but we perform the check here (as inspired from the lighthouse impl)
|
|
197
|
-
//
|
|
198
|
-
// Reasons:
|
|
199
|
-
// 1. If the block is not valid, we should fail early and not wait till
|
|
200
|
-
// forkChoice import.
|
|
201
|
-
// 2. It makes logical sense to pair it with the block validations and
|
|
202
|
-
// deal it with the external services like eth1 tracker here than
|
|
203
|
-
// in import block
|
|
204
|
-
if (isMergeTransitionBlock) {
|
|
205
|
-
const mergeBlock = blockInput.getBlock().message as bellatrix.BeaconBlock;
|
|
206
|
-
const mergeBlockHash = toRootHex(chain.config.getForkTypes(mergeBlock.slot).BeaconBlock.hashTreeRoot(mergeBlock));
|
|
207
|
-
const powBlockRootHex = toRootHex(mergeBlock.body.executionPayload.parentHash);
|
|
208
|
-
const powBlock = await chain.eth1.getPowBlock(powBlockRootHex).catch((error) => {
|
|
209
|
-
// Lets just warn the user here, errors if any will be reported on
|
|
210
|
-
// `assertValidTerminalPowBlock` checks
|
|
211
|
-
chain.logger.warn(
|
|
212
|
-
"Error fetching terminal PoW block referred in the merge transition block",
|
|
213
|
-
{powBlockHash: powBlockRootHex, mergeBlockHash},
|
|
214
|
-
error
|
|
215
|
-
);
|
|
216
|
-
return null;
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
const powBlockParent =
|
|
220
|
-
powBlock &&
|
|
221
|
-
(await chain.eth1.getPowBlock(powBlock.parentHash).catch((error) => {
|
|
222
|
-
// Lets just warn the user here, errors if any will be reported on
|
|
223
|
-
// `assertValidTerminalPowBlock` checks
|
|
224
|
-
chain.logger.warn(
|
|
225
|
-
"Error fetching parent of the terminal PoW block referred in the merge transition block",
|
|
226
|
-
{powBlockParentHash: powBlock.parentHash, powBlock: powBlockRootHex, mergeBlockHash},
|
|
227
|
-
error
|
|
228
|
-
);
|
|
229
|
-
return null;
|
|
230
|
-
}));
|
|
231
|
-
|
|
232
|
-
// executionStatus will never == ExecutionStatus.PreMerge if it's the mergeBlock. But gotta make TS happy =D
|
|
233
|
-
if (executionStatus === ExecutionStatus.PreMerge) {
|
|
234
|
-
throw Error("Merge block must not have executionStatus == PreMerge");
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
assertValidTerminalPowBlock(chain.config, mergeBlock, {executionStatus, powBlock, powBlockParent});
|
|
238
|
-
// Valid execution payload, but may not be in a valid beacon chain block. Delay printing the POS ACTIVATED banner
|
|
239
|
-
// to the end of the verify block routine, which confirms that this block is fully valid.
|
|
240
|
-
mergeBlockFound = mergeBlock;
|
|
241
|
-
}
|
|
242
108
|
}
|
|
243
109
|
|
|
244
110
|
const executionTime = Date.now();
|
|
@@ -265,7 +131,6 @@ export async function verifyBlocksExecutionPayload(
|
|
|
265
131
|
execAborted: null,
|
|
266
132
|
executionStatuses,
|
|
267
133
|
executionTime,
|
|
268
|
-
mergeBlockFound,
|
|
269
134
|
};
|
|
270
135
|
}
|
|
271
136
|
|
|
@@ -275,28 +140,18 @@ export async function verifyBlocksExecutionPayload(
|
|
|
275
140
|
export async function verifyBlockExecutionPayload(
|
|
276
141
|
chain: VerifyBlockExecutionPayloadModules,
|
|
277
142
|
blockInput: IBlockInput,
|
|
278
|
-
preState0: CachedBeaconStateAllForks
|
|
279
|
-
opts: BlockProcessOpts,
|
|
280
|
-
isOptimisticallySafe: boolean,
|
|
281
|
-
currentSlot: Slot
|
|
143
|
+
preState0: CachedBeaconStateAllForks
|
|
282
144
|
): Promise<VerifyBlockExecutionResponse> {
|
|
283
145
|
const block = blockInput.getBlock();
|
|
284
146
|
/** Not null if execution is enabled */
|
|
285
147
|
const executionPayloadEnabled =
|
|
286
|
-
isExecutionStateType(preState0) &&
|
|
287
|
-
isExecutionBlockBodyType(block.message.body) &&
|
|
288
|
-
// Safe to use with a state previous to block's preState. isMergeComplete can only transition from false to true.
|
|
289
|
-
// - If preState0 is after merge block: condition is true, and will always be true
|
|
290
|
-
// - If preState0 is before merge block: the block could lie but then state transition function will throw above
|
|
291
|
-
// It is kinda safe to send non-trusted payloads to the execution client because at most it can trigger sync.
|
|
292
|
-
// TODO: If this becomes a problem, do some basic verification beforehand, like checking the proposer signature.
|
|
293
|
-
isExecutionEnabled(preState0, block.message)
|
|
148
|
+
isExecutionStateType(preState0) && isExecutionBlockBodyType(block.message.body)
|
|
294
149
|
? block.message.body.executionPayload
|
|
295
150
|
: null;
|
|
296
151
|
|
|
297
152
|
if (!executionPayloadEnabled) {
|
|
298
|
-
//
|
|
299
|
-
return {executionStatus: ExecutionStatus.PreMerge, execError: null}
|
|
153
|
+
// Pre-merge block, no execution payload to verify
|
|
154
|
+
return {executionStatus: ExecutionStatus.PreMerge, lvhResponse: undefined, execError: null};
|
|
300
155
|
}
|
|
301
156
|
|
|
302
157
|
// TODO: Handle better notifyNewPayload() returning error is syncing
|
|
@@ -343,24 +198,10 @@ export async function verifyBlockExecutionPayload(
|
|
|
343
198
|
}
|
|
344
199
|
|
|
345
200
|
// Accepted and Syncing have the same treatment, as final validation of block is pending
|
|
201
|
+
// Post-merge, we're always safe to optimistically import
|
|
346
202
|
case ExecutionPayloadStatus.ACCEPTED:
|
|
347
|
-
case ExecutionPayloadStatus.SYNCING:
|
|
348
|
-
// Check if the entire segment was deemed safe or, this block specifically itself if not in
|
|
349
|
-
// the safeSlotsToImportOptimistically window of current slot, then we can import else
|
|
350
|
-
// we need to throw and not import his block
|
|
351
|
-
const safeSlotsToImportOptimistically =
|
|
352
|
-
opts.safeSlotsToImportOptimistically ?? SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY;
|
|
353
|
-
if (!isOptimisticallySafe && blockInput.slot + safeSlotsToImportOptimistically >= currentSlot) {
|
|
354
|
-
const execError = new BlockError(block, {
|
|
355
|
-
code: BlockErrorCode.EXECUTION_ENGINE_ERROR,
|
|
356
|
-
execStatus: ExecutionPayloadStatus.UNSAFE_OPTIMISTIC_STATUS,
|
|
357
|
-
errorMessage: `not safe to import ${execResult.status} payload within ${opts.safeSlotsToImportOptimistically} of currentSlot`,
|
|
358
|
-
});
|
|
359
|
-
return {executionStatus: null, execError} as VerifyBlockExecutionResponse;
|
|
360
|
-
}
|
|
361
|
-
|
|
203
|
+
case ExecutionPayloadStatus.SYNCING:
|
|
362
204
|
return {executionStatus: ExecutionStatus.Syncing, execError: null};
|
|
363
|
-
}
|
|
364
205
|
|
|
365
206
|
// If the block has is not valid, or it referenced an invalid terminal block then the
|
|
366
207
|
// block is invalid, however it has no bearing on any forkChoice cleanup
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {CachedBeaconStateAllForks, getBlockSignatureSets} from "@lodestar/state-transition";
|
|
1
|
+
import {CachedBeaconStateAllForks, Index2PubkeyCache, getBlockSignatureSets} from "@lodestar/state-transition";
|
|
2
2
|
import {IndexedAttestation, SignedBeaconBlock} from "@lodestar/types";
|
|
3
3
|
import {Logger} from "@lodestar/utils";
|
|
4
4
|
import {Metrics} from "../../metrics/metrics.js";
|
|
@@ -15,6 +15,7 @@ import {ImportBlockOpts} from "./types.js";
|
|
|
15
15
|
* Since all data is known in advance all signatures are verified at once in parallel.
|
|
16
16
|
*/
|
|
17
17
|
export async function verifyBlocksSignatures(
|
|
18
|
+
index2pubkey: Index2PubkeyCache,
|
|
18
19
|
bls: IBlsVerifier,
|
|
19
20
|
logger: Logger,
|
|
20
21
|
metrics: Metrics | null,
|
|
@@ -38,7 +39,7 @@ export async function verifyBlocksSignatures(
|
|
|
38
39
|
: //
|
|
39
40
|
// Verify signatures per block to track which block is invalid
|
|
40
41
|
bls.verifySignatureSets(
|
|
41
|
-
getBlockSignatureSets(preState0, block, indexedAttestationsByBlock[i], {
|
|
42
|
+
getBlockSignatureSets(index2pubkey, preState0, block, indexedAttestationsByBlock[i], {
|
|
42
43
|
skipProposerSignature: opts.validProposerSignature,
|
|
43
44
|
})
|
|
44
45
|
);
|
package/src/chain/chain.ts
CHANGED
|
@@ -3,7 +3,7 @@ import {PrivateKey} from "@libp2p/interface";
|
|
|
3
3
|
import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
|
|
4
4
|
import {CompositeTypeAny, TreeView, Type} from "@chainsafe/ssz";
|
|
5
5
|
import {BeaconConfig} from "@lodestar/config";
|
|
6
|
-
import {CheckpointWithHex,
|
|
6
|
+
import {CheckpointWithHex, IForkChoice, ProtoBlock, UpdateHeadOpt} from "@lodestar/fork-choice";
|
|
7
7
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
8
8
|
import {EFFECTIVE_BALANCE_INCREMENT, GENESIS_SLOT, SLOTS_PER_EPOCH, isForkPostElectra} from "@lodestar/params";
|
|
9
9
|
import {
|
|
@@ -757,7 +757,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
757
757
|
RegenCaller.produceBlock
|
|
758
758
|
);
|
|
759
759
|
const proposerIndex = state.epochCtx.getBeaconProposer(slot);
|
|
760
|
-
const proposerPubKey =
|
|
760
|
+
const proposerPubKey = this.index2pubkey[proposerIndex].toBytes();
|
|
761
761
|
|
|
762
762
|
const {body, produceResult, executionPayloadValue, shouldOverrideBuilder} = await produceBlockBody.call(
|
|
763
763
|
this,
|
|
@@ -1177,17 +1177,6 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1177
1177
|
this.seenAggregatedAttestations.prune(epoch);
|
|
1178
1178
|
this.seenBlockAttesters.prune(epoch);
|
|
1179
1179
|
this.beaconProposerCache.prune(epoch);
|
|
1180
|
-
|
|
1181
|
-
// Poll for merge block in the background to speed-up block production. Only if:
|
|
1182
|
-
// - after BELLATRIX_FORK_EPOCH
|
|
1183
|
-
// - Beacon node synced
|
|
1184
|
-
// - head state not isMergeTransitionComplete
|
|
1185
|
-
if (this.config.BELLATRIX_FORK_EPOCH - epoch < 1) {
|
|
1186
|
-
const head = this.forkChoice.getHead();
|
|
1187
|
-
if (epoch - computeEpochAtSlot(head.slot) < 5 && head.executionStatus === ExecutionStatus.PreMerge) {
|
|
1188
|
-
this.eth1.startPollingMergeBlock();
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
1180
|
}
|
|
1192
1181
|
|
|
1193
1182
|
protected onNewHead(head: ProtoBlock): void {
|
|
@@ -1372,6 +1361,6 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1372
1361
|
|
|
1373
1362
|
preState = processSlots(preState, block.slot); // Dial preState's slot to block.slot
|
|
1374
1363
|
|
|
1375
|
-
return computeSyncCommitteeRewards(block, preState.clone(), validatorIds);
|
|
1364
|
+
return computeSyncCommitteeRewards(this.index2pubkey, block, preState.clone(), validatorIds);
|
|
1376
1365
|
}
|
|
1377
1366
|
}
|
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
getBlockRootAtSlot,
|
|
19
19
|
getEffectiveBalanceIncrementsZeroInactive,
|
|
20
20
|
isExecutionStateType,
|
|
21
|
-
isMergeTransitionComplete,
|
|
22
21
|
} from "@lodestar/state-transition";
|
|
23
22
|
import {Slot, ssz} from "@lodestar/types";
|
|
24
23
|
import {Logger, toRootHex} from "@lodestar/utils";
|
|
@@ -135,7 +134,7 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
135
134
|
unrealizedFinalizedEpoch: finalizedCheckpoint.epoch,
|
|
136
135
|
unrealizedFinalizedRoot: toRootHex(finalizedCheckpoint.root),
|
|
137
136
|
|
|
138
|
-
...(isExecutionStateType(state)
|
|
137
|
+
...(isExecutionStateType(state)
|
|
139
138
|
? {
|
|
140
139
|
executionPayloadBlockHash: toRootHex(state.latestExecutionPayloadHeader.blockHash),
|
|
141
140
|
executionPayloadNumber: state.latestExecutionPayloadHeader.blockNumber,
|
|
@@ -216,7 +215,7 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
216
215
|
unrealizedFinalizedEpoch: finalizedCheckpoint.epoch,
|
|
217
216
|
unrealizedFinalizedRoot: toRootHex(finalizedCheckpoint.root),
|
|
218
217
|
|
|
219
|
-
...(isExecutionStateType(unfinalizedState)
|
|
218
|
+
...(isExecutionStateType(unfinalizedState)
|
|
220
219
|
? {
|
|
221
220
|
executionPayloadBlockHash: toRootHex(unfinalizedState.latestExecutionPayloadHeader.blockHash),
|
|
222
221
|
executionPayloadNumber: unfinalizedState.latestExecutionPayloadHeader.blockNumber,
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
import {
|
|
23
23
|
CachedBeaconStateAllForks,
|
|
24
24
|
CachedBeaconStateAltair,
|
|
25
|
+
CachedBeaconStateGloas,
|
|
25
26
|
CachedBeaconStatePhase0,
|
|
26
27
|
EffectiveBalanceIncrements,
|
|
27
28
|
RootCache,
|
|
@@ -486,7 +487,10 @@ export class AggregatedAttestationPool {
|
|
|
486
487
|
consolidation.attData,
|
|
487
488
|
inclusionDistance,
|
|
488
489
|
stateEpoch,
|
|
489
|
-
rootCache
|
|
490
|
+
rootCache,
|
|
491
|
+
ForkSeq[fork] >= ForkSeq.gloas
|
|
492
|
+
? (state as CachedBeaconStateGloas).executionPayloadAvailability.toBoolArray()
|
|
493
|
+
: null
|
|
490
494
|
);
|
|
491
495
|
|
|
492
496
|
const weight =
|
package/src/chain/options.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY} from "@lodestar/params";
|
|
2
1
|
import {defaultOptions as defaultValidatorOptions} from "@lodestar/validator";
|
|
3
2
|
import {DEFAULT_ARCHIVE_MODE} from "./archiveStore/constants.js";
|
|
4
3
|
import {ArchiveMode, ArchiveStoreOpts} from "./archiveStore/interface.js";
|
|
@@ -56,10 +55,6 @@ export type BlockProcessOpts = {
|
|
|
56
55
|
* Will double processing times. Use only for debugging purposes.
|
|
57
56
|
*/
|
|
58
57
|
disableBlsBatchVerify?: boolean;
|
|
59
|
-
/**
|
|
60
|
-
* Override SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY
|
|
61
|
-
*/
|
|
62
|
-
safeSlotsToImportOptimistically?: number;
|
|
63
58
|
/**
|
|
64
59
|
* Assert progressive balances the same to EpochTransitionCache
|
|
65
60
|
*/
|
|
@@ -109,7 +104,6 @@ export const defaultChainOptions: IChainOptions = {
|
|
|
109
104
|
proposerBoost: true,
|
|
110
105
|
proposerBoostReorg: true,
|
|
111
106
|
computeUnrealized: true,
|
|
112
|
-
safeSlotsToImportOptimistically: SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY,
|
|
113
107
|
suggestedFeeRecipient: defaultValidatorOptions.suggestedFeeRecipient,
|
|
114
108
|
serveHistoricalState: false,
|
|
115
109
|
assertCorrectProgressiveBalances: false,
|
|
@@ -197,7 +197,7 @@ export class PrepareNextSlotScheduler {
|
|
|
197
197
|
this.chain.opts.emitPayloadAttributes === true &&
|
|
198
198
|
this.chain.emitter.listenerCount(routes.events.EventType.payloadAttributes)
|
|
199
199
|
) {
|
|
200
|
-
const data =
|
|
200
|
+
const data = getPayloadAttributesForSSE(fork as ForkPostBellatrix, this.chain, {
|
|
201
201
|
prepareState: updatedPrepareState,
|
|
202
202
|
prepareSlot,
|
|
203
203
|
parentBlockRoot: fromHex(headRoot),
|
|
@@ -17,10 +17,8 @@ import {
|
|
|
17
17
|
CachedBeaconStateCapella,
|
|
18
18
|
CachedBeaconStateExecutions,
|
|
19
19
|
computeTimeAtSlot,
|
|
20
|
-
getCurrentEpoch,
|
|
21
20
|
getExpectedWithdrawals,
|
|
22
21
|
getRandaoMix,
|
|
23
|
-
isMergeTransitionComplete,
|
|
24
22
|
} from "@lodestar/state-transition";
|
|
25
23
|
import {
|
|
26
24
|
BLSPubkey,
|
|
@@ -44,12 +42,9 @@ import {
|
|
|
44
42
|
deneb,
|
|
45
43
|
electra,
|
|
46
44
|
fulu,
|
|
47
|
-
ssz,
|
|
48
|
-
sszTypesFor,
|
|
49
45
|
} from "@lodestar/types";
|
|
50
46
|
import {Logger, sleep, toHex, toPubkeyHex, toRootHex} from "@lodestar/utils";
|
|
51
|
-
import {
|
|
52
|
-
import {IEth1ForBlockProduction} from "../../eth1/index.js";
|
|
47
|
+
import {ZERO_HASH_HEX} from "../../constants/index.js";
|
|
53
48
|
import {numToQuantity} from "../../eth1/provider/utils.js";
|
|
54
49
|
import {
|
|
55
50
|
IExecutionBuilder,
|
|
@@ -337,14 +332,6 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
337
332
|
feeRecipient
|
|
338
333
|
);
|
|
339
334
|
|
|
340
|
-
if (prepareRes.isPremerge) {
|
|
341
|
-
return {
|
|
342
|
-
...prepareRes,
|
|
343
|
-
executionPayload: sszTypesFor(fork).ExecutionPayload.defaultValue(),
|
|
344
|
-
executionPayloadValue: BigInt(0),
|
|
345
|
-
};
|
|
346
|
-
}
|
|
347
|
-
|
|
348
335
|
const {prepType, payloadId} = prepareRes;
|
|
349
336
|
Object.assign(logMeta, {executionPayloadPrepType: prepType});
|
|
350
337
|
|
|
@@ -366,37 +353,14 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
366
353
|
|
|
367
354
|
return {...prepareRes, ...payloadRes};
|
|
368
355
|
})().catch((e) => {
|
|
369
|
-
// catch payload fetch here, because there is still a recovery path possible if we
|
|
370
|
-
// are pre-merge. We don't care the same for builder segment as the execution block
|
|
371
|
-
// will takeover if the builder flow was activated and errors
|
|
372
356
|
this.metrics?.blockPayload.payloadFetchErrors.inc();
|
|
373
|
-
|
|
374
|
-
if (!isMergeTransitionComplete(currentState as CachedBeaconStateBellatrix)) {
|
|
375
|
-
this.logger?.warn(
|
|
376
|
-
"Fetch payload from the execution failed, however since we are still pre-merge proceeding with an empty one.",
|
|
377
|
-
{},
|
|
378
|
-
e as Error
|
|
379
|
-
);
|
|
380
|
-
// ok we don't have an execution payload here, so we can assign an empty one
|
|
381
|
-
// if pre-merge
|
|
382
|
-
return {
|
|
383
|
-
isPremerge: true as const,
|
|
384
|
-
executionPayload: sszTypesFor(fork).ExecutionPayload.defaultValue(),
|
|
385
|
-
executionPayloadValue: BigInt(0),
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
// since merge transition is complete, we need a valid payload even if with an
|
|
389
|
-
// empty (transactions) one. defaultValue isn't gonna cut it!
|
|
390
357
|
throw e;
|
|
391
358
|
});
|
|
392
359
|
|
|
393
360
|
const [engineRes, commonBlockBody] = await Promise.all([enginePromise, commonBlockBodyPromise]);
|
|
394
361
|
blockBody = Object.assign({}, commonBlockBody) as AssembledBodyType<BlockType.Blinded>;
|
|
395
362
|
|
|
396
|
-
|
|
397
|
-
(blockBody as BeaconBlockBody<ForkPostBellatrix & ForkPreGloas>).executionPayload = engineRes.executionPayload;
|
|
398
|
-
executionPayloadValue = engineRes.executionPayloadValue;
|
|
399
|
-
} else {
|
|
363
|
+
{
|
|
400
364
|
const {prepType, payloadId, executionPayload, blobsBundle, executionRequests} = engineRes;
|
|
401
365
|
shouldOverrideBuilder = engineRes.shouldOverrideBuilder;
|
|
402
366
|
|
|
@@ -504,15 +468,10 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
504
468
|
}
|
|
505
469
|
|
|
506
470
|
/**
|
|
507
|
-
* Produce ExecutionPayload for
|
|
508
|
-
*
|
|
509
|
-
* Expects `eth1MergeBlockFinder` to be actively searching for blocks well in advance to being called.
|
|
510
|
-
*
|
|
511
|
-
* @returns PayloadId = pow block found, null = pow NOT found
|
|
471
|
+
* Produce ExecutionPayload for post-merge.
|
|
512
472
|
*/
|
|
513
473
|
export async function prepareExecutionPayload(
|
|
514
474
|
chain: {
|
|
515
|
-
eth1: IEth1ForBlockProduction;
|
|
516
475
|
executionEngine: IExecutionEngine;
|
|
517
476
|
config: ChainForkConfig;
|
|
518
477
|
},
|
|
@@ -523,14 +482,8 @@ export async function prepareExecutionPayload(
|
|
|
523
482
|
finalizedBlockHash: RootHex,
|
|
524
483
|
state: CachedBeaconStateExecutions,
|
|
525
484
|
suggestedFeeRecipient: string
|
|
526
|
-
): Promise<{
|
|
527
|
-
const
|
|
528
|
-
if (parentHashRes.isPremerge) {
|
|
529
|
-
// Return null only if the execution is pre-merge
|
|
530
|
-
return {isPremerge: true};
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
const {parentHash} = parentHashRes;
|
|
485
|
+
): Promise<{prepType: PayloadPreparationType; payloadId: PayloadId}> {
|
|
486
|
+
const parentHash = state.latestExecutionPayloadHeader.blockHash;
|
|
534
487
|
const timestamp = computeTimeAtSlot(chain.config, state.slot, state.genesisTime);
|
|
535
488
|
const prevRandao = getRandaoMix(state, state.epochCtx.epoch);
|
|
536
489
|
|
|
@@ -586,12 +539,11 @@ export async function prepareExecutionPayload(
|
|
|
586
539
|
// We are only returning payloadId here because prepareExecutionPayload is also called from
|
|
587
540
|
// prepareNextSlot, which is an advance call to execution engine to start building payload
|
|
588
541
|
// Actual payload isn't produced till getPayload is called.
|
|
589
|
-
return {
|
|
542
|
+
return {payloadId, prepType};
|
|
590
543
|
}
|
|
591
544
|
|
|
592
545
|
async function prepareExecutionPayloadHeader(
|
|
593
546
|
chain: {
|
|
594
|
-
eth1: IEth1ForBlockProduction;
|
|
595
547
|
executionBuilder?: IExecutionBuilder;
|
|
596
548
|
config: ChainForkConfig;
|
|
597
549
|
},
|
|
@@ -608,53 +560,13 @@ async function prepareExecutionPayloadHeader(
|
|
|
608
560
|
throw Error("executionBuilder required");
|
|
609
561
|
}
|
|
610
562
|
|
|
611
|
-
const
|
|
612
|
-
if (parentHashRes.isPremerge) {
|
|
613
|
-
throw Error("External builder disabled pre-merge");
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
const {parentHash} = parentHashRes;
|
|
563
|
+
const parentHash = state.latestExecutionPayloadHeader.blockHash;
|
|
617
564
|
return chain.executionBuilder.getHeader(fork, state.slot, parentHash, proposerPubKey);
|
|
618
565
|
}
|
|
619
566
|
|
|
620
|
-
export
|
|
621
|
-
chain: {
|
|
622
|
-
eth1: IEth1ForBlockProduction;
|
|
623
|
-
config: ChainForkConfig;
|
|
624
|
-
},
|
|
625
|
-
state: CachedBeaconStateExecutions
|
|
626
|
-
): Promise<{isPremerge: true} | {isPremerge: false; parentHash: Root}> {
|
|
627
|
-
// Use different POW block hash parent for block production based on merge status.
|
|
628
|
-
// Returned value of null == using an empty ExecutionPayload value
|
|
629
|
-
if (isMergeTransitionComplete(state)) {
|
|
630
|
-
// Post-merge, normal payload
|
|
631
|
-
return {isPremerge: false, parentHash: state.latestExecutionPayloadHeader.blockHash};
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
if (
|
|
635
|
-
!ssz.Root.equals(chain.config.TERMINAL_BLOCK_HASH, ZERO_HASH) &&
|
|
636
|
-
getCurrentEpoch(state) < chain.config.TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
|
|
637
|
-
) {
|
|
638
|
-
throw new Error(
|
|
639
|
-
`InvalidMergeTBH epoch: expected >= ${
|
|
640
|
-
chain.config.TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
|
|
641
|
-
}, actual: ${getCurrentEpoch(state)}`
|
|
642
|
-
);
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
const terminalPowBlockHash = await chain.eth1.getTerminalPowBlock();
|
|
646
|
-
if (terminalPowBlockHash === null) {
|
|
647
|
-
// Pre-merge, no prepare payload call is needed
|
|
648
|
-
return {isPremerge: true};
|
|
649
|
-
}
|
|
650
|
-
// Signify merge via producing on top of the last PoW block
|
|
651
|
-
return {isPremerge: false, parentHash: terminalPowBlockHash};
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
export async function getPayloadAttributesForSSE(
|
|
567
|
+
export function getPayloadAttributesForSSE(
|
|
655
568
|
fork: ForkPostBellatrix,
|
|
656
569
|
chain: {
|
|
657
|
-
eth1: IEth1ForBlockProduction;
|
|
658
570
|
config: ChainForkConfig;
|
|
659
571
|
},
|
|
660
572
|
{
|
|
@@ -663,30 +575,23 @@ export async function getPayloadAttributesForSSE(
|
|
|
663
575
|
parentBlockRoot,
|
|
664
576
|
feeRecipient,
|
|
665
577
|
}: {prepareState: CachedBeaconStateExecutions; prepareSlot: Slot; parentBlockRoot: Root; feeRecipient: string}
|
|
666
|
-
):
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
parentBlockHash: parentHash,
|
|
684
|
-
payloadAttributes,
|
|
685
|
-
};
|
|
686
|
-
return ssePayloadAttributes;
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
throw Error("The execution is still pre-merge");
|
|
578
|
+
): SSEPayloadAttributes {
|
|
579
|
+
const parentHash = prepareState.latestExecutionPayloadHeader.blockHash;
|
|
580
|
+
const payloadAttributes = preparePayloadAttributes(fork, chain, {
|
|
581
|
+
prepareState,
|
|
582
|
+
prepareSlot,
|
|
583
|
+
parentBlockRoot,
|
|
584
|
+
feeRecipient,
|
|
585
|
+
});
|
|
586
|
+
const ssePayloadAttributes: SSEPayloadAttributes = {
|
|
587
|
+
proposerIndex: prepareState.epochCtx.getBeaconProposer(prepareSlot),
|
|
588
|
+
proposalSlot: prepareSlot,
|
|
589
|
+
parentBlockNumber: prepareState.latestExecutionPayloadHeader.blockNumber,
|
|
590
|
+
parentBlockRoot,
|
|
591
|
+
parentBlockHash: parentHash,
|
|
592
|
+
payloadAttributes,
|
|
593
|
+
};
|
|
594
|
+
return ssePayloadAttributes;
|
|
690
595
|
}
|
|
691
596
|
|
|
692
597
|
function preparePayloadAttributes(
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ForkName, SYNC_COMMITTEE_SIZE} from "@lodestar/params";
|
|
3
|
-
import {CachedBeaconStateAllForks, CachedBeaconStateAltair} from "@lodestar/state-transition";
|
|
3
|
+
import {CachedBeaconStateAllForks, CachedBeaconStateAltair, Index2PubkeyCache} from "@lodestar/state-transition";
|
|
4
4
|
import {BeaconBlock, ValidatorIndex, altair} from "@lodestar/types";
|
|
5
5
|
|
|
6
6
|
export type SyncCommitteeRewards = routes.beacon.SyncCommitteeRewards;
|
|
7
7
|
type BalanceRecord = {val: number}; // Use val for convenient way to increment/decrement balance
|
|
8
8
|
|
|
9
9
|
export async function computeSyncCommitteeRewards(
|
|
10
|
+
index2pubkey: Index2PubkeyCache,
|
|
10
11
|
block: BeaconBlock,
|
|
11
12
|
preState: CachedBeaconStateAllForks,
|
|
12
13
|
validatorIds: (ValidatorIndex | string)[] = []
|
|
@@ -18,7 +19,6 @@ export async function computeSyncCommitteeRewards(
|
|
|
18
19
|
|
|
19
20
|
const altairBlock = block as altair.BeaconBlock;
|
|
20
21
|
const preStateAltair = preState as CachedBeaconStateAltair;
|
|
21
|
-
const {index2pubkey} = preStateAltair.epochCtx;
|
|
22
22
|
|
|
23
23
|
// Bound syncCommitteeValidatorIndices in case it goes beyond SYNC_COMMITTEE_SIZE just to be safe
|
|
24
24
|
const syncCommitteeValidatorIndices = preStateAltair.epochCtx.currentSyncCommitteeIndexed.validatorIndices.slice(
|