mirror of https://github.com/poanetwork/hbbft.git
Minor API and documentation improvements.
This commit is contained in:
parent
26ef33e4d1
commit
3981b37fa3
|
@ -77,7 +77,7 @@ impl<N: NodeIdT> DistAlgorithm for BinaryAgreement<N> {
|
|||
type Error = Error;
|
||||
|
||||
fn handle_input(&mut self, input: Self::Input) -> Result<Step<N>> {
|
||||
self.handle_input(input)
|
||||
self.propose(input)
|
||||
}
|
||||
|
||||
/// Receive input from a remote node.
|
||||
|
@ -120,9 +120,14 @@ impl<N: NodeIdT> BinaryAgreement<N> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Sets the input value for Binary Agreement.
|
||||
pub fn handle_input(&mut self, input: bool) -> Result<Step<N>> {
|
||||
if !self.can_input() {
|
||||
/// Proposes a boolean value for Binary Agreement.
|
||||
///
|
||||
/// If more than two thirds of validators propose the same value, that will eventually be
|
||||
/// output. Otherwise either output is possible.
|
||||
///
|
||||
/// Note that if `can_propose` returns `false`, it is already too late to affect the outcome.
|
||||
pub fn propose(&mut self, input: bool) -> Result<Step<N>> {
|
||||
if !self.can_propose() {
|
||||
return Ok(Step::default());
|
||||
}
|
||||
// Set the initial estimated value to the input value.
|
||||
|
@ -132,7 +137,9 @@ impl<N: NodeIdT> BinaryAgreement<N> {
|
|||
self.handle_sbvb_step(sbvb_step)
|
||||
}
|
||||
|
||||
/// Handles an incoming message.
|
||||
/// Handles a message received from `sender_id`.
|
||||
///
|
||||
/// This must be called with every message we receive from another node.
|
||||
pub fn handle_message(&mut self, sender_id: &N, msg: Message) -> Result<Step<N>> {
|
||||
let Message { epoch, content } = msg;
|
||||
if self.decision.is_some() || (epoch < self.epoch && content.can_expire()) {
|
||||
|
@ -150,7 +157,7 @@ impl<N: NodeIdT> BinaryAgreement<N> {
|
|||
|
||||
/// Whether we can still input a value. It is not an error to input if this returns `false`,
|
||||
/// but it will have no effect on the outcome.
|
||||
pub fn can_input(&self) -> bool {
|
||||
pub fn can_propose(&self) -> bool {
|
||||
self.epoch == 0 && self.estimated.is_none()
|
||||
}
|
||||
|
||||
|
@ -365,7 +372,7 @@ impl<N: NodeIdT> BinaryAgreement<N> {
|
|||
// Invoke the coin.
|
||||
let ts_step = match self.coin_state {
|
||||
CoinState::Decided(_) => return Ok(Step::default()), // Coin has already decided.
|
||||
CoinState::InProgress(ref mut ts) => ts.handle_input(()).map_err(Error::InvokeCoin)?,
|
||||
CoinState::InProgress(ref mut ts) => ts.sign().map_err(Error::InvokeCoin)?,
|
||||
};
|
||||
let mut step = self.on_coin_step(ts_step)?;
|
||||
step.extend(self.try_update_epoch()?);
|
||||
|
|
|
@ -21,6 +21,8 @@ pub struct Broadcast<N> {
|
|||
proposer_id: N,
|
||||
data_shard_num: usize,
|
||||
coding: Coding,
|
||||
/// If we are the proposer: whether we have already sent the `Value` messages with the shards.
|
||||
value_sent: bool,
|
||||
/// Whether we have already multicast `Echo`.
|
||||
echo_sent: bool,
|
||||
/// Whether we have already multicast `Ready`.
|
||||
|
@ -74,6 +76,7 @@ impl<N: NodeIdT> Broadcast<N> {
|
|||
proposer_id,
|
||||
data_shard_num,
|
||||
coding,
|
||||
value_sent: false,
|
||||
echo_sent: false,
|
||||
ready_sent: false,
|
||||
decided: false,
|
||||
|
@ -87,6 +90,10 @@ impl<N: NodeIdT> Broadcast<N> {
|
|||
if *self.netinfo.our_id() != self.proposer_id {
|
||||
return Err(Error::InstanceCannotPropose);
|
||||
}
|
||||
if self.value_sent {
|
||||
return Err(Error::MultipleInputs);
|
||||
}
|
||||
self.value_sent = true;
|
||||
// Split the value into chunks/shards, encode them with erasure codes.
|
||||
// Assemble a Merkle tree from data and parity shards. Take all proofs
|
||||
// from this tree and send them, each to its own node.
|
||||
|
@ -96,7 +103,9 @@ impl<N: NodeIdT> Broadcast<N> {
|
|||
Ok(step)
|
||||
}
|
||||
|
||||
/// Handles an incoming message.
|
||||
/// Handles a message received from `sender_id`.
|
||||
///
|
||||
/// This must be called with every message we receive from another node.
|
||||
pub fn handle_message(&mut self, sender_id: &N, message: Message) -> Result<Step<N>> {
|
||||
if !self.netinfo.is_node_validator(sender_id) {
|
||||
return Err(Error::UnknownSender);
|
||||
|
|
|
@ -16,6 +16,8 @@ pub enum Error {
|
|||
CodingReconstructShardsTrivialReedSolomon(#[cause] rse::Error),
|
||||
#[fail(display = "Instance cannot propose")]
|
||||
InstanceCannotPropose,
|
||||
#[fail(display = "Multiple inputs received")]
|
||||
MultipleInputs,
|
||||
#[fail(display = "Not implemented")]
|
||||
NotImplemented,
|
||||
#[fail(display = "Proof construction failed")]
|
||||
|
|
|
@ -93,6 +93,11 @@ where
|
|||
}
|
||||
|
||||
/// Proposes a contribution in the current epoch.
|
||||
///
|
||||
/// Returns an error if we already made a proposal in this epoch.
|
||||
///
|
||||
/// If we are the only validator, this will immediately output a batch, containing our
|
||||
/// proposal.
|
||||
pub fn propose(&mut self, contrib: C) -> Result<Step<C, N>> {
|
||||
let key_gen_messages = self
|
||||
.key_gen_msg_buffer
|
||||
|
@ -111,6 +116,9 @@ where
|
|||
}
|
||||
|
||||
/// Casts a vote to change the set of validators.
|
||||
///
|
||||
/// This stores a pending vote for the change. It will be included in some future batch, and
|
||||
/// once enough validators have been voted for the same change, it will take effect.
|
||||
pub fn vote_for(&mut self, change: Change<N>) -> Result<Step<C, N>> {
|
||||
if !self.netinfo.is_validator() {
|
||||
return Ok(Step::default()); // TODO: Return an error?
|
||||
|
@ -120,7 +128,9 @@ where
|
|||
Ok(Target::All.message(msg).into())
|
||||
}
|
||||
|
||||
/// Handles an incoming message.
|
||||
/// Handles a message received from `sender_id`.
|
||||
///
|
||||
/// This must be called with every message we receive from another node.
|
||||
pub fn handle_message(&mut self, sender_id: &N, message: Message<N>) -> Result<Step<C, N>> {
|
||||
let epoch = message.start_epoch();
|
||||
if epoch < self.start_epoch {
|
||||
|
|
|
@ -77,7 +77,12 @@ where
|
|||
HoneyBadgerBuilder::new(netinfo)
|
||||
}
|
||||
|
||||
/// Proposes a new item in the current epoch.
|
||||
/// Proposes a contribution in the current epoch.
|
||||
///
|
||||
/// Returns an error if we already made a proposal in this epoch.
|
||||
///
|
||||
/// If we are the only validator, this will immediately output a batch, containing our
|
||||
/// proposal.
|
||||
pub fn propose(&mut self, proposal: &C) -> Result<Step<C, N>> {
|
||||
if !self.netinfo.is_validator() {
|
||||
return Ok(Step::default());
|
||||
|
@ -97,7 +102,9 @@ where
|
|||
}
|
||||
|
||||
/// Handles a message received from `sender_id`.
|
||||
fn handle_message(&mut self, sender_id: &N, message: Message<N>) -> Result<Step<C, N>> {
|
||||
///
|
||||
/// This must be called with every message we receive from another node.
|
||||
pub fn handle_message(&mut self, sender_id: &N, message: Message<N>) -> Result<Step<C, N>> {
|
||||
if !self.netinfo.is_node_validator(sender_id) {
|
||||
return Err(ErrorKind::UnknownSender.into());
|
||||
}
|
||||
|
|
|
@ -234,12 +234,22 @@ where
|
|||
}
|
||||
|
||||
/// Adds a transaction to the queue.
|
||||
///
|
||||
/// This can be called at any time to append to the transaction queue. The new transaction will
|
||||
/// be proposed in some future epoch.
|
||||
///
|
||||
/// If no proposal has yet been made for the current epoch, this may trigger one. In this case,
|
||||
/// a nonempty step will returned, with the corresponding messages. (Or, if we are the only
|
||||
/// validator, even with the completed batch as an output.)
|
||||
pub fn push_transaction(&mut self, tx: T) -> Result<Step<T, N, Q>> {
|
||||
self.queue.extend(iter::once(tx));
|
||||
self.propose()
|
||||
}
|
||||
|
||||
/// Casts a vote to change the set of validators.
|
||||
///
|
||||
/// This stores a pending vote for the change. It will be included in some future batch, and
|
||||
/// once enough validators have been voted for the same change, it will take effect.
|
||||
pub fn vote_for(&mut self, change: Change<N>) -> Result<Step<T, N, Q>> {
|
||||
let mut step = self
|
||||
.dyn_hb
|
||||
|
@ -250,7 +260,9 @@ where
|
|||
Ok(step)
|
||||
}
|
||||
|
||||
/// Handles an incoming message.
|
||||
/// Handles a message received from `sender_id`.
|
||||
///
|
||||
/// This must be called with every message we receive from another node.
|
||||
pub fn handle_message(&mut self, sender_id: &N, message: Message<N>) -> Result<Step<T, N, Q>> {
|
||||
let mut step = self
|
||||
.dyn_hb
|
||||
|
|
|
@ -95,7 +95,7 @@ impl<N: NodeIdT + Rand> DistAlgorithm for Subset<N> {
|
|||
type Error = Error;
|
||||
|
||||
fn handle_input(&mut self, input: Self::Input) -> Result<Step<N>> {
|
||||
self.send_proposed_value(input)
|
||||
self.propose(input)
|
||||
}
|
||||
|
||||
fn handle_message(&mut self, sender_id: &N, message: Message<N>) -> Result<Step<N>> {
|
||||
|
@ -118,6 +118,10 @@ pub enum SubsetOutput<N> {
|
|||
}
|
||||
|
||||
impl<N: NodeIdT + Rand> Subset<N> {
|
||||
/// Creates a new `Subset` instance with the given session identifier.
|
||||
///
|
||||
/// If multiple `Subset`s are instantiated within a single network, they must use different
|
||||
/// session identifiers to foil replay attacks.
|
||||
pub fn new(netinfo: Arc<NetworkInfo<N>>, session_id: u64) -> Result<Self> {
|
||||
// Create all broadcast instances.
|
||||
let mut broadcast_instances: BTreeMap<N, Broadcast<N>> = BTreeMap::new();
|
||||
|
@ -149,9 +153,10 @@ impl<N: NodeIdT + Rand> Subset<N> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Subset input message handler. It receives a value for broadcast
|
||||
/// and redirects it to the corresponding broadcast instance.
|
||||
pub fn send_proposed_value(&mut self, value: ProposedValue) -> Result<Step<N>> {
|
||||
/// Proposes a value for the subset.
|
||||
///
|
||||
/// Returns an error if we already made a proposal.
|
||||
pub fn propose(&mut self, value: ProposedValue) -> Result<Step<N>> {
|
||||
if !self.netinfo.is_validator() {
|
||||
return Ok(Step::default());
|
||||
}
|
||||
|
@ -160,7 +165,9 @@ impl<N: NodeIdT + Rand> Subset<N> {
|
|||
self.process_broadcast(&id, |bc| bc.handle_input(value))
|
||||
}
|
||||
|
||||
/// Handles an incoming message.
|
||||
/// Handles a message received from `sender_id`.
|
||||
///
|
||||
/// This must be called with every message we receive from another node.
|
||||
pub fn handle_message(&mut self, sender_id: &N, message: Message<N>) -> Result<Step<N>> {
|
||||
match message {
|
||||
Message::Broadcast(p_id, b_msg) => self.handle_broadcast(sender_id, &p_id, b_msg),
|
||||
|
|
|
@ -116,7 +116,11 @@ impl<N: NodeIdT> ThresholdDecryption<N> {
|
|||
self.shares.keys()
|
||||
}
|
||||
|
||||
/// Handles an incoming message. If we have collected enough shares, outputs the plaintext.
|
||||
/// Handles a message with a decryption share received from `sender_id`.
|
||||
///
|
||||
/// This must be called with every message we receive from another node.
|
||||
///
|
||||
/// If we have collected enough, returns the decrypted message.
|
||||
pub fn handle_message(&mut self, sender_id: &N, message: Message) -> Result<Step<N>> {
|
||||
if self.terminated {
|
||||
return Ok(Step::default()); // Don't waste time on redundant shares.
|
||||
|
|
|
@ -120,7 +120,11 @@ impl<N: NodeIdT> ThresholdSign<N> {
|
|||
Ok(step)
|
||||
}
|
||||
|
||||
/// Handles an incoming share. If we have collected enough, returns the full signature.
|
||||
/// Handles a message with a signature share received from `sender_id`.
|
||||
///
|
||||
/// This must be called with every message we receive from another node.
|
||||
///
|
||||
/// If we have collected enough, returns the full signature.
|
||||
pub fn handle_message(&mut self, sender_id: &N, message: Message) -> Result<Step<N>> {
|
||||
if self.terminated {
|
||||
return Ok(Step::default());
|
||||
|
|
Loading…
Reference in New Issue