[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r10976: More directory voting code. Now, if everything works, and I (in tor/trunk: . doc src/or)
Author: nickm
Date: 2007-07-29 19:11:44 -0400 (Sun, 29 Jul 2007)
New Revision: 10976
Modified:
tor/trunk/
tor/trunk/ChangeLog
tor/trunk/doc/TODO
tor/trunk/src/or/directory.c
tor/trunk/src/or/dirserv.c
tor/trunk/src/or/dirvote.c
tor/trunk/src/or/main.c
tor/trunk/src/or/or.h
tor/trunk/src/or/routerlist.c
Log:
r13989@catbus: nickm | 2007-07-29 19:11:07 -0400
More directory voting code. Now, if everything works, and I haven't forgotten anything, it is possible to set up some v3 authorities and start voting. Of course, I have probably forgotten something, and there are probably bugs in there somewhere too.
Property changes on: tor/trunk
___________________________________________________________________
svk:merge ticket from /tor/trunk [r13989] on 8246c3cf-6607-4228-993b-4d95d33730f1
Modified: tor/trunk/ChangeLog
===================================================================
--- tor/trunk/ChangeLog 2007-07-29 23:11:42 UTC (rev 10975)
+++ tor/trunk/ChangeLog 2007-07-29 23:11:44 UTC (rev 10976)
@@ -10,6 +10,12 @@
- Be even more aggressive about separating local traffic from relayed
traffic when RelayBandwidthRate is set. (Refines proposal 111.)
+ o Major features (experimental):
+ - First cut of code for directory authorities to vote on a common
+ network status document rather than each publishing their own
+ opinion. This code needs more testing and more corner-case handling
+ before it's ready for use.
+
o Security fixes:
- Directory authorities now call routers Fast if their bandwidth is
at least 100KB/s, and consider their bandwidth adequate to be a
Modified: tor/trunk/doc/TODO
===================================================================
--- tor/trunk/doc/TODO 2007-07-29 23:11:42 UTC (rev 10975)
+++ tor/trunk/doc/TODO 2007-07-29 23:11:44 UTC (rev 10976)
@@ -95,29 +95,30 @@
- Download as needed.
o Actually invoke trusted_dirs_flush_certs_to_disk()
- Serve list as needed.
- * Detect whether votes are really all for the same period.
o Avoid double-checking signatures every time we get a vote.
- Warn about expired stuff.
- Fix all XXXX020s in vote code
- * Unit tests for detached signatures and signature manipulation.
o Code to generate votes
o Code to generate consensus from a list of votes
+ * Detect whether votes are really all for the same period.
o Add a signature to a consensus.
+ * Unit tests for detached signatures and signature manipulation.
o Code to check signatures on a consensus
- Push/pull documents as appropriate.
- . Push vote on voting
+ o Push vote on voting
o Push vote
o Process vote when received
o Even if we get it before we start voting ourself.
- * Push signature on forming consensus.
+ o Push signature on forming consensus.
o Push signature
o Add signatures when received
o Queue received signatures before consensus is ready
- * When consensus is ready, use queued signatures.
+ o When consensus is ready, use queued signatures.
- Pull votes and signatures if we don't get them.
- * Serve and store consensuses.
+ o Serve consensuses.
+ - Store consensuses
- Cache votes and signatures on disk.
- * Discard votes in advance of next voting period.
+ o Discard votes in advance of next voting period.
o Have clients know which authorities are v3 authorities, and what
their keys are.
- While we're at it, let v3 authorities have fqdns lines.
@@ -140,6 +141,9 @@
- Drop bandwidth history from router-descriptors
- 105: Version negotiation for the Tor protocol
- 108: Base "Stable" Flag on Mean Time Between Failures
+ - Track mtbf in rephist.c
+ - Record mtbf between invocations
+ - Base stable on mtbf.
o 109: No more than one server per IP address
o 103: Splitting identity key from regularly used signing key
o Merge with 101 into a new dir-spec.txt
Modified: tor/trunk/src/or/directory.c
===================================================================
--- tor/trunk/src/or/directory.c 2007-07-29 23:11:42 UTC (rev 10975)
+++ tor/trunk/src/or/directory.c 2007-07-29 23:11:44 UTC (rev 10976)
@@ -1817,6 +1817,7 @@
return 0;
}
+
if (!strcmp(url,"/tor/running-routers") ||
!strcmp(url,"/tor/running-routers.z")) { /* running-routers fetch */
int deflated = !strcmp(url,"/tor/running-routers.z");
@@ -1856,25 +1857,35 @@
return 0;
}
- if (!strcmpstart(url,"/tor/status/")) {
- /* v2 network status fetch. */
+ if (!strcmpstart(url,"/tor/status/")
+ || !strcmp(url, "/tor/status-vote/current/consensus")
+ || !strcmp(url, "/tor/status-vote/current/consensus.z")) {
+ /* v2 or v3 network status fetch. */
size_t url_len = strlen(url);
int deflated = !strcmp(url+url_len-2, ".z");
smartlist_t *dir_fps = smartlist_create();
+ int is_v3 = !strcmpstart(url, "/tor/status-vote");
const char *request_type = NULL;
const char *key = url + strlen("/tor/status/");
if (deflated)
url[url_len-2] = '\0';
- dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
- if (!strcmpstart(key, "fp/"))
- request_type = deflated?"/tor/status/fp.z":"/tor/status/fp";
- else if (!strcmpstart(key, "authority"))
- request_type = deflated?"/tor/status/authority.z":
- "/tor/status/authority";
- else if (!strcmpstart(key, "all"))
- request_type = deflated?"/tor/status/all.z":"/tor/status/all";
- else
- request_type = "/tor/status/?";
+ if (!is_v3) {
+ dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
+ if (!strcmpstart(key, "fp/"))
+ request_type = deflated?"/tor/status/fp.z":"/tor/status/fp";
+ else if (!strcmpstart(key, "authority"))
+ request_type = deflated?"/tor/status/authority.z":
+ "/tor/status/authority";
+ else if (!strcmpstart(key, "all"))
+ request_type = deflated?"/tor/status/all.z":"/tor/status/all";
+ else
+ request_type = "/tor/status/?";
+ } else {
+ smartlist_add(dir_fps, tor_memdup("\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0", 20));
+ request_type = deflated?"v3.z":"v3";
+ }
+
tor_free(url);
if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
write_http_status_line(conn, 503, "Network status object unavailable");
Modified: tor/trunk/src/or/dirserv.c
===================================================================
--- tor/trunk/src/or/dirserv.c 2007-07-29 23:11:42 UTC (rev 10975)
+++ tor/trunk/src/or/dirserv.c 2007-07-29 23:11:44 UTC (rev 10976)
@@ -1079,6 +1079,9 @@
* cached_dir_t. */
static digestmap_t *cached_v2_networkstatus = NULL;
+/** DOCDOC */
+static cached_dir_t *cached_v3_networkstatus = NULL;
+
/** Possibly replace the contents of <b>d</b> with the value of
* <b>directory</b> published on <b>when</b>, unless <b>when</b> is older than
* the last value, or too far in the future.
@@ -1245,6 +1248,17 @@
}
}
+/* DOCDOC */
+void
+dirserv_set_cached_networkstatus_v3(const char *networkstatus,
+ time_t published)
+{
+ if (cached_v3_networkstatus)
+ cached_dir_decref(cached_v3_networkstatus);
+ cached_v3_networkstatus = new_cached_dir(
+ tor_strdup(networkstatus), published);
+}
+
/** Remove any v2 networkstatus from the directory cache that was published
* before <b>cutoff</b>. */
void
@@ -1446,6 +1460,12 @@
"v1 network status list", V1_AUTHORITY);
}
+cached_dir_t *
+dirserv_get_consensus(void)
+{
+ return cached_v3_networkstatus;
+}
+
/** For authoritative directories: the current (v2) network status. */
static cached_dir_t *the_v2_networkstatus = NULL;
@@ -2909,7 +2929,9 @@
/* Add another networkstatus; start serving it. */
char *fp = smartlist_pop_last(conn->fingerprint_stack);
cached_dir_t *d;
- if (router_digest_is_me(fp))
+ if (tor_digest_is_zero(fp)) /* XXXX020 document this "feature". */
+ d = cached_v3_networkstatus;
+ else if (router_digest_is_me(fp))
d = the_v2_networkstatus;
else
d = digestmap_get(cached_v2_networkstatus, fp);
Modified: tor/trunk/src/or/dirvote.c
===================================================================
--- tor/trunk/src/or/dirvote.c 2007-07-29 23:11:42 UTC (rev 10975)
+++ tor/trunk/src/or/dirvote.c 2007-07-29 23:11:44 UTC (rev 10976)
@@ -13,6 +13,10 @@
* \brief Functions to compute directory consensus, and schedule voting.
**/
+static int dirvote_add_signatures_to_pending_consensus(
+ const char *detached_signatures_body,
+ const char **msg_out);
+
/* =====
* Voting and consensus generation
* ===== */
@@ -721,6 +725,7 @@
int n_bad = 0;
int n_unknown = 0;
int n_no_signature = 0;
+ int n_required = 1; /* XXXX020 This is completely wrong. */
tor_assert(! consensus->is_vote);
@@ -748,9 +753,10 @@
++n_no_signature;
});
- /* XXXX020 actually use the result. */
-
- return 0;
+ if (n_good > n_required)
+ return 0;
+ else
+ return -1;
}
/** DOCDOC */
@@ -1027,8 +1033,14 @@
time_t voting_starts;
time_t voting_ends;
time_t interval_starts;
-} voting_schedule;
+ time_t discard_old_votes;
+
+ int have_voted;
+ int have_built_consensus;
+ int have_published_consensus;
+} voting_schedule = {0,0,0,0,0,0,0};
+
/** DOCDOC */
void
dirvote_recalculate_timing(time_t now)
@@ -1037,6 +1049,8 @@
time_t start;
networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
+ memset(&voting_schedule, 0, sizeof(voting_schedule));
+
if (consensus) {
/* XXXX020 sanity-check these somewhere! */
interval = consensus->fresh_until - consensus->valid_after;
@@ -1052,9 +1066,42 @@
dirvote_get_start_of_next_interval(now,interval);
voting_schedule.voting_ends = start - vote_delay;
voting_schedule.voting_starts = start - vote_delay - dist_delay;
+
+ voting_schedule.discard_old_votes = start + 600; /* XXXX020 */
}
/** DOCDOC */
+void
+dirvote_act(time_t now)
+{
+ if (!voting_schedule.voting_starts)
+ dirvote_recalculate_timing(now);
+ if (voting_schedule.voting_starts < now && !voting_schedule.have_voted) {
+ dirvote_perform_vote();
+ voting_schedule.have_voted = 1;
+ }
+ /* XXXX020 after a couple minutes here, start trying to fetch votes. */
+ if (voting_schedule.voting_ends < now &&
+ !voting_schedule.have_built_consensus) {
+ dirvote_compute_consensus();
+ /* XXXX020 we will want to try again later if we haven't got enough
+ * votes yet. */
+ voting_schedule.have_built_consensus = 1;
+ }
+ if (voting_schedule.interval_starts < now &&
+ !voting_schedule.have_published_consensus) {
+ dirvote_publish_consensus();
+ /* XXXX020 we will want to try again later if we haven't got enough
+ * signatures yet. */
+ voting_schedule.have_published_consensus = 1;
+ }
+ if (voting_schedule.discard_old_votes < now) {
+ dirvote_clear_pending_votes();
+ dirvote_recalculate_timing(now);
+ }
+}
+
+/** DOCDOC */
typedef struct pending_vote_t {
cached_dir_t *vote_body;
networkstatus_vote_t *vote;
@@ -1240,6 +1287,19 @@
networkstatus_vote_free(pending_consensus);
pending_consensus = consensus;
+ if (pending_consensus_signature_list) {
+ /* we may have gotten signatures for this consensus before we built
+ * it ourself. Add them now. */
+ SMARTLIST_FOREACH(pending_consensus_signature_list, char *, sig,
+ {
+ const char *msg = NULL;
+ dirvote_add_signatures_to_pending_consensus(sig, &msg);
+ /* XXXX020 log result. */
+ tor_free(sig);
+ });
+ smartlist_clear(pending_consensus_signature_list);
+ }
+
return 0;
err:
if (votes)
@@ -1325,6 +1385,19 @@
}
}
+/** DOCDOC */
+int
+dirvote_publish_consensus(void)
+{
+ /* Can we actually publish it yet? */
+ if (!pending_consensus ||
+ networkstatus_check_consensus_signature(pending_consensus)<0)
+ return -1;
+
+ networkstatus_set_current_consensus(pending_consensus_body);
+ return 0;
+}
+
/** Release all static storage held in dirvote.c */
void
dirvote_free_all(void)
Modified: tor/trunk/src/or/main.c
===================================================================
--- tor/trunk/src/or/main.c 2007-07-29 23:11:42 UTC (rev 10975)
+++ tor/trunk/src/or/main.c 2007-07-29 23:11:44 UTC (rev 10976)
@@ -1006,6 +1006,10 @@
update_networkstatus_downloads(now);
}
+ /** 2c. Let directory voting happen. */
+ if (authdir_mode_v3(options))
+ dirvote_act(now);
+
/** 3a. Every second, we examine pending circuits and prune the
* ones which have been pending for more than a few seconds.
* We do this before step 4, so it can try building more if
Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h 2007-07-29 23:11:42 UTC (rev 10975)
+++ tor/trunk/src/or/or.h 2007-07-29 23:11:44 UTC (rev 10976)
@@ -2759,11 +2759,14 @@
void directory_set_dirty(void);
cached_dir_t *dirserv_get_directory(void);
cached_dir_t *dirserv_get_runningrouters(void);
+cached_dir_t *dirserv_get_consensus(void);
void dirserv_set_cached_directory(const char *directory, time_t when,
int is_running_routers);
void dirserv_set_cached_networkstatus_v2(const char *directory,
const char *identity,
time_t published);
+void dirserv_set_cached_networkstatus_v3(const char *consensus,
+ time_t published);
void dirserv_clear_old_networkstatuses(time_t cutoff);
void dirserv_clear_old_v1_info(time_t now);
void dirserv_get_networkstatus_v2(smartlist_t *result, const char *key);
@@ -2837,6 +2840,7 @@
void dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out);
time_t dirvote_get_start_of_next_interval(time_t now, int interval);
void dirvote_recalculate_timing(time_t now);
+void dirvote_act(time_t now);
/* invoked on timers and by outside triggers. */
void dirvote_perform_vote(void);
@@ -2845,6 +2849,7 @@
const char **msg_out);
int dirvote_compute_consensus(void);
int dirvote_add_signatures(const char *detached_signatures_body);
+int dirvote_publish_consensus(void);
#ifdef DIRVOTE_PRIVATE
int networkstatus_check_voter_signature(networkstatus_vote_t *consensus,
@@ -3419,6 +3424,7 @@
/* for consensuses. */
networkstatus_vote_t *networkstatus_get_latest_consensus(void);
networkstatus_vote_t *networkstatus_get_live_consensus(time_t now);
+int networkstatus_set_current_consensus(const char *consensus);
//routerstatus_t *routerstatus_get_by_hexdigest(const char *hexdigest);
int should_delay_dir_fetches(or_options_t *options);
Modified: tor/trunk/src/or/routerlist.c
===================================================================
--- tor/trunk/src/or/routerlist.c 2007-07-29 23:11:42 UTC (rev 10975)
+++ tor/trunk/src/or/routerlist.c 2007-07-29 23:11:44 UTC (rev 10976)
@@ -3832,6 +3832,32 @@
return current_consensus;
}
+int
+networkstatus_set_current_consensus(const char *consensus)
+{
+ networkstatus_vote_t *c;
+ /* Make sure it's parseable. */
+ c = networkstatus_parse_vote_from_string(consensus, 0);
+ if (!c)
+ return -1;
+
+ /* Make sure it's signed enough. */
+ if (networkstatus_check_consensus_signature(c)<0) {
+ networkstatus_vote_free(c);
+ return -1;
+ }
+
+ if (current_consensus)
+ networkstatus_vote_free(current_consensus);
+
+ current_consensus = c;
+
+ if (get_options()->DirPort)
+ dirserv_set_cached_networkstatus_v3(consensus, c->valid_after);
+
+ return 0;
+}
+
/** We believe networkstatuses more recent than this when they tell us that
* our server is broken, invalid, obsolete, etc. */
#define SELF_OPINION_INTERVAL (90*60)