@lodestar/beacon-node 1.41.0-dev.f2caa915ab → 1.41.0-dev.f36ec31497
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/api/impl/beacon/blocks/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/blocks/index.js +3 -2
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +26 -10
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/utils/updateBackfillRange.js +1 -1
- package/lib/chain/archiveStore/utils/updateBackfillRange.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +26 -3
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.js +4 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
- package/lib/chain/chain.js +6 -6
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +3 -3
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +2 -2
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +30 -24
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +1 -2
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +4 -1
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +5 -1
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/validation/aggregateAndProof.js +1 -1
- package/lib/chain/validation/aggregateAndProof.js.map +1 -1
- package/lib/chain/validation/attestation.js +3 -3
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
- package/lib/chain/validation/attesterSlashing.js +8 -1
- package/lib/chain/validation/attesterSlashing.js.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 +6 -3
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +1 -1
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +1 -2
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +4 -4
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +1 -2
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +1 -0
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.js +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
- package/package.json +26 -26
- package/src/api/impl/beacon/blocks/index.ts +3 -2
- package/src/api/impl/validator/index.ts +26 -12
- package/src/chain/archiveStore/utils/updateBackfillRange.ts +1 -1
- package/src/chain/blocks/importBlock.ts +34 -3
- package/src/chain/blocks/verifyBlocksSanityChecks.ts +7 -2
- package/src/chain/chain.ts +6 -6
- package/src/chain/emitter.ts +3 -3
- package/src/chain/errors/executionPayloadEnvelope.ts +6 -2
- package/src/chain/forkChoice/index.ts +39 -21
- package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
- package/src/chain/produceBlock/produceBlockBody.ts +1 -2
- package/src/chain/regen/queued.ts +7 -2
- package/src/chain/regen/regen.ts +8 -2
- package/src/chain/validation/aggregateAndProof.ts +1 -1
- package/src/chain/validation/attestation.ts +3 -3
- package/src/chain/validation/attesterSlashing.ts +9 -0
- package/src/chain/validation/blobSidecar.ts +2 -2
- package/src/chain/validation/block.ts +9 -4
- package/src/chain/validation/dataColumnSidecar.ts +1 -1
- package/src/chain/validation/executionPayloadBid.ts +1 -2
- package/src/chain/validation/executionPayloadEnvelope.ts +4 -4
- package/src/chain/validation/payloadAttestationMessage.ts +1 -2
- package/src/network/processor/gossipHandlers.ts +5 -0
- package/src/network/reqresp/handlers/blobSidecarsByRoot.ts +1 -1
- package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +1 -1
|
@@ -4,9 +4,11 @@ import {
|
|
|
4
4
|
ForkChoice,
|
|
5
5
|
ForkChoiceStore,
|
|
6
6
|
JustifiedBalancesGetter,
|
|
7
|
+
PayloadStatus,
|
|
7
8
|
ProtoArray,
|
|
8
9
|
ProtoBlock,
|
|
9
10
|
ForkChoiceOpts as RawForkChoiceOpts,
|
|
11
|
+
getCheckpointPayloadStatus,
|
|
10
12
|
} from "@lodestar/fork-choice";
|
|
11
13
|
import {ZERO_HASH_HEX} from "@lodestar/params";
|
|
12
14
|
import {
|
|
@@ -104,6 +106,14 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
104
106
|
// production code use ForkChoice constructor directly
|
|
105
107
|
const forkchoiceConstructor = opts.forkchoiceConstructor ?? ForkChoice;
|
|
106
108
|
|
|
109
|
+
const isForkPostGloas = (state as CachedBeaconStateGloas).latestBlockHash !== undefined;
|
|
110
|
+
|
|
111
|
+
// Determine justified checkpoint payload status
|
|
112
|
+
const justifiedPayloadStatus = getCheckpointPayloadStatus(state, justifiedCheckpoint.epoch);
|
|
113
|
+
|
|
114
|
+
// Determine finalized checkpoint payload status
|
|
115
|
+
const finalizedPayloadStatus = getCheckpointPayloadStatus(state, finalizedCheckpoint.epoch);
|
|
116
|
+
|
|
107
117
|
return new forkchoiceConstructor(
|
|
108
118
|
config,
|
|
109
119
|
|
|
@@ -113,6 +123,8 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
113
123
|
finalizedCheckpoint,
|
|
114
124
|
justifiedBalances,
|
|
115
125
|
justifiedBalancesGetter,
|
|
126
|
+
justifiedPayloadStatus,
|
|
127
|
+
finalizedPayloadStatus,
|
|
116
128
|
{
|
|
117
129
|
onJustified: (cp) => emitter.emit(ChainEvent.forkChoiceJustified, cp),
|
|
118
130
|
onFinalized: (cp) => emitter.emit(ChainEvent.forkChoiceFinalized, cp),
|
|
@@ -145,15 +157,12 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
145
157
|
: {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
|
|
146
158
|
|
|
147
159
|
dataAvailabilityStatus: DataAvailabilityStatus.PreData,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
builderIndex: (state as CachedBeaconStateGloas).latestExecutionPayloadBid.builderIndex,
|
|
155
|
-
blockHashHex: toRootHex((state as CachedBeaconStateGloas).latestExecutionPayloadBid.blockHash),
|
|
156
|
-
}),
|
|
160
|
+
payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL, // TODO GLOAS: Post-gloas how do we know if the checkpoint payload is FULL or EMPTY?
|
|
161
|
+
builderIndex: isForkPostGloas ? (state as CachedBeaconStateGloas).latestExecutionPayloadBid.builderIndex : null,
|
|
162
|
+
blockHashFromBid: isForkPostGloas
|
|
163
|
+
? toRootHex((state as CachedBeaconStateGloas).latestExecutionPayloadBid.blockHash)
|
|
164
|
+
: null,
|
|
165
|
+
parentBlockHash: isForkPostGloas ? toRootHex((state as CachedBeaconStateGloas).latestBlockHash) : null,
|
|
157
166
|
},
|
|
158
167
|
currentSlot
|
|
159
168
|
),
|
|
@@ -196,12 +205,22 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
196
205
|
|
|
197
206
|
// this is not the justified state, but there is no other ways to get justified balances
|
|
198
207
|
const justifiedBalances = getEffectiveBalanceIncrementsZeroInactive(unfinalizedState);
|
|
208
|
+
|
|
209
|
+
const isForkPostGloas = (unfinalizedState as CachedBeaconStateGloas).latestBlockHash !== undefined;
|
|
210
|
+
|
|
211
|
+
// For unfinalized state, use getCheckpointPayloadStatus to determine the correct status.
|
|
212
|
+
// It checks state.execution_payload_availability to determine EMPTY vs FULL.
|
|
213
|
+
const justifiedPayloadStatus = getCheckpointPayloadStatus(unfinalizedState, justifiedCheckpoint.epoch);
|
|
214
|
+
const finalizedPayloadStatus = getCheckpointPayloadStatus(unfinalizedState, finalizedCheckpoint.epoch);
|
|
215
|
+
|
|
199
216
|
const store = new ForkChoiceStore(
|
|
200
217
|
currentSlot,
|
|
201
218
|
justifiedCheckpoint,
|
|
202
219
|
finalizedCheckpoint,
|
|
203
220
|
justifiedBalances,
|
|
204
221
|
justifiedBalancesGetter,
|
|
222
|
+
justifiedPayloadStatus,
|
|
223
|
+
finalizedPayloadStatus,
|
|
205
224
|
{
|
|
206
225
|
onJustified: (cp) => emitter.emit(ChainEvent.forkChoiceJustified, cp),
|
|
207
226
|
onFinalized: (cp) => emitter.emit(ChainEvent.forkChoiceFinalized, cp),
|
|
@@ -235,15 +254,14 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
235
254
|
: {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
|
|
236
255
|
|
|
237
256
|
dataAvailabilityStatus: DataAvailabilityStatus.PreData,
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}),
|
|
257
|
+
payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL, // TODO GLOAS: Post-gloas how do we know if the checkpoint payload is FULL or EMPTY?
|
|
258
|
+
builderIndex: isForkPostGloas
|
|
259
|
+
? (unfinalizedState as CachedBeaconStateGloas).latestExecutionPayloadBid.builderIndex
|
|
260
|
+
: null,
|
|
261
|
+
blockHashFromBid: isForkPostGloas
|
|
262
|
+
? toRootHex((unfinalizedState as CachedBeaconStateGloas).latestExecutionPayloadBid.blockHash)
|
|
263
|
+
: null,
|
|
264
|
+
parentBlockHash: isForkPostGloas ? toRootHex((unfinalizedState as CachedBeaconStateGloas).latestBlockHash) : null,
|
|
247
265
|
};
|
|
248
266
|
|
|
249
267
|
const parentSlot = blockHeader.slot - 1;
|
|
@@ -285,9 +303,9 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
285
303
|
};
|
|
286
304
|
|
|
287
305
|
const protoArray = ProtoArray.initialize(finalizedBlock, currentSlot);
|
|
288
|
-
protoArray.onBlock(justifiedBlock, currentSlot);
|
|
289
|
-
protoArray.onBlock(parentBlock, currentSlot);
|
|
290
|
-
protoArray.onBlock(headBlock, currentSlot);
|
|
306
|
+
protoArray.onBlock(justifiedBlock, currentSlot, null);
|
|
307
|
+
protoArray.onBlock(parentBlock, currentSlot, null);
|
|
308
|
+
protoArray.onBlock(headBlock, currentSlot, null);
|
|
291
309
|
|
|
292
310
|
logger?.verbose("Initialized protoArray successfully", {...logCtx, length: protoArray.length()});
|
|
293
311
|
|
|
@@ -864,7 +864,7 @@ function isValidShuffling(
|
|
|
864
864
|
// attestation's shuffling is the same as the current state's.
|
|
865
865
|
// To account for skipped slots, find the first block at *or before* the pivot slot.
|
|
866
866
|
const beaconBlockRootHex = blockRootHex;
|
|
867
|
-
const beaconBlock = forkChoice.
|
|
867
|
+
const beaconBlock = forkChoice.getBlockHexDefaultStatus(beaconBlockRootHex);
|
|
868
868
|
if (!beaconBlock) {
|
|
869
869
|
return InvalidAttestationData.BlockNotInForkChoice;
|
|
870
870
|
}
|
|
@@ -723,8 +723,7 @@ export function getPayloadAttributesForSSE(
|
|
|
723
723
|
|
|
724
724
|
let parentBlockNumber: number;
|
|
725
725
|
if (isForkPostGloas(fork)) {
|
|
726
|
-
|
|
727
|
-
const parentBlock = chain.forkChoice.getBlock(parentBlockRoot);
|
|
726
|
+
const parentBlock = chain.forkChoice.getBlockHexAndBlockHash(toRootHex(parentBlockRoot), toRootHex(parentHash));
|
|
728
727
|
if (parentBlock?.executionPayloadBlockHash == null) {
|
|
729
728
|
throw Error(`Parent block not found in fork choice root=${toRootHex(parentBlockRoot)}`);
|
|
730
729
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
|
|
3
3
|
import {CachedBeaconStateAllForks, computeEpochAtSlot} from "@lodestar/state-transition";
|
|
4
|
-
import {BeaconBlock, Epoch, RootHex, Slot, phase0} from "@lodestar/types";
|
|
4
|
+
import {BeaconBlock, Epoch, RootHex, Slot, isGloasBeaconBlock, phase0} from "@lodestar/types";
|
|
5
5
|
import {Logger, toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {Metrics} from "../../metrics/index.js";
|
|
7
7
|
import {JobItemQueue} from "../../util/queue/index.js";
|
|
@@ -88,7 +88,12 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
88
88
|
*/
|
|
89
89
|
getPreStateSync(block: BeaconBlock): CachedBeaconStateAllForks | null {
|
|
90
90
|
const parentRoot = toRootHex(block.parentRoot);
|
|
91
|
-
const parentBlock =
|
|
91
|
+
const parentBlock = isGloasBeaconBlock(block)
|
|
92
|
+
? this.forkChoice.getBlockHexAndBlockHash(
|
|
93
|
+
parentRoot,
|
|
94
|
+
toRootHex(block.body.signedExecutionPayloadBid.message.parentBlockHash)
|
|
95
|
+
)
|
|
96
|
+
: this.forkChoice.getBlockHexDefaultStatus(parentRoot);
|
|
92
97
|
if (!parentBlock) {
|
|
93
98
|
throw new RegenError({
|
|
94
99
|
code: RegenErrorCode.BLOCK_NOT_IN_FORKCHOICE,
|
package/src/chain/regen/regen.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
processSlots,
|
|
12
12
|
stateTransition,
|
|
13
13
|
} from "@lodestar/state-transition";
|
|
14
|
-
import {BeaconBlock, RootHex, SignedBeaconBlock, Slot} from "@lodestar/types";
|
|
14
|
+
import {BeaconBlock, RootHex, SignedBeaconBlock, Slot, isGloasBeaconBlock} from "@lodestar/types";
|
|
15
15
|
import {Logger, fromHex, toRootHex} from "@lodestar/utils";
|
|
16
16
|
import {IBeaconDb} from "../../db/index.js";
|
|
17
17
|
import {Metrics} from "../../metrics/index.js";
|
|
@@ -58,7 +58,13 @@ export class StateRegenerator implements IStateRegeneratorInternal {
|
|
|
58
58
|
opts: StateRegenerationOpts,
|
|
59
59
|
regenCaller: RegenCaller
|
|
60
60
|
): Promise<CachedBeaconStateAllForks> {
|
|
61
|
-
const
|
|
61
|
+
const parentRoot = toRootHex(block.parentRoot);
|
|
62
|
+
const parentBlock = isGloasBeaconBlock(block)
|
|
63
|
+
? this.modules.forkChoice.getBlockHexAndBlockHash(
|
|
64
|
+
parentRoot,
|
|
65
|
+
toRootHex(block.body.signedExecutionPayloadBid.message.parentBlockHash)
|
|
66
|
+
)
|
|
67
|
+
: this.modules.forkChoice.getBlockHexDefaultStatus(parentRoot);
|
|
62
68
|
if (!parentBlock) {
|
|
63
69
|
throw new RegenError({
|
|
64
70
|
code: RegenErrorCode.BLOCK_NOT_IN_FORKCHOICE,
|
|
@@ -81,7 +81,7 @@ async function validateAggregateAndProof(
|
|
|
81
81
|
});
|
|
82
82
|
}
|
|
83
83
|
// [REJECT] `aggregate.data.index == 0` if `block.slot == aggregate.data.slot`.
|
|
84
|
-
const block = chain.forkChoice.
|
|
84
|
+
const block = chain.forkChoice.getBlockDefaultStatus(attData.beaconBlockRoot);
|
|
85
85
|
|
|
86
86
|
// If block is unknown, we don't handle it here. It will throw error later on at `verifyHeadBlockAndTargetRoot()`
|
|
87
87
|
if (block !== null && block.slot === attData.slot && attData.index !== 0) {
|
|
@@ -186,7 +186,7 @@ export async function validateGossipAttestationsSameAttData(
|
|
|
186
186
|
chain.seenAttesters.add(targetEpoch, validatorIndex);
|
|
187
187
|
} else {
|
|
188
188
|
step0ResultOrErrors[oldIndex] = {
|
|
189
|
-
err: new AttestationError(GossipAction.
|
|
189
|
+
err: new AttestationError(GossipAction.REJECT, {
|
|
190
190
|
code: AttestationErrorCode.INVALID_SIGNATURE,
|
|
191
191
|
}),
|
|
192
192
|
};
|
|
@@ -307,7 +307,7 @@ async function validateAttestationNoSignatureCheck(
|
|
|
307
307
|
}
|
|
308
308
|
|
|
309
309
|
// [REJECT] `attestation.data.index == 0` if `block.slot == attestation.data.slot`.
|
|
310
|
-
const block = chain.forkChoice.
|
|
310
|
+
const block = chain.forkChoice.getBlockDefaultStatus(attData.beaconBlockRoot);
|
|
311
311
|
|
|
312
312
|
// block being null will be handled by `verifyHeadBlockAndTargetRoot`
|
|
313
313
|
if (block !== null && block.slot === attSlot && attData.index !== 0) {
|
|
@@ -756,7 +756,7 @@ export function getAttestationDataSigningRoot(config: BeaconConfig, data: phase0
|
|
|
756
756
|
function verifyHeadBlockIsKnown(chain: IBeaconChain, beaconBlockRoot: Root): ProtoBlock {
|
|
757
757
|
// TODO (LH): Enforce a maximum skip distance for unaggregated attestations.
|
|
758
758
|
|
|
759
|
-
const headBlock = chain.forkChoice.
|
|
759
|
+
const headBlock = chain.forkChoice.getBlockDefaultStatus(beaconBlockRoot);
|
|
760
760
|
if (headBlock === null) {
|
|
761
761
|
throw new AttestationError(GossipAction.IGNORE, {
|
|
762
762
|
code: AttestationErrorCode.UNKNOWN_OR_PREFINALIZED_BEACON_BLOCK_ROOT,
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
assertValidAttesterSlashing,
|
|
3
3
|
getAttesterSlashableIndices,
|
|
4
4
|
getAttesterSlashingSignatureSets,
|
|
5
|
+
isSlashableValidator,
|
|
5
6
|
} from "@lodestar/state-transition";
|
|
6
7
|
import {AttesterSlashing} from "@lodestar/types";
|
|
7
8
|
import {AttesterSlashingError, AttesterSlashingErrorCode, GossipAction} from "../errors/index.js";
|
|
@@ -58,6 +59,14 @@ export async function validateAttesterSlashing(
|
|
|
58
59
|
});
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
const currentEpoch = state.epochCtx.epoch;
|
|
63
|
+
if (!intersectingIndices.some((index) => isSlashableValidator(state.validators.getReadonly(index), currentEpoch))) {
|
|
64
|
+
throw new AttesterSlashingError(GossipAction.REJECT, {
|
|
65
|
+
code: AttesterSlashingErrorCode.INVALID,
|
|
66
|
+
error: Error("AttesterSlashing has no slashable validators"),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
61
70
|
const signatureSets = getAttesterSlashingSignatureSets(chain.config, state.slot, attesterSlashing);
|
|
62
71
|
if (!(await chain.bls.verifySignatureSets(signatureSets, {batchable: true, priority: prioritizeBls}))) {
|
|
63
72
|
throw new AttesterSlashingError(GossipAction.REJECT, {
|
|
@@ -78,7 +78,7 @@ export async function validateGossipBlobSidecar(
|
|
|
78
78
|
// already know this block.
|
|
79
79
|
const blockRoot = ssz.phase0.BeaconBlockHeader.hashTreeRoot(blobSidecar.signedBlockHeader.message);
|
|
80
80
|
const blockHex = toRootHex(blockRoot);
|
|
81
|
-
if (chain.forkChoice.
|
|
81
|
+
if (chain.forkChoice.getBlockHexDefaultStatus(blockHex) !== null) {
|
|
82
82
|
throw new BlobSidecarGossipError(GossipAction.IGNORE, {code: BlobSidecarErrorCode.ALREADY_KNOWN, root: blockHex});
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -89,7 +89,7 @@ export async function validateGossipBlobSidecar(
|
|
|
89
89
|
// gossip and non-gossip sources) (a client MAY queue blocks for processing once the parent block is
|
|
90
90
|
// retrieved).
|
|
91
91
|
const parentRoot = toRootHex(blobSidecar.signedBlockHeader.message.parentRoot);
|
|
92
|
-
const parentBlock = chain.forkChoice.
|
|
92
|
+
const parentBlock = chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
|
|
93
93
|
if (parentBlock === null) {
|
|
94
94
|
// If fork choice does *not* consider the parent to be a descendant of the finalized block,
|
|
95
95
|
// then there are two more cases:
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
isExecutionEnabled,
|
|
10
10
|
isExecutionStateType,
|
|
11
11
|
} from "@lodestar/state-transition";
|
|
12
|
-
import {SignedBeaconBlock, deneb, gloas} from "@lodestar/types";
|
|
12
|
+
import {SignedBeaconBlock, deneb, gloas, isGloasBeaconBlock} from "@lodestar/types";
|
|
13
13
|
import {byteArrayEquals, sleep, toRootHex} from "@lodestar/utils";
|
|
14
14
|
import {BlockErrorCode, BlockGossipError, GossipAction} from "../errors/index.js";
|
|
15
15
|
import {IBeaconChain} from "../interface.js";
|
|
@@ -56,7 +56,7 @@ export async function validateGossipBlock(
|
|
|
56
56
|
// check, we will load the parent and state from disk only to find out later that we
|
|
57
57
|
// already know this block.
|
|
58
58
|
const blockRoot = toRootHex(config.getForkTypes(blockSlot).BeaconBlock.hashTreeRoot(block));
|
|
59
|
-
if (chain.forkChoice.
|
|
59
|
+
if (chain.forkChoice.getBlockHexDefaultStatus(blockRoot) !== null) {
|
|
60
60
|
throw new BlockGossipError(GossipAction.IGNORE, {code: BlockErrorCode.ALREADY_KNOWN, root: blockRoot});
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -72,7 +72,12 @@ export async function validateGossipBlock(
|
|
|
72
72
|
// [REJECT] The current finalized_checkpoint is an ancestor of block -- i.e.
|
|
73
73
|
// get_ancestor(store, block.parent_root, compute_start_slot_at_epoch(store.finalized_checkpoint.epoch)) == store.finalized_checkpoint.root
|
|
74
74
|
const parentRoot = toRootHex(block.parentRoot);
|
|
75
|
-
const parentBlock =
|
|
75
|
+
const parentBlock = isGloasBeaconBlock(block)
|
|
76
|
+
? chain.forkChoice.getBlockHexAndBlockHash(
|
|
77
|
+
parentRoot,
|
|
78
|
+
toRootHex(block.body.signedExecutionPayloadBid.message.parentBlockHash)
|
|
79
|
+
)
|
|
80
|
+
: chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
|
|
76
81
|
if (parentBlock === null) {
|
|
77
82
|
// If fork choice does *not* consider the parent to be a descendant of the finalized block,
|
|
78
83
|
// then there are two more cases:
|
|
@@ -104,7 +109,7 @@ export async function validateGossipBlock(
|
|
|
104
109
|
|
|
105
110
|
// [REJECT] The block is from a higher slot than its parent.
|
|
106
111
|
if (parentBlock.slot >= blockSlot) {
|
|
107
|
-
throw new BlockGossipError(GossipAction.
|
|
112
|
+
throw new BlockGossipError(GossipAction.REJECT, {
|
|
108
113
|
code: BlockErrorCode.NOT_LATER_THAN_PARENT,
|
|
109
114
|
parentSlot: parentBlock.slot,
|
|
110
115
|
slot: blockSlot,
|
|
@@ -73,7 +73,7 @@ export async function validateGossipDataColumnSidecar(
|
|
|
73
73
|
// 6) [IGNORE] The sidecar's block's parent (defined by block_header.parent_root) has been seen (via gossip
|
|
74
74
|
// or non-gossip sources)
|
|
75
75
|
const parentRoot = toRootHex(blockHeader.parentRoot);
|
|
76
|
-
const parentBlock = chain.forkChoice.
|
|
76
|
+
const parentBlock = chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
|
|
77
77
|
if (parentBlock === null) {
|
|
78
78
|
// If fork choice does *not* consider the parent to be a descendant of the finalized block,
|
|
79
79
|
// then there are two more cases:
|
|
@@ -113,8 +113,7 @@ async function validateExecutionPayloadBid(
|
|
|
113
113
|
|
|
114
114
|
// [IGNORE] `bid.parent_block_root` is the hash tree root of a known beacon
|
|
115
115
|
// block in fork choice.
|
|
116
|
-
|
|
117
|
-
if (block === null) {
|
|
116
|
+
if (!chain.forkChoice.hasBlock(bid.parentBlockRoot)) {
|
|
118
117
|
throw new ExecutionPayloadBidError(GossipAction.IGNORE, {
|
|
119
118
|
code: ExecutionPayloadBidErrorCode.UNKNOWN_BLOCK_ROOT,
|
|
120
119
|
parentBlockRoot: parentBlockRootHex,
|
|
@@ -37,7 +37,7 @@ async function validateExecutionPayloadEnvelope(
|
|
|
37
37
|
// the block is retrieved).
|
|
38
38
|
// TODO GLOAS: Need to review this, we should queue the envelope for later
|
|
39
39
|
// processing if the block is not yet known, otherwise we would ignore it here
|
|
40
|
-
const block = chain.forkChoice.
|
|
40
|
+
const block = chain.forkChoice.getBlockDefaultStatus(envelope.beaconBlockRoot);
|
|
41
41
|
if (block === null) {
|
|
42
42
|
throw new ExecutionPayloadEnvelopeError(GossipAction.IGNORE, {
|
|
43
43
|
code: ExecutionPayloadEnvelopeErrorCode.BLOCK_ROOT_UNKNOWN,
|
|
@@ -79,7 +79,7 @@ async function validateExecutionPayloadEnvelope(
|
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
if (block.builderIndex
|
|
82
|
+
if (block.builderIndex == null || block.blockHashFromBid == null) {
|
|
83
83
|
// This indicates this block is a pre-gloas block which is wrong
|
|
84
84
|
throw new ExecutionPayloadEnvelopeError(GossipAction.IGNORE, {
|
|
85
85
|
code: ExecutionPayloadEnvelopeErrorCode.CACHE_FAIL,
|
|
@@ -97,11 +97,11 @@ async function validateExecutionPayloadEnvelope(
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
// [REJECT] `payload.block_hash == bid.block_hash`
|
|
100
|
-
if (toRootHex(payload.blockHash) !== block.
|
|
100
|
+
if (toRootHex(payload.blockHash) !== block.blockHashFromBid) {
|
|
101
101
|
throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
|
|
102
102
|
code: ExecutionPayloadEnvelopeErrorCode.BLOCK_HASH_MISMATCH,
|
|
103
103
|
envelopeBlockHash: toRootHex(payload.blockHash),
|
|
104
|
-
bidBlockHash: block.
|
|
104
|
+
bidBlockHash: block.blockHashFromBid,
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
107
|
|
|
@@ -59,8 +59,7 @@ async function validatePayloadAttestationMessage(
|
|
|
59
59
|
// [IGNORE] The message's block `data.beacon_block_root` has been seen (via
|
|
60
60
|
// gossip or non-gossip sources) (a client MAY queue attestation for processing
|
|
61
61
|
// once the block is retrieved. Note a client might want to request payload after).
|
|
62
|
-
|
|
63
|
-
if (block === null) {
|
|
62
|
+
if (!chain.forkChoice.hasBlock(data.beaconBlockRoot)) {
|
|
64
63
|
throw new PayloadAttestationError(GossipAction.IGNORE, {
|
|
65
64
|
code: PayloadAttestationErrorCode.UNKNOWN_BLOCK_ROOT,
|
|
66
65
|
blockRoot: toRootHex(data.beaconBlockRoot),
|
|
@@ -856,6 +856,11 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
856
856
|
} catch (e) {
|
|
857
857
|
logger.error("Error adding to payloadAttestation pool", {}, e as Error);
|
|
858
858
|
}
|
|
859
|
+
chain.forkChoice.notifyPtcMessages(
|
|
860
|
+
toRootHex(payloadAttestationMessage.data.beaconBlockRoot),
|
|
861
|
+
[validationResult.validatorCommitteeIndex],
|
|
862
|
+
payloadAttestationMessage.data.payloadPresent
|
|
863
|
+
);
|
|
859
864
|
},
|
|
860
865
|
[GossipType.execution_payload_bid]: async ({
|
|
861
866
|
gossipData,
|
|
@@ -20,7 +20,7 @@ export async function* onBlobSidecarsByRoot(
|
|
|
20
20
|
for (const blobIdentifier of requestBody) {
|
|
21
21
|
const {blockRoot, index} = blobIdentifier;
|
|
22
22
|
const blockRootHex = toRootHex(blockRoot);
|
|
23
|
-
const block = chain.forkChoice.
|
|
23
|
+
const block = chain.forkChoice.getBlockHexDefaultStatus(blockRootHex);
|
|
24
24
|
|
|
25
25
|
// NOTE: Only support non-finalized blocks.
|
|
26
26
|
// SPEC: Clients MUST support requesting blocks and sidecars since the latest finalized epoch.
|
|
@@ -34,7 +34,7 @@ export async function* onDataColumnSidecarsByRoot(
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
const blockRootHex = toRootHex(blockRoot);
|
|
37
|
-
const block = chain.forkChoice.
|
|
37
|
+
const block = chain.forkChoice.getBlockHexDefaultStatus(blockRootHex);
|
|
38
38
|
// If the block is not in fork choice, it may be finalized. Attempt to find its slot in block archive
|
|
39
39
|
const slot = block ? block.slot : await db.blockArchive.getSlotByRoot(blockRoot);
|
|
40
40
|
|