simplify, genaralize to any size and fix tests

This commit is contained in:
Victor Shyba 2022-02-22 22:38:04 -03:00 committed by Victor Shyba
parent 8019f4bdb3
commit 1aa4d9d585
4 changed files with 16 additions and 19 deletions

View file

@ -71,7 +71,7 @@ class KBucket:
if len(self.peers) < constants.K: if len(self.peers) < constants.K:
self.peers.append(peer) self.peers.append(peer)
self.peer_in_routing_table_metric.labels("global").inc() self.peer_in_routing_table_metric.labels("global").inc()
bits_colliding = utils.get_colliding_prefix_bits(peer.node_id, self._node_id, 32) bits_colliding = utils.get_colliding_prefix_bits(peer.node_id, self._node_id)
self.peer_with_x_bit_colliding_metric.labels(amount=bits_colliding).inc() self.peer_with_x_bit_colliding_metric.labels(amount=bits_colliding).inc()
return True return True
else: else:
@ -140,7 +140,7 @@ class KBucket:
def remove_peer(self, peer: 'KademliaPeer') -> None: def remove_peer(self, peer: 'KademliaPeer') -> None:
self.peers.remove(peer) self.peers.remove(peer)
self.peer_in_routing_table_metric.labels("global").dec() self.peer_in_routing_table_metric.labels("global").dec()
bits_colliding = utils.get_colliding_prefix_bits(peer.node_id, self._node_id, 32) bits_colliding = utils.get_colliding_prefix_bits(peer.node_id, self._node_id)
self.peer_with_x_bit_colliding_metric.labels(amount=bits_colliding).dec() self.peer_with_x_bit_colliding_metric.labels(amount=bits_colliding).dec()
def key_in_range(self, key: bytes) -> bool: def key_in_range(self, key: bytes) -> bool:

View file

@ -421,7 +421,7 @@ class BackgroundDownloaderComponent(Component):
for blob_hash in self.dht_node.stored_blob_hashes: for blob_hash in self.dht_node.stored_blob_hashes:
if blob_hash.hex() in self.blob_manager.completed_blob_hashes: if blob_hash.hex() in self.blob_manager.completed_blob_hashes:
continue continue
if utils.get_colliding_prefix_bits(node_id, blob_hash, 32) >= self.MIN_PREFIX_COLLIDING_BITS: if utils.get_colliding_prefix_bits(node_id, blob_hash) >= self.MIN_PREFIX_COLLIDING_BITS:
self.ongoing_download = asyncio.create_task(self.background_downloader.download_blobs(blob_hash.hex())) self.ongoing_download = asyncio.create_task(self.background_downloader.download_blobs(blob_hash.hex()))
return return

View file

@ -476,19 +476,16 @@ class LockWithMetrics(asyncio.Lock):
self._lock_held_time_metric.observe(time.perf_counter() - self._lock_acquired_time) self._lock_held_time_metric.observe(time.perf_counter() - self._lock_acquired_time)
def get_colliding_prefix_bits(first_value: bytes, second_value: bytes, size: int): def get_colliding_prefix_bits(first_value: bytes, second_value: bytes):
""" """
Calculates the amount of colliding bits between <first_value> and <second_value> over the <size> first bits. Calculates the amount of colliding prefix bits between <first_value> and <second_value>.
This is given by the amount of bits that are the same until the first different one (via XOR). This is given by the amount of bits that are the same until the first different one (via XOR),
starting from the most significant bit to the least significant bit.
:param first_value: first value to compare, bigger than size. :param first_value: first value to compare, bigger than size.
:param second_value: second value to compare, bigger than size. :param second_value: second value to compare, bigger than size.
:param size: prefix size in bits.
:return: amount of prefix colliding bits. :return: amount of prefix colliding bits.
""" """
assert size % 8 == 0, "size has to be a multiple of 8" assert len(first_value) == len(second_value), "length should be the same"
size_in_bytes = size // 8 size = len(first_value) * 8
assert len(first_value) >= size_in_bytes, "first_value has to be larger than size parameter" first_value, second_value = int.from_bytes(first_value, "big"), int.from_bytes(second_value, "big")
first_value = int.from_bytes(first_value[:size_in_bytes], "big")
assert len(second_value) >= size_in_bytes, "second_value has to be larger than size parameter"
second_value = int.from_bytes(second_value[:size_in_bytes], "big")
return size - (first_value ^ second_value).bit_length() return size - (first_value ^ second_value).bit_length()

View file

@ -6,14 +6,14 @@ class UtilsTestCase(unittest.TestCase):
def test_get_colliding_prefix_bits(self): def test_get_colliding_prefix_bits(self):
self.assertEqual( self.assertEqual(
0, utils.get_colliding_prefix_bits(0xffffff.to_bytes(4, "big"), 0x00000000.to_bytes(4, "big"), 32)) 0, utils.get_colliding_prefix_bits(0xffffffff.to_bytes(4, "big"), 0x0000000000.to_bytes(4, "big")))
self.assertEqual( self.assertEqual(
1, utils.get_colliding_prefix_bits(0xefffff.to_bytes(4, "big"), 0x00000000.to_bytes(4, "big"), 32)) 1, utils.get_colliding_prefix_bits(0x7fffffff.to_bytes(4, "big"), 0x0000000000.to_bytes(4, "big")))
self.assertEqual( self.assertEqual(
8, utils.get_colliding_prefix_bits(0x00ffff.to_bytes(4, "big"), 0x00000000.to_bytes(4, "big"), 16)) 8, utils.get_colliding_prefix_bits(0x00ffffff.to_bytes(4, "big"), 0x0000000000.to_bytes(4, "big")))
self.assertEqual( self.assertEqual(
8, utils.get_colliding_prefix_bits(0x00ffff.to_bytes(4, "big"), 0x00000000.to_bytes(4, "big"), 8)) 8, utils.get_colliding_prefix_bits(0x00ffffff.to_bytes(4, "big"), 0x0000000000.to_bytes(4, "big")))
self.assertEqual( self.assertEqual(
1, utils.get_colliding_prefix_bits(0xefffff.to_bytes(4, "big"), 0x00000000.to_bytes(4, "big"), 16)) 1, utils.get_colliding_prefix_bits(0x7fffffff.to_bytes(4, "big"), 0x0000000000.to_bytes(4, "big")))
self.assertEqual( self.assertEqual(
1, utils.get_colliding_prefix_bits(0xefffff.to_bytes(4, "big"), 0x00000000.to_bytes(4, "big"), 8)) 1, utils.get_colliding_prefix_bits(0x7fffffff.to_bytes(4, "big"), 0x0000000000.to_bytes(4, "big")))