1. Guard rotation isn't discussed. 2. When a new consensus changes the guard/fast/stable/etc. status of a relay, does a client use the new flag to adjust its guards/fast circuits/etc. ? For example, when a chosen guard loses its guard flag, does the client choose a new guard? Answer: Guards statuses are updated when a new consensus is received. A guard that loses its Guard flag would have guard->bad_since = 1 and wouldn't be chosen for new circuits (bc it wouldn't be considered 'live'). Similarly, relay statuses are updated with a new consensus. 3. Are guards selected first irrespective of any circuit (and thus are always initially not required to be Fast or Stable)? When a guard is selected for a particular circuit, if some (or all) of the existing member of the guard list aren't usable for the circuit (e.g. one has been selected as an exit, a guard isn't marked 'Fast' and it's a fast circuit), are new guards added - possibly just for that circuit - if there are fewer than two usable ones? 4. Hibernation is not mentioned at all in path-spec.txt. It is mentioned in dir-spec.txt, but only off in the "Router descriptor format" section (2.1) to say that "if the value is 1, then the Tor relay was hibernating when the descriptor was published, and shouldn't be used to build circuits." This appears to conflict with later description in both dir-spec.txt (e.g. in Sec. 6.1) and path-spec.txt (e.g. in Sec. 2.2). Answer: It appears that only directory authorities use the hibernate state to set Running flag in vote, and that clients don't use it, relying on the Running flag. 5. In path-spec.txt Sec. 6.1, it is stated that "for non-"fast" circuits, all nodes are eligible, and in Sec. 2.1.2 circuits built on demand (which are made for any request that no current circuit can support) are not specified to be Fast. However, in Sec. 6.1, it is stated that "Clients SHOULD NOT use non-'Fast' routers for any purpose other than very-low-bandwidth circuits (such as introduction circuits)". What does the Tor client do? 6. It is unclear (from Sec. 5.2 in dir-spec.txt) if clients prefer the descriptor listed in a consensus or in a more-recently published one. 7. It is stated in path-spec.txt (Sec. 2.2) that "by default, we are configured to allow non-valid routers in 'middle' and 'rendezvous' positions.". However, dir-spec.txt states in Sec. 6.1 that "Clients SHOULD NOT use non-'Valid' or non-'Running' routers unless requested to do so.". Which is it? 8. I do not understand the difference between the "Wxb" and "Wbx" weights (where x is g,m,e, or d). 9. In path-spec.txt Sec. 2.2, there is the line "- Rules for Fast? XXXXX". What is missing here? 10. Is it indeed true that exit nodes need not have the "Exit" flag? So a relay with, say, an exit policy allowing one IP to be contacted on port 80 could be used on a pre-emptive port 80 circuit (I actually observed this with relay "riseuppad" in the 8/2/12 00:00 consensus). 11. For internal circuits, path-spec.txt says that in an internal circuit "the final node is chosen just like a middle node (ignoring its exit policy). So are the weights used the middle-node weights too? 12. For the /16 check, is it just a check that the first 16 bits of the IP addresses of the relays on a path don't appear more than once? That seems a bit simplistic. 13. Is it really true, as claimed by the COGS paper, that a guard won't be chosen for the list if it is in the same family or /16 as *any* guard in the list, regardless of its online status? And if so, how are the guard descriptors stored and updated to keep their families and addresses current - does the client just look in cached-descriptors (which, it seems, might drop guards that currently aren't active)? 14. According to router_choose_random_node() (routerlist.c), clients with ExcludeSingleHopRelays=1 exclude relays that allow single-hop exit circuits. This isn't noted in the docs. 15. In general, it often seems that if relays cannot be found satisfying certain restrictions (e.g. fast, stable, guard) the restrictions are removed and relay selection is tried again (cf. router_choose_random_node() and choose_random_entry_impl()). 16. For some reason, the weighted bandwidth is "weight*this_bw + 0.5" (routerlist.c), where weight is bw_weight/bwweightscale, e.g., 'Wgg' / 10000, and this_bw is the consensus bw in bytes. If we have an unused 3-hop circuit and we really need a not-too-fast circuit to node X right away, we can extend the 3-hop circuit to X rather than making a new one. That's "cannibalizing" the circuit