diff --git a/changes/ticket32806 b/changes/ticket32806
new file mode 100644
index 0000000000000000000000000000000000000000..357e281d364147afbc6ec024e53a849596ae4550
--- /dev/null
+++ b/changes/ticket32806
@@ -0,0 +1,3 @@
+  o Code simplification and refactoring:
+    - Use our new configuration architecture to move most authority-related
+      options to the directory authority module. Closes ticket 32806.
diff --git a/src/app/config/config.c b/src/app/config/config.c
index 2863c34b0e4595e8bb8796ab38dac13370a9dc33..bc65977b20a9aaef96300ab46753f2b6d0abf1a7 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -329,16 +329,11 @@ static const config_var_t option_vars_[] = {
   V(AuthDirBadExitCCs,           CSV,      ""),
   V(AuthDirInvalid,              LINELIST, NULL),
   V(AuthDirInvalidCCs,           CSV,      ""),
-  V(AuthDirFastGuarantee,        MEMUNIT,  "100 KB"),
-  V(AuthDirGuardBWGuarantee,     MEMUNIT,  "2 MB"),
-  V(AuthDirPinKeys,              BOOL,     "1"),
   V(AuthDirReject,               LINELIST, NULL),
   V(AuthDirRejectCCs,            CSV,      ""),
   OBSOLETE("AuthDirRejectUnlisted"),
   OBSOLETE("AuthDirListBadDirs"),
-  V(AuthDirListBadExits,         BOOL,     "0"),
   OBSOLETE("AuthDirMaxServersPerAuthAddr"),
-  V(AuthDirHasIPv6Connectivity,  BOOL,     "0"),
   VAR("AuthoritativeDirectory",  BOOL, AuthoritativeDir,    "0"),
   V(AutomapHostsOnResolve,       BOOL,     "0"),
   V(AutomapHostsSuffixes,        CSV,      ".onion,.exit"),
@@ -376,7 +371,6 @@ static const config_var_t option_vars_[] = {
   V(ClientTransportPlugin,       LINELIST, NULL),
   V(ClientUseIPv6,               BOOL,     "0"),
   V(ClientUseIPv4,               BOOL,     "1"),
-  V(ConsensusParams,             STRING,   NULL),
   V(ConnLimit,                   POSINT,     "1000"),
   V(ConnDirectionStatistics,     BOOL,     "0"),
   V(ConstrainedSockets,          BOOL,     "0"),
@@ -398,7 +392,6 @@ static const config_var_t option_vars_[] = {
   V(DisableOOSCheck,             BOOL,     "1"),
   V(DisableNetwork,              BOOL,     "0"),
   V(DirAllowPrivateAddresses,    BOOL,     "0"),
-  V(TestingAuthDirTimeToLearnReachability, INTERVAL, "30 minutes"),
   OBSOLETE("DirListenAddress"),
   V(DirPolicy,                   LINELIST, NULL),
   VPORT(DirPort),
@@ -562,7 +555,6 @@ static const config_var_t option_vars_[] = {
   OBSOLETE("MaxOnionsPending"),
   V(MaxOnionQueueDelay,          MSEC_INTERVAL, "1750 msec"),
   V(MaxUnparseableDescSizeToLog, MEMUNIT, "10 MB"),
-  V(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, "500"),
   VAR("MyFamily",                LINELIST, MyFamily_lines,       NULL),
   V(NewCircuitPeriod,            INTERVAL, "30 seconds"),
   OBSOLETE("NamingAuthoritativeDirectory"),
@@ -605,8 +597,6 @@ static const config_var_t option_vars_[] = {
   V(PerConnBWRate,               MEMUNIT,  "0"),
   V_IMMUTABLE(PidFile,           FILENAME,   NULL),
   V_IMMUTABLE(TestingTorNetwork, BOOL,     "0"),
-  V(TestingMinExitFlagThreshold, MEMUNIT,  "0"),
-  V(TestingMinFastFlagThreshold, MEMUNIT,  "0"),
 
   V(TestingLinkCertLifetime,          INTERVAL, "2 days"),
   V(TestingAuthKeyLifetime,          INTERVAL, "2 days"),
@@ -624,9 +614,6 @@ static const config_var_t option_vars_[] = {
   V(ReachableAddresses,          LINELIST, NULL),
   V(ReachableDirAddresses,       LINELIST, NULL),
   V(ReachableORAddresses,        LINELIST, NULL),
-  V(RecommendedVersions,         LINELIST, NULL),
-  V(RecommendedClientVersions,   LINELIST, NULL),
-  V(RecommendedServerVersions,   LINELIST, NULL),
   OBSOLETE("RecommendedPackages"),
   V(ReducedConnectionPadding,    BOOL,     "0"),
   V(ConnectionPadding,           AUTOBOOL, "auto"),
@@ -688,8 +675,6 @@ static const config_var_t option_vars_[] = {
   OBSOLETE("UseNTorHandshake"),
   V_IMMUTABLE(User,              STRING,   NULL),
   OBSOLETE("UserspaceIOCPBuffers"),
-  V(AuthDirSharedRandomness,     BOOL,     "1"),
-  V(AuthDirTestEd25519LinkKeys,  BOOL,     "1"),
   OBSOLETE("V1AuthoritativeDirectory"),
   OBSOLETE("V2AuthoritativeDirectory"),
   VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir,   "0"),
@@ -704,7 +689,6 @@ static const config_var_t option_vars_[] = {
   V(V3AuthUseLegacyKey,          BOOL,     "0"),
   V(V3BandwidthsFile,            FILENAME, NULL),
   V(GuardfractionFile,           FILENAME, NULL),
-  VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"),
   OBSOLETE("VoteOnHidServDirectoriesV2"),
   V(VirtualAddrNetworkIPv4,      STRING,   "127.192.0.0/10"),
   V(VirtualAddrNetworkIPv6,      STRING,   "[FE80::]/10"),
@@ -724,7 +708,6 @@ static const config_var_t option_vars_[] = {
                        OwningControllerProcess, NULL),
   VAR_NODUMP_IMMUTABLE("__OwningControllerFD", UINT64, OwningControllerFD,
              UINT64_MAX_STRING),
-  V(MinUptimeHidServDirectoryV2, INTERVAL, "96 hours"),
   V(TestingServerDownloadInitialDelay, CSV_INTERVAL, "0"),
   V(TestingClientDownloadInitialDelay, CSV_INTERVAL, "0"),
   V(TestingServerConsensusDownloadInitialDelay, CSV_INTERVAL, "0"),
@@ -770,12 +753,6 @@ static const config_var_t option_vars_[] = {
   OBSOLETE("TestingDescriptorMaxDownloadTries"),
   OBSOLETE("TestingMicrodescMaxDownloadTries"),
   OBSOLETE("TestingCertMaxDownloadTries"),
-  V_D(TestingDirAuthVoteExit, ROUTERSET, NULL),
-  V(TestingDirAuthVoteExitIsStrict,  BOOL,     "0"),
-  V_D(TestingDirAuthVoteGuard, ROUTERSET, NULL),
-  V(TestingDirAuthVoteGuardIsStrict,  BOOL,     "0"),
-  V_D(TestingDirAuthVoteHSDir, ROUTERSET, NULL),
-  V(TestingDirAuthVoteHSDirIsStrict,  BOOL,     "0"),
   VAR_INVIS("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_,
             "0"),
 
@@ -3889,8 +3866,6 @@ options_validate_cb(const void *old_options_, void *options_, char **msg)
 
   if (options_validate_relay_bandwidth(old_options, options, msg) < 0)
     return -1;
-  if (options_validate_dirauth_bandwidth(old_options, options, msg) < 0)
-    return -1;
 
   if (options->BandwidthRate > options->BandwidthBurst)
     REJECT("BandwidthBurst must be at least equal to BandwidthRate.");
diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h
index 2733bf775c7d7798c435805067c5f9f37c78521f..35ba15a9e2195626115950c4725778f55ffd53fe 100644
--- a/src/app/config/or_options_st.h
+++ b/src/app/config/or_options_st.h
@@ -122,11 +122,6 @@ struct or_options_t {
    * [][0] is IPv4, [][1] is IPv6
    */
   tor_addr_t OutboundBindAddresses[OUTBOUND_ADDR_MAX][2];
-  /** Directory server only: which versions of
-   * Tor should we tell users to run? */
-  struct config_line_t *RecommendedVersions;
-  struct config_line_t *RecommendedClientVersions;
-  struct config_line_t *RecommendedServerVersions;
   /** Whether dirservers allow router descriptors with private IPs. */
   int DirAllowPrivateAddresses;
   /** Whether routers accept EXTEND cells to routers with private IPs. */
@@ -201,9 +196,6 @@ struct or_options_t {
   int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
   int V3AuthoritativeDir; /**< Boolean: is this an authoritative directory
                            * for version 3 directories? */
-  int VersioningAuthoritativeDir; /**< Boolean: is this an authoritative
-                                   * directory that's willing to recommend
-                                   * versions? */
   int BridgeAuthoritativeDir; /**< Boolean: is this an authoritative directory
                                * that aggregates bridge descriptors? */
 
@@ -274,9 +266,6 @@ struct or_options_t {
   int FetchServerDescriptors; /**< Do we fetch server descriptors as normal? */
   int FetchHidServDescriptors; /**< and hidden service descriptors? */
 
-  int MinUptimeHidServDirectoryV2; /**< As directory authority, accept hidden
-                                    * service directories after what time? */
-
   int FetchUselessDescriptors; /**< Do we fetch non-running descriptors too? */
   int AllDirActionsPrivate; /**< Should every directory action be sent
                              * through a Tor circuit? */
@@ -479,19 +468,6 @@ struct or_options_t {
   struct smartlist_t *AuthDirRejectCCs;
   /**@}*/
 
-  int AuthDirListBadExits; /**< True iff we should list bad exits,
-                            * and vote for all other exits as good. */
-  int AuthDirHasIPv6Connectivity; /**< Boolean: are we on IPv6?  */
-  int AuthDirPinKeys; /**< Boolean: Do we enforce key-pinning? */
-
-  /** If non-zero, always vote the Fast flag for any relay advertising
-   * this amount of capacity or more. */
-  uint64_t AuthDirFastGuarantee;
-
-  /** If non-zero, this advertised capacity or more is always sufficient
-   * to satisfy the bandwidth requirement for the Guard flag. */
-  uint64_t AuthDirGuardBWGuarantee;
-
   char *AccountingStart; /**< How long is the accounting interval, and when
                           * does it start? */
   uint64_t AccountingMax; /**< How many bytes do we allow per accounting
@@ -708,14 +684,6 @@ struct or_options_t {
   /** Location of guardfraction file */
   char *GuardfractionFile;
 
-  /** Authority only: key=value pairs that we add to our networkstatus
-   * consensus vote on the 'params' line. */
-  char *ConsensusParams;
-
-  /** Authority only: minimum number of measured bandwidths we must see
-   * before we only believe measured bandwidths to assign flags. */
-  int MinMeasuredBWsForAuthToIgnoreAdvertised;
-
   /** The length of time that we think an initial consensus should be fresh.
    * Only altered on testing networks. */
   int TestingV3AuthInitialVotingInterval;
@@ -732,11 +700,6 @@ struct or_options_t {
       voting. Only altered on testing networks. */
   int TestingV3AuthVotingStartOffset;
 
-  /** If an authority has been around for less than this amount of time, it
-   * does not believe its reachability information is accurate.  Only
-   * altered on testing networks. */
-  int TestingAuthDirTimeToLearnReachability;
-
   /** Schedule for when servers should download things in general.  Only
    * altered on testing networks. */
   int TestingServerDownloadInitialDelay;
@@ -810,27 +773,6 @@ struct or_options_t {
    * of certain configuration options. */
   int TestingTorNetwork;
 
-  /** Minimum value for the Exit flag threshold on testing networks. */
-  uint64_t TestingMinExitFlagThreshold;
-
-  /** Minimum value for the Fast flag threshold on testing networks. */
-  uint64_t TestingMinFastFlagThreshold;
-
-  /** Relays in a testing network which should be voted Exit
-   * regardless of exit policy. */
-  struct routerset_t *TestingDirAuthVoteExit;
-  int TestingDirAuthVoteExitIsStrict;
-
-  /** Relays in a testing network which should be voted Guard
-   * regardless of uptime and bandwidth. */
-  struct routerset_t *TestingDirAuthVoteGuard;
-  int TestingDirAuthVoteGuardIsStrict;
-
-  /** Relays in a testing network which should be voted HSDir
-   * regardless of uptime and DirPort. */
-  struct routerset_t *TestingDirAuthVoteHSDir;
-  int TestingDirAuthVoteHSDirIsStrict;
-
   /** Enable CONN_BW events.  Only altered on testing networks. */
   int TestingEnableConnBwEvent;
 
@@ -1009,12 +951,6 @@ struct or_options_t {
    */
   uint64_t MaxUnparseableDescSizeToLog;
 
-  /** Bool (default: 1): Switch for the shared random protocol. Only
-   * relevant to a directory authority. If off, the authority won't
-   * participate in the protocol. If on (default), a flag is added to the
-   * vote indicating participation. */
-  int AuthDirSharedRandomness;
-
   /** If 1, we skip all OOS checks. */
   int DisableOOSCheck;
 
@@ -1022,11 +958,6 @@ struct or_options_t {
    * If -1, we should do whatever the consensus parameter says. */
   int ExtendByEd25519ID;
 
-  /** Bool (default: 1): When testing routerinfos as a directory authority,
-   * do we enforce Ed25519 identity match? */
-  /* NOTE: remove this option someday. */
-  int AuthDirTestEd25519LinkKeys;
-
   /** Bool (default: 0): Tells if a %include was used on torrc */
   int IncludeUsed;
 
diff --git a/src/feature/dirauth/bwauth.c b/src/feature/dirauth/bwauth.c
index a89cfc463c52476e38525cb9dee998d1ab67f34d..ff0c78f0182a4b68c66744820774cc076557f594 100644
--- a/src/feature/dirauth/bwauth.c
+++ b/src/feature/dirauth/bwauth.c
@@ -13,10 +13,12 @@
 #include "feature/dirauth/bwauth.h"
 
 #include "app/config/config.h"
+#include "feature/dirauth/dirauth_sys.h"
 #include "feature/nodelist/networkstatus.h"
 #include "feature/nodelist/routerlist.h"
 #include "feature/dirparse/ns_parse.h"
 
+#include "feature/dirauth/dirauth_options_st.h"
 #include "feature/nodelist/routerinfo_st.h"
 #include "feature/nodelist/vote_routerstatus_st.h"
 
@@ -182,7 +184,7 @@ dirserv_get_credible_bandwidth_kb(const routerinfo_t *ri)
   /* Check if we have a measured bandwidth, and check the threshold if not */
   if (!(dirserv_query_measured_bw_cache_kb(ri->cache_info.identity_digest,
                                        &mbw_kb, NULL))) {
-    threshold = get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
+    threshold = dirauth_get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
     if (routers_with_measured_bw > threshold) {
       /* Return zero for unmeasured bandwidth if we are above threshold */
       bw_kb = 0;
diff --git a/src/feature/dirauth/dirauth_config.c b/src/feature/dirauth/dirauth_config.c
index 6d2478f0026d4ca1409f18b34d6a117946d321f6..3aeeab3b310ca232c792964a5aa5dd55436ff88d 100644
--- a/src/feature/dirauth/dirauth_config.c
+++ b/src/feature/dirauth/dirauth_config.c
@@ -73,24 +73,6 @@ options_validate_dirauth_mode(const or_options_t *old_options,
 
   if (!options->ContactInfo && !options->TestingTorNetwork)
     REJECT("Authoritative directory servers must set ContactInfo");
-  if (!options->RecommendedClientVersions)
-    options->RecommendedClientVersions =
-      config_lines_dup(options->RecommendedVersions);
-  if (!options->RecommendedServerVersions)
-    options->RecommendedServerVersions =
-      config_lines_dup(options->RecommendedVersions);
-  if (options->VersioningAuthoritativeDir &&
-      (!options->RecommendedClientVersions ||
-       !options->RecommendedServerVersions))
-    REJECT("Versioning authoritative dir servers must set "
-           "Recommended*Versions.");
-
-  char *t;
-  /* Call these functions to produce warnings only. */
-  t = format_recommended_version_list(options->RecommendedClientVersions, 1);
-  tor_free(t);
-  t = format_recommended_version_list(options->RecommendedServerVersions, 1);
-  tor_free(t);
 
   if (options->UseEntryGuards) {
     log_info(LD_CONFIG, "Authoritative directory servers can't set "
@@ -126,45 +108,6 @@ options_validate_dirauth_mode(const or_options_t *old_options,
   if (options->ClientOnly)
     REJECT("Running as authoritative directory, but ClientOnly also set.");
 
-  if (options->MinUptimeHidServDirectoryV2 < 0) {
-    log_warn(LD_CONFIG, "MinUptimeHidServDirectoryV2 option must be at "
-             "least 0 seconds. Changing to 0.");
-    options->MinUptimeHidServDirectoryV2 = 0;
-  }
-
-  return 0;
-}
-
-/**
- * Legacy validation/normalization function for the dirauth bandwidth options
- * in options. Uses old_options as the previous options.
- *
- * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
- * on error.
- */
-int
-options_validate_dirauth_bandwidth(const or_options_t *old_options,
-                                   or_options_t *options,
-                                   char **msg)
-{
-  (void)old_options;
-
-  if (BUG(!options))
-    return -1;
-
-  if (BUG(!msg))
-    return -1;
-
-  if (!authdir_mode(options))
-    return 0;
-
-  if (config_ensure_bandwidth_cap(&options->AuthDirFastGuarantee,
-                           "AuthDirFastGuarantee", msg) < 0)
-    return -1;
-  if (config_ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee,
-                           "AuthDirGuardBWGuarantee", msg) < 0)
-    return -1;
-
   return 0;
 }
 
@@ -270,12 +213,6 @@ options_validate_dirauth_testing(const or_options_t *old_options,
   if (!authdir_mode(options))
     return 0;
 
-  if (options->TestingAuthDirTimeToLearnReachability < 0) {
-    REJECT("TestingAuthDirTimeToLearnReachability must be non-negative.");
-  } else if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) {
-    COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high.");
-  }
-
   if (!authdir_mode_v3(options))
     return 0;
 
@@ -441,6 +378,66 @@ options_act_dirauth_stats(const or_options_t *old_options,
   return 0;
 }
 
+/**
+ * Make any necessary modifications to a dirauth_options_t that occur
+ * before validation.  On success return 0; on failure return -1 and
+ * set *<b>msg_out</b> to a newly allocated error string.
+ **/
+static int
+dirauth_options_pre_normalize(void *arg, char **msg_out)
+{
+  dirauth_options_t *options = arg;
+  (void)msg_out;
+
+  if (!options->RecommendedClientVersions)
+    options->RecommendedClientVersions =
+      config_lines_dup(options->RecommendedVersions);
+  if (!options->RecommendedServerVersions)
+    options->RecommendedServerVersions =
+      config_lines_dup(options->RecommendedVersions);
+
+  if (config_ensure_bandwidth_cap(&options->AuthDirFastGuarantee,
+                           "AuthDirFastGuarantee", msg_out) < 0)
+    return -1;
+  if (config_ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee,
+                                  "AuthDirGuardBWGuarantee", msg_out) < 0)
+    return -1;
+
+  return 0;
+}
+
+/**
+ * Check whether a dirauth_options_t is correct.
+ *
+ * On success return 0; on failure return -1 and set *<b>msg_out</b> to a
+ * newly allocated error string.
+ **/
+static int
+dirauth_options_validate(const void *arg, char **msg)
+{
+  const dirauth_options_t *options = arg;
+
+  if (options->VersioningAuthoritativeDirectory &&
+      (!options->RecommendedClientVersions ||
+       !options->RecommendedServerVersions)) {
+      REJECT("Versioning authoritative dir servers must set "
+           "Recommended*Versions.");
+  }
+
+  char *t;
+  /* Call these functions to produce warnings only. */
+  t = format_recommended_version_list(options->RecommendedClientVersions, 1);
+  tor_free(t);
+  t = format_recommended_version_list(options->RecommendedServerVersions, 1);
+  tor_free(t);
+
+  if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) {
+    COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high.");
+  }
+
+  return 0;
+}
+
 /* Declare the options field table for dirauth_options */
 #define CONF_CONTEXT TABLE
 #include "feature/dirauth/dirauth_options.inc"
@@ -458,5 +455,7 @@ const config_format_t dirauth_options_fmt = {
              DIRAUTH_OPTIONS_MAGIC,
              offsetof(dirauth_options_t, magic) },
   .vars = dirauth_options_t_vars,
-};
 
+  .pre_normalize_fn = dirauth_options_pre_normalize,
+  .validate_fn = dirauth_options_validate
+};
diff --git a/src/feature/dirauth/dirauth_config.h b/src/feature/dirauth/dirauth_config.h
index a69a56bfcf3543dfb416ff582136d5676ea8cef9..2ebafd917e708221543be429575f8f77109dece1 100644
--- a/src/feature/dirauth/dirauth_config.h
+++ b/src/feature/dirauth/dirauth_config.h
@@ -22,10 +22,6 @@ int options_validate_dirauth_mode(const struct or_options_t *old_options,
                                   struct or_options_t *options,
                                   char **msg);
 
-int options_validate_dirauth_bandwidth(const struct or_options_t *old_options,
-                                       struct or_options_t *options,
-                                       char **msg);
-
 int options_validate_dirauth_schedule(const struct or_options_t *old_options,
                                       struct or_options_t *options,
                                       char **msg);
@@ -67,8 +63,6 @@ options_validate_dirauth_mode(const struct or_options_t *old_options,
   return 0;
 }
 
-#define options_validate_dirauth_bandwidth(old_options, options, msg) \
-  (((void)(old_options)),((void)(options)),((void)(msg)),0)
 #define options_validate_dirauth_schedule(old_options, options, msg) \
   (((void)(old_options)),((void)(options)),((void)(msg)),0)
 #define options_validate_dirauth_testing(old_options, options, msg) \
diff --git a/src/feature/dirauth/dirauth_options.inc b/src/feature/dirauth/dirauth_options.inc
index 6b66f1e28920b6ca5e806c028c75d929a3e51bf2..5939010fe7cc7957cc18fd37d8c60bb459569e03 100644
--- a/src/feature/dirauth/dirauth_options.inc
+++ b/src/feature/dirauth/dirauth_options.inc
@@ -12,7 +12,87 @@
 /** Holds configuration about our directory authority options. */
 BEGIN_CONF_STRUCT(dirauth_options_t)
 
+/** If non-zero, always vote the Fast flag for any relay advertising
+ * this amount of capacity or more. */
+CONF_VAR(AuthDirFastGuarantee, MEMUNIT, 0, "100 KB")
+
+/** If non-zero, this advertised capacity or more is always sufficient
+ * to satisfy the bandwidth requirement for the Guard flag. */
+CONF_VAR(AuthDirGuardBWGuarantee, MEMUNIT, 0, "2 MB")
+
+/** Boolean: are we on IPv6?  */
+CONF_VAR(AuthDirHasIPv6Connectivity, BOOL, 0, "0")
+
+/** True iff we should list bad exits, and vote for all other exits as
+ * good. */
+CONF_VAR(AuthDirListBadExits, BOOL, 0, "0")
+
 /** Do not permit more than this number of servers per IP address. */
 CONF_VAR(AuthDirMaxServersPerAddr, POSINT, 0, "2")
 
+/** Boolean: Do we enforce key-pinning? */
+CONF_VAR(AuthDirPinKeys, BOOL, 0, "1")
+
+/** Bool (default: 1): Switch for the shared random protocol. Only
+ * relevant to a directory authority. If off, the authority won't
+ * participate in the protocol. If on (default), a flag is added to the
+ * vote indicating participation. */
+CONF_VAR(AuthDirSharedRandomness, BOOL, 0, "1")
+
+/** Bool (default: 1): When testing routerinfos as a directory authority,
+ * do we enforce Ed25519 identity match? */
+/* NOTE: remove this option someday. */
+CONF_VAR(AuthDirTestEd25519LinkKeys, BOOL, 0, "1")
+
+/** Authority only: key=value pairs that we add to our networkstatus
+ * consensus vote on the 'params' line. */
+CONF_VAR(ConsensusParams, STRING, 0, NULL)
+
+/** Authority only: minimum number of measured bandwidths we must see
+ * before we only believe measured bandwidths to assign flags. */
+CONF_VAR(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, 0, "500")
+
+/** As directory authority, accept hidden service directories after what
+ * time? */
+CONF_VAR(MinUptimeHidServDirectoryV2, INTERVAL, 0, "96 hours")
+
+/** Which versions of tor should we tell users to run? */
+CONF_VAR(RecommendedVersions, LINELIST, 0, NULL)
+
+/** Which versions of tor should we tell users to run on clients? */
+CONF_VAR(RecommendedClientVersions, LINELIST, 0, NULL)
+
+/** Which versions of tor should we tell users to run on relays? */
+CONF_VAR(RecommendedServerVersions, LINELIST, 0, NULL)
+
+/** If an authority has been around for less than this amount of time, it
+ * does not believe its reachability information is accurate.  Only
+ * altered on testing networks. */
+CONF_VAR(TestingAuthDirTimeToLearnReachability, INTERVAL, 0, "30 minutes")
+
+  /** Relays in a testing network which should be voted Exit
+   * regardless of exit policy. */
+CONF_VAR(TestingDirAuthVoteExit, ROUTERSET, 0, NULL)
+CONF_VAR(TestingDirAuthVoteExitIsStrict, BOOL, 0, "0")
+
+/** Relays in a testing network which should be voted Guard
+ * regardless of uptime and bandwidth. */
+CONF_VAR(TestingDirAuthVoteGuard, ROUTERSET, 0, NULL)
+CONF_VAR(TestingDirAuthVoteGuardIsStrict, BOOL, 0, "0")
+
+/** Relays in a testing network which should be voted HSDir
+ * regardless of uptime and DirPort. */
+CONF_VAR(TestingDirAuthVoteHSDir, ROUTERSET, 0, NULL)
+CONF_VAR(TestingDirAuthVoteHSDirIsStrict, BOOL, 0, "0")
+
+/** Minimum value for the Exit flag threshold on testing networks. */
+CONF_VAR(TestingMinExitFlagThreshold, MEMUNIT, 0, "0")
+
+/** Minimum value for the Fast flag threshold on testing networks. */
+CONF_VAR(TestingMinFastFlagThreshold, MEMUNIT, 0, "0")
+
+/** Boolean: is this an authoritative directory that's willing to recommend
+ * versions? */
+CONF_VAR(VersioningAuthoritativeDirectory, BOOL, 0, "0")
+
 END_CONF_STRUCT(dirauth_options_t)
diff --git a/src/feature/dirauth/dirauth_options_st.h b/src/feature/dirauth/dirauth_options_st.h
index 86022ec22317bfbc6642d15b400a94a79fdb4780..02a498c054742583b1f53e733bf52fb53b2ba24c 100644
--- a/src/feature/dirauth/dirauth_options_st.h
+++ b/src/feature/dirauth/dirauth_options_st.h
@@ -13,6 +13,8 @@
 #define TOR_FEATURE_DIRAUTH_DIRAUTH_OPTIONS_ST_H
 
 #include "lib/conf/confdecl.h"
+#include "feature/nodelist/routerset.h"
+
 #define CONF_CONTEXT STRUCT
 #include "feature/dirauth/dirauth_options.inc"
 #undef CONF_CONTEXT
diff --git a/src/feature/dirauth/dirauth_sys.c b/src/feature/dirauth/dirauth_sys.c
index a95363463425930b7565df1077e302daddb49aed..56ac501e16a82751aae9b2a7e366a93bc2aceb27 100644
--- a/src/feature/dirauth/dirauth_sys.c
+++ b/src/feature/dirauth/dirauth_sys.c
@@ -11,6 +11,7 @@
 
 #include "core/or/or.h"
 
+#define DIRAUTH_SYS_PRIVATE
 #include "feature/dirauth/bwauth.h"
 #include "feature/dirauth/dirauth_sys.h"
 #include "feature/dirauth/dirvote.h"
@@ -49,7 +50,7 @@ dirauth_get_options(void)
   return global_dirauth_options;
 }
 
-static int
+STATIC int
 dirauth_set_options(void *arg)
 {
   dirauth_options_t *opts = arg;
diff --git a/src/feature/dirauth/dirauth_sys.h b/src/feature/dirauth/dirauth_sys.h
index ae99f8141a28a51740225d297c9806767b07722c..c512b91b33d67d428292fc43b6701aa315c89ed4 100644
--- a/src/feature/dirauth/dirauth_sys.h
+++ b/src/feature/dirauth/dirauth_sys.h
@@ -25,4 +25,8 @@ extern const struct subsys_fns_t sys_dirauth;
  **/
 #define DIRAUTH_SUBSYS_LEVEL 70
 
+#ifdef DIRAUTH_SYS_PRIVATE
+STATIC int dirauth_set_options(void *arg);
+#endif
+
 #endif /* !defined(DIRAUTH_SYS_H) */
diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c
index 97fe66c1a20f7155971d17bc08d647a061e3a330..9490867e8257992944cf560b3ee09beef30a6602 100644
--- a/src/feature/dirauth/dirvote.c
+++ b/src/feature/dirauth/dirvote.c
@@ -4406,6 +4406,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
                                         authority_cert_t *cert)
 {
   const or_options_t *options = get_options();
+  const dirauth_options_t *d_options = dirauth_get_options();
   networkstatus_t *v3_out = NULL;
   uint32_t addr;
   char *hostname = NULL, *client_versions = NULL, *server_versions = NULL;
@@ -4413,7 +4414,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
   smartlist_t *routers, *routerstatuses;
   char identity_digest[DIGEST_LEN];
   char signing_key_digest[DIGEST_LEN];
-  int listbadexits = options->AuthDirListBadExits;
+  const int listbadexits = d_options->AuthDirListBadExits;
   routerlist_t *rl = router_get_routerlist();
   time_t now = time(NULL);
   time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
@@ -4445,11 +4446,11 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
     hostname = tor_dup_ip(addr);
   }
 
-  if (options->VersioningAuthoritativeDir) {
+  if (d_options->VersioningAuthoritativeDirectory) {
     client_versions =
-      format_recommended_version_list(options->RecommendedClientVersions, 0);
+      format_recommended_version_list(d_options->RecommendedClientVersions, 0);
     server_versions =
-      format_recommended_version_list(options->RecommendedServerVersions, 0);
+      format_recommended_version_list(d_options->RecommendedServerVersions, 0);
   }
 
   contact = get_options()->ContactInfo;
@@ -4650,10 +4651,10 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
     smartlist_add_strdup(v3_out->known_flags, "BadExit");
   smartlist_sort_strings(v3_out->known_flags);
 
-  if (options->ConsensusParams) {
+  if (d_options->ConsensusParams) {
     v3_out->net_params = smartlist_new();
     smartlist_split_string(v3_out->net_params,
-                           options->ConsensusParams, NULL, 0, 0);
+                           d_options->ConsensusParams, NULL, 0, 0);
     smartlist_sort_strings(v3_out->net_params);
   }
   v3_out->bw_file_headers = bw_file_headers;
diff --git a/src/feature/dirauth/process_descs.c b/src/feature/dirauth/process_descs.c
index 139c6834a992f16b7cb48ba63fddd9142d51cce6..baf8f8c21737a0f89a3f763d3fafe9ce4b787783 100644
--- a/src/feature/dirauth/process_descs.c
+++ b/src/feature/dirauth/process_descs.c
@@ -20,6 +20,7 @@
 #include "app/config/config.h"
 #include "core/or/policies.h"
 #include "core/or/versions.h"
+#include "feature/dirauth/dirauth_sys.h"
 #include "feature/dirauth/keypin.h"
 #include "feature/dirauth/reachability.h"
 #include "feature/dirclient/dlstatus.h"
@@ -35,6 +36,7 @@
 #include "feature/relay/router.h"
 
 #include "core/or/tor_version_st.h"
+#include "feature/dirauth/dirauth_options_st.h"
 #include "feature/nodelist/extrainfo_st.h"
 #include "feature/nodelist/node_st.h"
 #include "feature/nodelist/microdesc_st.h"
@@ -289,7 +291,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
                           int severity)
 {
   char d[DIGEST_LEN];
-  const int key_pinning = get_options()->AuthDirPinKeys;
+  const int key_pinning = dirauth_get_options()->AuthDirPinKeys;
   uint32_t r;
   ed25519_public_key_t *signing_key = NULL;
 
@@ -741,7 +743,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
   char *desc, *nickname;
   const size_t desclen = ri->cache_info.signed_descriptor_len +
       ri->cache_info.annotations_len;
-  const int key_pinning = get_options()->AuthDirPinKeys;
+  const int key_pinning = dirauth_get_options()->AuthDirPinKeys;
   *msg = NULL;
 
   /* If it's too big, refuse it now. Otherwise we'll cache it all over the
diff --git a/src/feature/dirauth/reachability.c b/src/feature/dirauth/reachability.c
index 292c9be759a4a0829882ee78d3e3e40175fa5af0..65fa27ed80369daa96dd3889e500e8c62aca1b22 100644
--- a/src/feature/dirauth/reachability.c
+++ b/src/feature/dirauth/reachability.c
@@ -17,6 +17,7 @@
 #include "core/or/channeltls.h"
 #include "core/or/command.h"
 #include "feature/dirauth/authmode.h"
+#include "feature/dirauth/dirauth_sys.h"
 #include "feature/nodelist/describe.h"
 #include "feature/nodelist/nodelist.h"
 #include "feature/nodelist/routerinfo.h"
@@ -24,6 +25,7 @@
 #include "feature/nodelist/torcert.h"
 #include "feature/stats/rephist.h"
 
+#include "feature/dirauth/dirauth_options_st.h"
 #include "feature/nodelist/node_st.h"
 #include "feature/nodelist/routerinfo_st.h"
 #include "feature/nodelist/routerlist_st.h"
@@ -53,7 +55,7 @@ dirserv_orconn_tls_done(const tor_addr_t *addr,
 
   ri = node->ri;
 
-  if (get_options()->AuthDirTestEd25519LinkKeys &&
+  if (dirauth_get_options()->AuthDirTestEd25519LinkKeys &&
       node_supports_ed25519_link_authentication(node, 1) &&
       ri->cache_info.signing_key_cert) {
     /* We allow the node to have an ed25519 key if we haven't been told one in
@@ -125,7 +127,7 @@ dirserv_should_launch_reachability_test(const routerinfo_t *ri,
 void
 dirserv_single_reachability_test(time_t now, routerinfo_t *router)
 {
-  const or_options_t *options = get_options();
+  const dirauth_options_t *dirauth_options = dirauth_get_options();
   channel_t *chan = NULL;
   const node_t *node = NULL;
   tor_addr_t router_addr;
@@ -136,7 +138,7 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router)
   node = node_get_by_id(router->cache_info.identity_digest);
   tor_assert(node);
 
-  if (options->AuthDirTestEd25519LinkKeys &&
+  if (dirauth_options->AuthDirTestEd25519LinkKeys &&
       node_supports_ed25519_link_authentication(node, 1) &&
       router->cache_info.signing_key_cert) {
     ed_id_key = &router->cache_info.signing_key_cert->signing_key;
@@ -154,7 +156,7 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router)
   if (chan) command_setup_channel(chan);
 
   /* Possible IPv6. */
-  if (get_options()->AuthDirHasIPv6Connectivity == 1 &&
+  if (dirauth_get_options()->AuthDirHasIPv6Connectivity == 1 &&
       !tor_addr_is_null(&router->ipv6_addr)) {
     char addrstr[TOR_ADDR_BUF_LEN];
     log_debug(LD_OR, "Testing reachability of %s at %s:%u.",
diff --git a/src/feature/dirauth/shared_random.c b/src/feature/dirauth/shared_random.c
index 400c46faf3c2d1776b0013266f3f51e5d44c3c24..48e2147ea6fb47071e8e211b1d4acdf2854ebd2b 100644
--- a/src/feature/dirauth/shared_random.c
+++ b/src/feature/dirauth/shared_random.c
@@ -103,7 +103,9 @@
 
 #include "feature/dirauth/dirvote.h"
 #include "feature/dirauth/authmode.h"
+#include "feature/dirauth/dirauth_sys.h"
 
+#include "feature/dirauth/dirauth_options_st.h"
 #include "feature/nodelist/authority_cert_st.h"
 #include "feature/nodelist/networkstatus_st.h"
 
@@ -1130,7 +1132,7 @@ sr_get_string_for_vote(void)
   char *vote_str = NULL;
   digestmap_t *state_commits;
   smartlist_t *chunks = smartlist_new();
-  const or_options_t *options = get_options();
+  const dirauth_options_t *options = dirauth_get_options();
 
   /* Are we participating in the protocol? */
   if (!options->AuthDirSharedRandomness) {
@@ -1195,7 +1197,7 @@ sr_get_string_for_consensus(const smartlist_t *votes,
                             int32_t num_srv_agreements)
 {
   char *srv_str;
-  const or_options_t *options = get_options();
+  const dirauth_options_t *options = dirauth_get_options();
 
   tor_assert(votes);
 
diff --git a/src/feature/dirauth/voteflags.c b/src/feature/dirauth/voteflags.c
index 221b66d566d71964771d392e49d6d5b17492d005..477eb6f0b7a40308a31ad5040be2a5239c09cc62 100644
--- a/src/feature/dirauth/voteflags.c
+++ b/src/feature/dirauth/voteflags.c
@@ -18,6 +18,7 @@
 #include "core/or/policies.h"
 #include "feature/dirauth/bwauth.h"
 #include "feature/dirauth/reachability.h"
+#include "feature/dirauth/dirauth_sys.h"
 #include "feature/hibernate/hibernate.h"
 #include "feature/nodelist/dirlist.h"
 #include "feature/nodelist/networkstatus.h"
@@ -27,6 +28,7 @@
 #include "feature/relay/router.h"
 #include "feature/stats/rephist.h"
 
+#include "feature/dirauth/dirauth_options_st.h"
 #include "feature/nodelist/node_st.h"
 #include "feature/nodelist/routerinfo_st.h"
 #include "feature/nodelist/routerlist_st.h"
@@ -145,7 +147,7 @@ router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
    * if TestingTorNetwork, and TestingMinExitFlagThreshold is non-zero */
   if (!ri->bandwidthcapacity) {
     if (get_options()->TestingTorNetwork) {
-      if (get_options()->TestingMinExitFlagThreshold > 0) {
+      if (dirauth_get_options()->TestingMinExitFlagThreshold > 0) {
         /* If we're in a TestingTorNetwork, and TestingMinExitFlagThreshold is,
          * then require bandwidthcapacity */
         return 0;
@@ -175,14 +177,14 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
   long uptime;
 
   /* If we haven't been running for at least
-   * get_options()->MinUptimeHidServDirectoryV2 seconds, we can't
+   * MinUptimeHidServDirectoryV2 seconds, we can't
    * have accurate data telling us a relay has been up for at least
    * that long. We also want to allow a bit of slack: Reachability
    * tests aren't instant. If we haven't been running long enough,
    * trust the relay. */
 
   if (get_uptime() >
-      get_options()->MinUptimeHidServDirectoryV2 * 1.1)
+      dirauth_get_options()->MinUptimeHidServDirectoryV2 * 1.1)
     uptime = MIN(rep_hist_get_uptime(router->cache_info.identity_digest, now),
                  real_uptime(router, now));
   else
@@ -191,7 +193,7 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
   return (router->wants_to_be_hs_dir &&
           router->supports_tunnelled_dir_requests &&
           node->is_stable && node->is_fast &&
-          uptime >= get_options()->MinUptimeHidServDirectoryV2 &&
+          uptime >= dirauth_get_options()->MinUptimeHidServDirectoryV2 &&
           router_is_active(router, node, now));
 }
 
@@ -214,9 +216,10 @@ router_counts_toward_thresholds(const node_t *node, time_t now,
     dirserv_has_measured_bw(node->identity);
   uint64_t min_bw_kb = ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER_KB;
   const or_options_t *options = get_options();
+  const dirauth_options_t *dirauth_options = dirauth_get_options();
 
   if (options->TestingTorNetwork) {
-    min_bw_kb = (int64_t)options->TestingMinExitFlagThreshold / 1000;
+    min_bw_kb = (int64_t)dirauth_options->TestingMinExitFlagThreshold / 1000;
   }
 
   return node->ri && router_is_active(node->ri, node, now) &&
@@ -242,11 +245,12 @@ dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil)
   const smartlist_t *nodelist;
   time_t now = time(NULL);
   const or_options_t *options = get_options();
+  const dirauth_options_t *dirauth_options = dirauth_get_options();
 
   /* Require mbw? */
   int require_mbw =
     (dirserv_get_last_n_measured_bws() >
-     options->MinMeasuredBWsForAuthToIgnoreAdvertised) ? 1 : 0;
+     dirauth_options->MinMeasuredBWsForAuthToIgnoreAdvertised) ? 1 : 0;
 
   /* initialize these all here, in case there are no routers */
   stable_uptime = 0;
@@ -338,7 +342,7 @@ dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil)
       ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG,
       INT32_MAX);
     if (options->TestingTorNetwork) {
-      min_fast = (int32_t)options->TestingMinFastFlagThreshold;
+      min_fast = (int32_t)dirauth_options->TestingMinFastFlagThreshold;
     }
     max_fast = networkstatus_get_param(NULL, "FastFlagMaxThreshold",
                                        INT32_MAX, min_fast, INT32_MAX);
@@ -352,9 +356,11 @@ dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil)
   }
   /* Protect sufficiently fast nodes from being pushed out of the set
    * of Fast nodes. */
-  if (options->AuthDirFastGuarantee &&
-      fast_bandwidth_kb > options->AuthDirFastGuarantee/1000)
-    fast_bandwidth_kb = (uint32_t)options->AuthDirFastGuarantee/1000;
+  {
+    const uint64_t fast_opt = dirauth_get_options()->AuthDirFastGuarantee;
+    if (fast_opt && fast_bandwidth_kb > fast_opt / 1000)
+      fast_bandwidth_kb = (uint32_t)(fast_opt / 1000);
+  }
 
   /* Now that we have a time-known that 7/8 routers are known longer than,
    * fill wfus with the wfu of every such "familiar" router. */
@@ -428,7 +434,7 @@ dirserv_get_flag_thresholds_line(void)
 {
   char *result=NULL;
   const int measured_threshold =
-    get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
+    dirauth_get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
   const int enough_measured_bw =
     dirserv_get_last_n_measured_bws() > measured_threshold;
 
@@ -455,8 +461,9 @@ dirserv_get_flag_thresholds_line(void)
 int
 running_long_enough_to_decide_unreachable(void)
 {
-  return time_of_process_start
-    + get_options()->TestingAuthDirTimeToLearnReachability < approx_time();
+  const dirauth_options_t *opts = dirauth_get_options();
+  return time_of_process_start +
+    opts->TestingAuthDirTimeToLearnReachability < approx_time();
 }
 
 /** Each server needs to have passed a reachability test no more
@@ -481,6 +488,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
    */
   int answer;
   const or_options_t *options = get_options();
+  const dirauth_options_t *dirauth_options = dirauth_get_options();
   node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest);
   tor_assert(node);
 
@@ -507,7 +515,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
        IPv6 OR port since that'd kill all dual stack relays until a
        majority of the dir auths have IPv6 connectivity. */
     answer = (now < node->last_reachable + REACHABLE_TIMEOUT &&
-              (options->AuthDirHasIPv6Connectivity != 1 ||
+              (dirauth_options->AuthDirHasIPv6Connectivity != 1 ||
                tor_addr_is_null(&router->ipv6_addr) ||
                now < node->last_reachable6 + REACHABLE_TIMEOUT));
   }
@@ -538,7 +546,7 @@ static int
 should_publish_node_ipv6(const node_t *node, const routerinfo_t *ri,
                          time_t now)
 {
-  const or_options_t *options = get_options();
+  const dirauth_options_t *options = dirauth_get_options();
 
   return options->AuthDirHasIPv6Connectivity == 1 &&
     !tor_addr_is_null(&ri->ipv6_addr) &&
@@ -571,10 +579,10 @@ dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs,
   set_routerstatus_from_routerinfo(rs, node, ri);
 
   /* Override rs->is_possible_guard. */
+  const uint64_t bw_opt = dirauth_get_options()->AuthDirGuardBWGuarantee;
   if (node->is_fast && node->is_stable &&
       ri->supports_tunnelled_dir_requests &&
-      ((options->AuthDirGuardBWGuarantee &&
-        routerbw_kb >= options->AuthDirGuardBWGuarantee/1000) ||
+      ((bw_opt && routerbw_kb >= bw_opt / 1000) ||
        routerbw_kb >= MIN(guard_bandwidth_including_exits_kb,
                           guard_bandwidth_excluding_exits_kb))) {
     long tk = rep_hist_get_weighted_time_known(
@@ -612,9 +620,9 @@ dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs,
 STATIC void
 dirserv_set_routerstatus_testing(routerstatus_t *rs)
 {
-  const or_options_t *options = get_options();
+  const dirauth_options_t *options = dirauth_get_options();
 
-  tor_assert(options->TestingTorNetwork);
+  tor_assert(get_options()->TestingTorNetwork);
 
   if (routerset_contains_routerstatus(options->TestingDirAuthVoteExit,
                                       rs, 0)) {
diff --git a/src/feature/nodelist/routerset.h b/src/feature/nodelist/routerset.h
index 355c92c1c1b4f5fe3cdbe4191417dad9f9c047f9..0e4fedf64ec122337080c608eb43f08d1182bb65 100644
--- a/src/feature/nodelist/routerset.h
+++ b/src/feature/nodelist/routerset.h
@@ -46,7 +46,7 @@ int routerset_len(const routerset_t *set);
 
 struct var_type_def_t;
 extern const struct var_type_def_t ROUTERSET_type_defn;
-typedef routerset_t config_decl_ROUTERSET;
+typedef routerset_t *config_decl_ROUTERSET;
 
 #ifdef ROUTERSET_PRIVATE
 #include "lib/container/bitarray.h"
diff --git a/src/test/conf_examples/large_1/expected_log_no_dirauth b/src/test/conf_examples/large_1/expected_log_no_dirauth
new file mode 100644
index 0000000000000000000000000000000000000000..0b74de4e4057328c1e462067f0d05171480adada
--- /dev/null
+++ b/src/test/conf_examples/large_1/expected_log_no_dirauth
@@ -0,0 +1 @@
+This copy of Tor was built without support for the option "ConsensusParams". Skipping.
diff --git a/src/test/conf_examples/large_1/expected_no_dirauth b/src/test/conf_examples/large_1/expected_no_dirauth
new file mode 100644
index 0000000000000000000000000000000000000000..17c11f85fc15ced8bbb746702106d8adb12930d3
--- /dev/null
+++ b/src/test/conf_examples/large_1/expected_no_dirauth
@@ -0,0 +1,158 @@
+AccountingMax 10737418240
+AccountingRule sum
+AccountingStart day 05:15
+Address 128.66.8.8
+AllowNonRFC953Hostnames 1
+AndroidIdentityTag droidy
+AutomapHostsOnResolve 1
+AutomapHostsSuffixes .onions
+AvoidDiskWrites 1
+BandwidthBurst 2147483647
+BandwidthRate 1610612736
+Bridge 128.66.1.10:80
+CacheDirectory /this-is-a-cache
+CellStatistics 1
+CircuitBuildTimeout 200
+CircuitsAvailableTimeout 10
+CircuitStreamTimeout 20
+ClientAutoIPv6ORPort 1
+ClientOnly 1
+ClientPreferIPv6DirPort 1
+ClientPreferIPv6ORPort 1
+ClientRejectInternalAddresses 0
+ClientUseIPv4 0
+ClientUseIPv6 1
+ConnDirectionStatistics 1
+ConnectionPadding 1
+ConnLimit 64
+ConstrainedSockets 1
+ConstrainedSockSize 10240
+ContactInfo long_config@example.com
+ControlPortFileGroupReadable 1
+ControlPort 9058
+CookieAuthentication 1
+CookieAuthFile /control/cookie
+CookieAuthFileGroupReadable 1
+CountPrivateBandwidth 1
+DataDirectory /data/dir
+DirAllowPrivateAddresses 1
+DirPolicy reject 128.66.1.1/32, accept *:*
+DirPortFrontPage /dirport/frontpage
+DirPort 99
+DirReqStatistics 0
+DisableDebuggerAttachment 0
+DisableNetwork 1
+DisableOOSCheck 0
+DNSPort 53535
+DormantCanceledByStartup 1
+DormantClientTimeout 1260
+DormantOnFirstStartup 1
+DormantTimeoutDisabledByIdleStreams 0
+DoSCircuitCreationBurst 1000
+DoSCircuitCreationDefenseTimePeriod 300
+DoSCircuitCreationDefenseType 2
+DoSCircuitCreationEnabled 1
+DoSCircuitCreationMinConnections 10
+DoSCircuitCreationRate 100
+DoSConnectionDefenseType 2
+DoSConnectionEnabled 1
+DoSConnectionMaxConcurrentCount 6
+DoSRefuseSingleHopClientRendezvous 0
+DownloadExtraInfo 1
+EnforceDistinctSubnets 0
+EntryNodes potrzebie,triffid,cromulent
+EntryStatistics 1
+ExcludeExitNodes blaznort,kriffid,zeppelin
+ExcludeNodes 128.66.7.6
+ExitNodes 128.66.7.7,128.66.128.0/17,exitexit
+ExitPolicy accept *:80,reject *:*
+ExitPolicyRejectLocalInterfaces 1
+ExitPolicyRejectPrivate 0
+ExitPortStatistics 1
+ExitRelay 1
+ExtendAllowPrivateAddresses 1
+ExtendByEd25519ID 1
+ExtORPortCookieAuthFile /foobar
+ExtORPort 99
+FascistFirewall 1
+FetchDirInfoEarly 1
+FetchDirInfoExtraEarly 1
+FetchUselessDescriptors 1
+FirewallPorts 80,443,999
+GeoIPExcludeUnknown 1
+GeoIPFile /geoip
+GuardfractionFile /gff
+GuardLifetime 691200
+HeartbeatPeriod 2700
+IPv6Exit 1
+KeepalivePeriod 540
+KeyDirectory /keyz
+KISTSchedRunInterval 1
+Log notice file /logfile
+Log info file /logfile-verbose
+LogTimeGranularity 60000
+LongLivedPorts 9090
+MainloopStats 1
+MapAddress www.example.com:10.0.0.6
+MaxAdvertisedBandwidth 100
+MaxCircuitDirtiness 3600
+MaxClientCircuitsPending 127
+MaxConsensusAgeForDiffs 2629728
+MaxMemInQueues 314572800
+MaxOnionQueueDelay 60000
+MaxUnparseableDescSizeToLog 1048576
+MiddleNodes grommit,truffle,parcheesi
+MyFamily $ffffffffffffffffffffffffffffffffffffffff
+NewCircuitPeriod 7200
+Nickname nickname
+NodeFamily $ffffffffffffffffffffffffffffffffffffffff,$dddddddddddddddddddddddddddddddddddddddd
+NumCPUs 3
+NumDirectoryGuards 4
+NumEntryGuards 5
+NumPrimaryGuards 8
+OfflineMasterKey 1
+OptimisticData 1
+ORPort 2222
+OutboundBindAddress 10.0.0.7
+OutboundBindAddressExit 10.0.0.8
+OutboundBindAddressOR 10.0.0.9
+PerConnBWBurst 10485760
+PerConnBWRate 102400
+PidFile /piddy
+ProtocolWarnings 1
+PublishHidServDescriptors 0
+PublishServerDescriptor 0
+ReachableAddresses 0.0.0.0, *:*
+ReachableDirAddresses 128.0.0.0/1
+ReachableORAddresses 128.0.0.0/8
+RejectPlaintextPorts 23
+RelayBandwidthBurst 10000
+RelayBandwidthRate 1000
+RendPostPeriod 600
+RephistTrackTime 600
+SafeLogging 0
+Schedulers Vanilla,KISTLite,Kist
+ShutdownWaitLength 10
+SigningKeyLifetime 4838400
+Socks5Proxy 128.66.99.99:99
+Socks5ProxyPassword flynn
+Socks5ProxyUsername spaceparanoids
+SocksPolicy accept 127.0.0.0/24, reject *:*
+SocksPort 9099
+SocksTimeout 600
+SSLKeyLifetime 86400
+StrictNodes 1
+SyslogIdentityTag tortor
+TestSocks 1
+TokenBucketRefillInterval 1000
+TrackHostExits www.example.com
+TrackHostExitsExpire 3600
+TruncateLogFile 1
+UnixSocksGroupWritable 1
+UpdateBridgesFromAuthority 1
+UseDefaultFallbackDirs 0
+UseGuardFraction 1
+UseMicrodescriptors 0
+VirtualAddrNetworkIPv4 18.66.0.0/16
+VirtualAddrNetworkIPv6 [ff00::]/16
+WarnPlaintextPorts 7,11,23,1001
diff --git a/src/test/include.am b/src/test/include.am
index 3433e848eadb3b83ffa7a7a394ba2c07039053a8..90e50752ce65f1354e166c11111ea3ffefc2336f 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -107,6 +107,7 @@ src_test_test_SOURCES += \
 	src/test/fakecircs.c \
 	src/test/log_test_helpers.c \
 	src/test/hs_test_helpers.c \
+	src/test/opts_test_helpers.c \
 	src/test/rend_test_helpers.c \
 	src/test/resolve_test_helpers.c \
 	src/test/rng_test_helpers.c \
@@ -352,6 +353,7 @@ noinst_HEADERS+= \
 	src/test/fakecircs.h \
 	src/test/hs_test_helpers.h \
 	src/test/log_test_helpers.h \
+	src/test/opts_test_helpers.h \
 	src/test/rend_test_helpers.h \
 	src/test/resolve_test_helpers.h \
 	src/test/rng_test_helpers.h \
diff --git a/src/test/opts_test_helpers.c b/src/test/opts_test_helpers.c
new file mode 100644
index 0000000000000000000000000000000000000000..619ca407336871a040317cfd00169db0805a7ff1
--- /dev/null
+++ b/src/test/opts_test_helpers.c
@@ -0,0 +1,38 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file opts_testing_helpers.c
+ * @brief Helper functions to access module-specific config options.
+ **/
+
+#include "orconfig.h"
+#include "test/opts_test_helpers.h"
+
+#define CONFIG_PRIVATE
+#include "core/or/or.h"
+#include "lib/confmgt/confmgt.h"
+#include "app/main/subsysmgr.h"
+#include "app/config/config.h"
+
+#include "lib/crypt_ops/crypto_sys.h"
+#include "feature/dirauth/dirauth_sys.h"
+
+struct dirauth_options_t *
+get_dirauth_options(struct or_options_t *opt)
+{
+  int idx = subsystems_get_options_idx(&sys_dirauth);
+  tor_assert(idx >= 0);
+  return config_mgr_get_obj_mutable(get_options_mgr(), opt, idx);
+}
+
+struct crypto_options_t *
+get_crypto_options(struct or_options_t *opt)
+{
+  int idx = subsystems_get_options_idx(&sys_crypto);
+  tor_assert(idx >= 0);
+  return config_mgr_get_obj_mutable(get_options_mgr(), opt, idx);
+}
diff --git a/src/test/opts_test_helpers.h b/src/test/opts_test_helpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..f925194e636280ec8cd2ca80758059ac40510f8e
--- /dev/null
+++ b/src/test/opts_test_helpers.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file opts_testing_helpers.h
+ * @brief Header for test/opts_test_helpers.c
+ **/
+
+#ifndef TOR_TEST_OPTS_TESTING_HELPERS_H
+#define TOR_TEST_OPTS_TESTING_HELPERS_H
+
+struct crypto_options_t;
+struct dirauth_options_t;
+struct or_options_t;
+
+struct crypto_options_t *get_crypto_options(struct or_options_t *opt);
+struct dirauth_options_t *get_dirauth_options(struct or_options_t *opt);
+
+#endif /* !defined(TOR_TEST_OPTS_TESTING_HELPERS_H) */
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 76c86c258963645fdcce1686c2ba6a37d301f70b..3b2ba64d2c5d4cc4f1c31531a4cb7d6b555acef5 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -9,6 +9,7 @@
 #define BWAUTH_PRIVATE
 #define CONFIG_PRIVATE
 #define CONTROL_GETINFO_PRIVATE
+#define DIRAUTH_SYS_PRIVATE
 #define DIRCACHE_PRIVATE
 #define DIRCLIENT_PRIVATE
 #define DIRVOTE_PRIVATE
@@ -33,6 +34,7 @@
 #include "feature/client/entrynodes.h"
 #include "feature/control/control_getinfo.h"
 #include "feature/dirauth/bwauth.h"
+#include "feature/dirauth/dirauth_sys.h"
 #include "feature/dirauth/dirvote.h"
 #include "feature/dirauth/dsigs_parse.h"
 #include "feature/dirauth/process_descs.h"
@@ -71,10 +73,12 @@
 #include "lib/memarea/memarea.h"
 #include "lib/osinfo/uname.h"
 #include "test/log_test_helpers.h"
+#include "test/opts_test_helpers.h"
 #include "test/test.h"
 #include "test/test_dir_common.h"
 
 #include "core/or/addr_policy_st.h"
+#include "feature/dirauth/dirauth_options_st.h"
 #include "feature/nodelist/authority_cert_st.h"
 #include "feature/nodelist/document_signature_st.h"
 #include "feature/nodelist/extrainfo_st.h"
@@ -4689,10 +4693,13 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
   (void)arg;
 
   /* Init options */
+  dirauth_options_t *dirauth_options =
+    tor_malloc_zero(sizeof(dirauth_options_t));
+
   mock_options = tor_malloc(sizeof(or_options_t));
   reset_options(mock_options, &mock_get_options_calls);
-
   MOCK(get_options, mock_get_options);
+  dirauth_set_options(dirauth_options);
 
   /* Init routersets */
   routerset_t *routerset_all  = routerset_new();
@@ -4732,16 +4739,15 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
   /* Check that "*" sets flags on all routers: Exit
    * Check the flags aren't being confused with each other */
   reset_options(mock_options, &mock_get_options_calls);
+  memset(dirauth_options, 0, sizeof(*dirauth_options));
   reset_routerstatus(rs_a, ROUTER_A_ID_STR, ROUTER_A_IPV4);
   reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
 
-  mock_options->TestingDirAuthVoteExit = routerset_all;
-  mock_options->TestingDirAuthVoteExitIsStrict = 0;
+  dirauth_options->TestingDirAuthVoteExit = routerset_all;
+  dirauth_options->TestingDirAuthVoteExitIsStrict = 0;
 
   dirserv_set_routerstatus_testing(rs_a);
-  tt_int_op(mock_get_options_calls, OP_EQ, 1);
   dirserv_set_routerstatus_testing(rs_b);
-  tt_int_op(mock_get_options_calls, OP_EQ, 2);
 
   tt_uint_op(rs_a->is_exit, OP_EQ, 1);
   tt_uint_op(rs_b->is_exit, OP_EQ, 1);
@@ -4754,18 +4760,17 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
   /* Check that "*" sets flags on all routers: Guard & HSDir
    * Cover the remaining flags in one test */
   reset_options(mock_options, &mock_get_options_calls);
+  memset(dirauth_options, 0, sizeof(*dirauth_options));
   reset_routerstatus(rs_a, ROUTER_A_ID_STR, ROUTER_A_IPV4);
   reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
 
-  mock_options->TestingDirAuthVoteGuard = routerset_all;
-  mock_options->TestingDirAuthVoteGuardIsStrict = 0;
-  mock_options->TestingDirAuthVoteHSDir = routerset_all;
-  mock_options->TestingDirAuthVoteHSDirIsStrict = 0;
+  dirauth_options->TestingDirAuthVoteGuard = routerset_all;
+  dirauth_options->TestingDirAuthVoteGuardIsStrict = 0;
+  dirauth_options->TestingDirAuthVoteHSDir = routerset_all;
+  dirauth_options->TestingDirAuthVoteHSDirIsStrict = 0;
 
   dirserv_set_routerstatus_testing(rs_a);
-  tt_int_op(mock_get_options_calls, OP_EQ, 1);
   dirserv_set_routerstatus_testing(rs_b);
-  tt_int_op(mock_get_options_calls, OP_EQ, 2);
 
   tt_uint_op(rs_a->is_possible_guard, OP_EQ, 1);
   tt_uint_op(rs_b->is_possible_guard, OP_EQ, 1);
@@ -4778,20 +4783,19 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
   /* Check routerset A sets all flags on router A,
    * but leaves router B unmodified */
   reset_options(mock_options, &mock_get_options_calls);
+  memset(dirauth_options, 0, sizeof(*dirauth_options));
   reset_routerstatus(rs_a, ROUTER_A_ID_STR, ROUTER_A_IPV4);
   reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
 
-  mock_options->TestingDirAuthVoteExit = routerset_a;
-  mock_options->TestingDirAuthVoteExitIsStrict = 0;
-  mock_options->TestingDirAuthVoteGuard = routerset_a;
-  mock_options->TestingDirAuthVoteGuardIsStrict = 0;
-  mock_options->TestingDirAuthVoteHSDir = routerset_a;
-  mock_options->TestingDirAuthVoteHSDirIsStrict = 0;
+  dirauth_options->TestingDirAuthVoteExit = routerset_a;
+  dirauth_options->TestingDirAuthVoteExitIsStrict = 0;
+  dirauth_options->TestingDirAuthVoteGuard = routerset_a;
+  dirauth_options->TestingDirAuthVoteGuardIsStrict = 0;
+  dirauth_options->TestingDirAuthVoteHSDir = routerset_a;
+  dirauth_options->TestingDirAuthVoteHSDirIsStrict = 0;
 
   dirserv_set_routerstatus_testing(rs_a);
-  tt_int_op(mock_get_options_calls, OP_EQ, 1);
   dirserv_set_routerstatus_testing(rs_b);
-  tt_int_op(mock_get_options_calls, OP_EQ, 2);
 
   tt_uint_op(rs_a->is_exit, OP_EQ, 1);
   tt_uint_op(rs_b->is_exit, OP_EQ, 0);
@@ -4802,21 +4806,21 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
 
   /* Check routerset A unsets all flags on router B when Strict is set */
   reset_options(mock_options, &mock_get_options_calls);
+  memset(dirauth_options, 0, sizeof(*dirauth_options));
   reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
 
-  mock_options->TestingDirAuthVoteExit = routerset_a;
-  mock_options->TestingDirAuthVoteExitIsStrict = 1;
-  mock_options->TestingDirAuthVoteGuard = routerset_a;
-  mock_options->TestingDirAuthVoteGuardIsStrict = 1;
-  mock_options->TestingDirAuthVoteHSDir = routerset_a;
-  mock_options->TestingDirAuthVoteHSDirIsStrict = 1;
+  dirauth_options->TestingDirAuthVoteExit = routerset_a;
+  dirauth_options->TestingDirAuthVoteExitIsStrict = 1;
+  dirauth_options->TestingDirAuthVoteGuard = routerset_a;
+  dirauth_options->TestingDirAuthVoteGuardIsStrict = 1;
+  dirauth_options->TestingDirAuthVoteHSDir = routerset_a;
+  dirauth_options->TestingDirAuthVoteHSDirIsStrict = 1;
 
   rs_b->is_exit = 1;
   rs_b->is_possible_guard = 1;
   rs_b->is_hs_dir = 1;
 
   dirserv_set_routerstatus_testing(rs_b);
-  tt_int_op(mock_get_options_calls, OP_EQ, 1);
 
   tt_uint_op(rs_b->is_exit, OP_EQ, 0);
   tt_uint_op(rs_b->is_possible_guard, OP_EQ, 0);
@@ -4824,21 +4828,21 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
 
   /* Check routerset A doesn't modify flags on router B without Strict set */
   reset_options(mock_options, &mock_get_options_calls);
+  memset(dirauth_options, 0, sizeof(*dirauth_options));
   reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
 
-  mock_options->TestingDirAuthVoteExit = routerset_a;
-  mock_options->TestingDirAuthVoteExitIsStrict = 0;
-  mock_options->TestingDirAuthVoteGuard = routerset_a;
-  mock_options->TestingDirAuthVoteGuardIsStrict = 0;
-  mock_options->TestingDirAuthVoteHSDir = routerset_a;
-  mock_options->TestingDirAuthVoteHSDirIsStrict = 0;
+  dirauth_options->TestingDirAuthVoteExit = routerset_a;
+  dirauth_options->TestingDirAuthVoteExitIsStrict = 0;
+  dirauth_options->TestingDirAuthVoteGuard = routerset_a;
+  dirauth_options->TestingDirAuthVoteGuardIsStrict = 0;
+  dirauth_options->TestingDirAuthVoteHSDir = routerset_a;
+  dirauth_options->TestingDirAuthVoteHSDirIsStrict = 0;
 
   rs_b->is_exit = 1;
   rs_b->is_possible_guard = 1;
   rs_b->is_hs_dir = 1;
 
   dirserv_set_routerstatus_testing(rs_b);
-  tt_int_op(mock_get_options_calls, OP_EQ, 1);
 
   tt_uint_op(rs_b->is_exit, OP_EQ, 1);
   tt_uint_op(rs_b->is_possible_guard, OP_EQ, 1);
@@ -4847,21 +4851,21 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
   /* Check the empty routerset zeroes all flags
    * on routers A & B with Strict set */
   reset_options(mock_options, &mock_get_options_calls);
+  memset(dirauth_options, 0, sizeof(*dirauth_options));
   reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
 
-  mock_options->TestingDirAuthVoteExit = routerset_none;
-  mock_options->TestingDirAuthVoteExitIsStrict = 1;
-  mock_options->TestingDirAuthVoteGuard = routerset_none;
-  mock_options->TestingDirAuthVoteGuardIsStrict = 1;
-  mock_options->TestingDirAuthVoteHSDir = routerset_none;
-  mock_options->TestingDirAuthVoteHSDirIsStrict = 1;
+  dirauth_options->TestingDirAuthVoteExit = routerset_none;
+  dirauth_options->TestingDirAuthVoteExitIsStrict = 1;
+  dirauth_options->TestingDirAuthVoteGuard = routerset_none;
+  dirauth_options->TestingDirAuthVoteGuardIsStrict = 1;
+  dirauth_options->TestingDirAuthVoteHSDir = routerset_none;
+  dirauth_options->TestingDirAuthVoteHSDirIsStrict = 1;
 
   rs_b->is_exit = 1;
   rs_b->is_possible_guard = 1;
   rs_b->is_hs_dir = 1;
 
   dirserv_set_routerstatus_testing(rs_b);
-  tt_int_op(mock_get_options_calls, OP_EQ, 1);
 
   tt_uint_op(rs_b->is_exit, OP_EQ, 0);
   tt_uint_op(rs_b->is_possible_guard, OP_EQ, 0);
@@ -4870,24 +4874,23 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
   /* Check the empty routerset doesn't modify any flags
    * on A or B without Strict set */
   reset_options(mock_options, &mock_get_options_calls);
+  memset(dirauth_options, 0, sizeof(*dirauth_options));
   reset_routerstatus(rs_a, ROUTER_A_ID_STR, ROUTER_A_IPV4);
   reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
 
-  mock_options->TestingDirAuthVoteExit = routerset_none;
-  mock_options->TestingDirAuthVoteExitIsStrict = 0;
-  mock_options->TestingDirAuthVoteGuard = routerset_none;
-  mock_options->TestingDirAuthVoteGuardIsStrict = 0;
-  mock_options->TestingDirAuthVoteHSDir = routerset_none;
-  mock_options->TestingDirAuthVoteHSDirIsStrict = 0;
+  dirauth_options->TestingDirAuthVoteExit = routerset_none;
+  dirauth_options->TestingDirAuthVoteExitIsStrict = 0;
+  dirauth_options->TestingDirAuthVoteGuard = routerset_none;
+  dirauth_options->TestingDirAuthVoteGuardIsStrict = 0;
+  dirauth_options->TestingDirAuthVoteHSDir = routerset_none;
+  dirauth_options->TestingDirAuthVoteHSDirIsStrict = 0;
 
   rs_b->is_exit = 1;
   rs_b->is_possible_guard = 1;
   rs_b->is_hs_dir = 1;
 
   dirserv_set_routerstatus_testing(rs_a);
-  tt_int_op(mock_get_options_calls, OP_EQ, 1);
   dirserv_set_routerstatus_testing(rs_b);
-  tt_int_op(mock_get_options_calls, OP_EQ, 2);
 
   tt_uint_op(rs_a->is_exit, OP_EQ, 0);
   tt_uint_op(rs_a->is_possible_guard, OP_EQ, 0);
@@ -4898,6 +4901,7 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
 
  done:
   tor_free(mock_options);
+  tor_free(dirauth_options);
   mock_options = NULL;
 
   UNMOCK(get_options);
@@ -7466,7 +7470,7 @@ struct testcase_t dir_tests[] = {
   DIR_LEGACY(clip_unmeasured_bw_kb),
   DIR_LEGACY(clip_unmeasured_bw_kb_alt),
   DIR(fmt_control_ns, 0),
-  DIR(dirserv_set_routerstatus_testing, 0),
+  DIR(dirserv_set_routerstatus_testing, TT_FORK),
   DIR(http_handling, 0),
   DIR(purpose_needs_anonymity_returns_true_for_bridges, 0),
   DIR(purpose_needs_anonymity_returns_false_for_own_bridge_desc, 0),
diff --git a/src/test/test_options.c b/src/test/test_options.c
index fb12821aeeacfb766138b79812bcd5f3009742d0..b6a9a215013acda1c726f03818b9dd02c1b83304 100644
--- a/src/test/test_options.c
+++ b/src/test/test_options.c
@@ -6,15 +6,17 @@
 #define CONFIG_PRIVATE
 #define RELAY_CONFIG_PRIVATE
 #define LOG_PRIVATE
+#define ROUTERSET_PRIVATE
 #include "core/or/or.h"
 #include "lib/confmgt/confmgt.h"
 #include "app/config/config.h"
 #include "feature/dirauth/dirauth_config.h"
+#include "feature/dirauth/dirauth_options_st.h"
+#include "feature/dirauth/dirauth_sys.h"
 #include "feature/relay/relay_config.h"
 #include "test/test.h"
 #include "lib/geoip/geoip.h"
 
-#define ROUTERSET_PRIVATE
 #include "feature/nodelist/routerset.h"
 #include "core/mainloop/mainloop.h"
 #include "app/main/subsysmgr.h"
@@ -29,6 +31,7 @@
 #include "lib/encoding/confline.h"
 #include "core/or/policies.h"
 #include "test/test_helpers.h"
+#include "test/opts_test_helpers.h"
 #include "lib/net/resolve.h"
 
 #ifdef HAVE_SYS_PARAM_H
@@ -760,6 +763,7 @@ test_options_validate__authdir(void *ignored)
   options_test_data_t *tdata = get_options_test_data(
                                  ENABLE_AUTHORITY_V3_MIN
                                  "Address this.should.not!exist!.example.org");
+  const dirauth_options_t *da_opt;
 
   sandbox_disable_getaddrinfo_cache();
 
@@ -818,8 +822,9 @@ test_options_validate__authdir(void *ignored)
                                 "RecommendedVersions 1.2, 3.14\n");
   mock_clean_saved_logs();
   options_validate(NULL, tdata->opt, &msg);
-  tt_str_op(tdata->opt->RecommendedClientVersions->value, OP_EQ, "1.2, 3.14");
-  tt_str_op(tdata->opt->RecommendedServerVersions->value, OP_EQ, "1.2, 3.14");
+  da_opt = get_dirauth_options(tdata->opt);
+  tt_str_op(da_opt->RecommendedClientVersions->value, OP_EQ, "1.2, 3.14");
+  tt_str_op(da_opt->RecommendedServerVersions->value, OP_EQ, "1.2, 3.14");
   tor_free(msg);
 
   free_options_test_data(tdata);
@@ -829,8 +834,9 @@ test_options_validate__authdir(void *ignored)
                                 "RecommendedServerVersions 4.18\n");
   mock_clean_saved_logs();
   options_validate(NULL, tdata->opt, &msg);
-  tt_str_op(tdata->opt->RecommendedClientVersions->value, OP_EQ, "25");
-  tt_str_op(tdata->opt->RecommendedServerVersions->value, OP_EQ, "4.18");
+  da_opt = get_dirauth_options(tdata->opt);
+  tt_str_op(da_opt->RecommendedClientVersions->value, OP_EQ, "25");
+  tt_str_op(da_opt->RecommendedServerVersions->value, OP_EQ, "4.18");
   tor_free(msg);
 
   free_options_test_data(tdata);
@@ -841,6 +847,7 @@ test_options_validate__authdir(void *ignored)
                                 "RecommendedServerVersions 4.18\n");
   mock_clean_saved_logs();
   options_validate(NULL, tdata->opt, &msg);
+  da_opt = get_dirauth_options(tdata->opt);
   tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)"
             "AuthoritativeDir is set.");
   tor_free(msg);
@@ -851,6 +858,7 @@ test_options_validate__authdir(void *ignored)
                                 "RecommendedServerVersions 4.18\n");
   mock_clean_saved_logs();
   options_validate(NULL, tdata->opt, &msg);
+  da_opt = get_dirauth_options(tdata->opt);
   tt_str_op(msg, OP_EQ, "Versioning authoritative dir servers must set "
             "Recommended*Versions.");
   tor_free(msg);
@@ -861,9 +869,11 @@ test_options_validate__authdir(void *ignored)
                                 "RecommendedClientVersions 4.18\n");
   mock_clean_saved_logs();
   options_validate(NULL, tdata->opt, &msg);
+  da_opt = get_dirauth_options(tdata->opt);
   tt_str_op(msg, OP_EQ, "Versioning authoritative dir servers must set "
             "Recommended*Versions.");
   tor_free(msg);
+  da_opt = NULL;
 
   free_options_test_data(tdata);
   tdata = get_options_test_data(ENABLE_AUTHORITY_V3
@@ -979,18 +989,6 @@ test_options_validate__authdir(void *ignored)
             "but ClientOnly also set.");
   tor_free(msg);
 
-  free_options_test_data(tdata);
-  tdata = get_options_test_data(ENABLE_AUTHORITY_V3);
-  /* We have to set this value manually, because it won't parse */
-  tdata->opt->MinUptimeHidServDirectoryV2 = -1;
-  mock_clean_saved_logs();
-  ret = options_validate(NULL, tdata->opt, &msg);
-  tt_int_op(ret, OP_EQ, 0);
-  expect_log_msg("MinUptimeHidServDirectoryV2 "
-                 "option must be at least 0 seconds. Changing to 0.\n");
-  tt_int_op(tdata->opt->MinUptimeHidServDirectoryV2, OP_EQ, 0);
-  tor_free(msg);
-
  done:
   teardown_capture_of_logs();
   //  sandbox_free_getaddrinfo_cache();
@@ -3842,14 +3840,15 @@ test_options_validate__testing_options(void *ignored)
   options_test_data_t *tdata = NULL;
   setup_capture_of_logs(LOG_WARN);
 
-#define TEST_TESTING_OPTION(name, low_val, high_val, err_low, EXTRA_OPT_STR) \
+#define TEST_TESTING_OPTION(name, accessor, \
+                            low_val, high_val, err_low, EXTRA_OPT_STR)  \
   STMT_BEGIN                                                            \
     free_options_test_data(tdata);                                      \
   tdata = get_options_test_data(EXTRA_OPT_STR                           \
                                 VALID_DIR_AUTH                          \
                                 "TestingTorNetwork 1\n"                 \
                                 );                                      \
-  tdata->opt-> name = low_val;                                       \
+  accessor(tdata->opt)->name = low_val;                                 \
   ret = options_validate(NULL, tdata->opt,  &msg);            \
   tt_int_op(ret, OP_EQ, -1);                                            \
   tt_str_op(msg, OP_EQ, #name " " err_low);                \
@@ -3860,7 +3859,7 @@ test_options_validate__testing_options(void *ignored)
                                 VALID_DIR_AUTH                          \
                                 "TestingTorNetwork 1\n"                 \
                                 );                                      \
-  tdata->opt->  name = high_val;                                      \
+  accessor(tdata->opt)->name = high_val;                                \
   mock_clean_saved_logs();                                              \
   ret = options_validate(NULL, tdata->opt,  &msg);            \
   tt_int_op(ret, OP_EQ, 0);                                             \
@@ -3869,24 +3868,19 @@ test_options_validate__testing_options(void *ignored)
   tor_free(msg); \
   STMT_END
 
-  TEST_TESTING_OPTION(TestingAuthDirTimeToLearnReachability, -1, 8000,
-                      "must be non-negative.", ENABLE_AUTHORITY_V3);
-  TEST_TESTING_OPTION(TestingAuthDirTimeToLearnReachability, -1, 8000,
-                      "must be non-negative.", ENABLE_AUTHORITY_BRIDGE);
-
-  TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, -1, 3601,
+  TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, , -1, 3601,
                       "is way too low.", "");
-  TEST_TESTING_OPTION(TestingDirConnectionMaxStall, 1, 3601,
+  TEST_TESTING_OPTION(TestingDirConnectionMaxStall, , 1, 3601,
                       "is way too low.", "");
 
-  TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, -1, 3601,
+  TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, , -1, 3601,
                       "is way too low.", ENABLE_AUTHORITY_V3);
-  TEST_TESTING_OPTION(TestingDirConnectionMaxStall, 1, 3601,
+  TEST_TESTING_OPTION(TestingDirConnectionMaxStall, , 1, 3601,
                       "is way too low.", ENABLE_AUTHORITY_V3);
 
-  TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, -1, 3601,
+  TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, , -1, 3601,
                       "is way too low.", ENABLE_AUTHORITY_BRIDGE);
-  TEST_TESTING_OPTION(TestingDirConnectionMaxStall, 1, 3601,
+  TEST_TESTING_OPTION(TestingDirConnectionMaxStall, , 1, 3601,
                       "is way too low.", ENABLE_AUTHORITY_BRIDGE);
 
   free_options_test_data(tdata);
@@ -3984,14 +3978,6 @@ test_options_validate__testing_options(void *ignored)
   tor_free(msg);
 }
 
-static crypto_options_t *
-get_crypto_options(or_options_t *opt)
-{
-  int idx = subsystems_get_options_idx(&sys_crypto);
-  tor_assert(idx >= 0);
-  return config_mgr_get_obj_mutable(get_options_mgr(), opt, idx);
-}
-
 static void
 test_options_validate__accel(void *ignored)
 {
diff --git a/src/test/test_voting_flags.c b/src/test/test_voting_flags.c
index 28c3457678b18a109a9f3e0dd2832d1b19e11b01..ae89e4388989b4b706a46e5f900ec910cccda433 100644
--- a/src/test/test_voting_flags.c
+++ b/src/test/test_voting_flags.c
@@ -8,6 +8,7 @@
 #include "core/or/or.h"
 
 #include "feature/dirauth/voteflags.h"
+#include "feature/dirauth/dirauth_options_st.h"
 #include "feature/nodelist/node_st.h"
 #include "feature/nodelist/routerstatus_st.h"
 #include "feature/nodelist/routerinfo_st.h"
@@ -15,6 +16,7 @@
 #include "app/config/config.h"
 
 #include "test/test.h"
+#include "test/opts_test_helpers.h"
 
 typedef struct {
   time_t now;
@@ -119,7 +121,7 @@ test_voting_flags_ipv6(void *arg)
   if (!check_result(cfg))
     goto done;
 
-  get_options_mutable()->AuthDirHasIPv6Connectivity = 1;
+  get_dirauth_options(get_options_mutable())->AuthDirHasIPv6Connectivity = 1;
   // no change in expected results, since last_reachable6 won't be set.
   if (!check_result(cfg))
     goto done;