From 71b2c69e31a318669e56309c811c75fbe55a7dd0 Mon Sep 17 00:00:00 2001 From: Martin Raszyk Date: Tue, 16 Jun 2026 20:24:04 +0000 Subject: [PATCH 1/4] chore: make input fields in SubnetFeatures of type opt bool in registry canister --- rs/registry/canister/canister/canister.rs | 18 ++-- rs/registry/canister/canister/registry.did | 10 +- .../canister/canister/registry_test.did | 10 +- .../src/mutations/do_create_subnet.rs | 94 ++++++++++++++++++- .../src/mutations/do_update_subnet.rs | 87 +++++++++++++++++ rs/registry/subnet_features/src/lib.rs | 22 +++++ 6 files changed, 228 insertions(+), 13 deletions(-) diff --git a/rs/registry/canister/canister/canister.rs b/rs/registry/canister/canister/canister.rs index b3517e71dd9c..f9852dd6dfd2 100644 --- a/rs/registry/canister/canister/canister.rs +++ b/rs/registry/canister/canister/canister.rs @@ -45,7 +45,7 @@ use registry_canister::{ do_add_node_operator::AddNodeOperatorPayload, do_add_nodes_to_subnet::AddNodesToSubnetPayload, do_change_subnet_membership::ChangeSubnetMembershipPayload, - do_create_subnet::{CreateSubnetPayload, NewSubnet}, + do_create_subnet::{CreateSubnetArg, CreateSubnetPayload, NewSubnet}, do_delete_subnet::DeleteSubnetPayload, do_deploy_guestos_to_all_subnet_nodes::DeployGuestosToAllSubnetNodesPayload, do_deploy_guestos_to_all_unassigned_nodes::DeployGuestosToAllUnassignedNodesPayload, @@ -72,7 +72,7 @@ use registry_canister::{ DeployHostosToSomeNodes, UpdateNodesHostosVersionPayload, }, do_update_ssh_readonly_access_for_all_unassigned_nodes::UpdateSshReadOnlyAccessForAllUnassignedNodesPayload, - do_update_subnet::UpdateSubnetPayload, + do_update_subnet::{UpdateSubnetArg, UpdateSubnetPayload}, do_update_subnet_admins::UpdateSubnetAdminsPayload, do_update_unassigned_nodes_config::UpdateUnassignedNodesConfigPayload, firewall::{ @@ -637,7 +637,7 @@ fn add_node_operator_(payload: AddNodeOperatorPayload) { #[unsafe(export_name = "canister_update create_subnet")] fn create_subnet() { check_caller_is_governance_or_engine_controller_and_log("create_subnet"); - over_async(candid_one, |payload: CreateSubnetPayload| async move { + over_async(candid_one, |payload: CreateSubnetArg| async move { create_subnet_(payload).await }); } @@ -647,8 +647,10 @@ fn create_subnet() { /// panics instead of returning Err (ensuring any partial changes do not get /// committed). #[candid_method(update, rename = "create_subnet")] -async fn create_subnet_(payload: CreateSubnetPayload) -> Result { - let new_subnet = registry_mut().do_create_subnet(payload).await; +async fn create_subnet_(payload: CreateSubnetArg) -> Result { + let new_subnet = registry_mut() + .do_create_subnet(CreateSubnetPayload::from(payload)) + .await; recertify_registry(); Ok(new_subnet) } @@ -871,15 +873,15 @@ fn remove_node_operators_(payload: RemoveNodeOperatorsPayload) { #[unsafe(export_name = "canister_update update_subnet")] fn update_subnet() { check_caller_is_governance_or_engine_controller_and_log("update_subnet"); - over(candid_one, |payload: UpdateSubnetPayload| { + over(candid_one, |payload: UpdateSubnetArg| { update_subnet_(payload) }); } #[candid_method(update, rename = "update_subnet")] -fn update_subnet_(payload: UpdateSubnetPayload) { +fn update_subnet_(payload: UpdateSubnetArg) { let caller = dfn_core::api::caller(); - registry_mut().do_update_subnet(caller, payload); + registry_mut().do_update_subnet(caller, UpdateSubnetPayload::from(payload)); recertify_registry(); } diff --git a/rs/registry/canister/canister/registry.did b/rs/registry/canister/canister/registry.did index 9aea72cb4b98..4301171b681d 100644 --- a/rs/registry/canister/canister/registry.did +++ b/rs/registry/canister/canister/registry.did @@ -86,9 +86,15 @@ type ResourceLimits = record { maximum_state_delta : opt nat64; }; +type SubnetFeaturesInput = record { + canister_sandboxing : opt bool; + http_requests : opt bool; + sev_enabled : opt bool; +}; + type CreateSubnetPayload = record { unit_delay_millis : nat64; - features : SubnetFeatures; + features : SubnetFeaturesInput; max_ingress_bytes_per_message : nat64; max_ingress_bytes_per_block: opt nat64; dkg_dealings_per_block : nat64; @@ -496,7 +502,7 @@ type UpdateSshReadOnlyAccessForAllUnassignedNodesPayload = record { type UpdateSubnetPayload = record { unit_delay_millis : opt nat64; max_duplicity : opt nat32; - features : opt SubnetFeatures; + features : opt SubnetFeaturesInput; resource_limits : opt ResourceLimits; set_gossip_config_to_default : bool; halt_at_cup_height : opt bool; diff --git a/rs/registry/canister/canister/registry_test.did b/rs/registry/canister/canister/registry_test.did index 386a330a1972..c84344c81bc1 100644 --- a/rs/registry/canister/canister/registry_test.did +++ b/rs/registry/canister/canister/registry_test.did @@ -86,9 +86,15 @@ type ResourceLimits = record { maximum_state_delta : opt nat64; }; +type SubnetFeaturesInput = record { + canister_sandboxing : opt bool; + http_requests : opt bool; + sev_enabled : opt bool; +}; + type CreateSubnetPayload = record { unit_delay_millis : nat64; - features : SubnetFeatures; + features : SubnetFeaturesInput; max_ingress_bytes_per_message : nat64; max_ingress_bytes_per_block: opt nat64; dkg_dealings_per_block : nat64; @@ -496,7 +502,7 @@ type UpdateSshReadOnlyAccessForAllUnassignedNodesPayload = record { type UpdateSubnetPayload = record { unit_delay_millis : opt nat64; max_duplicity : opt nat32; - features : opt SubnetFeatures; + features : opt SubnetFeaturesInput; resource_limits : opt ResourceLimits; set_gossip_config_to_default : bool; halt_at_cup_height : opt bool; diff --git a/rs/registry/canister/src/mutations/do_create_subnet.rs b/rs/registry/canister/src/mutations/do_create_subnet.rs index 91a11caf9418..620f44fb6f18 100644 --- a/rs/registry/canister/src/mutations/do_create_subnet.rs +++ b/rs/registry/canister/src/mutations/do_create_subnet.rs @@ -24,7 +24,9 @@ use ic_registry_keys::{ make_node_record_key, make_subnet_list_record_key, make_subnet_record_key, }; use ic_registry_resource_limits::ResourceLimits; -use ic_registry_subnet_features::{KeyConfig as KeyConfigInternal, SubnetFeatures}; +use ic_registry_subnet_features::{ + KeyConfig as KeyConfigInternal, SubnetFeatures, SubnetFeaturesInput, +}; use ic_registry_subnet_type::SubnetType; use ic_registry_transport::pb::v1::{RegistryMutation, RegistryValue, registry_mutation}; use on_wire::bytes; @@ -325,6 +327,96 @@ pub struct CreateSubnetPayload { pub gossip_retransmission_request_ms: u32, } +/// Input type for `create_subnet` canister method. +/// Same as `CreateSubnetPayload` but with `SubnetFeaturesInput` (all `Option`) for `features`. +#[derive(Clone, Eq, PartialEq, Debug, Default, CandidType, Deserialize, Serialize)] +pub struct CreateSubnetArg { + pub node_ids: Vec, + + pub subnet_id_override: Option, + pub initial_dkg_subnet_id: Option, + + pub max_ingress_bytes_per_message: u64, + pub max_ingress_bytes_per_block: Option, + pub max_ingress_messages_per_block: u64, + pub max_block_payload_size: u64, + pub unit_delay_millis: u64, + pub initial_notary_delay_millis: u64, + pub replica_version_id: std::string::String, + pub dkg_interval_length: u64, + pub dkg_dealings_per_block: u64, + + pub start_as_nns: bool, + + pub subnet_type: SubnetType, + + pub is_halted: bool, + + pub features: SubnetFeaturesInput, + + pub max_number_of_canisters: u64, + pub ssh_readonly_access: Vec, + pub ssh_backup_access: Vec, + + pub chain_key_config: Option, + + pub canister_cycles_cost_schedule: Option, + + pub subnet_admins: Option>, + + pub resource_limits: Option, + + // TODO(NNS1-2444): The fields below are deprecated and they are not read anywhere. + pub ingress_bytes_per_block_soft_cap: u64, + pub gossip_max_artifact_streams_per_peer: u32, + pub gossip_max_chunk_wait_ms: u32, + pub gossip_max_duplicity: u32, + pub gossip_max_chunk_size: u32, + pub gossip_receive_check_cache_size: u32, + pub gossip_pfn_evaluation_period_ms: u32, + pub gossip_registry_poll_period_ms: u32, + pub gossip_retransmission_request_ms: u32, +} + +impl From for CreateSubnetPayload { + fn from(arg: CreateSubnetArg) -> Self { + Self { + node_ids: arg.node_ids, + subnet_id_override: arg.subnet_id_override, + initial_dkg_subnet_id: arg.initial_dkg_subnet_id, + max_ingress_bytes_per_message: arg.max_ingress_bytes_per_message, + max_ingress_bytes_per_block: arg.max_ingress_bytes_per_block, + max_ingress_messages_per_block: arg.max_ingress_messages_per_block, + max_block_payload_size: arg.max_block_payload_size, + unit_delay_millis: arg.unit_delay_millis, + initial_notary_delay_millis: arg.initial_notary_delay_millis, + replica_version_id: arg.replica_version_id, + dkg_interval_length: arg.dkg_interval_length, + dkg_dealings_per_block: arg.dkg_dealings_per_block, + start_as_nns: arg.start_as_nns, + subnet_type: arg.subnet_type, + is_halted: arg.is_halted, + features: SubnetFeatures::from(arg.features).into(), + max_number_of_canisters: arg.max_number_of_canisters, + ssh_readonly_access: arg.ssh_readonly_access, + ssh_backup_access: arg.ssh_backup_access, + chain_key_config: arg.chain_key_config, + canister_cycles_cost_schedule: arg.canister_cycles_cost_schedule, + subnet_admins: arg.subnet_admins, + resource_limits: arg.resource_limits, + ingress_bytes_per_block_soft_cap: arg.ingress_bytes_per_block_soft_cap, + gossip_max_artifact_streams_per_peer: arg.gossip_max_artifact_streams_per_peer, + gossip_max_chunk_wait_ms: arg.gossip_max_chunk_wait_ms, + gossip_max_duplicity: arg.gossip_max_duplicity, + gossip_max_chunk_size: arg.gossip_max_chunk_size, + gossip_receive_check_cache_size: arg.gossip_receive_check_cache_size, + gossip_pfn_evaluation_period_ms: arg.gossip_pfn_evaluation_period_ms, + gossip_registry_poll_period_ms: arg.gossip_registry_poll_period_ms, + gossip_retransmission_request_ms: arg.gossip_retransmission_request_ms, + } + } +} + #[derive(Clone, Eq, PartialEq, Debug, Default, CandidType, Deserialize, Serialize)] pub struct NewSubnet { pub new_subnet_id: Option, diff --git a/rs/registry/canister/src/mutations/do_update_subnet.rs b/rs/registry/canister/src/mutations/do_update_subnet.rs index b88f19e29f7d..31315dd6c4df 100644 --- a/rs/registry/canister/src/mutations/do_update_subnet.rs +++ b/rs/registry/canister/src/mutations/do_update_subnet.rs @@ -14,6 +14,7 @@ use ic_protobuf::{ use ic_registry_keys::{make_chain_key_enabled_subnet_list_key, make_subnet_record_key}; use ic_registry_subnet_features::{ ChainKeyConfig as ChainKeyConfigInternal, KeyConfig as KeyConfigInternal, SubnetFeatures, + SubnetFeaturesInput, }; use ic_registry_subnet_type::SubnetType; use ic_registry_transport::{pb::v1::RegistryMutation, upsert}; @@ -402,6 +403,92 @@ pub struct UpdateSubnetPayload { pub set_gossip_config_to_default: bool, } +/// Input type for `update_subnet` canister method. +/// Same as `UpdateSubnetPayload` but with `SubnetFeaturesInput` (all `Option`) for `features`. +#[derive(Clone, Eq, PartialEq, Debug, CandidType, Deserialize, Serialize)] +pub struct UpdateSubnetArg { + pub subnet_id: SubnetId, + + pub max_ingress_bytes_per_message: Option, + pub max_ingress_bytes_per_block: Option, + pub max_ingress_messages_per_block: Option, + pub max_block_payload_size: Option, + pub unit_delay_millis: Option, + pub initial_notary_delay_millis: Option, + pub dkg_interval_length: Option, + pub dkg_dealings_per_block: Option, + + pub start_as_nns: Option, + + pub subnet_type: Option, + + pub is_halted: Option, + pub halt_at_cup_height: Option, + + pub features: Option, + pub resource_limits: Option, + + pub chain_key_config: Option, + pub chain_key_signing_enable: Option>, + pub chain_key_signing_disable: Option>, + + pub max_number_of_canisters: Option, + + pub ssh_readonly_access: Option>, + pub ssh_backup_access: Option>, + + pub subnet_admins: Option>, + + // TODO(NNS1-2444): The fields below are deprecated and they are not read anywhere. + pub max_artifact_streams_per_peer: Option, + pub max_chunk_wait_ms: Option, + pub max_duplicity: Option, + pub max_chunk_size: Option, + pub receive_check_cache_size: Option, + pub pfn_evaluation_period_ms: Option, + pub registry_poll_period_ms: Option, + pub retransmission_request_ms: Option, + pub set_gossip_config_to_default: bool, +} + +impl From for UpdateSubnetPayload { + fn from(arg: UpdateSubnetArg) -> Self { + Self { + subnet_id: arg.subnet_id, + max_ingress_bytes_per_message: arg.max_ingress_bytes_per_message, + max_ingress_bytes_per_block: arg.max_ingress_bytes_per_block, + max_ingress_messages_per_block: arg.max_ingress_messages_per_block, + max_block_payload_size: arg.max_block_payload_size, + unit_delay_millis: arg.unit_delay_millis, + initial_notary_delay_millis: arg.initial_notary_delay_millis, + dkg_interval_length: arg.dkg_interval_length, + dkg_dealings_per_block: arg.dkg_dealings_per_block, + start_as_nns: arg.start_as_nns, + subnet_type: arg.subnet_type, + is_halted: arg.is_halted, + halt_at_cup_height: arg.halt_at_cup_height, + features: arg.features.map(|f| SubnetFeatures::from(f).into()), + resource_limits: arg.resource_limits, + chain_key_config: arg.chain_key_config, + chain_key_signing_enable: arg.chain_key_signing_enable, + chain_key_signing_disable: arg.chain_key_signing_disable, + max_number_of_canisters: arg.max_number_of_canisters, + ssh_readonly_access: arg.ssh_readonly_access, + ssh_backup_access: arg.ssh_backup_access, + subnet_admins: arg.subnet_admins, + max_artifact_streams_per_peer: arg.max_artifact_streams_per_peer, + max_chunk_wait_ms: arg.max_chunk_wait_ms, + max_duplicity: arg.max_duplicity, + max_chunk_size: arg.max_chunk_size, + receive_check_cache_size: arg.receive_check_cache_size, + pfn_evaluation_period_ms: arg.pfn_evaluation_period_ms, + registry_poll_period_ms: arg.registry_poll_period_ms, + retransmission_request_ms: arg.retransmission_request_ms, + set_gossip_config_to_default: arg.set_gossip_config_to_default, + } + } +} + #[derive(Clone, Eq, PartialEq, Debug, Default, CandidType, Deserialize, Serialize)] pub struct ChainKeyConfig { pub key_configs: Vec, diff --git a/rs/registry/subnet_features/src/lib.rs b/rs/registry/subnet_features/src/lib.rs index b9d0dfb2a157..bf2917f45e11 100644 --- a/rs/registry/subnet_features/src/lib.rs +++ b/rs/registry/subnet_features/src/lib.rs @@ -10,6 +10,28 @@ use std::{convert::TryFrom, str::FromStr}; pub const DEFAULT_ECDSA_MAX_QUEUE_SIZE: u32 = 20; +/// Input type for subnet features in canister API calls. +/// All fields are optional; `None` means "use the default value". +#[derive(Copy, Clone, Eq, PartialEq, Debug, Default, CandidType, Deserialize, Serialize)] +pub struct SubnetFeaturesInput { + pub canister_sandboxing: Option, + pub http_requests: Option, + pub sev_enabled: Option, +} + +impl From for SubnetFeatures { + fn from(input: SubnetFeaturesInput) -> Self { + let default = SubnetFeatures::default(); + Self { + canister_sandboxing: input + .canister_sandboxing + .unwrap_or(default.canister_sandboxing), + http_requests: input.http_requests.unwrap_or(default.http_requests), + sev_enabled: input.sev_enabled.unwrap_or(default.sev_enabled), + } + } +} + /// List of features that can be enabled or disabled on the given subnet. #[derive(Copy, Clone, Eq, PartialEq, Debug, CandidType, Deserialize, Serialize)] #[serde(default)] From 759654eff0f5b152f61fc596bc27f0025266d919 Mon Sep 17 00:00:00 2001 From: Martin Raszyk Date: Wed, 17 Jun 2026 06:17:03 +0000 Subject: [PATCH 2/4] changelog --- rs/registry/canister/unreleased_changelog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rs/registry/canister/unreleased_changelog.md b/rs/registry/canister/unreleased_changelog.md index b74d0b6fdf37..897ae4797501 100644 --- a/rs/registry/canister/unreleased_changelog.md +++ b/rs/registry/canister/unreleased_changelog.md @@ -24,6 +24,11 @@ on the process that this file is part of, see ## Changed +* The `features` field in `create_subnet` and `update_subnet` now has each + sub-field (`canister_sandboxing`, `http_requests`, `sev_enabled`) typed as + `opt bool` instead of `bool`. Omitting a sub-field (i.e., passing `null`) + leaves the corresponding feature at its default value. This is a + backward-compatible Candid interface change. * One-time post-upgrade migration converting the reward type of 100 currently unassigned nodes from `type1.1` to `type4.5`. The migration only mutates nodes whose reward type is still `type1.1`, so it is idempotent across upgrades. From f4061ff03e790e6243606f283c8366d5105ff37f Mon Sep 17 00:00:00 2001 From: Martin Raszyk Date: Tue, 23 Jun 2026 06:49:13 +0000 Subject: [PATCH 3/4] rename SubnetFeaturesInput to SubnetFeaturesV2 --- rs/registry/canister/canister/registry.did | 6 +++--- rs/registry/canister/canister/registry_test.did | 6 +++--- rs/registry/canister/src/mutations/do_create_subnet.rs | 6 +++--- rs/registry/canister/src/mutations/do_update_subnet.rs | 6 +++--- rs/registry/subnet_features/src/lib.rs | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/rs/registry/canister/canister/registry.did b/rs/registry/canister/canister/registry.did index 89c9520667d7..b0882a552902 100644 --- a/rs/registry/canister/canister/registry.did +++ b/rs/registry/canister/canister/registry.did @@ -86,7 +86,7 @@ type ResourceLimits = record { maximum_state_delta : opt nat64; }; -type SubnetFeaturesInput = record { +type SubnetFeaturesV2 = record { canister_sandboxing : opt bool; http_requests : opt bool; sev_enabled : opt bool; @@ -94,7 +94,7 @@ type SubnetFeaturesInput = record { type CreateSubnetPayload = record { unit_delay_millis : nat64; - features : SubnetFeaturesInput; + features : SubnetFeaturesV2; max_ingress_bytes_per_message : nat64; max_ingress_bytes_per_block: opt nat64; dkg_dealings_per_block : nat64; @@ -503,7 +503,7 @@ type UpdateSshReadOnlyAccessForAllUnassignedNodesPayload = record { type UpdateSubnetPayload = record { unit_delay_millis : opt nat64; max_duplicity : opt nat32; - features : opt SubnetFeaturesInput; + features : opt SubnetFeaturesV2; resource_limits : opt ResourceLimits; set_gossip_config_to_default : bool; halt_at_cup_height : opt bool; diff --git a/rs/registry/canister/canister/registry_test.did b/rs/registry/canister/canister/registry_test.did index dde4415c310e..9c6aed6a8651 100644 --- a/rs/registry/canister/canister/registry_test.did +++ b/rs/registry/canister/canister/registry_test.did @@ -86,7 +86,7 @@ type ResourceLimits = record { maximum_state_delta : opt nat64; }; -type SubnetFeaturesInput = record { +type SubnetFeaturesV2 = record { canister_sandboxing : opt bool; http_requests : opt bool; sev_enabled : opt bool; @@ -94,7 +94,7 @@ type SubnetFeaturesInput = record { type CreateSubnetPayload = record { unit_delay_millis : nat64; - features : SubnetFeaturesInput; + features : SubnetFeaturesV2; max_ingress_bytes_per_message : nat64; max_ingress_bytes_per_block: opt nat64; dkg_dealings_per_block : nat64; @@ -503,7 +503,7 @@ type UpdateSshReadOnlyAccessForAllUnassignedNodesPayload = record { type UpdateSubnetPayload = record { unit_delay_millis : opt nat64; max_duplicity : opt nat32; - features : opt SubnetFeaturesInput; + features : opt SubnetFeaturesV2; resource_limits : opt ResourceLimits; set_gossip_config_to_default : bool; halt_at_cup_height : opt bool; diff --git a/rs/registry/canister/src/mutations/do_create_subnet.rs b/rs/registry/canister/src/mutations/do_create_subnet.rs index 620f44fb6f18..3b9dfbe2879a 100644 --- a/rs/registry/canister/src/mutations/do_create_subnet.rs +++ b/rs/registry/canister/src/mutations/do_create_subnet.rs @@ -25,7 +25,7 @@ use ic_registry_keys::{ }; use ic_registry_resource_limits::ResourceLimits; use ic_registry_subnet_features::{ - KeyConfig as KeyConfigInternal, SubnetFeatures, SubnetFeaturesInput, + KeyConfig as KeyConfigInternal, SubnetFeatures, SubnetFeaturesV2, }; use ic_registry_subnet_type::SubnetType; use ic_registry_transport::pb::v1::{RegistryMutation, RegistryValue, registry_mutation}; @@ -328,7 +328,7 @@ pub struct CreateSubnetPayload { } /// Input type for `create_subnet` canister method. -/// Same as `CreateSubnetPayload` but with `SubnetFeaturesInput` (all `Option`) for `features`. +/// Same as `CreateSubnetPayload` but with `SubnetFeaturesV2` (all `Option`) for `features`. #[derive(Clone, Eq, PartialEq, Debug, Default, CandidType, Deserialize, Serialize)] pub struct CreateSubnetArg { pub node_ids: Vec, @@ -352,7 +352,7 @@ pub struct CreateSubnetArg { pub is_halted: bool, - pub features: SubnetFeaturesInput, + pub features: SubnetFeaturesV2, pub max_number_of_canisters: u64, pub ssh_readonly_access: Vec, diff --git a/rs/registry/canister/src/mutations/do_update_subnet.rs b/rs/registry/canister/src/mutations/do_update_subnet.rs index 31315dd6c4df..b58bf90baa7b 100644 --- a/rs/registry/canister/src/mutations/do_update_subnet.rs +++ b/rs/registry/canister/src/mutations/do_update_subnet.rs @@ -14,7 +14,7 @@ use ic_protobuf::{ use ic_registry_keys::{make_chain_key_enabled_subnet_list_key, make_subnet_record_key}; use ic_registry_subnet_features::{ ChainKeyConfig as ChainKeyConfigInternal, KeyConfig as KeyConfigInternal, SubnetFeatures, - SubnetFeaturesInput, + SubnetFeaturesV2, }; use ic_registry_subnet_type::SubnetType; use ic_registry_transport::{pb::v1::RegistryMutation, upsert}; @@ -404,7 +404,7 @@ pub struct UpdateSubnetPayload { } /// Input type for `update_subnet` canister method. -/// Same as `UpdateSubnetPayload` but with `SubnetFeaturesInput` (all `Option`) for `features`. +/// Same as `UpdateSubnetPayload` but with `SubnetFeaturesV2` (all `Option`) for `features`. #[derive(Clone, Eq, PartialEq, Debug, CandidType, Deserialize, Serialize)] pub struct UpdateSubnetArg { pub subnet_id: SubnetId, @@ -425,7 +425,7 @@ pub struct UpdateSubnetArg { pub is_halted: Option, pub halt_at_cup_height: Option, - pub features: Option, + pub features: Option, pub resource_limits: Option, pub chain_key_config: Option, diff --git a/rs/registry/subnet_features/src/lib.rs b/rs/registry/subnet_features/src/lib.rs index bf2917f45e11..ad307456323b 100644 --- a/rs/registry/subnet_features/src/lib.rs +++ b/rs/registry/subnet_features/src/lib.rs @@ -13,14 +13,14 @@ pub const DEFAULT_ECDSA_MAX_QUEUE_SIZE: u32 = 20; /// Input type for subnet features in canister API calls. /// All fields are optional; `None` means "use the default value". #[derive(Copy, Clone, Eq, PartialEq, Debug, Default, CandidType, Deserialize, Serialize)] -pub struct SubnetFeaturesInput { +pub struct SubnetFeaturesV2 { pub canister_sandboxing: Option, pub http_requests: Option, pub sev_enabled: Option, } -impl From for SubnetFeatures { - fn from(input: SubnetFeaturesInput) -> Self { +impl From for SubnetFeatures { + fn from(input: SubnetFeaturesV2) -> Self { let default = SubnetFeatures::default(); Self { canister_sandboxing: input From e688a3997ac68b889fcb3b969c3c3548e894d2eb Mon Sep 17 00:00:00 2001 From: Martin Raszyk Date: Tue, 23 Jun 2026 06:55:26 +0000 Subject: [PATCH 4/4] rename CreateSubnetArg/UpdateSubnetArg to CreateSubnetPayloadV2/UpdateSubnetPayloadV2 --- rs/registry/canister/canister/canister.rs | 12 ++++++------ rs/registry/canister/canister/registry.did | 8 ++++---- rs/registry/canister/canister/registry_test.did | 8 ++++---- .../canister/src/mutations/do_create_subnet.rs | 6 +++--- .../canister/src/mutations/do_update_subnet.rs | 6 +++--- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/rs/registry/canister/canister/canister.rs b/rs/registry/canister/canister/canister.rs index f9852dd6dfd2..119293d6e81b 100644 --- a/rs/registry/canister/canister/canister.rs +++ b/rs/registry/canister/canister/canister.rs @@ -45,7 +45,7 @@ use registry_canister::{ do_add_node_operator::AddNodeOperatorPayload, do_add_nodes_to_subnet::AddNodesToSubnetPayload, do_change_subnet_membership::ChangeSubnetMembershipPayload, - do_create_subnet::{CreateSubnetArg, CreateSubnetPayload, NewSubnet}, + do_create_subnet::{CreateSubnetPayload, CreateSubnetPayloadV2, NewSubnet}, do_delete_subnet::DeleteSubnetPayload, do_deploy_guestos_to_all_subnet_nodes::DeployGuestosToAllSubnetNodesPayload, do_deploy_guestos_to_all_unassigned_nodes::DeployGuestosToAllUnassignedNodesPayload, @@ -72,7 +72,7 @@ use registry_canister::{ DeployHostosToSomeNodes, UpdateNodesHostosVersionPayload, }, do_update_ssh_readonly_access_for_all_unassigned_nodes::UpdateSshReadOnlyAccessForAllUnassignedNodesPayload, - do_update_subnet::{UpdateSubnetArg, UpdateSubnetPayload}, + do_update_subnet::{UpdateSubnetPayload, UpdateSubnetPayloadV2}, do_update_subnet_admins::UpdateSubnetAdminsPayload, do_update_unassigned_nodes_config::UpdateUnassignedNodesConfigPayload, firewall::{ @@ -637,7 +637,7 @@ fn add_node_operator_(payload: AddNodeOperatorPayload) { #[unsafe(export_name = "canister_update create_subnet")] fn create_subnet() { check_caller_is_governance_or_engine_controller_and_log("create_subnet"); - over_async(candid_one, |payload: CreateSubnetArg| async move { + over_async(candid_one, |payload: CreateSubnetPayloadV2| async move { create_subnet_(payload).await }); } @@ -647,7 +647,7 @@ fn create_subnet() { /// panics instead of returning Err (ensuring any partial changes do not get /// committed). #[candid_method(update, rename = "create_subnet")] -async fn create_subnet_(payload: CreateSubnetArg) -> Result { +async fn create_subnet_(payload: CreateSubnetPayloadV2) -> Result { let new_subnet = registry_mut() .do_create_subnet(CreateSubnetPayload::from(payload)) .await; @@ -873,13 +873,13 @@ fn remove_node_operators_(payload: RemoveNodeOperatorsPayload) { #[unsafe(export_name = "canister_update update_subnet")] fn update_subnet() { check_caller_is_governance_or_engine_controller_and_log("update_subnet"); - over(candid_one, |payload: UpdateSubnetArg| { + over(candid_one, |payload: UpdateSubnetPayloadV2| { update_subnet_(payload) }); } #[candid_method(update, rename = "update_subnet")] -fn update_subnet_(payload: UpdateSubnetArg) { +fn update_subnet_(payload: UpdateSubnetPayloadV2) { let caller = dfn_core::api::caller(); registry_mut().do_update_subnet(caller, UpdateSubnetPayload::from(payload)); recertify_registry(); diff --git a/rs/registry/canister/canister/registry.did b/rs/registry/canister/canister/registry.did index b0882a552902..5e64b6731d77 100644 --- a/rs/registry/canister/canister/registry.did +++ b/rs/registry/canister/canister/registry.did @@ -92,7 +92,7 @@ type SubnetFeaturesV2 = record { sev_enabled : opt bool; }; -type CreateSubnetPayload = record { +type CreateSubnetPayloadV2 = record { unit_delay_millis : nat64; features : SubnetFeaturesV2; max_ingress_bytes_per_message : nat64; @@ -500,7 +500,7 @@ type UpdateSshReadOnlyAccessForAllUnassignedNodesPayload = record { ssh_readonly_keys : vec text; }; -type UpdateSubnetPayload = record { +type UpdateSubnetPayloadV2 = record { unit_delay_millis : opt nat64; max_duplicity : opt nat32; features : opt SubnetFeaturesV2; @@ -625,7 +625,7 @@ service : { change_subnet_membership : (ChangeSubnetMembershipPayload) -> (); clear_provisional_whitelist : () -> (); complete_canister_migration : (CompleteCanisterMigrationPayload) -> (); - create_subnet : (CreateSubnetPayload) -> (CreateSubnetResponse); + create_subnet : (CreateSubnetPayloadV2) -> (CreateSubnetResponse); delete_subnet : (DeleteSubnetPayload) -> (DeleteSubnetResponse); deploy_guestos_to_all_subnet_nodes : ( DeployGuestosToAllSubnetNodesPayload @@ -676,7 +676,7 @@ service : { update_ssh_readonly_access_for_all_unassigned_nodes : ( UpdateSshReadOnlyAccessForAllUnassignedNodesPayload ) -> (); - update_subnet : (UpdateSubnetPayload) -> (); + update_subnet : (UpdateSubnetPayloadV2) -> (); update_subnet_admins : (UpdateSubnetAdminsPayload) -> (); update_unassigned_nodes_config : (UpdateUnassignedNodesConfigPayload) -> (); swap_node_in_subnet_directly : (SwapNodeInSubnetDirectlyPayload) -> (); diff --git a/rs/registry/canister/canister/registry_test.did b/rs/registry/canister/canister/registry_test.did index 9c6aed6a8651..4d4d6dd19ee2 100644 --- a/rs/registry/canister/canister/registry_test.did +++ b/rs/registry/canister/canister/registry_test.did @@ -92,7 +92,7 @@ type SubnetFeaturesV2 = record { sev_enabled : opt bool; }; -type CreateSubnetPayload = record { +type CreateSubnetPayloadV2 = record { unit_delay_millis : nat64; features : SubnetFeaturesV2; max_ingress_bytes_per_message : nat64; @@ -500,7 +500,7 @@ type UpdateSshReadOnlyAccessForAllUnassignedNodesPayload = record { ssh_readonly_keys : vec text; }; -type UpdateSubnetPayload = record { +type UpdateSubnetPayloadV2 = record { unit_delay_millis : opt nat64; max_duplicity : opt nat32; features : opt SubnetFeaturesV2; @@ -625,7 +625,7 @@ service : { change_subnet_membership : (ChangeSubnetMembershipPayload) -> (); clear_provisional_whitelist : () -> (); complete_canister_migration : (CompleteCanisterMigrationPayload) -> (); - create_subnet : (CreateSubnetPayload) -> (CreateSubnetResponse); + create_subnet : (CreateSubnetPayloadV2) -> (CreateSubnetResponse); delete_subnet : (DeleteSubnetPayload) -> (DeleteSubnetResponse); deploy_guestos_to_all_subnet_nodes : ( DeployGuestosToAllSubnetNodesPayload @@ -676,7 +676,7 @@ service : { update_ssh_readonly_access_for_all_unassigned_nodes : ( UpdateSshReadOnlyAccessForAllUnassignedNodesPayload ) -> (); - update_subnet : (UpdateSubnetPayload) -> (); + update_subnet : (UpdateSubnetPayloadV2) -> (); update_subnet_admins : (UpdateSubnetAdminsPayload) -> (); update_unassigned_nodes_config : (UpdateUnassignedNodesConfigPayload) -> (); swap_node_in_subnet_directly : (SwapNodeInSubnetDirectlyPayload) -> (); diff --git a/rs/registry/canister/src/mutations/do_create_subnet.rs b/rs/registry/canister/src/mutations/do_create_subnet.rs index 3b9dfbe2879a..4efa3194c7b7 100644 --- a/rs/registry/canister/src/mutations/do_create_subnet.rs +++ b/rs/registry/canister/src/mutations/do_create_subnet.rs @@ -330,7 +330,7 @@ pub struct CreateSubnetPayload { /// Input type for `create_subnet` canister method. /// Same as `CreateSubnetPayload` but with `SubnetFeaturesV2` (all `Option`) for `features`. #[derive(Clone, Eq, PartialEq, Debug, Default, CandidType, Deserialize, Serialize)] -pub struct CreateSubnetArg { +pub struct CreateSubnetPayloadV2 { pub node_ids: Vec, pub subnet_id_override: Option, @@ -378,8 +378,8 @@ pub struct CreateSubnetArg { pub gossip_retransmission_request_ms: u32, } -impl From for CreateSubnetPayload { - fn from(arg: CreateSubnetArg) -> Self { +impl From for CreateSubnetPayload { + fn from(arg: CreateSubnetPayloadV2) -> Self { Self { node_ids: arg.node_ids, subnet_id_override: arg.subnet_id_override, diff --git a/rs/registry/canister/src/mutations/do_update_subnet.rs b/rs/registry/canister/src/mutations/do_update_subnet.rs index b58bf90baa7b..5b041ccbbfa9 100644 --- a/rs/registry/canister/src/mutations/do_update_subnet.rs +++ b/rs/registry/canister/src/mutations/do_update_subnet.rs @@ -406,7 +406,7 @@ pub struct UpdateSubnetPayload { /// Input type for `update_subnet` canister method. /// Same as `UpdateSubnetPayload` but with `SubnetFeaturesV2` (all `Option`) for `features`. #[derive(Clone, Eq, PartialEq, Debug, CandidType, Deserialize, Serialize)] -pub struct UpdateSubnetArg { +pub struct UpdateSubnetPayloadV2 { pub subnet_id: SubnetId, pub max_ingress_bytes_per_message: Option, @@ -451,8 +451,8 @@ pub struct UpdateSubnetArg { pub set_gossip_config_to_default: bool, } -impl From for UpdateSubnetPayload { - fn from(arg: UpdateSubnetArg) -> Self { +impl From for UpdateSubnetPayload { + fn from(arg: UpdateSubnetPayloadV2) -> Self { Self { subnet_id: arg.subnet_id, max_ingress_bytes_per_message: arg.max_ingress_bytes_per_message,