Add a new consensus method to handle MiddleOnly specially.

When this method is in place, then any relay which is assigned
MiddleOnly has Exit, V2Dir, Guard, and HSDir cleared
(and has BadExit set if appropriate).
This commit is contained in:
Nick Mathewson 2021-10-08 11:36:04 -04:00 committed by Alexander Færøy
parent fc542167cb
commit ab26475cab
2 changed files with 44 additions and 3 deletions

View File

@ -1479,6 +1479,21 @@ compute_nth_protocol_set(int n, int n_voters, const smartlist_t *votes)
return result; return result;
} }
/** Helper: Takes a smartlist of `const char *` flags, and a flag to remove.
*
* Removes that flag if it is present in the list. Doesn't free it.
*/
static void
remove_flag(smartlist_t *sl, const char *flag)
{
/* We can't use smartlist_string_remove() here, since that doesn't preserve
* order, and since it frees elements from the string. */
int idx = smartlist_string_pos(sl, flag);
if (idx >= 0)
smartlist_del_keeporder(sl, idx);
}
/** Given a list of vote networkstatus_t in <b>votes</b>, our public /** Given a list of vote networkstatus_t in <b>votes</b>, our public
* authority <b>identity_key</b>, our private authority <b>signing_key</b>, * authority <b>identity_key</b>, our private authority <b>signing_key</b>,
* and the number of <b>total_authorities</b> that we believe exist in our * and the number of <b>total_authorities</b> that we believe exist in our
@ -1633,6 +1648,9 @@ networkstatus_compute_consensus(smartlist_t *votes,
tor_free(votesec_list); tor_free(votesec_list);
tor_free(distsec_list); tor_free(distsec_list);
} }
// True if anybody is voting on the BadExit flag.
const bool badexit_flag_is_listed =
smartlist_contains_string(flags, "BadExit");
chunks = smartlist_new(); chunks = smartlist_new();
@ -1924,7 +1942,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
const char *chosen_name = NULL; const char *chosen_name = NULL;
int exitsummary_disagreement = 0; int exitsummary_disagreement = 0;
int is_named = 0, is_unnamed = 0, is_running = 0, is_valid = 0; int is_named = 0, is_unnamed = 0, is_running = 0, is_valid = 0;
int is_guard = 0, is_exit = 0, is_bad_exit = 0; int is_guard = 0, is_exit = 0, is_bad_exit = 0, is_middle_only = 0;
int naming_conflict = 0; int naming_conflict = 0;
int n_listing = 0; int n_listing = 0;
char microdesc_digest[DIGEST256_LEN]; char microdesc_digest[DIGEST256_LEN];
@ -2055,7 +2073,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
} }
/* Set the flags. */ /* Set the flags. */
smartlist_add(chosen_flags, (char*)"s"); /* for the start of the line. */
SMARTLIST_FOREACH_BEGIN(flags, const char *, fl) { SMARTLIST_FOREACH_BEGIN(flags, const char *, fl) {
if (!strcmp(fl, "Named")) { if (!strcmp(fl, "Named")) {
if (is_named) if (is_named)
@ -2077,6 +2094,8 @@ networkstatus_compute_consensus(smartlist_t *votes,
is_running = 1; is_running = 1;
else if (!strcmp(fl, "BadExit")) else if (!strcmp(fl, "BadExit"))
is_bad_exit = 1; is_bad_exit = 1;
else if (!strcmp(fl, "MiddleOnly"))
is_middle_only = 1;
else if (!strcmp(fl, "Valid")) else if (!strcmp(fl, "Valid"))
is_valid = 1; is_valid = 1;
} }
@ -2093,6 +2112,22 @@ networkstatus_compute_consensus(smartlist_t *votes,
if (!is_valid) if (!is_valid)
continue; continue;
/* Starting with consensus method 32, we handle the middle-only
* flag specially: when it is present, we clear some flags, and
* set others. */
if (is_middle_only && consensus_method >= MIN_METHOD_FOR_MIDDLEONLY) {
remove_flag(chosen_flags, "Exit");
remove_flag(chosen_flags, "V2Dir");
remove_flag(chosen_flags, "Guard");
remove_flag(chosen_flags, "HSDir");
is_exit = is_guard = 0;
if (! is_bad_exit && badexit_flag_is_listed) {
is_bad_exit = 1;
smartlist_add(chosen_flags, (char *)"BadExit");
smartlist_sort_strings(chosen_flags); // restore order.
}
}
/* Pick the version. */ /* Pick the version. */
if (smartlist_len(versions)) { if (smartlist_len(versions)) {
sort_version_list(versions, 0); sort_version_list(versions, 0);
@ -2253,6 +2288,8 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_add_asprintf(chunks, "m %s\n", m); smartlist_add_asprintf(chunks, "m %s\n", m);
} }
/* Next line is all flags. The "\n" is missing. */ /* Next line is all flags. The "\n" is missing. */
smartlist_add_asprintf(chunks, "s%s",
smartlist_len(chosen_flags)?" ":"");
smartlist_add(chunks, smartlist_add(chunks,
smartlist_join_strings(chosen_flags, " ", 0, NULL)); smartlist_join_strings(chosen_flags, " ", 0, NULL));
/* Now the version line. */ /* Now the version line. */

View File

@ -53,7 +53,7 @@
#define MIN_SUPPORTED_CONSENSUS_METHOD 28 #define MIN_SUPPORTED_CONSENSUS_METHOD 28
/** The highest consensus method that we currently support. */ /** The highest consensus method that we currently support. */
#define MAX_SUPPORTED_CONSENSUS_METHOD 31 #define MAX_SUPPORTED_CONSENSUS_METHOD 32
/** /**
* Lowest consensus method where microdescriptor lines are put in canonical * Lowest consensus method where microdescriptor lines are put in canonical
@ -70,6 +70,10 @@
*/ */
#define MIN_METHOD_FOR_CORRECT_BWWEIGHTSCALE 31 #define MIN_METHOD_FOR_CORRECT_BWWEIGHTSCALE 31
/** Lowest consensus method for which we handle the MiddleOnly flag specially.
*/
#define MIN_METHOD_FOR_MIDDLEONLY 32
/** Default bandwidth to clip unmeasured bandwidths to using method >= /** Default bandwidth to clip unmeasured bandwidths to using method >=
* MIN_METHOD_TO_CLIP_UNMEASURED_BW. (This is not a consensus method; do not * MIN_METHOD_TO_CLIP_UNMEASURED_BW. (This is not a consensus method; do not
* get confused with the above macros.) */ * get confused with the above macros.) */