Skip to main content

tor_netdoc/doc/netstatus/
each_variety.rs

1//! network status documents - items for all varieties, that vary
2//!
3//! **This file is reincluded multiple times**,
4//! by the macros in [`crate::doc::ns_variety_definition_macros`],
5//! once for votes, and once for each consensus flavour.
6//! It is *not* a module `crate::doc::netstatus::rs::each_variety`.
7//!
8//! Each time this file is included by one of the macros mentioned above,
9//! the `ns_***` macros (such as `ns_const_name!`) may expand to different values.
10//!
11//! See [`crate::doc::ns_variety_definition_macros`].
12
13use super::*;
14
15ns_use_this_variety! {
16    pub use [crate::doc::netstatus::rs]::?::{RouterStatus};
17}
18
19/// Network status document - consensus, or vote
20///
21/// <https://spec.torproject.org/dir-spec/consensus-formats.html>
22///
23/// <https://spec.torproject.org/dir-spec/computing-consensus.html#flavors>
24#[derive(Clone, Debug, Deftly)]
25#[derive_deftly(Constructor, NetdocEncodable, NetdocParseableUnverified)]
26#[deftly(netdoc(doctype_for_error = NETSTATUS_DOCTYPE_FOR_ERROR))]
27#[allow(clippy::exhaustive_structs)]
28pub struct NetworkStatus {
29    /// The `network-status-version` intro item
30    ///
31    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:network-status-version>
32    ///
33    /// In the "preamble" in the spec, but not in our `Preamble` type for Reasons.
34    pub network_status_version: NetworkStatusVersionItem,
35
36    /// `vote-status`
37    ///
38    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:vote-status>
39    ///
40    /// In the "preamble" in the spec, but not in our `Preamble` type for Reasons.
41    #[deftly(netdoc(single_arg))]
42    pub vote_status: ns_type!(
43        VoteStatusConsensus,
44        VoteStatusConsensus,
45        VoteStatusVote,
46    ),
47
48    /// The rest of the preamble
49    ///
50    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#section:preable>
51    #[deftly(constructor, netdoc(flatten))]
52    pub preamble: Preamble,
53
54    /// Authority section
55    ///
56    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#section:authority>
57    #[deftly(constructor, netdoc(subdoc))]
58    pub authority: ns_type!(
59        ConsensusAuthoritySection,
60        ConsensusAuthoritySection,
61        VoteAuthoritySection,
62    ),
63
64    /// Router status entries
65    ///
66    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#section:router-status>
67    #[deftly(netdoc(subdoc))]
68    pub routers: Vec<RouterStatus>,
69
70    /// Footer
71    ///
72    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#section:footer>
73    #[deftly(netdoc(subdoc))]
74    #[deftly(constructor)]
75    pub footer: Footer,
76
77    #[doc(hidden)]
78    #[deftly(netdoc(skip))]
79    pub __non_exhaustive: (),
80}
81
82/// `network-status-version` intro item in a consensus
83///
84/// This is hard to parse because it's so irregular (even, ambiguous).
85///
86/// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:network-status-version>
87///
88/// <https://spec.torproject.org/dir-spec/computing-consensus.html#flavor:microdesc>
89///
90/// <https://gitlab.torproject.org/tpo/core/torspec/-/work_items/359>
91#[derive(Clone, Debug, Deftly, Default)]
92#[derive_deftly(Constructor, ItemValueEncodable, ItemValueParseable)]
93#[allow(clippy::exhaustive_structs)]
94pub struct NetworkStatusVersionItem {
95    /// The version number, always `3`
96    pub version: NetworkStatusVersion,
97
98    /// The `flavor` argument
99    ///
100    ///  * In a plain consensus, this is an optional `ns`.
101    ///  * In an md consensus, this is always `microdesc`.
102    ///  * In a vote, there is no variety, but to avoid ambiguity, we reject.
103    pub variety: VarietyKeyword,
104
105    #[doc(hidden)]
106    #[deftly(netdoc(skip))]
107    pub __non_exhaustive: (),
108}
109
110/// The preamble of a network status document, except for the intro and `vote-status` items.
111///
112/// <https://spec.torproject.org/dir-spec/consensus-formats.html#section:preable>
113///
114/// **Does not include `network-status-version` and `vote-status`**.
115/// In the old parser this is not represented directly;
116/// instead, in `Consensus.flavor`, there's just the `ConsensusFlavor`.
117/// `parse2` doesn't (currently) support subdocuments which contain the parent's intro item
118/// (ie, `#[deftly(netdoc(flatten))]` is not supported on the first field.)
119#[derive(Clone, Debug, Deftly)]
120#[derive_deftly(Constructor, NetdocEncodableFields, NetdocParseableFields)]
121#[allow(clippy::exhaustive_structs)]
122pub struct Preamble {
123    /// Consensus methods supported by this voter.
124    #[deftly(constructor)]
125    pub consensus_methods: ns_type!( NotPresent, NotPresent, ConsensusMethods ),
126
127    /// What "method" was used to produce this consensus?  (A
128    /// consensus method is a version number used by authorities to
129    /// upgrade the consensus algorithm.)
130    #[deftly(constructor)]
131    // Not #[deftly(netdoc(single_arg))] because that would mean a consensuses
132    // had an always-present singleton `consensus_method` item with no arguments.
133    pub consensus_method: ns_type!( (u32,), (u32,), NotPresent ),
134
135    /// Publication time (of a vote)
136    #[deftly(constructor)]
137    // Not #[deftly(netdoc(single_arg))] because that would mean a consensuses
138    // had an always-present singleton `published` item with no arguments.
139    pub published: ns_type!( NotPresent, NotPresent, (Iso8601TimeSp,) ),
140
141    /// Over what time is this consensus valid?  (For votes, this is
142    /// the time over which the voted-upon consensus should be valid.)
143    #[deftly(constructor)]
144    #[deftly(netdoc(flatten))]
145    pub lifetime: Lifetime,
146
147    /// How long in seconds should voters wait for votes and
148    /// signatures (respectively) to propagate?
149    pub voting_delay: Option<(u32, u32)>,
150
151    /// List of recommended Tor client versions.
152    ///
153    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:client-versions>
154    #[deftly(netdoc(default))]
155    pub client_versions: RecommendedTorVersions,
156
157    /// List of recommended Tor relay versions.
158    ///
159    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:server-versions>
160    #[deftly(netdoc(default))]
161    pub server_versions: RecommendedTorVersions,
162
163    /// Router flags which could be determined
164    #[deftly(constructor)]
165    #[deftly(netdoc(with = "relay_flags::ParserEncoder::<relay_flags::NoImplicitRepr>"))]
166    pub known_flags: DocRelayFlags,
167
168    /// Lists of recommended and required subprotocols.
169    ///
170    /// **`{recommended,required}-{client,relay}-protocols`**
171    #[deftly(constructor)]
172    #[deftly(netdoc(flatten))]
173    pub proto_statuses: Arc<ProtoStatuses>,
174
175    /// Declared parameters for tunable settings about how to the
176    /// network should operator. Some of these adjust timeouts and
177    /// whatnot; some features things on and off.
178    #[deftly(constructor)]
179    pub params: NetParams<i32>,
180
181    /// Global shared-random values
182    #[deftly(netdoc(flatten))]
183    pub shared_rand: ns_type!( SharedRandStatuses, SharedRandStatuses, NotPresent ),
184
185    #[doc(hidden)]
186    #[deftly(netdoc(skip))]
187    pub __non_exhaustive: (),
188}
189
190/// The footer of a network status document.
191///
192/// <https://spec.torproject.org/dir-spec/consensus-formats.html#section:footer>>
193#[derive(Clone, Debug, Deftly)]
194#[derive_deftly(Constructor, NetdocEncodable, NetdocParseable)]
195#[allow(clippy::exhaustive_structs)]
196pub struct Footer {
197    /// Intro item
198    ///
199    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:directory-footer>
200    pub directory_footer: (),
201
202    /// Fields that appear in consensuses (only)
203    #[deftly(constructor, netdoc(flatten))]
204    pub consensus: ns_type!(ConsensusFooterFields, ConsensusFooterFields, NotPresent),
205
206    #[doc(hidden)]
207    #[deftly(netdoc(skip))]
208    pub __non_exhaustive: (),
209}
210
211/// Signatures on a network status document
212#[derive(Deftly, Clone, Debug)]
213#[derive_deftly(NetdocEncodableFields, NetdocParseableSignatures)]
214#[deftly(netdoc(signatures(hashes_accu = "DirectorySignaturesHashesAccu")))]
215#[non_exhaustive]
216pub struct NetworkStatusSignatures {
217    /// `directory-signature`s
218    pub directory_signature: ns_type!(Vec<Signature>, Vec<Signature>, Signature),
219}
220
221impl Preamble {
222    /// Calculate the validity range (time interval) for this network status document
223    pub fn validity_time_range(&self) -> std::ops::Range<SystemTime> {
224        let lifetime = self.lifetime.clone();
225        let delay = self.voting_delay.unwrap_or((0, 0));
226        let dist_interval = time::Duration::from_secs(delay.1.into());
227        let starting_time = lifetime.valid_after.saturating_sub(dist_interval);
228        starting_time..*lifetime.valid_until
229    }
230}