// Copyright 2017 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see .
//! The "consensus" networking code built on top of the base network service.
//! This fulfills the `polkadot_consensus::Network` trait, providing a hook to be called
//! each time consensus begins on a new chain head.
use bft;
use ed25519;
use substrate_network::{self as net, generic_message as msg};
use substrate_network::consensus_gossip::ConsensusMessage;
use polkadot_api::{PolkadotApi, LocalPolkadotApi};
use polkadot_consensus::{Network, SharedTable, Collators};
use polkadot_primitives::{AccountId, Block, Hash, SessionKey};
use polkadot_primitives::parachain::{Id as ParaId, Collation};
use codec::Decode;
use futures::prelude::*;
use futures::sync::mpsc;
use std::sync::Arc;
use tokio::runtime::TaskExecutor;
use parking_lot::Mutex;
use super::{Message, NetworkService, Knowledge, CurrentConsensus};
use router::Router;
/// Sink for output BFT messages.
pub struct BftSink {
network: Arc,
parent_hash: Hash,
_marker: ::std::marker::PhantomData,
}
impl Sink for BftSink {
type SinkItem = bft::Communication;
// TODO: replace this with the ! type when that's stabilized
type SinkError = E;
fn start_send(&mut self, message: bft::Communication) -> ::futures::StartSend, E> {
let network_message = net::LocalizedBftMessage {
message: match message {
::rhododendron::Communication::Consensus(c) => msg::BftMessage::Consensus(match c {
::rhododendron::LocalizedMessage::Propose(proposal) => msg::SignedConsensusMessage::Propose(msg::SignedConsensusProposal {
round_number: proposal.round_number as u32,
proposal: proposal.proposal,
digest: proposal.digest,
sender: proposal.sender,
digest_signature: proposal.digest_signature.signature,
full_signature: proposal.full_signature.signature,
}),
::rhododendron::LocalizedMessage::Vote(vote) => msg::SignedConsensusMessage::Vote(msg::SignedConsensusVote {
sender: vote.sender,
signature: vote.signature.signature,
vote: match vote.vote {
::rhododendron::Vote::Prepare(r, h) => msg::ConsensusVote::Prepare(r as u32, h),
::rhododendron::Vote::Commit(r, h) => msg::ConsensusVote::Commit(r as u32, h),
::rhododendron::Vote::AdvanceRound(r) => msg::ConsensusVote::AdvanceRound(r as u32),
}
}),
}),
::rhododendron::Communication::Auxiliary(justification) => {
let unchecked: bft::UncheckedJustification<_> = justification.uncheck().into();
msg::BftMessage::Auxiliary(unchecked.into())
}
},
parent_hash: self.parent_hash,
};
self.network.with_spec(
move |spec, ctx| spec.consensus_gossip.multicast_bft_message(ctx, network_message)
);
Ok(::futures::AsyncSink::Ready)
}
fn poll_complete(&mut self) -> ::futures::Poll<(), E> {
Ok(Async::Ready(()))
}
}
// check signature and authority validity of message.
fn process_bft_message(msg: msg::LocalizedBftMessage, local_id: &SessionKey, authorities: &[SessionKey]) -> Result