@lodestar/fork-choice 1.47.0-dev.4546ac1229 → 1.47.0-dev.467f8a72f2
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/forkChoice/forkChoice.d.ts +39 -1
- package/lib/forkChoice/forkChoice.d.ts.map +1 -1
- package/lib/forkChoice/forkChoice.js +171 -33
- package/lib/forkChoice/forkChoice.js.map +1 -1
- package/lib/protoArray/interface.d.ts +3 -1
- package/lib/protoArray/interface.d.ts.map +1 -1
- package/lib/protoArray/protoArray.d.ts +10 -1
- package/lib/protoArray/protoArray.d.ts.map +1 -1
- package/lib/protoArray/protoArray.js +27 -0
- package/lib/protoArray/protoArray.js.map +1 -1
- package/package.json +8 -8
- package/src/forkChoice/forkChoice.ts +205 -38
- package/src/protoArray/interface.ts +8 -1
- package/src/protoArray/protoArray.ts +36 -1
|
@@ -180,7 +180,8 @@ export declare class ForkChoice implements IForkChoice {
|
|
|
180
180
|
* https://github.com/ethereum/consensus-specs/pull/3034 for info about proposer boost reorg
|
|
181
181
|
* This function should only be called during block proposal and only be called after `updateHead()` in `updateAndGetHead()`
|
|
182
182
|
*
|
|
183
|
-
*
|
|
183
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.14/specs/phase0/fork-choice.md#get_proposer_head
|
|
184
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.14/specs/gloas/fork-choice.md#modified-get_proposer_head
|
|
184
185
|
*/
|
|
185
186
|
getProposerHead(headBlock: ProtoBlock, secFromSlot: number, slot: Slot): {
|
|
186
187
|
proposerHead: ProtoBlock;
|
|
@@ -461,6 +462,38 @@ export declare class ForkChoice implements IForkChoice {
|
|
|
461
462
|
* Child class can overwrite this for testing purpose.
|
|
462
463
|
*/
|
|
463
464
|
protected isBlockTimely(block: BeaconBlock, blockDelaySec: number): boolean;
|
|
465
|
+
/**
|
|
466
|
+
* Return true if the block arrived before the PTC (payload-timeliness committee) deadline,
|
|
467
|
+
* ie. block_timeliness[PTC_TIMELINESS_INDEX]. should_apply_proposer_boost uses this as the
|
|
468
|
+
* definition of an "early" proposer equivocation: only a sibling seen by the PTC deadline
|
|
469
|
+
* proves the proposer equivocated soon enough that honest nodes could have withheld the boost.
|
|
470
|
+
*
|
|
471
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.14/specs/gloas/fork-choice.md#modified-record_block_timeliness
|
|
472
|
+
*
|
|
473
|
+
* Child class can overwrite this for testing purpose.
|
|
474
|
+
*/
|
|
475
|
+
protected isBlockPtcTimely(block: BeaconBlock, blockDelaySec: number): boolean;
|
|
476
|
+
/**
|
|
477
|
+
* Determine whether proposer boost should be applied to `proposerBoostRoot`.
|
|
478
|
+
*
|
|
479
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.14/specs/gloas/fork-choice.md#new-should_apply_proposer_boost
|
|
480
|
+
*
|
|
481
|
+
* Pre-gloas blocks always receive the boost (unconditional, backward compatible). For gloas
|
|
482
|
+
* blocks the boost is withheld when the parent is a weak block from the previous slot and the
|
|
483
|
+
* proposer of that parent equivocated (published another PTC-timely block at the same slot).
|
|
484
|
+
*/
|
|
485
|
+
private shouldApplyProposerBoost;
|
|
486
|
+
/**
|
|
487
|
+
* Return true if another block at the same slot from the same proposer is known to fork choice.
|
|
488
|
+
*
|
|
489
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.14/specs/phase0/fork-choice.md#is_proposer_equivocation
|
|
490
|
+
*/
|
|
491
|
+
private isProposerEquivocation;
|
|
492
|
+
/**
|
|
493
|
+
* The proposer boost to apply to `proposerBoostRoot`, propagated up the branch by
|
|
494
|
+
* applyScoreChanges() together with the deltas.
|
|
495
|
+
*/
|
|
496
|
+
private getProposerBoost;
|
|
464
497
|
/**
|
|
465
498
|
* https://github.com/ethereum/consensus-specs/blob/v1.5.0/specs/phase0/fork-choice.md#is_proposing_on_time
|
|
466
499
|
*/
|
|
@@ -487,6 +520,8 @@ export declare class ForkChoice implements IForkChoice {
|
|
|
487
520
|
* May need the justified balances of:
|
|
488
521
|
* - unrealizedJustified: Already available in `CheckpointWithBalance`
|
|
489
522
|
* Since this balances are already available the getter is just `() => balances`, without cache interaction
|
|
523
|
+
*
|
|
524
|
+
* @returns Whether either checkpoint was updated.
|
|
490
525
|
*/
|
|
491
526
|
private updateCheckpoints;
|
|
492
527
|
/**
|
|
@@ -529,6 +564,8 @@ export declare class ForkChoice implements IForkChoice {
|
|
|
529
564
|
* Equivalent to:
|
|
530
565
|
*
|
|
531
566
|
* https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/fork-choice.md#on_tick
|
|
567
|
+
*
|
|
568
|
+
* @returns Whether an epoch-boundary checkpoint was updated.
|
|
532
569
|
*/
|
|
533
570
|
private onTick;
|
|
534
571
|
/**
|
|
@@ -538,6 +575,7 @@ export declare class ForkChoice implements IForkChoice {
|
|
|
538
575
|
*
|
|
539
576
|
*/
|
|
540
577
|
private getPreliminaryProposerHead;
|
|
578
|
+
/** Returns whether it recomputed the head, so the caller can avoid a redundant `updateHead()`. */
|
|
541
579
|
private runFastConfirmation;
|
|
542
580
|
private createFastConfirmationContext;
|
|
543
581
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forkChoice.d.ts","sourceRoot":"","sources":["../../src/forkChoice/forkChoice.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"forkChoice.d.ts","sourceRoot":"","sources":["../../src/forkChoice/forkChoice.ts"],"names":[],"mappings":"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"}
|
|
@@ -260,12 +260,22 @@ export class ForkChoice {
|
|
|
260
260
|
if (parentBlock === undefined) {
|
|
261
261
|
return { shouldOverrideFcu: false, reason: NotReorgedReason.ParentBlockNotAvailable };
|
|
262
262
|
}
|
|
263
|
+
const currentTimeOk = headBlock.slot === currentSlot ||
|
|
264
|
+
(proposalSlot === currentSlot && this.isProposingOnTime(secFromSlot, currentSlot));
|
|
265
|
+
// Mirror the proposer equivocation branch of getProposerHead(). The head slot's attestations are
|
|
266
|
+
// still queued at this point so the head is assumed weak, same as for the regular branch below.
|
|
267
|
+
if (currentTimeOk && this.isProposerEquivocation(headBlock)) {
|
|
268
|
+
this.logger?.verbose("Head proposer equivocated. Should override forkchoice update", {
|
|
269
|
+
blockRoot: headBlock.blockRoot,
|
|
270
|
+
slot: currentSlot,
|
|
271
|
+
proposerIndex: headBlock.proposerIndex,
|
|
272
|
+
});
|
|
273
|
+
return { shouldOverrideFcu: true, parentBlock };
|
|
274
|
+
}
|
|
263
275
|
const { prelimProposerHead, prelimNotReorgedReason } = this.getPreliminaryProposerHead(headBlock, parentBlock, proposalSlot);
|
|
264
276
|
if (prelimProposerHead === headBlock) {
|
|
265
277
|
return { shouldOverrideFcu: false, reason: prelimNotReorgedReason ?? NotReorgedReason.Unknown };
|
|
266
278
|
}
|
|
267
|
-
const currentTimeOk = headBlock.slot === currentSlot ||
|
|
268
|
-
(proposalSlot === currentSlot && this.isProposingOnTime(secFromSlot, currentSlot));
|
|
269
279
|
if (!currentTimeOk) {
|
|
270
280
|
return { shouldOverrideFcu: false, reason: NotReorgedReason.ReorgMoreThanOneSlot };
|
|
271
281
|
}
|
|
@@ -339,7 +349,8 @@ export class ForkChoice {
|
|
|
339
349
|
* https://github.com/ethereum/consensus-specs/pull/3034 for info about proposer boost reorg
|
|
340
350
|
* This function should only be called during block proposal and only be called after `updateHead()` in `updateAndGetHead()`
|
|
341
351
|
*
|
|
342
|
-
*
|
|
352
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.14/specs/phase0/fork-choice.md#get_proposer_head
|
|
353
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.14/specs/gloas/fork-choice.md#modified-get_proposer_head
|
|
343
354
|
*/
|
|
344
355
|
getProposerHead(headBlock, secFromSlot, slot) {
|
|
345
356
|
const isHeadTimely = headBlock.timeliness;
|
|
@@ -359,6 +370,24 @@ export class ForkChoice {
|
|
|
359
370
|
if (parentBlock === undefined) {
|
|
360
371
|
return { proposerHead, isHeadTimely, notReorgedReason: NotReorgedReason.ParentBlockNotAvailable };
|
|
361
372
|
}
|
|
373
|
+
// Half of single_slot_reorg check in the spec is done in getPreliminaryProposerHead()
|
|
374
|
+
const currentTimeOk = headBlock.slot + 1 === slot;
|
|
375
|
+
const isProposerBoostWornOff = this.proposerBoostRoot !== headBlock.blockRoot;
|
|
376
|
+
// Re-org more aggressively if there is a proposer equivocation in the previous slot, skipping the
|
|
377
|
+
// regular reorg conditions. Any known equivocation counts here, timely or not.
|
|
378
|
+
if (currentTimeOk &&
|
|
379
|
+
isProposerBoostWornOff &&
|
|
380
|
+
this.isProposerEquivocation(headBlock) &&
|
|
381
|
+
this.isHeadWeak(headBlock.blockRoot)) {
|
|
382
|
+
this.logger?.verbose("Performing single-slot reorg to remove weak head of equivocating proposer", {
|
|
383
|
+
slot,
|
|
384
|
+
proposerHead: parentBlock.blockRoot,
|
|
385
|
+
weakHead: headBlock.blockRoot,
|
|
386
|
+
proposerIndex: headBlock.proposerIndex,
|
|
387
|
+
});
|
|
388
|
+
proposerHead = parentBlock;
|
|
389
|
+
return { proposerHead, isHeadTimely };
|
|
390
|
+
}
|
|
362
391
|
const { prelimProposerHead, prelimNotReorgedReason } = this.getPreliminaryProposerHead(headBlock, parentBlock, slot);
|
|
363
392
|
if (prelimProposerHead === headBlock && prelimNotReorgedReason !== undefined) {
|
|
364
393
|
return { proposerHead, isHeadTimely, notReorgedReason: prelimNotReorgedReason };
|
|
@@ -368,13 +397,10 @@ export class ForkChoice {
|
|
|
368
397
|
return { proposerHead, isHeadTimely, notReorgedReason: NotReorgedReason.NotProposingOnTime };
|
|
369
398
|
}
|
|
370
399
|
// No reorg if attempted reorg is more than a single slot
|
|
371
|
-
// Half of single_slot_reorg check in the spec is done in getPreliminaryProposerHead()
|
|
372
|
-
const currentTimeOk = headBlock.slot + 1 === slot;
|
|
373
400
|
if (!currentTimeOk) {
|
|
374
401
|
return { proposerHead, isHeadTimely, notReorgedReason: NotReorgedReason.ReorgMoreThanOneSlot };
|
|
375
402
|
}
|
|
376
403
|
// No reorg if proposer boost is still in effect
|
|
377
|
-
const isProposerBoostWornOff = this.proposerBoostRoot !== headBlock.blockRoot;
|
|
378
404
|
if (!isProposerBoostWornOff) {
|
|
379
405
|
return { proposerHead, isHeadTimely, notReorgedReason: NotReorgedReason.ProposerBoostNotWornOff };
|
|
380
406
|
}
|
|
@@ -429,30 +455,45 @@ export class ForkChoice {
|
|
|
429
455
|
computeDeltasMetrics?.unchangedVoteValidators.set(unchangedVoteValidators);
|
|
430
456
|
computeDeltasMetrics?.newVoteValidators.set(newVoteValidators);
|
|
431
457
|
this.balances = newBalances;
|
|
432
|
-
/**
|
|
433
|
-
* The structure in line with deltas to propagate boost up the branch
|
|
434
|
-
* starting from the proposerIndex
|
|
435
|
-
*/
|
|
436
|
-
let proposerBoost = null;
|
|
437
|
-
if (this.opts?.proposerBoost && this.proposerBoostRoot) {
|
|
438
|
-
const proposerBoostScore = this.justifiedProposerBoostScore ??
|
|
439
|
-
getCommitteeFraction(this.fcStore.justified.totalBalance, {
|
|
440
|
-
slotsPerEpoch: SLOTS_PER_EPOCH,
|
|
441
|
-
committeePercent: this.config.PROPOSER_SCORE_BOOST,
|
|
442
|
-
});
|
|
443
|
-
proposerBoost = { root: this.proposerBoostRoot, score: proposerBoostScore };
|
|
444
|
-
this.justifiedProposerBoostScore = proposerBoostScore;
|
|
445
|
-
}
|
|
446
458
|
const currentSlot = this.fcStore.currentSlot;
|
|
447
|
-
|
|
448
|
-
attestationDeltas,
|
|
449
|
-
proposerBoost,
|
|
459
|
+
const checkpoints = {
|
|
450
460
|
justifiedEpoch: this.fcStore.justified.checkpoint.epoch,
|
|
451
461
|
justifiedRoot: this.fcStore.justified.checkpoint.rootHex,
|
|
452
462
|
finalizedEpoch: this.fcStore.finalizedCheckpoint.epoch,
|
|
453
463
|
finalizedRoot: this.fcStore.finalizedCheckpoint.rootHex,
|
|
454
464
|
currentSlot,
|
|
455
|
-
}
|
|
465
|
+
};
|
|
466
|
+
const boostedBlock = this.opts?.proposerBoost && this.proposerBoostRoot ? this.getBlockHexDefaultStatus(this.proposerBoostRoot) : null;
|
|
467
|
+
if (boostedBlock && isGloasBlock(boostedBlock)) {
|
|
468
|
+
// should_apply_proposer_boost judges the parent against the attestations known to the store,
|
|
469
|
+
// via is_head_weak (which also assumes equivocators' votes were already discounted before
|
|
470
|
+
// their balance is added back). Apply the attestation deltas first so the decision reads
|
|
471
|
+
// post-delta scores, then apply the boost in a second pass.
|
|
472
|
+
// TODO GLOAS: applyScoreChanges() updates weights and best child/descendant in one call;
|
|
473
|
+
// splitting them would let the two passes update weights and recompute best child/descendant
|
|
474
|
+
// once at the end.
|
|
475
|
+
// https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.14/specs/gloas/fork-choice.md#new-should_apply_proposer_boost
|
|
476
|
+
this.protoArray.applyScoreChanges({ attestationDeltas, proposerBoost: null, ...checkpoints });
|
|
477
|
+
const proposerBoost = this.shouldApplyProposerBoost() ? this.getProposerBoost() : null;
|
|
478
|
+
// The first pass already rolled back the previous boost and left a coherent tree, so a
|
|
479
|
+
// withheld boost needs no second pass
|
|
480
|
+
if (proposerBoost !== null) {
|
|
481
|
+
this.protoArray.applyScoreChanges({
|
|
482
|
+
attestationDeltas: new Array(this.protoArray.nodes.length).fill(0),
|
|
483
|
+
proposerBoost,
|
|
484
|
+
...checkpoints,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
// Pre-gloas the boost is unconditional, so attestation deltas and boost deltas can propagate
|
|
490
|
+
// up the branch in a single pass
|
|
491
|
+
this.protoArray.applyScoreChanges({
|
|
492
|
+
attestationDeltas,
|
|
493
|
+
proposerBoost: boostedBlock ? this.getProposerBoost() : null,
|
|
494
|
+
...checkpoints,
|
|
495
|
+
});
|
|
496
|
+
}
|
|
456
497
|
// findHead returns the ProtoNode representing the head
|
|
457
498
|
const head = this.protoArray.findHead(this.fcStore.justified.checkpoint.rootHex, currentSlot);
|
|
458
499
|
this.head = head;
|
|
@@ -633,6 +674,8 @@ export class ForkChoice {
|
|
|
633
674
|
targetRoot: toRootHex(targetRoot),
|
|
634
675
|
stateRoot: toRootHex(block.stateRoot),
|
|
635
676
|
timeliness: isTimely,
|
|
677
|
+
ptcTimeliness: this.isBlockPtcTimely(block, blockDelaySec),
|
|
678
|
+
proposerIndex: block.proposerIndex,
|
|
636
679
|
justifiedEpoch: stateJustifiedEpoch,
|
|
637
680
|
justifiedRoot: toRootHex(state.currentJustifiedCheckpoint.root),
|
|
638
681
|
finalizedEpoch: finalizedCheckpoint.epoch,
|
|
@@ -842,11 +885,18 @@ export class ForkChoice {
|
|
|
842
885
|
while (this.fcStore.currentSlot < currentSlot) {
|
|
843
886
|
const previousSlot = this.fcStore.currentSlot;
|
|
844
887
|
// Note: we are relying upon `onTick` to update `fcStore.time` to ensure we don't get stuck in a loop.
|
|
845
|
-
this.onTick(previousSlot + 1);
|
|
888
|
+
const didUpdateCheckpoints = this.onTick(previousSlot + 1);
|
|
846
889
|
this.queuedAttestationsPreviousSlot = 0;
|
|
847
890
|
// Process any attestations that might now be eligible before running FCR for this slot.
|
|
848
891
|
this.processAttestationQueue();
|
|
849
|
-
this.runFastConfirmation();
|
|
892
|
+
const didRecomputeHead = this.runFastConfirmation();
|
|
893
|
+
// An epoch-boundary checkpoint pull-up can move the head's dependent root and stale the cached
|
|
894
|
+
// head before block 0 of the new epoch is imported, making isProposerBoostSameDependentRoot()
|
|
895
|
+
// wrong for that block. Recompute the head so it reflects the new checkpoint and the queued
|
|
896
|
+
// votes — unless fast confirmation already did, to avoid a redundant head calculation.
|
|
897
|
+
if (didUpdateCheckpoints && !didRecomputeHead) {
|
|
898
|
+
this.updateHead();
|
|
899
|
+
}
|
|
850
900
|
this.validatedAttestationDatas = new Set();
|
|
851
901
|
}
|
|
852
902
|
}
|
|
@@ -1281,7 +1331,8 @@ export class ForkChoice {
|
|
|
1281
1331
|
// Only ever called on a block already in fork choice, so a miss is a broken invariant.
|
|
1282
1332
|
const node = this.protoArray.getNodeDefaultStatus(blockRoot);
|
|
1283
1333
|
if (node === undefined) {
|
|
1284
|
-
// this is called for head
|
|
1334
|
+
// this is called for head or the boosted block's parent, both of which should always be
|
|
1335
|
+
// in forkchoice, otherwise we have a serious error
|
|
1285
1336
|
throw new ForkChoiceError({ code: ForkChoiceErrorCode.MISSING_PROTO_ARRAY_BLOCK, root: blockRoot });
|
|
1286
1337
|
}
|
|
1287
1338
|
const reorgThreshold = getCommitteeFraction(this.fcStore.justified.totalBalance, {
|
|
@@ -1297,7 +1348,7 @@ export class ForkChoice {
|
|
|
1297
1348
|
// always 0. Return before fetching the state and walking the block's committees.
|
|
1298
1349
|
if (equivocatingIndices.size > 0) {
|
|
1299
1350
|
const state = this.fcStore.stateGetter({ stateRoot: node.stateRoot });
|
|
1300
|
-
// Only ever called on the head, so the state is always cached.
|
|
1351
|
+
// Only ever called on the head or the boosted block's parent, so the state is always cached.
|
|
1301
1352
|
// A miss is a broken invariant, not a recoverable state.
|
|
1302
1353
|
if (state === null) {
|
|
1303
1354
|
throw new ForkChoiceError({
|
|
@@ -1353,6 +1404,83 @@ export class ForkChoice {
|
|
|
1353
1404
|
const isBeforeLateBlockCutoff = blockDelaySec * 1000 < this.config.getAttestationDueMs(fork);
|
|
1354
1405
|
return this.fcStore.currentSlot === block.slot && isBeforeLateBlockCutoff;
|
|
1355
1406
|
}
|
|
1407
|
+
/**
|
|
1408
|
+
* Return true if the block arrived before the PTC (payload-timeliness committee) deadline,
|
|
1409
|
+
* ie. block_timeliness[PTC_TIMELINESS_INDEX]. should_apply_proposer_boost uses this as the
|
|
1410
|
+
* definition of an "early" proposer equivocation: only a sibling seen by the PTC deadline
|
|
1411
|
+
* proves the proposer equivocated soon enough that honest nodes could have withheld the boost.
|
|
1412
|
+
*
|
|
1413
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.14/specs/gloas/fork-choice.md#modified-record_block_timeliness
|
|
1414
|
+
*
|
|
1415
|
+
* Child class can overwrite this for testing purpose.
|
|
1416
|
+
*/
|
|
1417
|
+
isBlockPtcTimely(block, blockDelaySec) {
|
|
1418
|
+
const ptcThresholdMs = this.config.getSlotComponentDurationMs(this.config.PAYLOAD_ATTESTATION_DUE_BPS);
|
|
1419
|
+
return this.fcStore.currentSlot === block.slot && blockDelaySec * 1000 < ptcThresholdMs;
|
|
1420
|
+
}
|
|
1421
|
+
/**
|
|
1422
|
+
* Determine whether proposer boost should be applied to `proposerBoostRoot`.
|
|
1423
|
+
*
|
|
1424
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.14/specs/gloas/fork-choice.md#new-should_apply_proposer_boost
|
|
1425
|
+
*
|
|
1426
|
+
* Pre-gloas blocks always receive the boost (unconditional, backward compatible). For gloas
|
|
1427
|
+
* blocks the boost is withheld when the parent is a weak block from the previous slot and the
|
|
1428
|
+
* proposer of that parent equivocated (published another PTC-timely block at the same slot).
|
|
1429
|
+
*/
|
|
1430
|
+
shouldApplyProposerBoost() {
|
|
1431
|
+
if (!this.proposerBoostRoot) {
|
|
1432
|
+
return false;
|
|
1433
|
+
}
|
|
1434
|
+
const boostedBlock = this.getBlockHexDefaultStatus(this.proposerBoostRoot);
|
|
1435
|
+
// Pre-gloas blocks always get boost
|
|
1436
|
+
if (!boostedBlock || !isGloasBlock(boostedBlock)) {
|
|
1437
|
+
return true;
|
|
1438
|
+
}
|
|
1439
|
+
const parentBlock = this.getBlockHexDefaultStatus(boostedBlock.parentRoot);
|
|
1440
|
+
if (!parentBlock) {
|
|
1441
|
+
return true;
|
|
1442
|
+
}
|
|
1443
|
+
// Apply proposer boost if parent is not from the previous slot
|
|
1444
|
+
if (parentBlock.slot + 1 < boostedBlock.slot) {
|
|
1445
|
+
return true;
|
|
1446
|
+
}
|
|
1447
|
+
// Apply proposer boost if parent is not weak
|
|
1448
|
+
if (!this.isHeadWeak(parentBlock.blockRoot)) {
|
|
1449
|
+
return true;
|
|
1450
|
+
}
|
|
1451
|
+
// Parent is weak and from the previous slot: apply boost only if there are no early
|
|
1452
|
+
// equivocations, ie. no other PTC-timely block at the parent's slot from the same proposer.
|
|
1453
|
+
return !this.protoArray.hasEquivocatingBlock(parentBlock.proposerIndex, parentBlock.slot, parentBlock.blockRoot,
|
|
1454
|
+
// Only a sibling seen before the PTC deadline counts. A late released one might not have been
|
|
1455
|
+
// seen by the proposer, so it cannot be expected to reorg it and is not denied the boost for it.
|
|
1456
|
+
true);
|
|
1457
|
+
}
|
|
1458
|
+
/**
|
|
1459
|
+
* Return true if another block at the same slot from the same proposer is known to fork choice.
|
|
1460
|
+
*
|
|
1461
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.14/specs/phase0/fork-choice.md#is_proposer_equivocation
|
|
1462
|
+
*/
|
|
1463
|
+
isProposerEquivocation(block) {
|
|
1464
|
+
// Any known sibling counts, timely or not. Timeliness only matters for withholding the boost from
|
|
1465
|
+
// the next proposer, the reorg itself is safe to attempt whenever the equivocation is visible.
|
|
1466
|
+
return this.protoArray.hasEquivocatingBlock(block.proposerIndex, block.slot, block.blockRoot, false);
|
|
1467
|
+
}
|
|
1468
|
+
/**
|
|
1469
|
+
* The proposer boost to apply to `proposerBoostRoot`, propagated up the branch by
|
|
1470
|
+
* applyScoreChanges() together with the deltas.
|
|
1471
|
+
*/
|
|
1472
|
+
getProposerBoost() {
|
|
1473
|
+
if (!this.proposerBoostRoot) {
|
|
1474
|
+
return null;
|
|
1475
|
+
}
|
|
1476
|
+
const proposerBoostScore = this.justifiedProposerBoostScore ??
|
|
1477
|
+
getCommitteeFraction(this.fcStore.justified.totalBalance, {
|
|
1478
|
+
slotsPerEpoch: SLOTS_PER_EPOCH,
|
|
1479
|
+
committeePercent: this.config.PROPOSER_SCORE_BOOST,
|
|
1480
|
+
});
|
|
1481
|
+
this.justifiedProposerBoostScore = proposerBoostScore;
|
|
1482
|
+
return { root: this.proposerBoostRoot, score: proposerBoostScore };
|
|
1483
|
+
}
|
|
1356
1484
|
/**
|
|
1357
1485
|
* https://github.com/ethereum/consensus-specs/blob/v1.5.0/specs/phase0/fork-choice.md#is_proposing_on_time
|
|
1358
1486
|
*/
|
|
@@ -1395,18 +1523,24 @@ export class ForkChoice {
|
|
|
1395
1523
|
* May need the justified balances of:
|
|
1396
1524
|
* - unrealizedJustified: Already available in `CheckpointWithBalance`
|
|
1397
1525
|
* Since this balances are already available the getter is just `() => balances`, without cache interaction
|
|
1526
|
+
*
|
|
1527
|
+
* @returns Whether either checkpoint was updated.
|
|
1398
1528
|
*/
|
|
1399
1529
|
updateCheckpoints(justifiedCheckpoint, finalizedCheckpoint, getJustifiedBalances) {
|
|
1530
|
+
let updated = false;
|
|
1400
1531
|
// Update justified checkpoint.
|
|
1401
1532
|
if (justifiedCheckpoint.epoch > this.fcStore.justified.checkpoint.epoch) {
|
|
1402
1533
|
this.fcStore.justified = { checkpoint: justifiedCheckpoint, balances: getJustifiedBalances() };
|
|
1403
1534
|
this.justifiedProposerBoostScore = null;
|
|
1535
|
+
updated = true;
|
|
1404
1536
|
}
|
|
1405
1537
|
// Update finalized checkpoint.
|
|
1406
1538
|
if (finalizedCheckpoint.epoch > this.fcStore.finalizedCheckpoint.epoch) {
|
|
1407
1539
|
this.fcStore.finalizedCheckpoint = finalizedCheckpoint;
|
|
1408
1540
|
this.justifiedProposerBoostScore = null;
|
|
1541
|
+
updated = true;
|
|
1409
1542
|
}
|
|
1543
|
+
return updated;
|
|
1410
1544
|
}
|
|
1411
1545
|
/**
|
|
1412
1546
|
* Update unrealized checkpoints in store if necessary
|
|
@@ -1650,6 +1784,8 @@ export class ForkChoice {
|
|
|
1650
1784
|
* Equivalent to:
|
|
1651
1785
|
*
|
|
1652
1786
|
* https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/fork-choice.md#on_tick
|
|
1787
|
+
*
|
|
1788
|
+
* @returns Whether an epoch-boundary checkpoint was updated.
|
|
1653
1789
|
*/
|
|
1654
1790
|
onTick(time) {
|
|
1655
1791
|
const previousSlot = this.fcStore.currentSlot;
|
|
@@ -1669,10 +1805,10 @@ export class ForkChoice {
|
|
|
1669
1805
|
}
|
|
1670
1806
|
// Not a new epoch, return.
|
|
1671
1807
|
if (computeSlotsSinceEpochStart(time) !== 0) {
|
|
1672
|
-
return;
|
|
1808
|
+
return false;
|
|
1673
1809
|
}
|
|
1674
|
-
// If a new epoch, pull-up justification and finalization from previous epoch
|
|
1675
|
-
this.updateCheckpoints(this.fcStore.unrealizedJustified.checkpoint, this.fcStore.unrealizedFinalizedCheckpoint, () => this.fcStore.unrealizedJustified.balances);
|
|
1810
|
+
// If a new epoch, pull-up justification and finalization from previous epoch.
|
|
1811
|
+
return this.updateCheckpoints(this.fcStore.unrealizedJustified.checkpoint, this.fcStore.unrealizedFinalizedCheckpoint, () => this.fcStore.unrealizedJustified.balances);
|
|
1676
1812
|
}
|
|
1677
1813
|
/**
|
|
1678
1814
|
*
|
|
@@ -1715,11 +1851,12 @@ export class ForkChoice {
|
|
|
1715
1851
|
prelimProposerHead = parentBlock;
|
|
1716
1852
|
return { prelimProposerHead };
|
|
1717
1853
|
}
|
|
1854
|
+
/** Returns whether it recomputed the head, so the caller can avoid a redundant `updateHead()`. */
|
|
1718
1855
|
runFastConfirmation() {
|
|
1719
1856
|
const fastConfirmationRule = this.fastConfirmationRule;
|
|
1720
1857
|
const fastConfirmationContext = this.fastConfirmationContext;
|
|
1721
1858
|
if (!fastConfirmationRule || !fastConfirmationContext)
|
|
1722
|
-
return;
|
|
1859
|
+
return false;
|
|
1723
1860
|
if (this.fastConfirmationPaused) {
|
|
1724
1861
|
// Keep consumers on a safe, available root while the rule is paused
|
|
1725
1862
|
this.fcStore.confirmedRoot = this.fcStore.finalizedCheckpoint.rootHex;
|
|
@@ -1730,7 +1867,7 @@ export class ForkChoice {
|
|
|
1730
1867
|
// Runs outside the timed try/catch below; a throw would escape to the clock listener
|
|
1731
1868
|
this.logger?.debug("Fast confirmation notify failed", { slot: this.fcStore.currentSlot }, err);
|
|
1732
1869
|
}
|
|
1733
|
-
return;
|
|
1870
|
+
return false;
|
|
1734
1871
|
}
|
|
1735
1872
|
withObservedDuration(this.metrics?.fastConfirmation.totalDuration.startTimer(), () => {
|
|
1736
1873
|
try {
|
|
@@ -1745,6 +1882,7 @@ export class ForkChoice {
|
|
|
1745
1882
|
this.logger?.debug("Fast confirmation failed", { slot: this.fcStore.currentSlot, head: this.head.blockRoot, confirmedRoot: this.fcStore.confirmedRoot }, err);
|
|
1746
1883
|
}
|
|
1747
1884
|
});
|
|
1885
|
+
return true;
|
|
1748
1886
|
}
|
|
1749
1887
|
createFastConfirmationContext() {
|
|
1750
1888
|
const confirmationByzantineThreshold = this.config.CONFIRMATION_BYZANTINE_THRESHOLD;
|