ic_query/sns/report/model/reports/
upgrade.rs1use super::invocation::SnsCanisterMethod;
8#[cfg(any(test, feature = "sns-host"))]
9use crate::hex::is_canonical_lowercase_hex;
10use crate::sns::report::SnsReportContext;
11use serde::{Deserialize as SerdeDeserialize, Serialize};
12
13#[derive(Clone, Debug, Eq, PartialEq, SerdeDeserialize, Serialize)]
20#[serde(deny_unknown_fields)]
21pub struct SnsVersion {
22 pub archive_wasm_hash_hex: String,
24 pub root_wasm_hash_hex: String,
26 pub swap_wasm_hash_hex: String,
28 pub ledger_wasm_hash_hex: String,
30 pub governance_wasm_hash_hex: String,
32 pub index_wasm_hash_hex: String,
34}
35
36#[cfg(any(test, feature = "sns-host"))]
37impl SnsVersion {
38 pub(in crate::sns::report) fn validate_hashes(&self, field: &str) -> Result<(), String> {
39 for (role, hash) in [
40 ("archive", self.archive_wasm_hash_hex.as_str()),
41 ("root", self.root_wasm_hash_hex.as_str()),
42 ("swap", self.swap_wasm_hash_hex.as_str()),
43 ("ledger", self.ledger_wasm_hash_hex.as_str()),
44 ("governance", self.governance_wasm_hash_hex.as_str()),
45 ("index", self.index_wasm_hash_hex.as_str()),
46 ] {
47 if !is_canonical_lowercase_hex(hash) {
48 return Err(format!(
49 "{field}.{role}_wasm_hash_hex is not lowercase even-length hexadecimal text"
50 ));
51 }
52 }
53 Ok(())
54 }
55}
56
57#[derive(Clone, Debug, Eq, PartialEq, SerdeDeserialize, Serialize)]
64#[serde(deny_unknown_fields)]
65pub struct SnsPendingUpgrade {
66 pub mark_failed_at_seconds: u64,
68 pub checking_upgrade_lock: u64,
70 pub proposal_id: u64,
72 pub target_version: Option<SnsVersion>,
74}
75
76#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
83pub struct SnsUpgradeQueryGap {
84 pub method: SnsCanisterMethod,
86 pub reason: String,
88}
89
90#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
97pub struct SnsUpgradeReport {
98 pub schema_version: u32,
100 #[serde(flatten)]
102 pub context: SnsReportContext,
103 pub running_version_method: SnsCanisterMethod,
105 pub next_version_method: SnsCanisterMethod,
107 pub point_in_time_guaranteed: bool,
109 pub component_query_count: usize,
111 pub successful_component_query_count: usize,
113 pub component_gap_count: usize,
115 pub deployed_version: SnsVersion,
117 pub pending_upgrade: Option<SnsPendingUpgrade>,
119 pub next_version: Option<SnsVersion>,
121 pub next_version_gap: Option<SnsUpgradeQueryGap>,
123}
124
125#[cfg(test)]
126mod tests {
127 use super::SnsVersion;
128
129 #[test]
130 fn version_hash_admission_preserves_upgrade_policy() {
131 for (hash, upgrade_valid) in [
132 ("0a".repeat(32), true),
133 ("0a".to_string(), true),
134 ("0a".repeat(33), true),
135 (String::new(), false),
136 ("a".to_string(), false),
137 ("AB".repeat(32), false),
138 ("zz".repeat(32), false),
139 ] {
140 let version = SnsVersion {
141 archive_wasm_hash_hex: hash.clone(),
142 root_wasm_hash_hex: hash.clone(),
143 swap_wasm_hash_hex: hash.clone(),
144 ledger_wasm_hash_hex: hash.clone(),
145 governance_wasm_hash_hex: hash.clone(),
146 index_wasm_hash_hex: hash,
147 };
148 assert_eq!(version.validate_hashes("version").is_ok(), upgrade_valid);
149 }
150 }
151}