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

            
13
use super::*;
14

            
15
ns_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
pub 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)]
94
pub 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)]
122
pub 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)]
196
pub 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]
216
pub struct NetworkStatusSignatures {
217
    /// `directory-signature`s
218
    pub directory_signature: ns_type!(Vec<Signature>, Vec<Signature>, Signature),
219
}
220

            
221
impl Preamble {
222
    /// Calculate the validity range (time interval) for this network status document
223
385
    pub fn validity_time_range(&self) -> std::ops::Range<SystemTime> {
224
385
        let lifetime = self.lifetime.clone();
225
385
        let delay = self.voting_delay.unwrap_or((0, 0));
226
385
        let dist_interval = time::Duration::from_secs(delay.1.into());
227
385
        let starting_time = lifetime.valid_after.saturating_sub(dist_interval);
228
385
        starting_time..*lifetime.valid_until
229
385
    }
230
}