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 Relay
s, 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>>
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>>
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
impl NetDir
Sourcepub(crate) fn add_arc_microdesc(&mut self, md: Arc<Microdesc>) -> bool
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.
Sourcepub(crate) fn relay_from_rs_and_rsidx<'a>(
&'a self,
rs: &'a MdConsensusRouterStatus,
rsidx: RouterStatusIdx,
) -> UncheckedRelay<'a>
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.
Sourcepub(crate) fn n_replicas(&self) -> u8
Available on crate feature hs-common
only.
pub(crate) fn n_replicas(&self) -> u8
hs-common
only.Return the value of the hsdir_n_replicas param.
Sourcepub(crate) fn spread(&self, op: HsDirOp) -> usize
Available on crate feature hs-common
only.
pub(crate) fn spread(&self, op: HsDirOp) -> usize
hs-common
only.Return the spread parameter for the specified op
.
Sourcepub(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.
pub(crate) fn select_hsdirs<'h, 'r: 'h>( &'r self, hsid: HsBlindId, ring: &'h HsDirRing, spread: usize, ) -> impl Iterator<Item = Relay<'r>> + 'h
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.
Sourcepub fn replace_overridden_parameters(
&mut self,
new_replacement: &NetParams<i32>,
)
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.
Sourcepub fn all_relays(&self) -> impl Iterator<Item = UncheckedRelay<'_>>
pub fn all_relays(&self) -> impl Iterator<Item = UncheckedRelay<'_>>
Return an iterator over all Relay objects, including invalid ones that we can’t use.
Sourcepub fn relays(&self) -> impl Iterator<Item = Relay<'_>>
pub fn relays(&self) -> impl Iterator<Item = Relay<'_>>
Return an iterator over all usable Relays.
Sourcepub(crate) fn md_by_rsidx(&self, rsidx: RouterStatusIdx) -> Option<&Microdesc>
pub(crate) fn md_by_rsidx(&self, rsidx: RouterStatusIdx) -> Option<&Microdesc>
Look up a relay’s MicroDesc
by its RouterStatusIdx
Sourcepub fn by_id<'a, T>(&self, id: T) -> Option<Relay<'_>>where
T: Into<RelayIdRef<'a>>,
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.
Sourcepub(crate) fn relay_by_rs_idx(
&self,
rs_idx: RouterStatusIdx,
) -> Option<Relay<'_>>
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 withdebug_assert
that the relay in the netdir matches. - That function panics if the
RouterStatusIdx
is invalid; this one returnsNone
. - That function returns an
UncheckedRelay
; this one aRelay
.
None
could be returned here, even with a valid rsi
,
if rsi
refers to an unusable relay.
Sourcepub fn by_ids<T>(&self, target: &T) -> Option<Relay<'_>>where
T: HasRelayIds + ?Sized,
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.
Sourcepub fn by_ids_detailed<T>(
&self,
target: &T,
) -> Result<Option<Relay<'_>>, RelayLookupError>where
T: HasRelayIds + ?Sized,
Available on crate feature hs-common
only.
pub fn by_ids_detailed<T>(
&self,
target: &T,
) -> Result<Option<Relay<'_>>, RelayLookupError>where
T: HasRelayIds + ?Sized,
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.
Sourcepub(crate) fn id_pair_listed(
&self,
ed_id: &Ed25519Identity,
rsa_id: &RsaIdentity,
) -> Option<bool>
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.
Sourcepub fn ids_listed<T>(&self, target: &T) -> Option<bool>where
T: HasRelayIds + ?Sized,
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.
Sourcepub fn by_rsa_id_unchecked(
&self,
rsa_id: &RsaIdentity,
) -> Option<UncheckedRelay<'_>>
Available on crate feature experimental-api
only.
pub fn by_rsa_id_unchecked( &self, rsa_id: &RsaIdentity, ) -> Option<UncheckedRelay<'_>>
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.
Sourcepub(crate) fn by_rsa_id(&self, rsa_id: &RsaIdentity) -> Option<Relay<'_>>
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.
Sourcepub fn rsa_id_is_listed(&self, rsa_id: &RsaIdentity) -> bool
Available on crate feature experimental-api
only.
pub fn rsa_id_is_listed(&self, rsa_id: &RsaIdentity) -> bool
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.)
Sourcepub(crate) fn all_hsdirs(
&self,
) -> impl Iterator<Item = (RouterStatusIdx, Relay<'_>)>
Available on crate feature hs-common
only.
pub(crate) fn all_hsdirs( &self, ) -> impl Iterator<Item = (RouterStatusIdx, Relay<'_>)>
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.
Sourcepub fn params(&self) -> &NetParameters
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.
Sourcepub fn relay_protocol_status(&self) -> &ProtoStatus
Available on crate feature hs-common
only.
pub fn relay_protocol_status(&self) -> &ProtoStatus
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.
Sourcepub(crate) fn frac_for_role<'a, F>(&'a self, role: WeightRole, usable: F) -> f64
pub(crate) fn frac_for_role<'a, F>(&'a self, role: WeightRole, usable: F) -> f64
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.
Sourcepub(crate) fn frac_usable_paths(&self) -> f64
pub(crate) fn frac_usable_paths(&self) -> f64
Return the estimated fraction of possible paths that we have enough microdescriptors to build.
Sourcepub(crate) fn have_enough_paths(&self) -> bool
pub(crate) fn have_enough_paths(&self) -> bool
Return true if there is enough information in this NetDir to build multihop circuits.
Sourcepub fn pick_relay<'a, R, P>(
&'a self,
rng: &mut R,
role: WeightRole,
usable: P,
) -> Option<Relay<'a>>
pub fn pick_relay<'a, R, P>( &'a self, rng: &mut R, role: WeightRole, usable: P, ) -> Option<Relay<'a>>
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.
Sourcepub fn pick_n_relays<'a, R, P>(
&'a self,
rng: &mut R,
n: usize,
role: WeightRole,
usable: P,
) -> Vec<Relay<'a>>
pub fn pick_n_relays<'a, R, P>( &'a self, rng: &mut R, n: usize, role: WeightRole, usable: P, ) -> Vec<Relay<'a>>
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.
Sourcepub fn relay_weight<'a>(
&'a self,
relay: &Relay<'a>,
role: WeightRole,
) -> RelayWeight
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
.
Sourcepub fn total_weight<P>(&self, role: WeightRole, usable: P) -> RelayWeight
pub fn total_weight<P>(&self, role: WeightRole, usable: P) -> RelayWeight
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
.
Sourcepub fn weight_by_rsa_id(
&self,
rsa_id: &RsaIdentity,
role: WeightRole,
) -> Option<RelayWeight>
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.
Sourcepub fn known_family_members<'a>(
&'a self,
relay: &'a Relay<'a>,
) -> impl Iterator<Item = Relay<'a>>
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.
Sourcepub fn hs_time_period(&self) -> TimePeriod
Available on crate feature hs-common
only.
pub fn hs_time_period(&self) -> TimePeriod
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.
Sourcepub fn hs_all_time_periods(&self) -> Vec<HsDirParams>
Available on crate feature hs-service
only.
pub fn hs_all_time_periods(&self) -> Vec<HsDirParams>
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.
Sourcepub 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.
pub fn hs_dirs_download<'r, R>(
&'r self,
hsid: HsBlindId,
period: TimePeriod,
rng: &mut R,
) -> Result<Vec<Relay<'r>>, Bug>where
R: Rng,
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.
Sourcepub fn hs_dirs_upload(
&self,
hsid: HsBlindId,
period: TimePeriod,
) -> Result<impl Iterator<Item = Relay<'_>>, Bug>
Available on crate feature hs-service
only.
pub fn hs_dirs_upload( &self, hsid: HsBlindId, period: TimePeriod, ) -> Result<impl Iterator<Item = Relay<'_>>, Bug>
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.
Sourcepub 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 insteadAvailable on crate feature hs-common
only.
pub fn hs_dirs<'r, R>(
&'r self,
hsid: &HsBlindId,
op: HsDirOp,
rng: &mut R,
) -> Vec<Relay<'r>>where
R: Rng,
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
impl AsRef<NetParameters> for NetDir
Source§fn as_ref(&self) -> &NetParameters
fn as_ref(&self) -> &NetParameters
Source§impl ConsensusRelays for NetDir
impl ConsensusRelays for NetDir
Source§fn c_relays(&self) -> &TiSlice<RouterStatusIdx, MdConsensusRouterStatus>
fn c_relays(&self) -> &TiSlice<RouterStatusIdx, MdConsensusRouterStatus>
Source§impl From<NetDir> for TestNetDirProvider
Available on crate feature testing
only.
impl From<NetDir> for TestNetDirProvider
testing
only.Source§impl MdReceiver for NetDir
impl MdReceiver for NetDir
Source§fn missing_microdescs(&self) -> Box<dyn Iterator<Item = &MdDigest> + '_>
fn missing_microdescs(&self) -> Box<dyn Iterator<Item = &MdDigest> + '_>
Source§fn add_microdesc(&mut self, md: Microdesc) -> bool
fn add_microdesc(&mut self, md: Microdesc) -> bool
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§
§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&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
impl<T> DowncastSync for T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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