Skip to main content

ic_query/system/cmc/
mod.rs

1//! Certified Cycle Minting Canister ICP/XDR and cycles reports.
2
3#[cfg(feature = "host")]
4mod build;
5mod model;
6#[cfg(feature = "host")]
7mod source;
8mod text;
9#[cfg(feature = "host")]
10mod wire;
11
12#[cfg(feature = "host")]
13use crate::runtime::RuntimeError;
14#[cfg(feature = "host")]
15use thiserror::Error as ThisError;
16
17#[cfg(feature = "host")]
18pub use build::{
19    build_cmc_cycles_report, build_cmc_cycles_report_with_source, build_cmc_xdr_report,
20    build_cmc_xdr_report_with_source,
21};
22#[cfg(feature = "host")]
23pub use model::CmcCertifiedRate;
24pub use model::{
25    CmcCertification, CmcCyclesReport, CmcIcpXdrConversionRate, CmcReportContext, CmcXdrReport,
26};
27#[cfg(feature = "host")]
28pub use source::{CmcSource, CmcSourceRequest, LiveCmcSource};
29pub use text::{cmc_cycles_report_text, cmc_xdr_report_text};
30
31/// Mainnet Cycle Minting Canister principal.
32pub const MAINNET_CMC_CANISTER_ID: &str = "rkp4c-7iaaa-aaaaa-aaaca-cai";
33
34/// Default replica endpoint used for live CMC queries.
35pub const DEFAULT_CMC_SOURCE_ENDPOINT: &str = "https://icp-api.io";
36
37/// IC protocol conversion constant: one XDR corresponds to one trillion cycles.
38pub const CYCLES_PER_XDR: u128 = 1_000_000_000_000;
39
40#[cfg(feature = "host")]
41const ICP_XDR_PERMYRIAD_DENOMINATOR: u128 = 10_000;
42#[cfg(feature = "host")]
43const CMC_REPORT_SCHEMA_VERSION: u32 = 1;
44
45///
46/// CmcHostError
47///
48/// Failure while collecting or validating one live CMC report.
49///
50
51#[cfg(feature = "host")]
52#[derive(Debug, ThisError)]
53pub enum CmcHostError {
54    /// The requested network is not the supported mainnet identity.
55    #[error(
56        "`icq system` supports only the mainnet `ic` network\n\nThese reports query the Internet Computer mainnet Cycle Minting Canister.\n\nTry:\n  icq --network ic system xdr"
57    )]
58    UnsupportedNetwork {
59        /// Rejected network identity.
60        network: String,
61    },
62
63    /// The IC agent could not be constructed for the requested endpoint.
64    #[error("failed to build IC agent for {endpoint}: {reason}")]
65    AgentBuild {
66        /// Endpoint used to build the agent.
67        endpoint: String,
68        /// Agent construction failure.
69        reason: String,
70    },
71
72    /// The built-in mainnet CMC principal could not be parsed.
73    #[error("invalid built-in CMC canister principal: {reason}")]
74    CanisterId {
75        /// Principal parsing failure.
76        reason: String,
77    },
78
79    /// The CMC query call failed.
80    #[error("CMC agent call {method} failed: {reason}")]
81    AgentCall {
82        /// CMC method being queried.
83        method: &'static str,
84        /// Agent call failure.
85        reason: String,
86    },
87
88    /// The CMC query argument could not be Candid encoded.
89    #[error("failed to encode Candid {message}: {reason}")]
90    CandidEncode {
91        /// Candid request type.
92        message: &'static str,
93        /// Encoding failure.
94        reason: String,
95    },
96
97    /// The CMC response could not be Candid decoded.
98    #[error("failed to decode Candid {message}: {reason}")]
99    CandidDecode {
100        /// Candid response type.
101        message: &'static str,
102        /// Decoding failure.
103        reason: String,
104    },
105
106    /// The CMC certificate signature or delegation did not authenticate.
107    #[error("CMC certified-rate authentication failed: {reason}")]
108    CertificateAuthentication {
109        /// Authentication failure detail from the IC agent.
110        reason: String,
111    },
112
113    /// The CMC certified-rate witness did not prove the returned rate.
114    #[error("invalid CMC certified-rate evidence: {reason}")]
115    InvalidCertifiedRate {
116        /// Deterministic witness validation failure.
117        reason: String,
118    },
119
120    /// A custom CMC source returned structurally inconsistent evidence.
121    #[error("invalid CMC source data: {reason}")]
122    InvalidSourceData {
123        /// Deterministic source-contract failure.
124        reason: String,
125    },
126
127    /// The synchronous host runtime could not execute the live query.
128    #[error(transparent)]
129    Runtime(#[from] RuntimeError),
130}
131
132#[cfg(feature = "host")]
133fn enforce_mainnet_network(network: &str) -> Result<(), CmcHostError> {
134    crate::network::enforce_mainnet_network_with(network, |network| {
135        CmcHostError::UnsupportedNetwork { network }
136    })
137}
138
139#[cfg(all(test, feature = "host"))]
140mod tests;