Skip to content

Commit

Permalink
Merge 6e23df2 into 6c2638f
Browse files Browse the repository at this point in the history
  • Loading branch information
grumbach committed Jul 15, 2022
2 parents 6c2638f + 6e23df2 commit 67ca360
Show file tree
Hide file tree
Showing 7 changed files with 457 additions and 34 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ license = "MIT"
[dependencies]
bincode = "1.2.0"
byteorder = "1.3.2"
failure = "0.1.6"
hex_fmt = "0.3"
rand = "0.6.5"
serde = { version = "1.0.102", features = ["derive", "rc"] }
tiny-keccak = { version = "2.0.1", features = ["sha3"]}
bls = { package = "blsttc", version = "6.0.0" }
thiserror = "1.0.31"
bls = { package = "blsttc", version = "6.0.0" }
log = "0.4.13"
38 changes: 38 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2022 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.

use crate::sdkg::Error as DkgError;
use thiserror::Error;

/// All the Dkg Errors
#[derive(Error, Debug)]
pub enum Error {
/// SDKG faults and errors
#[error("Dkg Error")]
Sdkg(#[from] DkgError),
/// Encoding
#[error("Failed to encode with bincode")]
Encoding(#[from] bincode::Error),
/// Invalid DkgState init input parameters
#[error("Failed to initialize DkgState: secret key is not in provided pub key set")]
NotInPubKeySet,
/// Invalid signature
#[error("Invalid signature")]
InvalidSignature,
/// Got vote from an unknown sender id
#[error("Unknown sender")]
UnknownSender,
/// Got a faulty vote, some nodes are dishonest or dysfunctional
#[error("Faulty vote {0}")]
FaultyVote(String),
/// Unexpectedly failed to generate secret key share
#[error("Unexpectedly failed to generate secret key share")]
FailedToGenerateSecretKeyShare,
}

pub type Result<T> = std::result::Result<T, Error>;
96 changes: 96 additions & 0 deletions src/knowledge.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright 2022 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.

use log::debug;
use std::collections::{BTreeMap, BTreeSet};
use thiserror::Error;

use crate::vote::{DkgVote, IdAck, IdPart, NodeId};

pub(crate) struct Knowledge {
pub parts: BTreeSet<IdPart>,
pub acks: BTreeMap<IdPart, BTreeSet<IdAck>>,
pub agreed_with_all_acks: BTreeSet<NodeId>,
}

#[derive(Error, Debug)]
pub(crate) enum KnowledgeFault {
#[error("Missing Parts to deal with Acks in received vote")]
MissingParts,
#[error("Parts in received vote differ from ours")]
IncompatibleParts,
#[error("Missing Acks to deal with AllAcks in received vote")]
MissingAcks,
#[error("Acks received in vote differ from ours")]
IncompatibleAcks,
}

impl Knowledge {
fn new() -> Self {
Knowledge {
parts: BTreeSet::new(),
acks: BTreeMap::new(),
agreed_with_all_acks: BTreeSet::new(),
}
}

pub fn from_votes(mut votes: Vec<(DkgVote, NodeId)>) -> Result<Self, KnowledgeFault> {
votes.sort();
let mut knowledge = Knowledge::new();
for (vote, voter_id) in votes {
knowledge.handle_vote(vote, voter_id)?;
}

Ok(knowledge)
}

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

fn handle_vote(&mut self, vote: DkgVote, id: NodeId) -> Result<(), KnowledgeFault> {
match vote {
DkgVote::SinglePart(part) => {
self.parts.insert((id, part));
}
DkgVote::SingleAck(acked_parts) => {
let parts: BTreeSet<_> = acked_parts.keys().cloned().collect();
if self.parts.len() < parts.len() {
return Err(KnowledgeFault::MissingParts);
} else if self.parts != parts {
debug!(
"IncompatibleParts: ours: {:?}, theirs: {:?}",
self.parts, parts
);
return Err(KnowledgeFault::IncompatibleParts);
}
for (id_part, ack) in acked_parts {
if let Some(entry) = self.acks.get_mut(&id_part) {
entry.insert((id, ack));
} else {
self.acks.insert(id_part, BTreeSet::from([(id, ack)]));
}
}
}
DkgVote::AllAcks(all_acks) => {
if !self.got_all_acks(self.parts.len()) {
return Err(KnowledgeFault::MissingAcks);
} else if all_acks != self.acks {
debug!(
"IncompatibleAcks: ours: {:?}, theirs: {:?}",
self.acks, all_acks
);
return Err(KnowledgeFault::IncompatibleAcks);
}
self.agreed_with_all_acks.insert(id);
}
}
Ok(())
}
}
19 changes: 8 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,13 @@
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.
//
// The following code is based on hbbft : https://github.com/poanetwork/hbbft
//
// hbbft is copyright 2018, POA Networks, Ltd.
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. All files in the project
// carrying such notice may not be copied, modified, or distributed except
// according to those terms.

mod sdkg;
pub(crate) mod error;
pub(crate) mod knowledge;
pub mod sdkg;
mod state;
pub(crate) mod vote;

pub use sdkg::{to_pub_keys, AckOutcome, PartOutcome, SyncKeyGen};
pub use error::Error;
pub use state::{DkgState, VoteResponse};
pub use vote::DkgSignedVote;
42 changes: 21 additions & 21 deletions src/sdkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ use bls::{
serde_impl::FieldWrap,
Ciphertext, Fr, G1Affine, PublicKey, PublicKeySet, SecretKey, SecretKeyShare,
};
use failure::Fail;
use serde::{Deserialize, Serialize};
use std::{
borrow::Borrow,
Expand All @@ -87,6 +86,7 @@ use std::{
ops::{AddAssign, Mul},
sync::Arc,
};
use thiserror::Error;

/// A peer node's unique identifier.
pub trait NodeIdT: Eq + Ord + Clone + Debug + Hash + Send + Sync {}
Expand All @@ -109,22 +109,22 @@ where

/// A local error while handling an `Ack` or `Part` message, that was not caused by that message
/// being invalid.
#[derive(Clone, PartialEq, Debug, Fail)]
#[derive(Clone, PartialEq, Debug, Error)]
pub enum Error {
/// Error creating `SyncKeyGen`.
#[fail(display = "Error creating SyncKeyGen: {}", _0)]
#[error("Error creating SyncKeyGen: {0}")]
Creation(CryptoError),
/// Error generating keys.
#[fail(display = "Error generating keys: {}", _0)]
#[error("Error generating keys: {0}")]
Generation(CryptoError),
/// Unknown sender.
#[fail(display = "Unknown sender")]
#[error("Unknown sender")]
UnknownSender,
/// Failed to serialize message.
#[fail(display = "Serialization error: {}", _0)]
#[error("Serialization error: {0}")]
Serialize(String),
/// Failed to encrypt message parts for a peer.
#[fail(display = "Encryption error: {}", _0)]
#[error("Encryption error: {0}")]
Encrypt(String),
}

Expand All @@ -140,7 +140,7 @@ impl From<bincode::Error> for Error {
/// The message contains a commitment to a bivariate polynomial, and for each node, an encrypted
/// row of values. If this message receives enough `Ack`s, it will be used as summand to produce
/// the the key set in the end.
#[derive(Deserialize, Serialize, Clone, Hash, Eq, PartialEq)]
#[derive(Deserialize, Serialize, Clone, Hash, Eq, PartialEq, PartialOrd, Ord)]
pub struct Part(BivarCommitment, Vec<Ciphertext>);

impl Debug for Part {
Expand All @@ -157,7 +157,7 @@ impl Debug for Part {
///
/// The message is only produced after we verified our row against the commitment in the `Part`.
/// For each node, it contains one encrypted value of that row.
#[derive(Deserialize, Serialize, Clone, Hash, Eq, PartialEq)]
#[derive(Deserialize, Serialize, Clone, Hash, Eq, PartialEq, PartialOrd, Ord)]
pub struct Ack(u64, Vec<Ciphertext>);

impl Debug for Ack {
Expand Down Expand Up @@ -462,42 +462,42 @@ impl<N: NodeIdT> SyncKeyGen<N> {
}

/// An error in an `Ack` message sent by a faulty node.
#[derive(Clone, Copy, Eq, PartialEq, Debug, Fail)]
#[derive(Clone, Copy, Eq, PartialEq, Debug, Error)]
pub enum AckFault {
/// The number of values differs from the number of nodes.
#[fail(display = "The number of values differs from the number of nodes")]
#[error("The number of values differs from the number of nodes")]
ValueCount,
/// No corresponding Part received.
#[fail(display = "No corresponding Part received")]
#[error("No corresponding Part received")]
MissingPart,
/// Value decryption failed.
#[fail(display = "Value decryption failed")]
#[error("Value decryption failed")]
DecryptValue,
/// Value deserialization failed.
#[fail(display = "Value deserialization failed")]
#[error("Value deserialization failed")]
DeserializeValue,
/// Value doesn't match the commitment.
#[fail(display = "Value doesn't match the commitment")]
#[error("Value doesn't match the commitment")]
ValueCommitment,
}

/// An error in a `Part` message sent by a faulty node.
#[derive(Clone, Copy, Eq, PartialEq, Debug, Fail)]
#[derive(Clone, Copy, Eq, PartialEq, Debug, Error)]
pub enum PartFault {
/// The number of rows differs from the number of nodes.
#[fail(display = "The number of rows differs from the number of nodes")]
#[error("The number of rows differs from the number of nodes")]
RowCount,
/// Received multiple different Part messages from the same sender.
#[fail(display = "Received multiple different Part messages from the same sender")]
#[error("Received multiple different Part messages from the same sender")]
MultipleParts,
/// Could not decrypt our row in the Part message.
#[fail(display = "Could not decrypt our row in the Part message")]
#[error("Could not decrypt our row in the Part message")]
DecryptRow,
/// Could not deserialize our row in the Part message.
#[fail(display = "Could not deserialize our row in the Part message")]
#[error("Could not deserialize our row in the Part message")]
DeserializeRow,
/// Row does not match the commitment.
#[fail(display = "Row does not match the commitment")]
#[error("Row does not match the commitment")]
RowCommitment,
}

Expand Down
Loading

0 comments on commit 67ca360

Please sign in to comment.