Skip to content

Commit

Permalink
broadcast optimistic light client updates
Browse files Browse the repository at this point in the history
After proposing a new block, broadcasts a `OptimisticLightClientUpdate`.
Works for both locally proposed blocks as well as VC submitted ones.
  • Loading branch information
etan-status committed Mar 14, 2022
1 parent a92b175 commit 3b350d6
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 1 deletion.
14 changes: 14 additions & 0 deletions beacon_chain/networking/eth2_network.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2319,3 +2319,17 @@ proc broadcastSignedContributionAndProof*(
node: Eth2Node, msg: SignedContributionAndProof) =
let topic = getSyncCommitteeContributionAndProofTopic(node.forkDigests.altair)
node.broadcast(topic, msg)

proc broadcastOptimisticLightClientUpdate*(
node: Eth2Node, msg: OptimisticLightClientUpdate) =
let
forkDigest =
if msg.fork_version == node.cfg.SHARDING_FORK_VERSION:
node.forkDigests.sharding
elif msg.fork_version == node.cfg.BELLATRIX_FORK_VERSION:
node.forkDigests.bellatrix
else:
doAssert msg.fork_version == node.cfg.ALTAIR_FORK_VERSION
node.forkDigests.altair
topic = getOptimisticLightClientUpdateTopic(forkDigest)
node.broadcast(topic, msg)
9 changes: 9 additions & 0 deletions beacon_chain/spec/beacon_time.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

{.push raises: [Defect].}

# References to `vFuture` refer to the pre-release proposal of the libp2p based
# light client sync protocol. Conflicting release versions are not in use.
# https://github.com/ethereum/consensus-specs/pull/2802

import
std/[hashes, typetraits],
chronicles,
Expand Down Expand Up @@ -146,6 +150,9 @@ const
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/validator.md#broadcast-sync-committee-contribution
syncContributionSlotOffset* = TimeDiff(nanoseconds:
NANOSECONDS_PER_SLOT.int64 * 2 div INTERVALS_PER_SLOT)
# https://github.com/ethereum/consensus-specs/blob/vFuture/specs/altair/sync-protocol.md#block-proposal
optimisticLightClientUpdateSlotOffset* = TimeDiff(nanoseconds:
NANOSECONDS_PER_SLOT.int64 div INTERVALS_PER_SLOT)

func toFloatSeconds*(t: TimeDiff): float =
float(t.nanoseconds) / 1_000_000_000.0
Expand All @@ -167,6 +174,8 @@ func sync_committee_message_deadline*(s: Slot): BeaconTime =
s.start_beacon_time + syncCommitteeMessageSlotOffset
func sync_contribution_deadline*(s: Slot): BeaconTime =
s.start_beacon_time + syncContributionSlotOffset
func optimistic_light_client_update_deadline*(s: Slot): BeaconTime =
s.start_beacon_time + optimisticLightClientUpdateSlotOffset

func slotOrZero*(time: BeaconTime): Slot =
let exSlot = time.toSlot
Expand Down
43 changes: 42 additions & 1 deletion beacon_chain/validators/validator_duties.nim
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,18 @@ proc handleSyncCommitteeMessages(node: BeaconNode, head: BlockRef, slot: Slot) =
asyncSpawn createAndSendSyncCommitteeMessage(node, slot, validator,
subcommitteeIdx, head)

proc handleOptimisticLightClientUpdates(
node: BeaconNode, head: BlockRef, slot: Slot, didSubmitBlock: bool) =
if not didSubmitBlock or slot < node.dag.cfg.ALTAIR_FORK_EPOCH.start_slot():
return
let msg = node.dag.lightClientCache.optimisticUpdate
if msg.attested_header.slot != head.parent.bid.slot:
notice "No optimistic light client update for proposed block",
slot = slot, block_root = shortLog(head.root)
return
node.network.broadcastOptimisticLightClientUpdate(msg)
notice "Sent optimistic light client update", message = shortLog(msg)

proc signAndSendContribution(node: BeaconNode,
validator: AttachedValidator,
contribution: SyncCommitteeContribution,
Expand Down Expand Up @@ -1069,7 +1081,10 @@ proc handleValidatorDuties*(node: BeaconNode, lastSlot, slot: Slot) {.async.} =

curSlot += 1

head = await handleProposal(node, head, slot)
let
newHead = await handleProposal(node, head, slot)
didSubmitBlock = (newHead != head)
head = newHead

let
# The latest point in time when we'll be sending out attestations
Expand Down Expand Up @@ -1119,6 +1134,16 @@ proc handleValidatorDuties*(node: BeaconNode, lastSlot, slot: Slot) {.async.} =
handleAttestations(node, head, slot)
handleSyncCommitteeMessages(node, head, slot)

if node.config.serveLightClientData:
let cutoff = node.beaconClock.fromNow(
slot.optimistic_light_client_update_deadline())
if cutoff.inFuture:
debug "Waiting to send optimistic light client update",
head = shortLog(head),
optimisticLightClientUpdateCutoff = shortLog(cutoff.offset)
await sleepAsync(cutoff.offset)
handleOptimisticLightClientUpdates(node, head, slot, didSubmitBlock)

updateValidatorMetrics(node) # the important stuff is done, update the vanity numbers

# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/validator.md#broadcast-aggregate
Expand Down Expand Up @@ -1276,6 +1301,22 @@ proc sendBeaconBlock*(node: BeaconNode, forked: ForkedSignedBeaconBlock
notice "Block published",
blockRoot = shortLog(blck.root), blck = shortLog(blck.message),
signature = shortLog(blck.signature)

if node.config.serveLightClientData:
proc publishOptimisticLightClientUpdate() {.async.} =
let cutoff = node.beaconClock.fromNow(
wallTime.slotOrZero.optimistic_light_client_update_deadline())
if cutoff.inFuture:
debug "Waiting to publish optimistic light client update",
blockRoot = shortLog(blck.root), blck = shortLog(blck.message),
signature = shortLog(blck.signature),
optimisticLightClientUpdateCutoff = shortLog(cutoff.offset)
await sleepAsync(cutoff.offset)
handleOptimisticLightClientUpdates(
node, newBlockRef.get, wallTime.slotOrZero, didSubmitBlock = true)

asyncSpawn publishOptimisticLightClientUpdate()

true
else:
warn "Unable to add proposed block to block pool",
Expand Down

0 comments on commit 3b350d6

Please sign in to comment.