mirror of
https://github.com/logos-blockchain/logos-blockchain-specs.git
synced 2026-01-03 13:43:11 +00:00
make sync function return bool
This commit is contained in:
parent
2e2675380f
commit
08c9a1f9c2
@ -12,16 +12,22 @@ from cryptarchia.cryptarchia import (
|
||||
)
|
||||
|
||||
|
||||
def sync(local: Follower, peers: list[Follower]):
|
||||
def sync(local: Follower, peers: list[Follower]) -> bool:
|
||||
# Syncs the local block tree with the peers, starting from the local tip.
|
||||
# This covers the case where the local tip is not on the latest honest chain anymore.
|
||||
#
|
||||
# The caller should call this function repeatedly until it returns True,
|
||||
# which means that no peers have blocks ahead of the local tip.
|
||||
|
||||
# Fetch blocks from the peers in the range of slots from the local tip to the latest tip.
|
||||
# Gather orphaned blocks, which are blocks from forks that are absent in the local block tree.
|
||||
start_slot = local.tip().slot
|
||||
orphans: set[BlockHeader] = set()
|
||||
# Filter and group peers by their tip to minimize the number of fetches.
|
||||
for group in filter_and_group_peers_by_tip(peers, start_slot).values():
|
||||
groups = filter_and_group_peers_by_tip(peers, start_slot)
|
||||
if len(groups) == 0:
|
||||
return True # No peers have blocks ahead of the local tip.
|
||||
for group in groups.values():
|
||||
for block in fetch_blocks_by_slot(group, start_slot):
|
||||
try:
|
||||
local.on_block(block)
|
||||
@ -37,6 +43,10 @@ def sync(local: Follower, peers: list[Follower]):
|
||||
if orphan not in local.ledger_state:
|
||||
backfill_fork(local, peers, orphan)
|
||||
|
||||
# The caller should call this function again,
|
||||
# assuming that peers' tips have been updated during the sync.
|
||||
return False
|
||||
|
||||
|
||||
def filter_and_group_peers_by_tip(
|
||||
peers: list[Follower], start_slot: Slot
|
||||
|
||||
@ -22,9 +22,10 @@ class TestSync(TestCase):
|
||||
self.assertEqual(peer.forks, [])
|
||||
|
||||
local = Follower(genesis, config)
|
||||
sync(local, [peer])
|
||||
self.assertFalse(sync(local, [peer]))
|
||||
self.assertEqual(local.tip(), peer.tip())
|
||||
self.assertEqual(local.forks, peer.forks)
|
||||
self.assertTrue(sync(local, [peer]))
|
||||
|
||||
def test_sync_single_chain_from_middle(self):
|
||||
# b0 - b1 - b2 - b3
|
||||
@ -46,9 +47,10 @@ class TestSync(TestCase):
|
||||
for b in [b0, b1]:
|
||||
peer.on_block(b)
|
||||
# start syncing from b1
|
||||
sync(local, [peer])
|
||||
self.assertFalse(sync(local, [peer]))
|
||||
self.assertEqual(local.tip(), peer.tip())
|
||||
self.assertEqual(local.forks, peer.forks)
|
||||
self.assertTrue(sync(local, [peer]))
|
||||
|
||||
def test_sync_forks_from_genesis(self):
|
||||
# b0 - b1 - b2 - b5 == tip
|
||||
@ -70,9 +72,10 @@ class TestSync(TestCase):
|
||||
self.assertEqual(peer.forks, [b4.id()])
|
||||
|
||||
local = Follower(genesis, config)
|
||||
sync(local, [peer])
|
||||
self.assertFalse(sync(local, [peer]))
|
||||
self.assertEqual(local.tip(), peer.tip())
|
||||
self.assertEqual(local.forks, peer.forks)
|
||||
self.assertTrue(sync(local, [peer]))
|
||||
|
||||
def test_sync_forks_from_middle(self):
|
||||
# b0 - b1 - b2 - b5 == tip
|
||||
@ -99,9 +102,10 @@ class TestSync(TestCase):
|
||||
local = Follower(genesis, config)
|
||||
for b in [b0, b1, b3]:
|
||||
peer.on_block(b)
|
||||
sync(local, [peer])
|
||||
self.assertFalse(sync(local, [peer]))
|
||||
self.assertEqual(local.tip(), peer.tip())
|
||||
self.assertEqual(local.forks, peer.forks)
|
||||
self.assertTrue(sync(local, [peer]))
|
||||
|
||||
def test_sync_forks_by_backfilling(self):
|
||||
# b0 - b1 - b2 - b5 == tip
|
||||
@ -127,10 +131,11 @@ class TestSync(TestCase):
|
||||
local = Follower(genesis, config)
|
||||
for b in [b0, b1]:
|
||||
peer.on_block(b)
|
||||
sync(local, [peer])
|
||||
self.assertFalse(sync(local, [peer]))
|
||||
self.assertEqual(local.tip(), peer.tip())
|
||||
self.assertEqual(local.forks, peer.forks)
|
||||
self.assertEqual(len(local.ledger_state), len(peer.ledger_state))
|
||||
self.assertTrue(sync(local, [peer]))
|
||||
|
||||
def test_sync_multiple_peers_from_genesis(self):
|
||||
# Peer-0: b5
|
||||
@ -164,10 +169,11 @@ class TestSync(TestCase):
|
||||
self.assertEqual(peer2.forks, [])
|
||||
|
||||
local = Follower(genesis, config)
|
||||
sync(local, [peer0, peer1, peer2])
|
||||
self.assertFalse(sync(local, [peer0, peer1, peer2]))
|
||||
self.assertEqual(local.tip(), b5)
|
||||
self.assertEqual(local.forks, [b4.id()])
|
||||
self.assertEqual(len(local.ledger_state), 7)
|
||||
self.assertTrue(sync(local, [peer0, peer1, peer2]))
|
||||
|
||||
|
||||
class TestSyncFromCheckpoint(TestCase):
|
||||
@ -195,7 +201,7 @@ class TestSyncFromCheckpoint(TestCase):
|
||||
checkpoint = peer.ledger_state[b2.id()]
|
||||
local = Follower(genesis, config)
|
||||
local.apply_checkpoint(checkpoint)
|
||||
sync(local, [peer])
|
||||
self.assertFalse(sync(local, [peer]))
|
||||
# Result:
|
||||
# () - () - b2 - b3
|
||||
# ||
|
||||
@ -205,6 +211,7 @@ class TestSyncFromCheckpoint(TestCase):
|
||||
self.assertEqual(
|
||||
set(local.ledger_state.keys()), set([genesis.block.id(), b2.id(), b3.id()])
|
||||
)
|
||||
self.assertTrue(sync(local, [peer]))
|
||||
|
||||
def test_sync_forks(self):
|
||||
# checkpoint
|
||||
@ -234,7 +241,7 @@ class TestSyncFromCheckpoint(TestCase):
|
||||
checkpoint = peer.ledger_state[b2.id()]
|
||||
local = Follower(genesis, config)
|
||||
local.apply_checkpoint(checkpoint)
|
||||
sync(local, [peer])
|
||||
self.assertFalse(sync(local, [peer]))
|
||||
# Result:
|
||||
# b0 - b1 - b2 - b5 == tip
|
||||
# \
|
||||
@ -242,6 +249,7 @@ class TestSyncFromCheckpoint(TestCase):
|
||||
self.assertEqual(local.tip(), peer.tip())
|
||||
self.assertEqual(local.forks, peer.forks)
|
||||
self.assertEqual(set(local.ledger_state.keys()), set(peer.ledger_state.keys()))
|
||||
self.assertTrue(sync(local, [peer]))
|
||||
|
||||
def test_sync_from_dishonest_checkpoint(self):
|
||||
# Peer0: b0 - b1 - b2 - b5 == tip
|
||||
@ -276,10 +284,11 @@ class TestSyncFromCheckpoint(TestCase):
|
||||
checkpoint = peer1.ledger_state[b4.id()]
|
||||
local = Follower(genesis, config)
|
||||
local.apply_checkpoint(checkpoint)
|
||||
sync(local, [peer0, peer1])
|
||||
self.assertFalse(sync(local, [peer0, peer1]))
|
||||
# b0 - b1 - b2 - b5 == tip
|
||||
# \
|
||||
# b3 - b4
|
||||
self.assertEqual(local.tip(), b5)
|
||||
self.assertEqual(local.forks, [b4.id()])
|
||||
self.assertEqual(len(local.ledger_state.keys()), 7)
|
||||
self.assertTrue(sync(local, [peer0, peer1]))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user