LCOV - code coverage report
Current view: top level - feature/dirauth - voting_schedule.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 68 70 97.1 %
Date: 2021-11-24 03:28:48 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2018-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file voting_schedule.c
       6             :  * \brief Compute information about our voting schedule as a directory
       7             :  *    authority.
       8             :  **/
       9             : 
      10             : #include "feature/dirauth/voting_schedule.h"
      11             : 
      12             : #include "core/or/or.h"
      13             : #include "app/config/config.h"
      14             : #include "feature/nodelist/networkstatus.h"
      15             : 
      16             : #include "feature/nodelist/networkstatus_st.h"
      17             : 
      18             : /* =====
      19             :  * Vote scheduling
      20             :  * ===== */
      21             : 
      22             : /* Populate and return a new voting_schedule_t that can be used to schedule
      23             :  * voting. The object is allocated on the heap and it's the responsibility of
      24             :  * the caller to free it. Can't fail. */
      25             : static voting_schedule_t *
      26         105 : create_voting_schedule(const or_options_t *options, time_t now, int severity)
      27             : {
      28         105 :   int interval, vote_delay, dist_delay;
      29         105 :   time_t start;
      30         105 :   time_t end;
      31         105 :   networkstatus_t *consensus;
      32         105 :   voting_schedule_t *new_voting_schedule;
      33             : 
      34         105 :   new_voting_schedule = tor_malloc_zero(sizeof(voting_schedule_t));
      35             : 
      36         105 :   consensus = networkstatus_get_live_consensus(now);
      37             : 
      38         105 :   if (consensus) {
      39          23 :     interval = (int)( consensus->fresh_until - consensus->valid_after );
      40          23 :     vote_delay = consensus->vote_seconds;
      41          23 :     dist_delay = consensus->dist_seconds;
      42             : 
      43             :     /* Note down the consensus valid after, so that we detect outdated voting
      44             :      * schedules in case of skewed clocks etc. */
      45          23 :     new_voting_schedule->live_consensus_valid_after = consensus->valid_after;
      46             :   } else {
      47          82 :     interval = options->TestingV3AuthInitialVotingInterval;
      48          82 :     vote_delay = options->TestingV3AuthInitialVoteDelay;
      49          82 :     dist_delay = options->TestingV3AuthInitialDistDelay;
      50             :   }
      51             : 
      52         105 :   tor_assert(interval > 0);
      53         105 :   new_voting_schedule->interval = interval;
      54             : 
      55         105 :   if (vote_delay + dist_delay > interval/2)
      56           5 :     vote_delay = dist_delay = interval / 4;
      57             : 
      58         210 :   start = new_voting_schedule->interval_starts =
      59         105 :     voting_sched_get_start_of_interval_after(now,interval,
      60         105 :                                       options->TestingV3AuthVotingStartOffset);
      61         210 :   end = voting_sched_get_start_of_interval_after(start+1, interval,
      62         105 :                                       options->TestingV3AuthVotingStartOffset);
      63             : 
      64         105 :   tor_assert(end > start);
      65             : 
      66         105 :   new_voting_schedule->fetch_missing_signatures = start - (dist_delay/2);
      67         105 :   new_voting_schedule->voting_ends = start - dist_delay;
      68         105 :   new_voting_schedule->fetch_missing_votes =
      69         105 :     start - dist_delay - (vote_delay/2);
      70         105 :   new_voting_schedule->voting_starts = start - dist_delay - vote_delay;
      71             : 
      72             :   {
      73         105 :     char tbuf[ISO_TIME_LEN+1];
      74         105 :     format_iso_time(tbuf, new_voting_schedule->interval_starts);
      75         105 :     tor_log(severity, LD_DIR,"Choosing expected valid-after time as %s: "
      76             :             "consensus_set=%d, interval=%d",
      77             :             tbuf, consensus?1:0, interval);
      78             :   }
      79             : 
      80         105 :   return new_voting_schedule;
      81             : }
      82             : 
      83             : #define voting_schedule_free(s) \
      84             :   FREE_AND_NULL(voting_schedule_t, voting_schedule_free_, (s))
      85             : 
      86             : /** Frees a voting_schedule_t. This should be used instead of the generic
      87             :  * tor_free. */
      88             : static void
      89         105 : voting_schedule_free_(voting_schedule_t *voting_schedule_to_free)
      90             : {
      91         105 :   if (!voting_schedule_to_free)
      92             :     return;
      93         105 :   tor_free(voting_schedule_to_free);
      94             : }
      95             : 
      96             : voting_schedule_t voting_schedule;
      97             : 
      98             : /**
      99             :  * Return the current voting schedule, recreating it if necessary.
     100             :  *
     101             :  * Dirauth only.
     102             :  **/
     103             : static const voting_schedule_t *
     104          81 : dirauth_get_voting_schedule(void)
     105             : {
     106          81 :   time_t now = approx_time();
     107          81 :   bool need_to_recalculate_voting_schedule = false;
     108             : 
     109             :   /* This is a safe guard in order to make sure that the voting schedule
     110             :    * static object is at least initialized. Using this function with a zeroed
     111             :    * voting schedule can lead to bugs. */
     112          81 :   if (fast_mem_is_zero((const char *) &voting_schedule,
     113             :                       sizeof(voting_schedule))) {
     114          16 :     need_to_recalculate_voting_schedule = true;
     115          16 :     goto done; /* no need for next check if we have to recalculate anyway */
     116             :   }
     117             : 
     118             :   /* Also make sure we are not using an outdated voting schedule. If we have a
     119             :    * newer consensus, make sure we recalculate the voting schedule. */
     120          65 :   const networkstatus_t *ns = networkstatus_get_live_consensus(now);
     121          65 :   if (ns && ns->valid_after != voting_schedule.live_consensus_valid_after) {
     122           0 :     log_info(LD_DIR, "Voting schedule is outdated: recalculating (%d/%d)",
     123             :              (int) ns->valid_after,
     124             :              (int) voting_schedule.live_consensus_valid_after);
     125           0 :     need_to_recalculate_voting_schedule = true;
     126             :   }
     127             : 
     128          65 :  done:
     129          16 :   if (need_to_recalculate_voting_schedule) {
     130          16 :     dirauth_sched_recalculate_timing(get_options(), approx_time());
     131          16 :     voting_schedule.created_on_demand = 1;
     132             :   }
     133             : 
     134          81 :   return &voting_schedule;
     135             : }
     136             : 
     137             : /** Return the next voting valid-after time.
     138             :  *
     139             :  * Dirauth only. */
     140             : time_t
     141          18 : dirauth_sched_get_next_valid_after_time(void)
     142             : {
     143          18 :   return dirauth_get_voting_schedule()->interval_starts;
     144             : }
     145             : 
     146             : /**
     147             :  * Return our best idea of what the valid-after time for the _current_
     148             :  * consensus, whether we have one or not.
     149             :  *
     150             :  * Dirauth only.
     151             :  **/
     152             : time_t
     153          63 : dirauth_sched_get_cur_valid_after_time(void)
     154             : {
     155          63 :   const voting_schedule_t *sched = dirauth_get_voting_schedule();
     156          63 :   time_t next_start = sched->interval_starts;
     157          63 :   int interval = sched->interval;
     158          63 :   int offset = get_options()->TestingV3AuthVotingStartOffset;
     159          63 :   return voting_sched_get_start_of_interval_after(next_start - interval - 1,
     160             :                                                   interval,
     161             :                                                   offset);
     162             : }
     163             : 
     164             : /** Return the voting interval that we are configured to use.
     165             :  *
     166             :  * Dirauth only. */
     167             : int
     168         218 : dirauth_sched_get_configured_interval(void)
     169             : {
     170         218 :   return get_options()->V3AuthVotingInterval;
     171             : }
     172             : 
     173             : /** Set voting_schedule to hold the timing for the next vote we should be
     174             :  * doing. All type of tor do that because HS subsystem needs the timing as
     175             :  * well to function properly. */
     176             : void
     177         105 : dirauth_sched_recalculate_timing(const or_options_t *options, time_t now)
     178             : {
     179         105 :   voting_schedule_t *new_voting_schedule;
     180             : 
     181             :   /* get the new voting schedule */
     182         105 :   new_voting_schedule = create_voting_schedule(options, now, LOG_INFO);
     183         105 :   tor_assert(new_voting_schedule);
     184             : 
     185             :   /* Fill in the global static struct now */
     186         105 :   memcpy(&voting_schedule, new_voting_schedule, sizeof(voting_schedule));
     187         105 :   voting_schedule_free(new_voting_schedule);
     188         105 : }

Generated by: LCOV version 1.14