Skip to content

Commit

Permalink
Use OpenChatInstaller to install GroupIndex and NotificationsIndex (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
hpeebles authored Jan 3, 2025
1 parent 0752545 commit 85c2e39
Show file tree
Hide file tree
Showing 13 changed files with 190 additions and 152 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use candid::{CandidType, Principal};
use serde::{Deserialize, Serialize};
use types::{BuildVersion, CanisterId, CanisterWasm};
use types::{BuildVersion, CanisterId};

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub struct Args {
Expand All @@ -10,7 +10,6 @@ pub struct Args {
pub authorizers: Vec<CanisterId>,
pub cycles_dispenser_canister_id: CanisterId,
pub registry_canister_id: CanisterId,
pub notifications_canister_wasm: CanisterWasm,
pub wasm_version: BuildVersion,
pub test_mode: bool,
}
5 changes: 2 additions & 3 deletions backend/canisters/notifications_index/impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ impl Data {
user_index_canister_id: CanisterId,
cycles_dispenser_canister_id: CanisterId,
registry_canister_id: CanisterId,
notifications_canister_wasm: CanisterWasm,
test_mode: bool,
) -> Data {
Data {
Expand All @@ -153,8 +152,8 @@ impl Data {
registry_canister_id,
principal_to_user_id_map: PrincipalToUserIdMap::default(),
subscriptions: Subscriptions::default(),
notifications_canister_wasm_for_new_canisters: notifications_canister_wasm.clone(),
notifications_canister_wasm_for_upgrades: notifications_canister_wasm,
notifications_canister_wasm_for_new_canisters: CanisterWasm::default(),
notifications_canister_wasm_for_upgrades: CanisterWasm::default(),
canisters_requiring_upgrade: CanistersRequiringUpgrade::default(),
notifications_index_event_sync_queue: CanisterEventSyncQueue::default(),
rng_seed: [0; 32],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ fn init(args: Args) {
args.user_index_canister_id,
args.cycles_dispenser_canister_id,
args.registry_canister_id,
args.notifications_canister_wasm,
args.test_mode,
);

Expand Down
4 changes: 3 additions & 1 deletion backend/canisters/openchat_installer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

### Added

- Add OpenChatInstaller canister ([#7137](https://github.com/open-chat-labs/open-chat/pull/7137))
- Add OpenChatInstaller canister ([#7137](https://github.com/open-chat-labs/open-chat/pull/7137))
- Use OpenChatInstaller to install UserIndex ([#7137](https://github.com/open-chat-labs/open-chat/pull/7137))
- Use OpenChatInstaller to install GroupIndex and NotificationsIndex ([#7141](https://github.com/open-chat-labs/open-chat/pull/7141))
2 changes: 2 additions & 0 deletions backend/canisters/openchat_installer/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ pub use updates::*;
#[derive(CandidType, Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum CanisterType {
UserIndex,
GroupIndex,
NotificationsIndex,
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use types::{BuildVersion, Hash};
#[derive(CandidType, Serialize, Deserialize, Debug)]
pub struct Args {
pub user_index_wasm_hash: Hash,
pub group_index_wasm_hash: Hash,
pub notifications_index_wasm_hash: Hash,
pub video_call_operators: Vec<Principal>,
pub push_service_principals: Vec<Principal>,
pub wasm_version: BuildVersion,
}

Expand Down
3 changes: 3 additions & 0 deletions backend/canisters/openchat_installer/impl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@ canister_api_macros = { path = "../../../libraries/canister_api_macros" }
canister_logger = { path = "../../../libraries/canister_logger" }
canister_state_macros = { path = "../../../libraries/canister_state_macros" }
canister_tracing_macros = { path = "../../../libraries/canister_tracing_macros" }
futures = { workspace = true }
group_index_canister = { path = "../../group_index/api" }
hex = { workspace = true }
http_request = { path = "../../../libraries/http_request" }
human_readable = { path = "../../../libraries/human_readable" }
ic-cdk = { workspace = true }
ic-cdk-timers = { workspace = true }
ic-stable-structures = { workspace = true }
msgpack = { path = "../../../libraries/msgpack" }
notifications_index_canister = { path = "../../notifications_index/api" }
openchat_installer_canister = { path = "../api" }
rand = { workspace = true }
serde = { workspace = true }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::guards::caller_is_governance_principal;
use crate::{read_state, State};
use candid::CandidType;
use canister_tracing_macros::trace;
use ic_cdk::api::call::CallResult;
use ic_cdk::api::management_canister::main::CanisterInstallMode;
use ic_cdk::update;
use openchat_installer_canister::install_canisters::{Response::*, *};
Expand All @@ -14,63 +15,60 @@ use utils::canister::{
#[update(guard = "caller_is_governance_principal")]
#[trace]
async fn install_canisters(args: Args) -> Response {
let wasm_version = args.wasm_version;

let PrepareResult {
user_index_canister_id,
user_index_wasm,
user_index_wasm_hash,
user_index_init_args,
user_index,
group_index,
notifications_index,
} = match read_state(|state| prepare(args, state)) {
Ok(ok) => ok,
Err(response) => return response,
};

let chunks = match upload_wasm_in_chunks(&user_index_wasm, user_index_canister_id).await {
Ok(chunks) => chunks,
Err(error) => return InternalError(format!("{error:?}")),
};

if let Err(error) = install(CanisterToInstall {
canister_id: user_index_canister_id,
current_wasm_version: BuildVersion::default(),
new_wasm_version: user_index_init_args.wasm_version,
new_wasm: WasmToInstall::Chunked(ChunkedWasmToInstall {
chunks,
wasm_hash: user_index_wasm_hash,
store_canister_id: user_index_canister_id,
}),
deposit_cycles_if_needed: false,
args: user_index_init_args,
mode: CanisterInstallMode::Install,
stop_start_canister: false,
})
.await
{
return InternalError(format!("{error:?}"));
};

let _ = clear_chunk_store(user_index_canister_id).await;
let results = futures::future::try_join3(
install_canister(user_index, wasm_version),
install_canister(group_index, wasm_version),
install_canister(notifications_index, wasm_version),
)
.await;

Success
match results {
Ok(_) => Success,
Err(error) => InternalError(format!("{error:?}")),
}
}

struct PrepareResult {
user_index_canister_id: CanisterId,
user_index_wasm: CanisterWasmBytes,
user_index_wasm_hash: Hash,
user_index_init_args: user_index_canister::init::Args,
user_index: InstallCanisterArgs<user_index_canister::init::Args>,
group_index: InstallCanisterArgs<group_index_canister::init::Args>,
notifications_index: InstallCanisterArgs<notifications_index_canister::init::Args>,
}

struct InstallCanisterArgs<A: CandidType> {
canister_id: CanisterId,
wasm: CanisterWasmBytes,
wasm_hash: Hash,
init_args: A,
}

fn prepare(args: Args, state: &State) -> Result<PrepareResult, Response> {
let user_index_wasm_hash = state.data.canister_wasms.chunks_hash(CanisterType::UserIndex);
let group_index_wasm_hash = state.data.canister_wasms.chunks_hash(CanisterType::GroupIndex);
let notifications_index_wasm_hash = state.data.canister_wasms.chunks_hash(CanisterType::NotificationsIndex);

if user_index_wasm_hash != args.user_index_wasm_hash {
Err(HashMismatch(CanisterType::UserIndex, user_index_wasm_hash))
} else if group_index_wasm_hash != args.group_index_wasm_hash {
Err(HashMismatch(CanisterType::GroupIndex, group_index_wasm_hash))
} else if notifications_index_wasm_hash != args.notifications_index_wasm_hash {
Err(HashMismatch(CanisterType::NotificationsIndex, group_index_wasm_hash))
} else {
Ok(PrepareResult {
user_index_canister_id: state.data.user_index_canister_id,
user_index_wasm: state.data.canister_wasms.wasm_from_chunks(CanisterType::UserIndex),
user_index_wasm_hash: args.user_index_wasm_hash,
user_index_init_args: user_index_canister::init::Args {
let user_index = InstallCanisterArgs {
canister_id: state.data.user_index_canister_id,
wasm: state.data.canister_wasms.wasm_from_chunks(CanisterType::UserIndex),
wasm_hash: args.user_index_wasm_hash,
init_args: user_index_canister::init::Args {
governance_principals: state.data.governance_principals.clone(),
group_index_canister_id: state.data.group_index_canister_id,
notifications_index_canister_id: state.data.notifications_index_canister_id,
Expand All @@ -92,10 +90,76 @@ fn prepare(args: Args, state: &State) -> Result<PrepareResult, Response> {
wasm_version: args.wasm_version,
test_mode: state.data.test_mode,
},
};

let group_index = InstallCanisterArgs {
canister_id: state.data.group_index_canister_id,
wasm: state.data.canister_wasms.wasm_from_chunks(CanisterType::GroupIndex),
wasm_hash: args.group_index_wasm_hash,
init_args: group_index_canister::init::Args {
governance_principals: state.data.governance_principals.clone(),
user_index_canister_id: state.data.user_index_canister_id,
cycles_dispenser_canister_id: state.data.cycles_dispenser_canister_id,
proposals_bot_user_id: state.data.proposals_bot_canister_id.into(),
escrow_canister_id: state.data.escrow_canister_id,
event_relay_canister_id: state.data.event_relay_canister_id,
registry_canister_id: state.data.registry_canister_id,
internet_identity_canister_id: state.data.internet_identity_canister_id,
video_call_operators: args.video_call_operators.clone(),
ic_root_key: state.data.ic_root_key.clone(),
wasm_version: args.wasm_version,
test_mode: state.data.test_mode,
},
};

let notifications_index = InstallCanisterArgs {
canister_id: state.data.notifications_index_canister_id,
wasm: state.data.canister_wasms.wasm_from_chunks(CanisterType::NotificationsIndex),
wasm_hash: args.notifications_index_wasm_hash,
init_args: notifications_index_canister::init::Args {
governance_principals: state.data.governance_principals.clone(),
push_service_principals: args.push_service_principals,
user_index_canister_id: state.data.user_index_canister_id,
authorizers: vec![state.data.user_index_canister_id, state.data.group_index_canister_id],
cycles_dispenser_canister_id: state.data.cycles_dispenser_canister_id,
registry_canister_id: state.data.registry_canister_id,
wasm_version: args.wasm_version,
test_mode: state.data.test_mode,
},
};

Ok(PrepareResult {
user_index,
group_index,
notifications_index,
})
}
}

async fn install_canister<A: CandidType>(args: InstallCanisterArgs<A>, wasm_version: BuildVersion) -> CallResult<()> {
let chunks = upload_wasm_in_chunks(&args.wasm, args.canister_id).await?;

install(CanisterToInstall {
canister_id: args.canister_id,
current_wasm_version: BuildVersion::default(),
new_wasm_version: wasm_version,
new_wasm: WasmToInstall::Chunked(ChunkedWasmToInstall {
chunks,
wasm_hash: args.wasm_hash,
store_canister_id: args.canister_id,
}),
deposit_cycles_if_needed: false,
args: args.init_args,
mode: CanisterInstallMode::Install,
stop_start_canister: false,
})
.await?;

let _ = clear_chunk_store(args.canister_id).await;

Ok(())
}

#[derive(CandidType)]
struct UpgradeArgs {
wasm_version: BuildVersion,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ fn prepare(args: Args, state: &State) -> Result<PrepareResult, Response> {
} else {
let canister_id = match args.canister_type {
CanisterType::UserIndex => state.data.user_index_canister_id,
CanisterType::GroupIndex => state.data.group_index_canister_id,
CanisterType::NotificationsIndex => state.data.notifications_index_canister_id,
};

Ok(PrepareResult {
Expand Down
7 changes: 7 additions & 0 deletions backend/integration_tests/src/client/openchat_installer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ pub mod happy_path {
use pocket_ic::PocketIc;
use types::{BuildVersion, CanisterId, Hash};

#[allow(clippy::too_many_arguments)]
pub fn install_canisters(
env: &mut PocketIc,
sender: Principal,
openchat_installer_canister_id: CanisterId,
user_index_wasm_hash: Hash,
group_index_wasm_hash: Hash,
notifications_index_wasm_hash: Hash,
video_call_operators: Vec<Principal>,
push_service_principals: Vec<Principal>,
wasm_version: BuildVersion,
) {
let response = super::install_canisters(
Expand All @@ -25,7 +29,10 @@ pub mod happy_path {
openchat_installer_canister_id,
&openchat_installer_canister::install_canisters::Args {
user_index_wasm_hash,
group_index_wasm_hash,
notifications_index_wasm_hash,
video_call_operators,
push_service_principals,
wasm_version,
},
);
Expand Down
Loading

0 comments on commit 85c2e39

Please sign in to comment.