Skip to content

Commit

Permalink
restrict best LC update collection to canonical blocks (#5613)
Browse files Browse the repository at this point in the history
Simplify best `LightClientUpdate` collection by tracking only canonical
data instead of tracking the best update across all branches within the
sync committee period.

- ethereum/consensus-specs#3553
  • Loading branch information
etan-status authored Nov 21, 2023
1 parent 946ebe5 commit c33dd2c
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 214 deletions.
43 changes: 0 additions & 43 deletions beacon_chain/beacon_chain_db_light_client.nim
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,17 @@ type
getStmt: SqliteStmt[int64, (int64, seq[byte])]
putStmt: SqliteStmt[(int64, seq[byte]), void]
delStmt: SqliteStmt[int64, void]
delFromStmt: SqliteStmt[int64, void]
keepFromStmt: SqliteStmt[int64, void]

BestLightClientUpdateStore = object
getStmt: SqliteStmt[int64, (int64, seq[byte])]
putStmt: SqliteStmt[(int64, int64, seq[byte]), void]
delStmt: SqliteStmt[int64, void]
delFromStmt: SqliteStmt[int64, void]
keepFromStmt: SqliteStmt[int64, void]

SealedSyncCommitteePeriodStore = object
containsStmt: SqliteStmt[int64, int64]
putStmt: SqliteStmt[int64, void]
delFromStmt: SqliteStmt[int64, void]
keepFromStmt: SqliteStmt[int64, void]

LightClientDataDB* = ref object
Expand Down Expand Up @@ -405,10 +402,6 @@ proc initLegacyBestUpdatesStore(
DELETE FROM `""" & name & """`
WHERE `period` = ?;
""", int64, void, managed = false).expect("SQL query OK")
delFromStmt = backend.prepareStmt("""
DELETE FROM `""" & name & """`
WHERE `period` >= ?;
""", int64, void, managed = false).expect("SQL query OK")
keepFromStmt = backend.prepareStmt("""
DELETE FROM `""" & name & """`
WHERE `period` < ?;
Expand All @@ -418,14 +411,12 @@ proc initLegacyBestUpdatesStore(
getStmt: getStmt,
putStmt: putStmt,
delStmt: delStmt,
delFromStmt: delFromStmt,
keepFromStmt: keepFromStmt)

func close(store: var LegacyBestLightClientUpdateStore) =
store.getStmt.disposeSafe()
store.putStmt.disposeSafe()
store.delStmt.disposeSafe()
store.delFromStmt.disposeSafe()
store.keepFromStmt.disposeSafe()

proc initBestUpdatesStore(
Expand Down Expand Up @@ -470,10 +461,6 @@ proc initBestUpdatesStore(
DELETE FROM `""" & name & """`
WHERE `period` = ?;
""", int64, void, managed = false).expect("SQL query OK")
delFromStmt = backend.prepareStmt("""
DELETE FROM `""" & name & """`
WHERE `period` >= ?;
""", int64, void, managed = false).expect("SQL query OK")
keepFromStmt = backend.prepareStmt("""
DELETE FROM `""" & name & """`
WHERE `period` < ?;
Expand All @@ -483,14 +470,12 @@ proc initBestUpdatesStore(
getStmt: getStmt,
putStmt: putStmt,
delStmt: delStmt,
delFromStmt: delFromStmt,
keepFromStmt: keepFromStmt)

func close(store: var BestLightClientUpdateStore) =
store.getStmt.disposeSafe()
store.putStmt.disposeSafe()
store.delStmt.disposeSafe()
store.delFromStmt.disposeSafe()
store.keepFromStmt.disposeSafe()

proc getBestUpdate*(
Expand Down Expand Up @@ -559,13 +544,6 @@ func putBestUpdate*(
let res = db.legacyBestUpdates.delStmt.exec(period.int64)
res.expect("SQL query OK")

proc putUpdateIfBetter*(
db: LightClientDataDB, period: SyncCommitteePeriod,
update: ForkedLightClientUpdate) =
let existing = db.getBestUpdate(period)
if is_better_update(update, existing):
db.putBestUpdate(period, update)

proc initSealedPeriodsStore(
backend: SqStoreRef,
name: string): KvResult[SealedSyncCommitteePeriodStore] =
Expand All @@ -589,10 +567,6 @@ proc initSealedPeriodsStore(
`period`
) VALUES (?);
""", int64, void, managed = false).expect("SQL query OK")
delFromStmt = backend.prepareStmt("""
DELETE FROM `""" & name & """`
WHERE `period` >= ?;
""", int64, void, managed = false).expect("SQL query OK")
keepFromStmt = backend.prepareStmt("""
DELETE FROM `""" & name & """`
WHERE `period` < ?;
Expand All @@ -601,13 +575,11 @@ proc initSealedPeriodsStore(
ok SealedSyncCommitteePeriodStore(
containsStmt: containsStmt,
putStmt: putStmt,
delFromStmt: delFromStmt,
keepFromStmt: keepFromStmt)

func close(store: var SealedSyncCommitteePeriodStore) =
store.containsStmt.disposeSafe()
store.putStmt.disposeSafe()
store.delFromStmt.disposeSafe()
store.keepFromStmt.disposeSafe()

func isPeriodSealed*(
Expand All @@ -629,21 +601,6 @@ func sealPeriod*(
let res = db.sealedPeriods.putStmt.exec(period.int64)
res.expect("SQL query OK")

func delNonFinalizedPeriodsFrom*(
db: LightClientDataDB, minPeriod: SyncCommitteePeriod) =
doAssert not db.backend.readOnly # All `stmt` are non-nil
doAssert minPeriod.isSupportedBySQLite
block:
let res = db.sealedPeriods.delFromStmt.exec(minPeriod.int64)
res.expect("SQL query OK")
block:
let res = db.bestUpdates.delFromStmt.exec(minPeriod.int64)
res.expect("SQL query OK")
block:
let res = db.legacyBestUpdates.delFromStmt.exec(minPeriod.int64)
res.expect("SQL query OK")
# `syncCommittees`, `currentBranches` and `headers` only have finalized data

func keepPeriodsFrom*(
db: LightClientDataDB, minPeriod: SyncCommitteePeriod) =
doAssert not db.backend.readOnly # All `stmt` are non-nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,14 @@ type
finalized_slot*: Slot
finality_branch*: altair.FinalityBranch

current_period_best_update*: ref ForkedLightClientUpdate

LightClientDataCache* = object
data*: Table[BlockId, CachedLightClientData]
## Cached data for creating future `LightClientUpdate` instances.
## Key is the block ID of which the post state was used to get the data.
## Data stored for the finalized head block and all non-finalized blocks.

pendingBest*:
Table[(SyncCommitteePeriod, Eth2Digest), ForkedLightClientUpdate]
## Same as `db.bestUpdates`, but for `SyncCommitteePeriod` with not yet
## finalized `next_sync_committee`. Key is `(attested_period,
## hash_tree_root(current_sync_committee | next_sync_committee)`.

latest*: ForkedLightClientFinalityUpdate
## Tracks light client data for the latest slot that was signed by
## at least `MIN_SYNC_COMMITTEE_PARTICIPANTS`. May be older than head.
Expand Down
30 changes: 7 additions & 23 deletions beacon_chain/consensus_object_pools/blockchain_dag.nim
Original file line number Diff line number Diff line change
Expand Up @@ -799,21 +799,14 @@ proc currentSyncCommitteeForPeriod*(
else: err()
do: err()

func isNextSyncCommitteeFinalized*(
dag: ChainDAGRef, period: SyncCommitteePeriod): bool =
let finalizedSlot = dag.finalizedHead.slot
if finalizedSlot < period.start_slot:
false
elif finalizedSlot < dag.cfg.ALTAIR_FORK_EPOCH.start_slot:
false # Fork epoch not necessarily tied to sync committee period boundary
else:
true

func firstNonFinalizedPeriod*(dag: ChainDAGRef): SyncCommitteePeriod =
if dag.finalizedHead.slot >= dag.cfg.ALTAIR_FORK_EPOCH.start_slot:
dag.finalizedHead.slot.sync_committee_period + 1
proc getBlockIdAtSlot*(
dag: ChainDAGRef, state: ForkyHashedBeaconState, slot: Slot): Opt[BlockId] =
if slot >= state.data.slot:
Opt.some state.latest_block_id
elif state.data.slot <= slot + SLOTS_PER_HISTORICAL_ROOT:
dag.getBlockId(state.data.get_block_root_at_slot(slot))
else:
dag.cfg.ALTAIR_FORK_EPOCH.sync_committee_period
Opt.none(BlockId)

proc updateBeaconMetrics(
state: ForkedHashedBeaconState, bid: BlockId, cache: var StateCache) =
Expand Down Expand Up @@ -1338,15 +1331,6 @@ proc getFinalizedEpochRef*(dag: ChainDAGRef): EpochRef =
dag.finalizedHead.blck, dag.finalizedHead.slot.epoch, false).expect(
"getEpochRef for finalized head should always succeed")

proc getBlockIdAtSlot(
dag: ChainDAGRef, state: ForkyHashedBeaconState, slot: Slot): Opt[BlockId] =
if slot >= state.data.slot:
Opt.some state.latest_block_id
elif state.data.slot <= slot + SLOTS_PER_HISTORICAL_ROOT:
dag.getBlockId(state.data.get_block_root_at_slot(slot))
else:
Opt.none(BlockId)

proc ancestorSlot*(
dag: ChainDAGRef, state: ForkyHashedBeaconState, bid: BlockId,
lowSlot: Slot): Opt[Slot] =
Expand Down
Loading

0 comments on commit c33dd2c

Please sign in to comment.