[tor-commits] [metrics-web/release] Add consensuses to totalcw graph.
karsten at torproject.org
karsten at torproject.org
Sat Nov 9 21:45:06 UTC 2019
commit c0ba389d25a19f5d194e07541e53f6005991fb47
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date: Thu Nov 29 11:38:16 2018 +0100
Add consensuses to totalcw graph.
Implements #28352.
---
src/main/R/rserver/graphs.R | 5 +-
.../torproject/metrics/stats/totalcw/Database.java | 62 +++--
.../org/torproject/metrics/stats/totalcw/Main.java | 11 +-
.../metrics/stats/totalcw/OutputLine.java | 8 +-
.../torproject/metrics/stats/totalcw/Parser.java | 47 +++-
...tusVote.java => TotalcwRelayNetworkStatus.java} | 8 +-
src/main/sql/totalcw/init-totalcw.sql | 23 +-
...est.java => TotalcwRelayNetworkStatusTest.java} | 26 ++-
.../totalcw/2018-10-15-00-00-00-consensus.part | 251 +++++++++++++++++++++
9 files changed, 388 insertions(+), 53 deletions(-)
diff --git a/src/main/R/rserver/graphs.R b/src/main/R/rserver/graphs.R
index e3ac598..7501a95 100644
--- a/src/main/R/rserver/graphs.R
+++ b/src/main/R/rserver/graphs.R
@@ -1558,7 +1558,7 @@ write_advbw_ipv6 <- function(start_p = NULL, end_p = NULL, path_p) {
prepare_totalcw <- function(start_p, end_p) {
read.csv(paste(stats_dir, "totalcw.csv", sep = ""),
- colClasses = c("valid_after_date" = "Date")) %>%
+ colClasses = c("valid_after_date" = "Date", "nickname" = "character")) %>%
filter(if (!is.null(start_p))
valid_after_date >= as.Date(start_p) else TRUE) %>%
filter(if (!is.null(end_p))
@@ -1569,6 +1569,9 @@ prepare_totalcw <- function(start_p, end_p) {
plot_totalcw <- function(start_p, end_p, path_p) {
prepare_totalcw(start_p, end_p) %>%
+ mutate(nickname = ifelse(nickname == "", "consensus", nickname)) %>%
+ mutate(nickname = factor(nickname,
+ levels = c("consensus", unique(nickname[nickname != "consensus"])))) %>%
complete(valid_after_date = full_seq(valid_after_date, period = 1),
nesting(nickname)) %>%
ggplot(aes(x = valid_after_date, y = measured_sum_avg,
diff --git a/src/main/java/org/torproject/metrics/stats/totalcw/Database.java b/src/main/java/org/torproject/metrics/stats/totalcw/Database.java
index b6dc87c..e842bc6 100644
--- a/src/main/java/org/torproject/metrics/stats/totalcw/Database.java
+++ b/src/main/java/org/torproject/metrics/stats/totalcw/Database.java
@@ -10,6 +10,8 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
+import java.sql.Types;
+import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
@@ -63,23 +65,36 @@ class Database implements AutoCloseable {
"INSERT INTO authority (nickname, identity_hex) VALUES (?, ?)",
Statement.RETURN_GENERATED_KEYS);
this.psVoteSelect = this.connection.prepareStatement(
- "SELECT EXISTS (SELECT 1 FROM vote "
+ "SELECT EXISTS (SELECT 1 FROM status "
+ "WHERE valid_after = ? AND authority_id = ?)");
this.psVoteInsert = this.connection.prepareStatement(
- "INSERT INTO vote (valid_after, authority_id, have_guard_flag, "
+ "INSERT INTO status (valid_after, authority_id, have_guard_flag, "
+ "have_exit_flag, measured_sum) VALUES (?, ?, ?, ?, ?)");
}
- /** Insert a parsed vote into the vote table. */
- void insertVote(TotalcwRelayNetworkStatusVote vote) throws SQLException {
- if (null == vote) {
- /* Nothing to insert. */
- return;
+ /** Insert a parsed consensus into the status table. */
+ void insertConsensus(TotalcwRelayNetworkStatus consensus)
+ throws SQLException {
+ if (null != consensus) {
+ insertStatusIfAbsent(consensus.validAfter, null, consensus.measuredSums);
}
+ }
+
+ /** Insert a parsed vote into the status table. */
+ void insertVote(TotalcwRelayNetworkStatus vote) throws SQLException {
+ if (null != vote) {
+ int authorityId = insertAuthorityIfAbsent(vote.nickname,
+ vote.identityHex);
+ insertStatusIfAbsent(vote.validAfter, authorityId, vote.measuredSums);
+ }
+ }
+
+ private int insertAuthorityIfAbsent(String nickname, String identityHex)
+ throws SQLException {
int authorityId = -1;
this.psAuthoritySelect.clearParameters();
- this.psAuthoritySelect.setString(1, vote.nickname);
- this.psAuthoritySelect.setString(2, vote.identityHex);
+ this.psAuthoritySelect.setString(1, nickname);
+ this.psAuthoritySelect.setString(2, identityHex);
try (ResultSet rs = this.psAuthoritySelect.executeQuery()) {
if (rs.next()) {
authorityId = rs.getInt(1);
@@ -87,8 +102,8 @@ class Database implements AutoCloseable {
}
if (authorityId < 0) {
this.psAuthorityInsert.clearParameters();
- this.psAuthorityInsert.setString(1, vote.nickname);
- this.psAuthorityInsert.setString(2, vote.identityHex);
+ this.psAuthorityInsert.setString(1, nickname);
+ this.psAuthorityInsert.setString(2, identityHex);
this.psAuthorityInsert.execute();
try (ResultSet rs = this.psAuthorityInsert.getGeneratedKeys()) {
if (rs.next()) {
@@ -100,13 +115,22 @@ class Database implements AutoCloseable {
+ "authority entry.");
}
}
+ return authorityId;
+ }
+
+ private void insertStatusIfAbsent(LocalDateTime validAfter,
+ Integer authorityId, long[] measuredSums) throws SQLException {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"),
Locale.US);
this.psVoteSelect.clearParameters();
this.psVoteSelect.setTimestamp(1,
- Timestamp.from(ZonedDateTime.of(vote.validAfter,
- ZoneId.of("UTC")).toInstant()), calendar);
- this.psVoteSelect.setInt(2, authorityId);
+ Timestamp.from(ZonedDateTime.of(validAfter,
+ ZoneId.of("UTC")).toInstant()), calendar);
+ if (null == authorityId) {
+ this.psVoteSelect.setNull(2, Types.INTEGER);
+ } else {
+ this.psVoteSelect.setInt(2, authorityId);
+ }
try (ResultSet rs = this.psVoteSelect.executeQuery()) {
if (rs.next()) {
if (rs.getBoolean(1)) {
@@ -119,12 +143,16 @@ class Database implements AutoCloseable {
measuredSumsIndex++) {
this.psVoteInsert.clearParameters();
this.psVoteInsert.setTimestamp(1,
- Timestamp.from(ZonedDateTime.of(vote.validAfter,
+ Timestamp.from(ZonedDateTime.of(validAfter,
ZoneId.of("UTC")).toInstant()), calendar);
- this.psVoteInsert.setInt(2, authorityId);
+ if (null == authorityId) {
+ this.psVoteInsert.setNull(2, Types.INTEGER);
+ } else {
+ this.psVoteInsert.setInt(2, authorityId);
+ }
this.psVoteInsert.setBoolean(3, 1 == (measuredSumsIndex & 1));
this.psVoteInsert.setBoolean(4, 2 == (measuredSumsIndex & 2));
- this.psVoteInsert.setLong(5, vote.measuredSums[measuredSumsIndex]);
+ this.psVoteInsert.setLong(5, measuredSums[measuredSumsIndex]);
this.psVoteInsert.execute();
}
}
diff --git a/src/main/java/org/torproject/metrics/stats/totalcw/Main.java b/src/main/java/org/torproject/metrics/stats/totalcw/Main.java
index 7c77160..e5ba8ab 100644
--- a/src/main/java/org/torproject/metrics/stats/totalcw/Main.java
+++ b/src/main/java/org/torproject/metrics/stats/totalcw/Main.java
@@ -6,6 +6,7 @@ package org.torproject.metrics.stats.totalcw;
import org.torproject.descriptor.Descriptor;
import org.torproject.descriptor.DescriptorReader;
import org.torproject.descriptor.DescriptorSourceFactory;
+import org.torproject.descriptor.RelayNetworkStatusConsensus;
import org.torproject.descriptor.RelayNetworkStatusVote;
import org.slf4j.Logger;
@@ -24,6 +25,8 @@ public class Main {
private static Logger log = LoggerFactory.getLogger(Main.class);
private static String[][] paths = {
+ {"recent", "relay-descriptors", "consensuses"},
+ {"archive", "relay-descriptors", "consensuses"},
{"recent", "relay-descriptors", "votes"},
{"archive", "relay-descriptors", "votes"}};
@@ -32,7 +35,8 @@ public class Main {
log.info("Starting totalcw module.");
- log.info("Reading votes and inserting relevant parts into the database.");
+ log.info("Reading consensuses and votes and inserting relevant parts into "
+ + "the database.");
DescriptorReader reader = DescriptorSourceFactory.createDescriptorReader();
File historyFile = new File(Configuration.history);
reader.setHistoryFile(historyFile);
@@ -43,7 +47,10 @@ public class Main {
Arrays.stream(paths).map((String[] path)
-> Paths.get(Configuration.descriptors, path).toFile())
.toArray(File[]::new))) {
- if (descriptor instanceof RelayNetworkStatusVote) {
+ if (descriptor instanceof RelayNetworkStatusConsensus) {
+ database.insertConsensus(parser.parseRelayNetworkStatusConsensus(
+ (RelayNetworkStatusConsensus) descriptor));
+ } else if (descriptor instanceof RelayNetworkStatusVote) {
database.insertVote(parser.parseRelayNetworkStatusVote(
(RelayNetworkStatusVote) descriptor));
} else {
diff --git a/src/main/java/org/torproject/metrics/stats/totalcw/OutputLine.java b/src/main/java/org/torproject/metrics/stats/totalcw/OutputLine.java
index 5587e5d..3534e2a 100644
--- a/src/main/java/org/torproject/metrics/stats/totalcw/OutputLine.java
+++ b/src/main/java/org/torproject/metrics/stats/totalcw/OutputLine.java
@@ -26,7 +26,8 @@ class OutputLine {
/** Date. */
LocalDate validAfterDate;
- /** Server type, which can be "relay" or "bridge". */
+ /** Nickname of the authority generating votes, or <code>null</code> in case
+ * of consensuses. */
String nickname;
/** Whether contained relays all have the "Guard" flag. */
@@ -42,8 +43,9 @@ class OutputLine {
* file. */
@Override
public String toString() {
- return String.format("%s,%s,%s,%s,%d", validAfterDate, nickname,
- haveGuardFlag ? "t" : "f", haveExitFlag ? "t" : "f", measuredSumAvg);
+ return String.format("%s,%s,%s,%s,%d", validAfterDate,
+ null == nickname ? "" : nickname, haveGuardFlag ? "t" : "f",
+ haveExitFlag ? "t" : "f", measuredSumAvg);
}
}
diff --git a/src/main/java/org/torproject/metrics/stats/totalcw/Parser.java b/src/main/java/org/torproject/metrics/stats/totalcw/Parser.java
index 6070822..7d7e095 100644
--- a/src/main/java/org/torproject/metrics/stats/totalcw/Parser.java
+++ b/src/main/java/org/torproject/metrics/stats/totalcw/Parser.java
@@ -4,6 +4,7 @@
package org.torproject.metrics.stats.totalcw;
import org.torproject.descriptor.NetworkStatusEntry;
+import org.torproject.descriptor.RelayNetworkStatusConsensus;
import org.torproject.descriptor.RelayNetworkStatusVote;
import java.time.Instant;
@@ -13,9 +14,40 @@ import java.time.ZoneId;
* data objects for them. */
class Parser {
+ /** Parse and return a consensus, but return <code>null</code> if the
+ * consensus did not contain any bandwidth values. */
+ TotalcwRelayNetworkStatus parseRelayNetworkStatusConsensus(
+ RelayNetworkStatusConsensus consensus) {
+ boolean containsBandwidthValues = false;
+ long[] measuredSums = new long[4];
+ for (NetworkStatusEntry entry : consensus.getStatusEntries().values()) {
+ if (null == entry.getFlags() || !entry.getFlags().contains("Running")
+ || entry.getBandwidth() < 0L) {
+ continue;
+ }
+ containsBandwidthValues = true;
+ /* Encode flags as sum of Guard = 1 and (Exit and !BadExit) = 2. */
+ int measuredSumsIndex = (entry.getFlags().contains("Guard") ? 1 : 0)
+ + (entry.getFlags().contains("Exit")
+ && !entry.getFlags().contains("BadExit") ? 2 : 0);
+ measuredSums[measuredSumsIndex] += entry.getBandwidth();
+ }
+ if (!containsBandwidthValues) {
+ /* Return null, because we wouldn't want to add this consensus to the
+ * database anyway. */
+ return null;
+ }
+ TotalcwRelayNetworkStatus parsedStatus = new TotalcwRelayNetworkStatus();
+ parsedStatus.validAfter = Instant.ofEpochMilli(
+ consensus.getValidAfterMillis())
+ .atZone(ZoneId.of("UTC")).toLocalDateTime();
+ parsedStatus.measuredSums = measuredSums;
+ return parsedStatus;
+ }
+
/** Parse and return a vote, but return <code>null</code> if the vote did not
* contain any bandwidth measurements. */
- TotalcwRelayNetworkStatusVote parseRelayNetworkStatusVote(
+ TotalcwRelayNetworkStatus parseRelayNetworkStatusVote(
RelayNetworkStatusVote vote) {
boolean containsMeasuredBandwidths = false;
long[] measuredSums = new long[4];
@@ -36,14 +68,13 @@ class Parser {
* anyway. */
return null;
}
- TotalcwRelayNetworkStatusVote parsedVote
- = new TotalcwRelayNetworkStatusVote();
- parsedVote.validAfter = Instant.ofEpochMilli(vote.getValidAfterMillis())
+ TotalcwRelayNetworkStatus parsedStatus = new TotalcwRelayNetworkStatus();
+ parsedStatus.validAfter = Instant.ofEpochMilli(vote.getValidAfterMillis())
.atZone(ZoneId.of("UTC")).toLocalDateTime();
- parsedVote.identityHex = vote.getIdentity();
- parsedVote.nickname = vote.getNickname();
- parsedVote.measuredSums = measuredSums;
- return parsedVote;
+ parsedStatus.identityHex = vote.getIdentity();
+ parsedStatus.nickname = vote.getNickname();
+ parsedStatus.measuredSums = measuredSums;
+ return parsedStatus;
}
}
diff --git a/src/main/java/org/torproject/metrics/stats/totalcw/TotalcwRelayNetworkStatusVote.java b/src/main/java/org/torproject/metrics/stats/totalcw/TotalcwRelayNetworkStatus.java
similarity index 72%
rename from src/main/java/org/torproject/metrics/stats/totalcw/TotalcwRelayNetworkStatusVote.java
rename to src/main/java/org/torproject/metrics/stats/totalcw/TotalcwRelayNetworkStatus.java
index 0c5a095..f9b6610 100644
--- a/src/main/java/org/torproject/metrics/stats/totalcw/TotalcwRelayNetworkStatusVote.java
+++ b/src/main/java/org/torproject/metrics/stats/totalcw/TotalcwRelayNetworkStatus.java
@@ -5,18 +5,18 @@ package org.torproject.metrics.stats.totalcw;
import java.time.LocalDateTime;
-/** Data object holding all relevant parts parsed from a vote. */
-class TotalcwRelayNetworkStatusVote {
+/** Data object holding all relevant parts parsed from a consensus or vote. */
+class TotalcwRelayNetworkStatus {
/** Valid-after time of the vote. */
LocalDateTime validAfter;
/** The 1 to 19 character long alphanumeric nickname assigned to the authority
- * by its operator. */
+ * by its operator, or <code>null</code> if this is a consensus. */
String nickname;
/** Uppercase hex fingerprint of the authority's (v3 authority) identity
- * key. */
+ * key, or <code>null</code> if this is a consensus. */
String identityHex;
/** Sums of bandwidth measurements of all contained status entries with four
diff --git a/src/main/sql/totalcw/init-totalcw.sql b/src/main/sql/totalcw/init-totalcw.sql
index cdba275..62778d4 100644
--- a/src/main/sql/totalcw/init-totalcw.sql
+++ b/src/main/sql/totalcw/init-totalcw.sql
@@ -18,17 +18,19 @@ CREATE TABLE authority (
UNIQUE (nickname, identity_hex)
);
--- Table of all votes with statistics on contained bandwidth measurements. Only
--- contains votes containing bandwidth measurements.
-CREATE TABLE vote (
+-- Table of all consensuses and votes with statistics on contained bandwidth
+-- measurements. Only contains consensuses containing bandwidth values and votes
+-- containing bandwidth measurements.
+CREATE TABLE status (
- -- The auto-incremented numeric identifier for a vote.
- vote_id SERIAL PRIMARY KEY,
+ -- The auto-incremented numeric identifier for a status.
+ status_id SERIAL PRIMARY KEY,
-- Timestamp at which the consensus is supposed to become valid.
valid_after TIMESTAMP WITHOUT TIME ZONE NOT NULL,
- -- Numeric identifier uniquely identifying the authority generating this vote.
+ -- Numeric identifier uniquely identifying the authority generating this vote,
+ -- or NULL if this a consensus.
authority_id INTEGER REFERENCES authority (authority_id),
-- Whether contained relays had the Guard flag assigned.
@@ -45,13 +47,14 @@ CREATE TABLE vote (
-- View on aggregated total consensus weight statistics in a format that is
-- compatible for writing to an output CSV file. Votes are only included in the
--- output if at least 12 votes are known for a given authority and day.
+-- output if at least 12 statuses are known for a given authority and day.
CREATE OR REPLACE VIEW totalcw AS
SELECT DATE(valid_after) AS valid_after_date, nickname, have_guard_flag,
have_exit_flag, FLOOR(AVG(measured_sum)) AS measured_sum_avg
-FROM vote NATURAL JOIN authority
+FROM status LEFT JOIN authority
+ON status.authority_id = authority.authority_id
GROUP BY DATE(valid_after), nickname, have_guard_flag, have_exit_flag
-HAVING COUNT(vote_id) >= 12
- AND DATE(valid_after) < (SELECT MAX(DATE(valid_after)) FROM vote)
+HAVING COUNT(status_id) >= 12
+ AND DATE(valid_after) < (SELECT MAX(DATE(valid_after)) FROM status)
ORDER BY DATE(valid_after), nickname, have_guard_flag, have_exit_flag;
diff --git a/src/test/java/org/torproject/metrics/stats/totalcw/TotalcwRelayNetworkStatusVoteTest.java b/src/test/java/org/torproject/metrics/stats/totalcw/TotalcwRelayNetworkStatusTest.java
similarity index 76%
rename from src/test/java/org/torproject/metrics/stats/totalcw/TotalcwRelayNetworkStatusVoteTest.java
rename to src/test/java/org/torproject/metrics/stats/totalcw/TotalcwRelayNetworkStatusTest.java
index 189b3b7..1c5b408 100644
--- a/src/test/java/org/torproject/metrics/stats/totalcw/TotalcwRelayNetworkStatusVoteTest.java
+++ b/src/test/java/org/torproject/metrics/stats/totalcw/TotalcwRelayNetworkStatusTest.java
@@ -9,6 +9,7 @@ import static org.junit.Assert.assertNull;
import org.torproject.descriptor.Descriptor;
import org.torproject.descriptor.DescriptorSourceFactory;
+import org.torproject.descriptor.RelayNetworkStatusConsensus;
import org.torproject.descriptor.RelayNetworkStatusVote;
import org.junit.Test;
@@ -27,12 +28,15 @@ import java.util.Arrays;
import java.util.Collection;
@RunWith(Parameterized.class)
-public class TotalcwRelayNetworkStatusVoteTest {
+public class TotalcwRelayNetworkStatusTest {
/** Provide test data. */
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
+ { "2018-10-15-00-00-00-consensus.part",
+ ZonedDateTime.parse("2018-10-15T00:00:00Z").toLocalDateTime(),
+ null, null, new long[] { 16774L, 44820L, 26600L, 49500L } },
{ "2018-10-15-00-00-00-vote-0232AF901C31A04EE9848595AF9BB7620D4C5B2E-"
+ "55A38ED50848BE1F13C6A35C3CA637B0D962C2EF.part",
ZonedDateTime.parse("2018-10-15T00:00:00Z").toLocalDateTime(),
@@ -84,15 +88,21 @@ public class TotalcwRelayNetworkStatusVoteTest {
for (Descriptor descriptor
: DescriptorSourceFactory.createDescriptorParser().parseDescriptors(
sb.toString().getBytes(), new File(this.fileName), this.fileName)) {
- TotalcwRelayNetworkStatusVote parsedVote = new Parser()
- .parseRelayNetworkStatusVote((RelayNetworkStatusVote) descriptor);
+ TotalcwRelayNetworkStatus parsedStatus;
+ if (descriptor instanceof RelayNetworkStatusConsensus) {
+ parsedStatus = new Parser().parseRelayNetworkStatusConsensus(
+ (RelayNetworkStatusConsensus) descriptor);
+ } else {
+ parsedStatus = new Parser().parseRelayNetworkStatusVote(
+ (RelayNetworkStatusVote) descriptor);
+ }
if (null == this.expectedMeasuredSums) {
- assertNull(parsedVote);
+ assertNull(parsedStatus);
} else {
- assertEquals(this.expectedValidAfter, parsedVote.validAfter);
- assertEquals(this.expectedNickname, parsedVote.nickname);
- assertEquals(this.expectedIdentityHex, parsedVote.identityHex);
- assertArrayEquals(this.expectedMeasuredSums, parsedVote.measuredSums);
+ assertEquals(this.expectedValidAfter, parsedStatus.validAfter);
+ assertEquals(this.expectedNickname, parsedStatus.nickname);
+ assertEquals(this.expectedIdentityHex, parsedStatus.identityHex);
+ assertArrayEquals(this.expectedMeasuredSums, parsedStatus.measuredSums);
}
}
}
diff --git a/src/test/resources/totalcw/2018-10-15-00-00-00-consensus.part b/src/test/resources/totalcw/2018-10-15-00-00-00-consensus.part
new file mode 100644
index 0000000..b1ef7c5
--- /dev/null
+++ b/src/test/resources/totalcw/2018-10-15-00-00-00-consensus.part
@@ -0,0 +1,251 @@
+ at type network-status-consensus-3 1.0
+network-status-version 3
+vote-status consensus
+consensus-method 28
+valid-after 2018-10-15 00:00:00
+fresh-until 2018-10-15 01:00:00
+valid-until 2018-10-15 03:00:00
+voting-delay 300 300
+client-versions 0.2.9.14,0.2.9.15,0.2.9.16,0.2.9.17,0.3.2.6-alpha,0.3.2.7-rc,0.3.2.8-rc,0.3.2.9,0.3.2.10,0.3.2.11,0.3.2.12,0.3.3.1-alpha,0.3.3.2-alpha,0.3.3.3-alpha,0.3.3.4-alpha,0.3.3.5-rc,0.3.3.6,0.3.3.7,0.3.3.8,0.3.3.9,0.3.3.10,0.3.4.1-alpha,0.3.4.2-alpha,0.3.4.3-alpha,0.3.4.4-rc,0.3.4.5-rc,0.3.4.6-rc,0.3.4.7-rc,0.3.4.8,0.3.5.1-alpha,0.3.5.2-alpha,0.3.5.3-alpha
+server-versions 0.2.9.14,0.2.9.15,0.2.9.16,0.2.9.17,0.3.2.10,0.3.2.11,0.3.2.12,0.3.3.2-alpha,0.3.3.3-alpha,0.3.3.4-alpha,0.3.3.5-rc,0.3.3.6,0.3.3.7,0.3.3.8,0.3.3.9,0.3.3.10,0.3.4.1-alpha,0.3.4.2-alpha,0.3.4.3-alpha,0.3.4.4-rc,0.3.4.5-rc,0.3.4.6-rc,0.3.4.7-rc,0.3.4.8,0.3.5.1-alpha,0.3.5.2-alpha,0.3.5.3-alpha
+known-flags Authority BadExit Exit Fast Guard HSDir NoEdConsensus Running Stable V2Dir Valid
+recommended-client-protocols Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=4 Microdesc=1-2 Relay=2
+recommended-relay-protocols Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=4 Microdesc=1-2 Relay=2
+required-client-protocols Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=4 Microdesc=1-2 Relay=2
+required-relay-protocols Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=3-4 Microdesc=1 Relay=1-2
+params CircuitPriorityHalflifeMsec=30000 DoSCircuitCreationEnabled=1 DoSConnectionEnabled=1 DoSConnectionMaxConcurrentCount=50 DoSRefuseSingleHopClientRendezvous=1 NumDirectoryGuards=3 NumEntryGuards=1 NumNTorsPerTAP=100 Support022HiddenServices=0 UseNTorHandshake=1 UseOptimisticData=1 bwauthpid=1 cbttestfreq=10 hs_service_max_rdv_failures=1 hsdir_spread_store=4 pb_disablepct=0 usecreatefast=0
+shared-rand-previous-value 9 Vd2znClwwth89jp91diG/Bs1AH+0ExSgRFmyVOMJwwE=
+shared-rand-current-value 9 oiXRUZGkT26O9aQmu/A52utoBF3gp27h0TvJ4gkDHkw=
+dir-source dannenberg 0232AF901C31A04EE9848595AF9BB7620D4C5B2E dannenberg.torauth.de 193.23.244.244 80 443
+contact Andreas Lehner
+vote-digest 55A38ED50848BE1F13C6A35C3CA637B0D962C2EF
+dir-source tor26 14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 86.59.21.38 86.59.21.38 80 443
+contact Peter Palfrader
+vote-digest EB6F8C0AF9DBC7A6CCA92C633B1AEF38BE55C5DF
+dir-source longclaw 23D15D965BC35114467363C165C4F724B64B4F66 199.58.81.140 199.58.81.140 80 443
+contact Riseup Networks <collective at riseup dot net> - 1nNzekuHGGzBYRzyjfjFEfeisNvxkn4RT
+vote-digest 867D4F189EA9C6A0A4A688DA08B5BE63E0F974F9
+dir-source bastet 27102BC123E7AF1D4741AE047E160C91ADC76B21 204.13.164.118 204.13.164.118 80 443
+contact stefani <nocat at readthefinemanual dot net>
+vote-digest 049AB3179B12DACC391F06A10C2A8904E4339D33
+dir-source maatuska 49015F787433103580E3B66A1707A00E60F2D15B 171.25.193.9 171.25.193.9 443 80
+contact 4096R/1E8BF34923291265 Linus Nordberg <linus at nordberg.se>
+vote-digest C1FD622901C12211758F9FF507DAD821EA2B4A4D
+dir-source moria1 D586D18309DED4CD6D57C18FDB97EFA96D330566 128.31.0.34 128.31.0.34 9131 9101
+contact 1024D/28988BF5 arma mit edu
+vote-digest 9BD97F7B3205048B1FF8FC02EFE9D10B64BAB4EB
+dir-source dizum E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58 194.109.206.212 194.109.206.212 80 443
+contact 1024R/8D56913D Alex de Joode <adejoode at sabotage.org>
+vote-digest 6E40986B3025BB5916966EB98851D35809FF2B54
+dir-source gabelmoo ED03BB616EB2F60BEC80151114BB25CEF515B226 131.188.40.189 131.188.40.189 80 443
+contact 4096R/261C5FBE77285F88FB0C343266C8C2D7C5AA446D Sebastian Hahn <tor at sebastianhahn.net> - 12NbRAjAG5U3LLWETSF7fSTcdaz32Mu5CN
+vote-digest 2669AD153408F88E416CE6206D1A75EC3324A2F4
+dir-source Faravahar EFCBE720AB3A82B99F9E953CD5BF50F7EEFC7B97 154.35.175.225 154.35.175.225 80 443
+contact 0x0B47D56D Sina Rabbani (inf0) <sina redteam net>
+vote-digest 38C6A19F78948B689345EE41D7119D76246C4D3E
+r seele AAoQ1DAR6kkoo19hBAX5K0QztNw xlbC5aW8ovDVh2t6VcKF/phheSg 2018-10-14 21:41:22 67.174.243.193 9001 0
+s Running Stable V2Dir Valid
+v Tor 0.3.4.8
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=16
+p reject 1-65535
+r PutoElQueLee293884 AAwffNL+oHO5EdyUoWAOwvEX3ws Ay3cnaaHjnolSRe3ZjKcGlY17Q8 2018-10-14 08:06:47 174.127.217.73 55554 0
+s Fast Guard Running Stable V2Dir Valid
+v Tor 0.3.3.9
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=5620
+p reject 1-65535
+r CalyxInstitute14 ABG9JIWtRdmE7EFZyI/AZuXjMA4 +8xNQyAVPkKgtLH0AISVZFNuAq0 2018-10-14 11:10:20 162.247.74.201 443 80
+s Exit Fast Guard HSDir Running Stable V2Dir Valid
+v Tor 0.3.3.7
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=14700
+p accept 20-23,43,53,79-81,88,110,143,194,220,389,443,464,531,543-544,554,563,636,706,749,873,902-904,981,989-995,1194,1220,1293,1500,1533,1677,1723,1755,1863,2082-2083,2086-2087,2095-2096,2102-2104,3128,3389,3690,4321,4643,5050,5190,5222-5223,5228,5900,6660-6669,6679,6697,8000,8008,8074,8080,8087-8088,8332-8333,8443,8888,9418,9999-10000,11371,12350,19294,19638,23456,33033,64738
+r Neldoreth ABUk3UA9cp8I9+XXeBPvEnVs+o0 nms8ZM18C/K5XzLmgO5fHchjhFc 2018-10-14 19:09:56 185.13.39.197 443 80
+s Fast Guard Running Stable V2Dir Valid
+v Tor 0.3.4.8
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=10400
+p reject 1-65535
+r rotor25 ADQsDhVdRULlU5F4iy13nxRXjes m/3hkTP+ETmoYWZ3JrniJAeRHho 2018-10-14 17:19:08 188.24.22.193 9001 9030
+s Fast Running V2Dir Valid
+v Tor 0.3.4.8
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=5580
+p reject 1-65535
+r torbogen AEHgFQsKMHUGwoY+/J8rfjpSOzY DXa3G+iPbGQo4AK2iazVY6R4eKs 2018-10-14 20:19:33 178.142.72.49 9001 9030
+s Fast Running V2Dir Valid
+v Tor 0.3.3.9
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=1070
+p reject 1-65535
+r nicolass67atoll AES/YhfxWxj3ZvK1O85bPg4BV+k iK+QhopNtEipMSL+EeI6b/DitVc 2018-10-14 15:48:15 163.172.10.89 9001 0
+s Fast Running Stable V2Dir Valid
+v Tor 0.2.9.16
+pr Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1-2 Link=1-4 LinkAuth=1 Microdesc=1-2 Relay=1-2
+w Bandwidth=856
+p reject 1-65535
+r zzzzzzzzzzzzzzzzzzz AEVz/pNLpV0H2ucjF3k69OQbdbY 1FUGYNQtQo1MgV4jRP2XJapWemI 2018-10-14 23:43:10 77.12.174.141 9002 9031
+s Fast Running V2Dir Valid
+v Tor 0.3.2.10
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=235
+p reject 1-65535
+r helga AFnZKULbO4TlLrTYfp97GVz00AU ngp++P8hEV+Pj/j9OvvDCyuDqKA 2018-10-14 17:09:42 88.99.216.194 9001 9030
+s Fast HSDir Running Stable V2Dir Valid
+v Tor 0.3.4.8
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=261
+p reject 1-65535
+r Torpi AHJ/OiwdDxcxqRJnxBFQecFrILQ bLi/i6JuuPmoWm1aGd73dy2tYlA 2018-10-14 15:51:48 110.146.4.151 9001 9030
+s Running Stable V2Dir Valid
+v Tor 0.2.4.29
+pr Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=1-4 LinkAuth=1 Microdesc=1 Relay=1-2
+w Bandwidth=23
+p reject 1-65535
+r VeespRU2 AHTsqCvVi4uxkJycTyN/2XebI/w r3AsIyXKvSFzC+5eDuiUgPTmG9g 2018-10-14 09:25:26 185.22.172.237 443 80
+s Fast Guard HSDir Running Stable V2Dir Valid
+v Tor 0.3.3.7
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=21300
+p reject 1-65535
+r Quintex13 AHe8unJE2z5qXtJ0boYXAGZoSIc GwoBS5ddT7ktxwqHjHYNc2u53xU 2018-10-14 07:38:44 199.249.223.62 443 80
+s Exit Fast HSDir Running Stable V2Dir Valid
+v Tor 0.3.4.8
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=5000
+p accept 20-23,43,53,79-81,88,110,143,194,220,389,443,464-465,531,543-544,554,563,587,636,706,749,873,902-904,981,989-995,1194,1220,1293,1500,1533,1677,1723,1755,1863,2082-2083,2086-2087,2095-2096,2102-2104,3128,3389,3690,4321,4643,5050,5190,5222-5223,5228,5900,6660-6669,6679,6697,8000,8008,8074,8080,8082,8087-8088,8232-8233,8332-8333,8443,8888,9418,9999-10000,11371,19294,19638,50002,64738
+r torrelay04 AH/ZCOnPz1nmT7pCt1cdLPQBvF0 n5XUymNehFnO8hTftwd4NIozrjQ 2018-10-14 18:52:54 159.69.153.73 9000 0
+a [2a01:4f8:1c1c:5cec::1]:9000
+s Fast Running Stable Valid
+v Tor 0.3.4.8
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=8460
+p reject 1-65535
+r bigamy AH/cDMglli4ShKYaaMk4pmr75XA dMrr7wRTfKoVfCRHLuR0IZFSWsI 2018-10-14 13:28:57 185.24.218.171 9001 8080
+s Exit Fast Running Stable V2Dir Valid
+v Tor 0.3.4.8
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=21600
+p accept 20-21,23,43,53,79-81,88,110,143,194,220,389,443,464-465,531,543-544,554,563,587,636,706,749,853,873,902-904,981,989-995,1220,1293,1500,1533,1677,1723,1755,1863,2082-2087,2095-2096,2102-2104,2374-2382,3128,3389,3690,4321,4643,5050,5190,5222-5223,5228,5900,6660-6669,6679,6697,8000-8100,8232-8233,8332-8333,8443,8888,9418,9999-10000,11371,19294,19638,50002,64738
+r zech1989 AI57cMO0p1ILW+q4Bnq83I5j8f0 boK7UYxCaZy4lpe8irfYPFsX6SY 2018-10-14 21:18:08 185.243.53.99 9001 9030
+s Fast Guard HSDir Running Stable V2Dir Valid
+v Tor 0.3.4.8
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=7500
+p reject 1-65535
+r paris AJf70aisEQPfmPHoXdUsUPAdOtY 9x4Jiv45IDG4EDSSXfOd+Ss9qtc 2018-10-14 22:06:20 178.19.111.147 9001 8000
+s Exit Fast Guard HSDir Running Stable V2Dir Valid
+v Tor 0.3.4.8
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=34800
+p accept 20-21,23,43,53,79-81,88,110,143,194,220,389,443,464-465,531,543-544,554,563,587,636,706,749,853,873,902-904,981,989-995,1220,1293,1500,1533,1677,1723,1755,1863,2082-2087,2095-2096,2102-2104,2374-2382,3128,3389,3690,4321,4643,5050,5190,5222-5223,5228,5900,6660-6669,6679,6697,8000-8100,8232-8233,8332-8333,8443,8888,9418,9999-10000,11371,19294,19638,50002,64738
+r jactr AJhR35M3VLAN3odvzkCIzhtJQME RLckbaDnNUH4qGCkOmDo20UwE28 2018-10-14 23:26:36 84.40.112.70 9001 9030
+s Running Stable V2Dir Valid
+v Tor 0.2.9.15
+pr Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1-2 Link=1-4 LinkAuth=1 Microdesc=1-2 Relay=1-2
+w Bandwidth=68
+p reject 1-65535
+r IsThisAGoodIdea AJ2M8WzPcSMatc5VyCoDRG2j+Us Gce3qKSpkK8w2D+9k75V7vNdWzI 2018-10-14 16:51:45 220.233.27.93 9001 0
+s Running Valid
+v Tor 0.3.3.9
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=5
+p reject 1-65535
+r hozipi ALIqOUZNig9oebg/jlqo4oMPdAw vFalrkfCLlJRmGrSva7qK2nc30A 2018-10-14 15:27:06 93.104.163.230 80 110
+s Fast Running Stable V2Dir Valid
+v Tor 0.3.4.8
+pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
+w Bandwidth=162
+p reject 1-65535
+r Unnamed ALPJ+3njaQWlF6SJsFgkZ1mr+8g 6CQL/R+ltI9Jzx9GTDFJ3YLvMOg 2018-10-14 12:18:53 80.254.128.45 9001 0
+s Running Stable V2Dir Valid
+v Tor 0.2.9.14
+pr Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1-2 Link=1-4 LinkAuth=1 Microdesc=1-2 Relay=1-2
+w Bandwidth=38
+p reject 1-65535
+directory-footer
+bandwidth-weights Wbd=0 Wbe=0 Wbg=3669 Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 Wem=10000 Wgb=10000 Wgd=0 Wgg=6331 Wgm=6331 Wmb=10000 Wmd=0 Wme=0 Wmg=3669 Wmm=10000
+directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E CD1FD971855430880D3C31E0331C5C55800C2F79
+-----BEGIN SIGNATURE-----
+qLfqP5BkUTTxumtU7RAY5KM54bP6LPkU8dQqznJsipE7VyDXdZI+WHJztdvnuAyY
+5U97ZEypm/KLqlJz64eu5KoNb3I3nq5iOdONUZYZVY2THAaIUtx1I1ciHmmtjdiM
+deAZeD5hQEC255Nv12mSq5+1ILcXb2ubpUOMsYXZ/llLdLPD0z7YObaQYZ3dbfNW
+LocnNAN96ecAzBsanbTZoH6+dU4XkNNenH1VFokkpDEQggXyERYB1M/2bd2r62tO
+HD2NqSb45n5ZimeeSfFBJ7qLyMZBHmGCwaFY/AKl/MYYSNQzFOAPuKwP1Jqcx6nY
+3CcLZUeGtwmMwRpAX2+jxg==
+-----END SIGNATURE-----
+directory-signature 14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 1F4D49989DA1503D5B20EAADB0673C948BA73B49
+-----BEGIN SIGNATURE-----
+e4lIInOkXIN0ZxnBng5gzo/zO8VM6u/iQHUCG0RwIRbRVmJ51RCM0YktTI+gm3ML
+OIm8QwnAC9yzXsmqI7ebqCylAXKv4bvNttowVkVD3YHv5qZ3wPWLN74W4xvLbCqc
+yIW3Lt/Uo2PSS7yUPcwi8vVgR9rkDmBol+Wz9E8GsUoeaVDdNa1D3rXzcxZLFeuF
+kcnDIAkapKw9gFylzIKAh4UnpmorKd5+CLIcclKCp/Q3beG4XeFVP+DmlUIZxaxW
+B9jd13flJbiMtAk6FBZEThVYf1zL6tgFHigJ0/l3elEBV42RlvHRlxOD3p4xsqq5
+IbM6qmjNi+2QYLVURG6F/3oYuwunP7hP42OC8Z2BlL2bOetMFfm+b1mFcKZSlnuU
+6k8uWXl0yLVovd0s/+bJGp81SiPsFzKY7Ng/QiYnNzWgNduNGAyL40P6jd9oJzqX
+ex4p4OIf1EukgbM8QA4AErzmL9QqfP2EnFYNDjXogzUrVeLulOpZfp00Iwbth1QY
+-----END SIGNATURE-----
+directory-signature 23D15D965BC35114467363C165C4F724B64B4F66 A2E5511319AD43DF88EABFB8BB1FFD767D005601
+-----BEGIN SIGNATURE-----
+gVI0n2dVpbJHfMVxOrvFSXNGfMjNKVzWi9CsIhhq1fgg1oCsiK2z2w2K+3WXlZuI
+op8USZAXC4FFocBrWXcazv+8BMUZ8CyWHhi5nKV82wOsA7nj0UQg85ODzukYHAl6
+NMr7guHxGBZajjfSvvtyoA9EzFfu/Vctv25+sXAKI0VN/F16GBL7riZYh21L/jUs
+cLC2T3EptDpJSBD8DwE9dbBrWjdL6nQlvVnGnVPhhVV4ydMRrF4S91dxE1SfShRa
+x9PT9g/RfpO1m5JKqY9oiczj5DYKEUa+uUYAsgxrXerr/OBtMtIblve/OUD6iAR8
+1gZDUJgZFd/USuuE0Cd/hw==
+-----END SIGNATURE-----
+directory-signature 27102BC123E7AF1D4741AE047E160C91ADC76B21 6FF3CD454038B7FDD7862B2DD778E4F702C31419
+-----BEGIN SIGNATURE-----
+dHbu/GLZPwmSwKCWCapZqN9RA+kN71t8dARvyoA0AS4E8J2I7/IEs9fonIcbqgWI
+6K77YJhPnVrLJ2/lAiWXcgbQEW079egTdt9OspSm2EiDm+XhsNJu5Gi7vbltVgou
+p1A+8L1qlawHiJjJ1xr01sK3vsvyLpjC3KWidV4epyTL9AXXX81eMhTa0o8jH1k2
+JZ9R7FIXlNd18F+RpUW0cAUpyY1JMUf2Zh/4YoJE9PO3ToJWukOLVbp0Td96rJo8
+/9LhhKAK0gytZEGmZhgBAxEK3YBEeGjfFNWcLr5KXEV1SmKI58JuqMDCSp/eMCrr
+EkYIG/ZCdcoA5Y8pa8GR7Q==
+-----END SIGNATURE-----
+directory-signature 49015F787433103580E3B66A1707A00E60F2D15B 10A69F531F8421310537EAC881F7DD354F251D31
+-----BEGIN SIGNATURE-----
+JsNCDE1RvcKaTXmExZvt7JfiZuCom7VQOl2E3Ree/szIfbD6Py4z3i4MVi5YVRX2
+3T6UZlImnm6dXRDv78rcUm9C/swuTSzTXHHWJE2n+yY/Gveq097dQBUfoS0tRNUj
+KsvNhbaXu5VSrQg/L1q1h6YpZ6tvvwYOxdGykIAvSqfo2XmV0iRziNOHcRPLaupu
+Wg1JFDwn9PRGsqR8HUan7SaP9VpVM8IZVkQVVJhtIdZfq9ioPIXs3uF64vwpTxQZ
+sLW0SR2Spn+M4SJ/ds9GCO/fIIWQBrFZsl6z0wEWGqSboN2Xc90jBrIqZ7TSGG2N
+ruSzC54U3bf4F/fTO85p2A==
+-----END SIGNATURE-----
+directory-signature D586D18309DED4CD6D57C18FDB97EFA96D330566 8A45BACC94A6023A90C24FBCD10520C1741828F7
+-----BEGIN SIGNATURE-----
+y1OoF+WUYaJRjx7m0xgetRbi7nIP8z7rMeoRYDhSxtGnXSyJfZ20QMDQofNDsLtW
+B5iW+vfAj4osaKYk6RW47rIedSlgtGru4vPNawRsVKAnefU707lfOsgpchFY0GYM
+QyIryrCfoFWdbXcrnguvU22ZbTgHZIQ4oa9sJIpgEOk2OwjrGwQeUuq3O27bw2Tt
+VNEqBx+co3XSvWGZmejAI2OKEw9dpgFyM9GoNW3d9U35atxy6yRtm4ki8HeLkQMm
+VYXTVVE9nGoKv7h8n0jt3oxd3HMz5PhI3ZEj96TFIXiVscHZ7EtvbOrc4/MkiuMH
+M9yHJFKbhnhcCedgUrq37g==
+-----END SIGNATURE-----
+directory-signature E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58 109A865D7DBE58367C120353CBE9947EE263695A
+-----BEGIN SIGNATURE-----
+Y7yEDJd6cz9Xa9w/FCxn8MNWH6kstjQsMmgOTpEY75h79E3ZVZQKJhJ7yJUMYdVh
+tWINafeVvTsWIX5D3MN1WdXt09UJgP4G+CJtQfohiiUBWwCeFJALBNF+9PINIQHU
+1Lgnv2qRVyYz4FZum0pDFFMv2oemZzXOvTVoQHN0nmZdxZBFA5BNRK/EJupxxJYi
+sTt3WOdoiB5OZX5RUQcfOQwzhR0NcMbvWcEqPyucbSuvKHiN7Iga2FY7B9o167v2
+Ee9XIK2qDaAXcii9i5k0LJjTn/kSlzdbjILlPTJFnVnaMtpilYz59Mk24JiKGkny
+iZGcA8yD6AHjvtC76r6eag==
+-----END SIGNATURE-----
+directory-signature ED03BB616EB2F60BEC80151114BB25CEF515B226 E1249D5F87EAD43CD4A48DF9CFCFE810BEEE5287
+-----BEGIN SIGNATURE-----
+TiqLj1g8iGiVF+IPNVwMGC1n6iCZu4Q/GLT/x920A2DPt01mwuCx4fMp12mVdPj4
+vvEpNbjqsMaqlDYBlSsZ+80l2KP1+U5ydJSoYek+meuJlSEByXdoF00UFrW8/e2s
+Jl+ARex56j+vSzj1c1qHbAfIKw/N+7/F4/9IBgLUwOVoTuvd8qcBT/UtE/gyE+kR
+Hzdrpolgu6zVICKpxa8FA/PVNaya+PYIwEfhONqw84EiJXxShTdOYFTSM+FlhBkq
+MZEVVmFrPNOxH69vnBiNvt0X0nn6tVr8QhLki6zvlVzfvvE2JkJ2fGLMhOl33q/T
+312j/QBcQ3oOBv+rF+Dnpw==
+-----END SIGNATURE-----
+directory-signature EFCBE720AB3A82B99F9E953CD5BF50F7EEFC7B97 517095062288D1B5C7BD6517A677C586D996818B
+-----BEGIN SIGNATURE-----
+21SUNen81Mcgubfn5MLVdxM65tNN9DOIwJBTxlqmQ9UzrN5TsC8ygc89lp0l8Q3t
+GP2cuw4BBShmsaU0yVT7GdONc/gqgR3SCJs9vq1BS7/7tNPPufh8ycD5xmIIsiX2
+HcC9Bh2na9Z9cfERu3s7lLwfOekPhc+Z1nf1KWLKrl+saA/zUuPjMq0AVKJedOns
+vIvockXv98cYrSc6cJ+TQ9qCR7eyG2+5TzUFmXiyH6uDfeaoetIKbJK3f9iaLisS
+73KLagxjurzRFGN9r1fwgJe14WBh3eVLfDcnXKwkqjArlBDVS3QhnLbK2W/BGr+9
+URs9oqYJlBwBp2Ia26odSg==
+-----END SIGNATURE-----
More information about the tor-commits
mailing list