Skip to content

Commit dc451dc

Browse files
committed
Address review comments
1 parent e0766ea commit dc451dc

File tree

2 files changed

+35
-52
lines changed

2 files changed

+35
-52
lines changed

timeboost-crypto/src/mre.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,11 @@ impl<C: CurveGroup> LabeledDecryptionKey<C> {
129129
let m = k.iter().zip(ct.ct.iter()).map(|(ki, c)| ki ^ c).collect();
130130
Ok(m)
131131
}
132-
133-
pub fn with_node_idx(&self, node_idx: usize) -> Self {
134-
Self {
135-
alpha: self.alpha,
136-
u: self.u,
137-
node_idx,
132+
}
133+
impl<C: CurveGroup> From<LabeledDecryptionKey<C>> for DecryptionKey<C> {
134+
fn from(lab_key: LabeledDecryptionKey<C>) -> Self {
135+
DecryptionKey {
136+
alpha: lab_key.alpha,
138137
}
139138
}
140139
}

timeboost-sequencer/src/decrypt.rs

Lines changed: 30 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize};
1212
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque};
1313
use std::result::Result as StdResult;
1414
use std::sync::Arc;
15-
use timeboost_crypto::prelude::{LabeledDkgDecKey, Vess, Vss};
15+
use timeboost_crypto::prelude::{DkgDecKey, LabeledDkgDecKey, Vess, Vss};
1616
use timeboost_crypto::traits::dkg::VerifiableSecretSharing;
1717
use timeboost_crypto::traits::threshold_enc::{ThresholdEncError, ThresholdEncScheme};
1818
use timeboost_crypto::{DecryptionScheme, Plaintext};
@@ -96,8 +96,6 @@ pub struct Decrypter {
9696
worker_rx: Receiver<InclusionList>,
9797
/// Worker task handle.
9898
worker: JoinHandle<EndOfPlay>,
99-
/// Set of committees for which DKG bundles have already been submitted.
100-
submitted: BTreeSet<CommitteeId>,
10199
/// Pending threshold encryption key material
102100
enc_key: DecryptionKeyCell,
103101
/// Key stores (shared with Worker)
@@ -150,7 +148,7 @@ impl Decrypter {
150148
net.add(new_peers.collect()).await?;
151149
(
152150
Arc::new(RwLock::new(kv)),
153-
WorkerState::AwaitingHandover(HashMap::new()),
151+
WorkerState::HandoverPending(HashMap::new()),
154152
)
155153
}
156154
None => {
@@ -177,7 +175,6 @@ impl Decrypter {
177175
incls: VecDeque::new(),
178176
worker_tx: cmd_tx,
179177
worker_rx: dec_rx,
180-
submitted: BTreeSet::default(),
181178
worker: spawn(worker.go()),
182179
enc_key: cfg.threshold_enc_key,
183180
key_stores: key_stores.clone(),
@@ -236,10 +233,6 @@ impl Decrypter {
236233
/// - `Some(DkgBundle)` if a new dealing was successfully created for the current committee.
237234
/// - `None` if already submitted or if encryption key is missing.
238235
pub fn gen_dkg_bundle(&mut self) -> Option<DkgBundle> {
239-
if self.submitted.contains(&self.current) {
240-
trace!(node = %self.label, committee = %self.current, "dkg bundle already submitted");
241-
return None;
242-
}
243236
let guard = self.key_stores.read();
244237
let Some(store) = guard.get(self.current) else {
245238
warn!(node = %self.label, committee = %self.current, "missing current key store");
@@ -256,7 +249,6 @@ impl Decrypter {
256249
let (ct, cm) = vess
257250
.encrypt_shares(store.committee(), store.sorted_keys(), secret, DKG_AAD)
258251
.ok()?;
259-
self.submitted.insert(self.current);
260252
Some(DkgBundle::new((node_idx, self.label), self.current, ct, cm))
261253
}
262254

@@ -267,10 +259,6 @@ impl Decrypter {
267259
/// - `None` if already submitted or if encryption key is missing.
268260
pub fn gen_resharing_bundle(&mut self, next_store: KeyStore) -> Option<DkgBundle> {
269261
let committee_id = next_store.committee().id();
270-
if self.submitted.contains(&committee_id) {
271-
trace!(node = %self.label, committee = %committee_id, "resharing bundle already submitted");
272-
return None;
273-
}
274262
let guard = self.key_stores.read();
275263
let Some(current_store) = guard.get(self.current) else {
276264
warn!(node = %self.label, committee = %self.current, "missing current key store");
@@ -287,17 +275,14 @@ impl Decrypter {
287275
return None;
288276
};
289277
let vess = Vess::new_fast();
290-
let share = dec_sk.privkey().share();
291-
let secret = <Vss as VerifiableSecretSharing>::Secret::from(*share);
292278
let (ct, cm) = vess
293279
.encrypt_reshares(
294280
next_store.committee(),
295281
next_store.sorted_keys(),
296-
secret,
282+
*dec_sk.privkey().share(),
297283
DKG_AAD,
298284
)
299285
.ok()?;
300-
self.submitted.insert(committee_id);
301286
Some(DkgBundle::new((node_idx, self.label), committee_id, ct, cm))
302287
}
303288

@@ -338,12 +323,12 @@ impl Decrypter {
338323

339324
return Ok(dec_incl);
340325
} else {
341-
warn!(
326+
error!(
342327
node = %self.label,
343328
%round,
344-
"received unexpected inclusion list (no rounds in queue)"
329+
"received unexpected inclusion list"
345330
);
346-
return Ok(dec_incl);
331+
return Err(DecrypterDown(()));
347332
}
348333
}
349334
}
@@ -380,11 +365,15 @@ impl Drop for Decrypter {
380365
}
381366

382367
/// The operational state of the Worker.
368+
///
369+
/// State Machine Flow:
370+
/// - DkgPending -> Running <-> ResharingComplete -> ShuttingDown
371+
/// - HandoverPending -> HandoverComplete -> Running <-> ResharingComplete -> ShuttingDown
383372
#[derive(Debug, Clone)]
384373
#[allow(clippy::large_enum_variant)]
385374
enum WorkerState {
386375
/// Awaiting resharing messages from the previous committee.
387-
AwaitingHandover(HashMap<PublicKey, ResharingSubset>),
376+
HandoverPending(HashMap<PublicKey, ResharingSubset>),
388377
/// Received enough resharing messages to complete the handover.
389378
HandoverComplete(DecryptionKey),
390379
/// Expects to obtain the initial DKG key through DKG bundles.
@@ -393,7 +382,7 @@ enum WorkerState {
393382
/// such that, if the local node is behind, it will catchup immediately.
394383
DkgPending(HashMap<PublicKey, DkgSubset>),
395384
/// Already completed at least one instance of DKG. Ready for resharing.
396-
ResharingPending(DecryptionKey),
385+
Running(DecryptionKey),
397386
/// Obtained keys for both the current and next committee.
398387
ResharingComplete(DecryptionKey, DecryptionKey),
399388
/// Completed resharing and handover but is not a member of next committee.
@@ -488,9 +477,11 @@ struct Worker {
488477

489478
impl Worker {
490479
pub async fn go(mut self) -> EndOfPlay {
491-
let node = self.label;
492-
493-
if !matches!(self.state, WorkerState::AwaitingHandover(_)) {
480+
debug_assert!(matches!(
481+
self.state,
482+
WorkerState::HandoverPending(_) | WorkerState::DkgPending(_)
483+
));
484+
if matches!(self.state, WorkerState::DkgPending(_)) {
494485
// immediately try to catchup first
495486
match self.dkg_catchup().await {
496487
Ok(()) => {}
@@ -502,7 +493,7 @@ impl Worker {
502493
loop {
503494
let mut cache_modified = false;
504495
// process pending inclusion lists received during catchup
505-
if !self.pending.is_empty() && matches!(self.state, WorkerState::ResharingPending(_)) {
496+
if !self.pending.is_empty() && matches!(self.state, WorkerState::Running(_)) {
506497
for incl in std::mem::take(&mut self.pending).into_values() {
507498
match self.on_decrypt_request(incl, true).await {
508499
Ok(()) => {}
@@ -550,7 +541,7 @@ impl Worker {
550541
},
551542
Some(Command::Decrypt((incl, is_encrypted))) => {
552543
let round = incl.round();
553-
trace!(%node, %round, "decrypt request");
544+
trace!(node = %self.label, %round, "decrypt request");
554545
match self.on_decrypt_request(incl, is_encrypted).await {
555546
Ok(()) => { cache_modified = true }
556547
Err(DecrypterError::End(end)) => return end,
@@ -592,7 +583,7 @@ impl Worker {
592583
match self.hatch(round).await {
593584
Ok(_) => {}
594585
Err(DecrypterError::End(end)) => return end,
595-
Err(err) => warn!(%node, %round, %err, "error on hatch"),
586+
Err(err) => warn!(node = %self.label, %round, %err, "error on hatch"),
596587
}
597588

598589
if matches!(self.state, WorkerState::ShuttingDown(_)) {
@@ -735,7 +726,7 @@ impl Worker {
735726
.map_err(|e| DecrypterError::Dkg(e.to_string()))?;
736727

737728
self.enc_key.set(dec_sk.clone());
738-
self.state = WorkerState::ResharingPending(dec_sk);
729+
self.state = WorkerState::Running(dec_sk);
739730
info!(node = %self.label, committee_id = %committee.id(), "dkg finished (catchup successful)");
740731
}
741732

@@ -751,7 +742,7 @@ impl Worker {
751742
}
752743

753744
let subsets = match &mut self.state {
754-
WorkerState::AwaitingHandover(subsets) => subsets,
745+
WorkerState::HandoverPending(subsets) => subsets,
755746
_ => {
756747
trace!(node = %self.label, current = %self.current, %msg.committee_id, "not awaiting handover");
757748
return Ok(());
@@ -885,7 +876,7 @@ impl Worker {
885876
.map_err(|e| DecrypterError::Dkg(e.to_string()))?;
886877

887878
self.enc_key.set(dec_sk.clone());
888-
self.state = WorkerState::ResharingPending(dec_sk);
879+
self.state = WorkerState::Running(dec_sk);
889880
self.dkg_completed.insert(committee.id());
890881
info!(committee_id = %committee.id(), node = %self.label, "dkg finished");
891882
}
@@ -938,7 +929,7 @@ impl Worker {
938929
if let Some(next_node_idx) = committee.get_index(&self.label).map(|idx| idx.into()) {
939930
// node is a member of the next committee; decrypting reshares immediately
940931
let vess = Vess::new_fast();
941-
self.dkg_sk = self.dkg_sk.with_node_idx(next_node_idx);
932+
self.dkg_sk = DkgDecKey::from(self.dkg_sk.clone()).label(next_node_idx);
942933
let dealings: Vec<_> = subset
943934
.bundles()
944935
.iter()
@@ -1114,12 +1105,12 @@ impl Worker {
11141105
self.pending.insert(incl.round(), incl.clone());
11151106
return Err(DecrypterError::DkgPending);
11161107
}
1117-
WorkerState::AwaitingHandover(_) => {
1108+
WorkerState::HandoverPending(_) => {
11181109
return Err(DecrypterError::Dkg(
11191110
"Worker state does not hold decryption key".to_string(),
11201111
));
11211112
}
1122-
WorkerState::ResharingPending(dec_key)
1113+
WorkerState::Running(dec_key)
11231114
| WorkerState::ResharingComplete(dec_key, _)
11241115
| WorkerState::HandoverComplete(dec_key)
11251116
| WorkerState::ShuttingDown(dec_key) => dec_key,
@@ -1210,7 +1201,7 @@ impl Worker {
12101201
}
12111202

12121203
let dec_sk = match &self.state {
1213-
WorkerState::ResharingPending(dec_key)
1204+
WorkerState::Running(dec_key)
12141205
| WorkerState::ResharingComplete(dec_key, _)
12151206
| WorkerState::ShuttingDown(dec_key) => dec_key,
12161207
_ => {
@@ -1423,11 +1414,11 @@ impl Worker {
14231414
self.state = match &self.state {
14241415
WorkerState::HandoverComplete(decryption_key) => {
14251416
info!(node = %self.label, committee = %self.current, "(new node) successful committee switch");
1426-
WorkerState::ResharingPending(decryption_key.clone())
1417+
WorkerState::Running(decryption_key.clone())
14271418
}
14281419
WorkerState::ResharingComplete(_, next_key) => {
14291420
info!(node = %self.label, committee = %self.current, "(old node) successful committee switch");
1430-
WorkerState::ResharingPending(next_key.clone())
1421+
WorkerState::Running(next_key.clone())
14311422
}
14321423
WorkerState::ShuttingDown(dec_key) => {
14331424
info!("(old node) not a member of new committee. ready for shut down");
@@ -1598,7 +1589,7 @@ mod tests {
15981589
collections::VecDeque,
15991590
net::{Ipv4Addr, SocketAddr},
16001591
sync::Arc,
1601-
time::{Duration, Instant},
1592+
time::Instant,
16021593
};
16031594

16041595
use timeboost_utils::types::logging;
@@ -1628,7 +1619,6 @@ mod tests {
16281619
const TEST_EPOCH: u64 = 42;
16291620
const TEST_CHAIN_ID: u64 = 0;
16301621
const TEST_SEQNO: u64 = 10;
1631-
const NETWORK_SETUP_DELAY_SECS: u64 = 1;
16321622
const RETAIN_ROUNDS: usize = 100;
16331623
const COM1: u64 = 1;
16341624
const COM2: u64 = 2;
@@ -1913,7 +1903,6 @@ mod tests {
19131903
Some(com1_setup.clone()),
19141904
)
19151905
.await;
1916-
tokio::time::sleep(Duration::from_secs(NETWORK_SETUP_DELAY_SECS)).await;
19171906

19181907
let com1_round = RoundNumber::new(DECRYPTION_ROUND);
19191908
let com2_round = RoundNumber::new(DECRYPTION_ROUND + 1);
@@ -1955,8 +1944,6 @@ mod tests {
19551944
.expect("use committee event succeeds");
19561945
}
19571946

1958-
tokio::time::sleep(Duration::from_secs(NETWORK_SETUP_DELAY_SECS)).await;
1959-
19601947
let priority_tx_message = b"Priority message for old committee";
19611948
let regular_tx_message = b"Non-priority message for old committee";
19621949

@@ -2397,9 +2384,6 @@ mod tests {
23972384
encryption_key_cells.push(encryption_key_cell);
23982385
}
23992386

2400-
// Allow time for network setup
2401-
tokio::time::sleep(Duration::from_secs(NETWORK_SETUP_DELAY_SECS)).await;
2402-
24032387
(
24042388
decrypters,
24052389
DecrypterSetup::new(

0 commit comments

Comments
 (0)