tor_netdoc/doc/netstatus/rs/
md.rs

1//! Implementation for the style of router descriptors used in
2//! microdesc consensus documents.
3
4use super::{FromRsString, GenericRouterStatus};
5use crate::doc::microdesc::MdDigest;
6use crate::doc::netstatus::{
7    ConsensusFlavor, NetstatusKwd, ParseRouterStatus, RelayFlags, RelayWeight, RouterStatus,
8};
9use crate::types::misc::*;
10use crate::{parse::parser::Section, util::private::Sealed};
11use crate::{Error, Result};
12use std::net;
13
14use tor_error::internal;
15use tor_llcrypto::pk::rsa::RsaIdentity;
16use tor_protover::Protocols;
17
18/// A single relay's status, as represented in a microdesc consensus.
19#[cfg_attr(
20    feature = "dangerous-expose-struct-fields",
21    visible::StructFields(pub),
22    non_exhaustive
23)]
24#[derive(Debug, Clone)]
25pub struct MdConsensusRouterStatus {
26    /// Underlying generic routerstatus object.
27    ///
28    /// This is private because we don't want to leak that these two
29    /// types have the same implementation "under the hood".
30    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
31    rs: GenericRouterStatus<MdDigest>,
32}
33
34impl From<GenericRouterStatus<MdDigest>> for MdConsensusRouterStatus {
35    fn from(rs: GenericRouterStatus<MdDigest>) -> Self {
36        MdConsensusRouterStatus { rs }
37    }
38}
39
40super::implement_accessors! {MdConsensusRouterStatus}
41
42impl MdConsensusRouterStatus {
43    /// Return the expected microdescriptor digest for this routerstatus
44    pub fn md_digest(&self) -> &MdDigest {
45        &self.rs.doc_digest
46    }
47}
48
49impl Sealed for MdConsensusRouterStatus {}
50
51impl RouterStatus for MdConsensusRouterStatus {
52    type DocumentDigest = MdDigest;
53
54    /// Return the expected microdescriptor digest for this routerstatus
55    fn rsa_identity(&self) -> &RsaIdentity {
56        &self.rs.identity
57    }
58
59    fn doc_digest(&self) -> &MdDigest {
60        self.md_digest()
61    }
62}
63
64impl ParseRouterStatus for MdConsensusRouterStatus {
65    fn flavor() -> ConsensusFlavor {
66        ConsensusFlavor::Microdesc
67    }
68
69    fn from_section(sec: &Section<'_, NetstatusKwd>) -> Result<MdConsensusRouterStatus> {
70        let rs = GenericRouterStatus::from_section(sec, ConsensusFlavor::Microdesc)?;
71        Ok(MdConsensusRouterStatus { rs })
72    }
73}
74
75impl FromRsString for MdDigest {
76    fn decode(s: &str) -> Result<MdDigest> {
77        s.parse::<B64>()?
78            .check_len(32..=32)?
79            .as_bytes()
80            .try_into()
81            .map_err(|_| Error::from(internal!("correct length on digest, but unable to convert")))
82    }
83}