diff --git a/src/or/circpathbias.c b/src/or/circpathbias.c
index ff42bf91e4450f9b400faa32cbc87e4f53291dbf..f139c6d7e5fd5595a32b7437670ed873f28413b6 100644
--- a/src/or/circpathbias.c
+++ b/src/or/circpathbias.c
@@ -35,6 +35,8 @@
 #include "networkstatus.h"
 #include "relay.h"
 
+#include "origin_circuit_st.h"
+
 static void pathbias_count_successful_close(origin_circuit_t *circ);
 static void pathbias_count_collapse(origin_circuit_t *circ);
 static void pathbias_count_use_failed(origin_circuit_t *circ);
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 883f9307417f9ff9a0137ecb54af51f4590042d5..c5d1c65f59a167705c12163c6098d6ff255d5baa 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -66,6 +66,8 @@
 #include "transports.h"
 
 #include "entry_connection_st.h"
+#include "or_circuit_st.h"
+#include "origin_circuit_st.h"
 
 static channel_t * channel_connect_for_circuit(const tor_addr_t *addr,
                                             uint16_t port,
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 1a3f3a2290b4d3379864fcbdcc065a3f22a9ad82..7601bc613578970531fb026800eb23d32de5f835 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -94,6 +94,8 @@
 
 #include "dir_connection_st.h"
 #include "edge_connection_st.h"
+#include "or_circuit_st.h"
+#include "origin_circuit_st.h"
 
 /********* START VARIABLES **********/
 
@@ -130,6 +132,31 @@ static int any_opened_circs_cached_val = 0;
 
 /********* END VARIABLES ************/
 
+or_circuit_t *
+TO_OR_CIRCUIT(circuit_t *x)
+{
+  tor_assert(x->magic == OR_CIRCUIT_MAGIC);
+  return DOWNCAST(or_circuit_t, x);
+}
+const or_circuit_t *
+CONST_TO_OR_CIRCUIT(const circuit_t *x)
+{
+  tor_assert(x->magic == OR_CIRCUIT_MAGIC);
+  return DOWNCAST(or_circuit_t, x);
+}
+origin_circuit_t *
+TO_ORIGIN_CIRCUIT(circuit_t *x)
+{
+  tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC);
+  return DOWNCAST(origin_circuit_t, x);
+}
+const origin_circuit_t *
+CONST_TO_ORIGIN_CIRCUIT(const circuit_t *x)
+{
+  tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC);
+  return DOWNCAST(origin_circuit_t, x);
+}
+
 /** A map from channel and circuit ID to circuit.  (Lookup performance is
  * very important here, since we need to do it every time a cell arrives.) */
 typedef struct chan_circid_circuit_map_t {
diff --git a/src/or/circuitlist.h b/src/or/circuitlist.h
index 246f0c881585441f00e3205a2de9eafb822c1306..8eb6fefbfeb9b8bc87ac709487be7dac1d60403f 100644
--- a/src/or/circuitlist.h
+++ b/src/or/circuitlist.h
@@ -15,6 +15,15 @@
 #include "testsupport.h"
 #include "hs_ident.h"
 
+/** Convert a circuit_t* to a pointer to the enclosing or_circuit_t.  Assert
+ * if the cast is impossible. */
+or_circuit_t *TO_OR_CIRCUIT(circuit_t *);
+const or_circuit_t *CONST_TO_OR_CIRCUIT(const circuit_t *);
+/** Convert a circuit_t* to a pointer to the enclosing origin_circuit_t.
+ * Assert if the cast is impossible. */
+origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *);
+const origin_circuit_t *CONST_TO_ORIGIN_CIRCUIT(const circuit_t *);
+
 MOCK_DECL(smartlist_t *, circuit_get_global_list, (void));
 smartlist_t *circuit_get_global_origin_circuit_list(void);
 int circuit_any_opened_circuits(void);
diff --git a/src/or/circuitmux.c b/src/or/circuitmux.c
index f9f5faa05785ea8ef36abc3b3c7776a0467a094a..5f7f002f41dcbcba2491a5244d9c12adf41f5d5f 100644
--- a/src/or/circuitmux.c
+++ b/src/or/circuitmux.c
@@ -75,6 +75,8 @@
 #include "circuitmux.h"
 #include "relay.h"
 
+#include "or_circuit_st.h"
+
 /*
  * Private typedefs for circuitmux.c
  */
diff --git a/src/or/circuitstats.c b/src/or/circuitstats.c
index 94f75c590f4fc4ce63e4c709f312c1ba87cec859..bff553a02ba74cc188c36a4108a279fce545ddaa 100644
--- a/src/or/circuitstats.c
+++ b/src/or/circuitstats.c
@@ -41,6 +41,8 @@
 #include "circuitlist.h"
 #include "circuituse.h"
 
+#include "origin_circuit_st.h"
+
 #undef log
 #include <math.h>
 
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 45eeff433260b9b36f24afc8a0d6f5044e91e887..3a18c3403879d2ce617d68098a75955cb5806a7e 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -59,6 +59,8 @@
 
 #include "dir_connection_st.h"
 #include "entry_connection_st.h"
+#include "or_circuit_st.h"
+#include "origin_circuit_st.h"
 
 static void circuit_expire_old_circuits_clientside(void);
 static void circuit_increment_failure_count(void);
diff --git a/src/or/command.c b/src/or/command.c
index 39950f41bfa81779889a8d8c6200118c88beaba6..148578a26b6758966606fa3d2a93f1d0bee56dbd 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -56,6 +56,9 @@
 #include "router.h"
 #include "routerlist.h"
 
+#include "or_circuit_st.h"
+#include "origin_circuit_st.h"
+
 /** How many CELL_CREATE cells have we received, ever? */
 uint64_t stats_n_create_cells_processed = 0;
 /** How many CELL_CREATED cells have we received, ever? */
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 1ba61609bc2e66f1738a1d9690e6a38dff7647af..b972724a805c826e0b29f34c632eb63be930b700 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -99,6 +99,8 @@
 
 #include "dir_connection_st.h"
 #include "entry_connection_st.h"
+#include "or_circuit_st.h"
+#include "origin_circuit_st.h"
 
 #ifdef HAVE_LINUX_TYPES_H
 #include <linux/types.h>
diff --git a/src/or/control.c b/src/or/control.c
index 45914f0c1704263c6b710b55825b7ef14f0ac53c..18377880197be02fea22c9eb12d6ebc1d3cfe9f7 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -84,6 +84,8 @@
 #include "control_connection_st.h"
 #include "entry_connection_st.h"
 #include "or_connection_st.h"
+#include "or_circuit_st.h"
+#include "origin_circuit_st.h"
 
 #ifndef _WIN32
 #include <pwd.h>
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index 15ef6869cfd736408e2946896542c25d026ae331..ad66268c3a7f4db00fb3b00d2ff1e792a17560cc 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -32,6 +32,8 @@
 #include "router.h"
 #include "workqueue.h"
 
+#include "or_circuit_st.h"
+
 static void queue_pending_tasks(void);
 
 typedef struct worker_state_s {
diff --git a/src/or/directory.h b/src/or/directory.h
index e94c02b6c5088b0e883dbf2ccd86442ba084033b..8823de4d9a83dbc5c220f310b4c30f7061aa6f92 100644
--- a/src/or/directory.h
+++ b/src/or/directory.h
@@ -61,6 +61,7 @@ void directory_request_set_dir_addr_port(directory_request_t *req,
                                          const tor_addr_port_t *p);
 void directory_request_set_directory_id_digest(directory_request_t *req,
                                                const char *digest);
+struct circuit_guard_state_t;
 void directory_request_set_guard_state(directory_request_t *req,
                                        struct circuit_guard_state_t *state);
 void directory_request_set_router_purpose(directory_request_t *req,
diff --git a/src/or/dns.c b/src/or/dns.c
index 422751553ddd0570ab3da985c15b358dc2ade555..defc86bc930eb0a4f2d736adb1d695917e68d47e 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -66,6 +66,7 @@
 #include "sandbox.h"
 
 #include "edge_connection_st.h"
+#include "or_circuit_st.h"
 
 #include <event2/event.h>
 #include <event2/dns.h>
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 27d760f1a8b30dc82bb3784e5a4ec2fcd4f4f764..8aac07451c8af56625214972fef5008df497d17b 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -139,6 +139,8 @@
 #include "transports.h"
 #include "statefile.h"
 
+#include "origin_circuit_st.h"
+
 /** A list of existing guard selection contexts. */
 static smartlist_t *guard_contexts = NULL;
 /** The currently enabled guard selection context. */
diff --git a/src/or/hs_cell.c b/src/or/hs_cell.c
index 03273a44f903592420b7e98312dd529f081523fb..f5ed3df571d9f6fb71e188364d021825e419cc00 100644
--- a/src/or/hs_cell.c
+++ b/src/or/hs_cell.c
@@ -16,6 +16,8 @@
 #include "hs_cell.h"
 #include "hs_ntor.h"
 
+#include "origin_circuit_st.h"
+
 /* Trunnel. */
 #include "ed25519_cert.h"
 #include "hs/cell_common.h"
diff --git a/src/or/hs_circuit.c b/src/or/hs_circuit.c
index a35d2af8bafcc7fbef7ca09d42fb6d7fa6c8dece..189ebdc1b93eecb9d91a84ffe4064fd83899b1aa 100644
--- a/src/or/hs_circuit.c
+++ b/src/or/hs_circuit.c
@@ -33,6 +33,8 @@
 #include "hs/cell_common.h"
 #include "hs/cell_establish_intro.h"
 
+#include "origin_circuit_st.h"
+
 /* A circuit is about to become an e2e rendezvous circuit. Check
  * <b>circ_purpose</b> and ensure that it's properly set. Return true iff
  * circuit purpose is properly set, otherwise return false. */
diff --git a/src/or/hs_circuitmap.c b/src/or/hs_circuitmap.c
index 112c8bdced9a93d46df0031e766acd6557ff2f31..fd0a01f8ba6f6deb4271de9f9c742b49e45f4d49 100644
--- a/src/or/hs_circuitmap.c
+++ b/src/or/hs_circuitmap.c
@@ -18,6 +18,9 @@
 #include "circuitlist.h"
 #include "hs_circuitmap.h"
 
+#include "or_circuit_st.h"
+#include "origin_circuit_st.h"
+
 /************************** HS circuitmap code *******************************/
 
 /* This is the hidden service circuitmap. It's a hash table that maps
diff --git a/src/or/hs_client.c b/src/or/hs_client.c
index ff84296d04e84bde85ded7b9bcfc2dd18b5baa07..c4db60e527de36e22b836da81ec5ded1f6359f35 100644
--- a/src/or/hs_client.c
+++ b/src/or/hs_client.c
@@ -37,6 +37,7 @@
 
 #include "dir_connection_st.h"
 #include "entry_connection_st.h"
+#include "origin_circuit_st.h"
 
 /* Return a human-readable string for the client fetch status code. */
 static const char *
diff --git a/src/or/hs_common.c b/src/or/hs_common.c
index 33c09b53fe4a75af02366893638f3313481fcf2f..afe80467aadf726ce3a360067e5acbb97a87e0a7 100644
--- a/src/or/hs_common.c
+++ b/src/or/hs_common.c
@@ -34,6 +34,7 @@
 #include "dirauth/shared_random_state.h"
 
 #include "edge_connection_st.h"
+#include "origin_circuit_st.h"
 
 /* Trunnel */
 #include "ed25519_cert.h"
diff --git a/src/or/hs_intropoint.c b/src/or/hs_intropoint.c
index 3274e8e9c06d32064123ca0505d4ff5d6d0f1a97..58416fbe93ff77c116883ec167a739b8d3f74125 100644
--- a/src/or/hs_intropoint.c
+++ b/src/or/hs_intropoint.c
@@ -27,6 +27,8 @@
 #include "hs_intropoint.h"
 #include "hs_common.h"
 
+#include "or_circuit_st.h"
+
 /** Extract the authentication key from an ESTABLISH_INTRO or INTRODUCE1 using
  * the given <b>cell_type</b> from <b>cell</b> and place it in
  * <b>auth_key_out</b>. */
diff --git a/src/or/hs_service.c b/src/or/hs_service.c
index 9f12484ebee54b1435a9507e83999b2504813950..6c2c167347ef0347814410eca957c83bdbfca6f8 100644
--- a/src/or/hs_service.c
+++ b/src/or/hs_service.c
@@ -41,6 +41,7 @@
 
 #include "dir_connection_st.h"
 #include "edge_connection_st.h"
+#include "origin_circuit_st.h"
 
 /* Trunnel */
 #include "ed25519_cert.h"
diff --git a/src/or/include.am b/src/or/include.am
index de263e9b8cce69220ca1cb75e862eec3334f9ceb..eb8b52e93c3e756a77a1510b3529ba6115c6b048 100644
--- a/src/or/include.am
+++ b/src/or/include.am
@@ -250,9 +250,11 @@ ORHEADERS = \
 	src/or/onion_ntor.h				\
 	src/or/onion_tap.h				\
 	src/or/or.h					\
+	src/or/or_circuit_st.h				\
 	src/or/or_connection_st.h			\
 	src/or/or_handshake_certs_st.h			\
 	src/or/or_handshake_state_st.h			\
+	src/or/origin_circuit_st.h			\
 	src/or/transports.h				\
 	src/or/parsecommon.h			\
 	src/or/periodic.h				\
diff --git a/src/or/onion.c b/src/or/onion.c
index 829be12bae8cf94540490577af2f2b1f0ee28e5c..813ad265ee8a603279f03a22c23a692edf4c83c7 100644
--- a/src/or/onion.c
+++ b/src/or/onion.c
@@ -77,6 +77,8 @@
 #include "rephist.h"
 #include "router.h"
 
+#include "or_circuit_st.h"
+
 // trunnel
 #include "ed25519_cert.h"
 
diff --git a/src/or/or.h b/src/or/or.h
index c3506d3ffd69fff2017b667ecbf5060e279221f1..61987d8254f72a7dd08ba6f842c5ec13cfbb2cf0 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2561,6 +2561,9 @@ typedef struct circuit_t {
   HT_ENTRY(circuit_t) hs_circuitmap_node;
 } circuit_t;
 
+typedef struct origin_circuit_t origin_circuit_t;
+typedef struct or_circuit_t or_circuit_t;
+
 /** Largest number of relay_early cells that we can send on a given
  * circuit. */
 #define MAX_RELAY_EARLY_CELLS_PER_CIRCUIT 8
@@ -2622,288 +2625,6 @@ typedef enum {
 } path_state_t;
 #define path_state_bitfield_t ENUM_BF(path_state_t)
 
-/** An origin_circuit_t holds data necessary to build and use a circuit.
- */
-typedef struct origin_circuit_t {
-  circuit_t base_;
-
-  /** Linked list of AP streams (or EXIT streams if hidden service)
-   * associated with this circuit. */
-  edge_connection_t *p_streams;
-
-  /** Bytes read on this circuit since last call to
-   * control_event_circ_bandwidth_used().  Only used if we're configured
-   * to emit CIRC_BW events. */
-  uint32_t n_read_circ_bw;
-
-  /** Bytes written to on this circuit since last call to
-   * control_event_circ_bandwidth_used().  Only used if we're configured
-   * to emit CIRC_BW events. */
-  uint32_t n_written_circ_bw;
-
-  /** Total known-valid relay cell bytes since last call to
-   * control_event_circ_bandwidth_used().  Only used if we're configured
-   * to emit CIRC_BW events. */
-  uint32_t n_delivered_read_circ_bw;
-
-  /** Total written relay cell bytes since last call to
-   * control_event_circ_bandwidth_used().  Only used if we're configured
-   * to emit CIRC_BW events. */
-  uint32_t n_delivered_written_circ_bw;
-
-  /** Total overhead data in all known-valid relay data cells since last
-   * call to control_event_circ_bandwidth_used().  Only used if we're
-   * configured to emit CIRC_BW events. */
-  uint32_t n_overhead_read_circ_bw;
-
-  /** Total written overhead data in all relay data cells since last call to
-   * control_event_circ_bandwidth_used().  Only used if we're configured
-   * to emit CIRC_BW events. */
-  uint32_t n_overhead_written_circ_bw;
-
-  /** Build state for this circuit. It includes the intended path
-   * length, the chosen exit router, rendezvous information, etc.
-   */
-  cpath_build_state_t *build_state;
-  /** The doubly-linked list of crypt_path_t entries, one per hop,
-   * for this circuit. This includes ciphers for each hop,
-   * integrity-checking digests for each hop, and package/delivery
-   * windows for each hop.
-   */
-  crypt_path_t *cpath;
-
-  /** Holds all rendezvous data on either client or service side. */
-  rend_data_t *rend_data;
-
-  /** Holds hidden service identifier on either client or service side. This
-   * is for both introduction and rendezvous circuit. */
-  struct hs_ident_circuit_t *hs_ident;
-
-  /** Holds the data that the entry guard system uses to track the
-   * status of the guard this circuit is using, and thereby to determine
-   * whether this circuit can be used. */
-  struct circuit_guard_state_t *guard_state;
-
-  /** Index into global_origin_circuit_list for this circuit. -1 if not
-   * present. */
-  int global_origin_circuit_list_idx;
-
-  /** How many more relay_early cells can we send on this circuit, according
-   * to the specification? */
-  unsigned int remaining_relay_early_cells : 4;
-
-  /** Set if this circuit is insanely old and we already informed the user */
-  unsigned int is_ancient : 1;
-
-  /** Set if this circuit has already been opened. Used to detect
-   * cannibalized circuits. */
-  unsigned int has_opened : 1;
-
-  /**
-   * Path bias state machine. Used to ensure integrity of our
-   * circuit building and usage accounting. See path_state_t
-   * for more details.
-   */
-  path_state_bitfield_t path_state : 3;
-
-  /* If this flag is set, we should not consider attaching any more
-   * connections to this circuit. */
-  unsigned int unusable_for_new_conns : 1;
-
-  /**
-   * Tristate variable to guard against pathbias miscounting
-   * due to circuit purpose transitions changing the decision
-   * of pathbias_should_count(). This variable is informational
-   * only. The current results of pathbias_should_count() are
-   * the official decision for pathbias accounting.
-   */
-  uint8_t pathbias_shouldcount;
-#define PATHBIAS_SHOULDCOUNT_UNDECIDED 0
-#define PATHBIAS_SHOULDCOUNT_IGNORED   1
-#define PATHBIAS_SHOULDCOUNT_COUNTED   2
-
-  /** For path probing. Store the temporary probe stream ID
-   * for response comparison */
-  streamid_t pathbias_probe_id;
-
-  /** For path probing. Store the temporary probe address nonce
-   * (in host byte order) for response comparison. */
-  uint32_t pathbias_probe_nonce;
-
-  /** Set iff this is a hidden-service circuit which has timed out
-   * according to our current circuit-build timeout, but which has
-   * been kept around because it might still succeed in connecting to
-   * its destination, and which is not a fully-connected rendezvous
-   * circuit.
-   *
-   * (We clear this flag for client-side rendezvous circuits when they
-   * are 'joined' to the other side's rendezvous circuit, so that
-   * connection_ap_handshake_attach_circuit can put client streams on
-   * the circuit.  We also clear this flag for service-side rendezvous
-   * circuits when they are 'joined' to a client's rend circ, but only
-   * for symmetry with the client case.  Client-side introduction
-   * circuits are closed when we get a joined rend circ, and
-   * service-side introduction circuits never have this flag set.) */
-  unsigned int hs_circ_has_timed_out : 1;
-
-  /** Set iff this circuit has been given a relaxed timeout because
-   * no circuits have opened. Used to prevent spamming logs. */
-  unsigned int relaxed_timeout : 1;
-
-  /** Set iff this is a service-side rendezvous circuit for which a
-   * new connection attempt has been launched.  We consider launching
-   * a new service-side rend circ to a client when the previous one
-   * fails; now that we don't necessarily close a service-side rend
-   * circ when we launch a new one to the same client, this flag keeps
-   * us from launching two retries for the same failed rend circ. */
-  unsigned int hs_service_side_rend_circ_has_been_relaunched : 1;
-
-  /** What commands were sent over this circuit that decremented the
-   * RELAY_EARLY counter? This is for debugging task 878. */
-  uint8_t relay_early_commands[MAX_RELAY_EARLY_CELLS_PER_CIRCUIT];
-
-  /** How many RELAY_EARLY cells have been sent over this circuit? This is
-   * for debugging task 878, too. */
-  int relay_early_cells_sent;
-
-  /** The next stream_id that will be tried when we're attempting to
-   * construct a new AP stream originating at this circuit. */
-  streamid_t next_stream_id;
-
-  /* The intro key replaces the hidden service's public key if purpose is
-   * S_ESTABLISH_INTRO or S_INTRO, provided that no unversioned rendezvous
-   * descriptor is used. */
-  crypto_pk_t *intro_key;
-
-  /** Quasi-global identifier for this circuit; used for control.c */
-  /* XXXX NM This can get re-used after 2**32 circuits. */
-  uint32_t global_identifier;
-
-  /** True if we have associated one stream to this circuit, thereby setting
-   * the isolation parameters for this circuit.  Note that this doesn't
-   * necessarily mean that we've <em>attached</em> any streams to the circuit:
-   * we may only have marked up this circuit during the launch process.
-   */
-  unsigned int isolation_values_set : 1;
-  /** True iff any stream has <em>ever</em> been attached to this circuit.
-   *
-   * In a better world we could use timestamp_dirty for this, but
-   * timestamp_dirty is far too overloaded at the moment.
-   */
-  unsigned int isolation_any_streams_attached : 1;
-
-  /** A bitfield of ISO_* flags for every isolation field such that this
-   * circuit has had streams with more than one value for that field
-   * attached to it. */
-  uint8_t isolation_flags_mixed;
-
-  /** @name Isolation parameters
-   *
-   * If any streams have been associated with this circ (isolation_values_set
-   * == 1), and all streams associated with the circuit have had the same
-   * value for some field ((isolation_flags_mixed & ISO_FOO) == 0), then these
-   * elements hold the value for that field.
-   *
-   * Note again that "associated" is not the same as "attached": we
-   * preliminarily associate streams with a circuit while the circuit is being
-   * launched, so that we can tell whether we need to launch more circuits.
-   *
-   * @{
-   */
-  uint8_t client_proto_type;
-  uint8_t client_proto_socksver;
-  uint16_t dest_port;
-  tor_addr_t client_addr;
-  char *dest_address;
-  int session_group;
-  unsigned nym_epoch;
-  size_t socks_username_len;
-  uint8_t socks_password_len;
-  /* Note that the next two values are NOT NUL-terminated; see
-     socks_username_len and socks_password_len for their lengths. */
-  char *socks_username;
-  char *socks_password;
-  /** Global identifier for the first stream attached here; used by
-   * ISO_STREAM. */
-  uint64_t associated_isolated_stream_global_id;
-  /**@}*/
-  /** A list of addr_policy_t for this circuit in particular. Used by
-   * adjust_exit_policy_from_exitpolicy_failure.
-   */
-  smartlist_t *prepend_policy;
-
-  /** How long do we wait before closing this circuit if it remains
-   * completely idle after it was built, in seconds? This value
-   * is randomized on a per-circuit basis from CircuitsAvailableTimoeut
-   * to 2*CircuitsAvailableTimoeut. */
-  int circuit_idle_timeout;
-
-} origin_circuit_t;
-
-struct onion_queue_t;
-
-/** An or_circuit_t holds information needed to implement a circuit at an
- * OR. */
-typedef struct or_circuit_t {
-  circuit_t base_;
-
-  /** Pointer to an entry on the onion queue, if this circuit is waiting for a
-   * chance to give an onionskin to a cpuworker. Used only in onion.c */
-  struct onion_queue_t *onionqueue_entry;
-  /** Pointer to a workqueue entry, if this circuit has given an onionskin to
-   * a cpuworker and is waiting for a response. Used to decide whether it is
-   * safe to free a circuit or if it is still in use by a cpuworker. */
-  struct workqueue_entry_s *workqueue_entry;
-
-  /** The circuit_id used in the previous (backward) hop of this circuit. */
-  circid_t p_circ_id;
-  /** Queue of cells waiting to be transmitted on p_conn. */
-  cell_queue_t p_chan_cells;
-  /** The channel that is previous in this circuit. */
-  channel_t *p_chan;
-  /**
-   * Circuit mux associated with p_chan to which this circuit is attached;
-   * NULL if we have no p_chan.
-   */
-  circuitmux_t *p_mux;
-  /** Linked list of Exit streams associated with this circuit. */
-  edge_connection_t *n_streams;
-  /** Linked list of Exit streams associated with this circuit that are
-   * still being resolved. */
-  edge_connection_t *resolving_streams;
-
-  /** Cryptographic state used for encrypting and authenticating relay
-   * cells to and from this hop. */
-  relay_crypto_t crypto;
-
-  /** Points to spliced circuit if purpose is REND_ESTABLISHED, and circuit
-   * is not marked for close. */
-  struct or_circuit_t *rend_splice;
-
-  /** Stores KH for the handshake. */
-  char rend_circ_nonce[DIGEST_LEN];/* KH in tor-spec.txt */
-
-  /** How many more relay_early cells can we send on this circuit, according
-   * to the specification? */
-  unsigned int remaining_relay_early_cells : 4;
-
-  /* We have already received an INTRODUCE1 cell on this circuit. */
-  unsigned int already_received_introduce1 : 1;
-
-  /** If set, this circuit carries HS traffic. Consider it in any HS
-   *  statistics. */
-  unsigned int circuit_carries_hs_traffic_stats : 1;
-
-  /** Number of cells that were removed from circuit queue; reset every
-   * time when writing buffer stats to disk. */
-  uint32_t processed_cells;
-
-  /** Total time in milliseconds that cells spent in both app-ward and
-   * exit-ward queues of this circuit; reset every time when writing
-   * buffer stats to disk. */
-  uint64_t total_cell_waiting_time;
-} or_circuit_t;
-
 #if REND_COOKIE_LEN != DIGEST_LEN
 #error "The REND_TOKEN_LEN macro assumes REND_COOKIE_LEN == DIGEST_LEN"
 #endif
@@ -2912,15 +2633,6 @@ typedef struct or_circuit_t {
 /** Convert a circuit subtype to a circuit_t. */
 #define TO_CIRCUIT(x)  (&((x)->base_))
 
-/** Convert a circuit_t* to a pointer to the enclosing or_circuit_t.  Assert
- * if the cast is impossible. */
-static or_circuit_t *TO_OR_CIRCUIT(circuit_t *);
-static const or_circuit_t *CONST_TO_OR_CIRCUIT(const circuit_t *);
-/** Convert a circuit_t* to a pointer to the enclosing origin_circuit_t.
- * Assert if the cast is impossible. */
-static origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *);
-static const origin_circuit_t *CONST_TO_ORIGIN_CIRCUIT(const circuit_t *);
-
 /** Return 1 iff <b>node</b> has Exit flag and no BadExit flag.
  * Otherwise, return 0.
  */
@@ -2929,28 +2641,6 @@ static inline int node_is_good_exit(const node_t *node)
   return node->is_exit && ! node->is_bad_exit;
 }
 
-static inline or_circuit_t *TO_OR_CIRCUIT(circuit_t *x)
-{
-  tor_assert(x->magic == OR_CIRCUIT_MAGIC);
-  return DOWNCAST(or_circuit_t, x);
-}
-static inline const or_circuit_t *CONST_TO_OR_CIRCUIT(const circuit_t *x)
-{
-  tor_assert(x->magic == OR_CIRCUIT_MAGIC);
-  return DOWNCAST(or_circuit_t, x);
-}
-static inline origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *x)
-{
-  tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC);
-  return DOWNCAST(origin_circuit_t, x);
-}
-static inline const origin_circuit_t *CONST_TO_ORIGIN_CIRCUIT(
-    const circuit_t *x)
-{
-  tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC);
-  return DOWNCAST(origin_circuit_t, x);
-}
-
 /* limits for TCP send and recv buffer size used for constrained sockets */
 #define MIN_CONSTRAINED_TCP_BUFFER 2048
 #define MAX_CONSTRAINED_TCP_BUFFER 262144  /* 256k */
diff --git a/src/or/or_circuit_st.h b/src/or/or_circuit_st.h
new file mode 100644
index 0000000000000000000000000000000000000000..19c39f8e678420004dd25b2f16875abb02364846
--- /dev/null
+++ b/src/or/or_circuit_st.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef OR_CIRCUIT_ST_H
+#define OR_CIRCUIT_ST_H
+
+#include "or.h"
+
+struct onion_queue_t;
+
+/** An or_circuit_t holds information needed to implement a circuit at an
+ * OR. */
+struct or_circuit_t {
+  circuit_t base_;
+
+  /** Pointer to an entry on the onion queue, if this circuit is waiting for a
+   * chance to give an onionskin to a cpuworker. Used only in onion.c */
+  struct onion_queue_t *onionqueue_entry;
+  /** Pointer to a workqueue entry, if this circuit has given an onionskin to
+   * a cpuworker and is waiting for a response. Used to decide whether it is
+   * safe to free a circuit or if it is still in use by a cpuworker. */
+  struct workqueue_entry_s *workqueue_entry;
+
+  /** The circuit_id used in the previous (backward) hop of this circuit. */
+  circid_t p_circ_id;
+  /** Queue of cells waiting to be transmitted on p_conn. */
+  cell_queue_t p_chan_cells;
+  /** The channel that is previous in this circuit. */
+  channel_t *p_chan;
+  /**
+   * Circuit mux associated with p_chan to which this circuit is attached;
+   * NULL if we have no p_chan.
+   */
+  circuitmux_t *p_mux;
+  /** Linked list of Exit streams associated with this circuit. */
+  edge_connection_t *n_streams;
+  /** Linked list of Exit streams associated with this circuit that are
+   * still being resolved. */
+  edge_connection_t *resolving_streams;
+
+  /** Cryptographic state used for encrypting and authenticating relay
+   * cells to and from this hop. */
+  relay_crypto_t crypto;
+
+  /** Points to spliced circuit if purpose is REND_ESTABLISHED, and circuit
+   * is not marked for close. */
+  struct or_circuit_t *rend_splice;
+
+  /** Stores KH for the handshake. */
+  char rend_circ_nonce[DIGEST_LEN];/* KH in tor-spec.txt */
+
+  /** How many more relay_early cells can we send on this circuit, according
+   * to the specification? */
+  unsigned int remaining_relay_early_cells : 4;
+
+  /* We have already received an INTRODUCE1 cell on this circuit. */
+  unsigned int already_received_introduce1 : 1;
+
+  /** If set, this circuit carries HS traffic. Consider it in any HS
+   *  statistics. */
+  unsigned int circuit_carries_hs_traffic_stats : 1;
+
+  /** Number of cells that were removed from circuit queue; reset every
+   * time when writing buffer stats to disk. */
+  uint32_t processed_cells;
+
+  /** Total time in milliseconds that cells spent in both app-ward and
+   * exit-ward queues of this circuit; reset every time when writing
+   * buffer stats to disk. */
+  uint64_t total_cell_waiting_time;
+};
+
+#endif
+
diff --git a/src/or/origin_circuit_st.h b/src/or/origin_circuit_st.h
new file mode 100644
index 0000000000000000000000000000000000000000..e995776c2022692eb14e3336debbcba93cfbfcba
--- /dev/null
+++ b/src/or/origin_circuit_st.h
@@ -0,0 +1,233 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef ORIGIN_CIRCUIT_ST_H
+#define ORIGIN_CIRCUIT_ST_H
+
+#include "or.h"
+
+struct onion_queue_t;
+
+/** An origin_circuit_t holds data necessary to build and use a circuit.
+ */
+struct origin_circuit_t {
+  circuit_t base_;
+
+  /** Linked list of AP streams (or EXIT streams if hidden service)
+   * associated with this circuit. */
+  edge_connection_t *p_streams;
+
+  /** Bytes read on this circuit since last call to
+   * control_event_circ_bandwidth_used().  Only used if we're configured
+   * to emit CIRC_BW events. */
+  uint32_t n_read_circ_bw;
+
+  /** Bytes written to on this circuit since last call to
+   * control_event_circ_bandwidth_used().  Only used if we're configured
+   * to emit CIRC_BW events. */
+  uint32_t n_written_circ_bw;
+
+  /** Total known-valid relay cell bytes since last call to
+   * control_event_circ_bandwidth_used().  Only used if we're configured
+   * to emit CIRC_BW events. */
+  uint32_t n_delivered_read_circ_bw;
+
+  /** Total written relay cell bytes since last call to
+   * control_event_circ_bandwidth_used().  Only used if we're configured
+   * to emit CIRC_BW events. */
+  uint32_t n_delivered_written_circ_bw;
+
+  /** Total overhead data in all known-valid relay data cells since last
+   * call to control_event_circ_bandwidth_used().  Only used if we're
+   * configured to emit CIRC_BW events. */
+  uint32_t n_overhead_read_circ_bw;
+
+  /** Total written overhead data in all relay data cells since last call to
+   * control_event_circ_bandwidth_used().  Only used if we're configured
+   * to emit CIRC_BW events. */
+  uint32_t n_overhead_written_circ_bw;
+
+  /** Build state for this circuit. It includes the intended path
+   * length, the chosen exit router, rendezvous information, etc.
+   */
+  cpath_build_state_t *build_state;
+  /** The doubly-linked list of crypt_path_t entries, one per hop,
+   * for this circuit. This includes ciphers for each hop,
+   * integrity-checking digests for each hop, and package/delivery
+   * windows for each hop.
+   */
+  crypt_path_t *cpath;
+
+  /** Holds all rendezvous data on either client or service side. */
+  rend_data_t *rend_data;
+
+  /** Holds hidden service identifier on either client or service side. This
+   * is for both introduction and rendezvous circuit. */
+  struct hs_ident_circuit_t *hs_ident;
+
+  /** Holds the data that the entry guard system uses to track the
+   * status of the guard this circuit is using, and thereby to determine
+   * whether this circuit can be used. */
+  struct circuit_guard_state_t *guard_state;
+
+  /** Index into global_origin_circuit_list for this circuit. -1 if not
+   * present. */
+  int global_origin_circuit_list_idx;
+
+  /** How many more relay_early cells can we send on this circuit, according
+   * to the specification? */
+  unsigned int remaining_relay_early_cells : 4;
+
+  /** Set if this circuit is insanely old and we already informed the user */
+  unsigned int is_ancient : 1;
+
+  /** Set if this circuit has already been opened. Used to detect
+   * cannibalized circuits. */
+  unsigned int has_opened : 1;
+
+  /**
+   * Path bias state machine. Used to ensure integrity of our
+   * circuit building and usage accounting. See path_state_t
+   * for more details.
+   */
+  path_state_bitfield_t path_state : 3;
+
+  /* If this flag is set, we should not consider attaching any more
+   * connections to this circuit. */
+  unsigned int unusable_for_new_conns : 1;
+
+  /**
+   * Tristate variable to guard against pathbias miscounting
+   * due to circuit purpose transitions changing the decision
+   * of pathbias_should_count(). This variable is informational
+   * only. The current results of pathbias_should_count() are
+   * the official decision for pathbias accounting.
+   */
+  uint8_t pathbias_shouldcount;
+#define PATHBIAS_SHOULDCOUNT_UNDECIDED 0
+#define PATHBIAS_SHOULDCOUNT_IGNORED   1
+#define PATHBIAS_SHOULDCOUNT_COUNTED   2
+
+  /** For path probing. Store the temporary probe stream ID
+   * for response comparison */
+  streamid_t pathbias_probe_id;
+
+  /** For path probing. Store the temporary probe address nonce
+   * (in host byte order) for response comparison. */
+  uint32_t pathbias_probe_nonce;
+
+  /** Set iff this is a hidden-service circuit which has timed out
+   * according to our current circuit-build timeout, but which has
+   * been kept around because it might still succeed in connecting to
+   * its destination, and which is not a fully-connected rendezvous
+   * circuit.
+   *
+   * (We clear this flag for client-side rendezvous circuits when they
+   * are 'joined' to the other side's rendezvous circuit, so that
+   * connection_ap_handshake_attach_circuit can put client streams on
+   * the circuit.  We also clear this flag for service-side rendezvous
+   * circuits when they are 'joined' to a client's rend circ, but only
+   * for symmetry with the client case.  Client-side introduction
+   * circuits are closed when we get a joined rend circ, and
+   * service-side introduction circuits never have this flag set.) */
+  unsigned int hs_circ_has_timed_out : 1;
+
+  /** Set iff this circuit has been given a relaxed timeout because
+   * no circuits have opened. Used to prevent spamming logs. */
+  unsigned int relaxed_timeout : 1;
+
+  /** Set iff this is a service-side rendezvous circuit for which a
+   * new connection attempt has been launched.  We consider launching
+   * a new service-side rend circ to a client when the previous one
+   * fails; now that we don't necessarily close a service-side rend
+   * circ when we launch a new one to the same client, this flag keeps
+   * us from launching two retries for the same failed rend circ. */
+  unsigned int hs_service_side_rend_circ_has_been_relaunched : 1;
+
+  /** What commands were sent over this circuit that decremented the
+   * RELAY_EARLY counter? This is for debugging task 878. */
+  uint8_t relay_early_commands[MAX_RELAY_EARLY_CELLS_PER_CIRCUIT];
+
+  /** How many RELAY_EARLY cells have been sent over this circuit? This is
+   * for debugging task 878, too. */
+  int relay_early_cells_sent;
+
+  /** The next stream_id that will be tried when we're attempting to
+   * construct a new AP stream originating at this circuit. */
+  streamid_t next_stream_id;
+
+  /* The intro key replaces the hidden service's public key if purpose is
+   * S_ESTABLISH_INTRO or S_INTRO, provided that no unversioned rendezvous
+   * descriptor is used. */
+  crypto_pk_t *intro_key;
+
+  /** Quasi-global identifier for this circuit; used for control.c */
+  /* XXXX NM This can get re-used after 2**32 circuits. */
+  uint32_t global_identifier;
+
+  /** True if we have associated one stream to this circuit, thereby setting
+   * the isolation parameters for this circuit.  Note that this doesn't
+   * necessarily mean that we've <em>attached</em> any streams to the circuit:
+   * we may only have marked up this circuit during the launch process.
+   */
+  unsigned int isolation_values_set : 1;
+  /** True iff any stream has <em>ever</em> been attached to this circuit.
+   *
+   * In a better world we could use timestamp_dirty for this, but
+   * timestamp_dirty is far too overloaded at the moment.
+   */
+  unsigned int isolation_any_streams_attached : 1;
+
+  /** A bitfield of ISO_* flags for every isolation field such that this
+   * circuit has had streams with more than one value for that field
+   * attached to it. */
+  uint8_t isolation_flags_mixed;
+
+  /** @name Isolation parameters
+   *
+   * If any streams have been associated with this circ (isolation_values_set
+   * == 1), and all streams associated with the circuit have had the same
+   * value for some field ((isolation_flags_mixed & ISO_FOO) == 0), then these
+   * elements hold the value for that field.
+   *
+   * Note again that "associated" is not the same as "attached": we
+   * preliminarily associate streams with a circuit while the circuit is being
+   * launched, so that we can tell whether we need to launch more circuits.
+   *
+   * @{
+   */
+  uint8_t client_proto_type;
+  uint8_t client_proto_socksver;
+  uint16_t dest_port;
+  tor_addr_t client_addr;
+  char *dest_address;
+  int session_group;
+  unsigned nym_epoch;
+  size_t socks_username_len;
+  uint8_t socks_password_len;
+  /* Note that the next two values are NOT NUL-terminated; see
+     socks_username_len and socks_password_len for their lengths. */
+  char *socks_username;
+  char *socks_password;
+  /** Global identifier for the first stream attached here; used by
+   * ISO_STREAM. */
+  uint64_t associated_isolated_stream_global_id;
+  /**@}*/
+  /** A list of addr_policy_t for this circuit in particular. Used by
+   * adjust_exit_policy_from_exitpolicy_failure.
+   */
+  smartlist_t *prepend_policy;
+
+  /** How long do we wait before closing this circuit if it remains
+   * completely idle after it was built, in seconds? This value
+   * is randomized on a per-circuit basis from CircuitsAvailableTimoeut
+   * to 2*CircuitsAvailableTimoeut. */
+  int circuit_idle_timeout;
+
+};
+
+#endif
+
diff --git a/src/or/relay.c b/src/or/relay.c
index dca31498f1f2ddeac00866c5d47b240d24c05512..55c2abd121003e96aafb7c64e0b4b89cdbd0d81e 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -84,6 +84,8 @@
 
 #include "dir_connection_st.h"
 #include "entry_connection_st.h"
+#include "or_circuit_st.h"
+#include "origin_circuit_st.h"
 
 static edge_connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell,
                                             cell_direction_t cell_direction,
diff --git a/src/or/relay_crypto.c b/src/or/relay_crypto.c
index 530c8e582807ff3160784fb8b76da86ee7977c0f..7603d3b4e127e071165aa8ec71360d48988505b1 100644
--- a/src/or/relay_crypto.c
+++ b/src/or/relay_crypto.c
@@ -5,12 +5,16 @@
 /* See LICENSE for licensing information */
 
 #include "or.h"
+#include "circuitlist.h"
 #include "config.h"
 #include "crypto_util.h"
 #include "hs_ntor.h" // for HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN
 #include "relay.h"
 #include "relay_crypto.h"
 
+#include "or_circuit_st.h"
+#include "origin_circuit_st.h"
+
 /** Update digest from the payload of cell. Assign integrity part to
  * cell.
  */
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index c46b8c5656a237de7871a58e1f6fc40e83a2407f..6762bbfb0081170577062a91b2b58df6d1dbd1ca 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -35,6 +35,7 @@
 
 #include "dir_connection_st.h"
 #include "entry_connection_st.h"
+#include "origin_circuit_st.h"
 
 static extend_info_t *rend_client_get_random_intro_impl(
                           const rend_cache_entry_t *rend_query,
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index f3fa2f64d137a2de9bb64096e0863d52a308da33..308b91878bdf168c19e42f6c8748ec8f6f73dc59 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -12,6 +12,7 @@
 
 #include "or.h"
 #include "circuitbuild.h"
+#include "circuitlist.h"
 #include "circuituse.h"
 #include "config.h"
 #include "control.h"
@@ -30,6 +31,8 @@
 #include "routerlist.h"
 #include "routerparse.h"
 
+#include "origin_circuit_st.h"
+
 /** Return 0 if one and two are the same service ids, else -1 or 1 */
 int
 rend_cmp_service_ids(const char *one, const char *two)
diff --git a/src/or/rendmid.c b/src/or/rendmid.c
index c4a34ca62c6509bdca31030d0509a07e72245376..8afc730675212e06d941545dfc20ef02884ccf04 100644
--- a/src/or/rendmid.c
+++ b/src/or/rendmid.c
@@ -20,6 +20,8 @@
 #include "hs_circuitmap.h"
 #include "hs_intropoint.h"
 
+#include "or_circuit_st.h"
+
 /** Respond to an ESTABLISH_INTRO cell by checking the signed data and
  * setting the circuit's purpose and service pk digest.
  */
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 4d9309e493c2950f97b466b103bf1288fa2a0d6c..d1e6f8a8e30e43b507ea153fa37070d53878f43b 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -37,6 +37,7 @@
 #include "routerset.h"
 
 #include "edge_connection_st.h"
+#include "origin_circuit_st.h"
 
 struct rend_service_t;
 static origin_circuit_t *find_intro_circuit(rend_intro_point_t *intro,
diff --git a/src/or/rephist.c b/src/or/rephist.c
index c7117bad63f5ebb5f86f114f9b42e8973f5e6cd0..909cd043b8c74b7c9f3929cfb729c2e686a5829a 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -89,6 +89,8 @@
 #include "connection_or.h"
 #include "statefile.h"
 
+#include "or_circuit_st.h"
+
 static void bw_arrays_init(void);
 static void predicted_ports_alloc(void);
 
diff --git a/src/or/router.c b/src/or/router.c
index f1fff6be21851b2f38e8a7b6c968f038f771e7d3..11ee2e6aba5734fc018b07ffa31f3b2e05b0909f 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -41,6 +41,7 @@
 
 #include "dir_connection_st.h"
 #include "dir_server_st.h"
+#include "origin_circuit_st.h"
 #include "port_cfg_st.h"
 
 /**
diff --git a/src/test/bench.c b/src/test/bench.c
index 9ab23c9921693ca84c22100a3a66a84aede394c9..784bcf326b146d1c488755195d508c1fdd0e3217 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -26,6 +26,8 @@
 #include "crypto_rand.h"
 #include "consdiff.h"
 
+#include "or_circuit_st.h"
+
 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
 static uint64_t nanostart;
 static inline uint64_t
diff --git a/src/test/test.c b/src/test/test.c
index f0e8b9b728fa9a23a2f46dd152909f666e477dd7..b92dd3c8a0c9729d23e602b183135417b21cd740 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -62,6 +62,8 @@ double fabs(double x);
 #include "statefile.h"
 #include "crypto_curve25519.h"
 
+#include "or_circuit_st.h"
+
 /** Run unit tests for the onion handshake code. */
 static void
 test_onion_handshake(void *arg)
diff --git a/src/test/test_cell_queue.c b/src/test/test_cell_queue.c
index df987f82ce50aacd02c539621ec4d1ba17abe201..b41f7ac380528c93a886a731515cb4066287144d 100644
--- a/src/test/test_cell_queue.c
+++ b/src/test/test_cell_queue.c
@@ -8,6 +8,9 @@
 #include "relay.h"
 #include "test.h"
 
+#include "or_circuit_st.h"
+#include "origin_circuit_st.h"
+
 static void
 test_cq_manip(void *arg)
 {
diff --git a/src/test/test_channel.c b/src/test/test_channel.c
index 76124a6e7542aa8548a779e5da1962e73e3cc436..c41afff5d0ec60e73082f1fc2c33073e765efd85 100644
--- a/src/test/test_channel.c
+++ b/src/test/test_channel.c
@@ -20,6 +20,8 @@
 #include "scheduler.h"
 #include "networkstatus.h"
 
+#include "origin_circuit_st.h"
+
 /* Test suite stuff */
 #include "log_test_helpers.h"
 #include "test.h"
diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c
index 3794ffc2c6235d592f3a49057b35a861574ec4e4..86e78c331eb72be6ed954bd3828b5e15f7f8e47f 100644
--- a/src/test/test_circuitlist.c
+++ b/src/test/test_circuitlist.c
@@ -14,6 +14,9 @@
 #include "test.h"
 #include "log_test_helpers.h"
 
+#include "or_circuit_st.h"
+#include "origin_circuit_st.h"
+
 static channel_t *
 new_fake_channel(void)
 {
diff --git a/src/test/test_circuitstats.c b/src/test/test_circuitstats.c
index 8ebef659ca12d4e1e264a00914213c8a59510fad..c03164954aba7a50911974542afa35b0199a5a21 100644
--- a/src/test/test_circuitstats.c
+++ b/src/test/test_circuitstats.c
@@ -17,6 +17,8 @@
 #include "circuituse.h"
 #include "channel.h"
 
+#include "origin_circuit_st.h"
+
 void test_circuitstats_timeout(void *arg);
 void test_circuitstats_hoplen(void *arg);
 origin_circuit_t *subtest_fourhop_circuit(struct timeval, int);
diff --git a/src/test/test_circuituse.c b/src/test/test_circuituse.c
index df1b43807fdf8d8b5f69f88a37ebe4656a09a64d..7d1b1d9b00ba814866f918c18fd043117dd4dc21 100644
--- a/src/test/test_circuituse.c
+++ b/src/test/test_circuituse.c
@@ -14,6 +14,8 @@
 #include "circuitbuild.h"
 #include "nodelist.h"
 
+#include "origin_circuit_st.h"
+
 static void
 test_circuit_is_available_for_use_ret_false_when_marked_for_close(void *arg)
 {
diff --git a/src/test/test_controller_events.c b/src/test/test_controller_events.c
index e81aea8d668a78a9e99e80bd7a54141de1818987..70ce1a69603de7c224a4871288d956ddd6eedc1c 100644
--- a/src/test/test_controller_events.c
+++ b/src/test/test_controller_events.c
@@ -11,6 +11,9 @@
 #include "control.h"
 #include "test.h"
 
+#include "or_circuit_st.h"
+#include "origin_circuit_st.h"
+
 static void
 add_testing_cell_stats_entry(circuit_t *circ, uint8_t command,
                              unsigned int waiting_time,
diff --git a/src/test/test_dns.c b/src/test/test_dns.c
index c472b97900d410e868079e8c6b47c939040448b8..ffc6fb451452fc88fd19c9ccb8a43830128943bc 100644
--- a/src/test/test_dns.c
+++ b/src/test/test_dns.c
@@ -11,6 +11,7 @@
 #include "router.h"
 
 #include "edge_connection_st.h"
+#include "or_circuit_st.h"
 
 #define NS_MODULE dns
 
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index d4939355d12e191803e7c86a847bf591cfece971..19a32aa8a2a1e4ca4eda3782de84bca9fcb80480 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -34,6 +34,7 @@
 
 #include "test_helpers.h"
 #include "log_test_helpers.h"
+#include "origin_circuit_st.h"
 
 /* TODO:
  * choose_random_entry() test with state set.
diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c
index 86aeabb7c34930427c2c8aaad28f97354ba44ed1..91cc7d4d2e4aeed047750bacc59572116b4bb575 100644
--- a/src/test/test_helpers.c
+++ b/src/test/test_helpers.c
@@ -25,6 +25,7 @@
 #include "routerlist.h"
 
 #include "connection_st.h"
+#include "origin_circuit_st.h"
 
 #include "test.h"
 #include "test_helpers.h"
diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c
index 0420f70f8420e6a2ed256bfee4baa0ae6e420f91..bf0d56f8afe5d07adf83c5bf9583cae727ba229e 100644
--- a/src/test/test_hs_client.c
+++ b/src/test/test_hs_client.c
@@ -39,6 +39,7 @@
 
 #include "dir_connection_st.h"
 #include "entry_connection_st.h"
+#include "origin_circuit_st.h"
 
 static int
 mock_connection_ap_handshake_send_begin(entry_connection_t *ap_conn)
diff --git a/src/test/test_hs_intropoint.c b/src/test/test_hs_intropoint.c
index 4253c9a388b95e86765b00b513c726acd0a2d0d1..b8462d294e354dc367c9b310488243185a2367f9 100644
--- a/src/test/test_hs_intropoint.c
+++ b/src/test/test_hs_intropoint.c
@@ -28,6 +28,8 @@
 #include "hs_intropoint.h"
 #include "hs_service.h"
 
+#include "or_circuit_st.h"
+
 /* Trunnel. */
 #include "hs/cell_establish_intro.h"
 #include "hs/cell_introduce1.h"
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index 33b5e96070b078200a46e8bd8daad1dcd12bcba4..06df50740fe4835995708839ea53fa52f638ce0b 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -53,6 +53,8 @@
 #include "dirauth/shared_random_state.h"
 #include "voting_schedule.h"
 
+#include "origin_circuit_st.h"
+
 /* Trunnel */
 #include "hs/cell_establish_intro.h"
 
diff --git a/src/test/test_oom.c b/src/test/test_oom.c
index 98935fe455ac73b78189e39f691f78064626179f..fcee7cc73ffd1a8b46d2dbecc652ef0a806cb886 100644
--- a/src/test/test_oom.c
+++ b/src/test/test_oom.c
@@ -19,6 +19,8 @@
 #include "test_helpers.h"
 
 #include "entry_connection_st.h"
+#include "or_circuit_st.h"
+#include "origin_circuit_st.h"
 
 /* small replacement mock for circuit_mark_for_close_ to avoid doing all
  * the other bookkeeping that comes with marking circuits. */
diff --git a/src/test/test_relay.c b/src/test/test_relay.c
index 73c0ed5586e4686b897c4f74617fca2af69d7342..4a526671be14cfa91e86047fb8cef4d44a66ccd8 100644
--- a/src/test/test_relay.c
+++ b/src/test/test_relay.c
@@ -9,6 +9,8 @@
 /* For init/free stuff */
 #include "scheduler.h"
 
+#include "or_circuit_st.h"
+
 /* Test suite stuff */
 #include "test.h"
 #include "fakechans.h"
diff --git a/src/test/test_relaycell.c b/src/test/test_relaycell.c
index b4cb9d4bbc47f9b2cbd43ba663df462a896d2dc1..e6a67340325da249dfbfe2e824a5b93da1c7ae34 100644
--- a/src/test/test_relaycell.c
+++ b/src/test/test_relaycell.c
@@ -17,6 +17,7 @@
 #include "test.h"
 
 #include "entry_connection_st.h"
+#include "origin_circuit_st.h"
 
 static int srm_ncalls;
 static entry_connection_t *srm_conn;
diff --git a/src/test/test_relaycrypt.c b/src/test/test_relaycrypt.c
index 60bd4797192ef6be59467c97d1f67c1c224ed141..62bcedabc9a79aaa63d961d8bb23b76c664313c5 100644
--- a/src/test/test_relaycrypt.c
+++ b/src/test/test_relaycrypt.c
@@ -10,6 +10,10 @@
 #include "crypto_rand.h"
 #include "relay.h"
 #include "relay_crypto.h"
+
+#include "or_circuit_st.h"
+#include "origin_circuit_st.h"
+
 #include "test.h"
 
 static const char KEY_MATERIAL[3][CPATH_KEY_MATERIAL_LEN] = {
diff --git a/src/test/test_status.c b/src/test/test_status.c
index b4ca17891bb6d874f6da34b0508681fb7082d9d8..062a28f73028a75078975f6c6fd4db7ee8428311 100644
--- a/src/test/test_status.c
+++ b/src/test/test_status.c
@@ -24,6 +24,9 @@
 #include "main.h"
 #include "nodelist.h"
 #include "statefile.h"
+
+#include "origin_circuit_st.h"
+
 #include "test.h"
 
 #define NS_MODULE status