Skip to content

Commit 65bbaea

Browse files
committed
Replace DecShareCache alias with an actual type.
1 parent bd285bf commit 65bbaea

File tree

1 file changed

+64
-32
lines changed

1 file changed

+64
-32
lines changed

timeboost-sequencer/src/decrypt.rs

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use cliquenet::{
88
use rayon::iter::ParallelIterator;
99
use rayon::prelude::*;
1010

11-
use multisig::{CommitteeId, PublicKey};
11+
use multisig::{Committee, CommitteeId, PublicKey};
1212
use parking_lot::RwLock;
1313
use sailfish::types::{Evidence, Round, RoundNumber};
1414
use serde::{Deserialize, Serialize};
@@ -38,7 +38,6 @@ const THRES_AAD: &[u8] = b"threshold";
3838
type Result<T> = StdResult<T, DecrypterError>;
3939
type DecShare = <DecryptionScheme as ThresholdEncScheme>::DecShare;
4040
type Ciphertext = <DecryptionScheme as ThresholdEncScheme>::Ciphertext;
41-
type DecShareCache = BTreeMap<RoundNumber, Vec<Vec<Option<DecShare>>>>;
4241

4342
/// The message types exchanged during decryption phase.
4443
#[derive(Debug, Serialize, Deserialize)]
@@ -497,9 +496,9 @@ struct Worker {
497496
#[builder(default)]
498497
tracker: BTreeMap<CommitteeId, DkgAccumulator>,
499498

500-
/// Cache of decryption shares received from remote nodes or produced from local ciphertexts.
499+
/// Decryption shares received from remote nodes or produced from local ciphertexts.
501500
#[builder(default)]
502-
dec_shares: DecShareCache,
501+
dec_shares: ShareStore,
503502

504503
/// Map of received decryption shares for each round (DOS prevention).
505504
#[builder(default)]
@@ -882,7 +881,7 @@ impl Worker {
882881
// doesn't need those shares, thus pruning them.
883882
if self.first_requested_round.is_none() {
884883
trace!(node = %self.label, %round, "set first requested round");
885-
self.dec_shares.retain(|k, _| k >= &round);
884+
self.dec_shares.gc(&round);
886885
self.first_requested_round = Some(round);
887886
}
888887

@@ -901,7 +900,7 @@ impl Worker {
901900

902901
/// Garbage collect internally cached state.
903902
async fn gc(&mut self, round: &RoundNumber) -> Result<()> {
904-
self.dec_shares.retain(|r, _| r > round);
903+
self.dec_shares.gc(round);
905904
self.incls.retain(|r, _| r > round);
906905
self.acks.retain(|r, _| r > round);
907906
self.remove_old_committee().await?;
@@ -978,15 +977,7 @@ impl Worker {
978977
// there are 3 ciphertexts, and node a and b has contributed their decrypted shares batch so
979978
// far. with node c's batch [s1c, s2c, s3c], the new local cache is:
980979
// [[s1a, s1b, s1c], [s2a, s2b, s2c], [s3a, s3b, s3c]]
981-
let entry = self
982-
.dec_shares
983-
.entry(round.num())
984-
.or_insert_with(|| vec![vec![]; batch.len()]);
985-
entry
986-
.iter_mut()
987-
.zip(batch.dec_shares)
988-
.for_each(|(shares, new)| shares.push(new));
989-
980+
self.dec_shares.insert(round.num(), batch.dec_shares);
990981
Ok(())
991982
}
992983

@@ -1085,18 +1076,10 @@ impl Worker {
10851076
dec_key: &DecryptionKey,
10861077
) -> Result<Option<Vec<Option<Plaintext>>>> {
10871078
let ciphertexts = incl.filter_ciphertexts().map(|b| deserialize(b).ok());
1088-
let Some(dec_shares) = self.dec_shares.get(&round) else {
1089-
return Ok(None);
1090-
};
10911079
let key_store = self.current_store()?;
1092-
1093-
if dec_shares.is_empty()
1094-
|| dec_shares.iter().any(|opt_dec_shares| {
1095-
let valid = opt_dec_shares.iter().filter(|s| s.is_some()).count();
1096-
let invalid = opt_dec_shares.len() - valid;
1097-
valid < key_store.committee().one_honest_threshold().get()
1098-
&& invalid < key_store.committee().quorum_size().get()
1099-
})
1080+
if !self
1081+
.dec_shares
1082+
.has_sufficient_shares(&round, key_store.committee())
11001083
{
11011084
return Ok(None);
11021085
}
@@ -1368,6 +1351,61 @@ impl Worker {
13681351
}
13691352
}
13701353

1354+
#[derive(Debug, Default)]
1355+
struct ShareStore {
1356+
inner: BTreeMap<RoundNumber, Vec<Vec<Option<DecShare>>>>,
1357+
}
1358+
1359+
impl ShareStore {
1360+
/// Inserts decryption shares for a specific round
1361+
fn insert(&mut self, round: RoundNumber, shares: Vec<Option<DecShare>>) {
1362+
let entry = self
1363+
.inner
1364+
.entry(round)
1365+
.or_insert_with(|| vec![vec![]; shares.len()]);
1366+
entry
1367+
.iter_mut()
1368+
.zip(shares)
1369+
.for_each(|(shares, new)| shares.push(new));
1370+
}
1371+
1372+
/// Gets a reference to the decryption shares for a specific round, if any
1373+
fn get(&self, round: &RoundNumber) -> Option<&Vec<Vec<Option<DecShare>>>> {
1374+
self.inner.get(round)
1375+
}
1376+
1377+
/// Gets a mutable reference to the decryption shares for a specific round, if any
1378+
fn get_mut(&mut self, round: &RoundNumber) -> Option<&mut Vec<Vec<Option<DecShare>>>> {
1379+
self.inner.get_mut(round)
1380+
}
1381+
/// Returns true if the cache is empty.
1382+
fn is_empty(&self) -> bool {
1383+
self.inner.is_empty()
1384+
}
1385+
1386+
/// Checks if there are enough valid decryption shares for the given round.
1387+
fn has_sufficient_shares(&self, round: &RoundNumber, committee: &Committee) -> bool {
1388+
let Some(dec_shares) = self.get(round) else {
1389+
return false;
1390+
};
1391+
1392+
// Check if there are enough valid shares to proceed
1393+
let one_honest_threshold = committee.one_honest_threshold().get();
1394+
let quorum_size = committee.quorum_size().get();
1395+
1396+
!dec_shares.iter().any(|opt_dec_shares| {
1397+
let valid = opt_dec_shares.iter().filter(|s| s.is_some()).count();
1398+
let invalid = opt_dec_shares.len() - valid;
1399+
valid < one_honest_threshold && invalid < quorum_size
1400+
})
1401+
}
1402+
1403+
/// Removes and returns the decryption shares for a specific round
1404+
fn gc(&mut self, round: &RoundNumber) {
1405+
self.inner.retain(|k, _| k >= round)
1406+
}
1407+
}
1408+
13711409
/// A batch of decryption shares. Each batch is uniquely identified via round_number.
13721410
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
13731411
struct DecShareBatch {
@@ -1382,12 +1420,6 @@ struct DecShareBatch {
13821420
}
13831421

13841422
impl DecShareBatch {
1385-
/// Returns the number of decryption share in this batch. Equivalently, it's the number of
1386-
/// ciphertexts.
1387-
pub fn len(&self) -> usize {
1388-
self.dec_shares.len()
1389-
}
1390-
13911423
/// Returns true if there's no *valid* decryption share. There are three sub-cases this may be
13921424
/// true
13931425
/// - empty set of ciphertext/encrypted bundle

0 commit comments

Comments
 (0)