tor_netdir

Struct NetDir

Source
pub struct NetDir {
    pub(crate) consensus: Arc<MdConsensus>,
    pub(crate) params: NetParameters,
    pub(crate) mds: TiVec<RouterStatusIdx, Option<Arc<Microdesc>>>,
    pub(crate) rsidx_by_missing: HashMap<MdDigest, RouterStatusIdx>,
    pub(crate) rsidx_by_ed: HashMap<Ed25519Identity, RouterStatusIdx>,
    pub(crate) rsidx_by_rsa: Arc<HashMap<RsaIdentity, RouterStatusIdx>>,
    pub(crate) hsdir_rings: Arc<HsDirs<HsDirRing>>,
    pub(crate) weights: WeightSet,
    pub(crate) country_codes: Vec<Option<CountryCode>>,
}
Expand description

A view of the Tor directory, suitable for use in building circuits.

Abstractly, a NetDir is a set of usable public Relays, each of which has its own properties, identity, and correct weighted probability for use under different circumstances.

A NetDir is constructed by making a PartialNetDir from a consensus document, and then adding enough microdescriptors to that PartialNetDir so that it can be used to build paths. (Thus, if you have a NetDir, it is definitely adequate to build paths.)

§“Usable” relays

Many methods on NetDir are defined in terms of “Usable” relays. Unless otherwise stated, a relay is “usable” if it is listed in the consensus, if we have full directory information for that relay (including a microdescriptor), and if that relay does not have any flags indicating that we should never use it. (Currently, NoEdConsensus is the only such flag.)

§Limitations

The current NetDir implementation assumes fairly strongly that every relay has an Ed25519 identity and an RSA identity, that the consensus is indexed by RSA identities, and that the Ed25519 identities are stored in microdescriptors.

If these assumptions someday change, then we’ll have to revise the implementation.

Fields§

§consensus: Arc<MdConsensus>

A microdescriptor consensus that lists the members of the network, and maps each one to a ‘microdescriptor’ that has more information about it

§params: NetParameters

A map from keys to integer values, distributed in the consensus, and clamped to certain defaults.

§mds: TiVec<RouterStatusIdx, Option<Arc<Microdesc>>>

Map from routerstatus index, to that routerstatus’s microdescriptor (if we have one.)

§rsidx_by_missing: HashMap<MdDigest, RouterStatusIdx>

Map from SHA256 of missing microdescriptors to the index of their corresponding routerstatus.

§rsidx_by_ed: HashMap<Ed25519Identity, RouterStatusIdx>

Map from ed25519 identity to index of the routerstatus.

Note that we don’t know the ed25519 identity of a relay until we get the microdescriptor for it, so this won’t be filled in until we get the microdescriptors.

§Implementation note

For this field, and for rsidx_by_rsa, it might be cool to have references instead. But that would make this into a self-referential structure, which isn’t possible in safe rust.

§rsidx_by_rsa: Arc<HashMap<RsaIdentity, RouterStatusIdx>>

Map from RSA identity to index of the routerstatus.

This is constructed at the same time as the NetDir object, so it can be immutable.

§hsdir_rings: Arc<HsDirs<HsDirRing>>
Available on crate feature hs-common only.

Hash ring(s) describing the onion service directory.

This is empty in a PartialNetDir, and is filled in before the NetDir is built.

§weights: WeightSet

Weight values to apply to a given relay when deciding how frequently to choose it for a given role.

§country_codes: Vec<Option<CountryCode>>
Available on crate feature geoip only.

Country codes for each router in our consensus.

This is indexed by the RouterStatusIdx (i.e. a router idx of zero has the country code at position zero in this array).

Implementations§

Source§

impl NetDir

Source

pub fn lifetime(&self) -> &Lifetime

Return the declared lifetime of this NetDir.

Source

pub(crate) fn add_arc_microdesc(&mut self, md: Arc<Microdesc>) -> bool

Add md to this NetDir.

Return true if we wanted it, and false otherwise.

Source

pub(crate) fn relay_from_rs_and_rsidx<'a>( &'a self, rs: &'a MdConsensusRouterStatus, rsidx: RouterStatusIdx, ) -> UncheckedRelay<'a>

Construct a (possibly invalid) Relay object from a routerstatus and its index within the consensus.

Source

pub(crate) fn n_replicas(&self) -> u8

Available on crate feature hs-common only.

Return the value of the hsdir_n_replicas param.

Source

pub(crate) fn spread(&self, op: HsDirOp) -> usize

Available on crate feature hs-common only.

Return the spread parameter for the specified op.

Source

pub(crate) fn select_hsdirs<'h, 'r: 'h>( &'r self, hsid: HsBlindId, ring: &'h HsDirRing, spread: usize, ) -> impl Iterator<Item = Relay<'r>> + 'h

Available on crate feature hs-common only.

Select spread hsdir relays for the specified hsid from a given ring.

Algorithm:

for idx in 1..=n_replicas: - let H = hsdir_ring::onion_service_index(id, replica, rand, period). - Find the position of H within hsdir_ring. - Take elements from hsdir_ring starting at that position, adding them to Dirs until we have added spread new elements that were not there before.

Source

pub fn replace_overridden_parameters( &mut self, new_replacement: &NetParams<i32>, )

Replace the overridden parameters in this netdir with new_replacement.

After this function is done, the netdir’s parameters will be those in the consensus, overridden by settings from new_replacement. Any settings in the old replacement parameters will be discarded.

Source

pub fn all_relays(&self) -> impl Iterator<Item = UncheckedRelay<'_>>

Return an iterator over all Relay objects, including invalid ones that we can’t use.

Source

pub fn relays(&self) -> impl Iterator<Item = Relay<'_>>

Return an iterator over all usable Relays.

Source

pub(crate) fn md_by_rsidx(&self, rsidx: RouterStatusIdx) -> Option<&Microdesc>

Look up a relay’s MicroDesc by its RouterStatusIdx

Source

pub fn by_id<'a, T>(&self, id: T) -> Option<Relay<'_>>
where T: Into<RelayIdRef<'a>>,

Return a relay matching a given identity, if we have a usable relay with that key.

(Does not return unusable relays.)

Note that a None answer is not always permanent: if a microdescriptor is subsequently added for a relay with this ID, the ID may become usable even if it was not usable before.

Source

pub(crate) fn relay_by_rs_idx( &self, rs_idx: RouterStatusIdx, ) -> Option<Relay<'_>>

Obtain a Relay given a RouterStatusIdx

Differs from relay_from_rs_and_rsi as follows:

  • That function expects the caller to already have an MdConsensusRouterStatus; it checks with debug_assert that the relay in the netdir matches.
  • That function panics if the RouterStatusIdx is invalid; this one returns None.
  • That function returns an UncheckedRelay; this one a Relay.

None could be returned here, even with a valid rsi, if rsi refers to an unusable relay.

Source

pub fn by_ids<T>(&self, target: &T) -> Option<Relay<'_>>
where T: HasRelayIds + ?Sized,

Return a relay with the same identities as those in target, if one exists.

Does not return unusable relays.

Note that a negative result from this method is not necessarily permanent: it may be the case that a relay exists, but we don’t yet have enough information about it to know all of its IDs. To test whether a relay is definitely absent, use by_ids_detailed or ids_listed.

§Limitations

This will be very slow if target does not have an Ed25519 or RSA identity.

Source

pub fn by_ids_detailed<T>( &self, target: &T, ) -> Result<Option<Relay<'_>>, RelayLookupError>
where T: HasRelayIds + ?Sized,

Available on crate feature hs-common only.

Check whether there is a relay that has at least one identity from target, and which could have every identity from target. If so, return such a relay.

Return Ok(None) if we did not find a relay with any identity from target.

Return RelayLookupError::Impossible if we found a relay with at least one identity from target, but that relay’s other identities contradict what we learned from target.

Does not return unusable relays.

(This function is only useful if you need to distinguish the “impossible” case from the “no such relay known” case.)

§Limitations

This will be very slow if target does not have an Ed25519 or RSA identity.

Source

pub(crate) fn id_pair_listed( &self, ed_id: &Ed25519Identity, rsa_id: &RsaIdentity, ) -> Option<bool>

Return a boolean if this consensus definitely has (or does not have) a relay matching the listed identities.

Some(true) indicates that the relay exists. Some(false) indicates that the relay definitely does not exist. None indicates that we can’t yet tell whether such a relay exists, due to missing information.

Source

pub fn ids_listed<T>(&self, target: &T) -> Option<bool>
where T: HasRelayIds + ?Sized,

Check whether a relay exists (or may exist) with the same identities as those in target.

Some(true) indicates that the relay exists. Some(false) indicates that the relay definitely does not exist. None indicates that we can’t yet tell whether such a relay exists, due to missing information.

Source

pub fn by_rsa_id_unchecked( &self, rsa_id: &RsaIdentity, ) -> Option<UncheckedRelay<'_>>

Available on crate feature experimental-api only.

Return a (possibly unusable) relay with a given RSA identity.

This API can be used to find information about a relay that is listed in the current consensus, even if we don’t yet have enough information (like a microdescriptor) about the relay to use it.

Source

pub(crate) fn by_rsa_id(&self, rsa_id: &RsaIdentity) -> Option<Relay<'_>>

Return the relay with a given RSA identity, if we have one and it is usable.

Source

pub fn rsa_id_is_listed(&self, rsa_id: &RsaIdentity) -> bool

Available on crate feature experimental-api only.

Return true if rsa_id is listed in this directory, even if it isn’t currently usable.

(An “unusable” relay in this context is one for which we don’t have full directory information.)

Source

pub(crate) fn all_hsdirs( &self, ) -> impl Iterator<Item = (RouterStatusIdx, Relay<'_>)>

Available on crate feature hs-common only.

List the hsdirs in this NetDir, that should be in the HSDir rings

The results are not returned in any particular order.

Source

pub fn params(&self) -> &NetParameters

Return the parameters from the consensus, clamped to the correct ranges, with defaults filled in.

NOTE: that unsupported parameters aren’t returned here; only those values configured in the params module are available.

Source

pub fn relay_protocol_status(&self) -> &ProtoStatus

Available on crate feature hs-common only.

Return a ProtoStatus that lists the network’s current requirements and recommendations for the list of protocols that every relay must implement.

Source

pub(crate) fn frac_for_role<'a, F>(&'a self, role: WeightRole, usable: F) -> f64
where F: Fn(&UncheckedRelay<'a>) -> bool,

Return weighted the fraction of relays we can use. We only consider relays that match the predicate usable. We weight this bandwidth according to the provided role.

If no matching relays in the consensus have a nonzero weighted bandwidth value, we fall back to looking at the unweighted fraction of matching relays.

If there are no matching relays in the consensus, we return 0.0.

Source

pub(crate) fn frac_usable_paths(&self) -> f64

Return the estimated fraction of possible paths that we have enough microdescriptors to build.

Source

pub(crate) fn have_enough_paths(&self) -> bool

Return true if there is enough information in this NetDir to build multihop circuits.

Source

pub fn pick_relay<'a, R, P>( &'a self, rng: &mut R, role: WeightRole, usable: P, ) -> Option<Relay<'a>>
where R: Rng, P: FnMut(&Relay<'a>) -> bool,

Choose a relay at random.

Each relay is chosen with probability proportional to its weight in the role role, and is only selected if the predicate usable returns true for it.

This function returns None if (and only if) there are no relays with nonzero weight where usable returned true.

Source

pub fn pick_n_relays<'a, R, P>( &'a self, rng: &mut R, n: usize, role: WeightRole, usable: P, ) -> Vec<Relay<'a>>
where R: Rng, P: FnMut(&Relay<'a>) -> bool,

Choose n relay at random.

Each relay is chosen with probability proportional to its weight in the role role, and is only selected if the predicate usable returns true for it.

Relays are chosen without replacement: no relay will be returned twice. Therefore, the resulting vector may be smaller than n if we happen to have fewer than n appropriate relays.

This function returns an empty vector if (and only if) there are no relays with nonzero weight where usable returned true.

Source

pub fn relay_weight<'a>( &'a self, relay: &Relay<'a>, role: WeightRole, ) -> RelayWeight

Compute the weight with which relay will be selected for a given role.

Source

pub fn total_weight<P>(&self, role: WeightRole, usable: P) -> RelayWeight
where P: Fn(&UncheckedRelay<'_>) -> bool,

Compute the total weight with which any relay matching usable will be selected for a given role.

Note: because this function is used to assess the total properties of the consensus, the usable predicate takes a [RouterStatus] rather than a Relay.

Source

pub fn weight_by_rsa_id( &self, rsa_id: &RsaIdentity, role: WeightRole, ) -> Option<RelayWeight>

Compute the weight with which a relay with ID rsa_id would be selected for a given role.

Note that weight returned by this function assumes that the relay with that ID is actually usable; if it isn’t usable, then other weight-related functions will call its weight zero.

Source

pub fn known_family_members<'a>( &'a self, relay: &'a Relay<'a>, ) -> impl Iterator<Item = Relay<'a>>

Return all relays in this NetDir known to be in the same family as relay.

This list of members will not necessarily include relay itself.

§Limitations

Two relays only belong to the same family if each relay claims to share a family with the other. But if we are missing a microdescriptor for one of the relays listed by this relay, we cannot know whether it acknowledges family membership with this relay or not. Therefore, this function can omit family members for which there is not (as yet) any Relay object.

Source

pub fn hs_time_period(&self) -> TimePeriod

Available on crate feature hs-common only.

Return the current hidden service directory “time period”.

Specifically, this returns the time period that contains the beginning of the validity period of this NetDir’s consensus. That time period is the one we use when acting as an hidden service client.

Source

pub fn hs_all_time_periods(&self) -> Vec<HsDirParams>

Available on crate feature hs-service only.

Return the HsDirParams of all the relevant hidden service directory “time periods”

This includes the current time period (as from .hs_time_period) plus additional time periods that we publish descriptors for when we are acting as a hidden service.

Source

pub fn hs_dirs_download<'r, R>( &'r self, hsid: HsBlindId, period: TimePeriod, rng: &mut R, ) -> Result<Vec<Relay<'r>>, Bug>
where R: Rng,

Available on crate feature hs-common only.

Return the relays in this network directory that will be used as hidden service directories

These are suitable to retrieve a given onion service’s descriptor at a given time period.

Source

pub fn hs_dirs_upload( &self, hsid: HsBlindId, period: TimePeriod, ) -> Result<impl Iterator<Item = Relay<'_>>, Bug>

Available on crate feature hs-service only.

Return the relays in this network directory that will be used as hidden service directories

Returns the relays that are suitable for storing a given onion service’s descriptors at the given time period.

Source

pub fn hs_dirs<'r, R>( &'r self, hsid: &HsBlindId, op: HsDirOp, rng: &mut R, ) -> Vec<Relay<'r>>
where R: Rng,

👎Deprecated: Use hs_dirs_upload or hs_dirs_download instead
Available on crate feature hs-common only.

Return the relays in this network directory that will be used as hidden service directories

Depending on op, these are suitable to either store, or retrieve, a given onion service’s descriptor at a given time period.

When op is Download, the order is random. When op is Upload, the order is not specified.

Return an error if the time period is not one returned by onion_service_time_period or onion_service_secondary_time_periods.

Trait Implementations§

Source§

impl AsRef<NetParameters> for NetDir

Source§

fn as_ref(&self) -> &NetParameters

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl Clone for NetDir

Source§

fn clone(&self) -> NetDir

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl ConsensusRelays for NetDir

Source§

fn c_relays(&self) -> &TiSlice<RouterStatusIdx, MdConsensusRouterStatus>

Obtain the list of relays in the consensus
Source§

impl Debug for NetDir

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<NetDir> for TestNetDirProvider

Available on crate feature testing only.
Source§

fn from(nd: NetDir) -> Self

Converts to this type from the input type.
Source§

impl MdReceiver for NetDir

Source§

fn missing_microdescs(&self) -> Box<dyn Iterator<Item = &MdDigest> + '_>

Return an iterator over the digests for all of the microdescriptors that this netdir is missing.
Source§

fn add_microdesc(&mut self, md: Microdesc) -> bool

Add a microdescriptor to this netdir, if it was wanted. Read more
Source§

fn n_missing(&self) -> usize

Return the number of missing microdescriptors.

Auto Trait Implementations§

§

impl Freeze for NetDir

§

impl RefUnwindSafe for NetDir

§

impl Send for NetDir

§

impl Sync for NetDir

§

impl Unpin for NetDir

§

impl UnwindSafe for NetDir

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DynClone for T
where T: Clone,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where T: 'static,

§

impl<T> MaybeSendSync for T