diff --git a/core/upgrader/impl/src/lib.rs b/core/upgrader/impl/src/lib.rs index 5d335de7..449f4f62 100644 --- a/core/upgrader/impl/src/lib.rs +++ b/core/upgrader/impl/src/lib.rs @@ -1,4 +1,4 @@ -use crate::model::{DisasterRecovery, LogEntry}; +use crate::model::{DisasterRecovery, DisasterRecoveryV0, LogEntry}; use crate::services::insert_logs; use crate::upgrade::{ CheckController, Upgrade, Upgrader, WithAuthorization, WithBackground, WithLogs, WithStart, @@ -152,10 +152,10 @@ fn post_upgrade() { // if a principal can be parsed out of memory with OLD_MEMORY_ID_TARGET_CANISTER_ID // then we need to perform stable memory migration if let Ok(target_canister) = serde_cbor::from_slice::(&target_canister_bytes.0) { - let old_disaster_recovery: StableValue = StableValue::init( + let old_disaster_recovery: StableValue = StableValue::init( old_memory_manager.get(MemoryId::new(OLD_MEMORY_ID_DISASTER_RECOVERY)), ); - let disaster_recovery: DisasterRecovery = + let disaster_recovery: DisasterRecoveryV0 = old_disaster_recovery.get(&()).unwrap_or_default(); let old_logs: StableBTreeMap = @@ -168,7 +168,7 @@ fn post_upgrade() { let state = State { target_canister, - disaster_recovery, + disaster_recovery: disaster_recovery.into(), stable_memory_version: STABLE_MEMORY_VERSION, }; set_state(state); diff --git a/core/upgrader/impl/src/mappers/disaster_recovery.rs b/core/upgrader/impl/src/mappers/disaster_recovery.rs index 4e829c7d..ebdcd9aa 100644 --- a/core/upgrader/impl/src/mappers/disaster_recovery.rs +++ b/core/upgrader/impl/src/mappers/disaster_recovery.rs @@ -1,8 +1,9 @@ use crate::model::{ - RequestDisasterRecoveryInstallCodeLog, RequestDisasterRecoveryOperationLog, + DisasterRecovery, DisasterRecoveryV0, RequestDisasterRecoveryInstallCodeLog, + RequestDisasterRecoveryOperationLog, StationRecoveryRequest, StationRecoveryRequestInstallCodeOperation, StationRecoveryRequestInstallCodeOperationFootprint, StationRecoveryRequestOperation, - StationRecoveryRequestOperationFootprint, + StationRecoveryRequestOperationFootprint, StationRecoveryRequestV0, }; use orbit_essentials::utils::sha256_hash; @@ -78,3 +79,42 @@ impl From<&StationRecoveryRequestOperation> for upgrader_api::StationRecoveryReq } } } + +// legacy types + +impl From for StationRecoveryRequest { + fn from(request: StationRecoveryRequestV0) -> Self { + Self { + user_id: request.user_id, + operation: StationRecoveryRequestOperation::InstallCode( + StationRecoveryRequestInstallCodeOperation { + install_mode: request.install_mode, + wasm_module: request.wasm_module, + wasm_module_extra_chunks: request.wasm_module_extra_chunks, + wasm_sha256: request.wasm_sha256, + arg: request.arg, + arg_sha256: request.arg_sha256, + }, + ), + submitted_at: request.submitted_at, + } + } +} + +impl From for DisasterRecovery { + fn from(disaster_recovery: DisasterRecoveryV0) -> Self { + Self { + accounts: disaster_recovery.accounts, + multi_asset_accounts: disaster_recovery.multi_asset_accounts, + assets: disaster_recovery.assets, + committee: disaster_recovery.committee, + recovery_requests: disaster_recovery + .recovery_requests + .into_iter() + .map(|request| request.into()) + .collect(), + recovery_status: disaster_recovery.recovery_status, + last_recovery_result: disaster_recovery.last_recovery_result, + } + } +} diff --git a/core/upgrader/impl/src/model/disaster_recovery.rs b/core/upgrader/impl/src/model/disaster_recovery.rs index 9527b8f6..05440c3d 100644 --- a/core/upgrader/impl/src/model/disaster_recovery.rs +++ b/core/upgrader/impl/src/model/disaster_recovery.rs @@ -511,6 +511,62 @@ impl From for upgrader_api::GetDisasterRecoveryStateResponse { } } +// legacy types + +#[storable] +#[derive(Clone, Debug)] +pub struct StationRecoveryRequestV0 { + /// The user ID of the station. + pub user_id: UUID, + /// The wasm module to be installed. + #[serde(with = "serde_bytes")] + pub wasm_module: Vec, + /// Optional extra chunks of the wasm module to be installed. + pub wasm_module_extra_chunks: Option, + /// The SHA-256 hash of the wasm module. + pub wasm_sha256: Vec, + /// The install mode: upgrade or reinstall. + pub install_mode: InstallMode, + /// The install arguments. + #[serde(with = "serde_bytes")] + pub arg: Vec, + /// The SHA-256 hash of the install arguments. + pub arg_sha256: Vec, + /// Time in nanoseconds since the UNIX epoch when the request was submitted. + pub submitted_at: Timestamp, +} + +#[storable] +#[derive(Clone, Debug)] +pub struct DisasterRecoveryV0 { + pub accounts: Vec, + + #[serde(default)] + pub multi_asset_accounts: Vec, + #[serde(default)] + pub assets: Vec, + + pub committee: Option, + + pub recovery_requests: Vec, + pub recovery_status: RecoveryStatus, + pub last_recovery_result: Option, +} + +impl Default for DisasterRecoveryV0 { + fn default() -> Self { + DisasterRecoveryV0 { + accounts: vec![], + multi_asset_accounts: vec![], + assets: vec![], + committee: None, + recovery_requests: vec![], + recovery_status: RecoveryStatus::Idle, + last_recovery_result: None, + } + } +} + #[cfg(test)] pub mod tests { use candid::Principal; diff --git a/core/upgrader/impl/src/model/logging.rs b/core/upgrader/impl/src/model/logging.rs index 5609bc49..feb5b000 100644 --- a/core/upgrader/impl/src/model/logging.rs +++ b/core/upgrader/impl/src/model/logging.rs @@ -46,7 +46,7 @@ impl std::fmt::Display for RequestDisasterRecoveryOperationLog { RequestDisasterRecoveryOperationLog::InstallCode(install_code) => { write!( f, - "InstallCode with mode{}, wasm hash {}, and arg hash {}", + "InstallCode with mode {}, wasm hash {}, and arg hash {}", install_code.install_mode, install_code.wasm_sha256, install_code.arg_sha256 ) } diff --git a/tests/integration/src/upgrader_test_data.rs b/tests/integration/src/upgrader_test_data.rs index 147796f3..a820737e 100644 --- a/tests/integration/src/upgrader_test_data.rs +++ b/tests/integration/src/upgrader_test_data.rs @@ -314,6 +314,30 @@ impl<'a> UpgraderDataGenerator<'a> { ); let logs = get_all_upgrader_logs(self.env, &self.upgrader_id, &self.some_committee_member()); - assert_eq!(logs, self.logs); + assert_eq!(logs.len(), self.logs.len()); + for (i, log) in logs.iter().enumerate() { + assert_eq!(log.time, self.logs[i].time); + assert_eq!(log.entry_type, self.logs[i].entry_type); + // we made a breaking change to the log message format + if log.message != self.logs[i].message { + assert!( + log.message + .contains("requested disaster recovery with wasm hash") + || log + .message + .contains("Disaster recovery successfully initiated to") + ); + assert!( + self.logs[i] + .message + .contains("requested disaster recovery with operation") + || self.logs[i] + .message + .contains("Disaster recovery successfully initiated with operation") + ); + } else { + assert_eq!(log.data_json, self.logs[i].data_json); + } + } } }