mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-01-19 19:09:08 +00:00
extend light client protocol for Electra
Add missing Electra support for light client protocol: - https://github.com/ethereum/consensus-specs/pull/3811 Tested against PR consensus-spec-tests, the test runner automatically picks up the new tests once available.
This commit is contained in:
parent
31653d5869
commit
65ae4d8eb1
@ -542,12 +542,22 @@ proc new*(T: type BeaconChainDB,
|
||||
"lc_deneb_headers"
|
||||
else:
|
||||
"",
|
||||
electraHeaders:
|
||||
if cfg.DENEB_FORK_EPOCH != FAR_FUTURE_EPOCH:
|
||||
"lc_electra_headers"
|
||||
else:
|
||||
"",
|
||||
altairCurrentBranches: "lc_altair_current_branches",
|
||||
electraCurrentBranches:
|
||||
if cfg.ELECTRA_FORK_EPOCH != FAR_FUTURE_EPOCH:
|
||||
"lc_electra_current_branches"
|
||||
else:
|
||||
"",
|
||||
altairSyncCommittees: "lc_altair_sync_committees",
|
||||
legacyAltairBestUpdates: "lc_altair_best_updates",
|
||||
bestUpdates: "lc_best_updates",
|
||||
sealedPeriods: "lc_sealed_periods")).expectDb()
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Electra
|
||||
|
||||
var blobs : KvStoreRef
|
||||
if cfg.DENEB_FORK_EPOCH != FAR_FUTURE_EPOCH:
|
||||
|
@ -28,13 +28,15 @@ logScope: topics = "lcdata"
|
||||
# - Altair: ~38 KB per `SyncCommitteePeriod` (~1.0 MB per month)
|
||||
# - Capella: ~221 KB per `SyncCommitteePeriod` (~6.0 MB per month)
|
||||
# - Deneb: ~225 KB per `SyncCommitteePeriod` (~6.2 MB per month)
|
||||
# - Electra: ~249 KB per `SyncCommitteePeriod` (~6.8 MB per month)
|
||||
#
|
||||
# `lc_altair_current_branches` holds Merkle proofs needed to
|
||||
# `lc_xxxxx_current_branches` holds Merkle proofs needed to
|
||||
# construct `LightClientBootstrap` objects.
|
||||
# SSZ because this data does not compress well, and because this data
|
||||
# needs to be bundled together with other data to fulfill requests.
|
||||
# Mainnet data size (all columns):
|
||||
# - Altair ... Deneb: ~42 KB per `SyncCommitteePeriod` (~1.1 MB per month)
|
||||
# - Electra: ~50 KB per `SyncCommitteePeriod` (~1.4 MB per month)
|
||||
#
|
||||
# `lc_altair_sync_committees` contains a copy of finalized sync committees.
|
||||
# They are initially populated from the main DAG (usually a fast state access).
|
||||
@ -42,7 +44,7 @@ logScope: topics = "lcdata"
|
||||
# SSZ because this data does not compress well, and because this data
|
||||
# needs to be bundled together with other data to fulfill requests.
|
||||
# Mainnet data size (all columns):
|
||||
# - Altair ... Deneb: ~24 KB per `SyncCommitteePeriod` (~0.7 MB per month)
|
||||
# - Altair ... Electra: ~24 KB per `SyncCommitteePeriod` (~0.7 MB per month)
|
||||
#
|
||||
# `lc_best_updates` holds full `LightClientUpdate` objects in SSZ form.
|
||||
# These objects are frequently queried in bulk, but there is only one per
|
||||
@ -59,6 +61,7 @@ logScope: topics = "lcdata"
|
||||
# - Altair: ~25 KB per `SyncCommitteePeriod` (~0.7 MB per month)
|
||||
# - Capella: ~26 KB per `SyncCommitteePeriod` (~0.7 MB per month)
|
||||
# - Deneb: ~26 KB per `SyncCommitteePeriod` (~0.7 MB per month)
|
||||
# - Electra: ~27 KB per `SyncCommitteePeriod` (~0.7 MB per month)
|
||||
#
|
||||
# `lc_sealed_periods` contains the sync committee periods for which
|
||||
# full light client data was imported. Data for these periods may no longer
|
||||
@ -73,12 +76,16 @@ logScope: topics = "lcdata"
|
||||
# 600 = 32+20+32+32+256+32+8+8+8+8+4+32+32+32+32+32
|
||||
# - Deneb: 256*(112+4+616+128+40)/1024*28/1024
|
||||
# 616 = 32+20+32+32+256+32+8+8+8+8+4+32+32+32+32+32+8+8
|
||||
# - Electra: 256*(112+4+712+128+40)/1024*28/1024
|
||||
# 712 = 32+20+32+32+256+32+8+8+8+8+4+32+32+32+32+32+8+8+32+32+32
|
||||
#
|
||||
# Committee branch computations:
|
||||
# - Altair: 256*(5*32+8)/1024*28/1024
|
||||
# - Electra: 256*(6*32+8)/1024*28/1024
|
||||
#
|
||||
# Finality branch computations:
|
||||
# - Altair: 256*(6*32+8)/1024*28/1024
|
||||
# - Electra: 256*(7*32+8)/1024*28/1024
|
||||
#
|
||||
# Committee computations:
|
||||
# - Altair: (24624+8)/1024*28/1024
|
||||
@ -91,6 +98,7 @@ logScope: topics = "lcdata"
|
||||
# - Altair: (112+24624+5*32+112+6*32+112+8+9)/1024*28/1024
|
||||
# - Capella: (4+884+24624+5*32+4+884+6*32+112+8+9)/1024*28/1024
|
||||
# - Deneb: (4+900+24624+5*32+4+900+6*32+112+8+9)/1024*28/1024
|
||||
# - Electra: (4+996+24624+6*32+4+996+7*32+112+8+9)/1024*28/1024
|
||||
|
||||
type
|
||||
LightClientHeaderStore = object
|
||||
@ -98,6 +106,11 @@ type
|
||||
putStmt: SqliteStmt[(array[32, byte], int64, seq[byte]), void]
|
||||
keepFromStmt: SqliteStmt[int64, void]
|
||||
|
||||
BranchFork {.pure.} = enum
|
||||
None = 0,
|
||||
Altair,
|
||||
Electra
|
||||
|
||||
CurrentSyncCommitteeBranchStore = object
|
||||
containsStmt: SqliteStmt[int64, int64]
|
||||
getStmt: SqliteStmt[int64, seq[byte]]
|
||||
@ -135,8 +148,8 @@ type
|
||||
## Eth2Digest -> (Slot, LightClientHeader)
|
||||
## Cached block headers to support longer retention than block storage.
|
||||
|
||||
currentBranches: CurrentSyncCommitteeBranchStore
|
||||
## Slot -> altair.CurrentSyncCommitteeBranch
|
||||
currentBranches: array[BranchFork, CurrentSyncCommitteeBranchStore]
|
||||
## Slot -> CurrentSyncCommitteeBranch
|
||||
## Cached data for creating future `LightClientBootstrap` instances.
|
||||
## Key is the block slot of which the post state was used to get the data.
|
||||
## Data stored for all finalized epoch boundary blocks.
|
||||
@ -234,12 +247,14 @@ func putHeader*[T: ForkyLightClientHeader](
|
||||
|
||||
proc initCurrentBranchesStore(
|
||||
backend: SqStoreRef,
|
||||
name: string): KvResult[CurrentSyncCommitteeBranchStore] =
|
||||
name, typeName: string): KvResult[CurrentSyncCommitteeBranchStore] =
|
||||
if name == "":
|
||||
return ok CurrentSyncCommitteeBranchStore()
|
||||
if not backend.readOnly:
|
||||
? backend.exec("""
|
||||
CREATE TABLE IF NOT EXISTS `""" & name & """` (
|
||||
`slot` INTEGER PRIMARY KEY, -- `Slot` (up through 2^63-1)
|
||||
`branch` BLOB -- `altair.CurrentSyncCommitteeBranch` (SSZ)
|
||||
`branch` BLOB -- `""" & typeName & """` (SSZ)
|
||||
);
|
||||
""")
|
||||
if not ? backend.hasTable(name):
|
||||
@ -278,40 +293,46 @@ func close(store: var CurrentSyncCommitteeBranchStore) =
|
||||
store.putStmt.disposeSafe()
|
||||
store.keepFromStmt.disposeSafe()
|
||||
|
||||
func hasCurrentSyncCommitteeBranch*(
|
||||
template kind(x: typedesc[altair.CurrentSyncCommitteeBranch]): BranchFork =
|
||||
BranchFork.Altair
|
||||
|
||||
template kind(x: typedesc[electra.CurrentSyncCommitteeBranch]): BranchFork =
|
||||
BranchFork.Electra
|
||||
|
||||
func hasCurrentSyncCommitteeBranch*[T: ForkyCurrentSyncCommitteeBranch](
|
||||
db: LightClientDataDB, slot: Slot): bool =
|
||||
if not slot.isSupportedBySQLite or
|
||||
distinctBase(db.currentBranches.containsStmt) == nil:
|
||||
distinctBase(db.currentBranches[T.kind].containsStmt) == nil:
|
||||
return false
|
||||
var exists: int64
|
||||
for res in db.currentBranches.containsStmt.exec(slot.int64, exists):
|
||||
for res in db.currentBranches[T.kind].containsStmt.exec(slot.int64, exists):
|
||||
res.expect("SQL query OK")
|
||||
doAssert exists == 1
|
||||
return true
|
||||
false
|
||||
|
||||
proc getCurrentSyncCommitteeBranch*(
|
||||
db: LightClientDataDB, slot: Slot): Opt[altair.CurrentSyncCommitteeBranch] =
|
||||
proc getCurrentSyncCommitteeBranch*[T: ForkyCurrentSyncCommitteeBranch](
|
||||
db: LightClientDataDB, slot: Slot): Opt[T] =
|
||||
if not slot.isSupportedBySQLite or
|
||||
distinctBase(db.currentBranches.getStmt) == nil:
|
||||
return Opt.none(altair.CurrentSyncCommitteeBranch)
|
||||
distinctBase(db.currentBranches[T.kind].getStmt) == nil:
|
||||
return Opt.none(T)
|
||||
var branch: seq[byte]
|
||||
for res in db.currentBranches.getStmt.exec(slot.int64, branch):
|
||||
for res in db.currentBranches[T.kind].getStmt.exec(slot.int64, branch):
|
||||
res.expect("SQL query OK")
|
||||
try:
|
||||
return ok SSZ.decode(branch, altair.CurrentSyncCommitteeBranch)
|
||||
return ok SSZ.decode(branch, T)
|
||||
except SerializationError as exc:
|
||||
error "LC data store corrupted", store = "currentBranches",
|
||||
error "LC data store corrupted", store = "currentBranches", kind = T.kind,
|
||||
slot, exc = exc.msg
|
||||
return Opt.none(altair.CurrentSyncCommitteeBranch)
|
||||
return Opt.none(T)
|
||||
|
||||
func putCurrentSyncCommitteeBranch*(
|
||||
db: LightClientDataDB, slot: Slot,
|
||||
branch: altair.CurrentSyncCommitteeBranch) =
|
||||
func putCurrentSyncCommitteeBranch*[T: ForkyCurrentSyncCommitteeBranch](
|
||||
db: LightClientDataDB, slot: Slot, branch: T) =
|
||||
doAssert not db.backend.readOnly # All `stmt` are non-nil
|
||||
if not slot.isSupportedBySQLite:
|
||||
return
|
||||
let res = db.currentBranches.putStmt.exec((slot.int64, SSZ.encode(branch)))
|
||||
let res = db.currentBranches[T.kind].putStmt.exec(
|
||||
(slot.int64, SSZ.encode(branch)))
|
||||
res.expect("SQL query OK")
|
||||
|
||||
proc initSyncCommitteesStore(
|
||||
@ -643,9 +664,11 @@ func keepPeriodsFrom*(
|
||||
let res = db.syncCommittees.keepFromStmt.exec(minPeriod.int64)
|
||||
res.expect("SQL query OK")
|
||||
let minSlot = min(minPeriod.start_slot, int64.high.Slot)
|
||||
block:
|
||||
let res = db.currentBranches.keepFromStmt.exec(minSlot.int64)
|
||||
res.expect("SQL query OK")
|
||||
for branchFork, store in db.currentBranches:
|
||||
if branchFork > BranchFork.None and
|
||||
distinctBase(store.keepFromStmt) != nil:
|
||||
let res = store.keepFromStmt.exec(minSlot.int64)
|
||||
res.expect("SQL query OK")
|
||||
for lcDataFork, store in db.headers:
|
||||
if lcDataFork > LightClientDataFork.None and
|
||||
distinctBase(store.keepFromStmt) != nil:
|
||||
@ -656,7 +679,9 @@ type LightClientDataDBNames* = object
|
||||
altairHeaders*: string
|
||||
capellaHeaders*: string
|
||||
denebHeaders*: string
|
||||
electraHeaders*: string
|
||||
altairCurrentBranches*: string
|
||||
electraCurrentBranches*: string
|
||||
altairSyncCommittees*: string
|
||||
legacyAltairBestUpdates*: string
|
||||
bestUpdates*: string
|
||||
@ -665,7 +690,7 @@ type LightClientDataDBNames* = object
|
||||
proc initLightClientDataDB*(
|
||||
backend: SqStoreRef,
|
||||
names: LightClientDataDBNames): KvResult[LightClientDataDB] =
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Electra
|
||||
let
|
||||
headers = [
|
||||
# LightClientDataFork.None
|
||||
@ -678,10 +703,21 @@ proc initLightClientDataDB*(
|
||||
names.capellaHeaders, "capella.LightClientHeader"),
|
||||
# LightClientDataFork.Deneb
|
||||
? backend.initHeadersStore(
|
||||
names.denebHeaders, "deneb.LightClientHeader")
|
||||
names.denebHeaders, "deneb.LightClientHeader"),
|
||||
# LightClientDataFork.Electra
|
||||
? backend.initHeadersStore(
|
||||
names.electraHeaders, "electra.LightClientHeader"),
|
||||
]
|
||||
currentBranches = [
|
||||
# BranchFork.None
|
||||
CurrentSyncCommitteeBranchStore(),
|
||||
# BranchFork.Altair
|
||||
? backend.initCurrentBranchesStore(
|
||||
names.altairCurrentBranches, "altair.CurrentSyncCommitteeBranch"),
|
||||
# BranchFork.Electra
|
||||
? backend.initCurrentBranchesStore(
|
||||
names.electraCurrentBranches, "electra.CurrentSyncCommitteeBranch"),
|
||||
]
|
||||
currentBranches =
|
||||
? backend.initCurrentBranchesStore(names.altairCurrentBranches)
|
||||
syncCommittees =
|
||||
? backend.initSyncCommitteesStore(names.altairSyncCommittees)
|
||||
legacyBestUpdates =
|
||||
@ -706,7 +742,9 @@ proc close*(db: LightClientDataDB) =
|
||||
for lcDataFork in LightClientDataFork:
|
||||
if lcDataFork > LightClientDataFork.None:
|
||||
db.headers[lcDataFork].close()
|
||||
db.currentBranches.close()
|
||||
for branchFork in BranchFork:
|
||||
if branchFork > BranchFork.None:
|
||||
db.currentBranches[branchFork].close()
|
||||
db.syncCommittees.close()
|
||||
db.legacyBestUpdates.close()
|
||||
db.bestUpdates.close()
|
||||
|
@ -33,11 +33,13 @@ type
|
||||
CachedLightClientData* = object
|
||||
## Cached data from historical non-finalized states to improve speed when
|
||||
## creating future `LightClientUpdate` and `LightClientBootstrap` instances.
|
||||
current_sync_committee_branch*: altair.CurrentSyncCommitteeBranch
|
||||
next_sync_committee_branch*: altair.NextSyncCommitteeBranch
|
||||
current_sync_committee_branch*:
|
||||
LightClientDataFork.high.CurrentSyncCommitteeBranch
|
||||
next_sync_committee_branch*:
|
||||
LightClientDataFork.high.NextSyncCommitteeBranch
|
||||
|
||||
finalized_slot*: Slot
|
||||
finality_branch*: altair.FinalityBranch
|
||||
finality_branch*: LightClientDataFork.high.FinalityBranch
|
||||
|
||||
current_period_best_update*: ref ForkedLightClientUpdate
|
||||
latest_signature_slot*: Slot
|
||||
|
@ -22,6 +22,15 @@ template nextEpochBoundarySlot(slot: Slot): Slot =
|
||||
## referring to a block at given slot.
|
||||
(slot + (SLOTS_PER_EPOCH - 1)).epoch.start_slot
|
||||
|
||||
func hasCurrentSyncCommitteeBranch(dag: ChainDAGRef, slot: Slot): bool =
|
||||
let epoch = dag.cfg.consensusForkAtEpoch(slot.epoch)
|
||||
withLcDataFork(lcDataForkAtConsensusFork(epoch)):
|
||||
when lcDataFork > LightClientDataFork.None:
|
||||
hasCurrentSyncCommitteeBranch[lcDataFork.CurrentSyncCommitteeBranch](
|
||||
dag.lcDataStore.db, slot)
|
||||
else:
|
||||
true
|
||||
|
||||
proc updateExistingState(
|
||||
dag: ChainDAGRef, state: var ForkedHashedBeaconState, bsi: BlockSlotId,
|
||||
save: bool, cache: var StateCache): bool =
|
||||
@ -226,7 +235,7 @@ proc initLightClientBootstrapForPeriod(
|
||||
bid = bsi.bid
|
||||
boundarySlot = bid.slot.nextEpochBoundarySlot
|
||||
if boundarySlot == nextBoundarySlot and bid.slot >= lowSlot and
|
||||
not dag.lcDataStore.db.hasCurrentSyncCommitteeBranch(bid.slot):
|
||||
not dag.hasCurrentSyncCommitteeBranch(bid.slot):
|
||||
let bdata = dag.getExistingForkedBlock(bid).valueOr:
|
||||
dag.handleUnexpectedLightClientError(bid.slot)
|
||||
res.err()
|
||||
@ -246,7 +255,7 @@ proc initLightClientBootstrapForPeriod(
|
||||
forkyBlck.toLightClientHeader(lcDataFork))
|
||||
dag.lcDataStore.db.putCurrentSyncCommitteeBranch(
|
||||
bid.slot, forkyState.data.build_proof(
|
||||
altair.CURRENT_SYNC_COMMITTEE_GINDEX).get)
|
||||
lcDataFork.CURRENT_SYNC_COMMITTEE_GINDEX).get)
|
||||
else: raiseAssert "Unreachable"
|
||||
res
|
||||
|
||||
@ -393,13 +402,13 @@ proc initLightClientUpdateForPeriod(
|
||||
update = ForkedLightClientUpdate.init(lcDataFork.LightClientUpdate(
|
||||
attested_header: forkyBlck.toLightClientHeader(lcDataFork),
|
||||
next_sync_committee: forkyState.data.next_sync_committee,
|
||||
next_sync_committee_branch:
|
||||
forkyState.data.build_proof(altair.NEXT_SYNC_COMMITTEE_GINDEX).get,
|
||||
next_sync_committee_branch: forkyState.data.build_proof(
|
||||
lcDataFork.NEXT_SYNC_COMMITTEE_GINDEX).get,
|
||||
finality_branch:
|
||||
if finalizedBid.slot != FAR_FUTURE_SLOT:
|
||||
forkyState.data.build_proof(altair.FINALIZED_ROOT_GINDEX).get
|
||||
forkyState.data.build_proof(lcDataFork.FINALIZED_ROOT_GINDEX).get
|
||||
else:
|
||||
default(FinalityBranch)))
|
||||
default(lcDataFork.FinalityBranch)))
|
||||
else: raiseAssert "Unreachable"
|
||||
do:
|
||||
dag.handleUnexpectedLightClientError(attestedBid.slot)
|
||||
@ -464,17 +473,21 @@ proc cacheLightClientData(
|
||||
## Cache data for a given block and its post-state to speed up creating future
|
||||
## `LightClientUpdate` and `LightClientBootstrap` instances that refer to this
|
||||
## block and state.
|
||||
const lcDataFork = lcDataForkAtConsensusFork(typeof(state).kind)
|
||||
let
|
||||
bid = blck.toBlockId()
|
||||
cachedData = CachedLightClientData(
|
||||
current_sync_committee_branch:
|
||||
state.data.build_proof(altair.CURRENT_SYNC_COMMITTEE_GINDEX).get,
|
||||
next_sync_committee_branch:
|
||||
state.data.build_proof(altair.NEXT_SYNC_COMMITTEE_GINDEX).get,
|
||||
current_sync_committee_branch: normalize_merkle_branch(
|
||||
state.data.build_proof(lcDataFork.CURRENT_SYNC_COMMITTEE_GINDEX).get,
|
||||
LightClientDataFork.high.CURRENT_SYNC_COMMITTEE_GINDEX),
|
||||
next_sync_committee_branch: normalize_merkle_branch(
|
||||
state.data.build_proof(lcDataFork.NEXT_SYNC_COMMITTEE_GINDEX).get,
|
||||
LightClientDataFork.high.NEXT_SYNC_COMMITTEE_GINDEX),
|
||||
finalized_slot:
|
||||
state.data.finalized_checkpoint.epoch.start_slot,
|
||||
finality_branch:
|
||||
state.data.build_proof(altair.FINALIZED_ROOT_GINDEX).get,
|
||||
finality_branch: normalize_merkle_branch(
|
||||
state.data.build_proof(lcDataFork.FINALIZED_ROOT_GINDEX).get,
|
||||
LightClientDataFork.high.FINALIZED_ROOT_GINDEX),
|
||||
current_period_best_update:
|
||||
current_period_best_update,
|
||||
latest_signature_slot:
|
||||
@ -538,15 +551,18 @@ proc assignLightClientData(
|
||||
when lcDataFork > LightClientDataFork.None:
|
||||
forkyObject.next_sync_committee =
|
||||
next_sync_committee.get
|
||||
forkyObject.next_sync_committee_branch =
|
||||
attested_data.next_sync_committee_branch
|
||||
forkyObject.next_sync_committee_branch = normalize_merkle_branch(
|
||||
attested_data.next_sync_committee_branch,
|
||||
lcDataFork.NEXT_SYNC_COMMITTEE_GINDEX)
|
||||
else:
|
||||
doAssert next_sync_committee.isNone
|
||||
var finalized_slot = attested_data.finalized_slot
|
||||
withForkyObject(obj):
|
||||
when lcDataFork > LightClientDataFork.None:
|
||||
if finalized_slot == forkyObject.finalized_header.beacon.slot:
|
||||
forkyObject.finality_branch = attested_data.finality_branch
|
||||
forkyObject.finality_branch = normalize_merkle_branch(
|
||||
attested_data.finality_branch,
|
||||
lcDataFork.FINALIZED_ROOT_GINDEX)
|
||||
elif finalized_slot < max(dag.tail.slot, dag.backfill.slot):
|
||||
forkyObject.finalized_header.reset()
|
||||
forkyObject.finality_branch.reset()
|
||||
@ -564,10 +580,14 @@ proc assignLightClientData(
|
||||
attested_data.finalized_slot = finalized_slot
|
||||
dag.lcDataStore.cache.data[attested_bid] = attested_data
|
||||
if finalized_slot == forkyObject.finalized_header.beacon.slot:
|
||||
forkyObject.finality_branch = attested_data.finality_branch
|
||||
forkyObject.finality_branch = normalize_merkle_branch(
|
||||
attested_data.finality_branch,
|
||||
lcDataFork.FINALIZED_ROOT_GINDEX)
|
||||
elif finalized_slot == GENESIS_SLOT:
|
||||
forkyObject.finalized_header.reset()
|
||||
forkyObject.finality_branch = attested_data.finality_branch
|
||||
forkyObject.finality_branch = normalize_merkle_branch(
|
||||
attested_data.finality_branch,
|
||||
lcDataFork.FINALIZED_ROOT_GINDEX)
|
||||
else:
|
||||
var fin_header = dag.getExistingLightClientHeader(finalized_bid)
|
||||
if fin_header.kind == LightClientDataFork.None:
|
||||
@ -577,7 +597,9 @@ proc assignLightClientData(
|
||||
else:
|
||||
fin_header.migrateToDataFork(lcDataFork)
|
||||
forkyObject.finalized_header = fin_header.forky(lcDataFork)
|
||||
forkyObject.finality_branch = attested_data.finality_branch
|
||||
forkyObject.finality_branch = normalize_merkle_branch(
|
||||
attested_data.finality_branch,
|
||||
lcDataFork.FINALIZED_ROOT_GINDEX)
|
||||
withForkyObject(obj):
|
||||
when lcDataFork > LightClientDataFork.None:
|
||||
forkyObject.sync_aggregate = sync_aggregate
|
||||
@ -1014,7 +1036,7 @@ proc getLightClientBootstrap(
|
||||
|
||||
# Ensure `current_sync_committee_branch` is known
|
||||
if dag.lcDataStore.importMode == LightClientDataImportMode.OnDemand and
|
||||
not dag.lcDataStore.db.hasCurrentSyncCommitteeBranch(slot):
|
||||
not dag.hasCurrentSyncCommitteeBranch(slot):
|
||||
let
|
||||
bsi = dag.getExistingBlockIdAtSlot(slot).valueOr:
|
||||
return default(ForkedLightClientBootstrap)
|
||||
@ -1022,13 +1044,14 @@ proc getLightClientBootstrap(
|
||||
dag.withUpdatedExistingState(tmpState[], bsi) do:
|
||||
withState(updatedState):
|
||||
when consensusFork >= ConsensusFork.Altair:
|
||||
const lcDataFork = lcDataForkAtConsensusFork(consensusFork)
|
||||
if not dag.lcDataStore.db.hasSyncCommittee(period):
|
||||
dag.lcDataStore.db.putSyncCommittee(
|
||||
period, forkyState.data.current_sync_committee)
|
||||
dag.lcDataStore.db.putHeader(header)
|
||||
dag.lcDataStore.db.putCurrentSyncCommitteeBranch(
|
||||
slot, forkyState.data.build_proof(
|
||||
altair.CURRENT_SYNC_COMMITTEE_GINDEX).get)
|
||||
lcDataFork.CURRENT_SYNC_COMMITTEE_GINDEX).get)
|
||||
else: raiseAssert "Unreachable"
|
||||
do: return default(ForkedLightClientBootstrap)
|
||||
|
||||
@ -1050,7 +1073,8 @@ proc getLightClientBootstrap(
|
||||
debug "LC bootstrap unavailable: Sync committee not cached", period
|
||||
return default(ForkedLightClientBootstrap)),
|
||||
current_sync_committee_branch: (block:
|
||||
dag.lcDataStore.db.getCurrentSyncCommitteeBranch(slot).valueOr:
|
||||
getCurrentSyncCommitteeBranch[lcDataFork.CurrentSyncCommitteeBranch](
|
||||
dag.lcDataStore.db, slot).valueOr:
|
||||
debug "LC bootstrap unavailable: Committee branch not cached", slot
|
||||
return default(ForkedLightClientBootstrap))))
|
||||
|
||||
|
@ -626,14 +626,16 @@ func kzg_commitment_inclusion_proof_gindex*(
|
||||
|
||||
BLOB_KZG_COMMITMENTS_FIRST_GINDEX + index
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/deneb/light-client/sync-protocol.md#modified-get_lc_execution_root
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/deneb/light-client/sync-protocol.md#modified-get_lc_execution_root
|
||||
func get_lc_execution_root*(
|
||||
header: LightClientHeader, cfg: RuntimeConfig): Eth2Digest =
|
||||
let epoch = header.beacon.slot.epoch
|
||||
|
||||
# [New in Deneb]
|
||||
if epoch >= cfg.DENEB_FORK_EPOCH:
|
||||
return hash_tree_root(header.execution)
|
||||
|
||||
# [Modified in Deneb]
|
||||
if epoch >= cfg.CAPELLA_FORK_EPOCH:
|
||||
let execution_header = capella.ExecutionPayloadHeader(
|
||||
parent_hash: header.execution.parent_hash,
|
||||
@ -655,11 +657,12 @@ func get_lc_execution_root*(
|
||||
|
||||
ZERO_HASH
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/deneb/light-client/sync-protocol.md#modified-is_valid_light_client_header
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/deneb/light-client/sync-protocol.md#modified-is_valid_light_client_header
|
||||
func is_valid_light_client_header*(
|
||||
header: LightClientHeader, cfg: RuntimeConfig): bool =
|
||||
let epoch = header.beacon.slot.epoch
|
||||
|
||||
# [New in Deneb:EIP4844]
|
||||
if epoch < cfg.DENEB_FORK_EPOCH:
|
||||
if header.execution.blob_gas_used != 0 or
|
||||
header.execution.excess_blob_gas != 0:
|
||||
|
@ -29,24 +29,25 @@ from stew/bitops2 import log2trunc
|
||||
from stew/byteutils import to0xHex
|
||||
from ./altair import
|
||||
EpochParticipationFlags, InactivityScores, SyncAggregate, SyncCommittee,
|
||||
TrustedSyncAggregate
|
||||
TrustedSyncAggregate, num_active_participants
|
||||
from ./bellatrix import BloomLogs, ExecutionAddress, Transaction
|
||||
from ./capella import
|
||||
HistoricalSummary, SignedBLSToExecutionChangeList, Withdrawal
|
||||
ExecutionBranch, HistoricalSummary, SignedBLSToExecutionChangeList,
|
||||
Withdrawal, EXECUTION_PAYLOAD_GINDEX
|
||||
from ./deneb import Blobs, BlobsBundle, KzgCommitments, KzgProofs
|
||||
|
||||
export json_serialization, base, kzg4844
|
||||
|
||||
const
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/altair/light-client/sync-protocol.md#constants
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/light-client/sync-protocol.md#constants
|
||||
# All of these indices are rooted in `BeaconState`.
|
||||
# The first member (`genesis_time`) is 64, subsequent members +1 each.
|
||||
# If there are ever more than 64 members in `BeaconState`, indices change!
|
||||
# `FINALIZED_ROOT_GINDEX` is one layer deeper, i.e., `84 * 2 + 1`.
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/ssz/merkle-proofs.md
|
||||
FINALIZED_ROOT_GINDEX = 169.GeneralizedIndex # finalized_checkpoint > root
|
||||
CURRENT_SYNC_COMMITTEE_GINDEX = 86.GeneralizedIndex # current_sync_committee
|
||||
NEXT_SYNC_COMMITTEE_GINDEX = 87.GeneralizedIndex # next_sync_committee
|
||||
FINALIZED_ROOT_GINDEX* = 169.GeneralizedIndex # finalized_checkpoint > root
|
||||
CURRENT_SYNC_COMMITTEE_GINDEX* = 86.GeneralizedIndex # current_sync_committee
|
||||
NEXT_SYNC_COMMITTEE_GINDEX* = 87.GeneralizedIndex # next_sync_committee
|
||||
|
||||
type
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/beacon-chain.md#depositrequest
|
||||
@ -182,15 +183,6 @@ type
|
||||
source_pubkey*: ValidatorPubKey
|
||||
target_pubkey*: ValidatorPubKey
|
||||
|
||||
FinalityBranch =
|
||||
array[log2trunc(FINALIZED_ROOT_GINDEX), Eth2Digest]
|
||||
|
||||
CurrentSyncCommitteeBranch =
|
||||
array[log2trunc(CURRENT_SYNC_COMMITTEE_GINDEX), Eth2Digest]
|
||||
|
||||
NextSyncCommitteeBranch =
|
||||
array[log2trunc(NEXT_SYNC_COMMITTEE_GINDEX), Eth2Digest]
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/validator.md#aggregateandproof
|
||||
AggregateAndProof* = object
|
||||
aggregator_index*: uint64 # `ValidatorIndex` after validation
|
||||
@ -202,6 +194,15 @@ type
|
||||
message*: AggregateAndProof
|
||||
signature*: ValidatorSig
|
||||
|
||||
FinalityBranch* =
|
||||
array[log2trunc(FINALIZED_ROOT_GINDEX), Eth2Digest]
|
||||
|
||||
CurrentSyncCommitteeBranch* =
|
||||
array[log2trunc(CURRENT_SYNC_COMMITTEE_GINDEX), Eth2Digest]
|
||||
|
||||
NextSyncCommitteeBranch* =
|
||||
array[log2trunc(NEXT_SYNC_COMMITTEE_GINDEX), Eth2Digest]
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/light-client/sync-protocol.md#modified-lightclientheader
|
||||
LightClientHeader* = object
|
||||
beacon*: BeaconBlockHeader
|
||||
@ -675,6 +676,233 @@ func shortLog*(v: ExecutionPayload): auto =
|
||||
excess_blob_gas: $(v.excess_blob_gas)
|
||||
)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/light-client/sync-protocol.md#modified-get_lc_execution_root
|
||||
func get_lc_execution_root*(
|
||||
header: LightClientHeader, cfg: RuntimeConfig): Eth2Digest =
|
||||
let epoch = header.beacon.slot.epoch
|
||||
|
||||
# [New in Electra]
|
||||
if epoch >= cfg.ELECTRA_FORK_EPOCH:
|
||||
return hash_tree_root(header.execution)
|
||||
|
||||
# [Modified in Electra]
|
||||
if epoch >= cfg.DENEB_FORK_EPOCH:
|
||||
let execution_header = deneb.ExecutionPayloadHeader(
|
||||
parent_hash: header.execution.parent_hash,
|
||||
fee_recipient: header.execution.fee_recipient,
|
||||
state_root: header.execution.state_root,
|
||||
receipts_root: header.execution.receipts_root,
|
||||
logs_bloom: header.execution.logs_bloom,
|
||||
prev_randao: header.execution.prev_randao,
|
||||
block_number: header.execution.block_number,
|
||||
gas_limit: header.execution.gas_limit,
|
||||
gas_used: header.execution.gas_used,
|
||||
timestamp: header.execution.timestamp,
|
||||
extra_data: header.execution.extra_data,
|
||||
base_fee_per_gas: header.execution.base_fee_per_gas,
|
||||
block_hash: header.execution.block_hash,
|
||||
transactions_root: header.execution.transactions_root,
|
||||
withdrawals_root: header.execution.withdrawals_root,
|
||||
blob_gas_used: header.execution.blob_gas_used,
|
||||
excess_blob_gas: header.execution.excess_blob_gas)
|
||||
return hash_tree_root(execution_header)
|
||||
|
||||
if epoch >= cfg.CAPELLA_FORK_EPOCH:
|
||||
let execution_header = capella.ExecutionPayloadHeader(
|
||||
parent_hash: header.execution.parent_hash,
|
||||
fee_recipient: header.execution.fee_recipient,
|
||||
state_root: header.execution.state_root,
|
||||
receipts_root: header.execution.receipts_root,
|
||||
logs_bloom: header.execution.logs_bloom,
|
||||
prev_randao: header.execution.prev_randao,
|
||||
block_number: header.execution.block_number,
|
||||
gas_limit: header.execution.gas_limit,
|
||||
gas_used: header.execution.gas_used,
|
||||
timestamp: header.execution.timestamp,
|
||||
extra_data: header.execution.extra_data,
|
||||
base_fee_per_gas: header.execution.base_fee_per_gas,
|
||||
block_hash: header.execution.block_hash,
|
||||
transactions_root: header.execution.transactions_root,
|
||||
withdrawals_root: header.execution.withdrawals_root)
|
||||
return hash_tree_root(execution_header)
|
||||
|
||||
ZERO_HASH
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/light-client/sync-protocol.md#modified-is_valid_light_client_header
|
||||
func is_valid_light_client_header*(
|
||||
header: LightClientHeader, cfg: RuntimeConfig): bool =
|
||||
let epoch = header.beacon.slot.epoch
|
||||
|
||||
# [New in Electra:EIP6110:EIP7002:EIP7251]
|
||||
if epoch < cfg.ELECTRA_FORK_EPOCH:
|
||||
if not header.execution.deposit_requests_root.isZero or
|
||||
not header.execution.withdrawal_requests_root.isZero or
|
||||
not header.execution.consolidation_requests_root.isZero:
|
||||
return false
|
||||
|
||||
if epoch < cfg.DENEB_FORK_EPOCH:
|
||||
if header.execution.blob_gas_used != 0 or
|
||||
header.execution.excess_blob_gas != 0:
|
||||
return false
|
||||
|
||||
if epoch < cfg.CAPELLA_FORK_EPOCH:
|
||||
return
|
||||
header.execution == default(ExecutionPayloadHeader) and
|
||||
header.execution_branch == default(ExecutionBranch)
|
||||
|
||||
is_valid_merkle_branch(
|
||||
get_lc_execution_root(header, cfg),
|
||||
header.execution_branch,
|
||||
log2trunc(EXECUTION_PAYLOAD_GINDEX),
|
||||
get_subtree_index(EXECUTION_PAYLOAD_GINDEX),
|
||||
header.beacon.body_root)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/light-client/fork.md#normalize_merkle_branch
|
||||
func normalize_merkle_branch*[N](
|
||||
branch: array[N, Eth2Digest],
|
||||
gindex: static GeneralizedIndex): array[log2trunc(gindex), Eth2Digest] =
|
||||
const depth = log2trunc(gindex)
|
||||
var res: array[depth, Eth2Digest]
|
||||
when depth >= branch.len:
|
||||
const num_extra = depth - branch.len
|
||||
res[num_extra ..< depth] = branch
|
||||
else:
|
||||
const num_extra = branch.len - depth
|
||||
for node in branch[0 ..< num_extra]:
|
||||
doAssert node.isZero, "Truncation of Merkle branch cannot lose info"
|
||||
res[0 ..< depth] = branch[num_extra ..< branch.len]
|
||||
res
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/light-client/fork.md#upgrading-light-client-data
|
||||
func upgrade_lc_header_to_electra*(
|
||||
pre: deneb.LightClientHeader): LightClientHeader =
|
||||
LightClientHeader(
|
||||
beacon: pre.beacon,
|
||||
execution: ExecutionPayloadHeader(
|
||||
parent_hash: pre.execution.parent_hash,
|
||||
fee_recipient: pre.execution.fee_recipient,
|
||||
state_root: pre.execution.state_root,
|
||||
receipts_root: pre.execution.receipts_root,
|
||||
logs_bloom: pre.execution.logs_bloom,
|
||||
prev_randao: pre.execution.prev_randao,
|
||||
block_number: pre.execution.block_number,
|
||||
gas_limit: pre.execution.gas_limit,
|
||||
gas_used: pre.execution.gas_used,
|
||||
timestamp: pre.execution.timestamp,
|
||||
extra_data: pre.execution.extra_data,
|
||||
base_fee_per_gas: pre.execution.base_fee_per_gas,
|
||||
block_hash: pre.execution.block_hash,
|
||||
transactions_root: pre.execution.transactions_root,
|
||||
withdrawals_root: pre.execution.withdrawals_root,
|
||||
blob_gas_used: pre.execution.blob_gas_used,
|
||||
excess_blob_gas: pre.execution.blob_gas_used,
|
||||
deposit_requests_root: ZERO_HASH, # [New in Electra:EIP6110]
|
||||
withdrawal_requests_root: ZERO_HASH, # [New in Electra:EIP7002:EIP7251]
|
||||
consolidation_requests_root: ZERO_HASH), # [New in Electra:EIP7251]
|
||||
execution_branch: pre.execution_branch)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/light-client/fork.md#upgrading-light-client-data
|
||||
func upgrade_lc_bootstrap_to_electra*(
|
||||
pre: deneb.LightClientBootstrap): LightClientBootstrap =
|
||||
LightClientBootstrap(
|
||||
header: upgrade_lc_header_to_electra(pre.header),
|
||||
current_sync_committee: pre.current_sync_committee,
|
||||
current_sync_committee_branch: normalize_merkle_branch(
|
||||
pre.current_sync_committee_branch, CURRENT_SYNC_COMMITTEE_GINDEX))
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/light-client/fork.md#upgrading-light-client-data
|
||||
func upgrade_lc_update_to_electra*(
|
||||
pre: deneb.LightClientUpdate): LightClientUpdate =
|
||||
LightClientUpdate(
|
||||
attested_header: upgrade_lc_header_to_electra(pre.attested_header),
|
||||
next_sync_committee: pre.next_sync_committee,
|
||||
next_sync_committee_branch: normalize_merkle_branch(
|
||||
pre.next_sync_committee_branch, NEXT_SYNC_COMMITTEE_GINDEX),
|
||||
finalized_header: upgrade_lc_header_to_electra(pre.finalized_header),
|
||||
finality_branch: normalize_merkle_branch(
|
||||
pre.finality_branch, FINALIZED_ROOT_GINDEX),
|
||||
sync_aggregate: pre.sync_aggregate,
|
||||
signature_slot: pre.signature_slot)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/light-client/fork.md#upgrading-light-client-data
|
||||
func upgrade_lc_finality_update_to_electra*(
|
||||
pre: deneb.LightClientFinalityUpdate): LightClientFinalityUpdate =
|
||||
LightClientFinalityUpdate(
|
||||
attested_header: upgrade_lc_header_to_electra(pre.attested_header),
|
||||
finalized_header: upgrade_lc_header_to_electra(pre.finalized_header),
|
||||
finality_branch: normalize_merkle_branch(
|
||||
pre.finality_branch, FINALIZED_ROOT_GINDEX),
|
||||
sync_aggregate: pre.sync_aggregate,
|
||||
signature_slot: pre.signature_slot)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/light-client/fork.md#upgrading-light-client-data
|
||||
func upgrade_lc_optimistic_update_to_electra*(
|
||||
pre: deneb.LightClientOptimisticUpdate): LightClientOptimisticUpdate =
|
||||
LightClientOptimisticUpdate(
|
||||
attested_header: upgrade_lc_header_to_electra(pre.attested_header),
|
||||
sync_aggregate: pre.sync_aggregate,
|
||||
signature_slot: pre.signature_slot)
|
||||
|
||||
func shortLog*(v: LightClientHeader): auto =
|
||||
(
|
||||
beacon: shortLog(v.beacon),
|
||||
execution: (
|
||||
block_hash: v.execution.block_hash,
|
||||
block_number: v.execution.block_number)
|
||||
)
|
||||
|
||||
func shortLog*(v: LightClientBootstrap): auto =
|
||||
(
|
||||
header: shortLog(v.header)
|
||||
)
|
||||
|
||||
func shortLog*(v: LightClientUpdate): auto =
|
||||
(
|
||||
attested: shortLog(v.attested_header),
|
||||
has_next_sync_committee:
|
||||
v.next_sync_committee != default(typeof(v.next_sync_committee)),
|
||||
finalized: shortLog(v.finalized_header),
|
||||
num_active_participants: v.sync_aggregate.num_active_participants,
|
||||
signature_slot: v.signature_slot
|
||||
)
|
||||
|
||||
func shortLog*(v: LightClientFinalityUpdate): auto =
|
||||
(
|
||||
attested: shortLog(v.attested_header),
|
||||
finalized: shortLog(v.finalized_header),
|
||||
num_active_participants: v.sync_aggregate.num_active_participants,
|
||||
signature_slot: v.signature_slot
|
||||
)
|
||||
|
||||
func shortLog*(v: LightClientOptimisticUpdate): auto =
|
||||
(
|
||||
attested: shortLog(v.attested_header),
|
||||
num_active_participants: v.sync_aggregate.num_active_participants,
|
||||
signature_slot: v.signature_slot,
|
||||
)
|
||||
|
||||
chronicles.formatIt LightClientBootstrap: shortLog(it)
|
||||
chronicles.formatIt LightClientUpdate: shortLog(it)
|
||||
chronicles.formatIt LightClientFinalityUpdate: shortLog(it)
|
||||
chronicles.formatIt LightClientOptimisticUpdate: shortLog(it)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/light-client/fork.md#upgrading-the-store
|
||||
func upgrade_lc_store_to_electra*(
|
||||
pre: deneb.LightClientStore): LightClientStore =
|
||||
let best_valid_update =
|
||||
if pre.best_valid_update.isNone:
|
||||
Opt.none(LightClientUpdate)
|
||||
else:
|
||||
Opt.some upgrade_lc_update_to_electra(pre.best_valid_update.get)
|
||||
LightClientStore(
|
||||
finalized_header: upgrade_lc_header_to_electra(pre.finalized_header),
|
||||
current_sync_committee: pre.current_sync_committee,
|
||||
next_sync_committee: pre.next_sync_committee,
|
||||
best_valid_update: best_valid_update,
|
||||
optimistic_header: upgrade_lc_header_to_electra(pre.optimistic_header),
|
||||
previous_max_active_participants: pre.previous_max_active_participants,
|
||||
current_max_active_participants: pre.current_max_active_participants)
|
||||
|
||||
template asSigned*(
|
||||
x: SigVerifiedSignedBeaconBlock |
|
||||
MsgTrustedSignedBeaconBlock |
|
||||
|
@ -252,6 +252,11 @@ RestJson.useDefaultSerializationFor(
|
||||
electra.ExecutionPayload,
|
||||
electra.ExecutionPayloadHeader,
|
||||
electra.IndexedAttestation,
|
||||
electra.LightClientBootstrap,
|
||||
electra.LightClientFinalityUpdate,
|
||||
electra.LightClientHeader,
|
||||
electra.LightClientOptimisticUpdate,
|
||||
electra.LightClientUpdate,
|
||||
electra.SignedBeaconBlock,
|
||||
electra.TrustedAttestation,
|
||||
electra_mev.BlindedBeaconBlock,
|
||||
|
@ -1325,8 +1325,10 @@ func forkVersion*(cfg: RuntimeConfig, consensusFork: ConsensusFork): Version =
|
||||
|
||||
func lcDataForkAtConsensusFork*(
|
||||
consensusFork: ConsensusFork): LightClientDataFork =
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
||||
if consensusFork >= ConsensusFork.Deneb:
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Electra
|
||||
if consensusFork >= ConsensusFork.Electra:
|
||||
LightClientDataFork.Electra
|
||||
elif consensusFork >= ConsensusFork.Deneb:
|
||||
LightClientDataFork.Deneb
|
||||
elif consensusFork >= ConsensusFork.Capella:
|
||||
LightClientDataFork.Capella
|
||||
|
@ -16,32 +16,42 @@ type
|
||||
None = 0, # only use non-0 in DB to detect accidentally uninitialized data
|
||||
Altair = 1,
|
||||
Capella = 2,
|
||||
Deneb = 3
|
||||
Deneb = 3,
|
||||
Electra = 4
|
||||
|
||||
ForkyCurrentSyncCommitteeBranch* =
|
||||
altair.CurrentSyncCommitteeBranch |
|
||||
electra.CurrentSyncCommitteeBranch
|
||||
|
||||
ForkyLightClientHeader* =
|
||||
altair.LightClientHeader |
|
||||
capella.LightClientHeader |
|
||||
deneb.LightClientHeader
|
||||
deneb.LightClientHeader |
|
||||
electra.LightClientHeader
|
||||
|
||||
ForkyLightClientBootstrap* =
|
||||
altair.LightClientBootstrap |
|
||||
capella.LightClientBootstrap |
|
||||
deneb.LightClientBootstrap
|
||||
deneb.LightClientBootstrap |
|
||||
electra.LightClientBootstrap
|
||||
|
||||
ForkyLightClientUpdate* =
|
||||
altair.LightClientUpdate |
|
||||
capella.LightClientUpdate |
|
||||
deneb.LightClientUpdate
|
||||
deneb.LightClientUpdate |
|
||||
electra.LightClientUpdate
|
||||
|
||||
ForkyLightClientFinalityUpdate* =
|
||||
altair.LightClientFinalityUpdate |
|
||||
capella.LightClientFinalityUpdate |
|
||||
deneb.LightClientFinalityUpdate
|
||||
deneb.LightClientFinalityUpdate |
|
||||
electra.LightClientFinalityUpdate
|
||||
|
||||
ForkyLightClientOptimisticUpdate* =
|
||||
altair.LightClientOptimisticUpdate |
|
||||
capella.LightClientOptimisticUpdate |
|
||||
deneb.LightClientOptimisticUpdate
|
||||
deneb.LightClientOptimisticUpdate |
|
||||
electra.LightClientOptimisticUpdate
|
||||
|
||||
SomeForkyLightClientUpdateWithSyncCommittee* =
|
||||
ForkyLightClientUpdate
|
||||
@ -62,7 +72,8 @@ type
|
||||
ForkyLightClientStore* =
|
||||
altair.LightClientStore |
|
||||
capella.LightClientStore |
|
||||
deneb.LightClientStore
|
||||
deneb.LightClientStore |
|
||||
electra.LightClientStore
|
||||
|
||||
ForkedLightClientHeader* = object
|
||||
case kind*: LightClientDataFork
|
||||
@ -74,6 +85,8 @@ type
|
||||
capellaData*: capella.LightClientHeader
|
||||
of LightClientDataFork.Deneb:
|
||||
denebData*: deneb.LightClientHeader
|
||||
of LightClientDataFork.Electra:
|
||||
electraData*: electra.LightClientHeader
|
||||
|
||||
ForkedLightClientBootstrap* = object
|
||||
case kind*: LightClientDataFork
|
||||
@ -85,6 +98,8 @@ type
|
||||
capellaData*: capella.LightClientBootstrap
|
||||
of LightClientDataFork.Deneb:
|
||||
denebData*: deneb.LightClientBootstrap
|
||||
of LightClientDataFork.Electra:
|
||||
electraData*: electra.LightClientBootstrap
|
||||
|
||||
ForkedLightClientUpdate* = object
|
||||
case kind*: LightClientDataFork
|
||||
@ -96,6 +111,8 @@ type
|
||||
capellaData*: capella.LightClientUpdate
|
||||
of LightClientDataFork.Deneb:
|
||||
denebData*: deneb.LightClientUpdate
|
||||
of LightClientDataFork.Electra:
|
||||
electraData*: electra.LightClientUpdate
|
||||
|
||||
ForkedLightClientFinalityUpdate* = object
|
||||
case kind*: LightClientDataFork
|
||||
@ -107,6 +124,8 @@ type
|
||||
capellaData*: capella.LightClientFinalityUpdate
|
||||
of LightClientDataFork.Deneb:
|
||||
denebData*: deneb.LightClientFinalityUpdate
|
||||
of LightClientDataFork.Electra:
|
||||
electraData*: electra.LightClientFinalityUpdate
|
||||
|
||||
ForkedLightClientOptimisticUpdate* = object
|
||||
case kind*: LightClientDataFork
|
||||
@ -118,6 +137,8 @@ type
|
||||
capellaData*: capella.LightClientOptimisticUpdate
|
||||
of LightClientDataFork.Deneb:
|
||||
denebData*: deneb.LightClientOptimisticUpdate
|
||||
of LightClientDataFork.Electra:
|
||||
electraData*: electra.LightClientOptimisticUpdate
|
||||
|
||||
SomeForkedLightClientUpdateWithSyncCommittee* =
|
||||
ForkedLightClientUpdate
|
||||
@ -145,11 +166,15 @@ type
|
||||
capellaData*: capella.LightClientStore
|
||||
of LightClientDataFork.Deneb:
|
||||
denebData*: deneb.LightClientStore
|
||||
of LightClientDataFork.Electra:
|
||||
electraData*: electra.LightClientStore
|
||||
|
||||
func lcDataForkAtEpoch*(
|
||||
cfg: RuntimeConfig, epoch: Epoch): LightClientDataFork =
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
||||
if epoch >= cfg.DENEB_FORK_EPOCH:
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Electra
|
||||
if epoch >= cfg.ELECTRA_FORK_EPOCH:
|
||||
LightClientDataFork.Electra
|
||||
elif epoch >= cfg.DENEB_FORK_EPOCH:
|
||||
LightClientDataFork.Deneb
|
||||
elif epoch >= cfg.CAPELLA_FORK_EPOCH:
|
||||
LightClientDataFork.Capella
|
||||
@ -188,8 +213,71 @@ template kind*(
|
||||
deneb.LightClientStore]): LightClientDataFork =
|
||||
LightClientDataFork.Deneb
|
||||
|
||||
template kind*(
|
||||
x: typedesc[ # `SomeLightClientObject` doesn't work here (Nim 1.6)
|
||||
electra.LightClientHeader |
|
||||
electra.LightClientBootstrap |
|
||||
electra.LightClientUpdate |
|
||||
electra.LightClientFinalityUpdate |
|
||||
electra.LightClientOptimisticUpdate |
|
||||
electra.LightClientStore]): LightClientDataFork =
|
||||
LightClientDataFork.Electra
|
||||
|
||||
template FINALIZED_ROOT_GINDEX*(
|
||||
kind: static LightClientDataFork): GeneralizedIndex =
|
||||
when kind >= LightClientDataFork.Electra:
|
||||
electra.FINALIZED_ROOT_GINDEX
|
||||
elif kind >= LightClientDataFork.Altair:
|
||||
altair.FINALIZED_ROOT_GINDEX
|
||||
else:
|
||||
static: raiseAssert "Unreachable"
|
||||
|
||||
template FinalityBranch*(kind: static LightClientDataFork): auto =
|
||||
when kind >= LightClientDataFork.Electra:
|
||||
typedesc[electra.FinalityBranch]
|
||||
elif kind >= LightClientDataFork.Altair:
|
||||
typedesc[altair.FinalityBranch]
|
||||
else:
|
||||
static: raiseAssert "Unreachable"
|
||||
|
||||
template CURRENT_SYNC_COMMITTEE_GINDEX*(
|
||||
kind: static LightClientDataFork): GeneralizedIndex =
|
||||
when kind >= LightClientDataFork.Electra:
|
||||
electra.CURRENT_SYNC_COMMITTEE_GINDEX
|
||||
elif kind >= LightClientDataFork.Altair:
|
||||
altair.CURRENT_SYNC_COMMITTEE_GINDEX
|
||||
else:
|
||||
static: raiseAssert "Unreachable"
|
||||
|
||||
template CurrentSyncCommitteeBranch*(kind: static LightClientDataFork): auto =
|
||||
when kind >= LightClientDataFork.Electra:
|
||||
typedesc[electra.CurrentSyncCommitteeBranch]
|
||||
elif kind >= LightClientDataFork.Altair:
|
||||
typedesc[altair.CurrentSyncCommitteeBranch]
|
||||
else:
|
||||
static: raiseAssert "Unreachable"
|
||||
|
||||
template NEXT_SYNC_COMMITTEE_GINDEX*(
|
||||
kind: static LightClientDataFork): GeneralizedIndex =
|
||||
when kind >= LightClientDataFork.Electra:
|
||||
electra.NEXT_SYNC_COMMITTEE_GINDEX
|
||||
elif kind >= LightClientDataFork.Altair:
|
||||
altair.NEXT_SYNC_COMMITTEE_GINDEX
|
||||
else:
|
||||
static: raiseAssert "Unreachable"
|
||||
|
||||
template NextSyncCommitteeBranch*(kind: static LightClientDataFork): auto =
|
||||
when kind >= LightClientDataFork.Electra:
|
||||
typedesc[electra.NextSyncCommitteeBranch]
|
||||
elif kind >= LightClientDataFork.Altair:
|
||||
typedesc[altair.NextSyncCommitteeBranch]
|
||||
else:
|
||||
static: raiseAssert "Unreachable"
|
||||
|
||||
template LightClientHeader*(kind: static LightClientDataFork): auto =
|
||||
when kind == LightClientDataFork.Deneb:
|
||||
when kind == LightClientDataFork.Electra:
|
||||
typedesc[electra.LightClientHeader]
|
||||
elif kind == LightClientDataFork.Deneb:
|
||||
typedesc[deneb.LightClientHeader]
|
||||
elif kind == LightClientDataFork.Capella:
|
||||
typedesc[capella.LightClientHeader]
|
||||
@ -199,7 +287,9 @@ template LightClientHeader*(kind: static LightClientDataFork): auto =
|
||||
static: raiseAssert "Unreachable"
|
||||
|
||||
template LightClientBootstrap*(kind: static LightClientDataFork): auto =
|
||||
when kind == LightClientDataFork.Deneb:
|
||||
when kind == LightClientDataFork.Electra:
|
||||
typedesc[electra.LightClientBootstrap]
|
||||
elif kind == LightClientDataFork.Deneb:
|
||||
typedesc[deneb.LightClientBootstrap]
|
||||
elif kind == LightClientDataFork.Capella:
|
||||
typedesc[capella.LightClientBootstrap]
|
||||
@ -209,7 +299,9 @@ template LightClientBootstrap*(kind: static LightClientDataFork): auto =
|
||||
static: raiseAssert "Unreachable"
|
||||
|
||||
template LightClientUpdate*(kind: static LightClientDataFork): auto =
|
||||
when kind == LightClientDataFork.Deneb:
|
||||
when kind == LightClientDataFork.Electra:
|
||||
typedesc[electra.LightClientUpdate]
|
||||
elif kind == LightClientDataFork.Deneb:
|
||||
typedesc[deneb.LightClientUpdate]
|
||||
elif kind == LightClientDataFork.Capella:
|
||||
typedesc[capella.LightClientUpdate]
|
||||
@ -219,7 +311,9 @@ template LightClientUpdate*(kind: static LightClientDataFork): auto =
|
||||
static: raiseAssert "Unreachable"
|
||||
|
||||
template LightClientFinalityUpdate*(kind: static LightClientDataFork): auto =
|
||||
when kind == LightClientDataFork.Deneb:
|
||||
when kind == LightClientDataFork.Electra:
|
||||
typedesc[electra.LightClientFinalityUpdate]
|
||||
elif kind == LightClientDataFork.Deneb:
|
||||
typedesc[deneb.LightClientFinalityUpdate]
|
||||
elif kind == LightClientDataFork.Capella:
|
||||
typedesc[capella.LightClientFinalityUpdate]
|
||||
@ -229,7 +323,9 @@ template LightClientFinalityUpdate*(kind: static LightClientDataFork): auto =
|
||||
static: raiseAssert "Unreachable"
|
||||
|
||||
template LightClientOptimisticUpdate*(kind: static LightClientDataFork): auto =
|
||||
when kind == LightClientDataFork.Deneb:
|
||||
when kind == LightClientDataFork.Electra:
|
||||
typedesc[electra.LightClientOptimisticUpdate]
|
||||
elif kind == LightClientDataFork.Deneb:
|
||||
typedesc[deneb.LightClientOptimisticUpdate]
|
||||
elif kind == LightClientDataFork.Capella:
|
||||
typedesc[capella.LightClientOptimisticUpdate]
|
||||
@ -239,7 +335,9 @@ template LightClientOptimisticUpdate*(kind: static LightClientDataFork): auto =
|
||||
static: raiseAssert "Unreachable"
|
||||
|
||||
template LightClientStore*(kind: static LightClientDataFork): auto =
|
||||
when kind == LightClientDataFork.Deneb:
|
||||
when kind == LightClientDataFork.Electra:
|
||||
typedesc[electra.LightClientStore]
|
||||
elif kind == LightClientDataFork.Deneb:
|
||||
typedesc[deneb.LightClientStore]
|
||||
elif kind == LightClientDataFork.Capella:
|
||||
typedesc[capella.LightClientStore]
|
||||
@ -298,7 +396,10 @@ template Forked*(x: typedesc[ForkyLightClientStore]): auto =
|
||||
|
||||
template withAll*(
|
||||
x: typedesc[LightClientDataFork], body: untyped): untyped =
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Electra
|
||||
block:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Electra
|
||||
body
|
||||
block:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
||||
body
|
||||
@ -315,6 +416,9 @@ template withAll*(
|
||||
template withLcDataFork*(
|
||||
x: LightClientDataFork, body: untyped): untyped =
|
||||
case x
|
||||
of LightClientDataFork.Electra:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Electra
|
||||
body
|
||||
of LightClientDataFork.Deneb:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
||||
body
|
||||
@ -331,6 +435,10 @@ template withLcDataFork*(
|
||||
template withForkyHeader*(
|
||||
x: ForkedLightClientHeader, body: untyped): untyped =
|
||||
case x.kind
|
||||
of LightClientDataFork.Electra:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Electra
|
||||
template forkyHeader: untyped {.inject, used.} = x.electraData
|
||||
body
|
||||
of LightClientDataFork.Deneb:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
||||
template forkyHeader: untyped {.inject, used.} = x.denebData
|
||||
@ -350,6 +458,10 @@ template withForkyHeader*(
|
||||
template withForkyBootstrap*(
|
||||
x: ForkedLightClientBootstrap, body: untyped): untyped =
|
||||
case x.kind
|
||||
of LightClientDataFork.Electra:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Electra
|
||||
template forkyBootstrap: untyped {.inject, used.} = x.electraData
|
||||
body
|
||||
of LightClientDataFork.Deneb:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
||||
template forkyBootstrap: untyped {.inject, used.} = x.denebData
|
||||
@ -369,6 +481,10 @@ template withForkyBootstrap*(
|
||||
template withForkyUpdate*(
|
||||
x: ForkedLightClientUpdate, body: untyped): untyped =
|
||||
case x.kind
|
||||
of LightClientDataFork.Electra:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Electra
|
||||
template forkyUpdate: untyped {.inject, used.} = x.electraData
|
||||
body
|
||||
of LightClientDataFork.Deneb:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
||||
template forkyUpdate: untyped {.inject, used.} = x.denebData
|
||||
@ -388,6 +504,10 @@ template withForkyUpdate*(
|
||||
template withForkyFinalityUpdate*(
|
||||
x: ForkedLightClientFinalityUpdate, body: untyped): untyped =
|
||||
case x.kind
|
||||
of LightClientDataFork.Electra:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Electra
|
||||
template forkyFinalityUpdate: untyped {.inject, used.} = x.electraData
|
||||
body
|
||||
of LightClientDataFork.Deneb:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
||||
template forkyFinalityUpdate: untyped {.inject, used.} = x.denebData
|
||||
@ -407,6 +527,10 @@ template withForkyFinalityUpdate*(
|
||||
template withForkyOptimisticUpdate*(
|
||||
x: ForkedLightClientOptimisticUpdate, body: untyped): untyped =
|
||||
case x.kind
|
||||
of LightClientDataFork.Electra:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Electra
|
||||
template forkyOptimisticUpdate: untyped {.inject, used.} = x.electraData
|
||||
body
|
||||
of LightClientDataFork.Deneb:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
||||
template forkyOptimisticUpdate: untyped {.inject, used.} = x.denebData
|
||||
@ -426,6 +550,10 @@ template withForkyOptimisticUpdate*(
|
||||
template withForkyObject*(
|
||||
x: SomeForkedLightClientObject, body: untyped): untyped =
|
||||
case x.kind
|
||||
of LightClientDataFork.Electra:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Electra
|
||||
template forkyObject: untyped {.inject, used.} = x.electraData
|
||||
body
|
||||
of LightClientDataFork.Deneb:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
||||
template forkyObject: untyped {.inject, used.} = x.denebData
|
||||
@ -445,6 +573,10 @@ template withForkyObject*(
|
||||
template withForkyStore*(
|
||||
x: ForkedLightClientStore, body: untyped): untyped =
|
||||
case x.kind
|
||||
of LightClientDataFork.Electra:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Electra
|
||||
template forkyStore: untyped {.inject, used.} = x.electraData
|
||||
body
|
||||
of LightClientDataFork.Deneb:
|
||||
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
||||
template forkyStore: untyped {.inject, used.} = x.denebData
|
||||
@ -473,7 +605,9 @@ func init*(
|
||||
type ResultType = typeof(forkyData).Forked
|
||||
static: doAssert ResultType is x
|
||||
const kind = typeof(forkyData).kind
|
||||
when kind == LightClientDataFork.Deneb:
|
||||
when kind == LightClientDataFork.Electra:
|
||||
ResultType(kind: kind, electraData: forkyData)
|
||||
elif kind == LightClientDataFork.Deneb:
|
||||
ResultType(kind: kind, denebData: forkyData)
|
||||
elif kind == LightClientDataFork.Capella:
|
||||
ResultType(kind: kind, capellaData: forkyData)
|
||||
@ -488,7 +622,9 @@ template forky*(
|
||||
SomeForkedLightClientObject |
|
||||
ForkedLightClientStore,
|
||||
kind: static LightClientDataFork): untyped =
|
||||
when kind == LightClientDataFork.Deneb:
|
||||
when kind == LightClientDataFork.Electra:
|
||||
x.electraData
|
||||
elif kind == LightClientDataFork.Deneb:
|
||||
x.denebData
|
||||
elif kind == LightClientDataFork.Capella:
|
||||
x.capellaData
|
||||
@ -641,7 +777,15 @@ func migrateToDataFork*(
|
||||
denebData: upgrade_lc_header_to_deneb(
|
||||
x.forky(LightClientDataFork.Capella)))
|
||||
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
||||
# Upgrade to Electra
|
||||
when newKind >= LightClientDataFork.Electra:
|
||||
if x.kind == LightClientDataFork.Deneb:
|
||||
x = ForkedLightClientHeader(
|
||||
kind: LightClientDataFork.Electra,
|
||||
electraData: upgrade_lc_header_to_electra(
|
||||
x.forky(LightClientDataFork.Deneb)))
|
||||
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Electra
|
||||
doAssert x.kind == newKind
|
||||
|
||||
func migrateToDataFork*(
|
||||
@ -676,7 +820,15 @@ func migrateToDataFork*(
|
||||
denebData: upgrade_lc_bootstrap_to_deneb(
|
||||
x.forky(LightClientDataFork.Capella)))
|
||||
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
||||
# Upgrade to Electra
|
||||
when newKind >= LightClientDataFork.Electra:
|
||||
if x.kind == LightClientDataFork.Deneb:
|
||||
x = ForkedLightClientBootstrap(
|
||||
kind: LightClientDataFork.Electra,
|
||||
electraData: upgrade_lc_bootstrap_to_electra(
|
||||
x.forky(LightClientDataFork.Deneb)))
|
||||
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Electra
|
||||
doAssert x.kind == newKind
|
||||
|
||||
func migrateToDataFork*(
|
||||
@ -711,7 +863,15 @@ func migrateToDataFork*(
|
||||
denebData: upgrade_lc_update_to_deneb(
|
||||
x.forky(LightClientDataFork.Capella)))
|
||||
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
||||
# Upgrade to Electra
|
||||
when newKind >= LightClientDataFork.Electra:
|
||||
if x.kind == LightClientDataFork.Deneb:
|
||||
x = ForkedLightClientUpdate(
|
||||
kind: LightClientDataFork.Electra,
|
||||
electraData: upgrade_lc_update_to_electra(
|
||||
x.forky(LightClientDataFork.Deneb)))
|
||||
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Electra
|
||||
doAssert x.kind == newKind
|
||||
|
||||
func migrateToDataFork*(
|
||||
@ -746,7 +906,15 @@ func migrateToDataFork*(
|
||||
denebData: upgrade_lc_finality_update_to_deneb(
|
||||
x.forky(LightClientDataFork.Capella)))
|
||||
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
||||
# Upgrade to Electra
|
||||
when newKind >= LightClientDataFork.Electra:
|
||||
if x.kind == LightClientDataFork.Deneb:
|
||||
x = ForkedLightClientFinalityUpdate(
|
||||
kind: LightClientDataFork.Electra,
|
||||
electraData: upgrade_lc_finality_update_to_electra(
|
||||
x.forky(LightClientDataFork.Deneb)))
|
||||
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Electra
|
||||
doAssert x.kind == newKind
|
||||
|
||||
func migrateToDataFork*(
|
||||
@ -781,7 +949,15 @@ func migrateToDataFork*(
|
||||
denebData: upgrade_lc_optimistic_update_to_deneb(
|
||||
x.forky(LightClientDataFork.Capella)))
|
||||
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
||||
# Upgrade to Electra
|
||||
when newKind >= LightClientDataFork.Electra:
|
||||
if x.kind == LightClientDataFork.Deneb:
|
||||
x = ForkedLightClientOptimisticUpdate(
|
||||
kind: LightClientDataFork.Electra,
|
||||
electraData: upgrade_lc_optimistic_update_to_electra(
|
||||
x.forky(LightClientDataFork.Deneb)))
|
||||
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Electra
|
||||
doAssert x.kind == newKind
|
||||
|
||||
func migrateToDataFork*(
|
||||
@ -816,7 +992,15 @@ func migrateToDataFork*(
|
||||
denebData: upgrade_lc_store_to_deneb(
|
||||
x.forky(LightClientDataFork.Capella)))
|
||||
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
||||
# Upgrade to Electra
|
||||
when newKind >= LightClientDataFork.Electra:
|
||||
if x.kind == LightClientDataFork.Deneb:
|
||||
x = ForkedLightClientStore(
|
||||
kind: LightClientDataFork.Electra,
|
||||
electraData: upgrade_lc_store_to_electra(
|
||||
x.forky(LightClientDataFork.Deneb)))
|
||||
|
||||
static: doAssert LightClientDataFork.high == LightClientDataFork.Electra
|
||||
doAssert x.kind == newKind
|
||||
|
||||
func migratingToDataFork*[
|
||||
@ -951,6 +1135,108 @@ func toDenebLightClientHeader(
|
||||
execution_branch: blck.message.body.build_proof(
|
||||
capella.EXECUTION_PAYLOAD_GINDEX).get)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/light-client/full-node.md#modified-block_to_light_client_header
|
||||
func toElectraLightClientHeader(
|
||||
blck: # `SomeSignedBeaconBlock` doesn't work here (Nim 1.6)
|
||||
phase0.SignedBeaconBlock | phase0.TrustedSignedBeaconBlock |
|
||||
altair.SignedBeaconBlock | altair.TrustedSignedBeaconBlock |
|
||||
bellatrix.SignedBeaconBlock | bellatrix.TrustedSignedBeaconBlock
|
||||
): electra.LightClientHeader =
|
||||
# Note that during fork transitions, `finalized_header` may still
|
||||
# point to earlier forks. While Bellatrix blocks also contain an
|
||||
# `ExecutionPayload` (minus `withdrawals_root`), it was not included
|
||||
# in the corresponding light client data. To ensure compatibility
|
||||
# with legacy data going through `upgrade_lc_header_to_capella`,
|
||||
# leave out execution data.
|
||||
electra.LightClientHeader(
|
||||
beacon: blck.message.toBeaconBlockHeader())
|
||||
|
||||
func toElectraLightClientHeader(
|
||||
blck: # `SomeSignedBeaconBlock` doesn't work here (Nim 1.6)
|
||||
capella.SignedBeaconBlock | capella.TrustedSignedBeaconBlock
|
||||
): electra.LightClientHeader =
|
||||
template payload: untyped = blck.message.body.execution_payload
|
||||
electra.LightClientHeader(
|
||||
beacon: blck.message.toBeaconBlockHeader(),
|
||||
execution: electra.ExecutionPayloadHeader(
|
||||
parent_hash: payload.parent_hash,
|
||||
fee_recipient: payload.fee_recipient,
|
||||
state_root: payload.state_root,
|
||||
receipts_root: payload.receipts_root,
|
||||
logs_bloom: payload.logs_bloom,
|
||||
prev_randao: payload.prev_randao,
|
||||
block_number: payload.block_number,
|
||||
gas_limit: payload.gas_limit,
|
||||
gas_used: payload.gas_used,
|
||||
timestamp: payload.timestamp,
|
||||
extra_data: payload.extra_data,
|
||||
base_fee_per_gas: payload.base_fee_per_gas,
|
||||
block_hash: payload.block_hash,
|
||||
transactions_root: hash_tree_root(payload.transactions),
|
||||
withdrawals_root: hash_tree_root(payload.withdrawals)),
|
||||
execution_branch: blck.message.body.build_proof(
|
||||
capella.EXECUTION_PAYLOAD_GINDEX).get)
|
||||
|
||||
func toElectraLightClientHeader(
|
||||
blck: # `SomeSignedBeaconBlock` doesn't work here (Nim 1.6)
|
||||
deneb.SignedBeaconBlock | deneb.TrustedSignedBeaconBlock
|
||||
): electra.LightClientHeader =
|
||||
template payload: untyped = blck.message.body.execution_payload
|
||||
electra.LightClientHeader(
|
||||
beacon: blck.message.toBeaconBlockHeader(),
|
||||
execution: electra.ExecutionPayloadHeader(
|
||||
parent_hash: payload.parent_hash,
|
||||
fee_recipient: payload.fee_recipient,
|
||||
state_root: payload.state_root,
|
||||
receipts_root: payload.receipts_root,
|
||||
logs_bloom: payload.logs_bloom,
|
||||
prev_randao: payload.prev_randao,
|
||||
block_number: payload.block_number,
|
||||
gas_limit: payload.gas_limit,
|
||||
gas_used: payload.gas_used,
|
||||
timestamp: payload.timestamp,
|
||||
extra_data: payload.extra_data,
|
||||
base_fee_per_gas: payload.base_fee_per_gas,
|
||||
block_hash: payload.block_hash,
|
||||
transactions_root: hash_tree_root(payload.transactions),
|
||||
withdrawals_root: hash_tree_root(payload.withdrawals),
|
||||
blob_gas_used: payload.blob_gas_used,
|
||||
excess_blob_gas: payload.excess_blob_gas),
|
||||
execution_branch: blck.message.body.build_proof(
|
||||
capella.EXECUTION_PAYLOAD_GINDEX).get)
|
||||
|
||||
func toElectraLightClientHeader(
|
||||
blck: # `SomeSignedBeaconBlock` doesn't work here (Nim 1.6)
|
||||
electra.SignedBeaconBlock | electra.TrustedSignedBeaconBlock
|
||||
): electra.LightClientHeader =
|
||||
template payload: untyped = blck.message.body.execution_payload
|
||||
electra.LightClientHeader(
|
||||
beacon: blck.message.toBeaconBlockHeader(),
|
||||
execution: electra.ExecutionPayloadHeader(
|
||||
parent_hash: payload.parent_hash,
|
||||
fee_recipient: payload.fee_recipient,
|
||||
state_root: payload.state_root,
|
||||
receipts_root: payload.receipts_root,
|
||||
logs_bloom: payload.logs_bloom,
|
||||
prev_randao: payload.prev_randao,
|
||||
block_number: payload.block_number,
|
||||
gas_limit: payload.gas_limit,
|
||||
gas_used: payload.gas_used,
|
||||
timestamp: payload.timestamp,
|
||||
extra_data: payload.extra_data,
|
||||
base_fee_per_gas: payload.base_fee_per_gas,
|
||||
block_hash: payload.block_hash,
|
||||
transactions_root: hash_tree_root(payload.transactions),
|
||||
withdrawals_root: hash_tree_root(payload.withdrawals),
|
||||
blob_gas_used: payload.blob_gas_used,
|
||||
excess_blob_gas: payload.excess_blob_gas,
|
||||
deposit_requests_root: hash_tree_root(payload.deposit_requests),
|
||||
withdrawal_requests_root: hash_tree_root(payload.withdrawal_requests),
|
||||
consolidation_requests_root:
|
||||
hash_tree_root(payload.consolidation_requests)),
|
||||
execution_branch: blck.message.body.build_proof(
|
||||
capella.EXECUTION_PAYLOAD_GINDEX).get)
|
||||
|
||||
func toLightClientHeader*(
|
||||
blck: # `SomeSignedBeaconBlock` doesn't work here (Nim 1.6)
|
||||
phase0.SignedBeaconBlock | phase0.TrustedSignedBeaconBlock |
|
||||
@ -960,9 +1246,8 @@ func toLightClientHeader*(
|
||||
deneb.SignedBeaconBlock | deneb.TrustedSignedBeaconBlock |
|
||||
electra.SignedBeaconBlock | electra.TrustedSignedBeaconBlock,
|
||||
kind: static LightClientDataFork): auto =
|
||||
when blck is electra.SignedBeaconBlock or blck is electra.TrustedSignedBeaconBlock:
|
||||
debugComment "toLightClientHeader electra missing"
|
||||
default(deneb.LightClientHeader)
|
||||
when kind == LightClientDataFork.Electra:
|
||||
blck.toElectraLightClientHeader()
|
||||
elif kind == LightClientDataFork.Deneb:
|
||||
blck.toDenebLightClientHeader()
|
||||
elif kind == LightClientDataFork.Capella:
|
||||
@ -990,9 +1275,13 @@ func shortLog*[
|
||||
capellaData: typeof(x.capellaData.shortLog())
|
||||
of LightClientDataFork.Deneb:
|
||||
denebData: typeof(x.denebData.shortLog())
|
||||
of LightClientDataFork.Electra:
|
||||
electraData: typeof(x.electraData.shortLog())
|
||||
|
||||
let xKind = x.kind # Nim 1.6.12: Using `kind: x.kind` inside case is broken
|
||||
case xKind
|
||||
of LightClientDataFork.Electra:
|
||||
ResultType(kind: xKind, electraData: x.electraData.shortLog())
|
||||
of LightClientDataFork.Deneb:
|
||||
ResultType(kind: xKind, denebData: x.denebData.shortLog())
|
||||
of LightClientDataFork.Capella:
|
||||
|
@ -15,6 +15,21 @@ import
|
||||
from ../consensus_object_pools/block_pools_types import VerifierError
|
||||
export block_pools_types.VerifierError
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/light-client/sync-protocol.md#is_valid_normalized_merkle_branch
|
||||
func is_valid_normalized_merkle_branch[N](
|
||||
leaf: Eth2Digest,
|
||||
branch: array[N, Eth2Digest],
|
||||
gindex: static GeneralizedIndex,
|
||||
root: Eth2Digest): bool =
|
||||
const
|
||||
depth = log2trunc(gindex)
|
||||
index = get_subtree_index(gindex)
|
||||
num_extra = branch.len - depth
|
||||
for i in 0 ..< num_extra:
|
||||
if not branch[i].isZero:
|
||||
return false
|
||||
is_valid_merkle_branch(leaf, branch[num_extra .. ^1], depth, index, root)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/altair/light-client/sync-protocol.md#initialize_light_client_store
|
||||
func initialize_light_client_store*(
|
||||
trusted_block_root: Eth2Digest,
|
||||
@ -29,13 +44,15 @@ func initialize_light_client_store*(
|
||||
if hash_tree_root(bootstrap.header.beacon) != trusted_block_root:
|
||||
return ResultType.err(VerifierError.Invalid)
|
||||
|
||||
if not is_valid_merkle_branch(
|
||||
hash_tree_root(bootstrap.current_sync_committee),
|
||||
bootstrap.current_sync_committee_branch,
|
||||
log2trunc(altair.CURRENT_SYNC_COMMITTEE_GINDEX),
|
||||
get_subtree_index(altair.CURRENT_SYNC_COMMITTEE_GINDEX),
|
||||
bootstrap.header.beacon.state_root):
|
||||
return ResultType.err(VerifierError.Invalid)
|
||||
withLcDataFork(lcDataForkAtConsensusFork(
|
||||
cfg.consensusForkAtEpoch(bootstrap.header.beacon.slot.epoch))):
|
||||
when lcDataFork > LightClientDataFork.None:
|
||||
if not is_valid_normalized_merkle_branch(
|
||||
hash_tree_root(bootstrap.current_sync_committee),
|
||||
bootstrap.current_sync_committee_branch,
|
||||
lcDataFork.CURRENT_SYNC_COMMITTEE_GINDEX,
|
||||
bootstrap.header.beacon.state_root):
|
||||
return ResultType.err(VerifierError.Invalid)
|
||||
|
||||
return ResultType.ok(typeof(bootstrap).kind.LightClientStore(
|
||||
finalized_header: bootstrap.header,
|
||||
@ -109,13 +126,15 @@ proc validate_light_client_update*(
|
||||
finalized_root.reset()
|
||||
else:
|
||||
return err(VerifierError.Invalid)
|
||||
if not is_valid_merkle_branch(
|
||||
finalized_root,
|
||||
update.finality_branch,
|
||||
log2trunc(altair.FINALIZED_ROOT_GINDEX),
|
||||
get_subtree_index(altair.FINALIZED_ROOT_GINDEX),
|
||||
update.attested_header.beacon.state_root):
|
||||
return err(VerifierError.Invalid)
|
||||
withLcDataFork(lcDataForkAtConsensusFork(
|
||||
cfg.consensusForkAtEpoch(update.attested_header.beacon.slot.epoch))):
|
||||
when lcDataFork > LightClientDataFork.None:
|
||||
if not is_valid_normalized_merkle_branch(
|
||||
finalized_root,
|
||||
update.finality_branch,
|
||||
lcDataFork.FINALIZED_ROOT_GINDEX,
|
||||
update.attested_header.beacon.state_root):
|
||||
return err(VerifierError.Invalid)
|
||||
|
||||
# Verify that the `next_sync_committee`, if present, actually is the
|
||||
# next sync committee saved in the state of the `attested_header`
|
||||
@ -128,13 +147,15 @@ proc validate_light_client_update*(
|
||||
if attested_period == store_period and is_next_sync_committee_known:
|
||||
if update.next_sync_committee != store.next_sync_committee:
|
||||
return err(VerifierError.UnviableFork)
|
||||
if not is_valid_merkle_branch(
|
||||
hash_tree_root(update.next_sync_committee),
|
||||
update.next_sync_committee_branch,
|
||||
log2trunc(altair.NEXT_SYNC_COMMITTEE_GINDEX),
|
||||
get_subtree_index(altair.NEXT_SYNC_COMMITTEE_GINDEX),
|
||||
update.attested_header.beacon.state_root):
|
||||
return err(VerifierError.Invalid)
|
||||
withLcDataFork(lcDataForkAtConsensusFork(
|
||||
cfg.consensusForkAtEpoch(update.attested_header.beacon.slot.epoch))):
|
||||
when lcDataFork > LightClientDataFork.None:
|
||||
if not is_valid_normalized_merkle_branch(
|
||||
hash_tree_root(update.next_sync_committee),
|
||||
update.next_sync_committee_branch,
|
||||
lcDataFork.NEXT_SYNC_COMMITTEE_GINDEX,
|
||||
update.attested_header.beacon.state_root):
|
||||
return err(VerifierError.Invalid)
|
||||
|
||||
# Verify sync committee aggregate signature
|
||||
let sync_committee =
|
||||
|
@ -172,14 +172,15 @@ proc runTest(storeDataFork: static LightClientDataFork) =
|
||||
# Sync committee signing the attested_header
|
||||
(sync_aggregate, signature_slot) = get_sync_aggregate(cfg, forked[])
|
||||
next_sync_committee = SyncCommittee()
|
||||
next_sync_committee_branch = default(altair.NextSyncCommitteeBranch)
|
||||
next_sync_committee_branch =
|
||||
default(storeDataFork.NextSyncCommitteeBranch)
|
||||
|
||||
# Ensure that finality checkpoint is genesis
|
||||
check state.finalized_checkpoint.epoch == 0
|
||||
# Finality is unchanged
|
||||
let
|
||||
finality_header = default(storeDataFork.LightClientHeader)
|
||||
finality_branch = default(altair.FinalityBranch)
|
||||
finality_branch = default(storeDataFork.FinalityBranch)
|
||||
|
||||
update = storeDataFork.LightClientUpdate(
|
||||
attested_header: attested_header,
|
||||
@ -228,11 +229,12 @@ proc runTest(storeDataFork: static LightClientDataFork) =
|
||||
# Sync committee signing the attested_header
|
||||
(sync_aggregate, signature_slot) = get_sync_aggregate(cfg, forked[])
|
||||
next_sync_committee = SyncCommittee()
|
||||
next_sync_committee_branch = default(altair.NextSyncCommitteeBranch)
|
||||
next_sync_committee_branch =
|
||||
default(storeDataFork.NextSyncCommitteeBranch)
|
||||
|
||||
# Finality is unchanged
|
||||
finality_header = default(storeDataFork.LightClientHeader)
|
||||
finality_branch = default(altair.FinalityBranch)
|
||||
finality_branch = default(storeDataFork.FinalityBranch)
|
||||
|
||||
update = storeDataFork.LightClientUpdate(
|
||||
attested_header: attested_header,
|
||||
@ -283,12 +285,13 @@ proc runTest(storeDataFork: static LightClientDataFork) =
|
||||
# Sync committee is updated
|
||||
template next_sync_committee(): auto = state.next_sync_committee
|
||||
let
|
||||
next_sync_committee_branch =
|
||||
state.build_proof(altair.NEXT_SYNC_COMMITTEE_GINDEX).get
|
||||
next_sync_committee_branch = normalize_merkle_branch(
|
||||
state.build_proof(altair.NEXT_SYNC_COMMITTEE_GINDEX).get,
|
||||
storeDataFork.NEXT_SYNC_COMMITTEE_GINDEX)
|
||||
|
||||
# Finality is unchanged
|
||||
finality_header = default(storeDataFork.LightClientHeader)
|
||||
finality_branch = default(altair.FinalityBranch)
|
||||
finality_branch = default(storeDataFork.FinalityBranch)
|
||||
|
||||
update = storeDataFork.LightClientUpdate(
|
||||
attested_header: attested_header,
|
||||
@ -345,7 +348,8 @@ proc runTest(storeDataFork: static LightClientDataFork) =
|
||||
|
||||
# Updated sync_committee and finality
|
||||
next_sync_committee = SyncCommittee()
|
||||
next_sync_committee_branch = default(altair.NextSyncCommitteeBranch)
|
||||
next_sync_committee_branch =
|
||||
default(storeDataFork.NextSyncCommitteeBranch)
|
||||
finalized_block = blocks[SLOTS_PER_EPOCH - 1].altairData
|
||||
finalized_header = finalized_block.toLightClientHeader(storeDataFork)
|
||||
check:
|
||||
@ -354,7 +358,9 @@ proc runTest(storeDataFork: static LightClientDataFork) =
|
||||
finalized_header.beacon.hash_tree_root() ==
|
||||
state.finalized_checkpoint.root
|
||||
let
|
||||
finality_branch = state.build_proof(altair.FINALIZED_ROOT_GINDEX).get
|
||||
finality_branch = normalize_merkle_branch(
|
||||
state.build_proof(altair.FINALIZED_ROOT_GINDEX).get,
|
||||
storeDataFork.FINALIZED_ROOT_GINDEX)
|
||||
|
||||
update = storeDataFork.LightClientUpdate(
|
||||
attested_header: attested_header,
|
||||
|
Loading…
x
Reference in New Issue
Block a user