def test_get_hsdirs_no_consensus(): """ `get_hsdirs` should raise an exception when we don't have a valid HSDir list from the consensus. """ with pytest.raises(ValueError): consensus.get_hsdirs('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
def test_get_hsdirs_edge_of_ring(monkeypatch): """Test that selection wraps around the edge of the HSDir ring""" monkeypatch.setattr(consensus, 'HSDIR_LIST', MOCK_HSDIR_LIST) # Descriptor ID before '666....'' descriptor_id_base32 = "mzqaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" responsible_hsdirs = consensus.get_hsdirs(descriptor_id_base32) assert (responsible_hsdirs == [ "6666666666666666666666666666666666666666", "1111111111111111111111111111111111111111", "2222222222222222222222222222222222222222", ])
def test_get_hsdirs(monkeypatch): """Test for normal responsible HSDir selection""" monkeypatch.setattr(consensus, 'HSDIR_LIST', MOCK_HSDIR_LIST) # Descriptor ID before '222....'' descriptor_id_base32 = "eiqaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" responsible_hsdirs = consensus.get_hsdirs(descriptor_id_base32) assert (responsible_hsdirs == [ "2222222222222222222222222222222222222222", "3333333333333333333333333333333333333333", "4444444444444444444444444444444444444444", ])
def test_get_hsdirs_no_repeat(monkeypatch): """Test that selection wraps around the edge of the HSDir ring""" SHORT_HSDIR_LIST = [ "1111111111111111111111111111111111111111", "2222222222222222222222222222222222222222", ] monkeypatch.setattr(consensus, 'HSDIR_LIST', SHORT_HSDIR_LIST) # Descriptor ID before '111....'' descriptor_id_base32 = "ceiaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" responsible_hsdirs = consensus.get_hsdirs(descriptor_id_base32) assert (responsible_hsdirs == [ "1111111111111111111111111111111111111111", "2222222222222222222222222222222222222222", ])
def _publish_descriptor(self, deviation=0): """ Create, sign and upload master descriptors for this service """ # Retrieve the set of available introduction points intro_point_set = self._select_introduction_points() max_intro_points = config.MAX_INTRO_POINTS # Upload multiple unique descriptors which contain different # subsets of the available introduction points. # (https://github.com/DonnchaC/onionbalance/issues/16) distinct_descriptors = config.DISTINCT_DESCRIPTORS # If we have <= MAX_INTRO_POINTS we should choose the introduction # points now and use the same set in every descriptor. Using the # same set of introduction points will look more like a standard # Tor client. num_intro_points = len(intro_point_set) if num_intro_points <= max_intro_points: intro_points = intro_point_set.choose(num_intro_points) logger.debug("We have %d IPs, not using distinct descriptors.", len(intro_point_set)) distinct_descriptors = False for replica in range(0, config.REPLICAS): # Using distinct descriptors, choose a new set of intro points # for each descriptor and upload it to individual HSDirs. if distinct_descriptors: descriptor_id = util.calc_descriptor_id_b32( self.onion_address, time=time.time(), replica=replica, deviation=deviation, ) responsible_hsdirs = consensus.get_hsdirs(descriptor_id) for hsdir in responsible_hsdirs: intro_points = intro_point_set.choose(max_intro_points) try: signed_descriptor = ( descriptor.generate_service_descriptor( self.service_key, introduction_point_list=intro_points, replica=replica, deviation=deviation)) except ValueError as exc: logger.warning("Error generating descriptor: %s", exc) continue # Signed descriptor was generated successfully, upload it # to the respective HSDir self._upload_descriptor(signed_descriptor, replica, hsdirs=hsdir) logger.info( "Published distinct master descriptors for " "service %s.onion under replica %d.", self.onion_address, replica) else: # Not using distinct descriptors, upload one descriptor # under each replica and let Tor pick the HSDirs. try: signed_descriptor = descriptor.generate_service_descriptor( self.service_key, introduction_point_list=intro_points, replica=replica, deviation=deviation) except ValueError as exc: logger.warning("Error generating descriptor: %s", exc) continue # Signed descriptor was generated successfully, upload it self._upload_descriptor(signed_descriptor, replica) logger.info( "Published a descriptor for service %s.onion " "under replica %d.", self.onion_address, replica) # It would be better to set last_uploaded when an upload succeeds and # not when an upload is just attempted. Unfortunately the HS_DESC # # UPLOADED event does not provide information about the service and # so it can't be used to determine when descriptor upload succeeds self.uploaded = datetime.datetime.utcnow()