Skip to content

Commit 0f75108

Browse files
authored
Fix EpochCommittees returning stake tables out of order (#2514)
1 parent d6562d5 commit 0f75108

File tree

1 file changed

+42
-26
lines changed

1 file changed

+42
-26
lines changed

types/src/v0/impls/stake_table.rs

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use hotshot_types::{
2121
use itertools::Itertools;
2222
use std::{
2323
cmp::max,
24-
collections::{BTreeMap, BTreeSet, HashMap},
24+
collections::{BTreeSet, HashMap},
2525
num::NonZeroU64,
2626
str::FromStr,
2727
};
@@ -126,11 +126,17 @@ struct Committee {
126126
/// leader but without voting rights.
127127
eligible_leaders: Vec<StakeTableEntry<PubKey>>,
128128

129-
/// TODO: add comment
130-
indexed_stake_table: BTreeMap<PubKey, StakeTableEntry<PubKey>>,
129+
/// Keys for nodes participating in the network
130+
stake_table: Vec<StakeTableEntry<PubKey>>,
131131

132-
/// TODO: comment
133-
indexed_da_members: BTreeMap<PubKey, StakeTableEntry<PubKey>>,
132+
/// Keys for DA members
133+
da_members: Vec<StakeTableEntry<PubKey>>,
134+
135+
/// Stake entries indexed by public key, for efficient lookup.
136+
indexed_stake_table: HashMap<PubKey, StakeTableEntry<PubKey>>,
137+
138+
/// DA entries indexed by public key, for efficient lookup.
139+
indexed_da_members: HashMap<PubKey, StakeTableEntry<PubKey>>,
134140
}
135141

136142
impl EpochCommittees {
@@ -144,14 +150,18 @@ impl EpochCommittees {
144150
// update events and building the table for us. We will need
145151
// more subtlety when start fetching only the events since last update.
146152

147-
let indexed_stake_table: BTreeMap<PubKey, _> = st
153+
let stake_table = st.stake_table.0.clone();
154+
155+
let da_members = st.da_members.0.clone();
156+
157+
let indexed_stake_table: HashMap<PubKey, _> = st
148158
.stake_table
149159
.0
150160
.iter()
151161
.map(|entry| (PubKey::public_key(entry), entry.clone()))
152162
.collect();
153163

154-
let indexed_da_members: BTreeMap<PubKey, _> = st
164+
let indexed_da_members: HashMap<PubKey, _> = st
155165
.da_members
156166
.0
157167
.iter()
@@ -167,6 +177,8 @@ impl EpochCommittees {
167177

168178
let committee = Committee {
169179
eligible_leaders,
180+
stake_table,
181+
da_members,
170182
indexed_stake_table,
171183
indexed_da_members,
172184
};
@@ -191,7 +203,7 @@ impl EpochCommittees {
191203
.collect();
192204

193205
// For each member, get the stake table entry
194-
let members: Vec<_> = committee_members
206+
let stake_table: Vec<_> = committee_members
195207
.iter()
196208
.map(|member| member.stake_table_entry.clone())
197209
.filter(|entry| entry.stake() > U256::zero())
@@ -205,19 +217,21 @@ impl EpochCommittees {
205217
.collect();
206218

207219
// Index the stake table by public key
208-
let indexed_stake_table: BTreeMap<PubKey, _> = members
220+
let indexed_stake_table: HashMap<PubKey, _> = stake_table
209221
.iter()
210222
.map(|entry| (PubKey::public_key(entry), entry.clone()))
211223
.collect();
212224

213225
// Index the stake table by public key
214-
let indexed_da_members: BTreeMap<PubKey, _> = da_members
226+
let indexed_da_members: HashMap<PubKey, _> = da_members
215227
.iter()
216228
.map(|entry| (PubKey::public_key(entry), entry.clone()))
217229
.collect();
218230

219231
let members = Committee {
220232
eligible_leaders,
233+
stake_table,
234+
da_members,
221235
indexed_stake_table,
222236
indexed_da_members,
223237
};
@@ -259,7 +273,7 @@ impl Membership<SeqTypes> for EpochCommittees {
259273
.collect();
260274

261275
// For each member, get the stake table entry
262-
let members: Vec<_> = committee_members
276+
let stake_table: Vec<_> = committee_members
263277
.iter()
264278
.map(|member| member.stake_table_entry.clone())
265279
.filter(|entry| entry.stake() > U256::zero())
@@ -273,19 +287,21 @@ impl Membership<SeqTypes> for EpochCommittees {
273287
.collect();
274288

275289
// Index the stake table by public key
276-
let indexed_stake_table: BTreeMap<PubKey, _> = members
290+
let indexed_stake_table: HashMap<PubKey, _> = stake_table
277291
.iter()
278292
.map(|entry| (PubKey::public_key(entry), entry.clone()))
279293
.collect();
280294

281295
// Index the stake table by public key
282-
let indexed_da_members: BTreeMap<PubKey, _> = da_members
296+
let indexed_da_members: HashMap<PubKey, _> = da_members
283297
.iter()
284298
.map(|entry| (PubKey::public_key(entry), entry.clone()))
285299
.collect();
286300

287301
let members = Committee {
288302
eligible_leaders,
303+
stake_table,
304+
da_members,
289305
indexed_stake_table,
290306
indexed_da_members,
291307
};
@@ -306,15 +322,15 @@ impl Membership<SeqTypes> for EpochCommittees {
306322
/// Get the stake table for the current view
307323
fn stake_table(&self, epoch: Epoch) -> Vec<StakeTableEntry<PubKey>> {
308324
if let Some(st) = self.state.get(&epoch) {
309-
st.indexed_stake_table.clone().into_values().collect()
325+
st.stake_table.clone()
310326
} else {
311327
vec![]
312328
}
313329
}
314330
/// Get the stake table for the current view
315331
fn da_stake_table(&self, epoch: Epoch) -> Vec<StakeTableEntry<PubKey>> {
316332
if let Some(sc) = self.state.get(&epoch) {
317-
sc.indexed_da_members.clone().into_values().collect()
333+
sc.da_members.clone()
318334
} else {
319335
vec![]
320336
}
@@ -415,44 +431,44 @@ impl Membership<SeqTypes> for EpochCommittees {
415431
fn total_nodes(&self, epoch: Epoch) -> usize {
416432
self.state
417433
.get(&epoch)
418-
.map(|sc| sc.indexed_stake_table.len())
434+
.map(|sc| sc.stake_table.len())
419435
.unwrap_or_default()
420436
}
421437

422438
/// Get the total number of DA nodes in the committee
423439
fn da_total_nodes(&self, epoch: Epoch) -> usize {
424440
self.state
425441
.get(&epoch)
426-
.map(|sc: &Committee| sc.indexed_da_members.len())
442+
.map(|sc: &Committee| sc.da_members.len())
427443
.unwrap_or_default()
428444
}
429445

430446
/// Get the voting success threshold for the committee
431447
fn success_threshold(&self, epoch: Epoch) -> NonZeroU64 {
432-
let quorum = self.state.get(&epoch).unwrap().indexed_stake_table.clone();
433-
NonZeroU64::new(((quorum.len() as u64 * 2) / 3) + 1).unwrap()
448+
let quorum_len = self.state.get(&epoch).unwrap().stake_table.len();
449+
NonZeroU64::new(((quorum_len as u64 * 2) / 3) + 1).unwrap()
434450
}
435451

436452
/// Get the voting success threshold for the committee
437453
fn da_success_threshold(&self, epoch: Epoch) -> NonZeroU64 {
438-
let da = self.state.get(&epoch).unwrap().indexed_da_members.clone();
439-
NonZeroU64::new(((da.len() as u64 * 2) / 3) + 1).unwrap()
454+
let da_len = self.state.get(&epoch).unwrap().da_members.len();
455+
NonZeroU64::new(((da_len as u64 * 2) / 3) + 1).unwrap()
440456
}
441457

442458
/// Get the voting failure threshold for the committee
443459
fn failure_threshold(&self, epoch: Epoch) -> NonZeroU64 {
444-
let quorum = self.state.get(&epoch).unwrap().indexed_stake_table.clone();
460+
let quorum_len = self.state.get(&epoch).unwrap().stake_table.len();
445461

446-
NonZeroU64::new(((quorum.len() as u64) / 3) + 1).unwrap()
462+
NonZeroU64::new(((quorum_len as u64) / 3) + 1).unwrap()
447463
}
448464

449465
/// Get the voting upgrade threshold for the committee
450466
fn upgrade_threshold(&self, epoch: Epoch) -> NonZeroU64 {
451-
let quorum = self.state.get(&epoch).unwrap().indexed_stake_table.clone();
467+
let quorum_len = self.state.get(&epoch).unwrap().indexed_stake_table.len();
452468

453469
NonZeroU64::new(max(
454-
(quorum.len() as u64 * 9) / 10,
455-
((quorum.len() as u64 * 2) / 3) + 1,
470+
(quorum_len as u64 * 9) / 10,
471+
((quorum_len as u64 * 2) / 3) + 1,
456472
))
457473
.unwrap()
458474
}

0 commit comments

Comments
 (0)