mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 08:41:02 +00:00
Gossip refactoring (#1811)
* First part of gossip protocol refactoring * Message validation in GRANDPA * Reverted to time-based expiration for future round messages * Removed collect_garbage_for_topic * Use consensus engine id instead of kind * Use try_init Co-Authored-By: arkpar <arkady.paronyan@gmail.com> * Comment Co-Authored-By: arkpar <arkady.paronyan@gmail.com> * Added expiration check on broadcast Co-Authored-By: arkpar <arkady.paronyan@gmail.com> * Apply suggestions from code review Co-Authored-By: arkpar <arkady.paronyan@gmail.com> * Style * Style
This commit is contained in:
committed by
Gav Wood
parent
21779b8cf2
commit
b3eae17f65
@@ -28,7 +28,8 @@ use parity_codec::{Encode, Decode};
|
||||
use substrate_primitives::{ed25519, Ed25519AuthorityId};
|
||||
use runtime_primitives::traits::Block as BlockT;
|
||||
use tokio::timer::Interval;
|
||||
use crate::{Error, Network, Message, SignedMessage, Commit, CompactCommit};
|
||||
use crate::{Error, Network, Message, SignedMessage, Commit,
|
||||
CompactCommit, GossipMessage, FullCommitMessage, VoteOrPrecommitMessage};
|
||||
|
||||
fn localized_payload<E: Encode>(round: u64, set_id: u64, message: &E) -> Vec<u8> {
|
||||
(message, round, set_id).encode()
|
||||
@@ -259,8 +260,6 @@ pub(crate) fn check_message_sig<Block: BlockT>(
|
||||
/// converts a message stream into a stream of signed messages.
|
||||
/// the output stream checks signatures also.
|
||||
pub(crate) fn checked_message_stream<Block: BlockT, S>(
|
||||
round: u64,
|
||||
set_id: u64,
|
||||
inner: S,
|
||||
voters: Arc<VoterSet<Ed25519AuthorityId>>,
|
||||
)
|
||||
@@ -269,28 +268,27 @@ pub(crate) fn checked_message_stream<Block: BlockT, S>(
|
||||
{
|
||||
inner
|
||||
.filter_map(|raw| {
|
||||
let decoded = SignedMessage::<Block>::decode(&mut &raw[..]);
|
||||
let decoded = GossipMessage::<Block>::decode(&mut &raw[..]);
|
||||
if decoded.is_none() {
|
||||
debug!(target: "afg", "Skipping malformed message {:?}", raw);
|
||||
}
|
||||
decoded
|
||||
})
|
||||
.and_then(move |msg| {
|
||||
// check signature.
|
||||
if !voters.contains_key(&msg.id) {
|
||||
debug!(target: "afg", "Skipping message from unknown voter {}", msg.id);
|
||||
return Ok(None);
|
||||
match msg {
|
||||
GossipMessage::VoteOrPrecommit(msg) => {
|
||||
// check signature.
|
||||
if !voters.contains_key(&msg.message.id) {
|
||||
debug!(target: "afg", "Skipping message from unknown voter {}", msg.message.id);
|
||||
return Ok(None);
|
||||
}
|
||||
Ok(Some(msg.message))
|
||||
}
|
||||
_ => {
|
||||
debug!(target: "afg", "Skipping unknown message type");
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
|
||||
// we ignore messages where the signature doesn't check out.
|
||||
let res = check_message_sig::<Block>(
|
||||
&msg.message,
|
||||
&msg.id,
|
||||
&msg.signature,
|
||||
round,
|
||||
set_id
|
||||
);
|
||||
Ok(res.map(move |()| msg).ok())
|
||||
})
|
||||
.filter_map(|x| x)
|
||||
.map_err(|()| Error::Network(format!("Failed to receive message on unbounded stream")))
|
||||
@@ -322,10 +320,16 @@ impl<Block: BlockT, N: Network<Block>> Sink for OutgoingMessages<Block, N>
|
||||
id: local_id,
|
||||
};
|
||||
|
||||
let message = GossipMessage::VoteOrPrecommit(VoteOrPrecommitMessage::<Block> {
|
||||
message: signed.clone(),
|
||||
round: self.round,
|
||||
set_id: self.set_id,
|
||||
});
|
||||
|
||||
// announce our block hash to peers and propagate the
|
||||
// message.
|
||||
self.network.announce(self.round, self.set_id, target_hash);
|
||||
self.network.send_message(self.round, self.set_id, signed.encode());
|
||||
self.network.send_message(self.round, self.set_id, message.encode());
|
||||
|
||||
// forward the message to the inner sender.
|
||||
let _ = self.sender.unbounded_send(signed);
|
||||
@@ -392,34 +396,18 @@ pub(crate) fn outgoing_messages<Block: BlockT, N: Network<Block>>(
|
||||
fn check_compact_commit<Block: BlockT>(
|
||||
msg: CompactCommit<Block>,
|
||||
voters: &VoterSet<Ed25519AuthorityId>,
|
||||
round: u64,
|
||||
set_id: u64,
|
||||
) -> Option<CompactCommit<Block>> {
|
||||
use grandpa::Message as GrandpaMessage;
|
||||
if msg.precommits.len() != msg.auth_data.len() || msg.precommits.is_empty() {
|
||||
debug!(target: "afg", "Skipping malformed compact commit");
|
||||
return None;
|
||||
}
|
||||
|
||||
// check signatures on all contained precommits.
|
||||
for (precommit, &(ref sig, ref id)) in msg.precommits.iter().zip(&msg.auth_data) {
|
||||
for (_, ref id) in &msg.auth_data {
|
||||
if !voters.contains_key(id) {
|
||||
debug!(target: "afg", "Skipping commit containing unknown voter {}", id);
|
||||
return None;
|
||||
}
|
||||
|
||||
let res = check_message_sig::<Block>(
|
||||
&GrandpaMessage::Precommit(precommit.clone()),
|
||||
id,
|
||||
sig,
|
||||
round,
|
||||
set_id,
|
||||
);
|
||||
|
||||
if let Err(()) = res {
|
||||
debug!(target: "afg", "Skipping commit containing bad message");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
Some(msg)
|
||||
@@ -428,7 +416,6 @@ fn check_compact_commit<Block: BlockT>(
|
||||
/// A stream for incoming commit messages. This checks all the signatures on the
|
||||
/// messages.
|
||||
pub(crate) fn checked_commit_stream<Block: BlockT, S>(
|
||||
set_id: u64,
|
||||
inner: S,
|
||||
voters: Arc<VoterSet<Ed25519AuthorityId>>,
|
||||
)
|
||||
@@ -438,14 +425,23 @@ pub(crate) fn checked_commit_stream<Block: BlockT, S>(
|
||||
inner
|
||||
.filter_map(|raw| {
|
||||
// this could be optimized by decoding piecewise.
|
||||
let decoded = <(u64, CompactCommit<Block>)>::decode(&mut &raw[..]);
|
||||
let decoded = GossipMessage::<Block>::decode(&mut &raw[..]);
|
||||
if decoded.is_none() {
|
||||
trace!(target: "afg", "Skipping malformed commit message {:?}", raw);
|
||||
}
|
||||
decoded
|
||||
})
|
||||
.filter_map(move |(round, msg)| {
|
||||
check_compact_commit::<Block>(msg, &*voters, round, set_id).map(move |c| (round, c))
|
||||
.filter_map(move |msg| {
|
||||
match msg {
|
||||
GossipMessage::Commit(msg) => {
|
||||
let round = msg.round;
|
||||
check_compact_commit::<Block>(msg.message, &*voters).map(move |c| (round, c))
|
||||
},
|
||||
_ => {
|
||||
debug!(target: "afg", "Skipping unknown message type");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
})
|
||||
.map_err(|()| Error::Network(format!("Failed to receive message on unbounded stream")))
|
||||
}
|
||||
@@ -491,7 +487,13 @@ impl<Block: BlockT, N: Network<Block>> Sink for CommitsOut<Block, N> {
|
||||
auth_data
|
||||
};
|
||||
|
||||
self.network.send_commit(round, self.set_id, Encode::encode(&(round, compact_commit)));
|
||||
let message = FullCommitMessage::<Block> {
|
||||
round: round,
|
||||
set_id: self.set_id,
|
||||
message: compact_commit,
|
||||
};
|
||||
|
||||
self.network.send_commit(round, self.set_id, Encode::encode(&message));
|
||||
|
||||
Ok(AsyncSink::Ready)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user