diff --git a/doc/spec/dir-spec.txt b/doc/spec/dir-spec.txt index a7b2e5d803..1acfb46688 100644 --- a/doc/spec/dir-spec.txt +++ b/doc/spec/dir-spec.txt @@ -1115,8 +1115,12 @@ $Id$ minutes, 60 minutes, 90 minutes). Voting intervals SHOULD be chosen to divide evenly into a 24-hour day. - Authorities MUST take pains to ensure that their clocks remain accurate, - for example by running NTP. + Authorities SHOULD act according to interval and delays in the + latest consensus. Lacking a latest consensus, they SHOULD default to a + 30-minute Interval, a 5 minute VotingDelay, and a 5 minute DistDelay. + + Authorities MUST take pains to ensure that their clocks remain accurate + within a few seconds. (Running NTP is usually sufficient.) The first voting period of each day begins at 00:00 (midnight) GMT. If the last period of the day would be truncated by one-half or more, it is diff --git a/src/or/config.c b/src/or/config.c index 30ead7f400..a12ca86ef6 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -271,7 +271,6 @@ static config_var_t _option_vars[] = { VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"), VAR("V2AuthoritativeDirectory",BOOL, V2AuthoritativeDir, "0"), VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir, "0"), - /* XXXX020 check these for sanity. */ VAR("V3AuthVotingInterval",INTERVAL, V3AuthVotingInterval, "1 hour"), VAR("V3AuthVoteDelay", INTERVAL, V3AuthVoteDelay, "5 minutes"), VAR("V3AuthDistDelay", INTERVAL, V3AuthDistDelay, "5 minutes"), @@ -1090,7 +1089,9 @@ options_act(or_options_t *old_options) if (dns_reset()) return -1; } - /* XXXX020 init_keys() again if v3authoritativedir is newly set. */ + + if (options->V3AuthoritativeDir && !old_options->V3AuthoritativeDir) + init_keys(); } /* Check if we need to parse and add the EntryNodes config option. */ @@ -2999,6 +3000,23 @@ options_validate(or_options_t *old_options, or_options_t *options, } } + if (options->V3AuthVoteDelay + options->V3AuthDistDelay >= + options->V3AuthVotingInterval/2) { + REJECT("V3AuthVoteDelay and V3AuthDistDelay must be no more than half " + "V3AuthVotingInterval"); + } + if (options->V3AuthNIntervalsValid < 2) { + REJECT("V3AuthNIntervalsValid must be at least 2."); + } + + if (options->V3AuthVotingInterval < 300) { + REJECT("V3AuthVotingInterval is insanely low."); + } else if (options->V3AuthVotingInterval > 24*60*60) { + REJECT("V3AuthVotingInterval is insanely high."); + } else if (((24*60*60) % options->V3AuthVotingInterval) != 0) { + COMPLAIN("V3AuthVotingInterval does not divide evenly into 24 hours."); + } + if (rend_config_services(options, 1) < 0) REJECT("Failed to configure rendezvous options. See logs for details."); diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 0846772eda..760945c2d2 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -923,7 +923,7 @@ networkstatus_get_detached_signatures(networkstatus_vote_t *consensus) { char sk[HEX_DIGEST_LEN+1]; char id[HEX_DIGEST_LEN+1]; - if (!v->signature) // XXXX020 || !v->good_signature) + if (!v->signature || v->bad_signature) continue; ++n_sigs; base16_encode(sk, sizeof(sk), v->signing_key_digest, DIGEST_LEN); @@ -1038,9 +1038,15 @@ dirvote_get_start_of_next_interval(time_t now, int interval) next = midnight_today + ((now-midnight_today)/interval + 1)*interval; + /* Intervals never cross midnight. */ if (next > midnight_tomorrow) next = midnight_tomorrow; + /* If the interval would only last half as long as it's supposed to, then + * skip over to the next day. */ + if (next + interval/2 > midnight_tomorrow) + next = midnight_tomorrow; + return next; } @@ -1061,9 +1067,11 @@ static struct { void dirvote_recalculate_timing(time_t now) { - /*XXXX020 call this when inputs may have changed. */ + /* XXXX020 call this when inputs may have changed (i.e., whenver we get a + * fresh consensus.) */ int interval, vote_delay, dist_delay; time_t start; + time_t end; networkstatus_vote_t *consensus = networkstatus_get_latest_consensus(); memset(&voting_schedule, 0, sizeof(voting_schedule)); @@ -1074,18 +1082,27 @@ dirvote_recalculate_timing(time_t now) vote_delay = consensus->vote_seconds; dist_delay = consensus->dist_seconds; } else { - /* XXXX020 is this correct according the the spec? */ - /* XXXX020 drop this back down to 60 minutes, or whatever the spec says. */ + /* XXXX020 drop this back down to 30 minutes. */ interval = 1200; vote_delay = dist_delay = 300; } + tor_assert(interval > 0); + + if (vote_delay + dist_delay > interval/2) + vote_delay = dist_delay = interval / 4; + start = voting_schedule.interval_starts = dirvote_get_start_of_next_interval(now,interval); + end = dirvote_get_start_of_next_interval(start+1, interval); + + tor_assert(end > start); + voting_schedule.voting_ends = start - vote_delay; voting_schedule.voting_starts = start - vote_delay - dist_delay; - voting_schedule.discard_old_votes = start + 300; /* XXXX020 */ + voting_schedule.discard_old_votes = start + + ((end-start) - vote_delay - dist_delay)/2 ; } /** DOCDOC */ diff --git a/src/or/or.h b/src/or/or.h index 2ab1d7b0d6..63fe33d6e3 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2067,12 +2067,14 @@ typedef struct { * if we are a cache). For authorities, this is always true. */ int DownloadExtraInfo; - /** The length of time that we think a consensus should be */ + /** The length of time that we think a consensus should be fresh. */ int V3AuthVotingInterval; + /** The length of time we think it will take to distribute votes */ int V3AuthVoteDelay; + /** The length of time we think it will take to distribute signatures */ int V3AuthDistDelay; + /** The number of intervals we think a consensus should be valid. */ int V3AuthNIntervalsValid; - } or_options_t; /** Persistent state for an onion router, as saved to disk. */