Skip to main content

ic_query/sns/report/model/reports/upgrade/
mod.rs

1//! Module: sns::report::model::reports::upgrade
2//!
3//! Responsibility: bounded native SNS upgrade report DTOs.
4//! Does not own: Governance or SNS-W calls, target admission, lookup, or rendering.
5//! Boundary: preserves native versions and validates their shared hash representation.
6
7use 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///
14/// SnsVersion
15///
16/// Native six-role SNS Wasm version represented as lowercase hexadecimal hashes.
17///
18
19#[derive(Clone, Debug, Eq, PartialEq, SerdeDeserialize, Serialize)]
20#[serde(deny_unknown_fields)]
21pub struct SnsVersion {
22    /// Archive Wasm hash.
23    pub archive_wasm_hash_hex: String,
24    /// Root Wasm hash.
25    pub root_wasm_hash_hex: String,
26    /// Swap Wasm hash.
27    pub swap_wasm_hash_hex: String,
28    /// Ledger Wasm hash.
29    pub ledger_wasm_hash_hex: String,
30    /// Governance Wasm hash.
31    pub governance_wasm_hash_hex: String,
32    /// Ledger index Wasm hash.
33    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///
58/// SnsPendingUpgrade
59///
60/// Native pending-upgrade state reported by SNS Governance.
61///
62
63#[derive(Clone, Debug, Eq, PartialEq, SerdeDeserialize, Serialize)]
64#[serde(deny_unknown_fields)]
65pub struct SnsPendingUpgrade {
66    /// Native deadline after which Governance may mark the upgrade failed.
67    pub mark_failed_at_seconds: u64,
68    /// Native Governance upgrade-lock checking value.
69    pub checking_upgrade_lock: u64,
70    /// NNS proposal that initiated the pending upgrade.
71    pub proposal_id: u64,
72    /// Pending target version, when Governance returned it.
73    pub target_version: Option<SnsVersion>,
74}
75
76///
77/// SnsUpgradeQueryGap
78///
79/// Failed next-version query retained after deployed-version collection succeeded.
80///
81
82#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
83pub struct SnsUpgradeQueryGap {
84    /// Native SNS-W method that failed.
85    pub method: SnsCanisterMethod,
86    /// Transport, encoding, or decoding failure retained for diagnostics.
87    pub reason: String,
88}
89
90///
91/// SnsUpgradeReport
92///
93/// Bounded live report of one SNS deployed, pending, and next blessed version.
94///
95
96#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
97pub struct SnsUpgradeReport {
98    /// Report schema version.
99    pub schema_version: u32,
100    /// SNS identity and provenance, serialized as flat report fields.
101    #[serde(flatten)]
102    pub context: SnsReportContext,
103    /// Native Governance running-version method.
104    pub running_version_method: SnsCanisterMethod,
105    /// Native SNS-W next-version method.
106    pub next_version_method: SnsCanisterMethod,
107    /// Whether both component responses represent one authoritative point in time.
108    pub point_in_time_guaranteed: bool,
109    /// Fixed number of bounded upgrade component queries attempted.
110    pub component_query_count: usize,
111    /// Number of component queries that returned successfully.
112    pub successful_component_query_count: usize,
113    /// Number of retained next-version query gaps.
114    pub component_gap_count: usize,
115    /// Governance-reported deployed SNS version.
116    pub deployed_version: SnsVersion,
117    /// Governance-reported pending upgrade, when present.
118    pub pending_upgrade: Option<SnsPendingUpgrade>,
119    /// Next blessed SNS-W version, or `None` when no successor exists.
120    pub next_version: Option<SnsVersion>,
121    /// Failed next-version query, distinct from a successful response with no successor.
122    pub next_version_gap: Option<SnsUpgradeQueryGap>,
123}
124
125#[cfg(test)]
126mod tests;