tor-netdir: Use typed-index-collections for router status index
This commit is contained in:
parent
b7e41c3981
commit
2dbffa1208
|
@ -4061,6 +4061,7 @@ dependencies = [
|
||||||
"tor-protover",
|
"tor-protover",
|
||||||
"tor-units",
|
"tor-units",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"typed-index-collections",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4397,6 +4398,12 @@ version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typed-index-collections"
|
||||||
|
version = "3.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "183496e014253d15abbe6235677b1392dba2d40524c88938991226baa38ac7c4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
|
|
|
@ -55,6 +55,7 @@ tor-netdoc = { path = "../tor-netdoc", version = "0.6.1" }
|
||||||
tor-protover = { path = "../tor-protover", version = "0.4.0" }
|
tor-protover = { path = "../tor-protover", version = "0.4.0" }
|
||||||
tor-units = { path = "../tor-units", version = "0.4.1" }
|
tor-units = { path = "../tor-units", version = "0.4.1" }
|
||||||
tracing = "0.1.18"
|
tracing = "0.1.18"
|
||||||
|
typed-index-collections = "3.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
float_eq = "1.0.0"
|
float_eq = "1.0.0"
|
||||||
|
|
|
@ -63,6 +63,7 @@ use tor_netdoc::doc::microdesc::{MdDigest, Microdesc};
|
||||||
use tor_netdoc::doc::netstatus::{self, MdConsensus, MdConsensusRouterStatus, RouterStatus};
|
use tor_netdoc::doc::netstatus::{self, MdConsensus, MdConsensusRouterStatus, RouterStatus};
|
||||||
use tor_netdoc::types::policy::PortPolicy;
|
use tor_netdoc::types::policy::PortPolicy;
|
||||||
|
|
||||||
|
use derive_more::{From, Into};
|
||||||
use futures::stream::BoxStream;
|
use futures::stream::BoxStream;
|
||||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -72,6 +73,7 @@ use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use strum::{EnumCount, EnumIter};
|
use strum::{EnumCount, EnumIter};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
use typed_index_collections::{TiSlice, TiVec};
|
||||||
|
|
||||||
#[cfg(feature = "onion-common")]
|
#[cfg(feature = "onion-common")]
|
||||||
use tor_hscrypto::{pk::BlindedOnionId, time::TimePeriod};
|
use tor_hscrypto::{pk::BlindedOnionId, time::TimePeriod};
|
||||||
|
@ -86,6 +88,20 @@ pub use err::OnionDirLookupError;
|
||||||
|
|
||||||
use params::NetParameters;
|
use params::NetParameters;
|
||||||
|
|
||||||
|
/// Index into the consensus relays
|
||||||
|
///
|
||||||
|
/// This is an index into the list of relays returned by
|
||||||
|
/// [`.c_relays()`](ConsensusRelays::c_relays)
|
||||||
|
/// (on the corresponding consensus or netdir).
|
||||||
|
///
|
||||||
|
/// This is just a `usize` inside, but using a newtype prevents getting a relay index
|
||||||
|
/// confused with other kinds of slice indices or counts.
|
||||||
|
///
|
||||||
|
/// If you are in a part of the code which needs to work with multiple consensuses,
|
||||||
|
/// the typechecking cannot tell if you try to index into the wrong consensus.
|
||||||
|
#[derive(Debug, From, Into, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
|
pub(crate) struct RouterStatusIdx(usize);
|
||||||
|
|
||||||
/// Extension trait to provide index-type-safe `.c_relays()` method
|
/// Extension trait to provide index-type-safe `.c_relays()` method
|
||||||
//
|
//
|
||||||
// TODO: Really it would be better to have MdConsensns::relays() return TiSlice,
|
// TODO: Really it would be better to have MdConsensns::relays() return TiSlice,
|
||||||
|
@ -93,16 +109,16 @@ use params::NetParameters;
|
||||||
pub(crate) trait ConsensusRelays {
|
pub(crate) trait ConsensusRelays {
|
||||||
/// Obtain the list of relays in the consensus
|
/// Obtain the list of relays in the consensus
|
||||||
//
|
//
|
||||||
|
fn c_relays(&self) -> &TiSlice<RouterStatusIdx, MdConsensusRouterStatus>;
|
||||||
// TODO hs: This will return a TiSlice, shortly
|
// TODO hs: This will return a TiSlice, shortly
|
||||||
fn c_relays(&self) -> &[MdConsensusRouterStatus];
|
|
||||||
}
|
}
|
||||||
impl ConsensusRelays for MdConsensus {
|
impl ConsensusRelays for MdConsensus {
|
||||||
fn c_relays(&self) -> &[MdConsensusRouterStatus] {
|
fn c_relays(&self) -> &TiSlice<RouterStatusIdx, MdConsensusRouterStatus> {
|
||||||
MdConsensus::relays(self)
|
TiSlice::from_ref(MdConsensus::relays(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ConsensusRelays for NetDir {
|
impl ConsensusRelays for NetDir {
|
||||||
fn c_relays(&self) -> &[MdConsensusRouterStatus] {
|
fn c_relays(&self) -> &TiSlice<RouterStatusIdx, MdConsensusRouterStatus> {
|
||||||
self.consensus.c_relays()
|
self.consensus.c_relays()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -278,10 +294,10 @@ pub struct NetDir {
|
||||||
params: NetParameters,
|
params: NetParameters,
|
||||||
/// Map from routerstatus index (the position of a routerstatus within the
|
/// Map from routerstatus index (the position of a routerstatus within the
|
||||||
/// consensus), to that routerstatus's microdescriptor (if we have one.)
|
/// consensus), to that routerstatus's microdescriptor (if we have one.)
|
||||||
mds: Vec<Option<Arc<Microdesc>>>,
|
mds: TiVec<RouterStatusIdx, Option<Arc<Microdesc>>>,
|
||||||
/// Map from SHA256 of _missing_ microdescriptors to the position of their
|
/// Map from SHA256 of _missing_ microdescriptors to the position of their
|
||||||
/// corresponding routerstatus indices within `consensus`.
|
/// corresponding routerstatus indices within `consensus`.
|
||||||
rs_idx_by_missing: HashMap<MdDigest, usize>,
|
rs_idx_by_missing: HashMap<MdDigest, RouterStatusIdx>,
|
||||||
/// Map from ed25519 identity to index of the routerstatus within
|
/// Map from ed25519 identity to index of the routerstatus within
|
||||||
/// `self.consensus.relays()`.
|
/// `self.consensus.relays()`.
|
||||||
///
|
///
|
||||||
|
@ -295,13 +311,13 @@ pub struct NetDir {
|
||||||
/// `MdEntry::*::rsa_idx`, it might be cool to have references instead.
|
/// `MdEntry::*::rsa_idx`, it might be cool to have references instead.
|
||||||
/// But that would make this into a self-referential structure,
|
/// But that would make this into a self-referential structure,
|
||||||
/// which isn't possible in safe rust.
|
/// which isn't possible in safe rust.
|
||||||
rs_idx_by_ed: HashMap<Ed25519Identity, usize>,
|
rs_idx_by_ed: HashMap<Ed25519Identity, RouterStatusIdx>,
|
||||||
/// Map from RSA identity to index of the routerstatus within
|
/// Map from RSA identity to index of the routerstatus within
|
||||||
/// `self.consensus.relays()`.
|
/// `self.consensus.relays()`.
|
||||||
///
|
///
|
||||||
/// This is constructed at the same time as the NetDir object, so it
|
/// This is constructed at the same time as the NetDir object, so it
|
||||||
/// can be immutable.
|
/// can be immutable.
|
||||||
rs_idx_by_rsa: Arc<HashMap<RsaIdentity, usize>>,
|
rs_idx_by_rsa: Arc<HashMap<RsaIdentity, RouterStatusIdx>>,
|
||||||
|
|
||||||
/// A hash ring describing the onion service directory.
|
/// A hash ring describing the onion service directory.
|
||||||
///
|
///
|
||||||
|
@ -561,15 +577,13 @@ impl PartialNetDir {
|
||||||
|
|
||||||
let rs_idx_by_missing = consensus
|
let rs_idx_by_missing = consensus
|
||||||
.c_relays()
|
.c_relays()
|
||||||
.iter()
|
.iter_enumerated()
|
||||||
.enumerate()
|
|
||||||
.map(|(rs_idx, rs)| (*rs.md_digest(), rs_idx))
|
.map(|(rs_idx, rs)| (*rs.md_digest(), rs_idx))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let rs_idx_by_rsa = consensus
|
let rs_idx_by_rsa = consensus
|
||||||
.c_relays()
|
.c_relays()
|
||||||
.iter()
|
.iter_enumerated()
|
||||||
.enumerate()
|
|
||||||
.map(|(rs_idx, rs)| (*rs.rsa_identity(), rs_idx))
|
.map(|(rs_idx, rs)| (*rs.rsa_identity(), rs_idx))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -598,7 +612,7 @@ impl PartialNetDir {
|
||||||
let netdir = NetDir {
|
let netdir = NetDir {
|
||||||
consensus: Arc::new(consensus),
|
consensus: Arc::new(consensus),
|
||||||
params,
|
params,
|
||||||
mds: vec![None; n_relays],
|
mds: vec![None; n_relays].into(),
|
||||||
rs_idx_by_missing,
|
rs_idx_by_missing,
|
||||||
rs_idx_by_rsa: Arc::new(rs_idx_by_rsa),
|
rs_idx_by_rsa: Arc::new(rs_idx_by_rsa),
|
||||||
rs_idx_by_ed: HashMap::with_capacity(n_relays),
|
rs_idx_by_ed: HashMap::with_capacity(n_relays),
|
||||||
|
@ -720,7 +734,7 @@ impl NetDir {
|
||||||
fn relay_from_rs_and_idx<'a>(
|
fn relay_from_rs_and_idx<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
rs: &'a netstatus::MdConsensusRouterStatus,
|
rs: &'a netstatus::MdConsensusRouterStatus,
|
||||||
rs_idx: usize,
|
rs_idx: RouterStatusIdx,
|
||||||
) -> UncheckedRelay<'a> {
|
) -> UncheckedRelay<'a> {
|
||||||
debug_assert_eq!(self.c_relays()[rs_idx].rsa_identity(), rs.rsa_identity());
|
debug_assert_eq!(self.c_relays()[rs_idx].rsa_identity(), rs.rsa_identity());
|
||||||
let md = self.mds[rs_idx].as_deref();
|
let md = self.mds[rs_idx].as_deref();
|
||||||
|
@ -753,8 +767,7 @@ impl NetDir {
|
||||||
// TODO: I'd like if we could memoize this so we don't have to
|
// TODO: I'd like if we could memoize this so we don't have to
|
||||||
// do so many hashtable lookups.
|
// do so many hashtable lookups.
|
||||||
self.c_relays()
|
self.c_relays()
|
||||||
.iter()
|
.iter_enumerated()
|
||||||
.enumerate()
|
|
||||||
.map(move |(idx, rs)| self.relay_from_rs_and_idx(rs, idx))
|
.map(move |(idx, rs)| self.relay_from_rs_and_idx(rs, idx))
|
||||||
}
|
}
|
||||||
/// Return an iterator over all usable Relays.
|
/// Return an iterator over all usable Relays.
|
||||||
|
|
Loading…
Reference in New Issue