From c64ff787761f594abcc29b6c02bed3477fcd80c9 Mon Sep 17 00:00:00 2001
From: Robert Habermeier <rphmeier@gmail.com>
Date: Wed, 31 Oct 2018 12:39:27 +0100
Subject: [PATCH] initial test to ensure auxiliary data is generated correctly

---
 .../core/finality-grandpa/src/authorities.rs  |  21 ++-
 substrate/core/finality-grandpa/src/tests.rs  | 175 ++++++++++++++++--
 substrate/core/network/src/test/mod.rs        |  12 +-
 3 files changed, 186 insertions(+), 22 deletions(-)

diff --git a/substrate/core/finality-grandpa/src/authorities.rs b/substrate/core/finality-grandpa/src/authorities.rs
index 6a32e3ddb7c..8541a64123f 100644
--- a/substrate/core/finality-grandpa/src/authorities.rs
+++ b/substrate/core/finality-grandpa/src/authorities.rs
@@ -39,11 +39,7 @@ impl<H, N> SharedAuthoritySet<H, N> {
 	/// The genesis authority set.
 	pub(crate) fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self {
 		SharedAuthoritySet {
-			inner: Arc::new(RwLock::new(AuthoritySet {
-				current_authorities: initial,
-				set_id: 0,
-				pending_changes: Vec::new(),
-			}))
+			inner: Arc::new(RwLock::new(AuthoritySet::genesis(initial)))
 		}
 	}
 
@@ -91,6 +87,15 @@ pub(crate) struct AuthoritySet<H, N> {
 }
 
 impl<H, N> AuthoritySet<H, N> {
+	/// Get a genesis set with given authorities.
+	pub(crate) fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self {
+		AuthoritySet {
+			current_authorities: initial,
+			set_id: 0,
+			pending_changes: Vec::new(),
+		}
+	}
+
 	/// Get the current set id and a reference to the current authority set.
 	pub(crate) fn current(&self) -> (u64, &[(AuthorityId, u64)]) {
 		(self.set_id, &self.current_authorities[..])
@@ -113,6 +118,12 @@ impl<H: Eq, N> AuthoritySet<H, N>
 
 		self.pending_changes.insert(idx, pending);
 	}
+
+	/// Inspect pending changes.
+	pub(crate) fn pending_changes(&self) -> &[PendingChange<H, N>] {
+		&self.pending_changes
+	}
+
 	/// Get the earliest limit-block number, if any.
 	pub(crate) fn current_limit(&self) -> Option<N> {
 		self.pending_changes.get(0).map(|change| change.effective_number().clone())
diff --git a/substrate/core/finality-grandpa/src/tests.rs b/substrate/core/finality-grandpa/src/tests.rs
index adc16464130..252fbcf8305 100644
--- a/substrate/core/finality-grandpa/src/tests.rs
+++ b/substrate/core/finality-grandpa/src/tests.rs
@@ -1,3 +1,21 @@
+// Copyright 2018 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate 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.
+
+// Substrate 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 Substrate.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Tests and test helpers for GRANDPA.
+
 use super::*;
 use network::test::{Block, Hash, TestNetFactory, Peer, PeersClient};
 use network::import_queue::{PassThroughVerifier};
@@ -7,6 +25,10 @@ use tokio::runtime::current_thread;
 use keyring::Keyring;
 use client::BlockchainEvents;
 use test_client::{self, runtime::BlockNumber};
+use codec::Decode;
+use consensus_common::BlockOrigin;
+
+use authorities::AuthoritySet;
 
 type PeerData = Mutex<Option<LinkHalf<test_client::Backend, test_client::Executor, Block>>>;
 type GrandpaPeer = Peer<PassThroughVerifier, PeerData>;
@@ -135,14 +157,14 @@ impl Network for MessageRouting {
 #[derive(Default, Clone)]
 struct TestApi {
 	genesis_authorities: Vec<(AuthorityId, u64)>,
-	scheduled_changes: HashMap<BlockNumber, ScheduledChange<BlockNumber>>,
+	scheduled_changes: Arc<Mutex<HashMap<Hash, ScheduledChange<BlockNumber>>>>,
 }
 
 impl TestApi {
 	fn new(genesis_authorities: Vec<(AuthorityId, u64)>) -> Self {
 		TestApi {
 			genesis_authorities,
-			scheduled_changes: HashMap::new(),
+			scheduled_changes: Arc::new(Mutex::new(HashMap::new())),
 		}
 	}
 }
@@ -157,20 +179,29 @@ impl ApiClient<Block> for TestApi {
 	{
 		// we take only scheduled changes at given block number where there are no
 		// extrinsics.
-		Ok(self.scheduled_changes.get(header.number()).map(|c| c.clone()))
+		let change = self.scheduled_changes.lock().get(&header.hash()).map(|c| c.clone());
+		if change.is_some() {
+			println!("Found transition for {:?}", header.hash());
+		}
+
+		Ok(change)
 	}
 }
 
 const TEST_GOSSIP_DURATION: Duration = Duration::from_millis(500);
 const TEST_ROUTING_INTERVAL: Duration = Duration::from_millis(50);
 
+fn make_ids(keys: &[Keyring]) -> Vec<(AuthorityId, u64)> {
+	keys.iter()
+		.map(|key| AuthorityId(key.to_raw_public()))
+		.map(|id| (id, 1))
+		.collect()
+}
+
 #[test]
 fn finalize_3_voters_no_observers() {
 	let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie];
-	let voters: Vec<_> = peers.iter()
-		.map(|key| AuthorityId(key.to_raw_public()))
-		.map(|id| (id, 1))
-		.collect();
+	let voters = make_ids(peers);
 
 	let mut net = GrandpaTestNet::new(TestApi::new(voters), 3);
 	net.peer(0).push_blocks(20, false);
@@ -229,10 +260,7 @@ fn finalize_3_voters_no_observers() {
 #[test]
 fn finalize_3_voters_1_observer() {
 	let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie];
-	let voters: Vec<_> = peers.iter()
-		.map(|key| AuthorityId(key.to_raw_public()))
-		.map(|id| (id, 1))
-		.collect();
+	let voters = make_ids(peers);
 
 	let mut net = GrandpaTestNet::new(TestApi::new(voters), 4);
 	net.peer(0).push_blocks(20, false);
@@ -285,3 +313,128 @@ fn finalize_3_voters_1_observer() {
 
 	runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap();
 }
+
+#[test]
+fn transition_3_voters_twice_1_observer() {
+	let peers_a = &[
+		Keyring::Alice,
+		Keyring::Bob,
+		Keyring::Charlie,
+	];
+
+	let peers_b = &[
+		Keyring::Dave,
+		Keyring::Eve,
+		Keyring::Ferdie,
+	];
+
+	let peers_c = &[
+		Keyring::Alice,
+		Keyring::Eve,
+		Keyring::Two,
+	];
+
+	let observer = &[Keyring::One];
+
+	let genesis_voters = make_ids(peers_a);
+
+	let api = TestApi::new(genesis_voters);
+	let transitions = api.scheduled_changes.clone();
+	let add_transition = move |hash, change| {
+		transitions.lock().insert(hash, change);
+	};
+
+	let mut net = GrandpaTestNet::new(api, 8);
+
+	// first 20 blocks: transition at 15, applied at 20.
+	{
+		net.peer(0).push_blocks(14, false);
+		net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
+			let block = builder.bake().unwrap();
+			println!("Adding transition for {:?}", block.header.hash());
+			add_transition(block.header.hash(), ScheduledChange {
+				next_authorities: make_ids(peers_b),
+				delay: 4,
+			});
+
+			block
+		});
+		net.peer(0).push_blocks(5, false);
+	}
+
+	// at block 21 we do another transition, but this time instant.
+	// add more until we have 30.
+	{
+		net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
+			let block = builder.bake().unwrap();
+			println!("Adding transition for {:?}", block.header.hash());
+			add_transition(block.header.hash(), ScheduledChange {
+				next_authorities: make_ids(peers_c),
+				delay: 0,
+			});
+
+			block
+		});
+
+		net.peer(0).push_blocks(9, false);
+	}
+	net.sync();
+
+	for (i, peer) in net.peers().iter().enumerate() {
+		assert_eq!(peer.client().info().unwrap().chain.best_number, 30,
+			"Peer #{} failed to sync", i);
+
+		let set_raw = peer.client().backend().get_aux(::AUTHORITY_SET_KEY).unwrap().unwrap();
+		let set = AuthoritySet::<Hash, BlockNumber>::decode(&mut &set_raw[..]).unwrap();
+
+		assert_eq!(set.current(), (0, make_ids(peers_a).as_slice()));
+		assert_eq!(set.pending_changes().len(), 2);
+	}
+
+	// let net = Arc::new(Mutex::new(net));
+	// let mut finality_notifications = Vec::new();
+
+	// let mut runtime = current_thread::Runtime::new().unwrap();
+	// let all_peers = peers.iter()
+	// 	.cloned()
+	// 	.map(|key| Some(Arc::new(key.into())))
+	// 	.chain(::std::iter::once(None));
+
+	// for (peer_id, local_key) in all_peers.enumerate() {
+	// 	let (client, link) = {
+	// 		let mut net = net.lock();
+	// 		let link = net.peers[peer_id].data.lock().take().expect("link initialized at startup; qed");
+	// 		(
+	// 			net.peers[peer_id].client().clone(),
+	// 			link,
+	// 		)
+	// 	};
+	// 	finality_notifications.push(
+	// 		client.finality_notification_stream()
+	// 			.take_while(|n| Ok(n.header.number() < &20))
+	// 			.for_each(move |_| Ok(()))
+	// 	);
+	// 	let voter = run_grandpa(
+	// 		Config {
+	// 			gossip_duration: TEST_GOSSIP_DURATION,
+	// 			local_key,
+	// 		},
+	// 		link,
+	// 		MessageRouting::new(net.clone(), peer_id),
+	// 	).expect("all in order with client and network");
+
+	// 	runtime.spawn(voter);
+	// }
+
+	// // wait for all finalized on each.
+	// let wait_for = ::futures::future::join_all(finality_notifications)
+	// 	.map(|_| ())
+	// 	.map_err(|_| ());
+
+	// let drive_to_completion = ::tokio::timer::Interval::new_interval(TEST_ROUTING_INTERVAL)
+	// 	.for_each(move |_| { net.lock().route_until_complete(); Ok(()) })
+	// 	.map(|_| ())
+	// 	.map_err(|_| ());
+
+	// runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap();
+}
diff --git a/substrate/core/network/src/test/mod.rs b/substrate/core/network/src/test/mod.rs
index c5addcd4e18..f8869fcc81f 100644
--- a/substrate/core/network/src/test/mod.rs
+++ b/substrate/core/network/src/test/mod.rs
@@ -236,14 +236,13 @@ impl<V: 'static + Verifier<Block>, D> Peer<V, D> {
 
 	/// Add blocks to the peer -- edit the block before adding
 	pub fn generate_blocks<F>(&self, count: usize, origin: BlockOrigin, mut edit_block: F)
-	where F: FnMut(&mut BlockBuilder<test_client::Backend, test_client::Executor, Block, Blake2Hasher>)
+		where F: FnMut(BlockBuilder<test_client::Backend, test_client::Executor, Block, Blake2Hasher>) -> Block
 	{
 		use blocks::BlockData;
 
 		for _  in 0..count {
-			let mut builder = self.client.new_block().unwrap();
-			edit_block(&mut builder);
-			let block = builder.bake().unwrap();
+			let builder = self.client.new_block().unwrap();
+			let block = edit_block(builder);
 			let hash = block.header.hash();
 			trace!("Generating {}, (#{}, parent={})", hash, block.header.number, block.header.parent_hash);
 			let header = block.header.clone();
@@ -269,7 +268,7 @@ impl<V: 'static + Verifier<Block>, D> Peer<V, D> {
 	pub fn push_blocks(&self, count: usize, with_tx: bool) {
 		let mut nonce = 0;
 		if with_tx {
-			self.generate_blocks(count, BlockOrigin::File, |builder| {
+			self.generate_blocks(count, BlockOrigin::File, |mut builder| {
 				let transfer = Transfer {
 					from: Keyring::Alice.to_raw_public().into(),
 					to: Keyring::Alice.to_raw_public().into(),
@@ -279,9 +278,10 @@ impl<V: 'static + Verifier<Block>, D> Peer<V, D> {
 				let signature = Keyring::from_raw_public(transfer.from.0).unwrap().sign(&transfer.encode()).into();
 				builder.push(Extrinsic { transfer, signature }).unwrap();
 				nonce = nonce + 1;
+				builder.bake().unwrap()
 			});
 		} else {
-			self.generate_blocks(count, BlockOrigin::File, |_| ());
+			self.generate_blocks(count, BlockOrigin::File, |builder| builder.bake().unwrap());
 		}
 	}
 
-- 
GitLab