Skip to content

Commit eba8b44

Browse files
authored
Merge pull request #2378 from AleoHQ/tamper-resistant-leader-selection
[HackerOne-2289066] Make leader election tamper resistant
2 parents 46f2625 + 2fdb843 commit eba8b44

File tree

1 file changed

+7
-36
lines changed

1 file changed

+7
-36
lines changed

ledger/committee/src/lib.rs

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ impl<N: Network> Committee<N> {
181181
// Retrieve the total stake of the committee.
182182
let total_stake = self.total_stake();
183183
// Construct the round seed.
184-
let seed = [self.starting_round, current_round, total_stake].map(Field::from_u64);
184+
let seed = [current_round].map(Field::from_u64);
185185
// Hash the round seed.
186186
let hash = Literal::Field(N::hash_to_group_psd4(&seed)?.to_x_coordinate());
187187
// Compute the stake index from the hash output.
@@ -211,17 +211,13 @@ impl<N: Network> Committee<N> {
211211
Ok(leader.unwrap())
212212
}
213213

214-
/// Returns the committee members sorted by stake in decreasing order.
215-
/// For members with matching stakes, we further sort by their address' x-coordinate in decreasing order.
214+
/// Returns the committee members sorted by their address' x-coordinate in decreasing order.
216215
/// Note: This ensures the method returns a deterministic result that is SNARK-friendly.
217216
fn sorted_members(&self) -> indexmap::map::IntoIter<Address<N>, (u64, bool)> {
218217
let members = self.members.clone();
219218
// Note: The use of 'sorted_unstable_by' is safe here because the addresses are guaranteed to be unique.
220-
members.sorted_unstable_by(|address1, (stake1, _), address2, (stake2, _)| {
221-
// Sort by stake in decreasing order.
222-
let cmp = stake2.cmp(stake1);
223-
// If the stakes are equal, sort by x-coordinate in decreasing order.
224-
if cmp == Ordering::Equal { address2.to_x_coordinate().cmp(&address1.to_x_coordinate()) } else { cmp }
219+
members.sorted_unstable_by(|address1, (_, _), address2, (_, _)| {
220+
address2.to_x_coordinate().cmp(&address1.to_x_coordinate())
225221
})
226222
}
227223
}
@@ -433,34 +429,9 @@ mod tests {
433429
println!("sorted_members: {}ms", timer.elapsed().as_millis());
434430
// Check that the members are sorted based on our sorting criteria.
435431
for i in 0..sorted_members.len() - 1 {
436-
let (address1, (stake1, _)) = sorted_members[i];
437-
let (address2, (stake2, _)) = sorted_members[i + 1];
438-
assert!(stake1 >= stake2);
439-
if stake1 == stake2 {
440-
assert!(address1.to_x_coordinate() > address2.to_x_coordinate());
441-
}
442-
}
443-
}
444-
445-
#[test]
446-
fn test_sorted_members_with_equal_stake() {
447-
// Initialize the RNG.
448-
let rng = &mut TestRng::default();
449-
// Sample a committee.
450-
let committee = crate::test_helpers::sample_committee_equal_stake_committee(200, rng);
451-
// Start a timer.
452-
let timer = std::time::Instant::now();
453-
// Sort the members.
454-
let sorted_members = committee.sorted_members().collect::<Vec<_>>();
455-
println!("sorted_members: {}ms", timer.elapsed().as_millis());
456-
// Check that the members are sorted based on our sorting criteria.
457-
for i in 0..sorted_members.len() - 1 {
458-
let (address1, (stake1, _)) = sorted_members[i];
459-
let (address2, (stake2, _)) = sorted_members[i + 1];
460-
assert!(stake1 >= stake2);
461-
if stake1 == stake2 {
462-
assert!(address1.to_x_coordinate() > address2.to_x_coordinate());
463-
}
432+
let (address1, (_, _)) = sorted_members[i];
433+
let (address2, (_, _)) = sorted_members[i + 1];
434+
assert!(address1.to_x_coordinate() > address2.to_x_coordinate());
464435
}
465436
}
466437

0 commit comments

Comments
 (0)