@@ -24,12 +24,12 @@ use ic_crypto_tecdsa::derive_tecdsa_public_key;
2424use ic_cycles_account_manager:: { CyclesAccountManager , IngressInductionCost } ;
2525use ic_error_types:: { ErrorCode , RejectCode , UserError } ;
2626use 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} ;
3434use 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+
23382394fn get_canister_mut (
23392395 canister_id : CanisterId ,
23402396 state : & mut ReplicatedState ,
0 commit comments