[tor-commits] [tor/master] sr: Extract shared SR functions

nickm at torproject.org nickm at torproject.org
Tue May 1 14:32:50 UTC 2018


commit bdcf3a383932cc48a360c9a75b93b44a6968171e
Author: David Goulet <dgoulet at torproject.org>
Date:   Tue Apr 24 11:34:31 2018 -0400

    sr: Extract shared SR functions
    
    Move most of the shared random functions that are needed outside of the
    dirauth module.
    
    At this commit, because dirvote.c hasn't been refactor, it doesn't compile
    because some SR functions need a dirvote function.
    
    Furthermore, 5 functions haven't been touched yet because they are dirauth
    only but are in used in other C files than the dirauth module ones.
    
    No code behavior change. Only moving code around.
    
    Signed-off-by: David Goulet <dgoulet at torproject.org>
---
 src/or/control.c                     |   2 +-
 src/or/dirauth/shared_random.c       | 163 +---------------------
 src/or/dirauth/shared_random.h       |   8 --
 src/or/dirauth/shared_random_state.c |  80 +----------
 src/or/dirauth/shared_random_state.h |   5 -
 src/or/hs_common.c                   |   2 +-
 src/or/hs_service.c                  |   2 +-
 src/or/include.am                    |   2 +
 src/or/routerparse.c                 |   1 +
 src/or/shared_random_common.c        | 258 +++++++++++++++++++++++++++++++++++
 src/or/shared_random_common.h        |  47 +++++++
 11 files changed, 313 insertions(+), 257 deletions(-)

diff --git a/src/or/control.c b/src/or/control.c
index 3e643c2d7..aab854ecd 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -76,7 +76,7 @@
 #include "router.h"
 #include "routerlist.h"
 #include "routerparse.h"
-#include "dirauth/shared_random.h"
+#include "shared_random_common.h"
 
 #ifndef _WIN32
 #include <pwd.h>
diff --git a/src/or/dirauth/shared_random.c b/src/or/dirauth/shared_random.c
index e9644adf9..5dee77dce 100644
--- a/src/or/dirauth/shared_random.c
+++ b/src/or/dirauth/shared_random.c
@@ -96,6 +96,7 @@
 #include "router.h"
 #include "routerlist.h"
 #include "shared_random_state.h"
+#include "shared_random_common.h"
 #include "util.h"
 
 #include "dirauth/dirvote.h"
@@ -499,20 +500,6 @@ get_vote_line_from_commit(const sr_commit_t *commit, sr_phase_t phase)
   return vote_line;
 }
 
-/* Convert a given srv object to a string for the control port. This doesn't
- * fail and the srv object MUST be valid. */
-static char *
-srv_to_control_string(const sr_srv_t *srv)
-{
-  char *srv_str;
-  char srv_hash_encoded[SR_SRV_VALUE_BASE64_LEN + 1];
-  tor_assert(srv);
-
-  sr_srv_encode(srv_hash_encoded, sizeof(srv_hash_encoded), srv);
-  tor_asprintf(&srv_str, "%s", srv_hash_encoded);
-  return srv_str;
-}
-
 /* Return a heap allocated string that contains the given <b>srv</b> string
  * representation formatted for a networkstatus document using the
  * <b>key</b> as the start of the line. This doesn't return NULL. */
@@ -875,27 +862,6 @@ get_majority_srv_from_votes(const smartlist_t *votes, int current)
   return the_srv;
 }
 
-/* Encode the given shared random value and put it in dst. Destination
- * buffer must be at least SR_SRV_VALUE_BASE64_LEN plus the NULL byte. */
-void
-sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv)
-{
-  int ret;
-  /* Extra byte for the NULL terminated char. */
-  char buf[SR_SRV_VALUE_BASE64_LEN + 1];
-
-  tor_assert(dst);
-  tor_assert(srv);
-  tor_assert(dst_len >= sizeof(buf));
-
-  ret = base64_encode(buf, sizeof(buf), (const char *) srv->value,
-                      sizeof(srv->value), 0);
-  /* Always expect the full length without the NULL byte. */
-  tor_assert(ret == (sizeof(buf) - 1));
-  tor_assert(ret <= (int) dst_len);
-  strlcpy(dst, buf, dst_len);
-}
-
 /* Free a commit object. */
 void
 sr_commit_free_(sr_commit_t *commit)
@@ -1037,55 +1003,6 @@ sr_compute_srv(void)
   tor_free(reveals);
 }
 
-/* Parse a list of arguments from a SRV value either from a vote, consensus
- * or from our disk state and return a newly allocated srv object. NULL is
- * returned on error.
- *
- * The arguments' order:
- *    num_reveals, value
- */
-sr_srv_t *
-sr_parse_srv(const smartlist_t *args)
-{
-  char *value;
-  int ok, ret;
-  uint64_t num_reveals;
-  sr_srv_t *srv = NULL;
-
-  tor_assert(args);
-
-  if (smartlist_len(args) < 2) {
-    goto end;
-  }
-
-  /* First argument is the number of reveal values */
-  num_reveals = tor_parse_uint64(smartlist_get(args, 0),
-                                 10, 0, UINT64_MAX, &ok, NULL);
-  if (!ok) {
-    goto end;
-  }
-  /* Second and last argument is the shared random value it self. */
-  value = smartlist_get(args, 1);
-  if (strlen(value) != SR_SRV_VALUE_BASE64_LEN) {
-    goto end;
-  }
-
-  srv = tor_malloc_zero(sizeof(*srv));
-  srv->num_reveals = num_reveals;
-  /* We subtract one byte from the srclen because the function ignores the
-   * '=' character in the given buffer. This is broken but it's a documented
-   * behavior of the implementation. */
-  ret = base64_decode((char *) srv->value, sizeof(srv->value), value,
-                      SR_SRV_VALUE_BASE64_LEN - 1);
-  if (ret != sizeof(srv->value)) {
-    tor_free(srv);
-    srv = NULL;
-    goto end;
-  }
- end:
-  return srv;
-}
-
 /* Parse a commit from a vote or from our disk state and return a newly
  * allocated commit object. NULL is returned on error.
  *
@@ -1353,84 +1270,6 @@ sr_save_and_cleanup(void)
   sr_cleanup();
 }
 
-/* Return the current SRV string representation for the control port. Return a
- * newly allocated string on success containing the value else "" if not found
- * or if we don't have a valid consensus yet. */
-char *
-sr_get_current_for_control(void)
-{
-  char *srv_str;
-  const networkstatus_t *c = networkstatus_get_latest_consensus();
-  if (c && c->sr_info.current_srv) {
-    srv_str = srv_to_control_string(c->sr_info.current_srv);
-  } else {
-    srv_str = tor_strdup("");
-  }
-  return srv_str;
-}
-
-/* Return the previous SRV string representation for the control port. Return
- * a newly allocated string on success containing the value else "" if not
- * found or if we don't have a valid consensus yet. */
-char *
-sr_get_previous_for_control(void)
-{
-  char *srv_str;
-  const networkstatus_t *c = networkstatus_get_latest_consensus();
-  if (c && c->sr_info.previous_srv) {
-    srv_str = srv_to_control_string(c->sr_info.previous_srv);
-  } else {
-    srv_str = tor_strdup("");
-  }
-  return srv_str;
-}
-
-/* Return current shared random value from the latest consensus. Caller can
- * NOT keep a reference to the returned pointer. Return NULL if none. */
-const sr_srv_t *
-sr_get_current(const networkstatus_t *ns)
-{
-  const networkstatus_t *consensus;
-
-  /* Use provided ns else get a live one */
-  if (ns) {
-    consensus = ns;
-  } else {
-    consensus = networkstatus_get_live_consensus(approx_time());
-  }
-  /* Ideally we would never be asked for an SRV without a live consensus. Make
-   * sure this assumption is correct. */
-  tor_assert_nonfatal(consensus);
-
-  if (consensus) {
-    return consensus->sr_info.current_srv;
-  }
-  return NULL;
-}
-
-/* Return previous shared random value from the latest consensus. Caller can
- * NOT keep a reference to the returned pointer. Return NULL if none. */
-const sr_srv_t *
-sr_get_previous(const networkstatus_t *ns)
-{
-  const networkstatus_t *consensus;
-
-  /* Use provided ns else get a live one */
-  if (ns) {
-    consensus = ns;
-  } else {
-    consensus = networkstatus_get_live_consensus(approx_time());
-  }
-  /* Ideally we would never be asked for an SRV without a live consensus. Make
-   * sure this assumption is correct. */
-  tor_assert_nonfatal(consensus);
-
-  if (consensus) {
-    return consensus->sr_info.previous_srv;
-  }
-  return NULL;
-}
-
 #ifdef TOR_UNIT_TESTS
 
 /* Set the global value of number of SRV agreements so the test can play
diff --git a/src/or/dirauth/shared_random.h b/src/or/dirauth/shared_random.h
index 675a8d8b0..d1b2ac2e2 100644
--- a/src/or/dirauth/shared_random.h
+++ b/src/or/dirauth/shared_random.h
@@ -109,13 +109,11 @@ void sr_act_post_consensus(const networkstatus_t *consensus);
 void sr_handle_received_commits(smartlist_t *commits,
                                 crypto_pk_t *voter_key);
 sr_commit_t *sr_parse_commit(const smartlist_t *args);
-sr_srv_t *sr_parse_srv(const smartlist_t *args);
 char *sr_get_string_for_vote(void);
 char *sr_get_string_for_consensus(const smartlist_t *votes,
                                   int32_t num_srv_agreements);
 void sr_commit_free_(sr_commit_t *commit);
 #define sr_commit_free(sr) FREE_AND_NULL(sr_commit_t, sr_commit_free_, (sr))
-void sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv);
 
 /* Private methods (only used by shared_random_state.c): */
 static inline
@@ -128,12 +126,6 @@ void sr_compute_srv(void);
 sr_commit_t *sr_generate_our_commit(time_t timestamp,
                                     const authority_cert_t *my_rsa_cert);
 
-char *sr_get_current_for_control(void);
-char *sr_get_previous_for_control(void);
-
-const sr_srv_t *sr_get_current(const networkstatus_t *ns);
-const sr_srv_t *sr_get_previous(const networkstatus_t *ns);
-
 #ifdef SHARED_RANDOM_PRIVATE
 
 /* Encode */
diff --git a/src/or/dirauth/shared_random_state.c b/src/or/dirauth/shared_random_state.c
index 11d7a0637..846c3c7aa 100644
--- a/src/or/dirauth/shared_random_state.c
+++ b/src/or/dirauth/shared_random_state.c
@@ -17,6 +17,7 @@
 #include "networkstatus.h"
 #include "router.h"
 #include "shared_random_state.h"
+#include "shared_random_common.h"
 
 #include "dirauth/dirvote.h"
 
@@ -54,10 +55,6 @@ DUMMY_TYPECHECK_INSTANCE(sr_disk_state_t);
   VAR(#member, conftype, member, initvalue)
 /* Our persistent state magic number. */
 #define SR_DISK_STATE_MAGIC 0x98AB1254
-/* Each protocol phase has 12 rounds  */
-#define SHARED_RANDOM_N_ROUNDS 12
-/* Number of phase we have in a protocol. */
-#define SHARED_RANDOM_N_PHASES 2
 
 static int
 disk_state_validate_cb(void *old_state, void *state, void *default_state,
@@ -116,81 +113,6 @@ get_phase_str(sr_phase_t phase)
 
   return the_string;
 }
-
-/* Return the voting interval of the tor vote subsystem. */
-static int
-get_voting_interval(void)
-{
-  int interval;
-  networkstatus_t *consensus = networkstatus_get_live_consensus(time(NULL));
-
-  if (consensus) {
-    interval = (int)(consensus->fresh_until - consensus->valid_after);
-  } else {
-    /* Same for both a testing and real network. We voluntarily ignore the
-     * InitialVotingInterval since it complexifies things and it doesn't
-     * affect the SR protocol. */
-    interval = get_options()->V3AuthVotingInterval;
-  }
-  tor_assert(interval > 0);
-  return interval;
-}
-
-/* Given the time <b>now</b>, return the start time of the current round of
- * the SR protocol. For example, if it's 23:47:08, the current round thus
- * started at 23:47:00 for a voting interval of 10 seconds. */
-STATIC time_t
-get_start_time_of_current_round(void)
-{
-  const or_options_t *options = get_options();
-  int voting_interval = get_voting_interval();
-  /* First, get the start time of the next round */
-  time_t next_start = dirvote_get_next_valid_after_time();
-  /* Now roll back next_start by a voting interval to find the start time of
-     the current round. */
-  time_t curr_start = dirvote_get_start_of_next_interval(
-                                     next_start - voting_interval - 1,
-                                     voting_interval,
-                                     options->TestingV3AuthVotingStartOffset);
-  return curr_start;
-}
-
-/** Return the start time of the current SR protocol run. For example, if the
- *  time is 23/06/2017 23:47:08 and a full SR protocol run is 24 hours, this
- *  function should return 23/06/2017 00:00:00. */
-time_t
-sr_state_get_start_time_of_current_protocol_run(time_t now)
-{
-  int total_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
-  int voting_interval = get_voting_interval();
-  /* Find the time the current round started. */
-  time_t beginning_of_current_round = get_start_time_of_current_round();
-
-  /* Get current SR protocol round */
-  int current_round = (now / voting_interval) % total_rounds;
-
-  /* Get start time by subtracting the time elapsed from the beginning of the
-     protocol run */
-  time_t time_elapsed_since_start_of_run = current_round * voting_interval;
-  return beginning_of_current_round - time_elapsed_since_start_of_run;
-}
-
-/** Return the time (in seconds) it takes to complete a full SR protocol phase
- *  (e.g. the commit phase). */
-unsigned int
-sr_state_get_phase_duration(void)
-{
-  return SHARED_RANDOM_N_ROUNDS * get_voting_interval();
-}
-
-/** Return the time (in seconds) it takes to complete a full SR protocol run */
-unsigned int
-sr_state_get_protocol_run_duration(void)
-{
-  int total_protocol_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
-  return total_protocol_rounds * get_voting_interval();
-}
-
 /* Return the time we should expire the state file created at <b>now</b>.
  * We expire the state file in the beginning of the next protocol run. */
 STATIC time_t
diff --git a/src/or/dirauth/shared_random_state.h b/src/or/dirauth/shared_random_state.h
index fdbbf4919..60a326f86 100644
--- a/src/or/dirauth/shared_random_state.h
+++ b/src/or/dirauth/shared_random_state.h
@@ -121,16 +121,11 @@ int sr_state_is_initialized(void);
 void sr_state_save(void);
 void sr_state_free_all(void);
 
-time_t sr_state_get_start_time_of_current_protocol_run(time_t now);
-unsigned int sr_state_get_phase_duration(void);
-unsigned int sr_state_get_protocol_run_duration(void);
-
 #ifdef SHARED_RANDOM_STATE_PRIVATE
 
 STATIC int disk_state_load_from_disk_impl(const char *fname);
 
 STATIC sr_phase_t get_sr_protocol_phase(time_t valid_after);
-STATIC time_t get_start_time_of_current_round(void);
 
 STATIC time_t get_state_valid_until_time(time_t now);
 STATIC const char *get_phase_str(sr_phase_t phase);
diff --git a/src/or/hs_common.c b/src/or/hs_common.c
index fc7bc5729..8cc7d0891 100644
--- a/src/or/hs_common.c
+++ b/src/or/hs_common.c
@@ -28,7 +28,7 @@
 #include "rendservice.h"
 #include "routerset.h"
 #include "router.h"
-#include "dirauth/shared_random.h"
+#include "shared_random_common.h"
 #include "dirauth/shared_random_state.h"
 
 /* Trunnel */
diff --git a/src/or/hs_service.c b/src/or/hs_service.c
index ebb58f7f6..4ac0df2ad 100644
--- a/src/or/hs_service.c
+++ b/src/or/hs_service.c
@@ -24,7 +24,7 @@
 #include "router.h"
 #include "routerkeys.h"
 #include "routerlist.h"
-#include "dirauth/shared_random_state.h"
+#include "shared_random_common.h"
 #include "statefile.h"
 
 #include "hs_circuit.h"
diff --git a/src/or/include.am b/src/or/include.am
index 9265ecf48..e90b1fb2a 100644
--- a/src/or/include.am
+++ b/src/or/include.am
@@ -103,6 +103,7 @@ LIBTOR_A_SOURCES = \
 	src/or/scheduler.c				\
 	src/or/scheduler_kist.c				\
 	src/or/scheduler_vanilla.c			\
+	src/or/shared_random_common.c			\
 	src/or/statefile.c				\
 	src/or/status.c					\
 	src/or/torcert.c				\
@@ -260,6 +261,7 @@ ORHEADERS = \
 	src/or/routerset.h				\
 	src/or/routerparse.h				\
 	src/or/scheduler.h				\
+	src/or/shared_random_common.h			\
 	src/or/statefile.h				\
 	src/or/status.h					\
 	src/or/torcert.h				\
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 84db23915..2d64a82b6 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -74,6 +74,7 @@
 #include "entrynodes.h"
 #include "torcert.h"
 #include "sandbox.h"
+#include "shared_random_common.h"
 #include "dirauth/shared_random.h"
 
 #undef log
diff --git a/src/or/shared_random_common.c b/src/or/shared_random_common.c
new file mode 100644
index 000000000..c782e709f
--- /dev/null
+++ b/src/or/shared_random_common.c
@@ -0,0 +1,258 @@
+/* Copyright (c) 2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file shared_random_common.c
+ * \brief This file contains functions that are from the shared random
+ *        subsystem but used by many part of tor. The full feature is built
+ *        as part of the dirauth module.
+ **/
+
+#define SHARED_RANDOM_COMMON_PRIVATE
+#include "shared_random_common.h"
+
+#include "config.h"
+#include "networkstatus.h"
+#include "util.h"
+#include "util_format.h"
+
+/* Convert a given srv object to a string for the control port. This doesn't
+ * fail and the srv object MUST be valid. */
+static char *
+srv_to_control_string(const sr_srv_t *srv)
+{
+  char *srv_str;
+  char srv_hash_encoded[SR_SRV_VALUE_BASE64_LEN + 1];
+  tor_assert(srv);
+
+  sr_srv_encode(srv_hash_encoded, sizeof(srv_hash_encoded), srv);
+  tor_asprintf(&srv_str, "%s", srv_hash_encoded);
+  return srv_str;
+}
+
+/* Return the voting interval of the tor vote subsystem. */
+int
+get_voting_interval(void)
+{
+  int interval;
+  networkstatus_t *consensus = networkstatus_get_live_consensus(time(NULL));
+
+  if (consensus) {
+    interval = (int)(consensus->fresh_until - consensus->valid_after);
+  } else {
+    /* Same for both a testing and real network. We voluntarily ignore the
+     * InitialVotingInterval since it complexifies things and it doesn't
+     * affect the SR protocol. */
+    interval = get_options()->V3AuthVotingInterval;
+  }
+  tor_assert(interval > 0);
+  return interval;
+}
+
+/* Given the time <b>now</b>, return the start time of the current round of
+ * the SR protocol. For example, if it's 23:47:08, the current round thus
+ * started at 23:47:00 for a voting interval of 10 seconds. */
+time_t
+get_start_time_of_current_round(void)
+{
+  const or_options_t *options = get_options();
+  int voting_interval = get_voting_interval();
+  /* First, get the start time of the next round */
+  time_t next_start = dirvote_get_next_valid_after_time();
+  /* Now roll back next_start by a voting interval to find the start time of
+     the current round. */
+  time_t curr_start = dirvote_get_start_of_next_interval(
+                                     next_start - voting_interval - 1,
+                                     voting_interval,
+                                     options->TestingV3AuthVotingStartOffset);
+  return curr_start;
+}
+
+/*
+ * Public API
+ */
+
+/* Encode the given shared random value and put it in dst. Destination
+ * buffer must be at least SR_SRV_VALUE_BASE64_LEN plus the NULL byte. */
+void
+sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv)
+{
+  int ret;
+  /* Extra byte for the NULL terminated char. */
+  char buf[SR_SRV_VALUE_BASE64_LEN + 1];
+
+  tor_assert(dst);
+  tor_assert(srv);
+  tor_assert(dst_len >= sizeof(buf));
+
+  ret = base64_encode(buf, sizeof(buf), (const char *) srv->value,
+                      sizeof(srv->value), 0);
+  /* Always expect the full length without the NULL byte. */
+  tor_assert(ret == (sizeof(buf) - 1));
+  tor_assert(ret <= (int) dst_len);
+  strlcpy(dst, buf, dst_len);
+}
+
+/* Return the current SRV string representation for the control port. Return a
+ * newly allocated string on success containing the value else "" if not found
+ * or if we don't have a valid consensus yet. */
+char *
+sr_get_current_for_control(void)
+{
+  char *srv_str;
+  const networkstatus_t *c = networkstatus_get_latest_consensus();
+  if (c && c->sr_info.current_srv) {
+    srv_str = srv_to_control_string(c->sr_info.current_srv);
+  } else {
+    srv_str = tor_strdup("");
+  }
+  return srv_str;
+}
+
+/* Return the previous SRV string representation for the control port. Return
+ * a newly allocated string on success containing the value else "" if not
+ * found or if we don't have a valid consensus yet. */
+char *
+sr_get_previous_for_control(void)
+{
+  char *srv_str;
+  const networkstatus_t *c = networkstatus_get_latest_consensus();
+  if (c && c->sr_info.previous_srv) {
+    srv_str = srv_to_control_string(c->sr_info.previous_srv);
+  } else {
+    srv_str = tor_strdup("");
+  }
+  return srv_str;
+}
+
+/* Return current shared random value from the latest consensus. Caller can
+ * NOT keep a reference to the returned pointer. Return NULL if none. */
+const sr_srv_t *
+sr_get_current(const networkstatus_t *ns)
+{
+  const networkstatus_t *consensus;
+
+  /* Use provided ns else get a live one */
+  if (ns) {
+    consensus = ns;
+  } else {
+    consensus = networkstatus_get_live_consensus(approx_time());
+  }
+  /* Ideally we would never be asked for an SRV without a live consensus. Make
+   * sure this assumption is correct. */
+  tor_assert_nonfatal(consensus);
+
+  if (consensus) {
+    return consensus->sr_info.current_srv;
+  }
+  return NULL;
+}
+
+/* Return previous shared random value from the latest consensus. Caller can
+ * NOT keep a reference to the returned pointer. Return NULL if none. */
+const sr_srv_t *
+sr_get_previous(const networkstatus_t *ns)
+{
+  const networkstatus_t *consensus;
+
+  /* Use provided ns else get a live one */
+  if (ns) {
+    consensus = ns;
+  } else {
+    consensus = networkstatus_get_live_consensus(approx_time());
+  }
+  /* Ideally we would never be asked for an SRV without a live consensus. Make
+   * sure this assumption is correct. */
+  tor_assert_nonfatal(consensus);
+
+  if (consensus) {
+    return consensus->sr_info.previous_srv;
+  }
+  return NULL;
+}
+
+/* Parse a list of arguments from a SRV value either from a vote, consensus
+ * or from our disk state and return a newly allocated srv object. NULL is
+ * returned on error.
+ *
+ * The arguments' order:
+ *    num_reveals, value
+ */
+sr_srv_t *
+sr_parse_srv(const smartlist_t *args)
+{
+  char *value;
+  int ok, ret;
+  uint64_t num_reveals;
+  sr_srv_t *srv = NULL;
+
+  tor_assert(args);
+
+  if (smartlist_len(args) < 2) {
+    goto end;
+  }
+
+  /* First argument is the number of reveal values */
+  num_reveals = tor_parse_uint64(smartlist_get(args, 0),
+                                 10, 0, UINT64_MAX, &ok, NULL);
+  if (!ok) {
+    goto end;
+  }
+  /* Second and last argument is the shared random value it self. */
+  value = smartlist_get(args, 1);
+  if (strlen(value) != SR_SRV_VALUE_BASE64_LEN) {
+    goto end;
+  }
+
+  srv = tor_malloc_zero(sizeof(*srv));
+  srv->num_reveals = num_reveals;
+  /* We subtract one byte from the srclen because the function ignores the
+   * '=' character in the given buffer. This is broken but it's a documented
+   * behavior of the implementation. */
+  ret = base64_decode((char *) srv->value, sizeof(srv->value), value,
+                      SR_SRV_VALUE_BASE64_LEN - 1);
+  if (ret != sizeof(srv->value)) {
+    tor_free(srv);
+    srv = NULL;
+    goto end;
+  }
+ end:
+  return srv;
+}
+
+/** Return the start time of the current SR protocol run. For example, if the
+ *  time is 23/06/2017 23:47:08 and a full SR protocol run is 24 hours, this
+ *  function should return 23/06/2017 00:00:00. */
+time_t
+sr_state_get_start_time_of_current_protocol_run(time_t now)
+{
+  int total_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
+  int voting_interval = get_voting_interval();
+  /* Find the time the current round started. */
+  time_t beginning_of_current_round = get_start_time_of_current_round();
+
+  /* Get current SR protocol round */
+  int current_round = (now / voting_interval) % total_rounds;
+
+  /* Get start time by subtracting the time elapsed from the beginning of the
+     protocol run */
+  time_t time_elapsed_since_start_of_run = current_round * voting_interval;
+  return beginning_of_current_round - time_elapsed_since_start_of_run;
+}
+
+/** Return the time (in seconds) it takes to complete a full SR protocol phase
+ *  (e.g. the commit phase). */
+unsigned int
+sr_state_get_phase_duration(void)
+{
+  return SHARED_RANDOM_N_ROUNDS * get_voting_interval();
+}
+
+/** Return the time (in seconds) it takes to complete a full SR protocol run */
+unsigned int
+sr_state_get_protocol_run_duration(void)
+{
+  int total_protocol_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
+  return total_protocol_rounds * get_voting_interval();
+}
+
diff --git a/src/or/shared_random_common.h b/src/or/shared_random_common.h
new file mode 100644
index 000000000..35e08ddf3
--- /dev/null
+++ b/src/or/shared_random_common.h
@@ -0,0 +1,47 @@
+/* Copyright (c) 2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file shared_random_common.h
+ * \brief Header file for shared_random_common.c.
+ **/
+
+#ifndef TOR_SHARED_RANDOM_COMMON_H
+#define TOR_SHARED_RANDOM_COMMON_H
+
+/* Dirauth module. */
+#include "dirauth/shared_random.h"
+
+/* Helper functions. */
+void sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv);
+int get_voting_interval(void);
+
+/* Control port functions. */
+char *sr_get_current_for_control(void);
+char *sr_get_previous_for_control(void);
+
+/* SRV functions. */
+const sr_srv_t *sr_get_current(const networkstatus_t *ns);
+const sr_srv_t *sr_get_previous(const networkstatus_t *ns);
+sr_srv_t *sr_parse_srv(const smartlist_t *args);
+
+/*
+ * Shared Random State API
+ */
+
+/* Each protocol phase has 12 rounds  */
+#define SHARED_RANDOM_N_ROUNDS 12
+/* Number of phase we have in a protocol. */
+#define SHARED_RANDOM_N_PHASES 2
+
+time_t sr_state_get_start_time_of_current_protocol_run(time_t now);
+unsigned int sr_state_get_phase_duration(void);
+unsigned int sr_state_get_protocol_run_duration(void);
+time_t get_start_time_of_current_round(void);
+
+#ifdef TOR_UNIT_TESTS
+
+#endif /* TOR_UNIT_TESTS */
+
+#endif /* TOR_SHARED_RANDOM_COMMON_H */
+





More information about the tor-commits mailing list