3
3
altair ,
4
4
BeaconBlock ,
5
5
BeaconBlockBody ,
6
+ electra ,
6
7
LightClientBootstrap ,
7
8
LightClientFinalityUpdate ,
8
9
LightClientHeader ,
@@ -19,32 +20,34 @@ import {
19
20
} from "@lodestar/types" ;
20
21
import { ChainForkConfig } from "@lodestar/config" ;
21
22
import {
22
- CachedBeaconStateAltair ,
23
- computeStartSlotAtEpoch ,
24
- computeSyncPeriodAtEpoch ,
25
- computeSyncPeriodAtSlot ,
26
- executionPayloadToPayloadHeader ,
27
- } from "@lodestar/state-transition" ;
28
- import {
23
+ LightClientUpdateSummary ,
29
24
isBetterUpdate ,
30
25
toLightClientUpdateSummary ,
31
- LightClientUpdateSummary ,
32
26
upgradeLightClientHeader ,
33
27
} from "@lodestar/light-client/spec" ;
34
- import { Logger , MapDef , pruneSetToMax , toRootHex } from "@lodestar/utils" ;
35
- import { routes } from "@lodestar/api" ;
36
28
import {
37
- MIN_SYNC_COMMITTEE_PARTICIPANTS ,
38
- SYNC_COMMITTEE_SIZE ,
39
- ForkName ,
40
- ForkSeq ,
41
29
ForkExecution ,
42
30
ForkLightClient ,
43
- highestFork ,
31
+ ForkName ,
32
+ ForkSeq ,
33
+ MIN_SYNC_COMMITTEE_PARTICIPANTS ,
34
+ SYNC_COMMITTEE_SIZE ,
44
35
forkLightClient ,
36
+ highestFork ,
37
+ isForkPostElectra ,
45
38
} from "@lodestar/params" ;
39
+ import {
40
+ CachedBeaconStateAltair ,
41
+ computeStartSlotAtEpoch ,
42
+ computeSyncPeriodAtEpoch ,
43
+ computeSyncPeriodAtSlot ,
44
+ executionPayloadToPayloadHeader ,
45
+ } from "@lodestar/state-transition" ;
46
+ import { Logger , MapDef , pruneSetToMax , toRootHex } from "@lodestar/utils" ;
47
+ import { routes } from "@lodestar/api" ;
46
48
47
49
import { IBeaconDb } from "../../db/index.js" ;
50
+ import { NUM_WITNESS , NUM_WITNESS_ELECTRA } from "../../db/repositories/lightclientSyncCommitteeWitness.js" ;
48
51
import { Metrics } from "../../metrics/index.js" ;
49
52
import { ChainEventEmitter } from "../emitter.js" ;
50
53
import { byteArrayEquals } from "../../util/bytes.js" ;
@@ -208,7 +211,10 @@ export class LightClientServer {
208
211
private checkpointHeaders = new Map < BlockRooHex , LightClientHeader > ( ) ;
209
212
private latestHeadUpdate : LightClientOptimisticUpdate | null = null ;
210
213
211
- private readonly zero : Pick < altair . LightClientUpdate , "finalityBranch" | "finalizedHeader" > ;
214
+ private readonly zero : Pick <
215
+ altair . LightClientUpdate | electra . LightClientUpdate ,
216
+ "finalityBranch" | "finalizedHeader"
217
+ > ;
212
218
private finalized : LightClientFinalityUpdate | null = null ;
213
219
214
220
constructor (
@@ -225,7 +231,9 @@ export class LightClientServer {
225
231
this . zero = {
226
232
// Assign the hightest fork's default value because it can always be typecasted down to correct fork
227
233
finalizedHeader : sszTypesFor ( highestFork ( forkLightClient ) ) . LightClientHeader . defaultValue ( ) ,
228
- finalityBranch : ssz . altair . LightClientUpdate . fields . finalityBranch . defaultValue ( ) ,
234
+ // Electra finalityBranch has fixed length of 5 whereas altair has 4. The fifth element will be ignored
235
+ // when serializing as altair LightClientUpdate
236
+ finalityBranch : ssz . electra . LightClientUpdate . fields . finalityBranch . defaultValue ( ) ,
229
237
} ;
230
238
231
239
if ( metrics ) {
@@ -388,12 +396,13 @@ export class LightClientServer {
388
396
parentBlockSlot : Slot
389
397
) : Promise < void > {
390
398
const blockSlot = block . slot ;
391
- const header = blockToLightClientHeader ( this . config . getForkName ( blockSlot ) , block ) ;
399
+ const fork = this . config . getForkName ( blockSlot ) ;
400
+ const header = blockToLightClientHeader ( fork , block ) ;
392
401
393
402
const blockRoot = ssz . phase0 . BeaconBlockHeader . hashTreeRoot ( header . beacon ) ;
394
403
const blockRootHex = toRootHex ( blockRoot ) ;
395
404
396
- const syncCommitteeWitness = getSyncCommitteesWitness ( postState ) ;
405
+ const syncCommitteeWitness = getSyncCommitteesWitness ( fork , postState ) ;
397
406
398
407
// Only store current sync committee once per run
399
408
if ( ! this . storedCurrentSyncCommittee ) {
@@ -621,6 +630,16 @@ export class LightClientServer {
621
630
if ( ! syncCommitteeWitness ) {
622
631
throw Error ( `syncCommitteeWitness not available at ${ toRootHex ( attestedData . blockRoot ) } ` ) ;
623
632
}
633
+
634
+ const attestedFork = this . config . getForkName ( attestedHeader . beacon . slot ) ;
635
+ const numWitness = syncCommitteeWitness . witness . length ;
636
+ if ( isForkPostElectra ( attestedFork ) && numWitness !== NUM_WITNESS_ELECTRA ) {
637
+ throw Error ( `Expected ${ NUM_WITNESS_ELECTRA } witnesses in post-Electra numWitness=${ numWitness } ` ) ;
638
+ }
639
+ if ( ! isForkPostElectra ( attestedFork ) && numWitness !== NUM_WITNESS ) {
640
+ throw Error ( `Expected ${ NUM_WITNESS } witnesses in pre-Electra numWitness=${ numWitness } ` ) ;
641
+ }
642
+
624
643
const nextSyncCommittee = await this . db . syncCommittee . get ( syncCommitteeWitness . nextSyncCommitteeRoot ) ;
625
644
if ( ! nextSyncCommittee ) {
626
645
throw Error ( "nextSyncCommittee not available" ) ;
@@ -641,7 +660,6 @@ export class LightClientServer {
641
660
finalityBranch = attestedData . finalityBranch ;
642
661
finalizedHeader = finalizedHeaderAttested ;
643
662
// Fork of LightClientUpdate is based off on attested header's fork
644
- const attestedFork = this . config . getForkName ( attestedHeader . beacon . slot ) ;
645
663
if ( this . config . getForkName ( finalizedHeader . beacon . slot ) !== attestedFork ) {
646
664
finalizedHeader = upgradeLightClientHeader ( this . config , attestedFork , finalizedHeader ) ;
647
665
}
0 commit comments