|
@@ -17,20 +17,24 @@
|
|
static void dircollator_collate_by_rsa(dircollator_t *dc);
|
|
static void dircollator_collate_by_rsa(dircollator_t *dc);
|
|
static void dircollator_collate_by_ed25519(dircollator_t *dc);
|
|
static void dircollator_collate_by_ed25519(dircollator_t *dc);
|
|
|
|
|
|
|
|
+
|
|
|
|
+ * RSA SHA1 digest) to an array of vote_routerstatus_t. */
|
|
typedef struct ddmap_entry_s {
|
|
typedef struct ddmap_entry_s {
|
|
HT_ENTRY(ddmap_entry_s) node;
|
|
HT_ENTRY(ddmap_entry_s) node;
|
|
uint8_t d[DIGEST_LEN + DIGEST256_LEN];
|
|
uint8_t d[DIGEST_LEN + DIGEST256_LEN];
|
|
|
|
+
|
|
|
|
+ * any) received for this digest pair from the n'th voter. */
|
|
vote_routerstatus_t *vrs_lst[FLEXIBLE_ARRAY_MEMBER];
|
|
vote_routerstatus_t *vrs_lst[FLEXIBLE_ARRAY_MEMBER];
|
|
} ddmap_entry_t;
|
|
} ddmap_entry_t;
|
|
|
|
|
|
-double_digest_map_t *by_both_ids;
|
|
+
|
|
-
|
|
|
|
static void
|
|
static void
|
|
ddmap_entry_free(ddmap_entry_t *e)
|
|
ddmap_entry_free(ddmap_entry_t *e)
|
|
{
|
|
{
|
|
tor_free(e);
|
|
tor_free(e);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
static ddmap_entry_t *
|
|
static ddmap_entry_t *
|
|
ddmap_entry_new(int n_votes)
|
|
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));
|
|
return fast_memeq(a->d, b->d, sizeof(a->d));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ * ed25519 identity as <b>ed25519</b>. */
|
|
static void
|
|
static void
|
|
ddmap_entry_set_digests(ddmap_entry_t *ent,
|
|
ddmap_entry_set_digests(ddmap_entry_t *ent,
|
|
const uint8_t *rsa_sha1,
|
|
const uint8_t *rsa_sha1,
|
|
@@ -63,6 +69,10 @@ HT_PROTOTYPE(double_digest_map, ddmap_entry_s, node, ddmap_entry_hash,
|
|
ddmap_entry_eq);
|
|
ddmap_entry_eq);
|
|
HT_GENERATE2(double_digest_map, ddmap_entry_s, node, ddmap_entry_hash,
|
|
HT_GENERATE2(double_digest_map, ddmap_entry_s, node, ddmap_entry_hash,
|
|
ddmap_entry_eq, 0.6, tor_reallocarray, tor_free_);
|
|
ddmap_entry_eq, 0.6, tor_reallocarray, tor_free_);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ * <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
|
|
static void
|
|
dircollator_add_routerstatus(dircollator_t *dc,
|
|
dircollator_add_routerstatus(dircollator_t *dc,
|
|
int vote_num,
|
|
int vote_num,
|
|
@@ -99,6 +109,8 @@ dircollator_add_routerstatus(dircollator_t *dc,
|
|
vrs_lst[vote_num] = vrs;
|
|
vrs_lst[vote_num] = vrs;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ * <b>n_votes</b> out of a total of <b>n_authorities</b>. */
|
|
dircollator_t *
|
|
dircollator_t *
|
|
dircollator_new(int n_votes, int n_authorities)
|
|
dircollator_new(int n_votes, int n_authorities)
|
|
{
|
|
{
|
|
@@ -115,6 +127,7 @@ dircollator_new(int n_votes, int n_authorities)
|
|
return dc;
|
|
return dc;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
void
|
|
void
|
|
dircollator_free(dircollator_t *dc)
|
|
dircollator_free(dircollator_t *dc)
|
|
{
|
|
{
|
|
@@ -139,6 +152,10 @@ dircollator_free(dircollator_t *dc)
|
|
tor_free(dc);
|
|
tor_free(dc);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ * be called exactly once for each vote to be used in the consensus. It may
|
|
|
|
+ * only be called before dircollator_collate().
|
|
|
|
+ */
|
|
void
|
|
void
|
|
dircollator_add_vote(dircollator_t *dc, networkstatus_t *v)
|
|
dircollator_add_vote(dircollator_t *dc, networkstatus_t *v)
|
|
{
|
|
{
|
|
@@ -153,6 +170,9 @@ dircollator_add_vote(dircollator_t *dc, networkstatus_t *v)
|
|
} SMARTLIST_FOREACH_END(vrs);
|
|
} SMARTLIST_FOREACH_END(vrs);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ * that the consensus process can iterate over them with
|
|
|
|
+ * dircollator_n_routers() and dircollator_get_votes_for_router(). */
|
|
void
|
|
void
|
|
dircollator_collate(dircollator_t *dc, int consensus_method)
|
|
dircollator_collate(dircollator_t *dc, int consensus_method)
|
|
{
|
|
{
|
|
@@ -168,6 +188,15 @@ dircollator_collate(dircollator_t *dc, int consensus_method)
|
|
dc->is_collated = 1;
|
|
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
|
|
static void
|
|
dircollator_collate_by_rsa(dircollator_t *dc)
|
|
dircollator_collate_by_rsa(dircollator_t *dc)
|
|
{
|
|
{
|
|
@@ -189,6 +218,20 @@ dircollator_collate_by_rsa(dircollator_t *dc)
|
|
dc->by_collated_rsa_sha1 = dc->by_rsa_sha1;
|
|
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
|
|
static void
|
|
dircollator_collate_by_ed25519(dircollator_t *dc)
|
|
dircollator_collate_by_ed25519(dircollator_t *dc)
|
|
{
|
|
{
|
|
@@ -197,6 +240,7 @@ dircollator_collate_by_ed25519(dircollator_t *dc)
|
|
|
|
|
|
ddmap_entry_t **iter;
|
|
ddmap_entry_t **iter;
|
|
|
|
|
|
|
|
+
|
|
HT_FOREACH(iter, double_digest_map, &dc->by_both_ids) {
|
|
HT_FOREACH(iter, double_digest_map, &dc->by_both_ids) {
|
|
ddmap_entry_t *ent = *iter;
|
|
ddmap_entry_t *ent = *iter;
|
|
int n = 0, i;
|
|
int n = 0, i;
|
|
@@ -205,9 +249,13 @@ dircollator_collate_by_ed25519(dircollator_t *dc)
|
|
++n;
|
|
++n;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ * don't include it. */
|
|
if (n <= total_authorities / 2)
|
|
if (n <= total_authorities / 2)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
+
|
|
|
|
+ * RSA key (but with possibly different or missing ed value). */
|
|
vote_routerstatus_t **vrs_lst2 = digestmap_get(dc->by_rsa_sha1,
|
|
vote_routerstatus_t **vrs_lst2 = digestmap_get(dc->by_rsa_sha1,
|
|
(char*)ent->d);
|
|
(char*)ent->d);
|
|
tor_assert(vrs_lst2);
|
|
tor_assert(vrs_lst2);
|
|
@@ -220,13 +268,17 @@ dircollator_collate_by_ed25519(dircollator_t *dc)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
digestmap_set(rsa_digests, (char*)ent->d, ent->vrs_lst);
|
|
digestmap_set(rsa_digests, (char*)ent->d, ent->vrs_lst);
|
|
smartlist_add(dc->all_rsa_sha1_lst, ent->d);
|
|
smartlist_add(dc->all_rsa_sha1_lst, ent->d);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ * we didn't put in yet.
|
|
|
|
+ */
|
|
DIGESTMAP_FOREACH(dc->by_rsa_sha1, k, vote_routerstatus_t **, vrs_lst) {
|
|
DIGESTMAP_FOREACH(dc->by_rsa_sha1, k, vote_routerstatus_t **, vrs_lst) {
|
|
if (digestmap_get(rsa_digests, k) != NULL)
|
|
if (digestmap_get(rsa_digests, k) != NULL)
|
|
- continue;
|
|
+ continue;
|
|
|
|
|
|
int n = 0, i;
|
|
int n = 0, i;
|
|
for (i = 0; i < dc->n_votes; ++i) {
|
|
for (i = 0; i < dc->n_votes; ++i) {
|
|
@@ -235,7 +287,7 @@ dircollator_collate_by_ed25519(dircollator_t *dc)
|
|
}
|
|
}
|
|
|
|
|
|
if (n <= total_authorities / 2)
|
|
if (n <= total_authorities / 2)
|
|
- continue;
|
|
+ continue;
|
|
|
|
|
|
digestmap_set(rsa_digests, k, vrs_lst);
|
|
digestmap_set(rsa_digests, k, vrs_lst);
|
|
smartlist_add(dc->all_rsa_sha1_lst, (char *)k);
|
|
smartlist_add(dc->all_rsa_sha1_lst, (char *)k);
|
|
@@ -244,12 +296,22 @@ dircollator_collate_by_ed25519(dircollator_t *dc)
|
|
dc->by_collated_rsa_sha1 = rsa_digests;
|
|
dc->by_collated_rsa_sha1 = rsa_digests;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ * only be called after dircollator_collate. */
|
|
int
|
|
int
|
|
dircollator_n_routers(dircollator_t *dc)
|
|
dircollator_n_routers(dircollator_t *dc)
|
|
{
|
|
{
|
|
return smartlist_len(dc->all_rsa_sha1_lst);
|
|
return smartlist_len(dc->all_rsa_sha1_lst);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ * 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 **
|
|
vote_routerstatus_t **
|
|
dircollator_get_votes_for_router(dircollator_t *dc, int idx)
|
|
dircollator_get_votes_for_router(dircollator_t *dc, int idx)
|
|
{
|
|
{
|