From f4f780b526df83032748782fb5917a7ee7412902 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 2 Oct 2007 20:19:43 +0000 Subject: [PATCH] r15510@catbus: nickm | 2007-10-02 16:14:42 -0400 Add support for more vote URLs that weasel wanted. Weasel: please test this before I inflict it on anybody else. :) svn:r11749 --- ChangeLog | 4 ++ doc/spec/dir-spec.txt | 9 +++++ src/or/directory.c | 19 +++++++-- src/or/dirvote.c | 94 ++++++++++++++++++++++++++++++++----------- src/or/or.h | 6 ++- 5 files changed, 102 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4a5d98edd2..6b025704d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,10 @@ Changes in version 0.2.0.8-alpha - 2007-??-?? - Use annotations to record the source for each descriptor. - Use annotations to record the purpose of each descriptor. + o Minor features (v3 authority system): + - Add more ways for tools to download the votes that lead to the current + consensus. + o Major bugfixes (performance): - Fix really bad O(n^2) performance when parsing a long list of routers: Instead of searching the entire list for an "extra-info " string which diff --git a/doc/spec/dir-spec.txt b/doc/spec/dir-spec.txt index 63995254e6..9bbdfc4f3a 100644 --- a/doc/spec/dir-spec.txt +++ b/doc/spec/dir-spec.txt @@ -1152,6 +1152,9 @@ $Id$ at http:///tor/status-vote/next/.z where is the fingerprint of the other authority's identity key. + And at + http:///tor/status-vote/next/d/.z + where is the digest of the vote document. The consensus status, along with as many signatures as the server currently knows, should be available at @@ -1166,6 +1169,12 @@ $Id$ and http:///tor/status-vote/current/consensus-signatures.z + The other vote documents are analogously made available under + http:///tor/status-vote/current/authority.z + http:///tor/status-vote/current/.z + http:///tor/status-vote/current/d/.z + once the consensus is complete. + Once an authority has computed and signed a consensus network status, it should send its detached signature to each other authority in an HTTP POST request to the URL: diff --git a/src/or/directory.c b/src/or/directory.c index cedaeb9f38..da565b2ff0 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -2124,16 +2124,27 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, const char *item; if ((item=dirvote_get_pending_detached_signatures())) smartlist_add(items, (char*)item); - } else if (!current && !strcmp(url, "authority")) { + } else if (!strcmp(url, "authority")) { const cached_dir_t *d; - if ((d=dirvote_get_vote(NULL))) + if ((d=dirvote_get_vote(NULL, 1, current, !current))) smartlist_add(dir_items, (cached_dir_t*)d); - } else if (!current) { + } else { const cached_dir_t *d; smartlist_t *fps = smartlist_create(); + int by_id, include_pending, include_previous; + if (!strcmpstart(url, "d/")) { + url += 2; + by_id = 0; + include_pending = include_previous = 1; + } else { + by_id = 1; + include_pending = current; + include_previous = !current; + } dir_split_resource_into_fingerprints(url, fps, NULL, 1, 1); SMARTLIST_FOREACH(fps, char *, fp, { - if ((d = dirvote_get_vote(fp))) + if ((d = dirvote_get_vote(fp, by_id, + include_pending, include_previous))) smartlist_add(dir_items, (cached_dir_t*)d); tor_free(fp); }); diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 1710fb5a04..94025c54e3 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -1133,8 +1133,7 @@ dirvote_recalculate_timing(time_t now) voting_schedule.fetch_missing_votes = start - dist_delay - (vote_delay/2); voting_schedule.voting_starts = start - dist_delay - vote_delay; - voting_schedule.discard_old_votes = start + - ((end-start) - vote_delay - dist_delay)/2 ; + voting_schedule.discard_old_votes = start; } /** Entry point: Take whatever voting actions are pending as of now. */ @@ -1185,7 +1184,7 @@ dirvote_act(time_t now) } if (voting_schedule.discard_old_votes < now) { log_notice(LD_DIR, "Time to discard old votes."); - dirvote_clear_pending_votes(); + dirvote_clear_votes(0); dirvote_recalculate_timing(now); } } @@ -1198,8 +1197,12 @@ typedef struct pending_vote_t { networkstatus_vote_t *vote; } pending_vote_t; -/** List of pending_vote_t for the current vote. */ +/** List of pending_vote_t for the current vote. Before we've used them to + * build a consensus, the votes go here. */ static smartlist_t *pending_vote_list = NULL; +/** List of pending_vote_t for the previous vote. After we've used them to + * build a consensus, the votes go here for the next period. */ +static smartlist_t *previous_vote_list = NULL; /** The body of the consensus that we're currently building. Once we * have it built, it goes into dirserv.c */ static char *pending_consensus_body = NULL; @@ -1251,7 +1254,7 @@ dirvote_fetch_missing_votes(void) { if (!(ds->type & V3_AUTHORITY)) continue; - if (!dirvote_get_vote(ds->v3_identity_digest)) { + if (!dirvote_get_vote(ds->v3_identity_digest, 1, 1, 0)) { char *cp = tor_malloc(HEX_DIGEST_LEN+1); base16_encode(cp, HEX_DIGEST_LEN+1, ds->v3_identity_digest, DIGEST_LEN); @@ -1288,17 +1291,36 @@ dirvote_fetch_missing_signatures(void) /** Drop all currently pending votes, consensus, and detached signatures. */ void -dirvote_clear_pending_votes(void) +dirvote_clear_votes(int all_votes) { - if (pending_vote_list) { + if (!previous_vote_list) + previous_vote_list = smartlist_create(); + if (!pending_vote_list) + pending_vote_list = smartlist_create(); + + /* All "previous" votes are now junk. */ + SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, v, { + cached_dir_decref(v->vote_body); + v->vote_body = NULL; + networkstatus_vote_free(v->vote); + tor_free(v); + }); + smartlist_clear(previous_vote_list); + + if (all_votes) { + /* If we're dumping all the votes, we delete the pending ones. */ SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, { cached_dir_decref(v->vote_body); v->vote_body = NULL; networkstatus_vote_free(v->vote); tor_free(v); }); - smartlist_clear(pending_vote_list); + } else { + /* Otherwise, we move them into "previous". */ + smartlist_add_all(previous_vote_list, pending_vote_list); } + smartlist_clear(pending_vote_list); + if (pending_consensus_signature_list) { SMARTLIST_FOREACH(pending_consensus_signature_list, char *, cp, tor_free(cp)); @@ -1685,12 +1707,13 @@ dirvote_publish_consensus(void) void dirvote_free_all(void) { - dirvote_clear_pending_votes(); - if (pending_vote_list) { - /* now empty as a result of clear_pending_votes. */ - smartlist_free(pending_vote_list); - pending_vote_list = NULL; - } + dirvote_clear_votes(1); + /* now empty as a result of clear_pending_votes. */ + smartlist_free(pending_vote_list); + pending_vote_list = NULL; + smartlist_free(previous_vote_list); + previous_vote_list = NULL; + tor_free(pending_consensus_body); tor_free(pending_consensus_signatures); if (pending_consensus) { @@ -1725,22 +1748,45 @@ dirvote_get_pending_detached_signatures(void) /** Return the vote for the authority with the v3 authority identity key * digest id. If id is NULL, return our own vote. May return - * NULL if we have no vote for the authority in question. */ + * NULL if we have no vote for the authority in question. + * DOCDOC args */ const cached_dir_t * -dirvote_get_vote(const char *id) +dirvote_get_vote(const char *fp, int by_id, int include_previous, + int include_pending) { - if (!pending_vote_list) + if (!pending_vote_list && !previous_vote_list) return NULL; - if (id == NULL) { + if (fp == NULL) { authority_cert_t *c = get_my_v3_authority_cert(); - if (c) - id = c->cache_info.identity_digest; - else + if (c) { + fp = c->cache_info.identity_digest; + by_id = 1; + } else return NULL; } - SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv, - if (!memcmp(get_voter(pv->vote)->identity_digest, id, DIGEST_LEN)) - return pv->vote_body); + if (by_id) { + if (pending_vote_list && include_pending) { + SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv, + if (!memcmp(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN)) + return pv->vote_body); + } + if (previous_vote_list && include_previous) { + SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv, + if (!memcmp(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN)) + return pv->vote_body); + } + } else { + if (pending_vote_list && include_pending) { + SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv, + if (!memcmp(pv->vote->networkstatus_digest, fp, DIGEST_LEN)) + return pv->vote_body); + } + if (previous_vote_list && include_previous) { + SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv, + if (!memcmp(pv->vote->networkstatus_digest, fp, DIGEST_LEN)) + return pv->vote_body); + } + } return NULL; } diff --git a/src/or/or.h b/src/or/or.h index 361569f36e..79d3831a37 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2887,7 +2887,7 @@ void dirvote_act(time_t now); /* invoked on timers and by outside triggers. */ void dirvote_perform_vote(void); -void dirvote_clear_pending_votes(void); +void dirvote_clear_votes(int all_votes); struct pending_vote_t * dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out); @@ -2898,7 +2898,9 @@ int dirvote_publish_consensus(void); /* Item access */ const char *dirvote_get_pending_consensus(void); const char *dirvote_get_pending_detached_signatures(void); -const cached_dir_t *dirvote_get_vote(const char *id); +const cached_dir_t *dirvote_get_vote(const char *fp, int by_id, + int include_pending, + int include_previous); #ifdef DIRVOTE_PRIVATE int networkstatus_check_voter_signature(networkstatus_vote_t *consensus,