pallet_election_provider_multi_block/
helpers.rs1use crate::{
21 types::{PageIndex, VoterOf},
22 unsigned::miner::MinerConfig,
23 AllVoterPagesOf, SolutionTargetIndexOf, SolutionVoterIndexOf, VoteWeight,
24};
25use frame_support::{traits::Get, BoundedVec};
26use sp_runtime::SaturatedConversion;
27use sp_std::{collections::btree_map::BTreeMap, convert::TryInto, prelude::*};
28
29#[macro_export]
31macro_rules! log {
32 ($level:tt, $pattern:expr $(, $values:expr)* $(,)?) => {
33 log::$level!(
34 target: $crate::LOG_PREFIX,
35 concat!("[#{:?}] π³π³π³ ", $pattern), <frame_system::Pallet<T>>::block_number() $(, $values)*
36 )
37 };
38}
39
40#[macro_export]
42macro_rules! sublog {
43 ($level:tt, $sub_pallet:tt, $pattern:expr $(, $values:expr)* $(,)?) => {
44 #[cfg(not(feature = "std"))]
45 log!($level, $pattern $(, $values )*);
46 #[cfg(feature = "std")]
47 log::$level!(
48 target: format!("{}::{}", $crate::LOG_PREFIX, $sub_pallet).as_ref(),
49 concat!("[#{:?}] π³π³π³ ", $pattern), <frame_system::Pallet<T>>::block_number() $(, $values )*
50 )
51 };
52}
53
54#[macro_export]
56macro_rules! miner_log {
57 ($level:tt, $pattern:expr $(, $values:expr)* $(,)?) => {
58 log::$level!(
59 target: $crate::LOG_PREFIX,
60 concat!("[βοΈminer] π³π³π³ ", $pattern) $(, $values)*
61 )
62 };
63}
64
65pub(crate) fn generate_voter_page_fn<T: MinerConfig>(
67 paged_snapshot: &AllVoterPagesOf<T>,
68) -> impl Fn(&T::AccountId) -> Option<PageIndex> {
69 let mut cache: BTreeMap<T::AccountId, PageIndex> = BTreeMap::new();
70 paged_snapshot
71 .iter()
72 .enumerate()
73 .map(|(page, whatever)| (page.saturated_into::<PageIndex>(), whatever))
74 .for_each(|(page, page_voters)| {
75 page_voters.iter().for_each(|(v, _, _)| {
76 let _existed = cache.insert(v.clone(), page);
77 debug_assert!(_existed.is_none());
80 });
81 });
82 move |who| cache.get(who).copied()
83}
84
85pub(crate) fn generate_voter_cache<T: MinerConfig, AnyBound: Get<u32>>(
92 snapshot: &BoundedVec<VoterOf<T>, AnyBound>,
93) -> BTreeMap<T::AccountId, usize> {
94 let mut cache: BTreeMap<T::AccountId, usize> = BTreeMap::new();
95 snapshot.iter().enumerate().for_each(|(i, (x, _, _))| {
96 let _existed = cache.insert(x.clone(), i);
97 debug_assert!(_existed.is_none());
100 });
101
102 cache
103}
104
105pub(crate) fn voter_index_fn_owned<T: MinerConfig>(
110 cache: BTreeMap<T::AccountId, usize>,
111) -> impl Fn(&T::AccountId) -> Option<SolutionVoterIndexOf<T>> {
112 move |who| {
113 cache
114 .get(who)
115 .and_then(|i| <usize as TryInto<SolutionVoterIndexOf<T>>>::try_into(*i).ok())
116 }
117}
118
119pub(crate) fn voter_index_fn_usize<T: MinerConfig>(
125 cache: &BTreeMap<T::AccountId, usize>,
126) -> impl Fn(&T::AccountId) -> Option<usize> + '_ {
127 move |who| cache.get(who).cloned()
128}
129
130#[cfg(test)]
137pub(crate) fn voter_index_fn_linear<T: MinerConfig>(
138 snapshot: &Vec<VoterOf<T>>,
139) -> impl Fn(&T::AccountId) -> Option<SolutionVoterIndexOf<T>> + '_ {
140 move |who| {
141 snapshot
142 .iter()
143 .position(|(x, _, _)| x == who)
144 .and_then(|i| <usize as TryInto<SolutionVoterIndexOf<T>>>::try_into(i).ok())
145 }
146}
147
148pub(crate) fn target_index_fn<T: MinerConfig>(
156 snapshot: &Vec<T::AccountId>,
157) -> impl Fn(&T::AccountId) -> Option<SolutionTargetIndexOf<T>> + '_ {
158 let cache: BTreeMap<_, _> =
159 snapshot.iter().enumerate().map(|(idx, account_id)| (account_id, idx)).collect();
160 move |who| {
161 cache
162 .get(who)
163 .and_then(|i| <usize as TryInto<SolutionTargetIndexOf<T>>>::try_into(*i).ok())
164 }
165}
166
167#[cfg(test)]
175pub(crate) fn target_index_fn_linear<T: MinerConfig>(
176 snapshot: &Vec<T::AccountId>,
177) -> impl Fn(&T::AccountId) -> Option<SolutionTargetIndexOf<T>> + '_ {
178 move |who| {
179 snapshot
180 .iter()
181 .position(|x| x == who)
182 .and_then(|i| <usize as TryInto<SolutionTargetIndexOf<T>>>::try_into(i).ok())
183 }
184}
185
186pub(crate) fn voter_at_fn<T: MinerConfig>(
189 snapshot: &Vec<VoterOf<T>>,
190) -> impl Fn(SolutionVoterIndexOf<T>) -> Option<T::AccountId> + '_ {
191 move |i| {
192 <SolutionVoterIndexOf<T> as TryInto<usize>>::try_into(i)
193 .ok()
194 .and_then(|i| snapshot.get(i).map(|(x, _, _)| x).cloned())
195 }
196}
197
198pub(crate) fn target_at_fn<T: MinerConfig>(
201 snapshot: &Vec<T::AccountId>,
202) -> impl Fn(SolutionTargetIndexOf<T>) -> Option<T::AccountId> + '_ {
203 move |i| {
204 <SolutionTargetIndexOf<T> as TryInto<usize>>::try_into(i)
205 .ok()
206 .and_then(|i| snapshot.get(i).cloned())
207 }
208}
209
210pub(crate) fn stake_of_fn<'a, T: MinerConfig, AnyBound: Get<u32>>(
217 snapshot: &'a BoundedVec<VoterOf<T>, AnyBound>,
218 cache: &'a BTreeMap<T::AccountId, usize>,
219) -> impl Fn(&T::AccountId) -> VoteWeight + 'a {
220 move |who| {
221 if let Some(index) = cache.get(who) {
222 snapshot.get(*index).map(|(_, x, _)| x).cloned().unwrap_or_default()
223 } else {
224 0
225 }
226 }
227}