@@ -4,9 +4,9 @@ use crate::*;
44use frame_support:: { assert_err, assert_ok} ;
55use frame_system:: Config ;
66use sp_core:: U256 ;
7- use sp_std:: collections:: btree_map:: BTreeMap ;
7+ use sp_std:: collections:: { btree_map:: BTreeMap , vec_deque :: VecDeque } ;
88use substrate_fixed:: types:: { I96F32 , U64F64 , U96F32 } ;
9- use subtensor_runtime_common:: { NetUidStorageIndex , TaoCurrency } ;
9+ use subtensor_runtime_common:: { MechId , NetUidStorageIndex , TaoCurrency } ;
1010use subtensor_swap_interface:: { OrderType , SwapHandler } ;
1111
1212#[ test]
@@ -2046,3 +2046,105 @@ fn massive_dissolve_refund_and_reregistration_flow_is_lossless_and_cleans_state(
20462046 ) ;
20472047 } ) ;
20482048}
2049+
2050+ #[ test]
2051+ fn dissolve_clears_all_mechanism_scoped_maps_for_all_mechanisms ( ) {
2052+ new_test_ext ( 0 ) . execute_with ( || {
2053+ // Create a subnet we can dissolve.
2054+ let owner_cold = U256 :: from ( 123 ) ;
2055+ let owner_hot = U256 :: from ( 456 ) ;
2056+ let net = add_dynamic_network ( & owner_hot, & owner_cold) ;
2057+
2058+ // We'll use two mechanisms for this subnet.
2059+ MechanismCountCurrent :: < Test > :: insert ( net, MechId :: from ( 2 ) ) ;
2060+ let m0 = MechId :: from ( 0u8 ) ;
2061+ let m1 = MechId :: from ( 1u8 ) ;
2062+
2063+ let idx0 = SubtensorModule :: get_mechanism_storage_index ( net, m0) ;
2064+ let idx1 = SubtensorModule :: get_mechanism_storage_index ( net, m1) ;
2065+
2066+ // Minimal content to ensure each storage actually has keys for BOTH mechanisms.
2067+
2068+ // --- Weights (DMAP: (netuid_index, uid) -> Vec<(dest_uid, weight_u16)>)
2069+ Weights :: < Test > :: insert ( idx0, 0u16 , vec ! [ ( 1u16 , 1u16 ) ] ) ;
2070+ Weights :: < Test > :: insert ( idx1, 0u16 , vec ! [ ( 2u16 , 1u16 ) ] ) ;
2071+
2072+ // --- Bonds (DMAP: (netuid_index, uid) -> Vec<(dest_uid, weight_u16)>)
2073+ Bonds :: < Test > :: insert ( idx0, 0u16 , vec ! [ ( 1u16 , 1u16 ) ] ) ;
2074+ Bonds :: < Test > :: insert ( idx1, 0u16 , vec ! [ ( 2u16 , 1u16 ) ] ) ;
2075+
2076+ // --- TimelockedWeightCommits (DMAP: (netuid_index, epoch) -> VecDeque<...>)
2077+ let hotkey = U256 :: from ( 1 ) ;
2078+ TimelockedWeightCommits :: < Test > :: insert (
2079+ idx0,
2080+ 1u64 ,
2081+ VecDeque :: from ( [ ( hotkey, 1u64 , Default :: default ( ) , Default :: default ( ) ) ] ) ,
2082+ ) ;
2083+ TimelockedWeightCommits :: < Test > :: insert (
2084+ idx1,
2085+ 2u64 ,
2086+ VecDeque :: from ( [ ( hotkey, 2u64 , Default :: default ( ) , Default :: default ( ) ) ] ) ,
2087+ ) ;
2088+
2089+ // --- Incentive (MAP: netuid_index -> Vec<u16>)
2090+ Incentive :: < Test > :: insert ( idx0, vec ! [ 1u16 , 2u16 ] ) ;
2091+ Incentive :: < Test > :: insert ( idx1, vec ! [ 3u16 , 4u16 ] ) ;
2092+
2093+ // --- LastUpdate (MAP: netuid_index -> Vec<u64>)
2094+ LastUpdate :: < Test > :: insert ( idx0, vec ! [ 42u64 ] ) ;
2095+ LastUpdate :: < Test > :: insert ( idx1, vec ! [ 84u64 ] ) ;
2096+
2097+ // Sanity: keys are present before dissolve.
2098+ assert ! ( Weights :: <Test >:: contains_key( idx0, 0u16 ) ) ;
2099+ assert ! ( Weights :: <Test >:: contains_key( idx1, 0u16 ) ) ;
2100+ assert ! ( Bonds :: <Test >:: contains_key( idx0, 0u16 ) ) ;
2101+ assert ! ( Bonds :: <Test >:: contains_key( idx1, 0u16 ) ) ;
2102+ assert ! ( TimelockedWeightCommits :: <Test >:: contains_key( idx0, 1u64 ) ) ;
2103+ assert ! ( TimelockedWeightCommits :: <Test >:: contains_key( idx1, 2u64 ) ) ;
2104+ assert ! ( Incentive :: <Test >:: contains_key( idx0) ) ;
2105+ assert ! ( Incentive :: <Test >:: contains_key( idx1) ) ;
2106+ assert ! ( LastUpdate :: <Test >:: contains_key( idx0) ) ;
2107+ assert ! ( LastUpdate :: <Test >:: contains_key( idx1) ) ;
2108+ assert ! ( MechanismCountCurrent :: <Test >:: contains_key( net) ) ;
2109+
2110+ // --- Dissolve the subnet ---
2111+ assert_ok ! ( SubtensorModule :: do_dissolve_network( net) ) ;
2112+
2113+ // After dissolve, ALL mechanism-scoped items must be cleared for ALL mechanisms.
2114+
2115+ // Weights/Bonds double-maps should have no entries under either index.
2116+ assert ! ( Weights :: <Test >:: iter_prefix( idx0) . next( ) . is_none( ) ) ;
2117+ assert ! ( Weights :: <Test >:: iter_prefix( idx1) . next( ) . is_none( ) ) ;
2118+ assert ! ( Bonds :: <Test >:: iter_prefix( idx0) . next( ) . is_none( ) ) ;
2119+ assert ! ( Bonds :: <Test >:: iter_prefix( idx1) . next( ) . is_none( ) ) ;
2120+
2121+ // WeightCommits (OptionQuery) should have no keys remaining.
2122+ assert ! ( WeightCommits :: <Test >:: iter_prefix( idx0) . next( ) . is_none( ) ) ;
2123+ assert ! ( WeightCommits :: <Test >:: iter_prefix( idx1) . next( ) . is_none( ) ) ;
2124+ assert ! ( !WeightCommits :: <Test >:: contains_key( idx0, owner_hot) ) ;
2125+ assert ! ( !WeightCommits :: <Test >:: contains_key( idx1, owner_cold) ) ;
2126+
2127+ // TimelockedWeightCommits (ValueQuery) — ensure both prefix spaces empty and keys gone.
2128+ assert ! (
2129+ TimelockedWeightCommits :: <Test >:: iter_prefix( idx0)
2130+ . next( )
2131+ . is_none( )
2132+ ) ;
2133+ assert ! (
2134+ TimelockedWeightCommits :: <Test >:: iter_prefix( idx1)
2135+ . next( )
2136+ . is_none( )
2137+ ) ;
2138+ assert ! ( !TimelockedWeightCommits :: <Test >:: contains_key( idx0, 1u64 ) ) ;
2139+ assert ! ( !TimelockedWeightCommits :: <Test >:: contains_key( idx1, 2u64 ) ) ;
2140+
2141+ // Single-map per-mechanism vectors cleared.
2142+ assert ! ( !Incentive :: <Test >:: contains_key( idx0) ) ;
2143+ assert ! ( !Incentive :: <Test >:: contains_key( idx1) ) ;
2144+ assert ! ( !LastUpdate :: <Test >:: contains_key( idx0) ) ;
2145+ assert ! ( !LastUpdate :: <Test >:: contains_key( idx1) ) ;
2146+
2147+ // MechanismCountCurrent cleared
2148+ assert ! ( !MechanismCountCurrent :: <Test >:: contains_key( net) ) ;
2149+ } ) ;
2150+ }
0 commit comments