Skip to content

Commit 85e264e

Browse files
ruseinovmelekes
andcommitted
[Fix] Try-state feature-gated for BagsList (paritytech#13296)
* [Fix] Try-state feature-gated for BagsList * fix comment * fix try_state remote-tests * feature-gate try-state remote test for bags-list * remove try-state from a migration * more SortedListProvider fixes * more fixes * more fixes to allow do_try_state usage in other crates * do-try-state for fuzz * more fixes * more fixes * remove feature-flag * do-try-state * fix review comments * Update frame/bags-list/src/mock.rs Co-authored-by: Anton <anton.kalyaev@gmail.com> --------- Co-authored-by: parity-processbot <> Co-authored-by: Anton <anton.kalyaev@gmail.com>
1 parent ba5d4b7 commit 85e264e

File tree

13 files changed

+46
-30
lines changed

13 files changed

+46
-30
lines changed

frame/bags-list/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,4 @@ fuzz = [
7575
"sp-tracing",
7676
"frame-election-provider-support/fuzz",
7777
]
78-
try-runtime = [ "frame-support/try-runtime" ]
78+
try-runtime = [ "frame-support/try-runtime", "frame-election-provider-support/try-runtime" ]

frame/bags-list/fuzzer/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ fn main() {
8888
},
8989
}
9090

91-
assert!(BagsList::try_state().is_ok());
91+
assert!(BagsList::do_try_state().is_ok());
9292
})
9393
});
9494
}

frame/bags-list/remote-tests/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
1515
[dependencies]
1616
# frame
1717
pallet-staking = { path = "../../staking", version = "4.0.0-dev" }
18-
pallet-bags-list = { path = "../../bags-list", version = "4.0.0-dev" }
18+
pallet-bags-list = { path = "../../bags-list", version = "4.0.0-dev", features = ["fuzz"] }
1919
frame-election-provider-support = { path = "../../election-provider-support", version = "4.0.0-dev" }
2020
frame-system = { path = "../../system", version = "4.0.0-dev" }
2121
frame-support = { path = "../../support", version = "4.0.0-dev" }

frame/bags-list/remote-tests/src/try_state.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
//! Test to execute the sanity-check of the voter bag.
1818
19-
use frame_election_provider_support::SortedListProvider;
2019
use frame_support::{
2120
storage::generator::StorageMap,
2221
traits::{Get, PalletInfoAccess},
@@ -51,7 +50,9 @@ pub async fn execute<Runtime, Block>(
5150

5251
ext.execute_with(|| {
5352
sp_core::crypto::set_default_ss58_version(Runtime::SS58Prefix::get().try_into().unwrap());
54-
pallet_bags_list::Pallet::<Runtime, pallet_bags_list::Instance1>::try_state().unwrap();
53+
54+
pallet_bags_list::Pallet::<Runtime, pallet_bags_list::Instance1>::do_try_state().unwrap();
55+
5556
log::info!(target: crate::LOG_TARGET, "executed bags-list sanity check with no errors.");
5657

5758
crate::display_and_check_bags::<Runtime>(currency_unit, currency_name);

frame/bags-list/src/lib.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,13 @@ pub mod pallet {
274274
}
275275
}
276276

277+
#[cfg(any(test, feature = "try-runtime", feature = "fuzz"))]
278+
impl<T: Config<I>, I: 'static> Pallet<T, I> {
279+
pub fn do_try_state() -> Result<(), &'static str> {
280+
List::<T, I>::do_try_state()
281+
}
282+
}
283+
277284
impl<T: Config<I>, I: 'static> Pallet<T, I> {
278285
/// Move an account from one bag to another, depositing an event on success.
279286
///
@@ -348,8 +355,9 @@ impl<T: Config<I>, I: 'static> SortedListProvider<T::AccountId> for Pallet<T, I>
348355
List::<T, I>::unsafe_regenerate(all, score_of)
349356
}
350357

358+
#[cfg(feature = "try-runtime")]
351359
fn try_state() -> Result<(), &'static str> {
352-
List::<T, I>::try_state()
360+
Self::do_try_state()
353361
}
354362

355363
fn unsafe_clear() {

frame/bags-list/src/list/mod.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,6 @@ impl<T: Config<I>, I: 'static> List<T, I> {
220220
crate::ListBags::<T, I>::remove(removed_bag);
221221
}
222222

223-
#[cfg(feature = "std")]
224-
debug_assert_eq!(Self::try_state(), Ok(()));
225-
226223
num_affected
227224
}
228225

@@ -514,7 +511,8 @@ impl<T: Config<I>, I: 'static> List<T, I> {
514511
/// * length of this list is in sync with `ListNodes::count()`,
515512
/// * and sanity-checks all bags and nodes. This will cascade down all the checks and makes sure
516513
/// all bags and nodes are checked per *any* update to `List`.
517-
pub(crate) fn try_state() -> Result<(), &'static str> {
514+
#[cfg(any(test, feature = "try-runtime", feature = "fuzz"))]
515+
pub(crate) fn do_try_state() -> Result<(), &'static str> {
518516
let mut seen_in_list = BTreeSet::new();
519517
ensure!(
520518
Self::iter().map(|node| node.id).all(|id| seen_in_list.insert(id)),
@@ -542,7 +540,7 @@ impl<T: Config<I>, I: 'static> List<T, I> {
542540
thresholds.into_iter().filter_map(|t| Bag::<T, I>::get(t))
543541
};
544542

545-
let _ = active_bags.clone().try_for_each(|b| b.try_state())?;
543+
let _ = active_bags.clone().try_for_each(|b| b.do_try_state())?;
546544

547545
let nodes_in_bags_count =
548546
active_bags.clone().fold(0u32, |acc, cur| acc + cur.iter().count() as u32);
@@ -553,7 +551,7 @@ impl<T: Config<I>, I: 'static> List<T, I> {
553551
// check that all nodes are sane. We check the `ListNodes` storage item directly in case we
554552
// have some "stale" nodes that are not in a bag.
555553
for (_id, node) in crate::ListNodes::<T, I>::iter() {
556-
node.try_state()?
554+
node.do_try_state()?
557555
}
558556

559557
Ok(())
@@ -751,7 +749,8 @@ impl<T: Config<I>, I: 'static> Bag<T, I> {
751749
/// * Ensures head has no prev.
752750
/// * Ensures tail has no next.
753751
/// * Ensures there are no loops, traversal from head to tail is correct.
754-
fn try_state(&self) -> Result<(), &'static str> {
752+
#[cfg(any(test, feature = "try-runtime", feature = "fuzz"))]
753+
fn do_try_state(&self) -> Result<(), &'static str> {
755754
frame_support::ensure!(
756755
self.head()
757756
.map(|head| head.prev().is_none())
@@ -790,6 +789,7 @@ impl<T: Config<I>, I: 'static> Bag<T, I> {
790789
}
791790

792791
/// Check if the bag contains a node with `id`.
792+
#[cfg(any(test, feature = "try-runtime", feature = "fuzz"))]
793793
fn contains(&self, id: &T::AccountId) -> bool {
794794
self.iter().any(|n| n.id() == id)
795795
}
@@ -894,7 +894,8 @@ impl<T: Config<I>, I: 'static> Node<T, I> {
894894
self.bag_upper
895895
}
896896

897-
fn try_state(&self) -> Result<(), &'static str> {
897+
#[cfg(any(test, feature = "try-runtime", feature = "fuzz"))]
898+
fn do_try_state(&self) -> Result<(), &'static str> {
898899
let expected_bag = Bag::<T, I>::get(self.bag_upper).ok_or("bag not found for node")?;
899900

900901
let id = self.id();

frame/bags-list/src/list/tests.rs

+13-12
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ fn migrate_works() {
137137
BagThresholds::set(NEW_THRESHOLDS);
138138
// and we call
139139
List::<Runtime>::migrate(old_thresholds);
140+
assert_eq!(List::<Runtime>::do_try_state(), Ok(()));
140141

141142
// then
142143
assert_eq!(
@@ -352,13 +353,13 @@ mod list {
352353
#[test]
353354
fn try_state_works() {
354355
ExtBuilder::default().build_and_execute_no_post_check(|| {
355-
assert_ok!(List::<Runtime>::try_state());
356+
assert_ok!(List::<Runtime>::do_try_state());
356357
});
357358

358359
// make sure there are no duplicates.
359360
ExtBuilder::default().build_and_execute_no_post_check(|| {
360361
Bag::<Runtime>::get(10).unwrap().insert_unchecked(2, 10);
361-
assert_eq!(List::<Runtime>::try_state(), Err("duplicate identified"));
362+
assert_eq!(List::<Runtime>::do_try_state(), Err("duplicate identified"));
362363
});
363364

364365
// ensure count is in sync with `ListNodes::count()`.
@@ -372,7 +373,7 @@ mod list {
372373
CounterForListNodes::<Runtime>::mutate(|counter| *counter += 1);
373374
assert_eq!(crate::ListNodes::<Runtime>::count(), 5);
374375

375-
assert_eq!(List::<Runtime>::try_state(), Err("iter_count != stored_count"));
376+
assert_eq!(List::<Runtime>::do_try_state(), Err("iter_count != stored_count"));
376377
});
377378
}
378379

@@ -804,7 +805,7 @@ mod bags {
804805

805806
// then
806807
assert_eq!(bag_as_ids(&bag_1000), vec![2, 3, 13, 14]);
807-
assert_ok!(bag_1000.try_state());
808+
assert_ok!(bag_1000.do_try_state());
808809
// and the node isn't mutated when its removed
809810
assert_eq!(node_4, node_4_pre_remove);
810811

@@ -814,23 +815,23 @@ mod bags {
814815

815816
// then
816817
assert_eq!(bag_as_ids(&bag_1000), vec![3, 13, 14]);
817-
assert_ok!(bag_1000.try_state());
818+
assert_ok!(bag_1000.do_try_state());
818819

819820
// when removing a tail that is not pointing at the head
820821
let node_14 = Node::<Runtime>::get(&14).unwrap();
821822
bag_1000.remove_node_unchecked(&node_14);
822823

823824
// then
824825
assert_eq!(bag_as_ids(&bag_1000), vec![3, 13]);
825-
assert_ok!(bag_1000.try_state());
826+
assert_ok!(bag_1000.do_try_state());
826827

827828
// when removing a tail that is pointing at the head
828829
let node_13 = Node::<Runtime>::get(&13).unwrap();
829830
bag_1000.remove_node_unchecked(&node_13);
830831

831832
// then
832833
assert_eq!(bag_as_ids(&bag_1000), vec![3]);
833-
assert_ok!(bag_1000.try_state());
834+
assert_ok!(bag_1000.do_try_state());
834835

835836
// when removing a node that is both the head & tail
836837
let node_3 = Node::<Runtime>::get(&3).unwrap();
@@ -846,15 +847,15 @@ mod bags {
846847

847848
// then
848849
assert_eq!(bag_as_ids(&bag_10), vec![1, 12]);
849-
assert_ok!(bag_10.try_state());
850+
assert_ok!(bag_10.do_try_state());
850851

851852
// when removing a head that is pointing at the tail
852853
let node_1 = Node::<Runtime>::get(&1).unwrap();
853854
bag_10.remove_node_unchecked(&node_1);
854855

855856
// then
856857
assert_eq!(bag_as_ids(&bag_10), vec![12]);
857-
assert_ok!(bag_10.try_state());
858+
assert_ok!(bag_10.do_try_state());
858859
// and since we updated the bag's head/tail, we need to write this storage so we
859860
// can correctly `get` it again in later checks
860861
bag_10.put();
@@ -865,15 +866,15 @@ mod bags {
865866

866867
// then
867868
assert_eq!(bag_as_ids(&bag_2000), vec![15, 17, 18, 19]);
868-
assert_ok!(bag_2000.try_state());
869+
assert_ok!(bag_2000.do_try_state());
869870

870871
// when removing a node that is pointing at tail, but not head
871872
let node_18 = Node::<Runtime>::get(&18).unwrap();
872873
bag_2000.remove_node_unchecked(&node_18);
873874

874875
// then
875876
assert_eq!(bag_as_ids(&bag_2000), vec![15, 17, 19]);
876-
assert_ok!(bag_2000.try_state());
877+
assert_ok!(bag_2000.do_try_state());
877878

878879
// finally, when reading from storage, the state of all bags is as expected
879880
assert_eq!(
@@ -905,7 +906,7 @@ mod bags {
905906
// .. and the bag it was removed from
906907
let bag_1000 = Bag::<Runtime>::get(1_000).unwrap();
907908
// is sane
908-
assert_ok!(bag_1000.try_state());
909+
assert_ok!(bag_1000.do_try_state());
909910
// and has the correct head and tail.
910911
assert_eq!(bag_1000.head, Some(3));
911912
assert_eq!(bag_1000.tail, Some(4));

frame/bags-list/src/mock.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl ExtBuilder {
148148
pub fn build_and_execute(self, test: impl FnOnce() -> ()) {
149149
self.build().execute_with(|| {
150150
test();
151-
List::<Runtime>::try_state().expect("Try-state post condition failed")
151+
List::<Runtime>::do_try_state().expect("do_try_state post condition failed")
152152
})
153153
}
154154

frame/election-provider-support/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,4 @@ std = [
4343
"sp-std/std",
4444
]
4545
runtime-benchmarks = []
46+
try-runtime = []

frame/election-provider-support/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,8 @@ pub trait SortedListProvider<AccountId> {
562562
/// unbounded amount of storage accesses.
563563
fn unsafe_clear();
564564

565-
/// Check internal state of list. Only meant for debugging.
565+
/// Check internal state of the list. Only meant for debugging.
566+
#[cfg(feature = "try-runtime")]
566567
fn try_state() -> Result<(), &'static str>;
567568

568569
/// If `who` changes by the returned amount they are guaranteed to have a worst case change

frame/staking/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,4 @@ runtime-benchmarks = [
7474
"rand_chacha",
7575
"sp-staking/runtime-benchmarks",
7676
]
77-
try-runtime = ["frame-support/try-runtime"]
77+
try-runtime = ["frame-support/try-runtime", "frame-election-provider-support/try-runtime"]

frame/staking/src/migrations.rs

-1
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,6 @@ pub mod v8 {
386386
Nominators::<T>::iter().map(|(id, _)| id),
387387
Pallet::<T>::weight_of_fn(),
388388
);
389-
debug_assert_eq!(T::VoterList::try_state(), Ok(()));
390389

391390
StorageVersion::<T>::put(ObsoleteReleases::V8_0_0);
392391
crate::log!(

frame/staking/src/pallet/impls.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1451,9 +1451,11 @@ impl<T: Config> SortedListProvider<T::AccountId> for UseValidatorsMap<T> {
14511451
// nothing to do upon regenerate.
14521452
0
14531453
}
1454+
#[cfg(feature = "try-runtime")]
14541455
fn try_state() -> Result<(), &'static str> {
14551456
Ok(())
14561457
}
1458+
14571459
fn unsafe_clear() {
14581460
#[allow(deprecated)]
14591461
Validators::<T>::remove_all();
@@ -1525,6 +1527,8 @@ impl<T: Config> SortedListProvider<T::AccountId> for UseNominatorsAndValidatorsM
15251527
// nothing to do upon regenerate.
15261528
0
15271529
}
1530+
1531+
#[cfg(feature = "try-runtime")]
15281532
fn try_state() -> Result<(), &'static str> {
15291533
Ok(())
15301534
}

0 commit comments

Comments
 (0)