Skip to content

Commit 99b0b96

Browse files
committed
Merge branch 'mraszyk/ic00-canister-info' into 'master'
feat: Add canister_info management canister call This MR adds a new management canister call called `canister_info` to retrieve public information about a canister. Its Candid type is ``` canister_info : (record { canister_id : canister_id; num_requested_changes : opt nat64; }) -> (record { total_num_changes : nat64; changes : vec canister_change; module_hash : opt blob; controllers : vec principal; }); ``` See merge request dfinity-lab/public/ic!12603
2 parents bc32d91 + bb67891 commit 99b0b96

File tree

10 files changed

+431
-31
lines changed

10 files changed

+431
-31
lines changed

rs/execution_environment/src/canister_manager.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ impl CanisterManager {
311311
// are not allowed to send.
312312
Err(_)
313313
| Ok(Ic00Method::CreateCanister)
314+
| Ok(Ic00Method::CanisterInfo)
314315
| Ok(Ic00Method::ECDSAPublicKey)
315316
| Ok(Ic00Method::SetupInitialDKG)
316317
| Ok(Ic00Method::SignWithECDSA)

rs/execution_environment/src/execution_environment.rs

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ use ic_crypto_tecdsa::derive_tecdsa_public_key;
2424
use ic_cycles_account_manager::{CyclesAccountManager, IngressInductionCost};
2525
use ic_error_types::{ErrorCode, RejectCode, UserError};
2626
use ic_ic00_types::{
27-
CanisterChangeOrigin, CanisterHttpRequestArgs, CanisterIdRecord, CanisterSettingsArgs,
28-
ComputeInitialEcdsaDealingsArgs, CreateCanisterArgs, ECDSAPublicKeyArgs,
29-
ECDSAPublicKeyResponse, EcdsaKeyId, EmptyBlob, InstallCodeArgs, Method as Ic00Method,
30-
Payload as Ic00Payload, ProvisionalCreateCanisterWithCyclesArgs, ProvisionalTopUpCanisterArgs,
31-
SetControllerArgs, SetupInitialDKGArgs, SignWithECDSAArgs, UninstallCodeArgs,
32-
UpdateSettingsArgs, IC_00,
27+
CanisterChangeOrigin, CanisterHttpRequestArgs, CanisterIdRecord, CanisterInfoRequest,
28+
CanisterInfoResponse, CanisterSettingsArgs, ComputeInitialEcdsaDealingsArgs,
29+
CreateCanisterArgs, ECDSAPublicKeyArgs, ECDSAPublicKeyResponse, EcdsaKeyId, EmptyBlob,
30+
InstallCodeArgs, Method as Ic00Method, Payload as Ic00Payload,
31+
ProvisionalCreateCanisterWithCyclesArgs, ProvisionalTopUpCanisterArgs, SetControllerArgs,
32+
SetupInitialDKGArgs, SignWithECDSAArgs, UninstallCodeArgs, UpdateSettingsArgs, IC_00,
3333
};
3434
use ic_interfaces::{
3535
execution_environment::{
@@ -657,6 +657,23 @@ impl ExecutionEnvironment {
657657
Some((res, msg.take_cycles()))
658658
}
659659

660+
Ok(Ic00Method::CanisterInfo) => match &msg {
661+
CanisterCall::Request(_) => {
662+
let res = match CanisterInfoRequest::decode(payload) {
663+
Err(err) => Err(err),
664+
Ok(record) => self.get_canister_info(
665+
record.canister_id(),
666+
record.num_requested_changes(),
667+
&state,
668+
),
669+
};
670+
Some((res, msg.take_cycles()))
671+
}
672+
CanisterCall::Ingress(_) => {
673+
self.reject_unexpected_ingress(Ic00Method::CanisterInfo)
674+
}
675+
},
676+
660677
Ok(Ic00Method::StartCanister) => {
661678
let res = match CanisterIdRecord::decode(payload) {
662679
Err(err) => Err(err),
@@ -1354,6 +1371,32 @@ impl ExecutionEnvironment {
13541371
.map_err(|err| err.into())
13551372
}
13561373

1374+
fn get_canister_info(
1375+
&self,
1376+
canister_id: CanisterId,
1377+
num_requested_changes: Option<u64>,
1378+
state: &ReplicatedState,
1379+
) -> Result<Vec<u8>, UserError> {
1380+
let canister = get_canister(canister_id, state)?;
1381+
let canister_history = canister.system_state.get_canister_history();
1382+
let total_num_changes = canister_history.get_total_num_changes();
1383+
let changes = canister_history
1384+
.get_changes(num_requested_changes.unwrap_or(0) as usize)
1385+
.map(|e| (*e.clone()).clone())
1386+
.collect();
1387+
let module_hash = canister
1388+
.execution_state
1389+
.as_ref()
1390+
.map(|es| es.wasm_binary.binary.module_hash().to_vec());
1391+
let controllers = canister
1392+
.controllers()
1393+
.iter()
1394+
.copied()
1395+
.collect::<Vec<PrincipalId>>();
1396+
let res = CanisterInfoResponse::new(total_num_changes, changes, module_hash, controllers);
1397+
Ok(res.encode())
1398+
}
1399+
13571400
fn stop_canister(
13581401
&self,
13591402
canister_id: CanisterId,
@@ -2335,6 +2378,19 @@ pub(crate) fn subnet_memory_capacity(config: &ExecutionConfig) -> SubnetAvailabl
23352378
)
23362379
}
23372380

2381+
fn get_canister(
2382+
canister_id: CanisterId,
2383+
state: &ReplicatedState,
2384+
) -> Result<&CanisterState, UserError> {
2385+
match state.canister_state(&canister_id) {
2386+
Some(canister) => Ok(canister),
2387+
None => Err(UserError::new(
2388+
ErrorCode::CanisterNotFound,
2389+
format!("Canister {} not found.", &canister_id),
2390+
)),
2391+
}
2392+
}
2393+
23382394
fn get_canister_mut(
23392395
canister_id: CanisterId,
23402396
state: &mut ReplicatedState,

rs/execution_environment/src/scheduler.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,6 +2124,7 @@ fn get_instructions_limits_for_subnet_message(
21242124
match Ic00Method::from_str(method_name) {
21252125
Ok(method) => match method {
21262126
CanisterStatus
2127+
| CanisterInfo
21272128
| CreateCanister
21282129
| DeleteCanister
21292130
| DepositCycles

0 commit comments

Comments
 (0)