Browse Source

Merge branch 'maint-0.2.7'

Nick Mathewson 8 years ago
parent
commit
6a91cab79c
13 changed files with 239 additions and 45 deletions
  1. 5 0
      changes/bug17668
  2. 6 0
      changes/bug17702
  3. 7 0
      changes/bug18318_ed
  4. 5 0
      changes/bug18368
  5. 72 6
      src/or/dircollate.c
  6. 21 3
      src/or/dircollate.h
  7. 59 16
      src/or/dirserv.c
  8. 1 1
      src/or/dirserv.h
  9. 35 0
      src/or/dirvote.c
  10. 4 3
      src/or/dirvote.h
  11. 1 1
      src/or/networkstatus.c
  12. 11 2
      src/or/or.h
  13. 12 13
      src/or/routerparse.c

+ 5 - 0
changes/bug17668

@@ -0,0 +1,5 @@
+  o Major bugfixes (voting):
+    - When collating votes by Ed25519 identities, authorities now
+      include a "NoEdConsensus" flag if the ed25519 value (or lack thereof)
+      for a server does not reflect the majority consensus. Related to bug
+      17668; bugfix on 0.2.7.2-alpha.

+ 6 - 0
changes/bug17702

@@ -0,0 +1,6 @@
+  o Major bugfixes:
+    - Actually enable Ed25519-based directory collation.
+      Previously, the code had been written, but some debugging code that had
+      accidentally been left in the codebase made it stay turned off.
+      Fixes bug 17702; bugfix on 0.2.7.2-alpha.
+

+ 7 - 0
changes/bug18318_ed

@@ -0,0 +1,7 @@
+  o Major bugfixes:
+    - When generating a vote with keypinning disabled, never include two
+      entries for the same ed25519 identity.  This bug was causing
+      authorities to generate votes that they could not parse when a router
+      violated key pinning by changing its RSA identity but keeping its
+      Ed25519 identity.  Fixes bug 17668; fixes part of bug 18318.  Bugfix on
+      0.2.7.2-alpha.

+ 5 - 0
changes/bug18368

@@ -0,0 +1,5 @@
+  o Minor bugfixes:
+    - When logging information about an unparseable networkstatus vote or
+      consensus, do not say "vote" when we mean consensus. Fixes bug
+      18368; bugfix on 0.2.0.8-alpha.
+

+ 72 - 6
src/or/dircollate.c

@@ -17,20 +17,24 @@
 static void dircollator_collate_by_rsa(dircollator_t *dc);
 static void dircollator_collate_by_ed25519(dircollator_t *dc);
 
+/** Hashtable entry mapping a pair of digests (actually an ed25519 key and an
+ * RSA SHA1 digest) to an array of vote_routerstatus_t. */
 typedef struct ddmap_entry_s {
   HT_ENTRY(ddmap_entry_s) node;
   uint8_t d[DIGEST_LEN + DIGEST256_LEN];
+  /* The nth member of this array corresponds to the vote_routerstatus_t (if
+   * any) received for this digest pair from the nth voter. */
   vote_routerstatus_t *vrs_lst[FLEXIBLE_ARRAY_MEMBER];
 } ddmap_entry_t;
 
-double_digest_map_t *by_both_ids;
-
+/** Release all storage held by e. */
 static void
 ddmap_entry_free(ddmap_entry_t *e)
 {
   tor_free(e);
 }
 
+/** Return a new empty ddmap_entry, with <b>n_votes</b> elements in vrs_list. */
 static ddmap_entry_t *
 ddmap_entry_new(int n_votes)
 {
@@ -50,6 +54,8 @@ ddmap_entry_eq(const ddmap_entry_t *a, const ddmap_entry_t *b)
   return fast_memeq(a->d, b->d, sizeof(a->d));
 }
 
+/** Record the RSA identity of <b>ent</b> as <b>rsa_sha1</b>, and the
+ * ed25519 identity as <b>ed25519</b>. */
 static void
 ddmap_entry_set_digests(ddmap_entry_t *ent,
                         const uint8_t *rsa_sha1,
@@ -63,6 +69,10 @@ HT_PROTOTYPE(double_digest_map, ddmap_entry_s, node, ddmap_entry_hash,
              ddmap_entry_eq);
 HT_GENERATE2(double_digest_map, ddmap_entry_s, node, ddmap_entry_hash,
              ddmap_entry_eq, 0.6, tor_reallocarray, tor_free_);
+
+/** Helper: add a single vote_routerstatus_t <b>vrs</b> to the collator
+ * <b>dc</b>, indexing it by its RSA key digest, and by the 2-tuple of
+ * its RSA key digest and Ed25519 key.  */
 static void
 dircollator_add_routerstatus(dircollator_t *dc,
                              int vote_num,
@@ -71,6 +81,8 @@ dircollator_add_routerstatus(dircollator_t *dc,
 {
   const char *id = vrs->status.identity_digest;
 
+  vrs->ed25519_reflects_consensus = 0;
+
   (void) vote;
   vote_routerstatus_t **vrs_lst = digestmap_get(dc->by_rsa_sha1, id);
   if (NULL == vrs_lst) {
@@ -82,7 +94,7 @@ dircollator_add_routerstatus(dircollator_t *dc,
 
   const uint8_t *ed = vrs->ed25519_id;
 
-  if (tor_mem_is_zero((char*)ed, DIGEST256_LEN))
+  if (! vrs->has_ed25519_listing)
     return;
 
   ddmap_entry_t search, *found;
@@ -99,6 +111,8 @@ dircollator_add_routerstatus(dircollator_t *dc,
   vrs_lst[vote_num] = vrs;
 }
 
+/** Create and return a new dircollator object to use when collating
+ * <b>n_votes</b> out of a total of <b>n_authorities</b>. */
 dircollator_t *
 dircollator_new(int n_votes, int n_authorities)
 {
@@ -115,6 +129,7 @@ dircollator_new(int n_votes, int n_authorities)
   return dc;
 }
 
+/** Release all storage held by <b>dc</b>. */
 void
 dircollator_free(dircollator_t *dc)
 {
@@ -139,6 +154,10 @@ dircollator_free(dircollator_t *dc)
   tor_free(dc);
 }
 
+/** Add a single vote <b>v</b> to a dircollator <b>dc</b>.  This function must
+ * be called exactly once for each vote to be used in the consensus. It may
+ * only be called before dircollator_collate().
+ */
 void
 dircollator_add_vote(dircollator_t *dc, networkstatus_t *v)
 {
@@ -153,13 +172,16 @@ dircollator_add_vote(dircollator_t *dc, networkstatus_t *v)
   } SMARTLIST_FOREACH_END(vrs);
 }
 
+/** Sort the entries in <b>dc</b> according to <b>consensus_method</b>, so
+ * that the consensus process can iterate over them with
+ * dircollator_n_routers() and dircollator_get_votes_for_router(). */
 void
 dircollator_collate(dircollator_t *dc, int consensus_method)
 {
   tor_assert(!dc->is_collated);
   dc->all_rsa_sha1_lst = smartlist_new();
 
-  if (consensus_method < MIN_METHOD_FOR_ED25519_ID_VOTING + 10/*XXX*/)
+  if (consensus_method < MIN_METHOD_FOR_ED25519_ID_VOTING)
     dircollator_collate_by_rsa(dc);
   else
     dircollator_collate_by_ed25519(dc);
@@ -168,6 +190,15 @@ dircollator_collate(dircollator_t *dc, int consensus_method)
   dc->is_collated = 1;
 }
 
+/**
+ * Collation function for RSA-only consensuses: collate the votes for each
+ * entry in <b>dc</b> by their RSA keys.
+ *
+ * The rule is:
+ *    If an RSA identity key is listed by more than half of the authorities,
+ *    include that identity, and treat all descriptors with that RSA identity
+ *    as describing the same router.
+ */
 static void
 dircollator_collate_by_rsa(dircollator_t *dc)
 {
@@ -189,6 +220,20 @@ dircollator_collate_by_rsa(dircollator_t *dc)
   dc->by_collated_rsa_sha1 = dc->by_rsa_sha1;
 }
 
+/**
+ * Collation function for ed25519 consensuses: collate the votes for each
+ * entry in <b>dc</b> by ed25519 key and by RSA key.
+ *
+ * The rule is, approximately:
+ *    If a <ed,rsa> identity is listed by more than half of authorities,
+ *    include it.  And include all <rsa>-only votes about that node as
+ *    matching.
+ *
+ *    Otherwise, if an <*,rsa> or <rsa> identity is listed by more than
+ *    half of the authorities, and no <ed,rsa> pair for the same RSA key
+ *    has been already been included based on the rule above, include
+ *    that RSA identity.
+ */
 static void
 dircollator_collate_by_ed25519(dircollator_t *dc)
 {
@@ -197,6 +242,7 @@ dircollator_collate_by_ed25519(dircollator_t *dc)
 
   ddmap_entry_t **iter;
 
+  /* Go over all <ed,rsa> pairs */
   HT_FOREACH(iter, double_digest_map, &dc->by_both_ids) {
     ddmap_entry_t *ent = *iter;
     int n = 0, i;
@@ -205,9 +251,13 @@ dircollator_collate_by_ed25519(dircollator_t *dc)
         ++n;
     }
 
+    /* If not enough authorties listed this exact <ed,rsa> pair,
+     * don't include it. */
     if (n <= total_authorities / 2)
       continue;
 
+    /* Now consider whether there are any other entries with the same
+     * RSA key (but with possibly different or missing ed value). */
     vote_routerstatus_t **vrs_lst2 = digestmap_get(dc->by_rsa_sha1,
                                                    (char*)ent->d);
     tor_assert(vrs_lst2);
@@ -220,13 +270,17 @@ dircollator_collate_by_ed25519(dircollator_t *dc)
       }
     }
 
+    /* Record that we have seen this RSA digest. */
     digestmap_set(rsa_digests, (char*)ent->d, ent->vrs_lst);
     smartlist_add(dc->all_rsa_sha1_lst, ent->d);
   }
 
+  /* Now look over all entries with an RSA digest, looking for RSA digests
+   * we didn't put in yet.
+   */
   DIGESTMAP_FOREACH(dc->by_rsa_sha1, k, vote_routerstatus_t **, vrs_lst) {
     if (digestmap_get(rsa_digests, k) != NULL)
-      continue;
+      continue; /* We already included this RSA digest */
 
     int n = 0, i;
     for (i = 0; i < dc->n_votes; ++i) {
@@ -235,7 +289,7 @@ dircollator_collate_by_ed25519(dircollator_t *dc)
     }
 
     if (n <= total_authorities / 2)
-      continue;
+      continue; /* Not enough votes */
 
     digestmap_set(rsa_digests, k, vrs_lst);
     smartlist_add(dc->all_rsa_sha1_lst, (char *)k);
@@ -244,15 +298,27 @@ dircollator_collate_by_ed25519(dircollator_t *dc)
   dc->by_collated_rsa_sha1 = rsa_digests;
 }
 
+/** Return the total number of collated router entries.  This function may
+ * only be called after dircollator_collate. */
 int
 dircollator_n_routers(dircollator_t *dc)
 {
+  tor_assert(dc->is_collated);
   return smartlist_len(dc->all_rsa_sha1_lst);
 }
 
+/** Return an array of vote_routerstatus_t entries for the <b>idx</b>th router
+ * in the collation order.  Each array contains n_votes elements, where the
+ * nth element of the array is the vote_routerstatus_t from the nth voter for
+ * this identity (or NULL if there is no such entry).
+ *
+ * The maximum value for <b>idx</b> is dircollator_n_routers().
+ *
+ * This function may only be called after dircollator_collate. */
 vote_routerstatus_t **
 dircollator_get_votes_for_router(dircollator_t *dc, int idx)
 {
+  tor_assert(dc->is_collated);
   tor_assert(idx < smartlist_len(dc->all_rsa_sha1_lst));
   return digestmap_get(dc->by_collated_rsa_sha1,
                        smartlist_get(dc->all_rsa_sha1_lst, idx));

+ 21 - 3
src/or/dircollate.h

@@ -5,8 +5,8 @@
 /* See LICENSE for licensing information */
 
 /**
- * \file dirvote.h
- * \brief Header file for dirvote.c.
+ * \file dircollate.h
+ * \brief Header file for dircollate.c.
  **/
 
 #ifndef TOR_DIRCOLLATE_H
@@ -30,18 +30,36 @@ vote_routerstatus_t **dircollator_get_votes_for_router(dircollator_t *dc,
 #ifdef DIRCOLLATE_PRIVATE
 struct ddmap_entry_s;
 typedef HT_HEAD(double_digest_map, ddmap_entry_s) double_digest_map_t;
+/** A dircollator keeps track of all the routerstatus entries in a
+ * set of networkstatus votes, and matches them by an appropriate rule. */
 struct dircollator_s {
-  /**DOCDOC */
+  /** True iff we have run the collation algorithm. */
   int is_collated;
+  /** The total number of votes that we received. */
   int n_votes;
+  /** The total number of authorities we acknowledge. */
   int n_authorities;
 
+  /** The index which the next vote to be added to this collator should
+   * receive. */
   int next_vote_num;
+  /** Map from RSA-SHA1 identity digest to an array of <b>n_votes</b>
+   * vote_routerstatus_t* pointers, such that the i'th member of the
+   * array is the i'th vote's entry for that RSA-SHA1 ID.*/
   digestmap_t *by_rsa_sha1;
+  /** Map from <ed, RSA-SHA1> pair to an array similar to that used in
+   * by_rsa_sha1 above. We include <NULL,RSA-SHA1> entries for votes that
+   * say that there is no Ed key. */
   struct double_digest_map by_both_ids;
 
+  /** One of two outputs created by collation: a map from RSA-SHA1
+   * identity digest to an array of the vote_routerstatus_t objects.  Entries
+   * only exist in this map for identities that we should include in the
+   * consensus. */
   digestmap_t *by_collated_rsa_sha1;
 
+  /** One of two outputs created by collation: a sorted array of RSA-SHA1
+   * identity digests .*/
   smartlist_t *all_rsa_sha1_lst;
 };
 #endif

+ 59 - 16
src/or/dirserv.c

@@ -1424,7 +1424,7 @@ router_counts_toward_thresholds(const node_t *node, time_t now,
  *
  * Also, set the is_exit flag of each router appropriately. */
 static void
-dirserv_compute_performance_thresholds(routerlist_t *rl,
+dirserv_compute_performance_thresholds(const smartlist_t *routers,
                                        digestmap_t *omit_as_sybil)
 {
   int n_active, n_active_nonexit, n_familiar;
@@ -1452,18 +1452,18 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
    * sort them and use that to compute thresholds. */
   n_active = n_active_nonexit = 0;
   /* Uptime for every active router. */
-  uptimes = tor_calloc(smartlist_len(rl->routers), sizeof(uint32_t));
+  uptimes = tor_calloc(smartlist_len(routers), sizeof(uint32_t));
   /* Bandwidth for every active router. */
-  bandwidths_kb = tor_calloc(smartlist_len(rl->routers), sizeof(uint32_t));
+  bandwidths_kb = tor_calloc(smartlist_len(routers), sizeof(uint32_t));
   /* Bandwidth for every active non-exit router. */
   bandwidths_excluding_exits_kb =
-    tor_calloc(smartlist_len(rl->routers), sizeof(uint32_t));
+    tor_calloc(smartlist_len(routers), sizeof(uint32_t));
   /* Weighted mean time between failure for each active router. */
-  mtbfs = tor_calloc(smartlist_len(rl->routers), sizeof(double));
+  mtbfs = tor_calloc(smartlist_len(routers), sizeof(double));
   /* Time-known for each active router. */
-  tks = tor_calloc(smartlist_len(rl->routers), sizeof(long));
+  tks = tor_calloc(smartlist_len(routers), sizeof(long));
   /* Weighted fractional uptime for each active router. */
-  wfus = tor_calloc(smartlist_len(rl->routers), sizeof(double));
+  wfus = tor_calloc(smartlist_len(routers), sizeof(double));
 
   nodelist_assert_ok();
 
@@ -1598,11 +1598,11 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
  * networkstatus_getinfo_by_purpose().
  */
 void
-dirserv_compute_bridge_flag_thresholds(routerlist_t *rl)
+dirserv_compute_bridge_flag_thresholds(const smartlist_t *routers)
 {
 
   digestmap_t *omit_as_sybil = digestmap_new();
-  dirserv_compute_performance_thresholds(rl, omit_as_sybil);
+  dirserv_compute_performance_thresholds(routers, omit_as_sybil);
   digestmap_free(omit_as_sybil, NULL);
 }
 
@@ -1755,16 +1755,13 @@ dirserv_get_bandwidth_for_router_kb(const routerinfo_t *ri)
  * how many measured bandwidths we know.  This is used to decide whether we
  * ever trust advertised bandwidths for purposes of assigning flags. */
 static void
-dirserv_count_measured_bws(routerlist_t *rl)
+dirserv_count_measured_bws(const smartlist_t *routers)
 {
   /* Initialize this first */
   routers_with_measured_bw = 0;
 
-  tor_assert(rl);
-  tor_assert(rl->routers);
-
   /* Iterate over the routerlist and count measured bandwidths */
-  SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) {
+  SMARTLIST_FOREACH_BEGIN(routers, const routerinfo_t *, ri) {
     /* Check if we know a measured bandwidth for this one */
     if (dirserv_has_measured_bw(ri->cache_info.identity_digest)) {
       ++routers_with_measured_bw;
@@ -2128,6 +2125,50 @@ get_possible_sybil_list(const smartlist_t *routers)
   return omit_as_sybil;
 }
 
+/** If there are entries in <b>routers</b> with exactly the same ed25519 keys,
+ * remove the older one.  If they are exactly the same age, remove the one
+ * with the greater descriptor digest. May alter the order of the list. */
+static void
+routers_make_ed_keys_unique(smartlist_t *routers)
+{
+  routerinfo_t *ri2;
+  digest256map_t *by_ed_key = digest256map_new();
+
+  SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
+    ri->omit_from_vote = 0;
+    if (ri->signing_key_cert == NULL)
+      continue; /* No ed key */
+    const uint8_t *pk = ri->signing_key_cert->signing_key.pubkey;
+    if ((ri2 = digest256map_get(by_ed_key, pk))) {
+      /* Duplicate; must omit one.  Set the omit_from_vote flag in whichever
+       * one has the earlier published_on. */
+      const time_t ri_pub = ri->cache_info.published_on;
+      const time_t ri2_pub = ri2->cache_info.published_on;
+      if (ri2_pub < ri_pub ||
+          (ri2_pub == ri_pub &&
+           memcmp(ri->cache_info.signed_descriptor_digest,
+                  ri2->cache_info.signed_descriptor_digest,DIGEST_LEN)<0)) {
+        digest256map_set(by_ed_key, pk, ri);
+        ri2->omit_from_vote = 1;
+      } else {
+        ri->omit_from_vote = 1;
+      }
+    } else {
+      /* Add to map */
+      digest256map_set(by_ed_key, pk, ri);
+    }
+  } SMARTLIST_FOREACH_END(ri);
+
+  digest256map_free(by_ed_key, NULL);
+
+  /* Now remove every router where the omit_from_vote flag got set. */
+  SMARTLIST_FOREACH_BEGIN(routers, const routerinfo_t *, ri) {
+    if (ri->omit_from_vote) {
+      SMARTLIST_DEL_CURRENT(routers, ri);
+    }
+  } SMARTLIST_FOREACH_END(ri);
+}
+
 /** Extract status information from <b>ri</b> and from other authority
  * functions and store it in <b>rs</b>>.
  *
@@ -2818,6 +2859,8 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
 
   routers = smartlist_new();
   smartlist_add_all(routers, rl->routers);
+  routers_make_ed_keys_unique(routers);
+  /* After this point, don't use rl->routers; use 'routers' instead. */
   routers_sort_by_identity(routers);
   omit_as_sybil = get_possible_sybil_list(routers);
 
@@ -2828,9 +2871,9 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
 
   /* Count how many have measured bandwidths so we know how to assign flags;
    * this must come before dirserv_compute_performance_thresholds() */
-  dirserv_count_measured_bws(rl);
+  dirserv_count_measured_bws(routers);
 
-  dirserv_compute_performance_thresholds(rl, omit_as_sybil);
+  dirserv_compute_performance_thresholds(routers, omit_as_sybil);
 
   routerstatuses = smartlist_new();
   microdescriptors = smartlist_new();

+ 1 - 1
src/or/dirserv.h

@@ -50,7 +50,7 @@ int list_server_status_v1(smartlist_t *routers, char **router_status_out,
 int dirserv_dump_directory_to_string(char **dir_out,
                                      crypto_pk_t *private_key);
 char *dirserv_get_flag_thresholds_line(void);
-void dirserv_compute_bridge_flag_thresholds(routerlist_t *rl);
+void dirserv_compute_bridge_flag_thresholds(const smartlist_t *routers);
 
 int directory_fetches_from_authorities(const or_options_t *options);
 int directory_fetches_dir_info_early(const or_options_t *options);

+ 35 - 0
src/or/dirvote.c

@@ -557,6 +557,13 @@ compute_consensus_method(smartlist_t *votes)
 static int
 consensus_method_is_supported(int method)
 {
+  if (method == MIN_METHOD_FOR_ED25519_ID_IN_MD) {
+    /* This method was broken due to buggy code accidently left in
+     * dircollate.c; do not actually use it.
+     */
+    return 0;
+  }
+
   return (method >= MIN_SUPPORTED_CONSENSUS_METHOD) &&
     (method <= MAX_SUPPORTED_CONSENSUS_METHOD);
 }
@@ -1234,6 +1241,9 @@ networkstatus_compute_consensus(smartlist_t *votes,
     smartlist_free(combined_server_versions);
     smartlist_free(combined_client_versions);
 
+    if (consensus_method >= MIN_METHOD_FOR_ED25519_ID_VOTING)
+      smartlist_add(flags, tor_strdup("NoEdConsensus"));
+
     smartlist_sort_strings(flags);
     smartlist_uniq_strings(flags);
 
@@ -1531,6 +1541,8 @@ networkstatus_compute_consensus(smartlist_t *votes,
       num_bandwidths = 0;
       num_mbws = 0;
       num_guardfraction_inputs = 0;
+      int ed_consensus = 0;
+      const uint8_t *ed_consensus_val = NULL;
 
       /* Okay, go through all the entries for this digest. */
       for (int voter_idx = 0; voter_idx < smartlist_len(votes); ++voter_idx) {
@@ -1572,6 +1584,17 @@ networkstatus_compute_consensus(smartlist_t *votes,
 
         if (rs->status.has_bandwidth)
           bandwidths_kb[num_bandwidths++] = rs->status.bandwidth_kb;
+
+        /* Count number for which ed25519 is canonical. */
+        if (rs->ed25519_reflects_consensus) {
+          ++ed_consensus;
+          if (ed_consensus_val) {
+            tor_assert(fast_memeq(ed_consensus_val, rs->ed25519_id,
+                                  ED25519_PUBKEY_LEN));
+          } else {
+            ed_consensus_val = rs->ed25519_id;
+          }
+        }
       }
 
       /* We don't include this router at all unless more than half of
@@ -1579,6 +1602,14 @@ networkstatus_compute_consensus(smartlist_t *votes,
       if (n_listing <= total_authorities/2)
         continue;
 
+      if (ed_consensus > 0) {
+        tor_assert(consensus_method >= MIN_METHOD_FOR_ED25519_ID_VOTING);
+        if (ed_consensus <= total_authorities / 2) {
+          log_warn(LD_BUG, "Not enough entries had ed_consensus set; how "
+                   "can we have a consensus of %d?", ed_consensus);
+        }
+      }
+
       /* The clangalyzer can't figure out that this will never be NULL
        * if n_listing is at least 1 */
       tor_assert(current_rsa_id);
@@ -1632,6 +1663,10 @@ networkstatus_compute_consensus(smartlist_t *votes,
         } else if (!strcmp(fl, "Unnamed")) {
           if (is_unnamed)
             smartlist_add(chosen_flags, (char*)fl);
+        } else if (!strcmp(fl, "NoEdConsensus") &&
+                   consensus_method >= MIN_METHOD_FOR_ED25519_ID_VOTING) {
+          if (ed_consensus <= total_authorities/2)
+            smartlist_add(chosen_flags, (char*)fl);
         } else {
           if (flag_counts[fl_sl_idx] > n_flag_voters[fl_sl_idx]/2) {
             smartlist_add(chosen_flags, (char*)fl);

+ 4 - 3
src/or/dirvote.h

@@ -55,7 +55,7 @@
 #define MIN_SUPPORTED_CONSENSUS_METHOD 13
 
 /** The highest consensus method that we currently support. */
-#define MAX_SUPPORTED_CONSENSUS_METHOD 21
+#define MAX_SUPPORTED_CONSENSUS_METHOD 22
 
 /** Lowest consensus method where microdesc consensuses omit any entry
  * with no microdesc. */
@@ -87,11 +87,12 @@
 #define MIN_METHOD_FOR_GUARDFRACTION 20
 
 /** Lowest consensus method where authorities may include an "id" line for
- * ed25519 identities in microdescriptors. */
+ * ed25519 identities in microdescriptors. (Broken; see
+ * consensus_method_is_supported() for more info.) */
 #define MIN_METHOD_FOR_ED25519_ID_IN_MD 21
 /** Lowest consensus method where authorities vote on ed25519 ids and ensure
  * ed25519 id consistency. */
-#define MIN_METHOD_FOR_ED25519_ID_VOTING MIN_METHOD_FOR_ED25519_ID_IN_MD
+#define MIN_METHOD_FOR_ED25519_ID_VOTING 22
 
 /** Default bandwidth to clip unmeasured bandwidths to using method >=
  * MIN_METHOD_TO_CLIP_UNMEASURED_BW.  (This is not a consensus method; do not

+ 1 - 1
src/or/networkstatus.c

@@ -2047,7 +2047,7 @@ networkstatus_dump_bridge_status_to_file(time_t now)
   char published[ISO_TIME_LEN+1];
 
   format_iso_time(published, now);
-  dirserv_compute_bridge_flag_thresholds(rl);
+  dirserv_compute_bridge_flag_thresholds(rl->routers);
   thresholds = dirserv_get_flag_thresholds_line();
   tor_asprintf(&published_thresholds_and_status,
                "published %s\nflag-thresholds %s\n%s",

+ 11 - 2
src/or/or.h

@@ -2158,6 +2158,10 @@ typedef struct {
    * dir_port > 0. */
   unsigned int supports_tunnelled_dir_requests:1;
 
+  /** Used during voting to indicate that we should not include an entry for
+   * this routerinfo. Used only during voting. */
+  unsigned int omit_from_vote:1;
+
 /** Tor can use this router for general positions in circuits; we got it
  * from a directory server as usual, or we're an authority and a server
  * uploaded it. */
@@ -2454,8 +2458,13 @@ typedef struct vote_routerstatus_t {
   char *version; /**< The version that the authority says this router is
                   * running. */
   unsigned int has_measured_bw:1; /**< The vote had a measured bw */
-  unsigned int has_ed25519_listing:1; /** DOCDOC */
-  unsigned int ed25519_reflects_consensus:1; /** DOCDOC */
+  /** True iff the vote included an entry for ed25519 ID, or included
+   * "id ed25519 none" to indicate that there was no ed25519 ID. */
+  unsigned int has_ed25519_listing:1;
+  /** True if the Ed25519 listing here is the consensus-opinion for the
+   * Ed25519 listing; false if there was no consensus on Ed25519 key status,
+   * or if this VRS doesn't reflect it. */
+  unsigned int ed25519_reflects_consensus:1;
   uint32_t measured_bw_kb; /**< Measured bandwidth (capacity) of the router */
   /** The hash or hashes that the authority claims this microdesc has. */
   vote_microdesc_hash_t *microdesc;

+ 12 - 13
src/or/routerparse.c

@@ -2873,7 +2873,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
                       (ns_type == NS_TYPE_CONSENSUS) ?
                       networkstatus_consensus_token_table :
                       networkstatus_token_table, 0)) {
-    log_warn(LD_DIR, "Error tokenizing network-status vote header");
+    log_warn(LD_DIR, "Error tokenizing network-status header");
     goto err;
   }
 
@@ -3096,7 +3096,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
           base16_decode(voter->identity_digest, sizeof(voter->identity_digest),
                         tok->args[1], HEX_DIGEST_LEN) < 0) {
         log_warn(LD_DIR, "Error decoding identity digest %s in "
-                 "network-status vote.", escaped(tok->args[1]));
+                 "network-status document.", escaped(tok->args[1]));
         goto err;
       }
       if (ns->type != NS_TYPE_CONSENSUS &&
@@ -3155,7 +3155,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
     voter = NULL;
   }
   if (smartlist_len(ns->voters) == 0) {
-    log_warn(LD_DIR, "Missing dir-source elements in a vote networkstatus.");
+    log_warn(LD_DIR, "Missing dir-source elements in a networkstatus.");
     goto err;
   } else if (ns->type != NS_TYPE_CONSENSUS && smartlist_len(ns->voters) != 1) {
     log_warn(LD_DIR, "Too many dir-source elements in a vote networkstatus.");
@@ -3216,8 +3216,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
     }
     if (fast_memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN)
         >= 0) {
-      log_warn(LD_DIR, "Vote networkstatus entries not sorted by identity "
-               "digest");
+      log_warn(LD_DIR, "Networkstatus entries not sorted by identity digest");
       goto err;
     }
   }
@@ -3330,12 +3329,12 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
         base16_decode(declared_identity, sizeof(declared_identity),
                       id_hexdigest, HEX_DIGEST_LEN) < 0) {
       log_warn(LD_DIR, "Error decoding declared identity %s in "
-               "network-status vote.", escaped(id_hexdigest));
+               "network-status document.", escaped(id_hexdigest));
       goto err;
     }
     if (!(v = networkstatus_get_voter_by_id(ns, declared_identity))) {
-      log_warn(LD_DIR, "ID on signature on network-status vote does not match "
-               "any declared directory source.");
+      log_warn(LD_DIR, "ID on signature on network-status document does "
+               "not match any declared directory source.");
       goto err;
     }
     sig = tor_malloc_zero(sizeof(document_signature_t));
@@ -3345,7 +3344,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
         base16_decode(sig->signing_key_digest, sizeof(sig->signing_key_digest),
                       sk_hexdigest, HEX_DIGEST_LEN) < 0) {
       log_warn(LD_DIR, "Error decoding declared signing key digest %s in "
-               "network-status vote.", escaped(sk_hexdigest));
+               "network-status document.", escaped(sk_hexdigest));
       tor_free(sig);
       goto err;
     }
@@ -3364,8 +3363,8 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
       /* We already parsed a vote with this algorithm from this voter. Use the
          first one. */
       log_fn(LOG_PROTOCOL_WARN, LD_DIR, "We received a networkstatus "
-             "that contains two votes from the same voter with the same "
-             "algorithm. Ignoring the second vote.");
+             "that contains two signatures from the same voter with the same "
+             "algorithm. Ignoring the second signature.");
       tor_free(sig);
       continue;
     }
@@ -3373,7 +3372,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
     if (ns->type != NS_TYPE_CONSENSUS) {
       if (check_signature_token(ns_digests.d[DIGEST_SHA1], DIGEST_LEN,
                                 tok, ns->cert->signing_key, 0,
-                                "network-status vote")) {
+                                "network-status document")) {
         tor_free(sig);
         goto err;
       }
@@ -3392,7 +3391,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
   } SMARTLIST_FOREACH_END(_tok);
 
   if (! n_signatures) {
-    log_warn(LD_DIR, "No signatures on networkstatus vote.");
+    log_warn(LD_DIR, "No signatures on networkstatus document.");
     goto err;
   } else if (ns->type == NS_TYPE_VOTE && n_signatures != 1) {
     log_warn(LD_DIR, "Received more than one signature on a "