b += 1L q_try = 2L**b # Now try modulus = modulus_max explicitly N = 1L q_try = modulus_max assert modulus_max >= modulus_min a = 1L X = 2L**a logging.info("Trying modulus = modulus_max = {}".format(q_try)) logging.info( "Unsigned to signed counter conversion, modulus = {}:".format(q_try)) try_adjust_count_signed(q_try) logging.info("Success!") # we interpret values >= modulus/2 as negative # So make sure that modulus is larger than 2*(N*X + 1) while X < q_try // 2L: logging.debug("Trying count 2**{} = {} < modulus/2 ({})".format( a, X, q_try // 2)) try_counters(counters, q_try, N, X, multi_bin=False) # This should terminate in at most ~log2(modulus) steps a += 1L X = 2L**a logging.info( "Reached modulus = modulus_max = {} without overflow or inaccuracy".format( q_try)) logging.info("Hard-coded counter values: {}".format( add_counter_limits_to_config({})))
def check_stop_config(self, stop_config, counts): ''' When the round stops, perform common client actions: - log a message - tell the collection_delay ''' end_time = time() response = {} round_successful = False wants_counters = stop_config.get('send_counters', False) logging.info("tally server {} final counts".format( "wants" if wants_counters else "does not want")) if wants_counters and counts is not None: logging.info("sending counts from {} counters ({} bins)".format( len(counts), count_bins(counts))) response['Counts'] = counts # only delay a round if we have sent our counters round_successful = True else: logging.info("No counts available") # even though the counter limits are hard-coded, include them anyway response['Config'] = add_counter_limits_to_config(self.config) # and include the config sent by the tally server in do_start if self.start_config is not None: response['Config']['Start'] = deepcopy(self.start_config) PrivCountNode.summarise_config_lists(response['Config']['Start']) # and include the config sent by the tally server to stop if stop_config is not None: response['Config']['Stop'] = stop_config # if we never started, there's no point in registering end of round if (self.collect_period is None or self.last_noise_config is None or self.collection_start_time is None): logging.warning("TS sent stop command before start command") return response # Using the collect_period from the tally server is inaccurate, # because the DCs and SKs do not check that the actual collection time # requested by the TS matches the collection period it claims actual_collect = end_time - self.collection_start_time # add this info to the context response['Config']['Time'] = {} response['Config']['Time']['Start'] = self.collection_start_time response['Config']['Time']['Stop'] = end_time response['Config']['Time']['Collect'] = actual_collect # Register the stop with the collection delay self.collection_delay.set_delay_for_stop( round_successful, # set when the round started self.last_noise_config, self.collection_start_time, end_time, self.config['delay_period'], always_delay=self.config['always_delay'], tolerance=self.config['sigma_decrease_tolerance']) logging.info("collection phase was stopped") return response