pallet_collator_selection/
migrations.rs1use super::*;
20use frame_support::{pallet_prelude::*, traits::OnRuntimeUpgrade};
21use sp_std::{marker::PhantomData, vec::Vec};
22
23pub struct LastAuthoredBlockCleanup<T: Config>(PhantomData<T>);
30
31impl<T: Config> OnRuntimeUpgrade for LastAuthoredBlockCleanup<T> {
32 fn on_runtime_upgrade() -> Weight {
33 log::info!("Running CollatorSelection::LastAuthoredBlockCleanup...");
34
35 let invulnerables = Invulnerables::<T>::get();
37 let candidates: sp_std::collections::btree_set::BTreeSet<T::AccountId> =
38 Candidates::<T>::get().into_iter().map(|c| c.who).collect();
39
40 let mut read = 0u64;
41 let mut write = 0u64;
42 let mut stale = Vec::new();
43
44 const MAX_SCAN: u64 = 200;
46
47 for (account, _) in LastAuthoredBlock::<T>::iter() {
48 if read >= MAX_SCAN {
49 log::warn!("LastAuthoredBlockCleanup: scan limit {MAX_SCAN} reached.");
50 break;
51 }
52 read += 1;
53
54 let keep = invulnerables.contains(&account) || candidates.contains(&account);
55 if !keep {
56 stale.push(account);
57 }
58 }
59
60 for account in stale {
61 LastAuthoredBlock::<T>::remove(account);
62 write += 1;
63 }
64
65 log::info!(
66 "LastAuthoredBlockCleanup completed: removed {write:?} entries (reads {read:?}, writes {write:?})."
67 );
68
69 <T as frame_system::Config>::DbWeight::get().reads_writes(read, write)
70 }
71
72 #[cfg(feature = "try-runtime")]
73 fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
74 let old_count = LastAuthoredBlock::<T>::iter().count() as u64;
75 Ok(old_count.encode())
76 }
77
78 #[cfg(feature = "try-runtime")]
79 fn post_upgrade(data: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
80 let old_count: u64 = Decode::decode(&mut &data[..]).map_err(|_| {
81 sp_runtime::TryRuntimeError::Other("Failed to decode pre-upgrade count")
82 })?;
83
84 let new_count = LastAuthoredBlock::<T>::iter().count() as u64;
85
86 assert!(
87 new_count < old_count,
88 "LastAuthoredBlockCleanup: new count > old count (should only decrease)"
89 );
90
91 Ok(())
92 }
93}