pub mod async_job;
pub mod auth;
pub mod authority_restore;
pub mod cycles;
pub mod fleet_activation;
pub mod install;
pub mod intent;
pub mod log;
mod nonroot;
mod root;
pub mod timer;
use crate::ops::storage::{
icp_refill::IcpRefillStoreOps,
intent::{IntentStoreOps, ReceiptBackedIntentOps},
};
use crate::{
InternalError,
log::Topic,
ops::runtime::{env::EnvOps, memory::MemoryRegistryOps},
workflow,
};
pub use nonroot::{
init_local_nonroot_canister, init_local_nonroot_canister_with_automatic_topup,
init_nonroot_canister, init_wasm_store_canister,
post_upgrade_local_nonroot_canister_after_memory_init,
post_upgrade_local_nonroot_canister_with_automatic_topup_after_memory_init,
post_upgrade_nonroot_canister_after_memory_init,
post_upgrade_nonroot_canister_with_automatic_topup_after_memory_init,
};
pub use root::{init_root_canister, post_upgrade_root_canister_after_memory_init};
pub struct RuntimeWorkflow;
impl RuntimeWorkflow {
pub fn start_all() -> Result<(), InternalError> {
workflow::runtime::log::LogRetentionWorkflow::start()?;
workflow::runtime::intent::IntentCleanupWorkflow::start()?;
Ok(())
}
pub fn start_all_with_automatic_topup() -> Result<(), InternalError> {
Self::start_all()?;
workflow::runtime::cycles::CycleWorkflow::start()
}
pub fn start_all_root() -> Result<(), InternalError> {
EnvOps::require_root().map_err(|_err| InternalError::invariant())?;
workflow::runtime::log::LogRetentionWorkflow::start()?;
workflow::runtime::intent::IntentCleanupWorkflow::start()?;
workflow::runtime::auth::RuntimeAuthWorkflow::reconcile_root_issuer_renewal()?;
Ok(())
}
}
pub(super) fn log_memory_summary() {
crate::log!(Topic::Memory, Info, "💾 memory.registry: bootstrapped");
}
fn init_post_upgrade_memory_registry() -> Result<(), InternalError> {
MemoryRegistryOps::bootstrap_registry().map_err(|_err| InternalError::invariant())
}
pub fn init_memory_registry_post_upgrade() -> Result<(), InternalError> {
init_post_upgrade_memory_registry()
}
pub(super) fn rebuild_derived_storage_indexes() -> Result<(), InternalError> {
IntentStoreOps::rebuild_expiry_index()?;
ReceiptBackedIntentOps::reconcile_receipt_indexes()?;
let _receipt_capacity = ReceiptBackedIntentOps::receipt_capacity()?;
Ok(())
}
pub(super) fn rebuild_root_derived_storage_indexes() -> Result<(), InternalError> {
IcpRefillStoreOps::rebuild_indexes()?;
rebuild_derived_storage_indexes()
}
pub(super) fn require_no_resumable_refill_for_upgrade() -> Result<(), InternalError> {
validate_refill_upgrade_admission(IcpRefillStoreOps::resumable_operation_count())
}
const fn validate_refill_upgrade_admission(count: usize) -> Result<(), InternalError> {
if count == 0 {
return Ok(());
}
Err(InternalError::invariant())
}
#[cfg(test)]
mod tests {
use super::validate_refill_upgrade_admission;
#[test]
fn root_upgrade_accepts_terminal_refill_state() {
validate_refill_upgrade_admission(0).expect("terminal refill state should permit upgrade");
}
#[test]
fn root_upgrade_rejects_resumable_refill_state() {
let error = validate_refill_upgrade_admission(1)
.expect_err("resumable refill state must block upgrade");
assert_eq!(error.code(), crate::diagnostics::codes::STATE_INVALID);
}
}