Skip to content

Commit 4a67e16

Browse files
authored
Merge pull request #2075 from opentensor/fix/no-epoch-on-inconsistent-data
Epoch safeguards
2 parents e6af8a9 + b892a2d commit 4a67e16

File tree

3 files changed

+72
-2
lines changed

3 files changed

+72
-2
lines changed

pallets/subtensor/src/coinbase/run_coinbase.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,9 @@ impl<T: Config> Pallet<T> {
256256
log::warn!("Failed to reveal commits for subnet {netuid} due to error: {e:?}");
257257
};
258258
// Pass on subnets that have not reached their tempo.
259-
if Self::should_run_epoch(netuid, current_block) {
259+
if Self::should_run_epoch(netuid, current_block)
260+
&& Self::is_epoch_input_state_consistent(netuid)
261+
{
260262
// Restart counters.
261263
BlocksSinceLastStep::<T>::insert(netuid, 0);
262264
LastMechansimStepBlock::<T>::insert(netuid, current_block);

pallets/subtensor/src/epoch/run_epoch.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::*;
22
use crate::epoch::math::*;
3-
use alloc::collections::BTreeMap;
3+
use alloc::collections::{BTreeMap, BTreeSet};
44
use frame_support::IterableStorageDoubleMap;
55
use safe_math::*;
66
use sp_std::collections::btree_map::IntoIter;
@@ -1625,4 +1625,20 @@ impl<T: Config> Pallet<T> {
16251625

16261626
Ok(())
16271627
}
1628+
1629+
/// This function ensures major assumptions made by epoch function:
1630+
/// 1. Keys map has no duplicate hotkeys
1631+
///
1632+
pub fn is_epoch_input_state_consistent(netuid: NetUid) -> bool {
1633+
// Check if Keys map has duplicate hotkeys or uids
1634+
let mut hotkey_set: BTreeSet<T::AccountId> = BTreeSet::new();
1635+
// `iter_prefix` over a double map yields (uid, value) for the given first key.
1636+
for (_uid, hotkey) in Keys::<T>::iter_prefix(netuid) {
1637+
if !hotkey_set.insert(hotkey) {
1638+
log::error!("Duplicate hotkeys detected for netuid {netuid}");
1639+
return false;
1640+
}
1641+
}
1642+
true
1643+
}
16281644
}

pallets/subtensor/src/tests/epoch.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3884,3 +3884,55 @@ fn test_last_update_size_mismatch() {
38843884
assert_eq!(SubtensorModule::get_dividends_for_uid(netuid, uid), 0);
38853885
});
38863886
}
3887+
3888+
#[test]
3889+
fn empty_ok() {
3890+
new_test_ext(1).execute_with(|| {
3891+
let netuid: NetUid = 155.into();
3892+
assert!(Pallet::<Test>::is_epoch_input_state_consistent(netuid));
3893+
});
3894+
}
3895+
3896+
#[test]
3897+
fn unique_hotkeys_and_uids_ok() {
3898+
new_test_ext(1).execute_with(|| {
3899+
let netuid: NetUid = 155.into();
3900+
3901+
// (netuid, uid) -> hotkey (AccountId = U256)
3902+
Keys::<Test>::insert(netuid, 0u16, U256::from(1u64));
3903+
Keys::<Test>::insert(netuid, 1u16, U256::from(2u64));
3904+
Keys::<Test>::insert(netuid, 2u16, U256::from(3u64));
3905+
3906+
assert!(Pallet::<Test>::is_epoch_input_state_consistent(netuid));
3907+
});
3908+
}
3909+
3910+
#[test]
3911+
fn duplicate_hotkey_within_same_netuid_fails() {
3912+
new_test_ext(1).execute_with(|| {
3913+
let netuid: NetUid = 155.into();
3914+
3915+
// Same hotkey mapped from two different UIDs in the SAME netuid
3916+
let hk = U256::from(42u64);
3917+
Keys::<Test>::insert(netuid, 0u16, hk);
3918+
Keys::<Test>::insert(netuid, 1u16, U256::from(42u64)); // duplicate hotkey
3919+
3920+
assert!(!Pallet::<Test>::is_epoch_input_state_consistent(netuid));
3921+
});
3922+
}
3923+
3924+
#[test]
3925+
fn same_hotkey_across_different_netuids_is_ok() {
3926+
new_test_ext(1).execute_with(|| {
3927+
let net_a: NetUid = 10.into();
3928+
let net_b: NetUid = 11.into();
3929+
3930+
// Same hotkey appears once in each netuid — each net checks independently.
3931+
let hk = U256::from(777u64);
3932+
Keys::<Test>::insert(net_a, 0u16, hk);
3933+
Keys::<Test>::insert(net_b, 0u16, hk);
3934+
3935+
assert!(Pallet::<Test>::is_epoch_input_state_consistent(net_a));
3936+
assert!(Pallet::<Test>::is_epoch_input_state_consistent(net_b));
3937+
});
3938+
}

0 commit comments

Comments
 (0)