Coverage for src/lib/overlay.py: 100%
45 statements
« prev ^ index » next coverage.py v7.2.7, created at 2025-03-09 17:37 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2025-03-09 17:37 +0000
1from os import getenv
2from base58 import b58decode
5class Node():
6 id: str
8 def __init__(self, id: str):
9 self.id = id
11 def __str__(self): # pragma: no cover
12 return 'Node({})'.format(self.id)
14 def __repr__(self): # pragma: no cover
15 return 'Node({})'.format(self.id)
17 def __eq__(self, other):
18 if isinstance(other, str):
19 return self.id == other
21 if not isinstance(other, Node):
22 return False
24 return self.id == other.id
26 def decode(self) -> bytes:
27 return b58decode(self.id[3:])
29 def has_valid_id(self) -> bool:
30 if self.id[0:3] != 'FC_':
31 return False
33 return len(self.decode()) == 32
35 def distance(self, other):
36 return Distance(self, other)
38 @staticmethod
39 def parse(id: str):
40 node = Node(id)
41 if not getenv('IS_UNITTEST') and not node.has_valid_id(): # pragma: no cover
42 raise ValueError('Invalid ID')
44 return node
46class Distance():
47 _distance: int
49 def __init__(self, node1: Node = None, node2: Node = None):
50 self._distance = 256
52 if node1 is not None and node2 is not None:
53 id1 = node1.decode()
54 id2 = node2.decode()
56 for a, b in zip(id1, id2):
57 x = a ^ b
58 if x == 0:
59 self._distance -= 8
60 else:
61 self._distance -= bin(x)[2:].zfill(8).find('1')
62 break
64 def __str__(self): # pragma: no cover
65 return 'Distance({})'.format(self._distance)
67 def __lt__(self, other):
68 return self._distance < other._distance
70 def __eq__(self, other):
71 if isinstance(other, int):
72 return self._distance == other
74 if not isinstance(other, Distance):
75 return False
77 return self._distance == other._distance