commit c0ba389d25a19f5d194e07541e53f6005991fb47 Author: Karsten Loesing karsten.loesing@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 @@ +@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@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@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@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-----