Skip to content

feat: allow unlimited number of gen4 nodes#10448

Open
NikolaMilosa wants to merge 5 commits into
masterfrom
nim-allowing-arbitrary-number-of-nodes
Open

feat: allow unlimited number of gen4 nodes#10448
NikolaMilosa wants to merge 5 commits into
masterfrom
nim-allowing-arbitrary-number-of-nodes

Conversation

@NikolaMilosa

Copy link
Copy Markdown
Contributor

This pull request allows node providers to add more type4.x nodes (excluding type4.5 for now see #10393).

This is needed to allow for provisioning on-demand nodes in the cloud and registering them with the network.

@github-actions github-actions Bot added the feat label Jun 11, 2026
@NikolaMilosa NikolaMilosa changed the title feat: allow theoretically unlimited number of gen4 nodes feat: allow unlimited number of gen4 nodes Jun 11, 2026

Copilot AI left a comment

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.

Pull request overview

This PR modifies the registry canister’s node-add flow to relax max_rewardable_nodes enforcement for certain Gen4 node reward types, enabling node providers to register more cloud/on-demand nodes (while explicitly keeping type4.5 subject to the existing quota rule).

Changes:

  • Bypasses the max_rewardable_nodes quota check when adding nodes of reward types type4.1type4.4.
  • Keeps the quota check enforced for type4.5.
  • Adds unit tests covering the bypass behavior for type4.1type4.4 and continued enforcement for type4.5.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +144 to +150
let bypass_max_rewardable_nodes_check = matches!(
node_reward_type,
NodeRewardType::Type4dot1
| NodeRewardType::Type4dot2
| NodeRewardType::Type4dot3
| NodeRewardType::Type4dot4
);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We don't want to do it for type4 nodes. They were a one-off and won't be used for this feature.

Comment on lines +152 to +156
if !bypass_max_rewardable_nodes_check {
let max_rewardable_nodes_same_type = *node_operator_record
.max_rewardable_nodes
.get(&(node_reward_type.to_string()))
.ok_or(format!("{LOG_PREFIX}do_add_node: Node Operator does not have rewardable nodes for {node_reward_type}"))?;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

On the reward canister side, these aren't considered anyways. So if they exist they are skipped.

@NikolaMilosa NikolaMilosa marked this pull request as ready for review June 16, 2026 09:27
@NikolaMilosa NikolaMilosa requested a review from a team as a code owner June 16, 2026 09:27

@github-actions github-actions Bot left a comment

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.

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

@zeropath-ai

zeropath-ai Bot commented Jun 16, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to 8934f9f.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► rs/registry/canister/src/mutations/node_management/do_add_node.rs
    Temporarily bypass max_rewardable_nodes quota check for specific node reward types.
    Add test to verify arbitrary node additions for types 4.1-4.4.
    Add test to ensure max_rewardable_nodes quota is still enforced for type 4.5.
Other ► rs/registry/canister/unreleased_changelog.md
    Document temporary bypass of max_rewardable_nodes quota check.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like, this could cause problems space problems in the Registry canister... I mean, an alternative is just to have a very large (but finite!) limit, right??

// For now, node providers may deploy arbitrarily many nodes of these
// types without being constrained by `max_rewardable_nodes`. Type4.5 is
// explicitly excluded from this exemption.
let bypass_max_rewardable_nodes_check = matches!(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Do as you see fit.

Alternatively, you can just say that there must be < EXCESSIVE_NUMBER_OF_TYPE_4_NODES type 4.x nodes. That way, they do not need to be treated specially.

When it is possible to not treat something specially, it is better to treat it like everything else. Since the improvement here is marginal, I leave it up to you.

Comment on lines +165 to +166
if max_rewardable_nodes_same_type
<= num_in_registry_same_type.saturating_sub(num_removed_same_ip_same_type)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I know it was like this before already, but why <= ?

Suggestion:

Suggested change
if max_rewardable_nodes_same_type
<= num_in_registry_same_type.saturating_sub(num_removed_same_ip_same_type)
let num_remaining_nodes = num_in_registry_same_type.saturating_sub(num_removed_same_ip_same_type);
if num_remaining_nodes > max_rewardable_nodes_same_type {

Note that my suggestion is not equivalent, because > is used. Seems like the original code has an off by one bug? Equal to max should be fine, right??

The most important change in my suggestion is swapping the order of operands, putting the reference value on the right hand side of the comparison operator, because we pretty much always do it that way.

The dummy variable in my suggestion is less important. It helps because multi-line if expressions should be avoided (and in this case, it can be avoided pretty easily), but this is not something that we particularly follow; hence, lower importance.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I can address this, but this is the question for @pietrodimarco-dfinity, I assume that this isn't an array and is actually how many nodes you have vs how many you are allowed. If you have 5 and you are allowed 5 it is fine, right?

registry
.do_add_node_(payload, node_operator_id, now_system_time())
.unwrap_or_else(|e| {
panic!("do_add_node_ failed for {node_reward_type} on iteration {i}: {e}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Maybe, comment here that the next test shows that for other node reward types, this would fail. Otherwise, even if this test passes, it could be simply due to panic NEVER occurs, regardless of node reward type.

Comment on lines +27 to +31
* Temporarily bypass the `max_rewardable_nodes` quota check in `add_node` for
node reward types `type4.1` through `type4.4`, allowing node providers to
register an arbitrary number of such nodes. `type4.5` is explicitly excluded
and still subject to the quota. This is a temporary measure until rewards of
`type4.5` are no longer treated as `type1.1` (see CLO-15).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Can you maybe explain the motivation?

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.

3 participants