feat: Rebrand Polkadot/Substrate references to PezkuwiChain
This commit systematically rebrands various references from Parity Technologies' Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk. Key changes include: - Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks. - Modified internal documentation and code comments to reflect PezkuwiChain naming and structure. - Replaced direct references to with or specific paths within the for XCM, Pezkuwi, and other modules. - Cleaned up deprecated issue and PR references in various and files, particularly in and modules. - Adjusted image and logo URLs in documentation to point to PezkuwiChain assets. - Removed or rephrased comments related to external Polkadot/Substrate PRs and issues. This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
@@ -0,0 +1,720 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program 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.
|
||||
|
||||
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Tests for the communication portion of the GRANDPA crate.
|
||||
|
||||
use super::{
|
||||
gossip::{self, GossipValidator},
|
||||
Round, SetId, VoterSet,
|
||||
};
|
||||
use crate::{communication::grandpa_protocol_name, environment::SharedVoterSetState};
|
||||
use codec::{DecodeAll, Encode};
|
||||
use futures::prelude::*;
|
||||
use pezsc_network::{
|
||||
config::{MultiaddrWithPeerId, Role},
|
||||
event::Event as NetworkEvent,
|
||||
service::traits::{Direction, MessageSink, NotificationEvent, NotificationService},
|
||||
types::ProtocolName,
|
||||
Multiaddr, NetworkBlock, NetworkEventStream, NetworkPeers, NetworkSyncForkRequest,
|
||||
ReputationChange,
|
||||
};
|
||||
use pezsc_network_common::role::{ObservedRole, Roles};
|
||||
use pezsc_network_gossip::Validator;
|
||||
use pezsc_network_sync::{SyncEvent as SyncStreamEvent, SyncEventStream};
|
||||
use pezsc_network_test::{Block, Hash};
|
||||
use pezsc_network_types::PeerId;
|
||||
use pezsc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender};
|
||||
use pezsp_consensus_grandpa::AuthorityList;
|
||||
use pezsp_keyring::Ed25519Keyring;
|
||||
use pezsp_runtime::traits::NumberFor;
|
||||
use std::{collections::HashSet, pin::Pin, sync::Arc, task::Poll};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum Event {
|
||||
WriteNotification(PeerId, Vec<u8>),
|
||||
Report(PeerId, ReputationChange),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct TestNetwork {
|
||||
sender: TracingUnboundedSender<Event>,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl NetworkPeers for TestNetwork {
|
||||
fn set_authorized_peers(&self, _peers: HashSet<PeerId>) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn set_authorized_only(&self, _reserved_only: bool) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn add_known_address(&self, _peer_id: PeerId, _addr: Multiaddr) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn report_peer(&self, peer_id: PeerId, cost_benefit: ReputationChange) {
|
||||
let _ = self.sender.unbounded_send(Event::Report(peer_id, cost_benefit));
|
||||
}
|
||||
|
||||
fn peer_reputation(&self, _peer_id: &PeerId) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn disconnect_peer(&self, _peer_id: PeerId, _protocol: ProtocolName) {}
|
||||
|
||||
fn accept_unreserved_peers(&self) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn deny_unreserved_peers(&self) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn add_reserved_peer(&self, _peer: MultiaddrWithPeerId) -> Result<(), String> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn remove_reserved_peer(&self, _peer_id: PeerId) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn set_reserved_peers(
|
||||
&self,
|
||||
_protocol: ProtocolName,
|
||||
_peers: HashSet<Multiaddr>,
|
||||
) -> Result<(), String> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn add_peers_to_reserved_set(
|
||||
&self,
|
||||
_protocol: ProtocolName,
|
||||
_peers: HashSet<Multiaddr>,
|
||||
) -> Result<(), String> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn remove_peers_from_reserved_set(
|
||||
&self,
|
||||
_protocol: ProtocolName,
|
||||
_peers: Vec<PeerId>,
|
||||
) -> Result<(), String> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn sync_num_connected(&self) -> usize {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn peer_role(&self, _peer_id: PeerId, handshake: Vec<u8>) -> Option<ObservedRole> {
|
||||
Roles::decode_all(&mut &handshake[..])
|
||||
.ok()
|
||||
.and_then(|role| Some(ObservedRole::from(role)))
|
||||
}
|
||||
|
||||
async fn reserved_peers(&self) -> Result<Vec<PeerId>, ()> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkEventStream for TestNetwork {
|
||||
fn event_stream(
|
||||
&self,
|
||||
_name: &'static str,
|
||||
) -> Pin<Box<dyn Stream<Item = NetworkEvent> + Send>> {
|
||||
futures::stream::pending().boxed()
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkBlock<Hash, NumberFor<Block>> for TestNetwork {
|
||||
fn announce_block(&self, _: Hash, _data: Option<Vec<u8>>) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn new_best_block_imported(&self, _hash: Hash, _number: NumberFor<Block>) {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkSyncForkRequest<Hash, NumberFor<Block>> for TestNetwork {
|
||||
fn set_sync_fork_request(&self, _peers: Vec<PeerId>, _hash: Hash, _number: NumberFor<Block>) {}
|
||||
}
|
||||
|
||||
impl pezsc_network_gossip::ValidatorContext<Block> for TestNetwork {
|
||||
fn broadcast_topic(&mut self, _: Hash, _: bool) {}
|
||||
|
||||
fn broadcast_message(&mut self, _: Hash, _: Vec<u8>, _: bool) {}
|
||||
|
||||
fn send_message(&mut self, who: &PeerId, data: Vec<u8>) {
|
||||
let _ = self.sender.unbounded_send(Event::WriteNotification(*who, data));
|
||||
}
|
||||
|
||||
fn send_topic(&mut self, _: &PeerId, _: Hash, _: bool) {}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct TestSync;
|
||||
|
||||
impl SyncEventStream for TestSync {
|
||||
fn event_stream(
|
||||
&self,
|
||||
_name: &'static str,
|
||||
) -> Pin<Box<dyn Stream<Item = SyncStreamEvent> + Send>> {
|
||||
Box::pin(futures::stream::pending())
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkBlock<Hash, NumberFor<Block>> for TestSync {
|
||||
fn announce_block(&self, _hash: Hash, _data: Option<Vec<u8>>) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn new_best_block_imported(&self, _hash: Hash, _number: NumberFor<Block>) {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkSyncForkRequest<Hash, NumberFor<Block>> for TestSync {
|
||||
fn set_sync_fork_request(&self, _peers: Vec<PeerId>, _hash: Hash, _number: NumberFor<Block>) {}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct TestNotificationService {
|
||||
sender: TracingUnboundedSender<Event>,
|
||||
rx: TracingUnboundedReceiver<NotificationEvent>,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl NotificationService for TestNotificationService {
|
||||
/// Instruct `Notifications` to open a new substream for `peer`.
|
||||
async fn open_substream(&mut self, _peer: PeerId) -> Result<(), ()> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/// Instruct `Notifications` to close substream for `peer`.
|
||||
async fn close_substream(&mut self, _peer: PeerId) -> Result<(), ()> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/// Send synchronous `notification` to `peer`.
|
||||
fn send_sync_notification(&mut self, peer: &PeerId, notification: Vec<u8>) {
|
||||
let _ = self.sender.unbounded_send(Event::WriteNotification(*peer, notification));
|
||||
}
|
||||
|
||||
/// Send asynchronous `notification` to `peer`, allowing sender to exercise backpressure.
|
||||
async fn send_async_notification(
|
||||
&mut self,
|
||||
_peer: &PeerId,
|
||||
_notification: Vec<u8>,
|
||||
) -> Result<(), pezsc_network::error::Error> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/// Set handshake for the notification protocol replacing the old handshake.
|
||||
async fn set_handshake(&mut self, _handshake: Vec<u8>) -> Result<(), ()> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn try_set_handshake(&mut self, _handshake: Vec<u8>) -> Result<(), ()> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/// Get next event from the `Notifications` event stream.
|
||||
async fn next_event(&mut self) -> Option<NotificationEvent> {
|
||||
self.rx.next().await
|
||||
}
|
||||
|
||||
fn clone(&mut self) -> Result<Box<dyn NotificationService>, ()> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn protocol(&self) -> &ProtocolName {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn message_sink(&self, _peer: &PeerId) -> Option<Box<dyn MessageSink>> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Tester {
|
||||
pub(crate) net_handle: super::NetworkBridge<Block, TestNetwork, TestSync>,
|
||||
gossip_validator: Arc<GossipValidator<Block>>,
|
||||
pub(crate) events: TracingUnboundedReceiver<Event>,
|
||||
pub(crate) notification_tx: TracingUnboundedSender<NotificationEvent>,
|
||||
}
|
||||
|
||||
impl Tester {
|
||||
fn filter_network_events<F>(self, mut pred: F) -> impl Future<Output = Self>
|
||||
where
|
||||
F: FnMut(Event) -> bool,
|
||||
{
|
||||
let mut s = Some(self);
|
||||
futures::future::poll_fn(move |cx| loop {
|
||||
match Stream::poll_next(Pin::new(&mut s.as_mut().unwrap().events), cx) {
|
||||
Poll::Ready(None) => panic!("concluded early"),
|
||||
Poll::Ready(Some(item)) =>
|
||||
if pred(item) {
|
||||
return Poll::Ready(s.take().unwrap());
|
||||
},
|
||||
Poll::Pending => return Poll::Pending,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn trigger_gossip_validator_reputation_change(&self, p: &PeerId) {
|
||||
self.gossip_validator.validate(
|
||||
&mut crate::communication::tests::NoopContext,
|
||||
p,
|
||||
&vec![1, 2, 3],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// some random config (not really needed)
|
||||
fn config() -> crate::Config {
|
||||
crate::Config {
|
||||
gossip_duration: std::time::Duration::from_millis(10),
|
||||
justification_generation_period: 256,
|
||||
keystore: None,
|
||||
name: None,
|
||||
local_role: Role::Authority,
|
||||
observer_enabled: true,
|
||||
telemetry: None,
|
||||
protocol_name: grandpa_protocol_name::NAME.into(),
|
||||
}
|
||||
}
|
||||
|
||||
// dummy voter set state
|
||||
fn voter_set_state() -> SharedVoterSetState<Block> {
|
||||
use crate::{authorities::AuthoritySet, environment::VoterSetState};
|
||||
use finality_grandpa::round::State as RoundState;
|
||||
use pezsp_consensus_grandpa::AuthorityId;
|
||||
use pezsp_core::{crypto::ByteArray, H256};
|
||||
|
||||
let state = RoundState::genesis((H256::zero(), 0));
|
||||
let base = state.prevote_ghost.unwrap();
|
||||
|
||||
let voters = vec![(AuthorityId::from_slice(&[1; 32]).unwrap(), 1)];
|
||||
let voters = AuthoritySet::genesis(voters).unwrap();
|
||||
|
||||
let set_state = VoterSetState::live(0, &voters, base);
|
||||
|
||||
set_state.into()
|
||||
}
|
||||
|
||||
// needs to run in a tokio runtime.
|
||||
pub(crate) fn make_test_network() -> (impl Future<Output = Tester>, TestNetwork) {
|
||||
let (tx, rx) = tracing_unbounded("test", 100_000);
|
||||
let (notification_tx, notification_rx) = tracing_unbounded("test-notification", 100_000);
|
||||
|
||||
let notification_service = TestNotificationService { rx: notification_rx, sender: tx.clone() };
|
||||
let net = TestNetwork { sender: tx };
|
||||
let sync = TestSync {};
|
||||
|
||||
let bridge = super::NetworkBridge::new(
|
||||
net.clone(),
|
||||
sync,
|
||||
Box::new(notification_service),
|
||||
config(),
|
||||
voter_set_state(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
(
|
||||
futures::future::ready(Tester {
|
||||
gossip_validator: bridge.validator.clone(),
|
||||
net_handle: bridge,
|
||||
events: rx,
|
||||
notification_tx,
|
||||
}),
|
||||
net,
|
||||
)
|
||||
}
|
||||
|
||||
fn make_ids(keys: &[Ed25519Keyring]) -> AuthorityList {
|
||||
keys.iter().map(|&key| key.public().into()).map(|id| (id, 1)).collect()
|
||||
}
|
||||
|
||||
struct NoopContext;
|
||||
|
||||
impl pezsc_network_gossip::ValidatorContext<Block> for NoopContext {
|
||||
fn broadcast_topic(&mut self, _: Hash, _: bool) {}
|
||||
fn broadcast_message(&mut self, _: Hash, _: Vec<u8>, _: bool) {}
|
||||
fn send_message(&mut self, _: &PeerId, _: Vec<u8>) {}
|
||||
fn send_topic(&mut self, _: &PeerId, _: Hash, _: bool) {}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn good_commit_leads_to_relay() {
|
||||
let private = [Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
|
||||
let public = make_ids(&private[..]);
|
||||
let voter_set = Arc::new(VoterSet::new(public.iter().cloned()).unwrap());
|
||||
|
||||
let round = 1;
|
||||
let set_id = 1;
|
||||
|
||||
let commit = {
|
||||
let target_hash: Hash = [1; 32].into();
|
||||
let target_number = 500;
|
||||
|
||||
let precommit = finality_grandpa::Precommit { target_hash, target_number };
|
||||
let payload = pezsp_consensus_grandpa::localized_payload(
|
||||
round,
|
||||
set_id,
|
||||
&finality_grandpa::Message::Precommit(precommit.clone()),
|
||||
);
|
||||
|
||||
let mut precommits = Vec::new();
|
||||
let mut auth_data = Vec::new();
|
||||
|
||||
for (i, key) in private.iter().enumerate() {
|
||||
precommits.push(precommit.clone());
|
||||
|
||||
let signature = pezsp_consensus_grandpa::AuthoritySignature::from(key.sign(&payload[..]));
|
||||
auth_data.push((signature, public[i].0.clone()))
|
||||
}
|
||||
|
||||
finality_grandpa::CompactCommit { target_hash, target_number, precommits, auth_data }
|
||||
};
|
||||
|
||||
let encoded_commit = gossip::GossipMessage::<Block>::Commit(gossip::FullCommitMessage {
|
||||
round: Round(round),
|
||||
set_id: SetId(set_id),
|
||||
message: commit,
|
||||
})
|
||||
.encode();
|
||||
|
||||
let id = PeerId::random();
|
||||
let global_topic = super::global_topic::<Block>(set_id);
|
||||
|
||||
let test = make_test_network()
|
||||
.0
|
||||
.then(move |tester| {
|
||||
// register a peer.
|
||||
tester.gossip_validator.new_peer(&mut NoopContext, &id, ObservedRole::Full);
|
||||
future::ready((tester, id))
|
||||
})
|
||||
.then(move |(tester, id)| {
|
||||
// start round, dispatch commit, and wait for broadcast.
|
||||
let (commits_in, _) =
|
||||
tester.net_handle.global_communication(SetId(1), voter_set, false);
|
||||
|
||||
{
|
||||
let (action, ..) = tester.gossip_validator.do_validate(&id, &encoded_commit[..]);
|
||||
match action {
|
||||
gossip::Action::ProcessAndDiscard(t, _) => assert_eq!(t, global_topic),
|
||||
_ => panic!("wrong expected outcome from initial commit validation"),
|
||||
}
|
||||
}
|
||||
|
||||
let commit_to_send = encoded_commit.clone();
|
||||
let network_bridge = tester.net_handle.clone();
|
||||
|
||||
// `NetworkBridge` will be operational as soon as it's created and it's
|
||||
// waiting for events from the network. Send it events that inform that
|
||||
// a notification stream was opened and that a notification was received.
|
||||
//
|
||||
// Since each protocol has its own notification stream, events need not be filtered.
|
||||
let sender_id = id;
|
||||
|
||||
let send_message = async move {
|
||||
let _ = tester.notification_tx.unbounded_send(
|
||||
NotificationEvent::NotificationStreamOpened {
|
||||
peer: sender_id,
|
||||
direction: Direction::Inbound,
|
||||
negotiated_fallback: None,
|
||||
handshake: Roles::FULL.encode(),
|
||||
},
|
||||
);
|
||||
let _ = tester.notification_tx.unbounded_send(
|
||||
NotificationEvent::NotificationReceived {
|
||||
peer: sender_id,
|
||||
notification: commit_to_send.clone(),
|
||||
},
|
||||
);
|
||||
|
||||
// Add a random peer which will be the recipient of this message
|
||||
let receiver_id = PeerId::random();
|
||||
let _ = tester.notification_tx.unbounded_send(
|
||||
NotificationEvent::NotificationStreamOpened {
|
||||
peer: receiver_id,
|
||||
direction: Direction::Inbound,
|
||||
negotiated_fallback: None,
|
||||
handshake: Roles::FULL.encode(),
|
||||
},
|
||||
);
|
||||
|
||||
// Announce its local set being on the current set id through a neighbor
|
||||
// packet, otherwise it won't be eligible to receive the commit
|
||||
let _ = {
|
||||
let update = gossip::VersionedNeighborPacket::V1(gossip::NeighborPacket {
|
||||
round: Round(round),
|
||||
set_id: SetId(set_id),
|
||||
commit_finalized_height: 1,
|
||||
});
|
||||
|
||||
let msg = gossip::GossipMessage::<Block>::Neighbor(update);
|
||||
|
||||
let _ = tester.notification_tx.unbounded_send(
|
||||
NotificationEvent::NotificationReceived {
|
||||
peer: receiver_id,
|
||||
notification: msg.encode(),
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
tester
|
||||
}
|
||||
.boxed();
|
||||
|
||||
// when the commit comes in, we'll tell the callback it was good.
|
||||
let handle_commit = commits_in.into_future().map(|(item, _)| match item.unwrap() {
|
||||
finality_grandpa::voter::CommunicationIn::Commit(_, _, mut callback) => {
|
||||
callback.run(finality_grandpa::voter::CommitProcessingOutcome::good());
|
||||
},
|
||||
_ => panic!("commit expected"),
|
||||
});
|
||||
|
||||
// once the message is sent and commit is "handled" we should have
|
||||
// a repropagation event coming from the network.
|
||||
let fut = future::join(send_message, handle_commit)
|
||||
.then(move |(tester, ())| {
|
||||
tester.filter_network_events(move |event| match event {
|
||||
Event::WriteNotification(_, data) => data == encoded_commit,
|
||||
_ => false,
|
||||
})
|
||||
})
|
||||
.map(|_| ());
|
||||
|
||||
// Poll both the future sending and handling the commit, as well as the underlying
|
||||
// NetworkBridge. Complete once the former completes.
|
||||
future::select(fut, network_bridge)
|
||||
});
|
||||
|
||||
futures::executor::block_on(test);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bad_commit_leads_to_report() {
|
||||
pezsp_tracing::try_init_simple();
|
||||
let private = [Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
|
||||
let public = make_ids(&private[..]);
|
||||
let voter_set = Arc::new(VoterSet::new(public.iter().cloned()).unwrap());
|
||||
|
||||
let round = 1;
|
||||
let set_id = 1;
|
||||
|
||||
let commit = {
|
||||
let target_hash: Hash = [1; 32].into();
|
||||
let target_number = 500;
|
||||
|
||||
let precommit = finality_grandpa::Precommit { target_hash, target_number };
|
||||
let payload = pezsp_consensus_grandpa::localized_payload(
|
||||
round,
|
||||
set_id,
|
||||
&finality_grandpa::Message::Precommit(precommit.clone()),
|
||||
);
|
||||
|
||||
let mut precommits = Vec::new();
|
||||
let mut auth_data = Vec::new();
|
||||
|
||||
for (i, key) in private.iter().enumerate() {
|
||||
precommits.push(precommit.clone());
|
||||
|
||||
let signature = pezsp_consensus_grandpa::AuthoritySignature::from(key.sign(&payload[..]));
|
||||
auth_data.push((signature, public[i].0.clone()))
|
||||
}
|
||||
|
||||
finality_grandpa::CompactCommit { target_hash, target_number, precommits, auth_data }
|
||||
};
|
||||
|
||||
let encoded_commit = gossip::GossipMessage::<Block>::Commit(gossip::FullCommitMessage {
|
||||
round: Round(round),
|
||||
set_id: SetId(set_id),
|
||||
message: commit,
|
||||
})
|
||||
.encode();
|
||||
|
||||
let id = PeerId::random();
|
||||
let global_topic = super::global_topic::<Block>(set_id);
|
||||
|
||||
let test = make_test_network()
|
||||
.0
|
||||
.map(move |tester| {
|
||||
// register a peer.
|
||||
tester.gossip_validator.new_peer(&mut NoopContext, &id, ObservedRole::Full);
|
||||
(tester, id)
|
||||
})
|
||||
.then(move |(tester, id)| {
|
||||
// start round, dispatch commit, and wait for broadcast.
|
||||
let (commits_in, _) =
|
||||
tester.net_handle.global_communication(SetId(1), voter_set, false);
|
||||
|
||||
{
|
||||
let (action, ..) = tester.gossip_validator.do_validate(&id, &encoded_commit[..]);
|
||||
match action {
|
||||
gossip::Action::ProcessAndDiscard(t, _) => assert_eq!(t, global_topic),
|
||||
_ => panic!("wrong expected outcome from initial commit validation"),
|
||||
}
|
||||
}
|
||||
|
||||
let commit_to_send = encoded_commit.clone();
|
||||
let network_bridge = tester.net_handle.clone();
|
||||
|
||||
// `NetworkBridge` will be operational as soon as it's created and it's
|
||||
// waiting for events from the network. Send it events that inform that
|
||||
// a notification stream was opened and that a notification was received.
|
||||
//
|
||||
// Since each protocol has its own notification stream, events need not be filtered.
|
||||
let sender_id = id;
|
||||
|
||||
let send_message = async move {
|
||||
let _ = tester.notification_tx.unbounded_send(
|
||||
NotificationEvent::NotificationStreamOpened {
|
||||
peer: sender_id,
|
||||
direction: Direction::Inbound,
|
||||
negotiated_fallback: None,
|
||||
handshake: Roles::FULL.encode(),
|
||||
},
|
||||
);
|
||||
let _ = tester.notification_tx.unbounded_send(
|
||||
NotificationEvent::NotificationReceived {
|
||||
peer: sender_id,
|
||||
notification: commit_to_send.clone(),
|
||||
},
|
||||
);
|
||||
|
||||
tester
|
||||
}
|
||||
.boxed();
|
||||
|
||||
// when the commit comes in, we'll tell the callback it was bad.
|
||||
let handle_commit = commits_in.into_future().map(|(item, _)| match item.unwrap() {
|
||||
finality_grandpa::voter::CommunicationIn::Commit(_, _, mut callback) => {
|
||||
callback.run(finality_grandpa::voter::CommitProcessingOutcome::bad());
|
||||
},
|
||||
_ => panic!("commit expected"),
|
||||
});
|
||||
|
||||
// once the message is sent and commit is "handled" we should have
|
||||
// a report event coming from the network.
|
||||
let fut = future::join(send_message, handle_commit)
|
||||
.then(move |(tester, ())| {
|
||||
tester.filter_network_events(move |event| match event {
|
||||
Event::Report(who, cost_benefit) =>
|
||||
who == id && cost_benefit == super::cost::INVALID_COMMIT,
|
||||
_ => false,
|
||||
})
|
||||
})
|
||||
.map(|_| ());
|
||||
|
||||
// Poll both the future sending and handling the commit, as well as the underlying
|
||||
// NetworkBridge. Complete once the former completes.
|
||||
future::select(fut, network_bridge)
|
||||
});
|
||||
|
||||
futures::executor::block_on(test);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn peer_with_higher_view_leads_to_catch_up_request() {
|
||||
let id = PeerId::random();
|
||||
|
||||
let (tester, mut net) = make_test_network();
|
||||
let test = tester
|
||||
.map(move |tester| {
|
||||
// register a peer with authority role.
|
||||
tester.gossip_validator.new_peer(&mut NoopContext, &id, ObservedRole::Authority);
|
||||
(tester, id)
|
||||
})
|
||||
.then(move |(tester, id)| {
|
||||
// send neighbor message at round 10 and height 50
|
||||
let result = tester.gossip_validator.validate(
|
||||
&mut net,
|
||||
&id,
|
||||
&gossip::GossipMessage::<Block>::from(gossip::NeighborPacket {
|
||||
set_id: SetId(0),
|
||||
round: Round(10),
|
||||
commit_finalized_height: 50,
|
||||
})
|
||||
.encode(),
|
||||
);
|
||||
|
||||
// neighbor packets are always discard
|
||||
match result {
|
||||
pezsc_network_gossip::ValidationResult::Discard => {},
|
||||
_ => panic!("wrong expected outcome from neighbor validation"),
|
||||
}
|
||||
|
||||
// a catch up request should be sent to the peer for round - 1
|
||||
tester
|
||||
.filter_network_events(move |event| match event {
|
||||
Event::WriteNotification(peer, message) => {
|
||||
assert_eq!(peer, id);
|
||||
|
||||
assert_eq!(
|
||||
message,
|
||||
gossip::GossipMessage::<Block>::CatchUpRequest(
|
||||
gossip::CatchUpRequestMessage { set_id: SetId(0), round: Round(9) }
|
||||
)
|
||||
.encode(),
|
||||
);
|
||||
|
||||
true
|
||||
},
|
||||
_ => false,
|
||||
})
|
||||
.map(|_| ())
|
||||
});
|
||||
|
||||
futures::executor::block_on(test);
|
||||
}
|
||||
|
||||
fn local_chain_spec() -> Box<dyn pezsc_chain_spec::ChainSpec> {
|
||||
let chain_spec =
|
||||
pezsc_chain_spec::GenericChainSpec::<pezsc_chain_spec::NoExtension, ()>::from_json_bytes(
|
||||
&include_bytes!("../../../../chain-spec/res/chain_spec.json")[..],
|
||||
)
|
||||
.unwrap();
|
||||
pezsc_chain_spec::ChainSpec::cloned_box(&chain_spec)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn grandpa_protocol_name() {
|
||||
let chain_spec = local_chain_spec();
|
||||
|
||||
// Create protocol name using random genesis hash.
|
||||
let genesis_hash = pezsp_core::H256::random();
|
||||
let expected = format!("/{}/grandpa/1", array_bytes::bytes2hex("", genesis_hash));
|
||||
let proto_name = grandpa_protocol_name::standard_name(&genesis_hash, &chain_spec);
|
||||
assert_eq!(proto_name.to_string(), expected);
|
||||
|
||||
// Create protocol name using hardcoded genesis hash. Verify exact representation.
|
||||
let genesis_hash = [
|
||||
53, 79, 112, 97, 119, 217, 39, 202, 147, 138, 225, 38, 88, 182, 215, 185, 110, 88, 8, 53,
|
||||
125, 210, 158, 151, 50, 113, 102, 59, 245, 199, 221, 240,
|
||||
];
|
||||
let expected =
|
||||
"/354f706177d927ca938ae12658b6d7b96e5808357dd29e973271663bf5c7ddf0/grandpa/1".to_string();
|
||||
let proto_name = grandpa_protocol_name::standard_name(&genesis_hash, &chain_spec);
|
||||
assert_eq!(proto_name.to_string(), expected);
|
||||
}
|
||||
Reference in New Issue
Block a user