Skip to content

Conversation

@leonace924
Copy link

@leonace924 leonace924 commented Dec 23, 2025

Description

This fix addresses the constraint errors seen on mainnet where self-looped child/parent key relationships cause cycle detection errors.

1. Automatic Self-Loop Prevention During Swap

Instead of rejecting swaps when new_hotkey is a child of old_hotkey, the implementation now allows the swap to proceed but automatically filters out the self-loop edge. This is a simpler and more user-friendly approach.

Implementation:

  • When swapping hotkeys, if new_hotkey is a child of old_hotkey, it is automatically removed from the children list before the swap completes
  • This prevents creating cycles while still allowing the swap operation to succeed
  • The same filtering is applied to PendingChildKeys entries
  • Added unlink_child method to PCRelations to support this functionality

2. Existing Migration Handles Self-Loops

The existing migrate_fix_childkeys migration already removes self-looped entries from ChildKeys and ParentKeys storage by calling clean_self_loops(). This migration:

  • Removes entries where child == parent in ChildKeys
  • Removes entries where parent == child in ParentKeys
  • Cleans up empty vectors after removal
  • Is idempotent (checks HasMigrationRun before executing)
  • Already runs in the migration chain, so no additional migration is needed

Changes Made

Files Modified

  1. pallets/subtensor/src/swap/swap_hotkey.rs

    • Updated parent_child_swap_hotkey call site (no changes needed - filtering happens in the swap function)
    • Updated PendingChildKeys swap logic to filter out self-loops when other hotkeys reference old_hotkey
    • Updated function documentation to explain self-loop prevention
  2. pallets/subtensor/src/staking/set_children.rs

    • Added unlink_child method to PCRelations to remove a child from relations
    • Modified parent_child_swap_hotkey to automatically filter out new_hotkey from children if it exists (prevents self-loop)
    • Modified PendingChildKeys swap to filter out new_hotkey from pending children
  3. pallets/subtensor/src/tests/swap_hotkey.rs

    • Added test_swap_hotkey_to_child_removes_self_loop - verifies self-loop is removed when swapping to a child
    • Added test_swap_hotkey_filters_pending_child_self_loop - verifies PendingChildKeys self-loops are filtered
    • Added test_swap_hotkey_to_child_preserves_other_children - verifies other children are preserved
    • Updated test_swap_parent_hotkey_self_loops_in_pending - now expects success with self-loop removal

Testing

The implementation:

  • ✅ Passes all linting checks
  • ✅ Properly tracks weight for database operations
  • ✅ Prevents cycles in both all-subnet and subnet-specific swap scenarios
  • ✅ Migration is idempotent and safe to run multiple times

Related Issue(s)

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Other (please describe):

Breaking Change

If this PR introduces a breaking change, please provide a detailed description of the impact and the migration path for existing applications.

Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have run ./scripts/fix_rust.sh to ensure my code is formatted and linted correctly
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Screenshots (if applicable)

Please include any relevant screenshots or GIFs that demonstrate the changes made.

Additional Notes

Please provide any additional information or context that may be helpful for reviewers.

Contribution by Gittensor, learn more at https://gittensor.io/

@leonace924
Copy link
Author

@juniuszhou would you review this PR?

@open-junius
Copy link
Contributor

@juniuszhou would you review this PR?
Thanks for the PR, please add unit test for the code change.
For the case about new hot is the child of old hot, a simpler solution is to avoid adding the self loop edge, instead of take such swap as invalid. What do you think

@leonace924
Copy link
Author

@juniuszhou would you review this PR?
Thanks for the PR, please add unit test for the code change.
For the case about new hot is the child of old hot, a simpler solution is to avoid adding the self loop edge, instead of take such swap as invalid. What do you think

Thank you for your feedback, let me update all

@leonace924
Copy link
Author

@juniuszhou merry christmas!
I updated the code as your comment and push the test as gift 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants