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