add fork choice rule

This commit is contained in:
Giacomo Pasini 2024-01-29 11:13:59 +01:00
parent a587e3a164
commit 989e92635e
No known key found for this signature in database
GPG Key ID: FC08489D2D895D4B
1 changed files with 32 additions and 2 deletions

View File

@ -124,8 +124,8 @@ class Follower:
# in that case, just ignore the block # in that case, just ignore the block
# Evaluate the fork choice rule and return the block header of the block that should be the head of the chain # Evaluate the fork choice rule and return the block header of the block that should be the head of the chain
def fork_choice(local_chain: Chain, forks: List[Chain]) -> BlockHeader: def fork_choice(local_chain: Chain, forks: List[Chain]) -> Chain:
pass return maxvalid_bg(local_chain, forks)
def tip(self) -> BlockHeader: def tip(self) -> BlockHeader:
return self.fork_choice() return self.fork_choice()
@ -218,5 +218,35 @@ class Leader:
return BlockHeader(parent=parent.id(), slot=slot) return BlockHeader(parent=parent.id(), slot=slot)
def common_prefix_len(a: Chain, b: Chain) -> int:
for i, (x, y) in enumerate(zip(a.blocks, b.blocks)):
if x.id() != y.id():
return i
return min(len(a.blocks), len(b.blocks))
def chain_density(chain: Chain, slot: Slot) -> int:
return count(block for block in chain.blocks if block.slot < slot)
def maxvalid_bg(local_chain: Chain, forks: List[Chain], k: int, s: int) -> Chain:
cmax = local_chain
for chain in forks:
lowest_common_ancestor = common_prefix_len(cmax, chain)
m = cmax.length() - lowest_common_ancestor
if m <= k:
# Classic longest chain rule with parameter k
if cmax.length() < chain.length():
cmax = chain
else:
# The chain is forking too much, we need to pay a bit more attention
# In particular, select the chain that is the densest after the fork
forking_slot = cmax.blocks[lowest_common_ancestor].slot
cmax_density = chain_density(cmax, forking_slot + s)
chain_density = chain_density(chain, forking_slot + s)
if cmax_density < chain_density:
cmax = chain
return cmax
if __name__ == "__main__": if __name__ == "__main__":
pass pass