Log more DKG-related faults.

This commit is contained in:
Andreas Fackler 2018-10-22 16:09:00 +02:00
parent b3e858a079
commit d49350ecd9
4 changed files with 52 additions and 22 deletions

View File

@ -133,11 +133,17 @@ where
/// Proposes a contribution in the current epoch.
pub fn propose(&mut self, contrib: C) -> Result<Step<C, N>> {
let key_gen_messages = self
.key_gen_msg_buffer
.iter()
.filter(|kg_msg| kg_msg.epoch() == self.start_epoch)
.cloned()
.collect();
let step = self
.honey_badger
.handle_input(InternalContrib {
contrib,
key_gen_messages: self.key_gen_msg_buffer.clone(),
key_gen_messages,
votes: self.vote_counter.pending_votes().cloned().collect(),
}).map_err(ErrorKind::ProposeHoneyBadger)?;
self.process_output(step)
@ -273,23 +279,26 @@ where
self.key_gen_msg_buffer
.retain(|skgm| !key_gen_messages.contains(skgm));
for SignedKeyGenMsg(epoch, s_id, kg_msg, sig) in key_gen_messages {
if epoch < self.start_epoch {
info!("Obsolete key generation message: {:?}.", kg_msg);
continue;
}
if !self.verify_signature(&s_id, &sig, &kg_msg)? {
if epoch != self.start_epoch {
info!(
"Obsolete or premature key generation message: {:?}.",
kg_msg
);
let fault_kind = FaultKind::InvalidKeyGenMessageEpoch;
step.fault_log.append(id.clone(), fault_kind);
} else if !self.verify_signature(&s_id, &sig, &kg_msg)? {
info!(
"Invalid signature in {:?}'s batch from {:?} for: {:?}.",
id, s_id, kg_msg
);
let fault_kind = FaultKind::InvalidKeyGenMessageSignature;
step.fault_log.append(id.clone(), fault_kind);
continue;
} else {
step.extend(match kg_msg {
KeyGenMessage::Part(part) => self.handle_part(&s_id, part)?,
KeyGenMessage::Ack(ack) => self.handle_ack(&s_id, ack)?.into(),
});
}
step.extend(match kg_msg {
KeyGenMessage::Part(part) => self.handle_part(&s_id, part)?,
KeyGenMessage::Ack(ack) => self.handle_ack(&s_id, ack)?.into(),
});
}
}
@ -358,8 +367,7 @@ where
self.start_epoch = epoch;
self.key_gen_msg_buffer.retain(|kg_msg| kg_msg.0 >= epoch);
let netinfo = Arc::new(self.netinfo.clone());
let counter = VoteCounter::new(netinfo.clone(), epoch);
mem::replace(&mut self.vote_counter, counter);
self.vote_counter = VoteCounter::new(netinfo.clone(), epoch);
self.honey_badger = HoneyBadger::builder(netinfo)
.max_future_epochs(self.max_future_epochs)
.rng(self.rng.sub_rng())
@ -371,8 +379,9 @@ where
let outcome = if let Some(kgs) = self.key_gen_state.as_mut() {
kgs.key_gen.handle_part(&mut self.rng, &sender_id, part)
} else {
// No key generation ongoing. Return early.
return Ok(Step::default());
// No key generation ongoing.
let fault_kind = FaultKind::UnexpectedKeyGenPart;
return Ok(Fault::new(sender_id.clone(), fault_kind).into());
};
match outcome {
@ -387,7 +396,9 @@ where
if let Some(kgs) = self.key_gen_state.as_mut() {
Ok(kgs.key_gen.handle_ack(sender_id, ack))
} else {
Ok(FaultLog::new())
// No key generation ongoing.
let fault_kind = FaultKind::UnexpectedKeyGenAck;
return Ok(Fault::new(sender_id.clone(), fault_kind).into());
}
}

View File

@ -195,3 +195,10 @@ struct InternalContrib<C, N> {
/// A signed internal message.
#[derive(Eq, PartialEq, Debug, Serialize, Deserialize, Hash, Clone)]
struct SignedKeyGenMsg<N>(u64, N, KeyGenMessage, Signature);
impl<N> SignedKeyGenMsg<N> {
/// Returns the start epoch of the ongoing key generation.
fn epoch(&self) -> u64 {
self.0
}
}

View File

@ -44,12 +44,17 @@ pub enum FaultKind {
/// `HoneyBadger` could not deserialize bytes (i.e. a serialized Batch)
/// from a given proposer into a vector of transactions.
BatchDeserializationFailed,
/// `DynamicHoneyBadger` received a key generation message with an invalid
/// signature.
/// `DynamicHoneyBadger` received a key generation message with an invalid signature.
InvalidKeyGenMessageSignature,
/// `DynamicHoneyBadger` received a key generation message with an invalid epoch.
InvalidKeyGenMessageEpoch,
/// `DynamicHoneyBadger` received a key generation message when there was no key generation in
/// progress.
UnexpectedKeyGenMessage,
/// `DynamicHoneyBadger` received a signed `Ack` when no key generation in progress.
UnexpectedKeyGenAck,
/// `DynamicHoneyBadger` received a signed `Part` when no key generation in progress.
UnexpectedKeyGenPart,
/// `DynamicHoneyBadger` received more key generation messages from the candidate than expected.
TooManyCandidateKeyGenMessages,
/// `DynamicHoneyBadger` received a message (Accept, Propose, or Change)
@ -59,6 +64,8 @@ pub enum FaultKind {
AckMessage(AckMessageFault),
/// `DynamicHoneyBadger`/`SyncKeyGen` received an invalid Part message.
InvalidPartMessage,
/// `DynamicHoneyBadger`/`SyncKeyGen` received multiple Part messages from a node.
MultiplePartMessages,
/// `DynamicHoneyBadger` received a change vote with an invalid signature.
InvalidVoteSignature,
/// A validator committed an invalid vote in `DynamicHoneyBadger`.

View File

@ -226,7 +226,7 @@ impl Debug for Ack {
}
/// The information needed to track a single proposer's secret sharing process.
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq)]
struct ProposalState {
/// The proposer's commitment.
commit: BivarCommitment,
@ -340,11 +340,16 @@ impl<N: NodeIdT> SyncKeyGen<N> {
sender_id: &N,
Part(commit, rows): Part,
) -> Option<PartOutcome<N>> {
let sender_idx = self.node_index(sender_id)?;
let sender_idx = self.node_index(sender_id)?; // TODO: Return an error.
let opt_commit_row = self.our_idx.map(|idx| commit.row(idx + 1));
match self.parts.entry(sender_idx) {
Entry::Occupied(_) => {
debug!("Received multiple parts from node {:?}.", sender_id);
Entry::Occupied(entry) => {
if *entry.get() != ProposalState::new(commit) {
debug!("Received multiple parts from node {:?}.", sender_id);
let fault_log =
FaultLog::init(sender_id.clone(), FaultKind::MultiplePartMessages);
return Some(PartOutcome::Invalid(fault_log));
}
return None;
}
Entry::Vacant(entry) => {