Skip to content

Commit

Permalink
feat: add proof of participation merkleization
Browse files Browse the repository at this point in the history
  • Loading branch information
rupansh committed Nov 27, 2024
1 parent bc8334f commit de54223
Show file tree
Hide file tree
Showing 34 changed files with 1,399 additions and 189 deletions.
199 changes: 155 additions & 44 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion src/canister/individual_user_template/can.did
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,12 @@ type PostViewStatistics = record {
threshold_view_count : nat64;
};
type Principals = record { principals : vec principal };
type ProofOfChild = record { "principal" : principal; signature : blob };
type ProofOfChild = record {
proof_of_inclusion : vec blob;
"principal" : principal;
children_proof : ProofOfChildren;
};
type ProofOfChildren = record { signature : blob; merkle_root : blob };
type ProofOfParticipation = record { chain : vec ProofOfChild };
type RejectionCode = variant {
NoError;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use ic_cdk::api::call::ArgDecoderConfig;
use ic_cdk_macros::post_upgrade;
use ic_stable_structures::Memory;
use shared_utils::{
canister_specific::platform_orchestrator::types::args::PlatformOrchestratorInitArgs,
canister_specific::{platform_orchestrator::types::args::PlatformOrchestratorInitArgs, post_cache},
common::utils::system_time,
};

Expand All @@ -13,6 +13,7 @@ use crate::{data_model::memory, CANISTER_DATA};
pub fn post_upgrade() {
restore_data_from_stable_memory();
update_version_from_args();
initialize_children_merkle();
}

fn restore_data_from_stable_memory() {
Expand All @@ -38,3 +39,13 @@ fn update_version_from_args() {
canister_data.version_detail.last_update_on = system_time::get_current_system_time();
})
}

// TODO: remove this once the upgrade is complete
fn initialize_children_merkle() {
CANISTER_DATA.with_borrow_mut(|cdata| {
let mut children: Vec<_> = cdata.subnet_orchestrators().iter().copied().collect();
children.extend(cdata.post_cache_orchestrators());

cdata.children_merkle.insert_children(children)
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@ use crate::{guard::is_caller::is_caller_global_admin_or_controller, CANISTER_DAT
#[update(guard = "is_caller_global_admin_or_controller")]
fn deregister_subnet_orchestrator(canister_id: Principal, remove_it_completely: bool) {
CANISTER_DATA.with_borrow_mut(|canister_data| {
canister_data
.subet_orchestrator_with_capacity_left
.remove(&canister_id);

if remove_it_completely {
canister_data
.all_subnet_orchestrator_canisters_list
.remove(&canister_id);
}
canister_data.remove_subnet_orchestrator(canister_id, remove_it_completely);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::CANISTER_DATA;
#[query]
fn get_all_subnet_orchestrators() -> Vec<Principal> {
CANISTER_DATA.with_borrow(|canister_data| {
let canisters = canister_data.all_subnet_orchestrator_canisters_list.iter().map(|canister_id| {*canister_id}).collect::<Vec<Principal>>();
let canisters = canister_data.subnet_orchestrators().iter().map(|canister_id| {*canister_id}).collect::<Vec<Principal>>();
canisters
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ async fn issue_update_known_principal_for_all_subnet(
) {
let subnet_list: Vec<Principal> = CANISTER_DATA.with_borrow(|canister_data| {
canister_data
.all_subnet_orchestrator_canisters_list
.subnet_orchestrators()
.iter()
.copied()
.collect()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{guard::is_caller::is_caller_global_admin_or_controller, CANISTER_DAT
#[update(guard = "is_caller_global_admin_or_controller")]
async fn populate_known_principal_for_all_subnet() {
let subnet_orchestrators: Vec<Principal> = CANISTER_DATA.with_borrow(|canister_data| {
canister_data.all_subnet_orchestrator_canisters_list.iter().copied().collect()
canister_data.subnet_orchestrators().iter().copied().collect()
});

for subnet_id in subnet_orchestrators {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,19 +105,14 @@ pub async fn provision_subnet_orchestrator_canister(
);

CANISTER_DATA.with_borrow_mut(|canister_data| {
canister_data
.all_post_cache_orchestrator_list
.insert(post_cache_canister_id);
canister_data
.all_subnet_orchestrator_canisters_list
.insert(subnet_orchestrator_canister_id);
canister_data
.subet_orchestrator_with_capacity_left
.insert(subnet_orchestrator_canister_id);
canister_data.insert_subnet_orchestrator_and_post_cache(
subnet_orchestrator_canister_id,
post_cache_canister_id
);
});

let mut proof_of_participation = ProofOfParticipation::new_for_root();
proof_of_participation = proof_of_participation.derive_for_child(subnet_orchestrator_canister_id).await.unwrap();
proof_of_participation = proof_of_participation.derive_for_child(&CANISTER_DATA, subnet_orchestrator_canister_id).await.unwrap();
let user_index_init_arg = UserIndexInitArgs {
known_principal_ids: Some(known_principal_map.clone()),
access_control_map: None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ async fn register_new_subnet_orchestrator(

if let Some(first_subnet_orchestrator) = CANISTER_DATA.with_borrow(|canister_data| {
canister_data
.all_subnet_orchestrator_canisters_list
.subnet_orchestrators()
.iter()
.next()
.copied()
Expand All @@ -59,15 +59,10 @@ async fn register_new_subnet_orchestrator(
}

CANISTER_DATA.with_borrow_mut(|canister_data| {
canister_data
.all_subnet_orchestrator_canisters_list
.insert(new_subnet_orchestrator_caniter_id);

if subnet_is_available_for_provisioning_individual_canister {
canister_data
.subet_orchestrator_with_capacity_left
.insert(new_subnet_orchestrator_caniter_id);
}
canister_data.insert_subnet_orchestrator(
new_subnet_orchestrator_caniter_id,
subnet_is_available_for_provisioning_individual_canister,
);
Ok(())
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{guard::is_caller::is_caller_global_admin_or_controller, CANISTER_DAT
async fn stop_upgrades_for_individual_user_canisters() -> Result<String, String> {

let subnet_orchestrator_list = CANISTER_DATA.with_borrow(|canister_data| {
canister_data.all_subnet_orchestrator_canisters_list.clone()
canister_data.subnet_orchestrators().clone()
});

for subnet_orchestrator in subnet_orchestrator_list {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{guard::is_caller::is_caller_global_admin_or_controller, CANISTER_DAT
#[update(guard = "is_caller_global_admin_or_controller")]
async fn update_canisters_last_functionality_access_time() -> Result<String, String> {
let subnet_orchestrator_list = CANISTER_DATA
.with_borrow(|canister_data| canister_data.all_subnet_orchestrator_canisters_list.clone());
.with_borrow(|canister_data| canister_data.subnet_orchestrators().clone());

for subnet_orchestrator in subnet_orchestrator_list {
let result: CallResult<()> = call(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::CANISTER_DATA;
#[update]
fn update_profile_owner_for_individual_canisters() {
CANISTER_DATA.with_borrow(|canister_data| {
canister_data.all_subnet_orchestrator_canisters_list.iter().for_each(|subnet_canster_id| {
canister_data.subnet_orchestrators().iter().for_each(|subnet_canster_id| {
let _ = ic_cdk::notify(*subnet_canster_id, "update_profile_owner_for_individual_canisters", ());
})
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{guard::is_caller::is_caller_global_admin_or_controller, CANISTER_DAT
#[update(guard = "is_caller_global_admin_or_controller")]
async fn update_restart_timers_hon_game() -> Result<String, String> {
let subnet_orchestrator_list = CANISTER_DATA
.with_borrow(|canister_data| canister_data.all_subnet_orchestrator_canisters_list.clone());
.with_borrow(|canister_data| canister_data.subnet_orchestrators().clone());

for subnet_orchestrator in subnet_orchestrator_list {
let result: CallResult<()> = call(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ async fn upgrade_individual_canisters(upgrade_arg: UpgradeCanisterArg) {
canister_data.last_subnet_canister_upgrade_status.count = 0;
});
let subnet_orchestrator_canisters = CANISTER_DATA
.with_borrow(|canister_data| canister_data.all_subnet_orchestrator_canisters_list.clone());
.with_borrow(|canister_data| canister_data.subnet_orchestrators().clone());

for subnet_orchestrator in subnet_orchestrator_canisters.iter() {
match recharge_subnet_orchestrator_if_needed(*subnet_orchestrator).await {
Expand Down Expand Up @@ -118,9 +118,9 @@ async fn upgrade_subnet_canisters(upgrade_arg: UpgradeCanisterArg) {

let canister_list = CANISTER_DATA.with_borrow(|canister_data| {
match upgrade_arg.canister {
WasmType::PostCacheWasm => Ok(canister_data.all_post_cache_orchestrator_list.clone()),
WasmType::PostCacheWasm => Ok(canister_data.post_cache_orchestrators().clone()),
WasmType::SubnetOrchestratorWasm => {
Ok(canister_data.all_subnet_orchestrator_canisters_list.clone())
Ok(canister_data.subnet_orchestrators().clone())
}
_ => Err(()),
}
Expand Down Expand Up @@ -256,7 +256,7 @@ async fn upgrade_subnet_orchestrator_canister(
) -> Result<(), String> {
// TODO: remove this when all subnet orchestrators are upgraded
let mut proof_of_participation = ProofOfParticipation::new_for_root();
proof_of_participation = proof_of_participation.derive_for_child(canister_id).await?;
proof_of_participation = proof_of_participation.derive_for_child(&CANISTER_DATA, canister_id).await?;

let install_code_arg = InstallCodeArgument {
mode: CanisterInstallMode::Upgrade(None),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{guard::is_caller::is_caller_global_admin_or_controller, CANISTER_DAT
#[update(guard = "is_caller_global_admin_or_controller")]
fn upgrade_specific_individual_canister(individual_canister_id: Principal) {
CANISTER_DATA.with_borrow(|canister_data| {
canister_data.all_subnet_orchestrator_canisters_list.iter().for_each(|subnet_id| {
canister_data.subnet_orchestrators().iter().for_each(|subnet_id| {
let _ = ic_cdk::notify(*subnet_id, "upgrade_specific_individual_user_canister_with_latest_wasm", (individual_canister_id, ));
})
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{guard::is_caller::is_caller_global_admin_or_controller, CANISTER_DAT
fn start_reclaiming_cycles_from_individual_canisters() -> Result<String, String> {
CANISTER_DATA.with_borrow(|canister_data| {
canister_data
.all_subnet_orchestrator_canisters_list
.subnet_orchestrators()
.iter()
.for_each(|subnet_orchestrator_id| {
ic_cdk::notify(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{guard::is_caller::is_caller_global_admin_or_controller, CANISTER_DAT
#[update(guard = "is_caller_global_admin_or_controller")]
async fn start_reclaiming_cycles_from_subnet_orchestrator_canister() -> String {
CANISTER_DATA.with_borrow(|canister_data| {
canister_data.all_subnet_orchestrator_canisters_list.iter().for_each(|subnet_orchestrator_id| {
canister_data.subnet_orchestrators().iter().for_each(|subnet_orchestrator_id| {
ic_cdk::notify(*subnet_orchestrator_id, "return_cycles_to_platform_orchestrator_canister", ()).unwrap();
});
});
Expand Down
59 changes: 55 additions & 4 deletions src/canister/platform_orchestrator/src/data_model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ use shared_utils::{
SubnetUpgradeReport,
},
},
common::types::wasm::{CanisterWasm, WasmType},
types::creator_dao_stats::CreatorDaoTokenStats,
common::{
participant_crypto::{merkle::ChildrenMerkle, ProofOfParticipationDeriverStore},
types::{
wasm::{CanisterWasm, WasmType},
creator_dao_stats::CreatorDaoTokenStats,
},
};

use self::memory::{
Expand All @@ -34,8 +38,8 @@ pub struct StateGuard {

#[derive(Serialize, Deserialize)]
pub struct CanisterData {
pub all_subnet_orchestrator_canisters_list: HashSet<Principal>,
pub all_post_cache_orchestrator_list: HashSet<Principal>,
all_subnet_orchestrator_canisters_list: HashSet<Principal>,
all_post_cache_orchestrator_list: HashSet<Principal>,
pub subet_orchestrator_with_capacity_left: HashSet<Principal>,
pub version_detail: VersionDetails,
#[serde(skip, default = "_default_wasms")]
Expand All @@ -53,6 +57,8 @@ pub struct CanisterData {
pub state_guard: StateGuard,
#[serde(default)]
pub creator_dao_stats: CreatorDaoTokenStats,
#[serde(default)]
pub children_merkle: ChildrenMerkle,
}

fn _default_wasms() -> StableBTreeMap<WasmType, CanisterWasm, Memory> {
Expand Down Expand Up @@ -82,10 +88,55 @@ impl Default for CanisterData {
subnets_upgrade_report: SubnetUpgradeReport::default(),
state_guard: StateGuard::default(),
creator_dao_stats: CreatorDaoTokenStats::default(),
children_merkle: ChildrenMerkle::default(),
}
}
}

impl CanisterData {
pub fn insert_subnet_orchestrator_and_post_cache(&mut self, subnet_orchestrator: Principal, post_cache: Principal) {
self.all_subnet_orchestrator_canisters_list.insert(subnet_orchestrator);
self.all_post_cache_orchestrator_list.insert(post_cache);
self.subet_orchestrator_with_capacity_left.insert(subnet_orchestrator);
self.children_merkle.insert_children([subnet_orchestrator, post_cache]);
}

pub fn insert_subnet_orchestrator(&mut self, subnet_orchestrator: Principal, provisioning_available: bool) {
self.all_subnet_orchestrator_canisters_list.insert(subnet_orchestrator);
if provisioning_available {
self.subet_orchestrator_with_capacity_left.insert(subnet_orchestrator);
}
self.children_merkle.insert_children([subnet_orchestrator]);
}

pub fn remove_subnet_orchestrator(&mut self, subnet_orchestrator: Principal, remove_it_completely: bool) {
self.subet_orchestrator_with_capacity_left.remove(&subnet_orchestrator);
if remove_it_completely {
self.all_subnet_orchestrator_canisters_list.remove(&subnet_orchestrator);
// WARN: does not revoke their Proof of Participation
self.children_merkle.remove_child(subnet_orchestrator);
}
}

pub fn subnet_orchestrators(&self) -> &HashSet<Principal> {
&self.all_subnet_orchestrator_canisters_list
}

pub fn post_cache_orchestrators(&self) -> &HashSet<Principal> {
&self.all_post_cache_orchestrator_list
}
}

impl ProofOfParticipationDeriverStore for CanisterData {
fn children_merkle(&self) -> &ChildrenMerkle {
&self.children_merkle
}

fn children_merkle_mut(&mut self) -> &mut ChildrenMerkle {
&mut self.children_merkle
}
}

#[derive(Serialize, Deserialize, CandidType, Clone)]
pub struct VersionDetails {
pub version: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl RegisteredSubnetOrchestrator {
pub fn new(canister_id: Principal) -> Result<RegisteredSubnetOrchestrator, String> {
let contains = CANISTER_DATA.with_borrow(|canister_data| {
canister_data
.all_subnet_orchestrator_canisters_list
.subnet_orchestrators()
.contains(&canister_id)
});

Expand Down
7 changes: 6 additions & 1 deletion src/canister/user_index/can.did
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,12 @@ type KnownPrincipalType = variant {
UserIdGlobalSuperAdmin;
};
type LogVisibility = variant { controllers; public };
type ProofOfChild = record { "principal" : principal; signature : blob };
type ProofOfChild = record {
proof_of_inclusion : vec blob;
"principal" : principal;
children_proof : ProofOfChildren;
};
type ProofOfChildren = record { signature : blob; merkle_root : blob };
type ProofOfParticipation = record { chain : vec ProofOfChild };
type QueryStats = record {
response_payload_bytes_total : nat;
Expand Down
Loading

0 comments on commit de54223

Please sign in to comment.