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

Expose round votes through Environment #58

Merged
merged 4 commits into from
Apr 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,11 @@ impl<Id, H, N, Signature> Round<Id, H, N, Signature> where
self.voters.voter_by_index(self.round_number as usize % self.voters.len())
}

/// Return all imported prevotes.
pub fn prevotes(&self) -> Vec<(Id, Prevote<H, N>, Signature)> {
self.prevote.votes()
}

/// Return all imported precommits.
pub fn precommits(&self) -> Vec<(Id, Precommit<H, N>, Signature)> {
self.precommit.votes()
Expand Down
22 changes: 20 additions & 2 deletions src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use tokio::timer::Delay;
use parking_lot::Mutex;
use futures::prelude::*;
use futures::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
use super::{Chain, Commit, Error, Equivocation, Message, Prevote, Precommit, SignedMessage};
use super::{Chain, Commit, Error, Equivocation, Message, Prevote, Precommit, PrimaryPropose, SignedMessage};

pub const GENESIS_HASH: &str = "genesis";
const NULL_HASH: &str = "NULL";
Expand Down Expand Up @@ -215,7 +215,13 @@ impl crate::voter::Environment<&'static str, u32> for Environment {
Box::new(Delay::new(now + delay).map_err(|_| panic!("Timer failed")))
}

fn completed(&self, _round: u64, _state: RoundState<&'static str, u32>) -> Result<(), Error> {
fn completed(
&self,
_round: u64,
_state: RoundState<&'static str, u32>,
_base: (&'static str, u32),
_votes: Vec<SignedMessage<&'static str, u32, Signature, Id>>,
) -> Result<(), Error> {
Ok(())
}

Expand All @@ -230,6 +236,18 @@ impl crate::voter::Environment<&'static str, u32> for Environment {
Ok(())
}

fn proposed(&self, _round: u64, _propose: PrimaryPropose<&'static str, u32>) -> Result<(), Self::Error> {
Ok(())
}

fn prevoted(&self, _round: u64, _prevote: Prevote<&'static str, u32>) -> Result<(), Self::Error> {
Ok(())
}

fn precommitted(&self, _round: u64, _precommit: Precommit<&'static str, u32>) -> Result<(), Self::Error> {
Ok(())
}

fn prevote_equivocation(&self, round: u64, equivocation: Equivocation<Id, Prevote<&'static str, u32>, Signature>) {
panic!("Encountered equivocation in round {}: {:?}", round, equivocation);
}
Expand Down
35 changes: 30 additions & 5 deletions src/voter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ use std::sync::Arc;

use crate::round::State as RoundState;
use crate::{
Chain, Commit, CompactCommit, Equivocation, Message, Prevote, Precommit, SignedMessage,
BlockNumberOps, validate_commit
Chain, Commit, CompactCommit, Equivocation, Message, Prevote, Precommit, PrimaryPropose,
SignedMessage, BlockNumberOps, validate_commit
};
use crate::voter_set::VoterSet;
use past_rounds::PastRounds;
Expand Down Expand Up @@ -87,9 +87,24 @@ pub trait Environment<H: Eq, N: BlockNumberOps>: Chain<H, N> {
/// commit messages that are sent (e.g. random value in [0, 1] seconds).
fn round_commit_timer(&self) -> Self::Timer;

/// Note that we've done a primary proposal in the given round.
fn proposed(&self, round: u64, propose: PrimaryPropose<H, N>) -> Result<(), Self::Error>;

/// Note that we have prevoted in the given round.
fn prevoted(&self, round: u64, prevote: Prevote<H, N>) -> Result<(), Self::Error>;

/// Note that we have precommitted in the given round.
fn precommitted(&self, round: u64, precommit: Precommit<H, N>) -> Result<(), Self::Error>;

/// Note that a round was completed. This is called when a round has been
/// voted in. Should return an error when something fatal occurs.
fn completed(&self, round: u64, state: RoundState<H, N>) -> Result<(), Self::Error>;
fn completed(
&self,
round: u64,
state: RoundState<H, N>,
base: (H, N),
votes: Vec<SignedMessage<H, N, Self::Signature, Self::Id>>,
) -> Result<(), Self::Error>;

/// Called when a block should be finalized.
// TODO: make this a future that resolves when it's e.g. written to disk?
Expand Down Expand Up @@ -554,7 +569,12 @@ impl<H, N, E: Environment<H, N>, GlobalIn, GlobalOut> Voter<H, N, E, GlobalIn, G
}

fn completed_best_round(&mut self, next_round: Option<VotingRound<H, N, E>>) -> Result<(), E::Error> {
self.env.completed(self.best_round.round_number(), self.best_round.round_state())?;
self.env.completed(
self.best_round.round_number(),
self.best_round.round_state(),
self.best_round.dag_base(),
self.best_round.votes(),
)?;

let old_round_number = self.best_round.round_number();

Expand All @@ -577,7 +597,12 @@ impl<H, N, E: Environment<H, N>, GlobalIn, GlobalOut> Voter<H, N, E, GlobalIn, G
fn completed_prospective_round(&mut self, mut prospective_round: VotingRound<H, N, E>)
-> Result<(), E::Error>
{
self.env.completed(prospective_round.round_number(), prospective_round.round_state())?;
self.env.completed(
prospective_round.round_number(),
prospective_round.round_state(),
prospective_round.dag_base(),
prospective_round.votes(),
)?;

self.best_round = VotingRound::new(
prospective_round.round_number() + 1,
Expand Down
35 changes: 29 additions & 6 deletions src/voter/voting_round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,27 @@ impl<H, N, E: Environment<H, N>> VotingRound<H, N, E> where
self.best_finalized.as_ref()
}

/// Return all imported votes for the round (prevotes and precommits).
pub(super) fn votes(&self) -> Vec<SignedMessage<H, N, E::Signature, E::Id>> {
let prevotes = self.votes.prevotes().into_iter().map(|(id, prevote, signature)| {
SignedMessage {
id,
signature,
message: Message::Prevote(prevote),
}
});

let precommits = self.votes.precommits().into_iter().map(|(id, precommit, signature)| {
SignedMessage {
id,
signature,
message: Message::Precommit(precommit),
}
});

prevotes.chain(precommits).collect()
}

fn process_incoming(&mut self) -> Result<(), E::Error> {
while let Async::Ready(Some(incoming)) = self.incoming.poll()? {
trace!(target: "afg", "Got incoming message");
Expand Down Expand Up @@ -303,12 +324,12 @@ impl<H, N, E: Environment<H, N>> VotingRound<H, N, E> where
let should_send_primary = maybe_finalized.map_or(true, |f| last_round_estimate.1 < f.1);
if should_send_primary {
debug!(target: "afg", "Sending primary block hint for round {}", self.votes.number());
self.outgoing.push(Message::PrimaryPropose(
PrimaryPropose {
target_hash: last_round_estimate.0,
target_number: last_round_estimate.1,
})
);
let primary = PrimaryPropose {
target_hash: last_round_estimate.0,
target_number: last_round_estimate.1,
};
self.env.proposed(self.round_number(), primary.clone())?;
self.outgoing.push(Message::PrimaryPropose(primary));
self.state = Some(State::Proposed(prevote_timer, precommit_timer));

return Ok(());
Expand Down Expand Up @@ -342,6 +363,7 @@ impl<H, N, E: Environment<H, N>> VotingRound<H, N, E> where
if self.voting.is_active() {
if let Some(prevote) = self.construct_prevote(last_round_state)? {
debug!(target: "afg", "Casting prevote for round {}", self.votes.number());
self.env.prevoted(self.round_number(), prevote.clone())?;
self.outgoing.push(Message::Prevote(prevote));
}
}
Expand Down Expand Up @@ -393,6 +415,7 @@ impl<H, N, E: Environment<H, N>> VotingRound<H, N, E> where
if self.voting.is_active() {
debug!(target: "afg", "Casting precommit for round {}", self.votes.number());
let precommit = self.construct_precommit();
self.env.precommitted(self.round_number(), precommit.clone())?;
self.outgoing.push(Message::Precommit(precommit));
}
self.state = Some(State::Precommitted);
Expand Down