-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmod.rs
More file actions
210 lines (187 loc) · 6.79 KB
/
Copy pathmod.rs
File metadata and controls
210 lines (187 loc) · 6.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
//! Verification check infrastructure: result types and status enum.
use serde::{Deserialize, Serialize};
/// Status of a single verification check.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum CheckStatus {
Pass,
Fail,
Warn,
Skip,
}
impl std::fmt::Display for CheckStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Pass => write!(f, "PASS"),
Self::Fail => write!(f, "FAIL"),
Self::Warn => write!(f, "WARN"),
Self::Skip => write!(f, "SKIP"),
}
}
}
impl CheckStatus {
/// Severity rank for worst-status aggregation: `Fail > Warn > Pass > Skip`.
///
/// This is the order the hand-rolled worst-status folds in
/// `relay_pipeline::run_relay_checks` implied (a `Fail` from any relay must
/// win the aggregate; `Skip` is the least severe). Deriving `Ord` would use
/// declaration order (`Pass, Fail, Warn, Skip`) which is NOT this order, so
/// the rank is spelled out explicitly.
fn severity(self) -> u8 {
match self {
Self::Skip => 0,
Self::Pass => 1,
Self::Warn => 2,
Self::Fail => 3,
}
}
}
impl Ord for CheckStatus {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.severity().cmp(&other.severity())
}
}
impl PartialOrd for CheckStatus {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
/// Result of a single verification check.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CheckResult {
pub id: String,
pub tier: u8,
#[serde(rename = "result")]
pub status: CheckStatus,
pub detail: String,
#[serde(default = "empty_data")]
pub data: serde_json::Value,
/// The check was ARMED and produced no evidence either way.
///
/// Distinct from an annotative WARN. A Law 3 feature check that sets up a
/// differential and then observes nothing has not found a benign anomaly, it
/// has failed to measure: the scenario ran, proved nothing, and would
/// otherwise exit 0 because tier-1 WARN is non-fatal. `--require-feature-proof`
/// makes a tier-1 inconclusive check fail the run.
///
/// Do NOT set this for a check that is structurally unable to confirm its
/// feature (e.g. `skip_sigverify` on the happy path, a negative codepath that
/// emits nothing when it fires). That is an honest WARN, not a failure to
/// measure, and flagging it would make the scenario permanently red.
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub inconclusive: bool,
}
fn empty_data() -> serde_json::Value {
serde_json::Value::Object(serde_json::Map::new())
}
impl CheckResult {
pub fn pass(id: impl Into<String>, tier: u8, detail: impl Into<String>) -> Self {
Self {
id: id.into(),
tier,
status: CheckStatus::Pass,
detail: detail.into(),
data: empty_data(),
inconclusive: false,
}
}
pub fn fail(id: impl Into<String>, tier: u8, detail: impl Into<String>) -> Self {
Self {
id: id.into(),
tier,
status: CheckStatus::Fail,
detail: detail.into(),
data: empty_data(),
inconclusive: false,
}
}
pub fn warn(id: impl Into<String>, tier: u8, detail: impl Into<String>) -> Self {
Self {
id: id.into(),
tier,
status: CheckStatus::Warn,
detail: detail.into(),
data: empty_data(),
inconclusive: false,
}
}
pub fn skip(id: impl Into<String>, tier: u8, detail: impl Into<String>) -> Self {
Self {
id: id.into(),
tier,
status: CheckStatus::Skip,
detail: detail.into(),
data: empty_data(),
inconclusive: false,
}
}
pub fn with_data(mut self, data: serde_json::Value) -> Self {
self.data = data;
self
}
/// Mark this check as armed-but-unmeasured. See [`CheckResult::inconclusive`].
pub fn mark_inconclusive(mut self) -> Self {
self.inconclusive = true;
self
}
}
pub mod best_bid;
pub mod cb_metrics;
pub mod chain_health;
pub mod feature_fired;
pub mod mux_routing;
pub mod payload_matching;
pub mod relay_pipeline;
pub mod signer;
#[cfg(test)]
mod status_ord_tests {
use super::CheckStatus;
// Contract: the worst-status ordering is Fail > Warn > Pass > Skip. This is
// the rank the hand-rolled folds in run_relay_checks aggregate by, so
// `.max()` over an iterator of statuses reproduces "the worst wins".
#[test]
fn severity_order_is_fail_warn_pass_skip() {
assert!(CheckStatus::Fail > CheckStatus::Warn);
assert!(CheckStatus::Warn > CheckStatus::Pass);
assert!(CheckStatus::Pass > CheckStatus::Skip);
// Transitively, Fail is the maximum and Skip the minimum.
assert!(CheckStatus::Fail > CheckStatus::Skip);
}
// Contract: Fail beats Warn beats Pass when aggregating a mixed set.
#[test]
fn max_picks_fail_over_warn_over_pass() {
let statuses = [CheckStatus::Pass, CheckStatus::Warn, CheckStatus::Fail];
assert_eq!(statuses.into_iter().max(), Some(CheckStatus::Fail));
let no_fail = [CheckStatus::Pass, CheckStatus::Warn, CheckStatus::Pass];
assert_eq!(no_fail.into_iter().max(), Some(CheckStatus::Warn));
let all_pass = [CheckStatus::Pass, CheckStatus::Pass];
assert_eq!(all_pass.into_iter().max(), Some(CheckStatus::Pass));
}
// Contract: Skip is the least severe, so a Skip mixed with any real verdict
// never wins the aggregate (mirrors the registrations fold: Skip+Pass=Pass).
#[test]
fn skip_is_least_severe() {
assert_eq!(
[CheckStatus::Skip, CheckStatus::Pass].into_iter().max(),
Some(CheckStatus::Pass)
);
assert_eq!(
[CheckStatus::Skip, CheckStatus::Warn].into_iter().max(),
Some(CheckStatus::Warn)
);
// An all-Skip set aggregates to Skip (this input is unreachable in the
// registrations fold, which is why that fold's old init-Pass and this
// rule differ only on the impossible case — see the fold's comment).
assert_eq!(
[CheckStatus::Skip, CheckStatus::Skip].into_iter().max(),
Some(CheckStatus::Skip)
);
}
// Contract: an empty iterator yields None; callers pick their own default
// (run_relay_checks guards non-emptiness before aggregating).
#[test]
fn empty_iter_max_is_none() {
let empty: [CheckStatus; 0] = [];
assert_eq!(empty.into_iter().max(), None);
}
}