diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 5814171c5be947a2a76a167951623006baa5b93b..44e52914eeb28ec5b15df21b0579baccf232a19f 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -62,6 +62,16 @@ static cached_dir_t *the_directory = NULL;
 /** For authoritative directories: the current (v1) network status. */
 static cached_dir_t the_runningrouters;
 
+/** Array of start and end of consensus methods used for supported
+    microdescriptor formats. */
+static const struct consensus_method_range_t {
+  int low;
+  int high;
+} microdesc_consensus_methods[] = {
+  {MIN_METHOD_FOR_MICRODESC, MIN_METHOD_FOR_A_LINES - 1},
+  {MIN_METHOD_FOR_A_LINES, MAX_SUPPORTED_CONSENSUS_METHOD},
+  {-1, -1}};
+
 static void directory_remove_invalid(void);
 static cached_dir_t *dirserv_regenerate_directory(void);
 static char *format_versions_list(config_line_t *ln);
@@ -2685,7 +2695,8 @@ dirserv_read_measured_bandwidths(const char *from_file,
 }
 
 /** Return a new networkstatus_t* containing our current opinion. (For v3
- * authorities) */
+ * authorities)
+ */
 networkstatus_t *
 dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
                                         authority_cert_t *cert)
@@ -2757,6 +2768,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
   microdescriptors = smartlist_new();
 
   SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
+    const struct consensus_method_range_t *cmr = NULL;
     if (ri->cache_info.published_on >= cutoff) {
       routerstatus_t *rs;
       vote_routerstatus_t *vrs;
@@ -2778,15 +2790,20 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
         rs->is_flagged_running = 0;
 
       vrs->version = version_from_platform(ri->platform);
-      md = dirvote_create_microdescriptor(ri);
-      if (md) {
-        char buf[128];
-        vote_microdesc_hash_t *h;
-        dirvote_format_microdesc_vote_line(buf, sizeof(buf), md);
-        h = tor_malloc(sizeof(vote_microdesc_hash_t));
-        h->microdesc_hash_line = tor_strdup(buf);
-        h->next = NULL;
-        vrs->microdesc = h;
+      for (cmr = microdesc_consensus_methods;
+           cmr->low != -1 && cmr->high != -1;
+           cmr++) {
+        md = dirvote_create_microdescriptor(ri, cmr->low);
+        if (md) {
+          char buf[128];
+          vote_microdesc_hash_t *h;
+          dirvote_format_microdesc_vote_line(buf, sizeof(buf), md,
+                                             cmr->low, cmr->high);
+          h = tor_malloc(sizeof(vote_microdesc_hash_t));
+          h->microdesc_hash_line = tor_strdup(buf);
+          h->next = vrs->microdesc;
+          vrs->microdesc = h;
+        }
         md->last_listed = now;
         smartlist_add(microdescriptors, md);
       }
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index 9056cf59231af1eb04649a8fdb1db67cd8501176..e6601cffb71ef459b6d048a0df1b20ad046a734d 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -53,32 +53,6 @@ static int dirvote_compute_consensuses(void);
 static int dirvote_publish_consensus(void);
 static char *make_consensus_method_list(int low, int high, const char *sep);
 
-/** The highest consensus method that we currently support. */
-#define MAX_SUPPORTED_CONSENSUS_METHOD 14
-
-/** Lowest consensus method that contains a 'directory-footer' marker */
-#define MIN_METHOD_FOR_FOOTER 9
-
-/** Lowest consensus method that contains bandwidth weights */
-#define MIN_METHOD_FOR_BW_WEIGHTS 9
-
-/** Lowest consensus method that contains consensus params */
-#define MIN_METHOD_FOR_PARAMS 7
-
-/** Lowest consensus method that generates microdescriptors */
-#define MIN_METHOD_FOR_MICRODESC 8
-
-/** Lowest consensus method that ensures a majority of authorities voted
-  * for a param. */
-#define MIN_METHOD_FOR_MAJORITY_PARAMS 12
-
-/** Lowest consensus method where microdesc consensuses omit any entry
- * with no microdesc. */
-#define MIN_METHOD_FOR_MANDATORY_MICRODESC 13
-
-/** Lowest consensus method that contains "a" lines. */
-#define MIN_METHOD_FOR_A_LINES 14
-
 /* =====
  * Voting
  * =====*/
@@ -3570,7 +3544,7 @@ dirvote_get_vote(const char *fp, int flags)
  * particular method.
  **/
 microdesc_t *
-dirvote_create_microdescriptor(const routerinfo_t *ri)
+dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method)
 {
   microdesc_t *result = NULL;
   char *key = NULL, *summary = NULL, *family = NULL;
@@ -3586,6 +3560,12 @@ dirvote_create_microdescriptor(const routerinfo_t *ri)
 
   smartlist_add_asprintf(chunks, "onion-key\n%s", key);
 
+  if (consensus_method >= MIN_METHOD_FOR_A_LINES &&
+      !tor_addr_is_null(&ri->ipv6_addr) && ri->ipv6_orport)
+    smartlist_add_asprintf(chunks, "a %s:%d\n",
+                           fmt_and_decorate_addr(&ri->ipv6_addr),
+                           ri->ipv6_orport);
+
   if (family)
     smartlist_add_asprintf(chunks, "family %s\n", family);
 
@@ -3619,33 +3599,36 @@ dirvote_create_microdescriptor(const routerinfo_t *ri)
   return result;
 }
 
-/** Cached space-separated string to hold */
-static char *microdesc_consensus_methods = NULL;
-
 /** Format the appropriate vote line to describe the microdescriptor <b>md</b>
  * in a consensus vote document.  Write it into the <b>out_len</b>-byte buffer
  * in <b>out</b>.  Return -1 on failure and the number of characters written
  * on success. */
 ssize_t
-dirvote_format_microdesc_vote_line(char *out, size_t out_len,
-                                   const microdesc_t *md)
+dirvote_format_microdesc_vote_line(char *out_buf, size_t out_buf_len,
+                                   const microdesc_t *md,
+                                   int consensus_method_low,
+                                   int consensus_method_high)
 {
+  int ret = -1;
   char d64[BASE64_DIGEST256_LEN+1];
-  if (!microdesc_consensus_methods) {
-    microdesc_consensus_methods =
-      make_consensus_method_list(MIN_METHOD_FOR_MICRODESC,
-                                 MAX_SUPPORTED_CONSENSUS_METHOD,
-                                 ",");
-    tor_assert(microdesc_consensus_methods);
-  }
+  char *microdesc_consensus_methods =
+    make_consensus_method_list(consensus_method_low,
+                               consensus_method_high,
+                               ",");
+  tor_assert(microdesc_consensus_methods);
+
   if (digest256_to_base64(d64, md->digest)<0)
-    return -1;
+    goto out;
 
-  if (tor_snprintf(out, out_len, "m %s sha256=%s\n",
+  if (tor_snprintf(out_buf, out_buf_len, "m %s sha256=%s\n",
                    microdesc_consensus_methods, d64)<0)
-    return -1;
+    goto out;
 
-  return strlen(out);
+  ret = strlen(out_buf);
+
+ out:
+  tor_free(microdesc_consensus_methods);
+  return ret;
 }
 
 /** If <b>vrs</b> has a hash made for the consensus method <b>method</b> with
diff --git a/src/or/dirvote.h b/src/or/dirvote.h
index e6f9700614607023e3e316f89f8302eeac35261e..b3feeff06029d5f5f18a66f6516376a4303cbf01 100644
--- a/src/or/dirvote.h
+++ b/src/or/dirvote.h
@@ -19,6 +19,32 @@
 /** Smallest allowable voting interval. */
 #define MIN_VOTE_INTERVAL 300
 
+/** The highest consensus method that we currently support. */
+#define MAX_SUPPORTED_CONSENSUS_METHOD 14
+
+/** Lowest consensus method that contains a 'directory-footer' marker */
+#define MIN_METHOD_FOR_FOOTER 9
+
+/** Lowest consensus method that contains bandwidth weights */
+#define MIN_METHOD_FOR_BW_WEIGHTS 9
+
+/** Lowest consensus method that contains consensus params */
+#define MIN_METHOD_FOR_PARAMS 7
+
+/** Lowest consensus method that generates microdescriptors */
+#define MIN_METHOD_FOR_MICRODESC 8
+
+/** Lowest consensus method that ensures a majority of authorities voted
+  * for a param. */
+#define MIN_METHOD_FOR_MAJORITY_PARAMS 12
+
+/** Lowest consensus method where microdesc consensuses omit any entry
+ * with no microdesc. */
+#define MIN_METHOD_FOR_MANDATORY_MICRODESC 13
+
+/** Lowest consensus method that contains "a" lines. */
+#define MIN_METHOD_FOR_A_LINES 14
+
 void dirvote_free_all(void);
 
 /* vote manipulation */
@@ -70,10 +96,11 @@ networkstatus_t *
 dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
                                         authority_cert_t *cert);
 
-microdesc_t *dirvote_create_microdescriptor(const routerinfo_t *ri);
+microdesc_t *dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method);
 ssize_t dirvote_format_microdesc_vote_line(char *out, size_t out_len,
-                                       const microdesc_t *md);
-
+                                           const microdesc_t *md,
+                                           int consensus_method_low,
+                                           int consensus_method_high);
 int vote_routerstatus_find_microdesc_hash(char *digest256_out,
                                           const vote_routerstatus_t *vrs,
                                           int method,