mirror of https://github.com/poanetwork/hbbft.git
Replace `chain_error` with `failure`
Changes: * Remove `error_chain` and convert errors to `failure` types. * Add variants for each possible error generation point.
This commit is contained in:
parent
649353b999
commit
847a79793e
|
@ -20,7 +20,7 @@ travis-ci = { repository = "poanetwork/hbbft" }
|
|||
bincode = "1.0.0"
|
||||
byteorder = "1.2.3"
|
||||
env_logger = "0.5.10"
|
||||
error-chain = "0.11.0"
|
||||
failure = "0.1"
|
||||
init_with = "1.1.0"
|
||||
itertools = "0.7"
|
||||
log = "0.4.1"
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::io;
|
|||
use std::net::TcpStream;
|
||||
|
||||
use hbbft::messaging::SourcedMessage;
|
||||
use hbbft::proto_io::{self, ProtoIo};
|
||||
use hbbft::proto_io::{ErrorKind, ProtoIo};
|
||||
use protobuf::Message;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -85,13 +85,12 @@ impl<'a, P: Message + 'a, M: Into<P> + From<P> + Send + 'a> CommsTask<'a, P, M>
|
|||
message: message.into(),
|
||||
}).unwrap();
|
||||
}
|
||||
Err(proto_io::Error(proto_io::ErrorKind::Protobuf(e), _)) => {
|
||||
warn!("Node {} - Protobuf error {}", node_index, e)
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Node {} - Critical error {:?}", node_index, e);
|
||||
break;
|
||||
}
|
||||
Err(err) => match err.kind() {
|
||||
ErrorKind::Protobuf(pe) => {
|
||||
warn!("Node {} - Protobuf error {}", node_index, pe)
|
||||
}
|
||||
_ => warn!("Node {} - Critical error {:?}", node_index, err),
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -77,21 +77,22 @@ use common_coin::{self, CommonCoin, CommonCoinMessage};
|
|||
use fault_log::{Fault, FaultKind};
|
||||
use messaging::{self, DistAlgorithm, NetworkInfo, Target};
|
||||
|
||||
error_chain!{
|
||||
links {
|
||||
CommonCoin(common_coin::Error, common_coin::ErrorKind);
|
||||
}
|
||||
|
||||
errors {
|
||||
UnknownProposer {
|
||||
description("unknown proposer")
|
||||
}
|
||||
InputNotAccepted {
|
||||
description("input not accepted")
|
||||
}
|
||||
}
|
||||
/// An agreement error.
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Fail)]
|
||||
pub enum Error {
|
||||
#[fail(display = "HandleCoinCommonCoin error: {}", _0)]
|
||||
HandleCoinCommonCoin(common_coin::Error),
|
||||
#[fail(display = "TryFinishConfRoundCommonCoin error: {}", _0)]
|
||||
TryFinishConfRoundCommonCoin(common_coin::Error),
|
||||
#[fail(display = "Unknown proposer")]
|
||||
UnknownProposer,
|
||||
#[fail(display = "Input not accepted")]
|
||||
InputNotAccepted,
|
||||
}
|
||||
|
||||
/// An agreement result.
|
||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
pub enum AgreementContent {
|
||||
/// `BVal` message.
|
||||
|
@ -267,7 +268,7 @@ impl<NodeUid: Clone + Debug + Ord> Agreement<NodeUid> {
|
|||
proposer_id: NodeUid,
|
||||
) -> Result<Self> {
|
||||
if !netinfo.is_node_validator(&proposer_id) {
|
||||
return Err(ErrorKind::UnknownProposer.into());
|
||||
return Err(Error::UnknownProposer);
|
||||
}
|
||||
Ok(Agreement {
|
||||
netinfo,
|
||||
|
@ -291,7 +292,7 @@ impl<NodeUid: Clone + Debug + Ord> Agreement<NodeUid> {
|
|||
/// Sets the input value for agreement.
|
||||
fn set_input(&mut self, input: bool) -> Result<Step<NodeUid>> {
|
||||
if self.epoch != 0 || self.estimated.is_some() {
|
||||
return Err(ErrorKind::InputNotAccepted.into());
|
||||
return Err(Error::InputNotAccepted);
|
||||
}
|
||||
// Set the initial estimated value to the input value.
|
||||
self.estimated = Some(input);
|
||||
|
@ -411,9 +412,9 @@ impl<NodeUid: Clone + Debug + Ord> Agreement<NodeUid> {
|
|||
) -> Result<Step<NodeUid>> {
|
||||
let coin_step = match self.coin_state {
|
||||
CoinState::Decided(_) => return Ok(Step::default()), // Coin value is already decided.
|
||||
CoinState::InProgress(ref mut common_coin) => {
|
||||
common_coin.handle_message(sender_id, msg)?
|
||||
}
|
||||
CoinState::InProgress(ref mut common_coin) => common_coin
|
||||
.handle_message(sender_id, msg)
|
||||
.map_err(Error::HandleCoinCommonCoin)?,
|
||||
};
|
||||
self.on_coin_step(coin_step)
|
||||
}
|
||||
|
@ -571,7 +572,9 @@ impl<NodeUid: Clone + Debug + Ord> Agreement<NodeUid> {
|
|||
// Invoke the common coin.
|
||||
let coin_step = match self.coin_state {
|
||||
CoinState::Decided(_) => return Ok(Step::default()), // Coin has already decided.
|
||||
CoinState::InProgress(ref mut common_coin) => common_coin.input(())?,
|
||||
CoinState::InProgress(ref mut common_coin) => common_coin
|
||||
.input(())
|
||||
.map_err(Error::TryFinishConfRoundCommonCoin)?,
|
||||
};
|
||||
let mut step = self.on_coin_step(coin_step)?;
|
||||
step.extend(self.try_update_epoch()?);
|
||||
|
|
|
@ -164,21 +164,37 @@ use fault_log::{Fault, FaultKind};
|
|||
use fmt::{HexBytes, HexList, HexProof};
|
||||
use messaging::{self, DistAlgorithm, NetworkInfo, Target};
|
||||
|
||||
error_chain!{
|
||||
foreign_links {
|
||||
ReedSolomon(rse::Error);
|
||||
}
|
||||
|
||||
errors {
|
||||
InstanceCannotPropose
|
||||
NotImplemented
|
||||
ProofConstructionFailed
|
||||
RootHashMismatch
|
||||
Threading
|
||||
UnknownSender
|
||||
}
|
||||
/// A broadcast error.
|
||||
#[derive(Clone, PartialEq, Debug, Fail)]
|
||||
pub enum Error {
|
||||
#[fail(display = "CodingNewReedSolomon error: {}", _0)]
|
||||
CodingNewReedSolomon(#[cause] rse::Error),
|
||||
#[fail(display = "CodingEncodeReedSolomon error: {}", _0)]
|
||||
CodingEncodeReedSolomon(#[cause] rse::Error),
|
||||
#[fail(display = "CodingReconstructShardsReedSolomon error: {}", _0)]
|
||||
CodingReconstructShardsReedSolomon(#[cause] rse::Error),
|
||||
#[fail(
|
||||
display = "CodingReconstructShardsTrivialReedSolomon error: {}",
|
||||
_0
|
||||
)]
|
||||
CodingReconstructShardsTrivialReedSolomon(#[cause] rse::Error),
|
||||
#[fail(display = "Instance cannot propose")]
|
||||
InstanceCannotPropose,
|
||||
#[fail(display = "Not implemented")]
|
||||
NotImplemented,
|
||||
#[fail(display = "Proof construction failed")]
|
||||
ProofConstructionFailed,
|
||||
#[fail(display = "Root hash mismatch")]
|
||||
RootHashMismatch,
|
||||
#[fail(display = "Threading")]
|
||||
Threading,
|
||||
#[fail(display = "Unknown sender")]
|
||||
UnknownSender,
|
||||
}
|
||||
|
||||
/// A broadcast result.
|
||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
||||
|
||||
/// The three kinds of message sent during the reliable broadcast stage of the
|
||||
/// consensus algorithm.
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq)]
|
||||
|
@ -255,7 +271,7 @@ impl<NodeUid: Debug + Clone + Ord> DistAlgorithm for Broadcast<NodeUid> {
|
|||
|
||||
fn input(&mut self, input: Self::Input) -> Result<Step<NodeUid>> {
|
||||
if *self.netinfo.our_uid() != self.proposer_id {
|
||||
return Err(ErrorKind::InstanceCannotPropose.into());
|
||||
return Err(Error::InstanceCannotPropose);
|
||||
}
|
||||
// Split the value into chunks/shards, encode them with erasure codes.
|
||||
// Assemble a Merkle tree from data and parity shards. Take all proofs
|
||||
|
@ -272,7 +288,7 @@ impl<NodeUid: Debug + Clone + Ord> DistAlgorithm for Broadcast<NodeUid> {
|
|||
message: Self::Message,
|
||||
) -> Result<Step<NodeUid>> {
|
||||
if !self.netinfo.is_node_validator(sender_id) {
|
||||
return Err(ErrorKind::UnknownSender.into());
|
||||
return Err(Error::UnknownSender);
|
||||
}
|
||||
match message {
|
||||
BroadcastMessage::Value(p) => self.handle_value(sender_id, p),
|
||||
|
@ -368,7 +384,7 @@ impl<NodeUid: Debug + Clone + Ord> Broadcast<NodeUid> {
|
|||
let mtree = MerkleTree::from_vec(&digest::SHA256, shards_t);
|
||||
|
||||
// Default result in case of `gen_proof` error.
|
||||
let mut result = Err(ErrorKind::ProofConstructionFailed.into());
|
||||
let mut result = Err(Error::ProofConstructionFailed);
|
||||
assert_eq!(self.netinfo.num_nodes(), mtree.iter().count());
|
||||
|
||||
let mut step = Step::default();
|
||||
|
@ -376,7 +392,7 @@ impl<NodeUid: Debug + Clone + Ord> Broadcast<NodeUid> {
|
|||
for (leaf_value, uid) in mtree.iter().zip(self.netinfo.all_uids()) {
|
||||
let proof = mtree
|
||||
.gen_proof(leaf_value.to_vec())
|
||||
.ok_or(ErrorKind::ProofConstructionFailed)?;
|
||||
.ok_or(Error::ProofConstructionFailed)?;
|
||||
if *uid == *self.netinfo.our_uid() {
|
||||
// The proof is addressed to this node.
|
||||
result = Ok(proof);
|
||||
|
@ -591,7 +607,8 @@ impl Coding {
|
|||
/// Creates a new `Coding` instance with the given number of shards.
|
||||
fn new(data_shard_num: usize, parity_shard_num: usize) -> Result<Self> {
|
||||
Ok(if parity_shard_num > 0 {
|
||||
let rs = ReedSolomon::new(data_shard_num, parity_shard_num)?;
|
||||
let rs = ReedSolomon::new(data_shard_num, parity_shard_num)
|
||||
.map_err(Error::CodingNewReedSolomon)?;
|
||||
Coding::ReedSolomon(Box::new(rs))
|
||||
} else {
|
||||
Coding::Trivial(data_shard_num)
|
||||
|
@ -617,7 +634,9 @@ impl Coding {
|
|||
/// Constructs (and overwrites) the parity shards.
|
||||
fn encode(&self, slices: &mut [&mut [u8]]) -> Result<()> {
|
||||
match *self {
|
||||
Coding::ReedSolomon(ref rs) => rs.encode(slices)?,
|
||||
Coding::ReedSolomon(ref rs) => {
|
||||
rs.encode(slices).map_err(Error::CodingEncodeReedSolomon)?
|
||||
}
|
||||
Coding::Trivial(_) => (),
|
||||
}
|
||||
Ok(())
|
||||
|
@ -626,10 +645,14 @@ impl Coding {
|
|||
/// If enough shards are present, reconstructs the missing ones.
|
||||
fn reconstruct_shards(&self, shards: &mut [Option<Box<[u8]>>]) -> Result<()> {
|
||||
match *self {
|
||||
Coding::ReedSolomon(ref rs) => rs.reconstruct_shards(shards)?,
|
||||
Coding::ReedSolomon(ref rs) => rs
|
||||
.reconstruct_shards(shards)
|
||||
.map_err(Error::CodingReconstructShardsReedSolomon)?,
|
||||
Coding::Trivial(_) => {
|
||||
if shards.iter().any(Option::is_none) {
|
||||
return Err(rse::Error::TooFewShardsPresent.into());
|
||||
return Err(Error::CodingReconstructShardsTrivialReedSolomon(
|
||||
rse::Error::TooFewShardsPresent,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -645,7 +668,7 @@ fn decode_from_shards(
|
|||
) -> Option<Vec<u8>> {
|
||||
// Try to interpolate the Merkle tree using the Reed-Solomon erasure coding scheme.
|
||||
if let Err(err) = coding.reconstruct_shards(leaf_values) {
|
||||
debug!("Shard reconstruction failed: {:?}", err); // Faulty proposer
|
||||
error!("Shard reconstruction failed: {:?}", err); // Faulty proposer
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,21 +30,20 @@ use crypto::{Signature, SignatureShare};
|
|||
use fault_log::{Fault, FaultKind};
|
||||
use messaging::{self, DistAlgorithm, NetworkInfo, Target};
|
||||
|
||||
error_chain! {
|
||||
links {
|
||||
Crypto(cerror::Error, cerror::ErrorKind);
|
||||
}
|
||||
|
||||
errors {
|
||||
UnknownSender {
|
||||
description("unknown sender")
|
||||
}
|
||||
VerificationFailed {
|
||||
description("signature verification failed")
|
||||
}
|
||||
}
|
||||
/// A common coin error.
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Fail)]
|
||||
pub enum Error {
|
||||
#[fail(display = "CombineAndVerifySigCrypto error: {}", _0)]
|
||||
CombineAndVerifySigCrypto(cerror::Error),
|
||||
#[fail(display = "Unknown sender")]
|
||||
UnknownSender,
|
||||
#[fail(display = "Signature verification failed")]
|
||||
VerificationFailed,
|
||||
}
|
||||
|
||||
/// A common coin result.
|
||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Rand)]
|
||||
pub struct CommonCoinMessage(SignatureShare);
|
||||
|
||||
|
@ -160,7 +159,7 @@ where
|
|||
}
|
||||
self.received_shares.insert(sender_id.clone(), share);
|
||||
} else {
|
||||
return Err(ErrorKind::UnknownSender.into());
|
||||
return Err(Error::UnknownSender);
|
||||
}
|
||||
self.try_output()
|
||||
}
|
||||
|
@ -189,7 +188,11 @@ where
|
|||
// Pass the indices of sender nodes to `combine_signatures`.
|
||||
let to_idx = |(id, share)| (self.netinfo.node_index(id).unwrap(), share);
|
||||
let shares = self.received_shares.iter().map(to_idx);
|
||||
let sig = self.netinfo.public_key_set().combine_signatures(shares)?;
|
||||
let sig = self
|
||||
.netinfo
|
||||
.public_key_set()
|
||||
.combine_signatures(shares)
|
||||
.map_err(Error::CombineAndVerifySigCrypto)?;
|
||||
if !self
|
||||
.netinfo
|
||||
.public_key_set()
|
||||
|
@ -201,7 +204,7 @@ where
|
|||
"{:?} main public key verification failed",
|
||||
self.netinfo.our_uid()
|
||||
);
|
||||
Err(ErrorKind::VerificationFailed.into())
|
||||
Err(Error::VerificationFailed)
|
||||
} else {
|
||||
Ok(sig)
|
||||
}
|
||||
|
|
|
@ -34,19 +34,30 @@ use fmt::HexBytes;
|
|||
use messaging::{self, DistAlgorithm, NetworkInfo};
|
||||
use rand::Rand;
|
||||
|
||||
error_chain!{
|
||||
links {
|
||||
Agreement(agreement::Error, agreement::ErrorKind);
|
||||
Broadcast(broadcast::Error, broadcast::ErrorKind);
|
||||
}
|
||||
|
||||
errors {
|
||||
MultipleAgreementResults
|
||||
NoSuchAgreementInstance
|
||||
NoSuchBroadcastInstance
|
||||
}
|
||||
/// A common subset error.
|
||||
#[derive(Clone, PartialEq, Debug, Fail)]
|
||||
pub enum Error {
|
||||
#[fail(display = "NewAgreement error: {}", _0)]
|
||||
NewAgreement(agreement::Error),
|
||||
#[fail(display = "ProcessAgreementAgreement0 error: {}", _0)]
|
||||
ProcessAgreementAgreement0(agreement::Error),
|
||||
#[fail(display = "ProcessAgreementAgreement1 error: {}", _0)]
|
||||
ProcessAgreementAgreement1(agreement::Error),
|
||||
#[fail(display = "NewBroadcast error: {}", _0)]
|
||||
NewBroadcast(broadcast::Error),
|
||||
#[fail(display = "ProcessBroadcastBroadcast error: {}", _0)]
|
||||
ProcessBroadcastBroadcast(broadcast::Error),
|
||||
#[fail(display = "Multiple agreement results")]
|
||||
MultipleAgreementResults,
|
||||
#[fail(display = "No such agreement instance")]
|
||||
NoSuchAgreementInstance,
|
||||
#[fail(display = "No such broadcast instance")]
|
||||
NoSuchBroadcastInstance,
|
||||
}
|
||||
|
||||
/// A common subset result.
|
||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
||||
|
||||
// TODO: Make this a generic argument of `CommonSubset`.
|
||||
type ProposedValue = Vec<u8>;
|
||||
|
||||
|
@ -118,7 +129,7 @@ impl<NodeUid: Clone + Debug + Ord + Rand> CommonSubset<NodeUid> {
|
|||
for proposer_id in netinfo.all_uids() {
|
||||
broadcast_instances.insert(
|
||||
proposer_id.clone(),
|
||||
Broadcast::new(netinfo.clone(), proposer_id.clone())?,
|
||||
Broadcast::new(netinfo.clone(), proposer_id.clone()).map_err(Error::NewBroadcast)?,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -127,7 +138,8 @@ impl<NodeUid: Clone + Debug + Ord + Rand> CommonSubset<NodeUid> {
|
|||
for proposer_id in netinfo.all_uids() {
|
||||
agreement_instances.insert(
|
||||
proposer_id.clone(),
|
||||
Agreement::new(netinfo.clone(), session_id, proposer_id.clone())?,
|
||||
Agreement::new(netinfo.clone(), session_id, proposer_id.clone())
|
||||
.map_err(Error::NewAgreement)?,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -189,9 +201,12 @@ impl<NodeUid: Clone + Debug + Ord + Rand> CommonSubset<NodeUid> {
|
|||
let broadcast = self
|
||||
.broadcast_instances
|
||||
.get_mut(proposer_id)
|
||||
.ok_or(ErrorKind::NoSuchBroadcastInstance)?;
|
||||
.ok_or(Error::NoSuchBroadcastInstance)?;
|
||||
let to_msg = |b_msg| Message::Broadcast(proposer_id.clone(), b_msg);
|
||||
let output = step.extend_with(f(broadcast)?, to_msg);
|
||||
let output = step.extend_with(
|
||||
f(broadcast).map_err(Error::ProcessBroadcastBroadcast)?,
|
||||
to_msg,
|
||||
);
|
||||
if let Some(output) = output.into_iter().next() {
|
||||
output
|
||||
} else {
|
||||
|
@ -222,12 +237,15 @@ impl<NodeUid: Clone + Debug + Ord + Rand> CommonSubset<NodeUid> {
|
|||
let agreement = self
|
||||
.agreement_instances
|
||||
.get_mut(proposer_id)
|
||||
.ok_or(ErrorKind::NoSuchAgreementInstance)?;
|
||||
.ok_or(Error::NoSuchAgreementInstance)?;
|
||||
if agreement.terminated() {
|
||||
return Ok(step);
|
||||
}
|
||||
let to_msg = |a_msg| Message::Agreement(proposer_id.clone(), a_msg);
|
||||
let output = step.extend_with(f(agreement)?, to_msg);
|
||||
let output = step.extend_with(
|
||||
f(agreement).map_err(Error::ProcessAgreementAgreement0)?,
|
||||
to_msg,
|
||||
);
|
||||
if let Some(output) = output.into_iter().next() {
|
||||
output
|
||||
} else {
|
||||
|
@ -239,7 +257,7 @@ impl<NodeUid: Clone + Debug + Ord + Rand> CommonSubset<NodeUid> {
|
|||
.insert(proposer_id.clone(), value)
|
||||
.is_some()
|
||||
{
|
||||
return Err(ErrorKind::MultipleAgreementResults.into());
|
||||
return Err(Error::MultipleAgreementResults);
|
||||
}
|
||||
debug!(
|
||||
"{:?} Updated Agreement results: {:?}",
|
||||
|
@ -253,9 +271,14 @@ impl<NodeUid: Clone + Debug + Ord + Rand> CommonSubset<NodeUid> {
|
|||
for (uid, agreement) in &mut self.agreement_instances {
|
||||
if agreement.accepts_input() {
|
||||
let to_msg = |a_msg| Message::Agreement(uid.clone(), a_msg);
|
||||
for output in step.extend_with(agreement.input(false)?, to_msg) {
|
||||
for output in step.extend_with(
|
||||
agreement
|
||||
.input(false)
|
||||
.map_err(Error::ProcessAgreementAgreement1)?,
|
||||
to_msg,
|
||||
) {
|
||||
if self.agreement_results.insert(uid.clone(), output).is_some() {
|
||||
return Err(ErrorKind::MultipleAgreementResults.into());
|
||||
return Err(Error::MultipleAgreementResults);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
error_chain! {
|
||||
errors {
|
||||
NotEnoughShares {
|
||||
description("not enough signature shares")
|
||||
}
|
||||
DuplicateEntry {
|
||||
description("signature shares contain a duplicated index")
|
||||
}
|
||||
}
|
||||
//! Crypto errors.
|
||||
|
||||
/// A crypto error.
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Fail)]
|
||||
pub enum Error {
|
||||
#[fail(display = "Not enough signature shares")]
|
||||
NotEnoughShares,
|
||||
#[fail(display = "Signature shares contain a duplicated index")]
|
||||
DuplicateEntry,
|
||||
}
|
||||
|
||||
/// A crypto result.
|
||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
||||
|
|
|
@ -20,7 +20,7 @@ use pairing::{CurveAffine, CurveProjective, Engine, Field};
|
|||
use rand::{ChaChaRng, OsRng, Rng, SeedableRng};
|
||||
use ring::digest;
|
||||
|
||||
use self::error::{ErrorKind, Result};
|
||||
use self::error::{Error, Result};
|
||||
use self::into_fr::IntoFr;
|
||||
use self::poly::{Commitment, Poly};
|
||||
use fmt::HexBytes;
|
||||
|
@ -459,13 +459,13 @@ where
|
|||
.map(|(i, sample)| (into_fr_plus_1(i), sample))
|
||||
.collect();
|
||||
if samples.len() < t {
|
||||
return Err(ErrorKind::NotEnoughShares.into());
|
||||
return Err(Error::NotEnoughShares);
|
||||
}
|
||||
let mut result = C::zero();
|
||||
let mut indexes = Vec::new();
|
||||
for (x, sample) in samples.iter().take(t) {
|
||||
if indexes.contains(x) {
|
||||
return Err(ErrorKind::DuplicateEntry.into());
|
||||
return Err(Error::DuplicateEntry);
|
||||
}
|
||||
indexes.push(x.clone());
|
||||
// Compute the value at 0 of the Lagrange polynomial that is `0` at the other data
|
||||
|
|
|
@ -1,17 +1,70 @@
|
|||
use bincode;
|
||||
|
||||
use failure::{Backtrace, Context, Fail};
|
||||
use honey_badger;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
error_chain!{
|
||||
links {
|
||||
HoneyBadger(honey_badger::Error, honey_badger::ErrorKind);
|
||||
/// Dynamic honey badger error variants.
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum ErrorKind {
|
||||
#[fail(display = "SendTransactionBincode error: {}", _0)]
|
||||
SendTransactionBincode(bincode::ErrorKind),
|
||||
#[fail(display = "VerifySignatureBincode error: {}", _0)]
|
||||
VerifySignatureBincode(bincode::ErrorKind),
|
||||
#[fail(display = "SignVoteForBincode error: {}", _0)]
|
||||
SignVoteForBincode(bincode::ErrorKind),
|
||||
#[fail(display = "ValidateBincode error: {}", _0)]
|
||||
ValidateBincode(bincode::ErrorKind),
|
||||
#[fail(display = "ProposeHoneyBadger error: {}", _0)]
|
||||
ProposeHoneyBadger(honey_badger::Error),
|
||||
#[fail(
|
||||
display = "HandleHoneyBadgerMessageHoneyBadger error: {}",
|
||||
_0
|
||||
)]
|
||||
HandleHoneyBadgerMessageHoneyBadger(honey_badger::Error),
|
||||
#[fail(display = "Unknown sender")]
|
||||
UnknownSender,
|
||||
}
|
||||
|
||||
/// A dynamic honey badger error.
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
inner: Context<ErrorKind>,
|
||||
}
|
||||
|
||||
impl Fail for Error {
|
||||
fn cause(&self) -> Option<&Fail> {
|
||||
self.inner.cause()
|
||||
}
|
||||
|
||||
foreign_links {
|
||||
Bincode(Box<bincode::ErrorKind>);
|
||||
}
|
||||
|
||||
errors {
|
||||
UnknownSender
|
||||
fn backtrace(&self) -> Option<&Backtrace> {
|
||||
self.inner.backtrace()
|
||||
}
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn kind(&self) -> &ErrorKind {
|
||||
self.inner.get_context()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ErrorKind> for Error {
|
||||
fn from(kind: ErrorKind) -> Error {
|
||||
Error {
|
||||
inner: Context::new(kind),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Context<ErrorKind>> for Error {
|
||||
fn from(inner: Context<ErrorKind>) -> Error {
|
||||
Error { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.inner, f)
|
||||
}
|
||||
}
|
||||
|
||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
||||
|
|
|
@ -192,11 +192,14 @@ where
|
|||
|
||||
/// Proposes a contribution in the current epoch.
|
||||
pub fn propose(&mut self, contrib: C) -> Result<Step<C, NodeUid>> {
|
||||
let step = self.honey_badger.input(InternalContrib {
|
||||
contrib,
|
||||
key_gen_messages: self.key_gen_msg_buffer.clone(),
|
||||
votes: self.vote_counter.pending_votes().cloned().collect(),
|
||||
})?;
|
||||
let step = self
|
||||
.honey_badger
|
||||
.input(InternalContrib {
|
||||
contrib,
|
||||
key_gen_messages: self.key_gen_msg_buffer.clone(),
|
||||
votes: self.vote_counter.pending_votes().cloned().collect(),
|
||||
})
|
||||
.map_err(ErrorKind::ProposeHoneyBadger)?;
|
||||
self.process_output(step)
|
||||
}
|
||||
|
||||
|
@ -226,7 +229,10 @@ where
|
|||
return Err(ErrorKind::UnknownSender.into());
|
||||
}
|
||||
// Handle the message.
|
||||
let step = self.honey_badger.handle_message(sender_id, message)?;
|
||||
let step = self
|
||||
.honey_badger
|
||||
.handle_message(sender_id, message)
|
||||
.map_err(ErrorKind::HandleHoneyBadgerMessageHoneyBadger)?;
|
||||
self.process_output(step)
|
||||
}
|
||||
|
||||
|
@ -375,7 +381,8 @@ where
|
|||
|
||||
/// Signs and sends a `KeyGenMessage` and also tries to commit it.
|
||||
fn send_transaction(&mut self, kg_msg: KeyGenMessage) -> Result<Step<C, NodeUid>> {
|
||||
let ser = bincode::serialize(&kg_msg)?;
|
||||
let ser =
|
||||
bincode::serialize(&kg_msg).map_err(|err| ErrorKind::SendTransactionBincode(*err))?;
|
||||
let sig = Box::new(self.netinfo.secret_key().sign(ser));
|
||||
if self.netinfo.is_validator() {
|
||||
let our_uid = self.netinfo.our_uid().clone();
|
||||
|
@ -412,7 +419,8 @@ where
|
|||
sig: &Signature,
|
||||
kg_msg: &KeyGenMessage,
|
||||
) -> Result<bool> {
|
||||
let ser = bincode::serialize(kg_msg)?;
|
||||
let ser =
|
||||
bincode::serialize(kg_msg).map_err(|err| ErrorKind::VerifySignatureBincode(*err))?;
|
||||
let pk_opt = (self.netinfo.public_key(node_id)).or_else(|| {
|
||||
self.key_gen
|
||||
.iter()
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::sync::Arc;
|
|||
use bincode;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{Change, Result};
|
||||
use super::{Change, ErrorKind, Result};
|
||||
use crypto::Signature;
|
||||
use fault_log::{FaultKind, FaultLog};
|
||||
use messaging::NetworkInfo;
|
||||
|
@ -50,7 +50,8 @@ where
|
|||
era: self.era,
|
||||
num: self.pending.get(&voter).map_or(0, |sv| sv.vote.num + 1),
|
||||
};
|
||||
let ser_vote = bincode::serialize(&vote)?;
|
||||
let ser_vote =
|
||||
bincode::serialize(&vote).map_err(|err| ErrorKind::SignVoteForBincode(*err))?;
|
||||
let signed_vote = SignedVote {
|
||||
vote,
|
||||
voter: voter.clone(),
|
||||
|
@ -149,7 +150,8 @@ where
|
|||
|
||||
/// Returns `true` if the signature is valid.
|
||||
fn validate(&self, signed_vote: &SignedVote<NodeUid>) -> Result<bool> {
|
||||
let ser_vote = bincode::serialize(&signed_vote.vote)?;
|
||||
let ser_vote =
|
||||
bincode::serialize(&signed_vote.vote).map_err(|err| ErrorKind::ValidateBincode(*err))?;
|
||||
let pk_opt = self.netinfo.public_key(&signed_vote.voter);
|
||||
Ok(pk_opt.map_or(false, |pk| pk.verify(&signed_vote.sig, ser_vote)))
|
||||
}
|
||||
|
|
|
@ -25,13 +25,14 @@
|
|||
use rand::Rand;
|
||||
use std::collections::btree_map::Entry;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::fmt::Debug;
|
||||
use std::fmt::{self, Debug, Display};
|
||||
use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
|
||||
use bincode;
|
||||
use failure::{Backtrace, Context, Fail};
|
||||
use itertools::Itertools;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -40,20 +41,67 @@ use crypto::{Ciphertext, DecryptionShare};
|
|||
use fault_log::{Fault, FaultKind, FaultLog};
|
||||
use messaging::{self, DistAlgorithm, NetworkInfo, Target};
|
||||
|
||||
error_chain!{
|
||||
links {
|
||||
CommonSubset(common_subset::Error, common_subset::ErrorKind);
|
||||
/// Honey badger error variants.
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum ErrorKind {
|
||||
#[fail(display = "ProposeBincode error: {}", _0)]
|
||||
ProposeBincode(bincode::ErrorKind),
|
||||
#[fail(display = "ProposeCommonSubset0 error: {}", _0)]
|
||||
ProposeCommonSubset0(common_subset::Error),
|
||||
#[fail(display = "ProposeCommonSubset1 error: {}", _0)]
|
||||
ProposeCommonSubset1(common_subset::Error),
|
||||
#[fail(display = "HandleCommonMessageCommonSubset0 error: {}", _0)]
|
||||
HandleCommonMessageCommonSubset0(common_subset::Error),
|
||||
#[fail(display = "HandleCommonMessageCommonSubset1 error: {}", _0)]
|
||||
HandleCommonMessageCommonSubset1(common_subset::Error),
|
||||
#[fail(display = "Unknown sender")]
|
||||
UnknownSender,
|
||||
}
|
||||
|
||||
/// A honey badger error.
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
inner: Context<ErrorKind>,
|
||||
}
|
||||
|
||||
impl Fail for Error {
|
||||
fn cause(&self) -> Option<&Fail> {
|
||||
self.inner.cause()
|
||||
}
|
||||
|
||||
foreign_links {
|
||||
Bincode(Box<bincode::ErrorKind>);
|
||||
}
|
||||
|
||||
errors {
|
||||
UnknownSender
|
||||
fn backtrace(&self) -> Option<&Backtrace> {
|
||||
self.inner.backtrace()
|
||||
}
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn kind(&self) -> &ErrorKind {
|
||||
self.inner.get_context()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ErrorKind> for Error {
|
||||
fn from(kind: ErrorKind) -> Error {
|
||||
Error {
|
||||
inner: Context::new(kind),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Context<ErrorKind>> for Error {
|
||||
fn from(inner: Context<ErrorKind>) -> Error {
|
||||
Error { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.inner, f)
|
||||
}
|
||||
}
|
||||
|
||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
||||
|
||||
/// A Honey Badger builder, to configure the parameters and create new instances of `HoneyBadger`.
|
||||
pub struct HoneyBadgerBuilder<C, NodeUid> {
|
||||
/// Shared network data.
|
||||
|
@ -195,14 +243,17 @@ where
|
|||
let cs_step = {
|
||||
let cs = match self.common_subsets.entry(epoch) {
|
||||
Entry::Occupied(entry) => entry.into_mut(),
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(CommonSubset::new(self.netinfo.clone(), epoch)?)
|
||||
}
|
||||
Entry::Vacant(entry) => entry.insert(
|
||||
CommonSubset::new(self.netinfo.clone(), epoch)
|
||||
.map_err(ErrorKind::ProposeCommonSubset0)?,
|
||||
),
|
||||
};
|
||||
let ser_prop = bincode::serialize(&proposal)?;
|
||||
let ser_prop =
|
||||
bincode::serialize(&proposal).map_err(|err| ErrorKind::ProposeBincode(*err))?;
|
||||
let ciphertext = self.netinfo.public_key_set().public_key().encrypt(ser_prop);
|
||||
self.has_input = true;
|
||||
cs.input(bincode::serialize(&ciphertext).unwrap())?
|
||||
cs.input(bincode::serialize(&ciphertext).unwrap())
|
||||
.map_err(ErrorKind::ProposeCommonSubset1)?
|
||||
};
|
||||
self.process_output(cs_step, epoch)
|
||||
}
|
||||
|
@ -245,11 +296,15 @@ where
|
|||
// Epoch has already terminated. Message is obsolete.
|
||||
return Ok(Step::default());
|
||||
} else {
|
||||
entry.insert(CommonSubset::new(self.netinfo.clone(), epoch)?)
|
||||
entry.insert(
|
||||
CommonSubset::new(self.netinfo.clone(), epoch)
|
||||
.map_err(ErrorKind::HandleCommonMessageCommonSubset0)?,
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
cs.handle_message(sender_id, message)?
|
||||
cs.handle_message(sender_id, message)
|
||||
.map_err(ErrorKind::HandleCommonMessageCommonSubset1)?
|
||||
};
|
||||
let step = self.process_output(cs_step, epoch)?;
|
||||
self.remove_terminated(epoch);
|
||||
|
|
|
@ -107,7 +107,7 @@
|
|||
extern crate bincode;
|
||||
extern crate byteorder;
|
||||
#[macro_use]
|
||||
extern crate error_chain;
|
||||
extern crate failure;
|
||||
extern crate init_with;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
//! Protobuf message IO task structure.
|
||||
|
||||
use failure::{Backtrace, Context, Fail};
|
||||
use protobuf::{self, Message, ProtobufError};
|
||||
use std::io::{Read, Write};
|
||||
use std::io::{self, Read, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::net::TcpStream;
|
||||
use std::{cmp, io};
|
||||
use std::{
|
||||
cmp,
|
||||
fmt::{self, Display},
|
||||
};
|
||||
|
||||
/// A magic key to put right before each message. An atavism of primitive serial
|
||||
/// protocols.
|
||||
|
@ -12,23 +16,77 @@ use std::{cmp, io};
|
|||
/// TODO: Replace it with a proper handshake at connection initiation.
|
||||
const FRAME_START: u32 = 0x2C0F_FEE5;
|
||||
|
||||
error_chain!{
|
||||
types {
|
||||
Error, ErrorKind, ResultExt, ProtoIoResult;
|
||||
/// IO/Messaging error variants.
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum ErrorKind {
|
||||
#[fail(display = "Io error: {}", _0)]
|
||||
Io(#[cause] io::Error),
|
||||
#[fail(display = "Protobuf error: {}", _0)]
|
||||
Protobuf(#[cause] ProtobufError),
|
||||
#[fail(display = "Decode error")]
|
||||
Decode,
|
||||
#[fail(display = "Encode error")]
|
||||
Encode,
|
||||
#[fail(display = "Frame start mismatch error")]
|
||||
FrameStartMismatch,
|
||||
}
|
||||
|
||||
/// An IO/Messaging error.
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
inner: Context<ErrorKind>,
|
||||
}
|
||||
|
||||
impl Fail for Error {
|
||||
fn cause(&self) -> Option<&Fail> {
|
||||
self.inner.cause()
|
||||
}
|
||||
|
||||
foreign_links {
|
||||
Io(io::Error);
|
||||
Protobuf(ProtobufError);
|
||||
}
|
||||
|
||||
errors {
|
||||
Decode
|
||||
Encode
|
||||
FrameStartMismatch
|
||||
fn backtrace(&self) -> Option<&Backtrace> {
|
||||
self.inner.backtrace()
|
||||
}
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn kind(&self) -> &ErrorKind {
|
||||
self.inner.get_context()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ErrorKind> for Error {
|
||||
fn from(kind: ErrorKind) -> Error {
|
||||
Error {
|
||||
inner: Context::new(kind),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Context<ErrorKind>> for Error {
|
||||
fn from(inner: Context<ErrorKind>) -> Error {
|
||||
Error { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(err: io::Error) -> Error {
|
||||
ErrorKind::Io(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ProtobufError> for Error {
|
||||
fn from(err: ProtobufError) -> Error {
|
||||
ErrorKind::Protobuf(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.inner, f)
|
||||
}
|
||||
}
|
||||
|
||||
pub type ProtoIoResult<T> = ::std::result::Result<T, Error>;
|
||||
|
||||
fn encode_u32_to_be(value: u32, buffer: &mut [u8]) -> ProtoIoResult<()> {
|
||||
if buffer.len() < 4 {
|
||||
return Err(ErrorKind::Encode.into());
|
||||
|
|
|
@ -22,9 +22,11 @@
|
|||
|
||||
use std::cmp;
|
||||
use std::fmt::Debug;
|
||||
use std::fmt::{self, Display};
|
||||
use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use failure::{Backtrace, Context, Fail};
|
||||
use rand::Rand;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -34,12 +36,61 @@ use transaction_queue::TransactionQueue;
|
|||
|
||||
pub use dynamic_honey_badger::{Change, ChangeState, Input};
|
||||
|
||||
error_chain!{
|
||||
links {
|
||||
DynamicHoneyBadger(dynamic_honey_badger::Error, dynamic_honey_badger::ErrorKind);
|
||||
/// Queueing honey badger error variants.
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum ErrorKind {
|
||||
#[fail(display = "Input error: {}", _0)]
|
||||
Input(dynamic_honey_badger::Error),
|
||||
#[fail(display = "Handle message error: {}", _0)]
|
||||
HandleMessage(dynamic_honey_badger::Error),
|
||||
#[fail(display = "Propose error: {}", _0)]
|
||||
Propose(dynamic_honey_badger::Error),
|
||||
}
|
||||
|
||||
/// A queueing honey badger error.
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
inner: Context<ErrorKind>,
|
||||
}
|
||||
|
||||
impl Fail for Error {
|
||||
fn cause(&self) -> Option<&Fail> {
|
||||
self.inner.cause()
|
||||
}
|
||||
|
||||
fn backtrace(&self) -> Option<&Backtrace> {
|
||||
self.inner.backtrace()
|
||||
}
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn kind(&self) -> &ErrorKind {
|
||||
self.inner.get_context()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ErrorKind> for Error {
|
||||
fn from(kind: ErrorKind) -> Error {
|
||||
Error {
|
||||
inner: Context::new(kind),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Context<ErrorKind>> for Error {
|
||||
fn from(inner: Context<ErrorKind>) -> Error {
|
||||
Error { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.inner, f)
|
||||
}
|
||||
}
|
||||
|
||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
||||
|
||||
/// A Queueing Honey Badger builder, to configure the parameters and create new instances of
|
||||
/// `QueueingHoneyBadger`.
|
||||
pub struct QueueingHoneyBadgerBuilder<Tx, NodeUid: Rand> {
|
||||
|
@ -141,7 +192,11 @@ where
|
|||
self.queue.0.push_back(tx);
|
||||
Ok(Step::default())
|
||||
}
|
||||
Input::Change(change) => Ok(self.dyn_hb.input(Input::Change(change))?.convert()),
|
||||
Input::Change(change) => Ok(self
|
||||
.dyn_hb
|
||||
.input(Input::Change(change))
|
||||
.map_err(ErrorKind::Input)?
|
||||
.convert()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,7 +207,8 @@ where
|
|||
) -> Result<Step<Tx, NodeUid>> {
|
||||
let mut step = self
|
||||
.dyn_hb
|
||||
.handle_message(sender_id, message)?
|
||||
.handle_message(sender_id, message)
|
||||
.map_err(ErrorKind::HandleMessage)?
|
||||
.convert::<Self>();
|
||||
for batch in &step.output {
|
||||
self.queue.remove_all(batch.iter());
|
||||
|
@ -195,7 +251,12 @@ where
|
|||
let mut step = Step::default();
|
||||
while !self.dyn_hb.has_input() {
|
||||
let proposal = self.queue.choose(amount, self.batch_size);
|
||||
step.extend(self.dyn_hb.input(Input::User(proposal))?.convert());
|
||||
step.extend(
|
||||
self.dyn_hb
|
||||
.input(Input::User(proposal))
|
||||
.map_err(ErrorKind::Propose)?
|
||||
.convert(),
|
||||
);
|
||||
}
|
||||
Ok(step)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue