@@ -44,94 +44,6 @@ pub struct PredictionContext<'a> {
4444 pub data_source : ElectionDataSource ,
4545}
4646
47- /// Inject validator self-votes to ensure every candidate backs itself when generating
48- /// synthetic election snapshots.
49- ///
50- /// - If an account is a nominator, use their nominator data BUT ensure they vote for themselves
51- /// - If an account is a validator but NOT a nominator, inject them as voting for themselves
52- ///
53- /// We do NOT merge stakes - we respect the nominator data if it exists.
54- pub ( crate ) fn inject_self_votes (
55- candidates : & [ ValidatorData ] ,
56- nominators : Vec < NominatorData > ,
57- ) -> Vec < NominatorData > {
58- // Build a map of validator accounts to their stakes for lookup
59- let validator_stakes: HashMap < AccountId , u64 > = candidates
60- . iter ( )
61- . map ( |( account, stake) | {
62- let stake_u64 = if * stake > u64:: MAX as u128 {
63- log:: warn!(
64- target: LOG_TARGET ,
65- "Validator {:?} stake {} exceeds u64::MAX; truncating to {}" ,
66- account,
67- stake,
68- u64 :: MAX
69- ) ;
70- u64:: MAX
71- } else {
72- * stake as u64
73- } ;
74- ( account. clone ( ) , stake_u64)
75- } )
76- . collect ( ) ;
77-
78- // Build a set of all validator accounts for fast lookup
79- let validator_accounts: HashSet < AccountId > =
80- candidates. iter ( ) . map ( |( account, _) | account. clone ( ) ) . collect ( ) ;
81-
82- let mut combined: Vec < NominatorData > = Vec :: with_capacity ( nominators. len ( ) + candidates. len ( ) ) ;
83-
84- let mut self_votes_added = 0usize ;
85-
86- // Process all nominators, ensuring validators vote for themselves
87- for ( account, stake, mut targets) in nominators {
88- // If this nominator is also a validator, ensure they vote for themselves
89- if validator_accounts. contains ( & account) {
90- // Add self-target if not already present
91- if !targets. iter ( ) . any ( |t| t == & account) {
92- targets. push ( account. clone ( ) ) ;
93- self_votes_added += 1 ;
94- }
95- }
96- combined. push ( ( account, stake, targets) ) ;
97- }
98-
99- // Then, for validators that are NOT nominators, inject them as self-voters
100- let mut injected = 0usize ;
101- for ( account, _stake) in candidates {
102- // Skip if this validator is already a nominator (we already processed them above)
103- if combined. iter ( ) . any ( |( acc, _, _) | acc == account) {
104- continue ;
105- }
106-
107- // Get the validator stake (already converted to u64 in validator_stakes map)
108- let stake_u64 = validator_stakes
109- . get ( account)
110- . copied ( )
111- . expect ( "Validator stake should exist in map" ) ;
112-
113- // Add validator as a self-voter (voting only for themselves)
114- combined. push ( ( account. clone ( ) , stake_u64, vec ! [ account. clone( ) ] ) ) ;
115- injected += 1 ;
116- }
117- log:: info!(
118- target: LOG_TARGET ,
119- "Ensured {} validator self-votes in nominators, injected {} new validator self-voters (total: {} voters)" ,
120- self_votes_added,
121- injected,
122- combined. len( )
123- ) ;
124-
125- combined. sort_by ( |a, b| {
126- // Sort by Stake Descending (High stake first)
127- b. 1 . cmp ( & a. 1 )
128- // Tie-breaker: AccountId Ascending (for deterministic stability)
129- . then_with ( || a. 0 . cmp ( & b. 0 ) )
130- } ) ;
131-
132- combined
133- }
134-
13547/// Convert staking pallet data into the in-memory snapshot format expected by the miner.
13648///
13749/// Returns a single-page target snapshot and a Vec of voter pages (not bounded, so no pages are
@@ -408,6 +320,7 @@ where
408320 // try to fetch election data from the snapshot
409321 // if snapshot is not available fetch from staking
410322 log:: info!( target: LOG_TARGET , "Trying to fetch data from snapshot" ) ;
323+
411324 match try_fetch_snapshot :: < T > ( n_pages, round, & storage) . await {
412325 Ok ( ( target_snapshot, voter_pages) ) => {
413326 log:: info!( target: LOG_TARGET , "Snapshot found" ) ;
@@ -428,11 +341,10 @@ where
428341 . await
429342 . map_err ( |e| Error :: Other ( format ! ( "Failed to fetch nominators: {e}" ) ) ) ?;
430343
431- let nominators = inject_self_votes ( & candidates, nominators) ;
432-
433- let ( target_snapshot, voter_snapshot) =
344+ let ( target_snapshot, mut voter_snapshot) =
434345 convert_staking_data_to_snapshots :: < T > ( candidates, nominators) ?;
435-
346+ // Fix the order
347+ voter_snapshot. reverse ( ) ;
436348 Ok ( ( target_snapshot, voter_snapshot, ElectionDataSource :: Staking ) )
437349 } ,
438350 }
0 commit comments