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]::?::{
17
        RouterStatus, RouterStatusConstructor,
18
        RouterStatusIntroItem, RouterStatusIntroItemConstructor,
19
    };
20
}
21

            
22
/// Network status document - consensus, or vote
23
///
24
/// <https://spec.torproject.org/dir-spec/consensus-formats.html>
25
///
26
/// <https://spec.torproject.org/dir-spec/computing-consensus.html#flavors>
27
#[derive(Clone, Debug, Deftly)]
28
#[derive_deftly(Constructor, NetdocEncodable, NetdocParseableUnverified)]
29
#[deftly(netdoc(doctype_for_error = NETSTATUS_DOCTYPE_FOR_ERROR))]
30
#[allow(clippy::exhaustive_structs)]
31
pub struct NetworkStatus {
32
    /// The `network-status-version` intro item
33
    ///
34
    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:network-status-version>
35
    ///
36
    /// In the "preamble" in the spec, but not in our `Preamble` type for Reasons.
37
    pub network_status_version: NetworkStatusVersionItem,
38

            
39
    /// `vote-status`
40
    ///
41
    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:vote-status>
42
    ///
43
    /// In the "preamble" in the spec, but not in our `Preamble` type for Reasons.
44
    #[deftly(netdoc(single_arg))]
45
    pub vote_status: ns_type!(
46
        VoteStatusConsensus,
47
        VoteStatusConsensus,
48
        VoteStatusVote,
49
    ),
50

            
51
    /// The rest of the preamble
52
    ///
53
    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#section:preable>
54
    #[deftly(constructor, netdoc(flatten))]
55
    pub preamble: Preamble,
56

            
57
    /// Authority section
58
    ///
59
    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#section:authority>
60
    #[deftly(constructor, netdoc(subdoc))]
61
    pub authority: ns_type!(
62
        ConsensusAuthoritySection,
63
        ConsensusAuthoritySection,
64
        VoteAuthoritySection,
65
    ),
66

            
67
    /// Router status entries
68
    ///
69
    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#section:router-status>
70
    #[deftly(netdoc(subdoc))]
71
    pub routers: Vec<RouterStatus>,
72

            
73
    /// Footer
74
    ///
75
    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#section:footer>
76
    #[deftly(netdoc(subdoc))]
77
    #[deftly(constructor)]
78
    pub footer: Footer,
79

            
80
    #[doc(hidden)]
81
    #[deftly(netdoc(skip))]
82
    pub __non_exhaustive: (),
83
}
84

            
85
/// `network-status-version` intro item in a consensus
86
///
87
/// This is hard to parse because it's so irregular (even, ambiguous).
88
///
89
/// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:network-status-version>
90
///
91
/// <https://spec.torproject.org/dir-spec/computing-consensus.html#flavor:microdesc>
92
///
93
/// <https://gitlab.torproject.org/tpo/core/torspec/-/work_items/359>
94
#[derive(Clone, Debug, Deftly, Default)]
95
#[derive_deftly(Constructor, ItemValueEncodable, ItemValueParseable)]
96
#[allow(clippy::exhaustive_structs)]
97
pub struct NetworkStatusVersionItem {
98
    /// The version number, always `3`
99
    pub version: NetworkStatusVersion,
100

            
101
    /// The `flavor` argument
102
    ///
103
    ///  * In a plain consensus, this is an optional `ns`.
104
    ///  * In an md consensus, this is always `microdesc`.
105
    ///  * In a vote, there is no variety, but to avoid ambiguity, we reject.
106
    pub variety: VarietyKeyword,
107

            
108
    #[doc(hidden)]
109
    #[deftly(netdoc(skip))]
110
    pub __non_exhaustive: (),
111
}
112

            
113
/// The preamble of a network status document, except for the intro and `vote-status` items.
114
///
115
/// <https://spec.torproject.org/dir-spec/consensus-formats.html#section:preable>
116
///
117
/// **Does not include `network-status-version` and `vote-status`**.
118
/// In the old parser this is not represented directly;
119
/// instead, in `Consensus.flavor`, there's just the `ConsensusFlavor`.
120
/// `parse2` doesn't (currently) support subdocuments which contain the parent's intro item
121
/// (ie, `#[deftly(netdoc(flatten))]` is not supported on the first field.)
122
#[derive(Clone, Debug, Deftly)]
123
#[derive_deftly(Constructor, NetdocEncodableFields, NetdocParseableFields)]
124
#[allow(clippy::exhaustive_structs)]
125
pub struct Preamble {
126
    /// Consensus methods supported by this voter.
127
    #[deftly(constructor)]
128
    pub consensus_methods: ns_type!( NotPresent, NotPresent, ConsensusMethods ),
129

            
130
    /// What "method" was used to produce this consensus?  (A
131
    /// consensus method is a version number used by authorities to
132
    /// upgrade the consensus algorithm.)
133
    #[deftly(constructor)]
134
    // Not #[deftly(netdoc(single_arg))] because that would mean a consensuses
135
    // had an always-present singleton `consensus_method` item with no arguments.
136
    pub consensus_method: ns_type!( (u32,), (u32,), NotPresent ),
137

            
138
    /// Publication time (of a vote)
139
    #[deftly(constructor)]
140
    // Not #[deftly(netdoc(single_arg))] because that would mean a consensuses
141
    // had an always-present singleton `published` item with no arguments.
142
    pub published: ns_type!( NotPresent, NotPresent, (Iso8601TimeSp,) ),
143

            
144
    /// Over what time is this consensus valid?  (For votes, this is
145
    /// the time over which the voted-upon consensus should be valid.)
146
    #[deftly(constructor)]
147
    #[deftly(netdoc(flatten))]
148
    pub lifetime: Lifetime,
149

            
150
    /// How long in seconds should voters wait for votes and
151
    /// signatures (respectively) to propagate?
152
    ///
153
    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:voting-delay>
154
    #[deftly(constructor)]
155
    pub voting_delay: VotingDelay,
156

            
157
    /// List of recommended Tor client versions.
158
    ///
159
    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:client-versions>
160
    #[deftly(netdoc(default))]
161
    pub client_versions: RecommendedTorVersions,
162

            
163
    /// List of recommended Tor relay versions.
164
    ///
165
    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:server-versions>
166
    #[deftly(netdoc(default))]
167
    pub server_versions: RecommendedTorVersions,
168

            
169
    /// Router flags which could be determined
170
    #[deftly(constructor)]
171
    #[deftly(netdoc(with = "relay_flags::ParserEncoder::<relay_flags::NoImplicitRepr>"))]
172
    pub known_flags: DocRelayFlags,
173

            
174
    /// Lists of recommended and required subprotocols.
175
    ///
176
    /// **`{recommended,required}-{client,relay}-protocols`**
177
    #[deftly(constructor)]
178
    #[deftly(netdoc(flatten))]
179
    pub proto_statuses: Arc<ProtoStatuses>,
180

            
181
    /// Declared parameters for tunable settings about how to the
182
    /// network should operator. Some of these adjust timeouts and
183
    /// whatnot; some features things on and off.
184
    #[deftly(constructor)]
185
    pub params: NetParams<i32>,
186

            
187
    /// Global shared-random values
188
    #[deftly(netdoc(flatten))]
189
    pub shared_rand: ns_type!( SharedRandStatuses, SharedRandStatuses, NotPresent ),
190

            
191
    #[doc(hidden)]
192
    #[deftly(netdoc(skip))]
193
    pub __non_exhaustive: (),
194
}
195

            
196
/// The footer of a network status document.
197
///
198
/// <https://spec.torproject.org/dir-spec/consensus-formats.html#section:footer>>
199
#[derive(Clone, Debug, Deftly)]
200
#[derive_deftly(Constructor, NetdocEncodable, NetdocParseable)]
201
#[allow(clippy::exhaustive_structs)]
202
pub struct Footer {
203
    /// Intro item
204
    ///
205
    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:directory-footer>
206
    pub directory_footer: (),
207

            
208
    /// Fields that appear in consensuses (only)
209
    #[deftly(constructor, netdoc(flatten))]
210
    pub consensus: ns_type!(ConsensusFooterFields, ConsensusFooterFields, NotPresent),
211

            
212
    #[doc(hidden)]
213
    #[deftly(netdoc(skip))]
214
    pub __non_exhaustive: (),
215
}
216

            
217
/// Signatures on a network status document
218
#[derive(Deftly, Clone, Debug)]
219
#[derive_deftly(NetdocEncodableFields, NetdocParseableSignatures)]
220
#[deftly(netdoc(signatures(hashes_accu = "DirectorySignaturesHashesAccu")))]
221
#[non_exhaustive]
222
pub struct NetworkStatusSignatures {
223
    /// `directory-signature`s
224
    pub directory_signature: ns_type!(Vec<Signature>, Vec<Signature>, Signature),
225
}
226

            
227
impl Preamble {
228
    /// Calculate the validity range (time interval) for this network status document
229
590
    pub fn validity_time_range(&self) -> std::ops::Range<SystemTime> {
230
590
        let lifetime = self.lifetime.clone();
231
590
        let delay = self.voting_delay;
232
590
        let dist_interval = time::Duration::from_secs(delay.dist_seconds.into());
233
590
        let starting_time = lifetime.valid_after.saturating_sub(dist_interval);
234
590
        starting_time..*lifetime.valid_until
235
590
    }
236
}