mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Generate all the flavors of consensuses when building consensuses.
This commit is contained in:
parent
5576a3a094
commit
d9c71816b1
@ -2618,7 +2618,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
|
|||||||
const char *item;
|
const char *item;
|
||||||
tor_assert(!current); /* we handle current consensus specially above,
|
tor_assert(!current); /* we handle current consensus specially above,
|
||||||
* since it wants to be spooled. */
|
* since it wants to be spooled. */
|
||||||
if ((item = dirvote_get_pending_consensus()))
|
if ((item = dirvote_get_pending_consensus(FLAV_NS)))
|
||||||
smartlist_add(items, (char*)item);
|
smartlist_add(items, (char*)item);
|
||||||
} else if (!current && !strcmp(url, "consensus-signatures")) {
|
} else if (!current && !strcmp(url, "consensus-signatures")) {
|
||||||
/* XXXX the spec says that we should implement
|
/* XXXX the spec says that we should implement
|
||||||
|
350
src/or/dirvote.c
350
src/or/dirvote.c
@ -11,15 +11,21 @@
|
|||||||
* \brief Functions to compute directory consensus, and schedule voting.
|
* \brief Functions to compute directory consensus, and schedule voting.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
static int dirvote_add_signatures_to_pending_consensus(
|
typedef struct pending_consensus_t pending_consensus_t;
|
||||||
|
|
||||||
|
static int dirvote_add_signatures_to_all_pending_consensuses(
|
||||||
const char *detached_signatures_body,
|
const char *detached_signatures_body,
|
||||||
const char **msg_out);
|
const char **msg_out);
|
||||||
|
static int dirvote_add_signatures_to_pending_consensus(
|
||||||
|
pending_consensus_t *pc,
|
||||||
|
ns_detached_signatures_t *sigs,
|
||||||
|
const char **msg_out);
|
||||||
static char *list_v3_auth_ids(void);
|
static char *list_v3_auth_ids(void);
|
||||||
static void dirvote_fetch_missing_votes(void);
|
static void dirvote_fetch_missing_votes(void);
|
||||||
static void dirvote_fetch_missing_signatures(void);
|
static void dirvote_fetch_missing_signatures(void);
|
||||||
static int dirvote_perform_vote(void);
|
static int dirvote_perform_vote(void);
|
||||||
static void dirvote_clear_votes(int all_votes);
|
static void dirvote_clear_votes(int all_votes);
|
||||||
static int dirvote_compute_consensus(void);
|
static int dirvote_compute_consensuses(void);
|
||||||
static int dirvote_publish_consensus(void);
|
static int dirvote_publish_consensus(void);
|
||||||
static char *make_consensus_method_list(int low, int high, const char *sep);
|
static char *make_consensus_method_list(int low, int high, const char *sep);
|
||||||
|
|
||||||
@ -1480,40 +1486,17 @@ networkstatus_add_detached_signatures(networkstatus_t *target,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return a newly allocated string holding the detached-signatures document
|
/** DOCDOC */
|
||||||
* corresponding to the signatures on <b>consensus</b>. */
|
static char *
|
||||||
char *
|
networkstatus_format_signatures(networkstatus_t *consensus)
|
||||||
networkstatus_get_detached_signatures(networkstatus_t *consensus)
|
|
||||||
{
|
{
|
||||||
smartlist_t *elements;
|
smartlist_t *elements;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
int n_sigs = 0;
|
int n_sigs = 0;
|
||||||
tor_assert(consensus);
|
|
||||||
tor_assert(consensus->type == NS_TYPE_CONSENSUS);
|
|
||||||
|
|
||||||
tor_assert(consensus->flavor == FLAV_NS);
|
|
||||||
|
|
||||||
elements = smartlist_create();
|
elements = smartlist_create();
|
||||||
|
|
||||||
{
|
|
||||||
char va_buf[ISO_TIME_LEN+1], fu_buf[ISO_TIME_LEN+1],
|
|
||||||
vu_buf[ISO_TIME_LEN+1];
|
|
||||||
char d[HEX_DIGEST_LEN+1];
|
|
||||||
|
|
||||||
base16_encode(d, sizeof(d), consensus->digests.d[DIGEST_SHA1], DIGEST_LEN);
|
|
||||||
format_iso_time(va_buf, consensus->valid_after);
|
|
||||||
format_iso_time(fu_buf, consensus->fresh_until);
|
|
||||||
format_iso_time(vu_buf, consensus->valid_until);
|
|
||||||
|
|
||||||
tor_snprintf(buf, sizeof(buf),
|
|
||||||
"consensus-digest %s\n"
|
|
||||||
"valid-after %s\n"
|
|
||||||
"fresh-until %s\n"
|
|
||||||
"valid-until %s\n", d, va_buf, fu_buf, vu_buf);
|
|
||||||
smartlist_add(elements, tor_strdup(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
SMARTLIST_FOREACH_BEGIN(consensus->voters, networkstatus_voter_info_t *, v) {
|
SMARTLIST_FOREACH_BEGIN(consensus->voters, networkstatus_voter_info_t *, v) {
|
||||||
SMARTLIST_FOREACH_BEGIN(v->sigs, document_signature_t *, sig) {
|
SMARTLIST_FOREACH_BEGIN(v->sigs, document_signature_t *, sig) {
|
||||||
char sk[HEX_DIGEST_LEN+1];
|
char sk[HEX_DIGEST_LEN+1];
|
||||||
@ -1541,6 +1524,53 @@ networkstatus_get_detached_signatures(networkstatus_t *consensus)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Return a newly allocated string holding the detached-signatures document
|
||||||
|
* corresponding to the signatures on <b>consensus</b>. */
|
||||||
|
char *
|
||||||
|
networkstatus_get_detached_signatures(networkstatus_t *consensus)
|
||||||
|
{
|
||||||
|
smartlist_t *elements;
|
||||||
|
char buf[4096];
|
||||||
|
char *result = NULL;
|
||||||
|
tor_assert(consensus);
|
||||||
|
tor_assert(consensus->type == NS_TYPE_CONSENSUS);
|
||||||
|
|
||||||
|
tor_assert(consensus->flavor == FLAV_NS);
|
||||||
|
|
||||||
|
elements = smartlist_create();
|
||||||
|
|
||||||
|
{
|
||||||
|
char va_buf[ISO_TIME_LEN+1], fu_buf[ISO_TIME_LEN+1],
|
||||||
|
vu_buf[ISO_TIME_LEN+1];
|
||||||
|
char d[HEX_DIGEST_LEN+1];
|
||||||
|
|
||||||
|
base16_encode(d, sizeof(d), consensus->digests.d[DIGEST_SHA1], DIGEST_LEN);
|
||||||
|
format_iso_time(va_buf, consensus->valid_after);
|
||||||
|
format_iso_time(fu_buf, consensus->fresh_until);
|
||||||
|
format_iso_time(vu_buf, consensus->valid_until);
|
||||||
|
|
||||||
|
tor_snprintf(buf, sizeof(buf),
|
||||||
|
"consensus-digest %s\n"
|
||||||
|
"valid-after %s\n"
|
||||||
|
"fresh-until %s\n"
|
||||||
|
"valid-until %s\n", d, va_buf, fu_buf, vu_buf);
|
||||||
|
smartlist_add(elements, tor_strdup(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char *sigs = networkstatus_format_signatures(consensus);
|
||||||
|
if (!sigs)
|
||||||
|
goto err;
|
||||||
|
smartlist_add(elements, sigs);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = smartlist_join_strings(elements, "", 0, NULL);
|
||||||
|
err:
|
||||||
|
SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
|
||||||
|
smartlist_free(elements);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/** Release all storage held in <b>s</b>. */
|
/** Release all storage held in <b>s</b>. */
|
||||||
void
|
void
|
||||||
ns_detached_signatures_free(ns_detached_signatures_t *s)
|
ns_detached_signatures_free(ns_detached_signatures_t *s)
|
||||||
@ -1744,7 +1774,7 @@ dirvote_act(or_options_t *options, time_t now)
|
|||||||
if (voting_schedule.voting_ends < now &&
|
if (voting_schedule.voting_ends < now &&
|
||||||
!voting_schedule.have_built_consensus) {
|
!voting_schedule.have_built_consensus) {
|
||||||
log_notice(LD_DIR, "Time to compute a consensus.");
|
log_notice(LD_DIR, "Time to compute a consensus.");
|
||||||
dirvote_compute_consensus();
|
dirvote_compute_consensuses();
|
||||||
/* XXXX We will want to try again later if we haven't got enough
|
/* XXXX We will want to try again later if we haven't got enough
|
||||||
* votes yet. Implement this if it turns out to ever happen. */
|
* votes yet. Implement this if it turns out to ever happen. */
|
||||||
voting_schedule.have_built_consensus = 1;
|
voting_schedule.have_built_consensus = 1;
|
||||||
@ -1781,14 +1811,22 @@ static smartlist_t *pending_vote_list = NULL;
|
|||||||
/** List of pending_vote_t for the previous vote. After we've used them to
|
/** 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. */
|
* build a consensus, the votes go here for the next period. */
|
||||||
static smartlist_t *previous_vote_list = NULL;
|
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 */
|
/** DOCDOC*/
|
||||||
static char *pending_consensus_body = NULL;
|
struct pending_consensus_t {
|
||||||
|
/** The body of the consensus that we're currently building. Once we
|
||||||
|
* have it built, it goes into dirserv.c */
|
||||||
|
char *body;
|
||||||
|
/** The parsed in-progress consensus document. */
|
||||||
|
networkstatus_t *consensus;
|
||||||
|
};
|
||||||
|
|
||||||
|
static pending_consensus_t pending_consensuses[N_CONSENSUS_FLAVORS];
|
||||||
|
|
||||||
/** The detached signatures for the consensus that we're currently
|
/** The detached signatures for the consensus that we're currently
|
||||||
* building. */
|
* building. */
|
||||||
static char *pending_consensus_signatures = NULL;
|
static char *pending_consensus_signatures = NULL;
|
||||||
/** The parsed in-progress consensus document. */
|
|
||||||
static networkstatus_t *pending_consensus = NULL;
|
|
||||||
/** List of ns_detached_signatures_t: hold signatures that get posted to us
|
/** List of ns_detached_signatures_t: hold signatures that get posted to us
|
||||||
* before we have generated the consensus on our own. */
|
* before we have generated the consensus on our own. */
|
||||||
static smartlist_t *pending_consensus_signature_list = NULL;
|
static smartlist_t *pending_consensus_signature_list = NULL;
|
||||||
@ -1882,15 +1920,39 @@ dirvote_fetch_missing_votes(void)
|
|||||||
static void
|
static void
|
||||||
dirvote_fetch_missing_signatures(void)
|
dirvote_fetch_missing_signatures(void)
|
||||||
{
|
{
|
||||||
if (!pending_consensus)
|
int need_any = 0;
|
||||||
|
int i;
|
||||||
|
for (i=0; i < N_CONSENSUS_FLAVORS; ++i) {
|
||||||
|
networkstatus_t *consensus = pending_consensuses[i].consensus;
|
||||||
|
if (!consensus ||
|
||||||
|
networkstatus_check_consensus_signature(consensus, -1) == 1) {
|
||||||
|
/* We have no consensus, or we have one that's signed by everybody. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
need_any = 1;
|
||||||
|
}
|
||||||
|
if (!need_any)
|
||||||
return;
|
return;
|
||||||
if (networkstatus_check_consensus_signature(pending_consensus, -1) == 1)
|
|
||||||
return; /* we have a signature from everybody. */
|
|
||||||
|
|
||||||
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES,
|
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES,
|
||||||
0, NULL);
|
0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** DOCDOC */
|
||||||
|
static void
|
||||||
|
dirvote_clear_pending_consensuses(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < N_CONSENSUS_FLAVORS; ++i) {
|
||||||
|
pending_consensus_t *pc = &pending_consensuses[i];
|
||||||
|
tor_free(pc->body);
|
||||||
|
if (pc->consensus) {
|
||||||
|
networkstatus_vote_free(pc->consensus);
|
||||||
|
pc->consensus = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Drop all currently pending votes, consensus, and detached signatures. */
|
/** Drop all currently pending votes, consensus, and detached signatures. */
|
||||||
static void
|
static void
|
||||||
dirvote_clear_votes(int all_votes)
|
dirvote_clear_votes(int all_votes)
|
||||||
@ -1928,12 +1990,8 @@ dirvote_clear_votes(int all_votes)
|
|||||||
tor_free(cp));
|
tor_free(cp));
|
||||||
smartlist_clear(pending_consensus_signature_list);
|
smartlist_clear(pending_consensus_signature_list);
|
||||||
}
|
}
|
||||||
tor_free(pending_consensus_body);
|
|
||||||
tor_free(pending_consensus_signatures);
|
tor_free(pending_consensus_signatures);
|
||||||
if (pending_consensus) {
|
dirvote_clear_pending_consensuses();
|
||||||
networkstatus_vote_free(pending_consensus);
|
|
||||||
pending_consensus = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return a newly allocated string containing the hex-encoded v3 authority
|
/** Return a newly allocated string containing the hex-encoded v3 authority
|
||||||
@ -2121,7 +2179,7 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out)
|
|||||||
* pending_consensus: it won't be ready to be published until we have
|
* pending_consensus: it won't be ready to be published until we have
|
||||||
* everybody else's signatures collected too. (V3 Authority only) */
|
* everybody else's signatures collected too. (V3 Authority only) */
|
||||||
static int
|
static int
|
||||||
dirvote_compute_consensus(void)
|
dirvote_compute_consensuses(void)
|
||||||
{
|
{
|
||||||
/* Have we got enough votes to try? */
|
/* Have we got enough votes to try? */
|
||||||
int n_votes, n_voters;
|
int n_votes, n_voters;
|
||||||
@ -2129,6 +2187,10 @@ dirvote_compute_consensus(void)
|
|||||||
char *consensus_body = NULL, *signatures = NULL, *votefile;
|
char *consensus_body = NULL, *signatures = NULL, *votefile;
|
||||||
networkstatus_t *consensus = NULL;
|
networkstatus_t *consensus = NULL;
|
||||||
authority_cert_t *my_cert;
|
authority_cert_t *my_cert;
|
||||||
|
pending_consensus_t pending[N_CONSENSUS_FLAVORS];
|
||||||
|
int flav;
|
||||||
|
|
||||||
|
memset(pending, 0, sizeof(pending));
|
||||||
|
|
||||||
if (!pending_vote_list)
|
if (!pending_vote_list)
|
||||||
pending_vote_list = smartlist_create();
|
pending_vote_list = smartlist_create();
|
||||||
@ -2168,6 +2230,7 @@ dirvote_compute_consensus(void)
|
|||||||
char legacy_dbuf[DIGEST_LEN];
|
char legacy_dbuf[DIGEST_LEN];
|
||||||
crypto_pk_env_t *legacy_sign=NULL;
|
crypto_pk_env_t *legacy_sign=NULL;
|
||||||
char *legacy_id_digest = NULL;
|
char *legacy_id_digest = NULL;
|
||||||
|
int n_generated = 0;
|
||||||
if (get_options()->V3AuthUseLegacyKey) {
|
if (get_options()->V3AuthUseLegacyKey) {
|
||||||
authority_cert_t *cert = get_my_v3_legacy_cert();
|
authority_cert_t *cert = get_my_v3_legacy_cert();
|
||||||
legacy_sign = get_my_v3_legacy_signing_key();
|
legacy_sign = get_my_v3_legacy_signing_key();
|
||||||
@ -2176,40 +2239,59 @@ dirvote_compute_consensus(void)
|
|||||||
legacy_id_digest = legacy_dbuf;
|
legacy_id_digest = legacy_dbuf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
consensus_body = networkstatus_compute_consensus(
|
|
||||||
|
for (flav = 0; flav < N_CONSENSUS_FLAVORS; ++flav) {
|
||||||
|
const char *flavor_name = networkstatus_get_flavor_name(flav);
|
||||||
|
consensus_body = networkstatus_compute_consensus(
|
||||||
votes, n_voters,
|
votes, n_voters,
|
||||||
my_cert->identity_key,
|
my_cert->identity_key,
|
||||||
get_my_v3_authority_signing_key(), legacy_id_digest, legacy_sign,
|
get_my_v3_authority_signing_key(), legacy_id_digest, legacy_sign,
|
||||||
FLAV_NS);
|
flav);
|
||||||
}
|
|
||||||
if (!consensus_body) {
|
if (!consensus_body) {
|
||||||
log_warn(LD_DIR, "Couldn't generate a consensus at all!");
|
log_warn(LD_DIR, "Couldn't generate a %s consensus at all!",
|
||||||
goto err;
|
flavor_name);
|
||||||
}
|
continue;
|
||||||
consensus = networkstatus_parse_vote_from_string(consensus_body, NULL,
|
}
|
||||||
NS_TYPE_CONSENSUS);
|
consensus = networkstatus_parse_vote_from_string(consensus_body, NULL,
|
||||||
if (!consensus) {
|
NS_TYPE_CONSENSUS);
|
||||||
log_warn(LD_DIR, "Couldn't parse consensus we generated!");
|
if (!consensus) {
|
||||||
goto err;
|
log_warn(LD_DIR, "Couldn't parse %s consensus we generated!",
|
||||||
}
|
flavor_name);
|
||||||
/* 'Check' our own signature, to mark it valid. */
|
tor_free(consensus_body);
|
||||||
networkstatus_check_consensus_signature(consensus, -1);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 'Check' our own signature, to mark it valid. */
|
||||||
|
networkstatus_check_consensus_signature(consensus, -1);
|
||||||
|
|
||||||
|
pending[flav].body = consensus_body;
|
||||||
|
pending[flav].consensus = consensus;
|
||||||
|
n_generated++;
|
||||||
|
consensus_body = NULL;
|
||||||
|
consensus = NULL;
|
||||||
|
}
|
||||||
|
if (!n_generated) {
|
||||||
|
log_warn(LD_DIR, "Couldn't generate any consensus flavors at all.");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXXX NMNM NM NM wrong. */
|
||||||
|
signatures =
|
||||||
|
networkstatus_get_detached_signatures(pending[FLAV_NS].consensus);
|
||||||
|
|
||||||
signatures = networkstatus_get_detached_signatures(consensus);
|
|
||||||
if (!signatures) {
|
if (!signatures) {
|
||||||
log_warn(LD_DIR, "Couldn't extract signatures.");
|
log_warn(LD_DIR, "Couldn't extract signatures.");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
tor_free(pending_consensus_body);
|
dirvote_clear_pending_consensuses();
|
||||||
pending_consensus_body = consensus_body;
|
memcpy(pending_consensuses, pending, sizeof(pending));
|
||||||
|
|
||||||
tor_free(pending_consensus_signatures);
|
tor_free(pending_consensus_signatures);
|
||||||
pending_consensus_signatures = signatures;
|
pending_consensus_signatures = signatures;
|
||||||
|
|
||||||
if (pending_consensus)
|
|
||||||
networkstatus_vote_free(pending_consensus);
|
|
||||||
pending_consensus = consensus;
|
|
||||||
|
|
||||||
if (pending_consensus_signature_list) {
|
if (pending_consensus_signature_list) {
|
||||||
int n_sigs = 0;
|
int n_sigs = 0;
|
||||||
/* we may have gotten signatures for this consensus before we built
|
/* we may have gotten signatures for this consensus before we built
|
||||||
@ -2217,7 +2299,7 @@ dirvote_compute_consensus(void)
|
|||||||
SMARTLIST_FOREACH(pending_consensus_signature_list, char *, sig,
|
SMARTLIST_FOREACH(pending_consensus_signature_list, char *, sig,
|
||||||
{
|
{
|
||||||
const char *msg = NULL;
|
const char *msg = NULL;
|
||||||
int r = dirvote_add_signatures_to_pending_consensus(sig, &msg);
|
int r = dirvote_add_signatures_to_all_pending_consensuses(sig, &msg);
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
n_sigs += r;
|
n_sigs += r;
|
||||||
else
|
else
|
||||||
@ -2253,79 +2335,61 @@ dirvote_compute_consensus(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Helper: we just got the <b>detached_signatures_body</b> sent to us as
|
/** Helper: we just got the <b>detached_signatures_body</b> sent to us as
|
||||||
* signatures on the currently pending consensus. Add them to the consensus
|
* signatures on the currently pending consensus. Add them to <b>pc</b>
|
||||||
* as appropriate. Return the number of signatures added. (?) */
|
* as appropriate. Return the number of signatures added. (?) */
|
||||||
static int
|
static int
|
||||||
dirvote_add_signatures_to_pending_consensus(
|
dirvote_add_signatures_to_pending_consensus(
|
||||||
const char *detached_signatures_body,
|
pending_consensus_t *pc,
|
||||||
|
ns_detached_signatures_t *sigs,
|
||||||
const char **msg_out)
|
const char **msg_out)
|
||||||
{
|
{
|
||||||
ns_detached_signatures_t *sigs = NULL;
|
const char *flavor_name;
|
||||||
int r = -1;
|
int r = -1;
|
||||||
|
|
||||||
tor_assert(detached_signatures_body);
|
|
||||||
tor_assert(msg_out);
|
|
||||||
|
|
||||||
/* Only call if we have a pending consensus right now. */
|
/* Only call if we have a pending consensus right now. */
|
||||||
tor_assert(pending_consensus);
|
tor_assert(pc->consensus);
|
||||||
tor_assert(pending_consensus_body);
|
tor_assert(pc->body);
|
||||||
tor_assert(pending_consensus_signatures);
|
tor_assert(pending_consensus_signatures);
|
||||||
|
|
||||||
|
flavor_name = networkstatus_get_flavor_name(pc->consensus->flavor);
|
||||||
*msg_out = NULL;
|
*msg_out = NULL;
|
||||||
|
|
||||||
if (!(sigs = networkstatus_parse_detached_signatures(
|
|
||||||
detached_signatures_body, NULL))) {
|
|
||||||
*msg_out = "Couldn't parse detached signatures.";
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
smartlist_t *sig_list = strmap_get(sigs->signatures,
|
smartlist_t *sig_list = strmap_get(sigs->signatures, flavor_name);
|
||||||
networkstatus_get_flavor_name(pending_consensus->flavor));
|
log_info(LD_DIR, "Have %d signatures for adding to %s consensus.",
|
||||||
log_info(LD_DIR, "Have %d signatures for adding to consensus.",
|
sig_list ? smartlist_len(sig_list) : 0, flavor_name);
|
||||||
sig_list ? smartlist_len(sig_list) : 0);
|
|
||||||
}
|
}
|
||||||
r = networkstatus_add_detached_signatures(pending_consensus,
|
r = networkstatus_add_detached_signatures(pc->consensus, sigs, msg_out);
|
||||||
sigs, msg_out);
|
|
||||||
log_info(LD_DIR,"Added %d signatures to consensus.", r);
|
log_info(LD_DIR,"Added %d signatures to consensus.", r);
|
||||||
|
|
||||||
if (r >= 1) {
|
if (r >= 1) {
|
||||||
char *new_detached =
|
char *new_signatures =
|
||||||
networkstatus_get_detached_signatures(pending_consensus);
|
networkstatus_format_signatures(pc->consensus);
|
||||||
const char *src;
|
|
||||||
char *dst, *dst_end;
|
char *dst, *dst_end;
|
||||||
size_t new_consensus_len;
|
size_t new_consensus_len;
|
||||||
if (!new_detached) {
|
if (!new_signatures) {
|
||||||
*msg_out = "No signatures to add";
|
*msg_out = "No signatures to add";
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
new_consensus_len =
|
new_consensus_len =
|
||||||
strlen(pending_consensus_body) + strlen(new_detached) + 1;
|
strlen(pc->body) + strlen(new_signatures) + 1;
|
||||||
pending_consensus_body = tor_realloc(pending_consensus_body,
|
pc->body = tor_realloc(pc->body, new_consensus_len);
|
||||||
new_consensus_len);
|
dst_end = pc->body + new_consensus_len;
|
||||||
dst_end = pending_consensus_body + new_consensus_len;
|
dst = strstr(pc->body, "directory-signature ");
|
||||||
dst = strstr(pending_consensus_body, "directory-signature ");
|
|
||||||
tor_assert(dst);
|
tor_assert(dst);
|
||||||
src = strstr(new_detached, "directory-signature ");
|
strlcpy(dst, new_signatures, dst_end-dst);
|
||||||
tor_assert(src);
|
|
||||||
strlcpy(dst, src, dst_end-dst);
|
|
||||||
|
|
||||||
/* We remove this block once it has failed to crash for a while. But
|
/* We remove this block once it has failed to crash for a while. But
|
||||||
* unless it shows up in profiles, we're probably better leaving it in,
|
* unless it shows up in profiles, we're probably better leaving it in,
|
||||||
* just in case we break detached signature processing at some point. */
|
* just in case we break detached signature processing at some point. */
|
||||||
{
|
{
|
||||||
ns_detached_signatures_t *sigs =
|
|
||||||
networkstatus_parse_detached_signatures(new_detached, NULL);
|
|
||||||
networkstatus_t *v = networkstatus_parse_vote_from_string(
|
networkstatus_t *v = networkstatus_parse_vote_from_string(
|
||||||
pending_consensus_body, NULL,
|
pc->body, NULL,
|
||||||
NS_TYPE_CONSENSUS);
|
NS_TYPE_CONSENSUS);
|
||||||
tor_assert(sigs);
|
|
||||||
ns_detached_signatures_free(sigs);
|
|
||||||
tor_assert(v);
|
tor_assert(v);
|
||||||
networkstatus_vote_free(v);
|
networkstatus_vote_free(v);
|
||||||
}
|
}
|
||||||
tor_free(pending_consensus_signatures);
|
tor_free(pending_consensus_signatures);
|
||||||
pending_consensus_signatures = new_detached;
|
|
||||||
*msg_out = "Signatures added";
|
*msg_out = "Signatures added";
|
||||||
} else if (r == 0) {
|
} else if (r == 0) {
|
||||||
*msg_out = "Signatures ignored";
|
*msg_out = "Signatures ignored";
|
||||||
@ -2333,6 +2397,58 @@ dirvote_add_signatures_to_pending_consensus(
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
err:
|
||||||
|
if (!*msg_out)
|
||||||
|
*msg_out = "Unrecognized error while adding detached signatures.";
|
||||||
|
done:
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
dirvote_add_signatures_to_all_pending_consensuses(
|
||||||
|
const char *detached_signatures_body,
|
||||||
|
const char **msg_out)
|
||||||
|
{
|
||||||
|
int r=0, i, n_added = 0, errors = 0;
|
||||||
|
ns_detached_signatures_t *sigs;
|
||||||
|
tor_assert(detached_signatures_body);
|
||||||
|
tor_assert(msg_out);
|
||||||
|
|
||||||
|
if (!(sigs = networkstatus_parse_detached_signatures(
|
||||||
|
detached_signatures_body, NULL))) {
|
||||||
|
*msg_out = "Couldn't parse detached signatures.";
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < N_CONSENSUS_FLAVORS; ++i) {
|
||||||
|
int res;
|
||||||
|
pending_consensus_t *pc = &pending_consensuses[i];
|
||||||
|
if (!pc->consensus)
|
||||||
|
continue;
|
||||||
|
res = dirvote_add_signatures_to_pending_consensus(pc, sigs, msg_out);
|
||||||
|
if (res < 0)
|
||||||
|
errors++;
|
||||||
|
else
|
||||||
|
n_added += res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors) {
|
||||||
|
r = -1;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Still not right XXXX NM NM*/
|
||||||
|
if (pending_consensuses[FLAV_NS].consensus) {
|
||||||
|
char *new_detached = networkstatus_get_detached_signatures(
|
||||||
|
pending_consensuses[FLAV_NS].consensus);
|
||||||
|
if (new_detached) {
|
||||||
|
tor_free(pending_consensus_signatures);
|
||||||
|
pending_consensus_signatures = new_detached;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r = n_added;
|
||||||
goto done;
|
goto done;
|
||||||
err:
|
err:
|
||||||
if (!*msg_out)
|
if (!*msg_out)
|
||||||
@ -2340,6 +2456,8 @@ dirvote_add_signatures_to_pending_consensus(
|
|||||||
done:
|
done:
|
||||||
if (sigs)
|
if (sigs)
|
||||||
ns_detached_signatures_free(sigs);
|
ns_detached_signatures_free(sigs);
|
||||||
|
/* XXXX NM Check how return is used. We can now have an error *and*
|
||||||
|
signatures added. */
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2352,10 +2470,10 @@ dirvote_add_signatures(const char *detached_signatures_body,
|
|||||||
const char *source,
|
const char *source,
|
||||||
const char **msg)
|
const char **msg)
|
||||||
{
|
{
|
||||||
if (pending_consensus) {
|
if (pending_consensuses[FLAV_NS].consensus) {
|
||||||
log_notice(LD_DIR, "Got a signature from %s. "
|
log_notice(LD_DIR, "Got a signature from %s. "
|
||||||
"Adding it to the pending consensus.", source);
|
"Adding it to the pending consensus.", source);
|
||||||
return dirvote_add_signatures_to_pending_consensus(
|
return dirvote_add_signatures_to_all_pending_consensuses(
|
||||||
detached_signatures_body, msg);
|
detached_signatures_body, msg);
|
||||||
} else {
|
} else {
|
||||||
log_notice(LD_DIR, "Got a signature from %s. "
|
log_notice(LD_DIR, "Got a signature from %s. "
|
||||||
@ -2375,13 +2493,16 @@ static int
|
|||||||
dirvote_publish_consensus(void)
|
dirvote_publish_consensus(void)
|
||||||
{
|
{
|
||||||
/* Can we actually publish it yet? */
|
/* Can we actually publish it yet? */
|
||||||
if (!pending_consensus ||
|
if (!pending_consensuses[FLAV_NS].consensus ||
|
||||||
networkstatus_check_consensus_signature(pending_consensus, 1)<0) {
|
networkstatus_check_consensus_signature(
|
||||||
|
pending_consensuses[FLAV_NS].consensus, 1)<0) {
|
||||||
log_warn(LD_DIR, "Not enough info to publish pending consensus");
|
log_warn(LD_DIR, "Not enough info to publish pending consensus");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (networkstatus_set_current_consensus(pending_consensus_body, 0))
|
/* XXXXXX NMNMNM */
|
||||||
|
if (networkstatus_set_current_consensus(
|
||||||
|
pending_consensuses[FLAV_NS].body, 0))
|
||||||
log_warn(LD_DIR, "Error publishing consensus");
|
log_warn(LD_DIR, "Error publishing consensus");
|
||||||
else
|
else
|
||||||
log_notice(LD_DIR, "Consensus published.");
|
log_notice(LD_DIR, "Consensus published.");
|
||||||
@ -2400,12 +2521,8 @@ dirvote_free_all(void)
|
|||||||
smartlist_free(previous_vote_list);
|
smartlist_free(previous_vote_list);
|
||||||
previous_vote_list = NULL;
|
previous_vote_list = NULL;
|
||||||
|
|
||||||
tor_free(pending_consensus_body);
|
dirvote_clear_pending_consensuses();
|
||||||
tor_free(pending_consensus_signatures);
|
tor_free(pending_consensus_signatures);
|
||||||
if (pending_consensus) {
|
|
||||||
networkstatus_vote_free(pending_consensus);
|
|
||||||
pending_consensus = NULL;
|
|
||||||
}
|
|
||||||
if (pending_consensus_signature_list) {
|
if (pending_consensus_signature_list) {
|
||||||
/* now empty as a result of clear_pending_votes. */
|
/* now empty as a result of clear_pending_votes. */
|
||||||
smartlist_free(pending_consensus_signature_list);
|
smartlist_free(pending_consensus_signature_list);
|
||||||
@ -2419,9 +2536,10 @@ dirvote_free_all(void)
|
|||||||
|
|
||||||
/** Return the body of the consensus that we're currently trying to build. */
|
/** Return the body of the consensus that we're currently trying to build. */
|
||||||
const char *
|
const char *
|
||||||
dirvote_get_pending_consensus(void)
|
dirvote_get_pending_consensus(consensus_flavor_t flav)
|
||||||
{
|
{
|
||||||
return pending_consensus_body;
|
tor_assert(((int)flav) >= 0 && flav < N_CONSENSUS_FLAVORS);
|
||||||
|
return pending_consensuses[flav].body;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the signatures that we know for the consensus that we're currently
|
/** Return the signatures that we know for the consensus that we're currently
|
||||||
|
@ -1688,10 +1688,13 @@ typedef enum {
|
|||||||
|
|
||||||
/** DOCDOC */
|
/** DOCDOC */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FLAV_NS,
|
FLAV_NS = 0,
|
||||||
FLAV_MICRODESC,
|
FLAV_MICRODESC = 1,
|
||||||
} consensus_flavor_t;
|
} consensus_flavor_t;
|
||||||
|
|
||||||
|
/** DOCDOC */
|
||||||
|
#define N_CONSENSUS_FLAVORS ((int)(FLAV_MICRODESC)+1)
|
||||||
|
|
||||||
/** A common structure to hold a v3 network status vote, or a v3 network
|
/** A common structure to hold a v3 network status vote, or a v3 network
|
||||||
* status consensus. */
|
* status consensus. */
|
||||||
typedef struct networkstatus_t {
|
typedef struct networkstatus_t {
|
||||||
@ -3863,7 +3866,7 @@ int dirvote_add_signatures(const char *detached_signatures_body,
|
|||||||
const char **msg_out);
|
const char **msg_out);
|
||||||
|
|
||||||
/* Item access */
|
/* Item access */
|
||||||
const char *dirvote_get_pending_consensus(void);
|
const char *dirvote_get_pending_consensus(consensus_flavor_t flav);
|
||||||
const char *dirvote_get_pending_detached_signatures(void);
|
const char *dirvote_get_pending_detached_signatures(void);
|
||||||
#define DGV_BY_ID 1
|
#define DGV_BY_ID 1
|
||||||
#define DGV_INCLUDE_PENDING 2
|
#define DGV_INCLUDE_PENDING 2
|
||||||
|
Loading…
Reference in New Issue
Block a user