Skip to content

revert(registry): restore strict sev_enabled check in update_subnet#9956

Open
r-birkner wants to merge 2 commits intomasterfrom
rbirkner/revert-sev-update-relaxation
Open

revert(registry): restore strict sev_enabled check in update_subnet#9956
r-birkner wants to merge 2 commits intomasterfrom
rbirkner/revert-sev-update-relaxation

Conversation

@r-birkner
Copy link
Copy Markdown
Contributor

Partially reverts #9038:

  • Reverts the relaxation of validate_update_sev_feature in do_update_subnetsev_enabled can once again only be set at subnet creation; any update that sets features.sev_enabled now panics, as it did before.
  • Keeps the invariant added in the same PR requiring SEV-enabled subnets to consist only of nodes with a chip ID (check_sev_subnet_invariants in rs/registry/canister/src/invariants/subnet.rs and its tests).

@r-birkner r-birkner marked this pull request as ready for review April 23, 2026 07:30
@r-birkner r-birkner requested a review from a team as a code owner April 23, 2026 07:30
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pull request changes code owned by the Governance team. Therefore, make sure that
you have considered the following (for Governance-owned code):

  1. Update unreleased_changelog.md (if there are behavior changes, even if they are
    non-breaking).

  2. Are there BREAKING changes?

  3. Is a data migration needed?

  4. Security review?

How to Satisfy This Automatic Review

  1. Go to the bottom of the pull request page.

  2. Look for where it says this bot is requesting changes.

  3. Click the three dots to the right.

  4. Select "Dismiss review".

  5. In the text entry box, respond to each of the numbered items in the previous
    section, declare one of the following:

  • Done.

  • $REASON_WHY_NO_NEED. E.g. for unreleased_changelog.md, "No
    canister behavior changes.", or for item 2, "Existing APIs
    behave as before.".

Brief Guide to "Externally Visible" Changes

"Externally visible behavior change" is very often due to some NEW canister API.

Changes to EXISTING APIs are more likely to be "breaking".

If these changes are breaking, make sure that clients know how to migrate, how to
maintain their continuity of operations.

If your changes are behind a feature flag, then, do NOT add entrie(s) to
unreleased_changelog.md in this PR! But rather, add entrie(s) later, in the PR
that enables these changes in production.

Reference(s)

For a more comprehensive checklist, see here.

GOVERNANCE_CHECKLIST_REMINDER_DEDUP

@r-birkner r-birkner dismissed github-actions[bot]’s stale review April 27, 2026 15:02

DONE: updated changelog

let attempting_to_disable =
subnet_features.sev_enabled == Some(true) && update_features.sev_enabled == Some(false);
if attempting_to_disable {
if let Some(sev_enabled) = features.sev_enabled {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem to be right, because (surprisingly to me at least) the features are REPLACED when updating the subnet, and null seems to be treated the same as Some(false). In other words, a proposal can still disable SEV by setting the features to Some(SubnetFeatures { ..., sev_enabled: None}).

I think the problem was introduced by #3044, and I believe the right solution is to compare against the existing sev_enabled like pre-#3044, while still avoiding the unnecessary panic.

Other solutions came to mind but I don't think they are the right choice:

  • do a "merge" of the features from the payload to the existing record, it changes semantics and could be confusing when the features has a mixture of bool and opt bool
  • separate the types of SubnetFeatures between record and payload which introduces API changes and potentially data change

r-birkner added 2 commits May 7, 2026 10:15
Partially reverts #9038. `sev_enabled` can once again only be set at
subnet creation; any attempt to change it via `do_update_subnet` now
panics, as it did before. The SEV invariant added in the same PR
(SEV-enabled subnets must contain only nodes with a chip ID) is kept
intact.
Per @jasonz-dfinity's review on #9956: because `merge_subnet_record`
wholesale-replaces `subnet_record.features` via `maybe_set_option!`, a
proposal could disable SEV on an SEV-enabled subnet by setting
`features = Some(SubnetFeatures { ..., sev_enabled: None })`. The
restored strict check (introduced in #3044) only panicked when
`payload.features.sev_enabled` was explicitly `Some(_)`, so this
implicit transition slipped through.

Compare the effective `sev_enabled` (post-replacement) against the
existing record via the rust-level `SubnetFeatures`, which collapses
`None` and `Some(false)` to `false`. This catches both explicit and
implicit changes while still permitting no-op updates (the case #3044
originally fixed).

Adds two regression tests (explicit and implicit disable) plus a
no-op test, against an SEV-enabled fixture seeded with chip-ID'd
nodes so the SEV invariant stays satisfied.
@r-birkner r-birkner force-pushed the rbirkner/revert-sev-update-relaxation branch from 5ca6791 to 2e5ad74 Compare May 7, 2026 10:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants