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