Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DKG votes, sigs, knowledge and AE ground work #5

Merged
merged 6 commits into from
Jul 19, 2022

Conversation

grumbach
Copy link
Member

@grumbach grumbach commented Jul 15, 2022

This PR includes voting mechanisms for SDKG:

  • one round broadcasting Parts
  • one round broadcasting Acks over these Parts
  • one round broadcasting all the Acks over all the Parts, ensuring all the participants have the same sets (Acks and Parts)
  • termination once we've seen everyone's signature over those sets

Basic AE:

  • we deal with packet loss with RequestAntiEntropy responses
  • we have an AntiEntropy type containing all the votes we need to send to make AE requesting nodes catchup

Removes the deprecated Failure crate fixing #3

We still need:

  • tests
  • proptests


pub enum VoteResponse {
WaitingForMoreVotes,
BroadcastVote(Box<DkgSignedVote>),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Boxed this one to appease clippy

src/knowledge.rs Outdated

pub fn got_all_acks(&self, participants_len: usize) -> bool {
self.acks.len() == participants_len
&& self.acks.iter().any(|(_, a)| a.len() != participants_len)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean to say "all parts have acks from all participants?

Suggested change
&& self.acks.iter().any(|(_, a)| a.len() != participants_len)
&& self.acks.iter().all(|(_, a)| a.len() == participants_len)

src/knowledge.rs Outdated

pub(crate) struct Knowledge {
pub parts: BTreeSet<IdPart>,
pub acks: BTreeMap<IdPart, BTreeSet<IdAck>>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub acks: BTreeMap<IdPart, BTreeSet<IdAck>>,
pub part_acks: BTreeMap<IdPart, BTreeSet<IdAck>>,

pub_keys,
keygen: sync_key_gen,
all_votes: BTreeSet::new(),
our_part: opt_part.ok_or(Error::NotInPubKeySet)?,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you see any reason to have SyncKeyGen::new() return an optional Part? I don't really see any reason behind the Observer idea since messages are encrypted between participants, an observer would just be seeing ciphertext flying around.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SyncKeyGen::new() returns a None instead of Some(part) when you are an observer but still want a keygen to generate the PublicKeySet (but now private key shares). In our use here, all the nodes in DkgState are not observers, so we expect our_part to be Some.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although we don't use them here, observers can also create a SyncKeyGen to check all the messages and ultimately generate the PublicKeySet from all the Acks and Parts. They just don't generate a starting Part as they are not participants.

Copy link
Member Author

@grumbach grumbach Jul 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

messages are encrypted between participants

Messages are partly encrypted but enough data is leaked through so the observers can generate the PublicKeySet but not any secret key.

src/state.rs Outdated
}

impl<R: bls::rand::RngCore + Clone> DkgState<R> {
pub fn from(
Copy link
Contributor

@davidrusu davidrusu Jul 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use new instead of from. We need to change this in sn_consensus as well.

Suggested change
pub fn from(
pub fn new(

from is implies the From trait: https://doc.rust-lang.org/std/convert/trait.From.html

pub fn new(
our_id: NodeId,
secret_key: SecretKey,
pub_keys: BTreeMap<NodeId, PublicKey>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: where do we get these pub keys from? 🤔

Adults are using ed25519 keys normally, and then they generate a BLS key only when being promoted to elders

Copy link
Member Author

@grumbach grumbach Jul 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made an issue for that one #6

src/knowledge.rs Outdated
Comment on lines 77 to 81
if let Some(entry) = self.part_acks.get_mut(&id_part) {
entry.insert((id, ack));
} else {
self.part_acks.insert(id_part, BTreeSet::from([(id, ack)]));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the entry api:

Suggested change
if let Some(entry) = self.part_acks.get_mut(&id_part) {
entry.insert((id, ack));
} else {
self.part_acks.insert(id_part, BTreeSet::from([(id, ack)]));
}
let acks = self.part_acks.entry(id_part).or_default();
acks.insert((id, ack));

src/state.rs Outdated
let (sync_key_gen, opt_part) = SyncKeyGen::new(
our_id,
secret_key.clone(),
Arc::new(pub_keys.clone()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't need the Arc on these pub keys. If it's run in a multi-threaded context, then the caller can wrap the entire DkgState in an Arc themselves.

src/state.rs Outdated
Ok(k) => k,
};

let participants_len = self.pub_keys.len();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call this num_participants or n_participants to show it's the number of participants, rather than length

src/state.rs Outdated
Comment on lines 136 to 139
return Err(Error::FaultyVote(format!(
"Ack fault: {:?} by {:?} for part by {:?}",
fault, sender_id, part_id
)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can reduce these 4 lines down to 1 if you put the variables into the format string i.e. "... {fault:?} ..."

src/state.rs Outdated
Comment on lines 158 to 161
return Err(Error::FaultyVote(format!(
"Part fault: {:?} by {:?}",
fault, sender_id
)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, could reduce to 1 line

Copy link
Contributor

@davidrusu davidrusu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, we can address some of the bigger points in future PR's.

I like the DkgCurrentState enum, it may help to have something similar in sn_consensus 🤔

@grumbach grumbach merged commit b77034d into maidsafe:main Jul 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants