add fork choice rule
This commit is contained in:
parent
a587e3a164
commit
989e92635e
|
@ -124,8 +124,8 @@ class Follower:
|
|||
# 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
|
||||
def fork_choice(local_chain: Chain, forks: List[Chain]) -> BlockHeader:
|
||||
pass
|
||||
def fork_choice(local_chain: Chain, forks: List[Chain]) -> Chain:
|
||||
return maxvalid_bg(local_chain, forks)
|
||||
|
||||
def tip(self) -> BlockHeader:
|
||||
return self.fork_choice()
|
||||
|
@ -218,5 +218,35 @@ class Leader:
|
|||
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__":
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue