41 lines
1.7 KiB
Python
Raw Permalink Normal View History

2025-02-27 15:52:02 +09:00
from collections import defaultdict
2025-02-28 14:45:23 +09:00
from cryptarchia.cryptarchia import Follower, Id, Slot
2025-02-27 15:52:02 +09:00
2025-02-28 10:37:09 +09:00
SLOT_TOLERANCE = 1
2025-02-27 15:52:02 +09:00
2025-02-28 10:37:09 +09:00
def full_sync(local: Follower, remotes: list[Follower], start_slot: Slot):
2025-02-28 15:10:06 +09:00
# Start a full sync from the remotes to the local, starting from the given slot.
# Sync only with remotes that are at least SLOT_TOLERANCE ahead of the local.
# Continue until there is no target to sync with.
#
# Group the remotes by their tip slot, and sync only with one remote per group.
# This is safe as long as the remote provides all blocks necessary for the future fork choice.
2025-02-28 11:33:49 +09:00
while groups := group_targets(remotes, start_slot):
2025-02-28 15:10:06 +09:00
for _tip_id, group in groups.items():
2025-02-27 15:52:02 +09:00
remote = group[0]
2025-02-28 10:37:09 +09:00
range_sync(local, remote, start_slot, remote.tip().slot)
2025-02-28 15:10:06 +09:00
# Update the start_slot to check if the sync should continue.
2025-02-27 15:52:02 +09:00
start_slot = Slot(local.tip().slot.absolute_slot + 1)
2025-02-28 10:37:09 +09:00
def range_sync(local: Follower, remote: Follower, from_slot: Slot, to_slot: Slot):
2025-02-28 15:10:06 +09:00
# Fetch blocks in the given range of slots from the remote and apply them to the local.
# Blocks should be fetched in order of slot.
2025-02-28 14:45:23 +09:00
for block in remote.block_storage.blocks_by_range(from_slot, to_slot):
2025-02-28 10:37:09 +09:00
local.on_block(block)
2025-02-28 11:33:49 +09:00
def group_targets(
2025-02-28 10:37:09 +09:00
targets: list[Follower], start_slot: Slot
) -> dict[Id, list[Follower]]:
2025-02-28 15:10:06 +09:00
# Group the targets by their tip slot.
# Filter only the targets that are at least SLOT_TOLERANCE ahead of the start_slot.
2025-02-27 15:52:02 +09:00
groups: dict[Id, list[Follower]] = defaultdict(list)
2025-02-28 10:37:09 +09:00
for target in targets:
if target.tip().slot.absolute_slot - start_slot.absolute_slot > SLOT_TOLERANCE:
groups[target.tip_id()].append(target)
2025-02-27 15:52:02 +09:00
return groups