Register previous rounds' votes with gossip service on startup (#2676)

* grandpa: register previous round votes with gossip service on startup

* gossip: fix tests

* grandpa: optionally register previous round votes on startup

* grandpa: fix tests
This commit is contained in:
André Silva
2019-05-26 22:05:02 +01:00
committed by Arkadiy Paronyan
parent e2d1d0c951
commit 10c1dfcffb
7 changed files with 119 additions and 19 deletions
@@ -99,6 +99,12 @@ pub trait Network<Block: BlockT>: Clone + Send + 'static {
/// Only should be used in case of consensus stall.
fn gossip_message(&self, topic: Block::Hash, data: Vec<u8>, force: bool);
/// Register a message with the gossip service, it isn't broadcast right
/// away to any peers, but may be sent to new peers joining or when asked to
/// broadcast the topic. Useful to register previous messages on node
/// startup.
fn register_gossip_message(&self, topic: Block::Hash, data: Vec<u8>);
/// Send a message to a bunch of specific peers, even if they've seen it already.
fn send_message(&self, who: Vec<network::PeerId>, data: Vec<u8>);
@@ -145,11 +151,21 @@ impl<B, S> Network<B> for Arc<NetworkService<B, S>> where
engine_id: GRANDPA_ENGINE_ID,
data,
};
self.with_gossip(
move |gossip, ctx| gossip.multicast(ctx, topic, msg, force)
)
}
fn register_gossip_message(&self, topic: B::Hash, data: Vec<u8>) {
let msg = ConsensusMessage {
engine_id: GRANDPA_ENGINE_ID,
data,
};
self.with_gossip(move |gossip, _| gossip.register_message(topic, msg))
}
fn send_message(&self, who: Vec<network::PeerId>, data: Vec<u8>) {
let msg = ConsensusMessage {
engine_id: GRANDPA_ENGINE_ID,
@@ -212,9 +228,12 @@ pub(crate) struct NetworkBridge<B: BlockT, N: Network<B>> {
impl<B: BlockT, N: Network<B>> NetworkBridge<B, N> {
/// Create a new NetworkBridge to the given NetworkService. Returns the service
/// handle and a future that must be polled to completion to finish startup.
/// If a voter set state is given it registers previous round votes with the
/// gossip service.
pub(crate) fn new(
service: N,
config: crate::Config,
set_state: Option<(u64, &crate::environment::VoterSetState<B>)>,
on_exit: impl Future<Item=(),Error=()> + Clone + Send + 'static,
) -> (
Self,
@@ -225,6 +244,41 @@ impl<B: BlockT, N: Network<B>> NetworkBridge<B, N> {
let validator = Arc::new(validator);
service.register_validator(validator.clone());
if let Some((set_id, set_state)) = set_state {
// register all previous votes with the gossip service so that they're
// available to peers potentially stuck on a previous round.
for round in set_state.completed_rounds().iter() {
let topic = round_topic::<B>(round.number, set_id);
// we need to note the round with the gossip validator otherwise
// messages will be ignored.
validator.note_round(Round(round.number), SetId(set_id), |_, _| {});
for signed in round.votes.iter() {
let message = gossip::GossipMessage::VoteOrPrecommit(
gossip::VoteOrPrecommitMessage::<B> {
message: signed.clone(),
round: Round(round.number),
set_id: SetId(set_id),
}
);
service.register_gossip_message(
topic,
message.encode(),
);
}
trace!(target: "afg",
"Registered {} messages for topic {:?} (round: {}, set_id: {})",
round.votes.len(),
topic,
round.number,
set_id,
);
}
}
let (rebroadcast_job, neighbor_sender) = periodic::neighbor_packet_worker(service.clone());
let reporting_job = report_stream.consume(service.clone());
@@ -72,6 +72,15 @@ impl super::Network<Block> for TestNetwork {
let _ = self.sender.unbounded_send(Event::SendMessage(who, data));
}
/// Register a message with the gossip service, it isn't broadcast right
/// away to any peers, but may be sent to new peers joining or when asked to
/// broadcast the topic. Useful to register previous messages on node
/// startup.
fn register_gossip_message(&self, _topic: Hash, _data: Vec<u8>) {
// NOTE: only required to restore previous state on startup
// not required for tests currently
}
/// Report a peer's cost or benefit after some action.
fn report(&self, who: network::PeerId, cost_benefit: i32) {
let _ = self.sender.unbounded_send(Event::Report(who, cost_benefit));
@@ -136,6 +145,7 @@ fn make_test_network() -> impl Future<Item=Tester,Error=()> {
let (bridge, startup_work) = super::NetworkBridge::new(
net.clone(),
config(),
None,
Exit,
);